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 :
8 : #include "../util/wksp/fd_wksp_private.h"
9 :
10 0 : #define DST_PROTO_OUTGOING (0UL)
11 0 : #define DST_PROTO_TPU_UDP (1UL)
12 0 : #define DST_PROTO_TPU_QUIC (2UL)
13 0 : #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_DONE_PACKING (2UL)
21 0 : #define POH_PKT_TYPE_FEAT_ACT_SLOT (3UL)
22 :
23 : #define REPLAY_FLAG_FINISHED_BLOCK (0x01UL)
24 0 : #define REPLAY_FLAG_PACKED_MICROBLOCK (0x02UL)
25 : #define REPLAY_FLAG_MICROBLOCK (0x04UL)
26 : #define REPLAY_FLAG_CATCHING_UP (0x08UL)
27 0 : #define REPLAY_FLAG_INIT (0x10UL)
28 :
29 0 : #define EXEC_FLAG_READY_NEW (0x20UL)
30 0 : #define EXEC_FLAG_EXECUTING_SLICE (0x40UL)
31 0 : #define EXEC_FLAG_FINISHED_SLOT (0x80UL)
32 :
33 : /* FD_NET_MTU is the max full packet size, with ethernet, IP, and UDP
34 : headers that can go in or out of the net tile. 2048 is the maximum
35 : XSK entry size, so this value follows naturally. */
36 :
37 0 : #define FD_NET_MTU (2048UL)
38 :
39 : /* FD_TPU_MTU is the max serialized byte size of a txn sent over TPU.
40 :
41 : This is minimum MTU of IPv6 packet - IPv6 header - UDP header
42 : 1280 - 40 - 8 */
43 :
44 0 : #define FD_TPU_MTU (1232UL)
45 :
46 : /* FD_GOSSIP_MTU is the max sz of a gossip packet which is the same as
47 : above. */
48 :
49 : #define FD_GOSSIP_MTU (FD_TPU_MTU)
50 :
51 : /* FD_SHRED_STORE_MTU is the size of an fd_shred34_t (statically
52 : asserted in fd_shred_tile.c). */
53 :
54 0 : #define FD_SHRED_STORE_MTU (41792UL)
55 :
56 : /* FD_SHRED_REPAIR_MTU is the maximum size of a frag on the shred_repair
57 : link. This is the size of a data shred header + merkle root. */
58 :
59 0 : #define FD_SHRED_REPAIR_MTU (FD_SHRED_DATA_HEADER_SZ + FD_SHRED_MERKLE_ROOT_SZ)
60 : FD_STATIC_ASSERT( FD_SHRED_REPAIR_MTU == 120 , update FD_SHRED_REPAIR_MTU );
61 :
62 : /* Maximum size of frags going into the writer tile. */
63 : #define FD_REPLAY_WRITER_MTU (128UL)
64 0 : #define FD_EXEC_WRITER_MTU (128UL)
65 :
66 :
67 0 : #define FD_NETMUX_SIG_MIN_HDR_SZ ( 42UL) /* The default header size, which means no vlan tags and no IP options. */
68 : #define FD_NETMUX_SIG_IGNORE_HDR_SZ (102UL) /* Outside the allowable range, but still fits in 4 bits when compressed */
69 :
70 : FD_PROTOTYPES_BEGIN
71 :
72 : /* hdr_sz is the total size of network headers, including eth, ip, udp.
73 : Ignored for outgoing packets.
74 : For incoming packets, hash_{ip_addr,port} are the source IP and port,
75 : for outgoing packets, they are the destination IP and port. */
76 : FD_FN_CONST static inline ulong
77 : fd_disco_netmux_sig( uint hash_ip_addr,
78 : ushort hash_port,
79 : uint dst_ip_addr,
80 : ulong proto,
81 0 : ulong hdr_sz ) {
82 : /* The size of an Ethernet header is 14+4k bytes, where 0<=k<=3 (?) is
83 : the number of vlan tags. The size of an IP header is 4j, where
84 : 5<=j<=15 is the size given in the header. The size of a UDP header
85 : is 8B. Thus, the total sum of these is 42+4i, where i=k+j-5,
86 : 0<=i<=13. Since bits are at a premium here, we compress the header
87 : size by just storing i. */
88 0 : ulong hdr_sz_i = ((hdr_sz - 42UL)>>2)&0xFUL;
89 0 : ulong hash = 0xfffffUL & fd_ulong_hash( (ulong)hash_ip_addr | ((ulong)hash_port<<32) );
90 0 : return (hash<<44) | ((hdr_sz_i&0xFUL)<<40UL) | ((proto&0xFFUL)<<32UL) | ((ulong)dst_ip_addr);
91 0 : }
92 :
93 0 : FD_FN_CONST static inline ulong fd_disco_netmux_sig_hash ( ulong sig ) { return (sig>>44UL); }
94 0 : FD_FN_CONST static inline ulong fd_disco_netmux_sig_proto ( ulong sig ) { return (sig>>32UL) & 0xFFUL; }
95 0 : FD_FN_CONST static inline uint fd_disco_netmux_sig_dst_ip( ulong sig ) { return (uint)(sig & 0xFFFFFFFFUL); }
96 :
97 : /* fd_disco_netmux_sig_hdr_sz extracts the total size of the Ethernet,
98 : IP, and UDP headers from the netmux signature field. The UDP payload
99 : of the packet stored in the corresponding frag begins at the returned
100 : offset. */
101 0 : FD_FN_CONST static inline ulong fd_disco_netmux_sig_hdr_sz( ulong sig ) { return 4UL*((sig>>40UL) & 0xFUL) + 42UL; }
102 :
103 : FD_FN_CONST static inline ulong
104 : fd_disco_poh_sig( ulong slot,
105 : ulong pkt_type,
106 0 : ulong bank_tile ) {
107 : /* The high 6 bits of the low byte of the signature field is the bank
108 : idx. Banks will filter to only handle frags with their own idx.
109 : The higher 7 bytes are the slot number. Technically, the slot
110 : number is a ulong, but it won't hit 256^7 for about 10^9 years at
111 : the current rate. The lowest bits of the low byte is the packet
112 : type. */
113 0 : return (slot << 8) | ((bank_tile & 0x3FUL) << 2) | (pkt_type & 0x3UL);
114 0 : }
115 :
116 0 : FD_FN_CONST static inline ulong fd_disco_poh_sig_pkt_type( ulong sig ) { return (sig & 0x3UL); }
117 0 : FD_FN_CONST static inline ulong fd_disco_poh_sig_slot( ulong sig ) { return (sig >> 8); }
118 0 : FD_FN_CONST static inline ulong fd_disco_poh_sig_bank_tile( ulong sig ) { return (sig >> 2) & 0x3FUL; }
119 :
120 : FD_FN_CONST static inline ulong
121 : fd_disco_bank_sig( ulong slot,
122 0 : ulong microblock_idx ) {
123 0 : return (slot << 32) | microblock_idx;
124 0 : }
125 :
126 0 : FD_FN_CONST static inline ulong fd_disco_bank_sig_slot( ulong sig ) { return (sig >> 32); }
127 0 : FD_FN_CONST static inline ulong fd_disco_bank_sig_microblock_idx( ulong sig ) { return sig & 0xFFFFFFFFUL; }
128 :
129 : /* TODO remove with store_int */
130 :
131 : FD_FN_CONST static inline ulong
132 : fd_disco_replay_old_sig( ulong slot,
133 0 : ulong flags ) {
134 : /* The low byte of the signature field is the flags for replay message.
135 : The higher 7 bytes are the slot number. These flags indicate the status
136 : of a microblock as it transits through the replay system. Technically,
137 : the slot number is a ulong, but it won't hit 256^7 for about 10^9 years
138 : at the current rate. The lowest bit of the low byte is the packet
139 : type. */
140 0 : return (slot << 8) | (flags & 0xFFUL);
141 0 : }
142 :
143 0 : FD_FN_CONST static inline ulong fd_disco_replay_old_sig_flags( ulong sig ) { return (sig & 0xFFUL); }
144 0 : FD_FN_CONST static inline ulong fd_disco_replay_old_sig_slot( ulong sig ) { return (sig >> 8); }
145 :
146 : /* fd_disco_shred_repair_shred_sig constructs a sig for the shred_repair link.
147 : The encoded fields vary depending on the type of the sig. The
148 : diagram below describes the encoding.
149 :
150 : completes (1) | slot (32) | fec_set_idx (15) | is_code (1) | shred_idx or data_cnt (15)
151 : [63] | [31, 62] | [16, 30] | [15] | [0, 14]
152 :
153 : There are two types of messages on the shred_repair link. The first
154 : type is a generic shred message. The second is a FEC set completion
155 : message. Since we have run out of bits, the reciever must look at the
156 : sz of the dcache entry to determine which type of message it is.
157 :
158 : For the first message type (SHRED):
159 :
160 : The first bit [63] describes whether this shred marks the end of a
161 : batch and/or a slot, i.e. shred.flags & (DATA_COMPLETE | SLOT_COMPLETE)
162 :
163 : The next 32 bits [31, 62] describe the slot number. Note: if the slot
164 : number is >= UINT_MAX, the sender will store the value UINT_MAX in
165 : this field. If the receiver sees a value of UINT_MAX in the field, it
166 : must read the actual slot number from the dcache entry.
167 :
168 : The following 15 bits [16, 30] describe the fec_set_idx. This is a
169 : 15-bit value because shreds are bounded to 2^15 per slot, so in the
170 : worst case there is an independent FEC set for every shred, which
171 : results in at most 2^15 FEC sets per slot.
172 :
173 : The next bit [15] describes whether it is a coding shred (is_code).
174 : If is_code = 0, the sig describes a data shred, and the last 15 bits
175 : [0, 14] encode the shred_idx. If is_code = 1, the sig describes a
176 : coding shred, and the last 15 bits encode the data_cnt.
177 :
178 : For the second message type (FEC):
179 :
180 : Only the slot and fec_set_idx bits are populated. The data in the
181 : frag is the full shred header of the last data shred in the FEC set,
182 : the merkle root of the FEC set, and the chained merkle root of the
183 : FEC. Each field immediately follows the other field. */
184 :
185 : /* TODO this shred_repair_sig can be greatly simplified when FEC sets
186 : are uniformly coding shreds and fixed size. */
187 :
188 : FD_FN_CONST static inline ulong
189 : fd_disco_shred_repair_shred_sig( int completes,
190 : ulong slot,
191 : uint fec_set_idx,
192 : int is_code,
193 0 : uint shred_idx_or_data_cnt ) {
194 0 : ulong slot_ul = fd_ulong_min( slot, (ulong)UINT_MAX );
195 0 : ulong shred_idx_or_data_cnt_ul = fd_ulong_min( (ulong)shred_idx_or_data_cnt, (ulong)FD_SHRED_BLK_MAX );
196 0 : ulong fec_set_idx_ul = fd_ulong_min( (ulong)fec_set_idx, (ulong)FD_SHRED_BLK_MAX );
197 0 : ulong completes_ul = !!completes;
198 0 : ulong is_code_ul = !!is_code;
199 :
200 0 : return completes_ul << 63 | slot_ul << 31 | fec_set_idx_ul << 16 | is_code_ul << 15 | shred_idx_or_data_cnt_ul;
201 0 : }
202 :
203 : /* fd_disco_shred_repair_shred_sig_{...} are accessors for the fields encoded
204 : in the sig described above. */
205 :
206 0 : FD_FN_CONST static inline int fd_disco_shred_repair_shred_sig_completes ( ulong sig ) { return fd_ulong_extract_bit( sig, 63 ); }
207 0 : FD_FN_CONST static inline ulong fd_disco_shred_repair_shred_sig_slot ( ulong sig ) { return fd_ulong_extract ( sig, 31, 62 ); }
208 0 : FD_FN_CONST static inline uint fd_disco_shred_repair_shred_sig_fec_set_idx( ulong sig ) { return (uint)fd_ulong_extract ( sig, 16, 30 ); }
209 0 : FD_FN_CONST static inline int fd_disco_shred_repair_shred_sig_is_code ( ulong sig ) { return fd_ulong_extract_bit( sig, 15 ); }
210 0 : FD_FN_CONST static inline uint fd_disco_shred_repair_shred_sig_shred_idx ( ulong sig ) { return (uint)fd_ulong_extract_lsb( sig, 15 ); } /* only when is_code = 0 */
211 0 : FD_FN_CONST static inline uint fd_disco_shred_repair_shred_sig_data_cnt ( ulong sig ) { return (uint)fd_ulong_extract_lsb( sig, 15 ); } /* only when is_code = 1 */
212 :
213 : /*
214 : | slot (32) | fec_set_idx (15) | data_cnt (15) | is_data_complete (1) | is_batch_complete (1) |
215 : | [32, 63] | [17, 31] | [2, 16] | [1] | [0] |
216 :
217 : */
218 : FD_FN_CONST static inline ulong
219 0 : fd_disco_shred_repair_fec_sig( ulong slot, uint fec_set_idx, uint data_cnt, int is_slot_complete, int is_batch_complete ) {
220 0 : ulong slot_ul = fd_ulong_min( slot, (ulong)UINT_MAX );
221 0 : ulong fec_set_idx_ul = fd_ulong_min( (ulong)fec_set_idx, (ulong)FD_SHRED_BLK_MAX );
222 0 : ulong data_cnt_ul = fd_ulong_min( (ulong)data_cnt, (ulong)FD_SHRED_BLK_MAX );
223 0 : ulong is_slot_complete_ul = !!is_slot_complete;
224 0 : ulong is_batch_complete_ul = !!is_batch_complete;
225 0 : return slot_ul << 32 | fec_set_idx_ul << 17 | data_cnt_ul << 2 | is_slot_complete_ul << 1 | is_batch_complete_ul;
226 0 : }
227 :
228 0 : FD_FN_CONST static inline ulong fd_disco_shred_repair_fec_sig_slot ( ulong sig ) { return fd_ulong_extract ( sig, 32, 63 ); }
229 0 : FD_FN_CONST static inline uint fd_disco_shred_repair_fec_sig_fec_set_idx ( ulong sig ) { return (uint) fd_ulong_extract ( sig, 17, 31 ); }
230 0 : FD_FN_CONST static inline uint fd_disco_shred_repair_fec_sig_data_cnt ( ulong sig ) { return (uint) fd_ulong_extract ( sig, 2, 16 ); }
231 0 : FD_FN_CONST static inline int fd_disco_shred_repair_fec_sig_is_slot_complete ( ulong sig ) { return fd_ulong_extract_bit( sig, 1 ); }
232 0 : FD_FN_CONST static inline int fd_disco_shred_repair_fec_sig_is_batch_complete( ulong sig ) { return fd_ulong_extract_bit( sig, 0 ); }
233 :
234 : /* Exclusively used for force completion messages */
235 :
236 : FD_FN_CONST static inline ulong
237 0 : fd_disco_repair_shred_sig( uint last_shred_idx ){
238 0 : return (ulong) last_shred_idx;
239 0 : }
240 :
241 0 : FD_FN_CONST static inline uint fd_disco_repair_shred_sig_last_shred_idx( ulong sig ) { return (uint) sig; }
242 :
243 :
244 : FD_FN_CONST static inline ulong
245 0 : fd_disco_repair_replay_sig( ulong slot, ushort parent_off, uint data_cnt, int slot_complete ) {
246 : /*
247 : | slot (32) | parent_off (16) | data_cnt (15) | slot_complete(1)
248 : | [32, 63] | [16, 31] | [1, 15] | [0]
249 : */
250 0 : ulong slot_ul = fd_ulong_min( slot, (ulong)UINT_MAX );
251 0 : ulong parent_off_ul = (ulong)parent_off;
252 0 : ulong data_cnt_ul = fd_ulong_min( (ulong)data_cnt, (ulong)FD_SHRED_BLK_MAX );
253 0 : ulong slot_complete_ul = !!slot_complete;
254 0 : return slot_ul << 32 | parent_off_ul << 16 | data_cnt_ul << 1 | slot_complete_ul;
255 0 : }
256 :
257 0 : FD_FN_CONST static inline ulong fd_disco_repair_replay_sig_slot ( ulong sig ) { return fd_ulong_extract ( sig, 32, 63 ); }
258 0 : FD_FN_CONST static inline ushort fd_disco_repair_replay_sig_parent_off ( ulong sig ) { return (ushort)fd_ulong_extract ( sig, 16, 31 ); }
259 0 : FD_FN_CONST static inline uint fd_disco_repair_replay_sig_data_cnt ( ulong sig ) { return (uint) fd_ulong_extract ( sig, 1, 15 ); }
260 0 : FD_FN_CONST static inline int fd_disco_repair_replay_sig_slot_complete( ulong sig ) { return fd_ulong_extract_bit( sig, 0 ); }
261 :
262 0 : #define FD_DISCO_REPAIR_REPLAY_MTU (sizeof(ulong) + sizeof(ushort) + sizeof(uint) + sizeof(int))
263 :
264 : FD_FN_PURE static inline ulong
265 0 : fd_disco_compact_chunk0( void * wksp ) {
266 0 : return (((struct fd_wksp_private *)wksp)->gaddr_lo) >> FD_CHUNK_LG_SZ;
267 0 : }
268 :
269 : FD_FN_PURE static inline ulong
270 0 : fd_disco_compact_wmark( void * wksp, ulong mtu ) {
271 0 : ulong chunk_mtu = ((mtu + 2UL*FD_CHUNK_SZ-1UL) >> (1+FD_CHUNK_LG_SZ)) << 1;
272 0 : ulong wksp_hi = ((struct fd_wksp_private *)wksp)->gaddr_hi;
273 0 : return (wksp_hi >> FD_CHUNK_LG_SZ) - chunk_mtu;
274 0 : }
275 :
276 : FD_PROTOTYPES_END
277 :
278 : #endif /* HEADER_fd_src_disco_fd_disco_base_h */
|