Line data Source code
1 : #include "fd_netdev_tbl.h"
2 : #include "../../util/fd_util.h"
3 :
4 : struct fd_netdev_tbl_private {
5 : ulong magic;
6 : ulong dev_off;
7 : ulong bond_off;
8 : fd_netdev_tbl_hdr_t hdr;
9 : };
10 :
11 : FD_FN_CONST ulong
12 0 : fd_netdev_tbl_align( void ) {
13 0 : return FD_NETDEV_TBL_ALIGN;
14 0 : }
15 :
16 : FD_FN_CONST ulong
17 : fd_netdev_tbl_footprint( ulong dev_max,
18 0 : ulong bond_max ) {
19 0 : if( FD_UNLIKELY( dev_max ==0UL || dev_max >USHORT_MAX ) ) return 0UL;
20 0 : if( FD_UNLIKELY( bond_max==0UL || bond_max>USHORT_MAX ) ) return 0UL;
21 0 : return FD_LAYOUT_FINI( FD_LAYOUT_APPEND( FD_LAYOUT_APPEND( FD_LAYOUT_APPEND( FD_LAYOUT_INIT, \
22 0 : alignof(fd_netdev_tbl_t), sizeof(fd_netdev_tbl_t) ), \
23 0 : alignof(fd_netdev_t), sizeof(fd_netdev_t) * dev_max ), \
24 0 : alignof(fd_netdev_bond_t), sizeof(fd_netdev_bond_t) * bond_max ), \
25 0 : FD_NETDEV_TBL_ALIGN );
26 0 : }
27 :
28 : void *
29 : fd_netdev_tbl_new( void * shmem,
30 : ulong dev_max,
31 0 : ulong bond_max ) {
32 :
33 0 : if( FD_UNLIKELY( !shmem ) ) {
34 0 : FD_LOG_WARNING(( "NULL shmem" ));
35 0 : return NULL;
36 0 : }
37 :
38 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, FD_NETDEV_TBL_ALIGN ) ) ) {
39 0 : FD_LOG_WARNING(( "misaligned shmem" ));
40 0 : return NULL;
41 0 : }
42 :
43 0 : if( FD_UNLIKELY( !dev_max || dev_max>USHORT_MAX ) ) {
44 0 : FD_LOG_WARNING(( "invalid dev_max" ));
45 0 : return NULL;
46 0 : }
47 :
48 0 : if( FD_UNLIKELY( !bond_max || bond_max>USHORT_MAX ) ) {
49 0 : FD_LOG_WARNING(( "invalid bond_max" ));
50 0 : return NULL;
51 0 : }
52 :
53 0 : FD_SCRATCH_ALLOC_INIT( l, shmem );
54 0 : fd_netdev_tbl_t * tbl = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_netdev_tbl_t), sizeof(fd_netdev_tbl_t) );
55 0 : fd_netdev_t * dev = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_netdev_t), sizeof(fd_netdev_t) * dev_max );
56 0 : fd_netdev_bond_t * bond = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_netdev_bond_t), sizeof(fd_netdev_bond_t) * bond_max );
57 0 : FD_SCRATCH_ALLOC_FINI( l, FD_NETDEV_TBL_ALIGN );
58 :
59 0 : *tbl = (fd_netdev_tbl_t) {
60 0 : .magic = FD_NETDEV_TBL_MAGIC,
61 0 : .dev_off = (ulong)dev - (ulong)tbl,
62 0 : .bond_off = (ulong)bond - (ulong)tbl,
63 0 : .hdr = {
64 0 : .dev_max = (ushort)dev_max,
65 0 : .bond_max = (ushort)bond_max,
66 0 : .dev_cnt = 0,
67 0 : .bond_cnt = 0,
68 0 : }
69 0 : };
70 :
71 0 : fd_netdev_tbl_join_t join[1];
72 0 : fd_netdev_tbl_join( join, shmem );
73 0 : fd_netdev_tbl_reset( join );
74 0 : fd_netdev_tbl_leave( join );
75 :
76 0 : return tbl;
77 0 : }
78 :
79 : fd_netdev_tbl_join_t *
80 : fd_netdev_tbl_join( void * ljoin,
81 0 : void * shtbl ) {
82 :
83 0 : if( FD_UNLIKELY( !shtbl ) ) {
84 0 : FD_LOG_WARNING(( "NULL shtbl" ));
85 0 : return NULL;
86 0 : }
87 :
88 0 : fd_netdev_tbl_join_t * join = ljoin;
89 0 : fd_netdev_tbl_t * tbl = shtbl;
90 :
91 0 : if( FD_UNLIKELY( tbl->magic!=FD_NETDEV_TBL_MAGIC ) ) {
92 0 : FD_LOG_WARNING(( "bad magic" ));
93 0 : return NULL;
94 0 : }
95 :
96 0 : *join = (fd_netdev_tbl_join_t) {
97 0 : .hdr = &tbl->hdr,
98 0 : .dev_tbl = (fd_netdev_t *)( (ulong)tbl + tbl->dev_off ),
99 0 : .bond_tbl = (fd_netdev_bond_t *)( (ulong)tbl + tbl->bond_off ),
100 0 : };
101 :
102 0 : return join;
103 0 : }
104 :
105 : void *
106 0 : fd_netdev_tbl_leave( fd_netdev_tbl_join_t * join ) {
107 0 : return join;
108 0 : }
109 :
110 : void *
111 0 : fd_netdev_tbl_delete( void * shtbl ) {
112 :
113 0 : if( FD_UNLIKELY( !shtbl ) ) {
114 0 : FD_LOG_WARNING(( "NULL shtbl" ));
115 0 : return NULL;
116 0 : }
117 :
118 0 : fd_netdev_tbl_t * tbl = shtbl;
119 0 : tbl->magic = 0UL;
120 0 : return tbl;
121 0 : }
122 :
123 : void
124 0 : fd_netdev_tbl_reset( fd_netdev_tbl_join_t * tbl ) {
125 0 : tbl->hdr->dev_cnt = 0;
126 0 : tbl->hdr->bond_cnt = 0;
127 0 : for( ulong j=0UL; j<(tbl->hdr->dev_max); j++ ) {
128 0 : tbl->dev_tbl[j] = (fd_netdev_t) {
129 0 : .master_idx = -1,
130 0 : .slave_tbl_idx = -1
131 0 : };
132 0 : }
133 0 : fd_memset( tbl->bond_tbl, 0, sizeof(fd_netdev_bond_t) * tbl->hdr->bond_max );
134 0 : }
135 :
136 : ulong
137 : fd_netdev_tbl_copy( fd_netdev_tbl_join_t * dst,
138 0 : fd_netdev_tbl_join_t const * src ) {
139 0 : ushort dev_max = dst->hdr->dev_max;
140 0 : ushort bond_max = dst->hdr->bond_max;
141 0 : for(;;) {
142 0 : ulong seq = fd_seqlock_read_try( &src->hdr->seqlock );
143 0 : dst->hdr->dev_cnt = src->hdr->dev_cnt;
144 0 : dst->hdr->bond_cnt = src->hdr->bond_cnt;
145 0 : fd_memcpy( dst->dev_tbl, src->dev_tbl, sizeof(fd_netdev_t) * dev_max );
146 0 : fd_memcpy( dst->bond_tbl, src->bond_tbl, sizeof(fd_netdev_bond_t) * bond_max );
147 0 : if( FD_LIKELY( fd_seqlock_read_test( &src->hdr->seqlock, seq ) ) ) return seq;
148 0 : FD_SPIN_PAUSE();
149 0 : }
150 0 : }
151 :
152 : int
153 : fd_netdev_tbl_refresh( fd_netdev_tbl_join_t * dst,
154 : fd_netdev_tbl_join_t const * src,
155 0 : ulong * seq ) {
156 0 : ulong cur = atomic_load_explicit( &src->hdr->seqlock, memory_order_relaxed );
157 0 : if( FD_LIKELY( (cur&1UL) || cur==*seq ) ) return 0;
158 0 : *seq = fd_netdev_tbl_copy( dst, src );
159 0 : return 1;
160 0 : }
161 :
162 : #if FD_HAS_HOSTED
163 :
164 : #include <errno.h>
165 : #include <stdio.h>
166 : #include "../../util/net/fd_eth.h"
167 :
168 0 : #define WRAP_PRINT(file,str) if( FD_UNLIKELY( fputs( (str), (file) )<0 ) ) return errno
169 0 : #define WRAP_PRINTF(file,...) if( FD_UNLIKELY( fprintf( (file), __VA_ARGS__ )<0 ) ) return errno
170 :
171 : int
172 : fd_netdev_tbl_fprintf( fd_netdev_tbl_join_t const * tbl,
173 0 : void * file_ ) {
174 0 : FILE * file = file_;
175 0 : for( ulong j=0UL; j<(tbl->hdr->dev_cnt); j++ ) {
176 0 : fd_netdev_t const * dev = &tbl->dev_tbl[j];
177 0 : if( !dev->oper_status ) continue;
178 0 : WRAP_PRINTF( file,
179 0 : "%u: %s: mtu %u state (%i-%s)",
180 0 : dev->if_idx, dev->name, dev->mtu,
181 0 : dev->oper_status, fd_oper_status_cstr( dev->oper_status ) );
182 0 : if( dev->slave_tbl_idx>=0 ) {
183 0 : WRAP_PRINT( file, " master" );
184 0 : }
185 0 : WRAP_PRINTF( file,
186 0 : "\n link " FD_ETH_MAC_FMT "\n",
187 0 : FD_ETH_MAC_FMT_ARGS( dev->mac_addr ) );
188 0 : if( dev->slave_tbl_idx>=0 && tbl->bond_tbl[ dev->slave_tbl_idx ].slave_cnt ) {
189 0 : fd_netdev_bond_t * bond = &tbl->bond_tbl[ dev->slave_tbl_idx ];
190 0 : WRAP_PRINTF( file, " slaves (%u):", bond->slave_cnt );
191 0 : for( ulong k=0UL; k<(bond->slave_cnt); k++ ) {
192 0 : WRAP_PRINTF( file, " %u-%s", bond->slave_idx[k], tbl->dev_tbl[ bond->slave_idx[k] ].name );
193 0 : }
194 0 : WRAP_PRINT( file, "\n" );
195 0 : }
196 0 : }
197 0 : return 0;
198 0 : }
199 :
200 : #undef WRAP_PRINT
201 : #undef WRAP_PRINTF
202 :
203 : #endif /* FD_HAS_HOSTED */
204 :
205 : char const *
206 0 : fd_oper_status_cstr( uint oper_status ) {
207 0 : switch( oper_status ) {
208 0 : case FD_OPER_STATUS_UP: return "up";
209 0 : case FD_OPER_STATUS_DOWN: return "down";
210 0 : case FD_OPER_STATUS_TESTING: return "testing";
211 0 : case FD_OPER_STATUS_DORMANT: return "dormant";
212 0 : case FD_OPER_STATUS_NOT_PRESENT: return "not present";
213 0 : case FD_OPER_STATUS_LOWER_LAYER_DOWN: return "lower layer down";
214 0 : case FD_OPER_STATUS_UNKNOWN: /* fallthrough */
215 0 : default:
216 0 : return "unknown";
217 0 : }
218 0 : }
|