Home | History | Annotate | Line # | Download | only in internal
      1 /*
      2  * Copyright 2022-2025 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/quic_predef.h"
     17 #include "internal/time.h"
     18 #include "internal/list.h"
     19 
     20 #ifndef OPENSSL_NO_QUIC
     21 
     22 OSSL_ACKM *ossl_ackm_new(OSSL_TIME (*now)(void *arg),
     23     void *now_arg,
     24     OSSL_STATM *statm,
     25     const OSSL_CC_METHOD *cc_method,
     26     OSSL_CC_DATA *cc_data, int is_server);
     27 void ossl_ackm_free(OSSL_ACKM *ackm);
     28 
     29 void ossl_ackm_set_loss_detection_deadline_callback(OSSL_ACKM *ackm,
     30     void (*fn)(OSSL_TIME deadline,
     31         void *arg),
     32     void *arg);
     33 
     34 void ossl_ackm_set_ack_deadline_callback(OSSL_ACKM *ackm,
     35     void (*fn)(OSSL_TIME deadline,
     36         int pkt_space,
     37         void *arg),
     38     void *arg);
     39 
     40 /*
     41  * Configures the RX-side maximum ACK delay. This is the maximum amount of time
     42  * the peer is allowed to delay sending an ACK frame after receiving an
     43  * ACK-eliciting packet. The peer communicates this value via a transport
     44  * parameter and it must be provided to the ACKM.
     45  */
     46 void ossl_ackm_set_rx_max_ack_delay(OSSL_ACKM *ackm, OSSL_TIME rx_max_ack_delay);
     47 
     48 /*
     49  * Configures the TX-side maximum ACK delay. This is the maximum amount of time
     50  * we are allowed to delay sending an ACK frame after receiving an ACK-eliciting
     51  * packet. Note that this cannot be changed after a connection is established as
     52  * it must be accurately reported in the transport parameters we send to our
     53  * peer.
     54  */
     55 void ossl_ackm_set_tx_max_ack_delay(OSSL_ACKM *ackm, OSSL_TIME tx_max_ack_delay);
     56 
     57 typedef struct ossl_ackm_tx_pkt_st OSSL_ACKM_TX_PKT;
     58 struct ossl_ackm_tx_pkt_st {
     59     /* The packet number of the transmitted packet. */
     60     QUIC_PN pkt_num;
     61 
     62     /* The number of bytes in the packet which was sent. */
     63     size_t num_bytes;
     64 
     65     /* The time at which the packet was sent. */
     66     OSSL_TIME time;
     67 
     68     /*
     69      * If the packet being described by this structure contains an ACK frame,
     70      * this must be set to the largest PN ACK'd by that frame.
     71      *
     72      * Otherwise, it should be set to QUIC_PN_INVALID.
     73      *
     74      * This is necessary to bound the number of PNs we have to keep track of on
     75      * the RX side (RFC 9000 s. 13.2.4). It allows older PN tracking information
     76      * on the RX side to be discarded.
     77      */
     78     QUIC_PN largest_acked;
     79 
     80     /*
     81      * One of the QUIC_PN_SPACE_* values. This qualifies the pkt_num field
     82      * into a packet number space.
     83      */
     84     unsigned int pkt_space : 2;
     85 
     86     /*
     87      * 1 if the packet is in flight. A packet is considered 'in flight' if it is
     88      * counted for purposes of congestion control and 'bytes in flight' counts.
     89      * Most packets are considered in flight. The only circumstance where a
     90      * numbered packet is not considered in flight is if it contains only ACK
     91      * frames (not even PADDING frames), as these frames can bypass CC.
     92      */
     93     unsigned int is_inflight : 1;
     94 
     95     /*
     96      * 1 if the packet has one or more ACK-eliciting frames.
     97      * Note that if this is set, is_inflight must be set.
     98      */
     99     unsigned int is_ack_eliciting : 1;
    100 
    101     /* 1 if the packet is a PTO probe. */
    102     unsigned int is_pto_probe : 1;
    103 
    104     /* 1 if the packet is an MTU probe. */
    105     unsigned int is_mtu_probe : 1;
    106 
    107     /* Callback called if frames in this packet are lost. arg is cb_arg. */
    108     void (*on_lost)(void *arg);
    109     /* Callback called if frames in this packet are acked. arg is cb_arg. */
    110     void (*on_acked)(void *arg);
    111     /*
    112      * Callback called if frames in this packet are neither acked nor lost. arg
    113      * is cb_arg.
    114      */
    115     void (*on_discarded)(void *arg);
    116     void *cb_arg;
    117 
    118     /*
    119      * (Internal use fields; must be zero-initialized.)
    120      *
    121      * Keep a TX history list, anext is used to manifest
    122      * a singly-linked list of newly-acknowledged packets, and lnext is used to
    123      * manifest a singly-linked list of newly lost packets.
    124      */
    125     OSSL_LIST_MEMBER(tx_history, OSSL_ACKM_TX_PKT);
    126 
    127     struct ossl_ackm_tx_pkt_st *anext;
    128     struct ossl_ackm_tx_pkt_st *lnext;
    129 };
    130 
    131 int ossl_ackm_on_tx_packet(OSSL_ACKM *ackm, OSSL_ACKM_TX_PKT *pkt);
    132 int ossl_ackm_on_rx_datagram(OSSL_ACKM *ackm, size_t num_bytes);
    133 
    134 #define OSSL_ACKM_ECN_NONE 0
    135 #define OSSL_ACKM_ECN_ECT1 1
    136 #define OSSL_ACKM_ECN_ECT0 2
    137 #define OSSL_ACKM_ECN_ECNCE 3
    138 
    139 typedef struct ossl_ackm_rx_pkt_st {
    140     /* The packet number of the received packet. */
    141     QUIC_PN pkt_num;
    142 
    143     /* The time at which the packet was received. */
    144     OSSL_TIME time;
    145 
    146     /*
    147      * One of the QUIC_PN_SPACE_* values. This qualifies the pkt_num field
    148      * into a packet number space.
    149      */
    150     unsigned int pkt_space : 2;
    151 
    152     /* 1 if the packet has one or more ACK-eliciting frames. */
    153     unsigned int is_ack_eliciting : 1;
    154 
    155     /*
    156      * One of the OSSL_ACKM_ECN_* values. This is the ECN labelling applied to
    157      * the received packet. If unknown, use OSSL_ACKM_ECN_NONE.
    158      */
    159     unsigned int ecn : 2;
    160 } OSSL_ACKM_RX_PKT;
    161 
    162 int ossl_ackm_on_rx_packet(OSSL_ACKM *ackm, const OSSL_ACKM_RX_PKT *pkt);
    163 
    164 int ossl_ackm_on_rx_ack_frame(OSSL_ACKM *ackm, const OSSL_QUIC_FRAME_ACK *ack,
    165     int pkt_space, OSSL_TIME rx_time);
    166 
    167 /*
    168  * Discards a PN space. This must be called for a PN space before freeing the
    169  * ACKM if you want in-flight packets to have their discarded callbacks called.
    170  * This should never be called in ordinary QUIC usage for the Application Data
    171  * PN space, but it may be called for the Application Data PN space prior to
    172  * freeing the ACKM to simplify teardown implementations.
    173  */
    174 int ossl_ackm_on_pkt_space_discarded(OSSL_ACKM *ackm, int pkt_space);
    175 
    176 int ossl_ackm_on_handshake_confirmed(OSSL_ACKM *ackm);
    177 int ossl_ackm_on_timeout(OSSL_ACKM *ackm);
    178 
    179 OSSL_TIME ossl_ackm_get_loss_detection_deadline(OSSL_ACKM *ackm);
    180 
    181 /*
    182  * Generates an ACK frame, regardless of whether the ACK manager thinks
    183  * one should currently be sent.
    184  *
    185  * This clears the flag returned by ossl_ackm_is_ack_desired and the deadline
    186  * returned by ossl_ackm_get_ack_deadline.
    187  */
    188 const OSSL_QUIC_FRAME_ACK *ossl_ackm_get_ack_frame(OSSL_ACKM *ackm,
    189     int pkt_space);
    190 
    191 /*
    192  * Returns the deadline after which an ACK frame should be generated by calling
    193  * ossl_ackm_get_ack_frame, or OSSL_TIME_INFINITY if no deadline is currently
    194  * applicable. If the deadline has already passed, this function may return that
    195  * deadline, or may return OSSL_TIME_ZERO.
    196  */
    197 OSSL_TIME ossl_ackm_get_ack_deadline(OSSL_ACKM *ackm, int pkt_space);
    198 
    199 /*
    200  * Returns 1 if the ACK manager thinks an ACK frame ought to be generated and
    201  * sent at this time. ossl_ackm_get_ack_frame will always provide an ACK frame
    202  * whether or not this returns 1, so it is suggested that you call this function
    203  * first to determine whether you need to generate an ACK frame.
    204  *
    205  * The return value of this function can change based on calls to
    206  * ossl_ackm_on_rx_packet and based on the passage of time (see
    207  * ossl_ackm_get_ack_deadline).
    208  */
    209 int ossl_ackm_is_ack_desired(OSSL_ACKM *ackm, int pkt_space);
    210 
    211 /*
    212  * Returns 1 if the given RX PN is 'processable'. A processable PN is one that
    213  * is not either
    214  *
    215  *   - duplicate, meaning that we have already been passed such a PN in a call
    216  *     to ossl_ackm_on_rx_packet; or
    217  *
    218  *   - written off, meaning that the PN is so old we have stopped tracking state
    219  *     for it (meaning that we cannot tell whether it is a duplicate and cannot
    220  *     process it safely).
    221  *
    222  * This should be called for a packet before attempting to process its contents.
    223  * Failure to do so may result in processing a duplicated packet in violation of
    224  * the RFC.
    225  *
    226  * The return value of this function transitions from 1 to 0 for a given PN once
    227  * that PN is passed to ossl_ackm_on_rx_packet, thus this function must be used
    228  * before calling ossl_ackm_on_rx_packet.
    229  */
    230 int ossl_ackm_is_rx_pn_processable(OSSL_ACKM *ackm, QUIC_PN pn, int pkt_space);
    231 
    232 typedef struct ossl_ackm_probe_info_st {
    233     /*
    234      * The following two probe request types are used only for anti-deadlock
    235      * purposes in relation to the anti-amplification logic, by generating
    236      * packets to buy ourselves more anti-amplification credit with the server
    237      * until a client address is verified. Note that like all Initial packets,
    238      * any Initial probes are padded.
    239      *
    240      * Note: The ACKM will only ever increase these by one at a time,
    241      * as only one probe packet should be generated for these cases.
    242      */
    243     uint32_t anti_deadlock_initial, anti_deadlock_handshake;
    244 
    245     /*
    246      * Send an ACK-eliciting packet for each count here.
    247      *
    248      * Note: The ACKM may increase this by either one or two for each probe
    249      * request, depending on how many probe packets it thinks should be
    250      * generated.
    251      */
    252     uint32_t pto[QUIC_PN_SPACE_NUM];
    253 } OSSL_ACKM_PROBE_INFO;
    254 
    255 /*
    256  * Returns a pointer to a structure counting any pending probe requests which
    257  * have been generated by the ACKM. The fields in the structure are incremented
    258  * by one every time the ACKM wants another probe of the given type to be sent.
    259  * If the ACKM thinks two packets should be generated for a probe, it will
    260  * increment the field twice.
    261  *
    262  * It is permissible for the caller to decrement or zero these fields to keep
    263  * track of when it has generated a probe as asked. The returned structure
    264  * has the same lifetime as the ACKM.
    265  *
    266  * This function should be called after calling e.g. ossl_ackm_on_timeout
    267  * to determine if any probe requests have been generated.
    268  */
    269 OSSL_ACKM_PROBE_INFO *ossl_ackm_get0_probe_request(OSSL_ACKM *ackm);
    270 
    271 int ossl_ackm_get_largest_unacked(OSSL_ACKM *ackm, int pkt_space, QUIC_PN *pn);
    272 
    273 /*
    274  * Forces the ACKM to consider a packet with the given PN in the given PN space
    275  * as having been pseudo-lost. The main reason to use this is during a Retry, to
    276  * force any resources sent in the first Initial packet to be resent.
    277  *
    278  * The lost callback is called for the packet, but the packet is NOT considered
    279  * lost for congestion control purposes. Thus this is not exactly the same as a
    280  * true loss situation.
    281  */
    282 int ossl_ackm_mark_packet_pseudo_lost(OSSL_ACKM *ackm,
    283     int pkt_space, QUIC_PN pn);
    284 
    285 /*
    286  * Returns the PTO duration as currently calculated. This is a quantity of time.
    287  * This duration is used in various parts of QUIC besides the ACKM.
    288  */
    289 OSSL_TIME ossl_ackm_get_pto_duration(OSSL_ACKM *ackm);
    290 
    291 /* Returns the largest acked PN in the given PN space. */
    292 QUIC_PN ossl_ackm_get_largest_acked(OSSL_ACKM *ackm, int pkt_space);
    293 
    294 #endif
    295 
    296 #endif
    297