Skip to content

Commit

Permalink
Implement Connection Pool API
Browse files Browse the repository at this point in the history
  • Loading branch information
anrossi committed Feb 20, 2025
1 parent 2c81e07 commit af58125
Show file tree
Hide file tree
Showing 15 changed files with 574 additions and 11 deletions.
1 change: 1 addition & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ set(SOURCES
configuration.c
congestion_control.c
connection.c
connection_pool.c
crypto.c
crypto_tls.c
cubic.c
Expand Down
8 changes: 8 additions & 0 deletions src/core/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,3 +287,11 @@ MsQuicConnectionCertificateValidationComplete(
_In_ BOOLEAN Result,
_In_ QUIC_TLS_ALERT_CODES TlsAlert
);

_IRQL_requires_max_(PASSIVE_LEVEL)
_Check_return_
QUIC_STATUS
QUIC_API
MsQuicConnectionPoolApiOpen(
_Out_ _Pre_defensive_ const void** ConnPoolApi
);
77 changes: 77 additions & 0 deletions src/core/library.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ MsQuicLibraryInitialize(
CxPlatZeroMemory(MsQuicLib.PerfCounterSamples, sizeof(MsQuicLib.PerfCounterSamples));

CxPlatRandom(sizeof(MsQuicLib.ToeplitzHash.HashKey), MsQuicLib.ToeplitzHash.HashKey);
MsQuicLib.ToeplitzHash.InputSize = CXPLAT_TOEPLITZ_INPUT_SIZE_QUIC;
CxPlatToeplitzHashInitialize(&MsQuicLib.ToeplitzHash);

CxPlatZeroMemory(&MsQuicLib.Settings, sizeof(MsQuicLib.Settings));
Expand Down Expand Up @@ -1802,6 +1803,8 @@ MsQuicOpenVersion(

Api->DatagramSend = MsQuicDatagramSend;

Api->ConnectionPoolApiOpen = MsQuicConnectionPoolApiOpen;

*QuicApi = Api;

Exit:
Expand Down Expand Up @@ -2456,3 +2459,77 @@ QuicLibraryGenerateStatelessResetToken(
}
return Status;
}

_IRQL_requires_max_(PASSIVE_LEVEL)
void
MsQuicConnectionPoolApiClose(
_In_ _Pre_defensive_ const void* ConnPoolApi
)
{
if (ConnPoolApi != NULL) {
QuicTraceLogVerbose(
ApiMsQuicConnectionPoolApiClose,
"[ api] MsQuicConnectionPoolApiClose");
CXPLAT_FREE(ConnPoolApi, QUIC_POOL_CONN_POOL_API_TABLE);
MsQuicRelease();
}
}

_IRQL_requires_max_(PASSIVE_LEVEL)
_Check_return_
QUIC_STATUS
QUIC_API
MsQuicConnectionPoolApiOpen(
_Out_ _Pre_defensive_ const void** ConnPoolApi
)
{
QUIC_STATUS Status;
BOOLEAN ReleaseRefOnFailure = FALSE;

if (ConnPoolApi == NULL) {
QuicTraceLogVerbose(
ApiMsQuicConnectionPoolApiOpenNull,
"[ api] MsQuicConnectionPoolApiOpen, NULL");
Status = QUIC_STATUS_INVALID_PARAMETER;
goto Exit;
}

QuicTraceLogVerbose(
ApiMsQuicConnectionPoolApiOpenEntry,
"[ api] MsQuicConnectionPoolApiOpen");

Status = MsQuicAddRef();
if (QUIC_FAILED(Status)) {
goto Exit;
}
ReleaseRefOnFailure = TRUE;

QUIC_CONNECTION_POOL_API_TABLE* Api =
CXPLAT_ALLOC_NONPAGED(
sizeof(QUIC_CONNECTION_POOL_API_TABLE),
QUIC_POOL_CONN_POOL_API_TABLE);
if (Api == NULL) {
Status = QUIC_STATUS_OUT_OF_MEMORY;
goto Exit;
}

Api->ConnectionPoolApiClose = MsQuicConnectionPoolApiClose;
Api->SimpleConnectionPoolCreate = MsQuicSimpleConnectionPoolCreate;

*ConnPoolApi = Api;

Exit:

QuicTraceLogVerbose(
ApiMsQuicConnectionPoolApiOpenExit,
"[ api] MsQuicConnectionPoolApiOpen, status=0x%x",
Status);

if (QUIC_FAILED(Status)) {
if (ReleaseRefOnFailure) {
MsQuicRelease();
}
}

return Status;
}
1 change: 1 addition & 0 deletions src/core/precomp.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
#include "datagram.h"
#include "version_neg.h"
#include "connection.h"
#include "connection_pool.h"
#include "packet_builder.h"
#include "listener.h"
#include "cubic.h"
Expand Down
58 changes: 58 additions & 0 deletions src/inc/msquic.h
Original file line number Diff line number Diff line change
Expand Up @@ -1605,6 +1605,62 @@ QUIC_STATUS
_In_opt_ void* ClientSendContext
);

//
// Connection Pool API
//

//
// Closes the Connection Pool API table and cleans up the API reference.
//
typedef
_IRQL_requires_max_(PASSIVE_LEVEL)
void
(QUIC_API * QUIC_CONN_POOL_API_CLOSE)(
_In_ void* ConnPoolApi
);

//
// Creates a simple connection pool with NumberOfConnections connections
// all with the same Context and Handler, and puts them in the
// caller-supplied array.
//
// One of ServerName or ServerAddress *MUST* be supplied, and for the pool to
// work correctly, the connections *MUST* be started with the same ServerName
// and ServerPort as supplied in this call.
//
typedef
_IRQL_requires_max_(PASSIVE_LEVEL)
_Check_return_
QUIC_STATUS
(QUIC_API * QUIC_SIMPLE_CONN_POOL_CREATE_FN)(
_In_ HQUIC* Registration,
_In_ QUIC_CONNECTION_CALLBACK_HANDLER Handler,
_In_opt_ void* Context,
_In_opt_ const char* ServerName,
_In_opt_ const QUIC_ADDR* ServerAddress,
_In_ uint16_t ServerPort,
_In_ uint32_t NumberOfConnections,
_Out_writes_bytes_(NumberOfConnections * sizeof(HQUIC))
HQUIC** ConnectionPool
);

typedef struct QUIC_CONNECTION_POOL_API_TABLE {
QUIC_CONN_POOL_API_CLOSE ConnectionPoolApiClose;
QUIC_SIMPLE_CONN_POOL_CREATE_FN SimpleConnectionPoolCreate;

} QUIC_CONNECTION_POOL_API_TABLE;

//
// Gets the function table for the Connection Pool API, for a given version.
//
typedef
_IRQL_requires_max_(PASSIVE_LEVEL)
_Check_return_
QUIC_STATUS
(QUIC_API * QUIC_CONNECTION_POOL_API_OPEN_FN)(
_Out_ _Pre_defensive_ const void** ConnPoolApi
);

//
// Version 2 API Function Table. Returned from MsQuicOpenVersion when Version
// is 2. Also returned from MsQuicOpen2.
Expand Down Expand Up @@ -1657,6 +1713,8 @@ typedef struct QUIC_API_TABLE {
QUIC_STREAM_PROVIDE_RECEIVE_BUFFERS_FN
StreamProvideReceiveBuffers; // Available from v2.5
#endif
QUIC_CONNECTION_POOL_API_OPEN_FN ConnectionPoolApiOpen; // Available from v2.5

} QUIC_API_TABLE;

#define QUIC_API_VERSION_1 1 // Not supported any more
Expand Down
31 changes: 31 additions & 0 deletions src/inc/quic_datapath.h
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,37 @@ CxPlatUpdateRoute(
_In_ CXPLAT_ROUTE* SrcRoute
);

//
// Get the RSS Configuration of the interface.
//
#define CXPLAT_RSS_HASH_TYPE_IPV4 0x001
#define CXPLAT_RSS_HASH_TYPE_TCP_IPV4 0x002
#define CXPLAT_RSS_HASH_TYPE_UDP_IPV4 0x004
#define CXPLAT_RSS_HASH_TYPE_IPV6 0x008
#define CXPLAT_RSS_HASH_TYPE_TCP_IPV6 0x010
#define CXPLAT_RSS_HASH_TYPE_UDP_IPV6 0x020
#define CXPLAT_RSS_HASH_TYPE_IPV6_EX 0x040
#define CXPLAT_RSS_HASH_TYPE_TCP_IPV6_EX 0x080
#define CXPLAT_RSS_HASH_TYPE_UDP_IPV6_EX 0x100

typedef uint32_t CXPLAT_RSS_HASH_TYPE;

typedef struct CXPLAT_RSS_CONFIG {
CXPLAT_RSS_HASH_TYPE HashTypes;
uint32_t RssSecretKeyLength;
uint32_t RssIndirectionTableLength;
uint8_t* RssSecretKey;
CXPLAT_PROCESSOR_INFO* RssIndirectionTable;
} CXPLAT_RSS_CONFIG;

_IRQL_requires_max_(PASSIVE_LEVEL)
QUIC_STATUS
CxPlatDataPathGetRssConfig(
_In_ uint32_t InterfaceIndex,
_Outptr_ _At_(*RssConfig, __drv_allocatesMem(Mem))
CXPLAT_RSS_CONFIG** RssConfig
);

#if defined(__cplusplus)
}
#endif
2 changes: 2 additions & 0 deletions src/inc/quic_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ typedef struct CXPLAT_SLIST_ENTRY {
#define QUIC_POOL_ROUTE_RESOLUTION_OPER 'B4cQ' // Qc4B - QUIC route resolution operation
#define QUIC_POOL_EXECUTION_CONFIG 'C4cQ' // Qc4C - QUIC execution config
#define QUIC_POOL_APP_BUFFER_CHUNK 'D4cQ' // Qc4D - QUIC receive chunk for app buffers
#define QUIC_POOL_CONN_POOL_API_TABLE 'E4cQ' // Qc4E - QUIC Connection Pool API table
#define QUIC_POOL_DATAPATH_RSS_CONFIG 'F4cQ' // Qc4F - QUIC Datapath RSS configuration

typedef enum CXPLAT_THREAD_FLAGS {
CXPLAT_THREAD_FLAG_NONE = 0x0000,
Expand Down
91 changes: 84 additions & 7 deletions src/inc/quic_toeplitz.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,23 @@ extern "C" {

//
// The size (in bytes) of the input.
//
typedef uint32_t CXPLAT_TOEPLITZ_INPUT_SIZE;

//
// This includes space for 16 bytes for source IPv6 address, 16 bytes for
// destination IPv6 address, 2 bytes for source port, and 2 bytes for
// destination port.
//
#define CXPLAT_TOEPLITZ_INPUT_SIZE_IP 36

//
// This includes space for a 20 bytes for CID, 16 bytes for IPv6 address
// and 2 bytes for UDP port.
//
#define CXPLAT_TOEPLITZ_INPUT_SIZE 38
#define CXPLAT_TOEPLITZ_INPUT_SIZE_QUIC 38

#define CXPLAT_TOEPLITZ_INPUT_SIZE_MAX 38

//
// The size (in bytes) of the output hash.
Expand All @@ -29,27 +41,28 @@ extern "C" {
#define CXPLAT_TOEPLITZ_OUPUT_SIZE sizeof(uint32_t)

//
// The size (in bytes) of the key is equal to the size of the input and output.
// The max size (in bytes) of the key is equal to the size of the input and output.
//
#define CXPLAT_TOEPLITZ_KEY_SIZE (CXPLAT_TOEPLITZ_INPUT_SIZE + CXPLAT_TOEPLITZ_OUPUT_SIZE)
#define CXPLAT_TOEPLITZ_KEY_SIZE_MAX (CXPLAT_TOEPLITZ_INPUT_SIZE_MAX + CXPLAT_TOEPLITZ_OUPUT_SIZE)

//
// Fixed lookup table size.
//
#define CXPLAT_TOEPLITZ_LOOKUP_TABLE_SIZE 16

//
// Fixed number of lookup tables.
// Fixed number of lookup tables. Use the maximum of two possible values.
//
#define CXPLAT_TOEPLITZ_LOOKUP_TABLE_COUNT (CXPLAT_TOEPLITZ_INPUT_SIZE * NIBBLES_PER_BYTE)
#define CXPLAT_TOEPLITZ_LOOKUP_TABLE_COUNT_MAX (CXPLAT_TOEPLITZ_INPUT_SIZE_MAX * NIBBLES_PER_BYTE)

typedef struct CXPLAT_TOEPLITZ_LOOKUP_TABLE {
uint32_t Table[CXPLAT_TOEPLITZ_LOOKUP_TABLE_SIZE];
} CXPLAT_TOEPLITZ_LOOKUP_TABLE;

typedef struct CXPLAT_TOEPLITZ_HASH {
CXPLAT_TOEPLITZ_LOOKUP_TABLE LookupTableArray[CXPLAT_TOEPLITZ_LOOKUP_TABLE_COUNT];
uint8_t HashKey[CXPLAT_TOEPLITZ_KEY_SIZE];
CXPLAT_TOEPLITZ_LOOKUP_TABLE LookupTableArray[CXPLAT_TOEPLITZ_LOOKUP_TABLE_COUNT_MAX];
uint8_t HashKey[CXPLAT_TOEPLITZ_KEY_SIZE_MAX];
CXPLAT_TOEPLITZ_INPUT_SIZE InputSize;
} CXPLAT_TOEPLITZ_HASH;

//
Expand Down Expand Up @@ -113,6 +126,70 @@ CxPlatToeplitzHashComputeAddr(
}
}

//
// Computes the Toeplitz hash of two QUIC addresses as RSS would.
//
inline
void
CxPlatToeplitzHashComputeRss(
_In_ const CXPLAT_TOEPLITZ_HASH* Toeplitz,
_In_ const QUIC_ADDR* SrcAddr,
_In_ const QUIC_ADDR* DestAddr,
_Inout_ uint32_t* Key,
_Out_ uint32_t* Offset
)
{
CXPLAT_FRE_ASSERT(QuicAddrGetFamily(SrcAddr) == QuicAddrGetFamily(DestAddr));

if (QuicAddrGetFamily(SrcAddr) == QUIC_ADDRESS_FAMILY_INET) {
*Key ^=
CxPlatToeplitzHashCompute(
Toeplitz,
((uint8_t*)SrcAddr) + QUIC_ADDR_V4_IP_OFFSET,
4, 0);
*Key ^=
CxPlatToeplitzHashCompute(
Toeplitz,
((uint8_t*)DestAddr) + QUIC_ADDR_V4_IP_OFFSET,
4, 4);
*Key ^=
CxPlatToeplitzHashCompute(
Toeplitz,
((uint8_t*)SrcAddr) + QUIC_ADDR_V4_PORT_OFFSET,
2, 8);
*Key ^=
CxPlatToeplitzHashCompute(
Toeplitz,
((uint8_t*)DestAddr) + QUIC_ADDR_V4_PORT_OFFSET,
2, 10);
*Offset = 4 + 4 + 2 + 2;
} else {
CXPLAT_DBG_ASSERT(QuicAddrGetFamily(SrcAddr) == QUIC_ADDRESS_FAMILY_INET6);

*Key ^=
CxPlatToeplitzHashCompute(
Toeplitz,
((uint8_t*)SrcAddr) + QUIC_ADDR_V6_IP_OFFSET,
16, 0);
*Key ^=
CxPlatToeplitzHashCompute(
Toeplitz,
((uint8_t*)DestAddr) + QUIC_ADDR_V6_IP_OFFSET,
16, 16);
*Key ^=
CxPlatToeplitzHashCompute(
Toeplitz,
((uint8_t*)SrcAddr) + QUIC_ADDR_V6_PORT_OFFSET,
2, 32);
*Key ^=
CxPlatToeplitzHashCompute(
Toeplitz,
((uint8_t*)DestAddr) + QUIC_ADDR_V6_PORT_OFFSET,
2, 34);
*Offset = 16 + 16 + 2 + 2;
}
}

#if defined(__cplusplus)
}
#endif
Loading

0 comments on commit af58125

Please sign in to comment.