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_fec_set (statically
41 : asserted in fd_shred_tile.c). */
42 :
43 0 : #define FD_SHRED_STORE_MTU (78656UL)
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 + nonce/is_leader. */
48 :
49 0 : #define FD_SHRED_OUT_MTU (FD_SHRED_CODE_HEADER_SZ + 2*FD_SHRED_MERKLE_ROOT_SZ + sizeof(int))
50 : FD_STATIC_ASSERT( FD_SHRED_OUT_MTU == 157UL , 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 18 : #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 : for sz==FD_SHRED_OUT_MTU
131 :
132 : msg_type (1) | slot (32) | fec_set_idx (15) | is_turbine (1) | shred_idx (15) |
133 : MSG_TYPE_SHRED | [31, 62] | [16, 30] | [15] | [0, 14] |
134 :
135 : in the above case, the last 4 bytes of the dcache entry are the nonce.
136 :
137 : msg_type (1) | slot (32) | fec_set_idx (15)| is_slot_complete (1) | data_cnt (15) |
138 : MSG_TYPE_FEC | [31, 62] | [16, 30] | [15] | [0, 14] | => should soon always be 32
139 :
140 : in the above case, the last 4 bytes of the dcache entry are the is_leader flag..
141 :
142 : for sz==0:
143 : these are FEC_CLEAR messages and look like MSG_TYPE_SHRED but with some unpopulated fields:
144 : ... | slot (32) | fec_set_idx (15) | ... | max_shred_idx (15) |
145 : ... | [31, 62] | [16, 30] | ... | [0, 14] |
146 :
147 : is_turbine describes whether this shred source was turbine or repair.
148 : If the source is repair, then the nonce value in the dcache will
149 : have meaning.
150 :
151 : Note: if the slot number is >= UINT_MAX, the sender will store the
152 : value UINT_MAX in this field. If the receiver sees a value of
153 : UINT_MAX in the field, it must read the actual slot number from the
154 : dcache entry.
155 :
156 : The following 15 bits describe the fec_set_idx. This is a
157 : 15-bit value because shreds are bounded to 2^15 per slot, so in the
158 : worst case there is an independent FEC set for every shred, which
159 : results in at most 2^15 FEC sets per slot. */
160 :
161 0 : #define FD_SHRED_OUT_MSG_TYPE_SHRED (0)
162 0 : #define FD_SHRED_OUT_MSG_TYPE_FEC (1)
163 :
164 0 : FD_FN_CONST static inline int fd_disco_shred_out_msg_type( ulong sig ) { return fd_ulong_extract_bit( sig, 63 ); }
165 :
166 : FD_FN_CONST static inline ulong
167 : fd_disco_shred_out_shred_sig( int is_turbine,
168 : ulong slot,
169 : uint fec_set_idx,
170 0 : uint shred_idx ) {
171 0 : ulong slot_ul = fd_ulong_min( slot, (ulong)UINT_MAX );
172 0 : ulong shred_idx_ul = fd_ulong_min( (ulong)shred_idx, (ulong)FD_SHRED_BLK_MAX );
173 0 : ulong fec_set_idx_ul = fd_ulong_min( (ulong)fec_set_idx, (ulong)FD_SHRED_BLK_MAX );
174 0 : ulong is_turbine_ul = !!is_turbine;
175 0 : ulong msg_type_ul = FD_SHRED_OUT_MSG_TYPE_SHRED;
176 :
177 0 : return msg_type_ul << 63 | slot_ul << 31 | fec_set_idx_ul << 16 | is_turbine_ul << 15 | shred_idx_ul;
178 0 : }
179 :
180 : /* fd_disco_shred_out_shred_sig_{...} are accessors for the fields encoded
181 : in the sig described above. */
182 :
183 0 : FD_FN_CONST static inline ulong fd_disco_shred_out_shred_sig_slot ( ulong sig ) { return fd_ulong_extract ( sig, 31, 62 ); }
184 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 ); }
185 0 : FD_FN_CONST static inline int fd_disco_shred_out_shred_sig_is_turbine ( ulong sig ) { return fd_ulong_extract_bit( sig, 15 ); }
186 0 : FD_FN_CONST static inline uint fd_disco_shred_out_shred_sig_shred_idx ( ulong sig ) { return (uint)fd_ulong_extract ( sig, 0, 14 ); }
187 :
188 : FD_FN_CONST static inline ulong
189 0 : fd_disco_shred_out_fec_sig( ulong slot, uint fec_set_idx, uint data_cnt, int is_slot_complete ) {
190 0 : ulong slot_ul = fd_ulong_min( slot, (ulong)UINT_MAX );
191 0 : ulong fec_set_idx_ul = fd_ulong_min( (ulong)fec_set_idx, (ulong)FD_SHRED_BLK_MAX );
192 0 : ulong data_cnt_ul = fd_ulong_min( (ulong)data_cnt, (ulong)FD_SHRED_BLK_MAX );
193 0 : ulong is_slot_complete_ul = !!is_slot_complete;
194 0 : ulong msg_type_ul = FD_SHRED_OUT_MSG_TYPE_FEC;
195 0 : return msg_type_ul << 63 | slot_ul << 31 | fec_set_idx_ul << 16 | is_slot_complete_ul << 15 | data_cnt_ul;
196 0 : }
197 :
198 0 : FD_FN_CONST static inline ulong fd_disco_shred_out_fec_sig_slot ( ulong sig ) { return fd_ulong_extract ( sig, 31, 62 ); }
199 0 : FD_FN_CONST static inline uint fd_disco_shred_out_fec_sig_fec_set_idx ( ulong sig ) { return (uint) fd_ulong_extract ( sig, 16, 30 ); }
200 0 : FD_FN_CONST static inline int fd_disco_shred_out_fec_sig_is_slot_complete( ulong sig ) { return fd_ulong_extract_bit( sig, 15 ); }
201 0 : FD_FN_CONST static inline uint fd_disco_shred_out_fec_sig_data_cnt ( ulong sig ) { return (uint) fd_ulong_extract ( sig, 0, 14 ); }
202 :
203 : /* Exclusively used for force completion messages */
204 :
205 : FD_FN_CONST static inline ulong
206 0 : fd_disco_repair_shred_sig( uint last_shred_idx ){
207 0 : return (ulong) last_shred_idx;
208 0 : }
209 :
210 0 : FD_FN_CONST static inline uint fd_disco_repair_shred_sig_last_shred_idx( ulong sig ) { return (uint) sig; }
211 :
212 :
213 : FD_FN_CONST static inline ulong
214 0 : fd_disco_repair_replay_sig( ulong slot, ushort parent_off, uint data_cnt, int slot_complete ) {
215 0 : /*
216 0 : | slot (32) | parent_off (16) | data_cnt (15) | slot_complete(1)
217 0 : | [32, 63] | [16, 31] | [1, 15] | [0]
218 0 : */
219 0 : ulong slot_ul = fd_ulong_min( slot, (ulong)UINT_MAX );
220 0 : ulong parent_off_ul = (ulong)parent_off;
221 0 : ulong data_cnt_ul = fd_ulong_min( (ulong)data_cnt, (ulong)FD_SHRED_BLK_MAX );
222 0 : ulong slot_complete_ul = !!slot_complete;
223 0 : return slot_ul << 32 | parent_off_ul << 16 | data_cnt_ul << 1 | slot_complete_ul;
224 0 : }
225 :
226 : FD_FN_PURE static inline ulong
227 0 : fd_disco_compact_chunk0( void * wksp ) {
228 0 : return (((struct fd_wksp_private *)wksp)->gaddr_lo) >> FD_CHUNK_LG_SZ;
229 0 : }
230 :
231 : FD_FN_PURE static inline ulong
232 0 : fd_disco_compact_wmark( void * wksp, ulong mtu ) {
233 0 : ulong chunk_mtu = ((mtu + 2UL*FD_CHUNK_SZ-1UL) >> (1+FD_CHUNK_LG_SZ)) << 1;
234 0 : ulong wksp_hi = ((struct fd_wksp_private *)wksp)->gaddr_hi;
235 0 : return (wksp_hi >> FD_CHUNK_LG_SZ) - chunk_mtu;
236 0 : }
237 :
238 : FD_PROTOTYPES_END
239 :
240 : #endif /* HEADER_fd_src_disco_fd_disco_base_h */
|