Skip to content

Commit

Permalink
Add DPLPMTUD support (microsoft#1563)
Browse files Browse the repository at this point in the history
  • Loading branch information
ThadHouse authored Jun 1, 2021
1 parent 17662bb commit de0cddc
Show file tree
Hide file tree
Showing 41 changed files with 1,576 additions and 149 deletions.
1 change: 1 addition & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ set(SOURCES
listener.c
lookup.c
loss_detection.c
mtu_discovery.c
operation.c
packet.c
packet_builder.c
Expand Down
2 changes: 1 addition & 1 deletion src/core/binding.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
(ARRAYSIZE(QuicSupportedVersionList) * sizeof(uint32_t)) \
)
CXPLAT_STATIC_ASSERT(
QUIC_DEFAULT_PATH_MTU - 48 >= MAX_VER_NEG_PACKET_LENGTH,
QUIC_DPLPMUTD_MIN_MTU - 48 >= MAX_VER_NEG_PACKET_LENGTH,
"Too many supported version numbers! Requires too big of buffer for response!");

_IRQL_requires_max_(PASSIVE_LEVEL)
Expand Down
2 changes: 2 additions & 0 deletions src/core/configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ MsQuicConfigurationOpen(
&Configuration->Settings,
TRUE,
TRUE,
TRUE,
SettingsSize,
Settings)) {
Status = QUIC_STATUS_INVALID_PARAMETER;
Expand Down Expand Up @@ -465,6 +466,7 @@ QuicConfigurationParamSet(
&Configuration->Settings,
TRUE,
TRUE,
TRUE,
BufferLength,
(QUIC_SETTINGS*)Buffer)) {
return QUIC_STATUS_INVALID_PARAMETER;
Expand Down
2 changes: 2 additions & 0 deletions src/core/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -6445,6 +6445,7 @@ QuicConnApplyNewSettings(
&Connection->Settings,
OverWrite,
CopyExternalToInternal,
!Connection->State.Started,
NewSettingsSize,
NewSettings)) {
return FALSE;
Expand All @@ -6454,6 +6455,7 @@ QuicConnApplyNewSettings(

Connection->Paths[0].SmoothedRtt = MS_TO_US(Connection->Settings.InitialRttMs);
Connection->Paths[0].RttVariance = Connection->Paths[0].SmoothedRtt / 2;
Connection->Paths[0].Mtu = Connection->Settings.MinimumMtu;

if (Connection->Settings.ServerResumptionLevel > QUIC_SERVER_NO_RESUME &&
Connection->HandshakeTP == NULL) {
Expand Down
62 changes: 62 additions & 0 deletions src/core/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -1412,3 +1412,65 @@ QuicConnParamGet(
_Out_writes_bytes_opt_(*BufferLength)
void* Buffer
);

//
// Get the max MTU for a specific path.
//
_IRQL_requires_max_(DISPATCH_LEVEL)
inline
uint16_t
QuicConnGetMaxMtuForPath(
_In_ QUIC_CONNECTION* Connection,
_In_ QUIC_PATH* Path
)
{
//
// We can't currently cache the full value because this is called before
// handshake complete in QuicPacketBuilderFinalize. So cache the values
// we can.
//
uint16_t LocalMtu = Path->LocalMtu;
if (LocalMtu == 0) {
LocalMtu = CxPlatSocketGetLocalMtu(Path->Binding->Socket);
Path->LocalMtu = LocalMtu;
}
uint16_t RemoteMtu = 0xFFFF;
if ((Connection->PeerTransportParams.Flags & QUIC_TP_FLAG_MAX_UDP_PAYLOAD_SIZE)) {
RemoteMtu =
PacketSizeFromUdpPayloadSize(
QuicAddrGetFamily(&Path->RemoteAddress),
(uint16_t)Connection->PeerTransportParams.MaxUdpPayloadSize);
}
uint16_t SettingsMtu = Connection->Settings.MaximumMtu;
return min(min(LocalMtu, RemoteMtu), SettingsMtu);
}

//
// Check to see if enough time has passed while in Search Complete to retry MTU
// discovery.
//
_IRQL_requires_max_(PASSIVE_LEVEL)
inline
void
QuicMtuDiscoveryCheckSearchCompleteTimeout(
_In_ QUIC_CONNECTION* Connection,
_In_ uint64_t TimeNow
)
{
uint64_t TimeoutTime = Connection->Settings.MtuDiscoverySearchCompleteTimeoutUs;
for (uint8_t i = 0; i < Connection->PathsCount; i++) {
//
// Only trigger a new send if we're in Search Complete and enough time has
// passed.
//
QUIC_PATH* Path = &Connection->Paths[i];
if (!Path->IsActive || !Path->MtuDiscovery.IsSearchComplete) {
continue;
}
if (CxPlatTimeDiff64(
Path->MtuDiscovery.SearchCompleteEnterTimeUs,
TimeNow) >= TimeoutTime) {
QuicMtuDiscoveryMoveToSearching(&Path->MtuDiscovery, Connection);
}
}
}
2 changes: 2 additions & 0 deletions src/core/core.kernel.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
<ClCompile Include="listener.c" />
<ClCompile Include="lookup.c" />
<ClCompile Include="loss_detection.c" />
<ClCompile Include="mtu_discovery.c" />
<ClCompile Include="operation.c" />
<ClCompile Include="packet.c" />
<ClCompile Include="packet_builder.c" />
Expand Down Expand Up @@ -85,6 +86,7 @@
<ClInclude Include="listener.h" />
<ClInclude Include="lookup.h" />
<ClInclude Include="loss_detection.h" />
<ClInclude Include="mtu_discovery.h" />
<ClInclude Include="operation.h" />
<ClInclude Include="packet.h" />
<ClInclude Include="packet_builder.h" />
Expand Down
8 changes: 7 additions & 1 deletion src/core/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -1561,7 +1561,13 @@ QuicCryptoProcessTlsCompletion(
}
Connection->Stats.ResumptionSucceeded = Crypto->TlsState.SessionResumed;

QuicSendSetSendFlag(&Connection->Send, QUIC_CONN_SEND_FLAG_PMTUD);
//
// A handshake complete means the peer has been validated. Trigger MTU
// discovery on path.
//
CXPLAT_DBG_ASSERT(Connection->PathsCount == 1);
QUIC_PATH* Path = &Connection->Paths[0];
QuicMtuDiscoveryPeerValidated(&Path->MtuDiscovery, Connection);

if (QuicConnIsServer(Connection) &&
Crypto->TlsState.BufferOffset1Rtt != 0 &&
Expand Down
2 changes: 1 addition & 1 deletion src/core/datagram.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ QuicDatagramOnSendStateChanged(
MtuMaxSendLength =
QuicCalculateDatagramLength(
QUIC_ADDRESS_FAMILY_INET6,
QUIC_DEFAULT_PATH_MTU,
QUIC_DPLPMUTD_MIN_MTU,
QUIC_MIN_INITIAL_CONNECTION_ID_LENGTH);
} else {
const QUIC_PATH* Path = &Connection->Paths[0];
Expand Down
13 changes: 13 additions & 0 deletions src/core/inline.c
Original file line number Diff line number Diff line change
Expand Up @@ -670,3 +670,16 @@ BOOLEAN
QuicErrorIsProtocolError(
_In_ QUIC_VAR_INT ErrorCode
);

uint16_t
QuicConnGetMaxMtuForPath(
_In_ QUIC_CONNECTION* Connection,
_In_ QUIC_PATH* Path
);

_IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicMtuDiscoveryCheckSearchCompleteTimeout(
_In_ QUIC_CONNECTION* Connection,
_In_ uint64_t TimeNow
);
1 change: 1 addition & 0 deletions src/core/library.c
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,7 @@ QuicLibrarySetGlobalParam(
&MsQuicLib.Settings,
TRUE,
TRUE,
TRUE,
BufferLength,
(QUIC_SETTINGS*)Buffer)) {
Status = QUIC_STATUS_INVALID_PARAMETER;
Expand Down
49 changes: 33 additions & 16 deletions src/core/loss_detection.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ _IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicLossDetectionOnPacketDiscarded(
_In_ QUIC_LOSS_DETECTION* LossDetection,
_In_ QUIC_SENT_PACKET_METADATA* Packet
_In_ QUIC_SENT_PACKET_METADATA* Packet,
_In_ BOOLEAN DiscardedForLoss
);

_IRQL_requires_max_(PASSIVE_LEVEL)
Expand Down Expand Up @@ -137,7 +138,7 @@ QuicLossDetectionUninitialize(

}

QuicLossDetectionOnPacketDiscarded(LossDetection, Packet);
QuicLossDetectionOnPacketDiscarded(LossDetection, Packet, FALSE);
}
while (LossDetection->LostPackets != NULL) {
QUIC_SENT_PACKET_METADATA* Packet = LossDetection->LostPackets;
Expand All @@ -149,7 +150,7 @@ QuicLossDetectionUninitialize(
PtkConnPre(Connection),
Packet->PacketNumber);

QuicLossDetectionOnPacketDiscarded(LossDetection, Packet);
QuicLossDetectionOnPacketDiscarded(LossDetection, Packet, FALSE);
}
}

Expand Down Expand Up @@ -603,25 +604,28 @@ QuicLossDetectionOnPacketAcknowledged(
PacketSizeFromUdpPayloadSize(
QuicAddrGetFamily(&Path->RemoteAddress),
Packet->PacketLength);

BOOLEAN ChangedMtu = FALSE;
if (!Path->IsMinMtuValidated &&
Packet->PacketLength >= QUIC_INITIAL_PACKET_LENGTH) {
PacketMtu >= Path->Mtu) {
Path->IsMinMtuValidated = TRUE;
ChangedMtu = PacketMtu > Path->Mtu;
QuicTraceLogConnInfo(
PathMinMtuValidated,
Connection,
"Path[%hhu] Minimum MTU validated",
Path->ID);
}

if (PacketMtu > Path->Mtu) {
Path->Mtu = PacketMtu;
QuicTraceLogConnInfo(
PathMtuUpdated,
Connection,
"Path[%hhu] MTU updated to %hu bytes",
Path->ID,
Path->Mtu);
if (Packet->Flags.IsMtuProbe) {
CXPLAT_DBG_ASSERT(Path->IsMinMtuValidated);
if (QuicMtuDiscoveryOnAckedPacket(
&Path->MtuDiscovery,
PacketMtu,
Connection)) {
ChangedMtu = TRUE;
}
}
if (ChangedMtu) {
QuicDatagramOnSendStateChanged(&Connection->Datagram);
}
}
Expand All @@ -647,7 +651,7 @@ QuicLossDetectionRetransmitFrames(
for (uint8_t i = 0; i < Packet->FrameCount; i++) {
switch (Packet->Frames[i].Type) {
case QUIC_FRAME_PING:
if (!Packet->Flags.IsPMTUD) {
if (!Packet->Flags.IsMtuProbe) {
//
// Don't consider PING "new data" so that we might still find
// "real" data later that should be sent instead.
Expand Down Expand Up @@ -840,7 +844,8 @@ _IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicLossDetectionOnPacketDiscarded(
_In_ QUIC_LOSS_DETECTION* LossDetection,
_In_ QUIC_SENT_PACKET_METADATA* Packet
_In_ QUIC_SENT_PACKET_METADATA* Packet,
_In_ BOOLEAN DiscardedForLoss
)
{
QUIC_CONNECTION* Connection = QuicLossDetectionGetConnection(LossDetection);
Expand All @@ -856,6 +861,18 @@ QuicLossDetectionOnPacketDiscarded(
QUIC_DATAGRAM_SEND_LOST_DISCARDED);
break;
}
if (Packet->Flags.IsMtuProbe && DiscardedForLoss) {
uint8_t PathIndex;
QUIC_PATH* Path = QuicConnGetPathByID(Connection, Packet->PathId, &PathIndex);
UNREFERENCED_PARAMETER(PathIndex);
if (Path != NULL) {
uint16_t PacketMtu =
PacketSizeFromUdpPayloadSize(
QuicAddrGetFamily(&Path->RemoteAddress),
Packet->PacketLength);
QuicMtuDiscoveryProbePacketDiscarded(&Path->MtuDiscovery, Connection, PacketMtu);
}
}
}

QuicSentPacketPoolReturnPacketMetadata(&Connection->Worker->SentPacketPool, Packet);
Expand Down Expand Up @@ -894,7 +911,7 @@ QuicLossDetectionDetectAndHandleLostPackets(
PtkConnPre(Connection),
Packet->PacketNumber);
LossDetection->LostPackets = Packet->Next;
QuicLossDetectionOnPacketDiscarded(LossDetection, Packet);
QuicLossDetectionOnPacketDiscarded(LossDetection, Packet, TRUE);
}
if (LossDetection->LostPackets == NULL) {
LossDetection->LostPacketsTail = &LossDetection->LostPackets;
Expand Down
Loading

0 comments on commit de0cddc

Please sign in to comment.