lsquic_packet_out.h revision c7d81ce1
1/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc. See LICENSE. */ 2/* 3 * lsquic_packet_out.h -- Structure and routines dealing with packet_out 4 */ 5 6#ifndef LSQUIC_PACKET_OUT_H 7#define LSQUIC_PACKET_OUT_H 1 8 9#include <sys/queue.h> 10 11struct malo; 12struct lsquic_conn; 13struct lsquic_engine_public; 14struct lsquic_mm; 15struct lsquic_stream; 16struct parse_funcs; 17 18/* Each stream_rec is associated with one packet_out. packet_out can have 19 * zero or more stream_rec structures. stream_rec keeps a pointer to a stream 20 * that has STREAM or RST_STREAM frames inside packet_out. `sr_frame_type' 21 * specifies the type of the frame; if this value is zero, values of the 22 * other struct members are not valid. `sr_off' indicates where inside 23 * packet_out->po_data the frame begins and `sr_len' is its length. 24 * 25 * We need this information for three reasons: 26 * 1. A stream is not destroyed until all of its STREAM and RST_STREAM 27 * frames are acknowledged. This is to make sure that we do not exceed 28 * maximum allowed number of streams. 29 * 2. When a packet is resubmitted, STREAM frames for a stream that has 30 * been reset are not to be resubmitted. 31 * 3. A buffered packet may have to be split before it is scheduled (this 32 * occurs if we guessed incorrectly the number of bytes required to 33 * encode the packet number and the actual number would make packet 34 * larger than the max). 35 * 36 */ 37struct stream_rec { 38 struct lsquic_stream *sr_stream; 39 unsigned short sr_off, 40 sr_len; 41 enum quic_frame_type sr_frame_type:16; 42}; 43 44#define srec_taken(srec) ((srec)->sr_frame_type) 45 46struct stream_rec_arr { 47 TAILQ_ENTRY(stream_rec_arr) next_stream_rec_arr; 48 struct stream_rec srecs[ 49 ( 64 /* Efficient size for malo allocator */ 50 - sizeof(TAILQ_ENTRY(stream_rec)) /* next_stream_rec_arr */ 51 ) / sizeof(struct stream_rec) 52 ]; 53}; 54 55TAILQ_HEAD(stream_rec_arr_tailq, stream_rec_arr); 56 57typedef struct lsquic_packet_out 58{ 59 /* `po_next' is used for packets_out, unacked_packets and expired_packets 60 * lists. 61 */ 62 TAILQ_ENTRY(lsquic_packet_out) 63 po_next; 64 lsquic_time_t po_sent; /* Time sent */ 65 lsquic_packno_t po_packno; 66 67 enum packet_out_flags { 68 PO_HELLO = (1 << 1), /* Packet contains SHLO or CHLO data */ 69 PO_ENCRYPTED= (1 << 3), /* po_enc_data has encrypted data */ 70 PO_SREC_ARR = (1 << 4), 71#define POBIT_SHIFT 5 72 PO_BITS_0 = (1 << 5), /* PO_BITS_0 and PO_BITS_1 encode the */ 73 PO_BITS_1 = (1 << 6), /* packet number length. See macros below. */ 74 PO_NONCE = (1 << 7), /* Use value in `po_nonce' to generate header */ 75 PO_VERSION = (1 << 8), /* Use value in `po_ver_tag' to generate header */ 76 PO_CONN_ID = (1 << 9), /* Include connection ID in public header */ 77 PO_REPACKNO = (1 <<10), /* Regenerate packet number */ 78 PO_NOENCRYPT= (1 <<11), /* Do not encrypt data in po_data */ 79 PO_VERNEG = (1 <<12), /* Version negotiation packet. */ 80 PO_STREAM_END 81 = (1 <<13), /* STREAM frame reaches the end of the packet: no 82 * further writes are allowed. 83 */ 84 PO_SCHED = (1 <<14), /* On scheduled queue */ 85 PO_SENT_SZ = (1 <<15), 86 PO_LONGHEAD = (1 <<16), 87 PO_GQUIC = (1 <<17), /* Used for logging */ 88#define POLEV_SHIFT 18 89 PO_BITS_2 = (1 <<18), /* PO_BITS_2 and PO_BITS_3 encode the */ 90 PO_BITS_3 = (1 <<19), /* crypto level. Used for logging. */ 91#define POIPv6_SHIFT 20 92 PO_IPv6 = (1 <<20), /* Set if pmi_allocate was passed is_ipv6=1, 93 * otherwise unset. 94 */ 95 PO_LIMITED = (1 <<21), /* Used to credit sc_next_limit if needed. */ 96 } po_flags; 97 enum quic_ft_bit po_frame_types:16; /* Bitmask of QUIC_FRAME_* */ 98 unsigned short po_data_sz; /* Number of usable bytes in data */ 99 unsigned short po_enc_data_sz; /* Number of usable bytes in data */ 100 unsigned short po_sent_sz; /* If PO_SENT_SZ is set, real size of sent buffer. */ 101 unsigned short po_regen_sz; /* Number of bytes at the beginning 102 * of data containing bytes that are 103 * not to be retransmitted, e.g. ACK 104 * frames. 105 */ 106 unsigned short po_n_alloc; /* Total number of bytes allocated in po_data */ 107 enum header_type po_header_type:8; 108 unsigned char *po_data; 109 lsquic_packno_t po_ack2ed; /* If packet has ACK frame, value of 110 * largest acked in it. 111 */ 112 113 /* A lot of packets contain data belonging to only one stream. Thus, 114 * `one' is used first. If this is not enough, any number of 115 * stream_rec_arr structures can be allocated to handle more stream 116 * records. 117 */ 118 union { 119 struct stream_rec one; 120 struct stream_rec_arr_tailq arr; 121 } po_srecs; 122 123 /* If PO_ENCRYPTED is set, this points to the buffer that holds encrypted 124 * data. 125 */ 126 unsigned char *po_enc_data; 127 128 lsquic_ver_tag_t po_ver_tag; /* Set if PO_VERSION is set */ 129 unsigned char *po_nonce; /* Use to generate header if PO_NONCE is set */ 130} lsquic_packet_out_t; 131 132/* The size of lsquic_packet_out_t could be further reduced: 133 * 134 * po_ver_tag could be encoded as a few bits representing enum lsquic_version 135 * in po_flags. The cost is a bit of complexity. This will save us four bytes. 136 */ 137 138#define lsquic_packet_out_avail(p) ((unsigned short) \ 139 ((p)->po_n_alloc - (p)->po_data_sz)) 140 141#define lsquic_packet_out_packno_bits(p) (((p)->po_flags >> POBIT_SHIFT) & 0x3) 142 143#define lsquic_packet_out_set_packno_bits(p, b) do { \ 144 (p)->po_flags &= ~(0x3 << POBIT_SHIFT); \ 145 (p)->po_flags |= ((b) & 0x3) << POBIT_SHIFT; \ 146} while (0) 147 148#define lsquic_packet_out_ipv6(p) ((int)(((p)->po_flags >> POIPv6_SHIFT) & 1)) 149 150#define lsquic_packet_out_set_ipv6(p, b) do { \ 151 (p)->po_flags &= ~(1 << POIPv6_SHIFT); \ 152 (p)->po_flags |= ((b) & 1) << POIPv6_SHIFT; \ 153} while (0) 154 155#define lsquic_po_header_length(lconn, po_flags) ( \ 156 lconn->cn_pf->pf_packout_header_size(lconn, po_flags)) 157 158#define lsquic_packet_out_total_sz(lconn, p) (\ 159 lconn->cn_pf->pf_packout_size(lconn, p)) 160 161#if __GNUC__ 162#if LSQUIC_EXTRA_CHECKS 163#define lsquic_packet_out_sent_sz(lconn, p) ( \ 164 __builtin_expect(((p)->po_flags & PO_SENT_SZ), 1) ? \ 165 (assert((p)->po_sent_sz == lsquic_packet_out_total_sz(lconn, p)), \ 166 (p)->po_sent_sz) : lsquic_packet_out_total_sz(lconn, p)) 167# else 168#define lsquic_packet_out_sent_sz(lconn, p) ( \ 169 __builtin_expect(((p)->po_flags & PO_SENT_SZ), 1) ? \ 170 (p)->po_sent_sz : lsquic_packet_out_total_sz(lconn, p)) 171#endif 172#else 173# define lsquic_packet_out_sent_sz(lconn, p) ( \ 174 (p)->po_flags & PO_SENT_SZ ? \ 175 (p)->po_sent_sz : lsquic_packet_out_total_sz(lconn, p)) 176#endif 177 178#define lsquic_packet_out_verneg(p) \ 179 (((p)->po_flags & (PO_NOENCRYPT|PO_VERNEG)) == (PO_NOENCRYPT|PO_VERNEG)) 180 181#define lsquic_packet_out_pubres(p) \ 182 (((p)->po_flags & (PO_NOENCRYPT|PO_VERNEG)) == PO_NOENCRYPT ) 183 184#define lsquic_packet_out_set_enc_level(p, level) do { \ 185 (p)->po_flags &= ~(3 << POLEV_SHIFT); \ 186 (p)->po_flags |= level << POLEV_SHIFT; \ 187} while (0) 188 189#define lsquic_packet_out_enc_level(p) (((p)->po_flags >> POLEV_SHIFT) & 3) 190 191struct packet_out_srec_iter { 192 lsquic_packet_out_t *packet_out; 193 struct stream_rec_arr *cur_srec_arr; 194 unsigned srec_idx; 195 int impl_idx; 196}; 197 198struct stream_rec * 199posi_first (struct packet_out_srec_iter *posi, lsquic_packet_out_t *); 200 201struct stream_rec * 202posi_next (struct packet_out_srec_iter *posi); 203 204lsquic_packet_out_t * 205lsquic_packet_out_new (struct lsquic_mm *, struct malo *, int use_cid, 206 const struct lsquic_conn *, enum packno_bits, 207 const lsquic_ver_tag_t *, const unsigned char *nonce); 208 209void 210lsquic_packet_out_destroy (lsquic_packet_out_t *, 211 struct lsquic_engine_public *, void *peer_ctx); 212 213int 214lsquic_packet_out_add_stream (lsquic_packet_out_t *packet_out, 215 struct lsquic_mm *mm, 216 struct lsquic_stream *new_stream, 217 enum quic_frame_type, 218 unsigned short off, unsigned short len); 219 220unsigned 221lsquic_packet_out_elide_reset_stream_frames (lsquic_packet_out_t *, uint32_t); 222 223int 224lsquic_packet_out_split_in_two (struct lsquic_mm *, lsquic_packet_out_t *, 225 lsquic_packet_out_t *, const struct parse_funcs *, unsigned excess_bytes); 226 227void 228lsquic_packet_out_chop_regen (lsquic_packet_out_t *); 229 230void 231lsquic_packet_out_ack_streams (struct lsquic_packet_out *); 232 233void 234lsquic_packet_out_zero_pad (struct lsquic_packet_out *); 235 236size_t 237lsquic_packet_out_mem_used (const struct lsquic_packet_out *); 238 239int 240lsquic_packet_out_turn_on_fin (struct lsquic_packet_out *, 241 const struct parse_funcs *, const struct lsquic_stream *); 242 243#endif 244