Line data Source code
1 : #ifndef HEADER_fd_src_disco_fd_disco_base_h
2 : #define HEADER_fd_src_disco_fd_disco_base_h
3 :
4 : #include "../tango/fd_tango.h"
5 : #include "../ballet/shred/fd_shred.h"
6 : #include "../ballet/txn/fd_txn.h"
7 : #include "../flamenco/types/fd_types_custom.h"
8 : #include "../util/wksp/fd_wksp_private.h"
9 :
10 18 : #define DST_PROTO_OUTGOING (0UL)
11 0 : #define DST_PROTO_TPU_UDP (1UL)
12 0 : #define DST_PROTO_TPU_QUIC (2UL)
13 18 : #define DST_PROTO_SHRED (3UL)
14 0 : #define DST_PROTO_REPAIR (4UL)
15 0 : #define DST_PROTO_GOSSIP (5UL)
16 0 : #define DST_PROTO_SEND (6UL)
17 :
18 0 : #define POH_PKT_TYPE_MICROBLOCK (0UL)
19 0 : #define POH_PKT_TYPE_BECAME_LEADER (1UL)
20 0 : #define POH_PKT_TYPE_FEAT_ACT_SLOT (2UL)
21 :
22 : /* FD_NET_MTU is the max full packet size, with ethernet, IP, and UDP
23 : headers that can go in or out of the net tile. 2048 is the maximum
24 : XSK entry size, so this value follows naturally. */
25 :
26 39 : #define FD_NET_MTU (2048UL)
27 :
28 : /* FD_TPU_MTU is the max serialized byte size of a txn sent over TPU.
29 :
30 : This is minimum MTU of IPv6 packet - IPv6 header - UDP header
31 : 1280 - 40 - 8 */
32 :
33 0 : #define FD_TPU_MTU (1232UL)
34 :
35 : /* FD_GOSSIP_MTU is the max sz of a gossip packet which is the same as
36 : above. */
37 :
38 0 : #define FD_GOSSIP_MTU (FD_TPU_MTU)
39 :
40 : /* FD_SHRED_STORE_MTU is the size of an fd_shred34_t (statically
41 : asserted in fd_shred_tile.c). */
42 :
43 0 : #define FD_SHRED_STORE_MTU (41792UL)
44 :
45 : /* FD_SHRED_OUT_MTU is the maximum size of a frag on the shred_out
46 : link. This is the size of a data shred header + merkle root
47 : + chained merkle root. */
48 :
49 0 : #define FD_SHRED_OUT_MTU (FD_SHRED_DATA_HEADER_SZ + 2*FD_SHRED_MERKLE_ROOT_SZ + sizeof(int))
50 : FD_STATIC_ASSERT( FD_SHRED_OUT_MTU == 156UL , update FD_SHRED_OUT_MTU );
51 :
52 0 : #define FD_NETMUX_SIG_MIN_HDR_SZ ( 42UL) /* The default header size, which means no vlan tags and no IP options. */
53 : #define FD_NETMUX_SIG_IGNORE_HDR_SZ (102UL) /* Outside the allowable range, but still fits in 4 bits when compressed */
54 :
55 : /* These limits are defined here to prevent circular dependencies, and
56 : statically asserted they are calculated correctly in the relevant
57 : places. We get one bound using transactions that consume the minimum
58 : number of CUs and another bound using the minimum size transactions.
59 : The overall bound is the lower of the two. */
60 : #define FD_MAX_TXN_PER_SLOT_CU 98039UL
61 : #define FD_MAX_TXN_PER_SLOT_SHRED 272635UL
62 12 : #define FD_MAX_TXN_PER_SLOT 98039UL
63 : FD_STATIC_ASSERT( FD_MAX_TXN_PER_SLOT<=FD_MAX_TXN_PER_SLOT_CU&&FD_MAX_TXN_PER_SLOT<=FD_MAX_TXN_PER_SLOT_SHRED, max_txn_per_slot );
64 : FD_STATIC_ASSERT( FD_MAX_TXN_PER_SLOT>=FD_MAX_TXN_PER_SLOT_CU||FD_MAX_TXN_PER_SLOT>=FD_MAX_TXN_PER_SLOT_SHRED, max_txn_per_slot );
65 :
66 :
67 : FD_PROTOTYPES_BEGIN
68 :
69 : /* hdr_sz is the total size of network headers, including eth, ip, udp.
70 : Ignored for outgoing packets.
71 : For incoming packets, hash_{ip_addr,port} are the source IP and port,
72 : for outgoing packets, they are the destination IP and port. */
73 : FD_FN_CONST static inline ulong
74 : fd_disco_netmux_sig( uint hash_ip_addr,
75 : ushort hash_port,
76 : uint ip_addr,
77 : ulong proto,
78 36 : ulong hdr_sz ) {
79 : /* The size of an Ethernet header is 14+4k bytes, where 0<=k<=3 (?) is
80 : the number of vlan tags. The size of an IP header is 4j, where
81 : 5<=j<=15 is the size given in the header. The size of a UDP header
82 : is 8B. Thus, the total sum of these is 42+4i, where i=k+j-5,
83 : 0<=i<=13. Since bits are at a premium here, we compress the header
84 : size by just storing i. */
85 36 : ulong hdr_sz_i = ((hdr_sz - 42UL)>>2)&0xFUL;
86 36 : ulong hash = 0xfffffUL & fd_ulong_hash( (ulong)hash_ip_addr | ((ulong)hash_port<<32) );
87 36 : return (hash<<44) | ((hdr_sz_i&0xFUL)<<40UL) | ((proto&0xFFUL)<<32UL) | ((ulong)ip_addr);
88 36 : }
89 :
90 18 : FD_FN_CONST static inline ulong fd_disco_netmux_sig_hash ( ulong sig ) { return (sig>>44UL); }
91 18 : FD_FN_CONST static inline ulong fd_disco_netmux_sig_proto( ulong sig ) { return (sig>>32UL) & 0xFFUL; }
92 18 : FD_FN_CONST static inline uint fd_disco_netmux_sig_ip ( ulong sig ) { return (uint)(sig & 0xFFFFFFFFUL); }
93 :
94 : /* fd_disco_netmux_sig_hdr_sz extracts the total size of the Ethernet,
95 : IP, and UDP headers from the netmux signature field. The UDP payload
96 : of the packet stored in the corresponding frag begins at the returned
97 : offset. */
98 0 : FD_FN_CONST static inline ulong fd_disco_netmux_sig_hdr_sz( ulong sig ) { return 4UL*((sig>>40UL) & 0xFUL) + 42UL; }
99 :
100 : FD_FN_CONST static inline ulong
101 : fd_disco_poh_sig( ulong slot,
102 : ulong pkt_type,
103 0 : ulong execle_tile ) {
104 : /* The high 6 bits of the low byte of the signature field is the
105 : execle idx. Execles will filter to only handle frags with their
106 : own idx. The higher 7 bytes are the slot number. Technically,
107 : the slot number is a ulong, but it won't hit 256^7 for about 10^9
108 : years at the current rate. The lowest bits of the low byte is the
109 : packet type. */
110 0 : return (slot << 8) | ((execle_tile & 0x3FUL) << 2) | (pkt_type & 0x3UL);
111 0 : }
112 :
113 0 : FD_FN_CONST static inline ulong fd_disco_poh_sig_pkt_type( ulong sig ) { return (sig & 0x3UL); }
114 0 : FD_FN_CONST static inline ulong fd_disco_poh_sig_slot( ulong sig ) { return (sig >> 8); }
115 0 : FD_FN_CONST static inline ulong fd_disco_poh_sig_execle_tile( ulong sig ) { return (sig >> 2) & 0x3FUL; }
116 :
117 : FD_FN_CONST static inline ulong
118 : fd_disco_execle_sig( ulong slot,
119 0 : ulong pack_idx ) {
120 0 : return (slot << 32) | pack_idx;
121 0 : }
122 :
123 0 : FD_FN_CONST static inline ulong fd_disco_execle_sig_slot( ulong sig ) { return (sig >> 32); }
124 0 : FD_FN_CONST static inline ulong fd_disco_execle_sig_pack_idx( ulong sig ) { return sig & 0xFFFFFFFFUL; }
125 :
126 : /* fd_disco_shred_out_shred_sig constructs a sig for the shred_out link.
127 : The encoded fields vary depending on the type of the sig. The
128 : diagram below describes the encoding.
129 :
130 : is_turbine (1) | slot (32) | fec_set_idx (15) | is_code (1) | shred_idx or data_cnt (15)
131 : [63] | [31, 62] | [16, 30] | [15] | [0, 14]
132 :
133 : There are two types of messages on the shred_out link. The first
134 : type is a generic shred message. The second is a FEC set completion
135 : message. Since we have run out of bits, the receiver must look at the
136 : sz of the dcache entry to determine which type of message it is.
137 :
138 : For the first message type (SHRED):
139 :
140 : The first bit [63] describes whether this shred source was turbine
141 : or repair.
142 :
143 : The next 32 bits [31, 62] describe the slot number. Note: if the slot
144 : number is >= UINT_MAX, the sender will store the value UINT_MAX in
145 : this field. If the receiver sees a value of UINT_MAX in the field, it
146 : must read the actual slot number from the dcache entry.
147 :
148 : The following 15 bits [16, 30] describe the fec_set_idx. This is a
149 : 15-bit value because shreds are bounded to 2^15 per slot, so in the
150 : worst case there is an independent FEC set for every shred, which
151 : results in at most 2^15 FEC sets per slot.
152 :
153 : The next bit [15] describes whether it is a coding shred (is_code).
154 : If is_code = 0, the sig describes a data shred, and the last 15 bits
155 : [0, 14] encode the shred_idx. If is_code = 1, the sig describes a
156 : coding shred, and the last 15 bits encode the data_cnt.
157 :
158 : For the second message type (FEC):
159 :
160 : Currently, the size of the FEC message is
161 : FD_SHRED_DATA_HEADER_SZ + FD_SHRED_MERKLE_ROOT_SZ * 2 + sizeof(int).
162 :
163 : Only the slot and fec_set_idx bits are populated. The data in the
164 : frag is the full shred header of the last data shred in the FEC set,
165 : the merkle root of the FEC set, and the chained merkle root of the
166 : FEC. Each field immediately follows the other field. */
167 :
168 : /* TODO this shred_out_sig can be greatly simplified when FEC sets
169 : are uniformly coding shreds and fixed size. */
170 :
171 : FD_FN_CONST static inline ulong
172 : fd_disco_shred_out_shred_sig( int is_turbine,
173 : ulong slot,
174 : uint fec_set_idx,
175 : int is_code,
176 0 : uint shred_idx_or_data_cnt ) {
177 0 : ulong slot_ul = fd_ulong_min( slot, (ulong)UINT_MAX );
178 0 : ulong shred_idx_or_data_cnt_ul = fd_ulong_min( (ulong)shred_idx_or_data_cnt, (ulong)FD_SHRED_BLK_MAX );
179 0 : ulong fec_set_idx_ul = fd_ulong_min( (ulong)fec_set_idx, (ulong)FD_SHRED_BLK_MAX );
180 0 : ulong is_turbine_ul = !!is_turbine;
181 0 : ulong is_code_ul = !!is_code;
182 :
183 0 : return is_turbine_ul << 63 | slot_ul << 31 | fec_set_idx_ul << 16 | is_code_ul << 15 | shred_idx_or_data_cnt_ul;
184 0 : }
185 :
186 : /* fd_disco_shred_out_shred_sig_{...} are accessors for the fields encoded
187 : in the sig described above. */
188 :
189 0 : FD_FN_CONST static inline int fd_disco_shred_out_shred_sig_is_turbine ( ulong sig ) { return fd_ulong_extract_bit( sig, 63 ); }
190 0 : FD_FN_CONST static inline ulong fd_disco_shred_out_shred_sig_slot ( ulong sig ) { return fd_ulong_extract ( sig, 31, 62 ); }
191 0 : FD_FN_CONST static inline uint fd_disco_shred_out_shred_sig_fec_set_idx( ulong sig ) { return (uint)fd_ulong_extract ( sig, 16, 30 ); }
192 0 : FD_FN_CONST static inline int fd_disco_shred_out_shred_sig_is_code ( ulong sig ) { return fd_ulong_extract_bit( sig, 15 ); }
193 0 : FD_FN_CONST static inline uint fd_disco_shred_out_shred_sig_shred_idx ( ulong sig ) { return (uint)fd_ulong_extract_lsb( sig, 15 ); } /* only when is_code = 0 */
194 0 : FD_FN_CONST static inline uint fd_disco_shred_out_shred_sig_data_cnt ( ulong sig ) { return (uint)fd_ulong_extract_lsb( sig, 15 ); } /* only when is_code = 1 */
195 :
196 : /*
197 : | slot (32) | fec_set_idx (15) | data_cnt (15) | is_data_complete (1) | is_batch_complete (1) |
198 : | [32, 63] | [17, 31] | [2, 16] | [1] | [0] |
199 :
200 : */
201 : FD_FN_CONST static inline ulong
202 0 : fd_disco_shred_out_fec_sig( ulong slot, uint fec_set_idx, uint data_cnt, int is_slot_complete, int is_batch_complete ) {
203 0 : ulong slot_ul = fd_ulong_min( slot, (ulong)UINT_MAX );
204 0 : ulong fec_set_idx_ul = fd_ulong_min( (ulong)fec_set_idx, (ulong)FD_SHRED_BLK_MAX );
205 0 : ulong data_cnt_ul = fd_ulong_min( (ulong)data_cnt, (ulong)FD_SHRED_BLK_MAX );
206 0 : ulong is_slot_complete_ul = !!is_slot_complete;
207 0 : ulong is_batch_complete_ul = !!is_batch_complete;
208 0 : return slot_ul << 32 | fec_set_idx_ul << 17 | data_cnt_ul << 2 | is_slot_complete_ul << 1 | is_batch_complete_ul;
209 0 : }
210 :
211 0 : FD_FN_CONST static inline ulong fd_disco_shred_out_fec_sig_slot ( ulong sig ) { return fd_ulong_extract ( sig, 32, 63 ); }
212 0 : FD_FN_CONST static inline uint fd_disco_shred_out_fec_sig_fec_set_idx ( ulong sig ) { return (uint) fd_ulong_extract ( sig, 17, 31 ); }
213 0 : FD_FN_CONST static inline uint fd_disco_shred_out_fec_sig_data_cnt ( ulong sig ) { return (uint) fd_ulong_extract ( sig, 2, 16 ); }
214 0 : FD_FN_CONST static inline int fd_disco_shred_out_fec_sig_is_slot_complete ( ulong sig ) { return fd_ulong_extract_bit( sig, 1 ); }
215 0 : FD_FN_CONST static inline int fd_disco_shred_out_fec_sig_is_batch_complete( ulong sig ) { return fd_ulong_extract_bit( sig, 0 ); }
216 :
217 : /* Exclusively used for force completion messages */
218 :
219 : FD_FN_CONST static inline ulong
220 0 : fd_disco_repair_shred_sig( uint last_shred_idx ){
221 0 : return (ulong) last_shred_idx;
222 0 : }
223 :
224 0 : FD_FN_CONST static inline uint fd_disco_repair_shred_sig_last_shred_idx( ulong sig ) { return (uint) sig; }
225 :
226 :
227 : FD_FN_CONST static inline ulong
228 0 : fd_disco_repair_replay_sig( ulong slot, ushort parent_off, uint data_cnt, int slot_complete ) {
229 0 : /*
230 0 : | slot (32) | parent_off (16) | data_cnt (15) | slot_complete(1)
231 0 : | [32, 63] | [16, 31] | [1, 15] | [0]
232 0 : */
233 0 : ulong slot_ul = fd_ulong_min( slot, (ulong)UINT_MAX );
234 0 : ulong parent_off_ul = (ulong)parent_off;
235 0 : ulong data_cnt_ul = fd_ulong_min( (ulong)data_cnt, (ulong)FD_SHRED_BLK_MAX );
236 0 : ulong slot_complete_ul = !!slot_complete;
237 0 : return slot_ul << 32 | parent_off_ul << 16 | data_cnt_ul << 1 | slot_complete_ul;
238 0 : }
239 :
240 : FD_FN_PURE static inline ulong
241 0 : fd_disco_compact_chunk0( void * wksp ) {
242 0 : return (((struct fd_wksp_private *)wksp)->gaddr_lo) >> FD_CHUNK_LG_SZ;
243 0 : }
244 :
245 : FD_FN_PURE static inline ulong
246 0 : fd_disco_compact_wmark( void * wksp, ulong mtu ) {
247 0 : ulong chunk_mtu = ((mtu + 2UL*FD_CHUNK_SZ-1UL) >> (1+FD_CHUNK_LG_SZ)) << 1;
248 0 : ulong wksp_hi = ((struct fd_wksp_private *)wksp)->gaddr_hi;
249 0 : return (wksp_hi >> FD_CHUNK_LG_SZ) - chunk_mtu;
250 0 : }
251 :
252 : FD_PROTOTYPES_END
253 :
254 : #endif /* HEADER_fd_src_disco_fd_disco_base_h */
|