LCOV - code coverage report
Current view: top level - waltz/ip - fd_fib4_private.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 36 36 100.0 %
Date: 2025-12-06 04:45:29 Functions: 13 26 50.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_waltz_ip_fd_fib4_private_h
       2             : #define HEADER_fd_src_waltz_ip_fd_fib4_private_h
       3             : 
       4             : #include "fd_fib4.h"
       5             : #include "../../util/fd_util.h"
       6             : 
       7             : #if FD_HAS_X86
       8             : #include <immintrin.h>
       9             : #endif
      10             : 
      11             : struct __attribute__((aligned(16))) fd_fib4_key {
      12             :   /* FIXME optimize this to 8 bytes? */
      13             :   uint addr;       /* prefix bits, little endian (low bits outside of mask are undefined) */
      14             :   uint mask;       /* bit pattern */
      15             :   uint prio;       /* lower is higher */
      16             :   int  mask_bits;  /* precompute mask bits for comparison */
      17             : };
      18             : 
      19             : typedef struct fd_fib4_key fd_fib4_key_t;
      20             : 
      21             : /* Hashmap private APIs */
      22             : union __attribute__((aligned(16))) fd_fib4_hmap_entry {
      23             :   struct {
      24             :     uint dst_addr; /* Little endian. All 32-bits defined */
      25             :     uint hash;
      26             :     fd_fib4_hop_t next_hop; /* 16 bytes */
      27             :   };
      28             : #if FD_HAS_INT128
      29             :   uint128 uf[2];
      30             : #endif
      31             : #if FD_HAS_X86
      32             :   __m128i xmm[2];
      33             : #endif
      34             : #if FD_HAS_AVX
      35             :   __m256i avx[1];
      36             : #endif
      37             : };
      38             : 
      39             : typedef union fd_fib4_hmap_entry fd_fib4_hmap_entry_t;
      40             : 
      41             : /* fd_fib4_hmap_entry_st stores from src into dst. Assumes no other writers,
      42             :    and that src is non-volatile. Best effort for atomicity, but only guaranteed
      43             :    when FD_HAS_AVX. */
      44             : static inline void
      45             : fd_fib4_hmap_entry_st( fd_fib4_hmap_entry_t       * dst,
      46         240 :                        fd_fib4_hmap_entry_t const * src ) {
      47         240 : # if FD_HAS_AVX
      48         240 :   FD_VOLATILE( dst->avx[0] ) = src->avx[0];
      49             : # elif FD_HAS_X86
      50             :   FD_VOLATILE( dst->xmm[0] ) = src->xmm[0];
      51             :   FD_VOLATILE( dst->xmm[1] ) = src->xmm[1];
      52             : # elif FD_HAS_INT128
      53             :   FD_VOLATILE( dst->uf[0] )  = src->uf[0];
      54             :   FD_VOLATILE( dst->uf[1] )  = src->uf[1];
      55             : # else
      56             :   FD_VOLATILE( dst->dst_addr ) = src->dst_addr;
      57             :   FD_VOLATILE( dst->hash     ) = src->hash;
      58             :   FD_VOLATILE( dst->next_hop ) = src->next_hop;
      59             : #endif
      60         240 : }
      61             : 
      62             : /* fd_fib4_hmap_entry_ld loads from src into dst.
      63             :    Best effort for atomicity, but only guaranteed when FD_HAS_AVX.
      64             :    Assumes that dst is non-volatile. */
      65             : static inline void
      66             : fd_fib4_hmap_entry_ld( fd_fib4_hmap_entry_t       * dst,
      67         237 :                        fd_fib4_hmap_entry_t const * src ) {
      68             : 
      69         237 : # if FD_HAS_AVX
      70         237 :   dst->avx[0] = FD_VOLATILE_CONST( src->avx[0] );
      71             : # elif FD_HAS_X86
      72             :   dst->xmm[0] = FD_VOLATILE_CONST( src->xmm[0] );
      73             :   dst->xmm[1] = FD_VOLATILE_CONST( src->xmm[1] );
      74             : # elif FD_HAS_INT128
      75             :   dst->uf[0] = FD_VOLATILE_CONST( src->uf[0] );
      76             :   dst->uf[1] = FD_VOLATILE_CONST( src->uf[1] );
      77             : # else
      78             :   dst->dst_addr = FD_VOLATILE_CONST( src->dst_addr );
      79             :   dst->hash     = FD_VOLATILE_CONST( src->hash );
      80             :   dst->next_hop = FD_VOLATILE_CONST( src->next_hop );
      81             : #endif
      82         237 : }
      83             : 
      84             : static inline uint
      85         870 : fd_fib4_hmap_entry_hash( uint dst_addr, ulong seed ) {
      86         870 :   return fd_uint_hash( dst_addr ^ ((uint)seed) );
      87         870 : }
      88             : 
      89             : #define MAP_NAME            fd_fib4_hmap
      90        1095 : #define MAP_ELE_T           fd_fib4_hmap_entry_t
      91             : #define MAP_KEY_T           uint
      92        4389 : #define MAP_KEY             dst_addr
      93         630 : #define MAP_KEY_HASH(k,s)   fd_fib4_hmap_entry_hash( (*(k)), (s) )
      94             : #define MAP_ELE_MOVE(c,d,s) do { fd_fib4_hmap_entry_t * _src = (s); fd_fib4_hmap_entry_st( (d), _src ); _src->dst_addr = 0; } while(0)
      95             : 
      96             : #include "../../util/tmpl/fd_map_slot.c"
      97             : 
      98             : FD_STATIC_ASSERT( sizeof( fd_fib4_hmap_t)<=sizeof(( (fd_fib4_t){0}).hmap_join), "hmap_join is too small" );
      99             : 
     100             : /* fd_fib4_hmap_query_hop queries the /32 routing table for the next hop
     101             :    for the given destination address. Attempts (but does not guarantee) atomicity.
     102             :    If the destination address is not found, returns a route with rtype
     103             :    set to UNSPEC. The result is not guaranteed to be valid - the caller
     104             :    is responsible for validating the result. */
     105             : 
     106             : static inline fd_fib4_hop_t
     107             : fd_fib4_hmap_query_hop( fd_fib4_hmap_t const * map,
     108         390 :                         uint                   dst_addr ) {
     109         390 :   fd_fib4_hmap_entry_t const * entry = fd_fib4_hmap_query( map, &dst_addr );
     110         390 :   if( !entry ) return (fd_fib4_hop_t){0};
     111             : 
     112         213 :   fd_fib4_hmap_entry_t hmap_entry;
     113         213 :   fd_fib4_hmap_entry_ld( &hmap_entry, entry );
     114             : 
     115         213 :   return hmap_entry.next_hop;
     116         390 : }
     117             : 
     118             : struct __attribute__((aligned(FD_FIB4_ALIGN))) fd_fib4_priv {
     119             :   ulong hmap_offset;
     120             :   ulong hmap_cnt;
     121             :   ulong hmap_max;
     122             :   ulong generation;
     123             :   ulong cnt;
     124             :   ulong max;
     125             :   ulong hop_off;
     126             :   ulong seed;
     127             :   /* fd_fib4_key_t[] follows */
     128             :   /* fd_fib4_hop_t[] follows */
     129             :   /* hmap_mem        follows */
     130             : };
     131             : typedef struct fd_fib4_priv fd_fib4_priv_t;
     132             : 
     133             : FD_FN_CONST static inline ulong
     134         381 : fd_fib4_key_tbl_laddr( fd_fib4_priv_t const * fib ) {
     135         381 :   return (ulong)fib + sizeof(fd_fib4_priv_t);
     136         381 : }
     137             : 
     138             : FD_FN_PURE static inline ulong
     139         381 : fd_fib4_hop_tbl_laddr( fd_fib4_priv_t const * fib ) {
     140         381 :   return (ulong)fib + fib->hop_off;
     141         381 : }
     142             : 
     143         237 : FD_FN_CONST static inline fd_fib4_key_t const * fd_fib4_key_tbl_const( fd_fib4_priv_t const * fib ) { return (fd_fib4_key_t const *)fd_fib4_key_tbl_laddr( fib ); }
     144         144 : FD_FN_CONST static inline fd_fib4_key_t *       fd_fib4_key_tbl      ( fd_fib4_priv_t *       fib ) { return (fd_fib4_key_t *)      fd_fib4_key_tbl_laddr( fib ); }
     145         237 : FD_FN_CONST static inline fd_fib4_hop_t const * fd_fib4_hop_tbl_const( fd_fib4_priv_t const * fib ) { return (fd_fib4_hop_t const *)fd_fib4_hop_tbl_laddr( fib ); }
     146         144 : FD_FN_CONST static inline fd_fib4_hop_t *       fd_fib4_hop_tbl      ( fd_fib4_priv_t *       fib ) { return (fd_fib4_hop_t *)      fd_fib4_hop_tbl_laddr( fib ); }
     147             : 
     148          63 : static inline void *  fd_fib4_hmap_mem( fd_fib4_priv_t * priv ) {
     149          63 :   return (void *)( (ulong)priv + priv->hmap_offset);
     150          63 : }
     151             : 
     152             : /* Get the hashmap's total capacity (50% extra capacity beyond the requested size to optimize performance) */
     153         117 : static inline ulong   fd_fib4_hmap_get_ele_max   ( ulong max_cnt  ) { return fd_ulong_pow2_up( max_cnt + ( max_cnt>>1 ) ); }
     154             : /* Get the hashmap's probe limit (75% of total capacity). Higher than requested size to avoid probe failure */
     155          63 : static inline ulong   fd_fib4_hmap_get_probe_max ( ulong elem_max ) { return elem_max - ( elem_max>>2 );                   }
     156             : 
     157             : #endif /* HEADER_fd_src_waltz_ip_fd_fib4_private_h */

Generated by: LCOV version 1.14