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 */