Skip to content

Commit 5e3b134

Browse files
authored
Support Client Migration (Client Side) #1
## Description This PR adds the support of Client Migration (Client Side). This pull request includes significant changes to the QUIC connection ID management and introduces a new feature for manual connection ID generation for testing purposes. The most important changes include the replacement of `QUIC_CID_HASH_ENTRY` with `QUIC_CID_SLIST_ENTRY` to register connection IDs into more than one bindings, the addition of new APIs to add/remove local address in client, and the introduction of a conditional compilation feature for manual connection ID generation. To manage opening new paths for a connection, Two functions (`QuicConnOpenNewPath` and `QuicConnOpenNewPaths`) are added. The former is called when an App adds a local address or the latter is called. The latter is called when the Handshake is confirmed. And `QuicConnAssignCids` is added to set Destination Connection ID for paths. This function is called when any Dest CID is newly added. ## Testing Three tests are newly added and one test is modified. ParameterValidation.ValidateConnectionParam (modified) Basic/WithProbePathArgs.ProbePath (new) Basic/WithMigrationArgs.Migration (new) Basic/WithProbePathArgs.MultipleLocalAddresses (new) ## Documentation In this PR, the following two Connection level Parameters will be added. QUIC_PARAM_CONN_ADD_LOCAL_ADDRESS QUIC_PARAM_CONN_REMOVE_LOCAL_ADDRESS
1 parent 44235f0 commit 5e3b134

35 files changed

Lines changed: 1979 additions & 301 deletions

src/core/binding.c

Lines changed: 65 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -561,46 +561,91 @@ _IRQL_requires_max_(DISPATCH_LEVEL)
561561
BOOLEAN
562562
QuicBindingAddSourceConnectionID(
563563
_In_ QUIC_BINDING* Binding,
564-
_In_ QUIC_CID_HASH_ENTRY* SourceCid
564+
_In_ QUIC_CONNECTION* Connection,
565+
_In_ QUIC_CID_SLIST_ENTRY* SourceCid
565566
)
566567
{
567-
return QuicLookupAddLocalCid(&Binding->Lookup, SourceCid, NULL);
568+
return QuicLookupAddLocalCid(&Binding->Lookup, Connection, SourceCid, NULL);
569+
}
570+
571+
_IRQL_requires_max_(DISPATCH_LEVEL)
572+
BOOLEAN
573+
QuicBindingAddAllSourceConnectionIDs(
574+
_In_ QUIC_BINDING* Binding,
575+
_In_ QUIC_CONNECTION* Connection
576+
)
577+
{
578+
for (CXPLAT_SLIST_ENTRY* Link = Connection->SourceCids.Next;
579+
Link != NULL;
580+
Link = Link->Next) {
581+
582+
QUIC_CID_SLIST_ENTRY* Entry =
583+
CXPLAT_CONTAINING_RECORD(
584+
Link,
585+
QUIC_CID_SLIST_ENTRY,
586+
Link);
587+
if (!QuicBindingAddSourceConnectionID(Binding, Connection, Entry)) {
588+
return FALSE;
589+
}
590+
}
591+
592+
return TRUE;
568593
}
569594

570595
_IRQL_requires_max_(DISPATCH_LEVEL)
571596
void
572597
QuicBindingRemoveSourceConnectionID(
573598
_In_ QUIC_BINDING* Binding,
574-
_In_ QUIC_CID_HASH_ENTRY* SourceCid,
575-
_In_ CXPLAT_SLIST_ENTRY** Entry
599+
_In_ QUIC_CID_HASH_ENTRY* SourceCid
576600
)
577601
{
578-
QuicLookupRemoveLocalCid(&Binding->Lookup, SourceCid, Entry);
602+
QuicLookupRemoveLocalCid(&Binding->Lookup, SourceCid);
579603
}
580604

581605
_IRQL_requires_max_(DISPATCH_LEVEL)
582606
void
583-
QuicBindingRemoveConnection(
607+
QuicBindingRemoveAllSourceConnectionIDs(
584608
_In_ QUIC_BINDING* Binding,
585609
_In_ QUIC_CONNECTION* Connection
586610
)
587611
{
588-
if (Connection->RemoteHashEntry != NULL) {
589-
QuicLookupRemoveRemoteHash(&Binding->Lookup, Connection->RemoteHashEntry);
612+
for (CXPLAT_SLIST_ENTRY* Link = Connection->SourceCids.Next;
613+
Link != NULL;
614+
Link = Link->Next) {
615+
616+
QUIC_CID_SLIST_ENTRY* Entry =
617+
CXPLAT_CONTAINING_RECORD(
618+
Link,
619+
QUIC_CID_SLIST_ENTRY,
620+
Link);
621+
622+
CXPLAT_SLIST_ENTRY** HashLink = &Entry->HashEntries.Next;
623+
while (*HashLink != NULL) {
624+
QUIC_CID_HASH_ENTRY* HashEntry =
625+
CXPLAT_CONTAINING_RECORD(
626+
*HashLink,
627+
QUIC_CID_HASH_ENTRY,
628+
Link);
629+
if (HashEntry->Binding == Binding) {
630+
QuicBindingRemoveSourceConnectionID(Binding, HashEntry);
631+
*HashLink = (*HashLink)->Next;
632+
CXPLAT_FREE(HashEntry, QUIC_POOL_CIDHASH);
633+
HashEntry = NULL;
634+
} else {
635+
HashLink = &(*HashLink)->Next;
636+
}
637+
}
590638
}
591-
QuicLookupRemoveLocalCids(&Binding->Lookup, Connection);
592639
}
593640

594641
_IRQL_requires_max_(DISPATCH_LEVEL)
595642
void
596-
QuicBindingMoveSourceConnectionIDs(
597-
_In_ QUIC_BINDING* BindingSrc,
598-
_In_ QUIC_BINDING* BindingDest,
599-
_In_ QUIC_CONNECTION* Connection
643+
QuicBindingRemoveRemoteHash(
644+
_In_ QUIC_BINDING* Binding,
645+
_In_ QUIC_REMOTE_HASH_ENTRY* RemoteHashEntry
600646
)
601647
{
602-
QuicLookupMoveLocalConnectionIDs(
603-
&BindingSrc->Lookup, &BindingDest->Lookup, Connection);
648+
QuicLookupRemoveRemoteHash(&Binding->Lookup, RemoteHashEntry);
604649
}
605650

606651
_IRQL_requires_max_(DISPATCH_LEVEL)
@@ -1285,10 +1330,10 @@ QuicBindingCreateConnection(
12851330

12861331
BOOLEAN BindingRefAdded = FALSE;
12871332
CXPLAT_DBG_ASSERT(NewConnection->SourceCids.Next != NULL);
1288-
QUIC_CID_HASH_ENTRY* SourceCid =
1333+
QUIC_CID_SLIST_ENTRY* SourceCid =
12891334
CXPLAT_CONTAINING_RECORD(
12901335
NewConnection->SourceCids.Next,
1291-
QUIC_CID_HASH_ENTRY,
1336+
QUIC_CID_SLIST_ENTRY,
12921337
Link);
12931338

12941339
QuicConnAddRef(NewConnection, QUIC_CONN_REF_LOOKUP_RESULT);
@@ -1323,6 +1368,8 @@ QuicBindingCreateConnection(
13231368
}
13241369
goto Exit;
13251370
}
1371+
CXPLAT_DBG_ASSERT(NewConnection->RemoteHashEntry != NULL);
1372+
NewConnection->RemoteHashEntry->Binding = Binding;
13261373

13271374
QuicWorkerQueueConnection(NewConnection->Worker, NewConnection);
13281375

@@ -1357,7 +1404,7 @@ QuicBindingCreateConnection(
13571404

13581405
} else {
13591406
NewConnection->SourceCids.Next = NULL;
1360-
CXPLAT_FREE(SourceCid, QUIC_POOL_CIDHASH);
1407+
CXPLAT_FREE(SourceCid, QUIC_POOL_CIDSLIST);
13611408
QuicConnRelease(NewConnection, QUIC_CONN_REF_LOOKUP_RESULT);
13621409
#pragma prefast(suppress:6001, "SAL doesn't understand ref counts")
13631410
QuicConnRelease(NewConnection, QUIC_CONN_REF_HANDLE_OWNER);

src/core/binding.h

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,19 @@ _IRQL_requires_max_(DISPATCH_LEVEL)
386386
BOOLEAN
387387
QuicBindingAddSourceConnectionID(
388388
_In_ QUIC_BINDING* Binding,
389-
_In_ QUIC_CID_HASH_ENTRY* SourceCid
389+
_In_ QUIC_CONNECTION* Connection,
390+
_In_ QUIC_CID_SLIST_ENTRY* SourceCid
391+
);
392+
393+
//
394+
// Attempts to insert all the connection's new source CIDs into the binding's
395+
// lookup table.
396+
//
397+
_IRQL_requires_max_(DISPATCH_LEVEL)
398+
BOOLEAN
399+
QuicBindingAddAllSourceConnectionIDs(
400+
_In_ QUIC_BINDING* Binding,
401+
_In_ QUIC_CONNECTION* Connection
390402
);
391403

392404
//
@@ -396,30 +408,24 @@ _IRQL_requires_max_(DISPATCH_LEVEL)
396408
void
397409
QuicBindingRemoveSourceConnectionID(
398410
_In_ QUIC_BINDING* Binding,
399-
_In_ QUIC_CID_HASH_ENTRY* SourceCid,
400-
_In_ CXPLAT_SLIST_ENTRY** Entry
411+
_In_ QUIC_CID_HASH_ENTRY* SourceCid
401412
);
402413

403414
//
404-
// Removes all the connection's source CIDs from the binding's lookup table.
415+
// Removes all the source CIDs from the binding's lookup table.
405416
//
406417
_IRQL_requires_max_(DISPATCH_LEVEL)
407418
void
408-
QuicBindingRemoveConnection(
419+
QuicBindingRemoveAllSourceConnectionIDs(
409420
_In_ QUIC_BINDING* Binding,
410421
_In_ QUIC_CONNECTION* Connection
411422
);
412423

413-
//
414-
// Moves all the connections source CIDs from the one binding's lookup table to
415-
// another.
416-
//
417424
_IRQL_requires_max_(DISPATCH_LEVEL)
418425
void
419-
QuicBindingMoveSourceConnectionIDs(
420-
_In_ QUIC_BINDING* BindingSrc,
421-
_In_ QUIC_BINDING* BindingDest,
422-
_In_ QUIC_CONNECTION* Connection
426+
QuicBindingRemoveRemoteHash(
427+
_In_ QUIC_BINDING* Binding,
428+
_In_ QUIC_REMOTE_HASH_ENTRY* RemoteHashEntry
423429
);
424430

425431
//
@@ -546,3 +552,16 @@ QuicRetryTokenDecrypt(
546552
CxPlatDispatchLockRelease(&Partition->StatelessRetryKeysLock);
547553
return QUIC_SUCCEEDED(Status);
548554
}
555+
556+
//
557+
// Helper to get the owning QUIC_BINDING for the lookup module.
558+
//
559+
QUIC_INLINE
560+
_Ret_notnull_
561+
QUIC_BINDING*
562+
QuicLookupGetBinding(
563+
_In_ QUIC_LOOKUP* Lookup
564+
)
565+
{
566+
return CXPLAT_CONTAINING_RECORD(Lookup, QUIC_BINDING, Lookup);
567+
}

src/core/cid.h

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,21 @@ typedef struct QUIC_CID_LIST_ENTRY {
163163
#define QUIC_CID_VALIDATE_NULL(Conn, Cid) UNREFERENCED_PARAMETER(Cid)
164164
#endif
165165

166+
typedef struct QUIC_CID_SLIST_ENTRY {
167+
168+
CXPLAT_SLIST_ENTRY Link;
169+
CXPLAT_SLIST_ENTRY HashEntries;
170+
QUIC_CID CID;
171+
172+
} QUIC_CID_SLIST_ENTRY;
173+
166174
typedef struct QUIC_CID_HASH_ENTRY {
167175

168176
CXPLAT_HASHTABLE_ENTRY Entry;
169177
CXPLAT_SLIST_ENTRY Link;
170178
QUIC_CONNECTION* Connection;
171-
QUIC_CID CID;
179+
QUIC_BINDING* Binding;
180+
QUIC_CID_SLIST_ENTRY* Parent;
172181

173182
} QUIC_CID_HASH_ENTRY;
174183

@@ -178,18 +187,16 @@ typedef struct QUIC_CID_HASH_ENTRY {
178187
//
179188
QUIC_INLINE
180189
_Success_(return != NULL)
181-
QUIC_CID_HASH_ENTRY*
182-
QuicCidNewNullSource(
183-
_In_ QUIC_CONNECTION* Connection
184-
)
190+
QUIC_CID_SLIST_ENTRY*
191+
QuicCidNewNullSource()
185192
{
186-
QUIC_CID_HASH_ENTRY* Entry =
187-
(QUIC_CID_HASH_ENTRY*)CXPLAT_ALLOC_NONPAGED(
188-
sizeof(QUIC_CID_HASH_ENTRY),
189-
QUIC_POOL_CIDHASH);
193+
QUIC_CID_SLIST_ENTRY* Entry =
194+
(QUIC_CID_SLIST_ENTRY*)CXPLAT_ALLOC_NONPAGED(
195+
sizeof(QUIC_CID_SLIST_ENTRY),
196+
QUIC_POOL_CIDSLIST);
190197

191198
if (Entry != NULL) {
192-
Entry->Connection = Connection;
199+
Entry->HashEntries.Next = NULL;
193200
CxPlatZeroMemory(&Entry->CID, sizeof(Entry->CID));
194201
}
195202

@@ -201,23 +208,22 @@ QuicCidNewNullSource(
201208
//
202209
QUIC_INLINE
203210
_Success_(return != NULL)
204-
QUIC_CID_HASH_ENTRY*
211+
QUIC_CID_SLIST_ENTRY*
205212
QuicCidNewSource(
206-
_In_ QUIC_CONNECTION* Connection,
207213
_In_ uint8_t Length,
208214
_In_reads_(Length)
209215
const uint8_t* const Data
210216
)
211217
{
212-
QUIC_CID_HASH_ENTRY* Entry =
213-
(QUIC_CID_HASH_ENTRY*)
218+
QUIC_CID_SLIST_ENTRY* Entry =
219+
(QUIC_CID_SLIST_ENTRY*)
214220
CXPLAT_ALLOC_NONPAGED(
215-
sizeof(QUIC_CID_HASH_ENTRY) +
221+
sizeof(QUIC_CID_SLIST_ENTRY) +
216222
Length,
217-
QUIC_POOL_CIDHASH);
223+
QUIC_POOL_CIDSLIST);
218224

219225
if (Entry != NULL) {
220-
Entry->Connection = Connection;
226+
Entry->HashEntries.Next = NULL;
221227
CxPlatZeroMemory(&Entry->CID, sizeof(Entry->CID));
222228
Entry->CID.Length = Length;
223229
if (Length != 0) {

src/core/configuration.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,24 @@ QuicConfigurationParamGet(
465465

466466
return QUIC_STATUS_SUCCESS;
467467
}
468+
#if QUIC_TEST_MANUAL_CONN_ID_GENERATION
469+
if (Param == QUIC_PARAM_CONFIGURATION_CONN_ID_GENERATION_DISABLED) {
470+
471+
if (*BufferLength < sizeof(BOOLEAN)) {
472+
*BufferLength = sizeof(BOOLEAN);
473+
return QUIC_STATUS_BUFFER_TOO_SMALL;
474+
}
475+
476+
if (Buffer == NULL) {
477+
return QUIC_STATUS_INVALID_PARAMETER;
478+
}
479+
480+
*BufferLength = sizeof(BOOLEAN);
481+
*(BOOLEAN*)Buffer = Configuration->Settings.ConnIDGenDisabled;
482+
483+
return QUIC_STATUS_SUCCESS;
484+
}
485+
#endif
468486

469487
return QUIC_STATUS_INVALID_PARAMETER;
470488
}
@@ -574,6 +592,20 @@ QuicConfigurationParamSet(
574592

575593
return QUIC_STATUS_SUCCESS;
576594

595+
#if QUIC_TEST_MANUAL_CONN_ID_GENERATION
596+
case QUIC_PARAM_CONFIGURATION_CONN_ID_GENERATION_DISABLED:
597+
598+
if (Buffer == NULL ||
599+
BufferLength < sizeof(BOOLEAN)) {
600+
return QUIC_STATUS_INVALID_PARAMETER;
601+
}
602+
603+
Configuration->Settings.IsSet.ConnIDGenDisabled = TRUE;
604+
Configuration->Settings.ConnIDGenDisabled = *(BOOLEAN*)Buffer;
605+
606+
return QUIC_STATUS_SUCCESS;
607+
#endif
608+
577609
#ifdef WIN32
578610
case QUIC_PARAM_CONFIGURATION_SCHANNEL_CREDENTIAL_ATTRIBUTE_W:
579611

0 commit comments

Comments
 (0)