diff --git a/docs/Settings.md b/docs/Settings.md index db8dcfa143..8662316bff 100644 --- a/docs/Settings.md +++ b/docs/Settings.md @@ -31,7 +31,10 @@ The following settings are available via registry as well as via [QUIC_SETTINGS] | Idle Timeout | uint64_t | IdleTimeoutMs | 30,000 | How long a connection can go idle before it is silently shut down. 0 to disable timeout | | Max TLS Send Buffer (Client) | uint32_t | TlsClientMaxSendBuffer | 4,096 | How much client TLS data to buffer. | | Max TLS Send Buffer (Server) | uint32_t | TlsServerMaxSendBuffer | 8,192 | How much server TLS data to buffer. | -| Stream Receive Window | uint32_t | StreamRecvWindowDefault | 32,768 | Initial stream receive window size. | +| Stream Receive Window | uint32_t | StreamRecvWindowDefault | 65,536 | Initial stream receive window size for all stream types. | +| Stream Receive Window (Bidirectional, locally created) | uint32_t | StreamRecvWindowBidiLocalDefault | - | If set, overrides stream receive window size for locally initiated bidirectional streams. | +| Stream Receive Window (Bidirectional, remotely created) | uint32_t | StreamRecvWindowBidiRemoteDefault | - | If set, overrides stream receive window size for remote initiated bidirectional streams. | +| Stream Receive Window (Unidirectional) | uint32_t | StreamRecvWindowUnidiDefault | - | If set, overrides stream receive window size for remote initiated unidirectional streams. | | Stream Receive Buffer | uint32_t | StreamRecvBufferDefault | 4,096 | Stream initial buffer size. | | Flow Control Window | uint32_t | ConnFlowControlWindow | 16,777,216 | Connection-wide flow control window. | | Max Stateless Operations | uint32_t | MaxStatelessOperations | 16 | The maximum number of stateless operations that may be queued on a worker at any one time. | diff --git a/docs/api/QUIC_SETTINGS.md b/docs/api/QUIC_SETTINGS.md index f761380355..4000763bf7 100644 --- a/docs/api/QUIC_SETTINGS.md +++ b/docs/api/QUIC_SETTINGS.md @@ -45,7 +45,18 @@ typedef struct QUIC_SETTINGS { uint64_t DestCidUpdateIdleTimeoutMs : 1; uint64_t GreaseQuicBitEnabled : 1; uint64_t EcnEnabled : 1; - uint64_t RESERVED : 30; + uint64_t HyStartEnabled : 1; + uint64_t StreamRecvWindowBidiLocalDefault : 1; + uint64_t StreamRecvWindowBidiRemoteDefault : 1; + uint64_t StreamRecvWindowUnidiDefault : 1; +#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES + uint64_t EncryptionOffloadAllowed : 1; + uint64_t ReliableResetEnabled : 1; + uint64_t OneWayDelayEnabled : 1; + uint64_t RESERVED : 23; +#else + uint64_t RESERVED : 26; +#endif } IsSet; }; @@ -83,6 +94,23 @@ typedef struct QUIC_SETTINGS { uint8_t MaxOperationsPerDrain; uint8_t MtuDiscoveryMissingProbeCount; uint32_t DestCidUpdateIdleTimeoutMs; + union { + uint64_t Flags; + struct { + uint64_t HyStartEnabled : 1; +#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES + uint64_t EncryptionOffloadAllowed : 1; + uint64_t ReliableResetEnabled : 1; + uint64_t OneWayDelayEnabled : 1; + uint64_t ReservedFlags : 60; +#else + uint64_t ReservedFlags : 63; +#endif + }; + }; + uint32_t StreamRecvWindowBidiLocalDefault; + uint32_t StreamRecvWindowBidiRemoteDefault; + uint32_t StreamRecvWindowUnidiDefault; } QUIC_SETTINGS; ``` @@ -125,9 +153,9 @@ How much server TLS data to buffer. If the application expects very large serve `StreamRecvWindowDefault` -Initial stream receive window size. +Initial stream receive flow control window size. This applies to all stream types. Limits for specific stream types can be set using `StreamRecvWindowBidirLocalDefault`, `StreamRecvWindowBidirRemoteDefault` and `StreamRecvWindowUnidirDefault`. The value must be a power of 2. -**Default value:** 32,768 +**Default value:** 65,536 `StreamRecvBufferDefault` @@ -303,6 +331,24 @@ Enable sender-side ECN support. The connection will validate and react to ECN fe **Default value:** 0 (`FALSE`) +`StreamRecvWindowBidirLocalDefault` + +Initial stream receive flow control window size for locally initiated bidirectional streams. If set, this value overwrites the `StreamRecvWindowDefault`. + +**Default value:** 0 (no overwrite) + +`StreamRecvWindowBidirRemoteDefault` + +Initial stream receive flow control window size for remotely initiated bidirectional streams. If set, this value overwrites the `StreamRecvWindowDefault`. + +**Default value:** 0 (no overwrite) + +`StreamRecvWindowUnidiDefault` + +Initial stream receive flow control window size for remotely initiated unidirectional streams. If set, this value overwrites the `StreamRecvWindowDefault`. + +**Default value:** 0 (no overwrite) + # 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: diff --git a/src/core/connection.c b/src/core/connection.c index fc7370452d..8ce96c4517 100644 --- a/src/core/connection.c +++ b/src/core/connection.c @@ -2198,9 +2198,9 @@ QuicConnRecvResumptionTicket( // if (ResumedTP.ActiveConnectionIdLimit > QUIC_ACTIVE_CONNECTION_ID_LIMIT || ResumedTP.InitialMaxData > Connection->Send.MaxData || - ResumedTP.InitialMaxStreamDataBidiLocal > Connection->Settings.StreamRecvWindowDefault || - ResumedTP.InitialMaxStreamDataBidiRemote > Connection->Settings.StreamRecvWindowDefault || - ResumedTP.InitialMaxStreamDataUni > Connection->Settings.StreamRecvWindowDefault || + ResumedTP.InitialMaxStreamDataBidiLocal > Connection->Settings.StreamRecvWindowBidiLocalDefault || + ResumedTP.InitialMaxStreamDataBidiRemote > Connection->Settings.StreamRecvWindowBidiRemoteDefault || + ResumedTP.InitialMaxStreamDataUni > Connection->Settings.StreamRecvWindowUnidiDefault || ResumedTP.InitialMaxUniStreams > Connection->Streams.Types[STREAM_ID_FLAG_IS_CLIENT | STREAM_ID_FLAG_IS_UNI_DIR].MaxTotalStreamCount || ResumedTP.InitialMaxBidiStreams > Connection->Streams.Types[STREAM_ID_FLAG_IS_CLIENT | STREAM_ID_FLAG_IS_BI_DIR].MaxTotalStreamCount) { // @@ -2344,9 +2344,9 @@ QuicConnGenerateLocalTransportParameters( Link); LocalTP->InitialMaxData = Connection->Send.MaxData; - LocalTP->InitialMaxStreamDataBidiLocal = Connection->Settings.StreamRecvWindowDefault; - LocalTP->InitialMaxStreamDataBidiRemote = Connection->Settings.StreamRecvWindowDefault; - LocalTP->InitialMaxStreamDataUni = Connection->Settings.StreamRecvWindowDefault; + LocalTP->InitialMaxStreamDataBidiLocal = Connection->Settings.StreamRecvWindowBidiLocalDefault; + LocalTP->InitialMaxStreamDataBidiRemote = Connection->Settings.StreamRecvWindowBidiRemoteDefault; + LocalTP->InitialMaxStreamDataUni = Connection->Settings.StreamRecvWindowUnidiDefault; LocalTP->MaxUdpPayloadSize = MaxUdpPayloadSizeFromMTU( CxPlatSocketGetLocalMtu( diff --git a/src/core/quicdef.h b/src/core/quicdef.h index 7c176d08ad..1bc3a450fd 100644 --- a/src/core/quicdef.h +++ b/src/core/quicdef.h @@ -652,6 +652,9 @@ CXPLAT_STATIC_ASSERT( #define QUIC_SETTING_MAX_TLS_CLIENT_SEND_BUFFER "TlsClientMaxSendBuffer" #define QUIC_SETTING_MAX_TLS_SERVER_SEND_BUFFER "TlsServerMaxSendBuffer" #define QUIC_SETTING_STREAM_FC_WINDOW_SIZE "StreamRecvWindowDefault" +#define QUIC_SETTING_STREAM_FC_BIDI_LOCAL_WINDOW_SIZE "StreamRecvWindowBidiLocalDefault" +#define QUIC_SETTING_STREAM_FC_BIDI_REMOTE_WINDOW_SIZE "StreamRecvWindowBidiRemoteDefault" +#define QUIC_SETTING_STREAM_FC_UNIDI_WINDOW_SIZE "StreamRecvWindowUnidiDefault" #define QUIC_SETTING_STREAM_RECV_BUFFER_SIZE "StreamRecvBufferDefault" #define QUIC_SETTING_CONN_FLOW_CONTROL_WINDOW "ConnFlowControlWindow" diff --git a/src/core/settings.c b/src/core/settings.c index 89b6c523c1..940290b153 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -96,6 +96,15 @@ QuicSettingsSetDefault( if (!Settings->IsSet.StreamRecvWindowDefault) { Settings->StreamRecvWindowDefault = QUIC_DEFAULT_STREAM_FC_WINDOW_SIZE; } + if (!Settings->IsSet.StreamRecvWindowBidiLocalDefault) { + Settings->StreamRecvWindowBidiLocalDefault = QUIC_DEFAULT_STREAM_FC_WINDOW_SIZE; + } + if (!Settings->IsSet.StreamRecvWindowBidiRemoteDefault) { + Settings->StreamRecvWindowBidiRemoteDefault = QUIC_DEFAULT_STREAM_FC_WINDOW_SIZE; + } + if (!Settings->IsSet.StreamRecvWindowUnidiDefault) { + Settings->StreamRecvWindowUnidiDefault = QUIC_DEFAULT_STREAM_FC_WINDOW_SIZE; + } if (!Settings->IsSet.StreamRecvBufferDefault) { Settings->StreamRecvBufferDefault = QUIC_DEFAULT_STREAM_RECV_BUFFER_SIZE; } @@ -231,6 +240,15 @@ QuicSettingsCopy( if (!Destination->IsSet.StreamRecvWindowDefault) { Destination->StreamRecvWindowDefault = Source->StreamRecvWindowDefault; } + if (!Destination->IsSet.StreamRecvWindowBidiLocalDefault) { + Destination->StreamRecvWindowBidiLocalDefault = Source->StreamRecvWindowBidiLocalDefault; + } + if (!Destination->IsSet.StreamRecvWindowBidiRemoteDefault) { + Destination->StreamRecvWindowBidiRemoteDefault = Source->StreamRecvWindowBidiRemoteDefault; + } + if (!Destination->IsSet.StreamRecvWindowUnidiDefault) { + Destination->StreamRecvWindowUnidiDefault = Source->StreamRecvWindowUnidiDefault; + } if (!Destination->IsSet.StreamRecvBufferDefault) { Destination->StreamRecvBufferDefault = Source->StreamRecvBufferDefault; } @@ -496,6 +514,40 @@ QuicSettingApply( } Destination->StreamRecvWindowDefault = Source->StreamRecvWindowDefault; Destination->IsSet.StreamRecvWindowDefault = TRUE; + + // + // Also set window size for individual stream types, they will be overwritten by a more specific settings if set + // + if (!Destination->IsSet.StreamRecvWindowBidiLocalDefault || OverWrite) { + Destination->StreamRecvWindowBidiLocalDefault = Source->StreamRecvWindowDefault; + } + if (!Destination->IsSet.StreamRecvWindowBidiRemoteDefault || OverWrite) { + Destination->StreamRecvWindowBidiRemoteDefault = Source->StreamRecvWindowDefault; + } + if (!Destination->IsSet.StreamRecvWindowUnidiDefault || OverWrite) { + Destination->StreamRecvWindowUnidiDefault = Source->StreamRecvWindowDefault; + } + } + if (Source->IsSet.StreamRecvWindowBidiLocalDefault && (!Destination->IsSet.StreamRecvWindowBidiLocalDefault || OverWrite)) { + if (Source->StreamRecvWindowBidiLocalDefault == 0 || (Source->StreamRecvWindowBidiLocalDefault & (Source->StreamRecvWindowBidiLocalDefault - 1)) != 0) { + return FALSE; // Must be power of 2 + } + Destination->StreamRecvWindowBidiLocalDefault = Source->StreamRecvWindowBidiLocalDefault; + Destination->IsSet.StreamRecvWindowBidiLocalDefault = TRUE; + } + if (Source->IsSet.StreamRecvWindowBidiRemoteDefault && (!Destination->IsSet.StreamRecvWindowBidiRemoteDefault || OverWrite)) { + if (Source->StreamRecvWindowBidiRemoteDefault == 0 || (Source->StreamRecvWindowBidiRemoteDefault & (Source->StreamRecvWindowBidiRemoteDefault - 1)) != 0) { + return FALSE; // Must be power of 2 + } + Destination->StreamRecvWindowBidiRemoteDefault = Source->StreamRecvWindowBidiRemoteDefault; + Destination->IsSet.StreamRecvWindowBidiRemoteDefault = TRUE; + } + if (Source->IsSet.StreamRecvWindowUnidiDefault && (!Destination->IsSet.StreamRecvWindowUnidiDefault || OverWrite)) { + if (Source->StreamRecvWindowUnidiDefault == 0 || (Source->StreamRecvWindowUnidiDefault & (Source->StreamRecvWindowUnidiDefault - 1)) != 0) { + return FALSE; // Must be power of 2 + } + Destination->StreamRecvWindowUnidiDefault = Source->StreamRecvWindowUnidiDefault; + Destination->IsSet.StreamRecvWindowUnidiDefault = TRUE; } if (Source->IsSet.StreamRecvBufferDefault && (!Destination->IsSet.StreamRecvBufferDefault || OverWrite)) { if (Source->StreamRecvBufferDefault < QUIC_DEFAULT_STREAM_RECV_BUFFER_SIZE) { @@ -911,6 +963,33 @@ QuicSettingsLoad( &ValueLen); } + if (!Settings->IsSet.StreamRecvWindowBidiLocalDefault) { + ValueLen = sizeof(Settings->StreamRecvWindowBidiLocalDefault); + CxPlatStorageReadValue( + Storage, + QUIC_SETTING_STREAM_FC_BIDI_LOCAL_WINDOW_SIZE, + (uint8_t*)&Settings->StreamRecvWindowBidiLocalDefault, + &ValueLen); + } + + if (!Settings->IsSet.StreamRecvWindowBidiRemoteDefault) { + ValueLen = sizeof(Settings->StreamRecvWindowBidiRemoteDefault); + CxPlatStorageReadValue( + Storage, + QUIC_SETTING_STREAM_FC_BIDI_REMOTE_WINDOW_SIZE, + (uint8_t*)&Settings->StreamRecvWindowBidiRemoteDefault, + &ValueLen); + } + + if (!Settings->IsSet.StreamRecvWindowUnidiDefault) { + ValueLen = sizeof(Settings->StreamRecvWindowUnidiDefault); + CxPlatStorageReadValue( + Storage, + QUIC_SETTING_STREAM_FC_UNIDI_WINDOW_SIZE, + (uint8_t*)&Settings->StreamRecvWindowUnidiDefault, + &ValueLen); + } + if (!Settings->IsSet.StreamRecvBufferDefault) { ValueLen = sizeof(Settings->StreamRecvBufferDefault); CxPlatStorageReadValue( @@ -1291,7 +1370,9 @@ QuicSettingsDump( QuicTraceLogVerbose(SettingDumpTlsClientMaxSendBuffer, "[sett] TlsClientMaxSendBuffer = %u", Settings->TlsClientMaxSendBuffer); QuicTraceLogVerbose(SettingDumpTlsServerMaxSendBuffer, "[sett] TlsServerMaxSendBuffer = %u", Settings->TlsServerMaxSendBuffer); QuicTraceLogVerbose(SettingDumpStreamRecvWindowDefault, "[sett] StreamRecvWindowDefault= %u", Settings->StreamRecvWindowDefault); - QuicTraceLogVerbose(SettingDumpStreamRecvBufferDefault, "[sett] StreamRecvBufferDefault= %u", Settings->StreamRecvBufferDefault); + QuicTraceLogVerbose(SettingDumpStreamRecvWindowBidiLocalDefault, "[sett] StreamRecvWindowBidiLocalDefault = %u", Settings->StreamRecvWindowBidiLocalDefault); + QuicTraceLogVerbose(SettingDumpStreamRecvWindowBidiRemoteDefault, "[sett] StreamRecvWindowBidiRemoteDefault = %u", Settings->StreamRecvWindowBidiRemoteDefault); + QuicTraceLogVerbose(SettingDumpStreamRecvWindowUnidiDefault, "[sett] StreamRecvWindowUnidiDefault = %u", Settings->StreamRecvWindowUnidiDefault); QuicTraceLogVerbose(SettingDumpConnFlowControlWindow, "[sett] ConnFlowControlWindow = %u", Settings->ConnFlowControlWindow); QuicTraceLogVerbose(SettingDumpMaxBytesPerKey, "[sett] MaxBytesPerKey = %llu", Settings->MaxBytesPerKey); QuicTraceLogVerbose(SettingDumpServerResumptionLevel, "[sett] ServerResumptionLevel = %hhu", Settings->ServerResumptionLevel); @@ -1402,6 +1483,15 @@ QuicSettingsDumpNew( if (Settings->IsSet.StreamRecvWindowDefault) { QuicTraceLogVerbose(SettingDumpStreamRecvWindowDefault, "[sett] StreamRecvWindowDefault= %u", Settings->StreamRecvWindowDefault); } + if (Settings->IsSet.StreamRecvWindowBidiLocalDefault) { + QuicTraceLogVerbose(SettingDumpStreamRecvWindowBidiLocalDefault, "[sett] StreamRecvWindowBidiLocalDefault = %u", Settings->StreamRecvWindowBidiLocalDefault); + } + if (Settings->IsSet.StreamRecvWindowBidiRemoteDefault) { + QuicTraceLogVerbose(SettingDumpStreamRecvWindowBidiRemoteDefault, "[sett] StreamRecvWindowBidiRemoteDefault = %u", Settings->StreamRecvWindowBidiRemoteDefault); + } + if (Settings->IsSet.StreamRecvWindowUnidiDefault) { + QuicTraceLogVerbose(SettingDumpStreamRecvWindowUnidiDefault, "[sett] StreamRecvWindowUnidiDefault = %u", Settings->StreamRecvWindowUnidiDefault); + } if (Settings->IsSet.StreamRecvBufferDefault) { QuicTraceLogVerbose(SettingDumpStreamRecvBufferDefault, "[sett] StreamRecvBufferDefault= %u", Settings->StreamRecvBufferDefault); } @@ -1700,6 +1790,27 @@ QuicSettingsSettingsToInternal( SettingsSize, InternalSettings); + SETTING_COPY_TO_INTERNAL_SIZED( + StreamRecvWindowBidiLocalDefault, + QUIC_SETTINGS, + Settings, + SettingsSize, + InternalSettings); + + SETTING_COPY_TO_INTERNAL_SIZED( + StreamRecvWindowBidiRemoteDefault, + QUIC_SETTINGS, + Settings, + SettingsSize, + InternalSettings); + + SETTING_COPY_TO_INTERNAL_SIZED( + StreamRecvWindowUnidiDefault, + QUIC_SETTINGS, + Settings, + SettingsSize, + InternalSettings); + return QUIC_STATUS_SUCCESS; } @@ -1832,6 +1943,26 @@ QuicSettingsGetSettings( *SettingsLength, InternalSettings); + SETTING_COPY_FROM_INTERNAL_SIZED( + StreamRecvWindowBidiLocalDefault, + QUIC_SETTINGS, + Settings, + *SettingsLength, + InternalSettings); + + SETTING_COPY_FROM_INTERNAL_SIZED( + StreamRecvWindowBidiRemoteDefault, + QUIC_SETTINGS, + Settings, + *SettingsLength, + InternalSettings); + + SETTING_COPY_FROM_INTERNAL_SIZED(StreamRecvWindowUnidiDefault, + QUIC_SETTINGS, + Settings, + *SettingsLength, + InternalSettings); + *SettingsLength = CXPLAT_MIN(*SettingsLength, sizeof(QUIC_SETTINGS)); return QUIC_STATUS_SUCCESS; diff --git a/src/core/settings.h b/src/core/settings.h index 2073eb529c..3c94a0f7ed 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -20,6 +20,9 @@ typedef struct QUIC_SETTINGS_INTERNAL { uint64_t TlsClientMaxSendBuffer : 1; uint64_t TlsServerMaxSendBuffer : 1; uint64_t StreamRecvWindowDefault : 1; + uint64_t StreamRecvWindowBidiLocalDefault : 1; + uint64_t StreamRecvWindowBidiRemoteDefault : 1; + uint64_t StreamRecvWindowUnidiDefault : 1; uint64_t StreamRecvBufferDefault : 1; uint64_t ConnFlowControlWindow : 1; uint64_t MaxWorkerQueueDelayUs : 1; @@ -57,7 +60,7 @@ typedef struct QUIC_SETTINGS_INTERNAL { uint64_t EncryptionOffloadAllowed : 1; uint64_t ReliableResetEnabled : 1; uint64_t OneWayDelayEnabled : 1; - uint64_t RESERVED : 21; + uint64_t RESERVED : 18; } IsSet; }; @@ -69,6 +72,9 @@ typedef struct QUIC_SETTINGS_INTERNAL { uint32_t TlsClientMaxSendBuffer; uint32_t TlsServerMaxSendBuffer; uint32_t StreamRecvWindowDefault; + uint32_t StreamRecvWindowBidiLocalDefault; + uint32_t StreamRecvWindowBidiRemoteDefault; + uint32_t StreamRecvWindowUnidiDefault; uint32_t StreamRecvBufferDefault; uint32_t ConnFlowControlWindow; uint32_t MaxWorkerQueueDelayUs; diff --git a/src/core/stream.c b/src/core/stream.c index 5f58c9309c..2de5155393 100644 --- a/src/core/stream.c +++ b/src/core/stream.c @@ -114,11 +114,17 @@ QuicStreamInitialize( } } + const uint32_t FlowControlWindowSize = Stream->Flags.Unidirectional + ? Connection->Settings.StreamRecvWindowUnidiDefault + : OpenedRemotely + ? Connection->Settings.StreamRecvWindowBidiRemoteDefault + : Connection->Settings.StreamRecvWindowBidiLocalDefault; + Status = QuicRecvBufferInitialize( &Stream->RecvBuffer, InitialRecvBufferLength, - Connection->Settings.StreamRecvWindowDefault, + FlowControlWindowSize, FALSE, PreallocatedRecvBuffer); if (QUIC_FAILED(Status)) { diff --git a/src/core/unittest/SettingsTest.cpp b/src/core/unittest/SettingsTest.cpp index 13cf3ab95e..9abc5578d3 100644 --- a/src/core/unittest/SettingsTest.cpp +++ b/src/core/unittest/SettingsTest.cpp @@ -89,6 +89,9 @@ TEST(SettingsTest, TestAllSettingsFieldsSet) SETTINGS_FEATURE_SET_TEST(TlsClientMaxSendBuffer, QuicSettingsSettingsToInternal); SETTINGS_FEATURE_SET_TEST(TlsServerMaxSendBuffer, QuicSettingsSettingsToInternal); SETTINGS_FEATURE_SET_TEST(StreamRecvWindowDefault, QuicSettingsSettingsToInternal); + SETTINGS_FEATURE_SET_TEST(StreamRecvWindowBidiLocalDefault, QuicSettingsSettingsToInternal); + SETTINGS_FEATURE_SET_TEST(StreamRecvWindowBidiRemoteDefault, QuicSettingsSettingsToInternal); + SETTINGS_FEATURE_SET_TEST(StreamRecvWindowUnidiDefault, QuicSettingsSettingsToInternal); SETTINGS_FEATURE_SET_TEST(StreamRecvBufferDefault, QuicSettingsSettingsToInternal); SETTINGS_FEATURE_SET_TEST(ConnFlowControlWindow, QuicSettingsSettingsToInternal); SETTINGS_FEATURE_SET_TEST(MaxWorkerQueueDelayUs, QuicSettingsSettingsToInternal); @@ -170,6 +173,9 @@ TEST(SettingsTest, TestAllSettingsFieldsGet) SETTINGS_FEATURE_GET_TEST(TlsClientMaxSendBuffer, QuicSettingsGetSettings); SETTINGS_FEATURE_GET_TEST(TlsServerMaxSendBuffer, QuicSettingsGetSettings); SETTINGS_FEATURE_GET_TEST(StreamRecvWindowDefault, QuicSettingsGetSettings); + SETTINGS_FEATURE_GET_TEST(StreamRecvWindowBidiLocalDefault, QuicSettingsGetSettings); + SETTINGS_FEATURE_GET_TEST(StreamRecvWindowBidiRemoteDefault, QuicSettingsGetSettings); + SETTINGS_FEATURE_GET_TEST(StreamRecvWindowUnidiDefault, QuicSettingsGetSettings); SETTINGS_FEATURE_GET_TEST(StreamRecvBufferDefault, QuicSettingsGetSettings); SETTINGS_FEATURE_GET_TEST(ConnFlowControlWindow, QuicSettingsGetSettings); SETTINGS_FEATURE_GET_TEST(MaxWorkerQueueDelayUs, QuicSettingsGetSettings); @@ -223,6 +229,83 @@ TEST(SettingsTest, TestAllGlobalSettingsFieldsGet) ASSERT_EQ(FieldCount, (sizeof(Settings.IsSetFlags) * 8) - PopCount(Settings.IsSetFlags)); } +TEST(SettingsTest, StreamRecvWindowDefaultSetsIndividualLimits) +{ + QUIC_SETTINGS_INTERNAL Source; + QUIC_SETTINGS_INTERNAL Destination; + CxPlatZeroMemory(&Source, sizeof(Source)); + CxPlatZeroMemory(&Destination, sizeof(Destination)); + + const uint32_t Limit = 1024; + + Source.IsSet.StreamRecvWindowDefault = 1; + Source.StreamRecvWindowDefault = Limit; + + ASSERT_TRUE(QuicSettingApply(&Destination, TRUE, TRUE, &Source)); + + ASSERT_EQ(Destination.StreamRecvWindowDefault, Limit); + ASSERT_EQ(Destination.StreamRecvWindowBidiLocalDefault, Limit); + ASSERT_EQ(Destination.StreamRecvWindowBidiRemoteDefault, Limit); + ASSERT_EQ(Destination.StreamRecvWindowUnidiDefault, Limit); +} + +TEST(SettingsTest, StreamRecvWindowDefaultDoesNotOverrideIndividualLimitsWhenSetAtDestination) +{ + QUIC_SETTINGS_INTERNAL Source; + QUIC_SETTINGS_INTERNAL Destination; + CxPlatZeroMemory(&Source, sizeof(Source)); + CxPlatZeroMemory(&Destination, sizeof(Destination)); + + const uint32_t Limit = 1024; + const uint32_t Original = 2 * 1024; + + Source.IsSet.StreamRecvWindowDefault = 1; + Source.StreamRecvWindowDefault = Limit; + + Destination.IsSet.StreamRecvWindowBidiLocalDefault = 1; + Destination.StreamRecvWindowBidiLocalDefault = Original; + + Destination.IsSet.StreamRecvWindowBidiRemoteDefault = 1; + Destination.StreamRecvWindowBidiRemoteDefault = Original; + + Destination.IsSet.StreamRecvWindowUnidiDefault = 1; + Destination.StreamRecvWindowUnidiDefault = Original; + + ASSERT_TRUE(QuicSettingApply(&Destination, FALSE /* no override */, TRUE, &Source)); + + ASSERT_EQ(Destination.StreamRecvWindowDefault, Limit); + ASSERT_EQ(Destination.StreamRecvWindowBidiLocalDefault, Original); + ASSERT_EQ(Destination.StreamRecvWindowBidiRemoteDefault, Original); + ASSERT_EQ(Destination.StreamRecvWindowUnidiDefault, Original); +} + +TEST(SettingsTest, StreamRecvWindowDefaultGetsOverridenByIndividualLimits) +{ + QUIC_SETTINGS_INTERNAL Source; + QUIC_SETTINGS_INTERNAL Destination; + CxPlatZeroMemory(&Source, sizeof(Source)); + CxPlatZeroMemory(&Destination, sizeof(Destination)); + + Source.IsSet.StreamRecvWindowDefault = 1; + Source.StreamRecvWindowDefault = 1 * 1024; + + Source.IsSet.StreamRecvWindowBidiLocalDefault = 1; + Source.StreamRecvWindowBidiLocalDefault = 2 * 1024; + + Source.IsSet.StreamRecvWindowBidiRemoteDefault = 1; + Source.StreamRecvWindowBidiRemoteDefault = 4 * 1024; + + Source.IsSet.StreamRecvWindowUnidiDefault = 1; + Source.StreamRecvWindowUnidiDefault = 8 * 1024; + + ASSERT_TRUE(QuicSettingApply(&Destination, TRUE, TRUE, &Source)); + + ASSERT_EQ(Destination.StreamRecvWindowDefault, Source.StreamRecvWindowDefault); + ASSERT_EQ(Destination.StreamRecvWindowBidiLocalDefault, Source.StreamRecvWindowBidiLocalDefault); + ASSERT_EQ(Destination.StreamRecvWindowBidiRemoteDefault, Source.StreamRecvWindowBidiRemoteDefault); + ASSERT_EQ(Destination.StreamRecvWindowUnidiDefault, Source.StreamRecvWindowUnidiDefault); +} + // TEST(SettingsTest, TestAllVersionSettingsFieldsGet) // { // QUIC_VERSION_SETTINGS Settings; diff --git a/src/cs/lib/msquic_generated.cs b/src/cs/lib/msquic_generated.cs index 5f504f9628..b8c0b092df 100644 --- a/src/cs/lib/msquic_generated.cs +++ b/src/cs/lib/msquic_generated.cs @@ -1246,6 +1246,15 @@ internal byte EcnEnabled [NativeTypeName("QUIC_SETTINGS::(anonymous union)")] internal _Anonymous2_e__Union Anonymous2; + [NativeTypeName("uint32_t")] + internal uint StreamRecvWindowBidiLocalDefault; + + [NativeTypeName("uint32_t")] + internal uint StreamRecvWindowBidiRemoteDefault; + + [NativeTypeName("uint32_t")] + internal uint StreamRecvWindowUnidiDefault; + internal ref ulong IsSetFlags { get @@ -1841,7 +1850,7 @@ internal ulong HyStartEnabled } [NativeTypeName("uint64_t : 1")] - internal ulong EncryptionOffloadAllowed + internal ulong StreamRecvWindowBidiLocalDefault { get { @@ -1855,7 +1864,7 @@ internal ulong EncryptionOffloadAllowed } [NativeTypeName("uint64_t : 1")] - internal ulong ReliableResetEnabled + internal ulong StreamRecvWindowBidiRemoteDefault { get { @@ -1869,7 +1878,7 @@ internal ulong ReliableResetEnabled } [NativeTypeName("uint64_t : 1")] - internal ulong OneWayDelayEnabled + internal ulong StreamRecvWindowUnidiDefault { get { @@ -1882,17 +1891,59 @@ internal ulong OneWayDelayEnabled } } - [NativeTypeName("uint64_t : 26")] + [NativeTypeName("uint64_t : 1")] + internal ulong EncryptionOffloadAllowed + { + get + { + return (_bitfield >> 38) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 38)) | ((value & 0x1UL) << 38); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong ReliableResetEnabled + { + get + { + return (_bitfield >> 39) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 39)) | ((value & 0x1UL) << 39); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong OneWayDelayEnabled + { + get + { + return (_bitfield >> 40) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 40)) | ((value & 0x1UL) << 40); + } + } + + [NativeTypeName("uint64_t : 23")] internal ulong RESERVED { get { - return (_bitfield >> 38) & 0x3FFFFFFUL; + return (_bitfield >> 41) & 0x7FFFFFUL; } set { - _bitfield = (_bitfield & ~(0x3FFFFFFUL << 38)) | ((value & 0x3FFFFFFUL) << 38); + _bitfield = (_bitfield & ~(0x7FFFFFUL << 41)) | ((value & 0x7FFFFFUL) << 41); } } } diff --git a/src/generated/linux/settings.c.clog.h b/src/generated/linux/settings.c.clog.h index d40bacbac0..40fd1cc5c0 100644 --- a/src/generated/linux/settings.c.clog.h +++ b/src/generated/linux/settings.c.clog.h @@ -375,14 +375,44 @@ tracepoint(CLOG_SETTINGS_C, SettingDumpStreamRecvWindowDefault , arg2);\ /*---------------------------------------------------------- -// Decoder Ring for SettingDumpStreamRecvBufferDefault -// [sett] StreamRecvBufferDefault= %u -// QuicTraceLogVerbose(SettingDumpStreamRecvBufferDefault, "[sett] StreamRecvBufferDefault= %u", Settings->StreamRecvBufferDefault); -// arg2 = arg2 = Settings->StreamRecvBufferDefault = arg2 +// Decoder Ring for SettingDumpStreamRecvWindowBidiLocalDefault +// [sett] StreamRecvWindowBidiLocalDefault = %u +// QuicTraceLogVerbose(SettingDumpStreamRecvWindowBidiLocalDefault, "[sett] StreamRecvWindowBidiLocalDefault = %u", Settings->StreamRecvWindowBidiLocalDefault); +// arg2 = arg2 = Settings->StreamRecvWindowBidiLocalDefault = arg2 ----------------------------------------------------------*/ -#ifndef _clog_3_ARGS_TRACE_SettingDumpStreamRecvBufferDefault -#define _clog_3_ARGS_TRACE_SettingDumpStreamRecvBufferDefault(uniqueId, encoded_arg_string, arg2)\ -tracepoint(CLOG_SETTINGS_C, SettingDumpStreamRecvBufferDefault , arg2);\ +#ifndef _clog_3_ARGS_TRACE_SettingDumpStreamRecvWindowBidiLocalDefault +#define _clog_3_ARGS_TRACE_SettingDumpStreamRecvWindowBidiLocalDefault(uniqueId, encoded_arg_string, arg2)\ +tracepoint(CLOG_SETTINGS_C, SettingDumpStreamRecvWindowBidiLocalDefault , arg2);\ + +#endif + + + + +/*---------------------------------------------------------- +// Decoder Ring for SettingDumpStreamRecvWindowBidiRemoteDefault +// [sett] StreamRecvWindowBidiRemoteDefault = %u +// QuicTraceLogVerbose(SettingDumpStreamRecvWindowBidiRemoteDefault, "[sett] StreamRecvWindowBidiRemoteDefault = %u", Settings->StreamRecvWindowBidiRemoteDefault); +// arg2 = arg2 = Settings->StreamRecvWindowBidiRemoteDefault = arg2 +----------------------------------------------------------*/ +#ifndef _clog_3_ARGS_TRACE_SettingDumpStreamRecvWindowBidiRemoteDefault +#define _clog_3_ARGS_TRACE_SettingDumpStreamRecvWindowBidiRemoteDefault(uniqueId, encoded_arg_string, arg2)\ +tracepoint(CLOG_SETTINGS_C, SettingDumpStreamRecvWindowBidiRemoteDefault , arg2);\ + +#endif + + + + +/*---------------------------------------------------------- +// Decoder Ring for SettingDumpStreamRecvWindowUnidiDefault +// [sett] StreamRecvWindowUnidiDefault = %u +// QuicTraceLogVerbose(SettingDumpStreamRecvWindowUnidiDefault, "[sett] StreamRecvWindowUnidiDefault = %u", Settings->StreamRecvWindowUnidiDefault); +// arg2 = arg2 = Settings->StreamRecvWindowUnidiDefault = arg2 +----------------------------------------------------------*/ +#ifndef _clog_3_ARGS_TRACE_SettingDumpStreamRecvWindowUnidiDefault +#define _clog_3_ARGS_TRACE_SettingDumpStreamRecvWindowUnidiDefault(uniqueId, encoded_arg_string, arg2)\ +tracepoint(CLOG_SETTINGS_C, SettingDumpStreamRecvWindowUnidiDefault , arg2);\ #endif @@ -752,6 +782,21 @@ tracepoint(CLOG_SETTINGS_C, SettingDumpLFixedServerID , arg2);\ +/*---------------------------------------------------------- +// Decoder Ring for SettingDumpStreamRecvBufferDefault +// [sett] StreamRecvBufferDefault= %u +// QuicTraceLogVerbose(SettingDumpStreamRecvBufferDefault, "[sett] StreamRecvBufferDefault= %u", Settings->StreamRecvBufferDefault); +// arg2 = arg2 = Settings->StreamRecvBufferDefault = arg2 +----------------------------------------------------------*/ +#ifndef _clog_3_ARGS_TRACE_SettingDumpStreamRecvBufferDefault +#define _clog_3_ARGS_TRACE_SettingDumpStreamRecvBufferDefault(uniqueId, encoded_arg_string, arg2)\ +tracepoint(CLOG_SETTINGS_C, SettingDumpStreamRecvBufferDefault , arg2);\ + +#endif + + + + /*---------------------------------------------------------- // Decoder Ring for SettingsLoadInvalidAcceptableVersion // Invalid AcceptableVersion loaded from storage! 0x%x at position %d diff --git a/src/generated/linux/settings.c.clog.h.lttng.h b/src/generated/linux/settings.c.clog.h.lttng.h index 8cdbdd6e0a..e4786c6321 100644 --- a/src/generated/linux/settings.c.clog.h.lttng.h +++ b/src/generated/linux/settings.c.clog.h.lttng.h @@ -370,12 +370,44 @@ TRACEPOINT_EVENT(CLOG_SETTINGS_C, SettingDumpStreamRecvWindowDefault, /*---------------------------------------------------------- -// Decoder Ring for SettingDumpStreamRecvBufferDefault -// [sett] StreamRecvBufferDefault= %u -// QuicTraceLogVerbose(SettingDumpStreamRecvBufferDefault, "[sett] StreamRecvBufferDefault= %u", Settings->StreamRecvBufferDefault); -// arg2 = arg2 = Settings->StreamRecvBufferDefault = arg2 +// Decoder Ring for SettingDumpStreamRecvWindowBidiLocalDefault +// [sett] StreamRecvWindowBidiLocalDefault = %u +// QuicTraceLogVerbose(SettingDumpStreamRecvWindowBidiLocalDefault, "[sett] StreamRecvWindowBidiLocalDefault = %u", Settings->StreamRecvWindowBidiLocalDefault); +// arg2 = arg2 = Settings->StreamRecvWindowBidiLocalDefault = arg2 ----------------------------------------------------------*/ -TRACEPOINT_EVENT(CLOG_SETTINGS_C, SettingDumpStreamRecvBufferDefault, +TRACEPOINT_EVENT(CLOG_SETTINGS_C, SettingDumpStreamRecvWindowBidiLocalDefault, + TP_ARGS( + unsigned int, arg2), + TP_FIELDS( + ctf_integer(unsigned int, arg2, arg2) + ) +) + + + +/*---------------------------------------------------------- +// Decoder Ring for SettingDumpStreamRecvWindowBidiRemoteDefault +// [sett] StreamRecvWindowBidiRemoteDefault = %u +// QuicTraceLogVerbose(SettingDumpStreamRecvWindowBidiRemoteDefault, "[sett] StreamRecvWindowBidiRemoteDefault = %u", Settings->StreamRecvWindowBidiRemoteDefault); +// arg2 = arg2 = Settings->StreamRecvWindowBidiRemoteDefault = arg2 +----------------------------------------------------------*/ +TRACEPOINT_EVENT(CLOG_SETTINGS_C, SettingDumpStreamRecvWindowBidiRemoteDefault, + TP_ARGS( + unsigned int, arg2), + TP_FIELDS( + ctf_integer(unsigned int, arg2, arg2) + ) +) + + + +/*---------------------------------------------------------- +// Decoder Ring for SettingDumpStreamRecvWindowUnidiDefault +// [sett] StreamRecvWindowUnidiDefault = %u +// QuicTraceLogVerbose(SettingDumpStreamRecvWindowUnidiDefault, "[sett] StreamRecvWindowUnidiDefault = %u", Settings->StreamRecvWindowUnidiDefault); +// arg2 = arg2 = Settings->StreamRecvWindowUnidiDefault = arg2 +----------------------------------------------------------*/ +TRACEPOINT_EVENT(CLOG_SETTINGS_C, SettingDumpStreamRecvWindowUnidiDefault, TP_ARGS( unsigned int, arg2), TP_FIELDS( @@ -778,6 +810,22 @@ TRACEPOINT_EVENT(CLOG_SETTINGS_C, SettingDumpLFixedServerID, +/*---------------------------------------------------------- +// Decoder Ring for SettingDumpStreamRecvBufferDefault +// [sett] StreamRecvBufferDefault= %u +// QuicTraceLogVerbose(SettingDumpStreamRecvBufferDefault, "[sett] StreamRecvBufferDefault= %u", Settings->StreamRecvBufferDefault); +// arg2 = arg2 = Settings->StreamRecvBufferDefault = arg2 +----------------------------------------------------------*/ +TRACEPOINT_EVENT(CLOG_SETTINGS_C, SettingDumpStreamRecvBufferDefault, + TP_ARGS( + unsigned int, arg2), + TP_FIELDS( + ctf_integer(unsigned int, arg2, arg2) + ) +) + + + /*---------------------------------------------------------- // Decoder Ring for SettingsLoadInvalidAcceptableVersion // Invalid AcceptableVersion loaded from storage! 0x%x at position %d diff --git a/src/inc/msquic.h b/src/inc/msquic.h index 05a8d488a1..c1e369b520 100644 --- a/src/inc/msquic.h +++ b/src/inc/msquic.h @@ -672,13 +672,16 @@ typedef struct QUIC_SETTINGS { uint64_t GreaseQuicBitEnabled : 1; uint64_t EcnEnabled : 1; uint64_t HyStartEnabled : 1; + uint64_t StreamRecvWindowBidiLocalDefault : 1; + uint64_t StreamRecvWindowBidiRemoteDefault : 1; + uint64_t StreamRecvWindowUnidiDefault : 1; #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES uint64_t EncryptionOffloadAllowed : 1; uint64_t ReliableResetEnabled : 1; uint64_t OneWayDelayEnabled : 1; - uint64_t RESERVED : 26; + uint64_t RESERVED : 23; #else - uint64_t RESERVED : 29; + uint64_t RESERVED : 26; #endif } IsSet; }; @@ -731,6 +734,9 @@ typedef struct QUIC_SETTINGS { #endif }; }; + uint32_t StreamRecvWindowBidiLocalDefault; + uint32_t StreamRecvWindowBidiRemoteDefault; + uint32_t StreamRecvWindowUnidiDefault; } QUIC_SETTINGS; diff --git a/src/manifest/clog.sidecar b/src/manifest/clog.sidecar index 4894ff1428..aa4f7ccf3a 100644 --- a/src/manifest/clog.sidecar +++ b/src/manifest/clog.sidecar @@ -10226,6 +10226,30 @@ ], "macroName": "QuicTraceLogVerbose" }, + "SettingDumpStreamRecvWindowBidiLocalDefault": { + "ModuleProperites": {}, + "TraceString": "[sett] StreamRecvWindowBidiLocalDefault = %u", + "UniqueId": "SettingDumpStreamRecvWindowBidiLocalDefault", + "splitArgs": [ + { + "DefinationEncoding": "u", + "MacroVariableName": "arg2" + } + ], + "macroName": "QuicTraceLogVerbose" + }, + "SettingDumpStreamRecvWindowBidiRemoteDefault": { + "ModuleProperites": {}, + "TraceString": "[sett] StreamRecvWindowBidiRemoteDefault = %u", + "UniqueId": "SettingDumpStreamRecvWindowBidiRemoteDefault", + "splitArgs": [ + { + "DefinationEncoding": "u", + "MacroVariableName": "arg2" + } + ], + "macroName": "QuicTraceLogVerbose" + }, "SettingDumpStreamRecvWindowDefault": { "ModuleProperites": {}, "TraceString": "[sett] StreamRecvWindowDefault= %u", @@ -10238,6 +10262,18 @@ ], "macroName": "QuicTraceLogVerbose" }, + "SettingDumpStreamRecvWindowUnidiDefault": { + "ModuleProperites": {}, + "TraceString": "[sett] StreamRecvWindowUnidiDefault = %u", + "UniqueId": "SettingDumpStreamRecvWindowUnidiDefault", + "splitArgs": [ + { + "DefinationEncoding": "u", + "MacroVariableName": "arg2" + } + ], + "macroName": "QuicTraceLogVerbose" + }, "SettingDumpTlsClientMaxSendBuffer": { "ModuleProperites": {}, "TraceString": "[sett] TlsClientMaxSendBuffer = %u", @@ -15463,11 +15499,26 @@ "TraceID": "SettingDumpStreamRecvBufferDefault", "EncodingString": "[sett] StreamRecvBufferDefault= %u" }, + { + "UniquenessHash": "fdc700fa-3864-c7ad-b206-118edec7df3c", + "TraceID": "SettingDumpStreamRecvWindowBidiLocalDefault", + "EncodingString": "[sett] StreamRecvWindowBidiLocalDefault = %u" + }, + { + "UniquenessHash": "2237fc34-ff7e-3399-8836-01efea9bb06c", + "TraceID": "SettingDumpStreamRecvWindowBidiRemoteDefault", + "EncodingString": "[sett] StreamRecvWindowBidiRemoteDefault = %u" + }, { "UniquenessHash": "2da1de63-c2be-a594-45de-7dd6cb192b7e", "TraceID": "SettingDumpStreamRecvWindowDefault", "EncodingString": "[sett] StreamRecvWindowDefault= %u" }, + { + "UniquenessHash": "fdef2995-409f-a4fe-175f-a592671e0680", + "TraceID": "SettingDumpStreamRecvWindowUnidiDefault", + "EncodingString": "[sett] StreamRecvWindowUnidiDefault = %u" + }, { "UniquenessHash": "4eaf58f9-d813-f2de-2388-6f550e14f27d", "TraceID": "SettingDumpTlsClientMaxSendBuffer",