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 61206630 : # 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 314481 : fd_quic_ack_gen_init( fd_quic_ack_gen_t * ack_gen ) { 79 314481 : memset( ack_gen, 0, sizeof(fd_quic_ack_gen_t) ); 80 314481 : return ack_gen; 81 314481 : } 82 : 83 : /* fd_quic_ack_pkt queues a processed packet for acknowledgement. */ 84 : 85 : void 86 : fd_quic_ack_pkt( fd_quic_ack_gen_t * gen, 87 : ulong pkt_number, 88 : uint enc_level, 89 : ulong now ); 90 : 91 : /* fd_quic_ack_queue_ele returns the ack_queue element indexed by a 92 : sequence number. */ 93 : 94 : FD_FN_PURE static inline fd_quic_ack_t * 95 : fd_quic_ack_queue_ele( fd_quic_ack_gen_t * ack_gen, 96 60888151 : uint idx ) { 97 60888151 : return ack_gen->queue + (idx & (FD_QUIC_ACK_QUEUE_CNT-1)); 98 60888151 : } 99 : 100 : /* fd_quic_ack_gen_abandon_enc_level removes queued ACKs with an 101 : encryption level equal or lower than enc_level. */ 102 : 103 : void 104 : fd_quic_ack_gen_abandon_enc_level( fd_quic_ack_gen_t * ack_gen, 105 : uint enc_level ); 106 : 107 : /* fd_quic_gen_ack_frames writes ACK frames to the memory region 108 : [payload_ptr,payload_end). Returns a pointer one past the last byte 109 : written (in [payload_ptr,payload_end]). */ 110 : 111 : uchar * 112 : fd_quic_gen_ack_frames( fd_quic_ack_gen_t * gen, 113 : uchar * payload_ptr, 114 : uchar * payload_end, 115 : uint enc_level, 116 : ulong now ); 117 : 118 : FD_PROTOTYPES_END 119 : 120 : #endif /* HEADER_fd_src_waltz_quic_fd_quic_ack_tx_h */