From 56252de779a68df5f49c04a49b404fa693719d01 Mon Sep 17 00:00:00 2001 From: Matan Azrad Date: Thu, 18 Jan 2018 13:51:46 +0000 Subject: [PATCH] net/vdev_netvsc: add automatic probing Using DPDK in Hyper-V VM systems requires vdev_netvsc driver to pair the NetVSC netdev device with the same MAC address PCI device by fail-safe PMD. Add vdev_netvsc custom scan in vdev bus to allow automatic probing in Hyper-V VM systems unless it was already specified by command line. Add "ignore" parameter to disable this auto-detection. Signed-off-by: Matan Azrad --- doc/guides/nics/vdev_netvsc.rst | 9 ++++- drivers/net/vdev_netvsc/vdev_netvsc.c | 55 ++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/doc/guides/nics/vdev_netvsc.rst b/doc/guides/nics/vdev_netvsc.rst index 3c26990c54..55d130a3ed 100644 --- a/doc/guides/nics/vdev_netvsc.rst +++ b/doc/guides/nics/vdev_netvsc.rst @@ -71,8 +71,8 @@ Build options Run-time parameters ------------------- -To invoke this driver, applications have to explicitly provide the -``--vdev=net_vdev_netvsc`` EAL option. +This driver is invoked automatically in Hyper-V VM systems unless the user +invoked it by command line using ``--vdev=net_vdev_netvsc`` EAL option. The following device parameters are supported: @@ -91,5 +91,10 @@ The following device parameters are supported: If nonzero, forces the use of specified interfaces even if not detected as NetVSC or detected as routed NETVSC. +- ``ignore`` [int] + + If nonzero, ignores the driver runnig (actually used to disable the + auto-detection in Hyper-V VM). + Not specifying either ``iface`` or ``mac`` makes this driver attach itself to all unrouted NetVSC interfaces found on the system. diff --git a/drivers/net/vdev_netvsc/vdev_netvsc.c b/drivers/net/vdev_netvsc/vdev_netvsc.c index 2d030331b8..a8a1a7fe4e 100644 --- a/drivers/net/vdev_netvsc/vdev_netvsc.c +++ b/drivers/net/vdev_netvsc/vdev_netvsc.c @@ -30,13 +30,16 @@ #include #include #include +#include #include #include #define VDEV_NETVSC_DRIVER net_vdev_netvsc +#define VDEV_NETVSC_DRIVER_NAME RTE_STR(VDEV_NETVSC_DRIVER) #define VDEV_NETVSC_ARG_IFACE "iface" #define VDEV_NETVSC_ARG_MAC "mac" #define VDEV_NETVSC_ARG_FORCE "force" +#define VDEV_NETVSC_ARG_IGNORE "ignore" #define VDEV_NETVSC_PROBE_MS 1000 #define NETVSC_CLASS_ID "{f8615163-df3e-46c5-913f-f2d2f965ed0e}" @@ -45,7 +48,7 @@ #define DRV_LOG(level, ...) \ rte_log(RTE_LOG_ ## level, \ vdev_netvsc_logtype, \ - RTE_FMT(RTE_STR(VDEV_NETVSC_DRIVER) ": " \ + RTE_FMT(VDEV_NETVSC_DRIVER_NAME ": " \ RTE_FMT_HEAD(__VA_ARGS__,) "\n", \ RTE_FMT_TAIL(__VA_ARGS__,))) @@ -601,6 +604,7 @@ vdev_netvsc_vdev_probe(struct rte_vdev_device *dev) VDEV_NETVSC_ARG_IFACE, VDEV_NETVSC_ARG_MAC, VDEV_NETVSC_ARG_FORCE, + VDEV_NETVSC_ARG_IGNORE, NULL, }; const char *name = rte_vdev_device_name(dev); @@ -610,6 +614,7 @@ vdev_netvsc_vdev_probe(struct rte_vdev_device *dev) unsigned int specified = 0; unsigned int matched = 0; int force = 0; + int ignore = 0; unsigned int i; int ret; @@ -623,10 +628,17 @@ vdev_netvsc_vdev_probe(struct rte_vdev_device *dev) if (!strcmp(pair->key, VDEV_NETVSC_ARG_FORCE)) force = !!atoi(pair->value); + else if (!strcmp(pair->key, VDEV_NETVSC_ARG_IGNORE)) + ignore = !!atoi(pair->value); else if (!strcmp(pair->key, VDEV_NETVSC_ARG_IFACE) || !strcmp(pair->key, VDEV_NETVSC_ARG_MAC)) ++specified; } + if (ignore) { + if (kvargs) + rte_kvargs_free(kvargs); + return 0; + } rte_eal_alarm_cancel(vdev_netvsc_alarm, NULL); /* Gather interfaces. */ ret = vdev_netvsc_foreach_iface(vdev_netvsc_netvsc_probe, name, kvargs, @@ -690,7 +702,8 @@ RTE_PMD_REGISTER_ALIAS(VDEV_NETVSC_DRIVER, eth_vdev_netvsc); RTE_PMD_REGISTER_PARAM_STRING(net_vdev_netvsc, VDEV_NETVSC_ARG_IFACE "= " VDEV_NETVSC_ARG_MAC "= " - VDEV_NETVSC_ARG_FORCE "="); + VDEV_NETVSC_ARG_FORCE "= " + VDEV_NETVSC_ARG_IGNORE "="); /** Initialize driver log type. */ RTE_INIT(vdev_netvsc_init_log) @@ -699,3 +712,41 @@ RTE_INIT(vdev_netvsc_init_log) if (vdev_netvsc_logtype >= 0) rte_log_set_level(vdev_netvsc_logtype, RTE_LOG_NOTICE); } + +/** Compare function for vdev find device operation. */ +static int +vdev_netvsc_cmp_rte_device(const struct rte_device *dev1, + __rte_unused const void *_dev2) +{ + return strcmp(dev1->devargs->name, VDEV_NETVSC_DRIVER_NAME); +} + +/** + * A callback called by vdev bus scan function to ensure this driver probing + * automatically in Hyper-V VM system unless it already exists in the + * devargs list. + */ +static void +vdev_netvsc_scan_callback(__rte_unused void *arg) +{ + struct rte_vdev_device *dev; + struct rte_devargs *devargs; + struct rte_bus *vbus = rte_bus_find_by_name("vdev"); + + TAILQ_FOREACH(devargs, &devargs_list, next) + if (!strcmp(devargs->name, VDEV_NETVSC_DRIVER_NAME)) + return; + dev = (struct rte_vdev_device *)vbus->find_device(NULL, + vdev_netvsc_cmp_rte_device, VDEV_NETVSC_DRIVER_NAME); + if (dev) + return; + if (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL, VDEV_NETVSC_DRIVER_NAME)) + DRV_LOG(ERR, "unable to add netvsc devargs."); +} + +/** Initialize the custom scan. */ +RTE_INIT(vdev_netvsc_custom_scan_add) +{ + if (rte_hypervisor_get() == RTE_HYPERVISOR_HYPERV) + rte_vdev_add_custom_scan(vdev_netvsc_scan_callback, NULL); +} -- 2.20.1