mirror of https://github.com/openssl/openssl.git
QUIC RCIDM: Minor updates
Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/23022)
This commit is contained in:
parent
ad08c814d8
commit
9eabb30ab4
|
@ -128,6 +128,12 @@ in which API calls can be made on different threads.
|
||||||
**MSST:** Multi-stream single-thread. Refers to a type of multi-stream QUIC
|
**MSST:** Multi-stream single-thread. Refers to a type of multi-stream QUIC
|
||||||
usage in which API calls must not be made concurrently.
|
usage in which API calls must not be made concurrently.
|
||||||
|
|
||||||
|
**NCID:** New Connection ID. Refers to a QUIC `NEW_CONNECTION_ID` frame.
|
||||||
|
|
||||||
|
**Numbered CID:** Refers to a Connection ID which has a sequence number assigned
|
||||||
|
to it. All CIDs other than Initial ODCIDs and Retry ODCIDs have a sequence
|
||||||
|
number assigned. See also Unnumbered CID.
|
||||||
|
|
||||||
**ODCID:** Original Destination CID. This is the DCID found in the first Initial
|
**ODCID:** Original Destination CID. This is the DCID found in the first Initial
|
||||||
packet sent by a client, and is used to generate the secrets for encrypting
|
packet sent by a client, and is used to generate the secrets for encrypting
|
||||||
Initial packets. It is only used temporarily.
|
Initial packets. It is only used temporarily.
|
||||||
|
@ -195,7 +201,8 @@ an API object. As such, a `QUIC_CONNECTION` is to a `QUIC_CHANNEL` what a
|
||||||
`QUIC_XSO` is to a `QUIC_STREAM`.
|
`QUIC_XSO` is to a `QUIC_STREAM`.
|
||||||
|
|
||||||
**RCID:** Remote CID. Refers to a CID which has been provided to us by a peer
|
**RCID:** Remote CID. Refers to a CID which has been provided to us by a peer
|
||||||
and which we can place in the DCID field of an outgoing packet. See also LCID.
|
and which we can place in the DCID field of an outgoing packet. See also LCID,
|
||||||
|
Unnumbered CID and Numbered CID.
|
||||||
|
|
||||||
**RCIDM:** Remote CID Manager. Tracks RCIDs which have been provided to us by a
|
**RCIDM:** Remote CID Manager. Tracks RCIDs which have been provided to us by a
|
||||||
peer. See also LCIDM.
|
peer. See also LCIDM.
|
||||||
|
@ -284,6 +291,12 @@ to a *send stream buffer*, and that data is eventually TX'd by the TXP and QTX.)
|
||||||
**Uni:** Abbreviation of unidirectional, referring to a QUIC unidirectional
|
**Uni:** Abbreviation of unidirectional, referring to a QUIC unidirectional
|
||||||
stream.
|
stream.
|
||||||
|
|
||||||
|
**Unnumbered CID:** Refers to a CID which does not have a sequence number
|
||||||
|
associated with it and therefore cannot be referred to by a `NEW_CONNECTION_ID`
|
||||||
|
or `RETIRE_CONNECTION_ID` frame's sequence number fields. The only unnumbered
|
||||||
|
CIDs are Initial ODCIDs and Retry ODCIDs. These CIDs are exceptionally retired
|
||||||
|
automatically during handshake confirmation. See also Numbered CID.
|
||||||
|
|
||||||
**URXE:** Unprocessed RX entry. Structure containing yet-undecrypted received
|
**URXE:** Unprocessed RX entry. Structure containing yet-undecrypted received
|
||||||
datagrams pending processing. Stored in a queue known as the URXL.
|
datagrams pending processing. Stored in a queue known as the URXL.
|
||||||
Ownership of URXEs is shared between DEMUX and QRX.
|
Ownership of URXEs is shared between DEMUX and QRX.
|
||||||
|
|
|
@ -129,7 +129,7 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ossl_quic_rcidm_add_from_initial(rcidm, &arg_cid);
|
ossl_quic_rcidm_add_from_server_retry(rcidm, &arg_cid);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_ADD_FROM_NCID:
|
case CMD_ADD_FROM_NCID:
|
||||||
|
|
|
@ -22,10 +22,10 @@
|
||||||
* QUIC Remote Connection ID Manager
|
* QUIC Remote Connection ID Manager
|
||||||
* =================================
|
* =================================
|
||||||
*
|
*
|
||||||
* This manages connection IDs for the TX side, which is to say that it tracks
|
* This manages connection IDs for the TX side. The RCIDM tracks remote CIDs
|
||||||
* remote CIDs (RCIDs) which a peer has issued to us and which we can use as the
|
* (RCIDs) which a peer has issued to us and which we can use as the DCID of
|
||||||
* DCID of packets we transmit. It is entirely separate from the LCIDM, which
|
* packets we transmit. It is entirely separate from the LCIDM, which handles
|
||||||
* handles routing received packets by their DCIDs.
|
* routing received packets by their DCIDs.
|
||||||
*
|
*
|
||||||
* RCIDs fall into four categories:
|
* RCIDs fall into four categories:
|
||||||
*
|
*
|
||||||
|
@ -42,8 +42,8 @@ typedef struct quic_rcidm_st QUIC_RCIDM;
|
||||||
/*
|
/*
|
||||||
* Creates a new RCIDM. Returns NULL on failure.
|
* Creates a new RCIDM. Returns NULL on failure.
|
||||||
*
|
*
|
||||||
* For a client, initial_rcid is the client's Initial ODCID.
|
* For a client, initial_odcid is the client's Initial ODCID.
|
||||||
* For a server, initial_rcid is NULL.
|
* For a server, initial_odcid is NULL.
|
||||||
*/
|
*/
|
||||||
QUIC_RCIDM *ossl_quic_rcidm_new(const QUIC_CONN_ID *initial_odcid);
|
QUIC_RCIDM *ossl_quic_rcidm_new(const QUIC_CONN_ID *initial_odcid);
|
||||||
|
|
||||||
|
@ -135,12 +135,13 @@ void ossl_quic_rcidm_request_roll(QUIC_RCIDM *rcidm);
|
||||||
* packets using the RCID may still be in flight. The caller must determine an
|
* packets using the RCID may still be in flight. The caller must determine an
|
||||||
* appropriate delay using knowledge of network conditions (RTT, etc.) which is
|
* appropriate delay using knowledge of network conditions (RTT, etc.) which is
|
||||||
* outside the scope of the RCIDM. The caller is responsible for implementing
|
* outside the scope of the RCIDM. The caller is responsible for implementing
|
||||||
* this delay.
|
* this delay based on the last time a packet was transmitted using the RCID
|
||||||
|
* being retired.
|
||||||
*/
|
*/
|
||||||
int ossl_quic_rcidm_pop_retire_seq_num(QUIC_RCIDM *rcid, uint64_t *seq_num);
|
int ossl_quic_rcidm_pop_retire_seq_num(QUIC_RCIDM *rcid, uint64_t *seq_num);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Like ossl_quic_rcidm_pop_retire_seek_num, but does not pop the item from the
|
* Like ossl_quic_rcidm_pop_retire_seq_num, but does not pop the item from the
|
||||||
* queue. If this call succeeds, the next call to
|
* queue. If this call succeeds, the next call to
|
||||||
* ossl_quic_rcidm_pop_retire_seq_num is guaranteed to output the same sequence
|
* ossl_quic_rcidm_pop_retire_seq_num is guaranteed to output the same sequence
|
||||||
* number.
|
* number.
|
||||||
|
|
|
@ -37,7 +37,7 @@ static void rcidm_update(QUIC_RCIDM *rcidm);
|
||||||
static void rcidm_set_preferred_rcid(QUIC_RCIDM *rcidm,
|
static void rcidm_set_preferred_rcid(QUIC_RCIDM *rcidm,
|
||||||
const QUIC_CONN_ID *rcid);
|
const QUIC_CONN_ID *rcid);
|
||||||
|
|
||||||
#define PACKETS_PER_RCID 1000
|
#define PACKETS_PER_RCID 10000
|
||||||
|
|
||||||
#define INITIAL_SEQ_NUM 0
|
#define INITIAL_SEQ_NUM 0
|
||||||
#define PREF_ADDR_SEQ_NUM 1
|
#define PREF_ADDR_SEQ_NUM 1
|
||||||
|
@ -124,7 +124,7 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct rcid_st {
|
typedef struct rcid_st {
|
||||||
OSSL_LIST_MEMBER(retiring, struct rcid_st); /* valid iff retire == 1 */
|
OSSL_LIST_MEMBER(retiring, struct rcid_st); /* valid iff RETIRING */
|
||||||
|
|
||||||
QUIC_CONN_ID cid; /* The actual CID string for this RCID */
|
QUIC_CONN_ID cid; /* The actual CID string for this RCID */
|
||||||
uint64_t seq_num;
|
uint64_t seq_num;
|
||||||
|
@ -162,6 +162,11 @@ struct quic_rcidm_st {
|
||||||
/*
|
/*
|
||||||
* The current RCID we prefer to use (value undefined if
|
* The current RCID we prefer to use (value undefined if
|
||||||
* !have_preferred_rcid).
|
* !have_preferred_rcid).
|
||||||
|
*
|
||||||
|
* This is preferentially set to a numbered RCID (represented by an RCID
|
||||||
|
* object) if we have one (in which case preferred_rcid == cur_rcid->cid);
|
||||||
|
* otherwise it is set to one of the unnumbered RCIDs (the Initial ODCID or
|
||||||
|
* Retry ODCID) if available (and cur_rcid == NULL).
|
||||||
*/
|
*/
|
||||||
QUIC_CONN_ID preferred_rcid;
|
QUIC_CONN_ID preferred_rcid;
|
||||||
|
|
||||||
|
@ -189,11 +194,11 @@ struct quic_rcidm_st {
|
||||||
PRIORITY_QUEUE_OF(RCID) *rcids;
|
PRIORITY_QUEUE_OF(RCID) *rcids;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Current RCID we are using. This may differ from the first item in the
|
* Current RCID object we are using. This may differ from the first item in
|
||||||
* priority queue if we received NCID frames out of order. For example if we
|
* the priority queue if we received NCID frames out of order. For example
|
||||||
* get seq 5, switch to it immediately, then get seq 4, we want to keep
|
* if we get seq 5, switch to it immediately, then get seq 4, we want to
|
||||||
* using seq 5 until we decide to roll again rather than immediately switch
|
* keep using seq 5 until we decide to roll again rather than immediately
|
||||||
* to seq 4. Never points to an object on the retiring_list.
|
* switch to seq 4. Never points to an object on the retiring_list.
|
||||||
*/
|
*/
|
||||||
RCID *cur_rcid;
|
RCID *cur_rcid;
|
||||||
|
|
||||||
|
@ -229,6 +234,14 @@ struct quic_rcidm_st {
|
||||||
unsigned int roll_requested : 1;
|
unsigned int roll_requested : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Caller must periodically pop retired RCIDs and handle them. If the caller
|
||||||
|
* fails to do so, fail safely rather than start exhibiting integer rollover.
|
||||||
|
* Limit the total number of numbered RCIDs to an implausibly large but safe
|
||||||
|
* value.
|
||||||
|
*/
|
||||||
|
#define MAX_NUMBERED_RCIDS (SIZE_MAX / 2)
|
||||||
|
|
||||||
static void rcidm_transition_rcid(QUIC_RCIDM *rcidm, RCID *rcid,
|
static void rcidm_transition_rcid(QUIC_RCIDM *rcidm, RCID *rcid,
|
||||||
unsigned int state);
|
unsigned int state);
|
||||||
|
|
||||||
|
@ -254,7 +267,6 @@ static void rcidm_check_rcid(QUIC_RCIDM *rcidm, RCID *rcid)
|
||||||
|| rcid->state == RCID_STATE_RETIRING);
|
|| rcid->state == RCID_STATE_RETIRING);
|
||||||
assert(rcidm->num_changes == 0 || rcidm->handshake_complete);
|
assert(rcidm->num_changes == 0 || rcidm->handshake_complete);
|
||||||
assert(rcid->state != RCID_STATE_RETIRING || rcidm->num_retiring > 0);
|
assert(rcid->state != RCID_STATE_RETIRING || rcidm->num_retiring > 0);
|
||||||
assert(rcidm->num_retiring < SIZE_MAX / 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rcid_cmp(const RCID *a, const RCID *b)
|
static int rcid_cmp(const RCID *a, const RCID *b)
|
||||||
|
@ -263,10 +275,6 @@ static int rcid_cmp(const RCID *a, const RCID *b)
|
||||||
return -1;
|
return -1;
|
||||||
if (a->seq_num > b->seq_num)
|
if (a->seq_num > b->seq_num)
|
||||||
return 1;
|
return 1;
|
||||||
if ((uintptr_t)a < (uintptr_t)b)
|
|
||||||
return -1;
|
|
||||||
if ((uintptr_t)a > (uintptr_t)b)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,7 +345,9 @@ static RCID *rcidm_create_rcid(QUIC_RCIDM *rcidm, uint64_t seq_num,
|
||||||
RCID *rcid;
|
RCID *rcid;
|
||||||
|
|
||||||
if (cid->id_len < 1 || cid->id_len > QUIC_MAX_CONN_ID_LEN
|
if (cid->id_len < 1 || cid->id_len > QUIC_MAX_CONN_ID_LEN
|
||||||
|| seq_num > OSSL_QUIC_VLINT_MAX)
|
|| seq_num > OSSL_QUIC_VLINT_MAX
|
||||||
|
|| ossl_pqueue_RCID_num(rcidm->rcids) + rcidm->num_retiring
|
||||||
|
> MAX_NUMBERED_RCIDS)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if ((rcid = OPENSSL_zalloc(sizeof(*rcid))) == NULL)
|
if ((rcid = OPENSSL_zalloc(sizeof(*rcid))) == NULL)
|
||||||
|
@ -351,7 +361,6 @@ static RCID *rcidm_create_rcid(QUIC_RCIDM *rcidm, uint64_t seq_num,
|
||||||
rcid->state = RCID_STATE_PENDING;
|
rcid->state = RCID_STATE_PENDING;
|
||||||
|
|
||||||
if (!ossl_pqueue_RCID_push(rcidm->rcids, rcid, &rcid->pq_idx)) {
|
if (!ossl_pqueue_RCID_push(rcidm->rcids, rcid, &rcid->pq_idx)) {
|
||||||
assert(0);
|
|
||||||
OPENSSL_free(rcid);
|
OPENSSL_free(rcid);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -501,7 +510,7 @@ static void rcidm_update(QUIC_RCIDM *rcidm)
|
||||||
* If there are no RCIDs from NCID frames we can use, go through the various
|
* If there are no RCIDs from NCID frames we can use, go through the various
|
||||||
* kinds of bootstrapping RCIDs we can use in order of priority.
|
* kinds of bootstrapping RCIDs we can use in order of priority.
|
||||||
*/
|
*/
|
||||||
if (rcidm->added_retry_odcid) {
|
if (rcidm->added_retry_odcid && !rcidm->handshake_complete) {
|
||||||
rcidm_set_preferred_rcid(rcidm, &rcidm->retry_odcid);
|
rcidm_set_preferred_rcid(rcidm, &rcidm->retry_odcid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,11 @@ static const QUIC_CONN_ID cid8_3 = { 8, { 3 } };
|
||||||
static const QUIC_CONN_ID cid8_4 = { 8, { 4 } };
|
static const QUIC_CONN_ID cid8_4 = { 8, { 4 } };
|
||||||
static const QUIC_CONN_ID cid8_5 = { 8, { 5 } };
|
static const QUIC_CONN_ID cid8_5 = { 8, { 5 } };
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 0: Client, Initial ODCID
|
||||||
|
* 1: Client, Initial ODCID + Retry ODCID
|
||||||
|
* 2: Server, doesn't start with Initial ODCID
|
||||||
|
*/
|
||||||
static int test_rcidm(int idx)
|
static int test_rcidm(int idx)
|
||||||
{
|
{
|
||||||
int testresult = 0;
|
int testresult = 0;
|
||||||
|
|
Loading…
Reference in New Issue