]> git.ipfire.org Git - thirdparty/openssl.git/blame - doc/designs/quic-design/tx-packetiser.md
Add HISTORY section to EVP_KEM-EC document.
[thirdparty/openssl.git] / doc / designs / quic-design / tx-packetiser.md
CommitLineData
fabce809
P
1TX Packetiser
2=============
3
4This module creates frames from the application data obtained from
5the application. It also receives CRYPTO frames from the TLS Handshake
6Record Layer and ACK frames from the ACK Handling And Loss Detector
7subsystem.
8
9The packetiser also deals with the flow and congestion controllers.
10
11Creation & Destruction
12----------------------
13
14```c
15struct ossl_quic_tx_packetiser_st {
16 QUIC_CONNECTION *conn;
17};
18
19_owur typedef struct ossl_quic_tx_packetiser_st OSSL_QUIC_TX_PACKETISER;
20
21OSSL_QUIC_TX_PACKETISER ossl_quic_tx_packetiser_new(QUIC_CONNECTION *conn);
22void ossl_quic_tx_packetiser_free(OSSL_QUIC_TX_PACKETISER *tx);
23```
24
25Structures
26----------
27
28### Connection
29
30Represented by an QUIC_CONNECTION object.
31
32### Stream
33
34Represented by an QUIC_STREAM object.
35
36As per [RFC 9000 2.3 Stream Prioritization], streams should contain a priority
37provided by the calling application. For MVP, this is not required to be
38implemented because only one stream is supported. However, packets being
39retransmitted should be preferentially sent as noted in
40[RFC 9000 13.3 Retransmission of Information].
41
42```c
43void SSL_set_priority(SSL *stream, uint32_t priority);
44uint32_t SSL_get_priority(SSL *stream);
45```
46
47For protocols where priority is not meaningful, the set function is a noop and
48the get function returns a constant value.
49
50### Frame
51
52QUIC frames are represented by a leading variable length integer
53indicating the type of the frame. This is followed by the frame data.
54Only the first byte of the type is important because there are no defined
55packet types that need more than one byte to represent. Thus:
56
57```c
58struct ossl_quic_frame_st {
59 unsigned char type;
60};
61
62typedef struct ossl_quic_frame_st OSSL_QUIC_FRAME;
63
64struct ossl_quic_txp_frame_st {
65 OSSL_QUIC_FRAME *frame; /* Frame in wire format */
66 size_t frame_len; /* Size of frame */
67 uint32_t priority; /* Priority of frame */
68};
69
70typedef struct ossl_quic_txp_frame_st OSSL_QUIC_TXP_FRAME;
71```
72
73The packetiser/ACK manager can alter the priority of a frame a small amount.
74For example, a retransmitted frame may have it's priority increased slightly.
75
76#### Frames
77
78Frames are taken from [RFC 9000 12.4 Frames and Frame Types].
79
80| Type | Name | I | H | 0 | 1 | N | C | P | F |
81| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
82| 0x00 | padding | ✓ | ✓ | ✓ | ✓ | ✓ | | ✓
83| 0x01 | ping | ✓ | ✓ | ✓ | ✓ | | | | |
84| 0x02 | ack 0x02 | ✓ | ✓ | | ✓ | ✓ | ✓ | | |
85| 0x03 | ack 0x03 | ✓ | ✓ | | ✓ | ✓ | ✓ | | |
86| 0x04 | reset_stream | | | ✓ | ✓ | | | | |
87| 0x05 | stop_sending | | | ✓ | ✓ | | | | |
88| 0x06 | crypto | ✓ | ✓ | | ✓ | | | | |
89| 0x07 | new_token | | | | ✓ | | | | |
90| 0x08 | stream 0x08 | | | ✓ | ✓ | | | | ✓ |
91| 0x09 | stream 0x09 | | | ✓ | ✓ | | | | ✓ |
92| 0x0A | stream 0x0A | | | ✓ | ✓ | | | | ✓ |
93| 0x0B | stream 0x0B | | | ✓ | ✓ | | | | ✓ |
94| 0x0C | stream 0x0C | | | ✓ | ✓ | | | | ✓ |
95| 0x0D | stream 0x0D | | | ✓ | ✓ | | | | ✓ |
96| 0x0E | stream 0x0E | | | ✓ | ✓ | | | | ✓ |
97| 0x0F | stream 0x0F | | | ✓ | ✓ | | | | ✓ |
98| 0x10 | max_data | | | ✓ | ✓ | | | | |
99| 0x11 | max_stream_data | | | ✓ | ✓ | | | | |
100| 0x12 | max_streams 0x12 | | | ✓ | ✓ | | | | |
101| 0x13 | max_streams 0x13 | | | ✓ | ✓ | | | | |
102| 0x14 | data_blocked | | | ✓ | ✓ | | | | |
103| 0x15 | stream_data_blocked | | | ✓ | ✓ | | | | |
104| 0x16 | streams_blocked 0x16 | | | ✓ | ✓ | | | | |
105| 0x17 | streams_blocked 0x17 | | | ✓ | ✓ | | | | |
106| 0x18 | new_connection_id | | | ✓ | ✓ | | | ✓ | |
107| 0x19 | retire_connection_id | | | ✓ | ✓ | | | | |
108| 0x1A | path_challenge | | | ✓ | ✓ | | | ✓ | |
109| 0x1B | path_response | | | | ✓ | | | ✓ | |
110| 0x1C | connection_close 0x1C | ✓ | ✓ | ✓ | ✓ | ✓
111| 0x1D | connection_close 0x1D | | | ✓ | ✓ | ✓ | | | |
112| 0x1E | handshake_done | | | | ✓ | | | | |
113
114The various fields are as defined in RFC 9000.
115
116##### Pkts
117
118_Pkts_ are defined as:
119
120| Pkts | Description|
121| :---: | --- |
122| I | Valid in Initial packets|
123| H | Valid in Handshake packets|
124| 0 | Valid in 0-RTT packets|
125| 1 | Valid in 1-RTT packets|
126
127##### Spec
128
129_Spec_ is defined as:
130
131| Spec | Description |
132| :---: | --- |
133| N | Not ack-eliciting. |
134| C | does not count toward bytes in flight for congestion control purposes. |
135| P | Can be used to probe new network paths during connection migration. |
136| F | The contents of frames with this marking are flow controlled. |
137
138For `C`, `N` and `P`, the entire packet must consist of only frames with the
139marking for the packet to qualify for it. For example, a packet with an ACK
140frame and a _stream_ frame would qualify for neither the `C` or `N` markings.
141
142### Packets
143
144Frames are coalesced into packets which are then sent by the record layer.
145The `packet_header` is a pointer to the leading bytes of the packet.
146The `frames` are pointers to the individual frames that make up the
147packet's body.
148It is expected that the record layer will encrypt from the `packet_header` and
149`frames` directly without a copy.
150
151```c
152enum packet_validity_e {
153 QUIC_PACKET_INITIAL,
154 QUIC_PACKET_HANDSHAKE,
155 QUIC_PACKET_0_RTT,
156 QUIC_PACKET_1_RTT
157};
158
159typedef enum packet_validity_e PACKET_VALIDITY;
160
161struct ossl_quic_packet_st {
162 QUIC_CONNECTION *conn;
163 unsigned char *packet_header;
164 size_t packet_header_length;
165 STACK_OF(OSSL_QUIC_TXP_FRAME) *frames;
166
167 QUIC_PN packet_number; /* RFC 9000 12.3 */
168 size_t packet_length;
169
170 /*
171 * One of the QUIC_PN_SPACE_* values. This qualifies the pkt_num field
172 * into a packet number space.
173 */
174 unsigned int pkt_space : 2;
175
176 /* Pkts options */
177 PACKET_VALIDITY validity;
178
179 /* Spec */
180 unsigned int no_ack : 1;
181 unsigned int no_congestion_control : 1;
182 unsigned int probing : 1;
183 unsigned int flow_controlled : 1;
184};
185
186typedef struct ossl_quic_packet_st OSSL_QUIC_PACKET;
187```
188
189#### Notes
190
191- Do we need the distinction between 0-rtt and 1-rtt when both are in
192 the Application Data number space?
193- 0-RTT packets can morph into 1-RTT packets and this needs to be handled by
194 the packetiser.
195
196Interactions
197------------
198
199The packetiser needs to interact with other modules. This defines the APIs
200by which it does so.
201
202Frames are passed to the packetiser on a per stream basis.
203The frames must be fully formed. By passing a frame to this function,
204ownership is passed to the packetiser which queues the frames for later
205sending by the record layer.
206
207```c
208int ossl_quic_packetiser_buffer_frame(OSSL_QUIC_TX_PACKETISER *tx,
209 QUIC_CONNECTION *stream,
210 const OSSL_QUIC_FRAME *frame,
211 size_t frame_length);
212```
213
214### Stream Send Buffers
215
216Data from the stream send buffers is treated specially. The packetiser knows
217how much space is left in each packet and it will request that amount of data
218from the stream send buffers. The stream send buffers will return a
219constructed frame header and a pointer to the steam data and length. A second
220call exists to allow the packetiser to know how much data is queued for a stream
221so that planning for the creation of multiple packets is possible.
222
223```c
224int ossl_quic_get_app_data(QUIC_STREAM *stream, size_t request,
225 const OSSL_QUIC_FRAME **frame,
226 const unsigned char **data,
227 size_t *data_len);
228
229size_t ossl_quic_get_app_data_size(QUIC_STREAM *stream);
230```
231
232#### Notes
233
234* Unclear how to best free the data after sent data was acked.
235 The data will be fragments from the buffers so the stream send buffers will
236 need to remember which fragment have been sent and which are pending and
237 only free once everything is sent:
238
239```c
240int ossl_quic_free_app_data(QUIC_STREAM *stream, void *data, size_t data_len);
241```
242
243* Need a call to tell the stream send buffers to forget about previously
244 requested app data because it needs to be retransmitted and the
245 boundaries could change. Any record of the indicated data having being
246 transmitted should be removed and the data is made eligible to be sent
247 again.
248
249```c
250int ossl_quic_retransmitting_app_data(QUIC_STREAM *stream,
251 void *data, size_t data_len);
252```
253
254### TLS Handshake Record Layer
255
256Uses the Record Layer API to implement the inner TLS-1.3 protocol handshake.
257It produces the QUIC crypto frames which are queued using the same mechanism
258as the [Stream Send Buffers](#stream-send-buffers) above.
259
260### Flow Controller and Statistics Collector
261
262To make decisions about what frames to coalesce, the packetiser relies
263on the flow controller to enforce stream and connection bandwidth limits
264[RFC 9000 4.1 Data Flow Control].
265
266```c
267/*
268 * Return the maximum amount of data that is permitted for the given stream.
269 * This includes both the stream limit and it's associated connection limit.
270 */
271size_t ossl_quic_stream_flow_maximum_size(QUIC_STREAM *stream);
272
273/*
274 * Inform the flow controller that an amount of data has been queued for
275 * sending to a stream.
276 */
277int ossl_quic_flow_controller_sent_data(QUIC_FLOW_CONTROLLER *flow,
278 QUIC_STREAM *stream, size_t bytes);
279```
280
281### Congestion Controller
282
283Also part of the frame coalescing decision is the congestion controller
284[RFC 9002]. For MVP, this will be a _just send it_.
285
286```c
287/*
288 * Pluggable congestion controller APIs go here
289 * Extract that is required from #18018
290 */
291```
292
293### QUIC Write Record Layer
294
295Coalesced frames are passed to the QUIC record layer for encryption and sending.
296To send accumulated frames as packets to the QUIC Write Record Layer:
297
298```c
299int ossl_qtx_write_pkt(OSSL_QTX *qtx, const OSSL_QTX_PKT *pkt);
300```
301
302The packetiser will attempt to maximise the number of bytes in a packet.
303It will also attempt to create multiple packets to send simultaneously.
304
305The packetiser should also implement a wait time to allow more data to
306accumulate before exhausting it's supply of data. The length of the wait
307will depend on how much data is queue already and how much space remains in
308the packet being filled. Once the wait is finished, the packets will be sent
309by calling:
310
311```c
312void ossl_qtx_flush_net(OSSL_QTX *qtx);
313```
314
315The write record layer is responsible for coalescing multiple QUIC packets
316into datagrams.
317
318### ACK Handling and Loss Detector
319
3201. When a packet is sent, the packetiser needs to inform the ACK Manager.
3212. When a packet is ACKed, inform packetiser so it can drop sent frames.
3223. When a packet is lost, inform packetiser to create retransmission packet(s).
3234. When a packet is discarded without ACK/loss, inform packetiser to clean up.
324
325```c
326int ossl_ackm_on_tx_packet(OSSL_ACKM *ackm, OSSL_ACKM_TX_PKT *pkt)
327int ossl_quic_packet_acked(OSSL_QUIC_TX_PACKETISER *tx,
328 OSSL_QUIC_PACKET *packet);
329int ossl_quic_packet_lost(OSSL_QUIC_TX_PACKETISER *tx,
330 OSSL_QUIC_PACKET *packet);
331int ossl_quic_packet_discarded(OSSL_QUIC_TX_PACKETISER *tx,
332 OSSL_QUIC_PACKET *packet);
333```
334
335#### Notes
336
337| Name here | Name in ACK Manager |
338| --- | --- |
339| `ossl_quic_packet_sent` | `QUIC_ACKM_on_tx_ack_packet` |
340| `ossl_quic_packet_acked` | `on_acked` |
341| `ossl_quic_packet_lost` | `on_lost` |
342| `ossl_quic_packet_discarded` | `on_discarded` |
343
344Packets
345-------
346
347Packets formats are defined in [RFC 9000 17.1 Packet Formats].
348
349### Packet types
350
351QUIC supports a number of different packets. The combination of packets of
352different types as per [RFC 9000 12.2 Coalescing Packets], is done by the
353record layer.
354
355#### Version Negotiation Packet
356
357Refer to [RFC 9000 17.2.1 Version Negotiation Packet].
358
359#### Initial Packet
360
361Refer to [RFC 9000 17.2.2 Initial Packet].
362
363#### Handshake Packet
364
365Refer to [RFC 9000 17.2.4 Handshake Packet].
366
367#### App Data 0-RTT Packet
368
369Refer to [RFC 9000 17.2.3 0-RTT].
370
371#### App Data 1-RTT Packet
372
373Refer to [RFC 9000 17.3.1 1-RTT].
374
375#### Retry Packet
376
377Refer to [RFC 9000 17.2.5 Retry Packet.
378
379Packetisation and Processing
380----------------------------
381
382### Application data frames
383
384The packetiser builds application data frames after requesting a specific
385amount of application data. If insufficient data is available, or buffer
386boundaries prevent fulfilling the entire request, the stream send buffer module
387is free to return a smaller amount of data.
388
389### Retransmission
390
391When a packet is determined to be lost by the ACK Manager, the
392`ossl_quic_packet_lost()` function will be called. This function will
393extract the frame references from the packet and re-queue them for
394transmission as if `ossl_quic_packetiser_buffer_frame()` had been called
395for each
396frame followed by `ossl_quic_packetiser_send_packets()`. Frames that need to be
397retransmitted will be be considered higher priority than other pending
398frames, although both types are available to construct packets from.
399Moreover, any such constructed packets will not be subject to a delay
400before transmission.
401
402### Restricting packet sizes
403
404Three factors impact the size of packets that can be sent:
405
406* MTU restricting packet sizes
407* Flow control
408* Congestion control
409
410The MTU limits the size of an individual packet, the other two limit the
411total amount of data that can be sent. The packetiser needs to query the
412current limits using the `ossl_quic_stream_flow_maximum_size()`,
413`get_send_allowance()` and `get_data_mtu()` calls.
414
415The packetiser will prioritise sending [`C`](#spec) spec packets together
416in order to maximise the amount of data available for the application.
417
418### Stateless Reset
419
420Refer to [RFC 9000 10.3 Stateless Reset]. It's entirely reasonable for
421the state machine to send this directly and immediately if required.
422
423[RFC 9000 2.3 Stream Prioritization]: https://datatracker.ietf.org/doc/html/rfc9000#section-2.3
424[RFC 9000 4.1 Data Flow Control]: https://datatracker.ietf.org/doc/html/rfc9000#section-4.1
425[RFC 9000 10.3 Stateless Reset]: https://datatracker.ietf.org/doc/html/rfc9000#section-10.3
426[RFC 9000 12.2 Coalescing Packets]: https://datatracker.ietf.org/doc/html/rfc9000#section-12.2
427[RFC 9000 12.4 Frames and Frame Types]: https://datatracker.ietf.org/doc/html/rfc9000#section-12.4
428[RFC 9000 13.3 Retransmission of Information]: https://datatracker.ietf.org/doc/html/rfc9000#section-13.3
429[RFC 9000 17.1 Packet Formats]: https://datatracker.ietf.org/doc/html/rfc9000#section-17
430[RFC 9000 17.2.1 Version Negotiation Packet]: https://datatracker.ietf.org/doc/html/rfc9000#section-17.2.1
431[RFC 9000 17.2.2 Initial Packet]: https://datatracker.ietf.org/doc/html/rfc9000#section-17.2.2
432[RFC 9000 17.2.3 0-RTT]: https://datatracker.ietf.org/doc/html/rfc9000#section-17.2.3
433[RFC 9000 17.2.4 Handshake Packet]: https://datatracker.ietf.org/doc/html/rfc9000#section-17.2.4
434[RFC 9000 17.2.5 Retry Packet]: https://datatracker.ietf.org/doc/html/rfc9000#section-17.2.5
435[RFC 9000 17.3.1 1-RTT]: https://datatracker.ietf.org/doc/html/rfc9000#section-17.3.1
436[RFC 9002]: https://datatracker.ietf.org/doc/html/rfc9002