LCOV - code coverage report
Current view: top level - app/shared - fd_config_auto.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 248 278 89.2 %
Date: 2026-09-17 04:28:31 Functions: 40 59 67.8 %

          Line data    Source code
       1             : #include "fd_config_auto.h"
       2             : #include "../../disco/net/fd_linux_bond.h"
       3             : #include "../../disco/net/fd_net_tile.h"
       4             : #include "../../disco/net/mlx5/fd_mlx5.h"
       5             : #include "../../disco/netlink/fd_netlink_tile.h"
       6             : #include "../../waltz/mib/fd_netdev_netlink.h"
       7             : 
       8             : #include <stdlib.h> /* strtoul */
       9             : #include <limits.h>
      10             : #include <errno.h>
      11             : #include <string.h>
      12             : #include <unistd.h>
      13             : #include <sys/utsname.h>
      14             : #include <linux/if_arp.h>
      15             : 
      16         162 : #define PROVIDER_CNT       ( 2UL)
      17         432 : #define FEAT_CNT_MAX       (16UL)
      18         333 : #define NET_DRIVER_CNT_MAX (16UL)
      19             : 
      20             : struct fd_auto_info {
      21             :   /* System */
      22             :   ulong linux_major;
      23             :   ulong linux_minor;
      24             : 
      25             :   /* Networking */
      26             :   char driver[ NAME_SZ ];
      27             :   uint is_virtual_if:1;
      28             :   uint is_bonded_if:1;
      29             :   uint is_lacp_if:1;
      30             :   uint bonded_if_slave_count;
      31             :   int  is_using_gre;
      32             :   int  has_mlx5_rdma_port;
      33             :   int  has_uverbs;
      34             : };
      35             : typedef struct fd_auto_info fd_auto_info_t;
      36             : 
      37             : struct fd_auto_driver_rq {
      38             :   char const * name;
      39             :   ulong        min_linux_major;
      40             :   ulong        min_linux_minor;
      41             : 
      42             :   /* 0 = no max linux version */
      43             :   ulong        max_linux_major;
      44             :   ulong        max_linux_minor;
      45             : };
      46             : typedef struct fd_auto_driver_rq fd_auto_driver_rq_t;
      47             : 
      48             : struct fd_auto_feat {
      49             :   char const *         name;
      50             :   /* supported_drivers is for unconditional driver requirements.
      51             :      For conditional driver requirements leave this empty and call
      52             :      fd_auto_check_driver() inside the check() callback
      53             :      (like xdp_rss_queue_mode_check() does). */
      54             :   fd_auto_driver_rq_t  supported_drivers[ NET_DRIVER_CNT_MAX ];
      55             : 
      56             :   /* is_feat_auto() checks if feature is auto and sets the default */
      57             :   int  (*is_feat_auto)( fd_config_t          * config );
      58             :   int  (*check       )( fd_config_t    const * config,
      59             :                         fd_auto_info_t const * info   );
      60             :   void (*apply       )( fd_config_t          * config );
      61             : };
      62             : typedef struct fd_auto_feat fd_auto_feat_t;
      63             : 
      64             : struct fd_auto_provider {
      65             :   char const *         name;
      66             :   /* Later features observe earlier features updates to config,
      67             :      so the order is important.  e.g. ZC checks xdp_mode is DRV
      68             :      so DRV needs to come before ZC in the feats ordering. */
      69             :   fd_auto_feat_t       feats            [ FEAT_CNT_MAX ];
      70             :   fd_auto_driver_rq_t  supported_drivers[ NET_DRIVER_CNT_MAX ];
      71             : 
      72             :   int  (*check)( fd_config_t    const * config,
      73             :                  fd_auto_info_t const * info   );
      74             :   void (*apply)( fd_config_t          * config );
      75             : };
      76             : typedef struct fd_auto_provider fd_auto_provider_t;
      77             : 
      78             : static int
      79             : fd_auto_check_driver( fd_auto_info_t      const * info,
      80         273 :                       fd_auto_driver_rq_t const * supported_drivers ) {
      81             :   /* Check for driver requirements. */
      82         273 :   if( !supported_drivers[0].name ) return 1;
      83             : 
      84         333 :   for( ulong i=0UL; i<NET_DRIVER_CNT_MAX; i++ ) {
      85         333 :     fd_auto_driver_rq_t const * req = &supported_drivers[ i ];
      86         333 :     if( !req->name ) return 0;
      87             : 
      88         282 :     if( 0==strcmp( info->driver, req->name ) ) {
      89             :       /* Check system linux version is within bounds of min and max
      90             :          of what this driver req requires. */
      91         186 :       if( req->max_linux_major > 0UL ) {
      92          33 :         if( info->linux_major>req->max_linux_major ||
      93          33 :           ( info->linux_major==req->max_linux_major &&
      94          27 :             info->linux_minor>req->max_linux_minor ) ) continue;
      95          33 :       }
      96             : 
      97         159 :       if( info->linux_major>req->min_linux_major ||
      98         159 :         ( info->linux_major==req->min_linux_major &&
      99         129 :           info->linux_minor>=req->min_linux_minor ) ) return 1;
     100         159 :     }
     101         282 :   }
     102             : 
     103           0 :   return 0;
     104         180 : }
     105             : 
     106             : /* XDP checks/apply */
     107             : 
     108             : static int
     109             : xdp_check( fd_config_t    const * config,
     110          15 :            fd_auto_info_t const * info FD_PARAM_UNUSED ) {
     111          15 :   if( strcmp( config->net.provider, "auto" ) ) return 0;
     112          15 :   return 1;
     113          15 : }
     114             : 
     115             : static void
     116          15 : xdp_apply( fd_config_t * config ) {
     117          15 :   fd_memcpy( config->net.provider, "xdp", 4 );
     118          15 : }
     119             : 
     120             : static int
     121          54 : is_xdp_listen_gre_auto( fd_config_t * config ) {
     122          54 :   if( 2!=config->net.xdp.listen_gre ) return 0;
     123             :   /* Set to default */
     124          51 :   config->net.xdp.listen_gre = 0;
     125          51 :   return 1;
     126          54 : }
     127             : 
     128             : static int
     129             : xdp_listen_gre_check( fd_config_t    const * config FD_PARAM_UNUSED,
     130          39 :                       fd_auto_info_t const * info ) {
     131          39 :   return info->is_using_gre;
     132          39 : }
     133             : 
     134             : static void
     135           6 : xdp_listen_gre_apply( fd_config_t * config ) {
     136           6 :   config->net.xdp.listen_gre = 1;
     137           6 : }
     138             : 
     139             : static int
     140          54 : is_xdp_rss_queue_mode_auto( fd_config_t * config ) {
     141          54 :   if( strcmp( config->net.xdp.rss_queue_mode, "auto" ) ) return 0;
     142             :   /* Set to default */
     143          51 :   fd_memcpy( config->net.xdp.rss_queue_mode, "simple", 7 );
     144          51 :   return 1;
     145          54 : }
     146             : 
     147             : static int
     148             : xdp_rss_queue_mode_check( fd_config_t    const * config,
     149          39 :                           fd_auto_info_t const * info ) {
     150          39 :   if( 1==config->net.xdp.listen_gre ) {
     151           6 :     static fd_auto_driver_rq_t const gre_rss_drivers[ NET_DRIVER_CNT_MAX ] = {
     152           6 :       { "mlx5_core", 0, 0, 0, 0 }
     153           6 :     };
     154             : 
     155           6 :     if( 0==fd_auto_check_driver( info, gre_rss_drivers ) ) return 0;
     156           6 :   }
     157          36 :   return 1;
     158          39 : }
     159             : 
     160             : static void
     161          36 : xdp_rss_queue_mode_apply( fd_config_t * config ) {
     162          36 :   fd_memcpy( config->net.xdp.rss_queue_mode, "auto", 5 );
     163          36 : }
     164             : 
     165             : static int
     166          54 : is_xdp_native_bond_auto( fd_config_t * config ) {
     167          54 :   if( 2!=config->net.xdp.native_bond ) return 0;
     168             :   /* Set to default */
     169          54 :   config->net.xdp.native_bond = 0;
     170          54 :   return 1;
     171          54 : }
     172             : 
     173             : static int
     174             : xdp_native_bond_check( fd_config_t    const * config,
     175          30 :                        fd_auto_info_t const * info ) {
     176          30 :   if( !info->is_bonded_if ) return 0;
     177           6 :   if( !info->is_lacp_if ) return 0;
     178             : 
     179           3 :   if( 0==info->bonded_if_slave_count || info->bonded_if_slave_count>FD_NET_BOND_SLAVE_MAX ) return 0;
     180             : 
     181             :   /* net_tile_count must be a multiple of the bonded interface's slave count */
     182           3 :   if( 0!=config->layout.net_tile_count%info->bonded_if_slave_count ) return 0;
     183             : 
     184           3 :   return 1;
     185           3 : }
     186             : 
     187             : static void
     188           3 : xdp_native_bond_apply( fd_config_t * config ) {
     189           3 :   config->net.xdp.native_bond = 1;
     190           3 : }
     191             : 
     192             : static int
     193          54 : is_xdp_mode_auto( fd_config_t * config ) {
     194          54 :   if( strcmp( config->net.xdp.xdp_mode, "auto" ) ) return 0;
     195             :   /* Set to default */
     196          54 :   fd_memcpy( config->net.xdp.xdp_mode, "skb", 4 );
     197          54 :   return 1;
     198          54 : }
     199             : 
     200             : static int
     201             : xdp_drv_check( fd_config_t    const * config,
     202          30 :                fd_auto_info_t const * info ) {
     203          30 :   if( info->is_virtual_if &&
     204          30 :       !config->net.xdp.native_bond ) return 0;
     205          27 :   return 1;
     206          30 : }
     207             : 
     208             : static void
     209          27 : xdp_drv_apply( fd_config_t * config ) {
     210          27 :   fd_memcpy( config->net.xdp.xdp_mode, "drv", 4 );
     211          27 : }
     212             : 
     213             : static int
     214          54 : is_xdp_prefbusy_auto( fd_config_t * config ) {
     215          54 :   if( strcmp( config->net.xdp.poll_mode, "auto" ) ) return 0;
     216             :   /* Set to default */
     217          54 :   fd_memcpy( config->net.xdp.poll_mode, "softirq", 8 );
     218          54 :   return 1;
     219          54 : }
     220             : 
     221             : static int
     222             : xdp_prefbusy_check( fd_config_t    const * config,
     223          30 :                     fd_auto_info_t const * info FD_PARAM_UNUSED ) {
     224          30 :   if( strcmp( config->net.xdp.xdp_mode, "drv") ) return 0;
     225          27 :   return 1;
     226          30 : }
     227             : 
     228             : static void
     229          27 : xdp_prefbusy_apply( fd_config_t * config ) {
     230          27 :   fd_memcpy( config->net.xdp.poll_mode, "prefbusy", 9 );
     231          27 : }
     232             : 
     233             : static int
     234          54 : is_xdp_zc_auto( fd_config_t * config ) {
     235          54 :   if( 2!=config->net.xdp.xdp_zero_copy ) return 0;
     236             :   /* Set to default */
     237          54 :   config->net.xdp.xdp_zero_copy = 0;
     238          54 :   return 1;
     239          54 : }
     240             : 
     241             : static int
     242             : xdp_zc_check( fd_config_t    const * config,
     243          30 :               fd_auto_info_t const * info   FD_PARAM_UNUSED ) {
     244          30 :   if( strcmp( config->net.xdp.xdp_mode, "drv") ) return 0;
     245          27 :   return 1;
     246          30 : }
     247             : 
     248             : static void
     249          27 : xdp_zc_apply( fd_config_t * config ) {
     250          27 :   config->net.xdp.xdp_zero_copy = 1;
     251          27 : }
     252             : 
     253             : /* mlx5 tile checks/apply */
     254             : static int
     255             : mlx5_check( fd_config_t    const * config,
     256          21 :             fd_auto_info_t const * info ) {
     257          21 :   if( strcmp( config->net.provider, "auto" ) ) return 0;
     258          21 :   if( !info->has_mlx5_rdma_port ) return 0;
     259          12 :   if( !info->has_uverbs ) return 0;
     260           9 :   if( !fd_ulong_is_pow2( config->layout.net_tile_count ) ) return 0;
     261           6 :   return 1;
     262           9 : }
     263             : 
     264             : static void
     265           6 : mlx5_apply( fd_config_t * config ) {
     266           6 :   fd_memcpy( config->net.provider, "mlx5", 5 );
     267           6 : }
     268             : 
     269             : /* Each feature's supported Linux version matrix per driver decided
     270             :    based on fd-linux-version-testbed test results. */
     271             : static const fd_auto_provider_t NET_PROVIDERS[] = {
     272             :   {
     273             :     .name = "mlx5",
     274             :     .supported_drivers = { { "mlx5_core", 5, 14, 0, 0 } },
     275             :     .check = mlx5_check,
     276             :     .apply = mlx5_apply
     277             :   },
     278             :   {
     279             :     .name  = "xdp",
     280             :     .check = xdp_check,
     281             :     .apply = xdp_apply,
     282             :     .feats = {
     283             :       {
     284             :         .name              = "Listen GRE",
     285             :         .is_feat_auto      = is_xdp_listen_gre_auto,
     286             :         .check             = xdp_listen_gre_check,
     287             :         .apply             = xdp_listen_gre_apply
     288             :       },
     289             :       {
     290             :         .name              = "RSS Queue Mode",
     291             :         .is_feat_auto      = is_xdp_rss_queue_mode_auto,
     292             :         .check             = xdp_rss_queue_mode_check,
     293             :         .apply             = xdp_rss_queue_mode_apply
     294             :       },
     295             :       {
     296             :         .name              = "Native Bond",
     297             :         .supported_drivers = {
     298             :           { "mlx5_core", 5, 15, 0, 0 },
     299             :           { "i40e",      5, 15, 0, 0 },
     300             :         },
     301             :         .is_feat_auto      = is_xdp_native_bond_auto,
     302             :         .check             = xdp_native_bond_check,
     303             :         .apply             = xdp_native_bond_apply
     304             :       },
     305             :       {
     306             :         .name              = "DRV",
     307             :         .supported_drivers = {
     308             :           { "mlx5_core", 5, 15, 6, 3 },
     309             :           { "mlx5_core", 6,  5, 0, 0 },
     310             :           { "i40e",      5, 19, 0, 0 }
     311             :         },
     312             :         .is_feat_auto      = is_xdp_mode_auto,
     313             :         .check             = xdp_drv_check,
     314             :         .apply             = xdp_drv_apply,
     315             :       },
     316             :       {
     317             :         .name              = "Prefbusy",
     318             :         .supported_drivers = {
     319             :           { "mlx5_core", 5, 15, 0, 0 },
     320             :           { "i40e",      5, 15, 0, 0 }
     321             :         },
     322             :         .is_feat_auto      = is_xdp_prefbusy_auto,
     323             :         .check             = xdp_prefbusy_check,
     324             :         .apply             = xdp_prefbusy_apply
     325             :       },
     326             :       {
     327             :         .name              = "Zero Copy",
     328             :         .supported_drivers = {
     329             :           { "mlx5_core", 6,  1, 0, 0 },
     330             :           { "i40e",      5, 19, 0, 0 }
     331             :         },
     332             :         .is_feat_auto      = is_xdp_zc_auto,
     333             :         .check             = xdp_zc_check,
     334             :         .apply             = xdp_zc_apply
     335             :       }
     336             :     }
     337             :   }
     338             : };
     339             : 
     340             : static void
     341           3 : scrape_system( fd_auto_info_t * info ) {
     342           3 :   struct utsname utsname;
     343           3 :   if( FD_UNLIKELY( -1==uname( &utsname ) ) ) {
     344           0 :     FD_LOG_WARNING(( "uname() failed (%i-%s), auto config skipping kernel version detection",
     345           0 :                      errno, fd_io_strerror( errno ) ));
     346           0 :     return;
     347           0 :   }
     348             : 
     349             :   /* utsname.release is typically "major.minor.patch-distrojunk",
     350             :      e.g. "6.8.0-45-generic" or "5.14.0-362.8.1.el9_3.x86_64".  We
     351             :      only care about major.minor.  A missing ".minor" is treated as
     352             :      minor 0.  An unparseable release leaves {0,0}, which fails all
     353             :      version requirements (fail-soft). */
     354             : 
     355           3 :   char const * cur = utsname.release;
     356           3 :   char *       end = NULL;
     357             : 
     358           3 :   ulong major = strtoul( cur, &end, 10 );
     359           3 :   if( FD_UNLIKELY( end==cur ) ) {
     360           0 :     FD_LOG_WARNING(( "unrecognized kernel release `%s`, auto config skipping kernel version detection",
     361           0 :                      utsname.release ));
     362           0 :     return;
     363           0 :   }
     364             : 
     365           3 :   ulong minor = 0UL;
     366           3 :   if( FD_LIKELY( end[0]=='.' ) ) {
     367           3 :     cur   = end+1;
     368           3 :     minor = strtoul( cur, &end, 10 );
     369           3 :     if( FD_UNLIKELY( end==cur ) ) minor = 0UL; /* tolerate "6." */
     370           3 :   }
     371             : 
     372           3 :   info->linux_major = major;
     373           3 :   info->linux_minor = minor;
     374           3 : }
     375             : 
     376             : static void
     377             : scrape_driver( char       * driver,
     378           6 :                char const * if_name ) {
     379           6 :   char path[ PATH_MAX ], target[ PATH_MAX ];
     380           6 :   driver[0] = '\0';
     381           6 :   FD_TEST( fd_cstr_printf_check( path, PATH_MAX, NULL, "/sys/class/net/%s/device/driver", if_name ) );
     382             : 
     383           6 :   long n = readlink( path, target, PATH_MAX-1 );
     384           6 :   if( FD_UNLIKELY( n<0L ) ) return;
     385           6 :   target[ n ] = '\0';  /* readlink does not NUL-terminate */
     386             : 
     387           6 :   char const * base = strrchr( target, '/' );
     388           6 :   fd_cstr_ncpy( driver, base ? base+1 : target, NAME_SZ );
     389           6 : }
     390             : 
     391             : static int
     392           3 : scrape_is_using_gre( void ) {
     393           3 :   fd_netlink_t netlink[1];
     394           3 :   if( FD_UNLIKELY( !fd_netlink_init( netlink, 42U ) ) ) return 1;
     395             : 
     396           3 :   ulong  netdev_tbl_footprint = fd_netdev_tbl_footprint( NETDEV_MAX, BOND_MASTER_MAX );
     397           3 :   void * netdev_tbl_mem       = aligned_alloc( FD_NETDEV_TBL_ALIGN, netdev_tbl_footprint );
     398           3 :   if( FD_UNLIKELY( !netdev_tbl_mem ) ) {
     399           0 :     fd_netlink_fini( netlink );
     400           0 :     FD_LOG_WARNING(( "failed to allocate network interface table for GRE auto detection" ));
     401           0 :     return 1;
     402           0 :   }
     403             : 
     404           3 :   fd_netdev_tbl_join_t netdev_tbl[1];
     405           3 :   FD_TEST( fd_netdev_tbl_new( netdev_tbl_mem, NETDEV_MAX, BOND_MASTER_MAX ) );
     406           3 :   FD_TEST( fd_netdev_tbl_join( netdev_tbl, netdev_tbl_mem ) );
     407             : 
     408           3 :   int err = fd_netdev_netlink_load_table( netdev_tbl, netlink );
     409           3 :   fd_netlink_fini( netlink );
     410           3 :   if( FD_UNLIKELY( err ) ) {
     411           0 :     FD_LOG_WARNING(( "failed to load network interfaces for GRE auto detection (%i-%s)",
     412           0 :                      err, fd_io_strerror( err ) ));
     413           0 :     free( netdev_tbl_mem );
     414           0 :     return 1;
     415           0 :   }
     416             : 
     417           3 :   int is_using_gre = 0;
     418          24 :   for( ushort i=0U; i<netdev_tbl->hdr->dev_cnt; i++ ) {
     419          21 :     if( netdev_tbl->dev_tbl[ i ].dev_type==ARPHRD_IPGRE ) {
     420           0 :       is_using_gre = 1;
     421           0 :       break;
     422           0 :     }
     423          21 :   }
     424           3 :   free( netdev_tbl_mem );
     425           3 :   return is_using_gre;
     426           3 : }
     427             : 
     428             : static void
     429             : scrape_networking( fd_auto_info_t * info,
     430           3 :                    char const     * if_name ) {
     431           3 :   info->is_using_gre = scrape_is_using_gre();
     432             : 
     433             :   /* Check for virtual interface */
     434           3 :   char path[ PATH_MAX ];
     435           3 :   FD_TEST( fd_cstr_printf_check( path, PATH_MAX, NULL, "/sys/class/net/%s/device", if_name ) );
     436           3 :   info->is_virtual_if = ( -1==access( path, F_OK ) );
     437             : 
     438             :   /* Check for bond */
     439           3 :   info->is_bonded_if = !!fd_bonding_is_master( if_name );
     440           3 :   if( info->is_bonded_if ) {
     441           3 :     info->bonded_if_slave_count = (uint)fd_bonding_slave_cnt( if_name );
     442           3 :     info->is_lacp_if            = !!fd_bonding_is_lacp( if_name );
     443           3 :   }
     444             : 
     445             :   /* Get driver name.  A bond master reports "n/a" so no driver specific
     446             :      config is applied. If all slaves share a driver name then reports
     447             :      that instead. */
     448           3 :   if( info->is_bonded_if ) {
     449           3 :     fd_bonding_slave_iter_t iter_[1];
     450           3 :     for( fd_bonding_slave_iter_t * iter = fd_bonding_slave_iter_init( iter_, if_name );
     451           9 :          !fd_bonding_slave_iter_done( iter );
     452           6 :          fd_bonding_slave_iter_next ( iter ) ) {
     453             : 
     454           6 :       char slave_driver[ NAME_SZ ];
     455           6 :       scrape_driver( slave_driver, fd_bonding_slave_iter_ele( iter ) );
     456           6 :       if( FD_UNLIKELY( !slave_driver[0] ||
     457           6 :                      ( info->driver[0]  && strcmp( info->driver, slave_driver ) ) ) ) {
     458           0 :         fd_memcpy( info->driver, "n/a", 4 );
     459           0 :         break;
     460           0 :       }
     461           6 :       fd_cstr_ncpy( info->driver, slave_driver, NAME_SZ );
     462           6 :     }
     463           3 :   } else {
     464           0 :     scrape_driver( info->driver, if_name );
     465           0 :   }
     466             : 
     467           3 :   if( !strcmp( info->driver, "mlx5_core" ) ) {
     468           3 :     char rdma_name[ FD_MLX5_RDMA_NAME_MAX ];
     469           3 :     uint rdma_port;
     470           3 :     info->has_mlx5_rdma_port = fd_mlx5_rdma_dev_find( rdma_name, &rdma_port, if_name );
     471           3 :     info->has_uverbs         = fd_mlx5_uverbs_avail();
     472           3 :   }
     473           3 : }
     474             : 
     475             : static fd_auto_info_t
     476           3 : fd_auto_scrape_info( fd_config_t const * config ) {
     477           3 :   fd_auto_info_t info = {0};
     478             : 
     479           3 :   scrape_system    ( &info                        );
     480           3 :   scrape_networking( &info, config->net.interface );
     481             : 
     482           3 :   return info;
     483           3 : }
     484             : 
     485             : /* fd_auto_net resolves any "auto" fields in the networking
     486             : configuration. The resulting configuration is optimized for the system
     487             : but won't always maximally optimize, this is to reduce risk of failures. */
     488             : static void
     489             : fd_auto_net( fd_config_t          * config,
     490          54 :              fd_auto_info_t const * info ) {
     491             :   /* Providers are in order of priority with first being the highest */
     492          54 :   int const is_provider_auto = !strcmp( config->net.provider, "auto" );
     493          54 :   int is_provider_set = 0;
     494         162 :   for( ulong p=0UL; p<PROVIDER_CNT; p++ ) {
     495         108 :     fd_auto_provider_t const * provider = &NET_PROVIDERS[p];
     496             : 
     497             :     /* Check provider requirements */
     498         108 :     int const is_explicit_provider = !is_provider_auto && !strcmp( config->net.provider, provider->name );
     499         108 :     int is_chosen_provider = !is_provider_set &&
     500         108 :                              ( is_explicit_provider ||
     501          99 :                                ( is_provider_auto &&
     502          69 :                                  ( !provider->check || provider->check( config, info ) ) &&
     503          69 :                                  fd_auto_check_driver( info, provider->supported_drivers ) ) );
     504         108 :     if( is_chosen_provider ) {
     505          51 :       is_provider_set = 1;
     506          51 :       if( is_provider_auto ) {
     507          21 :         if( FD_UNLIKELY( !provider->apply ) ) {
     508           0 :           FD_LOG_ERR(( "Applying auto configure net provider %s failed since no apply function was found.", provider->name ));
     509           0 :         }
     510          21 :         provider->apply( config );
     511          21 :       }
     512          51 :     }
     513             : 
     514         432 :     for( ulong f=0UL; f<FEAT_CNT_MAX; f++ ) {
     515         432 :       fd_auto_feat_t const * feat = &provider->feats[f];
     516         432 :       if( !feat->name ) break;
     517             : 
     518             :       /* Checks feature is set to "auto", if so replaces "auto" with
     519             :          default and goes onto the next checks */
     520         324 :       if( !feat->is_feat_auto( config ) ) continue;
     521             : 
     522         318 :       if( !is_chosen_provider ) continue;
     523             : 
     524             :       /* Feature's driver/Linux version requirements */
     525         246 :       if( !fd_auto_check_driver( info, feat->supported_drivers ) ) continue;
     526             : 
     527             :       /* Feature's other requirements */
     528         198 :       if( feat->check && !feat->check( config, info ) ) continue;
     529             : 
     530         126 :       if( FD_UNLIKELY( !feat->apply ) ) {
     531           0 :         FD_LOG_ERR(( "Applying auto configure net feature %s failed since no apply function was found.", feat->name ));
     532           0 :       }
     533         126 :       feat->apply( config );
     534         126 :     }
     535         108 :   }
     536          54 : }
     537             : 
     538             : void
     539           3 : fd_config_auto( fd_config_t * config ) {
     540           3 :   fd_auto_info_t info = fd_auto_scrape_info( config );
     541           3 :   fd_auto_net( config, &info );
     542             : 
     543           3 :   fd_cstr_printf( config->auto_config_log, sizeof(config->auto_config_log), NULL,
     544           3 :       "network auto configure system info: provider=%s xdp_mode=%s poll_mode=%s zero_copy=%d native_bond=%d listen_gre=%d rss_queue_mode=%s (driver=%s kernel=%lu.%lu gre=%d virtual_if=%d bonded_if=%d lacp_if=%d slaves=%u, net_tile_cnt=%u)",
     545           3 :       config->net.provider,
     546           3 :       config->net.xdp.xdp_mode,
     547           3 :       config->net.xdp.poll_mode,
     548           3 :       config->net.xdp.xdp_zero_copy,
     549           3 :       config->net.xdp.native_bond,
     550           3 :       config->net.xdp.listen_gre,
     551           3 :       config->net.xdp.rss_queue_mode,
     552           3 :       info.driver[0] ? info.driver : "unknown",
     553           3 :       info.linux_major, info.linux_minor,
     554           3 :       info.is_using_gre,
     555           3 :       info.is_virtual_if,
     556           3 :       info.is_bonded_if,
     557           3 :       info.is_lacp_if,
     558           3 :       info.bonded_if_slave_count,
     559           3 :       config->layout.net_tile_count );
     560           3 : }

Generated by: LCOV version 1.14