LCOV - code coverage report
Current view: top level - app/fddev/configure - netns.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 74 0.0 %
Date: 2025-03-10 12:29:05 Functions: 0 6 0.0 %

          Line data    Source code
       1             : #define _GNU_SOURCE
       2             : #include "../../fdctl/configure/configure.h"
       3             : 
       4             : #include <sys/stat.h>
       5             : 
       6           0 : #define NAME "netns"
       7             : 
       8             : static int
       9           0 : enabled( config_t const * config ) {
      10           0 :   return config->development.netns.enabled;
      11           0 : }
      12             : 
      13             : static void
      14             : init_perm( fd_caps_ctx_t *  caps,
      15           0 :            config_t const * config FD_PARAM_UNUSED ) {
      16           0 :   fd_caps_check_root( caps, NAME, "create and enter network namespaces" );
      17           0 : }
      18             : 
      19             : static void
      20             : fini_perm( fd_caps_ctx_t *  caps,
      21           0 :            config_t const * config FD_PARAM_UNUSED ) {
      22           0 :   fd_caps_check_root( caps, NAME, "remove network namespaces" );
      23           0 : }
      24             : 
      25             : static void
      26           0 : init( config_t * config ) {
      27           0 :   uint tiles              = config->layout.net_tile_count;
      28           0 :   const char * interface0 = config->development.netns.interface0;
      29           0 :   const char * interface1 = config->development.netns.interface1;
      30             : 
      31           0 :   RUN( "ip netns add %s", interface0 );
      32           0 :   RUN( "ip netns add %s", interface1 );
      33           0 :   RUN( "ip link add dev %s netns %s type veth peer name %s netns %s numrxqueues %u numtxqueues %u",
      34           0 :         interface0, interface0, interface1, interface1, tiles, tiles );
      35           0 :   RUN( "ip netns exec %s ip link set dev %s address %s",
      36           0 :        interface0, interface0, config->development.netns.interface0_mac );
      37           0 :   RUN( "ip netns exec %s ip link set dev %s address %s",
      38           0 :        interface1, interface1, config->development.netns.interface1_mac );
      39           0 :   RUN( "ip netns exec %s ip address add %s/30 dev %s scope link",
      40           0 :        interface0, config->development.netns.interface0_addr, interface0 );
      41           0 :   RUN( "ip netns exec %s ip address add %s/30 dev %s scope link",
      42           0 :        interface1, config->development.netns.interface1_addr, interface1 );
      43           0 :   RUN( "ip netns exec %s ip link set dev %s up", interface0, interface0 );
      44           0 :   RUN( "ip netns exec %s ip link set dev %s up", interface1, interface1 );
      45             : 
      46             :   /* we need one channel for both TX and RX on the NIC for each QUIC
      47             :      tile, but the virtual interfaces default to one channel total */
      48           0 :   RUN( "nsenter --net=/var/run/netns/%s ethtool --set-channels %s rx %u tx %u",
      49           0 :        interface0, interface0, tiles, tiles );
      50           0 :   RUN( "nsenter --net=/var/run/netns/%s ethtool --set-channels %s rx %u tx %u",
      51           0 :        interface1, interface1, tiles, tiles );
      52             : 
      53             :   /* UDP segmentation is a kernel feature that batches multiple UDP
      54             :      packets into one in the kernel before splitting them later when
      55             :      dispatching. this feature is broken with network namespaces so we
      56             :      disable it. otherwise, we would see very large packets that don't
      57             :      decrypt. need on both tx and rx sides */
      58           0 :   RUN( "nsenter --net=/var/run/netns/%s ethtool -K %s tx-udp-segmentation off",
      59           0 :        interface0, interface0 );
      60           0 :   RUN( "nsenter --net=/var/run/netns/%s ethtool -K %s tx-udp-segmentation off",
      61           0 :        interface1, interface1 );
      62             : 
      63             :   /* generic segmentation offload and TX GRE segmentation are similar
      64             :      things on the tx side that also get messed up under netns in
      65             :      unknown ways */
      66           0 :   RUN( "nsenter --net=/var/run/netns/%s ethtool -K %s generic-segmentation-offload off",
      67           0 :        interface0, interface0 );
      68           0 :   RUN( "nsenter --net=/var/run/netns/%s ethtool -K %s generic-segmentation-offload off",
      69           0 :        interface1, interface1 );
      70           0 :   RUN( "nsenter --net=/var/run/netns/%s ethtool -K %s tx-gre-segmentation off",
      71           0 :        interface0, interface0 );
      72           0 :   RUN( "nsenter --net=/var/run/netns/%s ethtool -K %s tx-gre-segmentation off",
      73           0 :        interface1, interface1 );
      74           0 : }
      75             : 
      76             : static void
      77             : fini( config_t * config,
      78           0 :       int        pre_init FD_PARAM_UNUSED ) {
      79           0 :   const char * interface0 = config->development.netns.interface0;
      80           0 :   const char * interface1 = config->development.netns.interface1;
      81             : 
      82           0 :   char cmd[ 256 ];
      83           0 :   FD_TEST( fd_cstr_printf_check( cmd, sizeof(cmd), NULL, "ip link del dev %s", interface0 ) );
      84           0 :   int status3 = system( cmd ); // Destroys interface1 as well, no need to check failure
      85           0 :   if( FD_UNLIKELY( status3 ) ) FD_LOG_DEBUG(( "ip link del dev %s failed", interface0 ));
      86             : 
      87           0 :   FD_TEST( fd_cstr_printf_check( cmd, sizeof(cmd), NULL, "ip netns delete %s", interface0 ) );
      88           0 :   int status1 = system( cmd );
      89           0 :   FD_TEST( fd_cstr_printf_check( cmd, sizeof(cmd), NULL, "ip netns delete %s", interface1 ) );
      90           0 :   int status2 = system( cmd );
      91             : 
      92             :   /* if neither of them was present, we wouldn't get to the undo step so make sure we were
      93             :      able to delete whatever is there */
      94           0 :   if( FD_UNLIKELY( status1 && status2 ) ) FD_LOG_ERR(( "failed to delete network namespaces" ));
      95           0 : }
      96             : 
      97             : static configure_result_t
      98           0 : check( config_t const * config ) {
      99           0 :   const char * interface0 = config->development.netns.interface0;
     100           0 :   const char * interface1 = config->development.netns.interface1;
     101             : 
     102           0 :   char path[ PATH_MAX ];
     103           0 :   FD_TEST( fd_cstr_printf_check( path, sizeof(path), NULL, "/var/run/netns/%s", interface0 ) );
     104             : 
     105           0 :   struct stat st;
     106           0 :   int result1 = stat( path, &st );
     107           0 :   if( FD_UNLIKELY( result1 && errno != ENOENT ) ) PARTIALLY_CONFIGURED( "netns `%s` cannot be read", interface0 );
     108             : 
     109           0 :   FD_TEST( fd_cstr_printf_check( path, sizeof(path), NULL, "/var/run/netns/%s", interface1 ) );
     110           0 :   int result2 = stat( path, &st );
     111           0 :   if( FD_UNLIKELY( result2 && errno != ENOENT ) ) PARTIALLY_CONFIGURED( "netns `%s` cannot be read", interface1 );
     112             : 
     113           0 :   if( FD_UNLIKELY( result1 && result2 ) ) NOT_CONFIGURED( "netns `%s` and `%s` do not exist", interface0, interface1 );
     114           0 :   else if( FD_UNLIKELY( result1 ) ) NOT_CONFIGURED( "netns `%s` does not exist", interface0 );
     115           0 :   else if( FD_UNLIKELY( result2 ) ) NOT_CONFIGURED( "netns `%s` does not exist", interface1 );
     116             : 
     117             :   /* todo: use `ip netns exec`,  `ip link show` to verify the
     118             :      configuration is correct TODO: Check the ethtool stuff is correct
     119             :      as well */
     120           0 :   CONFIGURE_OK();
     121           0 : }
     122             : 
     123             : configure_stage_t fd_cfg_stage_netns = {
     124             :   .name            = NAME,
     125             :   .always_recreate = 0,
     126             :   .enabled         = enabled,
     127             :   .init_perm       = init_perm,
     128             :   .fini_perm       = fini_perm,
     129             :   .init            = init,
     130             :   .fini            = fini,
     131             :   .check           = check,
     132             : };
     133             : 
     134             : #undef NAME

Generated by: LCOV version 1.14