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
				
			
		
							
								
								
									
										13
									
								
								CHANGELOG
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								CHANGELOG
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,3 +1,16 @@
 | 
			
		|||
2019-01-28
 | 
			
		||||
    - 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.
 | 
			
		||||
 | 
			
		||||
2019-01-17
 | 
			
		||||
    - 1.17.15
 | 
			
		||||
    - [BUGFIX] http_client: make sure only one read per on_read() callback
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,8 +24,8 @@ extern "C" {
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
#define LSQUIC_MAJOR_VERSION 1
 | 
			
		||||
#define LSQUIC_MINOR_VERSION 17
 | 
			
		||||
#define LSQUIC_PATCH_VERSION 15
 | 
			
		||||
#define LSQUIC_MINOR_VERSION 18
 | 
			
		||||
#define LSQUIC_PATCH_VERSION 0
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Engine flags:
 | 
			
		||||
| 
						 | 
				
			
			@ -245,6 +245,9 @@ struct lsquic_stream_if {
 | 
			
		|||
/** By default, packets are paced */
 | 
			
		||||
#define LSQUIC_DF_PACE_PACKETS      1
 | 
			
		||||
 | 
			
		||||
/** Default clock granularity is 1000 microseconds */
 | 
			
		||||
#define LSQUIC_DF_CLOCK_GRANULARITY      1000
 | 
			
		||||
 | 
			
		||||
struct lsquic_engine_settings {
 | 
			
		||||
    /**
 | 
			
		||||
     * This is a bit mask wherein each bit corresponds to a value in
 | 
			
		||||
| 
						 | 
				
			
			@ -432,6 +435,11 @@ struct lsquic_engine_settings {
 | 
			
		|||
     */
 | 
			
		||||
    int             es_pace_packets;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Clock granularity information is used by the pacer.  The value
 | 
			
		||||
     * is in microseconds; default is @ref LSQUIC_DF_CLOCK_GRANULARITY.
 | 
			
		||||
     */
 | 
			
		||||
    unsigned        es_clock_granularity;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Initialize `settings' to default values */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1088,6 +1088,7 @@ main (int argc, char **argv)
 | 
			
		|||
        fprintf(stats_fh, "%.2Lf reqs/sec; %.0Lf bytes/sec\n",
 | 
			
		||||
            (long double) s_stat_req.n / elapsed,
 | 
			
		||||
            (long double) s_stat_downloaded_bytes / elapsed);
 | 
			
		||||
        fprintf(stats_fh, "read handler count %lu\n", prog.prog_read_count);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    prog_cleanup(&prog);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										12
									
								
								test/prog.c
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								test/prog.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -151,6 +151,10 @@ prog_print_common_options (const struct prog *prog, FILE *out)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    fprintf(out,
 | 
			
		||||
"   -i USECS    Clock granularity in microseconds.  Defaults to %u.\n",
 | 
			
		||||
        LSQUIC_DF_CLOCK_GRANULARITY
 | 
			
		||||
    );
 | 
			
		||||
    fprintf(out,
 | 
			
		||||
"   -h          Print this help screen and exit\n"
 | 
			
		||||
    );
 | 
			
		||||
| 
						 | 
				
			
			@ -193,6 +197,9 @@ prog_set_opt (struct prog *prog, int opt, const char *arg)
 | 
			
		|||
    case 'o':
 | 
			
		||||
        return set_engine_option(&prog->prog_settings,
 | 
			
		||||
                                            &prog->prog_version_cleared, arg);
 | 
			
		||||
    case 'i':
 | 
			
		||||
        prog->prog_settings.es_clock_granularity = atoi(arg);
 | 
			
		||||
        return 0;
 | 
			
		||||
    case 's':
 | 
			
		||||
        if (0 == (prog->prog_engine_flags & LSENG_SERVER) &&
 | 
			
		||||
                                            !TAILQ_EMPTY(prog->prog_sports))
 | 
			
		||||
| 
						 | 
				
			
			@ -286,10 +293,11 @@ prog_process_conns (struct prog *prog)
 | 
			
		|||
 | 
			
		||||
    if (lsquic_engine_earliest_adv_tick(prog->prog_engine, &diff))
 | 
			
		||||
    {
 | 
			
		||||
        if (diff < 4000)
 | 
			
		||||
        if (diff < 0
 | 
			
		||||
                || (unsigned) diff < prog->prog_settings.es_clock_granularity)
 | 
			
		||||
        {
 | 
			
		||||
            timeout.tv_sec  = 0;
 | 
			
		||||
            timeout.tv_usec = 4000;
 | 
			
		||||
            timeout.tv_usec = prog->prog_settings.es_clock_granularity;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,6 +21,7 @@ struct prog
 | 
			
		|||
    unsigned                        prog_packout_max;
 | 
			
		||||
    unsigned short                  prog_max_packet_size;
 | 
			
		||||
    int                             prog_version_cleared;
 | 
			
		||||
    unsigned long                   prog_read_count;
 | 
			
		||||
    struct event_base              *prog_eb;
 | 
			
		||||
    struct event                   *prog_timer,
 | 
			
		||||
                                   *prog_send,
 | 
			
		||||
| 
						 | 
				
			
			@ -41,7 +42,7 @@ prog_init (struct prog *, unsigned lsquic_engine_flags, struct sport_head *,
 | 
			
		|||
#   define IP_DONTFRAG_FLAG ""
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define PROG_OPTS "m:c:y:L:l:o:H:s:S:Y:z:" IP_DONTFRAG_FLAG
 | 
			
		||||
#define PROG_OPTS "i:m:c:y:L:l:o:H:s:S:Y:z:" IP_DONTFRAG_FLAG
 | 
			
		||||
 | 
			
		||||
/* Returns:
 | 
			
		||||
 *  0   Applied
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -560,6 +560,7 @@ read_handler (evutil_socket_t fd, short flags, void *ctx)
 | 
			
		|||
    n_batches = 0;
 | 
			
		||||
    iter.ri_sport = sport;
 | 
			
		||||
 | 
			
		||||
    sport->sp_prog->prog_read_count += 1;
 | 
			
		||||
    do
 | 
			
		||||
    {
 | 
			
		||||
        iter.ri_off = 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										0
									
								
								tools/bench/lsqb.sh
									
										
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								tools/bench/lsqb.sh
									
										
									
									
									
										
										
										Normal file → Executable file
									
								
							
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue