Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Track Received ECN Counts #677

Merged
merged 3 commits into from
Aug 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
34 changes: 26 additions & 8 deletions src/core/ack_tracker.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@ QuicAckTrackerInitialize(
_Inout_ QUIC_ACK_TRACKER* Tracker
)
{
Tracker->AckElicitingPacketsToAcknowledge = 0;
Tracker->LargestPacketNumberAcknowledged = 0;
Tracker->LargestPacketNumberRecvTime = 0;
Tracker->AlreadyWrittenAckFrame = FALSE;

QuicRangeInitialize(
QUIC_MAX_RANGE_DUPLICATE_PACKETS,
&Tracker->PacketNumbersReceived);
Expand Down Expand Up @@ -82,6 +77,8 @@ QuicAckTrackerReset(
Tracker->LargestPacketNumberAcknowledged = 0;
Tracker->LargestPacketNumberRecvTime = 0;
Tracker->AlreadyWrittenAckFrame = FALSE;
Tracker->NonZeroRecvECN = FALSE;
QuicZeroMemory(&Tracker->ReceivedECN, sizeof(Tracker->ReceivedECN));
QuicRangeReset(&Tracker->PacketNumbersToAck);
QuicRangeReset(&Tracker->PacketNumbersReceived);
}
Expand All @@ -104,6 +101,7 @@ void
QuicAckTrackerAckPacket(
_Inout_ QUIC_ACK_TRACKER* Tracker,
_In_ uint64_t PacketNumber,
_In_ QUIC_ECN_TYPE ECN,
_In_ BOOLEAN AckElicitingPayload
)
{
Expand Down Expand Up @@ -132,16 +130,34 @@ QuicAckTrackerAckPacket(

QuicTraceLogVerbose(
PacketRxMarkedForAck,
"[%c][RX][%llu] Marked for ACK",
"[%c][RX][%llu] Marked for ACK (ECN=%hhu)",
PtkConnPre(Connection),
PacketNumber);
PacketNumber,
ECN);

BOOLEAN NewLargestPacketNumber =
PacketNumber == QuicRangeGetMax(&Tracker->PacketNumbersToAck);
if (NewLargestPacketNumber) {
Tracker->LargestPacketNumberRecvTime = QuicTimeUs64();
}

switch (ECN) {
case QUIC_ECN_ECT_0:
Tracker->NonZeroRecvECN = TRUE;
Tracker->ReceivedECN.ECT_0_Count++;
break;
case QUIC_ECN_ECT_1:
Tracker->NonZeroRecvECN = TRUE;
Tracker->ReceivedECN.ECT_1_Count++;
break;
case QUIC_ECN_CE:
Tracker->NonZeroRecvECN = TRUE;
Tracker->ReceivedECN.CE_Count++;
break;
default:
break;
}

Tracker->AlreadyWrittenAckFrame = FALSE;

if (!AckElicitingPayload) {
Expand Down Expand Up @@ -211,7 +227,9 @@ QuicAckTrackerAckFrameEncode(
if (!QuicAckFrameEncode(
&Tracker->PacketNumbersToAck,
AckDelay,
NULL, // No ECN right now.
Tracker->NonZeroRecvECN ?
&Tracker->ReceivedECN :
NULL,
&Builder->DatagramLength,
(uint16_t)Builder->Datagram->Length - Builder->EncryptionOverhead,
Builder->Datagram->Buffer)) {
Expand Down
13 changes: 12 additions & 1 deletion src/core/ack_tracker.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ typedef struct QUIC_ACK_TRACKER {
//
QUIC_RANGE PacketNumbersToAck;

//
// The current count of recieved ECNs
//
QUIC_ACK_ECN_EX ReceivedECN;

//
// The largest packet number we have sent an ACK for.
//
Expand All @@ -40,7 +45,12 @@ typedef struct QUIC_ACK_TRACKER {
// Indicates an ACK frame has already been written for all the currently
// queued packet numbers.
//
BOOLEAN AlreadyWrittenAckFrame;
BOOLEAN AlreadyWrittenAckFrame : 1;

//
// Indicates that we have received a non-zero ECN type.
//
BOOLEAN NonZeroRecvECN : 1;

} QUIC_ACK_TRACKER;

Expand Down Expand Up @@ -89,6 +99,7 @@ void
QuicAckTrackerAckPacket(
_Inout_ QUIC_ACK_TRACKER* Tracker,
_In_ uint64_t PacketNumber,
_In_ QUIC_ECN_TYPE ECN,
_In_ BOOLEAN AckElicitingPayload
);

Expand Down
7 changes: 5 additions & 2 deletions src/core/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -3779,7 +3779,8 @@ BOOLEAN
QuicConnRecvFrames(
_In_ QUIC_CONNECTION* Connection,
_In_ QUIC_PATH* Path,
_In_ QUIC_RECV_PACKET* Packet
_In_ QUIC_RECV_PACKET* Packet,
_In_ QUIC_ECN_TYPE ECN
)
{
BOOLEAN AckPacketImmediately = FALSE; // Allows skipping delayed ACK timer.
Expand Down Expand Up @@ -4554,6 +4555,7 @@ QuicConnRecvFrames(
QuicAckTrackerAckPacket(
&Connection->Packets[EncryptLevel]->AckTracker,
Packet->PacketNumber,
ECN,
AckPacketImmediately);
}

Expand Down Expand Up @@ -4743,11 +4745,12 @@ QuicConnRecvDatagramBatch(

for (uint8_t i = 0; i < BatchCount; ++i) {
QUIC_DBG_ASSERT(Datagrams[i]->Allocated);
QUIC_ECN_TYPE ECN = QUIC_ECN_FROM_TOS(Datagrams[i]->TypeOfService);
Packet = QuicDataPathRecvDatagramToRecvPacket(Datagrams[i]);
if (QuicConnRecvPrepareDecrypt(
Connection, Packet, HpMask + i * QUIC_HP_SAMPLE_LENGTH) &&
QuicConnRecvDecryptAndAuthenticate(Connection, Path, Packet) &&
QuicConnRecvFrames(Connection, Path, Packet)) {
QuicConnRecvFrames(Connection, Path, Packet, ECN)) {

QuicConnRecvPostProcessing(Connection, &Path, Packet);
RecvState->ResetIdleTimeout |= Packet->CompletelyValid;
Expand Down
4 changes: 2 additions & 2 deletions src/core/frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ QuicAckEcnEncode(
{
uint16_t RequiredLength =
QuicVarIntSize(Ecn->ECT_0_Count) +
QuicVarIntSize(Ecn->ECT_0_Count) +
QuicVarIntSize(Ecn->ECT_1_Count) +
QuicVarIntSize(Ecn->CE_Count);

if (BufferLength < *Offset + RequiredLength) {
Expand All @@ -139,7 +139,7 @@ QuicAckEcnEncode(

Buffer = Buffer + *Offset;
Buffer = QuicVarIntEncode(Ecn->ECT_0_Count, Buffer);
Buffer = QuicVarIntEncode(Ecn->ECT_0_Count, Buffer);
Buffer = QuicVarIntEncode(Ecn->ECT_1_Count, Buffer);
Buffer = QuicVarIntEncode(Ecn->CE_Count, Buffer);
*Offset += RequiredLength;

Expand Down
21 changes: 21 additions & 0 deletions src/inc/quic_datapath.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,21 @@ extern "C" {
//
#define QUIC_UDP_HEADER_SIZE 8

typedef enum QUIC_ECN_TYPE {

QUIC_ECN_NON_ECT = 0x0, // Non ECN-Capable Transport, Non-ECT
QUIC_ECN_ECT_0 = 0x1, // ECN Capable Transport, ECT(0)
QUIC_ECN_ECT_1 = 0x2, // ECN Capable Transport, ECT(1)
QUIC_ECN_CE = 0x3 // Congestion Encountered, CE

} QUIC_ECN_TYPE;

//
// Helper to get the ECN type from the Type of Service field of a recieved
// datagram.
//
#define QUIC_ECN_FROM_TOS(ToS) (QUIC_ECN_TYPE)((ToS) & 0x3)

//
// The minimum allowed IP MTU for QUIC.
//
Expand Down Expand Up @@ -159,6 +174,12 @@ typedef struct QUIC_RECV_DATAGRAM {
//
uint8_t PartitionIndex;

//
// The Type of Service (ToS) field of the IPv4 header or Traffic Class field
// of the IPv6 header.
//
uint8_t TypeOfService;

//
// Flags.
//
Expand Down
8 changes: 4 additions & 4 deletions src/manifest/clog.sidecar
Original file line number Diff line number Diff line change
Expand Up @@ -19779,10 +19779,6 @@
},
"ModuleUniqueness": {
"TraceInformation": [
{
"UniquenessHash": "e0cfb1a0-1258-6f19-06e3-1c55dc984679",
"TraceID": "PacketRxMarkedForAck"
},
{
"UniquenessHash": "92b1bb9f-afd4-62fa-3fb6-1021c09c5916",
"TraceID": "ApiEnter"
Expand Down Expand Up @@ -21778,6 +21774,10 @@
{
"UniquenessHash": "43482b75-cdcb-d2cd-f082-c1928bc7864d",
"TraceID": "PeerPreferredAddress"
},
{
"UniquenessHash": "bb7402a7-ba47-dbce-71f2-fbbd659eb0ff",
"TraceID": "PacketRxMarkedForAck"
}
]
}
Expand Down
1 change: 1 addition & 0 deletions src/platform/datapath_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -1240,6 +1240,7 @@ QuicSocketContextRecvComplete(
RecvPacket->BufferLength = BytesTransferred;

RecvPacket->PartitionIndex = ProcContext->Index;
RecvPacket->TypeOfService = 0; // TODO - Support ToS/ECN

QUIC_DBG_ASSERT(SocketContext->Binding->Datapath->RecvHandler);
SocketContext->Binding->Datapath->RecvHandler(
Expand Down
1 change: 1 addition & 0 deletions src/platform/datapath_winkernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -2050,6 +2050,7 @@ QuicDataPathSocketReceive(
QUIC_DBG_ASSERT(Datagram != NULL);
Datagram->Next = NULL;
Datagram->PartitionIndex = (uint8_t)CurProcNumber;
Datagram->TypeOfService = 0; // TODO - Support ToS/ECN
Datagram->Allocated = TRUE;
Datagram->QueuedOnConnection = FALSE;

Expand Down
1 change: 1 addition & 0 deletions src/platform/datapath_winuser.c
Original file line number Diff line number Diff line change
Expand Up @@ -2016,6 +2016,7 @@ QuicDataPathRecvComplete(
Datagram->BufferLength = MessageLength;
Datagram->Tuple = &RecvContext->Tuple;
Datagram->PartitionIndex = (uint8_t)ProcContext->Index;
Datagram->TypeOfService = 0; // TODO - Support ToS/ECN
Datagram->Allocated = TRUE;
Datagram->QueuedOnConnection = FALSE;

Expand Down