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

Grab a UDP Port Reservation #2017

Merged
merged 11 commits into from
Oct 5, 2021
24 changes: 24 additions & 0 deletions src/generated/linux/datapath_winuser.c.clog.h
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,30 @@ tracepoint(CLOG_DATAPATH_WINUSER_C, DatapathErrorStatus , arg2, arg3, arg4);\



#ifndef _clog_5_ARGS_TRACE_DatapathErrorStatus
maolson-msft marked this conversation as resolved.
Show resolved Hide resolved



/*----------------------------------------------------------
// Decoder Ring for DatapathErrorStatus
// [data][%p] ERROR, %u, %s.
// QuicTraceEvent(
DatapathErrorStatus,
"[data][%p] ERROR, %u, %s.",
Socket,
WsaError,
"SIO_ACQUIRE_PORT_RESERVATION");
// arg2 = arg2 = Socket
// arg3 = arg3 = WsaError
// arg4 = arg4 = "SIO_ACQUIRE_PORT_RESERVATION"
----------------------------------------------------------*/
#define _clog_5_ARGS_TRACE_DatapathErrorStatus(uniqueId, encoded_arg_string, arg2, arg3, arg4)\

#endif




#ifndef _clog_5_ARGS_TRACE_DatapathErrorStatus


Expand Down
62 changes: 62 additions & 0 deletions src/platform/datapath_winuser.c
Original file line number Diff line number Diff line change
Expand Up @@ -1410,6 +1410,7 @@ CxPlatSocketCreateUdp(
int Option;
BOOLEAN IsServerSocket = Config->RemoteAddress == NULL;
uint16_t SocketCount = IsServerSocket ? Datapath->ProcCount : 1;
INET_PORT_RESERVATION_INSTANCE PortReservation;

CXPLAT_DBG_ASSERT(Datapath->UdpHandlers.Receive != NULL || Config->Flags & CXPLAT_SOCKET_FLAG_PCP);

Expand Down Expand Up @@ -1789,6 +1790,67 @@ QUIC_DISABLED_BY_FUZZER_START;
}
}

if (Config->LocalAddress &&
Config->LocalAddress->Ipv4.sin_port != 0) {
if (i == 0) {
//
// Create a port reservation for the local port.
//
INET_PORT_RANGE PortRange;
PortRange.StartPort = Config->LocalAddress->Ipv4.sin_port;
PortRange.NumberOfPorts = 1;

Result =
WSAIoctl(
SocketProc->Socket,
SIO_ACQUIRE_PORT_RESERVATION,
&PortRange,
sizeof(PortRange),
&PortReservation,
sizeof(PortReservation),
&BytesReturned,
NULL,
NULL);
if (Result == SOCKET_ERROR) {
int WsaError = WSAGetLastError();
QuicTraceEvent(
DatapathErrorStatus,
"[data][%p] ERROR, %u, %s.",
Socket,
WsaError,
"SIO_ACQUIRE_PORT_RESERVATION");
Status = HRESULT_FROM_WIN32(WsaError);
goto Error;
}
}

//
// Associate the port reservation with the socket.
//
Result =
WSAIoctl(
SocketProc->Socket,
SIO_ASSOCIATE_PORT_RESERVATION,
&PortReservation.Token,
sizeof(PortReservation.Token),
NULL,
0,
&BytesReturned,
NULL,
NULL);
if (Result == SOCKET_ERROR) {
int WsaError = WSAGetLastError();
QuicTraceEvent(
DatapathErrorStatus,
"[data][%p] ERROR, %u, %s.",
Socket,
WsaError,
"SIO_ASSOCIATE_PORT_RESERVATION");
Status = HRESULT_FROM_WIN32(WsaError);
goto Error;
}
}

Result =
bind(
SocketProc->Socket,
Expand Down
6 changes: 6 additions & 0 deletions src/test/lib/HandshakeTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2597,7 +2597,13 @@ QuicTestLoadBalancedHandshake(
// Sometimes the local port might be used already. Just ignore this
// failure and continue on.
//
#ifdef _WIN32
TEST_TRUE(
Connection.TransportShutdownStatus == QUIC_STATUS_ADDRESS_IN_USE ||
Connection.TransportShutdownStatus == HRESULT_FROM_WIN32(WSAEACCES));
#else
TEST_TRUE(Connection.TransportShutdownStatus == QUIC_STATUS_ADDRESS_IN_USE);
#endif

} else {
if (SchannelMode) {
Expand Down