diff --git a/CHANGELOG b/CHANGELOG index 4cb931b0..dd86f9e4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +2024-02-23 + - 4.0.6 + - Fix ACK handling. + - Do not apply congestion control to CONNECTION_CLOSE frame. + 2024-02-07 - 4.0.5 - Fix CPU spinning due to STREAM_BLOCKED frame. diff --git a/docs/conf.py b/docs/conf.py index 3d24c27c..90371413 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -26,7 +26,7 @@ # The short X.Y version version = u'4.0' # The full version, including alpha/beta/rc tags -release = u'4.0.5' +release = u'4.0.6' # -- General configuration --------------------------------------------------- diff --git a/include/lsquic.h b/include/lsquic.h index 9e360438..b2989669 100644 --- a/include/lsquic.h +++ b/include/lsquic.h @@ -27,7 +27,7 @@ extern "C" { #define LSQUIC_MAJOR_VERSION 4 #define LSQUIC_MINOR_VERSION 0 -#define LSQUIC_PATCH_VERSION 5 +#define LSQUIC_PATCH_VERSION 6 /** * Engine flags: diff --git a/src/liblsquic/lsquic_full_conn_ietf.c b/src/liblsquic/lsquic_full_conn_ietf.c index fd8501a4..2260ba9b 100644 --- a/src/liblsquic/lsquic_full_conn_ietf.c +++ b/src/liblsquic/lsquic_full_conn_ietf.c @@ -1933,7 +1933,7 @@ generate_ack_frame_for_pns (struct ietf_full_conn *conn, conn->ifc_flags |= IFC_ACK_HAD_MISS; else conn->ifc_flags &= ~IFC_ACK_HAD_MISS; - LSQ_DEBUG("Put %d bytes of ACK frame into packet %" PRIu64 + LSQ_DEBUG("Put %d bytes of ACK frame into packet #%" PRIu64 " on outgoing queue", w, packet_out->po_packno); if (conn->ifc_n_cons_unretx >= conn->ifc_ping_unretx_thresh && !lsquic_send_ctl_have_outgoing_retx_frames(&conn->ifc_send_ctl)) @@ -1944,6 +1944,7 @@ generate_ack_frame_for_pns (struct ietf_full_conn *conn, /* This gives a range [12, 27]: */ conn->ifc_ping_unretx_thresh = 12 + lsquic_crand_get_nybble(conn->ifc_enpub->enp_crand); + conn->ifc_n_cons_unretx = 0; } conn->ifc_n_slack_akbl[pns] = 0; @@ -7941,7 +7942,7 @@ ietf_full_conn_ci_packet_sent (struct lsquic_conn *lconn, struct ietf_full_conn *const conn = (struct ietf_full_conn *) lconn; int s; - if (packet_out->po_frame_types & (IQUIC_FRAME_RETX_MASK | QUIC_FTBIT_ACK)) + if (packet_out->po_frame_types & (IQUIC_FRAME_RETX_MASK)) conn->ifc_n_cons_unretx = 0; else ++conn->ifc_n_cons_unretx; @@ -8574,7 +8575,8 @@ ietf_full_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now) || 0 != lsquic_send_ctl_n_scheduled(&conn->ifc_send_ctl)) ) { - RETURN_IF_OUT_OF_PACKETS(); + /* CONNECTION_CLOSE frame should not be congestion controlled. + RETURN_IF_OUT_OF_PACKETS(); */ generate_connection_close_packet(conn); tick |= TICK_SEND|TICK_CLOSE; } diff --git a/src/liblsquic/lsquic_parse_common.c b/src/liblsquic/lsquic_parse_common.c index fe074245..fd6041af 100644 --- a/src/liblsquic/lsquic_parse_common.c +++ b/src/liblsquic/lsquic_parse_common.c @@ -232,10 +232,12 @@ lsquic_dcid_from_packet (const unsigned char *buf, size_t bufsz, { /* Xs vary, Gs are iGnored: */ /* 1X11 XGGG: */ + /* case (0x80|0x40|0x20|0x10|0x08) >> 3: case (0x80|0x00|0x20|0x10|0x08) >> 3: case (0x80|0x40|0x20|0x10|0x00) >> 3: case (0x80|0x00|0x20|0x10|0x00) >> 3: + */ Q046_long: /* lsquic_Q046_parse_packet_in_long_begin */ if (bufsz < 14) diff --git a/src/liblsquic/lsquic_send_ctl.c b/src/liblsquic/lsquic_send_ctl.c index d9ebb774..2d6fdf62 100644 --- a/src/liblsquic/lsquic_send_ctl.c +++ b/src/liblsquic/lsquic_send_ctl.c @@ -1704,16 +1704,23 @@ lsquic_send_ctl_pacer_blocked (struct lsquic_send_ctl *ctl) static int send_ctl_can_send (struct lsquic_send_ctl *ctl) { + uint64_t cwnd = ctl->sc_ci->cci_get_cwnd(CGP(ctl)); const unsigned n_out = send_ctl_all_bytes_out(ctl); - LSQ_DEBUG("%s: n_out: %u (unacked_all: %u); cwnd: %"PRIu64 - "; ccfc: %"PRIu64"/%"PRIu64, __func__, - n_out, ctl->sc_bytes_unacked_all, - ctl->sc_ci->cci_get_cwnd(CGP(ctl)), + LSQ_DEBUG("%s: sc_flags: 0x%X, b_out: %u = (%u + %u); b_retx: %u; cwnd: %"PRIu64 + "; ccfc: %"PRIu64"/%"PRIu64"; n_scheduled: %d, n_in_flight_all: %d" + "; pa_burst: %d; pa_next: %lu; pa_now: %lu" + , __func__, ctl->sc_flags, + n_out, ctl->sc_bytes_unacked_all, ctl->sc_bytes_scheduled, + ctl->sc_bytes_unacked_retx, cwnd, ctl->sc_conn_pub->conn_cap.cc_sent, - ctl->sc_conn_pub->conn_cap.cc_max); + ctl->sc_conn_pub->conn_cap.cc_max, + ctl->sc_n_scheduled, ctl->sc_n_in_flight_all, + ctl->sc_pacer.pa_burst_tokens, + ctl->sc_pacer.pa_next_sched, ctl->sc_pacer.pa_now); + if (ctl->sc_flags & SC_PACE) { - if (n_out >= ctl->sc_ci->cci_get_cwnd(CGP(ctl))) + if (n_out >= cwnd) return 0; if (lsquic_pacer_can_schedule(&ctl->sc_pacer, ctl->sc_n_scheduled + ctl->sc_n_in_flight_all)) @@ -1728,7 +1735,7 @@ send_ctl_can_send (struct lsquic_send_ctl *ctl) return 0; } else - return n_out < ctl->sc_ci->cci_get_cwnd(CGP(ctl)); + return n_out < cwnd; } diff --git a/src/liblsquic/lsquic_send_ctl.h b/src/liblsquic/lsquic_send_ctl.h index 22414d40..91ba00d2 100644 --- a/src/liblsquic/lsquic_send_ctl.h +++ b/src/liblsquic/lsquic_send_ctl.h @@ -285,32 +285,41 @@ lsquic_send_ctl_ack_to_front (struct lsquic_send_ctl *, unsigned n_acks); #define lsquic_send_ctl_n_stop_waiting(ctl) \ (+(ctl)->sc_n_stop_waiting) -#define lsquic_send_ctl_n_stop_waiting_reset(ctl) do { \ - (ctl)->sc_n_stop_waiting = 0; \ -} while (0) +static inline void +lsquic_send_ctl_n_stop_waiting_reset(lsquic_send_ctl_t *ctl) +{ + ctl->sc_n_stop_waiting = 0; +} void lsquic_send_ctl_drop_scheduled (lsquic_send_ctl_t *); -#define lsquic_send_ctl_tick_in(ctl, now) do { \ - if ((ctl)->sc_flags & SC_PACE) \ - { \ - (ctl)->sc_flags |= SC_SCHED_TICK; \ - lsquic_pacer_tick_in(&(ctl)->sc_pacer, now); \ - } \ - (ctl)->sc_flags &= ~SC_APP_LIMITED; \ -} while (0) - -#define lsquic_send_ctl_tick_out(ctl) do { \ - if ((ctl)->sc_flags & SC_PACE) \ - lsquic_pacer_tick_out(&(ctl)->sc_pacer); \ -} while (0) +static inline void +lsquic_send_ctl_tick_in(lsquic_send_ctl_t *ctl, lsquic_time_t now) +{ + if ((ctl)->sc_flags & SC_PACE) + { + (ctl)->sc_flags |= SC_SCHED_TICK; + lsquic_pacer_tick_in(&(ctl)->sc_pacer, now); + } + (ctl)->sc_flags &= ~SC_APP_LIMITED; +} + +static inline void +lsquic_send_ctl_tick_out(lsquic_send_ctl_t *ctl) +{ + if ((ctl)->sc_flags & SC_PACE) + lsquic_pacer_tick_out(&(ctl)->sc_pacer); +} -#define lsquic_send_ctl_next_pacer_time(ctl) ( \ - ((ctl)->sc_flags & SC_PACE) \ - && lsquic_pacer_delayed(&(ctl)->sc_pacer) \ - ? lsquic_pacer_next_sched(&(ctl)->sc_pacer) \ - : 0 ) +static inline lsquic_time_t +lsquic_send_ctl_next_pacer_time(lsquic_send_ctl_t *ctl) +{ + return ((ctl)->sc_flags & SC_PACE) + && lsquic_pacer_delayed(&(ctl)->sc_pacer) + ? lsquic_pacer_next_sched(&(ctl)->sc_pacer) + : 0; +} enum packno_bits lsquic_send_ctl_packno_bits (struct lsquic_send_ctl *, enum packnum_space);