From: Jan Doskočil Date: Mon, 20 Oct 2025 08:36:48 +0000 (+0200) Subject: libngtcp2: update embedded library to v1.17.0 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=35d6dcacbbeede00a5ae82a6fd9955fdd2080722;p=thirdparty%2Fknot-dns.git libngtcp2: update embedded library to v1.17.0 --- diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_addr.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_addr.c index 1fb273d494..a028a8a8f4 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_addr.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_addr.c @@ -58,14 +58,12 @@ int ngtcp2_sockaddr_eq(const ngtcp2_sockaddr *a, const ngtcp2_sockaddr *b) { switch (a->sa_family) { case NGTCP2_AF_INET: { - const ngtcp2_sockaddr_in *ai = (const ngtcp2_sockaddr_in *)(void *)a, - *bi = (const ngtcp2_sockaddr_in *)(void *)b; + const ngtcp2_sockaddr_in *ai = (void *)a, *bi = (void *)b; return ai->sin_port == bi->sin_port && memcmp(&ai->sin_addr, &bi->sin_addr, sizeof(ai->sin_addr)) == 0; } case NGTCP2_AF_INET6: { - const ngtcp2_sockaddr_in6 *ai = (const ngtcp2_sockaddr_in6 *)(void *)a, - *bi = (const ngtcp2_sockaddr_in6 *)(void *)b; + const ngtcp2_sockaddr_in6 *ai = (void *)a, *bi = (void *)b; return ai->sin6_port == bi->sin6_port && memcmp(&ai->sin6_addr, &bi->sin6_addr, sizeof(ai->sin6_addr)) == 0; } @@ -89,8 +87,7 @@ uint32_t ngtcp2_addr_cmp(const ngtcp2_addr *aa, const ngtcp2_addr *bb) { switch (a->sa_family) { case NGTCP2_AF_INET: { - const ngtcp2_sockaddr_in *ai = (const ngtcp2_sockaddr_in *)(void *)a, - *bi = (const ngtcp2_sockaddr_in *)(void *)b; + const ngtcp2_sockaddr_in *ai = (void *)a, *bi = (void *)b; if (memcmp(&ai->sin_addr, &bi->sin_addr, sizeof(ai->sin_addr))) { flags |= NGTCP2_ADDR_CMP_FLAG_ADDR; } @@ -100,8 +97,7 @@ uint32_t ngtcp2_addr_cmp(const ngtcp2_addr *aa, const ngtcp2_addr *bb) { return flags; } case NGTCP2_AF_INET6: { - const ngtcp2_sockaddr_in6 *ai = (const ngtcp2_sockaddr_in6 *)(void *)a, - *bi = (const ngtcp2_sockaddr_in6 *)(void *)b; + const ngtcp2_sockaddr_in6 *ai = (void *)a, *bi = (void *)b; if (memcmp(&ai->sin6_addr, &bi->sin6_addr, sizeof(ai->sin6_addr))) { flags |= NGTCP2_ADDR_CMP_FLAG_ADDR; } diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_balloc.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_balloc.c index 4a6797689f..cb865c5cef 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_balloc.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_balloc.c @@ -71,7 +71,7 @@ int ngtcp2_balloc_get(ngtcp2_balloc *balloc, void **pbuf, size_t n) { return NGTCP2_ERR_NOMEM; } - hd = (ngtcp2_memblock_hd *)(void *)p; + hd = (void *)p; hd->next = balloc->head; balloc->head = hd; ngtcp2_buf_init( diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.c index 2aa5d6fcad..62e6b2f125 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.c @@ -190,20 +190,20 @@ static int bbr_is_reno_coexistence_probe_time(ngtcp2_cc_bbr *bbr, static uint64_t bbr_target_inflight(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat); -static int bbr_is_inflight_too_high(ngtcp2_cc_bbr *bbr); +static int bbr_is_inflight_too_high(ngtcp2_cc_bbr *bbr, const ngtcp2_rs *rs); static void bbr_handle_inflight_too_high(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); + const ngtcp2_rs *rs, ngtcp2_tstamp ts); static void bbr_note_loss(ngtcp2_cc_bbr *bbr); static void bbr_handle_lost_packet(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts); -static uint64_t -bbr_inflight_longterm_from_lost_packet(ngtcp2_cc_bbr *bbr, - const ngtcp2_cc_pkt *pkt); +static uint64_t bbr_inflight_at_loss(ngtcp2_cc_bbr *bbr, + const ngtcp2_cc_pkt *pkt, + const ngtcp2_rs *rs); static void bbr_update_min_rtt(ngtcp2_cc_bbr *bbr, const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); @@ -334,8 +334,6 @@ static void bbr_on_init(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, bbr->max_inflight = 0; - bbr->congestion_recovery_start_ts = UINT64_MAX; - bbr->bdp = 0; } @@ -393,7 +391,7 @@ static void bbr_check_startup_high_loss(ngtcp2_cc_bbr *bbr) { if (bbr->full_bw_reached || bbr->loss_events_in_round <= 6 || (bbr->in_loss_recovery && bbr->round_count <= bbr->round_count_at_recovery) || - !bbr_is_inflight_too_high(bbr)) { + !bbr_is_inflight_too_high(bbr, &bbr->rst->rs)) { return; } @@ -403,11 +401,12 @@ static void bbr_check_startup_high_loss(ngtcp2_cc_bbr *bbr) { } static void bbr_init_pacing_rate(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { - cstat->pacing_interval_m = + cstat->pacing_interval_m = ngtcp2_max_uint64( ((cstat->first_rtt_sample_ts == UINT64_MAX ? NGTCP2_MILLISECONDS : cstat->smoothed_rtt) << 10) * - 100 / NGTCP2_BBR_STARTUP_PACING_GAIN_H / bbr->initial_cwnd; + 100 / NGTCP2_BBR_STARTUP_PACING_GAIN_H / bbr->initial_cwnd, + 1); } static void bbr_set_pacing_rate_with_gain(ngtcp2_cc_bbr *bbr, @@ -568,7 +567,8 @@ static void bbr_update_max_bw(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack) { bbr_update_round(bbr, ack); - if (cstat->delivery_rate_sec >= bbr->max_bw || !bbr->rst->rs.is_app_limited) { + if (cstat->delivery_rate_sec && (cstat->delivery_rate_sec >= bbr->max_bw || + !bbr->rst->rs.is_app_limited)) { ngtcp2_window_filter_update(&bbr->max_bw_filter, cstat->delivery_rate_sec, bbr->cycle_count); @@ -880,7 +880,7 @@ static void bbr_adapt_longterm_model(ngtcp2_cc_bbr *bbr, } } - if (!bbr_is_inflight_too_high(bbr)) { + if (!bbr_is_inflight_too_high(bbr, &bbr->rst->rs)) { if (bbr->inflight_longterm == UINT64_MAX) { return; } @@ -926,17 +926,16 @@ static uint64_t bbr_target_inflight(ngtcp2_cc_bbr *bbr, return ngtcp2_min_uint64(bbr->bdp, cstat->cwnd); } -static int bbr_is_inflight_too_high(ngtcp2_cc_bbr *bbr) { - const ngtcp2_rs *rs = &bbr->rst->rs; +static int bbr_is_inflight_too_high(ngtcp2_cc_bbr *bbr, const ngtcp2_rs *rs) { + (void)bbr; return rs->lost * NGTCP2_BBR_LOSS_THRESH_DENOM > rs->tx_in_flight * NGTCP2_BBR_LOSS_THRESH_NUMER; } static void bbr_handle_inflight_too_high(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + const ngtcp2_rs *rs, ngtcp2_tstamp ts) { - const ngtcp2_rs *rs = &bbr->rst->rs; - bbr->bw_probe_samples = 0; if (!rs->is_app_limited) { @@ -960,7 +959,7 @@ static void bbr_note_loss(ngtcp2_cc_bbr *bbr) { static void bbr_handle_lost_packet(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts) { - ngtcp2_rs *rs = &bbr->rst->rs; + ngtcp2_rs rs = {0}; bbr_note_loss(bbr); @@ -968,22 +967,21 @@ static void bbr_handle_lost_packet(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, return; } - rs->tx_in_flight = pkt->tx_in_flight; + rs.tx_in_flight = pkt->tx_in_flight; assert(bbr->rst->lost >= pkt->lost); - rs->lost = bbr->rst->lost - pkt->lost; - rs->is_app_limited = pkt->is_app_limited; + rs.lost = bbr->rst->lost - pkt->lost; + rs.is_app_limited = pkt->is_app_limited; - if (bbr_is_inflight_too_high(bbr)) { - rs->tx_in_flight = bbr_inflight_longterm_from_lost_packet(bbr, pkt); + if (bbr_is_inflight_too_high(bbr, &rs)) { + rs.tx_in_flight = bbr_inflight_at_loss(bbr, pkt, &rs); - bbr_handle_inflight_too_high(bbr, cstat, ts); + bbr_handle_inflight_too_high(bbr, cstat, &rs, ts); } } -static uint64_t -bbr_inflight_longterm_from_lost_packet(ngtcp2_cc_bbr *bbr, - const ngtcp2_cc_pkt *pkt) { - ngtcp2_rs *rs = &bbr->rst->rs; +static uint64_t bbr_inflight_at_loss(ngtcp2_cc_bbr *bbr, + const ngtcp2_cc_pkt *pkt, + const ngtcp2_rs *rs) { uint64_t inflight_prev, lost_prev, lost_prefix; (void)bbr; @@ -1280,28 +1278,15 @@ static int in_congestion_recovery(const ngtcp2_conn_stat *cstat, static void bbr_handle_recovery(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack) { - if (bbr->in_loss_recovery) { - if (ack->largest_pkt_sent_ts != UINT64_MAX && - !in_congestion_recovery(cstat, ack->largest_pkt_sent_ts)) { - bbr->in_loss_recovery = 0; - bbr->round_count_at_recovery = UINT64_MAX; - bbr_restore_cwnd(bbr, cstat); - } - + if (!bbr->in_loss_recovery) { return; } - if (bbr->congestion_recovery_start_ts != UINT64_MAX) { - bbr->in_loss_recovery = 1; - bbr->round_count_at_recovery = - bbr->round_start ? bbr->round_count : bbr->round_count + 1; - bbr_save_cwnd(bbr, cstat); - cstat->cwnd = - cstat->bytes_in_flight + - ngtcp2_max_uint64(ack->bytes_delivered, cstat->max_tx_udp_payload_size); - - cstat->congestion_recovery_start_ts = bbr->congestion_recovery_start_ts; - bbr->congestion_recovery_start_ts = UINT64_MAX; + if (ack->largest_pkt_sent_ts != UINT64_MAX && + !in_congestion_recovery(cstat, ack->largest_pkt_sent_ts)) { + bbr->in_loss_recovery = 0; + bbr->round_count_at_recovery = UINT64_MAX; + bbr_restore_cwnd(bbr, cstat); } } @@ -1313,18 +1298,24 @@ static void bbr_cc_on_pkt_lost(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, } static void bbr_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp sent_ts, uint64_t bytes_lost, + ngtcp2_tstamp sent_ts, + const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { ngtcp2_cc_bbr *bbr = ngtcp2_struct_of(cc, ngtcp2_cc_bbr, cc); - (void)bytes_lost; - if (bbr->in_loss_recovery || - bbr->congestion_recovery_start_ts != UINT64_MAX || - in_congestion_recovery(cstat, sent_ts)) { + if (bbr->in_loss_recovery || in_congestion_recovery(cstat, sent_ts)) { return; } - bbr->congestion_recovery_start_ts = ts; + bbr->in_loss_recovery = 1; + bbr->round_count_at_recovery = + bbr->round_start ? bbr->round_count : bbr->round_count + 1; + bbr_save_cwnd(bbr, cstat); + cstat->cwnd = + cstat->bytes_in_flight + + ngtcp2_max_uint64(ack->bytes_delivered, cstat->max_tx_udp_payload_size); + + cstat->congestion_recovery_start_ts = ts; } static void bbr_cc_on_spurious_congestion(ngtcp2_cc *cc, @@ -1333,7 +1324,6 @@ static void bbr_cc_on_spurious_congestion(ngtcp2_cc *cc, ngtcp2_cc_bbr *bbr = ngtcp2_struct_of(cc, ngtcp2_cc_bbr, cc); (void)ts; - bbr->congestion_recovery_start_ts = UINT64_MAX; cstat->congestion_recovery_start_ts = UINT64_MAX; if (bbr->in_loss_recovery) { @@ -1350,7 +1340,6 @@ static void bbr_cc_on_persistent_congestion(ngtcp2_cc *cc, (void)ts; cstat->congestion_recovery_start_ts = UINT64_MAX; - bbr->congestion_recovery_start_ts = UINT64_MAX; bbr->in_loss_recovery = 0; bbr->round_count_at_recovery = UINT64_MAX; @@ -1365,6 +1354,11 @@ static void bbr_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_cc_bbr *bbr = ngtcp2_struct_of(cc, ngtcp2_cc_bbr, cc); bbr_handle_recovery(bbr, cstat, ack); + + if (ack->bytes_delivered == 0) { + return; + } + bbr_update_on_ack(bbr, cstat, ack, ts); } diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.h index 0499924f58..f0d529639c 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.h @@ -130,7 +130,6 @@ typedef struct ngtcp2_cc_bbr { int in_loss_recovery; uint64_t round_count_at_recovery; uint64_t max_inflight; - ngtcp2_tstamp congestion_recovery_start_ts; uint64_t bdp; } ngtcp2_cc_bbr; diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.c index 3fffef5448..f8e420ed7d 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.c @@ -41,6 +41,40 @@ uint64_t ngtcp2_cc_compute_initcwnd(size_t max_udp_payload_size) { return ngtcp2_min_uint64(10 * max_udp_payload_size, n); } +/* 1.25 is the under-utilization avoidance factor described in + https://datatracker.ietf.org/doc/html/rfc9002#section-7.7 */ +#define NGTCP2_CC_PACING_GAIN_H 125 + +static void init_pacing_rate(ngtcp2_conn_stat *cstat) { + assert(cstat->cwnd); + + cstat->pacing_interval_m = ngtcp2_max_uint64( + (NGTCP2_MILLISECONDS << 10) * 100 / NGTCP2_CC_PACING_GAIN_H / cstat->cwnd, + 1); + cstat->send_quantum = 10 * cstat->max_tx_udp_payload_size; +} + +static void set_pacing_rate(ngtcp2_conn_stat *cstat) { + size_t send_quantum = 64 * 1024; + + assert(cstat->cwnd); + + cstat->pacing_interval_m = + ((cstat->first_rtt_sample_ts == UINT64_MAX ? NGTCP2_MILLISECONDS + : cstat->smoothed_rtt) + << 10) * + 100 / NGTCP2_CC_PACING_GAIN_H / cstat->cwnd; + + cstat->pacing_interval_m = ngtcp2_max_uint64(cstat->pacing_interval_m, 1); + + send_quantum = + ngtcp2_min_size(send_quantum, (size_t)((NGTCP2_MILLISECONDS << 10) / + cstat->pacing_interval_m)); + + cstat->send_quantum = + ngtcp2_max_size(send_quantum, 10 * cstat->max_tx_udp_payload_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, @@ -56,9 +90,14 @@ ngtcp2_cc_pkt *ngtcp2_cc_pkt_init(ngtcp2_cc_pkt *pkt, int64_t pkt_num, return pkt; } -static void reno_cc_reset(ngtcp2_cc_reno *reno) { reno->pending_add = 0; } +static void reno_cc_reset(ngtcp2_cc_reno *reno, ngtcp2_conn_stat *cstat) { + reno->pending_add = 0; -void ngtcp2_cc_reno_init(ngtcp2_cc_reno *reno, ngtcp2_log *log) { + init_pacing_rate(cstat); +} + +void ngtcp2_cc_reno_init(ngtcp2_cc_reno *reno, ngtcp2_log *log, + ngtcp2_conn_stat *cstat) { *reno = (ngtcp2_cc_reno){ .cc = { @@ -70,7 +109,7 @@ void ngtcp2_cc_reno_init(ngtcp2_cc_reno *reno, ngtcp2_log *log) { }, }; - reno_cc_reset(reno); + reno_cc_reset(reno, cstat); } static int in_congestion_recovery(const ngtcp2_conn_stat *cstat, @@ -92,6 +131,9 @@ void ngtcp2_cc_reno_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, if (cstat->cwnd < cstat->ssthresh) { cstat->cwnd += pkt->pktlen; + + set_pacing_rate(cstat); + ngtcp2_log_infof(reno->cc.log, NGTCP2_LOG_EVENT_CCA, "pkn=%" PRId64 " acked, slow start cwnd=%" PRIu64, pkt->pkt_num, cstat->cwnd); @@ -102,14 +144,17 @@ void ngtcp2_cc_reno_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, reno->pending_add = m % cstat->cwnd; cstat->cwnd += m / cstat->cwnd; + + set_pacing_rate(cstat); } 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) { + const ngtcp2_cc_ack *ack, + ngtcp2_tstamp ts) { ngtcp2_cc_reno *reno = ngtcp2_struct_of(cc, ngtcp2_cc_reno, cc); uint64_t min_cwnd; - (void)bytes_lost; + (void)ack; if (in_congestion_recovery(cstat, sent_ts)) { return; @@ -123,6 +168,8 @@ void ngtcp2_cc_reno_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, reno->pending_add = 0; + set_pacing_rate(cstat); + ngtcp2_log_infof(reno->cc.log, NGTCP2_LOG_EVENT_CCA, "reduce cwnd because of packet loss cwnd=%" PRIu64, cstat->cwnd); @@ -136,15 +183,16 @@ void ngtcp2_cc_reno_cc_on_persistent_congestion(ngtcp2_cc *cc, cstat->cwnd = 2 * cstat->max_tx_udp_payload_size; cstat->congestion_recovery_start_ts = UINT64_MAX; + + set_pacing_rate(cstat); } void ngtcp2_cc_reno_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { ngtcp2_cc_reno *reno = ngtcp2_struct_of(cc, ngtcp2_cc_reno, cc); - (void)cstat; (void)ts; - reno_cc_reset(reno); + reno_cc_reset(reno, cstat); } static void cubic_vars_reset(ngtcp2_cubic_vars *v) { @@ -156,11 +204,11 @@ static void cubic_vars_reset(ngtcp2_cubic_vars *v) { v->app_limited_start_ts = UINT64_MAX; v->app_limited_duration = 0; - v->pending_bytes_delivered = 0; - v->pending_est_bytes_delivered = 0; + v->pending_bytes_acked = 0; + v->pending_est_bytes_acked = 0; } -static void cubic_cc_reset(ngtcp2_cc_cubic *cubic) { +static void cubic_cc_reset(ngtcp2_cc_cubic *cubic, ngtcp2_conn_stat *cstat) { cubic_vars_reset(&cubic->current); cubic_vars_reset(&cubic->undo.v); cubic->undo.cwnd = 0; @@ -174,10 +222,12 @@ static void cubic_cc_reset(ngtcp2_cc_cubic *cubic) { cubic->hs.css_round = 0; cubic->next_round_delivered = 0; + + init_pacing_rate(cstat); } void ngtcp2_cc_cubic_init(ngtcp2_cc_cubic *cubic, ngtcp2_log *log, - ngtcp2_rst *rst) { + ngtcp2_conn_stat *cstat, ngtcp2_rst *rst) { *cubic = (ngtcp2_cc_cubic){ .cc = { @@ -191,7 +241,7 @@ void ngtcp2_cc_cubic_init(ngtcp2_cc_cubic *cubic, ngtcp2_log *log, .rst = rst, }; - cubic_cc_reset(cubic); + cubic_cc_reset(cubic, cstat); } uint64_t ngtcp2_cbrt(uint64_t n) { @@ -266,12 +316,14 @@ void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); uint64_t w_cubic, w_cubic_next; uint64_t target, m; + uint64_t bytes_acked; ngtcp2_duration rtt_thresh; int round_start; int is_app_limited = cubic->rst->rs.is_app_limited && !cubic->rst->is_cwnd_limited; - if (in_congestion_recovery(cstat, ack->largest_pkt_sent_ts)) { + if (ack->bytes_delivered == 0 || + in_congestion_recovery(cstat, ack->largest_pkt_sent_ts)) { return; } @@ -291,6 +343,8 @@ void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, cstat->cwnd += ack->bytes_delivered; } + set_pacing_rate(cstat); + ngtcp2_log_infof(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, "%" PRIu64 " bytes acked, slow start cwnd=%" PRIu64, ack->bytes_delivered, cstat->cwnd); @@ -379,25 +433,36 @@ void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, target = w_cubic_next; } - m = ack->bytes_delivered * cstat->max_tx_udp_payload_size + - cubic->current.pending_est_bytes_delivered; - cubic->current.pending_est_bytes_delivered = m % cstat->cwnd; + bytes_acked = ack->bytes_delivered * cstat->max_tx_udp_payload_size; + m = (bytes_acked + cubic->current.pending_est_bytes_acked) / cstat->cwnd; + + cubic->current.pending_est_bytes_acked += bytes_acked; + cubic->current.pending_est_bytes_acked -= m * cstat->cwnd; + + assert(cubic->current.pending_est_bytes_acked < cstat->cwnd); if (cubic->current.w_est < cubic->current.cwnd_prior) { - cubic->current.w_est += m * 9 / 17 / cstat->cwnd; + cubic->current.w_est += m * 9 / 17; } else { - cubic->current.w_est += m / cstat->cwnd; + cubic->current.w_est += m; } if (cubic->current.w_est > w_cubic) { cstat->cwnd = cubic->current.w_est; } else { - m = (target - cstat->cwnd) * cstat->max_tx_udp_payload_size + - cubic->current.pending_bytes_delivered; - cubic->current.pending_bytes_delivered = m % cstat->cwnd; - cstat->cwnd += m / cstat->cwnd; + bytes_acked = (target - cstat->cwnd) * cstat->max_tx_udp_payload_size; + m = (bytes_acked + cubic->current.pending_bytes_acked) / cstat->cwnd; + + cubic->current.pending_bytes_acked += bytes_acked; + cubic->current.pending_bytes_acked -= m * cstat->cwnd; + + assert(cubic->current.pending_bytes_acked < cstat->cwnd); + + cstat->cwnd += m; } + set_pacing_rate(cstat); + ngtcp2_log_infof(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, "%" PRIu64 " bytes acked, cubic-ca cwnd=%" PRIu64 " k_m=%" PRIu64 " target=%" PRIu64 " w_est=%" PRIu64, @@ -407,7 +472,7 @@ void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, void ngtcp2_cc_cubic_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp sent_ts, - uint64_t bytes_lost, + const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); uint64_t flight_size; @@ -428,8 +493,8 @@ void ngtcp2_cc_cubic_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, cubic->current.epoch_start = ts; cubic->current.app_limited_start_ts = UINT64_MAX; cubic->current.app_limited_duration = 0; - cubic->current.pending_bytes_delivered = 0; - cubic->current.pending_est_bytes_delivered = 0; + cubic->current.pending_bytes_acked = 0; + cubic->current.pending_est_bytes_acked = 0; if (cstat->cwnd < cubic->current.w_max) { cubic->current.w_max = cstat->cwnd * 17 / 20; @@ -443,7 +508,7 @@ void ngtcp2_cc_cubic_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, cstat->ssthresh = cstat->cwnd * 7 / 10; if (cubic->rst->rs.delivered * 2 < cstat->cwnd) { - flight_size = cstat->bytes_in_flight + bytes_lost; + flight_size = cstat->bytes_in_flight + ack->bytes_lost; cstat->ssthresh = ngtcp2_min_uint64( cstat->ssthresh, ngtcp2_max_uint64(cubic->rst->rs.delivered, flight_size)); @@ -464,6 +529,8 @@ void ngtcp2_cc_cubic_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, cubic->current.k_m = ngtcp2_cbrt((cwnd_delta << 30) * 10 / 4 / cstat->max_tx_udp_payload_size); + set_pacing_rate(cstat); + ngtcp2_log_infof(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, "reduce cwnd because of packet loss cwnd=%" PRIu64, cstat->cwnd); @@ -482,6 +549,8 @@ void ngtcp2_cc_cubic_cc_on_spurious_congestion(ngtcp2_cc *cc, cstat->cwnd = cubic->undo.cwnd; cstat->ssthresh = cubic->undo.ssthresh; + set_pacing_rate(cstat); + ngtcp2_log_infof(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, "spurious congestion is detected and congestion state is " "restored cwnd=%" PRIu64, @@ -499,17 +568,18 @@ void ngtcp2_cc_cubic_cc_on_persistent_congestion(ngtcp2_cc *cc, ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); (void)ts; - cubic_cc_reset(cubic); + cubic_cc_reset(cubic, cstat); cstat->cwnd = 2 * cstat->max_tx_udp_payload_size; cstat->congestion_recovery_start_ts = UINT64_MAX; + + set_pacing_rate(cstat); } void ngtcp2_cc_cubic_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); - (void)cstat; (void)ts; - cubic_cc_reset(cubic); + cubic_cc_reset(cubic, cstat); } diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.h index e4e19e1aa6..010a1c3541 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.h @@ -88,11 +88,6 @@ typedef struct ngtcp2_cc_pkt { * 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. */ @@ -143,13 +138,16 @@ typedef void (*ngtcp2_cc_on_pkt_lost)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, * @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. + * called when congestion event happens (e.g., when packet is lost or + * due to ECN). |ack| contains information after ACK processing. + * This callback may be called from non-ACK processing context. In + * that case, the information only taken from |ack| processing has + * default values, like 0 or UINT64_MAX; */ typedef void (*ngtcp2_cc_congestion_event)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp sent_ts, - uint64_t bytes_lost, + const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); /** @@ -254,7 +252,7 @@ typedef struct ngtcp2_cc { 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). + * when congestion event happens (e.g., packet is lost). */ ngtcp2_cc_congestion_event congestion_event; /** @@ -310,14 +308,16 @@ typedef struct ngtcp2_cc_reno { uint64_t pending_add; } ngtcp2_cc_reno; -void ngtcp2_cc_reno_init(ngtcp2_cc_reno *reno, ngtcp2_log *log); +void ngtcp2_cc_reno_init(ngtcp2_cc_reno *reno, ngtcp2_log *log, + ngtcp2_conn_stat *cstat); 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); + const ngtcp2_cc_ack *ack, + ngtcp2_tstamp ts); void ngtcp2_cc_reno_cc_on_persistent_congestion(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, @@ -340,8 +340,8 @@ typedef struct ngtcp2_cubic_vars { /* 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; + uint64_t pending_bytes_acked; + uint64_t pending_est_bytes_acked; } ngtcp2_cubic_vars; /* ngtcp2_cc_cubic is CUBIC congestion controller. */ @@ -371,14 +371,15 @@ typedef struct ngtcp2_cc_cubic { } ngtcp2_cc_cubic; void ngtcp2_cc_cubic_init(ngtcp2_cc_cubic *cc, ngtcp2_log *log, - ngtcp2_rst *rst); + ngtcp2_conn_stat *cstat, 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); + const ngtcp2_cc_ack *ack, + ngtcp2_tstamp ts); void ngtcp2_cc_cubic_cc_on_spurious_congestion(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.c index 13938761dd..b1a9840c6e 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.c @@ -1166,8 +1166,8 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, assert(settings->max_window <= NGTCP2_MAX_VARINT); assert(settings->max_stream_window <= NGTCP2_MAX_VARINT); - assert(settings->max_tx_udp_payload_size); - assert(settings->max_tx_udp_payload_size <= NGTCP2_HARD_MAX_UDP_PAYLOAD_SIZE); + assert(settings->max_tx_udp_payload_size >= NGTCP2_MAX_UDP_PAYLOAD_SIZE); + assert(settings->max_tx_udp_payload_size <= NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE); assert(settings->initial_pkt_num <= INT32_MAX); assert(settings->initial_rtt); assert(params->active_connection_id_limit >= @@ -1203,6 +1203,7 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, for (i = 0; i < settings->pmtud_probeslen; ++i) { assert(settings->pmtud_probes[i] > NGTCP2_MAX_UDP_PAYLOAD_SIZE); + assert(settings->pmtud_probes[i] <= NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE); } if (mem == NULL) { @@ -1335,11 +1336,12 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, switch (settings->cc_algo) { case NGTCP2_CC_ALGO_RENO: - ngtcp2_cc_reno_init(&(*pconn)->reno, &(*pconn)->log); + ngtcp2_cc_reno_init(&(*pconn)->reno, &(*pconn)->log, &(*pconn)->cstat); break; case NGTCP2_CC_ALGO_CUBIC: - ngtcp2_cc_cubic_init(&(*pconn)->cubic, &(*pconn)->log, &(*pconn)->rst); + ngtcp2_cc_cubic_init(&(*pconn)->cubic, &(*pconn)->log, &(*pconn)->cstat, + &(*pconn)->rst); break; case NGTCP2_CC_ALGO_BBR: @@ -2373,6 +2375,15 @@ conn_crumble_initial_crypto(ngtcp2_conn *conn, ngtcp2_frame_chain **pfrc, return (ngtcp2_ssize)datacnt; } +static size_t conn_dgram_padding(ngtcp2_conn *conn, ngtcp2_ppe *ppe) { + if (conn->local.settings.no_tx_udp_payload_size_shaping) { + return ngtcp2_ppe_dgram_padding_size( + ppe, conn->local.settings.max_tx_udp_payload_size); + } + + return ngtcp2_ppe_dgram_padding(ppe); +} + static size_t conn_min_pktlen(ngtcp2_conn *conn); /* @@ -2669,7 +2680,7 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, (rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) != 0, require_padding)) { lfr.type = NGTCP2_FRAME_PADDING; - lfr.padding.len = ngtcp2_ppe_dgram_padding(&ppe); + lfr.padding.len = conn_dgram_padding(conn, &ppe); } else if (pkt_empty) { return 0; } else { @@ -3450,7 +3461,6 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint64_t crypto_offset; uint64_t stream_offset; ngtcp2_ssize num_reclaimed; - int fin; uint64_t target_max_data; ngtcp2_conn_stat *cstat = &conn->cstat; uint64_t delta; @@ -4145,9 +4155,8 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, nfrc->fr.stream.datacnt = datacnt; ngtcp2_vec_copy(nfrc->fr.stream.data, data, datacnt); - fin = (vmsg->stream.flags & NGTCP2_WRITE_STREAM_FLAG_FIN) && - ndatalen == datalen; - nfrc->fr.stream.fin = (uint8_t)fin; + nfrc->fr.stream.fin = (vmsg->stream.flags & NGTCP2_WRITE_STREAM_FLAG_FIN) && + ndatalen == datalen; rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); if (rv != 0) { @@ -4166,7 +4175,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, conn->tx.offset += ndatalen; vmsg->stream.strm->flags |= NGTCP2_STRM_FLAG_ANY_SENT; - if (fin) { + if (nfrc->fr.stream.fin) { ngtcp2_strm_shutdown(vmsg->stream.strm, NGTCP2_STRM_FLAG_SHUT_WR); } @@ -4396,7 +4405,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, (rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING)) { lfr.padding.len = ngtcp2_ppe_padding_size(ppe, destlen); } else if (require_padding) { - lfr.padding.len = ngtcp2_ppe_dgram_padding(ppe); + lfr.padding.len = conn_dgram_padding(conn, ppe); } else { lfr.padding.len = ngtcp2_ppe_padding_size(ppe, min_pktlen); min_padded = 1; @@ -4595,13 +4604,13 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( if (flags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING_FULL) { lfr.padding.len = ngtcp2_ppe_dgram_padding_size(&ppe, destlen); } else if (flags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING) { - lfr.padding.len = ngtcp2_ppe_dgram_padding(&ppe); + lfr.padding.len = conn_dgram_padding(conn, &ppe); } else { switch (fr->type) { case NGTCP2_FRAME_PATH_CHALLENGE: case NGTCP2_FRAME_PATH_RESPONSE: if (!conn->server || destlen >= NGTCP2_MAX_UDP_PAYLOAD_SIZE) { - lfr.padding.len = ngtcp2_ppe_dgram_padding(&ppe); + lfr.padding.len = conn_dgram_padding(conn, &ppe); } else { lfr.padding.len = 0; } @@ -12639,7 +12648,7 @@ void ngtcp2_ccerr_set_liberr(ngtcp2_ccerr *ccerr, int liberr, reasonlen); return; - }; + } ngtcp2_ccerr_set_transport_error( ccerr, ngtcp2_err_infer_quic_transport_error_code(liberr), reason, @@ -13848,8 +13857,17 @@ int ngtcp2_conn_set_stream_user_data(ngtcp2_conn *conn, int64_t stream_id, return 0; } +void *ngtcp2_conn_get_stream_user_data(ngtcp2_conn *conn, int64_t stream_id) { + ngtcp2_strm *strm = ngtcp2_conn_find_stream(conn, stream_id); + + if (strm == NULL) { + return NULL; + } + + return strm->stream_user_data; +} + void ngtcp2_conn_update_pkt_tx_time(ngtcp2_conn *conn, ngtcp2_tstamp ts) { - uint64_t pacing_interval_m; ngtcp2_duration wait, d; conn_update_timestamp(conn, ts); @@ -13858,20 +13876,9 @@ void ngtcp2_conn_update_pkt_tx_time(ngtcp2_conn *conn, ngtcp2_tstamp ts) { return; } - if (conn->cstat.pacing_interval_m) { - pacing_interval_m = conn->cstat.pacing_interval_m; - } else { - /* 1.25 is the under-utilization avoidance factor described in - https://datatracker.ietf.org/doc/html/rfc9002#section-7.7 */ - pacing_interval_m = ((conn->cstat.first_rtt_sample_ts == UINT64_MAX - ? NGTCP2_MILLISECONDS - : conn->cstat.smoothed_rtt) - << 10) * - 100 / 125 / conn->cstat.cwnd; - pacing_interval_m = ngtcp2_max_uint64(pacing_interval_m, 1); - } - - wait = (ngtcp2_duration)((conn->tx.pacing.pktlen * pacing_interval_m) >> 10); + wait = (ngtcp2_duration)((conn->tx.pacing.pktlen * + conn->cstat.pacing_interval_m) >> + 10); d = ngtcp2_min_uint64(wait / 2, conn->tx.pacing.compensation); wait -= d; @@ -13909,6 +13916,25 @@ ngtcp2_ssize ngtcp2_conn_write_aggregate_pkt_versioned( ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, ngtcp2_pkt_info *pi, uint8_t *buf, size_t buflen, size_t *pgsolen, ngtcp2_write_pkt write_pkt, ngtcp2_tstamp ts) { + ngtcp2_ssize nwrite; + + buflen = ngtcp2_min_size(buflen, ngtcp2_conn_get_send_quantum(conn)); + + nwrite = ngtcp2_conn_write_aggregate_pkt2_versioned( + conn, path, pkt_info_version, pi, buf, buflen, pgsolen, write_pkt, 0, ts); + if (nwrite < 0) { + return nwrite; + } + + ngtcp2_conn_update_pkt_tx_time(conn, ts); + + return nwrite; +} + +ngtcp2_ssize ngtcp2_conn_write_aggregate_pkt2_versioned( + ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, + ngtcp2_pkt_info *pi, uint8_t *buf, size_t buflen, size_t *pgsolen, + ngtcp2_write_pkt write_pkt, size_t num_pkts, ngtcp2_tstamp ts) { size_t max_udp_payloadlen = ngtcp2_conn_get_max_tx_udp_payload_size(conn); size_t path_max_udp_payloadlen = ngtcp2_conn_get_path_max_tx_udp_payload_size(conn); @@ -13923,9 +13949,9 @@ ngtcp2_ssize ngtcp2_conn_write_aggregate_pkt_versioned( assert(buflen >= path_max_udp_payloadlen); - buflen = - ngtcp2_min_size(buflen, ngtcp2_max_size(ngtcp2_conn_get_send_quantum(conn), - path_max_udp_payloadlen)); + if (num_pkts == 0) { + num_pkts = SIZE_MAX; + } for (;;) { ecn_state = conn->tx.ecn.state; @@ -13947,13 +13973,16 @@ ngtcp2_ssize ngtcp2_conn_write_aggregate_pkt_versioned( wbuf += nwrite; buflen -= (size_t)nwrite; + --num_pkts; + if (first_pkt) { assert(!(conn->flags & NGTCP2_CONN_FLAG_AGGREGATE_PKTS)); *pgsolen = (size_t)nwrite; if ((size_t)nwrite != path_max_udp_payloadlen || - buflen < path_max_udp_payloadlen || ecn_state != conn->tx.ecn.state) { + buflen < path_max_udp_payloadlen || ecn_state != conn->tx.ecn.state || + num_pkts == 0) { nwrite = wbuf - buf; break; } @@ -13977,7 +14006,7 @@ ngtcp2_ssize ngtcp2_conn_write_aggregate_pkt_versioned( } if (buflen < path_max_udp_payloadlen || (size_t)nwrite < *pgsolen || - ecn_state != conn->tx.ecn.state) { + ecn_state != conn->tx.ecn.state || num_pkts == 0) { nwrite = wbuf - buf; break; } @@ -13985,8 +14014,6 @@ ngtcp2_ssize ngtcp2_conn_write_aggregate_pkt_versioned( conn->flags &= ~NGTCP2_CONN_FLAG_AGGREGATE_PKTS; - ngtcp2_conn_update_pkt_tx_time(conn, ts); - return nwrite; } diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.h index ed358dc48d..b3cdb1d64a 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.h @@ -103,10 +103,6 @@ /* NGTCP2_RETRY_TAGLEN is the length of Retry packet integrity tag. */ #define NGTCP2_RETRY_TAGLEN 16 -/* NGTCP2_HARD_MAX_UDP_PAYLOAD_SIZE is the maximum UDP datagram - payload size that this library can write. */ -#define NGTCP2_HARD_MAX_UDP_PAYLOAD_SIZE ((1 << 24) - 1) - /* NGTCP2_PKT_LENGTHLEN is the number of bytes that is occupied by Length field in Long packet header. */ #define NGTCP2_PKT_LENGTHLEN 4 @@ -195,7 +191,7 @@ typedef struct ngtcp2_stream { uint8_t flags; /* CRYPTO frame does not include this field, and must set it to 0. */ - uint8_t fin; + int fin; /* CRYPTO frame does not include this field, and must set it to 0. */ int64_t stream_id; diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c index 353afca4d4..40c25f2a3d 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c @@ -32,18 +32,8 @@ #include "ngtcp2_macro.h" #ifndef NDEBUG -static int ispow2(size_t n) { -# if defined(_MSC_VER) && !defined(__clang__) && \ - (defined(_M_ARM) || (defined(_M_ARM64) && _MSC_VER < 1941)) - return n && !(n & (n - 1)); -# elif defined(WIN32) - return 1 == __popcnt((unsigned int)n); -# else /* !((defined(_MSC_VER) && !defined(__clang__) && (defined(_M_ARM) || \ - (defined(_M_ARM64) && _MSC_VER < 1941))) || defined(WIN32)) */ - return 1 == __builtin_popcount((unsigned int)n); -# endif /* !((defined(_MSC_VER) && !defined(__clang__) && (defined(_M_ARM) || \ - (defined(_M_ARM64) && _MSC_VER < 1941))) || defined(WIN32)) */ -} +/* Power-of-two test; simple portable bit trick. */ +static int ispow2(size_t n) { return n && !(n & (n - 1)); } #endif /* !defined(NDEBUG) */ int ngtcp2_ringbuf_init(ngtcp2_ringbuf *rb, size_t nmemb, size_t size, diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rst.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rst.c index 6f44c8ac8d..77247108ec 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rst.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rst.c @@ -59,16 +59,27 @@ void ngtcp2_rst_reset(ngtcp2_rst *rst) { rst->lost = 0; } +void ngtcp2_rst_reset_rate_sample(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat) { + ngtcp2_rs *rs = &rst->rs; + + rs->interval = UINT64_MAX; + rs->prior_ts = UINT64_MAX; + + cstat->delivery_rate_sec = 0; +} + void ngtcp2_rst_on_pkt_sent(ngtcp2_rst *rst, ngtcp2_rtb_entry *ent, const ngtcp2_conn_stat *cstat) { - if (cstat->bytes_in_flight == 0) { + /* cstat->bytes_in_flight includes ent->pktlen. If they are the + same, there is no in-flight packets. */ + if (cstat->bytes_in_flight == ent->pktlen) { rst->first_sent_ts = rst->delivered_ts = ent->ts; } ent->rst.first_sent_ts = rst->first_sent_ts; ent->rst.delivered_ts = rst->delivered_ts; ent->rst.delivered = rst->delivered; ent->rst.is_app_limited = rst->app_limited != 0; - ent->rst.tx_in_flight = cstat->bytes_in_flight + ent->pktlen; + ent->rst.tx_in_flight = cstat->bytes_in_flight; ent->rst.lost = rst->lost; ent->rst.end_seq = ++rst->last_seq; } @@ -89,7 +100,6 @@ void ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat) { rs->delivered = rst->delivered - rs->prior_delivered; if (rs->interval < cstat->min_rtt) { - rs->interval = UINT64_MAX; return; } diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rst.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rst.h index 1bb624de79..b0bc2d06c9 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rst.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rst.h @@ -79,6 +79,8 @@ void ngtcp2_rst_init(ngtcp2_rst *rst); void ngtcp2_rst_reset(ngtcp2_rst *rst); +void ngtcp2_rst_reset_rate_sample(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat); + void ngtcp2_rst_on_pkt_sent(ngtcp2_rst *rst, ngtcp2_rtb_entry *ent, const ngtcp2_conn_stat *cstat); void ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat); diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c index f51c0f14ef..5908fcc5c5 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c @@ -128,13 +128,12 @@ void ngtcp2_rtb_free(ngtcp2_rtb *rtb) { static void rtb_on_add(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, ngtcp2_conn_stat *cstat) { - ngtcp2_rst_on_pkt_sent(rtb->rst, ent, cstat); - assert(rtb->cc_pkt_num <= ent->hd.pkt_num); cstat->bytes_in_flight += ent->pktlen; rtb->cc_bytes_in_flight += ent->pktlen; + ngtcp2_rst_on_pkt_sent(rtb->rst, ent, cstat); ngtcp2_rst_update_app_limited(rtb->rst, cstat); if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) { @@ -738,8 +737,7 @@ static void rtb_on_pkt_acked(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, static void conn_verify_ecn(ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, const ngtcp2_ack *fr, size_t ecn_acked, - ngtcp2_tstamp largest_pkt_sent_ts, - ngtcp2_tstamp ts) { + const ngtcp2_cc_ack *cc_ack, ngtcp2_tstamp ts) { if (conn->tx.ecn.state == NGTCP2_ECN_STATE_FAILED) { return; } @@ -766,9 +764,9 @@ static void conn_verify_ecn(ngtcp2_conn *conn, ngtcp2_pktns *pktns, } if (fr->type == NGTCP2_FRAME_ACK_ECN) { - if (cc->congestion_event && largest_pkt_sent_ts != UINT64_MAX && + if (cc->congestion_event && cc_ack->largest_pkt_sent_ts != UINT64_MAX && fr->ecn.ce > pktns->acktr.ecn.ack.ce) { - cc->congestion_event(cc, cstat, largest_pkt_sent_ts, 0, ts); + cc->congestion_event(cc, cstat, cc_ack->largest_pkt_sent_ts, cc_ack, ts); } pktns->acktr.ecn.ack.ect0 = fr->ecn.ect0; @@ -777,7 +775,7 @@ static void conn_verify_ecn(ngtcp2_conn *conn, ngtcp2_pktns *pktns, } } -static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, +static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_cc_ack *cc_ack, ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts); @@ -791,7 +789,6 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, int rv; ngtcp2_ksl_it it; size_t num_acked = 0; - ngtcp2_tstamp largest_pkt_sent_ts = UINT64_MAX; int64_t pkt_num; ngtcp2_cc *cc = rtb->cc; ngtcp2_rtb_entry *acked_ent = NULL; @@ -799,7 +796,7 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, size_t ecn_acked = 0; int verify_ecn = 0; ngtcp2_cc_ack cc_ack = { - .prior_bytes_in_flight = cstat->bytes_in_flight, + .largest_pkt_sent_ts = UINT64_MAX, .rtt = UINT64_MAX, }; size_t num_lost_pkts = rtb->num_lost_pkts - rtb->num_lost_ignore_pkts; @@ -819,12 +816,17 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, verify_ecn = 1; } + ngtcp2_rst_reset_rate_sample(rtb->rst, cstat); + /* Assume that ngtcp2_pkt_validate_ack(fr) returns 0 */ it = ngtcp2_ksl_lower_bound(&rtb->ents, &largest_ack); if (ngtcp2_ksl_it_end(&it)) { if (conn && verify_ecn) { - conn_verify_ecn(conn, pktns, rtb->cc, cstat, fr, ecn_acked, - largest_pkt_sent_ts, ts); + conn_verify_ecn(conn, pktns, rtb->cc, cstat, fr, ecn_acked, &cc_ack, ts); + } + + if (cc->on_ack_recv) { + cc->on_ack_recv(cc, cstat, &cc_ack, ts); } return 0; @@ -849,7 +851,7 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, } if (largest_ack == pkt_num) { - largest_pkt_sent_ts = ent->ts; + cc_ack.largest_pkt_sent_ts = ent->ts; } if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) { @@ -889,9 +891,9 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, } } - if (largest_pkt_sent_ts != UINT64_MAX && ack_eliciting_pkt_acked) { - cc_ack.rtt = - ngtcp2_max_uint64(pkt_ts - largest_pkt_sent_ts, NGTCP2_NANOSECONDS); + if (cc_ack.largest_pkt_sent_ts != UINT64_MAX && ack_eliciting_pkt_acked) { + cc_ack.rtt = ngtcp2_max_uint64(pkt_ts - cc_ack.largest_pkt_sent_ts, + NGTCP2_NANOSECONDS); rv = ngtcp2_conn_update_rtt(conn, cc_ack.rtt, fr->ack_delay_unscaled, ts); if (rv == 0 && cc->new_rtt_sample && @@ -927,11 +929,6 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, ngtcp2_rtb_entry_objalloc_del(ent, rtb->rtb_entry_objalloc, rtb->frc_objalloc, rtb->mem); } - - if (verify_ecn) { - conn_verify_ecn(conn, pktns, rtb->cc, cstat, fr, ecn_acked, - largest_pkt_sent_ts, ts); - } } else { /* For unit tests */ for (ent = acked_ent; ent; ent = acked_ent) { @@ -952,15 +949,18 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, ngtcp2_rst_on_ack_recv(rtb->rst, cstat); if (conn) { - rv = rtb_detect_lost_pkt(rtb, &cc_ack.bytes_lost, conn, pktns, cstat, ts); + rv = rtb_detect_lost_pkt(rtb, &cc_ack, conn, pktns, cstat, ts); if (rv != 0) { return rv; } } } - cc_ack.largest_pkt_sent_ts = largest_pkt_sent_ts; - if (num_acked && cc->on_ack_recv) { + if (conn && verify_ecn) { + conn_verify_ecn(conn, pktns, rtb->cc, cstat, fr, ecn_acked, &cc_ack, ts); + } + + if (cc->on_ack_recv) { cc->on_ack_recv(cc, cstat, &cc_ack, ts); } @@ -1026,7 +1026,11 @@ static int conn_all_ecn_pkt_lost(ngtcp2_conn *conn) { pktns->tx.ecn.validation_pkt_sent == pktns->tx.ecn.validation_pkt_lost; } -static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, +/* + * This function assigns the number of bytes lost to + * |cc_ack|->bytes_lost if any. + */ +static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_cc_ack *cc_ack, ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { ngtcp2_rtb_entry *ent; @@ -1144,8 +1148,10 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, break; } + cc_ack->bytes_lost = bytes_lost; + if (cc->congestion_event) { - cc->congestion_event(cc, cstat, latest_ts, bytes_lost, ts); + cc->congestion_event(cc, cstat, latest_ts, cc_ack, ts); } loss_window = latest_ts - oldest_ts; @@ -1181,18 +1187,18 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, ngtcp2_rtb_remove_excessive_lost_pkt(rtb, (size_t)pkt_thres); - if (ppkt_lost) { - *ppkt_lost = bytes_lost; - } - return 0; } int ngtcp2_rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { - return rtb_detect_lost_pkt(rtb, /* ppkt_lost = */ NULL, conn, pktns, cstat, - ts); + ngtcp2_cc_ack cc_ack = { + .largest_pkt_sent_ts = UINT64_MAX, + .rtt = UINT64_MAX, + }; + + return rtb_detect_lost_pkt(rtb, &cc_ack, conn, pktns, cstat, ts); } void ngtcp2_rtb_remove_excessive_lost_pkt(ngtcp2_rtb *rtb, size_t n) { diff --git a/src/contrib/libngtcp2/ngtcp2/ngtcp2.h b/src/contrib/libngtcp2/ngtcp2/ngtcp2.h index baecc277ee..5634c9c751 100644 --- a/src/contrib/libngtcp2/ngtcp2/ngtcp2.h +++ b/src/contrib/libngtcp2/ngtcp2/ngtcp2.h @@ -306,15 +306,29 @@ typedef struct ngtcp2_mem { * @macro * * :macro:`NGTCP2_MAX_UDP_PAYLOAD_SIZE` is the default maximum UDP - * datagram payload size that the local endpoint transmits. + * datagram payload size that the local endpoint transmits without + * Path MTU Discovery (PMTUD) or the custom settings (see + * :member:`ngtcp2_settings.max_tx_udp_payload_size` and + * :member:`ngtcp2_settings.no_tx_udp_payload_size_shaping`). */ #define NGTCP2_MAX_UDP_PAYLOAD_SIZE 1200 /** * @macro * - * :macro:`NGTCP2_MAX_PMTUD_UDP_PAYLOAD_SIZE` is the maximum UDP + * :macro:`NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE` is the maximum UDP datagram + * payload size that this library can output. + */ +#define NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE 65527 + +/** + * @macro + * + * :macro:`NGTCP2_MAX_PMTUD_UDP_PAYLOAD_SIZE` was the maximum UDP * datagram payload size that Path MTU Discovery can discover. + * + * Deprecated since v1.17.0. Path MTU Discovery is not capped to this + * value anymore. */ #define NGTCP2_MAX_PMTUD_UDP_PAYLOAD_SIZE 1452 @@ -1786,7 +1800,9 @@ typedef struct ngtcp2_settings { ngtcp2_printf log_printf; /** * :member:`max_tx_udp_payload_size` is the maximum size of UDP - * datagram payload that the local endpoint transmits. + * datagram payload that the local endpoint transmits. This must be + * larger than or equal to :macro:`NGTCP2_MAX_UDP_PAYLOAD_SIZE`, and + * less then or equal to :macro:`NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE`. */ size_t max_tx_udp_payload_size; /** @@ -1951,12 +1967,13 @@ typedef struct ngtcp2_settings { /** * :member:`pmtud_probes` is the array of UDP datagram payload size * to probe during Path MTU Discovery. The discovery is done in the - * order appeared in this array. The size must be strictly larger - * than 1200, otherwise the behavior is undefined. The maximum - * value in this array should be set to - * :member:`max_tx_udp_payload_size`. If this field is not set, the - * predefined PMTUD probes are made. This field has been available - * since v1.4.0. + * order appeared in this array. The payload size must be strictly + * larger than :macro:`NGTCP2_MAX_UDP_PAYLOAD_SIZE`, and less than + * or equal to :macro:`NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE`. Otherwise + * the behavior is undefined. The maximum value in this array + * should be set to :member:`max_tx_udp_payload_size`. If this + * field is not set, the predefined PMTUD probes are made. This + * field has been available since v1.4.0. */ const uint16_t *pmtud_probes; /** @@ -4155,9 +4172,7 @@ NGTCP2_EXTERN void ngtcp2_conn_set_keep_alive_timeout(ngtcp2_conn *conn, * `ngtcp2_conn_get_expiry` returns the next expiry time. It returns * ``UINT64_MAX`` if there is no next expiry. * - * Call `ngtcp2_conn_handle_expiry` and then - * `ngtcp2_conn_writev_stream` (or `ngtcp2_conn_writev_datagram`) when - * the expiry time has passed. + * Call `ngtcp2_conn_handle_expiry` when the expiry time has passed. */ NGTCP2_EXTERN ngtcp2_tstamp ngtcp2_conn_get_expiry(ngtcp2_conn *conn); @@ -4165,6 +4180,20 @@ NGTCP2_EXTERN ngtcp2_tstamp ngtcp2_conn_get_expiry(ngtcp2_conn *conn); * @function * * `ngtcp2_conn_handle_expiry` handles expired timer. + * + * If it returns :macro:`NGTCP2_ERR_IDLE_CLOSE`, it means that an idle + * timer has fired for this particular connection. In this case, drop + * the connection without calling + * `ngtcp2_conn_write_connection_close`. If it returns any of the + * other negative error codes, close the connection by sending the + * terminal packet produced by `ngtcp2_conn_write_connection_close`. + * Otherwise, schedule `ngtcp2_conn_writev_stream` call. An + * application may call any number of additional + * `ngtcp2_conn_read_pkt` and `ngtcp2_conn_handle_expiry` before + * calling `ngtcp2_conn_writev_stream`. After calling + * `ngtcp2_conn_writev_stream`, new expiry is set. The application + * should call `ngtcp2_conn_get_expiry` to get a new deadline and set + * the timer. */ NGTCP2_EXTERN int ngtcp2_conn_handle_expiry(ngtcp2_conn *conn, ngtcp2_tstamp ts); @@ -5629,6 +5658,26 @@ NGTCP2_EXTERN int ngtcp2_conn_set_stream_user_data(ngtcp2_conn *conn, int64_t stream_id, void *stream_user_data); +/** + * @function + * + * `ngtcp2_conn_get_stream_user_data` returns stream_user_data + * associated to the stream identified by |stream_id|. If the stream + * is not found, or no stream data is associated to the stream, this + * function returns NULL. + * + * The stream_user_data can be associated to the stream by one of the + * following functions: + * + * - `ngtcp2_conn_open_bidi_stream` + * - `ngtcp2_conn_open_uni_stream` + * - `ngtcp2_conn_set_stream_user_data` + * + * This function has been available since v1.17.0. + */ +NGTCP2_EXTERN void *ngtcp2_conn_get_stream_user_data(ngtcp2_conn *conn, + int64_t stream_id); + /** * @function * @@ -5714,14 +5763,23 @@ typedef ngtcp2_ssize (*ngtcp2_write_pkt)(ngtcp2_conn *conn, ngtcp2_path *path, * first packet is `ngtcp2_conn_get_path_max_tx_udp_payload_size(conn) * ` bytes long. The * application can adjust the length of the buffer to limit the number - * of packets to aggregate. If this function returns positive - * integer, all packets share the same :type:`ngtcp2_path` and - * :type:`ngtcp2_pkt_info` values, and they are assigned to the - * objects pointed by |path| and |pi| respectively. The length of all - * packets other than the last packet is assigned to |*pgsolen|. The - * length of last packet is equal to or less than |*pgsolen|. - * |write_pkt| must write a single packet. After all packets are - * written, this function calls `ngtcp2_conn_update_pkt_tx_time`. + * of packets to aggregate (or use `ngtcp2_conn_write_aggregate_pkt2` + * to control the number of packets to write directly). If this + * function returns positive integer, all packets share the same + * :type:`ngtcp2_path` and :type:`ngtcp2_pkt_info` values, and they + * are assigned to the objects pointed by |path| and |pi| + * respectively. The length of all packets other than the last packet + * is assigned to |*pgsolen|. The length of last packet is equal to + * or less than |*pgsolen|. |write_pkt| must write a single packet. + * After all packets are written, this function calls + * `ngtcp2_conn_update_pkt_tx_time`. + * + * This function is equivalent to call + * `ngtcp2_conn_write_aggregate_pkt2` with |buflen| = min(|buflen|, + * `ngtcp2_conn_get_send_quantum(conn) + * `) and |num_pkts| = 0 followed by + * `ngtcp2_conn_update_pkt_tx_time(conn) + * `. * * This function returns the number of bytes written to the buffer, or * a negative error code returned by |write_pkt|. @@ -5733,6 +5791,29 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_aggregate_pkt_versioned( ngtcp2_pkt_info *pi, uint8_t *buf, size_t buflen, size_t *pgsolen, ngtcp2_write_pkt write_pkt, ngtcp2_tstamp ts); +/** + * @function + * + * `ngtcp2_conn_write_aggregate_pkt2` behaves like + * `ngtcp2_conn_write_aggregate_pkt`, but it accepts |num_pkts| to + * specify the maximum number of packets to write. If |num_pkts| is + * 0, this function writes packets as much as possible. The actual + * number of packets to write is determined by the connection state + * (e.g., the congestion controller, data available to send) and the + * length of packet produced. It also does not clamp |buflen|, and + * does not call `ngtcp2_conn_update_pkt_tx_time`. + * + * This function offers more flexibility and optimization chances to + * an application. It can experiment different GSO buffer size + * strategy and number of GSO writes per event loop. + * + * This function has been available since v1.17.0. + */ +NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_aggregate_pkt2_versioned( + ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, + ngtcp2_pkt_info *pi, uint8_t *buf, size_t buflen, size_t *pgsolen, + ngtcp2_write_pkt write_pkt, size_t num_pkts, ngtcp2_tstamp ts); + /** * @function * @@ -6140,6 +6221,17 @@ NGTCP2_EXTERN uint32_t ngtcp2_select_version(const uint32_t *preferred_versions, (CONN), (PATH), NGTCP2_PKT_INFO_VERSION, (PI), (BUF), (BUFLEN), (PGSOLEN), \ (WRITE_PKT), (TS)) +/* + * `ngtcp2_conn_write_aggregate_pkt2` is a wrapper around + * `ngtcp2_conn_write_aggregate_pkt2_versioned` to set the correct + * struct version. + */ +#define ngtcp2_conn_write_aggregate_pkt2(CONN, PATH, PI, BUF, BUFLEN, PGSOLEN, \ + WRITE_PKT, NUM_PKTS, TS) \ + ngtcp2_conn_write_aggregate_pkt2_versioned( \ + (CONN), (PATH), NGTCP2_PKT_INFO_VERSION, (PI), (BUF), (BUFLEN), (PGSOLEN), \ + (WRITE_PKT), (NUM_PKTS), (TS)) + /* * `ngtcp2_settings_default` is a wrapper around * `ngtcp2_settings_default_versioned` to set the correct struct diff --git a/src/contrib/libngtcp2/ngtcp2/version.h b/src/contrib/libngtcp2/ngtcp2/version.h index 9fabd7b179..3ff1ebac97 100644 --- a/src/contrib/libngtcp2/ngtcp2/version.h +++ b/src/contrib/libngtcp2/ngtcp2/version.h @@ -36,7 +36,7 @@ * * Version number of the ngtcp2 library release. */ -#define NGTCP2_VERSION "1.16.0" +#define NGTCP2_VERSION "1.17.0" /** * @macro @@ -46,6 +46,6 @@ * number, 8 bits for minor and 8 bits for patch. Version 1.2.3 * becomes 0x010203. */ -#define NGTCP2_VERSION_NUM 0x011000 +#define NGTCP2_VERSION_NUM 0x011100 #endif /* !defined(NGTCP2_VERSION_H) */