QUIC ACKM: Clarify probe types
[openssl.git] / include / internal / quic_ackm.h
1 /*
2  * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 #ifndef OSSL_QUIC_ACKM_H
10 # define OSSL_QUIC_ACKM_H
11
12 # include "internal/quic_statm.h"
13 # include "internal/quic_cc.h"
14 # include "internal/quic_types.h"
15 # include "internal/quic_wire.h"
16 # include "internal/time.h"
17 # include "internal/list.h"
18
19 # ifndef OPENSSL_NO_QUIC
20
21 typedef struct ossl_ackm_st OSSL_ACKM;
22
23 OSSL_ACKM *ossl_ackm_new(OSSL_TIME (*now)(void *arg),
24                          void *now_arg,
25                          OSSL_STATM *statm,
26                          const OSSL_CC_METHOD *cc_method,
27                          OSSL_CC_DATA *cc_data);
28 void ossl_ackm_free(OSSL_ACKM *ackm);
29
30 void ossl_ackm_set_loss_detection_deadline_callback(OSSL_ACKM *ackm,
31                                                     void (*fn)(OSSL_TIME deadline,
32                                                                void *arg),
33                                                     void *arg);
34
35 void ossl_ackm_set_ack_deadline_callback(OSSL_ACKM *ackm,
36                                          void (*fn)(OSSL_TIME deadline,
37                                                     int pkt_space,
38                                                     void *arg),
39                                          void *arg);
40
41 typedef struct ossl_ackm_tx_pkt_st OSSL_ACKM_TX_PKT;
42 struct ossl_ackm_tx_pkt_st {
43     /* The packet number of the transmitted packet. */
44     QUIC_PN pkt_num;
45
46     /* The number of bytes in the packet which was sent. */
47     size_t num_bytes;
48
49     /* The time at which the packet was sent. */
50     OSSL_TIME time;
51
52     /*
53      * If the packet being described by this structure contains an ACK frame,
54      * this must be set to the largest PN ACK'd by that frame.
55      *
56      * Otherwise, it should be set to QUIC_PN_INVALID.
57      *
58      * This is necessary to bound the number of PNs we have to keep track of on
59      * the RX side (RFC 9000 s. 13.2.4). It allows older PN tracking information
60      * on the RX side to be discarded.
61      */
62     QUIC_PN largest_acked;
63
64     /*
65      * One of the QUIC_PN_SPACE_* values. This qualifies the pkt_num field
66      * into a packet number space.
67      */
68     unsigned int pkt_space :2;
69
70     /* 1 if the packet is in flight. */
71     unsigned int is_inflight :1;
72
73     /* 1 if the packet has one or more ACK-eliciting frames. */
74     unsigned int is_ack_eliciting :1;
75
76     /* 1 if the packet is a PTO probe. */
77     unsigned int is_pto_probe :1;
78
79     /* 1 if the packet is an MTU probe. */
80     unsigned int is_mtu_probe :1;
81
82     /* Callback called if frames in this packet are lost. arg is cb_arg. */
83     void (*on_lost)(void *arg);
84     /* Callback called if frames in this packet are acked. arg is cb_arg. */
85     void (*on_acked)(void *arg);
86     /*
87      * Callback called if frames in this packet are neither acked nor lost. arg
88      * is cb_arg.
89      */
90     void (*on_discarded)(void *arg);
91     void  *cb_arg;
92
93     /* 
94      * (Internal use fields; must be zero-initialized.)
95      *
96      * Keep a TX history list, anext is used to manifest
97      * a singly-linked list of newly-acknowledged packets, and lnext is used to
98      * manifest a singly-linked list of newly lost packets.
99      */
100     OSSL_LIST_MEMBER(tx_history, OSSL_ACKM_TX_PKT);
101
102     struct ossl_ackm_tx_pkt_st *anext;
103     struct ossl_ackm_tx_pkt_st *lnext;
104 };
105
106 int ossl_ackm_on_tx_packet(OSSL_ACKM *ackm, OSSL_ACKM_TX_PKT *pkt);
107 int ossl_ackm_on_rx_datagram(OSSL_ACKM *ackm, size_t num_bytes);
108
109 #  define OSSL_ACKM_ECN_NONE      0
110 #  define OSSL_ACKM_ECN_ECT1      1
111 #  define OSSL_ACKM_ECN_ECT0      2
112 #  define OSSL_ACKM_ECN_ECNCE     3
113
114 typedef struct ossl_ackm_rx_pkt_st {
115     /* The packet number of the received packet. */
116     QUIC_PN pkt_num;
117
118     /* The time at which the packet was received. */
119     OSSL_TIME time;
120
121     /*
122      * One of the QUIC_PN_SPACE_* values. This qualifies the pkt_num field
123      * into a packet number space.
124      */
125     unsigned int pkt_space :2;
126
127     /* 1 if the packet has one or more ACK-eliciting frames. */
128     unsigned int is_ack_eliciting :1;
129
130     /*
131      * One of the OSSL_ACKM_ECN_* values. This is the ECN labelling applied to
132      * the received packet. If unknown, use OSSL_ACKM_ECN_NONE.
133      */
134     unsigned int ecn :2;
135 } OSSL_ACKM_RX_PKT;
136
137 int ossl_ackm_on_rx_packet(OSSL_ACKM *ackm, const OSSL_ACKM_RX_PKT *pkt);
138
139 int ossl_ackm_on_rx_ack_frame(OSSL_ACKM *ackm, const OSSL_QUIC_FRAME_ACK *ack,
140                               int pkt_space, OSSL_TIME rx_time);
141
142 /*
143  * Discards a PN space. This must be called for a PN space before freeing the
144  * ACKM if you want in-flight packets to have their discarded callbacks called.
145  * This should never be called in ordinary QUIC usage for the Application Data
146  * PN space, but it may be called for the Application Data PN space prior to
147  * freeing the ACKM to simplify teardown implementations.
148  */
149 int ossl_ackm_on_pkt_space_discarded(OSSL_ACKM *ackm, int pkt_space);
150
151 int ossl_ackm_on_handshake_confirmed(OSSL_ACKM *ackm);
152 int ossl_ackm_on_timeout(OSSL_ACKM *ackm);
153
154 OSSL_TIME ossl_ackm_get_loss_detection_deadline(OSSL_ACKM *ackm);
155
156 /*
157  * Generates an ACK frame, regardless of whether the ACK manager thinks
158  * one should currently be sent.
159  *
160  * This clears the flag returned by ossl_ackm_is_ack_desired and the deadline
161  * returned by ossl_ackm_get_ack_deadline.
162  */
163 const OSSL_QUIC_FRAME_ACK *ossl_ackm_get_ack_frame(OSSL_ACKM *ackm,
164                                                    int pkt_space);
165
166 /*
167  * Returns the deadline after which an ACK frame should be generated by calling
168  * ossl_ackm_get_ack_frame, or OSSL_TIME_INFINITY if no deadline is currently
169  * applicable. If the deadline has already passed, this function may return that
170  * deadline, or may return OSSL_TIME_ZERO.
171  */
172 OSSL_TIME ossl_ackm_get_ack_deadline(OSSL_ACKM *ackm, int pkt_space);
173
174 /*
175  * Returns 1 if the ACK manager thinks an ACK frame ought to be generated and
176  * sent at this time. ossl_ackm_get_ack_frame will always provide an ACK frame
177  * whether or not this returns 1, so it is suggested that you call this function
178  * first to determine whether you need to generate an ACK frame.
179  *
180  * The return value of this function can change based on calls to
181  * ossl_ackm_on_rx_packet and based on the passage of time (see
182  * ossl_ackm_get_ack_deadline).
183  */
184 int ossl_ackm_is_ack_desired(OSSL_ACKM *ackm, int pkt_space);
185
186 /*
187  * Returns 1 if the given RX PN is 'processable'. A processable PN is one that
188  * is not either
189  *
190  *   - duplicate, meaning that we have already been passed such a PN in a call
191  *     to ossl_ackm_on_rx_packet; or
192  *
193  *   - written off, meaning that the PN is so old we have stopped tracking state
194  *     for it (meaning that we cannot tell whether it is a duplicate and cannot
195  *     process it safely).
196  *
197  * This should be called for a packet before attempting to process its contents.
198  * Failure to do so may result in processing a duplicated packet in violation of
199  * the RFC.
200  *
201  * The return value of this function transitions from 1 to 0 for a given PN once
202  * that PN is passed to ossl_ackm_on_rx_packet, thus thus function must be used
203  * before calling ossl_ackm_on_rx_packet.
204  */
205 int ossl_ackm_is_rx_pn_processable(OSSL_ACKM *ackm, QUIC_PN pn, int pkt_space);
206
207 typedef struct ossl_ackm_probe_info_st {
208     /*
209      * The following two probe request types are used only for anti-deadlock
210      * purposes in relation to the anti-amplification logic, by generating
211      * packets to buy ourselves more anti-amplification credit with the server
212      * until a client address is verified. Note that like all Initial packets,
213      * any Initial probes are padded.
214      *
215      * Note: The ACKM will only ever increase these by one at a time,
216      * as only one probe packet should be generated for these cases.
217      */
218     uint32_t anti_deadlock_initial, anti_deadlock_handshake;
219
220     /*
221      * Send an ACK-eliciting packet for each count here.
222      *
223      * Note: The ACKM may increase this by either one or two for each probe
224      * request, depending on how many probe packets it thinks should be
225      * generated.
226      */
227     uint32_t pto[QUIC_PN_SPACE_NUM];
228 } OSSL_ACKM_PROBE_INFO;
229
230 int ossl_ackm_get_probe_request(OSSL_ACKM *ackm, int clear,
231                                 OSSL_ACKM_PROBE_INFO *info);
232
233 int ossl_ackm_get_largest_unacked(OSSL_ACKM *ackm, int pkt_space, QUIC_PN *pn);
234
235 /*
236  * Forces the ACKM to consider a packet with the given PN in the given PN space
237  * as having been pseudo-lost. The main reason to use this is during a Retry, to
238  * force any resources sent in the first Initial packet to be resent.
239  *
240  * The lost callback is called for the packet, but the packet is NOT considered
241  * lost for congestion control purposes. Thus this is not exactly the same as a
242  * true loss situation.
243  */
244 int ossl_ackm_mark_packet_pseudo_lost(OSSL_ACKM *ackm,
245                                       int pkt_space, QUIC_PN pn);
246
247 /*
248  * Returns the PTO duration as currently calculated. This is a quantity of time.
249  * This duration is used in various parts of QUIC besides the ACKM.
250  */
251 OSSL_TIME ossl_ackm_get_pto_duration(OSSL_ACKM *ackm);
252
253 # endif
254
255 #endif