LCOV - code coverage report
Current view: top level - waltz/neigh - fd_neigh4_map.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 17 26 65.4 %
Date: 2025-12-16 05:08:26 Functions: 3 44 6.8 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_waltz_neigh_fd_neigh4_map_h
       2             : #define HEADER_fd_src_waltz_neigh_fd_neigh4_map_h
       3             : 
       4             : /* fd_neigh4.h provides APIs for IPv4 neighbor discovery using ARP. */
       5             : 
       6             : #include "../../util/log/fd_log.h" /* fd_log_wallclock */
       7             : #include "../../util/tmpl/fd_map.h"
       8             : 
       9             : #if FD_HAS_X86
      10             : #include <immintrin.h>
      11             : #endif
      12             : 
      13             : union __attribute__((aligned(16))) fd_neigh4_entry {
      14             :   struct {
      15             :     uint  ip4_addr;
      16             :     uchar mac_addr[6]; /* MAC address */
      17             :     uchar state;
      18             :     ulong probe_suppress_until : 40; /* Holds deadline>>24, so minimum delay
      19             :                                         is ~16.7M ticks (2**24) */
      20           0 :     #define FD_NEIGH4_PROBE_SUPPRESS_SHIFT ( sizeof(ulong)*8 - 40 )
      21           9 :     #define FD_NEIGH4_PROBE_SUPPRESS_MASK ( (1UL<<40) - 1 )
      22             : 
      23             :     #define FD_NEIGH4_PROBE_SUPPRESS_UNTIL_SET(entry, deadline) \
      24           0 :       ulong udead = ((ulong)(deadline))>>FD_NEIGH4_PROBE_SUPPRESS_SHIFT; \
      25           0 :       udead >>= FD_NEIGH4_PROBE_SUPPRESS_SHIFT; \
      26           0 :       (entry)->probe_suppress_until = udead & FD_NEIGH4_PROBE_SUPPRESS_MASK;
      27             :     #define FD_NEIGH4_PROBE_SUPPRESS_UNTIL_GET(entry) \
      28           0 :       (long)(((entry)->probe_suppress_until)<<FD_NEIGH4_PROBE_SUPPRESS_SHIFT)
      29             :   };
      30             : #if FD_HAS_INT128
      31             :   uint128 uf[1];
      32             : #endif
      33             : #if FD_HAS_X86
      34             :   __m128i xmm[1];
      35             : #endif
      36             : };
      37             : 
      38             : typedef union fd_neigh4_entry fd_neigh4_entry_t;
      39             : 
      40             : FD_STATIC_ASSERT( sizeof(fd_neigh4_entry_t) == 16, "fd_neigh4_entry_t must be 16 bytes" );
      41             : 
      42             : /* fd_neigh4_entry_atomic_st atomically stores from src into dst.
      43             :    Assumes no other writers, and that src is non-volatile. */
      44             : static inline void
      45             : fd_neigh4_entry_atomic_st( fd_neigh4_entry_t       * dst,
      46           9 :                            fd_neigh4_entry_t const * src ) {
      47           9 : # if FD_HAS_X86
      48           9 :   FD_VOLATILE( dst->xmm[0] ) = src->xmm[0];
      49             : # elif FD_HAS_INT128
      50             :   FD_VOLATILE( dst->uf[0] )  = src->uf[0];
      51             : # else
      52             :   memcpy( dst->mac_addr, src->mac_addr, 6 );
      53             :   dst->probe_suppress_until     = src->probe_suppress_until;
      54             :   FD_VOLATILE( dst->ip4_addr )  = src->ip4_addr;
      55             :   FD_VOLATILE( dst->state )     = src->state;
      56             : # endif
      57           9 : }
      58             : 
      59             : /* fd_neigh4_entry_atomic_ld atomically loads from src into dst.
      60             :    Assumes no other writers, and that dst is non-volatile. */
      61             : static inline void
      62             : fd_neigh4_entry_atomic_ld( fd_neigh4_entry_t       * dst,
      63          18 :                            fd_neigh4_entry_t const * src ) {
      64          18 : # if FD_HAS_X86
      65          18 :   dst->xmm[0] = FD_VOLATILE_CONST( src->xmm[0] );
      66             : # elif FD_HAS_INT128
      67             :   dst->uf[0] = FD_VOLATILE_CONST( src->uf[0] );
      68             : # else
      69             :   memcpy( dst->mac_addr, src->mac_addr, 6 );
      70             :   dst->probe_suppress_until = src->probe_suppress_until;
      71             :   dst->ip4_addr             = FD_VOLATILE_CONST( src->ip4_addr );
      72             :   dst->state                = FD_VOLATILE_CONST( src->state );
      73             : # endif
      74          18 : }
      75             : 
      76             : 
      77           0 : #define FD_NEIGH4_STATE_INCOMPLETE (0)
      78           9 : #define FD_NEIGH4_STATE_ACTIVE     (1)
      79             : 
      80             : #include "fd_neigh4_map_defines.h"
      81             : #include "../../util/tmpl/fd_map_slot.c"
      82             : 
      83             : /* fd_neigh4_hmap_query_entry queries a neighbor table entry by IP address.
      84             :    Returns FD_MAP_SUCCESS if out was successfully populated, and returns
      85             :    FD_MAP_ERR_KEY otherwise.
      86             :    out is a pointer to the entry to be filled in. Must have 16 byte alignment.
      87             :    map is a join to the neighbor table, and ip4_addr is the IP address to query.
      88             :    Reasons for failure include:
      89             :    - The entry was not found
      90             :    - Entry changed between query and copying out (out will be clobbered)
      91             :    */
      92             : static inline int
      93             : fd_neigh4_hmap_query_entry( fd_neigh4_hmap_t   *  map,
      94             :                             uint                  ip4_addr,
      95          18 :                             fd_neigh4_entry_t  *  out ) {
      96          18 :   fd_neigh4_entry_t const * e = fd_neigh4_hmap_query( map, &ip4_addr );
      97          18 :   if( FD_UNLIKELY( !e ) ) return FD_MAP_ERR_KEY;
      98          18 :   fd_neigh4_entry_atomic_ld( out, e );
      99             :   /* Confirm key we read matches what we expect */
     100          18 :   if( FD_UNLIKELY( out->ip4_addr!=ip4_addr ) ) return FD_MAP_ERR_KEY;
     101          18 :   return FD_MAP_SUCCESS;
     102          18 : }
     103             : 
     104             : /* fd_neigh4_hmap_est_slot_cnt computes the number of slots
     105             :    needed to store 'ele_max' entries. Uses a sparsity factor of 3.
     106             :    Assumes ele_max>0. */
     107             : static inline ulong
     108           0 : fd_neigh4_hmap_est_slot_cnt( ulong ele_max ) {
     109           0 :   return fd_ulong_pow2_up( 3 * ele_max );
     110           0 : }
     111             : 
     112             : FD_PROTOTYPES_BEGIN
     113             : 
     114             : #if FD_HAS_HOSTED
     115             : 
     116             : /* fd_neigh4_hmap_fprintf prints the routing table to the given FILE *
     117             :    pointer (or target equivalent).  Order of routes is undefined but
     118             :    guaranteed to be stable between calls.  Outputs ASCII encoding with LF
     119             :    newlines.  Returns errno on failure and 0 on success.  Only works on
     120             :    ACTIVE tables. */
     121             : 
     122             : int
     123             : fd_neigh4_hmap_fprintf( fd_neigh4_hmap_t const * map,
     124             :                         void *                   file );
     125             : 
     126             : #endif /* FD_HAS_HOSTED */
     127             : 
     128             : FD_PROTOTYPES_END
     129             : 
     130             : #endif /* HEADER_fd_src_waltz_neigh_fd_neigh4_map_h */

Generated by: LCOV version 1.14