Home | History | Annotate | Line # | Download | only in internal
      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