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