webrtc/experiments/field_trials.py
Philipp Hancke bce57cda1e Piggyback DTLS handshake in initial STUN packets
This change puts the DTLS handshake as payload of STUN packets with a custom STUN attribute (registered with the IANA) and starts the DTLS handshake before the ICE transport becomes writable. Effectively, STUN acts as a transport layer for DTLS during the handshake phase.

This will theoretically reduce the call setup time by one RTT for aggressive nomination or two RTTs for regular nomination.

The latest DTLS packet (flight) is cached and sent on every STUN request or response. DTLS packets are extracted from every authenticated STUN request or response and handled to the DTLS layer for processing.
The caching also increases the resilience to packet loss as STUN pacing is more aggressive (every 20ms) than the exponential backoff used by DTLS which should reduce call setup time in lossy networks.

If the other side of the connection does not support this feature the fallback to normal DTLS happens as soon as the ICE transport becomes writable. This also handles edge-cases like fragmentation of the DTLS handshake.

The feature is only supported when ECDSA certificates are used since RSA certificates are too large to transport as STUN attributes. The observed attributes for the server and client flights with the certificates were around 600 to 650 bytes. This may be further reduced by using raw public keys defined in RFC 7250.

This feature is disabled by default and guarded by the field trial
  WebRTC-IceHandshakeDtls
and requires experimentation and standardization before roll-out in the browser.

Parts of this landed in
  https://webrtc-review.googlesource.com/c/src/+/370679

BUG=webrtc:367395350

Change-Id: I4809438b2a267c4690a9b2bd6f1766d2f959500d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/362480
Commit-Queue: Jonas Oreland <jonaso@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Jonas Oreland <jonaso@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43742}
2025-01-15 07:54:23 -08:00

1123 lines
39 KiB
Python
Executable file

#!/usr/bin/env vpython3
# Copyright (c) 2022 The WebRTC Project Authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
import datetime
from datetime import date
import hashlib
import sys
from typing import FrozenSet, List, Set
import argparse
import dataclasses
@dataclasses.dataclass(frozen=True)
class FieldTrial:
"""Representation of all attributes associated with a field trial.
Attributes:
key: Field trial key.
bug_id: Associated open bug containing more context.
end_date: Date when the field trial expires and must be deleted.
"""
key: str
bug_id: int
end_date: date
def bug_url(self) -> str:
if self.bug_id <= 0:
return ''
return f'https://issues.webrtc.org/issues/{self.bug_id}'
# As per the policy in `g3doc/field-trials.md`, all field trials should be
# registered in the container below.
ACTIVE_FIELD_TRIALS: FrozenSet[FieldTrial] = frozenset([
# keep-sorted start
FieldTrial('WebRTC-Aec3BufferingMaxAllowedExcessRenderBlocksOverride',
337900458,
date(2024, 9, 1)),
FieldTrial('WebRTC-Audio-GainController2',
42232605,
date(2024, 4, 1)),
FieldTrial('WebRTC-Audio-OpusDecodeStereoByDefault',
379996136,
date(2025, 11, 15)),
FieldTrial('WebRTC-Audio-OpusGeneratePlc',
42223518,
date(2025, 4, 1)),
FieldTrial('WebRTC-Audio-PriorityBitrate',
42226125,
date(2024, 4, 1)),
FieldTrial('WebRTC-AV1-OverridePriorityBitrate',
42226119,
date(2024, 4, 1)),
FieldTrial('WebRTC-Av1-GetEncoderInfoOverride',
42225234,
date(2024, 4, 1)),
FieldTrial('WebRTC-BitrateAdjusterUseNewfangledHeadroomAdjustment',
349561566,
date(2025, 8, 26)),
FieldTrial('WebRTC-Bwe-LimitPacingFactorByUpperLinkCapacityEstimate',
42220543,
date(2025, 1, 1)),
FieldTrial('WebRTC-Bwe-ResetOnAdapterIdChange',
42225231,
date(2025, 5, 30)),
FieldTrial('WebRTC-DataChannelMessageInterleaving',
41481008,
date(2024, 10, 1)),
FieldTrial('WebRTC-DisableRtxRateLimiter',
42225500,
date(2024, 4, 1)),
FieldTrial('WebRTC-ElasticBitrateAllocation',
350555527,
date(2025, 3, 1)),
FieldTrial('WebRTC-EncoderDataDumpDirectory',
296242528,
date(2024, 4, 1)),
FieldTrial('WebRTC-ForceDtls13',
383141571,
date(2024,9,1)),
FieldTrial('WebRTC-FrameCadenceAdapter-UseVideoFrameTimestamp',
42226256,
date(2024, 10, 1)),
FieldTrial('WebRTC-IPv6NetworkResolutionFixes',
42224598,
date(2024, 4, 1)),
FieldTrial('WebRTC-IncomingTimestampOnMarkerBitOnly',
42224805,
date(2024, 4, 1)),
FieldTrial('WebRTC-IncreaseIceCandidatePriorityHostSrflx',
42225331,
date(2024, 4, 1)),
FieldTrial('WebRTC-JitterEstimatorConfig',
42224404,
date(2024, 4, 1)),
FieldTrial('WebRTC-LibaomAv1Encoder-AdaptiveMaxConsecDrops',
351644568,
date(2025, 7, 1)),
FieldTrial('WebRTC-LibvpxVp8Encoder-AndroidSpecificThreadingSettings',
42226191,
date(2024, 9, 1)),
FieldTrial('WebRTC-MixedCodecSimulcast',
362277533,
date(2025, 9, 1)),
FieldTrial('WebRTC-Pacer-FastRetransmissions',
40235589,
date(2024, 4, 1)),
FieldTrial('WebRTC-Pacer-KeyframeFlushing',
42221435,
date(2024, 4, 1)),
FieldTrial('WebRTC-QCM-Dynamic-AV1',
349860657,
date(2025, 7, 1)),
FieldTrial('WebRTC-QCM-Dynamic-VP8',
349860657,
date(2025, 7, 1)),
FieldTrial('WebRTC-QCM-Dynamic-VP9',
349860657,
date(2025, 7, 1)),
FieldTrial('WebRTC-QCM-Static-AV1',
349860657,
date(2025, 7, 1)),
FieldTrial('WebRTC-QCM-Static-VP8',
349860657,
date(2025, 7, 1)),
FieldTrial('WebRTC-QCM-Static-VP9',
349860657,
date(2025, 7, 1)),
FieldTrial('WebRTC-ReceiveBufferSize',
42225927,
date(2024, 4, 1)),
FieldTrial('WebRTC-RFC8888CongestionControlFeedback',
42225697,
date(2025, 1, 30)),
FieldTrial('WebRTC-RtcEventLogEncodeDependencyDescriptor',
42225280,
date(2024, 4, 1)),
FieldTrial('WebRTC-RtcEventLogEncodeNetEqSetMinimumDelayKillSwitch',
42225058,
date(2024, 4, 1)),
FieldTrial('WebRTC-SetReadyToSendFalseIfSendFail',
361124449,
date(2024, 12, 1)),
FieldTrial('WebRTC-SrtpRemoveReceiveStream',
42225949,
date(2024, 10, 1)),
FieldTrial('WebRTC-TaskQueue-ReplaceLibeventWithStdlib',
42224654,
date(2024, 4, 1)),
FieldTrial('WebRTC-PayloadTypesInTransport',
360058654,
date(2025, 9, 11)),
FieldTrial('WebRTC-UseNtpTimeAbsoluteSendTime',
42226305,
date(2024, 9, 1)),
FieldTrial('WebRTC-VP8-MaxFrameInterval',
42225870,
date(2024, 4, 1)),
FieldTrial('WebRTC-VP9-SvcForSimulcast',
347737882,
date(2024, 10, 1)),
FieldTrial('WebRTC-Video-AV1EvenPayloadSizes',
42226301,
date(2024, 11, 1)),
FieldTrial('WebRTC-Video-EnableRetransmitAllLayers',
42225262,
date(2024, 4, 1)),
FieldTrial('WebRTC-Video-EncoderFallbackSettings',
42231704,
date(2024, 4, 1)),
FieldTrial('WebRTC-Video-SimulcastIndependentFrameIds',
42226243,
date(2024, 12, 1)),
FieldTrial('WebRTC-VideoEncoderSettings',
40252667,
date(2024, 4, 1)),
FieldTrial('WebRTC-ZeroHertzQueueOverload',
42225879,
date(2024, 7, 1)),
FieldTrial('WebRTC-Video-H26xPacketBuffer',
41480904,
date(2024, 6, 1)),
FieldTrial('WebRTC-Video-Vp9FlexibleMode',
329396373,
date(2025, 6, 26)),
FieldTrial('WebRTC-IceHandshakeDtls',
367395350,
date(2026, 1, 1)),
# keep-sorted end
]) # yapf: disable
NO_BUG = -1
INDEFINITE = date(datetime.MAXYEAR, 1, 1)
# These field trials precedes the policy in `g3doc/field-trials.md` and are
# therefore not required to follow it. Do not add any new field trials here.
# If you remove an entry you should also update
# POLICY_EXEMPT_FIELD_TRIALS_DIGEST.
POLICY_EXEMPT_FIELD_TRIALS: FrozenSet[FieldTrial] = frozenset([
# keep-sorted start
FieldTrial('WebRTC-AddNetworkCostToVpn',
42223280,
date(2024, 4, 1)),
FieldTrial('WebRTC-AddPacingToCongestionWindowPushback',
42220204,
date(2024, 4, 1)),
FieldTrial('WebRTC-AdjustOpusBandwidth',
42233664,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3AecStateFullResetKillSwitch',
42221578,
INDEFINITE),
FieldTrial('WebRTC-Aec3AecStateSubtractorAnalyzerResetKillSwitch',
42221578,
INDEFINITE),
FieldTrial('WebRTC-Aec3AntiHowlingMinimizationKillSwitch',
150764764,
INDEFINITE),
FieldTrial('WebRTC-Aec3ClampInstQualityToOneKillSwitch',
42220991,
INDEFINITE),
FieldTrial('WebRTC-Aec3ClampInstQualityToZeroKillSwitch',
42220991,
INDEFINITE),
FieldTrial('WebRTC-Aec3CoarseFilterResetHangoverKillSwitch',
42222401,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3ConservativeTailFreqResponse',
42223361,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3DeactivateInitialStateResetKillSwitch',
42221578,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3DelayEstimateSmoothingDelayFoundOverride',
42222934,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3DelayEstimateSmoothingOverride',
42222934,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3EchoSaturationDetectionKillSwitch',
42221578,
INDEFINITE),
FieldTrial('WebRTC-Aec3EnforceCaptureDelayEstimationDownmixing',
42221238,
INDEFINITE),
FieldTrial(
'WebRTC-Aec3EnforceCaptureDelayEstimationLeftRightPrioritization',
42221238,
INDEFINITE),
FieldTrial('WebRTC-Aec3EnforceConservativeHfSuppression',
42222109,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3EnforceLowActiveRenderLimit',
42221578,
INDEFINITE),
FieldTrial('WebRTC-Aec3EnforceMoreTransparentNearendSuppressorHfTuning',
42221589,
INDEFINITE),
FieldTrial('WebRTC-Aec3EnforceMoreTransparentNearendSuppressorTuning',
42221578,
INDEFINITE),
FieldTrial('WebRTC-Aec3EnforceMoreTransparentNormalSuppressorHfTuning',
42221589,
INDEFINITE),
FieldTrial('WebRTC-Aec3EnforceMoreTransparentNormalSuppressorTuning',
42221578,
INDEFINITE),
FieldTrial('WebRTC-Aec3EnforceRapidlyAdjustingNearendSuppressorTunings',
42221578,
INDEFINITE),
FieldTrial('WebRTC-Aec3EnforceRapidlyAdjustingNormalSuppressorTunings',
42221578,
INDEFINITE),
FieldTrial('WebRTC-Aec3EnforceRenderDelayEstimationDownmixing',
42221238,
INDEFINITE),
FieldTrial('WebRTC-Aec3EnforceSlowlyAdjustingNearendSuppressorTunings',
42221578,
INDEFINITE),
FieldTrial('WebRTC-Aec3EnforceSlowlyAdjustingNormalSuppressorTunings',
42221578,
INDEFINITE),
FieldTrial('WebRTC-Aec3EnforceStationarityProperties',
42221578,
INDEFINITE),
FieldTrial('WebRTC-Aec3EnforceStationarityPropertiesAtInit',
42221578,
INDEFINITE),
FieldTrial('WebRTC-Aec3EnforceVeryLowActiveRenderLimit',
42221578,
INDEFINITE),
FieldTrial('WebRTC-Aec3HighPassFilterEchoReference',
42222401,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3MinErleDuringOnsetsKillSwitch',
42220385,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3NonlinearModeReverbKillSwitch',
42222109,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3OnsetDetectionKillSwitch',
42221578,
INDEFINITE),
FieldTrial(
'WebRTC-Aec3RenderDelayEstimationLeftRightPrioritizationKillSwitch',
42221238,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3SensitiveDominantNearendActivation',
42221578,
INDEFINITE),
FieldTrial('WebRTC-Aec3SetupSpecificDefaultConfigDefaultsKillSwitch',
42221236,
INDEFINITE),
FieldTrial('WebRTC-Aec3ShortHeadroomKillSwitch',
42220385,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3StereoContentDetectionKillSwitch',
42225201,
INDEFINITE),
FieldTrial('WebRTC-Aec3SuppressorAntiHowlingGainOverride',
42221589,
INDEFINITE),
FieldTrial('WebRTC-Aec3SuppressorDominantNearendEnrExitThresholdOverride',
42221589,
INDEFINITE),
FieldTrial('WebRTC-Aec3SuppressorDominantNearendEnrThresholdOverride',
42221589,
INDEFINITE),
FieldTrial('WebRTC-Aec3SuppressorDominantNearendHoldDurationOverride',
42221589,
INDEFINITE),
FieldTrial('WebRTC-Aec3SuppressorDominantNearendSnrThresholdOverride',
42221589,
INDEFINITE),
FieldTrial('WebRTC-Aec3SuppressorDominantNearendTriggerThresholdOverride',
42221589,
INDEFINITE),
FieldTrial('WebRTC-Aec3SuppressorNearendHfMaskSuppressOverride',
42221589,
INDEFINITE),
FieldTrial('WebRTC-Aec3SuppressorNearendHfMaskTransparentOverride',
42221589,
INDEFINITE),
FieldTrial('WebRTC-Aec3SuppressorNearendLfMaskSuppressOverride',
42221589,
INDEFINITE),
FieldTrial('WebRTC-Aec3SuppressorNearendLfMaskTransparentOverride',
42221589,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3SuppressorNearendMaxDecFactorLfOverride',
42221589,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3SuppressorNearendMaxIncFactorOverride',
42221589,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3SuppressorNormalHfMaskSuppressOverride',
42221589,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3SuppressorNormalHfMaskTransparentOverride',
42221589,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3SuppressorNormalLfMaskSuppressOverride',
42221589,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3SuppressorNormalLfMaskTransparentOverride',
42221589,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3SuppressorNormalMaxDecFactorLfOverride',
42221589,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3SuppressorNormalMaxIncFactorOverride',
42221589,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3SuppressorTuningOverride',
42221589,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3TransparentAntiHowlingGain',
42221578,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3TransparentModeHmm',
42222401,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3TransparentModeKillSwitch',
42234438,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3Use1Dot2SecondsInitialStateDuration',
42221578,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3Use1Dot6SecondsInitialStateDuration',
42221578,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3Use2Dot0SecondsInitialStateDuration',
42221578,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3UseDot1SecondsInitialStateDuration',
42221578,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3UseDot2SecondsInitialStateDuration',
42221578,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3UseDot3SecondsInitialStateDuration',
42221578,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3UseDot6SecondsInitialStateDuration',
42221578,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3UseDot9SecondsInitialStateDuration',
42221578,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3UseErleOnsetCompensationInDominantNearend',
42222842,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3UseLowEarlyReflectionsDefaultGain',
42221578,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3UseLowLateReflectionsDefaultGain',
42221578,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3UseNearendReverbLen',
42223329,
INDEFINITE),
FieldTrial('WebRTC-Aec3UseShortConfigChangeDuration',
42221578,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3UseZeroInitialStateDuration',
42221578,
date(2024, 4, 1)),
FieldTrial('WebRTC-Aec3VerySensitiveDominantNearendActivation',
42221578,
date(2024, 4, 1)),
FieldTrial('WebRTC-Agc2SimdAvx2KillSwitch',
42232605,
date(2024, 4, 1)),
FieldTrial('WebRTC-Agc2SimdNeonKillSwitch',
42232605,
date(2024, 4, 1)),
FieldTrial('WebRTC-Agc2SimdSse2KillSwitch',
42232605,
date(2024, 4, 1)),
FieldTrial('WebRTC-AllowMACBasedIPv6',
41480878,
date(2024, 4, 1)),
FieldTrial('WebRTC-AlrDetectorParameters',
42220590,
INDEFINITE),
FieldTrial('WebRTC-AndroidNetworkMonitor-IsAdapterAvailable',
42223964,
date(2024, 4, 1)),
FieldTrial('WebRTC-ApmExperimentalMultiChannelCaptureKillSwitch',
42225202,
INDEFINITE),
FieldTrial('WebRTC-ApmExperimentalMultiChannelRenderKillSwitch',
42225203,
INDEFINITE),
FieldTrial('WebRTC-Audio-2ndAgcMinMicLevelExperiment',
40207112,
date(2024, 4, 1)),
FieldTrial('WebRTC-Audio-ABWENoTWCC',
42233370,
INDEFINITE),
FieldTrial('WebRTC-Audio-AdaptivePtime',
40694579,
date(2024, 4, 1)),
FieldTrial('WebRTC-Audio-Allocation',
42220324,
INDEFINITE),
FieldTrial('WebRTC-Audio-AlrProbing',
42220234,
date(2024, 4, 1)),
FieldTrial('WebRTC-Audio-FecAdaptation',
42233254,
date(2024, 4, 1)),
FieldTrial('WebRTC-Audio-LegacyOverhead',
42221084,
INDEFINITE),
FieldTrial('WebRTC-Audio-MinimizeResamplingOnMobile',
42231221,
date(2024, 4, 1)),
FieldTrial('WebRTC-Audio-NetEqDecisionLogicConfig',
42223518,
date(2024, 4, 1)),
FieldTrial('WebRTC-Audio-NetEqDelayManagerConfig',
42220376,
date(2024, 4, 1)),
FieldTrial('WebRTC-Audio-NetEqNackTrackerConfig',
42220211,
date(2024, 4, 1)),
FieldTrial('WebRTC-Audio-NetEqSmartFlushing',
42222334,
date(2024, 4, 1)),
FieldTrial('WebRTC-Audio-OpusBitrateMultipliers',
42221139,
date(2024, 4, 1)),
FieldTrial('WebRTC-Audio-Red-For-Opus',
42221750,
date(2024, 4, 1)),
FieldTrial('WebRTC-Audio-StableTargetAdaptation',
42221061,
INDEFINITE),
FieldTrial('WebRTC-Audio-iOS-Holding',
42233253,
date(2024, 4, 1)),
FieldTrial('WebRTC-AudioDevicePlayoutBufferSizeFactor',
42221006,
date(2024, 4, 1)),
FieldTrial('WebRTC-BindUsingInterfaceName',
42220770,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-AllocationProbing',
42220440,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-AlrProbing',
42220440,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-EstimateBoundedIncrease',
42220543,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-ExponentialProbing',
42220440,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-IgnoreProbesLowerThanNetworkStateEstimate',
42220543,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-InitialProbing',
42220440,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-InjectedCongestionController',
'webrtc:8415',
INDEFINITE),
FieldTrial('WebRTC-Bwe-LimitProbesLowerThanThroughputEstimate',
42221601,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-LossBasedBweV2',
42222865,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-LossBasedControl',
NO_BUG,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-MaxRttLimit',
42234928,
INDEFINITE),
FieldTrial('WebRTC-Bwe-MinAllocAsLowerBound',
NO_BUG,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-NetworkRouteConstraints',
42221535,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-NoFeedbackReset',
42234928,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-PaceAtMaxOfBweAndLowerLinkCapacity',
NO_BUG,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-ProbingBehavior',
42220440,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-ProbingConfiguration',
42220440,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-ReceiveTimeFix',
42234228,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-ReceiverLimitCapsOnly',
42222445,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-RobustThroughputEstimatorSettings',
42220312,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-SafeResetOnRouteChange',
42234928,
INDEFINITE),
FieldTrial('WebRTC-Bwe-SeparateAudioPackets',
42221011,
date(2024, 4, 1)),
FieldTrial('WebRTC-Bwe-TrendlineEstimatorSettings',
42221011,
date(2024, 4, 1)),
FieldTrial('WebRTC-BweBackOffFactor',
42233342,
INDEFINITE),
FieldTrial('WebRTC-BweLossExperiment',
42230863,
date(2024, 4, 1)),
FieldTrial('WebRTC-BweRapidRecoveryExperiment',
42233136,
date(2024, 4, 1)),
FieldTrial('WebRTC-BweThroughputWindowConfig',
42220312,
date(2024, 4, 1)),
FieldTrial('WebRTC-BweWindowSizeInPackets',
42233342,
INDEFINITE),
FieldTrial('WebRTC-CongestionWindow',
42225197,
INDEFINITE),
FieldTrial('WebRTC-CpuLoadEstimator',
42233645,
date(2024, 4, 1)),
FieldTrial('WebRTC-Debugging-RtpDump',
42220735,
INDEFINITE),
FieldTrial('WebRTC-DecoderDataDumpDirectory',
42224491,
INDEFINITE),
FieldTrial('WebRTC-DefaultBitrateLimitsKillSwitch',
NO_BUG,
date(2024, 4, 1)),
FieldTrial('WebRTC-DependencyDescriptorAdvertised',
42220386,
date(2024, 4, 1)),
FieldTrial('WebRTC-DisableUlpFecExperiment',
NO_BUG,
date(2024, 4, 1)),
FieldTrial('WebRTC-DontIncreaseDelayBasedBweInAlr',
42220590,
date(2024, 4, 1)),
FieldTrial('WebRTC-DscpFieldTrial',
42223835,
date(2024, 4, 1)),
FieldTrial('WebRTC-ExtraICEPing',
42220311,
date(2024, 4, 1)),
FieldTrial('WebRTC-FakeNetworkReceiveConfig',
42224493,
INDEFINITE),
FieldTrial('WebRTC-FakeNetworkSendConfig',
42224493,
INDEFINITE),
FieldTrial('WebRTC-FilterAbsSendTimeExtension',
42220271,
INDEFINITE),
FieldTrial('WebRTC-FindNetworkHandleWithoutIpv6TemporaryPart',
42221149,
date(2024, 4, 1)),
FieldTrial('WebRTC-FlexFEC-03',
42230680,
date(2024, 4, 1)),
FieldTrial('WebRTC-FlexFEC-03-Advertised',
42230680,
date(2024, 4, 1)),
FieldTrial('WebRTC-ForcePlayoutDelay',
42222016,
INDEFINITE),
FieldTrial('WebRTC-ForceSendPlayoutDelay',
42222016,
INDEFINITE),
FieldTrial('WebRTC-ForceSimulatedOveruseIntervalMs',
42224494,
INDEFINITE),
FieldTrial('WebRTC-FrameDropper',
42234921,
INDEFINITE),
FieldTrial('WebRTC-FullBandHpfKillSwitch',
42221279,
date(2024, 4, 1)),
FieldTrial('WebRTC-GenericCodecDependencyDescriptor',
42225273,
INDEFINITE),
FieldTrial('WebRTC-GenericDescriptorAdvertised',
42234553,
INDEFINITE),
FieldTrial('WebRTC-GenericDescriptorAuth',
42220132,
INDEFINITE),
FieldTrial('WebRTC-GenericPictureId',
42234553,
INDEFINITE),
FieldTrial('WebRTC-GetEncoderInfoOverride',
NO_BUG,
date(2024, 4, 1)),
FieldTrial('WebRTC-H264HighProfile',
41481030,
date(2024, 4, 1)),
FieldTrial('WebRTC-IPv6Default',
NO_BUG, # chromium:413437
date(2024, 4, 1)),
FieldTrial('WebRTC-IceControllerFieldTrials',
40658968,
INDEFINITE),
FieldTrial('WebRTC-IceFieldTrials',
42221103,
INDEFINITE),
FieldTrial('WebRTC-KeyframeInterval',
42220470,
INDEFINITE),
FieldTrial('WebRTC-LegacyFrameIdJumpBehavior',
42223541,
date(2024, 4, 1)),
FieldTrial('WebRTC-LegacySimulcastLayerLimit',
42233936,
INDEFINITE),
FieldTrial('WebRTC-LowresSimulcastBitrateInterpolation',
42222558,
date(2024, 4, 1)),
FieldTrial('WebRTC-MutedStateKillSwitch',
177830919,
date(2024, 4, 1)),
FieldTrial('WebRTC-Network-UseNWPathMonitor',
42221045,
date(2024, 4, 1)),
FieldTrial('WebRTC-NetworkMonitorAutoDetect',
42223964,
date(2024, 4, 1)),
FieldTrial('WebRTC-NormalizeSimulcastResolution',
NO_BUG,
INDEFINITE),
FieldTrial('WebRTC-Pacer-BlockAudio',
42233548,
INDEFINITE),
FieldTrial('WebRTC-Pacer-DrainQueue',
42233548,
date(2024, 4, 1)),
FieldTrial('WebRTC-Pacer-IgnoreTransportOverhead',
42235102,
INDEFINITE),
FieldTrial('WebRTC-Pacer-PadInSilence',
42233548,
date(2024, 4, 1)),
FieldTrial('WebRTC-PacketBufferMaxSize',
42235070,
INDEFINITE),
FieldTrial('WebRTC-PcFactoryDefaultBitrates',
42220941,
date(2024, 4, 1)),
FieldTrial('WebRTC-PiggybackIceCheckAcknowledgement',
NO_BUG,
date(2024, 4, 1)),
FieldTrial('WebRTC-PixelLimitResource',
42222397,
INDEFINITE),
FieldTrial('WebRTC-ProbingScreenshareBwe',
42232804,
date(2024, 4, 1)),
FieldTrial('WebRTC-ProtectionOverheadRateThreshold',
42225198,
INDEFINITE),
FieldTrial('WebRTC-QpParsingKillSwitch',
42222690,
date(2024, 4, 1)),
FieldTrial('WebRTC-RtcEventLogKillSwitch',
42222210,
INDEFINITE),
FieldTrial('WebRTC-RtcEventLogNewFormat',
42233237,
date(2024, 4, 1)),
FieldTrial('WebRTC-RtcpLossNotification',
42220379,
date(2024, 4, 1)),
FieldTrial('WebRTC-SendBufferSizeBytes',
42222026,
date(2024, 4, 1)),
FieldTrial('WebRTC-SendNackDelayMs',
42235176,
date(2024, 4, 1)),
FieldTrial('WebRTC-SetSocketReceiveBuffer',
42223976,
date(2024, 4, 1)),
FieldTrial('WebRTC-SimulcastEncoderAdapter-GetEncoderInfoOverride',
NO_BUG,
date(2024, 4, 1)),
FieldTrial('WebRTC-SimulcastLayerLimitRoundUp',
NO_BUG,
date(2024, 4, 1)),
FieldTrial('WebRTC-SpsPpsIdrIsH264Keyframe',
42233557,
INDEFINITE),
FieldTrial('WebRTC-StableTargetRate',
42220156,
date(2024, 4, 1)),
FieldTrial('WebRTC-StrictPacingAndProbing',
42233198,
date(2024, 4, 1)),
FieldTrial('WebRTC-StunInterPacketDelay',
NO_BUG,
date(2024, 4, 1)),
FieldTrial('WebRTC-SurfaceCellularTypes',
42221576,
date(2024, 4, 1)),
FieldTrial('WebRTC-SwitchEncoderOnInitializationFailures',
42223783,
date(2024, 4, 1)),
FieldTrial('WebRTC-Target-Bitrate-Rtcp',
42235192,
INDEFINITE),
FieldTrial('WebRTC-TransientSuppressorForcedOff',
40172597,
INDEFINITE),
FieldTrial('WebRTC-UseBaseHeavyVP8TL3RateAllocation',
42234670,
date(2024, 4, 1)),
FieldTrial('WebRTC-UseDifferentiatedCellularCosts',
42221576,
date(2024, 4, 1)),
FieldTrial('WebRTC-UseStandardBytesStats',
42220573,
date(2024, 4, 1)),
FieldTrial('WebRTC-UseTurnServerAsStunServer',
42221142,
date(2024, 4, 1)),
FieldTrial('WebRTC-VP8-ForcePartitionResilience',
42221952,
INDEFINITE),
FieldTrial('WebRTC-VP8-Forced-Fallback-Encoder-v2',
42231704,
INDEFINITE),
FieldTrial('WebRTC-VP8-GetEncoderInfoOverride',
42221952,
INDEFINITE),
FieldTrial('WebRTC-VP8-Postproc-Config',
42221657,
date(2024, 4, 1)),
FieldTrial('WebRTC-VP8-Postproc-Config-Arm',
42231704,
INDEFINITE),
FieldTrial('WebRTC-VP8IosMaxNumberOfThread',
42220027,
date(2024, 4, 1)),
FieldTrial('WebRTC-VP9-GetEncoderInfoOverride',
NO_BUG,
date(2024, 4, 1)),
FieldTrial('WebRTC-VP9-LowTierOptimizations',
42224122,
date(2024, 4, 1)),
FieldTrial('WebRTC-VP9-PerformanceFlags',
42221657,
date(2024, 4, 1)),
FieldTrial('WebRTC-VP9QualityScaler',
42221411,
date(2024, 4, 1)),
FieldTrial('WebRTC-Video-BalancedDegradation',
42232717,
INDEFINITE),
FieldTrial('WebRTC-Video-BalancedDegradationSettings',
NO_BUG,
INDEFINITE),
FieldTrial('WebRTC-Video-DisableAutomaticResize',
42221931,
date(2024, 4, 1)),
FieldTrial('WebRTC-Video-DiscardPacketsWithUnknownSsrc',
42235091,
INDEFINITE),
FieldTrial('WebRTC-Video-ForcedSwDecoderFallback',
NO_BUG,
INDEFINITE),
FieldTrial('WebRTC-Video-InitialDecoderResolution',
42222018,
date(2024, 4, 1)),
FieldTrial('WebRTC-Video-MinVideoBitrate',
42220993,
date(2024, 4, 1)),
FieldTrial('WebRTC-Video-Pacing',
42220062,
date(2024, 4, 1)),
FieldTrial('WebRTC-Video-PreferTemporalSupportOnBaseLayer',
42221417,
INDEFINITE),
FieldTrial('WebRTC-Video-QualityScalerSettings',
NO_BUG,
INDEFINITE),
FieldTrial('WebRTC-Video-QualityScaling',
42234348,
INDEFINITE),
FieldTrial('WebRTC-Video-UseFrameRateForOverhead',
166341943,
date(2024, 4, 1)),
FieldTrial('WebRTC-VideoFrameTrackingIdAdvertised',
42222747,
INDEFINITE),
FieldTrial('WebRTC-VideoLayersAllocationAdvertised',
42222126,
INDEFINITE),
FieldTrial('WebRTC-VideoRateControl',
42220259,
INDEFINITE),
FieldTrial('WebRTC-Vp9ExternalRefCtrl',
42234783,
date(2024, 4, 1)),
FieldTrial('WebRTC-Vp9InterLayerPred',
NO_BUG, # chromium:949536
INDEFINITE),
FieldTrial('WebRTC-Vp9IssueKeyFrameOnLayerDeactivation',
40595338,
date(2024, 4, 1)),
FieldTrial('WebRTC-ZeroPlayoutDelay',
40228487,
date(2024, 4, 1)),
# keep-sorted end
]) # yapf: disable
POLICY_EXEMPT_FIELD_TRIALS_DIGEST: str = \
'32ec47da125c13ceb01a908627c7c10aada3d4dd'
REGISTERED_FIELD_TRIALS: FrozenSet[FieldTrial] = ACTIVE_FIELD_TRIALS.union(
POLICY_EXEMPT_FIELD_TRIALS)
def todays_date() -> date:
now = datetime.datetime.now(datetime.timezone.utc)
return date(now.year, now.month, now.day)
def registry_header(
field_trials: FrozenSet[FieldTrial] = REGISTERED_FIELD_TRIALS) -> str:
"""Generates a C++ header with all field trial keys.
Args:
field_trials: Field trials to include in the header.
Returns:
String representation of a C++ header file containing all field trial
keys.
>>> trials = {
... FieldTrial('B', '', date(1, 1, 1)),
... FieldTrial('A', '', date(1, 1, 1)),
... FieldTrial('B', '', date(2, 2, 2)),
... }
>>> print(registry_header(trials))
// This file was automatically generated. Do not edit.
<BLANKLINE>
#ifndef GEN_REGISTERED_FIELD_TRIALS_H_
#define GEN_REGISTERED_FIELD_TRIALS_H_
<BLANKLINE>
#include "absl/strings/string_view.h"
<BLANKLINE>
namespace webrtc {
<BLANKLINE>
inline constexpr absl::string_view kRegisteredFieldTrials[] = {
"A",
"B",
};
<BLANKLINE>
} // namespace webrtc
<BLANKLINE>
#endif // GEN_REGISTERED_FIELD_TRIALS_H_
<BLANKLINE>
"""
registered_keys = {f.key for f in field_trials}
keys = '\n'.join(f' "{k}",' for k in sorted(registered_keys))
return ('// This file was automatically generated. Do not edit.\n'
'\n'
'#ifndef GEN_REGISTERED_FIELD_TRIALS_H_\n'
'#define GEN_REGISTERED_FIELD_TRIALS_H_\n'
'\n'
'#include "absl/strings/string_view.h"\n'
'\n'
'namespace webrtc {\n'
'\n'
'inline constexpr absl::string_view kRegisteredFieldTrials[] = {\n'
f'{keys}\n'
'};\n'
'\n'
'} // namespace webrtc\n'
'\n'
'#endif // GEN_REGISTERED_FIELD_TRIALS_H_\n')
def expired_field_trials(
threshold: date,
field_trials: FrozenSet[FieldTrial] = REGISTERED_FIELD_TRIALS
) -> Set[FieldTrial]:
"""Obtains expired field trials.
Args:
threshold: Date from which to check end date.
field_trials: Field trials to validate.
Returns:
All expired field trials.
>>> trials = {
... FieldTrial('Expired', '', date(1, 1, 1)),
... FieldTrial('Not-Expired', '', date(1, 1, 2)),
... }
>>> expired_field_trials(date(1, 1, 1), trials)
{FieldTrial(key='Expired', bug='', end_date=datetime.date(1, 1, 1))}
"""
return {f for f in field_trials if f.end_date <= threshold}
def validate_field_trials(
field_trials: FrozenSet[FieldTrial] = ACTIVE_FIELD_TRIALS
) -> List[str]:
"""Validate that field trials conforms to the policy.
Args:
field_trials: Field trials to validate.
Returns:
A list of explanations for invalid field trials.
"""
invalid = []
sha1 = hashlib.sha1()
for trial in sorted(POLICY_EXEMPT_FIELD_TRIALS, key=lambda f: f.key):
sha1.update(trial.key.encode('ascii'))
if sha1.hexdigest() != POLICY_EXEMPT_FIELD_TRIALS_DIGEST:
invalid.append(
'POLICY_EXEMPT_FIELD_TRIALS has been modified. Please note that '
'you must not add any new entries there. If you removed an entry '
'you should also update POLICY_EXEMPT_FIELD_TRIALS_DIGEST. The '
f'new digest is "{sha1.hexdigest()}".')
for trial in field_trials:
if not trial.key.startswith('WebRTC-'):
invalid.append(f'{trial.key} does not start with "WebRTC-".')
if trial.bug_id <= 0:
invalid.append(f'{trial.key} must have an associated bug.')
if trial.end_date >= INDEFINITE:
invalid.append(f'{trial.key} must have an end date.')
return invalid
def cmd_header(args: argparse.Namespace) -> None:
if not args.no_validation:
if errors := validate_field_trials():
print('\n'.join(sorted(errors)))
sys.exit(1)
args.output.write(registry_header())
def cmd_expired(args: argparse.Namespace) -> None:
today = todays_date()
diff = datetime.timedelta(days=args.in_days)
expired = expired_field_trials(
today + diff,
ACTIVE_FIELD_TRIALS if args.no_exempt else REGISTERED_FIELD_TRIALS)
if len(expired) <= 0:
return
expired_by_date = sorted(expired, key=lambda f: (f.end_date, f.key))
print('\n'.join(
f'{f.key} '
f'{f"<{f.bug_url()}> " if f.bug_url() else ""}'
f'{"expired" if f.end_date <= today else "expires"} on {f.end_date}'
for f in expired_by_date))
if any(f.end_date <= today for f in expired_by_date):
sys.exit(1)
def cmd_validate(args: argparse.Namespace) -> None:
del args
invalid = validate_field_trials()
if len(invalid) <= 0:
return
print('\n'.join(sorted(invalid)))
sys.exit(1)
def main() -> None:
parser = argparse.ArgumentParser()
subcommand = parser.add_subparsers(dest='cmd')
parser_header = subcommand.add_parser(
'header',
help='generate C++ header file containing registered field trial keys')
parser_header.add_argument('--output',
default=sys.stdout,
type=argparse.FileType('w'),
required=False,
help='output file')
parser_header.add_argument(
'--no-validation',
default=False,
action='store_true',
required=False,
help='whether to validate the field trials before writing')
parser_header.set_defaults(cmd=cmd_header)
parser_expired = subcommand.add_parser(
'expired',
help='lists all expired field trials',
description='''
Lists all expired field trials. Exits with a non-zero exit status if
any field trials has expired, ignoring the --in-days argument.
''')
parser_expired.add_argument(
'--no-exempt',
default=False,
action='store_true',
required=False,
help='whether to include policy exempt field trials')
parser_expired.add_argument(
'--in-days',
default=0,
type=int,
required=False,
help='number of days relative to today to check')
parser_expired.set_defaults(cmd=cmd_expired)
parser_validate = subcommand.add_parser(
'validate',
help='validates that all field trials conforms to the policy.',
description='''
Validates that all field trials conforms to the policy. Exits with a
non-zero exit status if any field trials does not.
''')
parser_validate.set_defaults(cmd=cmd_validate)
args = parser.parse_args()
if not args.cmd:
parser.print_help(sys.stderr)
sys.exit(1)
args.cmd(args)
if __name__ == '__main__':
main()