Line data Source code
1 : #ifndef HEADER_fd_src_waltz_quic_fd_quic_ack_tx_h 2 : #define HEADER_fd_src_waltz_quic_fd_quic_ack_tx_h 3 : 4 : /* fd_quic_ack_tx.h provides APIs for generating ACK packets. 5 : 6 : fd_quic generates delayed ACKs fire-and-forget style. 7 : Outgoing ACKs are artificially delayed by a pseudorandom delay. 8 : The max delay is known to the peer via the max_ack_delay transport 9 : parameter. */ 10 : 11 : #include "fd_quic_common.h" 12 : 13 : #define FD_ACK_DEBUG(...) 14 : //#define FD_ACK_DEBUG(...) __VA_ARGS__ 15 : 16 : /* FD_QUIC_ACK_QUEUE_CNT controls the number of disjoint ACK ranges 17 : that can be acknowledged between two calls to fd_quic_service. 18 : Higher values decrease retransmission rates in case of excessive 19 : reordering. Must be a power of 2. 20 : 21 : Seq ack_queue_head-1 is always assumed to be valid. */ 22 : 23 111891621 : # define FD_QUIC_ACK_QUEUE_CNT (64) 24 : 25 : /* fd_quic_ack_t is used to build an ACK frame. It contains a 26 : contiguous range of packet numbers to ACK. Whenever an fd_quic_t 27 : instance successfully processes a packet, it accumulates the packet 28 : number into an fd_quic_ack_t. */ 29 : 30 : struct __attribute__((aligned(16))) fd_quic_ack { 31 : fd_quic_range_t pkt_number; /* Range of packet numbers being ACKed */ 32 : ulong ts; /* timestamp of highest packet number */ 33 : uchar enc_level; /* in [0,4) */ 34 : /* FIXME enc_level should technically be pn_space instead */ 35 : uchar _pad[7]; 36 : /* Tuned to 32 byte size */ 37 : }; 38 : 39 : typedef struct fd_quic_ack fd_quic_ack_t; 40 : 41 : /* fd_quic_ack_gen_t records processed packet numbers and builds ACK 42 : frames. 43 : 44 : is_elicited==1 if at least one ACK-eliciting frame was received. 45 : No ACK frames will be generated unless this is the case. 46 : 47 : ack_instant==1 if an ACK for a packet must not be delayed. 48 : This is currently the case for initial and handshake-level packets. 49 : Note that is_elicited==1 takes priority. 50 : 51 : The ack_queue ring caches the last generated ACK frames. It uses 52 : sequence numbers that wrap around in [0,2^32). queue_tail is the seq 53 : no of the oldest unsent ACK frame. queue_head is the next unused 54 : seq. Note that packet number ranges in this ring have no ordering 55 : requirements. 56 : 57 : All fd_quic_ack_t in the ack_queue array are initialized, even when 58 : they are not present in the ring. If the ring is empty (head==tail), 59 : may peek the element at seq queue_head-1. */ 60 : 61 : struct __attribute__((aligned(16))) fd_quic_ack_gen { 62 : 63 : fd_quic_ack_t queue[FD_QUIC_ACK_QUEUE_CNT]; 64 : uint head; 65 : uint tail; 66 : 67 : uchar is_elicited; 68 : 69 : }; 70 : 71 : typedef struct fd_quic_ack_gen fd_quic_ack_gen_t; 72 : 73 : FD_PROTOTYPES_BEGIN 74 : 75 : /* fd_quic_ack_gen_init initializes the fd_quic_ack_gen_t instance. */ 76 : 77 : static inline fd_quic_ack_gen_t * 78 314379 : fd_quic_ack_gen_init( fd_quic_ack_gen_t * ack_gen ) { 79 314379 : memset( ack_gen, 0, sizeof(fd_quic_ack_gen_t) ); 80 314379 : return ack_gen; 81 314379 : } 82 : 83 : /* fd_quic_ack_pkt queues a processed packet for acknowledgement. */ 84 : 85 : int 86 : fd_quic_ack_pkt( fd_quic_ack_gen_t * gen, 87 : ulong pkt_number, 88 : uint enc_level, 89 : ulong now ); 90 : 91 3 : #define FD_QUIC_ACK_TX_NOOP (0) 92 324255 : #define FD_QUIC_ACK_TX_NEW (1) 93 93346316 : #define FD_QUIC_ACK_TX_MERGED (2) 94 0 : #define FD_QUIC_ACK_TX_ENOSPC (3) 95 0 : #define FD_QUIC_ACK_TX_CANCEL (4) 96 : #define FD_QUIC_ACK_TX_CNT (5) 97 : 98 : /* fd_quic_ack_queue_ele returns the ack_queue element indexed by a 99 : sequence number. */ 100 : 101 : FD_FN_PURE static inline fd_quic_ack_t * 102 : fd_quic_ack_queue_ele( fd_quic_ack_gen_t * ack_gen, 103 111566985 : uint idx ) { 104 111566985 : return ack_gen->queue + (idx & (FD_QUIC_ACK_QUEUE_CNT-1)); 105 111566985 : } 106 : 107 : /* fd_quic_ack_gen_abandon_enc_level removes queued ACKs with an 108 : encryption level equal or lower than enc_level. */ 109 : 110 : void 111 : fd_quic_ack_gen_abandon_enc_level( fd_quic_ack_gen_t * ack_gen, 112 : uint enc_level ); 113 : 114 : /* fd_quic_gen_ack_frames writes ACK frames to the memory region 115 : [payload_ptr,payload_end). Returns a pointer one past the last byte 116 : written (in [payload_ptr,payload_end]). */ 117 : 118 : uchar * 119 : fd_quic_gen_ack_frames( fd_quic_ack_gen_t * gen, 120 : uchar * payload_ptr, 121 : uchar * payload_end, 122 : uint enc_level, 123 : ulong tickcount, 124 : float tick_per_us ); 125 : 126 : FD_PROTOTYPES_END 127 : 128 : #endif /* HEADER_fd_src_waltz_quic_fd_quic_ack_tx_h */