Skip to content

Commit

Permalink
Release 1.19.3
Browse files Browse the repository at this point in the history
- [BUGFIX] Q044: don't encode packet number in 6 bytes.  Six-byte
  packet number encoding does not exist in Q044.  This fixes a
  regression introduced in '[BUGFIX] Buffered packets can contain
  ACK frames' -- we need to keep QUIC version in mind when selecting
  the longest possible packet number encoding used for the buffered
  packet that carries the ACK.
- [BUGFIX] Do not increase CWND when timeout occurs.
- http_client: support setting handshake timeout on command line.
  Use -o handshake_to=timeout.
- http_client: use -k to connect UDP socket to pick up ICMP errors.
- http_client: allow pathless mode, when only handshake is performed
  without issuing any requests.  This can be done by simply not
  specifying a -p flag on the command line.
  • Loading branch information
Dmitri Tikhonov committed Feb 18, 2019
1 parent 3329170 commit 9c44452
Show file tree
Hide file tree
Showing 12 changed files with 113 additions and 20 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
2019-02-18
- 1.19.3
- [BUGFIX] Q044: don't encode packet number in 6 bytes. Six-byte
packet number encoding does not exist in Q044. This fixes a
regression introduced in '[BUGFIX] Buffered packets can contain
ACK frames' -- we need to keep QUIC version in mind when selecting
the longest possible packet number encoding used for the buffered
packet that carries the ACK.
- [BUGFIX] Do not increase CWND when timeout occurs.
- http_client: support setting handshake timeout on command line.
Use -o handshake_to=timeout.
- http_client: use -k to connect UDP socket to pick up ICMP errors.
- http_client: allow pathless mode, when only handshake is performed
without issuing any requests. This can be done by simply not
specifying a -p flag on the command line.

2019-02-11
- 1.19.2
- [BUGFIX] Begin negotiation with version provided in 0-RTT info.
Expand Down
2 changes: 1 addition & 1 deletion include/lsquic.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ extern "C" {

#define LSQUIC_MAJOR_VERSION 1
#define LSQUIC_MINOR_VERSION 19
#define LSQUIC_PATCH_VERSION 2
#define LSQUIC_PATCH_VERSION 3

/**
* Engine flags:
Expand Down
8 changes: 6 additions & 2 deletions src/liblsquic/lsquic_cubic.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,14 @@ lsquic_cubic_loss (struct lsquic_cubic *cubic)
void
lsquic_cubic_timeout (struct lsquic_cubic *cubic)
{
unsigned long cwnd;

cwnd = cubic->cu_cwnd;
LSQ_DEBUG("%s(cubic)", __func__);
cubic_reset(cubic);
cubic->cu_ssthresh = cubic->cu_cwnd;
cubic->cu_tcp_cwnd = cubic->cu_cwnd;
cubic->cu_ssthresh = cwnd / 2;
cubic->cu_tcp_cwnd = 2 * TCP_MSS;
cubic->cu_cwnd = 2 * TCP_MSS;
LSQ_INFO("timeout, cwnd: %lu", cubic->cu_cwnd);
LOG_CWND(cubic);
}
1 change: 1 addition & 0 deletions src/liblsquic/lsquic_full_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -2106,6 +2106,7 @@ process_incoming_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
}
LSQ_DEBUG("end of version negotiation: agreed upon %s",
lsquic_ver2str[conn->fc_ver_neg.vn_ver]);
lsquic_send_ctl_verneg_done(&conn->fc_send_ctl);
}
return process_regular_packet(conn, packet_in);
}
Expand Down
2 changes: 1 addition & 1 deletion src/liblsquic/lsquic_handshake.c
Original file line number Diff line number Diff line change
Expand Up @@ -1923,7 +1923,7 @@ lsquic_enc_session_get_zero_rtt (lsquic_enc_session_t *enc_session,
sz += sizeof(struct lsquic_zero_rtt_storage);
if (len < sz)
{
LSQ_DEBUG("client provided buf is too small %lu < %lu", len, sz);
LSQ_DEBUG("client provided buf is too small %zu < %zu", len, sz);
errno = ENOBUFS;
return -1;
}
Expand Down
27 changes: 24 additions & 3 deletions src/liblsquic/lsquic_send_ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ lsquic_send_ctl_init (lsquic_send_ctl_t *ctl, struct lsquic_alarmset *alset,
for (i = 0; i < sizeof(ctl->sc_buffered_packets) /
sizeof(ctl->sc_buffered_packets[0]); ++i)
TAILQ_INIT(&ctl->sc_buffered_packets[i].bpq_packets);
ctl->sc_max_packno_bits = PACKNO_LEN_4; /* Safe value before verneg */
}


Expand Down Expand Up @@ -1698,7 +1699,7 @@ send_ctl_get_buffered_packet (lsquic_send_ctl_t *ctl,
{
LSQ_DEBUG("steal ACK frame from low-priority buffered queue");
ack_action = AA_STEAL;
bits = PACKNO_LEN_6;
bits = ctl->sc_max_packno_bits;
}
/* If ACK can be generated, write it to the first buffered packet. */
else if (lconn->cn_if->ci_can_write_ack(lconn))
Expand All @@ -1709,7 +1710,7 @@ send_ctl_get_buffered_packet (lsquic_send_ctl_t *ctl,
/* Packet length is set to the largest possible size to guarantee
* that buffered packet with the ACK will not need to be split.
*/
bits = PACKNO_LEN_6;
bits = ctl->sc_max_packno_bits;
}
else
goto no_ack_action;
Expand Down Expand Up @@ -1781,12 +1782,17 @@ enum lsquic_packno_bits
lsquic_send_ctl_calc_packno_bits (lsquic_send_ctl_t *ctl)
{
lsquic_packno_t smallest_unacked;
enum lsquic_packno_bits bits;
unsigned n_in_flight;

smallest_unacked = lsquic_send_ctl_smallest_unacked(ctl);
n_in_flight = lsquic_cubic_get_cwnd(&ctl->sc_cubic) / ctl->sc_pack_size;
return calc_packno_bits(ctl->sc_cur_packno + 1, smallest_unacked,
bits = calc_packno_bits(ctl->sc_cur_packno + 1, smallest_unacked,
n_in_flight);
if (bits <= ctl->sc_max_packno_bits)
return bits;
else
return ctl->sc_max_packno_bits;
}


Expand Down Expand Up @@ -1929,3 +1935,18 @@ lsquic_send_ctl_mem_used (const struct lsquic_send_ctl *ctl)

return size;
}


void
lsquic_send_ctl_verneg_done (struct lsquic_send_ctl *ctl)
{
if ((1 << ctl->sc_conn_pub->lconn->cn_version) &
LSQUIC_GQUIC_HEADER_VERSIONS)
ctl->sc_max_packno_bits = PACKNO_LEN_6;
else
/* Assuming Q044 */
ctl->sc_max_packno_bits = PACKNO_LEN_4;
LSQ_DEBUG("version negotiation done (%s): max packno bits: %u",
lsquic_ver2str[ ctl->sc_conn_pub->lconn->cn_version ],
ctl->sc_max_packno_bits);
}
4 changes: 4 additions & 0 deletions src/liblsquic/lsquic_send_ctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ typedef struct lsquic_send_ctl {
} sc_cached_bpt;
unsigned sc_next_limit;
unsigned sc_n_scheduled;
enum lsquic_packno_bits sc_max_packno_bits;
#if LSQUIC_SEND_STATS
struct {
unsigned n_total_sent,
Expand Down Expand Up @@ -283,4 +284,7 @@ int
lsquic_send_ctl_buffered_and_same_prio_as_headers (struct lsquic_send_ctl *,
const struct lsquic_stream *);

void
lsquic_send_ctl_verneg_done (struct lsquic_send_ctl *);

#endif
25 changes: 14 additions & 11 deletions test/http_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ create_connections (struct http_client_ctx *client_ctx)
{
zero_rtt = client_ctx->hcc_zero_rtt;
zero_rtt_len = client_ctx->hcc_zero_rtt_len;
LSQ_INFO("create connection zero_rtt %ld bytes", zero_rtt_len);
LSQ_INFO("create connection zero_rtt %zu bytes", zero_rtt_len);
}

while (client_ctx->hcc_n_open_conns < client_ctx->hcc_concurrency &&
Expand Down Expand Up @@ -268,7 +268,8 @@ http_client_on_new_conn (void *stream_if_ctx, lsquic_conn_t *conn)
client_ctx->hcc_total_n_reqs -= conn_h->ch_n_reqs;
TAILQ_INSERT_TAIL(&client_ctx->conn_ctxs, conn_h, next_ch);
++conn_h->client_ctx->hcc_n_open_conns;
create_streams(client_ctx, conn_h);
if (!TAILQ_EMPTY(&client_ctx->hcc_path_elems))
create_streams(client_ctx, conn_h);
conn_h->ch_created = lsquic_time_now();
return conn_h;
}
Expand Down Expand Up @@ -365,7 +366,7 @@ http_client_on_hsk_done (lsquic_conn_t *conn, enum lsquic_hsk_status status)
if (ret > 0)
{
client_ctx->hcc_zero_rtt_len = ret;
LSQ_INFO("get zero_rtt %ld bytes", client_ctx->hcc_zero_rtt_len);
LSQ_INFO("get zero_rtt %zu bytes", client_ctx->hcc_zero_rtt_len);
client_ctx->hcc_flags |= HCC_RTT_INFO;
/* clear file and prepare to write */
if (client_ctx->hcc_zero_rtt_file)
Expand All @@ -392,7 +393,7 @@ http_client_on_hsk_done (lsquic_conn_t *conn, enum lsquic_hsk_status status)
size_t ret2 = fwrite(client_ctx->hcc_zero_rtt, 1,
client_ctx->hcc_zero_rtt_len,
client_ctx->hcc_zero_rtt_file);
LSQ_DEBUG("wrote %ld bytes to zero_rtt file", ret2);
LSQ_DEBUG("wrote %zu bytes to zero_rtt file", ret2);
if (ret2 == client_ctx->hcc_zero_rtt_len)
{
fclose(client_ctx->hcc_zero_rtt_file);
Expand All @@ -419,6 +420,11 @@ http_client_on_hsk_done (lsquic_conn_t *conn, enum lsquic_hsk_status status)
++s_stat_conns_ok;
update_sample_stats(&s_stat_to_conn,
lsquic_time_now() - conn_h->ch_created);
if (TAILQ_EMPTY(&client_ctx->hcc_path_elems))
{
LSQ_INFO("no paths mode: close connection");
lsquic_conn_close(conn_h->conn);
}
}
else
++s_stat_conns_failed;
Expand Down Expand Up @@ -762,7 +768,9 @@ usage (const char *prog)
"Usage: %s [opts]\n"
"\n"
"Options:\n"
" -p PATH Path to request. May be specified more than once.\n"
" -p PATH Path to request. May be specified more than once. If no\n"
" path is specified, the connection is closed as soon as\n"
" handshake succeeds.\n"
" -n CONNS Number of concurrent connections. Defaults to 1.\n"
" -r NREQS Total number of requests to send. Defaults to 1.\n"
" -R MAXREQS Maximum number of requests per single connection. Some\n"
Expand Down Expand Up @@ -1180,16 +1188,11 @@ main (int argc, char **argv)
{
client_ctx.hcc_flags |= HCC_RTT_INFO;
client_ctx.hcc_zero_rtt_len = ret;
LSQ_DEBUG("read %ld bytes from zero_rtt file", ret);
LSQ_DEBUG("read %zu bytes from zero_rtt file", ret);
}
else
LSQ_DEBUG("zero_rtt file is empty");
}
if (TAILQ_EMPTY(&client_ctx.hcc_path_elems))
{
fprintf(stderr, "Specify at least one path using -p option\n");
exit(1);
}

start_time = lsquic_time_now();
if (0 != prog_prep(&prog))
Expand Down
10 changes: 10 additions & 0 deletions test/prog.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ prog_print_common_options (const struct prog *prog, FILE *out)


fprintf(out,
" -k Connect UDP socket. Only meant to be used with clients\n"
" to pick up ICMP errors.\n"
" -i USECS Clock granularity in microseconds. Defaults to %u.\n",
LSQUIC_DF_CLOCK_GRANULARITY
);
Expand Down Expand Up @@ -239,6 +241,14 @@ prog_set_opt (struct prog *prog, int opt, const char *arg)
return -1;
}
}
case 'k':
{
struct service_port *sport = TAILQ_LAST(prog->prog_sports, sport_head);
if (!sport)
sport = &prog->prog_dummy_sport;
sport->sp_flags |= SPORT_CONNECT;
}
return 0;
default:
return 1;
}
Expand Down
2 changes: 1 addition & 1 deletion test/prog.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ prog_init (struct prog *, unsigned lsquic_engine_flags, struct sport_head *,
# define IP_DONTFRAG_FLAG ""
#endif

#define PROG_OPTS "i:m:c:y:L:l:o:H:s:S:Y:z:" IP_DONTFRAG_FLAG
#define PROG_OPTS "i:km:c:y:L:l:o:H:s:S:Y:z:" IP_DONTFRAG_FLAG

/* Returns:
* 0 Applied
Expand Down
35 changes: 34 additions & 1 deletion test/test_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,13 @@ read_one_packet (struct read_iter *iter)
}


#if __GNUC__
# define UNLIKELY(cond) __builtin_expect(cond, 0)
#else
# define UNLIKELY(cond) cond
#endif


static void
read_handler (evutil_socket_t fd, short flags, void *ctx)
{
Expand All @@ -570,6 +577,14 @@ read_handler (evutil_socket_t fd, short flags, void *ctx)
rop = read_one_packet(&iter);
while (ROP_OK == rop);

if (UNLIKELY(ROP_ERROR == rop && (sport->sp_flags & SPORT_CONNECT)
&& errno == ECONNREFUSED))
{
LSQ_ERROR("connection refused: exit program");
prog_cleanup(sport->sp_prog);
exit(1);
}

n_batches += iter.ri_idx > 0;

for (n = 0; n < iter.ri_idx; ++n)
Expand Down Expand Up @@ -623,7 +638,7 @@ sport_init_client (struct service_port *sport, struct lsquic_engine *engine,
int flags;
#endif
SOCKET_TYPE sockfd;
socklen_t socklen;
socklen_t socklen, peer_socklen;
union {
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
Expand Down Expand Up @@ -663,6 +678,19 @@ sport_init_client (struct service_port *sport, struct lsquic_engine *engine,
return -1;
}

if (sport->sp_flags & SPORT_CONNECT)
{
peer_socklen = AF_INET == sa_peer->sa_family
? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
if (0 != connect(sockfd, sa_peer, peer_socklen))
{
saved_errno = errno;
CLOSE_SOCKET(sockfd);
errno = saved_errno;
return -1;
}
}

/* Make socket non-blocking */
#ifndef WIN32
flags = fcntl(sockfd, F_GETFL);
Expand Down Expand Up @@ -1079,6 +1107,11 @@ set_engine_option (struct lsquic_engine_settings *settings,
settings->es_pace_packets = atoi(val);
return 0;
}
if (0 == strncmp(name, "handshake_to", 12))
{
settings->es_handshake_to = atoi(val);
return 0;
}
break;
case 13:
if (0 == strncmp(name, "support_tcid0", 13))
Expand Down
1 change: 1 addition & 0 deletions test/test_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ enum sport_flags
SPORT_SET_SNDBUF = (1 << 1), /* SO_SNDBUF */
SPORT_SET_RCVBUF = (1 << 2), /* SO_RCVBUF */
SPORT_SERVER = (1 << 3),
SPORT_CONNECT = (1 << 4),
};

struct service_port {
Expand Down

0 comments on commit 9c44452

Please sign in to comment.