mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
Release 1.18.0
- [API Change] Can specify clock granularity in engine settings. - [BUGFIX] Pacer uses fixed clock granularity. Since the change on 2018-04-09, it is not necessary to try to approximate the next tick time in the pacer: it can use fix clock granularity specified by the user. - [BUGFIX] Do not tick constantly before handshake is done. - [BUGFIX] Do not exit tick prematurely: reuse packet with ACK. Even if we cannot allocate *more* packets, we could still be able to write to one already allocated. - [BUGFIX] Do not schedule pacer if there are no lost packets.
This commit is contained in:
parent
1b3a179789
commit
6aba801d42
18 changed files with 99 additions and 142 deletions
|
@ -219,6 +219,7 @@ lsquic_engine_init_settings (struct lsquic_engine_settings *settings,
|
|||
settings->es_rw_once = LSQUIC_DF_RW_ONCE;
|
||||
settings->es_proc_time_thresh= LSQUIC_DF_PROC_TIME_THRESH;
|
||||
settings->es_pace_packets = LSQUIC_DF_PACE_PACKETS;
|
||||
settings->es_clock_granularity = LSQUIC_DF_CLOCK_GRANULARITY;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ void
|
|||
lsquic_ev_log_rst_stream_frame_in (lsquic_cid_t cid, uint32_t stream_id,
|
||||
uint64_t offset, uint32_t error_code)
|
||||
{
|
||||
LCID("RST_FRAME frame in: error code %"PRIu32", stream %"PRIu32
|
||||
LCID("RST_STREAM frame in: error code %"PRIu32", stream %"PRIu32
|
||||
", offset: %"PRIu64, error_code, stream_id, offset);
|
||||
}
|
||||
|
||||
|
|
|
@ -1877,7 +1877,7 @@ static unsigned
|
|||
process_packet_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
|
||||
const unsigned char *p, size_t len)
|
||||
{
|
||||
enum QUIC_FRAME_TYPE type = conn->fc_conn.cn_pf->pf_parse_frame_type(p[0]);
|
||||
enum quic_frame_type type = conn->fc_conn.cn_pf->pf_parse_frame_type(p[0]);
|
||||
packet_in->pi_frame_types |= 1 << type;
|
||||
recent_packet_hist_frames(conn, 0, 1 << type);
|
||||
return process_frames[type](conn, packet_in, p, len);
|
||||
|
@ -2954,8 +2954,6 @@ full_conn_ci_tick (lsquic_conn_t *lconn, lsquic_time_t now)
|
|||
if (n > 0)
|
||||
CLOSE_IF_NECESSARY();
|
||||
|
||||
RETURN_IF_OUT_OF_PACKETS();
|
||||
|
||||
if (conn->fc_conn.cn_flags & LSCONN_SEND_BLOCKED)
|
||||
{
|
||||
if (generate_blocked_frame(conn, 0))
|
||||
|
@ -3531,9 +3529,21 @@ full_conn_ci_is_tickable (lsquic_conn_t *lconn)
|
|||
return 1;
|
||||
if (!TAILQ_EMPTY(&conn->fc_pub.sending_streams))
|
||||
return 1;
|
||||
TAILQ_FOREACH(stream, &conn->fc_pub.write_streams, next_write_stream)
|
||||
if (lsquic_stream_write_avail(stream))
|
||||
return 1;
|
||||
if (conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
|
||||
{
|
||||
TAILQ_FOREACH(stream, &conn->fc_pub.write_streams,
|
||||
next_write_stream)
|
||||
if (lsquic_stream_write_avail(stream))
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
TAILQ_FOREACH(stream, &conn->fc_pub.write_streams,
|
||||
next_write_stream)
|
||||
if (LSQUIC_STREAM_HANDSHAKE == stream->id
|
||||
&& lsquic_stream_write_avail(stream))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(stream, &conn->fc_pub.read_streams, next_read_stream)
|
||||
|
|
|
@ -2,9 +2,6 @@
|
|||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#ifndef NDEBUG
|
||||
#include <stdlib.h> /* getenv */
|
||||
#endif
|
||||
#include <string.h>
|
||||
#ifdef WIN32
|
||||
#include <vc_compat.h>
|
||||
|
@ -27,20 +24,12 @@
|
|||
|
||||
|
||||
void
|
||||
pacer_init (struct pacer *pacer, lsquic_cid_t cid, unsigned max_intertick)
|
||||
pacer_init (struct pacer *pacer, lsquic_cid_t cid, unsigned clock_granularity)
|
||||
{
|
||||
memset(pacer, 0, sizeof(*pacer));
|
||||
pacer->pa_burst_tokens = 10;
|
||||
pacer->pa_cid = cid;
|
||||
pacer->pa_max_intertick = max_intertick;
|
||||
#ifndef NDEBUG
|
||||
const char *val;
|
||||
if ((val = getenv("LSQUIC_PACER_INTERTICK")))
|
||||
{
|
||||
pacer->pa_flags |= PA_CONSTANT_INTERTICK;
|
||||
pacer->pa_intertick_avg = atoi(val);
|
||||
}
|
||||
#endif
|
||||
pacer->pa_clock_granularity = clock_granularity;
|
||||
}
|
||||
|
||||
|
||||
|
@ -113,13 +102,6 @@ pacer_loss_event (struct pacer *pacer)
|
|||
}
|
||||
|
||||
|
||||
static unsigned
|
||||
clock_granularity (const struct pacer *pacer)
|
||||
{
|
||||
return pacer->pa_intertick_avg;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
pacer_can_schedule (struct pacer *pacer, unsigned n_in_flight)
|
||||
{
|
||||
|
@ -127,7 +109,7 @@ pacer_can_schedule (struct pacer *pacer, unsigned n_in_flight)
|
|||
|
||||
if (pacer->pa_burst_tokens > 0 || n_in_flight == 0)
|
||||
can = 1;
|
||||
else if (pacer->pa_next_sched > pacer->pa_now + clock_granularity(pacer))
|
||||
else if (pacer->pa_next_sched > pacer->pa_now + pacer->pa_clock_granularity)
|
||||
{
|
||||
pacer->pa_flags |= PA_LAST_SCHED_DELAYED;
|
||||
can = 0;
|
||||
|
@ -140,52 +122,9 @@ pacer_can_schedule (struct pacer *pacer, unsigned n_in_flight)
|
|||
}
|
||||
|
||||
|
||||
#define ALPHA_SHIFT 3
|
||||
#define BETA_SHIFT 2
|
||||
|
||||
static void
|
||||
update_avg_intertick (struct pacer *pacer, unsigned intertick)
|
||||
{
|
||||
unsigned diff;
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (pacer->pa_flags & PA_CONSTANT_INTERTICK)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (pacer->pa_intertick_avg)
|
||||
{
|
||||
if (intertick > pacer->pa_intertick_avg)
|
||||
diff = intertick - pacer->pa_intertick_avg;
|
||||
else
|
||||
diff = pacer->pa_intertick_avg - intertick;
|
||||
pacer->pa_intertick_var -= pacer->pa_intertick_var >> BETA_SHIFT;
|
||||
pacer->pa_intertick_var += diff >> BETA_SHIFT;
|
||||
pacer->pa_intertick_avg -= pacer->pa_intertick_avg >> ALPHA_SHIFT;
|
||||
pacer->pa_intertick_avg += intertick >> ALPHA_SHIFT;
|
||||
}
|
||||
else
|
||||
{
|
||||
pacer->pa_intertick_avg = intertick;
|
||||
pacer->pa_intertick_var = intertick >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pacer_tick (struct pacer *pacer, lsquic_time_t now)
|
||||
{
|
||||
unsigned intertick;
|
||||
|
||||
assert(now >= pacer->pa_now);
|
||||
if (pacer->pa_now)
|
||||
{
|
||||
assert(now - pacer->pa_now < (1ULL << sizeof(unsigned) * 8));
|
||||
intertick = now - pacer->pa_now;
|
||||
LSQ_DEBUG("intertick estimate: %u; real value: %u; error: %d",
|
||||
clock_granularity(pacer), intertick,
|
||||
(int) clock_granularity(pacer) - (int) intertick);
|
||||
update_avg_intertick(pacer, intertick);
|
||||
}
|
||||
pacer->pa_now = now;
|
||||
}
|
||||
|
|
|
@ -11,23 +11,12 @@ struct pacer
|
|||
|
||||
/* All tick times are in microseconds */
|
||||
|
||||
unsigned pa_max_intertick; /* Maximum intertick time */
|
||||
unsigned pa_clock_granularity;
|
||||
|
||||
/* We keep an average of intertick times, which is our best estimate
|
||||
* for the time when the connection ticks next. This estimate is used
|
||||
* to see whether a packet can be scheduled or not.
|
||||
*/
|
||||
unsigned pa_intertick_avg; /* Smoothed average */
|
||||
unsigned pa_intertick_var; /* Variance */
|
||||
|
||||
unsigned short pa_packet_size;
|
||||
unsigned char pa_burst_tokens;
|
||||
unsigned pa_burst_tokens;
|
||||
enum {
|
||||
PA_LAST_SCHED_DELAYED = (1 << 0),
|
||||
#ifndef NDEBUG
|
||||
PA_CONSTANT_INTERTICK = (1 << 1), /* Use fake intertick time for testing */
|
||||
#endif
|
||||
} pa_flags:8;
|
||||
} pa_flags;
|
||||
#ifndef NDEBUG
|
||||
struct {
|
||||
unsigned n_scheduled;
|
||||
|
@ -39,7 +28,7 @@ struct pacer
|
|||
typedef lsquic_time_t (*tx_time_f)(void *ctx);
|
||||
|
||||
void
|
||||
pacer_init (struct pacer *, lsquic_cid_t, unsigned max_intertick);
|
||||
pacer_init (struct pacer *, lsquic_cid_t, unsigned clock_granularity);
|
||||
|
||||
void
|
||||
pacer_cleanup (struct pacer *);
|
||||
|
|
|
@ -16,7 +16,7 @@ enum PACKET_PUBLIC_FLAGS
|
|||
PACKET_PUBLIC_FLAGS_TWO_OR_MORE_BYTES = 1 << 7,
|
||||
};
|
||||
|
||||
enum QUIC_FRAME_TYPE
|
||||
enum quic_frame_type
|
||||
{
|
||||
QUIC_FRAME_INVALID,
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ int
|
|||
lsquic_packet_out_add_stream (lsquic_packet_out_t *packet_out,
|
||||
struct lsquic_mm *mm,
|
||||
struct lsquic_stream *new_stream,
|
||||
enum QUIC_FRAME_TYPE frame_type,
|
||||
enum quic_frame_type frame_type,
|
||||
unsigned short off, unsigned short len)
|
||||
{
|
||||
struct stream_rec_arr *srec_arr;
|
||||
|
@ -348,23 +348,6 @@ lsquic_packet_out_chop_regen (lsquic_packet_out_t *packet_out)
|
|||
}
|
||||
|
||||
|
||||
int
|
||||
lsquic_packet_out_has_hsk_frames (struct lsquic_packet_out *packet_out)
|
||||
{
|
||||
struct packet_out_srec_iter posi;
|
||||
struct stream_rec *srec;
|
||||
|
||||
for (srec = posi_first(&posi, packet_out); srec; srec = posi_next(&posi))
|
||||
if (srec->sr_frame_type == QUIC_FRAME_STREAM
|
||||
&& LSQUIC_STREAM_HANDSHAKE == srec->sr_stream->id)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lsquic_packet_out_ack_streams (lsquic_packet_out_t *packet_out)
|
||||
{
|
||||
|
|
|
@ -38,7 +38,7 @@ struct stream_rec {
|
|||
struct lsquic_stream *sr_stream;
|
||||
unsigned short sr_off,
|
||||
sr_len;
|
||||
enum QUIC_FRAME_TYPE sr_frame_type:16;
|
||||
enum quic_frame_type sr_frame_type:16;
|
||||
};
|
||||
|
||||
#define srec_taken(srec) ((srec)->sr_frame_type)
|
||||
|
@ -214,7 +214,7 @@ int
|
|||
lsquic_packet_out_add_stream (lsquic_packet_out_t *packet_out,
|
||||
struct lsquic_mm *mm,
|
||||
struct lsquic_stream *new_stream,
|
||||
enum QUIC_FRAME_TYPE,
|
||||
enum quic_frame_type,
|
||||
unsigned short off, unsigned short len);
|
||||
|
||||
unsigned
|
||||
|
@ -227,9 +227,6 @@ lsquic_packet_out_split_in_two (struct lsquic_mm *, lsquic_packet_out_t *,
|
|||
void
|
||||
lsquic_packet_out_chop_regen (lsquic_packet_out_t *);
|
||||
|
||||
int
|
||||
lsquic_packet_out_has_hsk_frames (struct lsquic_packet_out *);
|
||||
|
||||
void
|
||||
lsquic_packet_out_ack_streams (struct lsquic_packet_out *);
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ struct parse_funcs
|
|||
void
|
||||
(*pf_parse_packet_in_finish) (struct lsquic_packet_in *packet_in,
|
||||
struct packin_parse_state *);
|
||||
enum QUIC_FRAME_TYPE
|
||||
enum quic_frame_type
|
||||
(*pf_parse_frame_type) (unsigned char);
|
||||
/* Return used buffer length or a negative value if there was not enough
|
||||
* room to write the stream frame. In the latter case, the negative of
|
||||
|
@ -186,7 +186,7 @@ int
|
|||
lsquic_iquic_parse_packet_in_short_begin (struct lsquic_packet_in *,
|
||||
size_t length, int is_server, struct packin_parse_state *state);
|
||||
|
||||
enum QUIC_FRAME_TYPE
|
||||
enum quic_frame_type
|
||||
parse_frame_type_gquic_Q035_thru_Q039 (unsigned char first_byte);
|
||||
|
||||
size_t
|
||||
|
|
|
@ -137,7 +137,7 @@ lsquic_gquic_parse_packet_in_begin (struct lsquic_packet_in *packet_in,
|
|||
}
|
||||
|
||||
|
||||
static const enum QUIC_FRAME_TYPE byte2frame_type_Q035_thru_Q039[0x100] =
|
||||
static const enum quic_frame_type byte2frame_type_Q035_thru_Q039[0x100] =
|
||||
{
|
||||
[0x00] = QUIC_FRAME_PADDING,
|
||||
[0x01] = QUIC_FRAME_RST_STREAM,
|
||||
|
@ -398,7 +398,7 @@ static const enum QUIC_FRAME_TYPE byte2frame_type_Q035_thru_Q039[0x100] =
|
|||
};
|
||||
|
||||
|
||||
enum QUIC_FRAME_TYPE
|
||||
enum quic_frame_type
|
||||
parse_frame_type_gquic_Q035_thru_Q039 (unsigned char b)
|
||||
{
|
||||
return byte2frame_type_Q035_thru_Q039[b];
|
||||
|
|
|
@ -252,7 +252,8 @@ lsquic_send_ctl_init (lsquic_send_ctl_t *ctl, struct lsquic_alarmset *alset,
|
|||
lsquic_senhist_init(&ctl->sc_senhist);
|
||||
lsquic_cubic_init(&ctl->sc_cubic, LSQUIC_LOG_CONN_ID);
|
||||
if (ctl->sc_flags & SC_PACE)
|
||||
pacer_init(&ctl->sc_pacer, LSQUIC_LOG_CONN_ID, 100000);
|
||||
pacer_init(&ctl->sc_pacer, LSQUIC_LOG_CONN_ID,
|
||||
enpub->enp_settings.es_clock_granularity);
|
||||
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);
|
||||
|
@ -833,18 +834,32 @@ lsquic_send_ctl_smallest_unacked (lsquic_send_ctl_t *ctl)
|
|||
static struct lsquic_packet_out *
|
||||
send_ctl_next_lost (lsquic_send_ctl_t *ctl)
|
||||
{
|
||||
lsquic_packet_out_t *lost_packet = TAILQ_FIRST(&ctl->sc_lost_packets);
|
||||
struct lsquic_packet_out *lost_packet;
|
||||
|
||||
get_next_lost:
|
||||
lost_packet = TAILQ_FIRST(&ctl->sc_lost_packets);
|
||||
if (lost_packet)
|
||||
{
|
||||
TAILQ_REMOVE(&ctl->sc_lost_packets, lost_packet, po_next);
|
||||
if (lost_packet->po_frame_types & (1 << QUIC_FRAME_STREAM))
|
||||
{
|
||||
lsquic_packet_out_elide_reset_stream_frames(lost_packet, 0);
|
||||
if (lost_packet->po_regen_sz >= lost_packet->po_data_sz)
|
||||
{
|
||||
LSQ_DEBUG("Dropping packet %"PRIu64" from lost queue",
|
||||
lost_packet->po_packno);
|
||||
TAILQ_REMOVE(&ctl->sc_lost_packets, lost_packet, po_next);
|
||||
send_ctl_destroy_packet(ctl, lost_packet);
|
||||
goto get_next_lost;
|
||||
}
|
||||
}
|
||||
return lost_packet;
|
||||
|
||||
if (!lsquic_send_ctl_can_send(ctl))
|
||||
return NULL;
|
||||
|
||||
TAILQ_REMOVE(&ctl->sc_lost_packets, lost_packet, po_next);
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
|
||||
return lost_packet;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1117,9 +1132,6 @@ lsquic_send_ctl_next_packet_to_send (lsquic_send_ctl_t *ctl)
|
|||
{
|
||||
if (packet_out->po_regen_sz < packet_out->po_data_sz)
|
||||
{
|
||||
#if LSQUIC_CONN_STATS
|
||||
++ctl->sc_conn_pub->conn_stats->out.retx_packets;
|
||||
#endif
|
||||
update_for_resending(ctl, packet_out);
|
||||
packet_out->po_flags &= ~PO_REPACKNO;
|
||||
}
|
||||
|
@ -1304,21 +1316,15 @@ lsquic_send_ctl_reschedule_packets (lsquic_send_ctl_t *ctl)
|
|||
lsquic_packet_out_t *packet_out;
|
||||
unsigned n = 0;
|
||||
|
||||
while (lsquic_send_ctl_can_send(ctl) &&
|
||||
(packet_out = send_ctl_next_lost(ctl)))
|
||||
while ((packet_out = send_ctl_next_lost(ctl)))
|
||||
{
|
||||
if (packet_out->po_regen_sz < packet_out->po_data_sz)
|
||||
{
|
||||
++n;
|
||||
update_for_resending(ctl, packet_out);
|
||||
lsquic_send_ctl_scheduled_one(ctl, packet_out);
|
||||
}
|
||||
else
|
||||
{
|
||||
LSQ_DEBUG("Dropping packet %"PRIu64" from unacked queue",
|
||||
packet_out->po_packno);
|
||||
send_ctl_destroy_packet(ctl, packet_out);
|
||||
}
|
||||
assert(packet_out->po_regen_sz < packet_out->po_data_sz);
|
||||
++n;
|
||||
#if LSQUIC_CONN_STATS
|
||||
++ctl->sc_conn_pub->conn_stats->out.retx_packets;
|
||||
#endif
|
||||
update_for_resending(ctl, packet_out);
|
||||
lsquic_send_ctl_scheduled_one(ctl, packet_out);
|
||||
}
|
||||
|
||||
if (n)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue