зеркало из https://github.com/microsoft/msquic.git
Add ECN support: ECN validation (#3168)
This PR implements 13.4.2. ECN Validation in RFC9000. The ECN validation algorithm implemented in this PR is very similar to the sample algorithm given in RFC9000 A.4. The details can be found at the top of path.h. This PR also adds a new global QUIC setting, EcnEnabled and a flag, EcnCapable, in connection stats. This PR does not implement CC ECN reaction, which will be done in a separate PR.
This commit is contained in:
Родитель
52144efbc6
Коммит
22e14863c4
|
@ -60,6 +60,7 @@ The following settings are available via registry as well as via [QUIC_SETTINGS]
|
|||
| Max Binding Stateless Operations | uint16_t | MaxBindingStatelessOperations | 100 | The maximum number of stateless operations that may be queued on a binding at any one time. |
|
||||
| Stateless Operation Expiration | uint16_t | StatelessOperationExpirationMs | 100 | The time limit between operations for the same endpoint, in milliseconds. |
|
||||
| Congestion Control Algorithm | uint16_t | CongestionControlAlgorithm | 0 (Cubic) | The congestion control algorithm used for the connection. |
|
||||
| ECN | uint8_t | EcnEnabled | 0 (FALSE) | Enable sender-side ECN support. |
|
||||
|
||||
The types map to registry types as follows:
|
||||
- `uint64_t` is a `REG_QWORD`.
|
||||
|
|
|
@ -44,7 +44,8 @@ typedef struct QUIC_SETTINGS {
|
|||
uint64_t MtuDiscoveryMissingProbeCount : 1;
|
||||
uint64_t DestCidUpdateIdleTimeoutMs : 1;
|
||||
uint64_t GreaseQuicBitEnabled : 1;
|
||||
uint64_t RESERVED : 31;
|
||||
uint64_t EcnEnabled : 1;
|
||||
uint64_t RESERVED : 30;
|
||||
} IsSet;
|
||||
};
|
||||
|
||||
|
@ -78,7 +79,7 @@ typedef struct QUIC_SETTINGS {
|
|||
uint8_t DatagramReceiveEnabled : 1;
|
||||
uint8_t ServerResumptionLevel : 2; // QUIC_SERVER_RESUMPTION_LEVEL
|
||||
uint8_t GreaseQuicBitEnabled : 1;
|
||||
uint8_t RESERVED : 1;
|
||||
uint8_t EcnEnabled : 1;
|
||||
uint8_t MaxOperationsPerDrain;
|
||||
uint8_t MtuDiscoveryMissingProbeCount;
|
||||
uint32_t DestCidUpdateIdleTimeoutMs;
|
||||
|
@ -296,6 +297,12 @@ Advertise support for QUIC Grease Bit Extension. Both sides of a connection need
|
|||
|
||||
**Default value:** 0 (`FALSE`)
|
||||
|
||||
`EcnEnabled`
|
||||
|
||||
Enable sender-side ECN support. The connection will validate and react to ECN feedback from peer.
|
||||
|
||||
**Default value:** 0 (`FALSE`)
|
||||
|
||||
# Remarks
|
||||
|
||||
When setting new values for the settings, the app must set the corresponding `.IsSet.*` parameter for each actual parameter that is being set or updated. For example:
|
||||
|
|
|
@ -634,6 +634,11 @@ QuicConnTraceRundownOper(
|
|||
"[conn][%p] Assigned worker: %p",
|
||||
Connection,
|
||||
Connection->Worker);
|
||||
QuicTraceEvent(
|
||||
ConnEcnCapable,
|
||||
"[conn][%p] Ecn: IsCapable=%hu",
|
||||
Connection,
|
||||
Connection->Paths[0].EcnValidationState == ECN_VALIDATION_CAPABLE);
|
||||
CXPLAT_DBG_ASSERT(Connection->Registration);
|
||||
QuicTraceEvent(
|
||||
ConnRegistered,
|
||||
|
@ -5942,6 +5947,7 @@ QuicConnResetIdleTimeout(
|
|||
)
|
||||
{
|
||||
uint64_t IdleTimeoutMs;
|
||||
QUIC_PATH* Path = &Connection->Paths[0];
|
||||
if (Connection->State.Connected) {
|
||||
//
|
||||
// Use the (non-zero) min value between local and peer's configuration.
|
||||
|
@ -5964,7 +5970,7 @@ QuicConnResetIdleTimeout(
|
|||
uint32_t MinIdleTimeoutMs =
|
||||
US_TO_MS(QuicLossDetectionComputeProbeTimeout(
|
||||
&Connection->LossDetection,
|
||||
&Connection->Paths[0],
|
||||
Path,
|
||||
QUIC_CLOSE_PTO_COUNT));
|
||||
if (IdleTimeoutMs < MinIdleTimeoutMs) {
|
||||
IdleTimeoutMs = MinIdleTimeoutMs;
|
||||
|
@ -6667,6 +6673,7 @@ QuicConnGetV2Statistics(
|
|||
Stats->ResumptionAttempted = Connection->Stats.ResumptionAttempted;
|
||||
Stats->ResumptionSucceeded = Connection->Stats.ResumptionSucceeded;
|
||||
Stats->GreaseBitNegotiated = Connection->Stats.GreaseBitNegotiated;
|
||||
Stats->EcnCapable = Path->EcnValidationState == ECN_VALIDATION_CAPABLE;
|
||||
Stats->Rtt = Path->SmoothedRtt;
|
||||
Stats->MinRtt = Path->MinRtt;
|
||||
Stats->MaxRtt = Path->MaxRtt;
|
||||
|
@ -7170,6 +7177,11 @@ QuicConnApplyNewSettings(
|
|||
Connection->State.FixedBit = (RandomValue % 2);
|
||||
Connection->Stats.GreaseBitNegotiated = TRUE;
|
||||
}
|
||||
|
||||
if (Connection->Settings.EcnEnabled) {
|
||||
QUIC_PATH* Path = &Connection->Paths[0];
|
||||
Path->EcnValidationState = ECN_VALIDATION_TESTING;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t PeerStreamType =
|
||||
|
|
|
@ -1299,7 +1299,8 @@ QuicLossDetectionProcessAckBlocks(
|
|||
_In_ QUIC_ENCRYPT_LEVEL EncryptLevel,
|
||||
_In_ uint64_t AckDelay,
|
||||
_In_ QUIC_RANGE* AckBlocks,
|
||||
_Out_ BOOLEAN* InvalidAckBlock
|
||||
_Out_ BOOLEAN* InvalidAckBlock,
|
||||
_In_opt_ QUIC_ACK_ECN_EX* Ecn
|
||||
)
|
||||
{
|
||||
QUIC_SENT_PACKET_METADATA* AckedPackets = NULL;
|
||||
|
@ -1432,7 +1433,7 @@ QuicLossDetectionProcessAckBlocks(
|
|||
|
||||
uint64_t LargestAckedPacketNum = 0;
|
||||
BOOLEAN IsLargestAckedPacketAppLimited = FALSE;
|
||||
|
||||
int64_t EcnEctCounter = 0;
|
||||
QUIC_SENT_PACKET_METADATA* AckedPacketsIterator = AckedPackets;
|
||||
|
||||
while (AckedPacketsIterator != NULL) {
|
||||
|
@ -1475,6 +1476,7 @@ QuicLossDetectionProcessAckBlocks(
|
|||
IsLargestAckedPacketAppLimited = Packet->Flags.IsAppLimited;
|
||||
}
|
||||
|
||||
EcnEctCounter += Packet->Flags.EcnEctSet;
|
||||
QuicLossDetectionOnPacketAcknowledged(LossDetection, EncryptLevel, Packet, FALSE, (uint32_t)TimeNow, AckDelay);
|
||||
}
|
||||
|
||||
|
@ -1496,6 +1498,67 @@ QuicLossDetectionProcessAckBlocks(
|
|||
}
|
||||
|
||||
if (NewLargestAck) {
|
||||
if (Path->EcnValidationState != ECN_VALIDATION_FAILED) {
|
||||
//
|
||||
// Per RFC 9000, we validate ECN counts from received ACK frames
|
||||
// when the largest acked packet number increases.
|
||||
//
|
||||
QUIC_PACKET_SPACE* Packets = Connection->Packets[EncryptLevel];
|
||||
BOOLEAN EcnValidated = TRUE;
|
||||
int64_t EctCeDeltaSum = 0;
|
||||
if (Ecn != NULL) {
|
||||
EctCeDeltaSum += Ecn->CE_Count - Packets->EcnCeCounter;
|
||||
EctCeDeltaSum += Ecn->ECT_0_Count - Packets->EcnEctCounter;
|
||||
//
|
||||
// Conditions where ECN validation fails:
|
||||
// 1. Reneging ECN counts from the peer.
|
||||
// 2. ECN counts do not match the marks that were applied to the packets sent.
|
||||
//
|
||||
if (EctCeDeltaSum < 0 ||
|
||||
EctCeDeltaSum < EcnEctCounter ||
|
||||
Ecn->ECT_1_Count != 0 ||
|
||||
Connection->Send.NumPacketsSentWithEct < Ecn->ECT_0_Count) {
|
||||
EcnValidated = FALSE;
|
||||
} else {
|
||||
//
|
||||
// TODO: Notify CC of the ECN signal before we update the CE counts.
|
||||
//
|
||||
Packets->EcnCeCounter = Ecn->CE_Count;
|
||||
Packets->EcnEctCounter = Ecn->ECT_0_Count;
|
||||
if (Path->EcnValidationState <= ECN_VALIDATION_UNKNOWN) {
|
||||
Path->EcnValidationState = ECN_VALIDATION_CAPABLE;
|
||||
QuicTraceEvent(
|
||||
ConnEcnCapable,
|
||||
"[conn][%p] Ecn: IsCapable=%hu",
|
||||
Connection,
|
||||
TRUE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// If an ACK frame newly acknowledges a packet that the endpoint sent
|
||||
// with either the ECT(0) or ECT(1) codepoint set, ECN validation fails
|
||||
// if the corresponding ECN counts are not present in the ACK frame.
|
||||
//
|
||||
if (EcnEctCounter != 0) {
|
||||
EcnValidated = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!EcnValidated) {
|
||||
QuicTraceEvent(
|
||||
ConnEcnFailed,
|
||||
"[conn][%p][%d] ECN failed: EctCnt %llu CeCnt %llu TxEct %llu DeltaSum %lld State %hu",
|
||||
Connection,
|
||||
EncryptLevel,
|
||||
Packets->EcnEctCounter, Packets->EcnCeCounter,
|
||||
Connection->Send.NumPacketsSentWithEct,
|
||||
EctCeDeltaSum,
|
||||
Path->EcnValidationState);
|
||||
Path->EcnValidationState = ECN_VALIDATION_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Handle packet loss (and any possible congestion events) before
|
||||
// data acknowledgement so that we have an accurate bytes in flight
|
||||
|
@ -1595,7 +1658,6 @@ QuicLossDetectionProcessAckFrame(
|
|||
|
||||
} else {
|
||||
|
||||
// TODO - Use ECN information.
|
||||
AckDelay <<= Connection->PeerTransportParams.AckDelayExponent;
|
||||
|
||||
QuicLossDetectionProcessAckBlocks(
|
||||
|
@ -1604,7 +1666,8 @@ QuicLossDetectionProcessAckFrame(
|
|||
EncryptLevel,
|
||||
AckDelay,
|
||||
&Connection->DecodedAckRanges,
|
||||
InvalidFrame);
|
||||
InvalidFrame,
|
||||
FrameType == QUIC_FRAME_ACK_1 ? &Ecn : NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -258,7 +258,7 @@ QuicPacketBuilderPrepare(
|
|||
Builder->SendData =
|
||||
CxPlatSendDataAlloc(
|
||||
Builder->Path->Binding->Socket,
|
||||
CXPLAT_ECN_NON_ECT,
|
||||
Builder->EcnEctSet ? CXPLAT_ECN_ECT_0 : CXPLAT_ECN_NON_ECT,
|
||||
IsPathMtuDiscovery ?
|
||||
0 :
|
||||
MaxUdpPayloadSizeForFamily(
|
||||
|
@ -927,7 +927,7 @@ QuicPacketBuilderFinalize(
|
|||
Builder->Metadata->SentTime = CxPlatTimeUs32();
|
||||
Builder->Metadata->PacketLength =
|
||||
Builder->HeaderLength + PayloadLength;
|
||||
|
||||
Builder->Metadata->Flags.EcnEctSet = Builder->EcnEctSet;
|
||||
QuicTraceEvent(
|
||||
ConnPacketSent,
|
||||
"[conn][%p][TX][%llu] %hhu (%hu bytes)",
|
||||
|
@ -963,6 +963,9 @@ Exit:
|
|||
|
||||
if (FinalQuicPacket) {
|
||||
if (Builder->Datagram != NULL) {
|
||||
if (Builder->Metadata->Flags.EcnEctSet) {
|
||||
++Connection->Send.NumPacketsSentWithEct;
|
||||
}
|
||||
Builder->Datagram->Length = Builder->DatagramLength;
|
||||
Builder->Datagram = NULL;
|
||||
++Builder->TotalCountDatagrams;
|
||||
|
|
|
@ -73,6 +73,11 @@ typedef struct QUIC_PACKET_BUILDER {
|
|||
//
|
||||
uint8_t BatchCount : 4;
|
||||
|
||||
//
|
||||
// Indicates whether ECN ECT bit is set on the packets to be sent.
|
||||
//
|
||||
uint8_t EcnEctSet : 1;
|
||||
|
||||
//
|
||||
// The total number of datagrams that have been created.
|
||||
//
|
||||
|
|
|
@ -62,6 +62,12 @@ typedef struct QUIC_PACKET_SPACE {
|
|||
//
|
||||
uint64_t NextRecvPacketNumber;
|
||||
|
||||
//
|
||||
// ECT and CE counters.
|
||||
//
|
||||
uint64_t EcnEctCounter;
|
||||
uint64_t EcnCeCounter; // maps to ecn_ce_counters in RFC 9002.
|
||||
|
||||
//
|
||||
// Owning connection of this packet space.
|
||||
//
|
||||
|
|
|
@ -31,7 +31,8 @@ QuicPathInitialize(
|
|||
Path->Mtu = Connection->Settings.MinimumMtu;
|
||||
Path->SmoothedRtt = MS_TO_US(Connection->Settings.InitialRttMs);
|
||||
Path->RttVariance = Path->SmoothedRtt / 2;
|
||||
|
||||
Path->EcnValidationState =
|
||||
Connection->Settings.EcnEnabled ? ECN_VALIDATION_TESTING : ECN_VALIDATION_FAILED;
|
||||
QuicTraceLogConnInfo(
|
||||
PathInitialized,
|
||||
Connection,
|
||||
|
|
|
@ -5,6 +5,40 @@
|
|||
|
||||
--*/
|
||||
|
||||
//
|
||||
// ECN validation state transition:
|
||||
//
|
||||
// ECN_VALIDATION_TESTING: when a new path is created AND ECN is enabled.
|
||||
//
|
||||
// ECN_VALIDATION_TESTING -> ECN_VALIDATION_UNKNOWN: after sending packets with ECT bit set for 3 PTOs.
|
||||
//
|
||||
// {ECN_VALIDATION_TESTING | ECN_VALIDATION_UNKNOWN} -> ECN_VALIDATION_CAPABLE:
|
||||
// when ECN validation passes.
|
||||
//
|
||||
// {ANY} -> ECN_VALIDATION_FAILED: when ECN validation fails.
|
||||
//
|
||||
// In ECN_VALIDATION_TESTING or ECN_VALIDATION_CAPABLE state, packets sent are marked with ECT bit.
|
||||
//
|
||||
// This algorithm is a slightly simplified and relaxed version of the sample ECN validation in
|
||||
// RFC9000 A.4. The main differences are:
|
||||
//
|
||||
// 1. Our algorithm can transition into capable state right from testing state if ECN validation passes.
|
||||
//
|
||||
// 2. The sample algorithm fails ECN validation when all packets sent in testing are considered lost.
|
||||
// Our algorithm does not do that. However, in that case, our algorithm stays in unknown state, where
|
||||
// we send packets without ECT mark, which is effectively the same as failing the validation.
|
||||
//
|
||||
|
||||
//
|
||||
// Different state of ECN validation for the network path.
|
||||
//
|
||||
typedef enum ECN_VALIDATION_STATE {
|
||||
ECN_VALIDATION_TESTING,
|
||||
ECN_VALIDATION_UNKNOWN,
|
||||
ECN_VALIDATION_CAPABLE,
|
||||
ECN_VALIDATION_FAILED, // or not enabled by the app.
|
||||
} ECN_VALIDATION_STATE;
|
||||
|
||||
//
|
||||
// Represents all the per-path information of a connection.
|
||||
//
|
||||
|
@ -67,6 +101,16 @@ typedef struct QUIC_PATH {
|
|||
//
|
||||
uint8_t PartitionUpdated : 1;
|
||||
|
||||
//
|
||||
// ECN validation state.
|
||||
//
|
||||
uint8_t EcnValidationState : 2;
|
||||
|
||||
//
|
||||
// The ending time of ECN validation testing state in microseconds.
|
||||
//
|
||||
uint64_t EcnTestingEndingTime;
|
||||
|
||||
//
|
||||
// The currently calculated path MTU.
|
||||
//
|
||||
|
|
|
@ -506,6 +506,11 @@ CXPLAT_STATIC_ASSERT(
|
|||
//
|
||||
#define QUIC_DEFAULT_GREASE_QUIC_BIT_ENABLED FALSE
|
||||
|
||||
//
|
||||
// The default value for enabling sender-side ECN support.
|
||||
//
|
||||
#define QUIC_DEFAULT_ECN_ENABLED FALSE
|
||||
|
||||
/*************************************************************
|
||||
TRANSPORT PARAMETERS
|
||||
*************************************************************/
|
||||
|
@ -575,6 +580,7 @@ CXPLAT_STATIC_ASSERT(
|
|||
#define QUIC_SETTING_MIGRATION_ENABLED "MigrationEnabled"
|
||||
#define QUIC_SETTING_DATAGRAM_RECEIVE_ENABLED "DatagramReceiveEnabled"
|
||||
#define QUIC_SETTING_GREASE_QUIC_BIT_ENABLED "GreaseQuicBitEnabled"
|
||||
#define QUIC_SETTING_ECN_ENABLED "EcnEnabled"
|
||||
|
||||
#define QUIC_SETTING_INITIAL_WINDOW_PACKETS "InitialWindowPackets"
|
||||
#define QUIC_SETTING_SEND_IDLE_TIMEOUT_MS "SendIdleTimeoutMs"
|
||||
|
|
|
@ -1196,6 +1196,28 @@ QuicSendFlush(
|
|||
}
|
||||
_Analysis_assume_(Builder.Metadata != NULL);
|
||||
|
||||
if (Builder.Path->EcnValidationState == ECN_VALIDATION_CAPABLE) {
|
||||
Builder.EcnEctSet = TRUE;
|
||||
} else if (Builder.Path->EcnValidationState == ECN_VALIDATION_TESTING) {
|
||||
if (Builder.Path->EcnTestingEndingTime != 0) {
|
||||
if (!CxPlatTimeAtOrBefore64(TimeNow, Builder.Path->EcnTestingEndingTime)) {
|
||||
Builder.Path->EcnValidationState = ECN_VALIDATION_UNKNOWN;
|
||||
QuicTraceLogConnInfo(
|
||||
EcnValidationUnknown,
|
||||
Connection,
|
||||
"ECN unknown.");
|
||||
}
|
||||
} else {
|
||||
uint32_t ThreePtosInUs =
|
||||
QuicLossDetectionComputeProbeTimeout(
|
||||
&Connection->LossDetection,
|
||||
&Connection->Paths[0],
|
||||
QUIC_CLOSE_PTO_COUNT);
|
||||
Builder.Path->EcnTestingEndingTime = TimeNow + ThreePtosInUs;
|
||||
}
|
||||
Builder.EcnEctSet = TRUE;
|
||||
}
|
||||
|
||||
QuicTraceEvent(
|
||||
ConnFlushSend,
|
||||
"[conn][%p] Flushing Send. Allowance=%u bytes",
|
||||
|
|
|
@ -255,6 +255,12 @@ typedef struct QUIC_SEND {
|
|||
//
|
||||
uint64_t LastFlushTime;
|
||||
|
||||
//
|
||||
// The total number of packets sent with each corresponding ECT codepoint in all encryption
|
||||
// level.
|
||||
//
|
||||
uint64_t NumPacketsSentWithEct;
|
||||
|
||||
//
|
||||
// The value we send in MAX_DATA frames.
|
||||
//
|
||||
|
|
|
@ -94,6 +94,7 @@ typedef struct QUIC_SEND_PACKET_FLAGS {
|
|||
//
|
||||
BOOLEAN IsAppLimited : 1;
|
||||
BOOLEAN HasLastAckedPacketInfo : 1;
|
||||
BOOLEAN EcnEctSet : 1;
|
||||
#if DEBUG
|
||||
BOOLEAN Freed : 1;
|
||||
#endif
|
||||
|
|
|
@ -135,6 +135,9 @@ QuicSettingsSetDefault(
|
|||
if (!Settings->IsSet.GreaseQuicBitEnabled) {
|
||||
Settings->GreaseQuicBitEnabled = QUIC_DEFAULT_GREASE_QUIC_BIT_ENABLED;
|
||||
}
|
||||
if (!Settings->IsSet.EcnEnabled) {
|
||||
Settings->EcnEnabled = QUIC_DEFAULT_ECN_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
|
@ -270,6 +273,9 @@ QuicSettingsCopy(
|
|||
if (!Destination->IsSet.GreaseQuicBitEnabled) {
|
||||
Destination->GreaseQuicBitEnabled = Source->GreaseQuicBitEnabled;
|
||||
}
|
||||
if (!Destination->IsSet.EcnEnabled) {
|
||||
Destination->EcnEnabled = Source->EcnEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
|
@ -343,7 +349,7 @@ BOOLEAN
|
|||
QuicSettingApply(
|
||||
_Inout_ QUIC_SETTINGS_INTERNAL* Destination,
|
||||
_In_ BOOLEAN OverWrite,
|
||||
_In_ BOOLEAN AllowMtuChanges,
|
||||
_In_ BOOLEAN AllowMtuAndEcnChanges,
|
||||
_In_reads_bytes_(sizeof(QUIC_SETTINGS_INTERNAL))
|
||||
const QUIC_SETTINGS_INTERNAL* Source
|
||||
)
|
||||
|
@ -499,7 +505,7 @@ QuicSettingApply(
|
|||
}
|
||||
}
|
||||
|
||||
if (AllowMtuChanges) {
|
||||
if (AllowMtuAndEcnChanges) {
|
||||
uint16_t MinimumMtu =
|
||||
Destination->IsSet.MinimumMtu ? Destination->MinimumMtu : QUIC_DPLPMTUD_MIN_MTU;
|
||||
uint16_t MaximumMtu =
|
||||
|
@ -568,6 +574,15 @@ QuicSettingApply(
|
|||
Destination->IsSet.GreaseQuicBitEnabled = TRUE;
|
||||
}
|
||||
|
||||
if (AllowMtuAndEcnChanges) {
|
||||
if (Source->IsSet.EcnEnabled && (!Destination->IsSet.EcnEnabled || OverWrite)) {
|
||||
Destination->EcnEnabled = Source->EcnEnabled;
|
||||
Destination->IsSet.EcnEnabled = TRUE;
|
||||
}
|
||||
} else if (Source->IsSet.EcnEnabled) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1129,6 +1144,16 @@ VersionSettingsFail:
|
|||
&ValueLen);
|
||||
Settings->GreaseQuicBitEnabled = !!Value;
|
||||
}
|
||||
if (!Settings->IsSet.EcnEnabled) {
|
||||
Value = QUIC_DEFAULT_ECN_ENABLED;
|
||||
ValueLen = sizeof(Value);
|
||||
CxPlatStorageReadValue(
|
||||
Storage,
|
||||
QUIC_SETTING_ECN_ENABLED,
|
||||
(uint8_t*)&Value,
|
||||
&ValueLen);
|
||||
Settings->EcnEnabled = !!Value;
|
||||
}
|
||||
}
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
|
@ -1188,6 +1213,7 @@ QuicSettingsDump(
|
|||
QuicTraceLogVerbose(SettingCongestionControlAlgorithm, "[sett] CongestionControlAlgorithm = %hu", Settings->CongestionControlAlgorithm);
|
||||
QuicTraceLogVerbose(SettingDestCidUpdateIdleTimeoutMs, "[sett] DestCidUpdateIdleTimeoutMs = %u", Settings->DestCidUpdateIdleTimeoutMs);
|
||||
QuicTraceLogVerbose(SettingGreaseQuicBitEnabled, "[sett] GreaseQuicBitEnabled = %hhu", Settings->GreaseQuicBitEnabled);
|
||||
QuicTraceLogVerbose(SettingEcnEnabled, "[sett] EcnEnabled = %hhu", Settings->EcnEnabled);
|
||||
}
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
|
@ -1319,6 +1345,9 @@ QuicSettingsDumpNew(
|
|||
if (Settings->IsSet.GreaseQuicBitEnabled) {
|
||||
QuicTraceLogVerbose(SettingGreaseQuicBitEnabled, "[sett] GreaseQuicBitEnabled = %hhu", Settings->GreaseQuicBitEnabled);
|
||||
}
|
||||
if (Settings->IsSet.EcnEnabled) {
|
||||
QuicTraceLogVerbose(SettingEcnEnabled, "[sett] EcnEnabled = %hhu", Settings->EcnEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
#define SETTINGS_SIZE_THRU_FIELD(SettingsType, Field) \
|
||||
|
@ -1478,7 +1507,8 @@ QuicSettingsSettingsToInternal(
|
|||
SETTING_COPY_TO_INTERNAL(MigrationEnabled, Settings, InternalSettings);
|
||||
SETTING_COPY_TO_INTERNAL(DatagramReceiveEnabled, Settings, InternalSettings);
|
||||
SETTING_COPY_TO_INTERNAL(ServerResumptionLevel, Settings, InternalSettings);
|
||||
SETTING_COPY_TO_INTERNAL(GreaseQuicBitEnabled, Settings, InternalSettings); // We can't copy it via sized version due to bit field operation not allowed on it.
|
||||
SETTING_COPY_TO_INTERNAL(GreaseQuicBitEnabled, Settings, InternalSettings);
|
||||
SETTING_COPY_TO_INTERNAL(EcnEnabled, Settings, InternalSettings);
|
||||
|
||||
//
|
||||
// N.B. Anything after this needs to be size checked
|
||||
|
@ -1571,7 +1601,8 @@ QuicSettingsGetSettings(
|
|||
SETTING_COPY_FROM_INTERNAL(MigrationEnabled, Settings, InternalSettings);
|
||||
SETTING_COPY_FROM_INTERNAL(DatagramReceiveEnabled, Settings, InternalSettings);
|
||||
SETTING_COPY_FROM_INTERNAL(ServerResumptionLevel, Settings, InternalSettings);
|
||||
SETTING_COPY_FROM_INTERNAL(GreaseQuicBitEnabled, Settings, InternalSettings); // We can't copy it via sized version due to bit field operation not allowed on it.
|
||||
SETTING_COPY_FROM_INTERNAL(GreaseQuicBitEnabled, Settings, InternalSettings);
|
||||
SETTING_COPY_FROM_INTERNAL(EcnEnabled, Settings, InternalSettings);
|
||||
|
||||
//
|
||||
// N.B. Anything after this needs to be size checked
|
||||
|
|
|
@ -51,7 +51,8 @@ typedef struct QUIC_SETTINGS_INTERNAL {
|
|||
uint64_t CongestionControlAlgorithm : 1;
|
||||
uint64_t DestCidUpdateIdleTimeoutMs : 1;
|
||||
uint64_t GreaseQuicBitEnabled : 1;
|
||||
uint64_t RESERVED : 27;
|
||||
uint64_t EcnEnabled : 1;
|
||||
uint64_t RESERVED : 26;
|
||||
} IsSet;
|
||||
};
|
||||
|
||||
|
@ -84,6 +85,7 @@ typedef struct QUIC_SETTINGS_INTERNAL {
|
|||
uint8_t ServerResumptionLevel : 2; // QUIC_SERVER_RESUMPTION_LEVEL
|
||||
uint8_t VersionNegotiationExtEnabled : 1;
|
||||
uint8_t GreaseQuicBitEnabled : 1;
|
||||
uint8_t EcnEnabled : 1;
|
||||
QUIC_VERSION_SETTINGS* VersionSettings;
|
||||
uint16_t MinimumMtu;
|
||||
uint16_t MaximumMtu;
|
||||
|
@ -123,7 +125,7 @@ BOOLEAN
|
|||
QuicSettingApply(
|
||||
_Inout_ QUIC_SETTINGS_INTERNAL* Destination,
|
||||
_In_ BOOLEAN OverWrite,
|
||||
_In_ BOOLEAN AllowMtuChanges,
|
||||
_In_ BOOLEAN AllowMtuAndEcnChanges,
|
||||
_In_reads_bytes_(sizeof(QUIC_SETTINGS_INTERNAL))
|
||||
const QUIC_SETTINGS_INTERNAL* Source
|
||||
);
|
||||
|
|
|
@ -115,6 +115,7 @@ TEST(SettingsTest, TestAllSettingsFieldsSet)
|
|||
SETTINGS_FEATURE_SET_TEST(ServerResumptionLevel, QuicSettingsSettingsToInternal);
|
||||
SETTINGS_FEATURE_SET_TEST(DestCidUpdateIdleTimeoutMs, QuicSettingsSettingsToInternal);
|
||||
SETTINGS_FEATURE_SET_TEST(GreaseQuicBitEnabled, QuicSettingsSettingsToInternal);
|
||||
SETTINGS_FEATURE_SET_TEST(EcnEnabled, QuicSettingsSettingsToInternal);
|
||||
|
||||
Settings.IsSetFlags = 0;
|
||||
Settings.IsSet.RESERVED = ~Settings.IsSet.RESERVED;
|
||||
|
@ -190,6 +191,7 @@ TEST(SettingsTest, TestAllSettingsFieldsGet)
|
|||
SETTINGS_FEATURE_GET_TEST(ServerResumptionLevel, QuicSettingsGetSettings);
|
||||
SETTINGS_FEATURE_GET_TEST(DestCidUpdateIdleTimeoutMs, QuicSettingsGetSettings);
|
||||
SETTINGS_FEATURE_GET_TEST(GreaseQuicBitEnabled, QuicSettingsGetSettings);
|
||||
SETTINGS_FEATURE_GET_TEST(EcnEnabled, QuicSettingsGetSettings);
|
||||
|
||||
Settings.IsSetFlags = 0;
|
||||
Settings.IsSet.RESERVED = ~Settings.IsSet.RESERVED;
|
||||
|
|
|
@ -723,17 +723,31 @@ namespace Microsoft.Quic
|
|||
}
|
||||
}
|
||||
|
||||
[NativeTypeName("uint32_t : 27")]
|
||||
internal uint RESERVED
|
||||
[NativeTypeName("uint32_t : 1")]
|
||||
internal uint EcnCapable
|
||||
{
|
||||
get
|
||||
{
|
||||
return (_bitfield >> 5) & 0x7FFFFFFu;
|
||||
return (_bitfield >> 5) & 0x1u;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_bitfield = (_bitfield & ~(0x7FFFFFFu << 5)) | ((value & 0x7FFFFFFu) << 5);
|
||||
_bitfield = (_bitfield & ~(0x1u << 5)) | ((value & 0x1u) << 5);
|
||||
}
|
||||
}
|
||||
|
||||
[NativeTypeName("uint32_t : 26")]
|
||||
internal uint RESERVED
|
||||
{
|
||||
get
|
||||
{
|
||||
return (_bitfield >> 6) & 0x3FFFFFFu;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_bitfield = (_bitfield & ~(0x3FFFFFFu << 6)) | ((value & 0x3FFFFFFu) << 6);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1145,7 +1159,7 @@ namespace Microsoft.Quic
|
|||
}
|
||||
|
||||
[NativeTypeName("uint8_t : 1")]
|
||||
internal byte RESERVED
|
||||
internal byte EcnEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -1660,17 +1674,31 @@ namespace Microsoft.Quic
|
|||
}
|
||||
}
|
||||
|
||||
[NativeTypeName("uint64_t : 31")]
|
||||
internal ulong RESERVED
|
||||
[NativeTypeName("uint64_t : 1")]
|
||||
internal ulong EcnEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return (_bitfield >> 33) & 0x7FFFFFFFUL;
|
||||
return (_bitfield >> 33) & 0x1UL;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_bitfield = (_bitfield & ~(0x7FFFFFFFUL << 33)) | ((value & 0x7FFFFFFFUL) << 33);
|
||||
_bitfield = (_bitfield & ~(0x1UL << 33)) | ((value & 0x1UL) << 33);
|
||||
}
|
||||
}
|
||||
|
||||
[NativeTypeName("uint64_t : 30")]
|
||||
internal ulong RESERVED
|
||||
{
|
||||
get
|
||||
{
|
||||
return (_bitfield >> 34) & 0x3FFFFFFFUL;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_bitfield = (_bitfield & ~(0x3FFFFFFFUL << 34)) | ((value & 0x3FFFFFFFUL) << 34);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1751,6 +1751,26 @@ tracepoint(CLOG_CONNECTION_C, ConnAssignWorker , arg2, arg3);\
|
|||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
// Decoder Ring for ConnEcnCapable
|
||||
// [conn][%p] Ecn: IsCapable=%hu
|
||||
// QuicTraceEvent(
|
||||
ConnEcnCapable,
|
||||
"[conn][%p] Ecn: IsCapable=%hu",
|
||||
Connection,
|
||||
Connection->Paths[0].EcnValidationState == ECN_VALIDATION_CAPABLE);
|
||||
// arg2 = arg2 = Connection = arg2
|
||||
// arg3 = arg3 = Connection->Paths[0].EcnValidationState == ECN_VALIDATION_CAPABLE = arg3
|
||||
----------------------------------------------------------*/
|
||||
#ifndef _clog_4_ARGS_TRACE_ConnEcnCapable
|
||||
#define _clog_4_ARGS_TRACE_ConnEcnCapable(uniqueId, encoded_arg_string, arg2, arg3)\
|
||||
tracepoint(CLOG_CONNECTION_C, ConnEcnCapable , arg2, arg3);\
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
// Decoder Ring for ConnVersionSet
|
||||
// [conn][%p] QUIC Version: %u
|
||||
|
|
|
@ -1952,6 +1952,29 @@ TRACEPOINT_EVENT(CLOG_CONNECTION_C, ConnAssignWorker,
|
|||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
// Decoder Ring for ConnEcnCapable
|
||||
// [conn][%p] Ecn: IsCapable=%hu
|
||||
// QuicTraceEvent(
|
||||
ConnEcnCapable,
|
||||
"[conn][%p] Ecn: IsCapable=%hu",
|
||||
Connection,
|
||||
Connection->Paths[0].EcnValidationState == ECN_VALIDATION_CAPABLE);
|
||||
// arg2 = arg2 = Connection = arg2
|
||||
// arg3 = arg3 = Connection->Paths[0].EcnValidationState == ECN_VALIDATION_CAPABLE = arg3
|
||||
----------------------------------------------------------*/
|
||||
TRACEPOINT_EVENT(CLOG_CONNECTION_C, ConnEcnCapable,
|
||||
TP_ARGS(
|
||||
const void *, arg2,
|
||||
unsigned short, arg3),
|
||||
TP_FIELDS(
|
||||
ctf_integer_hex(uint64_t, arg2, arg2)
|
||||
ctf_integer(unsigned short, arg3, arg3)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
// Decoder Ring for ConnVersionSet
|
||||
// [conn][%p] QUIC Version: %u
|
||||
|
|
|
@ -447,6 +447,55 @@ tracepoint(CLOG_LOSS_DETECTION_C, ConnError , arg2, arg3);\
|
|||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
// Decoder Ring for ConnEcnCapable
|
||||
// [conn][%p] Ecn: IsCapable=%hu
|
||||
// QuicTraceEvent(
|
||||
ConnEcnCapable,
|
||||
"[conn][%p] Ecn: IsCapable=%hu",
|
||||
Connection,
|
||||
TRUE);
|
||||
// arg2 = arg2 = Connection = arg2
|
||||
// arg3 = arg3 = TRUE = arg3
|
||||
----------------------------------------------------------*/
|
||||
#ifndef _clog_4_ARGS_TRACE_ConnEcnCapable
|
||||
#define _clog_4_ARGS_TRACE_ConnEcnCapable(uniqueId, encoded_arg_string, arg2, arg3)\
|
||||
tracepoint(CLOG_LOSS_DETECTION_C, ConnEcnCapable , arg2, arg3);\
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
// Decoder Ring for ConnEcnFailed
|
||||
// [conn][%p][%d] ECN failed: EctCnt %llu CeCnt %llu TxEct %llu DeltaSum %lld State %hu
|
||||
// QuicTraceEvent(
|
||||
ConnEcnFailed,
|
||||
"[conn][%p][%d] ECN failed: EctCnt %llu CeCnt %llu TxEct %llu DeltaSum %lld State %hu",
|
||||
Connection,
|
||||
EncryptLevel,
|
||||
Packets->EcnEctCounter, Packets->EcnCeCounter,
|
||||
Connection->Send.NumPacketsSentWithEct,
|
||||
EctCeDeltaSum,
|
||||
Path->EcnValidationState);
|
||||
// arg2 = arg2 = Connection = arg2
|
||||
// arg3 = arg3 = EncryptLevel = arg3
|
||||
// arg4 = arg4 = Packets->EcnEctCounter = arg4
|
||||
// arg5 = arg5 = Packets->EcnCeCounter = arg5
|
||||
// arg6 = arg6 = Connection->Send.NumPacketsSentWithEct = arg6
|
||||
// arg7 = arg7 = EctCeDeltaSum = arg7
|
||||
// arg8 = arg8 = Path->EcnValidationState = arg8
|
||||
----------------------------------------------------------*/
|
||||
#ifndef _clog_9_ARGS_TRACE_ConnEcnFailed
|
||||
#define _clog_9_ARGS_TRACE_ConnEcnFailed(uniqueId, encoded_arg_string, arg2, arg3, arg4, arg5, arg6, arg7, arg8)\
|
||||
tracepoint(CLOG_LOSS_DETECTION_C, ConnEcnFailed , arg2, arg3, arg4, arg5, arg6, arg7, arg8);\
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -486,3 +486,68 @@ TRACEPOINT_EVENT(CLOG_LOSS_DETECTION_C, ConnError,
|
|||
ctf_string(arg3, arg3)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
// Decoder Ring for ConnEcnCapable
|
||||
// [conn][%p] Ecn: IsCapable=%hu
|
||||
// QuicTraceEvent(
|
||||
ConnEcnCapable,
|
||||
"[conn][%p] Ecn: IsCapable=%hu",
|
||||
Connection,
|
||||
TRUE);
|
||||
// arg2 = arg2 = Connection = arg2
|
||||
// arg3 = arg3 = TRUE = arg3
|
||||
----------------------------------------------------------*/
|
||||
TRACEPOINT_EVENT(CLOG_LOSS_DETECTION_C, ConnEcnCapable,
|
||||
TP_ARGS(
|
||||
const void *, arg2,
|
||||
unsigned short, arg3),
|
||||
TP_FIELDS(
|
||||
ctf_integer_hex(uint64_t, arg2, arg2)
|
||||
ctf_integer(unsigned short, arg3, arg3)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
// Decoder Ring for ConnEcnFailed
|
||||
// [conn][%p][%d] ECN failed: EctCnt %llu CeCnt %llu TxEct %llu DeltaSum %lld State %hu
|
||||
// QuicTraceEvent(
|
||||
ConnEcnFailed,
|
||||
"[conn][%p][%d] ECN failed: EctCnt %llu CeCnt %llu TxEct %llu DeltaSum %lld State %hu",
|
||||
Connection,
|
||||
EncryptLevel,
|
||||
Packets->EcnEctCounter, Packets->EcnCeCounter,
|
||||
Connection->Send.NumPacketsSentWithEct,
|
||||
EctCeDeltaSum,
|
||||
Path->EcnValidationState);
|
||||
// arg2 = arg2 = Connection = arg2
|
||||
// arg3 = arg3 = EncryptLevel = arg3
|
||||
// arg4 = arg4 = Packets->EcnEctCounter = arg4
|
||||
// arg5 = arg5 = Packets->EcnCeCounter = arg5
|
||||
// arg6 = arg6 = Connection->Send.NumPacketsSentWithEct = arg6
|
||||
// arg7 = arg7 = EctCeDeltaSum = arg7
|
||||
// arg8 = arg8 = Path->EcnValidationState = arg8
|
||||
----------------------------------------------------------*/
|
||||
TRACEPOINT_EVENT(CLOG_LOSS_DETECTION_C, ConnEcnFailed,
|
||||
TP_ARGS(
|
||||
const void *, arg2,
|
||||
int, arg3,
|
||||
unsigned long long, arg4,
|
||||
unsigned long long, arg5,
|
||||
unsigned long long, arg6,
|
||||
long long, arg7,
|
||||
unsigned short, arg8),
|
||||
TP_FIELDS(
|
||||
ctf_integer_hex(uint64_t, arg2, arg2)
|
||||
ctf_integer(int, arg3, arg3)
|
||||
ctf_integer(uint64_t, arg4, arg4)
|
||||
ctf_integer(uint64_t, arg5, arg5)
|
||||
ctf_integer(uint64_t, arg6, arg6)
|
||||
ctf_integer(int64_t, arg7, arg7)
|
||||
ctf_integer(unsigned short, arg8, arg8)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
#define _clog_MACRO_QuicTraceLogStreamVerbose 1
|
||||
#define QuicTraceLogStreamVerbose(a, ...) _clog_CAT(_clog_ARGN_SELECTOR(__VA_ARGS__), _clog_CAT(_,a(#a, __VA_ARGS__)))
|
||||
#endif
|
||||
#ifndef _clog_MACRO_QuicTraceLogConnInfo
|
||||
#define _clog_MACRO_QuicTraceLogConnInfo 1
|
||||
#define QuicTraceLogConnInfo(a, ...) _clog_CAT(_clog_ARGN_SELECTOR(__VA_ARGS__), _clog_CAT(_,a(#a, __VA_ARGS__)))
|
||||
#endif
|
||||
#ifndef _clog_MACRO_QuicTraceLogConnVerbose
|
||||
#define _clog_MACRO_QuicTraceLogConnVerbose 1
|
||||
#define QuicTraceLogConnVerbose(a, ...) _clog_CAT(_clog_ARGN_SELECTOR(__VA_ARGS__), _clog_CAT(_,a(#a, __VA_ARGS__)))
|
||||
|
@ -71,6 +75,24 @@ tracepoint(CLOG_SEND_C, ClearSendFlags , arg1, arg3);\
|
|||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
// Decoder Ring for EcnValidationUnknown
|
||||
// [conn][%p] ECN unknown.
|
||||
// QuicTraceLogConnInfo(
|
||||
EcnValidationUnknown,
|
||||
Connection,
|
||||
"ECN unknown.");
|
||||
// arg1 = arg1 = Connection = arg1
|
||||
----------------------------------------------------------*/
|
||||
#ifndef _clog_3_ARGS_TRACE_EcnValidationUnknown
|
||||
#define _clog_3_ARGS_TRACE_EcnValidationUnknown(uniqueId, arg1, encoded_arg_string)\
|
||||
tracepoint(CLOG_SEND_C, EcnValidationUnknown , arg1);\
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
// Decoder Ring for ScheduleSendFlags
|
||||
// [conn][%p] Scheduling flags 0x%x to 0x%x
|
||||
|
|
|
@ -51,6 +51,25 @@ TRACEPOINT_EVENT(CLOG_SEND_C, ClearSendFlags,
|
|||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
// Decoder Ring for EcnValidationUnknown
|
||||
// [conn][%p] ECN unknown.
|
||||
// QuicTraceLogConnInfo(
|
||||
EcnValidationUnknown,
|
||||
Connection,
|
||||
"ECN unknown.");
|
||||
// arg1 = arg1 = Connection = arg1
|
||||
----------------------------------------------------------*/
|
||||
TRACEPOINT_EVENT(CLOG_SEND_C, EcnValidationUnknown,
|
||||
TP_ARGS(
|
||||
const void *, arg1),
|
||||
TP_FIELDS(
|
||||
ctf_integer_hex(uint64_t, arg1, arg1)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
// Decoder Ring for ScheduleSendFlags
|
||||
// [conn][%p] Scheduling flags 0x%x to 0x%x
|
||||
|
|
|
@ -647,6 +647,21 @@ tracepoint(CLOG_SETTINGS_C, SettingGreaseQuicBitEnabled , arg2);\
|
|||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
// Decoder Ring for SettingEcnEnabled
|
||||
// [sett] EcnEnabled = %hhu
|
||||
// QuicTraceLogVerbose(SettingEcnEnabled, "[sett] EcnEnabled = %hhu", Settings->EcnEnabled);
|
||||
// arg2 = arg2 = Settings->EcnEnabled = arg2
|
||||
----------------------------------------------------------*/
|
||||
#ifndef _clog_3_ARGS_TRACE_SettingEcnEnabled
|
||||
#define _clog_3_ARGS_TRACE_SettingEcnEnabled(uniqueId, encoded_arg_string, arg2)\
|
||||
tracepoint(CLOG_SETTINGS_C, SettingEcnEnabled , arg2);\
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
// Decoder Ring for SettingsLoadInvalidAcceptableVersion
|
||||
// Invalid AcceptableVersion loaded from storage! 0x%x at position %d
|
||||
|
|
|
@ -666,6 +666,22 @@ TRACEPOINT_EVENT(CLOG_SETTINGS_C, SettingGreaseQuicBitEnabled,
|
|||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
// Decoder Ring for SettingEcnEnabled
|
||||
// [sett] EcnEnabled = %hhu
|
||||
// QuicTraceLogVerbose(SettingEcnEnabled, "[sett] EcnEnabled = %hhu", Settings->EcnEnabled);
|
||||
// arg2 = arg2 = Settings->EcnEnabled = arg2
|
||||
----------------------------------------------------------*/
|
||||
TRACEPOINT_EVENT(CLOG_SETTINGS_C, SettingEcnEnabled,
|
||||
TP_ARGS(
|
||||
unsigned char, arg2),
|
||||
TP_FIELDS(
|
||||
ctf_integer(unsigned char, arg2, arg2)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
// Decoder Ring for SettingsLoadInvalidAcceptableVersion
|
||||
// Invalid AcceptableVersion loaded from storage! 0x%x at position %d
|
||||
|
|
|
@ -473,7 +473,8 @@ typedef struct QUIC_STATISTICS_V2 {
|
|||
uint32_t ResumptionAttempted : 1;
|
||||
uint32_t ResumptionSucceeded : 1;
|
||||
uint32_t GreaseBitNegotiated : 1; // Set if we negotiated the GREASE bit.
|
||||
uint32_t RESERVED : 27;
|
||||
uint32_t EcnCapable : 1;
|
||||
uint32_t RESERVED : 26;
|
||||
uint32_t Rtt; // In microseconds
|
||||
uint32_t MinRtt; // In microseconds
|
||||
uint32_t MaxRtt; // In microseconds
|
||||
|
@ -629,7 +630,8 @@ typedef struct QUIC_SETTINGS {
|
|||
uint64_t MtuDiscoveryMissingProbeCount : 1;
|
||||
uint64_t DestCidUpdateIdleTimeoutMs : 1;
|
||||
uint64_t GreaseQuicBitEnabled : 1;
|
||||
uint64_t RESERVED : 31;
|
||||
uint64_t EcnEnabled : 1;
|
||||
uint64_t RESERVED : 30;
|
||||
} IsSet;
|
||||
};
|
||||
|
||||
|
@ -663,7 +665,7 @@ typedef struct QUIC_SETTINGS {
|
|||
uint8_t DatagramReceiveEnabled : 1;
|
||||
uint8_t ServerResumptionLevel : 2; // QUIC_SERVER_RESUMPTION_LEVEL
|
||||
uint8_t GreaseQuicBitEnabled : 1;
|
||||
uint8_t RESERVED : 1;
|
||||
uint8_t EcnEnabled : 1;
|
||||
uint8_t MaxOperationsPerDrain;
|
||||
uint8_t MtuDiscoveryMissingProbeCount;
|
||||
uint32_t DestCidUpdateIdleTimeoutMs;
|
||||
|
|
|
@ -438,6 +438,7 @@ public:
|
|||
MsQuicSettings& SetCongestionControlAlgorithm(QUIC_CONGESTION_CONTROL_ALGORITHM Cc) { CongestionControlAlgorithm = (uint8_t)Cc; IsSet.CongestionControlAlgorithm = TRUE; return *this; }
|
||||
MsQuicSettings& SetDestCidUpdateIdleTimeoutMs(uint32_t Value) { DestCidUpdateIdleTimeoutMs = Value; IsSet.DestCidUpdateIdleTimeoutMs = TRUE; return *this; }
|
||||
MsQuicSettings& SetGreaseQuicBitEnabled(bool Value) { GreaseQuicBitEnabled = Value; IsSet.GreaseQuicBitEnabled = TRUE; return *this; }
|
||||
MsQuicSettings& SetEcnEnabled(bool Value) { EcnEnabled = Value; IsSet.EcnEnabled = TRUE; return *this; }
|
||||
|
||||
QUIC_STATUS
|
||||
SetGlobal() const noexcept {
|
||||
|
|
|
@ -1936,6 +1936,46 @@
|
|||
name="ID2"
|
||||
/>
|
||||
</template>
|
||||
<template tid="tid_CONN_ECN_CAPABLE">
|
||||
<data
|
||||
inType="win:Pointer"
|
||||
name="Connection"
|
||||
/>
|
||||
<data
|
||||
inType="win:UInt32"
|
||||
name="IsCapable"
|
||||
/>
|
||||
</template>
|
||||
<template tid="tid_CONN_ECN_FAILED">
|
||||
<data
|
||||
inType="win:Pointer"
|
||||
name="Connection"
|
||||
/>
|
||||
<data
|
||||
inType="win:UInt32"
|
||||
name="EncryptLevel"
|
||||
/>
|
||||
<data
|
||||
inType="win:UInt64"
|
||||
name="EcnEctCounter"
|
||||
/>
|
||||
<data
|
||||
inType="win:UInt64"
|
||||
name="EcnCeCounter"
|
||||
/>
|
||||
<data
|
||||
inType="win:UInt64"
|
||||
name="NumPacketsSentWithEct"
|
||||
/>
|
||||
<data
|
||||
inType="win:Int64"
|
||||
name="EctCeDeltaSum"
|
||||
/>
|
||||
<data
|
||||
inType="win:UInt8"
|
||||
name="State"
|
||||
/>
|
||||
</template>
|
||||
</templates>
|
||||
<events>
|
||||
<!-- Don't use value=0 as some parsers don't like it -->
|
||||
|
@ -3020,6 +3060,24 @@
|
|||
template="tid_CONN_BBR"
|
||||
value="5186"
|
||||
/>
|
||||
<event
|
||||
keywords="ut:Connection ut:LowVolume"
|
||||
level="win:Informational"
|
||||
message="$(string.Etw.ConnEcnCapable)"
|
||||
opcode="Connection"
|
||||
symbol="QuicConnEcnCapable"
|
||||
template="tid_CONN_ECN_CAPABLE"
|
||||
value="5187"
|
||||
/>
|
||||
<event
|
||||
keywords="ut:Connection ut:LowVolume"
|
||||
level="win:Informational"
|
||||
message="$(string.Etw.ConnEcnFailed)"
|
||||
opcode="Connection"
|
||||
symbol="QuicConnEcnFailed"
|
||||
template="tid_CONN_ECN_FAILED"
|
||||
value="5188"
|
||||
/>
|
||||
<!-- 6144 - 7167 | Stream Events -->
|
||||
<event
|
||||
keywords="ut:Stream ut:LowVolume ut:RPS"
|
||||
|
@ -4499,6 +4557,14 @@
|
|||
id="Etw.Bbr"
|
||||
value="[conn][%1] BBR: State=%2 RState=%3 CongestionWindow=%4 BytesInFlight=%5 BytesInFlightMax=%6 MinRttEst=%7 EstBw=%8 AppLimited=%9"
|
||||
/>
|
||||
<string
|
||||
id="Etw.ConnEcnCapable"
|
||||
value="[conn][%1] Ecn: IsCapable=%2"
|
||||
/>
|
||||
<string
|
||||
id="Etw.ConnEcnFailed"
|
||||
value="[conn][%1][%2] ECN failed: EctCnt %3 CeCnt %4 TxEct %5 DeltaSum %6 State %7"
|
||||
/>
|
||||
</stringTable>
|
||||
</resources>
|
||||
</localization>
|
||||
|
|
|
@ -1223,6 +1223,58 @@
|
|||
],
|
||||
"macroName": "QuicTraceEvent"
|
||||
},
|
||||
"ConnEcnCapable": {
|
||||
"ModuleProperites": {},
|
||||
"TraceString": "[conn][%p] Ecn: IsCapable=%hu",
|
||||
"UniqueId": "ConnEcnCapable",
|
||||
"splitArgs": [
|
||||
{
|
||||
"DefinationEncoding": "p",
|
||||
"MacroVariableName": "arg2"
|
||||
},
|
||||
{
|
||||
"DefinationEncoding": "hu",
|
||||
"MacroVariableName": "arg3"
|
||||
}
|
||||
],
|
||||
"macroName": "QuicTraceEvent"
|
||||
},
|
||||
"ConnEcnFailed": {
|
||||
"ModuleProperites": {},
|
||||
"TraceString": "[conn][%p][%d] ECN failed: EctCnt %llu CeCnt %llu TxEct %llu DeltaSum %lld State %hu",
|
||||
"UniqueId": "ConnEcnFailed",
|
||||
"splitArgs": [
|
||||
{
|
||||
"DefinationEncoding": "p",
|
||||
"MacroVariableName": "arg2"
|
||||
},
|
||||
{
|
||||
"DefinationEncoding": "d",
|
||||
"MacroVariableName": "arg3"
|
||||
},
|
||||
{
|
||||
"DefinationEncoding": "llu",
|
||||
"MacroVariableName": "arg4"
|
||||
},
|
||||
{
|
||||
"DefinationEncoding": "llu",
|
||||
"MacroVariableName": "arg5"
|
||||
},
|
||||
{
|
||||
"DefinationEncoding": "llu",
|
||||
"MacroVariableName": "arg6"
|
||||
},
|
||||
{
|
||||
"DefinationEncoding": "lld",
|
||||
"MacroVariableName": "arg7"
|
||||
},
|
||||
{
|
||||
"DefinationEncoding": "hu",
|
||||
"MacroVariableName": "arg8"
|
||||
}
|
||||
],
|
||||
"macroName": "QuicTraceEvent"
|
||||
},
|
||||
"ConnError": {
|
||||
"ModuleProperites": {},
|
||||
"TraceString": "[conn][%p] ERROR, %s.",
|
||||
|
@ -3455,6 +3507,46 @@
|
|||
],
|
||||
"macroName": "QuicTraceLogConnVerbose"
|
||||
},
|
||||
"EcnEnabled": {
|
||||
"ModuleProperites": {},
|
||||
"TraceString": "[conn][%p] Updated ECN enabled to %hhu",
|
||||
"UniqueId": "EcnEnabled",
|
||||
"splitArgs": [
|
||||
{
|
||||
"DefinationEncoding": "p",
|
||||
"MacroVariableName": "arg1"
|
||||
},
|
||||
{
|
||||
"DefinationEncoding": "hhu",
|
||||
"MacroVariableName": "arg3"
|
||||
}
|
||||
],
|
||||
"macroName": "QuicTraceLogConnVerbose"
|
||||
},
|
||||
"EcnValidationSuccess": {
|
||||
"ModuleProperites": {},
|
||||
"TraceString": "[conn][%p] ECN succeeded.",
|
||||
"UniqueId": "EcnValidationSuccess",
|
||||
"splitArgs": [
|
||||
{
|
||||
"DefinationEncoding": "p",
|
||||
"MacroVariableName": "arg1"
|
||||
}
|
||||
],
|
||||
"macroName": "QuicTraceLogConnInfo"
|
||||
},
|
||||
"EcnValidationUnknown": {
|
||||
"ModuleProperites": {},
|
||||
"TraceString": "[conn][%p] ECN unknown.",
|
||||
"UniqueId": "EcnValidationUnknown",
|
||||
"splitArgs": [
|
||||
{
|
||||
"DefinationEncoding": "p",
|
||||
"MacroVariableName": "arg1"
|
||||
}
|
||||
],
|
||||
"macroName": "QuicTraceLogConnInfo"
|
||||
},
|
||||
"EncodeMaxDatagramFrameSize": {
|
||||
"ModuleProperites": {},
|
||||
"TraceString": "[conn][%p] TP: Max Datagram Frame Size (%llu bytes)",
|
||||
|
@ -10011,6 +10103,18 @@
|
|||
],
|
||||
"macroName": "QuicTraceLogVerbose"
|
||||
},
|
||||
"SettingEcnEnabled": {
|
||||
"ModuleProperites": {},
|
||||
"TraceString": "[sett] EcnEnabled = %hhu",
|
||||
"UniqueId": "SettingEcnEnabled",
|
||||
"splitArgs": [
|
||||
{
|
||||
"DefinationEncoding": "hhu",
|
||||
"MacroVariableName": "arg2"
|
||||
}
|
||||
],
|
||||
"macroName": "QuicTraceLogVerbose"
|
||||
},
|
||||
"SettingGreaseQuicBitEnabled": {
|
||||
"ModuleProperites": {},
|
||||
"TraceString": "[sett] GreaseQuicBitEnabled = %hhu",
|
||||
|
@ -12419,6 +12523,16 @@
|
|||
"TraceID": "ConnDropPacketEx",
|
||||
"EncodingString": "[conn][%p] DROP packet Value=%llu Dst=%!ADDR! Src=%!ADDR! Reason=%s."
|
||||
},
|
||||
{
|
||||
"UniquenessHash": "9c10f710-84bf-766d-0da5-9e31796cf450",
|
||||
"TraceID": "ConnEcnCapable",
|
||||
"EncodingString": "[conn][%p] Ecn: IsCapable=%hu"
|
||||
},
|
||||
{
|
||||
"UniquenessHash": "5d7016bf-5f7f-7469-48f6-6212e8c8572b",
|
||||
"TraceID": "ConnEcnFailed",
|
||||
"EncodingString": "[conn][%p][%d] ECN failed: EctCnt %llu CeCnt %llu TxEct %llu DeltaSum %lld State %hu"
|
||||
},
|
||||
{
|
||||
"UniquenessHash": "0ebbffbe-69d8-3f2b-949d-d93cdd7f8b99",
|
||||
"TraceID": "ConnError",
|
||||
|
@ -13114,6 +13228,21 @@
|
|||
"TraceID": "DrainCrypto",
|
||||
"EncodingString": "[conn][%p] Draining %u crypto bytes"
|
||||
},
|
||||
{
|
||||
"UniquenessHash": "b978c2f3-b3a9-e423-d442-4860da0dc056",
|
||||
"TraceID": "EcnEnabled",
|
||||
"EncodingString": "[conn][%p] Updated ECN enabled to %hhu"
|
||||
},
|
||||
{
|
||||
"UniquenessHash": "2fd085ac-656c-8e23-9f2f-a7c4116dbe83",
|
||||
"TraceID": "EcnValidationSuccess",
|
||||
"EncodingString": "[conn][%p] ECN succeeded."
|
||||
},
|
||||
{
|
||||
"UniquenessHash": "59a602dd-2f8a-6b1d-4fe2-2ac0c1316f05",
|
||||
"TraceID": "EcnValidationUnknown",
|
||||
"EncodingString": "[conn][%p] ECN unknown."
|
||||
},
|
||||
{
|
||||
"UniquenessHash": "d276c997-5dfb-645e-b54a-7ec567967851",
|
||||
"TraceID": "EncodeMaxDatagramFrameSize",
|
||||
|
@ -15144,6 +15273,11 @@
|
|||
"TraceID": "SettingDumpVersionNegoExtEnabled",
|
||||
"EncodingString": "[sett] Version Negotiation Ext Enabled = %hhu"
|
||||
},
|
||||
{
|
||||
"UniquenessHash": "12ca7216-75fc-41d7-f9ce-3e93bd2fea64",
|
||||
"TraceID": "SettingEcnEnabled",
|
||||
"EncodingString": "[sett] EcnEnabled = %hhu"
|
||||
},
|
||||
{
|
||||
"UniquenessHash": "eb526b83-28f4-1046-57bf-7727ba70f36d",
|
||||
"TraceID": "SettingGreaseQuicBitEnabled",
|
||||
|
|
|
@ -107,7 +107,8 @@ public:
|
|||
MsQuicSettings()
|
||||
.SetDisconnectTimeoutMs(PERF_DEFAULT_DISCONNECT_TIMEOUT)
|
||||
.SetIdleTimeoutMs(HPS_DEFAULT_IDLE_TIMEOUT)
|
||||
.SetCongestionControlAlgorithm(PerfDefaultCongestionControl),
|
||||
.SetCongestionControlAlgorithm(PerfDefaultCongestionControl)
|
||||
.SetEcnEnabled(PerfDefaultEcnEnabled),
|
||||
MsQuicCredentialConfig(
|
||||
QUIC_CREDENTIAL_FLAG_CLIENT |
|
||||
QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION)};
|
||||
|
|
|
@ -41,3 +41,4 @@ Abstract:
|
|||
|
||||
extern QUIC_EXECUTION_PROFILE PerfDefaultExecutionProfile;
|
||||
extern QUIC_CONGESTION_CONTROL_ALGORITHM PerfDefaultCongestionControl;
|
||||
extern uint8_t PerfDefaultEcnEnabled;
|
||||
|
|
|
@ -140,7 +140,8 @@ private:
|
|||
.SetIdleTimeoutMs(PERF_DEFAULT_IDLE_TIMEOUT)
|
||||
.SetSendBufferingEnabled(false)
|
||||
.SetServerResumptionLevel(QUIC_SERVER_RESUME_AND_ZERORTT)
|
||||
.SetCongestionControlAlgorithm(PerfDefaultCongestionControl)};
|
||||
.SetCongestionControlAlgorithm(PerfDefaultCongestionControl)
|
||||
.SetEcnEnabled(PerfDefaultEcnEnabled)};
|
||||
MsQuicListener Listener {Registration, ListenerCallbackStatic, this};
|
||||
QUIC_ADDR LocalAddr;
|
||||
CXPLAT_EVENT* StopEvent {nullptr};
|
||||
|
|
|
@ -168,7 +168,8 @@ public:
|
|||
.SetDisconnectTimeoutMs(PERF_DEFAULT_DISCONNECT_TIMEOUT)
|
||||
.SetIdleTimeoutMs(PERF_DEFAULT_IDLE_TIMEOUT)
|
||||
.SetSendBufferingEnabled(false)
|
||||
.SetCongestionControlAlgorithm(PerfDefaultCongestionControl),
|
||||
.SetCongestionControlAlgorithm(PerfDefaultCongestionControl)
|
||||
.SetEcnEnabled(PerfDefaultEcnEnabled),
|
||||
MsQuicCredentialConfig(
|
||||
QUIC_CREDENTIAL_FLAG_CLIENT |
|
||||
QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION)};
|
||||
|
|
|
@ -27,6 +27,7 @@ char Buffer[BufferLength];
|
|||
PerfBase* TestToRun;
|
||||
QUIC_EXECUTION_PROFILE PerfDefaultExecutionProfile = QUIC_EXECUTION_PROFILE_LOW_LATENCY;
|
||||
QUIC_CONGESTION_CONTROL_ALGORITHM PerfDefaultCongestionControl = QUIC_CONGESTION_CONTROL_ALGORITHM_CUBIC;
|
||||
uint8_t PerfDefaultEcnEnabled = false;
|
||||
|
||||
#include "quic_datapath.h"
|
||||
|
||||
|
@ -97,6 +98,7 @@ PrintHelp(
|
|||
" -exec:<profile> Execution profile to use {lowlat, maxtput, scavenger, realtime}.\n"
|
||||
" -cc:<algo> Congestion control algorithm to use {cubic, bbr}.\n"
|
||||
" -pollidle:<time_us> Amount of time to poll while idle before sleeping (default: 0).\n"
|
||||
" -ecn:<0/1> Enables/disables sender-side ECN support. (def:0)\n"
|
||||
#ifndef _KERNEL_MODE
|
||||
" -cpu:<cpu_index> Specify the processor(s) to use.\n"
|
||||
" -cipher:<value> Decimal value of 1 or more QUIC_ALLOWED_CIPHER_SUITE_FLAGS.\n"
|
||||
|
@ -252,6 +254,8 @@ QuicMainStart(
|
|||
}
|
||||
}
|
||||
|
||||
TryGetValue(argc, argv, "ecn", &PerfDefaultEcnEnabled);
|
||||
|
||||
if (ServerMode) {
|
||||
TestToRun = new(std::nothrow) PerfServer(SelfSignedCredConfig);
|
||||
} else {
|
||||
|
|
|
@ -117,7 +117,8 @@ private:
|
|||
MsQuicSettings()
|
||||
.SetConnFlowControlWindow(PERF_DEFAULT_CONN_FLOW_CONTROL)
|
||||
.SetIdleTimeoutMs(TPUT_DEFAULT_IDLE_TIMEOUT)
|
||||
.SetCongestionControlAlgorithm(PerfDefaultCongestionControl),
|
||||
.SetCongestionControlAlgorithm(PerfDefaultCongestionControl)
|
||||
.SetEcnEnabled(PerfDefaultEcnEnabled),
|
||||
MsQuicCredentialConfig(
|
||||
QUIC_CREDENTIAL_FLAG_CLIENT |
|
||||
QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION)};
|
||||
|
|
|
@ -156,6 +156,8 @@ namespace QuicTrace.DataModel
|
|||
ConnTimerCancel,
|
||||
ConnTimerExpire,
|
||||
ConnBbr,
|
||||
ConnEcnCapable,
|
||||
ConnEcnFailed,
|
||||
|
||||
StreamCreated = 6144,
|
||||
StreamDestroyed,
|
||||
|
|
|
@ -514,6 +514,11 @@ QuicTestStreamBlockUnblockConnFlowControl(
|
|||
_In_ BOOLEAN Bidirectional
|
||||
);
|
||||
|
||||
void
|
||||
QuicTestEcn(
|
||||
_In_ int Family
|
||||
);
|
||||
|
||||
//
|
||||
// QuicDrill tests
|
||||
//
|
||||
|
@ -1146,4 +1151,7 @@ typedef struct {
|
|||
#define IOCTL_QUIC_RUN_STREAM_BLOCK_UNBLOCK_CONN_FLOW_CONTROL \
|
||||
QUIC_CTL_CODE(107, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
|
||||
#define QUIC_MAX_IOCTL_FUNC_CODE 107
|
||||
#define IOCTL_QUIC_RUN_ECN \
|
||||
QUIC_CTL_CODE(108, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
|
||||
#define QUIC_MAX_IOCTL_FUNC_CODE 108
|
||||
|
|
|
@ -508,6 +508,14 @@ TEST_P(WithBool, RejectConnection) {
|
|||
}
|
||||
|
||||
#ifdef QUIC_TEST_DATAPATH_HOOKS_ENABLED
|
||||
TEST_P(WithFamilyArgs, Ecn) {
|
||||
TestLoggerT<ParamType> Logger("Ecn", GetParam());
|
||||
if (TestingKernelMode) {
|
||||
ASSERT_TRUE(DriverClient.Run(IOCTL_QUIC_RUN_ECN, GetParam().Family));
|
||||
} else {
|
||||
QuicTestEcn(GetParam().Family);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(WithFamilyArgs, LocalPathChanges) {
|
||||
TestLoggerT<ParamType> Logger("QuicTestLocalPathChanges", GetParam());
|
||||
|
|
|
@ -479,6 +479,7 @@ size_t QUIC_IOCTL_BUFFER_SIZES[] =
|
|||
sizeof(UINT8),
|
||||
sizeof(UINT8),
|
||||
sizeof(BOOLEAN),
|
||||
sizeof(INT32),
|
||||
};
|
||||
|
||||
CXPLAT_STATIC_ASSERT(
|
||||
|
@ -1318,6 +1319,11 @@ QuicTestCtlEvtIoDeviceControl(
|
|||
QuicTestCtlRun(QuicTestStreamBlockUnblockConnFlowControl(Params->Bidirectional));
|
||||
break;
|
||||
|
||||
case IOCTL_QUIC_RUN_ECN:
|
||||
CXPLAT_FRE_ASSERT(Params != nullptr);
|
||||
QuicTestCtlRun(QuicTestEcn(Params->Family));
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
|
|
|
@ -1903,7 +1903,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
void SettingApplyTests(HQUIC Handle, uint32_t Param, bool AllowMtuChange = true) {
|
||||
void SettingApplyTests(HQUIC Handle, uint32_t Param, bool AllowMtuEcnChanges = true) {
|
||||
struct TestSpec {
|
||||
uint64_t Value;
|
||||
QUIC_STATUS Status;
|
||||
|
@ -2055,8 +2055,22 @@ void SettingApplyTests(HQUIC Handle, uint32_t Param, bool AllowMtuChange = true)
|
|||
sizeof(QUIC_SETTINGS),
|
||||
&Settings);
|
||||
|
||||
TEST_TRUE((AllowMtuChange && Status == QUIC_STATUS_SUCCESS) ||
|
||||
(!AllowMtuChange && Status == QUIC_STATUS_INVALID_PARAMETER));
|
||||
TEST_TRUE((AllowMtuEcnChanges && Status == QUIC_STATUS_SUCCESS) ||
|
||||
(!AllowMtuEcnChanges && Status == QUIC_STATUS_INVALID_PARAMETER));
|
||||
}
|
||||
|
||||
{
|
||||
QUIC_SETTINGS Settings{0};
|
||||
Settings.IsSet.EcnEnabled = TRUE;
|
||||
Settings.EcnEnabled = TRUE;
|
||||
QUIC_STATUS Status =
|
||||
MsQuic->SetParam(
|
||||
Handle,
|
||||
Param,
|
||||
sizeof(QUIC_SETTINGS),
|
||||
&Settings);
|
||||
TEST_TRUE((AllowMtuEcnChanges && Status == QUIC_STATUS_SUCCESS) ||
|
||||
(!AllowMtuEcnChanges && Status == QUIC_STATUS_INVALID_PARAMETER));
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -3458,7 +3472,7 @@ void QuicTestConnectionParam()
|
|||
//
|
||||
{
|
||||
TestScopeLogger LogScope3("After ConnectionStart");
|
||||
// Internally AllowMtuChanges become FALSE
|
||||
// Internally AllowMtuEcnChanges become FALSE
|
||||
MsQuicConnection Connection(Registration);
|
||||
TEST_QUIC_SUCCEEDED(Connection.GetInitStatus());
|
||||
TEST_QUIC_SUCCEEDED(
|
||||
|
|
|
@ -2165,6 +2165,188 @@ QuicTestAbortReceive(
|
|||
TEST_TRUE(RecvContext.ServerStreamShutdown.WaitTimeout(TestWaitTimeout));
|
||||
}
|
||||
|
||||
struct EcnTestContext {
|
||||
CxPlatEvent ServerStreamRecv;
|
||||
CxPlatEvent ServerStreamShutdown;
|
||||
MsQuicStream* ServerStream {nullptr};
|
||||
bool ServerStreamHasShutdown {false};
|
||||
|
||||
static QUIC_STATUS StreamCallback(_In_ MsQuicStream* Stream, _In_opt_ void* Context, _Inout_ QUIC_STREAM_EVENT* Event) {
|
||||
auto TestContext = (EcnTestContext*)Context;
|
||||
if (Event->Type == QUIC_STREAM_EVENT_RECEIVE) {
|
||||
TestContext->ServerStreamRecv.Set();
|
||||
} else if (Event->Type == QUIC_STREAM_EVENT_SHUTDOWN_COMPLETE) {
|
||||
TestContext->ServerStreamHasShutdown = true;
|
||||
TestContext->ServerStreamShutdown.Set();
|
||||
Stream->ConnectionShutdown(1);
|
||||
}
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static QUIC_STATUS ConnCallback(_In_ MsQuicConnection*, _In_opt_ void* Context, _Inout_ QUIC_CONNECTION_EVENT* Event) {
|
||||
auto TestContext = (EcnTestContext*)Context;
|
||||
if (Event->Type == QUIC_CONNECTION_EVENT_PEER_STREAM_STARTED) {
|
||||
TestContext->ServerStream = new(std::nothrow) MsQuicStream(Event->PEER_STREAM_STARTED.Stream, CleanUpAutoDelete, StreamCallback, Context);
|
||||
}
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
QuicTestEcn(
|
||||
_In_ int Family
|
||||
)
|
||||
{
|
||||
QUIC_ADDRESS_FAMILY QuicAddrFamily = (Family == 4) ? QUIC_ADDRESS_FAMILY_INET : QUIC_ADDRESS_FAMILY_INET6;
|
||||
|
||||
//
|
||||
// Postive ECN test.
|
||||
//
|
||||
{
|
||||
TestScopeLogger logScope("Postive ECN test");
|
||||
MsQuicRegistration Registration;
|
||||
TEST_QUIC_SUCCEEDED(Registration.GetInitStatus());
|
||||
|
||||
MsQuicConfiguration ServerConfiguration(Registration, "MsQuicTest", MsQuicSettings().SetPeerUnidiStreamCount(1), ServerSelfSignedCredConfig);
|
||||
TEST_QUIC_SUCCEEDED(ServerConfiguration.GetInitStatus());
|
||||
|
||||
MsQuicConfiguration ClientConfiguration(Registration, "MsQuicTest", MsQuicSettings().SetEcnEnabled(true), MsQuicCredentialConfig());
|
||||
TEST_QUIC_SUCCEEDED(ClientConfiguration.GetInitStatus());
|
||||
|
||||
EcnTestContext Context;
|
||||
MsQuicAutoAcceptListener Listener(Registration, ServerConfiguration, EcnTestContext::ConnCallback, &Context);
|
||||
TEST_QUIC_SUCCEEDED(Listener.GetInitStatus());
|
||||
TEST_QUIC_SUCCEEDED(Listener.Start("MsQuicTest"));
|
||||
QuicAddr ServerLocalAddr;
|
||||
TEST_QUIC_SUCCEEDED(Listener.GetLocalAddr(ServerLocalAddr));
|
||||
|
||||
MsQuicConnection Connection(Registration);
|
||||
TEST_QUIC_SUCCEEDED(Connection.GetInitStatus());
|
||||
TEST_QUIC_SUCCEEDED(Connection.Start(ClientConfiguration, QuicAddrFamily, QUIC_TEST_LOOPBACK_FOR_AF(QuicAddrFamily), ServerLocalAddr.GetPort()));
|
||||
|
||||
MsQuicStream Stream(Connection, QUIC_STREAM_OPEN_FLAG_UNIDIRECTIONAL);
|
||||
TEST_QUIC_SUCCEEDED(Stream.GetInitStatus());
|
||||
|
||||
//
|
||||
// Open a stream, send some data and a FIN.
|
||||
//
|
||||
uint8_t RawBuffer[100];
|
||||
QUIC_BUFFER Buffer { sizeof(RawBuffer), RawBuffer };
|
||||
TEST_QUIC_SUCCEEDED(Stream.Send(&Buffer, 1, QUIC_SEND_FLAG_START | QUIC_SEND_FLAG_FIN));
|
||||
|
||||
TEST_TRUE(Context.ServerStreamRecv.WaitTimeout(TestWaitTimeout));
|
||||
CxPlatSleep(50);
|
||||
|
||||
TEST_TRUE(Context.ServerStreamShutdown.WaitTimeout(TestWaitTimeout));
|
||||
TEST_TRUE(Context.ServerStreamHasShutdown);
|
||||
|
||||
QUIC_STATISTICS_V2 Stats;
|
||||
Connection.GetStatistics(&Stats);
|
||||
TEST_TRUE(Stats.EcnCapable);
|
||||
}
|
||||
|
||||
//
|
||||
// Negative ECN test: network erasing ECT bit or incorrectly modifying ECT bit.
|
||||
//
|
||||
TestScopeLogger logScope1("network erasing ECT bit or incorrectly modifying ECT bit");
|
||||
for (int EcnType = CXPLAT_ECN_NON_ECT; EcnType <= CXPLAT_ECN_ECT_1; ++EcnType) {
|
||||
EcnModifyHelper EctEraser;
|
||||
MsQuicRegistration Registration;
|
||||
TEST_QUIC_SUCCEEDED(Registration.GetInitStatus());
|
||||
|
||||
MsQuicConfiguration ServerConfiguration(Registration, "MsQuicTest", MsQuicSettings().SetPeerUnidiStreamCount(1), ServerSelfSignedCredConfig);
|
||||
TEST_QUIC_SUCCEEDED(ServerConfiguration.GetInitStatus());
|
||||
|
||||
MsQuicConfiguration ClientConfiguration(Registration, "MsQuicTest", MsQuicSettings().SetEcnEnabled(true), MsQuicCredentialConfig());
|
||||
TEST_QUIC_SUCCEEDED(ClientConfiguration.GetInitStatus());
|
||||
|
||||
EcnTestContext Context;
|
||||
MsQuicAutoAcceptListener Listener(Registration, ServerConfiguration, EcnTestContext::ConnCallback, &Context);
|
||||
TEST_QUIC_SUCCEEDED(Listener.GetInitStatus());
|
||||
TEST_QUIC_SUCCEEDED(Listener.Start("MsQuicTest"));
|
||||
QuicAddr ServerLocalAddr;
|
||||
TEST_QUIC_SUCCEEDED(Listener.GetLocalAddr(ServerLocalAddr));
|
||||
|
||||
EctEraser.SetEcnType((CXPLAT_ECN_TYPE)EcnType);
|
||||
MsQuicConnection Connection(Registration);
|
||||
TEST_QUIC_SUCCEEDED(Connection.GetInitStatus());
|
||||
TEST_QUIC_SUCCEEDED(Connection.Start(ClientConfiguration, QuicAddrFamily, QUIC_TEST_LOOPBACK_FOR_AF(QuicAddrFamily), ServerLocalAddr.GetPort()));
|
||||
|
||||
MsQuicStream Stream(Connection, QUIC_STREAM_OPEN_FLAG_UNIDIRECTIONAL);
|
||||
TEST_QUIC_SUCCEEDED(Stream.GetInitStatus());
|
||||
|
||||
//
|
||||
// Open a stream, send some data and a FIN.
|
||||
//
|
||||
uint8_t RawBuffer[100];
|
||||
QUIC_BUFFER Buffer { sizeof(RawBuffer), RawBuffer };
|
||||
TEST_QUIC_SUCCEEDED(Stream.Send(&Buffer, 1, QUIC_SEND_FLAG_START | QUIC_SEND_FLAG_FIN));
|
||||
|
||||
TEST_TRUE(Context.ServerStreamRecv.WaitTimeout(TestWaitTimeout));
|
||||
CxPlatSleep(50);
|
||||
TEST_TRUE(Context.ServerStreamShutdown.WaitTimeout(TestWaitTimeout));
|
||||
|
||||
QUIC_STATISTICS_V2 Stats;
|
||||
Connection.GetStatistics(&Stats);
|
||||
TEST_FALSE(Stats.EcnCapable);
|
||||
}
|
||||
|
||||
//
|
||||
// Negative ECN test: network erasing ECT bit or incorrectly modifying ECT bit after successful ECN validation.
|
||||
//
|
||||
TestScopeLogger logScope2("network erasing ECT bit or incorrectly modifying ECT bit successful ECN validation");
|
||||
for (int EcnType = CXPLAT_ECN_NON_ECT; EcnType <= CXPLAT_ECN_ECT_1; ++EcnType) {
|
||||
MsQuicRegistration Registration;
|
||||
TEST_QUIC_SUCCEEDED(Registration.GetInitStatus());
|
||||
|
||||
MsQuicConfiguration ServerConfiguration(Registration, "MsQuicTest", MsQuicSettings().SetPeerUnidiStreamCount(1), ServerSelfSignedCredConfig);
|
||||
TEST_QUIC_SUCCEEDED(ServerConfiguration.GetInitStatus());
|
||||
|
||||
MsQuicConfiguration ClientConfiguration(Registration, "MsQuicTest", MsQuicSettings().SetEcnEnabled(true), MsQuicCredentialConfig());
|
||||
TEST_QUIC_SUCCEEDED(ClientConfiguration.GetInitStatus());
|
||||
|
||||
EcnTestContext Context;
|
||||
MsQuicAutoAcceptListener Listener(Registration, ServerConfiguration, EcnTestContext::ConnCallback, &Context);
|
||||
TEST_QUIC_SUCCEEDED(Listener.GetInitStatus());
|
||||
TEST_QUIC_SUCCEEDED(Listener.Start("MsQuicTest"));
|
||||
QuicAddr ServerLocalAddr;
|
||||
TEST_QUIC_SUCCEEDED(Listener.GetLocalAddr(ServerLocalAddr));
|
||||
|
||||
MsQuicConnection Connection(Registration);
|
||||
TEST_QUIC_SUCCEEDED(Connection.GetInitStatus());
|
||||
TEST_QUIC_SUCCEEDED(Connection.Start(ClientConfiguration, QuicAddrFamily, QUIC_TEST_LOOPBACK_FOR_AF(QuicAddrFamily), ServerLocalAddr.GetPort()));
|
||||
|
||||
MsQuicStream Stream(Connection, QUIC_STREAM_OPEN_FLAG_UNIDIRECTIONAL);
|
||||
TEST_QUIC_SUCCEEDED(Stream.GetInitStatus());
|
||||
|
||||
//
|
||||
// Open a stream, send some data.
|
||||
//
|
||||
uint8_t RawBuffer[100];
|
||||
QUIC_BUFFER Buffer { sizeof(RawBuffer), RawBuffer };
|
||||
TEST_QUIC_SUCCEEDED(Stream.Send(&Buffer, 1, QUIC_SEND_FLAG_START));
|
||||
TEST_TRUE(Context.ServerStreamRecv.WaitTimeout(TestWaitTimeout));
|
||||
CxPlatSleep(50);
|
||||
QUIC_STATISTICS_V2 Stats;
|
||||
Connection.GetStatistics(&Stats);
|
||||
TEST_TRUE(Stats.EcnCapable);
|
||||
|
||||
//
|
||||
// Send some more data.
|
||||
//
|
||||
EcnModifyHelper EctEraser;
|
||||
EctEraser.SetEcnType((CXPLAT_ECN_TYPE)EcnType);
|
||||
QUIC_BUFFER AnotherBuffer { sizeof(RawBuffer), RawBuffer };
|
||||
TEST_QUIC_SUCCEEDED(Stream.Send(&AnotherBuffer, 1, QUIC_SEND_FLAG_FIN));
|
||||
TEST_TRUE(Context.ServerStreamRecv.WaitTimeout(TestWaitTimeout));
|
||||
CxPlatSleep(50);
|
||||
TEST_TRUE(Context.ServerStreamShutdown.WaitTimeout(TestWaitTimeout));
|
||||
TEST_TRUE(Context.ServerStreamHasShutdown);
|
||||
Connection.GetStatistics(&Stats);
|
||||
TEST_FALSE(Stats.EcnCapable);
|
||||
}
|
||||
}
|
||||
|
||||
struct SlowRecvTestContext {
|
||||
CxPlatEvent ServerStreamRecv;
|
||||
CxPlatEvent ServerStreamShutdown;
|
||||
|
|
|
@ -418,6 +418,23 @@ TestConnection::SetSettings(
|
|||
&value);
|
||||
}
|
||||
|
||||
bool
|
||||
TestConnection::GetEcnEnabled()
|
||||
{
|
||||
return GetSettings().EcnEnabled;
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
TestConnection::SetEcnEnabled(
|
||||
bool value
|
||||
)
|
||||
{
|
||||
QUIC_SETTINGS Settings{0};
|
||||
Settings.EcnEnabled = value;
|
||||
Settings.IsSet.EcnEnabled = TRUE;
|
||||
return SetSettings(Settings);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
TestConnection::GetIdleTimeout()
|
||||
{
|
||||
|
|
|
@ -251,6 +251,9 @@ public:
|
|||
QUIC_STATUS GetRemoteAddr(_Out_ QuicAddr &remoteAddr);
|
||||
QUIC_STATUS SetRemoteAddr(_In_ const QuicAddr &remoteAddr);
|
||||
|
||||
bool GetEcnEnabled();
|
||||
QUIC_STATUS SetEcnEnabled(bool value);
|
||||
|
||||
uint64_t GetIdleTimeout(); // milliseconds
|
||||
QUIC_STATUS SetIdleTimeout(uint64_t value); // milliseconds
|
||||
|
||||
|
|
|
@ -581,6 +581,26 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
struct EcnModifyHelper : public DatapathHook
|
||||
{
|
||||
CXPLAT_ECN_TYPE EcnType = CXPLAT_ECN_NON_ECT;
|
||||
EcnModifyHelper() {
|
||||
DatapathHooks::Instance->AddHook(this);
|
||||
}
|
||||
~EcnModifyHelper() {
|
||||
DatapathHooks::Instance->RemoveHook(this);
|
||||
}
|
||||
void SetEcnType(CXPLAT_ECN_TYPE Type) { EcnType = Type; }
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
BOOLEAN
|
||||
Receive(
|
||||
_Inout_ struct CXPLAT_RECV_DATA* Datagram
|
||||
) {
|
||||
Datagram->TypeOfService = (uint8_t)EcnType;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct RandomLossHelper : public DatapathHook
|
||||
{
|
||||
uint8_t LossPercentage;
|
||||
|
|
|
@ -344,6 +344,8 @@ typedef enum QUIC_EVENT_ID_CONNECTION {
|
|||
EventId_QuicConnClientReceivedVersionList,
|
||||
EventId_QuicConnServerSupportedVersionList,
|
||||
EventId_QuicConnBbr,
|
||||
EventId_QuicConnEcnCapable,
|
||||
EventId_QuicConnEcnFailed,
|
||||
|
||||
EventId_QuicConnCount
|
||||
} QUIC_EVENT_ID_CONNECTION;
|
||||
|
|
Загрузка…
Ссылка в новой задаче