LCOV - code coverage report
Current view: top level - disco/net - fd_net_tile_topo.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 513 0.0 %
Date: 2026-11-11 12:40:43 Functions: 0 20 0.0 %

          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 "iavf/fd_iavf.h"
      11             : #include "../../waltz/ip/fd_iproute.h"
      12             : 
      13             : #include <errno.h>
      14             : #include <limits.h>
      15             : #include <net/if.h>
      16             : #include <unistd.h>
      17             : 
      18             : static void
      19             : fd_net_read_device_driver( char *       driver,
      20             :                            ulong        driver_sz,
      21           0 :                            char const * if_name ) {
      22           0 :   FD_TEST( driver && driver_sz>=4UL );
      23           0 :   char path[ PATH_MAX ], target[ PATH_MAX ];
      24           0 :   fd_memcpy( driver, "n/a", 4UL );
      25           0 :   if( FD_UNLIKELY( !fd_cstr_printf_check( path, sizeof(path), NULL,
      26           0 :                                          "/sys/class/net/%s/device/driver", if_name ) ) ) {
      27           0 :     FD_LOG_WARNING(( "cannot read driver for interface `%s`: sysfs path too long", if_name ));
      28           0 :     return;
      29           0 :   }
      30             : 
      31           0 :   long n = readlink( path, target, sizeof(target)-1UL );
      32           0 :   if( FD_UNLIKELY( n<0L ) ) {
      33           0 :     if( errno!=ENOENT ) FD_LOG_WARNING(( "readlink(%s) failed (%i-%s)", path, errno, fd_io_strerror( errno ) ));
      34           0 :     return;
      35           0 :   }
      36           0 :   if( FD_UNLIKELY( (ulong)n==sizeof(target)-1UL ) ) {
      37           0 :     FD_LOG_WARNING(( "device driver link `%s` is too long", path ));
      38           0 :     return;
      39           0 :   }
      40           0 :   target[ n ] = '\0';
      41             : 
      42           0 :   char const * base = strrchr( target, '/' );
      43           0 :   base = base ? base+1 : target;
      44           0 :   if( FD_UNLIKELY( !base[0] ) ) {
      45           0 :     FD_LOG_WARNING(( "device driver link `%s` has an empty driver name", path ));
      46           0 :     return;
      47           0 :   }
      48           0 :   ulong name_sz = strlen( base )+1UL;
      49           0 :   if( FD_UNLIKELY( name_sz>driver_sz ) ) {
      50           0 :     FD_LOG_WARNING(( "driver name in `%s` exceeds output buffer size %lu", path, driver_sz ));
      51           0 :     return;
      52           0 :   }
      53           0 :   fd_memcpy( driver, base, name_sz );
      54           0 : }
      55             : 
      56             : void
      57             : fd_net_get_driver( char *       driver,
      58             :                    ulong        driver_sz,
      59           0 :                    char const * if_name ) {
      60           0 :   FD_TEST( driver && driver_sz>=4UL );
      61           0 :   if( !fd_bonding_is_master( if_name ) ) {
      62           0 :     fd_net_read_device_driver( driver, driver_sz, if_name );
      63           0 :     return;
      64           0 :   }
      65             : 
      66           0 :   driver[0] = '\0';
      67           0 :   fd_bonding_slave_iter_t iter[1];
      68           0 :   for( fd_bonding_slave_iter_init( iter, if_name );
      69           0 :        !fd_bonding_slave_iter_done( iter );
      70           0 :        fd_bonding_slave_iter_next( iter ) ) {
      71           0 :     char member_driver[ NAME_MAX+1UL ];
      72           0 :     fd_net_read_device_driver( member_driver, fd_ulong_min( sizeof(member_driver), driver_sz ),
      73           0 :                                fd_bonding_slave_iter_ele( iter ) );
      74           0 :     if( FD_UNLIKELY( !strcmp( member_driver, "n/a" ) || ( driver[0] && strcmp( driver, member_driver ) ) ) ) {
      75           0 :       driver[0] = '\0';
      76           0 :       break;
      77           0 :     }
      78           0 :     fd_cstr_ncpy( driver, member_driver, driver_sz );
      79           0 :   }
      80           0 :   if( FD_UNLIKELY( !driver[0] ) ) fd_memcpy( driver, "n/a", 4UL );
      81           0 : }
      82             : 
      83             : void
      84             : fd_net_rx_dest_list( fd_net_rx_dest_t           out[ FD_NET_RX_DEST_CNT ],
      85           0 :                      fd_topo_net_tile_t const * net ) {
      86           0 :   fd_net_rx_dest_t const rx_dests[ FD_NET_RX_DEST_CNT ] = {
      87           0 :     { DST_PROTO_TPU_UDP,  "net_quic",   net->legacy_transaction_listen_port, 1 },
      88           0 :     { DST_PROTO_TPU_QUIC, "net_quic",   net->quic_transaction_listen_port,   1 },
      89           0 :     { DST_PROTO_SHRED,    "net_shred",  net->shred_listen_port,              1 },
      90           0 :     { DST_PROTO_GOSSIP,   "net_gossvf", net->gossip_listen_port,             1 },
      91           0 :     { DST_PROTO_REPAIR,   "net_shred",  net->repair_client_listen_port,      1 },
      92           0 :     { DST_PROTO_RSERVE,   "net_rserve", net->repair_serve_listen_port,       0 },
      93           0 :     { DST_PROTO_VOTOR,    "net_votor",  net->votor_quic_client_listen_port,  1 },
      94           0 :     { DST_PROTO_VOTOR,    "net_votor",  net->votor_quic_server_listen_port,  1 }
      95           0 :   };
      96           0 :   fd_memcpy( out, rx_dests, sizeof(rx_dests) );
      97           0 : }
      98             : 
      99             : char const *
     100           0 : fd_net_tile_name( char const * provider ) {
     101           0 :   if( 0==strcmp( provider, "xdp" ) ) {
     102           0 :     return "net";
     103           0 :   } else if( 0==strcmp( provider, "mlx5" ) ) {
     104           0 :     return "mlx5";
     105           0 :   } else if( 0==strcmp( provider, "iavf" ) ) {
     106           0 :     return "iavf";
     107           0 :   } else if( 0==strcmp( provider, "socket" ) ) {
     108           0 :     return "sock";
     109           0 :   }
     110           0 :   FD_LOG_ERR(( "invalid net provider: %s", provider ));
     111           0 : }
     112             : 
     113             : static void
     114             : setup_mlx5_tile( fd_topo_t *             topo,
     115             :                  ulong                   tile_kind_id,
     116             :                  fd_topo_tile_t *        netlink_tile,
     117             :                  ulong const *           tile_to_cpu,
     118             :                  fd_config_net_t const * net_cfg,
     119             :                  ulong                   route_max,
     120           0 :                  ulong                   route_peer_max ) {
     121           0 :   fd_topo_tile_t * tile = fd_topob_tile( topo, "mlx5", "mlx5", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
     122           0 :   tile->sleep_eventfd = topo->sleep_obj_id!=ULONG_MAX;
     123           0 :   fd_topob_link( topo, "net_netlnk", "net_netlnk", 128UL, 0UL, 0UL );
     124           0 :   fd_topob_tile_in(  topo, "netlnk", 0UL,         "metric_in", "net_netlnk", tile_kind_id, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
     125           0 :   fd_topob_tile_out( topo, "mlx5", tile_kind_id,               "net_netlnk", tile_kind_id );
     126           0 :   fd_topob_tile_in(  topo, "mlx5", tile_kind_id, "metric_in", "iproute_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     127           0 :   fd_netlink_topo_join( topo, netlink_tile, tile );
     128             : 
     129           0 :   fd_topo_obj_t * umem_obj = fd_topob_obj( topo, "dcache", "net_umem" );
     130           0 :   fd_topob_tile_uses( topo, tile, umem_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     131           0 :   fd_pod_insertf_ulong( topo->props, umem_obj->id, "net.%lu.umem", tile_kind_id );
     132             : 
     133           0 :   FD_STATIC_ASSERT( sizeof(tile->mlx5.if_name)==IF_NAMESIZE, str_bounds );
     134           0 :   fd_cstr_ncpy( tile->mlx5.if_name, net_cfg->interface, IF_NAMESIZE );
     135             : 
     136           0 :   tile->mlx5.net.bind_address = net_cfg->bind_address_parsed;
     137           0 :   tile->mlx5.rx_queue_size    = net_cfg->mlx5.rx_queue_size;
     138           0 :   tile->mlx5.tx_queue_size    = net_cfg->mlx5.tx_queue_size;
     139           0 :   tile->mlx5.batch_size       = FD_MLX5_BATCH_SIZE;
     140             : 
     141           0 :   tile->net.umem_dcache_obj_id = umem_obj->id;
     142           0 :   tile->mlx5.netdev_tbl_obj_id = netlink_tile->netlink.netdev_tbl_obj_id;
     143           0 :   tile->mlx5.route_max         = route_max;
     144           0 :   tile->mlx5.route_peer_max    = route_peer_max;
     145           0 :   tile->mlx5.route_peer_seed   = 1UL + tile_kind_id;
     146           0 :   tile->mlx5.neigh4_obj_id     = netlink_tile->netlink.neigh4_obj_id;
     147           0 : }
     148             : 
     149             : static void
     150             : setup_iavf_tile( fd_topo_t *             topo,
     151             :                  ulong                   tile_kind_id,
     152             :                  fd_topo_tile_t *        netlink_tile,
     153             :                  ulong const *           tile_to_cpu,
     154             :                  fd_config_net_t const * net_cfg,
     155             :                  ulong                   route_max,
     156           0 :                  ulong                   route_peer_max ) {
     157           0 :   fd_topo_tile_t * tile = fd_topob_tile( topo, "iavf", "iavf", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
     158           0 :   fd_topo_tile_t const * first_tile = NULL;
     159           0 :   if( 0!=tile_kind_id ) {
     160           0 :     ulong first_tile_id = fd_topo_find_tile( topo, "iavf", 0UL );
     161           0 :     FD_TEST( first_tile_id!=ULONG_MAX );
     162           0 :     first_tile = &topo->tiles[ first_tile_id ];
     163             :     /* Only tile 0 consumes PF link events from the VF Admin Queues.
     164             :        The other iavf tiles copy its vf_link_usable array to track each
     165             :        VF's link state. */
     166           0 :     fd_topob_tile_uses( topo, tile, &topo->objs[ first_tile->tile_obj_id ], FD_SHMEM_JOIN_MODE_READ_ONLY );
     167           0 :   }
     168           0 :   fd_topob_link( topo, "net_netlnk", "net_netlnk", 128UL, 0UL, 0UL );
     169           0 :   fd_topob_tile_in(  topo, "netlnk", 0UL,         "metric_in", "net_netlnk", tile_kind_id, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
     170           0 :   fd_topob_tile_out( topo, "iavf", tile_kind_id,               "net_netlnk", tile_kind_id );
     171           0 :   fd_topob_tile_in(  topo, "iavf", tile_kind_id, "metric_in", "iproute_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     172           0 :   fd_netlink_topo_join( topo, netlink_tile, tile );
     173             : 
     174           0 :   fd_topo_obj_t * umem_obj = fd_topob_obj( topo, "dcache", "net_umem" );
     175           0 :   fd_topob_tile_uses( topo, tile, umem_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     176           0 :   fd_pod_insertf_ulong( topo->props, umem_obj->id, "net.%lu.umem", tile_kind_id );
     177             : 
     178           0 :   FD_STATIC_ASSERT( sizeof(tile->iavf.if_name)==IF_NAMESIZE, str_bounds );
     179           0 :   fd_cstr_ncpy( tile->iavf.if_name, net_cfg->interface, IF_NAMESIZE );
     180             : 
     181           0 :   if( first_tile!=NULL ) {
     182           0 :     tile->iavf.member_cnt = first_tile->iavf.member_cnt;
     183           0 :     fd_memcpy( tile->iavf.members, first_tile->iavf.members, sizeof(tile->iavf.members) );
     184           0 :   } else if( FD_UNLIKELY( -1==fd_iavf_member_interfaces( net_cfg->interface, tile->iavf.members, &tile->iavf.member_cnt ) ) ) {
     185           0 :     FD_LOG_ERR(( "IAVF member discovery failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     186           0 :   }
     187             : 
     188           0 :   tile->iavf.net.bind_address = net_cfg->bind_address_parsed;
     189           0 :   tile->iavf.rx_queue_size    = net_cfg->iavf.rx_queue_size;
     190           0 :   tile->iavf.tx_queue_size    = net_cfg->iavf.tx_queue_size;
     191             : 
     192           0 :   tile->net.umem_dcache_obj_id = umem_obj->id;
     193           0 :   tile->iavf.netdev_tbl_obj_id = netlink_tile->netlink.netdev_tbl_obj_id;
     194           0 :   tile->iavf.route_max         = route_max;
     195           0 :   tile->iavf.route_peer_max    = route_peer_max;
     196           0 :   tile->iavf.route_peer_seed   = 1UL + tile_kind_id;
     197           0 :   tile->iavf.neigh4_obj_id     = netlink_tile->netlink.neigh4_obj_id;
     198           0 : }
     199             : 
     200             : static void
     201             : setup_xdp_tile( fd_topo_t *             topo,
     202             :                 ulong                   tile_kind_id,
     203             :                 fd_topo_tile_t *        netlink_tile,
     204             :                 ulong const *           tile_to_cpu,
     205             :                 fd_config_net_t const * net_cfg,
     206             :                 ulong                   route_max,
     207             :                 ulong                   route_peer_max,
     208             :                 char const *            if_phys,
     209           0 :                 ulong                   if_queue ) {
     210           0 :   fd_topo_tile_t * tile = fd_topob_tile( topo, "net", "net", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, topo->sleep_obj_id!=ULONG_MAX );
     211           0 :   fd_topob_link( topo, "net_netlnk", "net_netlnk", 128UL, 0UL, 0UL );
     212           0 :   fd_topob_tile_in(  topo, "netlnk", 0UL, "metric_in", "net_netlnk", tile_kind_id, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
     213           0 :   fd_topob_tile_out( topo, "net",    tile_kind_id,                "net_netlnk", tile_kind_id );
     214           0 :   fd_topob_tile_in(  topo, "net", tile_kind_id, "metric_in", "iproute_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     215           0 :   fd_netlink_topo_join( topo, netlink_tile, tile );
     216             : 
     217           0 :   fd_topo_obj_t * umem_obj = fd_topob_obj( topo, "dcache", "net_umem" );
     218           0 :   fd_topob_tile_uses( topo, tile, umem_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     219           0 :   fd_pod_insertf_ulong( topo->props, umem_obj->id, "net.%lu.umem", tile_kind_id );
     220             : 
     221           0 :   FD_STATIC_ASSERT( sizeof(tile->xdp.if_virt)==IF_NAMESIZE, str_bounds );
     222           0 :   fd_cstr_ncpy( tile->xdp.if_virt, net_cfg->interface, IF_NAMESIZE );
     223           0 :   tile->net.bind_address = net_cfg->bind_address_parsed;
     224             : 
     225           0 :   FD_STATIC_ASSERT( sizeof(tile->xdp.if_phys)==IF_NAMESIZE, str_bounds );
     226           0 :   fd_cstr_ncpy( tile->xdp.if_phys, if_phys, IF_NAMESIZE );
     227           0 :   tile->xdp.if_queue = (uint)if_queue;
     228             : 
     229           0 :   tile->xdp.tx_flush_timeout_ns = (long)net_cfg->xdp.flush_timeout_micros * 1000L;
     230           0 :   tile->xdp.xdp_rx_queue_size   = net_cfg->xdp.xdp_rx_queue_size;
     231           0 :   tile->xdp.xdp_tx_queue_size   = net_cfg->xdp.xdp_tx_queue_size;
     232           0 :   tile->xdp.zero_copy           = net_cfg->xdp.xdp_zero_copy;
     233           0 :   fd_cstr_ncpy( tile->xdp.xdp_mode, net_cfg->xdp.xdp_mode, sizeof(tile->xdp.xdp_mode) );
     234             : 
     235           0 :   fd_cstr_ncpy( tile->xdp.poll_mode, net_cfg->xdp.poll_mode, sizeof(tile->xdp.poll_mode) );
     236             : 
     237           0 :   tile->xdp.net.umem_dcache_obj_id = umem_obj->id;
     238           0 :   tile->xdp.netdev_tbl_obj_id      = netlink_tile->netlink.netdev_tbl_obj_id;
     239           0 :   tile->xdp.route_max              = route_max;
     240           0 :   tile->xdp.route_peer_max         = route_peer_max;
     241           0 :   tile->xdp.route_peer_seed        = 1UL + tile_kind_id;
     242           0 :   tile->xdp.neigh4_obj_id          = netlink_tile->netlink.neigh4_obj_id;
     243             : 
     244             :   /* Allocate free ring */
     245             : 
     246           0 :   tile->xdp.free_ring_depth = tile->xdp.xdp_tx_queue_size;
     247           0 : }
     248             : 
     249             : static void
     250             : setup_sock_tile( fd_topo_t *             topo,
     251             :                  ulong const *           tile_to_cpu,
     252           0 :                  fd_config_net_t const * net_cfg ) {
     253           0 :   fd_topo_tile_t * tile = fd_topob_tile( topo, "sock", "sock", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
     254           0 :   tile->sock.net.bind_address = net_cfg->bind_address_parsed;
     255             : 
     256           0 :   if( FD_UNLIKELY( net_cfg->socket.receive_buffer_size>INT_MAX ) ) FD_LOG_ERR(( "invalid [net.socket.receive_buffer_size]" ));
     257           0 :   if( FD_UNLIKELY( net_cfg->socket.send_buffer_size   >INT_MAX ) ) FD_LOG_ERR(( "invalid [net.socket.send_buffer_size]" ));
     258           0 :   tile->sock.so_rcvbuf = (int)net_cfg->socket.receive_buffer_size;
     259           0 :   tile->sock.so_sndbuf = (int)net_cfg->socket.send_buffer_size   ;
     260           0 : }
     261             : 
     262             : void
     263             : fd_topos_net_tiles( fd_topo_t *             topo,
     264             :                     ulong                   net_tile_cnt,
     265             :                     fd_config_net_t const * net_cfg,
     266             :                     ulong                   netlnk_max_routes,
     267             :                     ulong                   netlnk_max_peer_routes,
     268             :                     ulong                   netlnk_max_neighbors,
     269           0 :                     ulong const             tile_to_cpu[ FD_TILE_MAX ] ) {
     270             :   /* net_umem: Packet buffers */
     271           0 :   fd_topob_wksp( topo, "net_umem" );
     272             : 
     273           0 :   fd_pod_insert_cstr( topo->props, "net.provider",  net_cfg->provider );
     274             : 
     275             :   /* Create workspaces */
     276             : 
     277           0 :   if( 0==strcmp( net_cfg->provider, "xdp" ) ) {
     278             : 
     279             :     /* net: private working memory of the net tiles */
     280           0 :     fd_topob_wksp( topo, "net" );
     281             :     /* netlnk: private working memory of the netlnk tile */
     282           0 :     fd_topob_wksp( topo, "netlnk" );
     283             :     /* netbase: shared network config (config plane) */
     284           0 :     fd_topob_wksp( topo, "netbase" );
     285             :     /* net_netlnk: net->netlnk ARP requests */
     286           0 :     fd_topob_wksp( topo, "net_netlnk" );
     287           0 :     fd_topob_wksp( topo, "iproute" );
     288             : 
     289           0 :     fd_topo_tile_t * netlink_tile = fd_topob_tile( topo, "netlnk", "netlnk", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 1 );
     290             :     /* A dump is emitted synchronously.  Keep room for one complete dump in
     291             :        addition to an already outstanding complete dump. */
     292           0 :     ulong iproute_depth = fd_ulong_pow2_up( 4UL*(netlnk_max_routes+netlnk_max_peer_routes)+8UL );
     293           0 :     fd_topob_link( topo, "iproute_out", "iproute", iproute_depth, sizeof(fd_iproute_msg_t), 1UL );
     294           0 :     fd_topob_tile_out( topo, "netlnk", 0UL, "iproute_out", 0UL );
     295           0 :     fd_netlink_topo_create( netlink_tile, topo, netlnk_max_routes, netlnk_max_peer_routes, netlnk_max_neighbors, net_cfg->interface );
     296             : 
     297             :     /* Enumerate network devices to attach to */
     298           0 :     uint devices[ FD_NET_BOND_SLAVE_MAX ] = {0};
     299           0 :     uint device_cnt = 1U;
     300           0 :     if( net_cfg->xdp.native_bond && fd_bonding_is_master( net_cfg->interface ) ) {
     301           0 :       fd_bonding_slave_iter_t iter_[1];
     302           0 :       fd_bonding_slave_iter_t * iter = fd_bonding_slave_iter_init( iter_, net_cfg->interface );
     303           0 :       uint slave_cnt;
     304           0 :       for( slave_cnt=0U;
     305           0 :            /*         */ !fd_bonding_slave_iter_done( iter );
     306           0 :            slave_cnt++,  fd_bonding_slave_iter_next( iter ) ) {
     307           0 :         if( FD_UNLIKELY( slave_cnt>=FD_NET_BOND_SLAVE_MAX ) ) {
     308           0 :           FD_LOG_ERR(( "bond interface %s has too many slave devices; max is %u (see [net.xdp.native_bond])",
     309           0 :                        net_cfg->interface, FD_NET_BOND_SLAVE_MAX ));
     310           0 :         }
     311           0 :         uint if_idx = if_nametoindex( fd_bonding_slave_iter_ele( iter ) );
     312           0 :         if( FD_UNLIKELY( !if_idx ) ) FD_LOG_ERR(( "if_nametoindex(%s) failed", fd_bonding_slave_iter_ele( iter ) ));
     313           0 :         devices[ slave_cnt ] = if_idx;
     314           0 :       }
     315           0 :       if( slave_cnt==0 ) {
     316           0 :         FD_LOG_ERR(( "no bond slave devices detected on interface %s (see [net.xdp.native_bond])", net_cfg->interface ));
     317           0 :       }
     318           0 :       device_cnt = (uint)slave_cnt;
     319           0 :     } else {
     320           0 :       devices[ 0 ] = if_nametoindex( net_cfg->interface );
     321           0 :       if( FD_UNLIKELY( !devices[ 0 ] ) ) FD_LOG_ERR(( "unsupported [net.interface]: `%s`", net_cfg->interface ));
     322           0 :       device_cnt = 1U;
     323           0 :     }
     324             : 
     325             :     /* Verify that net_tile_cnt is a multiple of device_cnt */
     326           0 :     if( FD_UNLIKELY( net_tile_cnt%device_cnt!=0 ) ) {
     327           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 ));
     328           0 :     }
     329           0 :     uint dev_queue_cnt = (uint)net_tile_cnt/device_cnt;
     330             : 
     331             :     /* Assign XDP tiles to device queues */
     332           0 :     ulong tile_kind_id = 0UL;
     333           0 :     for( uint i=0UL; i<device_cnt; i++ ) {
     334           0 :       char if_name[ IF_NAMESIZE ];
     335           0 :       if( FD_UNLIKELY( !if_indextoname( devices[ i ], if_name ) ) ) {
     336           0 :         FD_LOG_ERR(( "error initializing network stack: if_indextoname(%u) failed (try disabling [net.xdp.native_bond]?)", i ));
     337           0 :       }
     338           0 :       for( ulong j=0UL; j<dev_queue_cnt; j++ ) {
     339           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 );
     340           0 :       }
     341           0 :     }
     342           0 :     FD_TEST( tile_kind_id==net_tile_cnt );
     343             : 
     344           0 :   } else if( 0==strcmp( net_cfg->provider, "socket" ) ) {
     345             : 
     346             :     /* sock: private working memory of the sock tiles */
     347           0 :     fd_topob_wksp( topo, "sock" );
     348             : 
     349           0 :     for( ulong i=0UL; i<net_tile_cnt; i++ ) {
     350           0 :       setup_sock_tile( topo, tile_to_cpu, net_cfg );
     351           0 :     }
     352           0 :   } else if( 0==strcmp( net_cfg->provider, "mlx5" ) ) {
     353             : 
     354             :     /* mlx5: private working memory of the mlx5 tiles */
     355           0 :     fd_topob_wksp( topo, "mlx5" );
     356             :     /* netlnk: private working memory of the netlnk tile */
     357           0 :     fd_topob_wksp( topo, "netlnk" );
     358             :     /* netbase: shared network config (config plane) */
     359           0 :     fd_topob_wksp( topo, "netbase" );
     360             :     /* net_netlnk: net->netlnk ARP requests */
     361           0 :     fd_topob_wksp( topo, "net_netlnk" );
     362           0 :     fd_topob_wksp( topo, "iproute" );
     363             : 
     364           0 :     fd_topo_tile_t * netlink_tile = fd_topob_tile( topo, "netlnk", "netlnk", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 1 );
     365           0 :     ulong iproute_depth = fd_ulong_pow2_up( 4UL*(netlnk_max_routes+netlnk_max_peer_routes)+8UL );
     366           0 :     fd_topob_link( topo, "iproute_out", "iproute", iproute_depth, sizeof(fd_iproute_msg_t), 1UL );
     367           0 :     fd_topob_tile_out( topo, "netlnk", 0UL, "iproute_out", 0UL );
     368           0 :     fd_netlink_topo_create( netlink_tile, topo, netlnk_max_routes, netlnk_max_peer_routes, netlnk_max_neighbors, net_cfg->interface );
     369             : 
     370           0 :     for( ulong i=0UL; i<net_tile_cnt; i++ ) {
     371           0 :       setup_mlx5_tile( topo, i, netlink_tile, tile_to_cpu, net_cfg, netlnk_max_routes, netlnk_max_peer_routes );
     372           0 :     }
     373             : 
     374           0 :   } else if( 0==strcmp( net_cfg->provider, "iavf" ) ) {
     375             : 
     376             :     /* iavf: private working memory of the iavf tiles */
     377           0 :     fd_topob_wksp( topo, "iavf" );
     378             :     /* netlnk: private working memory of the netlnk tile */
     379           0 :     fd_topob_wksp( topo, "netlnk" );
     380             :     /* netbase: shared network config (config plane) */
     381           0 :     fd_topob_wksp( topo, "netbase" );
     382             :     /* net_netlnk: net->netlnk ARP requests */
     383           0 :     fd_topob_wksp( topo, "net_netlnk" );
     384           0 :     fd_topob_wksp( topo, "iproute" );
     385             : 
     386           0 :     fd_topo_tile_t * netlink_tile = fd_topob_tile( topo, "netlnk", "netlnk", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 1 );
     387           0 :     ulong iproute_depth = fd_ulong_pow2_up( 4UL*(netlnk_max_routes+netlnk_max_peer_routes)+8UL );
     388           0 :     fd_topob_link( topo, "iproute_out", "iproute", iproute_depth, sizeof(fd_iproute_msg_t), 1UL );
     389           0 :     fd_topob_tile_out( topo, "netlnk", 0UL, "iproute_out", 0UL );
     390           0 :     fd_netlink_topo_create( netlink_tile, topo, netlnk_max_routes, netlnk_max_peer_routes, netlnk_max_neighbors, net_cfg->interface );
     391             : 
     392           0 :     if( FD_UNLIKELY( 0==net_tile_cnt || net_tile_cnt>FD_IAVF_TILE_MAX ) ) {
     393           0 :       FD_LOG_ERR(( "IAVF net tile count %lu must be in [1,%lu]", net_tile_cnt, FD_IAVF_TILE_MAX ));
     394           0 :     }
     395           0 :     for( ulong i=0UL; i<net_tile_cnt; i++ ) {
     396           0 :       setup_iavf_tile( topo, i, netlink_tile, tile_to_cpu, net_cfg, netlnk_max_routes, netlnk_max_peer_routes );
     397           0 :     }
     398             : 
     399           0 :   } else {
     400           0 :     FD_LOG_ERR(( "invalid `net.provider`" ));
     401           0 :   }
     402           0 : }
     403             : 
     404             : static void
     405             : add_umem_rx_link( fd_topo_t *  topo,
     406             :                   char const * link_name,
     407             :                   ulong        net_kind_id,
     408             :                   ulong        depth,
     409           0 :                   ulong        burst ) {
     410           0 :   if( FD_UNLIKELY( !topo || !link_name  ) ) FD_LOG_ERR(( "NULL args" ));
     411           0 :   if( FD_UNLIKELY( strlen( link_name )>=sizeof(topo->links[ topo->link_cnt ].name ) ) ) FD_LOG_ERR(( "link name too long: %s", link_name ));
     412           0 :   if( FD_UNLIKELY( topo->link_cnt>=FD_TOPO_MAX_LINKS ) ) FD_LOG_ERR(( "too many links" ));
     413             : 
     414           0 :   ulong kind_id = 0UL;
     415           0 :   for( ulong i=0UL; i<topo->link_cnt; i++ ) {
     416           0 :     if( !strcmp( topo->links[ i ].name, link_name ) ) kind_id++;
     417           0 :   }
     418             : 
     419           0 :   fd_topo_link_t * link = &topo->links[ topo->link_cnt ];
     420           0 :   strncpy( link->name, link_name, sizeof(link->name) );
     421           0 :   link->id       = topo->link_cnt;
     422           0 :   link->kind_id  = kind_id;
     423           0 :   link->depth    = depth;
     424           0 :   link->mtu      = FD_NET_MTU;
     425           0 :   link->burst    = burst;
     426             : 
     427           0 :   fd_topo_obj_t * obj = fd_topob_obj( topo, "mcache", "net_umem" );
     428           0 :   link->mcache_obj_id = obj->id;
     429           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, depth, "obj.%lu.depth", obj->id ) );
     430             : 
     431           0 :   link->dcache_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "net.%lu.umem", net_kind_id );
     432           0 :   if( FD_UNLIKELY( link->dcache_obj_id==ULONG_MAX ) ) FD_LOG_ERR(( "umem dcache not found for net %lu", net_kind_id ));
     433             : 
     434           0 :   topo->link_cnt++;
     435           0 : }
     436             : 
     437             : void
     438             : fd_topos_net_rx_link( fd_topo_t *  topo,
     439             :                       char const * link_name,
     440             :                       ulong        net_kind_id,
     441           0 :                       ulong        depth ) {
     442           0 :   char const * provider = fd_pod_query_cstr( topo->props, "net.provider", "" );
     443           0 :   if( 0==strcmp( provider, "xdp" ) ) {
     444           0 :     add_umem_rx_link( topo, link_name, net_kind_id, depth, 0UL );
     445           0 :     fd_topob_tile_out( topo, "net", net_kind_id, link_name, net_kind_id );
     446           0 :   } else if( 0==strcmp( provider, "mlx5" ) ) {
     447           0 :     ulong tile_id = fd_topo_find_tile( topo, "mlx5", net_kind_id );
     448           0 :     if( FD_UNLIKELY( tile_id==ULONG_MAX ) ) FD_LOG_ERR(( "tile mlx5:%lu not found", net_kind_id ));
     449           0 :     add_umem_rx_link( topo, link_name, net_kind_id, depth, topo->tiles[ tile_id ].mlx5.batch_size );
     450           0 :     fd_topob_tile_out( topo, "mlx5", net_kind_id, link_name, net_kind_id );
     451           0 :   } else if( 0==strcmp( provider, "iavf" ) ) {
     452           0 :     ulong tile_id = fd_topo_find_tile( topo, "iavf", net_kind_id );
     453           0 :     if( FD_UNLIKELY( tile_id==ULONG_MAX ) ) FD_LOG_ERR(( "tile iavf:%lu not found", net_kind_id ));
     454           0 :     add_umem_rx_link( topo, link_name, net_kind_id, depth, topo->tiles[ tile_id ].iavf.member_cnt*FD_IAVF_BATCH_SIZE );
     455           0 :     fd_topob_tile_out( topo, "iavf", net_kind_id, link_name, net_kind_id );
     456           0 :   } else if( 0==strcmp( provider, "socket" ) ) {
     457           0 :     fd_topob_link( topo, link_name, "net_umem", depth, FD_NET_MTU, 64 );
     458           0 :     fd_topob_tile_out( topo, "sock", net_kind_id, link_name, net_kind_id );
     459           0 :   }
     460           0 : }
     461             : 
     462             : void
     463             : fd_topos_tile_in_net( fd_topo_t *  topo,
     464             :                       char const * fseq_wksp,
     465             :                       char const * link_name,
     466             :                       ulong        link_kind_id,
     467             :                       int          reliable,
     468           0 :                       int          polled ) {
     469           0 :   for( ulong j=0UL; j<(topo->tile_cnt); j++ ) {
     470           0 :     if( 0==strcmp( topo->tiles[ j ].name, "net"   ) ||
     471           0 :         0==strcmp( topo->tiles[ j ].name, "sock"  ) ||
     472           0 :         0==strcmp( topo->tiles[ j ].name, "mlx5" ) ||
     473           0 :         0==strcmp( topo->tiles[ j ].name, "iavf" ) ) {
     474           0 :       fd_topob_tile_in( topo, topo->tiles[ j ].name, topo->tiles[ j ].kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled );
     475           0 :     }
     476           0 :   }
     477           0 : }
     478             : 
     479             : static void
     480             : fd_topos_xdp_setup_mem( fd_topo_t *      topo,
     481           0 :                         fd_topo_tile_t * net_tile ) {
     482           0 :   ulong rx_depth = net_tile->xdp.xdp_rx_queue_size;
     483           0 :   ulong tx_depth = net_tile->xdp.xdp_tx_queue_size;
     484           0 :   rx_depth += (rx_depth/2UL);
     485           0 :   tx_depth += (tx_depth/2UL);
     486             : 
     487           0 :   if( net_tile->kind_id==0 ) {
     488             :     /* Double it for loopback XSK */
     489           0 :     rx_depth *= 2UL;
     490           0 :     tx_depth *= 2UL;
     491           0 :   }
     492             : 
     493           0 :   ulong cum_frame_cnt = rx_depth + tx_depth;
     494             : 
     495             :   /* Count up the depth of all RX mcaches */
     496             : 
     497           0 :   for( ulong j=0UL; j<(net_tile->out_cnt); j++ ) {
     498           0 :     ulong link_id       = net_tile->out_link_id[ j ];
     499           0 :     ulong mcache_obj_id = topo->links[ link_id ].mcache_obj_id;
     500           0 :     ulong depth = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "obj.%lu.depth", mcache_obj_id );
     501           0 :     if( FD_UNLIKELY( depth==ULONG_MAX ) ) FD_LOG_ERR(( "Didn't find depth for mcache %s", topo->links[ link_id ].name ));
     502           0 :     cum_frame_cnt += depth + 1UL;
     503           0 :   }
     504             : 
     505             :   /* Create a dcache object */
     506             : 
     507           0 :   ulong umem_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "net.%lu.umem", net_tile->kind_id );
     508           0 :   FD_TEST( umem_obj_id!=ULONG_MAX );
     509             : 
     510           0 :   FD_TEST( net_tile->net.umem_dcache_obj_id > 0 );
     511           0 :   fd_pod_insertf_ulong( topo->props, cum_frame_cnt, "obj.%lu.depth", umem_obj_id );
     512           0 :   fd_pod_insertf_ulong( topo->props, 2UL,           "obj.%lu.burst", umem_obj_id ); /* 4096 byte padding */
     513           0 :   fd_pod_insertf_ulong( topo->props, 2048UL,        "obj.%lu.mtu",   umem_obj_id );
     514           0 : }
     515             : 
     516             : void
     517             : fd_topo_install_xdp( fd_topo_t const * topo,
     518             :                      fd_xdp_fds_t *    fds,
     519             :                      uint *            fds_cnt,
     520             :                      uint              bind_addr,
     521           0 :                      int               dry_run ) {
     522           0 :   uint fds_max = *fds_cnt;
     523           0 :   memset( fds, 0, fds_max*sizeof(fd_xdp_fds_t) );
     524             : 
     525           0 :   uint if_cnt = 0U;
     526           0 : # define ADD_IF_IDX( idx_ ) do {                      \
     527           0 :     uint idx = (idx_);                                \
     528           0 :     int found = 0;                                    \
     529           0 :     for( uint i=0U; i<if_cnt; i++ ) {                 \
     530           0 :       if( fds[ i ].if_idx==idx ) {                    \
     531           0 :         found = 1;                                    \
     532           0 :         break;                                        \
     533           0 :       }                                               \
     534           0 :     }                                                 \
     535           0 :     if( !found ) {                                    \
     536           0 :       FD_TEST( if_cnt<FD_NET_BOND_SLAVE_MAX+1 );      \
     537           0 :       fds[ if_cnt++ ].if_idx = idx;                   \
     538           0 :     }                                                 \
     539           0 :   } while(0)
     540             : 
     541             :   /* Create a list of unique fds */
     542             : 
     543           0 :   ulong net_tile_cnt = fd_topo_tile_name_cnt( topo, "net" );
     544           0 :   for( ulong tile_kind_id=0UL; tile_kind_id<net_tile_cnt; tile_kind_id++ ) {
     545           0 :     ulong net_tile_id = fd_topo_find_tile( topo, "net", tile_kind_id );
     546           0 :     FD_TEST( net_tile_id!=ULONG_MAX );
     547           0 :     fd_topo_tile_t const * tile = &topo->tiles[ net_tile_id ];
     548           0 :     uint if_idx = if_nametoindex( tile->xdp.if_phys ); FD_TEST( if_idx );
     549           0 :     ADD_IF_IDX( if_idx );
     550           0 :   }
     551             : 
     552             :   /* Add loopback unless found */
     553             : 
     554           0 :   uint lo_idx = if_nametoindex( "lo" ); FD_TEST( lo_idx );
     555           0 :   ADD_IF_IDX( lo_idx );
     556             : 
     557             :   /* Done with config discovery */
     558             : 
     559           0 :   *fds_cnt = if_cnt;
     560           0 :   int next_fd = 123462;
     561           0 :   for( uint i=0U; i<if_cnt; i++ ) {
     562           0 :     fds[ i ].xsk_map_fd   = next_fd++;
     563           0 :     fds[ i ].prog_link_fd = next_fd++;
     564           0 :   }
     565           0 :   if( dry_run ) return;
     566             : 
     567             :   /* Install */
     568             : 
     569           0 :   ulong net0_tile_idx = fd_topo_find_tile( topo, "net", 0UL );
     570           0 :   FD_TEST( net0_tile_idx!=ULONG_MAX );
     571           0 :   fd_topo_tile_t const * net0_tile = &topo->tiles[ net0_tile_idx ];
     572             : 
     573             :   /* Get UDP ports to listen on */
     574           0 :   fd_net_rx_dest_t rx_dests[ FD_NET_RX_DEST_CNT ];
     575           0 :   fd_net_rx_dest_list( rx_dests, &net0_tile->net );
     576           0 :   ushort udp_port_candidates[ FD_NET_RX_DEST_CNT ];
     577           0 :   for( ulong i=0UL; i<FD_NET_RX_DEST_CNT; i++ ) udp_port_candidates[ i ] = rx_dests[ i ].listen_port;
     578             : 
     579           0 :   for( uint i=0U; i<if_cnt; i++ ) {
     580             :     /* Override XDP mode for loopback */
     581           0 :     char const * xdp_mode = net0_tile->xdp.xdp_mode;
     582           0 :     if( fds[ i ].if_idx==1U ) xdp_mode = "skb";
     583             : 
     584           0 :     fd_xdp_fds_t xdp_fds = fd_xdp_install(
     585           0 :         fds[ i ].if_idx,
     586           0 :         bind_addr,
     587           0 :         FD_NET_RX_DEST_CNT,
     588           0 :         udp_port_candidates,
     589           0 :         xdp_mode );
     590           0 :     if( FD_UNLIKELY( -1==dup2( xdp_fds.xsk_map_fd, fds[ i ].xsk_map_fd ) ) ) {
     591           0 :       FD_LOG_ERR(( "dup2() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     592           0 :     }
     593           0 :     if( FD_UNLIKELY( -1==close( xdp_fds.xsk_map_fd ) ) ) {
     594           0 :       FD_LOG_ERR(( "close() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     595           0 :     }
     596           0 :     if( FD_UNLIKELY( -1==dup2( xdp_fds.prog_link_fd, fds[ i ].prog_link_fd ) ) ) {
     597           0 :       FD_LOG_ERR(( "dup2() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     598           0 :     }
     599           0 :     if( FD_UNLIKELY( -1==close( xdp_fds.prog_link_fd ) ) ) {
     600           0 :       FD_LOG_ERR(( "close() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     601           0 :     }
     602           0 :   }
     603           0 : }
     604             : 
     605             : # undef ADD_IF_IDX
     606             : 
     607             : void
     608             : fd_topos_sock_lo( fd_topo_t *            topo,
     609           0 :                   fd_topo_tile_t const * net_tile ) {
     610           0 :   fd_topob_wksp( topo, "sock" );
     611           0 :   fd_topo_tile_t * sock = fd_topob_tile( topo, "sock", "sock", "metric_in", ULONG_MAX, 0, 0, 0 );
     612           0 :   sock->net = net_tile->net;
     613           0 :   sock->sock.only_recv_lo = 1;
     614           0 :   sock->sock.so_rcvbuf    = 32*1024*1024;
     615           0 :   sock->sock.net_tile_id  = net_tile->id;
     616             : 
     617           0 :   for( ulong i=0UL; i<net_tile->out_cnt; i++ ) {
     618           0 :     fd_topo_link_t const * net_out_link = &topo->links[ net_tile->out_link_id[ i ] ];
     619             : 
     620             :     /* Which links of net to duplicate */
     621           0 :     if( 0!=strncmp( net_out_link->name, "net_", 4UL ) || 0==strcmp( net_out_link->name, "net_netlnk" ) ) continue;
     622             : 
     623             :     /* Duplicate link */
     624           0 :     fd_topo_link_t * sock_out_link = fd_topob_link( topo, net_out_link->name, "sock", 4096UL, FD_NET_MTU, 64UL );
     625           0 :     fd_topob_tile_out( topo, "sock", sock->kind_id, sock_out_link->name, sock_out_link->kind_id );
     626             : 
     627             :     /* Loop through all tiles, check their in links for net */
     628           0 :     for( ulong j=0UL; j<topo->tile_cnt; j++ ) {
     629           0 :       fd_topo_tile_t * consumer = &topo->tiles[ j ];
     630           0 :       ulong const in_cnt = consumer->in_cnt;
     631           0 :       for( ulong k=0UL; k<in_cnt; k++ ) {
     632           0 :         if( consumer->in_link_id[ k ]!=net_out_link->id ) continue;
     633             : 
     634             :         /* Add as sock link consumer */
     635           0 :         char const * fseq_wksp = topo->workspaces[ topo->objs[ consumer->in_link_fseq_obj_id[ k ] ].wksp_id ].name;
     636           0 :         fd_topob_tile_in( topo, consumer->name, consumer->kind_id, fseq_wksp, sock_out_link->name, sock_out_link->kind_id,
     637           0 :                           consumer->in_link_reliable[ k ], consumer->in_link_poll[ k ] );
     638           0 :       }
     639           0 :     }
     640           0 :   }
     641           0 : }
     642             : 
     643             : ulong
     644           0 : sock_lo_net_tile_id( fd_topo_tile_t const * tile ) {
     645           0 :   if( 0==strcmp( tile->name, "sock" ) && tile->sock.only_recv_lo ) return tile->sock.net_tile_id;
     646           0 :   return ULONG_MAX;
     647           0 : }
     648             : 
     649             : void
     650           0 : sock_lo_set_affinity( fd_topo_t * topo ) {
     651           0 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     652           0 :     fd_topo_tile_t * tile = &topo->tiles[ i ];
     653           0 :     ulong net_tile_id = sock_lo_net_tile_id( tile );
     654           0 :     if( net_tile_id==ULONG_MAX ) continue;
     655           0 :     FD_TEST( net_tile_id<topo->tile_cnt );
     656           0 :     fd_topo_tile_t const * net_tile = &topo->tiles[ net_tile_id ];
     657           0 :     tile->cpu_idx = net_tile->cpu_idx;
     658           0 :     tile->floats  = net_tile->floats;
     659           0 :   }
     660           0 : }
     661             : 
     662             : static void
     663             : fd_topos_mlx5_setup_mem( fd_topo_t *      topo,
     664           0 :                          fd_topo_tile_t * mlx5_tile ) {
     665           0 :   ulong cum_frame_cnt = 0UL;
     666             : 
     667           0 :   ulong const rx_depth = mlx5_tile->mlx5.rx_queue_size;
     668           0 :   ulong const tx_depth = mlx5_tile->mlx5.tx_queue_size;
     669           0 :   cum_frame_cnt += rx_depth + tx_depth;
     670             : 
     671             :   /* Count up the depth of all RX mcaches */
     672             : 
     673           0 :   for( ulong j=0UL; j<(mlx5_tile->out_cnt); j++ ) {
     674           0 :     ulong link_id       = mlx5_tile->out_link_id[ j ];
     675           0 :     ulong mcache_obj_id = topo->links[ link_id ].mcache_obj_id;
     676           0 :     ulong depth = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "obj.%lu.depth", mcache_obj_id );
     677           0 :     if( FD_UNLIKELY( depth==ULONG_MAX ) ) FD_LOG_ERR(( "Didn't find depth for mcache %s", topo->links[ link_id ].name ));
     678           0 :     cum_frame_cnt += depth + 1UL;
     679           0 :   }
     680             : 
     681             :   /* Create a dcache object */
     682             : 
     683           0 :   ulong umem_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "net.%lu.umem", mlx5_tile->kind_id );
     684           0 :   FD_TEST( umem_obj_id!=ULONG_MAX );
     685             : 
     686           0 :   FD_TEST( mlx5_tile->net.umem_dcache_obj_id > 0 );
     687           0 :   fd_pod_insertf_ulong( topo->props, cum_frame_cnt, "obj.%lu.depth", umem_obj_id );
     688           0 :   fd_pod_insertf_ulong( topo->props, 2UL,           "obj.%lu.burst", umem_obj_id ); /* 4096 byte padding */
     689           0 :   fd_pod_insertf_ulong( topo->props, FD_NET_MTU,    "obj.%lu.mtu",   umem_obj_id );
     690           0 : }
     691             : 
     692             : static void
     693             : fd_topos_iavf_setup_mem( fd_topo_t *      topo,
     694           0 :                          fd_topo_tile_t * iavf_tile ) {
     695           0 :   ulong cum_frame_cnt = 0UL;
     696             : 
     697           0 :   ulong const rx_depth = iavf_tile->iavf.rx_queue_size;
     698           0 :   ulong const tx_depth = iavf_tile->iavf.tx_queue_size;
     699           0 :   cum_frame_cnt += iavf_tile->iavf.member_cnt*(rx_depth + tx_depth);
     700             : 
     701             :   /* Count up the depth of all RX mcaches */
     702             : 
     703           0 :   for( ulong j=0UL; j<(iavf_tile->out_cnt); j++ ) {
     704           0 :     ulong link_id       = iavf_tile->out_link_id[ j ];
     705           0 :     ulong mcache_obj_id = topo->links[ link_id ].mcache_obj_id;
     706           0 :     ulong depth = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "obj.%lu.depth", mcache_obj_id );
     707           0 :     if( FD_UNLIKELY( depth==ULONG_MAX ) ) FD_LOG_ERR(( "Didn't find depth for mcache %s", topo->links[ link_id ].name ));
     708           0 :     cum_frame_cnt += depth + 1UL;
     709           0 :   }
     710             : 
     711             :   /* Create a dcache object */
     712             : 
     713           0 :   ulong umem_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "net.%lu.umem", iavf_tile->kind_id );
     714           0 :   FD_TEST( umem_obj_id!=ULONG_MAX );
     715             : 
     716           0 :   FD_TEST( iavf_tile->net.umem_dcache_obj_id > 0 );
     717           0 :   fd_pod_insertf_ulong( topo->props, cum_frame_cnt, "obj.%lu.depth", umem_obj_id );
     718           0 :   fd_pod_insertf_ulong( topo->props, 2UL,           "obj.%lu.burst", umem_obj_id ); /* 4096 byte padding */
     719           0 :   fd_pod_insertf_ulong( topo->props, FD_NET_MTU,    "obj.%lu.mtu",   umem_obj_id );
     720           0 : }
     721             : 
     722             : void
     723             : fd_topos_net_tile_finish( fd_topo_t * topo,
     724           0 :                           ulong       net_kind_id ) {
     725           0 :   char const * provider = fd_pod_query_cstr( topo->props, "net.provider", "" );
     726           0 :   if( 0==strcmp( provider, "xdp" ) ) {
     727           0 :     ulong tile_id = fd_topo_find_tile( topo, "net", net_kind_id );
     728           0 :     if( FD_UNLIKELY( tile_id==ULONG_MAX ) ) {
     729           0 :       FD_LOG_ERR(( "tile net:%lu not found", net_kind_id ));
     730           0 :     }
     731           0 :     fd_topos_xdp_setup_mem( topo, &topo->tiles[ tile_id ] );
     732           0 :   } else if( 0==strcmp( provider, "mlx5" ) ) {
     733           0 :     ulong tile_id = fd_topo_find_tile( topo, "mlx5", net_kind_id );
     734           0 :     if( FD_UNLIKELY( tile_id==ULONG_MAX ) ) {
     735           0 :       FD_LOG_ERR(( "tile mlx5:%lu not found", net_kind_id ));
     736           0 :     }
     737           0 :     fd_topos_mlx5_setup_mem( topo, &topo->tiles[ tile_id ] );
     738           0 :   } else if( 0==strcmp( provider, "iavf" ) ) {
     739           0 :     ulong tile_id = fd_topo_find_tile( topo, "iavf", net_kind_id );
     740           0 :     if( FD_UNLIKELY( tile_id==ULONG_MAX ) ) {
     741           0 :       FD_LOG_ERR(( "tile iavf:%lu not found", net_kind_id ));
     742           0 :     }
     743           0 :     fd_topos_iavf_setup_mem( topo, &topo->tiles[ tile_id ] );
     744           0 :   } else {
     745           0 :     return;
     746           0 :   }
     747           0 : }

Generated by: LCOV version 1.14