Skip to content

Fix DSCP detection on Windows. Add DSCP support to SecNetPerf #5130

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

Merged
merged 8 commits into from
Jun 13, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/perf/lib/PerfClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,20 @@ PerfClientConnection::Initialize() {
}
}

if (PerfDefaultDscpValue != 0) {
Status =
MsQuic->SetParam(
Handle,
QUIC_PARAM_CONN_SEND_DSCP,
sizeof(PerfDefaultDscpValue),
&PerfDefaultDscpValue);
if (QUIC_FAILED(Status)) {
WriteOutput("SetSendDscp failed, 0x%x\n", Status);
Worker.ConnectionPool.Free(this);
return;
}
}

if (Client.CibirIdLength) {
Status =
MsQuic->SetParam(
Expand Down
7 changes: 7 additions & 0 deletions src/perf/lib/PerfServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,13 @@ PerfServer::ListenerCallback(
if (Event->Type == QUIC_LISTENER_EVENT_NEW_CONNECTION) {
BOOLEAN value = TRUE;
MsQuic->SetParam(Event->NEW_CONNECTION.Connection, QUIC_PARAM_CONN_DISABLE_1RTT_ENCRYPTION, sizeof(value), &value);
if (PerfDefaultDscpValue != 0) {
MsQuic->SetParam(
Event->NEW_CONNECTION.Connection,
QUIC_PARAM_CONN_SEND_DSCP,
sizeof(PerfDefaultDscpValue),
&PerfDefaultDscpValue);
}
QUIC_CONNECTION_CALLBACK_HANDLER Handler =
[](HQUIC Conn, void* Context, QUIC_CONNECTION_EVENT* Event) -> QUIC_STATUS {
return ((PerfServer*)Context)->ConnectionCallback(Conn, Event);
Expand Down
1 change: 1 addition & 0 deletions src/perf/lib/SecNetPerf.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ extern uint8_t PerfDefaultEcnEnabled;
extern uint8_t PerfDefaultQeoAllowed;
extern uint8_t PerfDefaultHighPriority;
extern uint8_t PerfDefaultAffinitizeThreads;
extern uint8_t PerfDefaultDscpValue;

extern CXPLAT_DATAPATH* Datapath;

Expand Down
7 changes: 7 additions & 0 deletions src/perf/lib/SecNetPerfMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ uint8_t PerfDefaultEcnEnabled = false;
uint8_t PerfDefaultQeoAllowed = false;
uint8_t PerfDefaultHighPriority = false;
uint8_t PerfDefaultAffinitizeThreads = false;
uint8_t PerfDefaultDscpValue = 0;

#ifdef _KERNEL_MODE
volatile int BufferCurrent;
Expand Down Expand Up @@ -142,6 +143,7 @@ PrintHelp(
" -cpu:<cpu_index> Specify the processor(s) to use.\n"
" -cipher:<value> Decimal value of 1 or more QUIC_ALLOWED_CIPHER_SUITE_FLAGS.\n"
" -highpri:<0/1> Configures MsQuic to run threads at high priority. (def:0)\n"
" -dscp:<0-63> Specify DSCP value to mark sent packets with. (def:0)\n"
"\n",
PERF_DEFAULT_PORT,
PERF_DEFAULT_PORT
Expand Down Expand Up @@ -290,6 +292,11 @@ QuicMainStart(

TryGetValue(argc, argv, "ecn", &PerfDefaultEcnEnabled);
TryGetValue(argc, argv, "qeo", &PerfDefaultQeoAllowed);
TryGetValue(argc, argv, "dscp", &PerfDefaultDscpValue);
if (PerfDefaultDscpValue > CXPLAT_MAX_DSCP) {
WriteOutput("DSCP Value %u is outside the valid range (0-63). Using 0.\n", PerfDefaultDscpValue);
PerfDefaultDscpValue = 0;
}

uint32_t WatchdogTimeout = 0;
if (TryGetValue(argc, argv, "watchdog", &WatchdogTimeout) && WatchdogTimeout != 0) {
Expand Down
26 changes: 13 additions & 13 deletions src/platform/datapath_winkernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ CxPlatDataPathQuerySockoptSupport(
} while (FALSE);

do {
DWORD TypeOfService = 1; // Lower Effort
DWORD TypeOfService = CXPLAT_DSCP_LE << 2;

IoReuseIrp(Irp, STATUS_SUCCESS);
IoSetCompletionRoutine(
Expand Down Expand Up @@ -1479,7 +1479,7 @@ SocketCreateUdp(
CxPlatDataPathSetControlSocket(
Binding,
WskSetOption,
IPV6_ECN,
IPV6_RECVTCLASS,
IPPROTO_IPV6,
sizeof(Option),
&Option);
Expand All @@ -1489,7 +1489,7 @@ SocketCreateUdp(
"[data][%p] ERROR, %u, %s.",
Binding,
Status,
"Set IPV6_ECN");
"Set IPV6_RECVTCLASS");
goto Error;
}

Expand All @@ -1498,7 +1498,7 @@ SocketCreateUdp(
CxPlatDataPathSetControlSocket(
Binding,
WskSetOption,
IP_ECN,
IP_RECVTOS,
IPPROTO_IP,
sizeof(Option),
&Option);
Expand All @@ -1508,7 +1508,7 @@ SocketCreateUdp(
"[data][%p] ERROR, %u, %s.",
Binding,
Status,
"Set IP_ECN");
"Set IP_RECVTOS");
goto Error;
}

Expand Down Expand Up @@ -2036,7 +2036,7 @@ CxPlatDataPathSocketReceive(
SOCKADDR_INET LocalAddr = { 0 };
SOCKADDR_INET RemoteAddr;
UINT16 MessageLength = 0;
INT ECN = 0;
INT TypeOfService = 0;
INT HopLimitTTL = 0;

//
Expand Down Expand Up @@ -2066,9 +2066,9 @@ CxPlatDataPathSocketReceive(
IsUnreachableError = TRUE;
break;
}
} else if (CMsg->cmsg_type == IPV6_ECN) {
ECN = *(PINT)WSA_CMSG_DATA(CMsg);
CXPLAT_DBG_ASSERT(ECN < UINT8_MAX);
} else if (CMsg->cmsg_type == IPV6_TCLASS) {
TypeOfService = *(PINT)WSA_CMSG_DATA(CMsg);
CXPLAT_DBG_ASSERT(TypeOfService < UINT8_MAX);
} else if (CMsg->cmsg_type == IPV6_HOPLIMIT) {
HopLimitTTL = *(PINT)WSA_CMSG_DATA(CMsg);
CXPLAT_DBG_ASSERT(HopLimitTTL < 256);
Expand All @@ -2089,9 +2089,9 @@ CxPlatDataPathSocketReceive(
IsUnreachableError = TRUE;
break;
}
} else if (CMsg->cmsg_type == IP_ECN) {
ECN = *(PINT)WSA_CMSG_DATA(CMsg);
CXPLAT_DBG_ASSERT(ECN < UINT8_MAX);
} else if (CMsg->cmsg_type == IP_TOS) {
TypeOfService = *(PINT)WSA_CMSG_DATA(CMsg);
CXPLAT_DBG_ASSERT(TypeOfService < UINT8_MAX);
} else if (CMsg->cmsg_type == IP_TTL) {
HopLimitTTL = *(PINT)WSA_CMSG_DATA(CMsg);
CXPLAT_DBG_ASSERT(HopLimitTTL < 256);
Expand Down Expand Up @@ -2252,7 +2252,7 @@ CxPlatDataPathSocketReceive(
Datagram->IoBlock = IoBlock;
Datagram->Data.Next = NULL;
Datagram->Data.PartitionIndex = (uint16_t)(CurProcNumber % Binding->Datapath->ProcCount);
Datagram->Data.TypeOfService = (uint8_t)ECN;
Datagram->Data.TypeOfService = (uint8_t)TypeOfService;
Datagram->Data.HopLimitTTL = (uint8_t)HopLimitTTL;
Datagram->Data.Allocated = TRUE;
Datagram->Data.QueuedOnConnection = FALSE;
Expand Down
27 changes: 14 additions & 13 deletions src/platform/datapath_winuser.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ typedef struct DATAPATH_RX_IO_BLOCK {
WSA_CMSG_SPACE(sizeof(IN6_PKTINFO)) + // IP_PKTINFO
WSA_CMSG_SPACE(sizeof(DWORD)) + // UDP_COALESCED_INFO
WSA_CMSG_SPACE(sizeof(INT)) + // IP_ECN
WSA_CMSG_SPACE(sizeof(INT)) + // IP_TOS
WSA_CMSG_SPACE(sizeof(INT)) // IP_HOP_LIMIT
];

Expand Down Expand Up @@ -704,7 +705,7 @@ CxPlatDataPathQuerySockoptSupport(
goto Error;
}

DWORD TypeOfService = 1; // Lower Effort
DWORD TypeOfService = CXPLAT_DSCP_LE << 2;
OptionLength = sizeof(TypeOfService);
Result =
setsockopt(
Expand Down Expand Up @@ -1663,7 +1664,7 @@ SocketCreateUdp(
setsockopt(
SocketProc->Socket,
IPPROTO_IPV6,
IPV6_ECN,
IPV6_RECVTCLASS,
(char*)&Option,
sizeof(Option));
if (Result == SOCKET_ERROR) {
Expand All @@ -1673,7 +1674,7 @@ SocketCreateUdp(
"[data][%p] ERROR, %u, %s.",
Socket,
WsaError,
"Set IPV6_ECN");
"Set IPV6_RECVTCLASS");
Status = HRESULT_FROM_WIN32(WsaError);
goto Error;
}
Expand All @@ -1683,7 +1684,7 @@ SocketCreateUdp(
setsockopt(
SocketProc->Socket,
IPPROTO_IP,
IP_ECN,
IP_RECVTOS,
(char*)&Option,
sizeof(Option));
if (Result == SOCKET_ERROR) {
Expand All @@ -1693,7 +1694,7 @@ SocketCreateUdp(
"[data][%p] ERROR, %u, %s.",
Socket,
WsaError,
"Set IP_ECN");
"Set IP_RECVTOS");
Status = HRESULT_FROM_WIN32(WsaError);
goto Error;
}
Expand Down Expand Up @@ -3435,7 +3436,7 @@ CxPlatDataPathUdpRecvComplete(
UINT16 MessageLength = NumberOfBytesTransferred;
ULONG MessageCount = 0;
BOOLEAN IsCoalesced = FALSE;
INT ECN = 0;
INT TypeOfService = 0;
INT HopLimitTTL = 0;
if (SocketProc->Parent->UseRio) {
PRIO_CMSG_BUFFER RioRcvMsg = (PRIO_CMSG_BUFFER)IoBlock->ControlBuf;
Expand All @@ -3456,9 +3457,9 @@ CxPlatDataPathUdpRecvComplete(
CxPlatConvertFromMappedV6(LocalAddr, LocalAddr);
LocalAddr->Ipv6.sin6_scope_id = PktInfo6->ipi6_ifindex;
FoundLocalAddr = TRUE;
} else if (CMsg->cmsg_type == IPV6_ECN) {
ECN = *(PINT)WSA_CMSG_DATA(CMsg);
CXPLAT_DBG_ASSERT(ECN < UINT8_MAX);
} else if (CMsg->cmsg_type == IPV6_TCLASS) {
TypeOfService = *(PINT)WSA_CMSG_DATA(CMsg);
CXPLAT_DBG_ASSERT(TypeOfService < UINT8_MAX);
} else if (CMsg->cmsg_type == IPV6_HOPLIMIT) {
HopLimitTTL = *(PINT)WSA_CMSG_DATA(CMsg);
CXPLAT_DBG_ASSERT(HopLimitTTL < 256);
Expand All @@ -3472,9 +3473,9 @@ CxPlatDataPathUdpRecvComplete(
LocalAddr->Ipv4.sin_port = SocketProc->Parent->LocalAddress.Ipv6.sin6_port;
LocalAddr->Ipv6.sin6_scope_id = PktInfo->ipi_ifindex;
FoundLocalAddr = TRUE;
} else if (CMsg->cmsg_type == IP_ECN) {
ECN = *(PINT)WSA_CMSG_DATA(CMsg);
CXPLAT_DBG_ASSERT(ECN < UINT8_MAX);
} else if (CMsg->cmsg_type == IP_TOS) {
TypeOfService = *(PINT)WSA_CMSG_DATA(CMsg);
CXPLAT_DBG_ASSERT(TypeOfService < UINT8_MAX);
} else if (CMsg->cmsg_type == IP_TTL) {
HopLimitTTL = *(PINT)WSA_CMSG_DATA(CMsg);
CXPLAT_DBG_ASSERT(HopLimitTTL < 256);
Expand Down Expand Up @@ -3535,7 +3536,7 @@ CxPlatDataPathUdpRecvComplete(
Datagram->Route = &IoBlock->Route;
Datagram->PartitionIndex =
SocketProc->DatapathProc->PartitionIndex % SocketProc->DatapathProc->Datapath->PartitionCount;
Datagram->TypeOfService = (uint8_t)ECN;
Datagram->TypeOfService = (uint8_t)TypeOfService;
Datagram->HopLimitTTL = (uint8_t) HopLimitTTL;
Datagram->Allocated = TRUE;
Datagram->Route->DatapathType = Datagram->DatapathType = CXPLAT_DATAPATH_TYPE_NORMAL;
Expand Down
Loading