pci: add option to force uio binding
Type: improvement Change-Id: Ifea4badd58f7e2b5e792d7506f6747851a08587f Signed-off-by: Benoît Ganne <bganne@cisco.com>
This commit is contained in:

committed by
Dave Wallace

parent
eea6edcda8
commit
6a07348f4a
@ -666,6 +666,18 @@ or auto (default)
|
||||
|
||||
uio-driver vfio-pci
|
||||
|
||||
uio-bind-force
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Force VPP to rebind the interface(s) to the selected UIO driver, even if the
|
||||
interface is up in Linux.
|
||||
By default, VPP will refuse to bind an interface if it is up in Linux,
|
||||
in case it is in active use.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
uio-bind-force
|
||||
|
||||
no-multi-seg
|
||||
^^^^^^^^^^^^
|
||||
|
||||
|
@ -265,6 +265,7 @@ typedef struct
|
||||
u8 **eal_init_args;
|
||||
u8 *eal_init_args_str;
|
||||
u8 *uio_driver_name;
|
||||
u8 uio_bind_force;
|
||||
u8 enable_telemetry;
|
||||
u16 max_simd_bitwidth;
|
||||
|
||||
|
@ -681,7 +681,8 @@ dpdk_bind_devices_to_uio (dpdk_config_main_t * conf)
|
||||
continue;
|
||||
}
|
||||
|
||||
error = vlib_pci_bind_to_uio (vm, addr, (char *) conf->uio_driver_name);
|
||||
error = vlib_pci_bind_to_uio (vm, addr, (char *) conf->uio_driver_name,
|
||||
conf->uio_bind_force);
|
||||
|
||||
if (error)
|
||||
{
|
||||
@ -1089,6 +1090,8 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
|
||||
}
|
||||
else if (unformat (input, "uio-driver %s", &conf->uio_driver_name))
|
||||
;
|
||||
else if (unformat (input, "uio-bind-force"))
|
||||
conf->uio_bind_force = 1;
|
||||
else if (unformat (input, "socket-mem %s", &socket_mem))
|
||||
;
|
||||
else if (unformat (input, "no-pci"))
|
||||
|
@ -47,8 +47,10 @@ vmxnet3_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
|
||||
args.enable_gso = 1;
|
||||
else if (unformat (line_input, "elog"))
|
||||
args.enable_elog = 1;
|
||||
else if (unformat (line_input, "bind force"))
|
||||
args.bind = VMXNET3_BIND_FORCE;
|
||||
else if (unformat (line_input, "bind"))
|
||||
args.bind = 1;
|
||||
args.bind = VMXNET3_BIND_DEFAULT;
|
||||
else if (unformat (line_input, "rx-queue-size %u", &size))
|
||||
args.rxq_size = size;
|
||||
else if (unformat (line_input, "tx-queue-size %u", &size))
|
||||
@ -77,10 +79,11 @@ vmxnet3_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
|
||||
/* *INDENT-OFF* */
|
||||
VLIB_CLI_COMMAND (vmxnet3_create_command, static) = {
|
||||
.path = "create interface vmxnet3",
|
||||
.short_help = "create interface vmxnet3 <pci-address>"
|
||||
" [rx-queue-size <size>] [tx-queue-size <size>]"
|
||||
" [num-tx-queues <number>] [num-rx-queues <number>] [bind]"
|
||||
" [gso]",
|
||||
.short_help =
|
||||
"create interface vmxnet3 <pci-address>"
|
||||
" [rx-queue-size <size>] [tx-queue-size <size>]"
|
||||
" [num-tx-queues <number>] [num-rx-queues <number>] [bind [force]]"
|
||||
" [gso]",
|
||||
.function = vmxnet3_create_command_fn,
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
@ -692,7 +692,8 @@ vmxnet3_create_if (vlib_main_t * vm, vmxnet3_create_if_args_t * args)
|
||||
|
||||
if (args->bind)
|
||||
{
|
||||
error = vlib_pci_bind_to_uio (vm, &args->addr, (char *) "auto");
|
||||
error = vlib_pci_bind_to_uio (vm, &args->addr, (char *) "auto",
|
||||
VMXNET3_BIND_FORCE == args->bind);
|
||||
if (error)
|
||||
{
|
||||
args->rv = VNET_API_ERROR_INVALID_INTERFACE;
|
||||
|
@ -606,6 +606,13 @@ typedef struct
|
||||
|
||||
extern vmxnet3_main_t vmxnet3_main;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VMXNET3_BIND_NONE = 0,
|
||||
VMXNET3_BIND_DEFAULT = 1,
|
||||
VMXNET3_BIND_FORCE = 2,
|
||||
} __clib_packed vmxnet3_bind_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vlib_pci_addr_t addr;
|
||||
@ -614,7 +621,7 @@ typedef struct
|
||||
u16 rxq_num;
|
||||
u16 txq_size;
|
||||
u16 txq_num;
|
||||
u8 bind;
|
||||
vmxnet3_bind_t bind;
|
||||
u8 enable_gso;
|
||||
/* return */
|
||||
i32 rv;
|
||||
|
@ -453,8 +453,8 @@ directory_exists (char *path)
|
||||
}
|
||||
|
||||
clib_error_t *
|
||||
vlib_pci_bind_to_uio (vlib_main_t * vm, vlib_pci_addr_t * addr,
|
||||
char *uio_drv_name)
|
||||
vlib_pci_bind_to_uio (vlib_main_t *vm, vlib_pci_addr_t *addr,
|
||||
char *uio_drv_name, int force)
|
||||
{
|
||||
clib_error_t *error = 0;
|
||||
u8 *s = 0, *driver_name = 0;
|
||||
@ -523,76 +523,80 @@ vlib_pci_bind_to_uio (vlib_main_t * vm, vlib_pci_addr_t * addr,
|
||||
(strcmp ("igb_uio", (char *) driver_name) == 0)))
|
||||
goto done;
|
||||
|
||||
/* walk trough all linux interfaces and if interface belonging to
|
||||
this device is founf check if interface is admin up */
|
||||
dir = opendir ("/sys/class/net");
|
||||
s = format (s, "%U%c", format_vlib_pci_addr, addr, 0);
|
||||
|
||||
if (!dir)
|
||||
if (!force)
|
||||
{
|
||||
error = clib_error_return (0, "Skipping PCI device %U: failed to "
|
||||
"read /sys/class/net",
|
||||
format_vlib_pci_addr, addr);
|
||||
goto done;
|
||||
}
|
||||
/* walk trough all linux interfaces and if interface belonging to
|
||||
this device is found check if interface is admin up */
|
||||
dir = opendir ("/sys/class/net");
|
||||
s = format (s, "%U%c", format_vlib_pci_addr, addr, 0);
|
||||
|
||||
fd = socket (PF_INET, SOCK_DGRAM, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
error = clib_error_return_unix (0, "socket");
|
||||
goto done;
|
||||
}
|
||||
|
||||
while ((e = readdir (dir)))
|
||||
{
|
||||
struct ifreq ifr;
|
||||
struct ethtool_drvinfo drvinfo;
|
||||
|
||||
if (e->d_name[0] == '.') /* skip . and .. */
|
||||
continue;
|
||||
|
||||
clib_memset (&ifr, 0, sizeof ifr);
|
||||
clib_memset (&drvinfo, 0, sizeof drvinfo);
|
||||
ifr.ifr_data = (char *) &drvinfo;
|
||||
clib_strncpy (ifr.ifr_name, e->d_name, sizeof (ifr.ifr_name) - 1);
|
||||
|
||||
drvinfo.cmd = ETHTOOL_GDRVINFO;
|
||||
if (ioctl (fd, SIOCETHTOOL, &ifr) < 0)
|
||||
if (!dir)
|
||||
{
|
||||
/* Some interfaces (eg "lo") don't support this ioctl */
|
||||
if ((errno != ENOTSUP) && (errno != ENODEV))
|
||||
clib_unix_warning ("ioctl fetch intf %s bus info error",
|
||||
e->d_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp ((char *) s, drvinfo.bus_info))
|
||||
continue;
|
||||
|
||||
clib_memset (&ifr, 0, sizeof (ifr));
|
||||
clib_strncpy (ifr.ifr_name, e->d_name, sizeof (ifr.ifr_name) - 1);
|
||||
|
||||
if (ioctl (fd, SIOCGIFFLAGS, &ifr) < 0)
|
||||
{
|
||||
error = clib_error_return_unix (0, "ioctl fetch intf %s flags",
|
||||
e->d_name);
|
||||
close (fd);
|
||||
error = clib_error_return (0,
|
||||
"Skipping PCI device %U: failed to "
|
||||
"read /sys/class/net",
|
||||
format_vlib_pci_addr, addr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ifr.ifr_flags & IFF_UP)
|
||||
fd = socket (PF_INET, SOCK_DGRAM, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
vlib_log (VLIB_LOG_LEVEL_WARNING, pci_main.log_default,
|
||||
"Skipping PCI device %U as host "
|
||||
"interface %s is up", format_vlib_pci_addr, addr,
|
||||
e->d_name);
|
||||
close (fd);
|
||||
error = clib_error_return_unix (0, "socket");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
close (fd);
|
||||
vec_reset_length (s);
|
||||
while ((e = readdir (dir)))
|
||||
{
|
||||
struct ifreq ifr;
|
||||
struct ethtool_drvinfo drvinfo;
|
||||
|
||||
if (e->d_name[0] == '.') /* skip . and .. */
|
||||
continue;
|
||||
|
||||
clib_memset (&ifr, 0, sizeof ifr);
|
||||
clib_memset (&drvinfo, 0, sizeof drvinfo);
|
||||
ifr.ifr_data = (char *) &drvinfo;
|
||||
clib_strncpy (ifr.ifr_name, e->d_name, sizeof (ifr.ifr_name) - 1);
|
||||
|
||||
drvinfo.cmd = ETHTOOL_GDRVINFO;
|
||||
if (ioctl (fd, SIOCETHTOOL, &ifr) < 0)
|
||||
{
|
||||
/* Some interfaces (eg "lo") don't support this ioctl */
|
||||
if ((errno != ENOTSUP) && (errno != ENODEV))
|
||||
clib_unix_warning ("ioctl fetch intf %s bus info error",
|
||||
e->d_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp ((char *) s, drvinfo.bus_info))
|
||||
continue;
|
||||
|
||||
clib_memset (&ifr, 0, sizeof (ifr));
|
||||
clib_strncpy (ifr.ifr_name, e->d_name, sizeof (ifr.ifr_name) - 1);
|
||||
|
||||
if (ioctl (fd, SIOCGIFFLAGS, &ifr) < 0)
|
||||
{
|
||||
error = clib_error_return_unix (0, "ioctl fetch intf %s flags",
|
||||
e->d_name);
|
||||
close (fd);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ifr.ifr_flags & IFF_UP)
|
||||
{
|
||||
vlib_log (VLIB_LOG_LEVEL_WARNING, pci_main.log_default,
|
||||
"Skipping PCI device %U as host "
|
||||
"interface %s is up",
|
||||
format_vlib_pci_addr, addr, e->d_name);
|
||||
close (fd);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
close (fd);
|
||||
vec_reset_length (s);
|
||||
}
|
||||
|
||||
s = format (s, "%v/driver/unbind%c", dev_dir_name, 0);
|
||||
clib_sysfs_write ((char *) s, "%U", format_vlib_pci_addr, addr);
|
||||
|
@ -182,8 +182,8 @@ static void __vlib_rm_pci_device_registration_##x (void) \
|
||||
} \
|
||||
__VA_ARGS__ pci_device_registration_t x
|
||||
|
||||
clib_error_t *vlib_pci_bind_to_uio (vlib_main_t * vm, vlib_pci_addr_t * addr,
|
||||
char *uio_driver_name);
|
||||
clib_error_t *vlib_pci_bind_to_uio (vlib_main_t *vm, vlib_pci_addr_t *addr,
|
||||
char *uio_driver_name, int force);
|
||||
|
||||
/* Configuration space read/write. */
|
||||
clib_error_t *vlib_pci_read_write_config (vlib_main_t * vm,
|
||||
|
Reference in New Issue
Block a user