diff --git a/src/core/connection.c b/src/core/connection.c index 2235a32914..9964f1e3cd 100644 --- a/src/core/connection.c +++ b/src/core/connection.c @@ -5769,21 +5769,14 @@ QuicConnRecvDatagrams( CXPLAT_DBG_ASSERT(Packet->ReleaseDeferred == IsDeferred); Packet->ReleaseDeferred = FALSE; - QUIC_PATH* DatagramPath = QuicConnGetPathForPacket(Connection, Packet); - if (DatagramPath == NULL) { - QuicPacketLogDrop(Connection, Packet, "Max paths already tracked"); - goto Drop; - } - - CxPlatUpdateRoute(&DatagramPath->Route, Packet->Route); - - if (DatagramPath != CurrentPath) { + if (CurrentPath == NULL) { + CurrentPath = QuicConnGetPathForPacket(Connection, Packet); + } else if (!QuicPathMatchPacket(CurrentPath, Packet)) { if (BatchCount != 0) { // // This datagram is from a different path than the current // batch. Flush the current batch before continuing. // - CXPLAT_DBG_ASSERT(CurrentPath != NULL); QuicConnRecvDatagramBatch( Connection, CurrentPath, @@ -5793,9 +5786,20 @@ QuicConnRecvDatagrams( &RecvState); BatchCount = 0; } - CurrentPath = DatagramPath; + // + // Path lookup can modify the path array, so only do it after the + // current batch no longer holds a path pointer. + // + CurrentPath = QuicConnGetPathForPacket(Connection, Packet); + } + + if (CurrentPath == NULL) { + QuicPacketLogDrop(Connection, Packet, "Max paths already tracked"); + goto Drop; } + CxPlatUpdateRoute(&CurrentPath->Route, Packet->Route); + if (!IsDeferred) { Connection->Stats.Recv.TotalBytes += Packet->BufferLength; if (Connection->Stats.Handshake.HandshakeHopLimitTTL == 0) { diff --git a/src/core/path.c b/src/core/path.c index 563f8d30d1..c302f377ea 100644 --- a/src/core/path.c +++ b/src/core/path.c @@ -257,6 +257,22 @@ QuicConnGetPathByID( return NULL; } +_IRQL_requires_max_(PASSIVE_LEVEL) +BOOLEAN +QuicPathMatchPacket( + _In_ const QUIC_PATH* Path, + _In_ const QUIC_RX_PACKET* Packet + ) +{ + return + QuicAddrCompare( + &Packet->Route->LocalAddress, + &Path->Route.LocalAddress) && + QuicAddrCompare( + &Packet->Route->RemoteAddress, + &Path->Route.RemoteAddress); +} + _IRQL_requires_max_(PASSIVE_LEVEL) _Ret_maybenull_ QUIC_PATH* @@ -267,12 +283,7 @@ QuicConnGetPathForPacket( { QUIC_PATH_SET* PathSet = &Connection->Paths; for (uint8_t i = 0; i < PathSet->Count; ++i) { - if (!QuicAddrCompare( - &Packet->Route->LocalAddress, - &PathSet->Paths[i].Route.LocalAddress) || - !QuicAddrCompare( - &Packet->Route->RemoteAddress, - &PathSet->Paths[i].Route.RemoteAddress)) { + if (!QuicPathMatchPacket(&PathSet->Paths[i], Packet)) { if (!Connection->State.HandshakeConfirmed) { // // Ignore packets on any other paths until connected/confirmed. diff --git a/src/core/path.h b/src/core/path.h index 4dafd7d53e..2024c31f10 100644 --- a/src/core/path.h +++ b/src/core/path.h @@ -333,6 +333,13 @@ QuicConnGetPathByID( _Out_ uint8_t* Index ); +_IRQL_requires_max_(PASSIVE_LEVEL) +BOOLEAN +QuicPathMatchPacket( + _In_ const QUIC_PATH* Path, + _In_ const QUIC_RX_PACKET* Packet + ); + _IRQL_requires_max_(PASSIVE_LEVEL) _Ret_maybenull_ QUIC_PATH*