LCOV - code coverage report
Current view: top level - waltz/neigh - fd_neigh4_map.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 17 25 68.0 %
Date: 2026-06-07 08:10:31 Functions: 3 36 8.3 %

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

Generated by: LCOV version 1.14