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.
This commit is contained in:
Dmitri Tikhonov 2020-09-02 09:03:19 -04:00
parent 792df0522e
commit 49f1f4f620
26 changed files with 201 additions and 209 deletions

View File

@ -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.

View File

@ -26,7 +26,7 @@ author = u'LiteSpeed Technologies'
# 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 ---------------------------------------------------

View File

@ -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:

View File

@ -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)(
&params, 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);

View File

@ -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;
}

View File

@ -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,
&timestamp);
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);
}

View File

@ -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

View File

@ -21,6 +21,7 @@
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
@ -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),

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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) \

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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;

View File

@ -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,

View File

@ -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);
}

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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;

View File

@ -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));