1QUIC Connection ID Cache 2======================== 3 4The connection ID cache is responsible for managing connection IDs, both local 5and remote. 6 7Remote Connection IDs 8--------------------- 9 10For remote connection IDs, we need to be able to: 11 12* add new IDs per connection; 13* pick a non-retired ID associated from those available for a connection and 14* select a connection ID by sequence number and retire that and all older IDs. 15 16The cache will be implemented as a double ended queue as part of the 17QUIC_CONNECTION object. The queue will be sorted by sequence number 18and must maintain a count of the number of connection IDs present. 19There is no requirement to maintain a global mapping since remote IDs 20are only used when sending packets, not receiving them. 21 22In MVP, a many-to-1 matching of Connection IDs per Connection object 23is required. Refer third paragraph in [5.1]. 24 25When picking a non-retired connection ID for MVP, the youngest available will 26be chosen. 27 28Local Connection IDs 29-------------------- 30 31For local connection IDs, we need to be able to: 32 33* generate a new connection ID and associate it with a connection; 34* query if a connection ID is present; 35* for a server, map a connection ID to a QUIC_CONNECTION; 36* drop all connection IDs associated with a QUIC_CONNECTION; 37* select a connection ID by sequence number and retire that and all older IDs 38 and 39* select a connection ID by sequence number and drop that and all older IDs. 40 41All connection IDs issued by our stack must be the same length because 42short form packets include the connection ID but no length byte. Random 43connection IDs of this length will be allocated. Note that no additional 44information will be contained in the connection ID. 45 46There will be one global set of local connection IDs, `QUIC_ROUTE_TABLE`, 47which is shared by all connections over all SSL_CTX objects. This is 48used to dispatch incoming datagrams to their correct destination and 49will be implemented as a dictionary. 50 51### Notes 52 53* For MVP, it would be sufficient to only use a zero length connection ID. 54* For MVP, a connection ID to QUIC_CONNECTION mapping need not be implemented. 55* Post MVP, funnelling all received packets through a single socket is 56 likely to be bottleneck. 57 An alternative would be receiving from <host address, source port> pairs. 58* For MVP, the local connection ID cache need only have one element. 59 I.e. there is no requirement to implement any form of lookup. 60 61Routes 62------ 63 64A pair of connection IDs identify a route between the two ends of the 65communication. This contains the connection IDs of both ends of the 66connection and the common sequence number. We need to be able to: 67 68* select a connection ID by sequence number and retire that and all older IDs 69 and 70* select a connection ID by sequence number and drop that and all older IDs. 71 72It is likely that operations on local and remote connection IDs can be 73subsumed by the route functionality. 74 75ID Retirement 76------------- 77 78Connection IDs are retired by either a [NEW_CONNECTION_ID] or 79a [RETIRE_CONNECTION_ID] frame and this is acknowledged by a 80RETIRE_CONNECTION_ID or a NEW_CONNECTION_ID frame respectively. 81 82When a retirement frame is received, we can immediately _remove_ the 83IDs covered from our cache and then send back an acknowledgement of 84the retirement. 85 86If we want to retire a frame, we send a retirement frame and mark the 87IDs covered in our cache as _retired_. This means that we cannot send 88using any of these IDs but can still receive using them. Once our peer 89acknowledges the retirement, we can _remove_ the IDs. 90 91It is possible to receive out of order packets **after** receiving a 92retirement notification. It's unclear what to do with these, however 93dropping them seems reasonable. The alternative would be to maintain 94the route in a _deletable_ state until all packets in flight at the time 95of retirement have been acked. 96 97API 98--- 99 100QUIC connection IDs are defined in #18949 but some extra functions 101are available: 102 103```c 104/* QUIC connection ID representation. */ 105#define QUIC_MAX_CONN_ID_LEN 20 106 107typedef struct quic_conn_id_st { 108 unsigned char id_len; 109 unsigned char id[QUIC_MAX_CONN_ID_LEN]; 110#if 0 111 /* likely required later, although this might not be the ideal location */ 112 unsigned char reset_token[16]; /* stateless reset token is per conn ID */ 113#endif 114} QUIC_CONN_ID; 115 116static ossl_unused ossl_inline int ossl_quic_conn_id_eq(const QUIC_CONN_ID *a, 117 const QUIC_CONN_ID *b); 118 119/* New functions */ 120int ossl_quic_conn_id_set(QUIC_CONN_ID *cid, unsigned char *id, 121 unsigned int id_len); 122 123int ossl_quic_conn_id_generate(QUIC_CONN_ID *cid); 124``` 125 126### Remote Connection ID APIs 127 128```c 129typedef struct quic_remote_conn_id_cache_st QUIC_REMOTE_CONN_ID_CACHE; 130 131/* 132 * Allocate and free a remote connection ID cache 133 */ 134QUIC_REMOTE_CONN_ID_CACHE *ossl_quic_remote_conn_id_cache_new( 135 size_t id_limit /* [active_connection_id_limit] */ 136 ); 137void ossl_quic_remote_conn_id_cache_free(QUIC_REMOTE_CONN_ID_CACHE *cache); 138 139/* 140 * Add a remote connection ID to the cache 141 */ 142int ossl_quic_remote_conn_id_cache_add(QUIC_REMOTE_CONN_ID_CACHE *cache, 143 const QUIC_CONNECTION *conn, 144 const unsigned char *conn_id, 145 size_t conn_id_len, 146 uint64_t seq_no); 147 148/* 149 * Query a remote connection for a connection ID. 150 * Each connection can have multiple connection IDs associated with different 151 * routes. This function returns one of these in a non-specified manner. 152 */ 153int ossl_quic_remote_conn_id_cache_get0_conn_id( 154 const QUIC_REMOTE_CONN_ID_CACHE *cache, 155 const QUIC_CONNECTION *conn, QUIC_CONN_ID **cid); 156 157/* 158 * Retire remote connection IDs up to and including the one determined by the 159 * sequence number. 160 */ 161int ossl_quic_remote_conn_id_cache_retire( 162 QUIC_REMOTE_CONN_ID_CACHE *cache, uint64_t seq_no); 163 164/* 165 * Remove remote connection IDs up to and including the one determined by the 166 * sequence number. 167 */ 168int ossl_quic_remote_conn_id_cache_remove( 169 QUIC_REMOTE_CONN_ID_CACHE *cache, uint64_t seq_no); 170``` 171 172### Local Connection ID APIs 173 174```c 175typedef struct quic_local_conn_id_cache_st QUIC_LOCAL_CONN_ID_CACHE; 176 177/* 178 * Allocate and free a local connection ID cache 179 */ 180QUIC_LOCAL_CONN_ID_CACHE *ossl_quic_local_conn_id_cache_new(void); 181void ossl_quic_local_conn_id_cache_free(QUIC_LOCAL_CONN_ID_CACHE *cache); 182 183/* 184 * Generate a new random local connection ID and associate it with a connection. 185 * For MVP this could just be a zero length ID. 186 */ 187int ossl_quic_local_conn_id_cache_new_conn_id(QUIC_LOCAL_CONN_ID_CACHE *cache, 188 QUIC_CONNECTION *conn, 189 QUIC_CONN_ID **cid); 190 191/* 192 * Remove a local connection and all associated cached IDs 193 */ 194int ossl_quic_local_conn_id_cache_remove_conn(QUIC_LOCAL_CONN_ID_CACHE *cache, 195 const QUIC_CONNECTION *conn); 196 197/* 198 * Lookup a local connection by ID. 199 * Returns the connection or NULL if absent. 200 */ 201QUIC_CONNECTION *ossl_quic_local_conn_id_cache_get0_conn( 202 const QUIC_LOCAL_CONN_ID_CACHE *cache, 203 const unsigned char *conn_id, size_t conn_id_len); 204 205/* 206 * Retire local connection IDs up to and including the one specified by the 207 * sequence number. 208 */ 209int ossl_quic_local_conn_id_cache_retire( 210 QUIC_LOCAL_CONN_ID_CACHE *cache, uint64_t from_seq_no); 211 212/* 213 * Remove local connection IDs up to and including the one specified by the 214 * sequence number. 215 */ 216int ossl_quic_local_conn_id_cache_remove( 217 QUIC_LOCAL_CONN_ID_CACHE *cache, uint64_t from_seq_no); 218``` 219 220### Routes 221 222Additional status and source information is also included. 223 224```c 225typedef struct quic_route_st QUIC_ROUTE; 226typedef struct quic_route_table QUIC_ROUTE_TABLE; 227 228struct quic_route_st { 229 QUIC_CONNECTION *conn; 230 QUIC_CONN_ID local; 231 QUIC_CONN_ID remote; 232 uint64_t seq_no; /* Sequence number for both ends */ 233 unsigned int retired : 1; /* Connection ID has been retired */ 234#if 0 235 /* Later will require */ 236 BIO_ADDR remote_address;/* remote source address */ 237#endif 238}; 239 240QUIC_ROUTE_TABLE *ossl_quic_route_table_new(void); 241void ossl_quic_route_table_free(QUIC_ROUTE_TABLE *routes); 242``` 243 244### Add route to route table 245 246```c 247int ossl_route_table_add_route(QUIC_ROUTE_TABLE *cache, 248 QUIC_ROUTE_TABLE *route); 249``` 250 251### Route query 252 253```c 254/* 255 * Query a route table entry by either local or remote ID 256 */ 257QUIC_ROUTE *ossl_route_table_get0_route_from_local( 258 const QUIC_ROUTE_TABLE *cache, 259 const unsigned char *conn_id, size_t conn_id_len); 260QUIC_ROUTE *ossl_route_table_get0_route_from_remote( 261 const QUIC_ROUTE_TABLE *cache, 262 const unsigned char *conn_id, size_t conn_id_len); 263``` 264 265### Route retirement 266 267```c 268/* 269 * Retire by sequence number up to and including the one specified. 270 */ 271int ossl_quic_route_table_retire(QUIC_ROUTE_TABLE *routes, 272 QUIC_CONNECTION *conn, 273 uint64_t seq_no); 274 275/* 276 * Delete by sequence number up to and including the one specified. 277 */ 278int ossl_quic_route_table_remove(QUIC_ROUTE_TABLE *routes, 279 QUIC_CONNECTION *conn, 280 uint64_t seq_no); 281``` 282 283[5.1]: (https://datatracker.ietf.org/doc/html/rfc9000#section-5.1) 284[active_connection_id_limit]: (https://datatracker.ietf.org/doc/html/rfc9000#section-18.2) 285[NEW_CONNECTION_ID]: (https://datatracker.ietf.org/doc/html/rfc9000#section-19.15) 286[RETIRE_CONNECTION_ID]: (https://datatracker.ietf.org/doc/html/rfc9000#section-19.16) 287[retired]: (https://datatracker.ietf.org/doc/html/rfc9000#section-5.1.2) 288