From bbee242ac0f73c349e667dfa6b0bec6b89c5e099 Mon Sep 17 00:00:00 2001 From: Dmitri Tikhonov Date: Mon, 18 Jan 2021 13:26:33 -0500 Subject: [PATCH] Release 2.27.5 - [BUGFIX] Assertion in send controller when path validation fails. - [BUGFIX] Assertion in BBR when sending out-of-order packets is detected. - [BUGFIX] Drop overflow receive history ranges when cloning. - Log correct size of the incoming packet. - Fix internal stream function. --- CHANGELOG | 9 +++++++++ docs/conf.py | 2 +- include/lsquic.h | 2 +- src/liblsquic/lsquic_bbr.c | 10 ++++++---- src/liblsquic/lsquic_ev_log.c | 17 ++++++++++------- src/liblsquic/lsquic_full_conn_ietf.c | 3 ++- src/liblsquic/lsquic_rechist.c | 8 +++++++- src/liblsquic/lsquic_send_ctl.c | 11 ++++++----- src/liblsquic/lsquic_send_ctl.h | 2 +- src/liblsquic/lsquic_stream.c | 10 +++++----- tests/test_rechist.c | 14 ++++++++++++++ 11 files changed, 62 insertions(+), 26 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d20cbc3..4474204 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,12 @@ +2021-01-18 + - 2.27.5 + - [BUGFIX] Assertion in send controller when path validation fails. + - [BUGFIX] Assertion in BBR when sending out-of-order packets is + detected. + - [BUGFIX] Drop overflow receive history ranges when cloning. + - Log correct size of the incoming packet. + - Fix internal stream function. + 2021-01-13 - 2.27.4 - [API] Add lsquic_conn_get_sni(), fixes issue #203. diff --git a/docs/conf.py b/docs/conf.py index 44d87fb..2569879 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -26,7 +26,7 @@ author = u'LiteSpeed Technologies' # The short X.Y version version = u'2.27' # The full version, including alpha/beta/rc tags -release = u'2.27.4' +release = u'2.27.5' # -- General configuration --------------------------------------------------- diff --git a/include/lsquic.h b/include/lsquic.h index a3b39b4..28c962e 100644 --- a/include/lsquic.h +++ b/include/lsquic.h @@ -25,7 +25,7 @@ extern "C" { #define LSQUIC_MAJOR_VERSION 2 #define LSQUIC_MINOR_VERSION 27 -#define LSQUIC_PATCH_VERSION 4 +#define LSQUIC_PATCH_VERSION 5 /** * Engine flags: diff --git a/src/liblsquic/lsquic_bbr.c b/src/liblsquic/lsquic_bbr.c index 3610eec..dfdc347 100644 --- a/src/liblsquic/lsquic_bbr.c +++ b/src/liblsquic/lsquic_bbr.c @@ -344,10 +344,12 @@ lsquic_bbr_ack (void *cong_ctl, struct lsquic_packet_out *packet_out, if (sample) TAILQ_INSERT_TAIL(&bbr->bbr_ack_state.samples, sample, next); - if (is_valid_packno(bbr->bbr_ack_state.max_packno)) - /* We assume packet numbers are ordered */ - assert(packet_out->po_packno > bbr->bbr_ack_state.max_packno); - bbr->bbr_ack_state.max_packno = packet_out->po_packno; + if (!is_valid_packno(bbr->bbr_ack_state.max_packno) + /* Packet ordering is checked for, and warned about, in + * lsquic_senhist_add(). + */ + || packet_out->po_packno > bbr->bbr_ack_state.max_packno) + bbr->bbr_ack_state.max_packno = packet_out->po_packno; bbr->bbr_ack_state.acked_bytes += packet_sz; } diff --git a/src/liblsquic/lsquic_ev_log.c b/src/liblsquic/lsquic_ev_log.c index 06107cb..69573ef 100644 --- a/src/liblsquic/lsquic_ev_log.c +++ b/src/liblsquic/lsquic_ev_log.c @@ -52,9 +52,9 @@ void lsquic_ev_log_packet_in (const lsquic_cid_t *cid, const lsquic_packet_in_t *packet_in) { - switch (packet_in->pi_flags & ( - PI_FROM_MINI| - PI_GQUIC)) + unsigned packet_sz; + + switch (packet_in->pi_flags & (PI_FROM_MINI|PI_GQUIC)) { case PI_FROM_MINI|PI_GQUIC: LCID("packet in: %"PRIu64" (from mini)", packet_in->pi_packno); @@ -65,15 +65,18 @@ lsquic_ev_log_packet_in (const lsquic_cid_t *cid, lsquic_packet_in_ecn(packet_in)); break; case PI_GQUIC: - LCID("packet in: %"PRIu64", size: %u", packet_in->pi_packno, - (unsigned) (packet_in->pi_data_sz + GQUIC_PACKET_HASH_SZ)); + packet_sz = packet_in->pi_data_sz + + (packet_in->pi_flags & PI_DECRYPTED ? GQUIC_PACKET_HASH_SZ : 0); + LCID("packet in: %"PRIu64", size: %u", packet_in->pi_packno, packet_sz); break; default: + packet_sz = packet_in->pi_data_sz + + (packet_in->pi_flags & PI_DECRYPTED ? IQUIC_TAG_LEN : 0); if (packet_in->pi_flags & PI_LOG_QL_BITS) LCID("packet in: %"PRIu64", type: %s, size: %u; ecn: %u, spin: %d; " "path: %hhu; Q: %d; L: %d", packet_in->pi_packno, lsquic_hety2str[packet_in->pi_header_type], - (unsigned) (packet_in->pi_data_sz + IQUIC_TAG_LEN), + packet_sz, lsquic_packet_in_ecn(packet_in), /* spin bit value is only valid for short packet headers */ lsquic_packet_in_spin_bit(packet_in), packet_in->pi_path_id, @@ -83,7 +86,7 @@ lsquic_ev_log_packet_in (const lsquic_cid_t *cid, LCID("packet in: %"PRIu64", type: %s, size: %u; ecn: %u, spin: %d; " "path: %hhu", packet_in->pi_packno, lsquic_hety2str[packet_in->pi_header_type], - (unsigned) (packet_in->pi_data_sz + IQUIC_TAG_LEN), + packet_sz, lsquic_packet_in_ecn(packet_in), /* spin bit value is only valid for short packet headers */ lsquic_packet_in_spin_bit(packet_in), packet_in->pi_path_id); diff --git a/src/liblsquic/lsquic_full_conn_ietf.c b/src/liblsquic/lsquic_full_conn_ietf.c index 3c13e7f..1133011 100644 --- a/src/liblsquic/lsquic_full_conn_ietf.c +++ b/src/liblsquic/lsquic_full_conn_ietf.c @@ -731,7 +731,8 @@ path_chal_alarm_expired (enum alarm_id al_id, void *ctx, LSQ_INFO("migration to path #%u failed after none of %u path " "challenges received responses", path_id, copath->cop_n_chals); /* There may be a lingering challenge if its generation is delayed */ - lsquic_send_ctl_cancel_chals(&conn->ifc_send_ctl, &copath->cop_path); + lsquic_send_ctl_cancel_path_verification(&conn->ifc_send_ctl, + &copath->cop_path); wipe_path(conn, path_id); } else diff --git a/src/liblsquic/lsquic_rechist.c b/src/liblsquic/lsquic_rechist.c index 222f586..98350ef 100644 --- a/src/liblsquic/lsquic_rechist.c +++ b/src/liblsquic/lsquic_rechist.c @@ -503,7 +503,13 @@ lsquic_rechist_copy_ranges (struct lsquic_rechist *rechist, void *src_rechist, assert(rechist->rh_n_used == 0); prev_idx = UINT_MAX; - for (range = first(src_rechist); range; range = next(src_rechist)) + for (range = first(src_rechist); range && + /* Do not overwrite higher-numbered ranges. (Also, logic below + * does not work if rechist_reuse_last_elem() is used.) + */ + (rechist->rh_max_ranges == 0 + || rechist->rh_n_used < rechist->rh_max_ranges); + range = next(src_rechist)) { idx = rechist_alloc_elem(rechist); if (idx < 0) diff --git a/src/liblsquic/lsquic_send_ctl.c b/src/liblsquic/lsquic_send_ctl.c index dba590e..245ad41 100644 --- a/src/liblsquic/lsquic_send_ctl.c +++ b/src/liblsquic/lsquic_send_ctl.c @@ -3603,15 +3603,15 @@ lsquic_send_ctl_repath (struct lsquic_send_ctl *ctl, } -/* Drop PATH_CHALLENGE packets for path `path'. */ +/* Drop PATH_CHALLENGE and PATH_RESPONSE packets for path `path'. */ void -lsquic_send_ctl_cancel_chals (struct lsquic_send_ctl *ctl, +lsquic_send_ctl_cancel_path_verification (struct lsquic_send_ctl *ctl, const struct network_path *path) { struct lsquic_packet_out *packet_out, *next; - /* We need only to examine the scheduled queue as lost challenges are - * not retransmitted. + /* We need only to examine the scheduled queue as lost challenges and + * responses are not retransmitted. */ for (packet_out = TAILQ_FIRST(&ctl->sc_scheduled_packets); packet_out; packet_out = next) @@ -3619,7 +3619,8 @@ lsquic_send_ctl_cancel_chals (struct lsquic_send_ctl *ctl, next = TAILQ_NEXT(packet_out, po_next); if (packet_out->po_path == path) { - assert(packet_out->po_frame_types & QUIC_FTBIT_PATH_CHALLENGE); + assert(packet_out->po_frame_types + & (QUIC_FTBIT_PATH_CHALLENGE|QUIC_FTBIT_PATH_RESPONSE)); assert(!(packet_out->po_frame_types & ctl->sc_retx_frames)); send_ctl_maybe_renumber_sched_to_right(ctl, packet_out); send_ctl_sched_remove(ctl, packet_out); diff --git a/src/liblsquic/lsquic_send_ctl.h b/src/liblsquic/lsquic_send_ctl.h index 798858b..18e4278 100644 --- a/src/liblsquic/lsquic_send_ctl.h +++ b/src/liblsquic/lsquic_send_ctl.h @@ -387,7 +387,7 @@ lsquic_send_ctl_repath (struct lsquic_send_ctl *ctl, int keep_path_properties); void -lsquic_send_ctl_cancel_chals (struct lsquic_send_ctl *, +lsquic_send_ctl_cancel_path_verification (struct lsquic_send_ctl *, const struct network_path *); void diff --git a/src/liblsquic/lsquic_stream.c b/src/liblsquic/lsquic_stream.c index fa57af0..6929fdc 100644 --- a/src/liblsquic/lsquic_stream.c +++ b/src/liblsquic/lsquic_stream.c @@ -909,11 +909,11 @@ lsquic_stream_readable (struct lsquic_stream *stream) int lsquic_stream_is_write_reset (const struct lsquic_stream *stream) { - if (stream->sm_bflags & SMBF_IETF) - return stream->stream_flags & STREAM_SS_RECVD; - else - return (stream->stream_flags & (STREAM_RST_RECVD|STREAM_RST_SENT)) - || (stream->sm_qflags & SMQF_SEND_RST); + /* The two protocols use different frames to effect write reset: */ + const enum stream_flags cause_flag = stream->sm_bflags & SMBF_IETF + ? STREAM_SS_RECVD : STREAM_RST_RECVD; + return (stream->stream_flags & (cause_flag|STREAM_RST_SENT)) + || (stream->sm_qflags & SMQF_SEND_RST); } diff --git a/tests/test_rechist.c b/tests/test_rechist.c index 4af4ce3..cc46ffd 100644 --- a/tests/test_rechist.c +++ b/tests/test_rechist.c @@ -121,6 +121,7 @@ test_range_copy (struct lsquic_rechist *orig, int ietf) { char orig_str[0x1000], new_str[0x1000]; struct lsquic_rechist new; + size_t len; rechist2str(orig, orig_str, sizeof(orig_str)); @@ -130,6 +131,19 @@ test_range_copy (struct lsquic_rechist *orig, int ietf) (const struct lsquic_packno_range * (*) (void *)) lsquic_rechist_next); rechist2str(&new, new_str, sizeof(new_str)); assert(0 == strcmp(orig_str, new_str)); + lsquic_rechist_cleanup(&new); + + /* This tests that lower-numbered ranges do not overwrite higher-numbered + * ranges. + */ + lsquic_rechist_init(&new, ietf, 10); + lsquic_rechist_copy_ranges(&new, orig, + (const struct lsquic_packno_range * (*) (void *)) lsquic_rechist_first, + (const struct lsquic_packno_range * (*) (void *)) lsquic_rechist_next); + rechist2str(&new, new_str, sizeof(new_str)); + len = strlen(new_str); + assert(0 == strncmp(orig_str, new_str, len)); + lsquic_rechist_cleanup(&new); }