Some Congestion Control Cleanup (#1989)

* Some Congestion Control Cleanup

* Remove extra space

* Fix clog
This commit is contained in:
Nick Banks 2021-09-15 12:10:45 -04:00 коммит произвёл GitHub
Родитель 10659bbfdf
Коммит 8180438274
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
16 изменённых файлов: 390 добавлений и 498 удалений

Просмотреть файл

@ -11,7 +11,7 @@
"f9ebf01a280eb751180e0b8b554451a4d3fb33eae19bddc931c7ddd7990837d7": {
"signature": "f9ebf01a280eb751180e0b8b554451a4d3fb33eae19bddc931c7ddd7990837d7",
"alternativeSignatures": [],
"target": "src/core/cubic_impl.c",
"target": "src/core/cubic.c",
"memberOf": [
"default"
],
@ -25,7 +25,7 @@
"601218ec80c09584203293e0a12f3d56d4b137a79d77b9a602e3a249274791a7": {
"signature": "601218ec80c09584203293e0a12f3d56d4b137a79d77b9a602e3a249274791a7",
"alternativeSignatures": [],
"target": "src/core/cubic_impl.c",
"target": "src/core/cubic.c",
"memberOf": [
"default"
],

Просмотреть файл

@ -18,6 +18,7 @@ set(SOURCES
connection.c
crypto.c
crypto_tls.c
cubic.c
datagram.c
frame.c
library.c
@ -47,7 +48,6 @@ set(SOURCES
operation.h
stream.h
connection.h
cubic_impl.c
)
if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")

Просмотреть файл

@ -27,106 +27,15 @@ QuicCongestionControlInitialize(
CXPLAT_DBG_ASSERT(Settings->CongestionControlAlgorithm < QUIC_CONGESTION_CONTROL_ALGORITHM_MAX);
switch (Settings->CongestionControlAlgorithm) {
case QUIC_CONGESTION_CONTROL_ALGORITHM_CUBIC: {
CubicCongestionControlInitialize(Cc, Settings);
break;
}
default: {
QUIC_CONNECTION* Connection = QuicCongestionControlGetConnection(Cc);
QuicTraceLogConnWarning(
InvalidCongestionControlAlgorithm,
Connection,
"Unknown congestion control algorithm: %d, fallback to Cubic",
Settings->CongestionControlAlgorithm);
CubicCongestionControlInitialize(Cc, Settings);
break;
}
default:
QuicTraceLogConnWarning(
InvalidCongestionControlAlgorithm,
QuicCongestionControlGetConnection(Cc),
"Unknown congestion control algorithm: %d, fallback to Cubic",
Settings->CongestionControlAlgorithm);
__fallthrough;
case QUIC_CONGESTION_CONTROL_ALGORITHM_CUBIC:
CubicCongestionControlInitialize(Cc, Settings);
break;
}
}
_IRQL_requires_max_(DISPATCH_LEVEL)
void
QuicCongestionControlReset(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ BOOLEAN FullReset
)
{
Cc->QuicCongestionControlReset(Cc, FullReset);
}
_IRQL_requires_max_(DISPATCH_LEVEL)
uint32_t
QuicCongestionControlGetSendAllowance(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint64_t TimeSinceLastSend, // microsec
_In_ BOOLEAN TimeSinceLastSendValid
)
{
return Cc->QuicCongestionControlGetSendAllowance(Cc, TimeSinceLastSend, TimeSinceLastSendValid);
}
_IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicCongestionControlOnDataSent(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint32_t NumRetransmittableBytes
)
{
Cc->QuicCongestionControlOnDataSent(Cc, NumRetransmittableBytes);
}
_IRQL_requires_max_(DISPATCH_LEVEL)
BOOLEAN
QuicCongestionControlOnDataInvalidated(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint32_t NumRetransmittableBytes
)
{
return Cc->QuicCongestionControlOnDataInvalidated(Cc, NumRetransmittableBytes);
}
_IRQL_requires_max_(DISPATCH_LEVEL)
BOOLEAN
QuicCongestionControlOnDataAcknowledged(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint64_t TimeNow, // microsecond
_In_ uint64_t LargestPacketNumberAcked,
_In_ uint32_t NumRetransmittableBytes,
_In_ uint32_t SmoothedRtt
)
{
return Cc->QuicCongestionControlOnDataAcknowledged(
Cc, TimeNow, LargestPacketNumberAcked, NumRetransmittableBytes, SmoothedRtt);
}
_IRQL_requires_max_(DISPATCH_LEVEL)
void
QuicCongestionControlOnDataLost(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint64_t LargestPacketNumberLost,
_In_ uint64_t LargestPacketNumberSent,
_In_ uint32_t NumRetransmittableBytes,
_In_ BOOLEAN PersistentCongestion
)
{
Cc->QuicCongestionControlOnDataLost(
Cc, LargestPacketNumberLost, LargestPacketNumberSent, NumRetransmittableBytes, PersistentCongestion);
}
_IRQL_requires_max_(DISPATCH_LEVEL)
void
QuicCongestionControlOnSpuriousCongestionEvent(
_In_ QUIC_CONGESTION_CONTROL* Cc
)
{
Cc->QuicCongestionControlOnSpuriousCongestionEvent(Cc);
}
_IRQL_requires_max_(DISPATCH_LEVEL)
uint8_t
QuicCongestionControlGetExemptions(
_In_ const QUIC_CONGESTION_CONTROL* Cc
)
{
return Cc->QuicCongestionControlGetExemptions(Cc);
}

Просмотреть файл

@ -7,15 +7,6 @@
#include "cubic.h"
typedef union QUIC_CONGESTION_CONTROL_CONTEXT {
QUIC_CONGESTION_CONTROL_CUBIC CubicCtx;
//
// Add new congestion control context here
//
} QUIC_CONGESTION_CONTROL_CONTEXT;
typedef struct QUIC_CONGESTION_CONTROL {
//
@ -32,11 +23,6 @@ typedef struct QUIC_CONGESTION_CONTROL {
_In_ uint8_t NumPackets
);
void (*QuicCongestionControlInitialize)(
_In_ struct QUIC_CONGESTION_CONTROL* Cc,
_In_ const QUIC_SETTINGS* Settings
);
void (*QuicCongestionControlReset)(
_In_ struct QUIC_CONGESTION_CONTROL* Cc,
_In_ BOOLEAN FullReset
@ -90,14 +76,24 @@ typedef struct QUIC_CONGESTION_CONTROL {
_In_ const struct QUIC_CONGESTION_CONTROL* Cc
);
QUIC_CONGESTION_CONTROL_CONTEXT Ctx;
//
// Algorithm specific state.
//
union {
QUIC_CONGESTION_CONTROL_CUBIC Cubic;
};
} QUIC_CONGESTION_CONTROL;
#define QUIC_CONGESTION_CONTROL_CONTEXT_SIZE (RTL_FIELD_SIZE(QUIC_CONGESTION_CONTROL, Ctx))
CXPLAT_STATIC_ASSERT(
sizeof(QUIC_CONGESTION_CONTROL_CUBIC) <= QUIC_CONGESTION_CONTROL_CONTEXT_SIZE,
"Context size for Cubic exceeds the expected size");
//
// Initializes the algorithm specific congestion control algorithm.
//
_IRQL_requires_max_(DISPATCH_LEVEL)
void
QuicCongestionControlInitialize(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ const QUIC_SETTINGS* Settings
);
//
// Returns TRUE if more bytes can be sent on the network.
@ -124,55 +120,65 @@ QuicCongestionControlSetExemption(
}
_IRQL_requires_max_(DISPATCH_LEVEL)
void
QuicCongestionControlInitialize(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ const QUIC_SETTINGS* Settings
);
_IRQL_requires_max_(DISPATCH_LEVEL)
inline
void
QuicCongestionControlReset(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ BOOLEAN FullReset
);
)
{
Cc->QuicCongestionControlReset(Cc, FullReset);
}
//
// Returns the number of bytes that can be sent immediately.
//
_IRQL_requires_max_(DISPATCH_LEVEL)
inline
uint32_t
QuicCongestionControlGetSendAllowance(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint64_t TimeSinceLastSend, // microsec
_In_ BOOLEAN TimeSinceLastSendValid
);
)
{
return Cc->QuicCongestionControlGetSendAllowance(Cc, TimeSinceLastSend, TimeSinceLastSendValid);
}
//
// Called when any retransmittable data is sent.
//
_IRQL_requires_max_(PASSIVE_LEVEL)
inline
void
QuicCongestionControlOnDataSent(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint32_t NumRetransmittableBytes
);
)
{
Cc->QuicCongestionControlOnDataSent(Cc, NumRetransmittableBytes);
}
//
// Called when any data needs to be removed from inflight but cannot be
// considered lost or acknowledged.
//
_IRQL_requires_max_(DISPATCH_LEVEL)
inline
BOOLEAN
QuicCongestionControlOnDataInvalidated(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint32_t NumRetransmittableBytes
);
)
{
return Cc->QuicCongestionControlOnDataInvalidated(Cc, NumRetransmittableBytes);
}
//
// Called when any data is acknowledged.
//
_IRQL_requires_max_(DISPATCH_LEVEL)
inline
BOOLEAN
QuicCongestionControlOnDataAcknowledged(
_In_ QUIC_CONGESTION_CONTROL* Cc,
@ -180,12 +186,17 @@ QuicCongestionControlOnDataAcknowledged(
_In_ uint64_t LargestPacketNumberAcked,
_In_ uint32_t NumRetransmittableBytes,
_In_ uint32_t SmoothedRtt
);
)
{
return Cc->QuicCongestionControlOnDataAcknowledged(
Cc, TimeNow, LargestPacketNumberAcked, NumRetransmittableBytes, SmoothedRtt);
}
//
// Called when data is determined lost.
//
_IRQL_requires_max_(DISPATCH_LEVEL)
inline
void
QuicCongestionControlOnDataLost(
_In_ QUIC_CONGESTION_CONTROL* Cc,
@ -193,22 +204,34 @@ QuicCongestionControlOnDataLost(
_In_ uint64_t LargestPacketNumberSent,
_In_ uint32_t NumRetransmittableBytes,
_In_ BOOLEAN PersistentCongestion
);
)
{
Cc->QuicCongestionControlOnDataLost(
Cc, LargestPacketNumberLost, LargestPacketNumberSent, NumRetransmittableBytes, PersistentCongestion);
}
//
// Called when all recently considered lost data was actually acknowledged.
//
_IRQL_requires_max_(DISPATCH_LEVEL)
inline
void
QuicCongestionControlOnSpuriousCongestionEvent(
_In_ QUIC_CONGESTION_CONTROL* Cc
);
)
{
Cc->QuicCongestionControlOnSpuriousCongestionEvent(Cc);
}
_IRQL_requires_max_(DISPATCH_LEVEL)
inline
uint8_t
QuicCongestionControlGetExemptions(
_In_ const QUIC_CONGESTION_CONTROL* Cc
);
)
{
return Cc->QuicCongestionControlGetExemptions(Cc);
}
_IRQL_requires_max_(DISPATCH_LEVEL)
inline
@ -224,7 +247,7 @@ _IRQL_requires_max_(DISPATCH_LEVEL)
inline
uint32_t
QuicCongestionControlGetBytesInFlightMax(
_In_ const struct QUIC_CONGESTION_CONTROL* Cc
_In_ const QUIC_CONGESTION_CONTROL* Cc
)
{
return Cc->QuicCongestionControlGetBytesInFlightMax(Cc);

Просмотреть файл

@ -43,7 +43,7 @@
<ClCompile Include="connection.c" />
<ClCompile Include="crypto.c" />
<ClCompile Include="crypto_tls.c" />
<ClCompile Include="cubic_impl.c" />
<ClCompile Include="cubic.c" />
<ClCompile Include="datagram.c" />
<ClCompile Include="frame.c" />
<ClCompile Include="injection.c" />
@ -82,7 +82,6 @@
<ClInclude Include="connection.h" />
<ClInclude Include="crypto.h" />
<ClInclude Include="cubic.h" />
<ClInclude Include="cubic_impl.h" />
<ClInclude Include="datagram.h" />
<ClInclude Include="frame.h" />
<ClInclude Include="library.h" />

Просмотреть файл

@ -9,13 +9,13 @@ Abstract:
Future work:
-Early slowstart exit via HyStart or similar.
- Early slowstart exit via HyStart or similar.
--*/
#include "precomp.h"
#ifdef QUIC_CLOG
#include "cubic_impl.c.clog.h"
#include "cubic.c.clog.h"
#endif
#include "cubic.h"
@ -26,23 +26,6 @@ Future work:
#define TEN_TIMES_BETA_CUBIC 7
#define TEN_TIMES_C_CUBIC 4
static const QUIC_CONGESTION_CONTROL QuicCongestionControlCubic = {
.Name = "Cubic",
.QuicCongestionControlCanSend = CubicCongestionControlCanSend,
.QuicCongestionControlSetExemption = CubicCongestionControlSetExemption,
.QuicCongestionControlInitialize = CubicCongestionControlInitialize,
.QuicCongestionControlReset = CubicCongestionControlReset,
.QuicCongestionControlGetSendAllowance = CubicCongestionControlGetSendAllowance,
.QuicCongestionControlOnDataSent = CubicCongestionControlOnDataSent,
.QuicCongestionControlOnDataInvalidated = CubicCongestionControlOnDataInvalidated,
.QuicCongestionControlOnDataAcknowledged = CubicCongestionControlOnDataAcknowledged,
.QuicCongestionControlOnDataLost = CubicCongestionControlOnDataLost,
.QuicCongestionControlOnSpuriousCongestionEvent = CubicCongestionControlOnSpuriousCongestionEvent,
.QuicCongestionControlLogOutFlowStatus = CubicCongestionControlLogOutFlowStatus,
.QuicCongestionControlGetExemptions = CubicCongestionControlGetExemptions,
.QuicCongestionControlGetBytesInFlightMax = CubicCongestionControlGetBytesInFlightMax,
};
//
// Shifting nth root algorithm.
//
@ -82,44 +65,42 @@ CubeRoot(
return y;
}
_IRQL_requires_max_(DISPATCH_LEVEL)
void
QuicConnLogCubic(
_In_ const QUIC_CONNECTION* const Connection
)
{
UNREFERENCED_PARAMETER(Connection);
QUIC_CONGESTION_CONTROL_CUBIC* Ctx = (QUIC_CONGESTION_CONTROL_CUBIC*)(&Connection->CongestionControl.Ctx);
const QUIC_CONGESTION_CONTROL_CUBIC* Cubic = &Connection->CongestionControl.Cubic;
QuicTraceEvent(
ConnCubic,
"[conn][%p] CUBIC: SlowStartThreshold=%u K=%u WindowMax=%u WindowLastMax=%u",
Connection,
Ctx->SlowStartThreshold,
Ctx->KCubic,
Ctx->WindowMax,
Ctx->WindowLastMax);
Cubic->SlowStartThreshold,
Cubic->KCubic,
Cubic->WindowMax,
Cubic->WindowLastMax);
}
_IRQL_requires_max_(DISPATCH_LEVEL)
BOOLEAN
CubicCongestionControlCanSend(
_In_ QUIC_CONGESTION_CONTROL* Cc
)
{
QUIC_CONGESTION_CONTROL_CUBIC* Cubic = &Cc->Cubic;
return Cubic->BytesInFlight < Cubic->CongestionWindow || Cubic->Exemptions > 0;
}
_IRQL_requires_max_(DISPATCH_LEVEL)
void
CubicCongestionControlInitialize(
CubicCongestionControlSetExemption(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ const QUIC_SETTINGS* Settings
_In_ uint8_t NumPackets
)
{
*Cc = QuicCongestionControlCubic;
QUIC_CONGESTION_CONTROL_CUBIC* Ctx = (QUIC_CONGESTION_CONTROL_CUBIC*)&Cc->Ctx;
QUIC_CONNECTION* Connection = QuicCongestionControlGetConnection(Cc);
Ctx->SlowStartThreshold = UINT32_MAX;
Ctx->SendIdleTimeoutMs = Settings->SendIdleTimeoutMs;
Ctx->InitialWindowPackets = Settings->InitialWindowPackets;
Ctx->CongestionWindow = Connection->Paths[0].Mtu * Ctx->InitialWindowPackets;
Ctx->BytesInFlightMax = Ctx->CongestionWindow / 2;
QuicConnLogOutFlowStats(Connection);
QuicConnLogCubic(Connection);
Cc->Cubic.Exemptions = NumPackets;
}
_IRQL_requires_max_(DISPATCH_LEVEL)
@ -129,16 +110,16 @@ CubicCongestionControlReset(
_In_ BOOLEAN FullReset
)
{
QUIC_CONGESTION_CONTROL_CUBIC* Ctx = (QUIC_CONGESTION_CONTROL_CUBIC*)&Cc->Ctx;
QUIC_CONGESTION_CONTROL_CUBIC* Cubic = &Cc->Cubic;
QUIC_CONNECTION* Connection = QuicCongestionControlGetConnection(Cc);
Ctx->SlowStartThreshold = UINT32_MAX;
Ctx->IsInRecovery = FALSE;
Ctx->HasHadCongestionEvent = FALSE;
Ctx->CongestionWindow = Connection->Paths[0].Mtu * Ctx->InitialWindowPackets;
Ctx->BytesInFlightMax = Ctx->CongestionWindow / 2;
Cubic->SlowStartThreshold = UINT32_MAX;
Cubic->IsInRecovery = FALSE;
Cubic->HasHadCongestionEvent = FALSE;
Cubic->CongestionWindow = Connection->Paths[0].Mtu * Cubic->InitialWindowPackets;
Cubic->BytesInFlightMax = Cubic->CongestionWindow / 2;
if (FullReset) {
Ctx->BytesInFlight = 0;
Cubic->BytesInFlight = 0;
}
QuicConnLogOutFlowStats(Connection);
QuicConnLogCubic(Connection);
@ -152,11 +133,11 @@ CubicCongestionControlGetSendAllowance(
_In_ BOOLEAN TimeSinceLastSendValid
)
{
QUIC_CONGESTION_CONTROL_CUBIC* Ctx = (QUIC_CONGESTION_CONTROL_CUBIC*)&Cc->Ctx;
QUIC_CONGESTION_CONTROL_CUBIC* Cubic = &Cc->Cubic;
uint32_t SendAllowance;
QUIC_CONNECTION* Connection = QuicCongestionControlGetConnection(Cc);
if (Ctx->BytesInFlight >= Ctx->CongestionWindow) {
if (Cubic->BytesInFlight >= Cubic->CongestionWindow) {
//
// We are CC blocked, so we can't send anything.
//
@ -170,7 +151,7 @@ CubicCongestionControlGetSendAllowance(
//
// We're not in the necessary state to pace.
//
SendAllowance = Ctx->CongestionWindow - Ctx->BytesInFlight;
SendAllowance = Cubic->CongestionWindow - Cubic->BytesInFlight;
} else {
@ -189,22 +170,22 @@ CubicCongestionControlGetSendAllowance(
// more complicated, and we use a simple estimate of 25% growth.
//
uint64_t EstimatedWnd;
if (Ctx->CongestionWindow < Ctx->SlowStartThreshold) {
EstimatedWnd = (uint64_t)Ctx->CongestionWindow << 1;
if (EstimatedWnd > Ctx->SlowStartThreshold) {
EstimatedWnd = Ctx->SlowStartThreshold;
if (Cubic->CongestionWindow < Cubic->SlowStartThreshold) {
EstimatedWnd = (uint64_t)Cubic->CongestionWindow << 1;
if (EstimatedWnd > Cubic->SlowStartThreshold) {
EstimatedWnd = Cubic->SlowStartThreshold;
}
} else {
EstimatedWnd = Ctx->CongestionWindow + (Ctx->CongestionWindow >> 2); // CongestionWindow * 1.25
EstimatedWnd = Cubic->CongestionWindow + (Cubic->CongestionWindow >> 2); // CongestionWindow * 1.25
}
SendAllowance =
(uint32_t)((EstimatedWnd * TimeSinceLastSend) / Connection->Paths[0].SmoothedRtt);
if (SendAllowance > (Ctx->CongestionWindow - Ctx->BytesInFlight)) {
SendAllowance = Ctx->CongestionWindow - Ctx->BytesInFlight;
if (SendAllowance > (Cubic->CongestionWindow - Cubic->BytesInFlight)) {
SendAllowance = Cubic->CongestionWindow - Cubic->BytesInFlight;
}
if (SendAllowance > (Ctx->CongestionWindow >> 2)) {
SendAllowance = Ctx->CongestionWindow >> 2; // Don't send more than a quarter of the current window.
if (SendAllowance > (Cubic->CongestionWindow >> 2)) {
SendAllowance = Cubic->CongestionWindow >> 2; // Don't send more than a quarter of the current window.
}
}
return SendAllowance;
@ -242,7 +223,7 @@ CubicCongestionControlOnCongestionEvent(
_In_ QUIC_CONGESTION_CONTROL* Cc
)
{
QUIC_CONGESTION_CONTROL_CUBIC* Ctx = (QUIC_CONGESTION_CONTROL_CUBIC*)&Cc->Ctx;
QUIC_CONGESTION_CONTROL_CUBIC* Cubic = &Cc->Cubic;
QUIC_CONNECTION* Connection = QuicCongestionControlGetConnection(Cc);
QuicTraceEvent(
@ -251,27 +232,27 @@ CubicCongestionControlOnCongestionEvent(
Connection);
Connection->Stats.Send.CongestionCount++;
Ctx->IsInRecovery = TRUE;
Ctx->HasHadCongestionEvent = TRUE;
Cubic->IsInRecovery = TRUE;
Cubic->HasHadCongestionEvent = TRUE;
//
// Save previous state, just in case this ends up being spurious.
//
Ctx->PrevWindowMax = Ctx->WindowMax;
Ctx->PrevWindowLastMax = Ctx->WindowLastMax;
Ctx->PrevKCubic = Ctx->KCubic;
Ctx->PrevSlowStartThreshold = Ctx->SlowStartThreshold;
Ctx->PrevCongestionWindow = Ctx->CongestionWindow;
Cubic->PrevWindowMax = Cubic->WindowMax;
Cubic->PrevWindowLastMax = Cubic->WindowLastMax;
Cubic->PrevKCubic = Cubic->KCubic;
Cubic->PrevSlowStartThreshold = Cubic->SlowStartThreshold;
Cubic->PrevCongestionWindow = Cubic->CongestionWindow;
Ctx->WindowMax = Ctx->CongestionWindow;
if (Ctx->WindowLastMax > Ctx->WindowMax) {
Cubic->WindowMax = Cubic->CongestionWindow;
if (Cubic->WindowLastMax > Cubic->WindowMax) {
//
// Fast convergence.
//
Ctx->WindowLastMax = Ctx->WindowMax;
Ctx->WindowMax = Ctx->WindowMax * (10 + TEN_TIMES_BETA_CUBIC) / 20;
Cubic->WindowLastMax = Cubic->WindowMax;
Cubic->WindowMax = Cubic->WindowMax * (10 + TEN_TIMES_BETA_CUBIC) / 20;
} else {
Ctx->WindowLastMax = Ctx->WindowMax;
Cubic->WindowLastMax = Cubic->WindowMax;
}
//
@ -282,18 +263,18 @@ CubicCongestionControlOnCongestionEvent(
// by 9 before the division and then right-shifting the result by 3
// (since 2^9 = 2^3^3).
//
Ctx->KCubic =
Cubic->KCubic =
CubeRoot(
(Ctx->WindowMax / Connection->Paths[0].Mtu * (10 - TEN_TIMES_BETA_CUBIC) << 9) /
(Cubic->WindowMax / Connection->Paths[0].Mtu * (10 - TEN_TIMES_BETA_CUBIC) << 9) /
TEN_TIMES_C_CUBIC);
Ctx->KCubic = S_TO_MS(Ctx->KCubic);
Ctx->KCubic >>= 3;
Cubic->KCubic = S_TO_MS(Cubic->KCubic);
Cubic->KCubic >>= 3;
Ctx->SlowStartThreshold =
Ctx->CongestionWindow =
Cubic->SlowStartThreshold =
Cubic->CongestionWindow =
CXPLAT_MAX(
(uint32_t)Connection->Paths[0].Mtu * QUIC_PERSISTENT_CONGESTION_WINDOW_PACKETS,
Ctx->CongestionWindow * TEN_TIMES_BETA_CUBIC / 10);
Cubic->CongestionWindow * TEN_TIMES_BETA_CUBIC / 10);
}
_IRQL_requires_max_(DISPATCH_LEVEL)
@ -302,7 +283,7 @@ CubicCongestionControlOnPersistentCongestionEvent(
_In_ QUIC_CONGESTION_CONTROL* Cc
)
{
QUIC_CONGESTION_CONTROL_CUBIC* Ctx = (QUIC_CONGESTION_CONTROL_CUBIC*)&Cc->Ctx;
QUIC_CONGESTION_CONTROL_CUBIC* Cubic = &Cc->Cubic;
QUIC_CONNECTION* Connection = QuicCongestionControlGetConnection(Cc);
QuicTraceEvent(
@ -311,14 +292,14 @@ CubicCongestionControlOnPersistentCongestionEvent(
Connection);
Connection->Stats.Send.PersistentCongestionCount++;
Ctx->IsInPersistentCongestion = TRUE;
Ctx->WindowMax =
Ctx->WindowLastMax =
Ctx->SlowStartThreshold =
Ctx->CongestionWindow * TEN_TIMES_BETA_CUBIC / 10;
Ctx->CongestionWindow =
Cubic->IsInPersistentCongestion = TRUE;
Cubic->WindowMax =
Cubic->WindowLastMax =
Cubic->SlowStartThreshold =
Cubic->CongestionWindow * TEN_TIMES_BETA_CUBIC / 10;
Cubic->CongestionWindow =
Connection->Paths[0].Mtu * QUIC_PERSISTENT_CONGESTION_WINDOW_PACKETS;
Ctx->KCubic = 0;
Cubic->KCubic = 0;
}
_IRQL_requires_max_(PASSIVE_LEVEL)
@ -328,18 +309,18 @@ CubicCongestionControlOnDataSent(
_In_ uint32_t NumRetransmittableBytes
)
{
QUIC_CONGESTION_CONTROL_CUBIC* Ctx = (QUIC_CONGESTION_CONTROL_CUBIC*)&Cc->Ctx;
QUIC_CONGESTION_CONTROL_CUBIC* Cubic = &Cc->Cubic;
BOOLEAN PreviousCanSendState = QuicCongestionControlCanSend(Cc);
Ctx->BytesInFlight += NumRetransmittableBytes;
if (Ctx->BytesInFlightMax < Ctx->BytesInFlight) {
Ctx->BytesInFlightMax = Ctx->BytesInFlight;
Cubic->BytesInFlight += NumRetransmittableBytes;
if (Cubic->BytesInFlightMax < Cubic->BytesInFlight) {
Cubic->BytesInFlightMax = Cubic->BytesInFlight;
QuicSendBufferConnectionAdjust(QuicCongestionControlGetConnection(Cc));
}
if (Ctx->Exemptions > 0) {
--Ctx->Exemptions;
if (Cubic->Exemptions > 0) {
--Cubic->Exemptions;
}
CubicCongestionControlUpdateBlockedState(Cc, PreviousCanSendState);
@ -352,12 +333,12 @@ CubicCongestionControlOnDataInvalidated(
_In_ uint32_t NumRetransmittableBytes
)
{
QUIC_CONGESTION_CONTROL_CUBIC* Ctx = (QUIC_CONGESTION_CONTROL_CUBIC*)&Cc->Ctx;
QUIC_CONGESTION_CONTROL_CUBIC* Cubic = &Cc->Cubic;
BOOLEAN PreviousCanSendState = CubicCongestionControlCanSend(Cc);
CXPLAT_DBG_ASSERT(Ctx->BytesInFlight >= NumRetransmittableBytes);
Ctx->BytesInFlight -= NumRetransmittableBytes;
CXPLAT_DBG_ASSERT(Cubic->BytesInFlight >= NumRetransmittableBytes);
Cubic->BytesInFlight -= NumRetransmittableBytes;
return CubicCongestionControlUpdateBlockedState(Cc, PreviousCanSendState);
}
@ -372,17 +353,17 @@ CubicCongestionControlOnDataAcknowledged(
_In_ uint32_t SmoothedRtt
)
{
QUIC_CONGESTION_CONTROL_CUBIC* Ctx = (QUIC_CONGESTION_CONTROL_CUBIC*)&Cc->Ctx;
QUIC_CONGESTION_CONTROL_CUBIC* Cubic = &Cc->Cubic;
TimeNow = US_TO_MS(TimeNow);
QUIC_CONNECTION* Connection = QuicCongestionControlGetConnection(Cc);
BOOLEAN PreviousCanSendState = CubicCongestionControlCanSend(Cc);
CXPLAT_DBG_ASSERT(Ctx->BytesInFlight >= NumRetransmittableBytes);
Ctx->BytesInFlight -= NumRetransmittableBytes;
CXPLAT_DBG_ASSERT(Cubic->BytesInFlight >= NumRetransmittableBytes);
Cubic->BytesInFlight -= NumRetransmittableBytes;
if (Ctx->IsInRecovery) {
if (LargestPacketNumberAcked > Ctx->RecoverySentPacketNumber) {
if (Cubic->IsInRecovery) {
if (LargestPacketNumberAcked > Cubic->RecoverySentPacketNumber) {
//
// Done recovering. Note that completion of recovery is defined a
// bit differently here than in TCP: we simply require an ACK for a
@ -392,24 +373,24 @@ CubicCongestionControlOnDataAcknowledged(
ConnRecoveryExit,
"[conn][%p] Recovery complete",
Connection);
Ctx->IsInRecovery = FALSE;
Ctx->IsInPersistentCongestion = FALSE;
Ctx->TimeOfCongAvoidStart = CxPlatTimeMs64();
Cubic->IsInRecovery = FALSE;
Cubic->IsInPersistentCongestion = FALSE;
Cubic->TimeOfCongAvoidStart = CxPlatTimeMs64();
}
goto Exit;
} else if (NumRetransmittableBytes == 0) {
goto Exit;
}
if (Ctx->CongestionWindow < Ctx->SlowStartThreshold) {
if (Cubic->CongestionWindow < Cubic->SlowStartThreshold) {
//
// Slow Start
//
Ctx->CongestionWindow += NumRetransmittableBytes;
if (Ctx->CongestionWindow >= Ctx->SlowStartThreshold) {
Ctx->TimeOfCongAvoidStart = CxPlatTimeMs64();
Cubic->CongestionWindow += NumRetransmittableBytes;
if (Cubic->CongestionWindow >= Cubic->SlowStartThreshold) {
Cubic->TimeOfCongAvoidStart = CxPlatTimeMs64();
}
} else {
@ -424,19 +405,19 @@ CubicCongestionControlOnDataAcknowledged(
// reduce the value of TimeInCongAvoid, which effectively freezes window
// growth during the gap.
//
if (Ctx->TimeOfLastAckValid) {
uint64_t TimeSinceLastAck = CxPlatTimeDiff64(Ctx->TimeOfLastAck, TimeNow);
if (TimeSinceLastAck > Ctx->SendIdleTimeoutMs &&
if (Cubic->TimeOfLastAckValid) {
uint64_t TimeSinceLastAck = CxPlatTimeDiff64(Cubic->TimeOfLastAck, TimeNow);
if (TimeSinceLastAck > Cubic->SendIdleTimeoutMs &&
TimeSinceLastAck > US_TO_MS(Connection->Paths[0].SmoothedRtt + 4 * Connection->Paths[0].RttVariance)) {
Ctx->TimeOfCongAvoidStart += TimeSinceLastAck;
if (CxPlatTimeAtOrBefore64(TimeNow, Ctx->TimeOfCongAvoidStart)) {
Ctx->TimeOfCongAvoidStart = TimeNow;
Cubic->TimeOfCongAvoidStart += TimeSinceLastAck;
if (CxPlatTimeAtOrBefore64(TimeNow, Cubic->TimeOfCongAvoidStart)) {
Cubic->TimeOfCongAvoidStart = TimeNow;
}
}
}
uint64_t TimeInCongAvoid =
CxPlatTimeDiff64(Ctx->TimeOfCongAvoidStart, CxPlatTimeMs64());
CxPlatTimeDiff64(Cubic->TimeOfCongAvoidStart, CxPlatTimeMs64());
if (TimeInCongAvoid > UINT32_MAX) {
TimeInCongAvoid = UINT32_MAX;
}
@ -459,20 +440,20 @@ CubicCongestionControlOnDataAcknowledged(
int64_t DeltaT =
(int64_t)TimeInCongAvoid -
(int64_t)Ctx->KCubic +
(int64_t)Cubic->KCubic +
(int64_t)US_TO_MS(SmoothedRtt);
int64_t CubicWindow =
((((DeltaT * DeltaT) >> 10) * DeltaT *
(int64_t)(Connection->Paths[0].Mtu * TEN_TIMES_C_CUBIC / 10)) >> 20) +
(int64_t)Ctx->WindowMax;
(int64_t)Cubic->WindowMax;
if (CubicWindow < 0) {
//
// The window came out so large it overflowed. We want to limit the
// huge window below anyway, so just set it to the limiting value.
//
CubicWindow = 2 * Ctx->BytesInFlightMax;
CubicWindow = 2 * Cubic->BytesInFlightMax;
}
//
@ -496,14 +477,14 @@ CubicCongestionControlOnDataAcknowledged(
CXPLAT_STATIC_ASSERT(TEN_TIMES_BETA_CUBIC == 7, "TEN_TIMES_BETA_CUBIC must be 7 for simplified calculation.");
int64_t AimdWindow =
Ctx->WindowMax * TEN_TIMES_BETA_CUBIC / 10 +
Cubic->WindowMax * TEN_TIMES_BETA_CUBIC / 10 +
TimeInCongAvoid * Connection->Paths[0].Mtu / (2 * CXPLAT_MAX(1, US_TO_MS(SmoothedRtt)));
//
// Use the cubic or AIMD window, whichever is larger.
//
if (AimdWindow > CubicWindow) {
Ctx->CongestionWindow = (uint32_t)CXPLAT_MAX(AimdWindow, Ctx->CongestionWindow + 1);
Cubic->CongestionWindow = (uint32_t)CXPLAT_MAX(AimdWindow, Cubic->CongestionWindow + 1);
} else {
//
// Here we increment by a fraction of the difference, per the spec,
@ -511,9 +492,9 @@ CubicCongestionControlOnDataAcknowledged(
// prevent a burst when transitioning into congestion avoidance, since
// the cubic window may be significantly different from SlowStartThreshold.
//
Ctx->CongestionWindow +=
Cubic->CongestionWindow +=
(uint32_t)CXPLAT_MAX(
((CubicWindow - Ctx->CongestionWindow) * Connection->Paths[0].Mtu) / Ctx->CongestionWindow,
((CubicWindow - Cubic->CongestionWindow) * Connection->Paths[0].Mtu) / Cubic->CongestionWindow,
1);
}
}
@ -528,14 +509,14 @@ CubicCongestionControlOnDataAcknowledged(
// Using 2 * BytesInFlightMax for the limit allows for exponential growth
// in the window when not otherwise limited.
//
if (Ctx->CongestionWindow > 2 * Ctx->BytesInFlightMax) {
Ctx->CongestionWindow = 2 * Ctx->BytesInFlightMax;
if (Cubic->CongestionWindow > 2 * Cubic->BytesInFlightMax) {
Cubic->CongestionWindow = 2 * Cubic->BytesInFlightMax;
}
Exit:
Ctx->TimeOfLastAck = TimeNow;
Ctx->TimeOfLastAckValid = TRUE;
Cubic->TimeOfLastAck = TimeNow;
Cubic->TimeOfLastAckValid = TRUE;
return CubicCongestionControlUpdateBlockedState(Cc, PreviousCanSendState);
}
@ -549,7 +530,7 @@ CubicCongestionControlOnDataLost(
_In_ BOOLEAN PersistentCongestion
)
{
QUIC_CONGESTION_CONTROL_CUBIC* Ctx = (QUIC_CONGESTION_CONTROL_CUBIC*)&Cc->Ctx;
QUIC_CONGESTION_CONTROL_CUBIC* Cubic = &Cc->Cubic;
BOOLEAN PreviousCanSendState = CubicCongestionControlCanSend(Cc);
@ -558,19 +539,19 @@ CubicCongestionControlOnDataLost(
// hasn't been a congestion event yet) then treat this loss as a new
// congestion event.
//
if (!Ctx->HasHadCongestionEvent ||
LargestPacketNumberLost > Ctx->RecoverySentPacketNumber) {
if (!Cubic->HasHadCongestionEvent ||
LargestPacketNumberLost > Cubic->RecoverySentPacketNumber) {
Ctx->RecoverySentPacketNumber = LargestPacketNumberSent;
Cubic->RecoverySentPacketNumber = LargestPacketNumberSent;
CubicCongestionControlOnCongestionEvent(Cc);
if (PersistentCongestion && !Ctx->IsInPersistentCongestion) {
if (PersistentCongestion && !Cubic->IsInPersistentCongestion) {
CubicCongestionControlOnPersistentCongestionEvent(Cc);
}
}
CXPLAT_DBG_ASSERT(Ctx->BytesInFlight >= NumRetransmittableBytes);
Ctx->BytesInFlight -= NumRetransmittableBytes;
CXPLAT_DBG_ASSERT(Cubic->BytesInFlight >= NumRetransmittableBytes);
Cubic->BytesInFlight -= NumRetransmittableBytes;
CubicCongestionControlUpdateBlockedState(Cc, PreviousCanSendState);
QuicConnLogCubic(QuicCongestionControlGetConnection(Cc));
@ -582,9 +563,9 @@ CubicCongestionControlOnSpuriousCongestionEvent(
_In_ QUIC_CONGESTION_CONTROL* Cc
)
{
QUIC_CONGESTION_CONTROL_CUBIC* Ctx = (QUIC_CONGESTION_CONTROL_CUBIC*)&Cc->Ctx;
QUIC_CONGESTION_CONTROL_CUBIC* Cubic = &Cc->Cubic;
if (!Ctx->IsInRecovery) {
if (!Cubic->IsInRecovery) {
return;
}
@ -599,14 +580,14 @@ CubicCongestionControlOnSpuriousCongestionEvent(
//
// Revert to previous state.
//
Ctx->WindowMax = Ctx->PrevWindowMax;
Ctx->WindowLastMax = Ctx->PrevWindowLastMax;
Ctx->KCubic = Ctx->PrevKCubic;
Ctx->SlowStartThreshold = Ctx->PrevSlowStartThreshold;
Ctx->CongestionWindow = Ctx->PrevCongestionWindow;
Cubic->WindowMax = Cubic->PrevWindowMax;
Cubic->WindowLastMax = Cubic->PrevWindowLastMax;
Cubic->KCubic = Cubic->PrevKCubic;
Cubic->SlowStartThreshold = Cubic->PrevSlowStartThreshold;
Cubic->CongestionWindow = Cubic->PrevCongestionWindow;
Ctx->IsInRecovery = FALSE;
Ctx->HasHadCongestionEvent = FALSE;
Cubic->IsInRecovery = FALSE;
Cubic->HasHadCongestionEvent = FALSE;
CubicCongestionControlUpdateBlockedState(Cc, PreviousCanSendState);
QuicConnLogCubic(Connection);
@ -617,22 +598,19 @@ CubicCongestionControlLogOutFlowStatus(
_In_ const QUIC_CONGESTION_CONTROL* Cc
)
{
QUIC_CONGESTION_CONTROL_CUBIC* Ctx = (QUIC_CONGESTION_CONTROL_CUBIC*)&Cc->Ctx;
QUIC_CONNECTION* Connection = QuicCongestionControlGetConnection(Cc);
const QUIC_CONNECTION* Connection = QuicCongestionControlGetConnection(Cc);
const QUIC_PATH* Path = &Connection->Paths[0];
UNREFERENCED_PARAMETER(Path);
const QUIC_CONGESTION_CONTROL_CUBIC* Cubic = &Cc->Cubic;
QuicTraceEvent(
ConnOutFlowStats,
"[conn][%p] OUT: BytesSent=%llu InFlight=%u InFlightMax=%u CWnd=%u SSThresh=%u ConnFC=%llu ISB=%llu PostedBytes=%llu SRtt=%u",
Connection,
Connection->Stats.Send.TotalBytes,
Ctx->BytesInFlight,
Ctx->BytesInFlightMax,
Ctx->CongestionWindow,
Ctx->SlowStartThreshold,
Cubic->BytesInFlight,
Cubic->BytesInFlightMax,
Cubic->CongestionWindow,
Cubic->SlowStartThreshold,
Connection->Send.PeerMaxData - Connection->Send.OrderedStreamBytesSent,
Connection->SendBuffer.IdealBytes,
Connection->SendBuffer.PostedBytes,
@ -641,11 +619,10 @@ CubicCongestionControlLogOutFlowStatus(
uint32_t
CubicCongestionControlGetBytesInFlightMax(
_In_ const struct QUIC_CONGESTION_CONTROL* Cc
_In_ const QUIC_CONGESTION_CONTROL* Cc
)
{
QUIC_CONGESTION_CONTROL_CUBIC* Ctx = (QUIC_CONGESTION_CONTROL_CUBIC*)&Cc->Ctx;
return Ctx->BytesInFlightMax;
return Cc->Cubic.BytesInFlightMax;
}
_IRQL_requires_max_(DISPATCH_LEVEL)
@ -654,6 +631,42 @@ CubicCongestionControlGetExemptions(
_In_ const QUIC_CONGESTION_CONTROL* Cc
)
{
QUIC_CONGESTION_CONTROL_CUBIC* Ctx = (QUIC_CONGESTION_CONTROL_CUBIC*)&Cc->Ctx;
return Ctx->Exemptions;
return Cc->Cubic.Exemptions;
}
static const QUIC_CONGESTION_CONTROL QuicCongestionControlCubic = {
.Name = "Cubic",
.QuicCongestionControlCanSend = CubicCongestionControlCanSend,
.QuicCongestionControlSetExemption = CubicCongestionControlSetExemption,
.QuicCongestionControlReset = CubicCongestionControlReset,
.QuicCongestionControlGetSendAllowance = CubicCongestionControlGetSendAllowance,
.QuicCongestionControlOnDataSent = CubicCongestionControlOnDataSent,
.QuicCongestionControlOnDataInvalidated = CubicCongestionControlOnDataInvalidated,
.QuicCongestionControlOnDataAcknowledged = CubicCongestionControlOnDataAcknowledged,
.QuicCongestionControlOnDataLost = CubicCongestionControlOnDataLost,
.QuicCongestionControlOnSpuriousCongestionEvent = CubicCongestionControlOnSpuriousCongestionEvent,
.QuicCongestionControlLogOutFlowStatus = CubicCongestionControlLogOutFlowStatus,
.QuicCongestionControlGetExemptions = CubicCongestionControlGetExemptions,
.QuicCongestionControlGetBytesInFlightMax = CubicCongestionControlGetBytesInFlightMax,
};
_IRQL_requires_max_(DISPATCH_LEVEL)
void
CubicCongestionControlInitialize(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ const QUIC_SETTINGS* Settings
)
{
*Cc = QuicCongestionControlCubic;
QUIC_CONGESTION_CONTROL_CUBIC* Cubic = &Cc->Cubic;
QUIC_CONNECTION* Connection = QuicCongestionControlGetConnection(Cc);
Cubic->SlowStartThreshold = UINT32_MAX;
Cubic->SendIdleTimeoutMs = Settings->SendIdleTimeoutMs;
Cubic->InitialWindowPackets = Settings->InitialWindowPackets;
Cubic->CongestionWindow = Connection->Paths[0].Mtu * Cubic->InitialWindowPackets;
Cubic->BytesInFlightMax = Cubic->CongestionWindow / 2;
QuicConnLogOutFlowStats(Connection);
QuicConnLogCubic(Connection);
}

Просмотреть файл

@ -83,3 +83,10 @@ typedef struct QUIC_CONGESTION_CONTROL_CUBIC {
uint64_t RecoverySentPacketNumber;
} QUIC_CONGESTION_CONTROL_CUBIC;
_IRQL_requires_max_(DISPATCH_LEVEL)
void
CubicCongestionControlInitialize(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ const QUIC_SETTINGS* Settings
);

Просмотреть файл

@ -1,107 +0,0 @@
/*++
Copyright (c) Microsoft Corporation.
Licensed under the MIT License.
--*/
_IRQL_requires_max_(DISPATCH_LEVEL)
inline
BOOLEAN
CubicCongestionControlCanSend(
_In_ QUIC_CONGESTION_CONTROL* Cc
)
{
QUIC_CONGESTION_CONTROL_CUBIC* Ctx = (QUIC_CONGESTION_CONTROL_CUBIC*)&Cc->Ctx;
return Ctx->BytesInFlight < Ctx->CongestionWindow || Ctx->Exemptions > 0;
}
_IRQL_requires_max_(DISPATCH_LEVEL)
inline
void
CubicCongestionControlSetExemption(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint8_t NumPackets
)
{
QUIC_CONGESTION_CONTROL_CUBIC* Ctx = (QUIC_CONGESTION_CONTROL_CUBIC*)&Cc->Ctx;
Ctx->Exemptions = NumPackets;
}
_IRQL_requires_max_(DISPATCH_LEVEL)
void
CubicCongestionControlInitialize(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ const QUIC_SETTINGS* Settings
);
_IRQL_requires_max_(DISPATCH_LEVEL)
void
CubicCongestionControlReset(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ BOOLEAN FullReset
);
_IRQL_requires_max_(DISPATCH_LEVEL)
uint32_t
CubicCongestionControlGetSendAllowance(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint64_t TimeSinceLastSend, // microsec
_In_ BOOLEAN TimeSinceLastSendValid
);
_IRQL_requires_max_(PASSIVE_LEVEL)
void
CubicCongestionControlOnDataSent(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint32_t NumRetransmittableBytes
);
_IRQL_requires_max_(DISPATCH_LEVEL)
BOOLEAN
CubicCongestionControlOnDataInvalidated(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint32_t NumRetransmittableBytes
);
_IRQL_requires_max_(DISPATCH_LEVEL)
BOOLEAN
CubicCongestionControlOnDataAcknowledged(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint64_t TimeNow, // microsecond
_In_ uint64_t LargestPacketNumberAcked,
_In_ uint32_t NumRetransmittableBytes,
_In_ uint32_t SmoothedRtt
);
_IRQL_requires_max_(DISPATCH_LEVEL)
void
CubicCongestionControlOnDataLost(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint64_t LargestPacketNumberLost,
_In_ uint64_t LargestPacketNumberSent,
_In_ uint32_t NumRetransmittableBytes,
_In_ BOOLEAN PersistentCongestion
);
_IRQL_requires_max_(DISPATCH_LEVEL)
void
CubicCongestionControlOnSpuriousCongestionEvent(
_In_ QUIC_CONGESTION_CONTROL* Cc
);
_IRQL_requires_max_(DISPATCH_LEVEL)
uint8_t
CubicCongestionControlGetExemptions(
_In_ const QUIC_CONGESTION_CONTROL* Cc
);
void
CubicCongestionControlLogOutFlowStatus(
_In_ const QUIC_CONGESTION_CONTROL* Cc
);
uint32_t
CubicCongestionControlGetBytesInFlightMax(
_In_ const struct QUIC_CONGESTION_CONTROL* Cc
);

Просмотреть файл

@ -297,6 +297,12 @@ QuicCidEncodeLength(
_In_ uint8_t Length
);
_IRQL_requires_max_(DISPATCH_LEVEL)
BOOLEAN
QuicCongestionControlCanSend(
_In_ QUIC_CONGESTION_CONTROL* Cc
);
_IRQL_requires_max_(DISPATCH_LEVEL)
void
QuicCongestionControlSetExemption(
@ -304,12 +310,84 @@ QuicCongestionControlSetExemption(
_In_ uint8_t NumPackets
);
_IRQL_requires_max_(DISPATCH_LEVEL)
void
QuicCongestionControlReset(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ BOOLEAN FullReset
);
_IRQL_requires_max_(DISPATCH_LEVEL)
uint32_t
QuicCongestionControlGetSendAllowance(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint64_t TimeSinceLastSend, // microsec
_In_ BOOLEAN TimeSinceLastSendValid
);
_IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicCongestionControlOnDataSent(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint32_t NumRetransmittableBytes
);
_IRQL_requires_max_(DISPATCH_LEVEL)
BOOLEAN
QuicCongestionControlCanSend(
QuicCongestionControlOnDataInvalidated(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint32_t NumRetransmittableBytes
);
_IRQL_requires_max_(DISPATCH_LEVEL)
BOOLEAN
QuicCongestionControlOnDataAcknowledged(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint64_t TimeNow, // microsecond
_In_ uint64_t LargestPacketNumberAcked,
_In_ uint32_t NumRetransmittableBytes,
_In_ uint32_t SmoothedRtt
);
_IRQL_requires_max_(DISPATCH_LEVEL)
void
QuicCongestionControlOnDataLost(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint64_t LargestPacketNumberLost,
_In_ uint64_t LargestPacketNumberSent,
_In_ uint32_t NumRetransmittableBytes,
_In_ BOOLEAN PersistentCongestion
);
_IRQL_requires_max_(DISPATCH_LEVEL)
void
QuicCongestionControlOnSpuriousCongestionEvent(
_In_ QUIC_CONGESTION_CONTROL* Cc
);
_IRQL_requires_max_(DISPATCH_LEVEL)
uint8_t
QuicCongestionControlGetExemptions(
_In_ const QUIC_CONGESTION_CONTROL* Cc
);
_IRQL_requires_max_(DISPATCH_LEVEL)
void
QuicCongestionControlLogOutFlowStatus(
_In_ const QUIC_CONGESTION_CONTROL* Cc
);
_IRQL_requires_max_(DISPATCH_LEVEL)
uint32_t
QuicCongestionControlGetBytesInFlightMax(
_In_ const QUIC_CONGESTION_CONTROL* Cc
);
QUIC_CONNECTION*
QuicCongestionControlGetConnection(
_In_ const QUIC_CONGESTION_CONTROL* Cc
);
QUIC_CONNECTION*
QuicSendGetConnection(
_In_ QUIC_SEND* Send
@ -346,11 +424,6 @@ QuicAckTrackerGetPacketSpace(
_In_ QUIC_ACK_TRACKER* Tracker
);
QUIC_CONNECTION*
QuicCongestionControlGetConnection(
_In_ const QUIC_CONGESTION_CONTROL* Cc
);
QUIC_CID_STR
QuicCidToStr(
_In_ const QUIC_CID* const CID
@ -688,28 +761,3 @@ QuicMtuDiscoveryCheckSearchCompleteTimeout(
_In_ QUIC_CONNECTION* Connection,
_In_ uint64_t TimeNow
);
_IRQL_requires_max_(DISPATCH_LEVEL)
void
QuicCongestionControlLogOutFlowStatus(
_In_ const QUIC_CONGESTION_CONTROL* Cc
);
_IRQL_requires_max_(DISPATCH_LEVEL)
uint32_t
QuicCongestionControlGetBytesInFlightMax(
_In_ const struct QUIC_CONGESTION_CONTROL* Cc
);
_IRQL_requires_max_(DISPATCH_LEVEL)
BOOLEAN
CubicCongestionControlCanSend(
_In_ QUIC_CONGESTION_CONTROL* Cc
);
_IRQL_requires_max_(DISPATCH_LEVEL)
void
CubicCongestionControlSetExemption(
_In_ QUIC_CONGESTION_CONTROL* Cc,
_In_ uint8_t NumPackets
);

Просмотреть файл

@ -78,7 +78,6 @@ extern "C" {
#include "packet_builder.h"
#include "listener.h"
#include "cubic.h"
#include "cubic_impl.h"
#if defined(__cplusplus)
}

Просмотреть файл

@ -12,6 +12,7 @@ typedef struct QUIC_WORKER_POOL QUIC_WORKER_POOL;
typedef struct QUIC_REGISTRATION QUIC_REGISTRATION;
typedef struct QUIC_CONFIGURATION QUIC_CONFIGURATION;
typedef struct QUIC_LISTENER QUIC_LISTENER;
typedef struct QUIC_CONGESTION_CONTROL QUIC_CONGESTION_CONTROL;
typedef struct QUIC_CONNECTION QUIC_CONNECTION;
typedef struct QUIC_STREAM QUIC_STREAM;
typedef struct QUIC_PACKET_BUILDER QUIC_PACKET_BUILDER;

Просмотреть файл

@ -27,11 +27,11 @@ extern "C" {
// Decoder Ring for InvalidCongestionControlAlgorithm
// [conn][%p] Unknown congestion control algorithm: %d, fallback to Cubic
// QuicTraceLogConnWarning(
InvalidCongestionControlAlgorithm,
Connection,
"Unknown congestion control algorithm: %d, fallback to Cubic",
Settings->CongestionControlAlgorithm);
// arg1 = arg1 = Connection
InvalidCongestionControlAlgorithm,
QuicCongestionControlGetConnection(Cc),
"Unknown congestion control algorithm: %d, fallback to Cubic",
Settings->CongestionControlAlgorithm);
// arg1 = arg1 = QuicCongestionControlGetConnection(Cc)
// arg3 = arg3 = Settings->CongestionControlAlgorithm
----------------------------------------------------------*/
#define _clog_4_ARGS_TRACE_InvalidCongestionControlAlgorithm(uniqueId, arg1, encoded_arg_string, arg3)\

Просмотреть файл

@ -5,11 +5,11 @@
// Decoder Ring for InvalidCongestionControlAlgorithm
// [conn][%p] Unknown congestion control algorithm: %d, fallback to Cubic
// QuicTraceLogConnWarning(
InvalidCongestionControlAlgorithm,
Connection,
"Unknown congestion control algorithm: %d, fallback to Cubic",
Settings->CongestionControlAlgorithm);
// arg1 = arg1 = Connection
InvalidCongestionControlAlgorithm,
QuicCongestionControlGetConnection(Cc),
"Unknown congestion control algorithm: %d, fallback to Cubic",
Settings->CongestionControlAlgorithm);
// arg1 = arg1 = QuicCongestionControlGetConnection(Cc)
// arg3 = arg3 = Settings->CongestionControlAlgorithm
----------------------------------------------------------*/
TRACEPOINT_EVENT(CLOG_CONGESTION_CONTROL_C, InvalidCongestionControlAlgorithm,

Просмотреть файл

@ -1,15 +1,15 @@
#include <clog.h>
#undef TRACEPOINT_PROVIDER
#define TRACEPOINT_PROVIDER CLOG_CUBIC_IMPL_C
#define TRACEPOINT_PROVIDER CLOG_CUBIC_C
#undef TRACEPOINT_PROBE_DYNAMIC_LINKAGE
#define TRACEPOINT_PROBE_DYNAMIC_LINKAGE
#undef TRACEPOINT_INCLUDE
#define TRACEPOINT_INCLUDE "cubic_impl.c.clog.h.lttng.h"
#if !defined(DEF_CLOG_CUBIC_IMPL_C) || defined(TRACEPOINT_HEADER_MULTI_READ)
#define DEF_CLOG_CUBIC_IMPL_C
#define TRACEPOINT_INCLUDE "cubic.c.clog.h.lttng.h"
#if !defined(DEF_CLOG_CUBIC_C) || defined(TRACEPOINT_HEADER_MULTI_READ)
#define DEF_CLOG_CUBIC_C
#include <lttng/tracepoint.h>
#define __int64 __int64_t
#include "cubic_impl.c.clog.h.lttng.h"
#include "cubic.c.clog.h.lttng.h"
#endif
#include <lttng/tracepoint-event.h>
#ifndef _clog_MACRO_QuicTraceEvent
@ -30,18 +30,18 @@ extern "C" {
ConnCubic,
"[conn][%p] CUBIC: SlowStartThreshold=%u K=%u WindowMax=%u WindowLastMax=%u",
Connection,
Ctx->SlowStartThreshold,
Ctx->KCubic,
Ctx->WindowMax,
Ctx->WindowLastMax);
Cubic->SlowStartThreshold,
Cubic->KCubic,
Cubic->WindowMax,
Cubic->WindowLastMax);
// arg2 = arg2 = Connection
// arg3 = arg3 = Ctx->SlowStartThreshold
// arg4 = arg4 = Ctx->KCubic
// arg5 = arg5 = Ctx->WindowMax
// arg6 = arg6 = Ctx->WindowLastMax
// arg3 = arg3 = Cubic->SlowStartThreshold
// arg4 = arg4 = Cubic->KCubic
// arg5 = arg5 = Cubic->WindowMax
// arg6 = arg6 = Cubic->WindowLastMax
----------------------------------------------------------*/
#define _clog_7_ARGS_TRACE_ConnCubic(uniqueId, encoded_arg_string, arg2, arg3, arg4, arg5, arg6)\
tracepoint(CLOG_CUBIC_IMPL_C, ConnCubic , arg2, arg3, arg4, arg5, arg6);\
tracepoint(CLOG_CUBIC_C, ConnCubic , arg2, arg3, arg4, arg5, arg6);\
#endif
@ -62,7 +62,7 @@ tracepoint(CLOG_CUBIC_IMPL_C, ConnCubic , arg2, arg3, arg4, arg5, arg6);\
// arg2 = arg2 = Connection
----------------------------------------------------------*/
#define _clog_3_ARGS_TRACE_ConnCongestion(uniqueId, encoded_arg_string, arg2)\
tracepoint(CLOG_CUBIC_IMPL_C, ConnCongestion , arg2);\
tracepoint(CLOG_CUBIC_C, ConnCongestion , arg2);\
#endif
@ -83,7 +83,7 @@ tracepoint(CLOG_CUBIC_IMPL_C, ConnCongestion , arg2);\
// arg2 = arg2 = Connection
----------------------------------------------------------*/
#define _clog_3_ARGS_TRACE_ConnPersistentCongestion(uniqueId, encoded_arg_string, arg2)\
tracepoint(CLOG_CUBIC_IMPL_C, ConnPersistentCongestion , arg2);\
tracepoint(CLOG_CUBIC_C, ConnPersistentCongestion , arg2);\
#endif
@ -104,7 +104,7 @@ tracepoint(CLOG_CUBIC_IMPL_C, ConnPersistentCongestion , arg2);\
// arg2 = arg2 = Connection
----------------------------------------------------------*/
#define _clog_3_ARGS_TRACE_ConnRecoveryExit(uniqueId, encoded_arg_string, arg2)\
tracepoint(CLOG_CUBIC_IMPL_C, ConnRecoveryExit , arg2);\
tracepoint(CLOG_CUBIC_C, ConnRecoveryExit , arg2);\
#endif
@ -125,7 +125,7 @@ tracepoint(CLOG_CUBIC_IMPL_C, ConnRecoveryExit , arg2);\
// arg2 = arg2 = Connection
----------------------------------------------------------*/
#define _clog_3_ARGS_TRACE_ConnSpuriousCongestion(uniqueId, encoded_arg_string, arg2)\
tracepoint(CLOG_CUBIC_IMPL_C, ConnSpuriousCongestion , arg2);\
tracepoint(CLOG_CUBIC_C, ConnSpuriousCongestion , arg2);\
#endif
@ -144,27 +144,27 @@ tracepoint(CLOG_CUBIC_IMPL_C, ConnSpuriousCongestion , arg2);\
"[conn][%p] OUT: BytesSent=%llu InFlight=%u InFlightMax=%u CWnd=%u SSThresh=%u ConnFC=%llu ISB=%llu PostedBytes=%llu SRtt=%u",
Connection,
Connection->Stats.Send.TotalBytes,
Ctx->BytesInFlight,
Ctx->BytesInFlightMax,
Ctx->CongestionWindow,
Ctx->SlowStartThreshold,
Cubic->BytesInFlight,
Cubic->BytesInFlightMax,
Cubic->CongestionWindow,
Cubic->SlowStartThreshold,
Connection->Send.PeerMaxData - Connection->Send.OrderedStreamBytesSent,
Connection->SendBuffer.IdealBytes,
Connection->SendBuffer.PostedBytes,
Path->GotFirstRttSample ? Path->SmoothedRtt : 0);
// arg2 = arg2 = Connection
// arg3 = arg3 = Connection->Stats.Send.TotalBytes
// arg4 = arg4 = Ctx->BytesInFlight
// arg5 = arg5 = Ctx->BytesInFlightMax
// arg6 = arg6 = Ctx->CongestionWindow
// arg7 = arg7 = Ctx->SlowStartThreshold
// arg4 = arg4 = Cubic->BytesInFlight
// arg5 = arg5 = Cubic->BytesInFlightMax
// arg6 = arg6 = Cubic->CongestionWindow
// arg7 = arg7 = Cubic->SlowStartThreshold
// arg8 = arg8 = Connection->Send.PeerMaxData - Connection->Send.OrderedStreamBytesSent
// arg9 = arg9 = Connection->SendBuffer.IdealBytes
// arg10 = arg10 = Connection->SendBuffer.PostedBytes
// arg11 = arg11 = Path->GotFirstRttSample ? Path->SmoothedRtt : 0
----------------------------------------------------------*/
#define _clog_12_ARGS_TRACE_ConnOutFlowStats(uniqueId, encoded_arg_string, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11)\
tracepoint(CLOG_CUBIC_IMPL_C, ConnOutFlowStats , arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11);\
tracepoint(CLOG_CUBIC_C, ConnOutFlowStats , arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11);\
#endif
@ -175,5 +175,5 @@ tracepoint(CLOG_CUBIC_IMPL_C, ConnOutFlowStats , arg2, arg3, arg4, arg5, arg6, a
}
#endif
#ifdef CLOG_INLINE_IMPLEMENTATION
#include "quic.clog_cubic_impl.c.clog.h.c"
#include "quic.clog_cubic.c.clog.h.c"
#endif

Просмотреть файл

@ -8,17 +8,17 @@
ConnCubic,
"[conn][%p] CUBIC: SlowStartThreshold=%u K=%u WindowMax=%u WindowLastMax=%u",
Connection,
Ctx->SlowStartThreshold,
Ctx->KCubic,
Ctx->WindowMax,
Ctx->WindowLastMax);
Cubic->SlowStartThreshold,
Cubic->KCubic,
Cubic->WindowMax,
Cubic->WindowLastMax);
// arg2 = arg2 = Connection
// arg3 = arg3 = Ctx->SlowStartThreshold
// arg4 = arg4 = Ctx->KCubic
// arg5 = arg5 = Ctx->WindowMax
// arg6 = arg6 = Ctx->WindowLastMax
// arg3 = arg3 = Cubic->SlowStartThreshold
// arg4 = arg4 = Cubic->KCubic
// arg5 = arg5 = Cubic->WindowMax
// arg6 = arg6 = Cubic->WindowLastMax
----------------------------------------------------------*/
TRACEPOINT_EVENT(CLOG_CUBIC_IMPL_C, ConnCubic,
TRACEPOINT_EVENT(CLOG_CUBIC_C, ConnCubic,
TP_ARGS(
const void *, arg2,
unsigned int, arg3,
@ -45,7 +45,7 @@ TRACEPOINT_EVENT(CLOG_CUBIC_IMPL_C, ConnCubic,
Connection);
// arg2 = arg2 = Connection
----------------------------------------------------------*/
TRACEPOINT_EVENT(CLOG_CUBIC_IMPL_C, ConnCongestion,
TRACEPOINT_EVENT(CLOG_CUBIC_C, ConnCongestion,
TP_ARGS(
const void *, arg2),
TP_FIELDS(
@ -64,7 +64,7 @@ TRACEPOINT_EVENT(CLOG_CUBIC_IMPL_C, ConnCongestion,
Connection);
// arg2 = arg2 = Connection
----------------------------------------------------------*/
TRACEPOINT_EVENT(CLOG_CUBIC_IMPL_C, ConnPersistentCongestion,
TRACEPOINT_EVENT(CLOG_CUBIC_C, ConnPersistentCongestion,
TP_ARGS(
const void *, arg2),
TP_FIELDS(
@ -83,7 +83,7 @@ TRACEPOINT_EVENT(CLOG_CUBIC_IMPL_C, ConnPersistentCongestion,
Connection);
// arg2 = arg2 = Connection
----------------------------------------------------------*/
TRACEPOINT_EVENT(CLOG_CUBIC_IMPL_C, ConnRecoveryExit,
TRACEPOINT_EVENT(CLOG_CUBIC_C, ConnRecoveryExit,
TP_ARGS(
const void *, arg2),
TP_FIELDS(
@ -102,7 +102,7 @@ TRACEPOINT_EVENT(CLOG_CUBIC_IMPL_C, ConnRecoveryExit,
Connection);
// arg2 = arg2 = Connection
----------------------------------------------------------*/
TRACEPOINT_EVENT(CLOG_CUBIC_IMPL_C, ConnSpuriousCongestion,
TRACEPOINT_EVENT(CLOG_CUBIC_C, ConnSpuriousCongestion,
TP_ARGS(
const void *, arg2),
TP_FIELDS(
@ -120,26 +120,26 @@ TRACEPOINT_EVENT(CLOG_CUBIC_IMPL_C, ConnSpuriousCongestion,
"[conn][%p] OUT: BytesSent=%llu InFlight=%u InFlightMax=%u CWnd=%u SSThresh=%u ConnFC=%llu ISB=%llu PostedBytes=%llu SRtt=%u",
Connection,
Connection->Stats.Send.TotalBytes,
Ctx->BytesInFlight,
Ctx->BytesInFlightMax,
Ctx->CongestionWindow,
Ctx->SlowStartThreshold,
Cubic->BytesInFlight,
Cubic->BytesInFlightMax,
Cubic->CongestionWindow,
Cubic->SlowStartThreshold,
Connection->Send.PeerMaxData - Connection->Send.OrderedStreamBytesSent,
Connection->SendBuffer.IdealBytes,
Connection->SendBuffer.PostedBytes,
Path->GotFirstRttSample ? Path->SmoothedRtt : 0);
// arg2 = arg2 = Connection
// arg3 = arg3 = Connection->Stats.Send.TotalBytes
// arg4 = arg4 = Ctx->BytesInFlight
// arg5 = arg5 = Ctx->BytesInFlightMax
// arg6 = arg6 = Ctx->CongestionWindow
// arg7 = arg7 = Ctx->SlowStartThreshold
// arg4 = arg4 = Cubic->BytesInFlight
// arg5 = arg5 = Cubic->BytesInFlightMax
// arg6 = arg6 = Cubic->CongestionWindow
// arg7 = arg7 = Cubic->SlowStartThreshold
// arg8 = arg8 = Connection->Send.PeerMaxData - Connection->Send.OrderedStreamBytesSent
// arg9 = arg9 = Connection->SendBuffer.IdealBytes
// arg10 = arg10 = Connection->SendBuffer.PostedBytes
// arg11 = arg11 = Path->GotFirstRttSample ? Path->SmoothedRtt : 0
----------------------------------------------------------*/
TRACEPOINT_EVENT(CLOG_CUBIC_IMPL_C, ConnOutFlowStats,
TRACEPOINT_EVENT(CLOG_CUBIC_C, ConnOutFlowStats,
TP_ARGS(
const void *, arg2,
unsigned long long, arg3,

Просмотреть файл

@ -4,4 +4,4 @@
#else
#define TRACEPOINT_DEFINE
#endif
#include "cubic_impl.c.clog.h"
#include "cubic.c.clog.h"