lsquic_send_ctl.h revision 50aadb33
1/* Copyright (c) 2017 LiteSpeed Technologies Inc.  See LICENSE. */
2#ifndef LSQUIC_SEND_CTL_H
3#define LSQUIC_SEND_CTL_H 1
4
5#include <sys/queue.h>
6
7#include "lsquic_types.h"
8
9#ifndef LSQUIC_SEND_STATS
10#   define LSQUIC_SEND_STATS 1
11#endif
12
13TAILQ_HEAD(lsquic_packets_tailq, lsquic_packet_out);
14
15struct lsquic_packet_out;
16struct ack_info;
17struct lsquic_alarmset;
18struct lsquic_engine_public;
19struct lsquic_conn_public;
20struct ver_neg;
21
22typedef struct lsquic_send_ctl {
23    struct lsquic_packets_tailq     sc_scheduled_packets,
24                                    sc_unacked_packets,
25                                    sc_lost_packets;
26    struct lsquic_engine_public    *sc_enpub;
27    struct lsquic_alarmset         *sc_alset;
28    const struct ver_neg           *sc_ver_neg;
29    struct lsquic_conn_public      *sc_conn_pub;
30    struct lsquic_cubic             sc_cubic;
31    struct pacer                    sc_pacer;
32    lsquic_senhist_t                sc_senhist;
33    lsquic_packno_t                 sc_cur_packno;
34    lsquic_packno_t                 sc_largest_sent_at_cutback;
35    lsquic_packno_t                 sc_max_rtt_packno;
36    lsquic_packno_t                 sc_largest_acked_packno;
37    lsquic_time_t                   sc_largest_acked_sent_time;
38    /* sc_largest_ack2ed is the packet number sent by peer that we acked and
39     * we know that our ACK was received by peer.  This is used to determine
40     * the receive history cutoff point for the purposes of generating ACK
41     * frames in the absense of STOP_WAITING frames.  Used when NSTP option
42     * is set.  (The "ack2ed" is odd enough to not be confused with anything
43     * else and it is not insanely long.)
44     */
45    lsquic_packno_t                 sc_largest_ack2ed;
46    lsquic_time_t                   sc_loss_to;
47    unsigned                        sc_n_consec_rtos;
48    unsigned                        sc_next_limit;
49    unsigned                        sc_n_in_flight;    /* Number of packets in flight */
50    unsigned                        sc_n_scheduled;
51    unsigned                        sc_n_stop_waiting;
52    unsigned short                  sc_pack_size;
53    enum {
54        SC_TCID0        = (1 << 0),
55        SC_LOST_ACK     = (1 << 1),
56        SC_NSTP         = (1 << 2),
57        SC_PACE         = (1 << 3),
58        SC_SCHED_TICK   = (1 << 4),
59    }                               sc_flags:8;
60    unsigned char                   sc_n_hsk;
61    unsigned char                   sc_n_tlp;
62#if LSQUIC_SEND_STATS
63    struct {
64        unsigned            n_total_sent,
65                            n_resent,
66                            n_delayed;
67    }                               sc_stats;
68#endif
69} lsquic_send_ctl_t;
70
71void
72lsquic_send_ctl_init (lsquic_send_ctl_t *, struct lsquic_alarmset *,
73          struct lsquic_engine_public *, const struct ver_neg *,
74          struct lsquic_conn_public *, unsigned short max_packet_size);
75
76int
77lsquic_send_ctl_sent_packet (lsquic_send_ctl_t *, struct lsquic_packet_out *);
78
79int
80lsquic_send_ctl_got_ack (lsquic_send_ctl_t *, const struct ack_info *,
81                                                            lsquic_time_t);
82
83lsquic_packno_t
84lsquic_send_ctl_smallest_unacked (lsquic_send_ctl_t *ctl);
85
86int
87lsquic_send_ctl_have_unacked_stream_frames (const lsquic_send_ctl_t *);
88
89void
90lsquic_send_ctl_cleanup (lsquic_send_ctl_t *);
91
92int
93lsquic_send_ctl_can_send (lsquic_send_ctl_t *ctl);
94
95void
96lsquic_send_ctl_scheduled_one (lsquic_send_ctl_t *, lsquic_packet_out_t *);
97
98void
99lsquic_send_ctl_delayed_one (lsquic_send_ctl_t *, lsquic_packet_out_t *);
100
101lsquic_packet_out_t *
102lsquic_send_ctl_next_packet_to_send (lsquic_send_ctl_t *);
103
104void
105lsquic_send_ctl_expire_all (lsquic_send_ctl_t *ctl);
106
107#define lsquic_send_ctl_n_in_flight(ctl) (+(ctl)->sc_n_in_flight)
108
109#define lsquic_send_ctl_n_scheduled(ctl) (+(ctl)->sc_n_scheduled)
110
111#define lsquic_send_ctl_largest_ack2ed(ctl) (+(ctl)->sc_largest_ack2ed)
112
113#ifdef NDEBUG
114#   define lsquic_send_ctl_sanity_check(ctl)
115#else
116void
117lsquic_send_ctl_sanity_check (const lsquic_send_ctl_t *ctl);
118#endif
119
120int
121lsquic_send_ctl_have_outgoing_stream_frames (const lsquic_send_ctl_t *);
122
123int
124lsquic_send_ctl_have_outgoing_retx_frames (const lsquic_send_ctl_t *);
125
126#define lsquic_send_ctl_last_scheduled(ctl) \
127            TAILQ_LAST(&(ctl)->sc_scheduled_packets, lsquic_packets_tailq)
128
129lsquic_packet_out_t *
130lsquic_send_ctl_new_packet_out (lsquic_send_ctl_t *, unsigned);
131
132lsquic_packet_out_t *
133lsquic_send_ctl_get_writeable_packet (lsquic_send_ctl_t *,
134                                      unsigned need_at_least, int *is_err);
135
136unsigned
137lsquic_send_ctl_reschedule_packets (lsquic_send_ctl_t *);
138
139#define lsquic_send_ctl_lost_ack(ctl) ((ctl)->sc_flags & SC_LOST_ACK)
140
141#define lsquic_send_ctl_scheduled_ack(ctl) do {                     \
142    (ctl)->sc_flags &= ~SC_LOST_ACK;                                \
143} while (0)
144
145void
146lsquic_send_ctl_set_tcid0 (lsquic_send_ctl_t *, int);
147
148#define lsquic_send_ctl_turn_nstp_on(ctl) ((ctl)->sc_flags |= SC_NSTP)
149
150void
151lsquic_send_ctl_reset_stream (lsquic_send_ctl_t *, uint32_t);
152
153int
154lsquic_send_ctl_squeeze_sched (lsquic_send_ctl_t *);
155
156/* Same return value as for squeezing, but without actual squeezing. */
157int
158lsquic_send_ctl_have_delayed_packets (const lsquic_send_ctl_t *ctl);
159
160void
161lsquic_send_ctl_reset_packnos (lsquic_send_ctl_t *);
162
163void
164lsquic_send_ctl_ack_to_front (lsquic_send_ctl_t *);
165
166#define lsquic_send_ctl_n_stop_waiting(ctl) (+(ctl)->sc_n_stop_waiting)
167
168#define lsquic_send_ctl_n_stop_waiting_reset(ctl) do {      \
169    (ctl)->sc_n_stop_waiting = 0;                           \
170} while (0)
171
172void
173lsquic_send_ctl_drop_scheduled (lsquic_send_ctl_t *);
174
175#define lsquic_send_ctl_tick(ctl, now) do {                 \
176    if ((ctl)->sc_flags & SC_PACE)                          \
177    {                                                       \
178        (ctl)->sc_flags |= SC_SCHED_TICK;                   \
179        pacer_tick(&(ctl)->sc_pacer, now);                  \
180    }                                                       \
181} while (0)
182
183#endif
184