Release 2.26.0

- [OPTIMIZATION] Adjust packet reordering threshold when spurious losses
  are detected.
- [API] Pass pointer to local sockaddr to ea_get_ssl_ctx() callback.
This commit is contained in:
Dmitri Tikhonov 2020-12-09 09:11:03 -05:00
parent 7f96c7c7f3
commit fcbdf653b6
11 changed files with 98 additions and 25 deletions

View file

@ -1,3 +1,9 @@
2020-12-09
- 2.26.0
- [OPTIMIZATION] Adjust packet reordering threshold when spurious losses
are detected.
- [API] Pass pointer to local sockaddr to ea_get_ssl_ctx() callback.
2020-12-04 2020-12-04
- 2.25.0 - 2.25.0
- [API, FEATURE] Add es_delay_onclose option to delay on_close until all - [API, FEATURE] Add es_delay_onclose option to delay on_close until all

View file

@ -39,7 +39,7 @@
static int prog_stopped; static int prog_stopped;
static SSL_CTX * get_ssl_ctx (void *); static SSL_CTX * get_ssl_ctx (void *, const struct sockaddr *);
static const struct lsquic_packout_mem_if pmi = { static const struct lsquic_packout_mem_if pmi = {
.pmi_allocate = pba_allocate, .pmi_allocate = pba_allocate,
@ -417,7 +417,7 @@ prog_init_client (struct prog *prog)
static SSL_CTX * static SSL_CTX *
get_ssl_ctx (void *peer_ctx) get_ssl_ctx (void *peer_ctx, const struct sockaddr *unused)
{ {
const struct service_port *const sport = peer_ctx; const struct service_port *const sport = peer_ctx;
return sport->sp_prog->prog_ssl_ctx; return sport->sp_prog->prog_ssl_ctx;

View file

@ -257,10 +257,10 @@ optional members.
Look up certificate. Mandatory in server mode. Look up certificate. Mandatory in server mode.
.. member:: struct ssl_ctx_st * (*ea_get_ssl_ctx)(void *peer_ctx) .. member:: struct ssl_ctx_st * (*ea_get_ssl_ctx)(void *peer_ctx, const struct sockaddr *local)
Get SSL_CTX associated with a peer context. Mandatory in server Get SSL_CTX associated with a peer context. Mandatory in server
mode. This is use for default values for SSL instantiation. mode. This is used for default values for SSL instantiation.
.. member:: const struct lsquic_hset_if *ea_hsi_if .. member:: const struct lsquic_hset_if *ea_hsi_if
.. member:: void *ea_hsi_ctx .. member:: void *ea_hsi_ctx

View file

@ -24,9 +24,9 @@ copyright = u'2020, LiteSpeed Technologies'
author = u'LiteSpeed Technologies' author = u'LiteSpeed Technologies'
# The short X.Y version # The short X.Y version
version = u'2.25' version = u'2.26'
# The full version, including alpha/beta/rc tags # The full version, including alpha/beta/rc tags
release = u'2.25.0' release = u'2.26.0'
# -- General configuration --------------------------------------------------- # -- General configuration ---------------------------------------------------

View file

@ -863,7 +863,8 @@ The server requires SSL callbacks to be present. The basic required callback is
struct lsquic_engine_api { struct lsquic_engine_api {
lsquic_lookup_cert_f ea_lookup_cert; lsquic_lookup_cert_f ea_lookup_cert;
void *ea_cert_lu_ctx; void *ea_cert_lu_ctx;
struct ssl_ctx_st * (*ea_get_ssl_ctx)(void *peer_ctx); struct ssl_ctx_st * (*ea_get_ssl_ctx)(void *peer_ctx,
const struct sockaddr *local);
/* (Other members of the struct are not shown) */ /* (Other members of the struct are not shown) */
}; };

View file

@ -24,7 +24,7 @@ extern "C" {
#endif #endif
#define LSQUIC_MAJOR_VERSION 2 #define LSQUIC_MAJOR_VERSION 2
#define LSQUIC_MINOR_VERSION 25 #define LSQUIC_MINOR_VERSION 26
#define LSQUIC_PATCH_VERSION 0 #define LSQUIC_PATCH_VERSION 0
/** /**
@ -1274,7 +1274,8 @@ struct lsquic_engine_api
lsquic_lookup_cert_f ea_lookup_cert; lsquic_lookup_cert_f ea_lookup_cert;
void *ea_cert_lu_ctx; void *ea_cert_lu_ctx;
/** Mandatory callback for server, optional for client. */ /** Mandatory callback for server, optional for client. */
struct ssl_ctx_st * (*ea_get_ssl_ctx)(void *peer_ctx); struct ssl_ctx_st * (*ea_get_ssl_ctx)(void *peer_ctx,
const struct sockaddr *local);
/** /**
* Shared hash interface is optional. If set to zero, performance of * Shared hash interface is optional. If set to zero, performance of
* multiple LSQUIC instances will be degraded. * multiple LSQUIC instances will be degraded.

View file

@ -888,11 +888,20 @@ iquic_esfi_create_client (const char *hostname,
enc_sess->esi_alpn = am->alpn; enc_sess->esi_alpn = am->alpn;
} }
if (enc_sess->esi_enpub->enp_get_ssl_ctx if (enc_sess->esi_enpub->enp_get_ssl_ctx)
&& (ssl_ctx = enc_sess->esi_enpub->enp_get_ssl_ctx(peer_ctx))) {
set_app_ctx = 1; struct network_path *const path =
enc_sess->esi_conn->cn_if->ci_get_path(enc_sess->esi_conn, NULL);
ssl_ctx = enc_sess->esi_enpub->enp_get_ssl_ctx(peer_ctx,
NP_LOCAL_SA(path));
if (ssl_ctx)
set_app_ctx = 1;
else
goto create_new_ssl_ctx;
}
else else
{ {
create_new_ssl_ctx:
LSQ_DEBUG("Create new SSL_CTX"); LSQ_DEBUG("Create new SSL_CTX");
ssl_ctx = SSL_CTX_new(TLS_method()); ssl_ctx = SSL_CTX_new(TLS_method());
if (!ssl_ctx) if (!ssl_ctx)
@ -1363,6 +1372,7 @@ static int
iquic_esfi_init_server (enc_session_t *enc_session_p) iquic_esfi_init_server (enc_session_t *enc_session_p)
{ {
struct enc_sess_iquic *const enc_sess = enc_session_p; struct enc_sess_iquic *const enc_sess = enc_session_p;
struct network_path *path;
const struct alpn_map *am; const struct alpn_map *am;
unsigned quic_ctx_idx; unsigned quic_ctx_idx;
int transpa_len; int transpa_len;
@ -1390,8 +1400,9 @@ iquic_esfi_init_server (enc_session_t *enc_session_p)
ok: enc_sess->esi_alpn = am->alpn; ok: enc_sess->esi_alpn = am->alpn;
} }
ssl_ctx = enc_sess->esi_enpub->enp_get_ssl_ctx( path = enc_sess->esi_conn->cn_if->ci_get_path(enc_sess->esi_conn, NULL);
lsquic_conn_get_peer_ctx(enc_sess->esi_conn, NULL)); ssl_ctx = enc_sess->esi_enpub->enp_get_ssl_ctx(path->np_peer_ctx,
NP_LOCAL_SA(path));
if (!ssl_ctx) if (!ssl_ctx)
{ {
LSQ_ERROR("fetching SSL context associated with peer context failed"); LSQ_ERROR("fetching SSL context associated with peer context failed");

View file

@ -20,6 +20,7 @@ struct ssl_ctx_st;
struct crand; struct crand;
struct evp_aead_ctx_st; struct evp_aead_ctx_st;
struct lsquic_server_config; struct lsquic_server_config;
struct sockaddr;
enum warning_type enum warning_type
{ {
@ -37,7 +38,8 @@ struct lsquic_engine_public {
struct token_generator *enp_tokgen; struct token_generator *enp_tokgen;
lsquic_lookup_cert_f enp_lookup_cert; lsquic_lookup_cert_f enp_lookup_cert;
void *enp_cert_lu_ctx; void *enp_cert_lu_ctx;
struct ssl_ctx_st * (*enp_get_ssl_ctx)(void *peer_ctx); struct ssl_ctx_st * (*enp_get_ssl_ctx)(void *peer_ctx,
const struct sockaddr *);
const struct lsquic_shared_hash_if const struct lsquic_shared_hash_if
*enp_shi; *enp_shi;
void *enp_shi_ctx; void *enp_shi_ctx;

View file

@ -166,6 +166,7 @@ typedef struct lsquic_packet_out
POL_HEADER_PROT = 1 << 9, /* Header protection applied */ POL_HEADER_PROT = 1 << 9, /* Header protection applied */
#endif #endif
POL_LIMITED = 1 << 10, /* Used to credit sc_next_limit if needed. */ POL_LIMITED = 1 << 10, /* Used to credit sc_next_limit if needed. */
POL_FACKED = 1 << 11, /* Lost due to FACK check */
} po_lflags:16; } po_lflags:16;
unsigned char *po_data; unsigned char *po_data;

View file

@ -417,6 +417,13 @@ lsquic_send_ctl_init (lsquic_send_ctl_t *ctl, struct lsquic_alarmset *alset,
ctl->sc_can_send = send_ctl_can_send_pre_hsk; ctl->sc_can_send = send_ctl_can_send_pre_hsk;
else else
ctl->sc_can_send = send_ctl_can_send; ctl->sc_can_send = send_ctl_can_send;
ctl->sc_reord_thresh = N_NACKS_BEFORE_RETX;
#if LSQUIC_DEVEL
const char *s;
s = getenv("LSQUIC_DYN_PTHRESH");
if (s == NULL || atoi(s))
ctl->sc_flags |= SC_DYN_PTHRESH;
#endif
} }
@ -884,7 +891,7 @@ send_ctl_destroy_chain (struct lsquic_send_ctl *ctl,
} }
static void static struct lsquic_packet_out *
send_ctl_record_loss (struct lsquic_send_ctl *ctl, send_ctl_record_loss (struct lsquic_send_ctl *ctl,
struct lsquic_packet_out *packet_out) struct lsquic_packet_out *packet_out)
{ {
@ -909,16 +916,21 @@ send_ctl_record_loss (struct lsquic_send_ctl *ctl,
* remove from the list: * remove from the list:
*/ */
TAILQ_INSERT_BEFORE(packet_out, loss_record, po_next); TAILQ_INSERT_BEFORE(packet_out, loss_record, po_next);
return loss_record;
} }
else else
{
LSQ_INFO("cannot allocate memory for loss record"); LSQ_INFO("cannot allocate memory for loss record");
return NULL;
}
} }
static int static struct lsquic_packet_out *
send_ctl_handle_regular_lost_packet (struct lsquic_send_ctl *ctl, send_ctl_handle_regular_lost_packet (struct lsquic_send_ctl *ctl,
lsquic_packet_out_t *packet_out, struct lsquic_packet_out **next) lsquic_packet_out_t *packet_out, struct lsquic_packet_out **next)
{ {
struct lsquic_packet_out *loss_record;
unsigned packet_sz; unsigned packet_sz;
assert(ctl->sc_n_in_flight_all); assert(ctl->sc_n_in_flight_all);
@ -952,11 +964,11 @@ send_ctl_handle_regular_lost_packet (struct lsquic_send_ctl *ctl,
{ {
LSQ_DEBUG("lost retransmittable packet %"PRIu64, LSQ_DEBUG("lost retransmittable packet %"PRIu64,
packet_out->po_packno); packet_out->po_packno);
send_ctl_record_loss(ctl, packet_out); loss_record = send_ctl_record_loss(ctl, packet_out);
send_ctl_unacked_remove(ctl, packet_out, packet_sz); send_ctl_unacked_remove(ctl, packet_out, packet_sz);
TAILQ_INSERT_TAIL(&ctl->sc_lost_packets, packet_out, po_next); TAILQ_INSERT_TAIL(&ctl->sc_lost_packets, packet_out, po_next);
packet_out->po_flags |= PO_LOST; packet_out->po_flags |= PO_LOST;
return 1; return loss_record;
} }
else else
{ {
@ -965,7 +977,7 @@ send_ctl_handle_regular_lost_packet (struct lsquic_send_ctl *ctl,
send_ctl_unacked_remove(ctl, packet_out, packet_sz); send_ctl_unacked_remove(ctl, packet_out, packet_sz);
send_ctl_destroy_chain(ctl, packet_out, next); send_ctl_destroy_chain(ctl, packet_out, next);
send_ctl_destroy_packet(ctl, packet_out); send_ctl_destroy_packet(ctl, packet_out);
return 0; return NULL;
} }
} }
@ -993,7 +1005,7 @@ send_ctl_handle_lost_packet (struct lsquic_send_ctl *ctl,
struct lsquic_packet_out *packet_out, struct lsquic_packet_out **next) struct lsquic_packet_out *packet_out, struct lsquic_packet_out **next)
{ {
if (0 == (packet_out->po_flags & PO_MTU_PROBE)) if (0 == (packet_out->po_flags & PO_MTU_PROBE))
return send_ctl_handle_regular_lost_packet(ctl, packet_out, next); return send_ctl_handle_regular_lost_packet(ctl, packet_out, next) != NULL;
else else
return send_ctl_handle_lost_mtu_probe(ctl, packet_out); return send_ctl_handle_lost_mtu_probe(ctl, packet_out);
} }
@ -1031,7 +1043,7 @@ static int
send_ctl_detect_losses (struct lsquic_send_ctl *ctl, enum packnum_space pns, send_ctl_detect_losses (struct lsquic_send_ctl *ctl, enum packnum_space pns,
lsquic_time_t time) lsquic_time_t time)
{ {
lsquic_packet_out_t *packet_out, *next; struct lsquic_packet_out *packet_out, *next, *loss_record;
lsquic_packno_t largest_retx_packno, largest_lost_packno; lsquic_packno_t largest_retx_packno, largest_lost_packno;
largest_retx_packno = largest_retx_packet_number(ctl, pns); largest_retx_packno = largest_retx_packet_number(ctl, pns);
@ -1047,14 +1059,22 @@ send_ctl_detect_losses (struct lsquic_send_ctl *ctl, enum packnum_space pns,
if (packet_out->po_flags & (PO_LOSS_REC|PO_POISON)) if (packet_out->po_flags & (PO_LOSS_REC|PO_POISON))
continue; continue;
if (packet_out->po_packno + N_NACKS_BEFORE_RETX < if (packet_out->po_packno + ctl->sc_reord_thresh <
ctl->sc_largest_acked_packno) ctl->sc_largest_acked_packno)
{ {
LSQ_DEBUG("loss by FACK detected, packet %"PRIu64, LSQ_DEBUG("loss by FACK detected (dist: %"PRIu64"), packet %"PRIu64,
ctl->sc_largest_acked_packno - packet_out->po_packno,
packet_out->po_packno); packet_out->po_packno);
if (0 == (packet_out->po_flags & PO_MTU_PROBE)) if (0 == (packet_out->po_flags & PO_MTU_PROBE))
{
largest_lost_packno = packet_out->po_packno; largest_lost_packno = packet_out->po_packno;
(void) send_ctl_handle_lost_packet(ctl, packet_out, &next); loss_record = send_ctl_handle_regular_lost_packet(ctl,
packet_out, &next);
if (loss_record)
loss_record->po_lflags |= POL_FACKED;
}
else
send_ctl_handle_lost_mtu_probe(ctl, packet_out);
continue; continue;
} }
@ -1120,6 +1140,26 @@ send_ctl_mtu_probe_acked (struct lsquic_send_ctl *ctl,
} }
static void
send_ctl_maybe_increase_reord_thresh (struct lsquic_send_ctl *ctl,
const struct lsquic_packet_out *loss_record,
lsquic_packno_t prev_largest_acked)
{
#if LSQUIC_DEVEL
if (ctl->sc_flags & SC_DYN_PTHRESH)
#endif
if ((loss_record->po_lflags & POL_FACKED)
&& loss_record->po_packno + ctl->sc_reord_thresh
< prev_largest_acked)
{
ctl->sc_reord_thresh = prev_largest_acked - loss_record->po_packno;
LSQ_DEBUG("packet %"PRIu64" was a spurious loss by FACK, increase "
"reordering threshold to %u", loss_record->po_packno,
ctl->sc_reord_thresh);
}
}
int int
lsquic_send_ctl_got_ack (lsquic_send_ctl_t *ctl, lsquic_send_ctl_got_ack (lsquic_send_ctl_t *ctl,
const struct ack_info *acki, const struct ack_info *acki,
@ -1129,6 +1169,7 @@ lsquic_send_ctl_got_ack (lsquic_send_ctl_t *ctl,
&acki->ranges[ acki->n_ranges - 1 ]; &acki->ranges[ acki->n_ranges - 1 ];
lsquic_packet_out_t *packet_out, *next; lsquic_packet_out_t *packet_out, *next;
lsquic_packno_t smallest_unacked; lsquic_packno_t smallest_unacked;
lsquic_packno_t prev_largest_acked;
lsquic_packno_t ack2ed[2]; lsquic_packno_t ack2ed[2];
unsigned packet_sz; unsigned packet_sz;
int app_limited, losses_detected; int app_limited, losses_detected;
@ -1190,6 +1231,7 @@ lsquic_send_ctl_got_ack (lsquic_send_ctl_t *ctl,
ctl->sc_cur_rt_end = lsquic_senhist_largest(&ctl->sc_senhist); ctl->sc_cur_rt_end = lsquic_senhist_largest(&ctl->sc_senhist);
} }
prev_largest_acked = ctl->sc_largest_acked_packno;
do_rtt = 0, skip_checks = 0; do_rtt = 0, skip_checks = 0;
app_limited = -1; app_limited = -1;
do do
@ -1234,6 +1276,8 @@ lsquic_send_ctl_got_ack (lsquic_send_ctl_t *ctl,
po_next); po_next);
LSQ_DEBUG("acking via loss record %"PRIu64, LSQ_DEBUG("acking via loss record %"PRIu64,
packet_out->po_packno); packet_out->po_packno);
send_ctl_maybe_increase_reord_thresh(ctl, packet_out,
prev_largest_acked);
#if LSQUIC_CONN_STATS #if LSQUIC_CONN_STATS
++ctl->sc_conn_pub->conn_stats->out.acked_via_loss; ++ctl->sc_conn_pub->conn_stats->out.acked_via_loss;
#endif #endif

View file

@ -54,6 +54,9 @@ enum send_ctl_flags {
SC_ACK_RECV_HSK = SC_ACK_RECV_INIT << PNS_HSK, SC_ACK_RECV_HSK = SC_ACK_RECV_INIT << PNS_HSK,
SC_ACK_RECV_APP = SC_ACK_RECV_INIT << PNS_APP, SC_ACK_RECV_APP = SC_ACK_RECV_INIT << PNS_APP,
SC_ROUGH_RTT = 1 << 22, SC_ROUGH_RTT = 1 << 22,
#if LSQUIC_DEVEL
SC_DYN_PTHRESH = 1 << 31u, /* dynamic packet threshold enabled */
#endif
}; };
typedef struct lsquic_send_ctl { typedef struct lsquic_send_ctl {
@ -110,6 +113,9 @@ typedef struct lsquic_send_ctl {
* This information is used to drop stale ACK frames from packets in * This information is used to drop stale ACK frames from packets in
* buffered queues. * buffered queues.
*/ */
/* XXX We have both sc_largest_acked_packno and sc_largest_acked. Rename
* the latter to make the code more readable.
*/
lsquic_packno_t sc_largest_acked; lsquic_packno_t sc_largest_acked;
lsquic_time_t sc_loss_to; lsquic_time_t sc_loss_to;
uint64_t sc_ecn_total_acked[N_PNS]; uint64_t sc_ecn_total_acked[N_PNS];
@ -137,6 +143,7 @@ typedef struct lsquic_send_ctl {
lsquic_packno_t sc_gap; lsquic_packno_t sc_gap;
unsigned sc_loss_count; /* Used to set loss bit */ unsigned sc_loss_count; /* Used to set loss bit */
unsigned sc_square_count;/* Used to set square bit */ unsigned sc_square_count;/* Used to set square bit */
unsigned sc_reord_thresh;
signed char sc_cidlen; /* For debug purposes */ signed char sc_cidlen; /* For debug purposes */
} lsquic_send_ctl_t; } lsquic_send_ctl_t;