Skip to content

Commit

Permalink
fddev netns fixes
Browse files Browse the repository at this point in the history
- Add back netns support to fddev init sequence
- Fix netdev reading of interfaces with 15 char name length
- Better error message for fd_http_server_listen bind failure
- Run ethtool configure stages after entering netns
- Bring up loopback after entering netns
  • Loading branch information
riptl authored and ripatel-fd committed Feb 13, 2025
1 parent 4deaf03 commit e02875d
Show file tree
Hide file tree
Showing 13 changed files with 79 additions and 36 deletions.
14 changes: 11 additions & 3 deletions src/app/fdctl/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -531,12 +531,20 @@ fdctl_cfg_from_env( int * pargc,
config->is_live_cluster = cluster != FD_CLUSTER_UNKNOWN;

if( FD_UNLIKELY( config->development.netns.enabled ) ) {
/* not currently supporting multihoming on netns */
if( FD_UNLIKELY( strcmp( config->development.netns.interface0, config->tiles.net.interface ) ) )
if( !strcmp( config->tiles.net.interface, "" ) ) {
memcpy( config->tiles.net.interface, config->development.netns.interface0, sizeof(config->tiles.net.interface) );
}

if( !strcmp( config->development.pktgen.fake_dst_ip, "" ) ) {
memcpy( config->development.pktgen.fake_dst_ip, config->development.netns.interface1_addr, sizeof(config->development.netns.interface1_addr) );
}

if( FD_UNLIKELY( strcmp( config->development.netns.interface0, config->tiles.net.interface ) ) ) {
FD_LOG_ERR(( "netns interface and firedancer interface are different. If you are using the "
"[development.netns] functionality to run Firedancer in a network namespace "
"for development, the configuration file must specify that "
"[development.netns.interface0] is the same as [net.interface]" ));
"[development.netns.interface0] is the same as [tiles.net.interface]" ));
}

if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( config->development.netns.interface0_addr, &config->tiles.net.ip_addr ) ) )
FD_LOG_ERR(( "configuration specifies invalid netns IP address `%s`", config->development.netns.interface0_addr ));
Expand Down
4 changes: 2 additions & 2 deletions src/app/fdctl/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,10 @@ struct fdctl_config {
int enabled;
char interface0 [ 16 ];
char interface0_mac [ 32 ];
char interface0_addr[ 32 ];
char interface0_addr[ 16 ];
char interface1 [ 16 ];
char interface1_mac [ 32 ];
char interface1_addr[ 32 ];
char interface1_addr[ 16 ];
} netns;

struct {
Expand Down
6 changes: 1 addition & 5 deletions src/app/fdctl/netconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,7 @@ netconf_cmd_fn( args_t * args,
fd_fib4_fprintf( fib4_local, stdout );
fd_fib4_leave( fib4_local );

char if_name[ IF_NAMESIZE ] = "???";
if( FD_UNLIKELY( !if_indextoname( tile->netlink.neigh_if_idx, if_name ) ) ) {
memcpy( if_name, "???", 4 );
}
printf( "\nNEIGHBOR TABLE (%u-%s)\n\n", tile->netlink.neigh_if_idx, if_name );
printf( "\nNEIGHBOR TABLE (%.16s)\n\n", tile->netlink.neigh_if );
fd_neigh4_hmap_t neigh4[1];
FD_TEST( fd_neigh4_hmap_join( neigh4, fd_topo_obj_laddr( topo, tile->netlink.neigh4_obj_id ), fd_topo_obj_laddr( topo, tile->netlink.neigh4_ele_obj_id ) ) );
fd_neigh4_hmap_fprintf( neigh4, stdout );
Expand Down
48 changes: 31 additions & 17 deletions src/app/fdctl/run/run.c
Original file line number Diff line number Diff line change
Expand Up @@ -690,27 +690,29 @@ extern configure_stage_t fd_cfg_stage_ethtool_loopback;
extern configure_stage_t fd_cfg_stage_sysctl;

void
fdctl_check_configure( config_t * const config ) {
fdctl_check_configure( config_t * config ) {
configure_result_t check = fd_cfg_stage_hugetlbfs.check( config );
if( FD_UNLIKELY( check.result!=CONFIGURE_OK ) )
FD_LOG_ERR(( "Huge pages are not configured correctly: %s. You can run `fdctl configure init hugetlbfs` "
"to create the mounts correctly. This must be done after every system restart before running "
"Firedancer.", check.message ));

check = fd_cfg_stage_ethtool_channels.check( config );
if( FD_UNLIKELY( check.result!=CONFIGURE_OK ) )
FD_LOG_ERR(( "Network %s. You can run `fdctl configure init ethtool-channels` to set the number of channels on the "
"network device correctly.", check.message ));

check = fd_cfg_stage_ethtool_gro.check( config );
if( FD_UNLIKELY( check.result!=CONFIGURE_OK ) )
FD_LOG_ERR(( "Network %s. You can run `fdctl configure init ethtool-gro` to disable generic-receive-offload "
"as required.", check.message ));

check = fd_cfg_stage_ethtool_loopback.check( config );
if( FD_UNLIKELY( check.result!=CONFIGURE_OK ) )
FD_LOG_ERR(( "Network %s. You can run `fdctl configure init ethtool-loopback` to disable tx-udp-segmentation "
"on the loopback device.", check.message ));
if( FD_LIKELY( !config->development.netns.enabled ) ) {
check = fd_cfg_stage_ethtool_channels.check( config );
if( FD_UNLIKELY( check.result!=CONFIGURE_OK ) )
FD_LOG_ERR(( "Network %s. You can run `fdctl configure init ethtool-channels` to set the number of channels on the "
"network device correctly.", check.message ));

check = fd_cfg_stage_ethtool_gro.check( config );
if( FD_UNLIKELY( check.result!=CONFIGURE_OK ) )
FD_LOG_ERR(( "Network %s. You can run `fdctl configure init ethtool-gro` to disable generic-receive-offload "
"as required.", check.message ));

check = fd_cfg_stage_ethtool_loopback.check( config );
if( FD_UNLIKELY( check.result!=CONFIGURE_OK ) )
FD_LOG_ERR(( "Network %s. You can run `fdctl configure init ethtool-loopback` to disable tx-udp-segmentation "
"on the loopback device.", check.message ));
}

check = fd_cfg_stage_sysctl.check( config );
if( FD_UNLIKELY( check.result!=CONFIGURE_OK ) )
Expand All @@ -719,8 +721,8 @@ fdctl_check_configure( config_t * const config ) {
}

void
run_firedancer_init( config_t * const config,
int init_workspaces ) {
run_firedancer_init( config_t * config,
int init_workspaces ) {
struct stat st;
int err = stat( config->consensus.identity_path, &st );
if( FD_UNLIKELY( -1==err && errno==ENOENT ) ) FD_LOG_ERR(( "[consensus.identity_path] key does not exist `%s`. You can generate an identity key at this path by running `fdctl keys new identity --config <toml>`", config->consensus.identity_path ));
Expand All @@ -737,6 +739,18 @@ run_firedancer_init( config_t * const config,
initialize_stacks( config );
}

void
fdctl_setup_netns( config_t * config ) {
if( config->development.netns.enabled ) {
enter_network_namespace( config->tiles.net.interface );
close_network_namespace_original_fd();
}

fd_cfg_stage_ethtool_channels.init( config );
fd_cfg_stage_ethtool_gro .init( config );
fd_cfg_stage_ethtool_loopback.init( config );
}

/* The boot sequence is a little bit involved...
A process tree is created that looks like,
Expand Down
3 changes: 3 additions & 0 deletions src/app/fdctl/run/run.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ void
run_firedancer_init( config_t * const config,
int init_workspaces );

void
fdctl_setup_netns( config_t * config );

void
run_firedancer( config_t * const config,
int parent_pipefd,
Expand Down
12 changes: 12 additions & 0 deletions src/app/fdctl/utility.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
#include <fcntl.h>
#include <sched.h>
#include <dirent.h>
#include <net/if.h> /* IFF_UP */

#include <sys/ioctl.h> /* ioctl(2) */
#include <sys/mman.h> /* for mprotect */
#include <sys/stat.h>
#include <sys/socket.h>
Expand Down Expand Up @@ -40,6 +42,16 @@ enter_network_namespace( const char * interface ) {
FD_LOG_ERR(( "failed to enter network namespace `%s` (%i-%s)", path, errno, fd_io_strerror( errno ) ));
int ret = close( fd );
if( FD_UNLIKELY( ret ) ) FD_LOG_ERR(( "enter_network_namespace %d (%i-%s)", ret, errno, fd_io_strerror( errno ) ));

/* `ip link set dev lo up`
Done via the ioctl API for simplicity. Requires a dummy socket. */
int ifreq_fd = socket( AF_INET, SOCK_DGRAM, 0 );
if( FD_UNLIKELY( ifreq_fd<0 ) ) FD_LOG_ERR(( "socket(AF_INET,SOCK_DGRAM,0) failed (%i-%s)", errno, fd_io_strerror( errno ) ));
struct ifreq ifr = { .ifr_name = "lo" };
if( FD_UNLIKELY( ioctl( ifreq_fd, SIOCGIFFLAGS, &ifr ) ) ) FD_LOG_ERR(( "ioctl(SIOCGIFFLAGS,\"lo\") failed (%i-%s)", errno, fd_io_strerror( errno ) ));
ifr.ifr_flags |= (IFF_UP|IFF_RUNNING);
if( FD_UNLIKELY( ioctl( ifreq_fd, SIOCSIFFLAGS, &ifr ) ) ) FD_LOG_ERR(( "ioctl(SIOCGIFFLAGS,\"lo\",IFF_UP|IFF_RUNNING) failed (%i-%s)", errno, fd_io_strerror( errno ) ));
if( FD_UNLIKELY( close( ifreq_fd ) ) ) FD_LOG_ERR(( "failed to close dummy UDP socket (%i-%s)", errno, fd_io_strerror( errno ) ));
}

void
Expand Down
1 change: 1 addition & 0 deletions src/app/fddev/bench.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ bench_cmd_fn( args_t * args,
update_config_for_dev( config );

run_firedancer_init( config, 1 );
fdctl_setup_netns( config );

fd_xdp_fds_t fds = fd_topo_install_xdp( &config->topo );
(void)fds;
Expand Down
1 change: 1 addition & 0 deletions src/app/fddev/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ run_firedancer_threaded( config_t * config , int init_workspaces) {
fd_topo_print_log( 0, &config->topo );

run_firedancer_init( config, init_workspaces );
fdctl_setup_netns( config );

if( FD_UNLIKELY( config->development.debug_tile ) ) {
fd_log_private_shared_lock[ 1 ] = 1;
Expand Down
1 change: 1 addition & 0 deletions src/app/fddev/pktgen.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ pktgen_cmd_fn( args_t * args,
/* FIXME this allocates lots of memory unnecessarily */
initialize_workspaces( config );
initialize_stacks( config );
fdctl_setup_netns( config );
(void)fd_topo_install_xdp( &config->topo );;
fd_topo_join_workspaces( &config->topo, FD_SHMEM_JOIN_MODE_READ_WRITE );

Expand Down
9 changes: 7 additions & 2 deletions src/ballet/http/fd_http_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "picohttpparser.h"
#include "fd_sha1.h"
#include "../base64/fd_base64.h"
#include "../../util/net/fd_ip4.h"

#include <stdarg.h>
#include <stdio.h>
Expand Down Expand Up @@ -282,8 +283,12 @@ fd_http_server_listen( fd_http_server_t * http,
.sin_addr.s_addr = address,
};

if( FD_UNLIKELY( -1==bind( sockfd, fd_type_pun( &addr ), sizeof( addr ) ) ) ) FD_LOG_ERR(( "bind failed (%i-%s)", errno, strerror( errno ) ));
if( FD_UNLIKELY( -1==listen( sockfd, (int)http->max_conns ) ) ) FD_LOG_ERR(( "listen failed (%i-%s)", errno, strerror( errno ) ));
if( FD_UNLIKELY( -1==bind( sockfd, fd_type_pun( &addr ), sizeof( addr ) ) ) ) {
FD_LOG_ERR(( "bind(%i,AF_INET," FD_IP4_ADDR_FMT ":%u) failed (%i-%s)",
sockfd, FD_IP4_ADDR_FMT_ARGS( address ), port,
errno, fd_io_strerror( errno ) ));
}
if( FD_UNLIKELY( -1==listen( sockfd, (int)http->max_conns ) ) ) FD_LOG_ERR(( "listen failed (%i-%s)", errno, fd_io_strerror( errno ) ));

http->socket_fd = sockfd;
http->pollfds[ http->max_conns+http->max_ws_conns ].fd = http->socket_fd;
Expand Down
9 changes: 5 additions & 4 deletions src/disco/netlink/fd_netlink_tile.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ fd_netlink_topo_create( fd_topo_tile_t * netlink_tile,

/* Configure neighbor hashmap: Open addressed hashmap with 3.0 sparsity
factor and 16 long probe chain */
uint const neigh_if_idx = if_nametoindex( config->tiles.net.interface );
if( FD_UNLIKELY( !neigh_if_idx ) ) FD_LOG_ERR(( "if_nametoindex(%s) failed (%i-%s)", config->tiles.net.interface, errno, fd_io_strerror( errno ) ));
ulong const neigh_ele_max = fd_ulong_pow2_up( 3UL * config->tiles.netlink.max_neighbors );
ulong const neigh_ele_align = alignof(fd_neigh4_entry_t);
ulong const neigh_ele_fp = neigh_ele_max * sizeof(fd_neigh4_entry_t);
Expand All @@ -67,7 +65,7 @@ fd_netlink_topo_create( fd_topo_tile_t * netlink_tile,
netlink_tile->netlink.netdev_dbl_buf_obj_id = netdev_dbl_buf_obj->id;
netlink_tile->netlink.fib4_main_obj_id = fib4_main_obj->id;
netlink_tile->netlink.fib4_local_obj_id = fib4_local_obj->id;
netlink_tile->netlink.neigh_if_idx = neigh_if_idx;
memcpy( netlink_tile->netlink.neigh_if, config->tiles.net.interface, sizeof(netlink_tile->netlink.neigh_if) );
netlink_tile->netlink.neigh4_obj_id = neigh4_obj->id;
netlink_tile->netlink.neigh4_ele_obj_id = neigh4_ele_obj->id;
}
Expand Down Expand Up @@ -135,10 +133,13 @@ privileged_init( fd_topo_t * topo,
FD_LOG_ERR(( "Topology contains more than one netlink tile" ));
}

uint const neigh_if_idx = if_nametoindex( tile->netlink.neigh_if );
if( FD_UNLIKELY( !neigh_if_idx ) ) FD_LOG_ERR(( "if_nametoindex(%.16s) failed (%i-%s)", tile->netlink.neigh_if, errno, fd_io_strerror( errno ) ));

fd_netlink_tile_ctx_t * ctx = fd_topo_obj_laddr( topo, tile->tile_obj_id );
fd_memset( ctx, 0, sizeof(fd_netlink_tile_ctx_t) );
ctx->magic = FD_NETLINK_TILE_CTX_MAGIC;
ctx->neigh4_ifidx = tile->netlink.neigh_if_idx;
ctx->neigh4_ifidx = neigh_if_idx;

if( FD_UNLIKELY( !fd_netlink_init( ctx->nl_monitor, 1000U ) ) ) {
FD_LOG_ERR(( "Failed to connect to rtnetlink" ));
Expand Down
2 changes: 1 addition & 1 deletion src/disco/topo/fd_topo.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ typedef struct {
ulong netdev_dbl_buf_obj_id; /* dbl_buf containing netdev_tbl */
ulong fib4_main_obj_id; /* fib4 containing main route table */
ulong fib4_local_obj_id; /* fib4 containing local route table */
uint neigh_if_idx; /* neigh4 interface index */
char neigh_if[ 16 ]; /* neigh4 interface name */
ulong neigh4_obj_id; /* neigh4 hash map header */
ulong neigh4_ele_obj_id; /* neigh4 hash map slots */
} netlink;
Expand Down
5 changes: 3 additions & 2 deletions src/waltz/mib/fd_netdev_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,14 @@ fd_netdev_netlink_load_table( fd_netdev_tbl_join_t * tbl,
switch( rat->rta_type ) {

case IFLA_IFNAME:
if( FD_UNLIKELY( rta_sz==0 || rta_sz>=IFNAMSIZ ) ) {
/* Includes trailing zero */
if( FD_UNLIKELY( rta_sz==0 || rta_sz>IFNAMSIZ ) ) {
FD_LOG_WARNING(( "Error reading interface table: IFLA_IFNAME has unsupported size %lu", rta_sz ));
err = EPROTO;
goto fail;
}
memcpy( netdev->name, rta, rta_sz );
netdev->name[ rta_sz ] = '\0';
netdev->name[ rta_sz-1 ] = '\0';
break;

case IFLA_ADDRESS:
Expand Down

0 comments on commit e02875d

Please sign in to comment.