get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/1316/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 1316,
    "url": "https://patches.dpdk.org/api/patches/1316/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1416173215-27533-1-git-send-email-nicolas.pernas.maradei@emutex.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1416173215-27533-1-git-send-email-nicolas.pernas.maradei@emutex.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1416173215-27533-1-git-send-email-nicolas.pernas.maradei@emutex.com",
    "date": "2014-11-16T21:26:55",
    "name": "[dpdk-dev] eal: allow virtual devices to be white/black listed",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "1d853d3fbecd8633813e3168e8c2ff6a76b7b567",
    "submitter": {
        "id": 115,
        "url": "https://patches.dpdk.org/api/people/115/?format=api",
        "name": "Nicolás Pernas Maradei",
        "email": "nicolas.pernas.maradei@emutex.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1416173215-27533-1-git-send-email-nicolas.pernas.maradei@emutex.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/1316/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/1316/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id DCAF27F74;\n\tSun, 16 Nov 2014 22:16:53 +0100 (CET)",
            "from smtp.digiweb.ie (smtp2.digiweb.ie [83.147.160.14])\n\tby dpdk.org (Postfix) with ESMTP id 0F0147F71\n\tfor <dev@dpdk.org>; Sun, 16 Nov 2014 22:16:52 +0100 (CET)",
            "from statler.emutex.com (unknown [92.51.199.138])\n\tby smtp.digiweb.ie (Postfix) with ESMTP id AE0C9290037\n\tfor <dev@dpdk.org>; Sun, 16 Nov 2014 21:27:02 +0000 (GMT)",
            "from [10.10.64.102] (helo=nico-emutex.emutex.com)\n\tby statler.emutex.com with esmtpsa\n\t(TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32)\n\t(Exim 4.72) (envelope-from <nicolas.pernas.maradei@emutex.com>)\n\tid 1Xq7La-0001u4-GR; Sun, 16 Nov 2014 21:27:02 +0000"
        ],
        "From": "=?UTF-8?q?Nicol=C3=A1s=20Pernas=20Maradei?=\n\t<nicolas.pernas.maradei@emutex.com>",
        "To": "dev@dpdk.org",
        "Date": "Sun, 16 Nov 2014 21:26:55 +0000",
        "Message-Id": "<1416173215-27533-1-git-send-email-nicolas.pernas.maradei@emutex.com>",
        "X-Mailer": "git-send-email 1.8.3.2",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "Cc": "=?UTF-8?q?Nicol=C3=A1s=20Pernas=20Maradei?= <nico@emutex.com>",
        "Subject": "[dpdk-dev] [PATCH] eal: allow virtual devices to be white/black\n\tlisted",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: Nicolás Pernas Maradei <nico@emutex.com>\n\nVirtual and physical devices are now treated the same in terms of\nwhite/black listing. Virtual devices can be defined using --vdev as\nbefore and also whitelisted (using -w vdev_name) or blacklisted (using -b\nvdev_name). This allows the user to have only a virtual device (port) in\nuse.\n\nSigned-off-by: Nicolás Pernas Maradei <nico@emutex.com>\n---\n app/test-pmd/cmdline.c                      |   5 +-\n app/test/commands.c                         |   4 +-\n app/test/test_devargs.c                     |  69 +++++-----\n app/test/test_pci.c                         |   3 +-\n lib/librte_eal/bsdapp/eal/eal.c             |   8 +-\n lib/librte_eal/bsdapp/eal/eal_pci.c         |   2 +-\n lib/librte_eal/common/eal_common_dev.c      |  24 ++--\n lib/librte_eal/common/eal_common_devargs.c  | 196 ++++++++++++++++++++--------\n lib/librte_eal/common/eal_common_options.c  |  11 +-\n lib/librte_eal/common/eal_common_pci.c      |  11 +-\n lib/librte_eal/common/include/rte_devargs.h | 124 +++++++++++++-----\n lib/librte_eal/linuxapp/eal/eal.c           |   8 +-\n lib/librte_eal/linuxapp/eal/eal_pci.c       |   2 +-\n 13 files changed, 319 insertions(+), 148 deletions(-)",
    "diff": "diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c\nindex 4c3fc76..f6ba4fe 100644\n--- a/app/test-pmd/cmdline.c\n+++ b/app/test-pmd/cmdline.c\n@@ -6844,6 +6844,8 @@ static void cmd_dump_parsed(void *parsed_result,\n \t\trte_mempool_list_dump(stdout);\n \telse if (!strcmp(res->dump, \"dump_devargs\"))\n \t\trte_eal_devargs_dump(stdout);\n+\telse if (!strcmp(res->dump, \"dump_vdevargs\"))\n+\t\trte_eal_vdevargs_dump(stdout);\n }\n \n cmdline_parse_token_string_t cmd_dump_dump =\n@@ -6854,7 +6856,8 @@ cmdline_parse_token_string_t cmd_dump_dump =\n \t\t\"dump_struct_sizes#\"\n \t\t\"dump_ring#\"\n \t\t\"dump_mempool#\"\n-\t\t\"dump_devargs\");\n+\t\t\"dump_devargs#\"\n+\t\t\"dump_vdevargs\");\n \n cmdline_parse_inst_t cmd_dump = {\n \t.f = cmd_dump_parsed,  /* function to call */\ndiff --git a/app/test/commands.c b/app/test/commands.c\nindex 92a17ed..6799d63 100644\n--- a/app/test/commands.c\n+++ b/app/test/commands.c\n@@ -161,13 +161,15 @@ static void cmd_dump_parsed(void *parsed_result,\n \t\trte_mempool_list_dump(stdout);\n \telse if (!strcmp(res->dump, \"dump_devargs\"))\n \t\trte_eal_devargs_dump(stdout);\n+\telse if (!strcmp(res->dump, \"dump_vdevargs\"))\n+\t\trte_eal_vdevargs_dump(stdout);\n }\n \n cmdline_parse_token_string_t cmd_dump_dump =\n \tTOKEN_STRING_INITIALIZER(struct cmd_dump_result, dump,\n \t\t\t\t \"dump_physmem#dump_memzone#dump_log_history#\"\n \t\t\t\t \"dump_struct_sizes#dump_ring#dump_mempool#\"\n-\t\t\t\t \"dump_devargs\");\n+\t\t\t\t \"dump_devargs#dump_vdevargs\");\n \n cmdline_parse_inst_t cmd_dump = {\n \t.f = cmd_dump_parsed,  /* function to call */\ndiff --git a/app/test/test_devargs.c b/app/test/test_devargs.c\nindex f0acf8e..8fb93df 100644\n--- a/app/test/test_devargs.c\n+++ b/app/test/test_devargs.c\n@@ -52,52 +52,60 @@ static void free_devargs_list(void)\n \t}\n }\n \n+/* clear vdevargs list that was modified by the test */\n+static void free_vdevargs_list(void)\n+{\n+\tstruct rte_vdevargs *vdevargs;\n+\n+\twhile (!TAILQ_EMPTY(&vdevargs_list)) {\n+\t\tvdevargs = TAILQ_FIRST(&vdevargs_list);\n+\t\tTAILQ_REMOVE(&vdevargs_list, vdevargs, next);\n+\t\tfree(vdevargs);\n+\t}\n+}\n+\n static int\n test_devargs(void)\n {\n \tstruct rte_devargs_list save_devargs_list;\n+\tstruct rte_vdevargs_list save_vdevargs_list;\n \tstruct rte_devargs *devargs;\n+\tstruct rte_vdevargs *vdevargs;\n \n \t/* save the real devargs_list, it is restored at the end of the test */\n \tsave_devargs_list = devargs_list;\n+\tsave_vdevargs_list = vdevargs_list;\n \tTAILQ_INIT(&devargs_list);\n+\tTAILQ_INIT(&vdevargs_list);\n \n \t/* test valid cases */\n-\tif (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, \"08:00.1\") < 0)\n-\t\tgoto fail;\n-\tif (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, \"0000:5:00.0\") < 0)\n-\t\tgoto fail;\n-\tif (rte_eal_devargs_add(RTE_DEVTYPE_BLACKLISTED_PCI, \"04:00.0,arg=val\") < 0)\n-\t\tgoto fail;\n-\tif (rte_eal_devargs_add(RTE_DEVTYPE_BLACKLISTED_PCI, \"0000:01:00.1\") < 0)\n+\tif (rte_eal_devargs_add(RTE_DEV_WHITELISTED, \"08:00.1\") < 0)\n \t\tgoto fail;\n-\tif (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) != 2)\n+\tif (rte_eal_devargs_add(RTE_DEV_WHITELISTED, \"0000:5:00.0\") < 0)\n \t\tgoto fail;\n-\tif (rte_eal_devargs_type_count(RTE_DEVTYPE_BLACKLISTED_PCI) != 2)\n+\tif (rte_eal_devargs_add(RTE_DEV_BLACKLISTED, \"04:00.0\") < 0)\n \t\tgoto fail;\n-\tif (rte_eal_devargs_type_count(RTE_DEVTYPE_VIRTUAL) != 0)\n+\tif (rte_eal_devargs_add(RTE_DEV_BLACKLISTED, \"0000:01:00.1\") < 0)\n \t\tgoto fail;\n-\tif (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL, \"eth_ring0\") < 0)\n+\tif (rte_eal_devargs_type_count(RTE_DEV_WHITELISTED) != 2)\n \t\tgoto fail;\n-\tif (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL, \"eth_ring1,key=val,k2=val2\") < 0)\n-\t\tgoto fail;\n-\tif (rte_eal_devargs_type_count(RTE_DEVTYPE_VIRTUAL) != 2)\n+\tif (rte_eal_devargs_type_count(RTE_DEV_BLACKLISTED) != 2)\n \t\tgoto fail;\n \tfree_devargs_list();\n \n \t/* check virtual device with argument parsing */\n-\tif (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL, \"eth_ring1,k1=val,k2=val2\") < 0)\n+\tif (rte_eal_vdevargs_add(\"eth_ring1,k1=val,k2=val2\") < 0)\n \t\tgoto fail;\n-\tdevargs = TAILQ_FIRST(&devargs_list);\n-\tif (strncmp(devargs->virtual.drv_name, \"eth_ring1\",\n-\t\t\tsizeof(devargs->virtual.drv_name) != 0))\n+\tvdevargs = TAILQ_FIRST(&vdevargs_list);\n+\tif (strncmp(vdevargs->drv_name, \"eth_ring1\",\n+\t\t\tsizeof(vdevargs->drv_name) != 0))\n \t\tgoto fail;\n-\tif (strncmp(devargs->args, \"k1=val,k2=val2\", sizeof(devargs->args) != 0))\n+\tif (strncmp(vdevargs->args, \"k1=val,k2=val2\", sizeof(vdevargs->args) != 0))\n \t\tgoto fail;\n-\tfree_devargs_list();\n+\tfree_vdevargs_list();\n \n \t/* check PCI device with empty argument parsing */\n-\tif (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, \"04:00.1\") < 0)\n+\tif (rte_eal_devargs_add(RTE_DEV_WHITELISTED, \"04:00.1\") < 0)\n \t\tgoto fail;\n \tdevargs = TAILQ_FIRST(&devargs_list);\n \tif (devargs->pci.addr.domain != 0 ||\n@@ -105,28 +113,25 @@ test_devargs(void)\n \t\tdevargs->pci.addr.devid != 0 ||\n \t\tdevargs->pci.addr.function != 1)\n \t\tgoto fail;\n-\tif (strncmp(devargs->args, \"\", sizeof(devargs->args) != 0))\n-\t\tgoto fail;\n \tfree_devargs_list();\n \n-\t/* test error case: bad PCI address */\n-\tif (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, \"08:1\") == 0)\n+\t/* Check that virtual devices can be also whitelisted */\n+\tif (rte_eal_devargs_add(RTE_DEV_WHITELISTED, \"eth_pcap0\") < 0)\n \t\tgoto fail;\n-\tif (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, \"00.1\") == 0)\n-\t\tgoto fail;\n-\tif (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, \"foo\") == 0)\n-\t\tgoto fail;\n-\tif (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, \",\") == 0)\n-\t\tgoto fail;\n-\tif (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, \"000f:0:0\") == 0)\n+\tdevargs = TAILQ_FIRST(&devargs_list);\n+\tif (strncmp(devargs->virtual.drv_name, \"eth_pcap0\",\n+\t\tsizeof(devargs->virtual.drv_name)) != 0)\n \t\tgoto fail;\n \n \tdevargs_list = save_devargs_list;\n+\tvdevargs_list = save_vdevargs_list;\n \treturn 0;\n \n  fail:\n \tfree_devargs_list();\n+\tfree_vdevargs_list();\n \tdevargs_list = save_devargs_list;\n+\tvdevargs_list = save_vdevargs_list;\n \treturn -1;\n }\n \ndiff --git a/app/test/test_pci.c b/app/test/test_pci.c\nindex 4f0169a..308abb9 100644\n--- a/app/test/test_pci.c\n+++ b/app/test/test_pci.c\n@@ -126,8 +126,7 @@ blacklist_all_devices(void)\n \t\tsnprintf(pci_addr_str, sizeof(pci_addr_str), PCI_PRI_FMT,\n \t\t\tdev->addr.domain, dev->addr.bus, dev->addr.devid,\n \t\t\tdev->addr.function);\n-\t\tif (rte_eal_devargs_add(RTE_DEVTYPE_BLACKLISTED_PCI,\n-\t\t\t\tpci_addr_str) < 0) {\n+\t\tif (rte_eal_devargs_add(RTE_DEV_BLACKLISTED, pci_addr_str) < 0) {\n \t\t\tprintf(\"Error: cannot blacklist <%s>\", pci_addr_str);\n \t\t\tbreak;\n \t\t}\ndiff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c\nindex ca99cb9..c59c203 100644\n--- a/lib/librte_eal/bsdapp/eal/eal.c\n+++ b/lib/librte_eal/bsdapp/eal/eal.c\n@@ -429,14 +429,18 @@ eal_parse_args(int argc, char **argv)\n \t\treturn -1;\n \t}\n \n-\tif (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) != 0 &&\n-\t\trte_eal_devargs_type_count(RTE_DEVTYPE_BLACKLISTED_PCI) != 0) {\n+\tif (rte_eal_devargs_type_count(RTE_DEV_WHITELISTED) != 0 &&\n+\t\trte_eal_devargs_type_count(RTE_DEV_BLACKLISTED) != 0) {\n \t\tRTE_LOG(ERR, EAL, \"Error: blacklist [-b] and whitelist \"\n \t\t\t\"[-w] options cannot be used at the same time\\n\");\n \t\teal_usage(prgname);\n \t\treturn -1;\n \t}\n \n+\t/* Check if all white/black listed virtual devices were also defined */\n+\tif (rte_eal_check_vdevs_definition() < 0)\n+\t\treturn -1;\n+\n \tif (optind >= 0)\n \t\targv[optind-1] = prgname;\n \ndiff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c\nindex 74ecce7..df179eb 100644\n--- a/lib/librte_eal/bsdapp/eal/eal_pci.c\n+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c\n@@ -462,7 +462,7 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *d\n \n \t\t/* no initialization when blacklisted, return without error */\n \t\tif (dev->devargs != NULL &&\n-\t\t\tdev->devargs->type == RTE_DEVTYPE_BLACKLISTED_PCI) {\n+\t\t\tdev->devargs->select == RTE_DEV_BLACKLISTED) {\n \n \t\t\tRTE_LOG(DEBUG, EAL, \"  Device is blacklisted, not initializing\\n\");\n \t\t\treturn 0;\ndiff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c\nindex eae5656..5181ba8 100644\n--- a/lib/librte_eal/common/eal_common_dev.c\n+++ b/lib/librte_eal/common/eal_common_dev.c\n@@ -64,8 +64,11 @@ rte_eal_driver_unregister(struct rte_driver *driver)\n int\n rte_eal_dev_init(void)\n {\n-\tstruct rte_devargs *devargs;\n+\tstruct rte_vdevargs *vdevargs;\n \tstruct rte_driver *driver;\n+\tint whitelisted_devs;\n+\n+\twhitelisted_devs = rte_eal_devargs_type_count(RTE_DEV_WHITELISTED);\n \n \t/*\n \t * Note that the dev_driver_list is populated here\n@@ -74,9 +77,13 @@ rte_eal_dev_init(void)\n \t */\n \n \t/* call the init function for each virtual device */\n-\tTAILQ_FOREACH(devargs, &devargs_list, next) {\n+\tTAILQ_FOREACH(vdevargs, &vdevargs_list, next) {\n+\n+\t\tif (rte_eal_vdevargs_is(vdevargs, RTE_DEV_BLACKLISTED))\n+\t\t\tcontinue;\n \n-\t\tif (devargs->type != RTE_DEVTYPE_VIRTUAL)\n+\t\tif (whitelisted_devs\n+\t\t        && !rte_eal_vdevargs_is(vdevargs, RTE_DEV_WHITELISTED))\n \t\t\tcontinue;\n \n \t\tTAILQ_FOREACH(driver, &dev_driver_list, next) {\n@@ -84,18 +91,15 @@ rte_eal_dev_init(void)\n \t\t\t\tcontinue;\n \n \t\t\t/* search a driver prefix in virtual device name */\n-\t\t\tif (!strncmp(driver->name, devargs->virtual.drv_name,\n+\t\t\tif (!strncmp(driver->name, vdevargs->drv_name,\n \t\t\t\t\tstrlen(driver->name))) {\n-\t\t\t\tdriver->init(devargs->virtual.drv_name,\n-\t\t\t\t\tdevargs->args);\n+\t\t\t\tdriver->init(vdevargs->drv_name, vdevargs->args);\n \t\t\t\tbreak;\n \t\t\t}\n \t\t}\n \n-\t\tif (driver == NULL) {\n-\t\t\trte_panic(\"no driver found for %s\\n\",\n-\t\t\t\t  devargs->virtual.drv_name);\n-\t\t}\n+\t\tif (driver == NULL)\n+\t\t\trte_panic(\"no driver found for %s\\n\", vdevargs->drv_name);\n \t}\n \n \t/* Once the vdevs are initalized, start calling all the pdev drivers */\ndiff --git a/lib/librte_eal/common/eal_common_devargs.c b/lib/librte_eal/common/eal_common_devargs.c\nindex 4c7d11a..4171654 100644\n--- a/lib/librte_eal/common/eal_common_devargs.c\n+++ b/lib/librte_eal/common/eal_common_devargs.c\n@@ -43,14 +43,15 @@\n /** Global list of user devices */\n struct rte_devargs_list devargs_list =\n \tTAILQ_HEAD_INITIALIZER(devargs_list);\n+struct rte_vdevargs_list vdevargs_list =\n+\tTAILQ_HEAD_INITIALIZER(vdevargs_list);\n \n /* store a whitelist parameter for later parsing */\n int\n-rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str)\n+rte_eal_devargs_add(enum rte_devselect devselect, const char *devargs_str)\n {\n \tstruct rte_devargs *devargs;\n-\tchar buf[RTE_DEVARGS_LEN];\n-\tchar *sep;\n+\tchar buf[RTE_VDEV_NAME_LEN];\n \tint ret;\n \n \tret = snprintf(buf, sizeof(buf), \"%s\", devargs_str);\n@@ -67,86 +68,177 @@ rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str)\n \t\treturn -1;\n \t}\n \tmemset(devargs, 0, sizeof(*devargs));\n-\tdevargs->type = devtype;\n+\tdevargs->select = devselect;\n+\n+\t/* try to parse short PCI identifier */\n+\tif (eal_parse_pci_BDF(buf, &devargs->pci.addr) == 0)\n+\t\tgoto done;\n+\n+\t/* try to parse long PCI identifier */\n+\tif (eal_parse_pci_DomBDF(buf, &devargs->pci.addr) == 0)\n+\t\tgoto done;\n+\n+\t/* If device ID is not a valid PCI ID assume is a virtual driver name */\n+\tdevargs->is_vdev = 1;\n+\tret = snprintf(devargs->virtual.drv_name, sizeof(devargs->virtual.drv_name), \"%s\", buf);\n+\tif (ret < 0 || ret >= (int)sizeof(devargs->virtual.drv_name)) {\n+\t\tRTE_LOG(ERR, EAL, \"driver name too large: <%s>\\n\", buf);\n+\t\tfree(devargs);\n+\t\treturn -1;\n+\t}\n+\n+done:\n+\tTAILQ_INSERT_TAIL(&devargs_list, devargs, next);\n+\treturn 0;\n+}\n+\n+int\n+rte_eal_vdevargs_add(const char *vdevargs_str)\n+{\n+\tstruct rte_vdevargs *vdevargs;\n+\tchar buf[RTE_VDEVARGS_LEN];\n+\tchar *sep;\n+\tint ret;\n+\n+\tret = snprintf(buf, sizeof(buf), \"%s\", vdevargs_str);\n+\tif (ret < 0 || ret >= (int)sizeof(buf)) {\n+\t\tRTE_LOG(ERR, EAL, \"user device args too large: <%s>\\n\", vdevargs_str);\n+\t\treturn -1;\n+\t}\n+\n+\t/* use malloc instead of rte_malloc as it's called early at init */\n+\tvdevargs = malloc(sizeof(*vdevargs));\n+\tif (vdevargs == NULL) {\n+\t\tRTE_LOG(ERR, EAL, \"cannot allocate vdevargs\\n\");\n+\t\treturn -1;\n+\t}\n+\tmemset(vdevargs, 0, sizeof(*vdevargs));\n \n \t/* set the first ',' to '\\0' to split name and arguments */\n \tsep = strchr(buf, ',');\n \tif (sep != NULL) {\n \t\tsep[0] = '\\0';\n-\t\tsnprintf(devargs->args, sizeof(devargs->args), \"%s\", sep + 1);\n+\t\tsnprintf(vdevargs->args, sizeof(vdevargs->args), \"%s\", sep + 1);\n \t}\n \n-\tswitch (devargs->type) {\n-\tcase RTE_DEVTYPE_WHITELISTED_PCI:\n-\tcase RTE_DEVTYPE_BLACKLISTED_PCI:\n-\t\t/* try to parse pci identifier */\n-\t\tif (eal_parse_pci_BDF(buf, &devargs->pci.addr) != 0 &&\n-\t\t\teal_parse_pci_DomBDF(buf, &devargs->pci.addr) != 0) {\n-\t\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\t\"invalid PCI identifier <%s>\\n\", buf);\n-\t\t\tfree(devargs);\n-\t\t\treturn -1;\n-\t\t}\n-\t\tbreak;\n-\tcase RTE_DEVTYPE_VIRTUAL:\n-\t\t/* save driver name */\n-\t\tret = snprintf(devargs->virtual.drv_name,\n-\t\t\tsizeof(devargs->virtual.drv_name), \"%s\", buf);\n-\t\tif (ret < 0 || ret >= (int)sizeof(devargs->virtual.drv_name)) {\n-\t\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\t\"driver name too large: <%s>\\n\", buf);\n-\t\t\tfree(devargs);\n-\t\t\treturn -1;\n-\t\t}\n-\t\tbreak;\n+\t/* save driver name */\n+\tret = snprintf(vdevargs->drv_name, sizeof(vdevargs->drv_name), \"%s\", buf);\n+\tif (ret < 0 || ret >= (int)sizeof(vdevargs->drv_name)) {\n+\t\tRTE_LOG(ERR, EAL, \"driver name too large: <%s>\\n\", buf);\n+\t\tfree(vdevargs);\n+\t\treturn -1;\n \t}\n \n-\tTAILQ_INSERT_TAIL(&devargs_list, devargs, next);\n+\tTAILQ_INSERT_TAIL(&vdevargs_list, vdevargs, next);\n \treturn 0;\n }\n \n /* count the number of devices of a specified type */\n unsigned int\n-rte_eal_devargs_type_count(enum rte_devtype devtype)\n+rte_eal_devargs_type_count(enum rte_devselect devselect)\n {\n \tstruct rte_devargs *devargs;\n \tunsigned int count = 0;\n \n \tTAILQ_FOREACH(devargs, &devargs_list, next) {\n-\t\tif (devargs->type != devtype)\n+\t\tif (devargs->select != devselect)\n \t\t\tcontinue;\n \t\tcount++;\n \t}\n \treturn count;\n }\n \n-/* dump the user devices on the console */\n+int\n+rte_eal_vdevargs_is(struct rte_vdevargs *vdevargs, enum rte_devselect devselect)\n+{\n+\tstruct rte_devargs *devargs;\n+\n+\tTAILQ_FOREACH(devargs, &devargs_list, next) {\n+\t\tif (!devargs->is_vdev)\n+\t\t\tcontinue;\n+\n+\t\tif (!strncmp(vdevargs->drv_name, devargs->virtual.drv_name,\n+\t\t\t\tsizeof(vdevargs->drv_name)))\n+\t\t\treturn !!(devargs->select == devselect);\n+\t}\n+\treturn 0;\n+}\n+\n+/* dump the user selected devices on the console */\n void\n rte_eal_devargs_dump(FILE *f)\n {\n \tstruct rte_devargs *devargs;\n \n-\tfprintf(f, \"User device white list:\\n\");\n+\tfprintf(f, \"User selected devices list:\\n\");\n \tTAILQ_FOREACH(devargs, &devargs_list, next) {\n-\t\tif (devargs->type == RTE_DEVTYPE_WHITELISTED_PCI)\n-\t\t\tfprintf(f, \"  PCI whitelist \" PCI_PRI_FMT \" %s\\n\",\n-\t\t\t       devargs->pci.addr.domain,\n-\t\t\t       devargs->pci.addr.bus,\n-\t\t\t       devargs->pci.addr.devid,\n-\t\t\t       devargs->pci.addr.function,\n-\t\t\t       devargs->args);\n-\t\telse if (devargs->type == RTE_DEVTYPE_BLACKLISTED_PCI)\n-\t\t\tfprintf(f, \"  PCI blacklist \" PCI_PRI_FMT \" %s\\n\",\n-\t\t\t       devargs->pci.addr.domain,\n-\t\t\t       devargs->pci.addr.bus,\n-\t\t\t       devargs->pci.addr.devid,\n-\t\t\t       devargs->pci.addr.function,\n-\t\t\t       devargs->args);\n-\t\telse if (devargs->type == RTE_DEVTYPE_VIRTUAL)\n-\t\t\tfprintf(f, \"  VIRTUAL %s %s\\n\",\n-\t\t\t       devargs->virtual.drv_name,\n-\t\t\t       devargs->args);\n+\t\tif (devargs->select == RTE_DEV_WHITELISTED)\n+\t\t\tfprintf(f, \"  PCI whitelist \");\n+\t\telse if (devargs->select == RTE_DEV_BLACKLISTED)\n+\t\t\tfprintf(f, \"  PCI blacklist \");\n+\t\telse\n+\t\t\tfprintf(f, \"  UNKNOWN \");\n+\n+\t\tif (devargs->is_vdev)\n+\t\t\tfprintf(f, \"(VIRTUAL) %s %s\\n\", devargs->virtual.vdev->drv_name,\n+\t\t\t\tdevargs->virtual.vdev->args);\n \t\telse\n-\t\t\tfprintf(f, \"  UNKNOWN %s\\n\", devargs->args);\n+\t\t\tfprintf(f, PCI_PRI_FMT \"\\n\",\n+\t\t\t\tdevargs->pci.addr.domain,\n+\t\t\t\tdevargs->pci.addr.bus,\n+\t\t\t\tdevargs->pci.addr.devid,\n+\t\t\t\tdevargs->pci.addr.function);\n+\t}\n+}\n+\n+/* dump the user virtual devices on the console */\n+void\n+rte_eal_vdevargs_dump(FILE *f)\n+{\n+\tstruct rte_vdevargs *vdevargs;\n+\n+\tfprintf(f, \"User virtual devices list:\\n\");\n+\tTAILQ_FOREACH(vdevargs, &vdevargs_list, next) {\n+\t\tfprintf(f, \"  VIRTUAL %s %s\\n\",\n+\t\t\tvdevargs->drv_name,\n+\t\t\tvdevargs->args);\n+\t}\n+}\n+\n+int\n+rte_eal_check_vdevs_definition(void)\n+{\n+\tstruct rte_devargs *devargs;\n+\tstruct rte_vdevargs *vdevargs;\n+\tint found;\n+\n+\t/* Go through all white/black listed devices */\n+\tTAILQ_FOREACH(devargs, &devargs_list, next) {\n+\n+\t\t/* Only check the virtual ones */\n+\t\tif (!devargs->is_vdev)\n+\t\t\tcontinue;\n+\n+\t\t/* Search for the virtual device definition */\n+\t\tfound = 0;\n+\t\tTAILQ_FOREACH(vdevargs, &vdevargs_list, next) {\n+\t\t\tif (!strncmp(vdevargs->drv_name, devargs->virtual.drv_name,\n+\t\t\t\t\tsizeof(vdevargs->drv_name))) {\n+\t\t\t\tfound = 1;\n+\t\t\t\tdevargs->virtual.vdev = vdevargs;\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* If the virtual device was not defined return an error */\n+\t\tif (!found) {\n+\t\t\tRTE_LOG(ERR, EAL, \"Virtual device %s is %slisted but not defined. \"\n+\t\t\t\t\t\"Use '--vdev=%s,...' to define it.\\n\",\n+\t\t\t\t\tdevargs->virtual.drv_name,\n+\t\t\t\t\tdevargs->select == RTE_DEV_WHITELISTED ? \"white\" : \"black\",\n+\t\t\t\t\tdevargs->virtual.drv_name);\n+\t\t\treturn -1;\n+\t\t}\n \t}\n+\n+\treturn 0;\n }\ndiff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c\nindex 7a5d55e..e044a51 100644\n--- a/lib/librte_eal/common/eal_common_options.c\n+++ b/lib/librte_eal/common/eal_common_options.c\n@@ -244,17 +244,13 @@ eal_parse_common_option(int opt, const char *optarg,\n \tswitch (opt) {\n \t/* blacklist */\n \tcase 'b':\n-\t\tif (rte_eal_devargs_add(RTE_DEVTYPE_BLACKLISTED_PCI,\n-\t\t\t\toptarg) < 0) {\n+\t\tif (rte_eal_devargs_add(RTE_DEV_BLACKLISTED, optarg) < 0)\n \t\t\treturn -1;\n-\t\t}\n \t\tbreak;\n \t/* whitelist */\n \tcase 'w':\n-\t\tif (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI,\n-\t\t\t\toptarg) < 0) {\n+\t\tif (rte_eal_devargs_add(RTE_DEV_WHITELISTED, optarg) < 0)\n \t\t\treturn -1;\n-\t\t}\n \t\tbreak;\n \t/* coremask */\n \tcase 'c':\n@@ -321,8 +317,7 @@ eal_parse_common_option(int opt, const char *optarg,\n \t\tbreak;\n \n \tcase OPT_VDEV_NUM:\n-\t\tif (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL,\n-\t\t\t\toptarg) < 0) {\n+\t\tif (rte_eal_vdevargs_add(optarg) < 0) {\n \t\t\treturn -1;\n \t\t}\n \t\tbreak;\ndiff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c\nindex f3c7f71..19b3ce4 100644\n--- a/lib/librte_eal/common/eal_common_pci.c\n+++ b/lib/librte_eal/common/eal_common_pci.c\n@@ -85,13 +85,14 @@\n struct pci_driver_list pci_driver_list;\n struct pci_device_list pci_device_list;\n \n-static struct rte_devargs *pci_devargs_lookup(struct rte_pci_device *dev)\n+static struct rte_devargs *\n+pci_devargs_lookup(struct rte_pci_device *dev)\n {\n \tstruct rte_devargs *devargs;\n \n \tTAILQ_FOREACH(devargs, &devargs_list, next) {\n-\t\tif (devargs->type != RTE_DEVTYPE_BLACKLISTED_PCI &&\n-\t\t\tdevargs->type != RTE_DEVTYPE_WHITELISTED_PCI)\n+\t\tif (devargs->select != RTE_DEV_BLACKLISTED &&\n+\t\t\tdevargs->select != RTE_DEV_WHITELISTED)\n \t\t\tcontinue;\n \t\tif (!memcmp(&dev->addr, &devargs->pci.addr, sizeof(dev->addr)))\n \t\t\treturn devargs;\n@@ -136,7 +137,7 @@ rte_eal_pci_probe(void)\n \tint probe_all = 0;\n \tint ret = 0;\n \n-\tif (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)\n+\tif (rte_eal_devargs_type_count(RTE_DEV_WHITELISTED) == 0)\n \t\tprobe_all = 1;\n \n \tTAILQ_FOREACH(dev, &pci_device_list, next) {\n@@ -150,7 +151,7 @@ rte_eal_pci_probe(void)\n \t\tif (probe_all)\n \t\t\tret = pci_probe_all_drivers(dev);\n \t\telse if (devargs != NULL &&\n-\t\t\tdevargs->type == RTE_DEVTYPE_WHITELISTED_PCI)\n+\t\t\tdevargs->select == RTE_DEV_WHITELISTED)\n \t\t\tret = pci_probe_all_drivers(dev);\n \t\tif (ret < 0)\n \t\t\trte_exit(EXIT_FAILURE, \"Requested device \" PCI_PRI_FMT\ndiff --git a/lib/librte_eal/common/include/rte_devargs.h b/lib/librte_eal/common/include/rte_devargs.h\nindex 9f9c98f..b6599ef 100644\n--- a/lib/librte_eal/common/include/rte_devargs.h\n+++ b/lib/librte_eal/common/include/rte_devargs.h\n@@ -52,96 +52,158 @@ extern \"C\" {\n #include <sys/queue.h>\n #include <rte_pci.h>\n \n+#define RTE_VDEV_NAME_LEN 32\n+\n /**\n- * Type of generic device\n+ * Type of device selection\n  */\n-enum rte_devtype {\n-\tRTE_DEVTYPE_WHITELISTED_PCI,\n-\tRTE_DEVTYPE_BLACKLISTED_PCI,\n-\tRTE_DEVTYPE_VIRTUAL,\n+enum rte_devselect {\n+\tRTE_DEV_WHITELISTED,\n+\tRTE_DEV_BLACKLISTED,\n };\n \n /**\n- * Structure that stores a device given by the user with its arguments\n+ * Structure that stores a virtual device given by the user with its arguments\n+ *\n+ * The structure stores the configuration of the device and its name which\n+ * contains its driver name\n+ */\n+struct rte_vdevargs {\n+\t/** Next in list. */\n+\tTAILQ_ENTRY(rte_vdevargs) next;\n+\t/** Driver name. */\n+\tchar drv_name[RTE_VDEV_NAME_LEN];\n+#define RTE_VDEVARGS_LEN 256\n+\tchar args[RTE_VDEVARGS_LEN]; /**< Arguments string as given by user. */\n+};\n+\n+/**\n+ * Structure that stores the user selected devices.\n  *\n  * A user device is a physical or a virtual device given by the user to\n  * the DPDK application at startup through command line arguments.\n  *\n- * The structure stores the configuration of the device, its PCI\n- * identifier if it's a PCI device or the driver name if it's a virtual\n- * device.\n+ * The devices can be whitelisted or blacklisted independently if they are\n+ * physical or virtual devices.\n  */\n struct rte_devargs {\n \t/** Next in list. */\n \tTAILQ_ENTRY(rte_devargs) next;\n-\t/** Type of device. */\n-\tenum rte_devtype type;\n+\t/** Type of device selection. */\n+\tenum rte_devselect select;\n+\tint is_vdev;\n \tunion {\n-\t\t/** Used if type is RTE_DEVTYPE_*_PCI. */\n+\t\t/** Used if physical device. */\n \t\tstruct {\n \t\t\t/** PCI location. */\n \t\t\tstruct rte_pci_addr addr;\n \t\t} pci;\n-\t\t/** Used if type is RTE_DEVTYPE_VIRTUAL. */\n+\t\t/** Used if virtual device. */\n \t\tstruct {\n \t\t\t/** Driver name. */\n-\t\t\tchar drv_name[32];\n+\t\t\tchar drv_name[RTE_VDEV_NAME_LEN];\n+\t\t\tstruct rte_vdevargs *vdev;\n \t\t} virtual;\n \t};\n-#define RTE_DEVARGS_LEN 256\n-\tchar args[RTE_DEVARGS_LEN]; /**< Arguments string as given by user. */\n };\n \n /** user device double-linked queue type definition */\n TAILQ_HEAD(rte_devargs_list, rte_devargs);\n+TAILQ_HEAD(rte_vdevargs_list, rte_vdevargs);\n \n /** Global list of user devices */\n extern struct rte_devargs_list devargs_list;\n \n+/** Global list of virtual devices */\n+extern struct rte_vdevargs_list vdevargs_list;\n+\n /**\n  * Add a device to the user device list\n  *\n- * For PCI devices, the format of arguments string is \"PCI_ADDR\" or\n- * \"PCI_ADDR,key=val,key2=val2,...\". Examples: \"08:00.1\", \"0000:5:00.0\",\n- * \"04:00.0,arg=val\".\n+ * For PCI devices, the format of arguments string is \"PCI_ADDR\"\n+ * Examples: \"08:00.1\", \"0000:5:00.0\".\n  *\n- * For virtual devices, the format of arguments string is \"DRIVER_NAME*\"\n- * or \"DRIVER_NAME*,key=val,key2=val2,...\". Examples: \"eth_ring\",\n- * \"eth_ring0\", \"eth_pmdAnything,arg=0:arg2=1\". The validity of the\n- * driver name is not checked by this function, it is done when probing\n- * the drivers.\n+ * For virtual devices, the format of arguments string is \"DRIVER_NAME\".\n+ * Examples: \"eth_ring\", \"eth_ring0\", \"eth_pmdAnything\". This function does not\n+ * validate if the driver name is valid or if it was already defined with\n+ * --vdev.\n  *\n- * @param devtype\n- *   The type of the device.\n- * @param devargs_list\n+ * @param devselect\n+ *   Whether the device is black or white listed.\n+ * @param devargs_str\n  *   The arguments as given by the user.\n  *\n  * @return\n  *   - 0 on success\n  *   - A negative value on error\n  */\n-int rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str);\n+int rte_eal_devargs_add(enum rte_devselect devselect, const char *devargs_str);\n \n /**\n  * Count the number of user devices of a specified type\n  *\n- * @param devtype\n+ * @param devselect\n  *   The type of the devices to counted.\n  *\n  * @return\n  *   The number of devices.\n  */\n unsigned int\n-rte_eal_devargs_type_count(enum rte_devtype devtype);\n+rte_eal_devargs_type_count(enum rte_devselect devselect);\n \n /**\n- * This function dumps the list of user device and their arguments.\n+ * This function dumps the list of user selected devices.\n  *\n  * @param f\n  *   A pointer to a file for output\n  */\n void rte_eal_devargs_dump(FILE *f);\n \n+/**\n+ * This function dumps the list of user virtual devices and their arguments.\n+ *\n+ * @param f\n+ *   A pointer to a file for output\n+ */\n+void rte_eal_vdevargs_dump(FILE *f);\n+\n+/**\n+ * Add a virtual device\n+ *\n+ * The format of arguments string is \"DRIVER_NAME*\"\n+ * or \"DRIVER_NAME*,key=val,key2=val2,...\". Examples: \"eth_ring\",\n+ * \"eth_ring0\", \"eth_pmdAnything,arg=0:arg2=1\". The validity of the\n+ * driver name is not checked by this function, it is done when probing\n+ * the drivers.\n+ *\n+ * @param devargs_str\n+ *   The arguments as given by the user.\n+ *\n+ * @return\n+ *   - 0 on success\n+ *   - A negative value on error\n+ */\n+int rte_eal_vdevargs_add(const char *devargs_str);\n+\n+/**\n+ * Check if the white/black-listed virtual devices have been defined\n+ *\n+ * @return\n+ *   - 0 on success\n+ *   - A negative value on error\n+ */\n+int rte_eal_check_vdevs_definition(void);\n+\n+/**\n+ * Check if the virtual device is white/black-listed\n+ *\n+ * @return\n+ *   - 1 if the device is white/black-listed.\n+ *   - 0 otherwise.\n+ */\n+int rte_eal_vdevargs_is(struct rte_vdevargs *vdevargs,\n+\t\tenum rte_devselect devselect);\n+\n #ifdef __cplusplus\n }\n #endif\ndiff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c\nindex 7a1d087..e898688 100644\n--- a/lib/librte_eal/linuxapp/eal/eal.c\n+++ b/lib/librte_eal/linuxapp/eal/eal.c\n@@ -696,14 +696,18 @@ eal_parse_args(int argc, char **argv)\n \t\treturn -1;\n \t}\n \n-\tif (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) != 0 &&\n-\t\trte_eal_devargs_type_count(RTE_DEVTYPE_BLACKLISTED_PCI) != 0) {\n+\tif (rte_eal_devargs_type_count(RTE_DEV_WHITELISTED) != 0 &&\n+\t\trte_eal_devargs_type_count(RTE_DEV_BLACKLISTED) != 0) {\n \t\tRTE_LOG(ERR, EAL, \"Error: blacklist [-b] and whitelist \"\n \t\t\t\"[-w] options cannot be used at the same time\\n\");\n \t\teal_usage(prgname);\n \t\treturn -1;\n \t}\n \n+\t/* Check if all white/black listed virtual devices were also defined */\n+\tif (rte_eal_check_vdevs_definition() < 0)\n+\t\treturn -1;\n+\n \tif (optind >= 0)\n \t\targv[optind-1] = prgname;\n \ndiff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c\nindex ddb0535..b49722e 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_pci.c\n+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c\n@@ -544,7 +544,7 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *d\n \n \t\t/* no initialization when blacklisted, return without error */\n \t\tif (dev->devargs != NULL &&\n-\t\t\tdev->devargs->type == RTE_DEVTYPE_BLACKLISTED_PCI) {\n+\t\t\tdev->devargs->select == RTE_DEV_BLACKLISTED) {\n \t\t\tRTE_LOG(DEBUG, EAL, \"  Device is blacklisted, not initializing\\n\");\n \t\t\treturn 1;\n \t\t}\n",
    "prefixes": [
        "dpdk-dev"
    ]
}