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
- 2.25.0
- [API, FEATURE] Add es_delay_onclose option to delay on_close until all

View file

@ -39,7 +39,7 @@
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 = {
.pmi_allocate = pba_allocate,
@ -417,7 +417,7 @@ prog_init_client (struct prog *prog)
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;
return sport->sp_prog->prog_ssl_ctx;

View file

@ -257,10 +257,10 @@ optional members.
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
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:: void *ea_hsi_ctx

View file

@ -24,9 +24,9 @@ copyright = u'2020, LiteSpeed Technologies'
author = u'LiteSpeed Technologies'
# The short X.Y version
version = u'2.25'
version = u'2.26'
# The full version, including alpha/beta/rc tags
release = u'2.25.0'
release = u'2.26.0'
# -- 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 {
lsquic_lookup_cert_f ea_lookup_cert;
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) */
};

View file

@ -24,7 +24,7 @@ extern "C" {
#endif
#define LSQUIC_MAJOR_VERSION 2
#define LSQUIC_MINOR_VERSION 25
#define LSQUIC_MINOR_VERSION 26
#define LSQUIC_PATCH_VERSION 0
/**
@ -1274,7 +1274,8 @@ struct lsquic_engine_api
lsquic_lookup_cert_f ea_lookup_cert;
void *ea_cert_lu_ctx;
/** 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
* 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;
}
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;
if (enc_sess->esi_enpub->enp_get_ssl_ctx)
{
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
{
create_new_ssl_ctx:
LSQ_DEBUG("Create new SSL_CTX");
ssl_ctx = SSL_CTX_new(TLS_method());
if (!ssl_ctx)
@ -1363,6 +1372,7 @@ static int
iquic_esfi_init_server (enc_session_t *enc_session_p)
{
struct enc_sess_iquic *const enc_sess = enc_session_p;
struct network_path *path;
const struct alpn_map *am;
unsigned quic_ctx_idx;
int transpa_len;
@ -1390,8 +1400,9 @@ iquic_esfi_init_server (enc_session_t *enc_session_p)
ok: enc_sess->esi_alpn = am->alpn;
}
ssl_ctx = enc_sess->esi_enpub->enp_get_ssl_ctx(
lsquic_conn_get_peer_ctx(enc_sess->esi_conn, NULL));
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(path->np_peer_ctx,
NP_LOCAL_SA(path));
if (!ssl_ctx)
{
LSQ_ERROR("fetching SSL context associated with peer context failed");

View file

@ -20,6 +20,7 @@ struct ssl_ctx_st;
struct crand;
struct evp_aead_ctx_st;
struct lsquic_server_config;
struct sockaddr;
enum warning_type
{
@ -37,7 +38,8 @@ struct lsquic_engine_public {
struct token_generator *enp_tokgen;
lsquic_lookup_cert_f enp_lookup_cert;
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
*enp_shi;
void *enp_shi_ctx;

View file

@ -166,6 +166,7 @@ typedef struct lsquic_packet_out
POL_HEADER_PROT = 1 << 9, /* Header protection applied */
#endif
POL_LIMITED = 1 << 10, /* Used to credit sc_next_limit if needed. */
POL_FACKED = 1 << 11, /* Lost due to FACK check */
} po_lflags:16;
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;
else
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,
struct lsquic_packet_out *packet_out)
{
@ -909,16 +916,21 @@ send_ctl_record_loss (struct lsquic_send_ctl *ctl,
* remove from the list:
*/
TAILQ_INSERT_BEFORE(packet_out, loss_record, po_next);
return loss_record;
}
else
{
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,
lsquic_packet_out_t *packet_out, struct lsquic_packet_out **next)
{
struct lsquic_packet_out *loss_record;
unsigned packet_sz;
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,
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);
TAILQ_INSERT_TAIL(&ctl->sc_lost_packets, packet_out, po_next);
packet_out->po_flags |= PO_LOST;
return 1;
return loss_record;
}
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_destroy_chain(ctl, packet_out, next);
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)
{
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
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,
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;
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))
continue;
if (packet_out->po_packno + N_NACKS_BEFORE_RETX <
if (packet_out->po_packno + ctl->sc_reord_thresh <
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);
if (0 == (packet_out->po_flags & PO_MTU_PROBE))
{
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;
}
@ -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
lsquic_send_ctl_got_ack (lsquic_send_ctl_t *ctl,
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 ];
lsquic_packet_out_t *packet_out, *next;
lsquic_packno_t smallest_unacked;
lsquic_packno_t prev_largest_acked;
lsquic_packno_t ack2ed[2];
unsigned packet_sz;
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);
}
prev_largest_acked = ctl->sc_largest_acked_packno;
do_rtt = 0, skip_checks = 0;
app_limited = -1;
do
@ -1234,6 +1276,8 @@ lsquic_send_ctl_got_ack (lsquic_send_ctl_t *ctl,
po_next);
LSQ_DEBUG("acking via loss record %"PRIu64,
packet_out->po_packno);
send_ctl_maybe_increase_reord_thresh(ctl, packet_out,
prev_largest_acked);
#if LSQUIC_CONN_STATS
++ctl->sc_conn_pub->conn_stats->out.acked_via_loss;
#endif

View file

@ -54,6 +54,9 @@ enum send_ctl_flags {
SC_ACK_RECV_HSK = SC_ACK_RECV_INIT << PNS_HSK,
SC_ACK_RECV_APP = SC_ACK_RECV_INIT << PNS_APP,
SC_ROUGH_RTT = 1 << 22,
#if LSQUIC_DEVEL
SC_DYN_PTHRESH = 1 << 31u, /* dynamic packet threshold enabled */
#endif
};
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
* 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_time_t sc_loss_to;
uint64_t sc_ecn_total_acked[N_PNS];
@ -137,6 +143,7 @@ typedef struct lsquic_send_ctl {
lsquic_packno_t sc_gap;
unsigned sc_loss_count; /* Used to set loss bit */
unsigned sc_square_count;/* Used to set square bit */
unsigned sc_reord_thresh;
signed char sc_cidlen; /* For debug purposes */
} lsquic_send_ctl_t;