Line data Source code
1 : /* Topology support routines for the net tile */
2 :
3 : #define _GNU_SOURCE
4 : #include "fd_net_tile.h"
5 : #include "../topo/fd_topob.h"
6 : #include "../netlink/fd_netlink_tile.h"
7 : #include "../../app/shared/fd_config.h" /* FIXME layering violation */
8 : #include "../../util/pod/fd_pod_format.h"
9 : #include "fd_linux_bond.h"
10 : #include "../../waltz/ip/fd_iproute.h"
11 :
12 : #include <errno.h>
13 : #include <net/if.h>
14 : #include <unistd.h>
15 :
16 : char const *
17 0 : fd_net_tile_name( char const * provider ) {
18 0 : if( 0==strcmp( provider, "xdp" ) ) {
19 0 : return "net";
20 0 : } else if( 0==strcmp( provider, "mlx5" ) ) {
21 0 : return "mlx5";
22 0 : } else if( 0==strcmp( provider, "socket" ) ) {
23 0 : return "sock";
24 0 : }
25 0 : FD_LOG_ERR(( "invalid net provider: %s", provider ));
26 0 : }
27 :
28 : fd_fib4_t *
29 : fd_net_tile_fib4_join( fd_fib4_t * out,
30 : fd_topo_t const * topo,
31 : fd_topo_tile_t const * net_tile,
32 0 : int main_table ) {
33 0 : if( 0==strcmp( net_tile->name, "net" ) ) {
34 0 : return fd_xdp_tile_fib4_join( out, topo, net_tile, main_table );
35 0 : } else if( 0==strcmp( net_tile->name, "mlx5" ) ) {
36 0 : return fd_mlx5_tile_fib4_join( out, topo, net_tile, main_table );
37 0 : }
38 0 : FD_LOG_ERR(( "tile %s has no fib4", net_tile->name ));
39 0 : }
40 :
41 : static void
42 : setup_mlx5_tile( fd_topo_t * topo,
43 : ulong tile_kind_id,
44 : fd_topo_tile_t * netlink_tile,
45 : ulong const * tile_to_cpu,
46 : fd_config_net_t const * net_cfg,
47 : ulong route_max,
48 0 : ulong route_peer_max ) {
49 0 : fd_topo_tile_t * tile = fd_topob_tile( topo, "mlx5", "mlx5", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0, 0 );
50 0 : fd_topob_link( topo, "net_netlnk", "net_netlnk", 128UL, 0UL, 0UL );
51 0 : fd_topob_tile_in( topo, "netlnk", 0UL, "metric_in", "net_netlnk", tile_kind_id, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
52 0 : fd_topob_tile_out( topo, "mlx5", tile_kind_id, "net_netlnk", tile_kind_id );
53 0 : fd_topob_tile_in( topo, "mlx5", tile_kind_id, "metric_in", "iproute_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
54 0 : fd_netlink_topo_join( topo, netlink_tile, tile );
55 :
56 0 : fd_topo_obj_t * umem_obj = fd_topob_obj( topo, "dcache", "net_umem" );
57 0 : fd_topob_tile_uses( topo, tile, umem_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
58 0 : fd_pod_insertf_ulong( topo->props, umem_obj->id, "net.%lu.umem", tile_kind_id );
59 :
60 0 : FD_STATIC_ASSERT( sizeof(tile->mlx5.if_name)==IF_NAMESIZE, str_bounds );
61 0 : fd_cstr_ncpy( tile->mlx5.if_name, net_cfg->interface, IF_NAMESIZE );
62 :
63 0 : tile->mlx5.net.bind_address = net_cfg->bind_address_parsed;
64 0 : tile->mlx5.rx_queue_size = net_cfg->mlx5.rx_queue_size;
65 0 : tile->mlx5.tx_queue_size = net_cfg->mlx5.tx_queue_size;
66 0 : tile->mlx5.batch_size = FD_MLX5_BATCH_SIZE;
67 :
68 0 : tile->net.umem_dcache_obj_id = umem_obj->id;
69 0 : tile->mlx5.netdev_tbl_obj_id = netlink_tile->netlink.netdev_tbl_obj_id;
70 0 : tile->mlx5.route_max = route_max;
71 0 : tile->mlx5.route_peer_max = route_peer_max;
72 0 : tile->mlx5.route_peer_seed = 1UL + tile_kind_id;
73 0 : tile->mlx5.neigh4_obj_id = netlink_tile->netlink.neigh4_obj_id;
74 0 : }
75 :
76 : static void
77 : setup_xdp_tile( fd_topo_t * topo,
78 : ulong tile_kind_id,
79 : fd_topo_tile_t * netlink_tile,
80 : ulong const * tile_to_cpu,
81 : fd_config_net_t const * net_cfg,
82 : ulong route_max,
83 : ulong route_peer_max,
84 : char const * if_phys,
85 : ulong if_queue,
86 0 : int xsk_core_dump ) {
87 0 : fd_topo_tile_t * tile = fd_topob_tile( topo, "net", "net", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0, 0 );
88 0 : fd_topob_link( topo, "net_netlnk", "net_netlnk", 128UL, 0UL, 0UL );
89 0 : fd_topob_tile_in( topo, "netlnk", 0UL, "metric_in", "net_netlnk", tile_kind_id, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
90 0 : fd_topob_tile_out( topo, "net", tile_kind_id, "net_netlnk", tile_kind_id );
91 0 : fd_topob_tile_in( topo, "net", tile_kind_id, "metric_in", "iproute_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
92 0 : fd_netlink_topo_join( topo, netlink_tile, tile );
93 :
94 0 : fd_topo_obj_t * umem_obj = fd_topob_obj( topo, "dcache", "net_umem" );
95 0 : fd_topob_tile_uses( topo, tile, umem_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
96 0 : fd_pod_insertf_ulong( topo->props, umem_obj->id, "net.%lu.umem", tile_kind_id );
97 :
98 0 : FD_STATIC_ASSERT( sizeof(tile->xdp.if_virt)==IF_NAMESIZE, str_bounds );
99 0 : fd_cstr_ncpy( tile->xdp.if_virt, net_cfg->interface, IF_NAMESIZE );
100 0 : tile->net.bind_address = net_cfg->bind_address_parsed;
101 :
102 0 : FD_STATIC_ASSERT( sizeof(tile->xdp.if_phys)==IF_NAMESIZE, str_bounds );
103 0 : fd_cstr_ncpy( tile->xdp.if_phys, if_phys, IF_NAMESIZE );
104 0 : tile->xdp.if_queue = (uint)if_queue;
105 :
106 0 : tile->xdp.tx_flush_timeout_ns = (long)net_cfg->xdp.flush_timeout_micros * 1000L;
107 0 : tile->xdp.xdp_rx_queue_size = net_cfg->xdp.xdp_rx_queue_size;
108 0 : tile->xdp.xdp_tx_queue_size = net_cfg->xdp.xdp_tx_queue_size;
109 0 : tile->xdp.zero_copy = net_cfg->xdp.xdp_zero_copy;
110 0 : fd_cstr_ncpy( tile->xdp.xdp_mode, net_cfg->xdp.xdp_mode, sizeof(tile->xdp.xdp_mode) );
111 :
112 0 : fd_cstr_ncpy( tile->xdp.poll_mode, net_cfg->xdp.poll_mode, sizeof(tile->xdp.poll_mode) );
113 :
114 0 : tile->xdp.net.umem_dcache_obj_id = umem_obj->id;
115 0 : tile->xdp.netdev_tbl_obj_id = netlink_tile->netlink.netdev_tbl_obj_id;
116 0 : tile->xdp.route_max = route_max;
117 0 : tile->xdp.route_peer_max = route_peer_max;
118 0 : tile->xdp.route_peer_seed = 1UL + tile_kind_id;
119 0 : tile->xdp.neigh4_obj_id = netlink_tile->netlink.neigh4_obj_id;
120 :
121 0 : tile->xdp.xsk_core_dump = xsk_core_dump;
122 :
123 : /* Allocate free ring */
124 :
125 0 : tile->xdp.free_ring_depth = tile->xdp.xdp_tx_queue_size;
126 0 : if( tile_kind_id==0 ) {
127 : /* Allocate additional frames for loopback */
128 0 : tile->xdp.free_ring_depth += 16384UL;
129 0 : }
130 0 : }
131 :
132 : static void
133 : setup_sock_tile( fd_topo_t * topo,
134 : ulong const * tile_to_cpu,
135 0 : fd_config_net_t const * net_cfg ) {
136 0 : fd_topo_tile_t * tile = fd_topob_tile( topo, "sock", "sock", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0, 0 );
137 0 : tile->sock.net.bind_address = net_cfg->bind_address_parsed;
138 :
139 0 : if( FD_UNLIKELY( net_cfg->socket.receive_buffer_size>INT_MAX ) ) FD_LOG_ERR(( "invalid [net.socket.receive_buffer_size]" ));
140 0 : if( FD_UNLIKELY( net_cfg->socket.send_buffer_size >INT_MAX ) ) FD_LOG_ERR(( "invalid [net.socket.send_buffer_size]" ));
141 0 : tile->sock.so_rcvbuf = (int)net_cfg->socket.receive_buffer_size;
142 0 : tile->sock.so_sndbuf = (int)net_cfg->socket.send_buffer_size ;
143 0 : }
144 :
145 : void
146 : fd_topos_net_tiles( fd_topo_t * topo,
147 : ulong net_tile_cnt,
148 : fd_config_net_t const * net_cfg,
149 : ulong netlnk_max_routes,
150 : ulong netlnk_max_peer_routes,
151 : ulong netlnk_max_neighbors,
152 : int xsk_core_dump,
153 0 : ulong const tile_to_cpu[ FD_TILE_MAX ] ) {
154 : /* net_umem: Packet buffers */
155 0 : fd_topob_wksp( topo, "net_umem" );
156 :
157 0 : fd_pod_insert_cstr( topo->props, "net.provider", net_cfg->provider );
158 :
159 : /* Create workspaces */
160 :
161 0 : if( 0==strcmp( net_cfg->provider, "xdp" ) ) {
162 :
163 : /* net: private working memory of the net tiles */
164 0 : fd_topob_wksp( topo, "net" );
165 : /* netlnk: private working memory of the netlnk tile */
166 0 : fd_topob_wksp( topo, "netlnk" );
167 : /* netbase: shared network config (config plane) */
168 0 : fd_topob_wksp( topo, "netbase" );
169 : /* net_netlnk: net->netlnk ARP requests */
170 0 : fd_topob_wksp( topo, "net_netlnk" );
171 0 : fd_topob_wksp( topo, "iproute" );
172 :
173 0 : fd_topo_tile_t * netlink_tile = fd_topob_tile( topo, "netlnk", "netlnk", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0, 1 );
174 : /* A dump is emitted synchronously. Keep room for one complete dump in
175 : addition to an already outstanding complete dump. */
176 0 : ulong iproute_depth = fd_ulong_pow2_up( 4UL*(netlnk_max_routes+netlnk_max_peer_routes)+8UL );
177 0 : fd_topob_link( topo, "iproute_out", "iproute", iproute_depth, sizeof(fd_iproute_msg_t), 1UL );
178 0 : fd_topob_tile_out( topo, "netlnk", 0UL, "iproute_out", 0UL );
179 0 : fd_netlink_topo_create( netlink_tile, topo, netlnk_max_routes, netlnk_max_peer_routes, netlnk_max_neighbors, net_cfg->interface );
180 :
181 : /* Enumerate network devices to attach to */
182 0 : uint devices[ FD_NET_BOND_SLAVE_MAX ] = {0};
183 0 : uint device_cnt = 1U;
184 0 : if( net_cfg->xdp.native_bond && fd_bonding_is_master( net_cfg->interface ) ) {
185 0 : fd_bonding_slave_iter_t iter_[1];
186 0 : fd_bonding_slave_iter_t * iter = fd_bonding_slave_iter_init( iter_, net_cfg->interface );
187 0 : uint slave_cnt;
188 0 : for( slave_cnt=0U;
189 0 : /* */ !fd_bonding_slave_iter_done( iter );
190 0 : slave_cnt++, fd_bonding_slave_iter_next( iter ) ) {
191 0 : if( FD_UNLIKELY( slave_cnt>=FD_NET_BOND_SLAVE_MAX ) ) {
192 0 : FD_LOG_ERR(( "bond interface %s has too many slave devices; max is %u (see [net.xdp.native_bond])",
193 0 : net_cfg->interface, FD_NET_BOND_SLAVE_MAX ));
194 0 : }
195 0 : uint if_idx = if_nametoindex( fd_bonding_slave_iter_ele( iter ) );
196 0 : if( FD_UNLIKELY( !if_idx ) ) FD_LOG_ERR(( "if_nametoindex(%s) failed", fd_bonding_slave_iter_ele( iter ) ));
197 0 : devices[ slave_cnt ] = if_idx;
198 0 : }
199 0 : if( slave_cnt==0 ) {
200 0 : FD_LOG_ERR(( "no bond slave devices detected on interface %s (see [net.xdp.native_bond])", net_cfg->interface ));
201 0 : }
202 0 : device_cnt = (uint)slave_cnt;
203 0 : } else {
204 0 : devices[ 0 ] = if_nametoindex( net_cfg->interface );
205 0 : if( FD_UNLIKELY( !devices[ 0 ] ) ) FD_LOG_ERR(( "unsupported [net.interface]: `%s`", net_cfg->interface ));
206 0 : device_cnt = 1U;
207 0 : }
208 :
209 : /* Verify that net_tile_cnt is a multiple of device_cnt */
210 0 : if( FD_UNLIKELY( net_tile_cnt%device_cnt!=0 ) ) {
211 0 : FD_LOG_ERR(( "net tile count %lu must be a multiple of the number of slave devices %u (incompatible settings [layout.net_tile_count] and [net.xdp.native_bond])", net_tile_cnt, device_cnt ));
212 0 : }
213 0 : uint dev_queue_cnt = (uint)net_tile_cnt/device_cnt;
214 :
215 : /* Assign XDP tiles to device queues */
216 0 : ulong tile_kind_id = 0UL;
217 0 : for( uint i=0UL; i<device_cnt; i++ ) {
218 0 : char if_name[ IF_NAMESIZE ];
219 0 : if( FD_UNLIKELY( !if_indextoname( devices[ i ], if_name ) ) ) {
220 0 : FD_LOG_ERR(( "error initializing network stack: if_indextoname(%u) failed (try disabling [net.xdp.native_bond]?)", i ));
221 0 : }
222 0 : for( ulong j=0UL; j<dev_queue_cnt; j++ ) {
223 0 : setup_xdp_tile( topo, tile_kind_id++, netlink_tile, tile_to_cpu, net_cfg, netlnk_max_routes, netlnk_max_peer_routes, if_name, (uint)j, xsk_core_dump );
224 0 : }
225 0 : }
226 0 : FD_TEST( tile_kind_id==net_tile_cnt );
227 :
228 0 : } else if( 0==strcmp( net_cfg->provider, "socket" ) ) {
229 :
230 : /* sock: private working memory of the sock tiles */
231 0 : fd_topob_wksp( topo, "sock" );
232 :
233 0 : for( ulong i=0UL; i<net_tile_cnt; i++ ) {
234 0 : setup_sock_tile( topo, tile_to_cpu, net_cfg );
235 0 : }
236 0 : } else if( 0==strcmp( net_cfg->provider, "mlx5" ) ) {
237 :
238 : /* mlx5: private working memory of the mlx5 tiles */
239 0 : fd_topob_wksp( topo, "mlx5" );
240 : /* netlnk: private working memory of the netlnk tile */
241 0 : fd_topob_wksp( topo, "netlnk" );
242 : /* netbase: shared network config (config plane) */
243 0 : fd_topob_wksp( topo, "netbase" );
244 : /* net_netlnk: net->netlnk ARP requests */
245 0 : fd_topob_wksp( topo, "net_netlnk" );
246 0 : fd_topob_wksp( topo, "iproute" );
247 :
248 0 : fd_topo_tile_t * netlink_tile = fd_topob_tile( topo, "netlnk", "netlnk", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0, 1 );
249 0 : ulong iproute_depth = fd_ulong_pow2_up( 4UL*(netlnk_max_routes+netlnk_max_peer_routes)+8UL );
250 0 : fd_topob_link( topo, "iproute_out", "iproute", iproute_depth, sizeof(fd_iproute_msg_t), 1UL );
251 0 : fd_topob_tile_out( topo, "netlnk", 0UL, "iproute_out", 0UL );
252 0 : fd_netlink_topo_create( netlink_tile, topo, netlnk_max_routes, netlnk_max_peer_routes, netlnk_max_neighbors, net_cfg->interface );
253 :
254 0 : if( FD_UNLIKELY( !fd_ulong_is_pow2( net_tile_cnt ) ) ) {
255 0 : FD_LOG_ERR(( "net.provider=\"mlx5\" requires layout.net_tile_count to be a power of two" ));
256 0 : }
257 0 : for( ulong i=0UL; i<net_tile_cnt; i++ ) {
258 0 : setup_mlx5_tile( topo, i, netlink_tile, tile_to_cpu, net_cfg, netlnk_max_routes, netlnk_max_peer_routes );
259 0 : }
260 :
261 0 : } else {
262 0 : FD_LOG_ERR(( "invalid `net.provider`" ));
263 0 : }
264 0 : }
265 :
266 : static void
267 : add_umem_rx_link( fd_topo_t * topo,
268 : char const * link_name,
269 : ulong net_kind_id,
270 : ulong depth,
271 162 : ulong burst ) {
272 162 : if( FD_UNLIKELY( !topo || !link_name ) ) FD_LOG_ERR(( "NULL args" ));
273 162 : if( FD_UNLIKELY( strlen( link_name )>=sizeof(topo->links[ topo->link_cnt ].name ) ) ) FD_LOG_ERR(( "link name too long: %s", link_name ));
274 162 : if( FD_UNLIKELY( topo->link_cnt>=FD_TOPO_MAX_LINKS ) ) FD_LOG_ERR(( "too many links" ));
275 :
276 162 : ulong kind_id = 0UL;
277 810 : for( ulong i=0UL; i<topo->link_cnt; i++ ) {
278 648 : if( !strcmp( topo->links[ i ].name, link_name ) ) kind_id++;
279 648 : }
280 :
281 162 : fd_topo_link_t * link = &topo->links[ topo->link_cnt ];
282 162 : strncpy( link->name, link_name, sizeof(link->name) );
283 162 : link->id = topo->link_cnt;
284 162 : link->kind_id = kind_id;
285 162 : link->depth = depth;
286 162 : link->mtu = FD_NET_MTU;
287 162 : link->burst = burst;
288 :
289 162 : fd_topo_obj_t * obj = fd_topob_obj( topo, "mcache", "net_umem" );
290 162 : link->mcache_obj_id = obj->id;
291 162 : FD_TEST( fd_pod_insertf_ulong( topo->props, depth, "obj.%lu.depth", obj->id ) );
292 :
293 162 : link->dcache_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "net.%lu.umem", net_kind_id );
294 162 : if( FD_UNLIKELY( link->dcache_obj_id==ULONG_MAX ) ) FD_LOG_ERR(( "umem dcache not found for net %lu", net_kind_id ));
295 :
296 162 : topo->link_cnt++;
297 162 : }
298 :
299 : void
300 : fd_topos_net_rx_link( fd_topo_t * topo,
301 : char const * link_name,
302 : ulong net_kind_id,
303 162 : ulong depth ) {
304 162 : char const * provider = fd_pod_query_cstr( topo->props, "net.provider", "" );
305 162 : if( 0==strcmp( provider, "xdp" ) ) {
306 0 : add_umem_rx_link( topo, link_name, net_kind_id, depth, 0UL );
307 0 : fd_topob_tile_out( topo, "net", net_kind_id, link_name, net_kind_id );
308 162 : } else if( 0==strcmp( provider, "mlx5" ) ) {
309 162 : ulong tile_id = fd_topo_find_tile( topo, "mlx5", net_kind_id );
310 162 : if( FD_UNLIKELY( tile_id==ULONG_MAX ) ) FD_LOG_ERR(( "tile mlx5:%lu not found", net_kind_id ));
311 162 : add_umem_rx_link( topo, link_name, net_kind_id, depth, topo->tiles[ tile_id ].mlx5.batch_size );
312 162 : fd_topob_tile_out( topo, "mlx5", net_kind_id, link_name, net_kind_id );
313 162 : } else if( 0==strcmp( provider, "socket" ) ) {
314 0 : fd_topob_link( topo, link_name, "net_umem", depth, FD_NET_MTU, 64 );
315 0 : fd_topob_tile_out( topo, "sock", net_kind_id, link_name, net_kind_id );
316 0 : }
317 162 : }
318 :
319 : void
320 : fd_topos_tile_in_net( fd_topo_t * topo,
321 : char const * fseq_wksp,
322 : char const * link_name,
323 : ulong link_kind_id,
324 : int reliable,
325 0 : int polled ) {
326 0 : for( ulong j=0UL; j<(topo->tile_cnt); j++ ) {
327 0 : if( 0==strcmp( topo->tiles[ j ].name, "net" ) ||
328 0 : 0==strcmp( topo->tiles[ j ].name, "sock" ) ||
329 0 : 0==strcmp( topo->tiles[ j ].name, "mlx5" ) ) {
330 0 : fd_topob_tile_in( topo, topo->tiles[ j ].name, topo->tiles[ j ].kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled );
331 0 : }
332 0 : }
333 0 : }
334 :
335 : static void
336 : fd_topos_xdp_setup_mem( fd_topo_t * topo,
337 0 : fd_topo_tile_t * net_tile ) {
338 0 : ulong rx_depth = net_tile->xdp.xdp_rx_queue_size;
339 0 : ulong tx_depth = net_tile->xdp.xdp_tx_queue_size;
340 0 : rx_depth += (rx_depth/2UL);
341 0 : tx_depth += (tx_depth/2UL);
342 :
343 0 : if( net_tile->kind_id==0 ) {
344 : /* Double it for loopback XSK */
345 0 : rx_depth *= 2UL;
346 0 : tx_depth *= 2UL;
347 0 : }
348 :
349 0 : ulong cum_frame_cnt = rx_depth + tx_depth;
350 :
351 : /* Count up the depth of all RX mcaches */
352 :
353 0 : for( ulong j=0UL; j<(net_tile->out_cnt); j++ ) {
354 0 : ulong link_id = net_tile->out_link_id[ j ];
355 0 : ulong mcache_obj_id = topo->links[ link_id ].mcache_obj_id;
356 0 : ulong depth = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "obj.%lu.depth", mcache_obj_id );
357 0 : if( FD_UNLIKELY( depth==ULONG_MAX ) ) FD_LOG_ERR(( "Didn't find depth for mcache %s", topo->links[ link_id ].name ));
358 0 : cum_frame_cnt += depth + 1UL;
359 0 : }
360 :
361 : /* Create a dcache object */
362 :
363 0 : ulong umem_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "net.%lu.umem", net_tile->kind_id );
364 0 : FD_TEST( umem_obj_id!=ULONG_MAX );
365 :
366 0 : FD_TEST( net_tile->net.umem_dcache_obj_id > 0 );
367 0 : fd_pod_insertf_ulong( topo->props, cum_frame_cnt, "obj.%lu.depth", umem_obj_id );
368 0 : fd_pod_insertf_ulong( topo->props, 2UL, "obj.%lu.burst", umem_obj_id ); /* 4096 byte padding */
369 0 : fd_pod_insertf_ulong( topo->props, 2048UL, "obj.%lu.mtu", umem_obj_id );
370 0 : }
371 :
372 : void
373 : fd_topo_install_xdp( fd_topo_t const * topo,
374 : fd_xdp_fds_t * fds,
375 : uint * fds_cnt,
376 : uint bind_addr,
377 0 : int dry_run ) {
378 0 : uint fds_max = *fds_cnt;
379 0 : memset( fds, 0, fds_max*sizeof(fd_xdp_fds_t) );
380 :
381 0 : uint if_cnt = 0U;
382 0 : # define ADD_IF_IDX( idx_ ) do { \
383 0 : uint idx = (idx_); \
384 0 : int found = 0; \
385 0 : for( uint i=0U; i<if_cnt; i++ ) { \
386 0 : if( fds[ i ].if_idx==idx ) { \
387 0 : found = 1; \
388 0 : break; \
389 0 : } \
390 0 : } \
391 0 : if( !found ) { \
392 0 : FD_TEST( if_cnt<FD_NET_BOND_SLAVE_MAX+1 ); \
393 0 : fds[ if_cnt++ ].if_idx = idx; \
394 0 : } \
395 0 : } while(0)
396 :
397 : /* Create a list of unique fds */
398 :
399 0 : ulong net_tile_cnt = fd_topo_tile_name_cnt( topo, "net" );
400 0 : for( ulong tile_kind_id=0UL; tile_kind_id<net_tile_cnt; tile_kind_id++ ) {
401 0 : ulong net_tile_id = fd_topo_find_tile( topo, "net", tile_kind_id );
402 0 : FD_TEST( net_tile_id!=ULONG_MAX );
403 0 : fd_topo_tile_t const * tile = &topo->tiles[ net_tile_id ];
404 0 : uint if_idx = if_nametoindex( tile->xdp.if_phys ); FD_TEST( if_idx );
405 0 : ADD_IF_IDX( if_idx );
406 0 : }
407 :
408 : /* Add loopback unless found */
409 :
410 0 : uint lo_idx = if_nametoindex( "lo" ); FD_TEST( lo_idx );
411 0 : ADD_IF_IDX( lo_idx );
412 :
413 : /* Done with config discovery */
414 :
415 0 : *fds_cnt = if_cnt;
416 0 : int next_fd = 123462;
417 0 : for( uint i=0U; i<if_cnt; i++ ) {
418 0 : fds[ i ].xsk_map_fd = next_fd++;
419 0 : fds[ i ].prog_link_fd = next_fd++;
420 0 : }
421 0 : if( dry_run ) return;
422 :
423 : /* Install */
424 :
425 0 : ulong net0_tile_idx = fd_topo_find_tile( topo, "net", 0UL );
426 0 : FD_TEST( net0_tile_idx!=ULONG_MAX );
427 0 : fd_topo_tile_t const * net0_tile = &topo->tiles[ net0_tile_idx ];
428 :
429 0 : ushort udp_port_candidates[] = {
430 0 : (ushort)net0_tile->xdp.net.legacy_transaction_listen_port,
431 0 : (ushort)net0_tile->xdp.net.quic_transaction_listen_port,
432 0 : (ushort)net0_tile->xdp.net.shred_listen_port,
433 0 : (ushort)net0_tile->xdp.net.gossip_listen_port,
434 0 : (ushort)net0_tile->xdp.net.repair_client_listen_port,
435 0 : (ushort)net0_tile->xdp.net.repair_serve_listen_port,
436 0 : (ushort)net0_tile->xdp.net.txsend_src_port,
437 0 : (ushort)net0_tile->xdp.net.votor_quic_client_listen_port,
438 0 : (ushort)net0_tile->xdp.net.votor_quic_server_listen_port,
439 0 : };
440 :
441 0 : for( uint i=0U; i<if_cnt; i++ ) {
442 : /* Override XDP mode for loopback */
443 0 : char const * xdp_mode = net0_tile->xdp.xdp_mode;
444 0 : if( fds[ i ].if_idx==1U ) xdp_mode = "skb";
445 :
446 0 : fd_xdp_fds_t xdp_fds = fd_xdp_install(
447 0 : fds[ i ].if_idx,
448 0 : bind_addr,
449 0 : sizeof(udp_port_candidates)/sizeof(udp_port_candidates[0]),
450 0 : udp_port_candidates,
451 0 : xdp_mode );
452 0 : if( FD_UNLIKELY( -1==dup2( xdp_fds.xsk_map_fd, fds[ i ].xsk_map_fd ) ) ) {
453 0 : FD_LOG_ERR(( "dup2() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
454 0 : }
455 0 : if( FD_UNLIKELY( -1==close( xdp_fds.xsk_map_fd ) ) ) {
456 0 : FD_LOG_ERR(( "close() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
457 0 : }
458 0 : if( FD_UNLIKELY( -1==dup2( xdp_fds.prog_link_fd, fds[ i ].prog_link_fd ) ) ) {
459 0 : FD_LOG_ERR(( "dup2() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
460 0 : }
461 0 : if( FD_UNLIKELY( -1==close( xdp_fds.prog_link_fd ) ) ) {
462 0 : FD_LOG_ERR(( "close() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
463 0 : }
464 0 : }
465 0 : }
466 :
467 : # undef ADD_IF_IDX
468 :
469 : static void
470 : fd_topos_mlx5_setup_mem( fd_topo_t * topo,
471 0 : fd_topo_tile_t * mlx5_tile ) {
472 0 : ulong cum_frame_cnt = 0UL;
473 :
474 0 : ulong const rx_depth = mlx5_tile->mlx5.rx_queue_size;
475 0 : ulong const tx_depth = mlx5_tile->mlx5.tx_queue_size;
476 0 : cum_frame_cnt += rx_depth + tx_depth;
477 :
478 : /* Count up the depth of all RX mcaches */
479 :
480 0 : for( ulong j=0UL; j<(mlx5_tile->out_cnt); j++ ) {
481 0 : ulong link_id = mlx5_tile->out_link_id[ j ];
482 0 : ulong mcache_obj_id = topo->links[ link_id ].mcache_obj_id;
483 0 : ulong depth = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "obj.%lu.depth", mcache_obj_id );
484 0 : if( FD_UNLIKELY( depth==ULONG_MAX ) ) FD_LOG_ERR(( "Didn't find depth for mcache %s", topo->links[ link_id ].name ));
485 0 : cum_frame_cnt += depth + 1UL;
486 0 : }
487 :
488 : /* Create a dcache object */
489 :
490 0 : ulong umem_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "net.%lu.umem", mlx5_tile->kind_id );
491 0 : FD_TEST( umem_obj_id!=ULONG_MAX );
492 :
493 0 : FD_TEST( mlx5_tile->net.umem_dcache_obj_id > 0 );
494 0 : fd_pod_insertf_ulong( topo->props, cum_frame_cnt, "obj.%lu.depth", umem_obj_id );
495 0 : fd_pod_insertf_ulong( topo->props, 2UL, "obj.%lu.burst", umem_obj_id ); /* 4096 byte padding */
496 0 : fd_pod_insertf_ulong( topo->props, FD_NET_MTU, "obj.%lu.mtu", umem_obj_id );
497 0 : }
498 :
499 : void
500 : fd_topos_net_tile_finish( fd_topo_t * topo,
501 0 : ulong net_kind_id ) {
502 0 : char const * provider = fd_pod_query_cstr( topo->props, "net.provider", "" );
503 0 : if( 0==strcmp( provider, "xdp" ) ) {
504 0 : ulong tile_id = fd_topo_find_tile( topo, "net", net_kind_id );
505 0 : if( FD_UNLIKELY( tile_id==ULONG_MAX ) ) {
506 0 : FD_LOG_ERR(( "tile net:%lu not found", net_kind_id ));
507 0 : }
508 0 : fd_topos_xdp_setup_mem( topo, &topo->tiles[ tile_id ] );
509 0 : } else if( 0==strcmp( provider, "mlx5" ) ) {
510 0 : ulong tile_id = fd_topo_find_tile( topo, "mlx5", net_kind_id );
511 0 : if( FD_UNLIKELY( tile_id==ULONG_MAX ) ) {
512 0 : FD_LOG_ERR(( "tile mlx5:%lu not found", net_kind_id ));
513 0 : }
514 0 : fd_topos_mlx5_setup_mem( topo, &topo->tiles[ tile_id ] );
515 0 : } else {
516 0 : return;
517 0 : }
518 0 : }
|