LCOV - code coverage report
Current view: top level - disco - fd_disco_base.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 43 111 38.7 %
Date: 2025-09-19 04:41:14 Functions: 20 9040 0.2 %

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

Generated by: LCOV version 1.14