summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Ratnikov <vratnikov@netgate.com>2020-11-11 08:00:48 -0500
committerMatthew Smith <mgsmith@netgate.com>2021-01-11 20:40:23 +0000
commit9822729742168c877a301ff50a3a1067b90a89ad (patch)
tree6060722a9b4f72282e78e5076f759a42c9e1d3d7
parentdcacdc4fd90d6cc71aaafccbca3ea91c7481ddbd (diff)
dpdk: allow configure individual VMBUS devices
now startup.conf supports confuguration for VMBUS devices as for PCI devices for whitelisting/blacklisting dpdk { dev fa5a6e7a-cf3a-4b98-9569-addb479b84bc } with sub-configuration as for PCI devices dpdk { blacklist fa5a6e7a-cf3a-4b98-9569-addb479b84bc } where fa5a6e7a-cf3a-4b98-9569-addb479b84bc - example of UUID struct vlib_vmbus_addr_t changed to union with UUID described fields Added device_config_index_by_vmbus_addr blacklist_by_vmbus_addr to enumerate available device configs hash_key is as_u32[0] field(last 4 bytes of UUID) Lost of precision against full UUID, but 2^32 is enough to handle all the devices available Added is_blacklisted check while creating vnet devices in order to supress creation of dev if it's blacklisted Type: feature Signed-off-by: Vladimir Ratnikov <vratnikov@netgate.com> Change-Id: Id82611e54fed082190e488c7e5fbe14ecbe5b2ab
-rw-r--r--src/plugins/dpdk/device/common.c13
-rw-r--r--src/plugins/dpdk/device/dpdk.h21
-rw-r--r--src/plugins/dpdk/device/init.c234
-rw-r--r--src/vlib/linux/vmbus.c22
-rw-r--r--src/vlib/vmbus/vmbus.c15
-rw-r--r--src/vlib/vmbus/vmbus.h6
6 files changed, 253 insertions, 58 deletions
diff --git a/src/plugins/dpdk/device/common.c b/src/plugins/dpdk/device/common.c
index 0c43bfe02bb..2521abde97a 100644
--- a/src/plugins/dpdk/device/common.c
+++ b/src/plugins/dpdk/device/common.c
@@ -260,6 +260,19 @@ dpdk_get_pci_device (const struct rte_eth_dev_info *info)
return NULL;
}
+/* If this device is VMBUS return pointer to info, otherwise NULL */
+struct rte_vmbus_device *
+dpdk_get_vmbus_device (const struct rte_eth_dev_info *info)
+{
+ const struct rte_bus *bus;
+
+ bus = rte_bus_find_by_device (info->device);
+ if (bus && !strcmp (bus->name, "vmbus"))
+ return container_of (info->device, struct rte_vmbus_device, device);
+ else
+ return NULL;
+}
+
/*
* fd.io coding-style-patch-verification: ON
*
diff --git a/src/plugins/dpdk/device/dpdk.h b/src/plugins/dpdk/device/dpdk.h
index c81f23d769c..504bac5b6ee 100644
--- a/src/plugins/dpdk/device/dpdk.h
+++ b/src/plugins/dpdk/device/dpdk.h
@@ -32,6 +32,7 @@
#include <rte_per_lcore.h>
#include <rte_interrupts.h>
#include <rte_pci.h>
+#include <rte_bus_vmbus.h>
#include <rte_ether.h>
#include <rte_ethdev.h>
#include <rte_ring.h>
@@ -52,6 +53,7 @@
#endif
#include <vlib/pci/pci.h>
+#include <vlib/vmbus/vmbus.h>
#include <vnet/flow/flow.h>
extern vnet_device_class_t dpdk_device_class;
@@ -250,9 +252,21 @@ typedef struct
_ (num_tx_desc) \
_ (rss_fn)
+typedef enum
+{
+ VNET_DEV_ADDR_PCI,
+ VNET_DEV_ADDR_VMBUS,
+ VNET_DEV_ADDR_ANY,
+} dpdk_device_addr_type_t;
+
typedef struct
{
- vlib_pci_addr_t pci_addr;
+ union
+ {
+ vlib_pci_addr_t pci_addr;
+ vlib_vmbus_addr_t vmbus_addr;
+ };
+ dpdk_device_addr_type_t dev_addr_type;
u8 *name;
u8 is_blacklisted;
u8 vlan_strip_offload;
@@ -302,9 +316,12 @@ typedef struct
dpdk_device_config_t default_devconf;
dpdk_device_config_t *dev_confs;
uword *device_config_index_by_pci_addr;
+ uword *device_config_index_by_vmbus_addr;
/* devices blacklist by pci vendor_id, device_id */
u32 *blacklist_by_pci_vendor_and_device;
+ /* devices blacklist by VMBUS address */
+ u32 *blacklist_by_vmbus_addr;
} dpdk_config_main_t;
@@ -459,6 +476,8 @@ clib_error_t *unformat_rss_fn (unformat_input_t * input, uword * rss_fn);
struct rte_pci_device *dpdk_get_pci_device (const struct rte_eth_dev_info
*info);
+struct rte_vmbus_device *
+dpdk_get_vmbus_device (const struct rte_eth_dev_info *info);
void dpdk_cli_reference (void);
#if CLI_DEBUG
diff --git a/src/plugins/dpdk/device/init.c b/src/plugins/dpdk/device/init.c
index 19898b186fe..f3d228c5820 100644
--- a/src/plugins/dpdk/device/init.c
+++ b/src/plugins/dpdk/device/init.c
@@ -249,9 +249,11 @@ dpdk_lib_init (dpdk_main_t * dm)
int vlan_off;
struct rte_eth_dev_info dev_info;
struct rte_pci_device *pci_dev;
+ struct rte_vmbus_device *vmbus_dev;
dpdk_portid_t next_port_id;
dpdk_device_config_t *devconf = 0;
vlib_pci_addr_t pci_addr;
+ vlib_vmbus_addr_t vmbus_addr;
uword *p = 0;
if (!rte_eth_dev_is_valid_port(i))
@@ -278,20 +280,42 @@ dpdk_lib_init (dpdk_main_t * dm)
pci_addr.as_u32);
}
+ vmbus_dev = dpdk_get_vmbus_device (&dev_info);
+
+ if (vmbus_dev)
+ {
+ unformat_input_t input_vmbus;
+
+ unformat_init_vector (&input_vmbus, (u8 *) dev_info.device->name);
+ if (unformat (&input_vmbus, "%U", unformat_vlib_vmbus_addr,
+ &vmbus_addr))
+ {
+ p = hash_get (dm->conf->device_config_index_by_vmbus_addr,
+ vmbus_addr.as_u32[0]);
+ }
+ }
+
+ if (p)
+ {
+ devconf = pool_elt_at_index (dm->conf->dev_confs, p[0]);
+ /* If device is blacklisted, we should skip it */
+ if (devconf->is_blacklisted)
+ {
+ continue;
+ }
+ }
+ else
+ devconf = &dm->conf->default_devconf;
/* Create vnet interface */
vec_add2_aligned (dm->devices, xd, 1, CLIB_CACHE_LINE_BYTES);
xd->nb_rx_desc = DPDK_NB_RX_DESC_DEFAULT;
xd->nb_tx_desc = DPDK_NB_TX_DESC_DEFAULT;
xd->cpu_socket = (i8) rte_eth_dev_socket_id (i);
-
if (p)
{
- devconf = pool_elt_at_index (dm->conf->dev_confs, p[0]);
xd->name = devconf->name;
}
- else
- devconf = &dm->conf->default_devconf;
/* Handle representor devices that share the same PCI ID */
if (dev_info.switch_info.domain_id != RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID)
@@ -876,9 +900,9 @@ dpdk_bind_devices_to_uio (dpdk_config_main_t * conf)
if (!p)
{
- skipped:
- continue;
- }
+ skipped_pci:
+ continue;
+ }
devconf = pool_elt_at_index (conf->dev_confs, p[0]);
}
@@ -902,12 +926,13 @@ dpdk_bind_devices_to_uio (dpdk_config_main_t * conf)
hash_set (conf->device_config_index_by_pci_addr, addr->as_u32,
devconf - conf->dev_confs);
devconf->pci_addr.as_u32 = addr->as_u32;
- devconf->is_blacklisted = 1;
- goto skipped;
- }
- else /* explicitly whitelisted, ignore the device blacklist */
- break;
- }
+ devconf->dev_addr_type = VNET_DEV_ADDR_PCI;
+ devconf->is_blacklisted = 1;
+ goto skipped_pci;
+ }
+ else /* explicitly whitelisted, ignore the device blacklist */
+ break;
+ }
}
/* virtio */
@@ -1002,6 +1027,7 @@ dpdk_bind_devices_to_uio (dpdk_config_main_t * conf)
devconf - conf->dev_confs);
devconf->pci_addr.as_u32 = addr->as_u32;
}
+ devconf->dev_addr_type = VNET_DEV_ADDR_PCI;
devconf->is_blacklisted = 1;
clib_error_report (error);
}
@@ -1016,16 +1042,72 @@ dpdk_bind_vmbus_devices_to_uio (dpdk_config_main_t * conf)
{
clib_error_t *error;
vlib_vmbus_addr_t *addrs, *addr = 0;
+ int num_whitelisted = vec_len (conf->dev_confs);
+ int i;
addrs = vlib_vmbus_get_all_dev_addrs ();
/* *INDENT-OFF* */
vec_foreach (addr, addrs)
{
- error = vlib_vmbus_bind_to_uio (addr);
+ dpdk_device_config_t *devconf = 0;
+ if (num_whitelisted)
+ {
+ uword *p = hash_get (conf->device_config_index_by_vmbus_addr,
+ addr->as_u32[0]);
+ if (!p)
+ {
+ /* No devices blacklisted, but have whitelisted. blacklist all
+ * non-whitelisted */
+ pool_get (conf->dev_confs, devconf);
+ hash_set (conf->device_config_index_by_vmbus_addr,
+ addr->as_u32[0], devconf - conf->dev_confs);
+ devconf->vmbus_addr = *addr;
+ devconf->dev_addr_type = VNET_DEV_ADDR_VMBUS;
+ devconf->is_blacklisted = 1;
+ skipped_vmbus:
+ continue;
+ }
+
+ devconf = pool_elt_at_index (conf->dev_confs, p[0]);
+ }
+
+ /* Enforce Device blacklist by vmbus_addr */
+ for (i = 0; i < vec_len (conf->blacklist_by_vmbus_addr); i++)
+ {
+ u32 vmbus_as_u32 = conf->blacklist_by_vmbus_addr[i];
+ if (vmbus_as_u32 == addr->as_u32[0])
+ {
+ if (devconf == 0)
+ {
+ /* Device not whitelisted */
+ pool_get (conf->dev_confs, devconf);
+ hash_set (conf->device_config_index_by_vmbus_addr,
+ addr->as_u32[0], devconf - conf->dev_confs);
+ devconf->vmbus_addr = *addr;
+ devconf->dev_addr_type = VNET_DEV_ADDR_VMBUS;
+ devconf->is_blacklisted = 1;
+ goto skipped_vmbus;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ error = vlib_vmbus_bind_to_uio (addr);
if (error)
{
+ if (devconf == 0)
+ {
+ pool_get (conf->dev_confs, devconf);
+ hash_set (conf->device_config_index_by_vmbus_addr,
+ addr->as_u32[0], devconf - conf->dev_confs);
+ devconf->vmbus_addr = *addr;
+ }
+ devconf->dev_addr_type = VNET_DEV_ADDR_VMBUS;
+ devconf->is_blacklisted = 1;
clib_error_report (error);
}
}
@@ -1033,36 +1115,66 @@ dpdk_bind_vmbus_devices_to_uio (dpdk_config_main_t * conf)
}
static clib_error_t *
-dpdk_device_config (dpdk_config_main_t * conf, vlib_pci_addr_t pci_addr,
- unformat_input_t * input, u8 is_default)
+dpdk_device_config (dpdk_config_main_t *conf, void *addr,
+ dpdk_device_addr_type_t addr_type, unformat_input_t *input,
+ u8 is_default)
{
clib_error_t *error = 0;
uword *p;
- dpdk_device_config_t *devconf;
+ dpdk_device_config_t *devconf = 0;
unformat_input_t sub_input;
if (is_default)
{
devconf = &conf->default_devconf;
}
- else
+ else if (addr_type == VNET_DEV_ADDR_PCI)
{
- p = hash_get (conf->device_config_index_by_pci_addr, pci_addr.as_u32);
+ p = hash_get (conf->device_config_index_by_pci_addr,
+ ((vlib_pci_addr_t *) (addr))->as_u32);
if (!p)
{
pool_get (conf->dev_confs, devconf);
- hash_set (conf->device_config_index_by_pci_addr, pci_addr.as_u32,
+ hash_set (conf->device_config_index_by_pci_addr,
+ ((vlib_pci_addr_t *) (addr))->as_u32,
devconf - conf->dev_confs);
}
else
return clib_error_return (0,
"duplicate configuration for PCI address %U",
- format_vlib_pci_addr, &pci_addr);
+ format_vlib_pci_addr, addr);
+ }
+ else if (addr_type == VNET_DEV_ADDR_VMBUS)
+ {
+ p = hash_get (conf->device_config_index_by_vmbus_addr,
+ ((vlib_vmbus_addr_t *) (addr))->as_u32[0]);
+
+ if (!p)
+ {
+ pool_get (conf->dev_confs, devconf);
+ hash_set (conf->device_config_index_by_vmbus_addr,
+ ((vlib_vmbus_addr_t *) (addr))->as_u32[0],
+ devconf - conf->dev_confs);
+ }
+ else
+ return clib_error_return (
+ 0, "duplicate configuration for VMBUS address %U",
+ format_vlib_vmbus_addr, addr);
}
- devconf->pci_addr.as_u32 = pci_addr.as_u32;
- devconf->tso = DPDK_DEVICE_TSO_DEFAULT;
+ if (addr_type == VNET_DEV_ADDR_PCI)
+ {
+ devconf->pci_addr.as_u32 = ((vlib_pci_addr_t *) (addr))->as_u32;
+ devconf->tso = DPDK_DEVICE_TSO_DEFAULT;
+ devconf->dev_addr_type = VNET_DEV_ADDR_PCI;
+ }
+ else if (addr_type == VNET_DEV_ADDR_VMBUS)
+ {
+ devconf->vmbus_addr = *((vlib_vmbus_addr_t *) (addr));
+ devconf->tso = DPDK_DEVICE_TSO_DEFAULT;
+ devconf->dev_addr_type = VNET_DEV_ADDR_VMBUS;
+ }
if (!input)
return 0;
@@ -1124,11 +1236,10 @@ dpdk_device_config (dpdk_config_main_t * conf, vlib_pci_addr_t pci_addr,
else if (devconf->workers &&
clib_bitmap_count_set_bits (devconf->workers) !=
devconf->num_rx_queues)
- error =
- clib_error_return (0,
- "%U: number of worker threads must be "
- "equal to number of rx queues", format_vlib_pci_addr,
- &pci_addr);
+ error = clib_error_return (0,
+ "%U: number of worker threads must be "
+ "equal to number of rx queues",
+ format_vlib_pci_addr, addr);
return error;
}
@@ -1171,7 +1282,8 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
dpdk_config_main_t *conf = &dpdk_config_main;
vlib_thread_main_t *tm = vlib_get_thread_main ();
dpdk_device_config_t *devconf;
- vlib_pci_addr_t pci_addr;
+ vlib_pci_addr_t pci_addr = { 0 };
+ vlib_vmbus_addr_t vmbus_addr = { 0 };
unformat_input_t sub_input;
uword default_hugepage_sz, x;
u8 *s, *tmp = 0;
@@ -1189,6 +1301,7 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
format (0, "%s/hugepages%c", vlib_unix_get_runtime_dir (), 0);
conf->device_config_index_by_pci_addr = hash_create (0, sizeof (uword));
+ conf->device_config_index_by_vmbus_addr = hash_create (0, sizeof (uword));
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
@@ -1217,8 +1330,7 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
&sub_input))
{
error =
- dpdk_device_config (conf, (vlib_pci_addr_t) (u32) ~ 1, &sub_input,
- 1);
+ dpdk_device_config (conf, 0, VNET_DEV_ADDR_ANY, &sub_input, 1);
if (error)
return error;
@@ -1228,7 +1340,8 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
(input, "dev %U %U", unformat_vlib_pci_addr, &pci_addr,
unformat_vlib_cli_sub_input, &sub_input))
{
- error = dpdk_device_config (conf, pci_addr, &sub_input, 0);
+ error = dpdk_device_config (conf, &pci_addr, VNET_DEV_ADDR_PCI,
+ &sub_input, 0);
if (error)
return error;
@@ -1237,7 +1350,30 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
}
else if (unformat (input, "dev %U", unformat_vlib_pci_addr, &pci_addr))
{
- error = dpdk_device_config (conf, pci_addr, 0, 0);
+ error =
+ dpdk_device_config (conf, &pci_addr, VNET_DEV_ADDR_PCI, 0, 0);
+
+ if (error)
+ return error;
+
+ num_whitelisted++;
+ }
+ else if (unformat (input, "dev %U %U", unformat_vlib_vmbus_addr,
+ &vmbus_addr, unformat_vlib_cli_sub_input, &sub_input))
+ {
+ error = dpdk_device_config (conf, &vmbus_addr, VNET_DEV_ADDR_VMBUS,
+ &sub_input, 0);
+
+ if (error)
+ return error;
+
+ num_whitelisted++;
+ }
+ else if (unformat (input, "dev %U", unformat_vlib_vmbus_addr,
+ &vmbus_addr))
+ {
+ error =
+ dpdk_device_config (conf, &vmbus_addr, VNET_DEV_ADDR_VMBUS, 0, 0);
if (error)
return error;
@@ -1259,6 +1395,11 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
tmp = format (0, "--no-pci%c", 0);
vec_add1 (conf->eal_init_args, tmp);
}
+ else if (unformat (input, "blacklist %U", unformat_vlib_vmbus_addr,
+ &vmbus_addr))
+ {
+ vec_add1 (conf->blacklist_by_vmbus_addr, vmbus_addr.as_u32[0]);
+ }
else
if (unformat
(input, "blacklist %x:%x:%x.%x", &domain, &bus, &device, &func))
@@ -1434,23 +1575,21 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
/* default per-device config items */
foreach_dpdk_device_config_item
- /* copy vlan_strip config from default device */
- if (devconf->vlan_strip_offload == 0 &&
- conf->default_devconf.vlan_strip_offload > 0)
- devconf->vlan_strip_offload =
- conf->default_devconf.vlan_strip_offload;
+ /* copy vlan_strip config from default device */
+ _ (vlan_strip_offload)
- /* copy tso config from default device */
- _(tso)
+ /* copy tso config from default device */
+ _ (tso)
- /* copy tso config from default device */
- _(devargs)
+ /* copy tso config from default device */
+ _ (devargs)
- /* copy rss_queues config from default device */
- _(rss_queues)
+ /* copy rss_queues config from default device */
+ _ (rss_queues)
- /* add DPDK EAL whitelist/blacklist entry */
- if (num_whitelisted > 0 && devconf->is_blacklisted == 0)
+ /* add DPDK EAL whitelist/blacklist entry */
+ if (num_whitelisted > 0 && devconf->is_blacklisted == 0 &&
+ devconf->dev_addr_type == VNET_DEV_ADDR_PCI)
{
tmp = format (0, "-a%c", 0);
vec_add1 (conf->eal_init_args, tmp);
@@ -1464,7 +1603,8 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
}
vec_add1 (conf->eal_init_args, tmp);
}
- else if (num_whitelisted == 0 && devconf->is_blacklisted != 0)
+ else if (num_whitelisted == 0 && devconf->is_blacklisted != 0 &&
+ devconf->dev_addr_type == VNET_DEV_ADDR_PCI)
{
tmp = format (0, "-b%c", 0);
vec_add1 (conf->eal_init_args, tmp);
diff --git a/src/vlib/linux/vmbus.c b/src/vlib/linux/vmbus.c
index 2fc438b4778..d50b539910b 100644
--- a/src/vlib/linux/vmbus.c
+++ b/src/vlib/linux/vmbus.c
@@ -118,8 +118,8 @@ linux_vmbus_main_t linux_vmbus_main;
* "f2c086b2-ff2e-11e8-88de-7bad0a57de05" and convert
* it to u8[16]
*/
-static uword
-unformat_vlib_vmbus_addr (unformat_input_t * input, va_list * args)
+uword
+unformat_vlib_vmbus_addr (unformat_input_t *input, va_list *args)
{
vlib_vmbus_addr_t *addr = va_arg (*args, vlib_vmbus_addr_t *);
uword ret = 0;
@@ -137,8 +137,8 @@ unformat_vlib_vmbus_addr (unformat_input_t * input, va_list * args)
}
/* Convert bus address to standard UUID string */
-static u8 *
-format_vlib_vmbus_addr (u8 * s, va_list * va)
+u8 *
+format_vlib_vmbus_addr (u8 *s, va_list *va)
{
vlib_vmbus_addr_t *addr = va_arg (*va, vlib_vmbus_addr_t *);
char tmp[40];
@@ -297,15 +297,21 @@ vlib_vmbus_bind_to_uio (vlib_vmbus_addr_t * addr)
vec_reset_length (s);
s = format (s, "%s/%s/new_id%c", sysfs_vmbus_drv_path, uio_drv_name, 0);
error = clib_sysfs_write ((char *) s, "%s", netvsc_uuid);
-
+ /* If device already exists, we can bind/unbind/override driver */
if (error)
{
- close (fd);
- goto done;
+ if (error->code == EEXIST)
+ {
+ clib_error_free (error);
+ }
+ else
+ {
+ close (fd);
+ goto done;
+ }
}
uio_new_id_needed = 0;
-
}
error = vlib_vmbus_raise_lower (fd, ifname);
diff --git a/src/vlib/vmbus/vmbus.c b/src/vlib/vmbus/vmbus.c
index eadf5f176d6..045e2dd9503 100644
--- a/src/vlib/vmbus/vmbus.c
+++ b/src/vlib/vmbus/vmbus.c
@@ -25,11 +25,24 @@
#include <net/if.h>
/* this is a stub replaced by the Linux specfic version */
-vlib_vmbus_addr_t * __attribute__ ((weak)) vlib_vmbus_get_all_dev_addrs ()
+vlib_vmbus_addr_t *__clib_weak
+vlib_vmbus_get_all_dev_addrs ()
{
return NULL;
}
+u8 *__clib_weak
+format_vlib_vmbus_addr (u8 *s, va_list *va)
+{
+ return 0;
+}
+
+uword __clib_weak
+unformat_vlib_vmbus_addr (unformat_input_t *input, va_list *args)
+{
+ return 0;
+}
+
clib_error_t *
vmbus_bus_init (vlib_main_t * vm)
{
diff --git a/src/vlib/vmbus/vmbus.h b/src/vlib/vmbus/vmbus.h
index 0927b8990d6..7df62ab4d16 100644
--- a/src/vlib/vmbus/vmbus.h
+++ b/src/vlib/vmbus/vmbus.h
@@ -21,10 +21,12 @@
#include <vlib/vlib.h>
-typedef struct
+typedef union
{
u8 guid[16];
+ u32 as_u32[4];
} vlib_vmbus_addr_t;
+
typedef u32 vlib_vmbus_dev_handle_t;
vlib_vmbus_addr_t *vlib_vmbus_get_all_dev_addrs ();
@@ -33,6 +35,8 @@ uword vlib_vmbus_get_private_data (vlib_vmbus_dev_handle_t h);
void vlib_vmbus_set_private_data (vlib_vmbus_dev_handle_t h,
uword private_data);
+format_function_t format_vlib_vmbus_addr;
+unformat_function_t unformat_vlib_vmbus_addr;
clib_error_t *vlib_vmbus_bind_to_uio (vlib_vmbus_addr_t * addr);
#endif /* included_vlib_vmbus_h */