diff --git a/src/platform/datapath_raw.c b/src/platform/datapath_raw.c index f9b827eafd..0750b17fae 100644 --- a/src/platform/datapath_raw.c +++ b/src/platform/datapath_raw.c @@ -189,7 +189,7 @@ RawSocketDelete( { CxPlatDpRawPlumbRulesOnSocket(Socket, FALSE); CxPlatRemoveSocket(&Socket->RawDatapath->SocketPool, Socket); - CxPlatRundownReleaseAndWait(&Socket->Rundown); + CxPlatRundownReleaseAndWait(&Socket->RawRundown); if (Socket->PausedTcpSend) { CxPlatDpRawTxFree(Socket->PausedTcpSend); } @@ -269,7 +269,7 @@ CxPlatDpRawRxEthernet( CxPlatDpRawRxFree(PacketChain); } - CxPlatRundownRelease(&Socket->Rundown); + CxPlatRundownRelease(&Socket->RawRundown); } else { CxPlatDpRawRxFree(PacketChain); } diff --git a/src/platform/datapath_raw.h b/src/platform/datapath_raw.h index c23d63d449..c77f42ced9 100644 --- a/src/platform/datapath_raw.h +++ b/src/platform/datapath_raw.h @@ -260,7 +260,7 @@ CxPlatDpRawTxEnqueue( typedef struct CXPLAT_SOCKET_RAW { CXPLAT_HASHTABLE_ENTRY Entry; - CXPLAT_RUNDOWN_REF Rundown; + CXPLAT_RUNDOWN_REF RawRundown; CXPLAT_DATAPATH_RAW* RawDatapath; SOCKET AuxSocket; BOOLEAN Wildcard; // Using a wildcard local address. Optimization @@ -392,43 +392,6 @@ CxPlatFramingWriteHeaders( #pragma pack(push) #pragma pack(1) -typedef struct ETHERNET_HEADER { - uint8_t Destination[6]; - uint8_t Source[6]; - uint16_t Type; - uint8_t Data[0]; -} ETHERNET_HEADER; - -typedef struct IPV4_HEADER { - uint8_t VersionAndHeaderLength; - union { - uint8_t TypeOfServiceAndEcnField; - struct { - uint8_t EcnField : 2; - uint8_t TypeOfService : 6; - }; - }; - uint16_t TotalLength; - uint16_t Identification; - uint16_t FlagsAndFragmentOffset; - uint8_t TimeToLive; - uint8_t Protocol; - uint16_t HeaderChecksum; - uint8_t Source[4]; - uint8_t Destination[4]; - uint8_t Data[0]; -} IPV4_HEADER; - -typedef struct IPV6_HEADER { - uint32_t VersionClassEcnFlow; - uint16_t PayloadLength; - uint8_t NextHeader; - uint8_t HopLimit; - uint8_t Source[16]; - uint8_t Destination[16]; - uint8_t Data[0]; -} IPV6_HEADER; - typedef struct IPV6_EXTENSION { uint8_t NextHeader; uint8_t Length; @@ -474,11 +437,52 @@ typedef struct TCP_HEADER { #define TH_CWR 0x80 #define IPV4_VERSION 4 -#define IPV6_VERSION 6 #define IPV4_VERSION_BYTE (IPV4_VERSION << 4) -#define IPV4_DEFAULT_VERHLEN ((IPV4_VERSION_BYTE) | (sizeof(IPV4_HEADER) / sizeof(uint32_t))) #define IP_DEFAULT_HOP_LIMIT 128 +#ifndef _KERNEL_MODE +typedef struct ETHERNET_HEADER { + uint8_t Destination[6]; + uint8_t Source[6]; + uint16_t Type; + uint8_t Data[0]; +} ETHERNET_HEADER; + +typedef struct IPV4_HEADER { + uint8_t VersionAndHeaderLength; + union { + uint8_t TypeOfServiceAndEcnField; + struct { + uint8_t EcnField : 2; + uint8_t TypeOfService : 6; + }; + }; + uint16_t TotalLength; + uint16_t Identification; + uint16_t FlagsAndFragmentOffset; + uint8_t TimeToLive; + uint8_t Protocol; + uint16_t HeaderChecksum; + uint8_t Source[4]; + uint8_t Destination[4]; + uint8_t Data[0]; +} IPV4_HEADER; + +typedef struct IPV6_HEADER { + uint32_t VersionClassEcnFlow; + uint16_t PayloadLength; + uint8_t NextHeader; + uint8_t HopLimit; + uint8_t Source[16]; + uint8_t Destination[16]; + uint8_t Data[0]; +} IPV6_HEADER; + +#define IPV6_VERSION 6 +#define IPV4_DEFAULT_VERHLEN ((IPV4_VERSION_BYTE) | (sizeof(IPV4_HEADER) / sizeof(uint32_t))) + #define ETHERNET_TYPE_IPV4 0x0008 #define ETHERNET_TYPE_IPV6 0xdd86 + +#endif \ No newline at end of file diff --git a/src/platform/datapath_raw_linux.c b/src/platform/datapath_raw_linux.c index 06c712c6cc..02fbf05dd4 100644 --- a/src/platform/datapath_raw_linux.c +++ b/src/platform/datapath_raw_linux.c @@ -112,7 +112,7 @@ RawSocketCreateUdp( { QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - CxPlatRundownInitialize(&NewSocket->Rundown); + CxPlatRundownInitialize(&NewSocket->RawRundown); NewSocket->RawDatapath = Raw; NewSocket->CibirIdLength = Config->CibirIdLength; NewSocket->CibirIdOffsetSrc = Config->CibirIdOffsetSrc; @@ -169,7 +169,7 @@ RawSocketCreateUdp( if (QUIC_FAILED(Status)) { if (NewSocket != NULL) { - CxPlatRundownUninitialize(&NewSocket->Rundown); + CxPlatRundownUninitialize(&NewSocket->RawRundown); CxPlatZeroMemory(NewSocket, sizeof(CXPLAT_SOCKET_RAW) - sizeof(CXPLAT_SOCKET)); NewSocket = NULL; } diff --git a/src/platform/datapath_raw_socket.c b/src/platform/datapath_raw_socket.c index e0a31c07da..7e33b932c9 100644 --- a/src/platform/datapath_raw_socket.c +++ b/src/platform/datapath_raw_socket.c @@ -62,7 +62,7 @@ CxPlatGetSocket( while (Entry != NULL) { CXPLAT_SOCKET_RAW* Temp = CXPLAT_CONTAINING_RECORD(Entry, CXPLAT_SOCKET_RAW, Entry); if (CxPlatSocketCompare(Temp, LocalAddress, RemoteAddress)) { - if (CxPlatRundownAcquire(&Temp->Rundown)) { + if (CxPlatRundownAcquire(&Temp->RawRundown)) { Socket = Temp; } break; diff --git a/src/platform/datapath_raw_win.c b/src/platform/datapath_raw_win.c index c5aa8b18bb..d3f01926cd 100644 --- a/src/platform/datapath_raw_win.c +++ b/src/platform/datapath_raw_win.c @@ -113,7 +113,7 @@ RawSocketCreateUdp( CXPLAT_DBG_ASSERT(Socket != NULL); QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - CxPlatRundownInitialize(&Socket->Rundown); + CxPlatRundownInitialize(&Socket->RawRundown); Socket->RawDatapath = Raw; Socket->CibirIdLength = Config->CibirIdLength; Socket->CibirIdOffsetSrc = Config->CibirIdOffsetSrc; @@ -167,7 +167,7 @@ RawSocketCreateUdp( if (QUIC_FAILED(Status)) { if (Socket != NULL) { - CxPlatRundownUninitialize(&Socket->Rundown); + CxPlatRundownUninitialize(&Socket->RawRundown); CxPlatZeroMemory(Socket, sizeof(CXPLAT_SOCKET_RAW) - sizeof(CXPLAT_SOCKET)); Socket = NULL; } diff --git a/src/platform/datapath_win.c b/src/platform/datapath_win.c index 6cab97b861..6512dc98ab 100644 --- a/src/platform/datapath_win.c +++ b/src/platform/datapath_win.c @@ -15,334 +15,6 @@ #include "datapath_winuser.c.clog.h" #endif -_IRQL_requires_max_(PASSIVE_LEVEL) -_Success_(QUIC_SUCCEEDED(return)) -QUIC_STATUS -CxPlatDataPathGetLocalAddresses( - _In_ CXPLAT_DATAPATH* Datapath, - _Outptr_ _At_(*Addresses, __drv_allocatesMem(Mem)) - CXPLAT_ADAPTER_ADDRESS** Addresses, - _Out_ uint32_t* AddressesCount - ) -{ - const ULONG Flags = - GAA_FLAG_INCLUDE_ALL_INTERFACES | - GAA_FLAG_SKIP_ANYCAST | - GAA_FLAG_SKIP_MULTICAST | - GAA_FLAG_SKIP_DNS_SERVER | - GAA_FLAG_SKIP_FRIENDLY_NAME | - GAA_FLAG_SKIP_DNS_INFO; - - UNREFERENCED_PARAMETER(Datapath); - - ULONG AdapterAddressesSize = 0; - PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL; - uint32_t Index = 0; - - QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - ULONG Error; - do { - Error = - GetAdaptersAddresses( - AF_UNSPEC, - Flags, - NULL, - AdapterAddresses, - &AdapterAddressesSize); - if (Error == ERROR_BUFFER_OVERFLOW) { - if (AdapterAddresses) { - CXPLAT_FREE(AdapterAddresses, QUIC_POOL_DATAPATH_ADDRESSES); - } - AdapterAddresses = CXPLAT_ALLOC_NONPAGED(AdapterAddressesSize, QUIC_POOL_DATAPATH_ADDRESSES); - if (!AdapterAddresses) { - Error = ERROR_NOT_ENOUGH_MEMORY; - QuicTraceEvent( - AllocFailure, - "Allocation of '%s' failed. (%llu bytes)", - "PIP_ADAPTER_ADDRESSES", - AdapterAddressesSize); - } - } - } while (Error == ERROR_BUFFER_OVERFLOW); - - if (Error != ERROR_SUCCESS) { - QuicTraceEvent( - LibraryErrorStatus, - "[ lib] ERROR, %u, %s.", - Error, - "GetAdaptersAddresses"); - Status = HRESULT_FROM_WIN32(Error); - goto Exit; - } - - for (PIP_ADAPTER_ADDRESSES Iter = AdapterAddresses; Iter != NULL; Iter = Iter->Next) { - for (PIP_ADAPTER_UNICAST_ADDRESS_LH Iter2 = Iter->FirstUnicastAddress; Iter2 != NULL; Iter2 = Iter2->Next) { - Index++; - } - } - - if (Index == 0) { - QuicTraceEvent( - LibraryError, - "[ lib] ERROR, %s.", - "No local unicast addresses found"); - Status = QUIC_STATUS_NOT_FOUND; - goto Exit; - } - - *Addresses = CXPLAT_ALLOC_NONPAGED(Index * sizeof(CXPLAT_ADAPTER_ADDRESS), QUIC_POOL_DATAPATH_ADDRESSES); - if (*Addresses == NULL) { - Status = QUIC_STATUS_OUT_OF_MEMORY; - QuicTraceEvent( - AllocFailure, - "Allocation of '%s' failed. (%llu bytes)", - "Addresses", - Index * sizeof(CXPLAT_ADAPTER_ADDRESS)); - goto Exit; - } - - CxPlatZeroMemory(*Addresses, Index * sizeof(CXPLAT_ADAPTER_ADDRESS)); - *AddressesCount = Index; - Index = 0; - - for (PIP_ADAPTER_ADDRESSES Iter = AdapterAddresses; Iter != NULL; Iter = Iter->Next) { - for (PIP_ADAPTER_UNICAST_ADDRESS_LH Iter2 = Iter->FirstUnicastAddress; Iter2 != NULL; Iter2 = Iter2->Next) { - CxPlatCopyMemory( - &(*Addresses)[Index].Address, - Iter2->Address.lpSockaddr, - sizeof(QUIC_ADDR)); - (*Addresses)[Index].InterfaceIndex = - Iter2->Address.lpSockaddr->sa_family == AF_INET ? - (uint32_t)Iter->IfIndex : (uint32_t)Iter->Ipv6IfIndex; - (*Addresses)[Index].InterfaceType = (uint16_t)Iter->IfType; - (*Addresses)[Index].OperationStatus = (CXPLAT_OPERATION_STATUS)Iter->OperStatus; - Index++; - } - } - -Exit: - - if (AdapterAddresses) { - CXPLAT_FREE(AdapterAddresses, QUIC_POOL_DATAPATH_ADDRESSES); - } - - return Status; -} - -_IRQL_requires_max_(PASSIVE_LEVEL) -_Success_(QUIC_SUCCEEDED(return)) -QUIC_STATUS -CxPlatDataPathGetGatewayAddresses( - _In_ CXPLAT_DATAPATH* Datapath, - _Outptr_ _At_(*GatewayAddresses, __drv_allocatesMem(Mem)) - QUIC_ADDR** GatewayAddresses, - _Out_ uint32_t* GatewayAddressesCount - ) -{ - const ULONG Flags = - GAA_FLAG_INCLUDE_GATEWAYS | - GAA_FLAG_INCLUDE_ALL_INTERFACES | - GAA_FLAG_SKIP_DNS_SERVER | - GAA_FLAG_SKIP_MULTICAST; - - UNREFERENCED_PARAMETER(Datapath); - - ULONG AdapterAddressesSize = 0; - PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL; - uint32_t Index = 0; - - QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - ULONG Error; - do { - Error = - GetAdaptersAddresses( - AF_UNSPEC, - Flags, - NULL, - AdapterAddresses, - &AdapterAddressesSize); - if (Error == ERROR_BUFFER_OVERFLOW) { - if (AdapterAddresses) { - CXPLAT_FREE(AdapterAddresses, QUIC_POOL_DATAPATH_ADDRESSES); - } - AdapterAddresses = CXPLAT_ALLOC_NONPAGED(AdapterAddressesSize, QUIC_POOL_DATAPATH_ADDRESSES); - if (!AdapterAddresses) { - Error = ERROR_NOT_ENOUGH_MEMORY; - QuicTraceEvent( - AllocFailure, - "Allocation of '%s' failed. (%llu bytes)", - "PIP_ADAPTER_ADDRESSES", - AdapterAddressesSize); - } - } - } while (Error == ERROR_BUFFER_OVERFLOW); - - if (Error != ERROR_SUCCESS) { - QuicTraceEvent( - LibraryErrorStatus, - "[ lib] ERROR, %u, %s.", - Error, - "GetAdaptersAddresses"); - Status = HRESULT_FROM_WIN32(Error); - goto Exit; - } - - for (PIP_ADAPTER_ADDRESSES Iter = AdapterAddresses; Iter != NULL; Iter = Iter->Next) { - for (PIP_ADAPTER_GATEWAY_ADDRESS_LH Iter2 = Iter->FirstGatewayAddress; Iter2 != NULL; Iter2 = Iter2->Next) { - Index++; - } - } - - if (Index == 0) { - QuicTraceEvent( - LibraryError, - "[ lib] ERROR, %s.", - "No gateway server addresses found"); - Status = QUIC_STATUS_NOT_FOUND; - goto Exit; - } - - *GatewayAddresses = CXPLAT_ALLOC_NONPAGED(Index * sizeof(QUIC_ADDR), QUIC_POOL_DATAPATH_ADDRESSES); - if (*GatewayAddresses == NULL) { - Status = QUIC_STATUS_OUT_OF_MEMORY; - QuicTraceEvent( - AllocFailure, - "Allocation of '%s' failed. (%llu bytes)", - "GatewayAddresses", - Index * sizeof(QUIC_ADDR)); - goto Exit; - } - - CxPlatZeroMemory(*GatewayAddresses, Index * sizeof(QUIC_ADDR)); - *GatewayAddressesCount = Index; - Index = 0; - - for (PIP_ADAPTER_ADDRESSES Iter = AdapterAddresses; Iter != NULL; Iter = Iter->Next) { - for (PIP_ADAPTER_GATEWAY_ADDRESS_LH Iter2 = Iter->FirstGatewayAddress; Iter2 != NULL; Iter2 = Iter2->Next) { - CxPlatCopyMemory( - &(*GatewayAddresses)[Index], - Iter2->Address.lpSockaddr, - sizeof(QUIC_ADDR)); - Index++; - } - } - -Exit: - - if (AdapterAddresses) { - CXPLAT_FREE(AdapterAddresses, QUIC_POOL_DATAPATH_ADDRESSES); - } - - return Status; -} - -// private func -void -CxPlatDataPathPopulateTargetAddress( - _In_ ADDRESS_FAMILY Family, - _In_ ADDRINFOW *Ai, - _Out_ SOCKADDR_INET* Address - ) -{ - if (Ai->ai_addr->sa_family == QUIC_ADDRESS_FAMILY_INET6) { - // - // Is this a mapped ipv4 one? - // - PSOCKADDR_IN6 SockAddr6 = (PSOCKADDR_IN6)Ai->ai_addr; - - if (Family == QUIC_ADDRESS_FAMILY_UNSPEC && IN6ADDR_ISV4MAPPED(SockAddr6)) - { - PSOCKADDR_IN SockAddr4 = &Address->Ipv4; - // - // Get the ipv4 address from the mapped address. - // - SockAddr4->sin_family = QUIC_ADDRESS_FAMILY_INET; - SockAddr4->sin_addr = - *(IN_ADDR UNALIGNED *) - IN6_GET_ADDR_V4MAPPED(&SockAddr6->sin6_addr); - SockAddr4->sin_port = SockAddr6->sin6_port; - return; - } - } - - CxPlatCopyMemory(Address, Ai->ai_addr, Ai->ai_addrlen); -} - -_IRQL_requires_max_(PASSIVE_LEVEL) -QUIC_STATUS -CxPlatDataPathResolveAddress( - _In_ CXPLAT_DATAPATH* Datapath, - _In_z_ const char* HostName, - _Inout_ QUIC_ADDR* Address - ) -{ - QUIC_STATUS Status; - PWSTR HostNameW = NULL; - ADDRINFOW Hints = { 0 }; - ADDRINFOW *Ai; - - Status = - CxPlatUtf8ToWideChar( - HostName, - QUIC_POOL_PLATFORM_TMP_ALLOC, - &HostNameW); - if (QUIC_FAILED(Status)) { - QuicTraceEvent( - LibraryErrorStatus, - "[ lib] ERROR, %u, %s.", - Status, - "Convert HostName to unicode"); - goto Exit; - } - - // - // Prepopulate hint with input family. It might be unspecified. - // - Hints.ai_family = Address->si_family; - - // - // Try numeric name first. - // - Hints.ai_flags = AI_NUMERICHOST; - if (GetAddrInfoW(HostNameW, NULL, &Hints, &Ai) == 0) { - CxPlatDataPathPopulateTargetAddress((ADDRESS_FAMILY)Hints.ai_family, Ai, Address); - FreeAddrInfoW(Ai); - Status = QUIC_STATUS_SUCCESS; - goto Exit; - } - - // - // Try canonical host name. - // - Hints.ai_flags = AI_CANONNAME; - if (GetAddrInfoW(HostNameW, NULL, &Hints, &Ai) == 0) { - CxPlatDataPathPopulateTargetAddress((ADDRESS_FAMILY)Hints.ai_family, Ai, Address); - FreeAddrInfoW(Ai); - Status = QUIC_STATUS_SUCCESS; - goto Exit; - } - - QuicTraceEvent( - LibraryError, - "[ lib] ERROR, %s.", - "Resolving hostname to IP"); - QuicTraceLogError( - DatapathResolveHostNameFailed, - "[%p] Couldn't resolve hostname '%s' to an IP address", - Datapath, - HostName); - Status = HRESULT_FROM_WIN32(WSAHOST_NOT_FOUND); - -Exit: - - if (HostNameW != NULL) { - CXPLAT_FREE(HostNameW, QUIC_POOL_PLATFORM_TMP_ALLOC); - } - - return Status; -} - - _IRQL_requires_max_(PASSIVE_LEVEL) QUIC_STATUS CxPlatSocketUpdateQeo( diff --git a/src/platform/datapath_winkernel.c b/src/platform/datapath_winkernel.c index 111b72890e..03a458f64f 100644 --- a/src/platform/datapath_winkernel.c +++ b/src/platform/datapath_winkernel.c @@ -273,158 +273,6 @@ CxPlatDataPathSocketReceive( _In_opt_ PWSK_DATAGRAM_INDICATION DataIndication ); -typedef struct _WSK_DATAGRAM_SOCKET { - const WSK_PROVIDER_DATAGRAM_DISPATCH* Dispatch; -} WSK_DATAGRAM_SOCKET, * PWSK_DATAGRAM_SOCKET; - -// -// Per-port state. -// -typedef struct CXPLAT_SOCKET { - - // - // Flag indicates the binding has a default remote destination. - // - BOOLEAN Connected : 1; - - // - // Flag indicates the binding is being used for PCP. - // - BOOLEAN PcpBinding : 1; - - // - // Parent datapath. - // - CXPLAT_DATAPATH* Datapath; - - // - // UDP socket used for sending/receiving datagrams. - // - union { - PWSK_SOCKET Socket; - PWSK_DATAGRAM_SOCKET DgrmSocket; - }; - - // - // Event used to wait for completion of socket functions. - // - CXPLAT_EVENT WskCompletionEvent; - - // - // The local address and UDP port. - // - SOCKADDR_INET LocalAddress; - - // - // The remote address and UDP port. - // - SOCKADDR_INET RemoteAddress; - - // - // The local interface's MTU. - // - UINT16 Mtu; - - // - // Client context pointer. - // - void *ClientContext; - - // - // IRP used for socket functions. - // - union { - IRP Irp; - UCHAR IrpBuffer[sizeof(IRP) + sizeof(IO_STACK_LOCATION)]; - }; - - CXPLAT_RUNDOWN_REF Rundown[0]; // Per-proc - -} CXPLAT_SOCKET; - -// -// Represents the per-processor state of the datapath context. -// -typedef struct CXPLAT_DATAPATH_PROC_CONTEXT { - - // - // Pool of send contexts to be shared by all sockets on this core. - // - CXPLAT_POOL SendDataPool; - - // - // Pool of send buffers to be shared by all sockets on this core. - // - CXPLAT_POOL SendBufferPool; - - // - // Pool of large segmented send buffers to be shared by all sockets on this - // core. - // - CXPLAT_POOL LargeSendBufferPool; - - // - // Pool of receive datagram contexts and buffers to be shared by all sockets - // on this core. Index 0 is regular, Index 1 is URO. - // - // - CXPLAT_POOL RecvDatagramPools[2]; - - // - // Pool of receive data buffers. Index 0 is 4096, Index 1 is 65536. - // - CXPLAT_POOL RecvBufferPools[2]; - - int64_t OutstandingPendingBytes; - -} CXPLAT_DATAPATH_PROC_CONTEXT; - -// -// Structure that maintains all the internal state for the -// CxPlatDataPath interface. -// -typedef struct CXPLAT_DATAPATH { - - // - // Set of supported features. - // - uint32_t Features; - - // - // The registration with WinSock Kernel. - // - WSK_REGISTRATION WskRegistration; - WSK_PROVIDER_NPI WskProviderNpi; - WSK_CLIENT_DATAGRAM_DISPATCH WskDispatch; - - // - // The UDP callback function pointers. - // - CXPLAT_UDP_DATAPATH_CALLBACKS UdpHandlers; - - // - // The size of the buffer to allocate for client's receive context structure. - // - uint32_t ClientRecvDataLength; - - // - // The size of each receive datagram array element, including client context, - // internal context, and padding. - // - uint32_t DatagramStride; - - // - // The number of processors. - // - uint32_t ProcCount; - - // - // Per-processor completion contexts. - // - CXPLAT_DATAPATH_PROC_CONTEXT ProcContexts[0]; - -} CXPLAT_DATAPATH; - _IRQL_requires_same_ _Function_class_(ALLOCATE_FUNCTION_EX) PVOID @@ -789,7 +637,7 @@ CxPlatDataPathQuerySockoptSupport( _IRQL_requires_max_(PASSIVE_LEVEL) QUIC_STATUS -CxPlatDataPathInitialize( +DataPathInitialize( _In_ uint32_t ClientRecvDataLength, _In_opt_ const CXPLAT_UDP_DATAPATH_CALLBACKS* UdpCallbacks, _In_opt_ const CXPLAT_TCP_DATAPATH_CALLBACKS* TcpCallbacks, @@ -1008,7 +856,7 @@ CxPlatDataPathInitialize( _IRQL_requires_max_(PASSIVE_LEVEL) void -CxPlatDataPathUninitialize( +DataPathUninitialize( _In_ CXPLAT_DATAPATH* Datapath ) { @@ -1032,7 +880,7 @@ CxPlatDataPathUninitialize( _IRQL_requires_max_(PASSIVE_LEVEL) void -CxPlatDataPathUpdateConfig( +DataPathUpdateConfig( _In_ CXPLAT_DATAPATH* Datapath, _In_ QUIC_EXECUTION_CONFIG* Config ) @@ -1043,7 +891,7 @@ CxPlatDataPathUpdateConfig( _IRQL_requires_max_(DISPATCH_LEVEL) uint32_t -CxPlatDataPathGetSupportedFeatures( +DataPathGetSupportedFeatures( _In_ CXPLAT_DATAPATH* Datapath ) { @@ -1052,12 +900,10 @@ CxPlatDataPathGetSupportedFeatures( _IRQL_requires_max_(DISPATCH_LEVEL) BOOLEAN -CxPlatDataPathIsPaddingPreferred( - _In_ CXPLAT_DATAPATH* Datapath, - _In_ CXPLAT_SEND_DATA* SendData +DataPathIsPaddingPreferred( + _In_ CXPLAT_DATAPATH* Datapath ) { - UNREFERENCED_PARAMETER(SendData); return !!(Datapath->Features & CXPLAT_DATAPATH_FEATURE_SEND_SEGMENTATION); } @@ -1384,7 +1230,7 @@ CxPlatDataPathSetControlSocket( _IRQL_requires_max_(PASSIVE_LEVEL) QUIC_STATUS -CxPlatSocketCreateUdp( +SocketCreateUdp( _In_ CXPLAT_DATAPATH* Datapath, _In_ const CXPLAT_UDP_CONFIG* Config, _Out_ CXPLAT_SOCKET** NewBinding @@ -1868,7 +1714,7 @@ CxPlatSocketCreateUdp( _IRQL_requires_max_(PASSIVE_LEVEL) QUIC_STATUS -CxPlatSocketCreateTcp( +SocketCreateTcp( _In_ CXPLAT_DATAPATH* Datapath, _In_opt_ const QUIC_ADDR* LocalAddress, _In_ const QUIC_ADDR* RemoteAddress, @@ -1886,7 +1732,7 @@ CxPlatSocketCreateTcp( _IRQL_requires_max_(PASSIVE_LEVEL) QUIC_STATUS -CxPlatSocketCreateTcpListener( +SocketCreateTcpListener( _In_ CXPLAT_DATAPATH* Datapath, _In_opt_ const QUIC_ADDR* LocalAddress, _In_opt_ void* CallbackContext, @@ -1954,7 +1800,7 @@ CxPlatDataPathCloseSocketIoCompletion( _IRQL_requires_max_(PASSIVE_LEVEL) void -CxPlatSocketDelete( +SocketDelete( _In_ CXPLAT_SOCKET* Binding ) { @@ -2002,21 +1848,6 @@ CxPlatSocketDelete( CxPlatSocketDeleteComplete(Binding); } -_IRQL_requires_max_(PASSIVE_LEVEL) -QUIC_STATUS -CxPlatSocketUpdateQeo( - _In_ CXPLAT_SOCKET* Socket, - _In_reads_(OffloadCount) - const CXPLAT_QEO_CONNECTION* Offloads, - _In_ uint32_t OffloadCount - ) -{ - UNREFERENCED_PARAMETER(Socket); - UNREFERENCED_PARAMETER(Offloads); - UNREFERENCED_PARAMETER(OffloadCount); - return QUIC_STATUS_NOT_SUPPORTED; -} - _IRQL_requires_max_(DISPATCH_LEVEL) BOOLEAN CxPlatSocketSetContext( @@ -2045,48 +1876,6 @@ CxPlatSocketGetContext( return Binding->ClientContext; } -_IRQL_requires_max_(DISPATCH_LEVEL) -UINT16 -CxPlatSocketGetLocalMtu( - _In_ CXPLAT_SOCKET* Binding - ) -{ - CXPLAT_DBG_ASSERT(Binding != NULL); - return Binding->Mtu; -} - -_IRQL_requires_max_(DISPATCH_LEVEL) -void -CxPlatSocketGetLocalAddress( - _In_ CXPLAT_SOCKET* Binding, - _Out_ QUIC_ADDR* Address - ) -{ - CXPLAT_DBG_ASSERT(Binding != NULL); - *Address = Binding->LocalAddress; -} - -_IRQL_requires_max_(DISPATCH_LEVEL) -void -CxPlatSocketGetRemoteAddress( - _In_ CXPLAT_SOCKET* Binding, - _Out_ QUIC_ADDR* Address - ) -{ - CXPLAT_DBG_ASSERT(Binding != NULL); - *Address = Binding->RemoteAddress; -} - -_IRQL_requires_max_(DISPATCH_LEVEL) -BOOLEAN -CxPlatSocketRawSocketAvailable( - _In_ CXPLAT_SOCKET* Socket - ) -{ - UNREFERENCED_PARAMETER(Socket); - return FALSE; -} - _IRQL_requires_max_(DISPATCH_LEVEL) DATAPATH_RX_IO_BLOCK* CxPlatSocketAllocRxIoBlock( @@ -2513,8 +2302,8 @@ CxPlatDataPathSocketReceive( _IRQL_requires_max_(DISPATCH_LEVEL) void -CxPlatRecvDataReturn( - _In_opt_ CXPLAT_RECV_DATA* RecvDataChain +RecvDataReturn( + _In_ CXPLAT_RECV_DATA* RecvDataChain ) { CXPLAT_SOCKET* Binding = NULL; @@ -2589,7 +2378,7 @@ CxPlatRecvDataReturn( _IRQL_requires_max_(DISPATCH_LEVEL) _Success_(return != NULL) CXPLAT_SEND_DATA* -CxPlatSendDataAlloc( +SendDataAlloc( _In_ CXPLAT_SOCKET* Binding, _Inout_ CXPLAT_SEND_CONFIG* Config ) @@ -2621,7 +2410,7 @@ CxPlatSendDataAlloc( _IRQL_requires_max_(DISPATCH_LEVEL) void -CxPlatSendDataFree( +SendDataFree( _In_ CXPLAT_SEND_DATA* SendData ) { @@ -2858,7 +2647,7 @@ CxPlatSendDataAllocSegmentBuffer( _IRQL_requires_max_(DISPATCH_LEVEL) _Success_(return != NULL) QUIC_BUFFER* -CxPlatSendDataAllocBuffer( +SendDataAllocBuffer( _In_ CXPLAT_SEND_DATA* SendData, _In_ UINT16 MaxBufferLength ) @@ -2912,7 +2701,7 @@ CxPlatSendDataFreeSendBuffer( _IRQL_requires_max_(DISPATCH_LEVEL) void -CxPlatSendDataFreeBuffer( +SendDataFreeBuffer( _In_ CXPLAT_SEND_DATA* SendData, _In_ QUIC_BUFFER* Buffer ) @@ -2943,7 +2732,7 @@ CxPlatSendDataFreeBuffer( _IRQL_requires_max_(DISPATCH_LEVEL) BOOLEAN -CxPlatSendDataIsFull( +SendDataIsFull( _In_ CXPLAT_SEND_DATA* SendData ) { @@ -2976,7 +2765,7 @@ CxPlatDataPathSendComplete( } IoCleanupIrp(&SendData->Irp); - CxPlatSendDataFree(SendData); + SendDataFree(SendData); return STATUS_MORE_PROCESSING_REQUIRED; } @@ -3005,7 +2794,7 @@ CxPlatSocketPrepareSendData( _IRQL_requires_max_(DISPATCH_LEVEL) void -CxPlatSocketSend( +SocketSend( _In_ CXPLAT_SOCKET* Binding, _In_ const CXPLAT_ROUTE* Route, _In_ CXPLAT_SEND_DATA* SendData @@ -3136,55 +2925,11 @@ CxPlatSocketGetTcpStatistics( return QUIC_STATUS_NOT_SUPPORTED; } -_IRQL_requires_max_(PASSIVE_LEVEL) -void -QuicCopyRouteInfo( - _Inout_ CXPLAT_ROUTE* DstRoute, - _In_ CXPLAT_ROUTE* SrcRoute - ) -{ - *DstRoute = *SrcRoute; -} - void -CxPlatResolveRouteComplete( - _In_ void* Context, - _Inout_ CXPLAT_ROUTE* Route, - _In_reads_bytes_(6) const uint8_t* PhysicalAddress, - _In_ uint8_t PathId +DataPathProcessCqe( + _In_ CXPLAT_CQE* Cqe ) { - UNREFERENCED_PARAMETER(Context); - UNREFERENCED_PARAMETER(Route); - UNREFERENCED_PARAMETER(PhysicalAddress); - UNREFERENCED_PARAMETER(PathId); -} - -_IRQL_requires_max_(PASSIVE_LEVEL) -QUIC_STATUS -CxPlatResolveRoute( - _In_ CXPLAT_SOCKET* Socket, - _Inout_ CXPLAT_ROUTE* Route, - _In_ uint8_t PathId, - _In_ void* Context, - _In_ CXPLAT_ROUTE_RESOLUTION_CALLBACK_HANDLER Callback - ) -{ - UNREFERENCED_PARAMETER(Socket); - UNREFERENCED_PARAMETER(PathId); - UNREFERENCED_PARAMETER(Context); - UNREFERENCED_PARAMETER(Callback); - Route->State = RouteResolved; - return QUIC_STATUS_SUCCESS; -} - -_IRQL_requires_max_(PASSIVE_LEVEL) -void -CxPlatUpdateRoute( - _Inout_ CXPLAT_ROUTE* DstRoute, - _In_ CXPLAT_ROUTE* SrcRoute - ) -{ - UNREFERENCED_PARAMETER(DstRoute); - UNREFERENCED_PARAMETER(SrcRoute); -} + UNREFERENCED_PARAMETER(Cqe); + CXPLAT_DBG_ASSERT(FALSE); +} \ No newline at end of file diff --git a/src/platform/datapath_winuser.c b/src/platform/datapath_winuser.c index bfaafb947d..c0f78159a7 100644 --- a/src/platform/datapath_winuser.c +++ b/src/platform/datapath_winuser.c @@ -1081,6 +1081,334 @@ DataPathIsPaddingPreferred( return !!(Datapath->Features & CXPLAT_DATAPATH_FEATURE_SEND_SEGMENTATION); } +_IRQL_requires_max_(PASSIVE_LEVEL) +_Success_(QUIC_SUCCEEDED(return)) +QUIC_STATUS +CxPlatDataPathGetLocalAddresses( + _In_ CXPLAT_DATAPATH* Datapath, + _Outptr_ _At_(*Addresses, __drv_allocatesMem(Mem)) + CXPLAT_ADAPTER_ADDRESS** Addresses, + _Out_ uint32_t* AddressesCount + ) +{ + const ULONG Flags = + GAA_FLAG_INCLUDE_ALL_INTERFACES | + GAA_FLAG_SKIP_ANYCAST | + GAA_FLAG_SKIP_MULTICAST | + GAA_FLAG_SKIP_DNS_SERVER | + GAA_FLAG_SKIP_FRIENDLY_NAME | + GAA_FLAG_SKIP_DNS_INFO; + + UNREFERENCED_PARAMETER(Datapath); + + ULONG AdapterAddressesSize = 0; + PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL; + uint32_t Index = 0; + + QUIC_STATUS Status = QUIC_STATUS_SUCCESS; + ULONG Error; + do { + Error = + GetAdaptersAddresses( + AF_UNSPEC, + Flags, + NULL, + AdapterAddresses, + &AdapterAddressesSize); + if (Error == ERROR_BUFFER_OVERFLOW) { + if (AdapterAddresses) { + CXPLAT_FREE(AdapterAddresses, QUIC_POOL_DATAPATH_ADDRESSES); + } + AdapterAddresses = CXPLAT_ALLOC_NONPAGED(AdapterAddressesSize, QUIC_POOL_DATAPATH_ADDRESSES); + if (!AdapterAddresses) { + Error = ERROR_NOT_ENOUGH_MEMORY; + QuicTraceEvent( + AllocFailure, + "Allocation of '%s' failed. (%llu bytes)", + "PIP_ADAPTER_ADDRESSES", + AdapterAddressesSize); + } + } + } while (Error == ERROR_BUFFER_OVERFLOW); + + if (Error != ERROR_SUCCESS) { + QuicTraceEvent( + LibraryErrorStatus, + "[ lib] ERROR, %u, %s.", + Error, + "GetAdaptersAddresses"); + Status = HRESULT_FROM_WIN32(Error); + goto Exit; + } + + for (PIP_ADAPTER_ADDRESSES Iter = AdapterAddresses; Iter != NULL; Iter = Iter->Next) { + for (PIP_ADAPTER_UNICAST_ADDRESS_LH Iter2 = Iter->FirstUnicastAddress; Iter2 != NULL; Iter2 = Iter2->Next) { + Index++; + } + } + + if (Index == 0) { + QuicTraceEvent( + LibraryError, + "[ lib] ERROR, %s.", + "No local unicast addresses found"); + Status = QUIC_STATUS_NOT_FOUND; + goto Exit; + } + + *Addresses = CXPLAT_ALLOC_NONPAGED(Index * sizeof(CXPLAT_ADAPTER_ADDRESS), QUIC_POOL_DATAPATH_ADDRESSES); + if (*Addresses == NULL) { + Status = QUIC_STATUS_OUT_OF_MEMORY; + QuicTraceEvent( + AllocFailure, + "Allocation of '%s' failed. (%llu bytes)", + "Addresses", + Index * sizeof(CXPLAT_ADAPTER_ADDRESS)); + goto Exit; + } + + CxPlatZeroMemory(*Addresses, Index * sizeof(CXPLAT_ADAPTER_ADDRESS)); + *AddressesCount = Index; + Index = 0; + + for (PIP_ADAPTER_ADDRESSES Iter = AdapterAddresses; Iter != NULL; Iter = Iter->Next) { + for (PIP_ADAPTER_UNICAST_ADDRESS_LH Iter2 = Iter->FirstUnicastAddress; Iter2 != NULL; Iter2 = Iter2->Next) { + CxPlatCopyMemory( + &(*Addresses)[Index].Address, + Iter2->Address.lpSockaddr, + sizeof(QUIC_ADDR)); + (*Addresses)[Index].InterfaceIndex = + Iter2->Address.lpSockaddr->sa_family == AF_INET ? + (uint32_t)Iter->IfIndex : (uint32_t)Iter->Ipv6IfIndex; + (*Addresses)[Index].InterfaceType = (uint16_t)Iter->IfType; + (*Addresses)[Index].OperationStatus = (CXPLAT_OPERATION_STATUS)Iter->OperStatus; + Index++; + } + } + +Exit: + + if (AdapterAddresses) { + CXPLAT_FREE(AdapterAddresses, QUIC_POOL_DATAPATH_ADDRESSES); + } + + return Status; +} + + +_IRQL_requires_max_(PASSIVE_LEVEL) +_Success_(QUIC_SUCCEEDED(return)) +QUIC_STATUS +CxPlatDataPathGetGatewayAddresses( + _In_ CXPLAT_DATAPATH* Datapath, + _Outptr_ _At_(*GatewayAddresses, __drv_allocatesMem(Mem)) + QUIC_ADDR** GatewayAddresses, + _Out_ uint32_t* GatewayAddressesCount + ) +{ + const ULONG Flags = + GAA_FLAG_INCLUDE_GATEWAYS | + GAA_FLAG_INCLUDE_ALL_INTERFACES | + GAA_FLAG_SKIP_DNS_SERVER | + GAA_FLAG_SKIP_MULTICAST; + + UNREFERENCED_PARAMETER(Datapath); + + ULONG AdapterAddressesSize = 0; + PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL; + uint32_t Index = 0; + + QUIC_STATUS Status = QUIC_STATUS_SUCCESS; + ULONG Error; + do { + Error = + GetAdaptersAddresses( + AF_UNSPEC, + Flags, + NULL, + AdapterAddresses, + &AdapterAddressesSize); + if (Error == ERROR_BUFFER_OVERFLOW) { + if (AdapterAddresses) { + CXPLAT_FREE(AdapterAddresses, QUIC_POOL_DATAPATH_ADDRESSES); + } + AdapterAddresses = CXPLAT_ALLOC_NONPAGED(AdapterAddressesSize, QUIC_POOL_DATAPATH_ADDRESSES); + if (!AdapterAddresses) { + Error = ERROR_NOT_ENOUGH_MEMORY; + QuicTraceEvent( + AllocFailure, + "Allocation of '%s' failed. (%llu bytes)", + "PIP_ADAPTER_ADDRESSES", + AdapterAddressesSize); + } + } + } while (Error == ERROR_BUFFER_OVERFLOW); + + if (Error != ERROR_SUCCESS) { + QuicTraceEvent( + LibraryErrorStatus, + "[ lib] ERROR, %u, %s.", + Error, + "GetAdaptersAddresses"); + Status = HRESULT_FROM_WIN32(Error); + goto Exit; + } + + for (PIP_ADAPTER_ADDRESSES Iter = AdapterAddresses; Iter != NULL; Iter = Iter->Next) { + for (PIP_ADAPTER_GATEWAY_ADDRESS_LH Iter2 = Iter->FirstGatewayAddress; Iter2 != NULL; Iter2 = Iter2->Next) { + Index++; + } + } + + if (Index == 0) { + QuicTraceEvent( + LibraryError, + "[ lib] ERROR, %s.", + "No gateway server addresses found"); + Status = QUIC_STATUS_NOT_FOUND; + goto Exit; + } + + *GatewayAddresses = CXPLAT_ALLOC_NONPAGED(Index * sizeof(QUIC_ADDR), QUIC_POOL_DATAPATH_ADDRESSES); + if (*GatewayAddresses == NULL) { + Status = QUIC_STATUS_OUT_OF_MEMORY; + QuicTraceEvent( + AllocFailure, + "Allocation of '%s' failed. (%llu bytes)", + "GatewayAddresses", + Index * sizeof(QUIC_ADDR)); + goto Exit; + } + + CxPlatZeroMemory(*GatewayAddresses, Index * sizeof(QUIC_ADDR)); + *GatewayAddressesCount = Index; + Index = 0; + + for (PIP_ADAPTER_ADDRESSES Iter = AdapterAddresses; Iter != NULL; Iter = Iter->Next) { + for (PIP_ADAPTER_GATEWAY_ADDRESS_LH Iter2 = Iter->FirstGatewayAddress; Iter2 != NULL; Iter2 = Iter2->Next) { + CxPlatCopyMemory( + &(*GatewayAddresses)[Index], + Iter2->Address.lpSockaddr, + sizeof(QUIC_ADDR)); + Index++; + } + } + +Exit: + + if (AdapterAddresses) { + CXPLAT_FREE(AdapterAddresses, QUIC_POOL_DATAPATH_ADDRESSES); + } + + return Status; +} + +// private func +void +CxPlatDataPathPopulateTargetAddress( + _In_ ADDRESS_FAMILY Family, + _In_ ADDRINFOW *Ai, + _Out_ SOCKADDR_INET* Address + ) +{ + if (Ai->ai_addr->sa_family == QUIC_ADDRESS_FAMILY_INET6) { + // + // Is this a mapped ipv4 one? + // + PSOCKADDR_IN6 SockAddr6 = (PSOCKADDR_IN6)Ai->ai_addr; + + if (Family == QUIC_ADDRESS_FAMILY_UNSPEC && IN6ADDR_ISV4MAPPED(SockAddr6)) + { + PSOCKADDR_IN SockAddr4 = &Address->Ipv4; + // + // Get the ipv4 address from the mapped address. + // + SockAddr4->sin_family = QUIC_ADDRESS_FAMILY_INET; + SockAddr4->sin_addr = + *(IN_ADDR UNALIGNED *) + IN6_GET_ADDR_V4MAPPED(&SockAddr6->sin6_addr); + SockAddr4->sin_port = SockAddr6->sin6_port; + return; + } + } + + CxPlatCopyMemory(Address, Ai->ai_addr, Ai->ai_addrlen); +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +QUIC_STATUS +CxPlatDataPathResolveAddress( + _In_ CXPLAT_DATAPATH* Datapath, + _In_z_ const char* HostName, + _Inout_ QUIC_ADDR* Address + ) +{ + QUIC_STATUS Status; + PWSTR HostNameW = NULL; + ADDRINFOW Hints = { 0 }; + ADDRINFOW *Ai; + + Status = + CxPlatUtf8ToWideChar( + HostName, + QUIC_POOL_PLATFORM_TMP_ALLOC, + &HostNameW); + if (QUIC_FAILED(Status)) { + QuicTraceEvent( + LibraryErrorStatus, + "[ lib] ERROR, %u, %s.", + Status, + "Convert HostName to unicode"); + goto Exit; + } + + // + // Prepopulate hint with input family. It might be unspecified. + // + Hints.ai_family = Address->si_family; + + // + // Try numeric name first. + // + Hints.ai_flags = AI_NUMERICHOST; + if (GetAddrInfoW(HostNameW, NULL, &Hints, &Ai) == 0) { + CxPlatDataPathPopulateTargetAddress((ADDRESS_FAMILY)Hints.ai_family, Ai, Address); + FreeAddrInfoW(Ai); + Status = QUIC_STATUS_SUCCESS; + goto Exit; + } + + // + // Try canonical host name. + // + Hints.ai_flags = AI_CANONNAME; + if (GetAddrInfoW(HostNameW, NULL, &Hints, &Ai) == 0) { + CxPlatDataPathPopulateTargetAddress((ADDRESS_FAMILY)Hints.ai_family, Ai, Address); + FreeAddrInfoW(Ai); + Status = QUIC_STATUS_SUCCESS; + goto Exit; + } + + QuicTraceEvent( + LibraryError, + "[ lib] ERROR, %s.", + "Resolving hostname to IP"); + QuicTraceLogError( + DatapathResolveHostNameFailed, + "[%p] Couldn't resolve hostname '%s' to an IP address", + Datapath, + HostName); + Status = HRESULT_FROM_WIN32(WSAHOST_NOT_FOUND); + +Exit: + + if (HostNameW != NULL) { + CXPLAT_FREE(HostNameW, QUIC_POOL_PLATFORM_TMP_ALLOC); + } + + return Status; +} + void CxPlatSocketArmRioNotify( _In_ CXPLAT_SOCKET_PROC* SocketProc diff --git a/src/platform/platform.kernel.vcxproj b/src/platform/platform.kernel.vcxproj index 765fdf67af..6e1f4506de 100644 --- a/src/platform/platform.kernel.vcxproj +++ b/src/platform/platform.kernel.vcxproj @@ -22,6 +22,9 @@ + + + diff --git a/src/platform/platform_internal.h b/src/platform/platform_internal.h index be58ef523d..142d6e0f63 100644 --- a/src/platform/platform_internal.h +++ b/src/platform/platform_internal.h @@ -137,6 +137,10 @@ typedef enum CXPLAT_SOCKET_TYPE { #define CXPLAT_BASE_REG_PATH L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\MsQuic\\Parameters\\" +// TODO: remove guard? +#define SOCKET PWSK_SOCKET +#define INVALID_SOCKET NULL + typedef struct CX_PLATFORM { // @@ -159,6 +163,178 @@ typedef struct CX_PLATFORM { } CX_PLATFORM; +typedef struct _WSK_DATAGRAM_SOCKET { + const WSK_PROVIDER_DATAGRAM_DISPATCH* Dispatch; +} WSK_DATAGRAM_SOCKET, * PWSK_DATAGRAM_SOCKET; + +// +// Per-port state. +// +typedef struct CXPLAT_SOCKET { + // CXPLAT_SOCKET_COMMON; + + // + // Flag indicates the binding has a default remote destination. + // + BOOLEAN Connected : 1; + + // + // Flag indicates the binding is being used for PCP. + // + BOOLEAN PcpBinding : 1; + + // + // Parent datapath. + // + CXPLAT_DATAPATH* Datapath; + + // + // UDP socket used for sending/receiving datagrams. + // + union { + PWSK_SOCKET Socket; + PWSK_DATAGRAM_SOCKET DgrmSocket; + }; + + // + // Event used to wait for completion of socket functions. + // + CXPLAT_EVENT WskCompletionEvent; + + // TODO: set. use QUICADDR by using CXPLAT_SOCKET_COMMON --- + // + // The local address and UDP port. + // + SOCKADDR_INET LocalAddress; + + // + // The remote address and UDP port. + // + SOCKADDR_INET RemoteAddress; + + // + // The local interface's MTU. + // + UINT16 Mtu; + + // + // Client context pointer. + // + void *ClientContext; + + // + // IRP used for socket functions. + // + union { + IRP Irp; + UCHAR IrpBuffer[sizeof(IRP) + sizeof(IO_STACK_LOCATION)]; + }; + + uint8_t UseTcp : 1; // always false? + uint8_t RawSocketAvailable : 1; + + CXPLAT_RUNDOWN_REF Rundown[0]; // Per-proc + +} CXPLAT_SOCKET; + +// +// Represents the per-processor state of the datapath context. +// +typedef struct CXPLAT_DATAPATH_PROC_CONTEXT { + + // + // Pool of send contexts to be shared by all sockets on this core. + // + CXPLAT_POOL SendDataPool; + + // + // Pool of send buffers to be shared by all sockets on this core. + // + CXPLAT_POOL SendBufferPool; + + // + // Pool of large segmented send buffers to be shared by all sockets on this + // core. + // + CXPLAT_POOL LargeSendBufferPool; + + // + // Pool of receive datagram contexts and buffers to be shared by all sockets + // on this core. Index 0 is regular, Index 1 is URO. + // + // + CXPLAT_POOL RecvDatagramPools[2]; + + // + // Pool of receive data buffers. Index 0 is 4096, Index 1 is 65536. + // + CXPLAT_POOL RecvBufferPools[2]; + + int64_t OutstandingPendingBytes; + +} CXPLAT_DATAPATH_PROC_CONTEXT; + +// +// Structure that maintains all the internal state for the +// CxPlatDataPath interface. +// +typedef struct CXPLAT_DATAPATH { + CXPLAT_DATAPATH_COMMON; + + // + // Set of supported features. + // + uint32_t Features; + + // + // The registration with WinSock Kernel. + // + WSK_REGISTRATION WskRegistration; + WSK_PROVIDER_NPI WskProviderNpi; + WSK_CLIENT_DATAGRAM_DISPATCH WskDispatch; + + // + // The UDP callback function pointers. + // + // CXPLAT_UDP_DATAPATH_CALLBACKS UdpHandlers; + + // + // The size of the buffer to allocate for client's receive context structure. + // + uint32_t ClientRecvDataLength; + + // + // The size of each receive datagram array element, including client context, + // internal context, and padding. + // + uint32_t DatagramStride; + + // + // The number of processors. + // + uint32_t ProcCount; + + uint8_t UseTcp : 1; // TODO: set. always false? + + CXPLAT_DATAPATH_RAW* RawDataPath; // TODO: set. + + // + // Per-processor completion contexts. + // + CXPLAT_DATAPATH_PROC_CONTEXT ProcContexts[0]; + +} CXPLAT_DATAPATH; + +#ifndef htonl +#define htonl _byteswap_ulong +#endif + +// TODO: unify accross all platforms? +#define IS_LOOPBACK(Address) ((Address.si_family == QUIC_ADDRESS_FAMILY_INET && \ + Address.Ipv4.sin_addr.S_un.S_addr == htonl(INADDR_LOOPBACK)) || \ + (Address.si_family == QUIC_ADDRESS_FAMILY_INET6 && \ + IN6_IS_ADDR_LOOPBACK(&Address.Ipv6.sin6_addr))) + #elif _WIN32 #pragma warning(push)