xref: /openssl/include/internal/quic_cc.h (revision ff3a26b2)
1 /*
2  * Copyright 2022-2023 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_CC_H
10 # define OSSL_QUIC_CC_H
11 
12 #include "openssl/params.h"
13 #include "internal/time.h"
14 #include "internal/quic_predef.h"
15 
16 # ifndef OPENSSL_NO_QUIC
17 
18 typedef struct ossl_cc_ack_info_st {
19     /* The time the packet being acknowledged was originally sent. */
20     OSSL_TIME   tx_time;
21 
22     /* The size in bytes of the packet being acknowledged. */
23     size_t      tx_size;
24 } OSSL_CC_ACK_INFO;
25 
26 typedef struct ossl_cc_loss_info_st {
27     /* The time the packet being lost was originally sent. */
28     OSSL_TIME   tx_time;
29 
30     /* The size in bytes of the packet which has been determined lost. */
31     size_t      tx_size;
32 } OSSL_CC_LOSS_INFO;
33 
34 typedef struct ossl_cc_ecn_info_st {
35     /*
36      * The time at which the largest acked PN (in the incoming ACK frame) was
37      * sent.
38      */
39     OSSL_TIME   largest_acked_time;
40 } OSSL_CC_ECN_INFO;
41 
42 /* Parameter (read-write): Maximum datagram payload length in bytes. */
43 #define OSSL_CC_OPTION_MAX_DGRAM_PAYLOAD_LEN        "max_dgram_payload_len"
44 
45 /* Diagnostic (read-only): current congestion window size in bytes. */
46 #define OSSL_CC_OPTION_CUR_CWND_SIZE                "cur_cwnd_size"
47 
48 /* Diagnostic (read-only): minimum congestion window size in bytes. */
49 #define OSSL_CC_OPTION_MIN_CWND_SIZE                "min_cwnd_size"
50 
51 /* Diagnostic (read-only): current net bytes in flight. */
52 #define OSSL_CC_OPTION_CUR_BYTES_IN_FLIGHT          "bytes_in_flight"
53 
54 /* Diagnostic (read-only): method-specific state value. */
55 #define OSSL_CC_OPTION_CUR_STATE                    "cur_state"
56 
57 /*
58  * Congestion control abstract interface.
59  *
60  * This interface is broadly based on the design described in RFC 9002. However,
61  * the demarcation between the ACKM and the congestion controller does not
62  * exactly match that delineated in the RFC 9002 pseudocode. Where aspects of
63  * the demarcation involve the congestion controller accessing internal state of
64  * the ACKM, the interface has been revised where possible to provide the
65  * information needed by the congestion controller and avoid needing to give the
66  * congestion controller access to the ACKM's internal data structures.
67  *
68  * Particular changes include:
69  *
70  *   - In our implementation, it is the responsibility of the ACKM to determine
71  *     if a loss event constitutes persistent congestion.
72  *
73  *   - In our implementation, it is the responsibility of the ACKM to determine
74  *     if the ECN-CE counter has increased. The congestion controller is simply
75  *     informed when an ECN-CE event occurs.
76  *
77  * All of these changes are intended to avoid having a congestion controller
78  * have to access ACKM internal state.
79  */
80 #define OSSL_CC_LOST_FLAG_PERSISTENT_CONGESTION     (1U << 0)
81 
82 struct ossl_cc_method_st {
83     /*
84      * Instantiation.
85      */
86     OSSL_CC_DATA *(*new)(OSSL_TIME (*now_cb)(void *arg),
87                          void *now_cb_arg);
88 
89     void (*free)(OSSL_CC_DATA *ccdata);
90 
91     /*
92      * Reset of state.
93      */
94     void (*reset)(OSSL_CC_DATA *ccdata);
95 
96     /*
97      * Escape hatch for option configuration.
98      *
99      * params is an array of OSSL_PARAM structures.
100      *
101      * Returns 1 on success and 0 on failure.
102      */
103     int (*set_input_params)(OSSL_CC_DATA *ccdata,
104                             const OSSL_PARAM *params);
105 
106     /*
107      * (Re)bind output (diagnostic) information.
108      *
109      * params is an array of OSSL_PARAM structures used to output values. The
110      * storage locations associated with each parameter are stored internally
111      * and updated whenever the state of the congestion controller is updated;
112      * thus, the storage locations associated with the OSSL_PARAMs passed in the
113      * call to this function must remain valid until the congestion controller
114      * is freed or those parameters are unbound. A given parameter name may be
115      * bound to only one location at a time. The params structures themselves
116      * do not need to remain allocated after this call returns.
117      *
118      * Returns 1 on success and 0 on failure.
119      */
120     int (*bind_diagnostics)(OSSL_CC_DATA *ccdata,
121                             OSSL_PARAM *params);
122 
123     /*
124      * Unbind diagnostic information. The parameters with the given names are
125      * unbound, cancelling the effects of a previous call to bind_diagnostic().
126      * params is an array of OSSL_PARAMs. The values of the parameters are
127      * ignored. If a parameter is already unbound, there is no effect for that
128      * parameter but other parameters are still unbound.
129      *
130      * Returns 1 on success or 0 on failure.
131      */
132     int (*unbind_diagnostics)(OSSL_CC_DATA *ccdata,
133                               OSSL_PARAM *params);
134 
135     /*
136      * Returns the amount of additional data (above and beyond the data
137      * currently in flight) which can be sent in bytes. Returns 0 if no more
138      * data can be sent at this time. The return value of this method
139      * can vary as time passes.
140      */
141     uint64_t (*get_tx_allowance)(OSSL_CC_DATA *ccdata);
142 
143     /*
144      * Returns the time at which the return value of get_tx_allowance might be
145      * higher than its current value. This is not a guarantee and spurious
146      * wakeups are allowed. Returns ossl_time_infinite() if there is no current
147      * wakeup deadline.
148      */
149     OSSL_TIME (*get_wakeup_deadline)(OSSL_CC_DATA *ccdata);
150 
151     /*
152      * The On Data Sent event. num_bytes should be the size of the packet in
153      * bytes (or the aggregate size of multiple packets which have just been
154      * sent).
155      */
156     int (*on_data_sent)(OSSL_CC_DATA *ccdata,
157                         uint64_t num_bytes);
158 
159     /*
160      * The On Data Acked event. See OSSL_CC_ACK_INFO structure for details
161      * of the information to be passed.
162      */
163     int (*on_data_acked)(OSSL_CC_DATA *ccdata,
164                          const OSSL_CC_ACK_INFO *info);
165 
166     /*
167      * The On Data Lost event. See OSSL_CC_LOSS_INFO structure for details
168      * of the information to be passed.
169      *
170      * Note: When the ACKM determines that a set of multiple packets has been
171      * lost, it is useful for a congestion control algorithm to be able to
172      * process this as a single loss event rather than multiple loss events.
173      * Thus, calling this function may cause the congestion controller to defer
174      * state updates under the assumption that subsequent calls to
175      * on_data_lost() representing further lost packets in the same loss event
176      * may be forthcoming. Always call on_data_lost_finished() after one or more
177      * calls to on_data_lost().
178      */
179     int (*on_data_lost)(OSSL_CC_DATA *ccdata,
180                         const OSSL_CC_LOSS_INFO *info);
181 
182     /*
183      * To be called after a sequence of one or more on_data_lost() calls
184      * representing multiple packets in a single loss detection incident.
185      *
186      * Flags may be 0 or OSSL_CC_LOST_FLAG_PERSISTENT_CONGESTION.
187      */
188     int (*on_data_lost_finished)(OSSL_CC_DATA *ccdata, uint32_t flags);
189 
190     /*
191      * For use when a PN space is invalidated or a packet must otherwise be
192      * 'undone' for congestion control purposes without acting as a loss signal.
193      * Only the size of the packet is needed.
194      */
195     int (*on_data_invalidated)(OSSL_CC_DATA *ccdata,
196                                uint64_t num_bytes);
197 
198     /*
199      * Called from the ACKM when detecting an increased ECN-CE value in an ACK
200      * frame. This indicates congestion.
201      *
202      * Note that this differs from the RFC's conceptual segregation of the loss
203      * detection and congestion controller functions, as in our implementation
204      * the ACKM is responsible for detecting increases to ECN-CE and simply
205      * tells the congestion controller when ECN-triggered congestion has
206      * occurred. This allows a slightly more efficient implementation and
207      * narrower interface between the ACKM and CC.
208      */
209     int (*on_ecn)(OSSL_CC_DATA *ccdata,
210                   const OSSL_CC_ECN_INFO *info);
211 };
212 
213 extern const OSSL_CC_METHOD ossl_cc_dummy_method;
214 extern const OSSL_CC_METHOD ossl_cc_newreno_method;
215 
216 # endif
217 
218 #endif
219