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
|
---|