1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */ 250aadb33SDmitri Tikhonov/* 350aadb33SDmitri Tikhonov * lsquic_packet_out.h -- Structure and routines dealing with packet_out 450aadb33SDmitri Tikhonov */ 550aadb33SDmitri Tikhonov 650aadb33SDmitri Tikhonov#ifndef LSQUIC_PACKET_OUT_H 750aadb33SDmitri Tikhonov#define LSQUIC_PACKET_OUT_H 1 850aadb33SDmitri Tikhonov 950aadb33SDmitri Tikhonov#include <sys/queue.h> 1050aadb33SDmitri Tikhonov 1150aadb33SDmitri Tikhonovstruct malo; 129626cfc2SDmitri Tikhonovstruct lsquic_conn; 1350aadb33SDmitri Tikhonovstruct lsquic_engine_public; 1450aadb33SDmitri Tikhonovstruct lsquic_mm; 1550aadb33SDmitri Tikhonovstruct lsquic_stream; 165392f7a3SLiteSpeed Techstruct network_path; 1750aadb33SDmitri Tikhonovstruct parse_funcs; 185392f7a3SLiteSpeed Techstruct bwp_state; 1950aadb33SDmitri Tikhonov 20b8fa6195SDmitri Tikhonov/* Each frame_rec is associated with one packet_out. packet_out can have 21b8fa6195SDmitri Tikhonov * zero or more frame_rec structures. frame_rec keeps a pointer to a stream 22b8fa6195SDmitri Tikhonov * that has STREAM, CRYPTO, or RST_STREAM frames inside packet_out. 23b8fa6195SDmitri Tikhonov * `fe_frame_type' specifies the type of the frame; if this value is zero 24b8fa6195SDmitri Tikhonov * (this happens when a frame is elided), values of the other struct members 25b8fa6195SDmitri Tikhonov * are not valid. `fe_off' indicates where inside packet_out->po_data the 26b8fa6195SDmitri Tikhonov * frame begins and `fe_len' is its length. 2750aadb33SDmitri Tikhonov * 28b8fa6195SDmitri Tikhonov * We need this information for four reasons: 2950aadb33SDmitri Tikhonov * 1. A stream is not destroyed until all of its STREAM and RST_STREAM 3050aadb33SDmitri Tikhonov * frames are acknowledged. This is to make sure that we do not exceed 3150aadb33SDmitri Tikhonov * maximum allowed number of streams. 3250aadb33SDmitri Tikhonov * 2. When a packet is resubmitted, STREAM frames for a stream that has 3350aadb33SDmitri Tikhonov * been reset are not to be resubmitted. 34c51ce338SDmitri Tikhonov * 3. A buffered packet may have to be split before it is scheduled (this 35c51ce338SDmitri Tikhonov * occurs if we guessed incorrectly the number of bytes required to 36c51ce338SDmitri Tikhonov * encode the packet number and the actual number would make packet 37c51ce338SDmitri Tikhonov * larger than the max). 38b8fa6195SDmitri Tikhonov * 4. A lost or scheduled packet may need to be resized (down) when path 39b8fa6195SDmitri Tikhonov * changes or MTU is reduced due to an RTO. 40c51ce338SDmitri Tikhonov * 41b8fa6195SDmitri Tikhonov * In IETF, all frames are recorded. In gQUIC, only STREAM, RST_STREAM, 42b8fa6195SDmitri Tikhonov * ACK, and STOP_WAITING are recorded. The latter two are done so that 43b8fa6195SDmitri Tikhonov * ACK-deleting code in send controller (see po_regen_sz) is the same for 44b8fa6195SDmitri Tikhonov * both QUIC versions. 4550aadb33SDmitri Tikhonov */ 46b8fa6195SDmitri Tikhonovstruct frame_rec { 47b8fa6195SDmitri Tikhonov union { 48b8fa6195SDmitri Tikhonov struct lsquic_stream *stream; 49b8fa6195SDmitri Tikhonov uintptr_t data; 50b8fa6195SDmitri Tikhonov } fe_u; 51b8fa6195SDmitri Tikhonov#define fe_stream fe_u.stream 52b8fa6195SDmitri Tikhonov unsigned short fe_off, 53b8fa6195SDmitri Tikhonov fe_len; 54b8fa6195SDmitri Tikhonov enum quic_frame_type fe_frame_type; 5550aadb33SDmitri Tikhonov}; 5650aadb33SDmitri Tikhonov 57b8fa6195SDmitri Tikhonov#define frec_taken(frec) ((frec)->fe_frame_type) 5850aadb33SDmitri Tikhonov 59b8fa6195SDmitri Tikhonovstruct frame_rec_arr { 60b8fa6195SDmitri Tikhonov TAILQ_ENTRY(frame_rec_arr) next_stream_rec_arr; 61b8fa6195SDmitri Tikhonov struct frame_rec frecs[ 6250aadb33SDmitri Tikhonov ( 64 /* Efficient size for malo allocator */ 63b8fa6195SDmitri Tikhonov - sizeof(TAILQ_ENTRY(frame_rec)) /* next_stream_rec_arr */ 64b8fa6195SDmitri Tikhonov ) / sizeof(struct frame_rec) 6550aadb33SDmitri Tikhonov ]; 6650aadb33SDmitri Tikhonov}; 6750aadb33SDmitri Tikhonov 68b8fa6195SDmitri TikhonovTAILQ_HEAD(frame_rec_arr_tailq, frame_rec_arr); 69c51ce338SDmitri Tikhonov 705392f7a3SLiteSpeed Tech 7150aadb33SDmitri Tikhonovtypedef struct lsquic_packet_out 7250aadb33SDmitri Tikhonov{ 7350aadb33SDmitri Tikhonov /* `po_next' is used for packets_out, unacked_packets and expired_packets 7450aadb33SDmitri Tikhonov * lists. 7550aadb33SDmitri Tikhonov */ 7650aadb33SDmitri Tikhonov TAILQ_ENTRY(lsquic_packet_out) 7750aadb33SDmitri Tikhonov po_next; 7850aadb33SDmitri Tikhonov lsquic_time_t po_sent; /* Time sent */ 7950aadb33SDmitri Tikhonov lsquic_packno_t po_packno; 805392f7a3SLiteSpeed Tech lsquic_packno_t po_ack2ed; /* If packet has ACK frame, value of 815392f7a3SLiteSpeed Tech * largest acked in it. 825392f7a3SLiteSpeed Tech */ 835392f7a3SLiteSpeed Tech struct lsquic_packet_out 845392f7a3SLiteSpeed Tech *po_loss_chain; /* Circular linked list */ 8550aadb33SDmitri Tikhonov 865392f7a3SLiteSpeed Tech enum quic_ft_bit po_frame_types; /* Bitmask of QUIC_FRAME_* */ 87bfc7bfd8SDmitri Tikhonov enum packet_out_flags { 885392f7a3SLiteSpeed Tech /* TODO XXX Phase out PO_MINI in favor of a more specialized flag: 895392f7a3SLiteSpeed Tech * we only need an indicator that a packet contains STREAM frames 90b8fa6195SDmitri Tikhonov * but no associated frecs. This type of packets in only created 915392f7a3SLiteSpeed Tech * by GQUIC mini conn. 925392f7a3SLiteSpeed Tech */ 935392f7a3SLiteSpeed Tech PO_MINI = (1 << 0), /* Allocated by mini connection */ 94bfc7bfd8SDmitri Tikhonov PO_HELLO = (1 << 1), /* Packet contains SHLO or CHLO data */ 955392f7a3SLiteSpeed Tech PO_SENT = (1 << 2), /* Packet has been sent (mini only) */ 96bfc7bfd8SDmitri Tikhonov PO_ENCRYPTED= (1 << 3), /* po_enc_data has encrypted data */ 97b8fa6195SDmitri Tikhonov PO_FREC_ARR = (1 << 4), 98bfc7bfd8SDmitri Tikhonov#define POBIT_SHIFT 5 99bfc7bfd8SDmitri Tikhonov PO_BITS_0 = (1 << 5), /* PO_BITS_0 and PO_BITS_1 encode the */ 100bfc7bfd8SDmitri Tikhonov PO_BITS_1 = (1 << 6), /* packet number length. See macros below. */ 101bfc7bfd8SDmitri Tikhonov PO_NONCE = (1 << 7), /* Use value in `po_nonce' to generate header */ 102bfc7bfd8SDmitri Tikhonov PO_VERSION = (1 << 8), /* Use value in `po_ver_tag' to generate header */ 103bfc7bfd8SDmitri Tikhonov PO_CONN_ID = (1 << 9), /* Include connection ID in public header */ 104bfc7bfd8SDmitri Tikhonov PO_REPACKNO = (1 <<10), /* Regenerate packet number */ 105bfc7bfd8SDmitri Tikhonov PO_NOENCRYPT= (1 <<11), /* Do not encrypt data in po_data */ 106bfc7bfd8SDmitri Tikhonov PO_VERNEG = (1 <<12), /* Version negotiation packet. */ 107bfc7bfd8SDmitri Tikhonov PO_STREAM_END 108bfc7bfd8SDmitri Tikhonov = (1 <<13), /* STREAM frame reaches the end of the packet: no 109bfc7bfd8SDmitri Tikhonov * further writes are allowed. 110bfc7bfd8SDmitri Tikhonov */ 111bfc7bfd8SDmitri Tikhonov PO_SCHED = (1 <<14), /* On scheduled queue */ 11216a9b66aSDmitri Tikhonov PO_SENT_SZ = (1 <<15), 1137a8b2eceSDmitri Tikhonov PO_LONGHEAD = (1 <<16), 1141e75f938SDmitri Tikhonov#define POIPv6_SHIFT 20 1151e75f938SDmitri Tikhonov PO_IPv6 = (1 <<20), /* Set if pmi_allocate was passed is_ipv6=1, 1161e75f938SDmitri Tikhonov * otherwise unset. 1171e75f938SDmitri Tikhonov */ 118b8fa6195SDmitri Tikhonov PO_MTU_PROBE= (1 <<21), /* Special loss and ACK rules apply */ 1195392f7a3SLiteSpeed Tech#define POPNS_SHIFT 22 1205392f7a3SLiteSpeed Tech PO_PNS_HSK = (1 <<22), /* PNS bits contain the value of the */ 1215392f7a3SLiteSpeed Tech PO_PNS_APP = (1 <<23), /* packet number space. */ 1225392f7a3SLiteSpeed Tech PO_RETRY = (1 <<24), /* Retry packet */ 1235392f7a3SLiteSpeed Tech PO_RETX = (1 <<25), /* Retransmitted packet: don't append to it */ 124de46bf2fSDmitri Tikhonov PO_POISON = (1 <<26), /* Used to detect opt-ACK attack */ 1255392f7a3SLiteSpeed Tech PO_LOSS_REC = (1 <<27), /* This structure is a loss record */ 1265392f7a3SLiteSpeed Tech /* Only one of PO_SCHED, PO_UNACKED, or PO_LOST can be set. If pressed 1275392f7a3SLiteSpeed Tech * for room in the enum, we can switch to using two bits to represent 1285392f7a3SLiteSpeed Tech * this information. 1295392f7a3SLiteSpeed Tech */ 1305392f7a3SLiteSpeed Tech PO_UNACKED = (1 <<28), /* On unacked queue */ 1315392f7a3SLiteSpeed Tech PO_LOST = (1 <<29), /* On lost queue */ 1325392f7a3SLiteSpeed Tech#define POSPIN_SHIFT 30 1335392f7a3SLiteSpeed Tech PO_SPIN_BIT = (1 <<30), /* Value of the spin bit */ 1349626cfc2SDmitri Tikhonov } po_flags; 135bfc7bfd8SDmitri Tikhonov unsigned short po_data_sz; /* Number of usable bytes in data */ 136bfc7bfd8SDmitri Tikhonov unsigned short po_enc_data_sz; /* Number of usable bytes in data */ 13716a9b66aSDmitri Tikhonov unsigned short po_sent_sz; /* If PO_SENT_SZ is set, real size of sent buffer. */ 138b8fa6195SDmitri Tikhonov /* TODO Revisit po_regen_sz once gQUIC is dropped. Now that all frames 139b8fa6195SDmitri Tikhonov * are recorded, we have more flexibility where to place ACK frames; they 140b8fa6195SDmitri Tikhonov * no longer really have to be at the beginning of the packet, since we 141b8fa6195SDmitri Tikhonov * can locate them. 142b8fa6195SDmitri Tikhonov */ 143bfc7bfd8SDmitri Tikhonov unsigned short po_regen_sz; /* Number of bytes at the beginning 144bfc7bfd8SDmitri Tikhonov * of data containing bytes that are 145bfc7bfd8SDmitri Tikhonov * not to be retransmitted, e.g. ACK 146bfc7bfd8SDmitri Tikhonov * frames. 147bfc7bfd8SDmitri Tikhonov */ 148bfc7bfd8SDmitri Tikhonov unsigned short po_n_alloc; /* Total number of bytes allocated in po_data */ 1495392f7a3SLiteSpeed Tech unsigned short po_token_len; 1509626cfc2SDmitri Tikhonov enum header_type po_header_type:8; 151b1a7c3f9SDmitri Tikhonov unsigned char po_dcid_len; /* If PO_ENCRYPTED is set */ 1525392f7a3SLiteSpeed Tech enum { 1535392f7a3SLiteSpeed Tech POL_GQUIC = 1 << 0, /* Used for logging */ 1545392f7a3SLiteSpeed Tech#define POLEV_SHIFT 1 1555392f7a3SLiteSpeed Tech POL_ELBIT_0 = 1 << 1, /* EL bits encode the crypto level. */ 1565392f7a3SLiteSpeed Tech POL_ELBIT_1 = 1 << 2, 1575392f7a3SLiteSpeed Tech#define POKP_SHIFT 3 1589fc12041SDmitri Tikhonov POL_KEY_PHASE= 1 << 3, 1595392f7a3SLiteSpeed Tech#define POECN_SHIFT 4 1605392f7a3SLiteSpeed Tech POL_ECNBIT_0 = 1 << 4, 1615392f7a3SLiteSpeed Tech POL_ECNBIT_1 = 1 << 5, 16202b6086dSDmitri Tikhonov POL_LOG_QL_BITS = 1 << 6, 16302b6086dSDmitri Tikhonov POL_SQUARE_BIT = 1 << 7, 16402b6086dSDmitri Tikhonov POL_LOSS_BIT = 1 << 8, 165da99665bSDmitri Tikhonov#ifndef NDEBUG 166da99665bSDmitri Tikhonov POL_HEADER_PROT = 1 << 9, /* Header protection applied */ 167da99665bSDmitri Tikhonov#endif 168b8fa6195SDmitri Tikhonov POL_LIMITED = 1 << 10, /* Used to credit sc_next_limit if needed. */ 169fcbdf653SDmitri Tikhonov POL_FACKED = 1 << 11, /* Lost due to FACK check */ 17002b6086dSDmitri Tikhonov } po_lflags:16; 171bfc7bfd8SDmitri Tikhonov unsigned char *po_data; 172bfc7bfd8SDmitri Tikhonov 173b8fa6195SDmitri Tikhonov /* A lot of packets contain only one frame. Thus, `one' is used first. 174b8fa6195SDmitri Tikhonov * If this is not enough, any number of frame_rec_arr structures can be 175b8fa6195SDmitri Tikhonov * allocated to handle more frame records. 17650aadb33SDmitri Tikhonov */ 177c51ce338SDmitri Tikhonov union { 178b8fa6195SDmitri Tikhonov struct frame_rec one; 179b8fa6195SDmitri Tikhonov struct frame_rec_arr_tailq arr; 180b8fa6195SDmitri Tikhonov } po_frecs; 18150aadb33SDmitri Tikhonov 18250aadb33SDmitri Tikhonov /* If PO_ENCRYPTED is set, this points to the buffer that holds encrypted 18350aadb33SDmitri Tikhonov * data. 18450aadb33SDmitri Tikhonov */ 18550aadb33SDmitri Tikhonov unsigned char *po_enc_data; 18650aadb33SDmitri Tikhonov 18750aadb33SDmitri Tikhonov lsquic_ver_tag_t po_ver_tag; /* Set if PO_VERSION is set */ 18850aadb33SDmitri Tikhonov unsigned char *po_nonce; /* Use to generate header if PO_NONCE is set */ 1895392f7a3SLiteSpeed Tech const struct network_path 1905392f7a3SLiteSpeed Tech *po_path; 1915392f7a3SLiteSpeed Tech#define po_token po_nonce 1925392f7a3SLiteSpeed Tech struct bwp_state *po_bwp_state; 19350aadb33SDmitri Tikhonov} lsquic_packet_out_t; 19450aadb33SDmitri Tikhonov 1955392f7a3SLiteSpeed Tech/* This is to make sure these bit names are not used, they are only for 1965392f7a3SLiteSpeed Tech * convenience in gdb output. 1975392f7a3SLiteSpeed Tech */ 1985392f7a3SLiteSpeed Tech#define PO_PNS_HSK 1995392f7a3SLiteSpeed Tech#define PO_PNS_APP 2005392f7a3SLiteSpeed Tech 20150aadb33SDmitri Tikhonov/* The size of lsquic_packet_out_t could be further reduced: 20250aadb33SDmitri Tikhonov * 20350aadb33SDmitri Tikhonov * po_ver_tag could be encoded as a few bits representing enum lsquic_version 20450aadb33SDmitri Tikhonov * in po_flags. The cost is a bit of complexity. This will save us four bytes. 20550aadb33SDmitri Tikhonov */ 20650aadb33SDmitri Tikhonov 20750aadb33SDmitri Tikhonov#define lsquic_packet_out_avail(p) ((unsigned short) \ 20850aadb33SDmitri Tikhonov ((p)->po_n_alloc - (p)->po_data_sz)) 20950aadb33SDmitri Tikhonov 21050aadb33SDmitri Tikhonov#define lsquic_packet_out_packno_bits(p) (((p)->po_flags >> POBIT_SHIFT) & 0x3) 21150aadb33SDmitri Tikhonov 212bfc7bfd8SDmitri Tikhonov#define lsquic_packet_out_set_packno_bits(p, b) do { \ 213bfc7bfd8SDmitri Tikhonov (p)->po_flags &= ~(0x3 << POBIT_SHIFT); \ 214bfc7bfd8SDmitri Tikhonov (p)->po_flags |= ((b) & 0x3) << POBIT_SHIFT; \ 215bfc7bfd8SDmitri Tikhonov} while (0) 216bfc7bfd8SDmitri Tikhonov 2171e75f938SDmitri Tikhonov#define lsquic_packet_out_ipv6(p) ((int)(((p)->po_flags >> POIPv6_SHIFT) & 1)) 2181e75f938SDmitri Tikhonov 2191e75f938SDmitri Tikhonov#define lsquic_packet_out_set_ipv6(p, b) do { \ 2201e75f938SDmitri Tikhonov (p)->po_flags &= ~(1 << POIPv6_SHIFT); \ 2211e75f938SDmitri Tikhonov (p)->po_flags |= ((b) & 1) << POIPv6_SHIFT; \ 2221e75f938SDmitri Tikhonov} while (0) 2231e75f938SDmitri Tikhonov 2245392f7a3SLiteSpeed Tech#define lsquic_packet_out_spin_bit(p) (((p)->po_flags & PO_SPIN_BIT) > 0) 22502b6086dSDmitri Tikhonov#define lsquic_packet_out_square_bit(p) (((p)->po_lflags & POL_SQUARE_BIT) > 0) 22602b6086dSDmitri Tikhonov#define lsquic_packet_out_loss_bit(p) (((p)->po_lflags & POL_LOSS_BIT) > 0) 2275392f7a3SLiteSpeed Tech 2285392f7a3SLiteSpeed Tech#define lsquic_packet_out_set_spin_bit(p, b) do { \ 2295392f7a3SLiteSpeed Tech (p)->po_flags &= ~PO_SPIN_BIT; \ 2305392f7a3SLiteSpeed Tech (p)->po_flags |= ((b) & 1) << POSPIN_SHIFT; \ 2315392f7a3SLiteSpeed Tech} while (0) 2325392f7a3SLiteSpeed Tech 2334429f8eaSDmitri Tikhonov#define lsquic_po_header_length(lconn, po_flags, dcid_len, header_type) ( \ 2344429f8eaSDmitri Tikhonov lconn->cn_pf->pf_packout_max_header_size(lconn, po_flags, dcid_len, \ 2354429f8eaSDmitri Tikhonov header_type)) \ 23650aadb33SDmitri Tikhonov 2379626cfc2SDmitri Tikhonov#define lsquic_packet_out_total_sz(lconn, p) (\ 238b55a5117SDmitri Tikhonov (lconn)->cn_pf->pf_packout_size(lconn, p)) 239bfc7bfd8SDmitri Tikhonov 24016a9b66aSDmitri Tikhonov#if __GNUC__ 24116a9b66aSDmitri Tikhonov#if LSQUIC_EXTRA_CHECKS 2429626cfc2SDmitri Tikhonov#define lsquic_packet_out_sent_sz(lconn, p) ( \ 24316a9b66aSDmitri Tikhonov __builtin_expect(((p)->po_flags & PO_SENT_SZ), 1) ? \ 2448ae5ecb4SDmitri Tikhonov (assert(((p)->po_flags & PO_HELLO /* Avoid client DCID change */) \ 2458ae5ecb4SDmitri Tikhonov || (p)->po_sent_sz == lsquic_packet_out_total_sz(lconn, p)), \ 2469626cfc2SDmitri Tikhonov (p)->po_sent_sz) : lsquic_packet_out_total_sz(lconn, p)) 24716a9b66aSDmitri Tikhonov# else 2489626cfc2SDmitri Tikhonov#define lsquic_packet_out_sent_sz(lconn, p) ( \ 24916a9b66aSDmitri Tikhonov __builtin_expect(((p)->po_flags & PO_SENT_SZ), 1) ? \ 2509626cfc2SDmitri Tikhonov (p)->po_sent_sz : lsquic_packet_out_total_sz(lconn, p)) 25116a9b66aSDmitri Tikhonov#endif 25216a9b66aSDmitri Tikhonov#else 2539626cfc2SDmitri Tikhonov# define lsquic_packet_out_sent_sz(lconn, p) ( \ 25416a9b66aSDmitri Tikhonov (p)->po_flags & PO_SENT_SZ ? \ 2559626cfc2SDmitri Tikhonov (p)->po_sent_sz : lsquic_packet_out_total_sz(lconn, p)) 25616a9b66aSDmitri Tikhonov#endif 25716a9b66aSDmitri Tikhonov 25850aadb33SDmitri Tikhonov#define lsquic_packet_out_verneg(p) \ 2595392f7a3SLiteSpeed Tech (((p)->po_flags & (PO_NOENCRYPT|PO_VERNEG|PO_RETRY)) == (PO_NOENCRYPT|PO_VERNEG)) 26050aadb33SDmitri Tikhonov 26150aadb33SDmitri Tikhonov#define lsquic_packet_out_pubres(p) \ 2625392f7a3SLiteSpeed Tech (((p)->po_flags & (PO_NOENCRYPT|PO_VERNEG|PO_RETRY)) == PO_NOENCRYPT ) 2635392f7a3SLiteSpeed Tech 2645392f7a3SLiteSpeed Tech#define lsquic_packet_out_retry(p) \ 2655392f7a3SLiteSpeed Tech (((p)->po_flags & (PO_NOENCRYPT|PO_VERNEG|PO_RETRY)) == (PO_NOENCRYPT|PO_RETRY) ) 26650aadb33SDmitri Tikhonov 2679626cfc2SDmitri Tikhonov#define lsquic_packet_out_set_enc_level(p, level) do { \ 2685392f7a3SLiteSpeed Tech (p)->po_lflags &= ~(3 << POLEV_SHIFT); \ 2695392f7a3SLiteSpeed Tech (p)->po_lflags |= level << POLEV_SHIFT; \ 2705392f7a3SLiteSpeed Tech} while (0) 2715392f7a3SLiteSpeed Tech 2725392f7a3SLiteSpeed Tech#define lsquic_packet_out_enc_level(p) (((p)->po_lflags >> POLEV_SHIFT) & 3) 2735392f7a3SLiteSpeed Tech 2745392f7a3SLiteSpeed Tech#define lsquic_packet_out_set_kp(p, kp) do { \ 2755392f7a3SLiteSpeed Tech (p)->po_lflags &= ~(1 << POKP_SHIFT); \ 2765392f7a3SLiteSpeed Tech (p)->po_lflags |= kp << POKP_SHIFT; \ 2775392f7a3SLiteSpeed Tech} while (0) 2785392f7a3SLiteSpeed Tech 2795392f7a3SLiteSpeed Tech#define lsquic_packet_out_kp(p) (((p)->po_lflags >> POKP_SHIFT) & 1) 2805392f7a3SLiteSpeed Tech 2815392f7a3SLiteSpeed Tech#define lsquic_packet_out_set_pns(p, pns) do { \ 2825392f7a3SLiteSpeed Tech (p)->po_flags &= ~(3 << POPNS_SHIFT); \ 2835392f7a3SLiteSpeed Tech (p)->po_flags |= pns << POPNS_SHIFT; \ 2845392f7a3SLiteSpeed Tech} while (0) 2855392f7a3SLiteSpeed Tech 2865392f7a3SLiteSpeed Tech#define lsquic_packet_out_pns(p) (((p)->po_flags >> POPNS_SHIFT) & 3) 2875392f7a3SLiteSpeed Tech 2885392f7a3SLiteSpeed Tech#define lsquic_packet_out_set_ecn(p, ecn) do { \ 2895392f7a3SLiteSpeed Tech (p)->po_lflags &= ~(3 << POECN_SHIFT); \ 2905392f7a3SLiteSpeed Tech (p)->po_lflags |= ecn << POECN_SHIFT; \ 2919626cfc2SDmitri Tikhonov} while (0) 2929626cfc2SDmitri Tikhonov 2935392f7a3SLiteSpeed Tech#define lsquic_packet_out_ecn(p) (((p)->po_lflags >> POECN_SHIFT) & 3) 2949626cfc2SDmitri Tikhonov 295b8fa6195SDmitri Tikhonovstruct packet_out_frec_iter { 29650aadb33SDmitri Tikhonov lsquic_packet_out_t *packet_out; 297b8fa6195SDmitri Tikhonov struct frame_rec_arr *cur_frec_arr; 298b8fa6195SDmitri Tikhonov unsigned frec_idx; 299c51ce338SDmitri Tikhonov int impl_idx; 30050aadb33SDmitri Tikhonov}; 30150aadb33SDmitri Tikhonov 3025392f7a3SLiteSpeed Tech 303b8fa6195SDmitri Tikhonovstruct frame_rec * 304b8fa6195SDmitri Tikhonovlsquic_pofi_first (struct packet_out_frec_iter *pofi, lsquic_packet_out_t *); 30550aadb33SDmitri Tikhonov 306b8fa6195SDmitri Tikhonovstruct frame_rec * 307b8fa6195SDmitri Tikhonovlsquic_pofi_next (struct packet_out_frec_iter *pofi); 30850aadb33SDmitri Tikhonov 30950aadb33SDmitri Tikhonovlsquic_packet_out_t * 31050aadb33SDmitri Tikhonovlsquic_packet_out_new (struct lsquic_mm *, struct malo *, int use_cid, 311c7d81ce1SDmitri Tikhonov const struct lsquic_conn *, enum packno_bits, 3125392f7a3SLiteSpeed Tech const lsquic_ver_tag_t *, const unsigned char *nonce, 3134429f8eaSDmitri Tikhonov const struct network_path *, enum header_type); 31450aadb33SDmitri Tikhonov 31550aadb33SDmitri Tikhonovvoid 31650aadb33SDmitri Tikhonovlsquic_packet_out_destroy (lsquic_packet_out_t *, 3171e75f938SDmitri Tikhonov struct lsquic_engine_public *, void *peer_ctx); 31850aadb33SDmitri Tikhonov 31950aadb33SDmitri Tikhonovint 320b8fa6195SDmitri Tikhonovlsquic_packet_out_add_frame (struct lsquic_packet_out *, 321b8fa6195SDmitri Tikhonov struct lsquic_mm *, uintptr_t data, enum quic_frame_type, 322b8fa6195SDmitri Tikhonov unsigned short off, unsigned short len); 323b8fa6195SDmitri Tikhonov 324b8fa6195SDmitri Tikhonovint 32550aadb33SDmitri Tikhonovlsquic_packet_out_add_stream (lsquic_packet_out_t *packet_out, 32650aadb33SDmitri Tikhonov struct lsquic_mm *mm, 32750aadb33SDmitri Tikhonov struct lsquic_stream *new_stream, 3286aba801dSDmitri Tikhonov enum quic_frame_type, 329c51ce338SDmitri Tikhonov unsigned short off, unsigned short len); 33050aadb33SDmitri Tikhonov 331bfc7bfd8SDmitri Tikhonovunsigned 3325392f7a3SLiteSpeed Techlsquic_packet_out_elide_reset_stream_frames (lsquic_packet_out_t *, 3335392f7a3SLiteSpeed Tech lsquic_stream_id_t); 334c51ce338SDmitri Tikhonov 33550aadb33SDmitri Tikhonovvoid 33650aadb33SDmitri Tikhonovlsquic_packet_out_chop_regen (lsquic_packet_out_t *); 33750aadb33SDmitri Tikhonov 338c51ce338SDmitri Tikhonovvoid 339c51ce338SDmitri Tikhonovlsquic_packet_out_ack_streams (struct lsquic_packet_out *); 340c51ce338SDmitri Tikhonov 341c51ce338SDmitri Tikhonovvoid 342c51ce338SDmitri Tikhonovlsquic_packet_out_zero_pad (struct lsquic_packet_out *); 343c51ce338SDmitri Tikhonov 344c51ce338SDmitri Tikhonovsize_t 345c51ce338SDmitri Tikhonovlsquic_packet_out_mem_used (const struct lsquic_packet_out *); 346c51ce338SDmitri Tikhonov 347c51ce338SDmitri Tikhonovint 348c51ce338SDmitri Tikhonovlsquic_packet_out_turn_on_fin (struct lsquic_packet_out *, 349c51ce338SDmitri Tikhonov const struct parse_funcs *, const struct lsquic_stream *); 350c51ce338SDmitri Tikhonov 351b1a7c3f9SDmitri Tikhonovint 352b1a7c3f9SDmitri Tikhonovlsquic_packet_out_equal_dcids (const struct lsquic_packet_out *, 353b1a7c3f9SDmitri Tikhonov const struct lsquic_packet_out *); 35471eb4000SDmitri Tikhonov 35571eb4000SDmitri Tikhonovvoid 35671eb4000SDmitri Tikhonovlsquic_packet_out_pad_over (struct lsquic_packet_out *packet_out, 35771eb4000SDmitri Tikhonov enum quic_ft_bit frame_types); 35871eb4000SDmitri Tikhonov 35950aadb33SDmitri Tikhonov#endif 360