From: Nicol?s Pernas Maradei <n...@emutex.com>

Virtual and physical devices are now treated the same in terms of
white/black listing. Virtual devices can be defined using --vdev as
before and also whitelisted (using -w vdev_name) or blacklisted (using -b
vdev_name). This allows the user to have only a virtual device (port) in
use.

Signed-off-by: Nicol?s Pernas Maradei <nico at emutex.com>
---
 app/test-pmd/cmdline.c                      |   5 +-
 app/test/commands.c                         |   4 +-
 app/test/test_devargs.c                     |  69 +++++-----
 app/test/test_pci.c                         |   3 +-
 lib/librte_eal/bsdapp/eal/eal.c             |   8 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c         |   2 +-
 lib/librte_eal/common/eal_common_dev.c      |  24 ++--
 lib/librte_eal/common/eal_common_devargs.c  | 196 ++++++++++++++++++++--------
 lib/librte_eal/common/eal_common_options.c  |  11 +-
 lib/librte_eal/common/eal_common_pci.c      |  11 +-
 lib/librte_eal/common/include/rte_devargs.h | 124 +++++++++++++-----
 lib/librte_eal/linuxapp/eal/eal.c           |   8 +-
 lib/librte_eal/linuxapp/eal/eal_pci.c       |   2 +-
 13 files changed, 319 insertions(+), 148 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 4c3fc76..f6ba4fe 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -6844,6 +6844,8 @@ static void cmd_dump_parsed(void *parsed_result,
                rte_mempool_list_dump(stdout);
        else if (!strcmp(res->dump, "dump_devargs"))
                rte_eal_devargs_dump(stdout);
+       else if (!strcmp(res->dump, "dump_vdevargs"))
+               rte_eal_vdevargs_dump(stdout);
 }

 cmdline_parse_token_string_t cmd_dump_dump =
@@ -6854,7 +6856,8 @@ cmdline_parse_token_string_t cmd_dump_dump =
                "dump_struct_sizes#"
                "dump_ring#"
                "dump_mempool#"
-               "dump_devargs");
+               "dump_devargs#"
+               "dump_vdevargs");

 cmdline_parse_inst_t cmd_dump = {
        .f = cmd_dump_parsed,  /* function to call */
diff --git a/app/test/commands.c b/app/test/commands.c
index 92a17ed..6799d63 100644
--- a/app/test/commands.c
+++ b/app/test/commands.c
@@ -161,13 +161,15 @@ static void cmd_dump_parsed(void *parsed_result,
                rte_mempool_list_dump(stdout);
        else if (!strcmp(res->dump, "dump_devargs"))
                rte_eal_devargs_dump(stdout);
+       else if (!strcmp(res->dump, "dump_vdevargs"))
+               rte_eal_vdevargs_dump(stdout);
 }

 cmdline_parse_token_string_t cmd_dump_dump =
        TOKEN_STRING_INITIALIZER(struct cmd_dump_result, dump,
                                 "dump_physmem#dump_memzone#dump_log_history#"
                                 "dump_struct_sizes#dump_ring#dump_mempool#"
-                                "dump_devargs");
+                                "dump_devargs#dump_vdevargs");

 cmdline_parse_inst_t cmd_dump = {
        .f = cmd_dump_parsed,  /* function to call */
diff --git a/app/test/test_devargs.c b/app/test/test_devargs.c
index f0acf8e..8fb93df 100644
--- a/app/test/test_devargs.c
+++ b/app/test/test_devargs.c
@@ -52,52 +52,60 @@ static void free_devargs_list(void)
        }
 }

+/* clear vdevargs list that was modified by the test */
+static void free_vdevargs_list(void)
+{
+       struct rte_vdevargs *vdevargs;
+
+       while (!TAILQ_EMPTY(&vdevargs_list)) {
+               vdevargs = TAILQ_FIRST(&vdevargs_list);
+               TAILQ_REMOVE(&vdevargs_list, vdevargs, next);
+               free(vdevargs);
+       }
+}
+
 static int
 test_devargs(void)
 {
        struct rte_devargs_list save_devargs_list;
+       struct rte_vdevargs_list save_vdevargs_list;
        struct rte_devargs *devargs;
+       struct rte_vdevargs *vdevargs;

        /* save the real devargs_list, it is restored at the end of the test */
        save_devargs_list = devargs_list;
+       save_vdevargs_list = vdevargs_list;
        TAILQ_INIT(&devargs_list);
+       TAILQ_INIT(&vdevargs_list);

        /* test valid cases */
-       if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, "08:00.1") < 0)
-               goto fail;
-       if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, "0000:5:00.0") < 0)
-               goto fail;
-       if (rte_eal_devargs_add(RTE_DEVTYPE_BLACKLISTED_PCI, "04:00.0,arg=val") 
< 0)
-               goto fail;
-       if (rte_eal_devargs_add(RTE_DEVTYPE_BLACKLISTED_PCI, "0000:01:00.1") < 
0)
+       if (rte_eal_devargs_add(RTE_DEV_WHITELISTED, "08:00.1") < 0)
                goto fail;
-       if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) != 2)
+       if (rte_eal_devargs_add(RTE_DEV_WHITELISTED, "0000:5:00.0") < 0)
                goto fail;
-       if (rte_eal_devargs_type_count(RTE_DEVTYPE_BLACKLISTED_PCI) != 2)
+       if (rte_eal_devargs_add(RTE_DEV_BLACKLISTED, "04:00.0") < 0)
                goto fail;
-       if (rte_eal_devargs_type_count(RTE_DEVTYPE_VIRTUAL) != 0)
+       if (rte_eal_devargs_add(RTE_DEV_BLACKLISTED, "0000:01:00.1") < 0)
                goto fail;
-       if (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL, "eth_ring0") < 0)
+       if (rte_eal_devargs_type_count(RTE_DEV_WHITELISTED) != 2)
                goto fail;
-       if (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL, 
"eth_ring1,key=val,k2=val2") < 0)
-               goto fail;
-       if (rte_eal_devargs_type_count(RTE_DEVTYPE_VIRTUAL) != 2)
+       if (rte_eal_devargs_type_count(RTE_DEV_BLACKLISTED) != 2)
                goto fail;
        free_devargs_list();

        /* check virtual device with argument parsing */
-       if (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL, 
"eth_ring1,k1=val,k2=val2") < 0)
+       if (rte_eal_vdevargs_add("eth_ring1,k1=val,k2=val2") < 0)
                goto fail;
-       devargs = TAILQ_FIRST(&devargs_list);
-       if (strncmp(devargs->virtual.drv_name, "eth_ring1",
-                       sizeof(devargs->virtual.drv_name) != 0))
+       vdevargs = TAILQ_FIRST(&vdevargs_list);
+       if (strncmp(vdevargs->drv_name, "eth_ring1",
+                       sizeof(vdevargs->drv_name) != 0))
                goto fail;
-       if (strncmp(devargs->args, "k1=val,k2=val2", sizeof(devargs->args) != 
0))
+       if (strncmp(vdevargs->args, "k1=val,k2=val2", sizeof(vdevargs->args) != 
0))
                goto fail;
-       free_devargs_list();
+       free_vdevargs_list();

        /* check PCI device with empty argument parsing */
-       if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, "04:00.1") < 0)
+       if (rte_eal_devargs_add(RTE_DEV_WHITELISTED, "04:00.1") < 0)
                goto fail;
        devargs = TAILQ_FIRST(&devargs_list);
        if (devargs->pci.addr.domain != 0 ||
@@ -105,28 +113,25 @@ test_devargs(void)
                devargs->pci.addr.devid != 0 ||
                devargs->pci.addr.function != 1)
                goto fail;
-       if (strncmp(devargs->args, "", sizeof(devargs->args) != 0))
-               goto fail;
        free_devargs_list();

-       /* test error case: bad PCI address */
-       if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, "08:1") == 0)
+       /* Check that virtual devices can be also whitelisted */
+       if (rte_eal_devargs_add(RTE_DEV_WHITELISTED, "eth_pcap0") < 0)
                goto fail;
-       if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, "00.1") == 0)
-               goto fail;
-       if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, "foo") == 0)
-               goto fail;
-       if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, ",") == 0)
-               goto fail;
-       if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, "000f:0:0") == 0)
+       devargs = TAILQ_FIRST(&devargs_list);
+       if (strncmp(devargs->virtual.drv_name, "eth_pcap0",
+               sizeof(devargs->virtual.drv_name)) != 0)
                goto fail;

        devargs_list = save_devargs_list;
+       vdevargs_list = save_vdevargs_list;
        return 0;

  fail:
        free_devargs_list();
+       free_vdevargs_list();
        devargs_list = save_devargs_list;
+       vdevargs_list = save_vdevargs_list;
        return -1;
 }

diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index 4f0169a..308abb9 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -126,8 +126,7 @@ blacklist_all_devices(void)
                snprintf(pci_addr_str, sizeof(pci_addr_str), PCI_PRI_FMT,
                        dev->addr.domain, dev->addr.bus, dev->addr.devid,
                        dev->addr.function);
-               if (rte_eal_devargs_add(RTE_DEVTYPE_BLACKLISTED_PCI,
-                               pci_addr_str) < 0) {
+               if (rte_eal_devargs_add(RTE_DEV_BLACKLISTED, pci_addr_str) < 0) 
{
                        printf("Error: cannot blacklist <%s>", pci_addr_str);
                        break;
                }
diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index ca99cb9..c59c203 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -429,14 +429,18 @@ eal_parse_args(int argc, char **argv)
                return -1;
        }

-       if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) != 0 &&
-               rte_eal_devargs_type_count(RTE_DEVTYPE_BLACKLISTED_PCI) != 0) {
+       if (rte_eal_devargs_type_count(RTE_DEV_WHITELISTED) != 0 &&
+               rte_eal_devargs_type_count(RTE_DEV_BLACKLISTED) != 0) {
                RTE_LOG(ERR, EAL, "Error: blacklist [-b] and whitelist "
                        "[-w] options cannot be used at the same time\n");
                eal_usage(prgname);
                return -1;
        }

+       /* Check if all white/black listed virtual devices were also defined */
+       if (rte_eal_check_vdevs_definition() < 0)
+               return -1;
+
        if (optind >= 0)
                argv[optind-1] = prgname;

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c 
b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 74ecce7..df179eb 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -462,7 +462,7 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, 
struct rte_pci_device *d

                /* no initialization when blacklisted, return without error */
                if (dev->devargs != NULL &&
-                       dev->devargs->type == RTE_DEVTYPE_BLACKLISTED_PCI) {
+                       dev->devargs->select == RTE_DEV_BLACKLISTED) {

                        RTE_LOG(DEBUG, EAL, "  Device is blacklisted, not 
initializing\n");
                        return 0;
diff --git a/lib/librte_eal/common/eal_common_dev.c 
b/lib/librte_eal/common/eal_common_dev.c
index eae5656..5181ba8 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -64,8 +64,11 @@ rte_eal_driver_unregister(struct rte_driver *driver)
 int
 rte_eal_dev_init(void)
 {
-       struct rte_devargs *devargs;
+       struct rte_vdevargs *vdevargs;
        struct rte_driver *driver;
+       int whitelisted_devs;
+
+       whitelisted_devs = rte_eal_devargs_type_count(RTE_DEV_WHITELISTED);

        /*
         * Note that the dev_driver_list is populated here
@@ -74,9 +77,13 @@ rte_eal_dev_init(void)
         */

        /* call the init function for each virtual device */
-       TAILQ_FOREACH(devargs, &devargs_list, next) {
+       TAILQ_FOREACH(vdevargs, &vdevargs_list, next) {
+
+               if (rte_eal_vdevargs_is(vdevargs, RTE_DEV_BLACKLISTED))
+                       continue;

-               if (devargs->type != RTE_DEVTYPE_VIRTUAL)
+               if (whitelisted_devs
+                       && !rte_eal_vdevargs_is(vdevargs, RTE_DEV_WHITELISTED))
                        continue;

                TAILQ_FOREACH(driver, &dev_driver_list, next) {
@@ -84,18 +91,15 @@ rte_eal_dev_init(void)
                                continue;

                        /* search a driver prefix in virtual device name */
-                       if (!strncmp(driver->name, devargs->virtual.drv_name,
+                       if (!strncmp(driver->name, vdevargs->drv_name,
                                        strlen(driver->name))) {
-                               driver->init(devargs->virtual.drv_name,
-                                       devargs->args);
+                               driver->init(vdevargs->drv_name, 
vdevargs->args);
                                break;
                        }
                }

-               if (driver == NULL) {
-                       rte_panic("no driver found for %s\n",
-                                 devargs->virtual.drv_name);
-               }
+               if (driver == NULL)
+                       rte_panic("no driver found for %s\n", 
vdevargs->drv_name);
        }

        /* Once the vdevs are initalized, start calling all the pdev drivers */
diff --git a/lib/librte_eal/common/eal_common_devargs.c 
b/lib/librte_eal/common/eal_common_devargs.c
index 4c7d11a..4171654 100644
--- a/lib/librte_eal/common/eal_common_devargs.c
+++ b/lib/librte_eal/common/eal_common_devargs.c
@@ -43,14 +43,15 @@
 /** Global list of user devices */
 struct rte_devargs_list devargs_list =
        TAILQ_HEAD_INITIALIZER(devargs_list);
+struct rte_vdevargs_list vdevargs_list =
+       TAILQ_HEAD_INITIALIZER(vdevargs_list);

 /* store a whitelist parameter for later parsing */
 int
-rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str)
+rte_eal_devargs_add(enum rte_devselect devselect, const char *devargs_str)
 {
        struct rte_devargs *devargs;
-       char buf[RTE_DEVARGS_LEN];
-       char *sep;
+       char buf[RTE_VDEV_NAME_LEN];
        int ret;

        ret = snprintf(buf, sizeof(buf), "%s", devargs_str);
@@ -67,86 +68,177 @@ rte_eal_devargs_add(enum rte_devtype devtype, const char 
*devargs_str)
                return -1;
        }
        memset(devargs, 0, sizeof(*devargs));
-       devargs->type = devtype;
+       devargs->select = devselect;
+
+       /* try to parse short PCI identifier */
+       if (eal_parse_pci_BDF(buf, &devargs->pci.addr) == 0)
+               goto done;
+
+       /* try to parse long PCI identifier */
+       if (eal_parse_pci_DomBDF(buf, &devargs->pci.addr) == 0)
+               goto done;
+
+       /* If device ID is not a valid PCI ID assume is a virtual driver name */
+       devargs->is_vdev = 1;
+       ret = snprintf(devargs->virtual.drv_name, 
sizeof(devargs->virtual.drv_name), "%s", buf);
+       if (ret < 0 || ret >= (int)sizeof(devargs->virtual.drv_name)) {
+               RTE_LOG(ERR, EAL, "driver name too large: <%s>\n", buf);
+               free(devargs);
+               return -1;
+       }
+
+done:
+       TAILQ_INSERT_TAIL(&devargs_list, devargs, next);
+       return 0;
+}
+
+int
+rte_eal_vdevargs_add(const char *vdevargs_str)
+{
+       struct rte_vdevargs *vdevargs;
+       char buf[RTE_VDEVARGS_LEN];
+       char *sep;
+       int ret;
+
+       ret = snprintf(buf, sizeof(buf), "%s", vdevargs_str);
+       if (ret < 0 || ret >= (int)sizeof(buf)) {
+               RTE_LOG(ERR, EAL, "user device args too large: <%s>\n", 
vdevargs_str);
+               return -1;
+       }
+
+       /* use malloc instead of rte_malloc as it's called early at init */
+       vdevargs = malloc(sizeof(*vdevargs));
+       if (vdevargs == NULL) {
+               RTE_LOG(ERR, EAL, "cannot allocate vdevargs\n");
+               return -1;
+       }
+       memset(vdevargs, 0, sizeof(*vdevargs));

        /* set the first ',' to '\0' to split name and arguments */
        sep = strchr(buf, ',');
        if (sep != NULL) {
                sep[0] = '\0';
-               snprintf(devargs->args, sizeof(devargs->args), "%s", sep + 1);
+               snprintf(vdevargs->args, sizeof(vdevargs->args), "%s", sep + 1);
        }

-       switch (devargs->type) {
-       case RTE_DEVTYPE_WHITELISTED_PCI:
-       case RTE_DEVTYPE_BLACKLISTED_PCI:
-               /* try to parse pci identifier */
-               if (eal_parse_pci_BDF(buf, &devargs->pci.addr) != 0 &&
-                       eal_parse_pci_DomBDF(buf, &devargs->pci.addr) != 0) {
-                       RTE_LOG(ERR, EAL,
-                               "invalid PCI identifier <%s>\n", buf);
-                       free(devargs);
-                       return -1;
-               }
-               break;
-       case RTE_DEVTYPE_VIRTUAL:
-               /* save driver name */
-               ret = snprintf(devargs->virtual.drv_name,
-                       sizeof(devargs->virtual.drv_name), "%s", buf);
-               if (ret < 0 || ret >= (int)sizeof(devargs->virtual.drv_name)) {
-                       RTE_LOG(ERR, EAL,
-                               "driver name too large: <%s>\n", buf);
-                       free(devargs);
-                       return -1;
-               }
-               break;
+       /* save driver name */
+       ret = snprintf(vdevargs->drv_name, sizeof(vdevargs->drv_name), "%s", 
buf);
+       if (ret < 0 || ret >= (int)sizeof(vdevargs->drv_name)) {
+               RTE_LOG(ERR, EAL, "driver name too large: <%s>\n", buf);
+               free(vdevargs);
+               return -1;
        }

-       TAILQ_INSERT_TAIL(&devargs_list, devargs, next);
+       TAILQ_INSERT_TAIL(&vdevargs_list, vdevargs, next);
        return 0;
 }

 /* count the number of devices of a specified type */
 unsigned int
-rte_eal_devargs_type_count(enum rte_devtype devtype)
+rte_eal_devargs_type_count(enum rte_devselect devselect)
 {
        struct rte_devargs *devargs;
        unsigned int count = 0;

        TAILQ_FOREACH(devargs, &devargs_list, next) {
-               if (devargs->type != devtype)
+               if (devargs->select != devselect)
                        continue;
                count++;
        }
        return count;
 }

-/* dump the user devices on the console */
+int
+rte_eal_vdevargs_is(struct rte_vdevargs *vdevargs, enum rte_devselect 
devselect)
+{
+       struct rte_devargs *devargs;
+
+       TAILQ_FOREACH(devargs, &devargs_list, next) {
+               if (!devargs->is_vdev)
+                       continue;
+
+               if (!strncmp(vdevargs->drv_name, devargs->virtual.drv_name,
+                               sizeof(vdevargs->drv_name)))
+                       return !!(devargs->select == devselect);
+       }
+       return 0;
+}
+
+/* dump the user selected devices on the console */
 void
 rte_eal_devargs_dump(FILE *f)
 {
        struct rte_devargs *devargs;

-       fprintf(f, "User device white list:\n");
+       fprintf(f, "User selected devices list:\n");
        TAILQ_FOREACH(devargs, &devargs_list, next) {
-               if (devargs->type == RTE_DEVTYPE_WHITELISTED_PCI)
-                       fprintf(f, "  PCI whitelist " PCI_PRI_FMT " %s\n",
-                              devargs->pci.addr.domain,
-                              devargs->pci.addr.bus,
-                              devargs->pci.addr.devid,
-                              devargs->pci.addr.function,
-                              devargs->args);
-               else if (devargs->type == RTE_DEVTYPE_BLACKLISTED_PCI)
-                       fprintf(f, "  PCI blacklist " PCI_PRI_FMT " %s\n",
-                              devargs->pci.addr.domain,
-                              devargs->pci.addr.bus,
-                              devargs->pci.addr.devid,
-                              devargs->pci.addr.function,
-                              devargs->args);
-               else if (devargs->type == RTE_DEVTYPE_VIRTUAL)
-                       fprintf(f, "  VIRTUAL %s %s\n",
-                              devargs->virtual.drv_name,
-                              devargs->args);
+               if (devargs->select == RTE_DEV_WHITELISTED)
+                       fprintf(f, "  PCI whitelist ");
+               else if (devargs->select == RTE_DEV_BLACKLISTED)
+                       fprintf(f, "  PCI blacklist ");
+               else
+                       fprintf(f, "  UNKNOWN ");
+
+               if (devargs->is_vdev)
+                       fprintf(f, "(VIRTUAL) %s %s\n", 
devargs->virtual.vdev->drv_name,
+                               devargs->virtual.vdev->args);
                else
-                       fprintf(f, "  UNKNOWN %s\n", devargs->args);
+                       fprintf(f, PCI_PRI_FMT "\n",
+                               devargs->pci.addr.domain,
+                               devargs->pci.addr.bus,
+                               devargs->pci.addr.devid,
+                               devargs->pci.addr.function);
+       }
+}
+
+/* dump the user virtual devices on the console */
+void
+rte_eal_vdevargs_dump(FILE *f)
+{
+       struct rte_vdevargs *vdevargs;
+
+       fprintf(f, "User virtual devices list:\n");
+       TAILQ_FOREACH(vdevargs, &vdevargs_list, next) {
+               fprintf(f, "  VIRTUAL %s %s\n",
+                       vdevargs->drv_name,
+                       vdevargs->args);
+       }
+}
+
+int
+rte_eal_check_vdevs_definition(void)
+{
+       struct rte_devargs *devargs;
+       struct rte_vdevargs *vdevargs;
+       int found;
+
+       /* Go through all white/black listed devices */
+       TAILQ_FOREACH(devargs, &devargs_list, next) {
+
+               /* Only check the virtual ones */
+               if (!devargs->is_vdev)
+                       continue;
+
+               /* Search for the virtual device definition */
+               found = 0;
+               TAILQ_FOREACH(vdevargs, &vdevargs_list, next) {
+                       if (!strncmp(vdevargs->drv_name, 
devargs->virtual.drv_name,
+                                       sizeof(vdevargs->drv_name))) {
+                               found = 1;
+                               devargs->virtual.vdev = vdevargs;
+                       }
+               }
+
+               /* If the virtual device was not defined return an error */
+               if (!found) {
+                       RTE_LOG(ERR, EAL, "Virtual device %s is %slisted but 
not defined. "
+                                       "Use '--vdev=%s,...' to define it.\n",
+                                       devargs->virtual.drv_name,
+                                       devargs->select == RTE_DEV_WHITELISTED 
? "white" : "black",
+                                       devargs->virtual.drv_name);
+                       return -1;
+               }
        }
+
+       return 0;
 }
diff --git a/lib/librte_eal/common/eal_common_options.c 
b/lib/librte_eal/common/eal_common_options.c
index 7a5d55e..e044a51 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -244,17 +244,13 @@ eal_parse_common_option(int opt, const char *optarg,
        switch (opt) {
        /* blacklist */
        case 'b':
-               if (rte_eal_devargs_add(RTE_DEVTYPE_BLACKLISTED_PCI,
-                               optarg) < 0) {
+               if (rte_eal_devargs_add(RTE_DEV_BLACKLISTED, optarg) < 0)
                        return -1;
-               }
                break;
        /* whitelist */
        case 'w':
-               if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI,
-                               optarg) < 0) {
+               if (rte_eal_devargs_add(RTE_DEV_WHITELISTED, optarg) < 0)
                        return -1;
-               }
                break;
        /* coremask */
        case 'c':
@@ -321,8 +317,7 @@ eal_parse_common_option(int opt, const char *optarg,
                break;

        case OPT_VDEV_NUM:
-               if (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL,
-                               optarg) < 0) {
+               if (rte_eal_vdevargs_add(optarg) < 0) {
                        return -1;
                }
                break;
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index f3c7f71..19b3ce4 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -85,13 +85,14 @@
 struct pci_driver_list pci_driver_list;
 struct pci_device_list pci_device_list;

-static struct rte_devargs *pci_devargs_lookup(struct rte_pci_device *dev)
+static struct rte_devargs *
+pci_devargs_lookup(struct rte_pci_device *dev)
 {
        struct rte_devargs *devargs;

        TAILQ_FOREACH(devargs, &devargs_list, next) {
-               if (devargs->type != RTE_DEVTYPE_BLACKLISTED_PCI &&
-                       devargs->type != RTE_DEVTYPE_WHITELISTED_PCI)
+               if (devargs->select != RTE_DEV_BLACKLISTED &&
+                       devargs->select != RTE_DEV_WHITELISTED)
                        continue;
                if (!memcmp(&dev->addr, &devargs->pci.addr, sizeof(dev->addr)))
                        return devargs;
@@ -136,7 +137,7 @@ rte_eal_pci_probe(void)
        int probe_all = 0;
        int ret = 0;

-       if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
+       if (rte_eal_devargs_type_count(RTE_DEV_WHITELISTED) == 0)
                probe_all = 1;

        TAILQ_FOREACH(dev, &pci_device_list, next) {
@@ -150,7 +151,7 @@ rte_eal_pci_probe(void)
                if (probe_all)
                        ret = pci_probe_all_drivers(dev);
                else if (devargs != NULL &&
-                       devargs->type == RTE_DEVTYPE_WHITELISTED_PCI)
+                       devargs->select == RTE_DEV_WHITELISTED)
                        ret = pci_probe_all_drivers(dev);
                if (ret < 0)
                        rte_exit(EXIT_FAILURE, "Requested device " PCI_PRI_FMT
diff --git a/lib/librte_eal/common/include/rte_devargs.h 
b/lib/librte_eal/common/include/rte_devargs.h
index 9f9c98f..b6599ef 100644
--- a/lib/librte_eal/common/include/rte_devargs.h
+++ b/lib/librte_eal/common/include/rte_devargs.h
@@ -52,96 +52,158 @@ extern "C" {
 #include <sys/queue.h>
 #include <rte_pci.h>

+#define RTE_VDEV_NAME_LEN 32
+
 /**
- * Type of generic device
+ * Type of device selection
  */
-enum rte_devtype {
-       RTE_DEVTYPE_WHITELISTED_PCI,
-       RTE_DEVTYPE_BLACKLISTED_PCI,
-       RTE_DEVTYPE_VIRTUAL,
+enum rte_devselect {
+       RTE_DEV_WHITELISTED,
+       RTE_DEV_BLACKLISTED,
 };

 /**
- * Structure that stores a device given by the user with its arguments
+ * Structure that stores a virtual device given by the user with its arguments
+ *
+ * The structure stores the configuration of the device and its name which
+ * contains its driver name
+ */
+struct rte_vdevargs {
+       /** Next in list. */
+       TAILQ_ENTRY(rte_vdevargs) next;
+       /** Driver name. */
+       char drv_name[RTE_VDEV_NAME_LEN];
+#define RTE_VDEVARGS_LEN 256
+       char args[RTE_VDEVARGS_LEN]; /**< Arguments string as given by user. */
+};
+
+/**
+ * Structure that stores the user selected devices.
  *
  * A user device is a physical or a virtual device given by the user to
  * the DPDK application at startup through command line arguments.
  *
- * The structure stores the configuration of the device, its PCI
- * identifier if it's a PCI device or the driver name if it's a virtual
- * device.
+ * The devices can be whitelisted or blacklisted independently if they are
+ * physical or virtual devices.
  */
 struct rte_devargs {
        /** Next in list. */
        TAILQ_ENTRY(rte_devargs) next;
-       /** Type of device. */
-       enum rte_devtype type;
+       /** Type of device selection. */
+       enum rte_devselect select;
+       int is_vdev;
        union {
-               /** Used if type is RTE_DEVTYPE_*_PCI. */
+               /** Used if physical device. */
                struct {
                        /** PCI location. */
                        struct rte_pci_addr addr;
                } pci;
-               /** Used if type is RTE_DEVTYPE_VIRTUAL. */
+               /** Used if virtual device. */
                struct {
                        /** Driver name. */
-                       char drv_name[32];
+                       char drv_name[RTE_VDEV_NAME_LEN];
+                       struct rte_vdevargs *vdev;
                } virtual;
        };
-#define RTE_DEVARGS_LEN 256
-       char args[RTE_DEVARGS_LEN]; /**< Arguments string as given by user. */
 };

 /** user device double-linked queue type definition */
 TAILQ_HEAD(rte_devargs_list, rte_devargs);
+TAILQ_HEAD(rte_vdevargs_list, rte_vdevargs);

 /** Global list of user devices */
 extern struct rte_devargs_list devargs_list;

+/** Global list of virtual devices */
+extern struct rte_vdevargs_list vdevargs_list;
+
 /**
  * Add a device to the user device list
  *
- * For PCI devices, the format of arguments string is "PCI_ADDR" or
- * "PCI_ADDR,key=val,key2=val2,...". Examples: "08:00.1", "0000:5:00.0",
- * "04:00.0,arg=val".
+ * For PCI devices, the format of arguments string is "PCI_ADDR"
+ * Examples: "08:00.1", "0000:5:00.0".
  *
- * For virtual devices, the format of arguments string is "DRIVER_NAME*"
- * or "DRIVER_NAME*,key=val,key2=val2,...". Examples: "eth_ring",
- * "eth_ring0", "eth_pmdAnything,arg=0:arg2=1". The validity of the
- * driver name is not checked by this function, it is done when probing
- * the drivers.
+ * For virtual devices, the format of arguments string is "DRIVER_NAME".
+ * Examples: "eth_ring", "eth_ring0", "eth_pmdAnything". This function does not
+ * validate if the driver name is valid or if it was already defined with
+ * --vdev.
  *
- * @param devtype
- *   The type of the device.
- * @param devargs_list
+ * @param devselect
+ *   Whether the device is black or white listed.
+ * @param devargs_str
  *   The arguments as given by the user.
  *
  * @return
  *   - 0 on success
  *   - A negative value on error
  */
-int rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str);
+int rte_eal_devargs_add(enum rte_devselect devselect, const char *devargs_str);

 /**
  * Count the number of user devices of a specified type
  *
- * @param devtype
+ * @param devselect
  *   The type of the devices to counted.
  *
  * @return
  *   The number of devices.
  */
 unsigned int
-rte_eal_devargs_type_count(enum rte_devtype devtype);
+rte_eal_devargs_type_count(enum rte_devselect devselect);

 /**
- * This function dumps the list of user device and their arguments.
+ * This function dumps the list of user selected devices.
  *
  * @param f
  *   A pointer to a file for output
  */
 void rte_eal_devargs_dump(FILE *f);

+/**
+ * This function dumps the list of user virtual devices and their arguments.
+ *
+ * @param f
+ *   A pointer to a file for output
+ */
+void rte_eal_vdevargs_dump(FILE *f);
+
+/**
+ * Add a virtual device
+ *
+ * The format of arguments string is "DRIVER_NAME*"
+ * or "DRIVER_NAME*,key=val,key2=val2,...". Examples: "eth_ring",
+ * "eth_ring0", "eth_pmdAnything,arg=0:arg2=1". The validity of the
+ * driver name is not checked by this function, it is done when probing
+ * the drivers.
+ *
+ * @param devargs_str
+ *   The arguments as given by the user.
+ *
+ * @return
+ *   - 0 on success
+ *   - A negative value on error
+ */
+int rte_eal_vdevargs_add(const char *devargs_str);
+
+/**
+ * Check if the white/black-listed virtual devices have been defined
+ *
+ * @return
+ *   - 0 on success
+ *   - A negative value on error
+ */
+int rte_eal_check_vdevs_definition(void);
+
+/**
+ * Check if the virtual device is white/black-listed
+ *
+ * @return
+ *   - 1 if the device is white/black-listed.
+ *   - 0 otherwise.
+ */
+int rte_eal_vdevargs_is(struct rte_vdevargs *vdevargs,
+               enum rte_devselect devselect);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_eal/linuxapp/eal/eal.c 
b/lib/librte_eal/linuxapp/eal/eal.c
index 7a1d087..e898688 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -696,14 +696,18 @@ eal_parse_args(int argc, char **argv)
                return -1;
        }

-       if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) != 0 &&
-               rte_eal_devargs_type_count(RTE_DEVTYPE_BLACKLISTED_PCI) != 0) {
+       if (rte_eal_devargs_type_count(RTE_DEV_WHITELISTED) != 0 &&
+               rte_eal_devargs_type_count(RTE_DEV_BLACKLISTED) != 0) {
                RTE_LOG(ERR, EAL, "Error: blacklist [-b] and whitelist "
                        "[-w] options cannot be used at the same time\n");
                eal_usage(prgname);
                return -1;
        }

+       /* Check if all white/black listed virtual devices were also defined */
+       if (rte_eal_check_vdevs_definition() < 0)
+               return -1;
+
        if (optind >= 0)
                argv[optind-1] = prgname;

diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c 
b/lib/librte_eal/linuxapp/eal/eal_pci.c
index ddb0535..b49722e 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -544,7 +544,7 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, 
struct rte_pci_device *d

                /* no initialization when blacklisted, return without error */
                if (dev->devargs != NULL &&
-                       dev->devargs->type == RTE_DEVTYPE_BLACKLISTED_PCI) {
+                       dev->devargs->select == RTE_DEV_BLACKLISTED) {
                        RTE_LOG(DEBUG, EAL, "  Device is blacklisted, not 
initializing\n");
                        return 1;
                }
-- 
1.8.3.2

Reply via email to