xref: /openssl/include/internal/quic_ackm.h (revision fa4e92a7)
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 
18 typedef struct ossl_ackm_st OSSL_ACKM;
19 
20 OSSL_ACKM *ossl_ackm_new(OSSL_TIME (*now)(void *arg),
21                          void *now_arg,
22                          OSSL_STATM *statm,
23                          const OSSL_CC_METHOD *cc_method,
24                          OSSL_CC_DATA *cc_data);
25 void ossl_ackm_free(OSSL_ACKM *ackm);
26 
27 void ossl_ackm_set_loss_detection_deadline_callback(OSSL_ACKM *ackm,
28                                                     void (*fn)(OSSL_TIME deadline,
29                                                                void *arg),
30                                                     void *arg);
31 
32 void ossl_ackm_set_ack_deadline_callback(OSSL_ACKM *ackm,
33                                          void (*fn)(OSSL_TIME deadline,
34                                                     int pkt_space,
35                                                     void *arg),
36                                          void *arg);
37 
38 typedef struct ossl_ackm_tx_pkt_st {
39     /* The packet number of the transmitted packet. */
40     QUIC_PN pkt_num;
41 
42     /* The number of bytes in the packet which was sent. */
43     size_t num_bytes;
44 
45     /* The time at which the packet was sent. */
46     OSSL_TIME time;
47 
48     /*
49      * If the packet being described by this structure contains an ACK frame,
50      * this must be set to the largest PN ACK'd by that frame.
51      *
52      * Otherwise, it should be set to QUIC_PN_INVALID.
53      *
54      * This is necessary to bound the number of PNs we have to keep track of on
55      * the RX side (RFC 9000 s. 13.2.4). It allows older PN tracking information
56      * on the RX side to be discarded.
57      */
58     QUIC_PN largest_acked;
59 
60     /*
61      * One of the QUIC_PN_SPACE_* values. This qualifies the pkt_num field
62      * into a packet number space.
63      */
64     unsigned int pkt_space :2;
65 
66     /* 1 if the packet is in flight. */
67     unsigned int is_inflight :1;
68 
69     /* 1 if the packet has one or more ACK-eliciting frames. */
70     unsigned int is_ack_eliciting :1;
71 
72     /* 1 if the packet is a PTO probe. */
73     unsigned int is_pto_probe :1;
74 
75     /* 1 if the packet is an MTU probe. */
76     unsigned int is_mtu_probe :1;
77 
78     /* Callback called if frames in this packet are lost. arg is cb_arg. */
79     void (*on_lost)(void *arg);
80     /* Callback called if frames in this packet are acked. arg is cb_arg. */
81     void (*on_acked)(void *arg);
82     /*
83      * Callback called if frames in this packet are neither acked nor lost. arg
84      * is cb_arg.
85      */
86     void (*on_discarded)(void *arg);
87     void  *cb_arg;
88 
89     /*
90      * (Internal use fields; must be zero-initialized.)
91      *
92      * prev and next link us into the TX history list, anext is used to manifest
93      * a singly-linked list of newly-acknowledged packets, and lnext is used to
94      * manifest a singly-linked list of newly lost packets.
95      */
96     struct ossl_ackm_tx_pkt_st *prev;
97     struct ossl_ackm_tx_pkt_st *next;
98     struct ossl_ackm_tx_pkt_st *anext;
99     struct ossl_ackm_tx_pkt_st *lnext;
100 } OSSL_ACKM_TX_PKT;
101 
102 int ossl_ackm_on_tx_packet(OSSL_ACKM *ackm, OSSL_ACKM_TX_PKT *pkt);
103 int ossl_ackm_on_rx_datagram(OSSL_ACKM *ackm, size_t num_bytes);
104 
105 #define OSSL_ACKM_ECN_NONE      0
106 #define OSSL_ACKM_ECN_ECT1      1
107 #define OSSL_ACKM_ECN_ECT0      2
108 #define OSSL_ACKM_ECN_ECNCE     3
109 
110 typedef struct ossl_ackm_rx_pkt_st {
111     /* The packet number of the received packet. */
112     QUIC_PN pkt_num;
113 
114     /* The time at which the packet was received. */
115     OSSL_TIME time;
116 
117     /*
118      * One of the QUIC_PN_SPACE_* values. This qualifies the pkt_num field
119      * into a packet number space.
120      */
121     unsigned int pkt_space :2;
122 
123     /* 1 if the packet has one or more ACK-eliciting frames. */
124     unsigned int is_ack_eliciting :1;
125 
126     /*
127      * One of the OSSL_ACKM_ECN_* values. This is the ECN labelling applied to
128      * the received packet. If unknown, use OSSL_ACKM_ECN_NONE.
129      */
130     unsigned int ecn :2;
131 } OSSL_ACKM_RX_PKT;
132 
133 int ossl_ackm_on_rx_packet(OSSL_ACKM *ackm, const OSSL_ACKM_RX_PKT *pkt);
134 
135 int ossl_ackm_on_rx_ack_frame(OSSL_ACKM *ackm, const OSSL_QUIC_FRAME_ACK *ack,
136                               int pkt_space, OSSL_TIME rx_time);
137 
138 int ossl_ackm_on_pkt_space_discarded(OSSL_ACKM *ackm, int pkt_space);
139 int ossl_ackm_on_handshake_confirmed(OSSL_ACKM *ackm);
140 int ossl_ackm_on_timeout(OSSL_ACKM *ackm);
141 
142 OSSL_TIME ossl_ackm_get_loss_detection_deadline(OSSL_ACKM *ackm);
143 
144 /*
145  * Generates an ACK frame, regardless of whether the ACK manager thinks
146  * one should currently be sent.
147  *
148  * This clears the flag returned by ossl_ackm_is_ack_desired and the deadline
149  * returned by ossl_ackm_get_ack_deadline.
150  */
151 const OSSL_QUIC_FRAME_ACK *ossl_ackm_get_ack_frame(OSSL_ACKM *ackm,
152                                                    int pkt_space);
153 
154 /*
155  * Returns the deadline after which an ACK frame should be generated by calling
156  * ossl_ackm_get_ack_frame, or OSSL_TIME_INFINITY if no deadline is currently
157  * applicable. If the deadline has already passed, this function may return that
158  * deadline, or may return OSSL_TIME_ZERO.
159  */
160 OSSL_TIME ossl_ackm_get_ack_deadline(OSSL_ACKM *ackm, int pkt_space);
161 
162 /*
163  * Returns 1 if the ACK manager thinks an ACK frame ought to be generated and
164  * sent at this time. ossl_ackm_get_ack_frame will always provide an ACK frame
165  * whether or not this returns 1, so it is suggested that you call this function
166  * first to determine whether you need to generate an ACK frame.
167  *
168  * The return value of this function can change based on calls to
169  * ossl_ackm_on_rx_packet and based on the passage of time (see
170  * ossl_ackm_get_ack_deadline).
171  */
172 int ossl_ackm_is_ack_desired(OSSL_ACKM *ackm, int pkt_space);
173 
174 /*
175  * Returns 1 if the given RX PN is 'processable'. A processable PN is one that
176  * is not either
177  *
178  *   - duplicate, meaning that we have already been passed such a PN in a call
179  *     to ossl_ackm_on_rx_packet; or
180  *
181  *   - written off, meaning that the PN is so old we have stopped tracking state
182  *     for it (meaning that we cannot tell whether it is a duplicate and cannot
183  *     process it safely).
184  *
185  * This should be called for a packet before attempting to process its contents.
186  * Failure to do so may result in processing a duplicated packet in violation of
187  * the RFC.
188  *
189  * The return value of this function transitions from 1 to 0 for a given PN once
190  * that PN is passed to ossl_ackm_on_rx_packet, thus thus function must be used
191  * before calling ossl_ackm_on_rx_packet.
192  */
193 int ossl_ackm_is_rx_pn_processable(OSSL_ACKM *ackm, QUIC_PN pn, int pkt_space);
194 
195 typedef struct ossl_ackm_probe_info_st {
196     uint32_t handshake;
197     uint32_t padded_initial;
198     uint32_t pto[QUIC_PN_SPACE_NUM];
199 } OSSL_ACKM_PROBE_INFO;
200 
201 int ossl_ackm_get_probe_request(OSSL_ACKM *ackm, int clear,
202                                 OSSL_ACKM_PROBE_INFO *info);
203 
204 int ossl_ackm_get_largest_unacked(OSSL_ACKM *ackm, int pkt_space, QUIC_PN *pn);
205 
206 #endif
207