123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409 |
- /*
- * ngtcp2
- *
- * Copyright (c) 2018 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
- #ifndef NGTCP2_CC_H
- #define NGTCP2_CC_H
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif /* defined(HAVE_CONFIG_H) */
- #include <ngtcp2/ngtcp2.h>
- #include "ngtcp2_pktns_id.h"
- #define NGTCP2_LOSS_REDUCTION_FACTOR_BITS 1
- #define NGTCP2_PERSISTENT_CONGESTION_THRESHOLD 3
- typedef struct ngtcp2_log ngtcp2_log;
- typedef struct ngtcp2_conn_stat ngtcp2_conn_stat;
- typedef struct ngtcp2_rst ngtcp2_rst;
- /**
- * @struct
- *
- * :type:`ngtcp2_cc_pkt` is a convenient structure to include
- * acked/lost/sent packet.
- */
- typedef struct ngtcp2_cc_pkt {
- /**
- * :member:`pkt_num` is the packet number
- */
- int64_t pkt_num;
- /**
- * :member:`pktlen` is the length of packet.
- */
- size_t pktlen;
- /**
- * :member:`pktns_id` is the ID of packet number space which this
- * packet belongs to.
- */
- ngtcp2_pktns_id pktns_id;
- /**
- * :member:`sent_ts` is the timestamp when packet is sent.
- */
- ngtcp2_tstamp sent_ts;
- /**
- * :member:`lost` is the number of bytes lost when this packet was
- * sent.
- */
- uint64_t lost;
- /**
- * :member:`tx_in_flight` is the bytes in flight when this packet
- * was sent.
- */
- uint64_t tx_in_flight;
- /**
- * :member:`is_app_limited` is nonzero if the connection is
- * app-limited when this packet was sent.
- */
- int is_app_limited;
- } ngtcp2_cc_pkt;
- /**
- * @struct
- *
- * :type:`ngtcp2_cc_ack` is a convenient structure which stores
- * acknowledged and lost bytes.
- */
- typedef struct ngtcp2_cc_ack {
- /**
- * :member:`prior_bytes_in_flight` is the in-flight bytes before
- * processing this ACK.
- */
- uint64_t prior_bytes_in_flight;
- /**
- * :member:`bytes_delivered` is the number of bytes acknowledged.
- */
- uint64_t bytes_delivered;
- /**
- * :member:`bytes_lost` is the number of bytes declared lost.
- */
- uint64_t bytes_lost;
- /**
- * :member:`pkt_delivered` is the cumulative acknowledged bytes when
- * the last packet acknowledged by this ACK was sent.
- */
- uint64_t pkt_delivered;
- /**
- * :member:`largest_pkt_sent_ts` is the time when the largest
- * acknowledged packet was sent. It is UINT64_MAX if it is unknown.
- */
- ngtcp2_tstamp largest_pkt_sent_ts;
- /**
- * :member:`rtt` is the RTT sample. It is UINT64_MAX if no RTT
- * sample is available.
- */
- ngtcp2_duration rtt;
- } ngtcp2_cc_ack;
- typedef struct ngtcp2_cc ngtcp2_cc;
- /**
- * @functypedef
- *
- * :type:`ngtcp2_cc_on_pkt_acked` is a callback function which is
- * called with an acknowledged packet.
- */
- typedef void (*ngtcp2_cc_on_pkt_acked)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- const ngtcp2_cc_pkt *pkt,
- ngtcp2_tstamp ts);
- /**
- * @functypedef
- *
- * :type:`ngtcp2_cc_on_pkt_lost` is a callback function which is
- * called with a lost packet.
- */
- typedef void (*ngtcp2_cc_on_pkt_lost)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- const ngtcp2_cc_pkt *pkt,
- ngtcp2_tstamp ts);
- /**
- * @functypedef
- *
- * :type:`ngtcp2_cc_congestion_event` is a callback function which is
- * called when congestion event happens (e.g., when packet is lost).
- * |bytes_lost| is the number of bytes lost in this congestion event.
- */
- typedef void (*ngtcp2_cc_congestion_event)(ngtcp2_cc *cc,
- ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp sent_ts,
- uint64_t bytes_lost,
- ngtcp2_tstamp ts);
- /**
- * @functypedef
- *
- * :type:`ngtcp2_cc_on_spurious_congestion` is a callback function
- * which is called when a spurious congestion is detected.
- */
- typedef void (*ngtcp2_cc_on_spurious_congestion)(ngtcp2_cc *cc,
- ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts);
- /**
- * @functypedef
- *
- * :type:`ngtcp2_cc_on_persistent_congestion` is a callback function
- * which is called when persistent congestion is established.
- */
- typedef void (*ngtcp2_cc_on_persistent_congestion)(ngtcp2_cc *cc,
- ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts);
- /**
- * @functypedef
- *
- * :type:`ngtcp2_cc_on_ack_recv` is a callback function which is
- * called when an acknowledgement is received.
- */
- typedef void (*ngtcp2_cc_on_ack_recv)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- const ngtcp2_cc_ack *ack,
- ngtcp2_tstamp ts);
- /**
- * @functypedef
- *
- * :type:`ngtcp2_cc_on_pkt_sent` is a callback function which is
- * called when an ack-eliciting packet is sent.
- */
- typedef void (*ngtcp2_cc_on_pkt_sent)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- const ngtcp2_cc_pkt *pkt);
- /**
- * @functypedef
- *
- * :type:`ngtcp2_cc_new_rtt_sample` is a callback function which is
- * called when new RTT sample is obtained.
- */
- typedef void (*ngtcp2_cc_new_rtt_sample)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts);
- /**
- * @functypedef
- *
- * :type:`ngtcp2_cc_reset` is a callback function which is called when
- * congestion state must be reset.
- */
- typedef void (*ngtcp2_cc_reset)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts);
- /**
- * @enum
- *
- * :type:`ngtcp2_cc_event_type` defines congestion control events.
- */
- typedef enum ngtcp2_cc_event_type {
- /**
- * :enum:`NGTCP2_CC_EVENT_TX_START` occurs when ack-eliciting packet
- * is sent and no other ack-eliciting packet is present.
- */
- NGTCP2_CC_EVENT_TYPE_TX_START
- } ngtcp2_cc_event_type;
- /**
- * @functypedef
- *
- * :type:`ngtcp2_cc_event` is a callback function which is called when
- * a specific event happens.
- */
- typedef void (*ngtcp2_cc_event)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- ngtcp2_cc_event_type event, ngtcp2_tstamp ts);
- /**
- * @struct
- *
- * :type:`ngtcp2_cc` is congestion control algorithm interface shared
- * by implementations. All callback functions are optional.
- */
- typedef struct ngtcp2_cc {
- /**
- * :member:`log` is ngtcp2 library internal logger.
- */
- ngtcp2_log *log;
- /**
- * :member:`on_pkt_acked` is a callback function which is called
- * when a packet is acknowledged.
- */
- ngtcp2_cc_on_pkt_acked on_pkt_acked;
- /**
- * :member:`on_pkt_lost` is a callback function which is called when
- * a packet is lost.
- */
- ngtcp2_cc_on_pkt_lost on_pkt_lost;
- /**
- * :member:`congestion_event` is a callback function which is called
- * when congestion event happens (.e.g, packet is lost).
- */
- ngtcp2_cc_congestion_event congestion_event;
- /**
- * :member:`on_spurious_congestion` is a callback function which is
- * called when a spurious congestion is detected.
- */
- ngtcp2_cc_on_spurious_congestion on_spurious_congestion;
- /**
- * :member:`on_persistent_congestion` is a callback function which
- * is called when persistent congestion is established.
- */
- ngtcp2_cc_on_persistent_congestion on_persistent_congestion;
- /**
- * :member:`on_ack_recv` is a callback function which is called when
- * an acknowledgement is received.
- */
- ngtcp2_cc_on_ack_recv on_ack_recv;
- /**
- * :member:`on_pkt_sent` is a callback function which is called when
- * ack-eliciting packet is sent.
- */
- ngtcp2_cc_on_pkt_sent on_pkt_sent;
- /**
- * :member:`new_rtt_sample` is a callback function which is called
- * when new RTT sample is obtained.
- */
- ngtcp2_cc_new_rtt_sample new_rtt_sample;
- /**
- * :member:`reset` is a callback function which is called when
- * congestion control state must be reset.
- */
- ngtcp2_cc_reset reset;
- /**
- * :member:`event` is a callback function which is called when a
- * specific event happens.
- */
- ngtcp2_cc_event event;
- } ngtcp2_cc;
- /*
- * ngtcp2_cc_compute_initcwnd computes initial cwnd.
- */
- uint64_t ngtcp2_cc_compute_initcwnd(size_t max_packet_size);
- ngtcp2_cc_pkt *ngtcp2_cc_pkt_init(ngtcp2_cc_pkt *pkt, int64_t pkt_num,
- size_t pktlen, ngtcp2_pktns_id pktns_id,
- ngtcp2_tstamp sent_ts, uint64_t lost,
- uint64_t tx_in_flight, int is_app_limited);
- /* ngtcp2_cc_reno is the RENO congestion controller. */
- typedef struct ngtcp2_cc_reno {
- ngtcp2_cc cc;
- uint64_t pending_add;
- } ngtcp2_cc_reno;
- void ngtcp2_cc_reno_init(ngtcp2_cc_reno *reno, ngtcp2_log *log);
- void ngtcp2_cc_reno_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts);
- void ngtcp2_cc_reno_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp sent_ts,
- uint64_t bytes_lost, ngtcp2_tstamp ts);
- void ngtcp2_cc_reno_cc_on_persistent_congestion(ngtcp2_cc *cc,
- ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts);
- void ngtcp2_cc_reno_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts);
- typedef enum ngtcp2_cubic_state {
- /* NGTCP2_CUBIC_STATE_INITIAL is the state where CUBIC is in slow
- start phase, or congestion avoidance phase before congestion
- events occur. */
- NGTCP2_CUBIC_STATE_INITIAL,
- /* NGTCP2_CUBIC_STATE_RECOVERY is the state that a connection is in
- recovery period. */
- NGTCP2_CUBIC_STATE_RECOVERY,
- /* NGTCP2_CUBIC_STATE_CONGESTION_AVOIDANCE is the state where CUBIC
- is in congestion avoidance phase after recovery period ends. */
- NGTCP2_CUBIC_STATE_CONGESTION_AVOIDANCE,
- } ngtcp2_cubic_state;
- typedef struct ngtcp2_cubic_vars {
- uint64_t cwnd_prior;
- uint64_t w_max;
- ngtcp2_duration k;
- ngtcp2_tstamp epoch_start;
- uint64_t w_est;
- ngtcp2_cubic_state state;
- /* app_limited_start_ts is the timestamp where app limited period
- started. */
- ngtcp2_tstamp app_limited_start_ts;
- /* app_limited_duration is the cumulative duration where a
- connection is under app limited when ACK is received. */
- ngtcp2_duration app_limited_duration;
- uint64_t pending_bytes_delivered;
- uint64_t pending_est_bytes_delivered;
- } ngtcp2_cubic_vars;
- /* ngtcp2_cc_cubic is CUBIC congestion controller. */
- typedef struct ngtcp2_cc_cubic {
- ngtcp2_cc cc;
- ngtcp2_rst *rst;
- /* current is a set of variables that are currently in effect. */
- ngtcp2_cubic_vars current;
- /* undo stores the congestion state when a congestion event occurs
- in order to restore the state when it turns out that the event is
- spurious. */
- struct {
- ngtcp2_cubic_vars v;
- uint64_t cwnd;
- uint64_t ssthresh;
- } undo;
- /* HyStart++ variables */
- struct {
- ngtcp2_duration current_round_min_rtt;
- ngtcp2_duration last_round_min_rtt;
- ngtcp2_duration curr_rtt;
- size_t rtt_sample_count;
- ngtcp2_duration css_baseline_min_rtt;
- size_t css_round;
- } hs;
- uint64_t next_round_delivered;
- } ngtcp2_cc_cubic;
- void ngtcp2_cc_cubic_init(ngtcp2_cc_cubic *cc, ngtcp2_log *log,
- ngtcp2_rst *rst);
- void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts);
- void ngtcp2_cc_cubic_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp sent_ts,
- uint64_t bytes_lost, ngtcp2_tstamp ts);
- void ngtcp2_cc_cubic_cc_on_spurious_congestion(ngtcp2_cc *ccx,
- ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts);
- void ngtcp2_cc_cubic_cc_on_persistent_congestion(ngtcp2_cc *cc,
- ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts);
- void ngtcp2_cc_cubic_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts);
- uint64_t ngtcp2_cbrt(uint64_t n);
- #endif /* !defined(NGTCP2_CC_H) */
|