From 49f1f4f620faf235adf16eb7bcee768e906796a4 Mon Sep 17 00:00:00 2001 From: Dmitri Tikhonov Date: Wed, 2 Sep 2020 09:03:19 -0400 Subject: [PATCH] Release 2.19.8 - [FEATURE] Update the timestamp extension to latest version. - [FEATURE] Cope with appearance of ECN blackholes. - [OPTIMIZATION] return packno offset and size when header is generated. - [BUGFIX] ignore old ACK frames in mini conns. - [BUGFIX] Mark initial server path as initialized. - [BUGFIX] Do not merge ACK if ECN counts do not match. - Turn incoming packet number history in mini conn back on. - Record mini conn event history again when compiled in debug mode. - IETF mini conn: log when ACK is queued. - Clean up and refactor code in several places. --- CHANGELOG | 13 +++++ docs/conf.py | 2 +- include/lsquic.h | 2 +- src/liblsquic/lsquic_enc_sess_ietf.c | 18 ++---- src/liblsquic/lsquic_frame_reader.c | 29 ++++------ src/liblsquic/lsquic_full_conn_ietf.c | 70 ++++++++++++++--------- src/liblsquic/lsquic_handshake.c | 5 +- src/liblsquic/lsquic_mini_conn.c | 32 +++++++++-- src/liblsquic/lsquic_mini_conn.h | 7 +-- src/liblsquic/lsquic_mini_conn_ietf.c | 4 +- src/liblsquic/lsquic_packet_common.h | 5 ++ src/liblsquic/lsquic_packet_gquic.h | 9 --- src/liblsquic/lsquic_packet_out.c | 4 +- src/liblsquic/lsquic_packet_resize.c | 2 +- src/liblsquic/lsquic_parse.h | 9 +-- src/liblsquic/lsquic_parse_Q046.c | 12 +--- src/liblsquic/lsquic_parse_Q050.c | 51 ++++++----------- src/liblsquic/lsquic_parse_gquic_be.c | 12 +--- src/liblsquic/lsquic_parse_gquic_common.c | 15 ++++- src/liblsquic/lsquic_parse_ietf_v1.c | 43 ++++---------- src/liblsquic/lsquic_send_ctl.c | 35 +++++++----- src/liblsquic/lsquic_send_ctl.h | 5 +- src/liblsquic/lsquic_trans_params.c | 14 +++-- src/liblsquic/lsquic_trans_params.h | 6 +- tests/test_packet_resize.c | 4 +- tests/test_reg_pkt_headergen.c | 2 +- 26 files changed, 201 insertions(+), 209 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 1a1ac1bd8..c1b8fdd09 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,16 @@ +2020-09-02 + - 2.19.8 + - [FEATURE] Update the timestamp extension to latest version. + - [FEATURE] Cope with appearance of ECN blackholes. + - [OPTIMIZATION] return packno offset and size when header is generated. + - [BUGFIX] ignore old ACK frames in mini conns. + - [BUGFIX] Mark initial server path as initialized. + - [BUGFIX] Do not merge ACK if ECN counts do not match. + - Turn incoming packet number history in mini conn back on. + - Record mini conn event history again when compiled in debug mode. + - IETF mini conn: log when ACK is queued. + - Clean up and refactor code in several places. + 2020-08-26 - 2.19.7 - Handle ECT-CE event: issue a loss event. diff --git a/docs/conf.py b/docs/conf.py index 1a5279071..f3df41f6f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -26,7 +26,7 @@ # The short X.Y version version = u'2.19' # The full version, including alpha/beta/rc tags -release = u'2.19.7' +release = u'2.19.8' # -- General configuration --------------------------------------------------- diff --git a/include/lsquic.h b/include/lsquic.h index 1ddd770a8..a7f7a8ab7 100644 --- a/include/lsquic.h +++ b/include/lsquic.h @@ -25,7 +25,7 @@ extern "C" { #define LSQUIC_MAJOR_VERSION 2 #define LSQUIC_MINOR_VERSION 19 -#define LSQUIC_PATCH_VERSION 7 +#define LSQUIC_PATCH_VERSION 8 /** * Engine flags: diff --git a/src/liblsquic/lsquic_enc_sess_ietf.c b/src/liblsquic/lsquic_enc_sess_ietf.c index f3c9fe03d..df5e3cf36 100644 --- a/src/liblsquic/lsquic_enc_sess_ietf.c +++ b/src/liblsquic/lsquic_enc_sess_ietf.c @@ -623,7 +623,10 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf, params.tp_set |= 1 << TPI_MIN_ACK_DELAY; } if (settings->es_timestamps) + { + params.tp_numerics[TPI_TIMESTAMPS] = TS_GENERATE_THEM; params.tp_set |= 1 << TPI_TIMESTAMPS; + } len = (version == LSQVER_ID27 ? lsquic_tp_encode_27 : lsquic_tp_encode)( ¶ms, enc_sess->esi_flags & ESI_SERVER, buf, bufsz); @@ -1570,15 +1573,6 @@ get_crypto_params (const struct enc_sess_iquic *enc_sess, return -1; } - /* FIXME: figure out why this duplicate check is here and either fix it - * or get rid of it. - */ - if (key_sz > EVP_MAX_KEY_LENGTH) - { - LSQ_DEBUG("PN size %u is too large", key_sz); - return -1; - } - return 0; } @@ -1987,11 +1981,8 @@ iquic_esf_encrypt_packet (enc_session_t *enc_session_p, #endif *((uint64_t *) begin_xor) ^= packno; - /* TODO: have this call return packno_off and packno_len to avoid - * another function call. - */ header_sz = lconn->cn_pf->pf_gen_reg_pkt_header(lconn, packet_out, dst, - dst_sz); + dst_sz, &packno_off, &packno_len); if (header_sz < 0) goto err; if (enc_level == ENC_LEV_FORW) @@ -2017,7 +2008,6 @@ iquic_esf_encrypt_packet (enc_session_t *enc_session_p, } assert(out_sz == dst_sz - header_sz); - lconn->cn_pf->pf_packno_info(lconn, packet_out, &packno_off, &packno_len); #ifndef NDEBUG const unsigned sample_off = packno_off + 4; assert(sample_off + IQUIC_TAG_LEN <= dst_sz); diff --git a/src/liblsquic/lsquic_frame_reader.c b/src/liblsquic/lsquic_frame_reader.c index 5fecf56b1..11ff7b9ca 100644 --- a/src/liblsquic/lsquic_frame_reader.c +++ b/src/liblsquic/lsquic_frame_reader.c @@ -561,8 +561,7 @@ skip_headers (struct lsquic_frame_reader *fr) } -/* TODO: this function always returns 0. Make it void */ -static int +static void decode_and_pass_payload (struct lsquic_frame_reader *fr) { struct headers_state *hs = &fr->fr_state.by_type.headers_state; @@ -588,7 +587,7 @@ decode_and_pass_payload (struct lsquic_frame_reader *fr) if (!target_stream) { skip_headers(fr); - return 0; + return; } } hset = fr->fr_hsi_if->hsi_create_header_set(fr->fr_hsi_ctx, target_stream, @@ -688,14 +687,13 @@ decode_and_pass_payload (struct lsquic_frame_reader *fr) fr->fr_conn_stats->in.headers_comp += fr->fr_header_block_sz; #endif - return 0; + return; stream_error: LSQ_INFO("%s: stream error %u", __func__, err); if (hset) fr->fr_hsi_if->hsi_discard_header_set(hset); fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, fr_get_stream_id(fr), err); - return 0; } @@ -725,13 +723,12 @@ read_headers_block_fragment (struct lsquic_frame_reader *fr) if (hs->nread == payload_length && (fr->fr_state.header.hfh_flags & HFHF_END_HEADERS)) { - int rv = decode_and_pass_payload(fr); + decode_and_pass_payload(fr); free(fr->fr_header_block); fr->fr_header_block = NULL; - return rv; } - else - return 0; + + return 0; } @@ -865,20 +862,14 @@ read_contin (struct lsquic_frame_reader *fr) { if (fr->fr_state.header.hfh_flags & HFHF_END_HEADERS) { - int rv = decode_and_pass_payload(fr); + decode_and_pass_payload(fr); free(fr->fr_header_block); fr->fr_header_block = NULL; - reset_state(fr); - return rv; - } - else - { - reset_state(fr); - return 0; } + reset_state(fr); } - else - return 0; + + return 0; } diff --git a/src/liblsquic/lsquic_full_conn_ietf.c b/src/liblsquic/lsquic_full_conn_ietf.c index 7a7d3c2f5..4655738cf 100644 --- a/src/liblsquic/lsquic_full_conn_ietf.c +++ b/src/liblsquic/lsquic_full_conn_ietf.c @@ -145,6 +145,7 @@ enum more_flags MF_CHECK_MTU_PROBE = 1 << 2, MF_IGNORE_MISSING = 1 << 3, MF_CONN_CLOSE_PACK = 1 << 4, /* CONNECTION_CLOSE has been packetized */ + MF_SEND_WRONG_COUNTS= 1 << 5, /* Send wrong ECN counts to peer */ }; @@ -1400,7 +1401,7 @@ lsquic_ietf_full_conn_server_new (struct lsquic_engine_public *enpub, conn->ifc_flags |= IFC_IGNORE_INIT; conn->ifc_paths[0].cop_path = imc->imc_path; - conn->ifc_paths[0].cop_flags = COP_VALIDATED; + conn->ifc_paths[0].cop_flags = COP_VALIDATED|COP_INITIALIZED; conn->ifc_used_paths = 1 << 0; if (imc->imc_flags & IMC_ADDR_VALIDATED) lsquic_send_ctl_path_validated(&conn->ifc_send_ctl); @@ -1540,8 +1541,6 @@ lsquic_ietf_full_conn_server_new (struct lsquic_engine_public *enpub, conn->ifc_conn_ctx = conn->ifc_enpub->enp_stream_if->on_new_conn( conn->ifc_enpub->enp_stream_if_ctx, &conn->ifc_conn); - /* TODO: do something if there is outgoing ACK */ - if (0 != handshake_ok(&conn->ifc_conn)) goto err3; @@ -1666,6 +1665,14 @@ generate_ack_frame_for_pns (struct ietf_full_conn *conn, if (conn->ifc_incoming_ecn && lsquic_send_ctl_ecn_turned_on(&conn->ifc_send_ctl)) ecn_counts = conn->ifc_ecn_counts_in[pns]; + else if ((conn->ifc_mflags & MF_SEND_WRONG_COUNTS) && pns == PNS_APP) + { + /* We try once. A more advanced version would wait until we get a + * packet from peer and only then stop. + */ + conn->ifc_mflags &= ~MF_SEND_WRONG_COUNTS; + ecn_counts = conn->ifc_ecn_counts_in[pns]; + } else ecn_counts = NULL; @@ -3262,9 +3269,10 @@ handshake_ok (struct lsquic_conn *lconn) conn->ifc_flags |= IFC_DELAYED_ACKS; } if (conn->ifc_settings->es_timestamps - && (params->tp_set & (1 << TPI_TIMESTAMPS))) + && (params->tp_set & (1 << TPI_TIMESTAMPS)) + && (params->tp_numerics[TPI_TIMESTAMPS] & TS_WANT_THEM)) { - LSQ_DEBUG("timestamps enabled"); + LSQ_DEBUG("timestamps enabled: will send TIMESTAMP frames"); conn->ifc_flags |= IFC_TIMESTAMPS; } @@ -5909,29 +5917,9 @@ static unsigned process_timestamp_frame (struct ietf_full_conn *conn, struct lsquic_packet_in *packet_in, const unsigned char *p, size_t len) { - uint64_t timestamp; - int parsed_len; - - if (!(conn->ifc_flags & IFC_TIMESTAMPS)) - { - ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION, + ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION, "Received unexpected TIMESTAMP frame (not negotiated)"); - return 0; - } - - parsed_len = conn->ifc_conn.cn_pf->pf_parse_timestamp_frame(p, len, - ×tamp); - if (parsed_len < 0) - return 0; - - timestamp <<= conn->ifc_cfg.ack_exp; - EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "TIMESTAMP(%"PRIu64" us)", timestamp); - LSQ_DEBUG("TIMESTAMP(%"PRIu64" us) (%"PRIu64" << %"PRIu8")", timestamp, - timestamp >> conn->ifc_cfg.ack_exp, conn->ifc_cfg.ack_exp); - - /* We don't do anything with the timestamp */ - - return parsed_len; + return 0; } @@ -6167,6 +6155,16 @@ many_in_and_will_write (struct ietf_full_conn *conn) } +static void +force_queueing_ack_app (struct ietf_full_conn *conn) +{ + lsquic_alarmset_unset(&conn->ifc_alset, AL_ACK_APP); + lsquic_send_ctl_sanity_check(&conn->ifc_send_ctl); + conn->ifc_flags |= IFC_ACK_QUED_APP; + LSQ_DEBUG("force-queued ACK"); +} + + static void try_queueing_ack_app (struct ietf_full_conn *conn, int was_missing, int ecn, lsquic_time_t now) @@ -7184,6 +7182,22 @@ ietf_full_conn_ci_retx_timeout (struct lsquic_conn *lconn) lsquic_send_ctl_resize(&conn->ifc_send_ctl); else LSQ_DEBUG("RTO occurred, but no MTUs to reset"); + + if (lsquic_send_ctl_ecn_turned_on(&conn->ifc_send_ctl)) + { + LSQ_INFO("RTO occurred, disable ECN"); + lsquic_send_ctl_disable_ecn(&conn->ifc_send_ctl); + if (lsquic_rechist_first(&conn->ifc_rechist[PNS_APP])) + { + LSQ_DEBUG("Send wrong ECN counts to peer so that it turns off " + "ECN as well"); + memset(conn->ifc_ecn_counts_in[PNS_APP], 0, + sizeof(conn->ifc_ecn_counts_in[PNS_APP])); + conn->ifc_mflags |= MF_SEND_WRONG_COUNTS; + force_queueing_ack_app(conn); + conn->ifc_send_flags |= SF_SEND_PING; + } + } } @@ -7878,13 +7892,13 @@ cancel_push_promise (struct ietf_full_conn *conn, struct push_promise *promise) LSQ_DEBUG("cancel promise %"PRIu64, promise->pp_id); /* Remove promise from hash to prevent multiple cancellations */ lsquic_hash_erase(conn->ifc_pub.u.ietf.promises, &promise->pp_hash_id); - lsquic_pp_put(promise, conn->ifc_pub.u.ietf.promises); /* But let stream dtor free the promise object as sm_promise may yet * be used by the stream in some ways. */ lsquic_stream_shutdown_internal(promise->pp_pushed_stream); if (0 != lsquic_hcso_write_cancel_push(&conn->ifc_hcso, promise->pp_id)) ABORT_WARN("cannot write CANCEL_PUSH"); + lsquic_pp_put(promise, conn->ifc_pub.u.ietf.promises); } diff --git a/src/liblsquic/lsquic_handshake.c b/src/liblsquic/lsquic_handshake.c index 9a8608187..ec52371f4 100644 --- a/src/liblsquic/lsquic_handshake.c +++ b/src/liblsquic/lsquic_handshake.c @@ -3625,7 +3625,7 @@ gquic_really_encrypt_packet (struct lsquic_enc_session *enc_session, unsigned char header_buf[GQUIC_MAX_PUBHDR_SZ]; header_sz = lconn->cn_pf->pf_gen_reg_pkt_header(lconn, packet_out, - header_buf, sizeof(header_buf)); + header_buf, sizeof(header_buf), NULL, NULL); if (header_sz < 0) return -1; @@ -3963,7 +3963,7 @@ gquic2_esf_encrypt_packet (enc_session_t *enc_session_p, *((uint64_t *) begin_xor) ^= packno; header_sz = lconn->cn_pf->pf_gen_reg_pkt_header(lconn, packet_out, dst, - dst_sz); + dst_sz, &packno_off, &packno_len); if (header_sz < 0) goto err; @@ -3987,7 +3987,6 @@ gquic2_esf_encrypt_packet (enc_session_t *enc_session_p, } assert(out_sz == dst_sz - header_sz); - lconn->cn_pf->pf_packno_info(lconn, packet_out, &packno_off, &packno_len); if (!packet_out->po_nonce) divers_nonce_len = 0; else diff --git a/src/liblsquic/lsquic_mini_conn.c b/src/liblsquic/lsquic_mini_conn.c index a0d5b01da..a45f39656 100644 --- a/src/liblsquic/lsquic_mini_conn.c +++ b/src/liblsquic/lsquic_mini_conn.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -291,6 +292,8 @@ process_ack_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in, LSQ_DEBUG("Ignore old ack (max %u)", mc->mc_max_ack_packno); return parsed_len; } + if (packet_in->pi_packno <= UCHAR_MAX) + mc->mc_max_ack_packno = packet_in->pi_packno; /* Verify ACK frame and update list of acked packet numbers: */ for (n = 0; n < acki->n_ranges; ++n) @@ -1185,7 +1188,7 @@ continue_handshake (struct mini_conn *mc) MCHIST_APPEND(mc, he == DATA_NOT_ENOUGH ? MCHE_HANDLE_NOT_ENOUGH : he == HS_SHLO ? MCHE_HANDLE_SHLO : he == HS_1RTT ? MCHE_HANDLE_1RTT : - he == HS_2RTT ? MCHE_HANDLE_2RTT : + he == HS_SREJ ? MCHE_HANDLE_SREJ : he == HS_ERROR ? MCHE_HANDLE_ERROR : MCHE_HAHDLE_UNKNOWN); @@ -1701,6 +1704,7 @@ process_deferred_packets (struct mini_conn *mc) #if LSQUIC_RECORD_INORD_HIST +/* FIXME This does not work for Q050, where 0 is a valid packet number. */ /* Packet number is encoded as a sequence of 1-bits and stored in mc_inord_hist * separated by 0 bits. For example, sequence of packet numbers 3, 2, 1 would * be encoded as (starting with LSB) 1110110100000000... This is not the most @@ -1731,6 +1735,26 @@ record_inord_packno (struct mini_conn *mc, lsquic_packno_t packno) } +#if __GNUC__ +# define ctz __builtin_ctzll +#else +static unsigned +ctz (unsigned long long x) +{ + unsigned n = 0; + if (0 == (x & ((1ULL << 32) - 1))) { n += 32; x >>= 32; } + if (0 == (x & ((1ULL << 16) - 1))) { n += 16; x >>= 16; } + if (0 == (x & ((1ULL << 8) - 1))) { n += 8; x >>= 8; } + if (0 == (x & ((1ULL << 4) - 1))) { n += 4; x >>= 4; } + if (0 == (x & ((1ULL << 2) - 1))) { n += 2; x >>= 2; } + if (0 == (x & ((1ULL << 1) - 1))) { n += 1; x >>= 1; } + return n; +} + + +#endif + + static void inord_to_str (const struct mini_conn *mc, char *buf, size_t bufsz) { @@ -1747,7 +1771,7 @@ inord_to_str (const struct mini_conn *mc, char *buf, size_t bufsz) hist = mc->mc_inord_hist[n]; while (hist) { - n_trail = __builtin_ctzll(~hist); + n_trail = ctz(~hist); nw = snprintf(buf + off, bufsz - off, /* No spaces are included on purpose: this makes it a single * field and thus easy to process log using standard command- @@ -2001,7 +2025,7 @@ mini_conn_ci_destroy (struct lsquic_conn *lconn) mc->mc_received_packnos, mc->mc_sent_packnos, mc->mc_lost_packnos, mc->mc_deferred_packnos, still_deferred, mc->mc_dropped_packnos, in_flight, mc->mc_acked_packnos, - mc->mc_error_code, mc->mc_n_ticks, mc->mc_conn.cn_pack_size, + mc->mc_error_code, mc->mc_n_ticks, mc->mc_path.np_pack_size, lsquic_time_now() - mc->mc_created, lsquic_ver2str[mc->mc_conn.cn_version], (int) hist_idx, mc->mc_hist_buf); @@ -2025,7 +2049,7 @@ mini_conn_ci_destroy (struct lsquic_conn *lconn) mc->mc_received_packnos, mc->mc_sent_packnos, mc->mc_lost_packnos, mc->mc_deferred_packnos, still_deferred, mc->mc_dropped_packnos, in_flight, mc->mc_acked_packnos, - mc->mc_error_code, mc->mc_n_ticks, mc->mc_conn.cn_pack_size, + mc->mc_error_code, mc->mc_n_ticks, mc->mc_path.np_pack_size, lsquic_time_now() - mc->mc_created, lsquic_ver2str[mc->mc_conn.cn_version], (int) (sizeof(mc->mc_hist_buf) - hist_idx), diff --git a/src/liblsquic/lsquic_mini_conn.h b/src/liblsquic/lsquic_mini_conn.h index a0ac419c8..84298b8b5 100644 --- a/src/liblsquic/lsquic_mini_conn.h +++ b/src/liblsquic/lsquic_mini_conn.h @@ -21,7 +21,7 @@ struct lsquic_engine_public; #ifndef LSQUIC_KEEP_MINICONN_HISTORY # ifndef NDEBUG -# define LSQUIC_KEEP_MINICONN_HISTORY 0 /* XXX */ +# define LSQUIC_KEEP_MINICONN_HISTORY 1 # else # define LSQUIC_KEEP_MINICONN_HISTORY 0 # endif @@ -38,7 +38,7 @@ enum miniconn_history_event MCHE_EMPTY = '\0', MCHE_PLUS = '+', MCHE_HANDLE_1RTT = '1', - MCHE_HANDLE_2RTT = '2', + MCHE_HANDLE_SREJ = '2', MCHE_PACKET2LARGE_IN = 'a', MCHE_CONN_CLOSE = 'c', MCHE_CREATED = 'C', @@ -74,7 +74,7 @@ enum miniconn_history_event #ifndef LSQUIC_RECORD_INORD_HIST # if __GNUC__ -# define LSQUIC_RECORD_INORD_HIST 0 /* XXX */ +# define LSQUIC_RECORD_INORD_HIST 1 # else # define LSQUIC_RECORD_INORD_HIST 0 # endif @@ -112,7 +112,6 @@ struct mini_conn { unsigned short mc_read_off, /* Read offset for stream 1 */ mc_write_off;/* Write offset for stream 1 */ unsigned char mc_max_ack_packno, - /* XXX: mc_max_ack_packno is never set */ mc_cutoff, mc_cur_packno; unsigned char mc_hsk_count; diff --git a/src/liblsquic/lsquic_mini_conn_ietf.c b/src/liblsquic/lsquic_mini_conn_ietf.c index 6a2e016cf..98aabdb5e 100644 --- a/src/liblsquic/lsquic_mini_conn_ietf.c +++ b/src/liblsquic/lsquic_mini_conn_ietf.c @@ -1294,6 +1294,8 @@ ietf_mini_conn_ci_packet_in (struct lsquic_conn *lconn, return; } + if (!(conn->imc_flags & (IMC_QUEUED_ACK_INIT << pns))) + LSQ_DEBUG("queued ACK in %s", lsquic_pns2str[pns]); conn->imc_flags |= IMC_QUEUED_ACK_INIT << pns; ++conn->imc_ecn_counts_in[pns][ lsquic_packet_in_ecn(packet_in) ]; conn->imc_incoming_ecn <<= 1; @@ -1567,7 +1569,7 @@ imico_generate_ack (struct ietf_mini_conn *conn, enum packnum_space pns, packet_out->po_data_sz += len; packet_out->po_regen_sz += len; conn->imc_flags &= ~(IMC_QUEUED_ACK_INIT << pns); - LSQ_DEBUG("wrote ACK frame of size %d", len); + LSQ_DEBUG("wrote ACK frame of size %d in %s", len, lsquic_pns2str[pns]); return 0; } diff --git a/src/liblsquic/lsquic_packet_common.h b/src/liblsquic/lsquic_packet_common.h index 4fd28e259..837fbbc36 100644 --- a/src/liblsquic/lsquic_packet_common.h +++ b/src/liblsquic/lsquic_packet_common.h @@ -240,4 +240,9 @@ extern const char *const lsquic_pns2str[]; extern const enum quic_ft_bit lsquic_legal_frames_by_level[][4]; +/* Applies both to gQUIC and IETF QUIC, thus "B" for "both" */ +#define BQUIC_FRAME_REGEN_MASK ((1 << QUIC_FRAME_ACK) \ + | (1 << QUIC_FRAME_PATH_CHALLENGE) | (1 << QUIC_FRAME_PATH_RESPONSE) \ + | (1 << QUIC_FRAME_STOP_WAITING) | (1 << QUIC_FRAME_TIMESTAMP)) + #endif diff --git a/src/liblsquic/lsquic_packet_gquic.h b/src/liblsquic/lsquic_packet_gquic.h index 138e36c0a..c23561a76 100644 --- a/src/liblsquic/lsquic_packet_gquic.h +++ b/src/liblsquic/lsquic_packet_gquic.h @@ -16,15 +16,6 @@ enum PACKET_PUBLIC_FLAGS PACKET_PUBLIC_FLAGS_TWO_OR_MORE_BYTES = 1 << 7, }; -/* XXX The name of this macro no longer matches: it applies both to gQUIC and - * IETF QUIC. - */ -#define GQUIC_FRAME_REGEN_MASK ((1 << QUIC_FRAME_ACK) \ - | (1 << QUIC_FRAME_PATH_CHALLENGE) | (1 << QUIC_FRAME_PATH_RESPONSE) \ - | (1 << QUIC_FRAME_STOP_WAITING) | (1 << QUIC_FRAME_TIMESTAMP)) - -#define GQUIC_FRAME_REGENERATE(frame_type) ((1 << (frame_type)) & GQUIC_FRAME_REGEN_MASK) - #define GQUIC_FRAME_ACKABLE_MASK ( \ (1 << QUIC_FRAME_STREAM) \ | (1 << QUIC_FRAME_RST_STREAM) \ diff --git a/src/liblsquic/lsquic_packet_out.c b/src/liblsquic/lsquic_packet_out.c index 5830d8e5a..0043428c8 100644 --- a/src/liblsquic/lsquic_packet_out.c +++ b/src/liblsquic/lsquic_packet_out.c @@ -371,7 +371,7 @@ lsquic_packet_out_chop_regen (lsquic_packet_out_t *packet_out) frec = lsquic_pofi_next(&pofi)) { frec->fe_off -= adj; - if (GQUIC_FRAME_REGEN_MASK & (1 << frec->fe_frame_type)) + if (BQUIC_FRAME_REGEN_MASK & (1 << frec->fe_frame_type)) { assert(frec->fe_off == 0); /* This checks that all the regen frames are at the beginning of the packet. It can be removed @@ -388,7 +388,7 @@ lsquic_packet_out_chop_regen (lsquic_packet_out_t *packet_out) assert(adj); /* Otherwise why are we called? */ assert(packet_out->po_regen_sz == adj); packet_out->po_regen_sz = 0; - packet_out->po_frame_types &= ~GQUIC_FRAME_REGEN_MASK; + packet_out->po_frame_types &= ~BQUIC_FRAME_REGEN_MASK; } diff --git a/src/liblsquic/lsquic_packet_resize.c b/src/liblsquic/lsquic_packet_resize.c index 39aab7967..dc85c051f 100644 --- a/src/liblsquic/lsquic_packet_resize.c +++ b/src/liblsquic/lsquic_packet_resize.c @@ -201,7 +201,7 @@ lsquic_packet_resize_next (struct packet_resize_ctx *prctx) } else if (prctx->prc_cur_frec->fe_len <= lsquic_packet_out_avail(new)) { - if ((1 << frec->fe_frame_type) & GQUIC_FRAME_REGEN_MASK) + if ((1 << frec->fe_frame_type) & BQUIC_FRAME_REGEN_MASK) { if (new->po_regen_sz == new->po_data_sz) new->po_regen_sz += frec->fe_len; diff --git a/src/liblsquic/lsquic_parse.h b/src/liblsquic/lsquic_parse.h index 7d2012fd9..a81f27963 100644 --- a/src/liblsquic/lsquic_parse.h +++ b/src/liblsquic/lsquic_parse.h @@ -68,7 +68,9 @@ struct parse_funcs /* Return buf length */ int (*pf_gen_reg_pkt_header) (const struct lsquic_conn *, - const struct lsquic_packet_out *, unsigned char *, size_t); + const struct lsquic_packet_out *, unsigned char *, size_t, + /* In Q050 and IETF QUIC, these are set: */ + unsigned *packno_off, unsigned *packno_len); void (*pf_parse_packet_in_finish) (struct lsquic_packet_in *packet_in, struct packin_parse_state *); @@ -223,11 +225,6 @@ struct parse_funcs unsigned (*pf_packno_bits2len) (enum packno_bits); - /* Used by IETF QUIC and gQUIC >= Q050 */ - void - (*pf_packno_info) (const struct lsquic_conn *, - const struct lsquic_packet_out *, unsigned *packno_off, - unsigned *packno_len); int (*pf_parse_max_data) (const unsigned char *, size_t, uint64_t *); int diff --git a/src/liblsquic/lsquic_parse_Q046.c b/src/liblsquic/lsquic_parse_Q046.c index 0b8742482..420c714f5 100644 --- a/src/liblsquic/lsquic_parse_Q046.c +++ b/src/liblsquic/lsquic_parse_Q046.c @@ -188,7 +188,7 @@ gen_long_pkt_header (const struct lsquic_conn *lconn, static int gquic_Q046_gen_reg_pkt_header (const struct lsquic_conn *lconn, const struct lsquic_packet_out *packet_out, unsigned char *buf, - size_t bufsz) + size_t bufsz, unsigned *packno_off_UNUSED, unsigned *packno_len_UNUSED) { if (0 == (packet_out->po_flags & PO_LONGHEAD)) return gen_short_pkt_header(lconn, packet_out, buf, bufsz); @@ -281,15 +281,6 @@ gquic_Q046_parse_crypto_frame (const unsigned char *buf, size_t rem_packet_sz, } -static void -gquic_Q046_packno_info (const struct lsquic_conn *lconn, - const struct lsquic_packet_out *packet_out, unsigned *packno_off, - unsigned *packno_len) -{ - assert(0); -} - - /* No simple PRST for Q046 */ static ssize_t gquic_Q046_generate_simple_prst (const lsquic_cid_t *cidp, unsigned char *buf, @@ -357,7 +348,6 @@ const struct parse_funcs lsquic_parse_funcs_gquic_Q046 = .pf_packno_bits2len = gquic_Q046_packno_bits2len, .pf_gen_crypto_frame = gquic_Q046_gen_crypto_frame, .pf_parse_crypto_frame = gquic_Q046_parse_crypto_frame, - .pf_packno_info = gquic_Q046_packno_info, .pf_gen_handshake_done_frame = gquic_Q046_gen_handshake_done_frame, .pf_parse_handshake_done_frame = gquic_Q046_parse_handshake_done_frame, .pf_handshake_done_frame_size = gquic_Q046_handshake_done_frame_size, diff --git a/src/liblsquic/lsquic_parse_Q050.c b/src/liblsquic/lsquic_parse_Q050.c index 40180b848..c2ca0a1e8 100644 --- a/src/liblsquic/lsquic_parse_Q050.c +++ b/src/liblsquic/lsquic_parse_Q050.c @@ -259,10 +259,11 @@ write_packno (unsigned char *p, lsquic_packno_t packno, enum packno_bits bits) static int gen_short_pkt_header (const struct lsquic_conn *lconn, const struct lsquic_packet_out *packet_out, unsigned char *buf, - size_t bufsz) + size_t bufsz, unsigned *packno_off_p, unsigned *packno_len_p) { unsigned packno_len, need; enum packno_bits bits; + unsigned char *p = buf; bits = lsquic_packet_out_packno_bits(packet_out); packno_len = iquic_packno_bits2len(bits); @@ -275,15 +276,17 @@ gen_short_pkt_header (const struct lsquic_conn *lconn, if (need > bufsz) return -1; - *buf++ = 0x40 | bits; + *p++ = 0x40 | bits; if (0 == (lconn->cn_flags & LSCONN_SERVER)) { - memcpy(buf, lconn->cn_cid.idbuf, 8); - buf += 8; + memcpy(p, lconn->cn_cid.idbuf, 8); + p += 8; } - (void) write_packno(buf, packet_out->po_packno, bits); + *packno_off_p = p - buf; + *packno_len_p = packno_len; + (void) write_packno(p, packet_out->po_packno, bits); return need; } @@ -349,35 +352,10 @@ gquic_Q050_packout_header_size_long_by_packet (const struct lsquic_conn *lconn, } -static void -gquic_Q050_packno_info (const struct lsquic_conn *lconn, - const struct lsquic_packet_out *packet_out, unsigned *packno_off, - unsigned *packno_len) -{ - unsigned token_len; /* Need intermediate value to quiet compiler warning */ - - if (packet_out->po_header_type == HETY_NOT_SET) - *packno_off = 1 + - (lconn->cn_flags & LSCONN_SERVER ? 0 : 8); - else - *packno_off = 1 - + 4 - + 1 - + 1 - + lconn->cn_cid.len - + (packet_out->po_header_type == HETY_INITIAL ? - (token_len = packet_out->po_token_len, - (1 << vint_val2bits(token_len)) + token_len) : 0) - + 2; - *packno_len = iquic_packno_bits2len( - lsquic_packet_out_packno_bits(packet_out)); -} - - static int gquic_Q050_gen_long_pkt_header (const struct lsquic_conn *lconn, const struct lsquic_packet_out *packet_out, unsigned char *buf, - size_t bufsz) + size_t bufsz, unsigned *packno_off_p, unsigned *packno_len_p) { enum packno_bits packno_bits; lsquic_ver_tag_t ver_tag; @@ -434,6 +412,8 @@ gquic_Q050_gen_long_pkt_header (const struct lsquic_conn *lconn, bits = 1; /* Always use two bytes to encode payload length */ vint_write(p, payload_len, bits, 1 << bits); p += 1 << bits; + *packno_off_p = p - buf; + *packno_len_p = iquic_packno_bits2len(packno_bits); p += write_packno(p, packet_out->po_packno, packno_bits); if (packet_out->po_nonce) @@ -450,12 +430,14 @@ gquic_Q050_gen_long_pkt_header (const struct lsquic_conn *lconn, static int gquic_Q050_gen_reg_pkt_header (const struct lsquic_conn *lconn, const struct lsquic_packet_out *packet_out, unsigned char *buf, - size_t bufsz) + size_t bufsz, unsigned *packno_off, unsigned *packno_len) { if (0 == (packet_out->po_flags & PO_LONGHEAD)) - return gen_short_pkt_header(lconn, packet_out, buf, bufsz); + return gen_short_pkt_header(lconn, packet_out, buf, bufsz, + packno_off, packno_len); else - return gquic_Q050_gen_long_pkt_header(lconn, packet_out, buf, bufsz); + return gquic_Q050_gen_long_pkt_header(lconn, packet_out, buf, bufsz, + packno_off, packno_len); } @@ -896,7 +878,6 @@ const struct parse_funcs lsquic_parse_funcs_gquic_Q050 = .pf_packno_bits2len = gquic_Q050_packno_bits2len, .pf_gen_crypto_frame = gquic_Q050_gen_crypto_frame, .pf_parse_crypto_frame = gquic_Q050_parse_crypto_frame, - .pf_packno_info = gquic_Q050_packno_info, .pf_calc_crypto_frame_header_sz = gquic_Q050_calc_crypto_frame_header_sz, .pf_gen_handshake_done_frame = gquic_Q050_gen_handshake_done_frame, .pf_parse_handshake_done_frame = gquic_Q050_parse_handshake_done_frame, diff --git a/src/liblsquic/lsquic_parse_gquic_be.c b/src/liblsquic/lsquic_parse_gquic_be.c index b3de902a6..c629c2a67 100644 --- a/src/liblsquic/lsquic_parse_gquic_be.c +++ b/src/liblsquic/lsquic_parse_gquic_be.c @@ -108,7 +108,7 @@ lsquic_gquic_be_parse_packet_in_finish (lsquic_packet_in_t *packet_in, static int lsquic_gquic_be_gen_reg_pkt_header (const struct lsquic_conn *lconn, const struct lsquic_packet_out *packet_out, unsigned char *buf, - size_t bufsz) + size_t bufsz, unsigned *packno_off_UNUSED, unsigned *packno_len_UNUSED) { unsigned packnum_len, header_len; enum packno_bits bits; @@ -1003,15 +1003,6 @@ lsquic_gquic_be_parse_crypto_frame (const unsigned char *buf, size_t rem_packet_ } -static void -lsquic_gquic_be_packno_info (const struct lsquic_conn *lconn, - const struct lsquic_packet_out *packet_out, unsigned *packno_off, - unsigned *packno_len) -{ - assert(0); -} - - static unsigned gquic_Q043_handshake_done_frame_size (void) { @@ -1071,7 +1062,6 @@ const struct parse_funcs lsquic_parse_funcs_gquic_Q043 = .pf_packno_bits2len = lsquic_gquic_packno_bits2len, .pf_gen_crypto_frame = lsquic_gquic_be_gen_crypto_frame, .pf_parse_crypto_frame = lsquic_gquic_be_parse_crypto_frame, - .pf_packno_info = lsquic_gquic_be_packno_info, .pf_gen_handshake_done_frame = gquic_Q043_gen_handshake_done_frame, .pf_parse_handshake_done_frame = gquic_Q043_parse_handshake_done_frame, .pf_handshake_done_frame_size = gquic_Q043_handshake_done_frame_size, diff --git a/src/liblsquic/lsquic_parse_gquic_common.c b/src/liblsquic/lsquic_parse_gquic_common.c index 644530f47..b85d913e9 100644 --- a/src/liblsquic/lsquic_parse_gquic_common.c +++ b/src/liblsquic/lsquic_parse_gquic_common.c @@ -641,6 +641,7 @@ lsquic_merge_acks (struct ack_info *dst, const struct ack_info *src) const struct lsquic_packno_range *a, *a_end, *b, *b_end, **p; struct lsquic_packno_range *out, *out_end; unsigned i; + int ok; struct lsquic_packno_range out_ranges[256]; if (!(dst->n_ranges && src->n_ranges)) @@ -687,9 +688,21 @@ lsquic_merge_acks (struct ack_info *dst, const struct ack_info *src) } if (src->flags & AI_ECN) + { + /* New ACK frame (src) should not contain ECN counts that are smaller + * than previous ACK frame, otherwise we cannot merge. + */ + ok = 1; for (i = 0; i < sizeof(src->ecn_counts) / sizeof(src->ecn_counts[0]); ++i) - dst->ecn_counts[i] += src->ecn_counts[i]; + ok &= dst->ecn_counts[i] <= src->ecn_counts[i]; + if (ok) + for (i = 0; i < sizeof(src->ecn_counts) + / sizeof(src->ecn_counts[0]); ++i) + dst->ecn_counts[i] = src->ecn_counts[i]; + else + return -1; + } dst->flags |= src->flags; dst->lack_delta = src->lack_delta; dst->n_ranges = out - out_ranges; diff --git a/src/liblsquic/lsquic_parse_ietf_v1.c b/src/liblsquic/lsquic_parse_ietf_v1.c index 2d44c34e2..ef99cc96d 100644 --- a/src/liblsquic/lsquic_parse_ietf_v1.c +++ b/src/liblsquic/lsquic_parse_ietf_v1.c @@ -192,7 +192,7 @@ write_packno (unsigned char *p, lsquic_packno_t packno, static int gen_long_pkt_header (const struct lsquic_conn *lconn, const struct lsquic_packet_out *packet_out, unsigned char *buf, - size_t bufsz) + size_t bufsz, unsigned *packno_off_p, unsigned *packno_len_p) { unsigned payload_len, bits; enum packno_bits packno_bits; @@ -242,6 +242,8 @@ gen_long_pkt_header (const struct lsquic_conn *lconn, vint_write(p, payload_len, bits, 1 << bits); p += 1 << bits; + *packno_off_p = p - buf; + *packno_len_p = iquic_packno_bits2len(packno_bits); p += write_packno(p, packet_out->po_packno, packno_bits); return p - buf; @@ -251,7 +253,7 @@ gen_long_pkt_header (const struct lsquic_conn *lconn, static int gen_short_pkt_header (const struct lsquic_conn *lconn, const struct lsquic_packet_out *packet_out, unsigned char *buf, - size_t bufsz) + size_t bufsz, unsigned *packno_off_p, unsigned *packno_len_p) { unsigned packno_len, cid_len, need; enum packno_bits packno_bits; @@ -277,6 +279,8 @@ gen_short_pkt_header (const struct lsquic_conn *lconn, (void) write_packno(buf + 1 + cid_len, packet_out->po_packno, packno_bits); + *packno_off_p = 1 + cid_len; + *packno_len_p = packno_len; return need; } @@ -284,38 +288,14 @@ gen_short_pkt_header (const struct lsquic_conn *lconn, static int ietf_v1_gen_reg_pkt_header (const struct lsquic_conn *lconn, const struct lsquic_packet_out *packet_out, unsigned char *buf, - size_t bufsz) + size_t bufsz, unsigned *packno_off, unsigned *packno_len) { if (packet_out->po_header_type == HETY_NOT_SET) - return gen_short_pkt_header(lconn, packet_out, buf, bufsz); + return gen_short_pkt_header(lconn, packet_out, buf, bufsz, packno_off, + packno_len); else - return gen_long_pkt_header(lconn, packet_out, buf, bufsz); -} - - -static void -ietf_v1_packno_info (const struct lsquic_conn *lconn, - const struct lsquic_packet_out *packet_out, unsigned *packno_off, - unsigned *packno_len) -{ - unsigned token_len; /* Need intermediate value to quiet compiler warning */ - - if (packet_out->po_header_type == HETY_NOT_SET) - *packno_off = 1 + - (packet_out->po_flags & PO_CONN_ID ? packet_out->po_path->np_dcid.len : 0); - else - *packno_off = 1 - + 4 - + 1 - + packet_out->po_path->np_dcid.len - + 1 - + CN_SCID(lconn)->len - + (packet_out->po_header_type == HETY_INITIAL ? - (token_len = packet_out->po_token_len, - (1 << vint_val2bits(token_len)) + token_len) : 0) - + 2; - *packno_len = iquic_packno_bits2len( - lsquic_packet_out_packno_bits(packet_out)); + return gen_long_pkt_header(lconn, packet_out, buf, bufsz, packno_off, + packno_len); } @@ -2166,7 +2146,6 @@ const struct parse_funcs lsquic_parse_funcs_ietf_v1 = .pf_parse_path_resp_frame = ietf_v1_parse_path_resp_frame, .pf_calc_packno_bits = ietf_v1_calc_packno_bits, .pf_packno_bits2len = ietf_v1_packno_bits2len, - .pf_packno_info = ietf_v1_packno_info, .pf_gen_crypto_frame = ietf_v1_gen_crypto_frame, .pf_parse_crypto_frame = ietf_v1_parse_crypto_frame, .pf_calc_crypto_frame_header_sz = ietf_v1_calc_crypto_frame_header_sz, diff --git a/src/liblsquic/lsquic_send_ctl.c b/src/liblsquic/lsquic_send_ctl.c index 6ca6cb157..2d55eb437 100644 --- a/src/liblsquic/lsquic_send_ctl.c +++ b/src/liblsquic/lsquic_send_ctl.c @@ -382,13 +382,6 @@ lsquic_send_ctl_init (lsquic_send_ctl_t *ctl, struct lsquic_alarmset *alset, } -static int -send_ctl_ecn_on (const struct lsquic_send_ctl *ctl) -{ - return ctl->sc_ecn != ECN_NOT_ECT; -} - - static lsquic_time_t calculate_packet_rto (lsquic_send_ctl_t *ctl) { @@ -861,13 +854,13 @@ send_ctl_handle_regular_lost_packet (struct lsquic_send_ctl *ctl, ctl->sc_ci->cci_lost(CGP(ctl), packet_out, packet_sz); /* This is a client-only check, server check happens in mini conn */ - if (send_ctl_ecn_on(ctl) + if (lsquic_send_ctl_ecn_turned_on(ctl) && 0 == ctl->sc_ecn_total_acked[PNS_INIT] && HETY_INITIAL == packet_out->po_header_type && 3 == packet_out->po_packno) { LSQ_DEBUG("possible ECN black hole during handshake, disable ECN"); - ctl->sc_ecn = ECN_NOT_ECT; + lsquic_send_ctl_disable_ecn(ctl); } if (packet_out->po_frame_types & ctl->sc_retx_frames) @@ -1217,7 +1210,7 @@ lsquic_send_ctl_got_ack (lsquic_send_ctl_t *ctl, if (one_rtt_cnt) ctl->sc_flags |= SC_1RTT_ACKED; - if (send_ctl_ecn_on(ctl)) + if (lsquic_send_ctl_ecn_turned_on(ctl)) { const uint64_t sum = acki->ecn_counts[ECN_ECT0] + acki->ecn_counts[ECN_ECT1] @@ -1250,7 +1243,7 @@ lsquic_send_ctl_got_ack (lsquic_send_ctl_t *ctl, LSQ_INFO("ECN total ACKed (%"PRIu64") is greater than the sum " "of ECN counters (%"PRIu64"): disable ECN", ctl->sc_ecn_total_acked[pns], sum); - ctl->sc_ecn = ECN_NOT_ECT; + lsquic_send_ctl_disable_ecn(ctl); } } @@ -2145,7 +2138,7 @@ update_for_resending (lsquic_send_ctl_t *ctl, lsquic_packet_out_t *packet_out) packno = send_ctl_next_packno(ctl); packet_out->po_flags &= ~PO_SENT_SZ; - packet_out->po_frame_types &= ~GQUIC_FRAME_REGEN_MASK; + packet_out->po_frame_types &= ~BQUIC_FRAME_REGEN_MASK; assert(packet_out->po_frame_types); packet_out->po_packno = packno; lsquic_packet_out_set_ecn(packet_out, ctl->sc_ecn); @@ -2541,7 +2534,7 @@ send_ctl_move_ack (struct lsquic_send_ctl *ctl, struct lsquic_packet_out *dst, * buffered packet to another. We don't generate any other regen frame * types in buffered packets. */ - assert(!(GQUIC_FRAME_REGEN_MASK & (1 << src->po_frame_types) + assert(!(BQUIC_FRAME_REGEN_MASK & (1 << src->po_frame_types) & ~QUIC_FTBIT_ACK)); if (lsquic_packet_out_avail(dst) >= src->po_regen_sz @@ -2555,8 +2548,8 @@ send_ctl_move_ack (struct lsquic_send_ctl *ctl, struct lsquic_packet_out *dst, return -1; dst->po_data_sz = src->po_regen_sz; dst->po_regen_sz = src->po_regen_sz; - dst->po_frame_types |= (GQUIC_FRAME_REGEN_MASK & src->po_frame_types); - src->po_frame_types &= ~GQUIC_FRAME_REGEN_MASK; + dst->po_frame_types |= (BQUIC_FRAME_REGEN_MASK & src->po_frame_types); + src->po_frame_types &= ~BQUIC_FRAME_REGEN_MASK; lsquic_packet_out_chop_regen(src); } @@ -3517,3 +3510,15 @@ lsquic_send_ctl_can_send_probe (const struct lsquic_send_ctl *ctl, else return n_out + path->np_pack_size < cwnd; } + + +void +lsquic_send_ctl_disable_ecn (struct lsquic_send_ctl *ctl) +{ + struct lsquic_packet_out *packet_out; + + LSQ_INFO("disable ECN"); + ctl->sc_ecn = ECN_NOT_ECT; + TAILQ_FOREACH(packet_out, &ctl->sc_scheduled_packets, po_next) + lsquic_packet_out_set_ecn(packet_out, ECN_NOT_ECT); +} diff --git a/src/liblsquic/lsquic_send_ctl.h b/src/liblsquic/lsquic_send_ctl.h index bae577fae..82b2b0a53 100644 --- a/src/liblsquic/lsquic_send_ctl.h +++ b/src/liblsquic/lsquic_send_ctl.h @@ -407,6 +407,9 @@ int lsquic_send_ctl_can_send_probe (const struct lsquic_send_ctl *, const struct network_path *); -#define lsquic_send_ctl_ecn_turned_on(ctl_) ((ctl_)->sc_flags & SC_ECN) +#define lsquic_send_ctl_ecn_turned_on(ctl_) ((ctl_)->sc_ecn != ECN_NOT_ECT) + +void +lsquic_send_ctl_disable_ecn (struct lsquic_send_ctl *); #endif diff --git a/src/liblsquic/lsquic_trans_params.c b/src/liblsquic/lsquic_trans_params.c index 3d547321c..0e0e03f83 100644 --- a/src/liblsquic/lsquic_trans_params.c +++ b/src/liblsquic/lsquic_trans_params.c @@ -60,7 +60,7 @@ tpi_val_2_enum (uint64_t tpi_val) case 0x1057: return TPI_LOSS_BITS; case 0x2AB2: return TPI_GREASE_QUIC_BIT; case 0xDE1A: return TPI_MIN_ACK_DELAY; - case 0x7157: return TPI_TIMESTAMPS; + case 0x7158: return TPI_TIMESTAMPS; default: return INT_MAX; } } @@ -90,7 +90,7 @@ static const unsigned enum_2_tpi_val[LAST_TPI + 1] = #endif [TPI_LOSS_BITS] = 0x1057, [TPI_MIN_ACK_DELAY] = 0xDE1A, - [TPI_TIMESTAMPS] = 0x7157, + [TPI_TIMESTAMPS] = 0x7158, [TPI_GREASE_QUIC_BIT] = 0x2AB2, }; @@ -159,6 +159,7 @@ static const uint64_t max_vals[MAX_NUMERIC_TPI + 1] = [TPI_ACTIVE_CONNECTION_ID_LIMIT] = VINT_MAX_VALUE, [TPI_LOSS_BITS] = 1, [TPI_MIN_ACK_DELAY] = (1u << 24) - 1u, + [TPI_TIMESTAMPS] = TS_WANT_THEM|TS_GENERATE_THEM, }; @@ -168,6 +169,7 @@ static const uint64_t min_vals[MAX_NUMERIC_TPI + 1] = [TPI_MAX_UDP_PAYLOAD_SIZE] = 1200, [TPI_MIN_ACK_DELAY] = 1, [TPI_ACTIVE_CONNECTION_ID_LIMIT] = 2, + [TPI_TIMESTAMPS] = TS_WANT_THEM, }; @@ -372,6 +374,7 @@ lsquic_tp_encode (const struct transport_params *params, int is_server, case TPI_ACTIVE_CONNECTION_ID_LIMIT: case TPI_LOSS_BITS: case TPI_MIN_ACK_DELAY: + case TPI_TIMESTAMPS: vint_write(p, 1 << bits[tpi][2], bits[tpi][1], 1 << bits[tpi][1]); p += 1 << bits[tpi][1]; @@ -412,7 +415,6 @@ lsquic_tp_encode (const struct transport_params *params, int is_server, sizeof(params->tp_preferred_address.srst)); break; case TPI_DISABLE_ACTIVE_MIGRATION: - case TPI_TIMESTAMPS: case TPI_GREASE_QUIC_BIT: *p++ = 0; break; @@ -498,6 +500,7 @@ lsquic_tp_decode (const unsigned char *const buf, size_t bufsz, case TPI_ACTIVE_CONNECTION_ID_LIMIT: case TPI_LOSS_BITS: case TPI_MIN_ACK_DELAY: + case TPI_TIMESTAMPS: switch (len) { case 1: @@ -536,7 +539,6 @@ lsquic_tp_decode (const unsigned char *const buf, size_t bufsz, } break; case TPI_DISABLE_ACTIVE_MIGRATION: - case TPI_TIMESTAMPS: case TPI_GREASE_QUIC_BIT: EXPECT_LEN(0); break; @@ -881,6 +883,7 @@ lsquic_tp_encode_27 (const struct transport_params *params, int is_server, case TPI_ACTIVE_CONNECTION_ID_LIMIT: case TPI_LOSS_BITS: case TPI_MIN_ACK_DELAY: + case TPI_TIMESTAMPS: vint_write(p, 1 << bits[tpi][2], bits[tpi][1], 1 << bits[tpi][1]); p += 1 << bits[tpi][1]; @@ -923,7 +926,6 @@ lsquic_tp_encode_27 (const struct transport_params *params, int is_server, sizeof(params->tp_preferred_address.srst)); break; case TPI_DISABLE_ACTIVE_MIGRATION: - case TPI_TIMESTAMPS: case TPI_GREASE_QUIC_BIT: *p++ = 0; break; @@ -1009,6 +1011,7 @@ lsquic_tp_decode_27 (const unsigned char *const buf, size_t bufsz, case TPI_ACTIVE_CONNECTION_ID_LIMIT: case TPI_LOSS_BITS: case TPI_MIN_ACK_DELAY: + case TPI_TIMESTAMPS: switch (len) { case 1: @@ -1047,7 +1050,6 @@ lsquic_tp_decode_27 (const unsigned char *const buf, size_t bufsz, } break; case TPI_DISABLE_ACTIVE_MIGRATION: - case TPI_TIMESTAMPS: EXPECT_LEN(0); break; case TPI_STATELESS_RESET_TOKEN: diff --git a/src/liblsquic/lsquic_trans_params.h b/src/liblsquic/lsquic_trans_params.h index e5612fba1..aab9edb98 100644 --- a/src/liblsquic/lsquic_trans_params.h +++ b/src/liblsquic/lsquic_trans_params.h @@ -33,12 +33,12 @@ enum transport_param_id * Numeric transport parameters without default values: */ TPI_MIN_ACK_DELAY, + TPI_TIMESTAMPS, TPI_LOSS_BITS, MAX_NUMERIC_TPI = TPI_LOSS_BITS, /* * Empty transport parameters: */ - TPI_TIMESTAMPS, TPI_GREASE_QUIC_BIT, TPI_DISABLE_ACTIVE_MIGRATION, MAX_EMPTY_TPI = TPI_DISABLE_ACTIVE_MIGRATION, @@ -176,4 +176,8 @@ lsquic_tp_has_pref_ipv6 (const struct transport_params *); extern const char * const lsquic_tpi2str[LAST_TPI + 1]; +/* From [draft-huitema-quic-ts-03] */ +#define TS_WANT_THEM 1 +#define TS_GENERATE_THEM 2 + #endif diff --git a/tests/test_packet_resize.c b/tests/test_packet_resize.c index 92f2b220f..43b8d6d02 100644 --- a/tests/test_packet_resize.c +++ b/tests/test_packet_resize.c @@ -334,7 +334,7 @@ make_non_stream_frame (struct test_ctx *ctx, fill_byte, frame_type, packet_out->po_data_sz, nbytes); packet_out->po_data_sz += nbytes; packet_out->po_frame_types |= 1 << frame_type; - if ((1 << frame_type) & GQUIC_FRAME_REGEN_MASK) + if ((1 << frame_type) & BQUIC_FRAME_REGEN_MASK) packet_out->po_regen_sz += nbytes; LSQ_DEBUG("wrote %s frame of %zd bytes", frame_type_2_str[frame_type], nbytes); @@ -482,7 +482,7 @@ verify_non_stream_frames (struct test_ctx *ctx, const struct test_spec *spec) for (frec = lsquic_pofi_first(&pofi, packet_out); frec; frec = lsquic_pofi_next(&pofi)) { - if ((1 << frec->fe_frame_type) & GQUIC_FRAME_REGEN_MASK) + if ((1 << frec->fe_frame_type) & BQUIC_FRAME_REGEN_MASK) { assert(regen_sz == 0 || regen_sz == off); regen_sz += frec->fe_len; diff --git a/tests/test_reg_pkt_headergen.c b/tests/test_reg_pkt_headergen.c index 4cb03e0cf..ca561370d 100644 --- a/tests/test_reg_pkt_headergen.c +++ b/tests/test_reg_pkt_headergen.c @@ -220,7 +220,7 @@ run_test (int i) unsigned char out[GQUIC_MAX_PUBHDR_SZ]; int len = test->pf->pf_gen_reg_pkt_header(&lconn, &packet_out, out, - sizeof(out)); + sizeof(out), NULL, NULL); assert(("Packet length is correct", len == test->len));