From patchwork Sun Feb 14 03:21:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xueming Li X-Patchwork-Id: 87909 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id BD5C0A0546; Sun, 14 Feb 2021 04:23:00 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id A6773227EA5; Sun, 14 Feb 2021 04:23:00 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id F2FBD406A2 for ; Sun, 14 Feb 2021 04:22:59 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from xuemingl@nvidia.com) with SMTP; 14 Feb 2021 05:22:59 +0200 Received: from nvidia.com (pegasus05.mtr.labs.mlnx [10.210.16.100]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 11E3MYvN008525; Sun, 14 Feb 2021 05:22:59 +0200 From: Xueming Li To: Cc: dev@dpdk.org, Viacheslav Ovsiienko , xuemingl@nvidia.com, Asaf Penso , Ajit Khaparde , Somnath Kotur , John Daley , Hyong Youb Kim , Beilei Xing , Jeff Guo , Haiyue Wang , Matan Azrad , Shahaf Shuler , Thomas Monjalon , Ferruh Yigit , Andrew Rybchenko Date: Sun, 14 Feb 2021 03:21:31 +0000 Message-Id: <1613272907-22563-2-git-send-email-xuemingl@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1613272907-22563-1-git-send-email-xuemingl@nvidia.com> References: <1613272907-22563-1-git-send-email-xuemingl@nvidia.com> In-Reply-To: <1608303356-13089-2-git-send-email-xuemingl@nvidia.com> References: <1608303356-13089-2-git-send-email-xuemingl@nvidia.com> Subject: [dpdk-dev] [PATCH v6 1/9] ethdev: introduce representor type X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" To support more representor type, this patch introduces representor type enum. The enum is subject to be extended to support new representor in patches upcoming. For each devarg structure, only one type supported. Signed-off-by: Xueming Li Acked-by: Viacheslav Ovsiienko Acked-by: Thomas Monjalon Acked-by: Ajit Khaparde Acked-by: Andrew Rybchenko Acked-by: Hyong Youb Kim --- drivers/net/bnxt/bnxt_ethdev.c | 7 +++++++ drivers/net/enic/enic_ethdev.c | 6 ++++++ drivers/net/i40e/i40e_ethdev.c | 7 +++++++ drivers/net/ixgbe/ixgbe_ethdev.c | 7 +++++++ drivers/net/mlx5/linux/mlx5_os.c | 11 +++++++++++ lib/librte_ethdev/ethdev_driver.h | 7 ++++++- lib/librte_ethdev/ethdev_private.c | 5 +++++ lib/librte_ethdev/rte_ethdev.h | 8 ++++++++ 8 files changed, 57 insertions(+), 1 deletion(-) diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c index 22c880c5c3..1a276c9b9e 100644 --- a/drivers/net/bnxt/bnxt_ethdev.c +++ b/drivers/net/bnxt/bnxt_ethdev.c @@ -5618,6 +5618,13 @@ static int bnxt_rep_port_probe(struct rte_pci_device *pci_dev, int i, ret = 0; struct rte_kvargs *kvlist = NULL; + if (eth_da->type == RTE_ETH_REPRESENTOR_NONE) + return 0; + if (eth_da->type != RTE_ETH_REPRESENTOR_VF) { + PMD_DRV_LOG(ERR, "unsupported representor type %d\n", + eth_da->type); + return -ENOTSUP; + } num_rep = eth_da->nb_representor_ports; if (num_rep > BNXT_MAX_VF_REPS) { PMD_DRV_LOG(ERR, "nb_representor_ports = %d > %d MAX VF REPS\n", diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c index b3f441c8f7..def669f411 100644 --- a/drivers/net/enic/enic_ethdev.c +++ b/drivers/net/enic/enic_ethdev.c @@ -1312,6 +1312,12 @@ static int eth_enic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, if (retval) return retval; } + if (eth_da.nb_representor_ports > 0 && + eth_da.type != RTE_ETH_REPRESENTOR_VF) { + ENICPMD_LOG(ERR, "unsupported representor type: %s\n", + pci_dev->device.devargs->args); + return -ENOTSUP; + } retval = rte_eth_dev_create(&pci_dev->device, pci_dev->device.name, sizeof(struct enic), eth_dev_pci_specific_init, pci_dev, diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index d7cd049891..9b86bcdc69 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -639,6 +639,13 @@ eth_i40e_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, return retval; } + if (eth_da.nb_representor_ports > 0 && + eth_da.type != RTE_ETH_REPRESENTOR_VF) { + PMD_DRV_LOG(ERR, "unsupported representor type: %s\n", + pci_dev->device.devargs->args); + return -ENOTSUP; + } + retval = rte_eth_dev_create(&pci_dev->device, pci_dev->device.name, sizeof(struct i40e_adapter), eth_dev_pci_specific_init, pci_dev, diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c index 761a0f26bb..8a9a21e7c2 100644 --- a/drivers/net/ixgbe/ixgbe_ethdev.c +++ b/drivers/net/ixgbe/ixgbe_ethdev.c @@ -1718,6 +1718,13 @@ eth_ixgbe_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, } else memset(ð_da, 0, sizeof(eth_da)); + if (eth_da.nb_representor_ports > 0 && + eth_da.type != RTE_ETH_REPRESENTOR_VF) { + PMD_DRV_LOG(ERR, "unsupported representor type: %s\n", + pci_dev->device.devargs->args); + return -ENOTSUP; + } + retval = rte_eth_dev_create(&pci_dev->device, pci_dev->device.name, sizeof(struct ixgbe_adapter), eth_dev_pci_specific_init, pci_dev, diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c index 2dc079779d..b041e1752d 100644 --- a/drivers/net/mlx5/linux/mlx5_os.c +++ b/drivers/net/mlx5/linux/mlx5_os.c @@ -704,6 +704,17 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev, strerror(rte_errno)); return NULL; } + if (eth_da.type == RTE_ETH_REPRESENTOR_NONE) { + /* Representor not specified. */ + rte_errno = EBUSY; + return NULL; + } + if (eth_da.type != RTE_ETH_REPRESENTOR_VF) { + rte_errno = ENOTSUP; + DRV_LOG(ERR, "unsupported representor type: %s", + dpdk_dev->devargs->args); + return NULL; + } for (i = 0; i < eth_da.nb_representor_ports; ++i) if (eth_da.representor_ports[i] == (uint16_t)switch_info->port_name) diff --git a/lib/librte_ethdev/ethdev_driver.h b/lib/librte_ethdev/ethdev_driver.h index 57fdedaa1a..d68b8401e7 100644 --- a/lib/librte_ethdev/ethdev_driver.h +++ b/lib/librte_ethdev/ethdev_driver.h @@ -1216,7 +1216,11 @@ __rte_internal int rte_eth_switch_domain_free(uint16_t domain_id); -/** Generic Ethernet device arguments */ +/** + * Generic Ethernet device arguments + * + * One type of representor each structure. + */ struct rte_eth_devargs { uint16_t ports[RTE_MAX_ETHPORTS]; /** port/s number to enable on a multi-port single function */ @@ -1226,6 +1230,7 @@ struct rte_eth_devargs { /** representor port/s identifier to enable on device */ uint16_t nb_representor_ports; /** number of ports in representor port field */ + enum rte_eth_representor_type type; /* type of representor */ }; /** diff --git a/lib/librte_ethdev/ethdev_private.c b/lib/librte_ethdev/ethdev_private.c index 5960c75cc5..2d51e3857a 100644 --- a/lib/librte_ethdev/ethdev_private.c +++ b/lib/librte_ethdev/ethdev_private.c @@ -111,11 +111,16 @@ rte_eth_devargs_process_range(char *str, uint16_t *list, uint16_t *len_list, return 0; } +/* + * representor format: + * #: range or single number of VF representor + */ int rte_eth_devargs_parse_representor_ports(char *str, void *data) { struct rte_eth_devargs *eth_da = data; + eth_da->type = RTE_ETH_REPRESENTOR_VF; return rte_eth_devargs_process_range(str, eth_da->representor_ports, ð_da->nb_representor_ports, RTE_MAX_ETHPORTS); } diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h index 059a061072..1f378958ca 100644 --- a/lib/librte_ethdev/rte_ethdev.h +++ b/lib/librte_ethdev/rte_ethdev.h @@ -1506,6 +1506,14 @@ struct rte_eth_rxseg_capa { * Ethernet device information */ +/** + * Ethernet device representor port type. + */ +enum rte_eth_representor_type { + RTE_ETH_REPRESENTOR_NONE, /**< not a representor. */ + RTE_ETH_REPRESENTOR_VF, /**< representor of Virtual Function. */ +}; + /** * A structure used to retrieve the contextual information of * an Ethernet device, such as the controlling driver of the From patchwork Sun Feb 14 03:21:32 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xueming Li X-Patchwork-Id: 87910 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 09D6FA0546; Sun, 14 Feb 2021 04:23:20 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id E5F49406A3; Sun, 14 Feb 2021 04:23:19 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id 4B5AD406A2 for ; Sun, 14 Feb 2021 04:23:18 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from xuemingl@nvidia.com) with SMTP; 14 Feb 2021 05:23:17 +0200 Received: from nvidia.com (pegasus05.mtr.labs.mlnx [10.210.16.100]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 11E3MYvO008525; Sun, 14 Feb 2021 05:23:17 +0200 From: Xueming Li To: Cc: dev@dpdk.org, Viacheslav Ovsiienko , xuemingl@nvidia.com, Asaf Penso , Thomas Monjalon , Ferruh Yigit , Andrew Rybchenko Date: Sun, 14 Feb 2021 03:21:32 +0000 Message-Id: <1613272907-22563-3-git-send-email-xuemingl@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1613272907-22563-1-git-send-email-xuemingl@nvidia.com> References: <1613272907-22563-1-git-send-email-xuemingl@nvidia.com> In-Reply-To: <1608303356-13089-2-git-send-email-xuemingl@nvidia.com> References: <1608303356-13089-2-git-send-email-xuemingl@nvidia.com> Subject: [dpdk-dev] [PATCH v6 2/9] ethdev: support representor port list X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" To support extended representor syntax, this patch extends the representor list parsing to support for representor port range in devargs, examples: representor=[1,2,3] - single list representor=[1,3-5,7,9-11] - list with singles and ranges Signed-off-by: Xueming Li Acked-by: Viacheslav Ovsiienko Acked-by: Thomas Monjalon Acked-by: Andrew Rybchenko --- lib/librte_ethdev/ethdev_private.c | 129 ++++++++++++++++------------- lib/librte_ethdev/ethdev_private.h | 3 - lib/librte_ethdev/rte_class_eth.c | 4 +- lib/librte_ethdev/rte_ethdev.c | 5 +- 4 files changed, 74 insertions(+), 67 deletions(-) diff --git a/lib/librte_ethdev/ethdev_private.c b/lib/librte_ethdev/ethdev_private.c index 2d51e3857a..d5ef05ea6f 100644 --- a/lib/librte_ethdev/ethdev_private.c +++ b/lib/librte_ethdev/ethdev_private.c @@ -38,82 +38,91 @@ eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp, return NULL; } -int -rte_eth_devargs_parse_list(char *str, rte_eth_devargs_callback_t callback, - void *data) +/* Put new value into list. */ +static int +rte_eth_devargs_enlist(uint16_t *list, uint16_t *len_list, + const uint16_t max_list, uint16_t val) { - char *str_start; - int state; - int result; - - if (*str != '[') - /* Single element, not a list */ - return callback(str, data); - - /* Sanity check, then strip the brackets */ - str_start = &str[strlen(str) - 1]; - if (*str_start != ']') { - RTE_LOG(ERR, EAL, "(%s): List does not end with ']'\n", str); - return -EINVAL; - } - str++; - *str_start = '\0'; + uint16_t i; - /* Process list elements */ - state = 0; - while (1) { - if (state == 0) { - if (*str == '\0') - break; - if (*str != ',') { - str_start = str; - state = 1; - } - } else if (state == 1) { - if (*str == ',' || *str == '\0') { - if (str > str_start) { - /* Non-empty string fragment */ - *str = '\0'; - result = callback(str_start, data); - if (result < 0) - return result; - } - state = 0; - } - } - str++; + for (i = 0; i < *len_list; i++) { + if (list[i] == val) + return 0; } + if (*len_list >= max_list) + return -1; + list[(*len_list)++] = val; return 0; } -static int +/* Parse and enlist a range expression of "min-max" or a single value. */ +static char * rte_eth_devargs_process_range(char *str, uint16_t *list, uint16_t *len_list, const uint16_t max_list) { uint16_t lo, hi, val; - int result; + int result, n = 0; + char *pos = str; - result = sscanf(str, "%hu-%hu", &lo, &hi); + result = sscanf(str, "%hu%n-%hu%n", &lo, &n, &hi, &n); if (result == 1) { - if (*len_list >= max_list) - return -ENOMEM; - list[(*len_list)++] = lo; + if (rte_eth_devargs_enlist(list, len_list, max_list, lo) != 0) + return NULL; } else if (result == 2) { - if (lo >= hi || lo > RTE_MAX_ETHPORTS || hi > RTE_MAX_ETHPORTS) - return -EINVAL; + if (lo > hi) + return NULL; for (val = lo; val <= hi; val++) { - if (*len_list >= max_list) - return -ENOMEM; - list[(*len_list)++] = val; + if (rte_eth_devargs_enlist(list, len_list, max_list, + val) != 0) + return NULL; } } else - return -EINVAL; - return 0; + return NULL; + return pos + n; +} + +/* + * Parse list of values separated by ",". + * Each value could be a range [min-max] or single number. + * Examples: + * 2 - single + * [1,2,3] - single list + * [1,3-5,7,9-11] - list with singles and ranges + */ +static char * +rte_eth_devargs_process_list(char *str, uint16_t *list, uint16_t *len_list, + const uint16_t max_list) +{ + char *pos = str; + + if (*pos == '[') + pos++; + while (1) { + pos = rte_eth_devargs_process_range(pos, list, len_list, + max_list); + if (pos == NULL) + return NULL; + if (*pos != ',') /* end of list */ + break; + pos++; + } + if (*str == '[' && *pos != ']') + return NULL; + if (*pos == ']') + pos++; + return pos; } /* - * representor format: + * Parse representor ports from a single value or lists. + * + * Representor format: * #: range or single number of VF representor + * + * Examples of #: + * 2 - single + * [1,2,3] - single list + * [1,3-5,7,9-11] - list with singles and ranges */ int rte_eth_devargs_parse_representor_ports(char *str, void *data) @@ -121,6 +130,10 @@ rte_eth_devargs_parse_representor_ports(char *str, void *data) struct rte_eth_devargs *eth_da = data; eth_da->type = RTE_ETH_REPRESENTOR_VF; - return rte_eth_devargs_process_range(str, eth_da->representor_ports, - ð_da->nb_representor_ports, RTE_MAX_ETHPORTS); + str = rte_eth_devargs_process_list(str, eth_da->representor_ports, + ð_da->nb_representor_ports, + RTE_DIM(eth_da->representor_ports)); + if (str == NULL) + RTE_LOG(ERR, EAL, "wrong representor format: %s\n", str); + return str == NULL ? -1 : 0; } diff --git a/lib/librte_ethdev/ethdev_private.h b/lib/librte_ethdev/ethdev_private.h index 905a45c337..220ddd4408 100644 --- a/lib/librte_ethdev/ethdev_private.h +++ b/lib/librte_ethdev/ethdev_private.h @@ -26,9 +26,6 @@ eth_find_device(const struct rte_eth_dev *_start, rte_eth_cmp_t cmp, const void *data); /* Parse devargs value for representor parameter. */ -typedef int (*rte_eth_devargs_callback_t)(char *str, void *data); -int rte_eth_devargs_parse_list(char *str, rte_eth_devargs_callback_t callback, - void *data); int rte_eth_devargs_parse_representor_ports(char *str, void *data); #ifdef __cplusplus diff --git a/lib/librte_ethdev/rte_class_eth.c b/lib/librte_ethdev/rte_class_eth.c index ca2ce87f7a..051c892b40 100644 --- a/lib/librte_ethdev/rte_class_eth.c +++ b/lib/librte_ethdev/rte_class_eth.c @@ -77,9 +77,7 @@ eth_representor_cmp(const char *key __rte_unused, if (values == NULL) return -1; memset(&representors, 0, sizeof(representors)); - ret = rte_eth_devargs_parse_list(values, - rte_eth_devargs_parse_representor_ports, - &representors); + ret = rte_eth_devargs_parse_representor_ports(values, &representors); free(values); if (ret != 0) return -1; /* invalid devargs value */ diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c index 6f514c388b..fe9466a03e 100644 --- a/lib/librte_ethdev/rte_ethdev.c +++ b/lib/librte_ethdev/rte_ethdev.c @@ -5589,9 +5589,8 @@ rte_eth_devargs_parse(const char *dargs, struct rte_eth_devargs *eth_da) for (i = 0; i < args.count; i++) { pair = &args.pairs[i]; if (strcmp("representor", pair->key) == 0) { - result = rte_eth_devargs_parse_list(pair->value, - rte_eth_devargs_parse_representor_ports, - eth_da); + result = rte_eth_devargs_parse_representor_ports( + pair->value, eth_da); if (result < 0) goto parse_cleanup; } From patchwork Sun Feb 14 03:21:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xueming Li X-Patchwork-Id: 87911 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id D7DC4A0546; Sun, 14 Feb 2021 04:23:30 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id B97C822A23C; Sun, 14 Feb 2021 04:23:30 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id 72626406A2 for ; Sun, 14 Feb 2021 04:23:28 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from xuemingl@nvidia.com) with SMTP; 14 Feb 2021 05:23:25 +0200 Received: from nvidia.com (pegasus05.mtr.labs.mlnx [10.210.16.100]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 11E3MYvP008525; Sun, 14 Feb 2021 05:23:25 +0200 From: Xueming Li To: Cc: dev@dpdk.org, Viacheslav Ovsiienko , xuemingl@nvidia.com, Asaf Penso , Thomas Monjalon , Ferruh Yigit , Andrew Rybchenko Date: Sun, 14 Feb 2021 03:21:33 +0000 Message-Id: <1613272907-22563-4-git-send-email-xuemingl@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1613272907-22563-1-git-send-email-xuemingl@nvidia.com> References: <1613272907-22563-1-git-send-email-xuemingl@nvidia.com> In-Reply-To: <1608303356-13089-2-git-send-email-xuemingl@nvidia.com> References: <1608303356-13089-2-git-send-email-xuemingl@nvidia.com> Subject: [dpdk-dev] [PATCH v6 3/9] ethdev: support new VF representor syntax X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Current VF representor syntax: representor=2 - single representor representor=[0-3] - single range To prepare for more representor types, this patch adds compatible VF representor devargs syntax: vf#: representor=vf2 - single representor representor=vf[1,3,5] - single list representor=vf[0-3] - single range representor=vf[0,1,4-7] - list with singles and range For backwards compatibility, representor "#" is interpreted as "vf#". Signed-off-by: Xueming Li Acked-by: Viacheslav Ovsiienko Acked-by: Thomas Monjalon Acked-by: Andrew Rybchenko --- doc/guides/prog_guide/poll_mode_drv.rst | 7 ++++--- lib/librte_ethdev/ethdev_private.c | 5 ++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/doc/guides/prog_guide/poll_mode_drv.rst b/doc/guides/prog_guide/poll_mode_drv.rst index 239ec820ea..0117c2af07 100644 --- a/doc/guides/prog_guide/poll_mode_drv.rst +++ b/doc/guides/prog_guide/poll_mode_drv.rst @@ -374,9 +374,10 @@ parameters to those ports. this argument allows user to specify which switch ports to enable port representors for.:: - -a DBDF,representor=0 - -a DBDF,representor=[0,4,6,9] - -a DBDF,representor=[0-31] + -a DBDF,representor=vf0 + -a DBDF,representor=vf[0,4,6,9] + -a DBDF,representor=vf[0-31] + -a DBDF,representor=vf[0,2-4,7,9-11] Note: PMDs are not required to support the standard device arguments and users should consult the relevant PMD documentation to see support devargs. diff --git a/lib/librte_ethdev/ethdev_private.c b/lib/librte_ethdev/ethdev_private.c index d5ef05ea6f..4bb3879859 100644 --- a/lib/librte_ethdev/ethdev_private.c +++ b/lib/librte_ethdev/ethdev_private.c @@ -117,7 +117,8 @@ rte_eth_devargs_process_list(char *str, uint16_t *list, uint16_t *len_list, * Parse representor ports from a single value or lists. * * Representor format: - * #: range or single number of VF representor + * #: range or single number of VF representor - legacy + * vf#: VF port representor/s * * Examples of #: * 2 - single @@ -130,6 +131,8 @@ rte_eth_devargs_parse_representor_ports(char *str, void *data) struct rte_eth_devargs *eth_da = data; eth_da->type = RTE_ETH_REPRESENTOR_VF; + if (str[0] == 'v' && str[1] == 'f') + str += 2; str = rte_eth_devargs_process_list(str, eth_da->representor_ports, ð_da->nb_representor_ports, RTE_DIM(eth_da->representor_ports)); From patchwork Sun Feb 14 03:21:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xueming Li X-Patchwork-Id: 87912 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 96CF4A0546; Sun, 14 Feb 2021 04:23:37 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 081BB22A246; Sun, 14 Feb 2021 04:23:35 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id 6171422A246 for ; Sun, 14 Feb 2021 04:23:33 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from xuemingl@nvidia.com) with SMTP; 14 Feb 2021 05:23:29 +0200 Received: from nvidia.com (pegasus05.mtr.labs.mlnx [10.210.16.100]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 11E3MYvQ008525; Sun, 14 Feb 2021 05:23:29 +0200 From: Xueming Li To: Cc: dev@dpdk.org, Viacheslav Ovsiienko , xuemingl@nvidia.com, Asaf Penso , Thomas Monjalon , Ferruh Yigit , Andrew Rybchenko Date: Sun, 14 Feb 2021 03:21:34 +0000 Message-Id: <1613272907-22563-5-git-send-email-xuemingl@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1613272907-22563-1-git-send-email-xuemingl@nvidia.com> References: <1613272907-22563-1-git-send-email-xuemingl@nvidia.com> In-Reply-To: <1608303356-13089-2-git-send-email-xuemingl@nvidia.com> References: <1608303356-13089-2-git-send-email-xuemingl@nvidia.com> Subject: [dpdk-dev] [PATCH v6 4/9] ethdev: support sub function representor X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" SubFunction is a portion of the PCI device, created on demand, a SF netdev has its own dedicated queues(txq, rxq). A SF netdev supports eswitch representation offload similar to existing PF and VF representors. To support SF representor, this patch introduces new devargs syntax, examples: representor=sf0 - single SubFunction representor representor=sf[1,3,5] - single list representor=sf[0-3], - single range representor=sf[0,2-6,8,10-12] - list with singles and ranges Signed-off-by: Xueming Li Acked-by: Viacheslav Ovsiienko Acked-by: Thomas Monjalon Acked-by: Andrew Rybchenko --- doc/guides/prog_guide/poll_mode_drv.rst | 4 +++ .../prog_guide/switch_representation.rst | 35 +++++++++++++------ lib/librte_ethdev/ethdev_private.c | 11 ++++-- lib/librte_ethdev/rte_ethdev.h | 1 + 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/doc/guides/prog_guide/poll_mode_drv.rst b/doc/guides/prog_guide/poll_mode_drv.rst index 0117c2af07..86e5867f1b 100644 --- a/doc/guides/prog_guide/poll_mode_drv.rst +++ b/doc/guides/prog_guide/poll_mode_drv.rst @@ -378,6 +378,10 @@ parameters to those ports. -a DBDF,representor=vf[0,4,6,9] -a DBDF,representor=vf[0-31] -a DBDF,representor=vf[0,2-4,7,9-11] + -a DBDF,representor=sf0 + -a DBDF,representor=sf[1,3,5] + -a DBDF,representor=sf[0-1023] + -a DBDF,representor=sf[0,2-4,7,9-11] Note: PMDs are not required to support the standard device arguments and users should consult the relevant PMD documentation to see support devargs. diff --git a/doc/guides/prog_guide/switch_representation.rst b/doc/guides/prog_guide/switch_representation.rst index 07ba12bea6..ff6aa91c80 100644 --- a/doc/guides/prog_guide/switch_representation.rst +++ b/doc/guides/prog_guide/switch_representation.rst @@ -13,7 +13,7 @@ Introduction Network adapters with multiple physical ports and/or SR-IOV capabilities usually support the offload of traffic steering rules between their virtual -functions (VFs), physical functions (PFs) and ports. +functions (VFs), sub functions (SFs), physical functions (PFs) and ports. Like for standard Ethernet switches, this involves a combination of automatic MAC learning and manual configuration. For most purposes it is @@ -24,7 +24,7 @@ layer 2 (L2) traffic (such as OVS) need to steer traffic themselves according on their own criteria. Without a standard software interface to manage traffic steering rules -between VFs, PFs and the various physical ports of a given device, +between VFs, SFs, PFs and the various physical ports of a given device, applications cannot take advantage of these offloads; software processing is mandatory even for traffic which ends up re-injected into the device it originates from. @@ -34,6 +34,17 @@ the DPDK flow API (**rte_flow**), with emphasis on the SR-IOV use case (PF/VF steering) using a single physical port for clarity, however the same logic applies to any number of ports without necessarily involving SR-IOV. +Sub Function +------------ +Besides SR-IOV, Sub function is a portion of the PCI device, a SF netdev +has its own dedicated queues(txq, rxq). A SF netdev supports E-Switch +representation offload similar to existing PF and VF representors. +A SF shares PCI level resources with other SFs and/or with its parent PCI +function. + +Sub function is created on-demand, coexists with VFs. Number of SFs is +limited by hardware resources. + Port Representors ----------------- @@ -42,15 +53,16 @@ applications usually have to process a bit of traffic in software before thinking about offloading specific flows to hardware. Applications therefore need the ability to receive and inject traffic to -various device endpoints (other VFs, PFs or physical ports) before +various device endpoints (other VFs, SFs, PFs or physical ports) before connecting them together. Device drivers must provide means to hook the "other end" of these endpoints and to refer them when configuring flow rules. This role is left to so-called "port representors" (also known as "VF -representors" in the specific context of VFs), which are to DPDK what the -Ethernet switch device driver model (**switchdev**) [1]_ is to Linux, and -which can be thought as a software "patch panel" front-end for applications. +representors" in the specific context of VFs, "SF representors" in the +specific context of SFs), which are to DPDK what the Ethernet switch +device driver model (**switchdev**) [1]_ is to Linux, and which can be +thought as a software "patch panel" front-end for applications. - DPDK port representors are implemented as additional virtual Ethernet device (**ethdev**) instances, spawned on an as needed basis through @@ -59,9 +71,12 @@ which can be thought as a software "patch panel" front-end for applications. :: - -a pci:dbdf,representor=0 - -a pci:dbdf,representor=[0-3] - -a pci:dbdf,representor=[0,5-11] + -a pci:dbdf,representor=vf0 + -a pci:dbdf,representor=vf[0-3] + -a pci:dbdf,representor=vf[0,5-11] + -a pci:dbdf,representor=sf1 + -a pci:dbdf,representor=sf[0-1023] + -a pci:dbdf,representor=sf[0,2-1023] - As virtual devices, they may be more limited than their physical counterparts, for instance by exposing only a subset of device @@ -360,7 +375,7 @@ Compared to creating a brand new dedicated interface, **rte_flow** was deemed flexible enough to manage representor traffic only with minor extensions: -- Using physical ports, PF, VF or port representors as targets. +- Using physical ports, PF, SF, VF or port representors as targets. - Affecting traffic that is not necessarily addressed to the DPDK port ID a flow rule is associated with (e.g. forcing VF traffic redirection to PF). diff --git a/lib/librte_ethdev/ethdev_private.c b/lib/librte_ethdev/ethdev_private.c index 4bb3879859..13c191192e 100644 --- a/lib/librte_ethdev/ethdev_private.c +++ b/lib/librte_ethdev/ethdev_private.c @@ -119,6 +119,7 @@ rte_eth_devargs_process_list(char *str, uint16_t *list, uint16_t *len_list, * Representor format: * #: range or single number of VF representor - legacy * vf#: VF port representor/s + * sf#: SF port representor/s * * Examples of #: * 2 - single @@ -130,9 +131,15 @@ rte_eth_devargs_parse_representor_ports(char *str, void *data) { struct rte_eth_devargs *eth_da = data; - eth_da->type = RTE_ETH_REPRESENTOR_VF; - if (str[0] == 'v' && str[1] == 'f') + if (str[0] == 'v' && str[1] == 'f') { + eth_da->type = RTE_ETH_REPRESENTOR_VF; str += 2; + } else if (str[0] == 's' && str[1] == 'f') { + eth_da->type = RTE_ETH_REPRESENTOR_SF; + str += 2; + } else { + eth_da->type = RTE_ETH_REPRESENTOR_VF; + } str = rte_eth_devargs_process_list(str, eth_da->representor_ports, ð_da->nb_representor_ports, RTE_DIM(eth_da->representor_ports)); diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h index 1f378958ca..26b5e109c3 100644 --- a/lib/librte_ethdev/rte_ethdev.h +++ b/lib/librte_ethdev/rte_ethdev.h @@ -1512,6 +1512,7 @@ struct rte_eth_rxseg_capa { enum rte_eth_representor_type { RTE_ETH_REPRESENTOR_NONE, /**< not a representor. */ RTE_ETH_REPRESENTOR_VF, /**< representor of Virtual Function. */ + RTE_ETH_REPRESENTOR_SF, /**< representor of Sub Function. */ }; /** From patchwork Sun Feb 14 03:21:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xueming Li X-Patchwork-Id: 87913 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 2F70BA0546; Sun, 14 Feb 2021 04:23:46 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 3BC9822A251; Sun, 14 Feb 2021 04:23:36 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id 58C1D22A245 for ; Sun, 14 Feb 2021 04:23:33 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from xuemingl@nvidia.com) with SMTP; 14 Feb 2021 05:23:31 +0200 Received: from nvidia.com (pegasus05.mtr.labs.mlnx [10.210.16.100]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 11E3MYvR008525; Sun, 14 Feb 2021 05:23:31 +0200 From: Xueming Li To: Cc: dev@dpdk.org, Viacheslav Ovsiienko , xuemingl@nvidia.com, Asaf Penso , Thomas Monjalon , Ferruh Yigit , Andrew Rybchenko Date: Sun, 14 Feb 2021 03:21:35 +0000 Message-Id: <1613272907-22563-6-git-send-email-xuemingl@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1613272907-22563-1-git-send-email-xuemingl@nvidia.com> References: <1613272907-22563-1-git-send-email-xuemingl@nvidia.com> In-Reply-To: <1608303356-13089-2-git-send-email-xuemingl@nvidia.com> References: <1608303356-13089-2-git-send-email-xuemingl@nvidia.com> Subject: [dpdk-dev] [PATCH v6 5/9] ethdev: support PF index in representor X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" With Kernel bonding, multiple underlying PFs are bonded, VFs come from different PF, need to identify representor of VFs unambiguously by adding PF index. This patch introduces optional 'pf' section to representor devargs syntax, examples: representor=pf0vf0 - single VF representor representor=pf[0-1]sf[0-1023] - SF representors from 2 PFs PF type representor is supported by using standalone 'pf' section: representor=pf1 - PF representor Signed-off-by: Xueming Li Acked-by: Viacheslav Ovsiienko Acked-by: Thomas Monjalon Acked-by: Andrew Rybchenko --- doc/guides/prog_guide/poll_mode_drv.rst | 2 ++ lib/librte_ethdev/ethdev_private.c | 18 ++++++++++++++++-- lib/librte_ethdev/rte_ethdev.h | 1 + 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/doc/guides/prog_guide/poll_mode_drv.rst b/doc/guides/prog_guide/poll_mode_drv.rst index 86e5867f1b..b2147aad30 100644 --- a/doc/guides/prog_guide/poll_mode_drv.rst +++ b/doc/guides/prog_guide/poll_mode_drv.rst @@ -382,6 +382,8 @@ parameters to those ports. -a DBDF,representor=sf[1,3,5] -a DBDF,representor=sf[0-1023] -a DBDF,representor=sf[0,2-4,7,9-11] + -a DBDF,representor=pf1vf0 + -a DBDF,representor=pf[0-1]sf[0-127] Note: PMDs are not required to support the standard device arguments and users should consult the relevant PMD documentation to see support devargs. diff --git a/lib/librte_ethdev/ethdev_private.c b/lib/librte_ethdev/ethdev_private.c index 13c191192e..eea0686020 100644 --- a/lib/librte_ethdev/ethdev_private.c +++ b/lib/librte_ethdev/ethdev_private.c @@ -118,8 +118,8 @@ rte_eth_devargs_process_list(char *str, uint16_t *list, uint16_t *len_list, * * Representor format: * #: range or single number of VF representor - legacy - * vf#: VF port representor/s - * sf#: SF port representor/s + * [pf#]vf#: VF port representor/s + * [pf#]sf#: SF port representor/s * * Examples of #: * 2 - single @@ -131,6 +131,14 @@ rte_eth_devargs_parse_representor_ports(char *str, void *data) { struct rte_eth_devargs *eth_da = data; + if (str[0] == 'p' && str[1] == 'f') { + eth_da->type = RTE_ETH_REPRESENTOR_PF; + str += 2; + str = rte_eth_devargs_process_list(str, eth_da->ports, + ð_da->nb_ports, RTE_DIM(eth_da->ports)); + if (str == NULL) + goto err; + } if (str[0] == 'v' && str[1] == 'f') { eth_da->type = RTE_ETH_REPRESENTOR_VF; str += 2; @@ -138,11 +146,17 @@ rte_eth_devargs_parse_representor_ports(char *str, void *data) eth_da->type = RTE_ETH_REPRESENTOR_SF; str += 2; } else { + /* Don't mix legacy syntax with 'pf' section. */ + if (eth_da->type == RTE_ETH_REPRESENTOR_PF) { + str = NULL; + goto err; + } eth_da->type = RTE_ETH_REPRESENTOR_VF; } str = rte_eth_devargs_process_list(str, eth_da->representor_ports, ð_da->nb_representor_ports, RTE_DIM(eth_da->representor_ports)); +err: if (str == NULL) RTE_LOG(ERR, EAL, "wrong representor format: %s\n", str); return str == NULL ? -1 : 0; diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h index 26b5e109c3..9cd519bf59 100644 --- a/lib/librte_ethdev/rte_ethdev.h +++ b/lib/librte_ethdev/rte_ethdev.h @@ -1513,6 +1513,7 @@ enum rte_eth_representor_type { RTE_ETH_REPRESENTOR_NONE, /**< not a representor. */ RTE_ETH_REPRESENTOR_VF, /**< representor of Virtual Function. */ RTE_ETH_REPRESENTOR_SF, /**< representor of Sub Function. */ + RTE_ETH_REPRESENTOR_PF, /**< representor of Physical Function. */ }; /** From patchwork Sun Feb 14 03:21:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xueming Li X-Patchwork-Id: 87914 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 8F0F3A0546; Sun, 14 Feb 2021 04:23:56 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 7647422A257; Sun, 14 Feb 2021 04:23:39 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id 64F7022A24C for ; Sun, 14 Feb 2021 04:23:38 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from xuemingl@nvidia.com) with SMTP; 14 Feb 2021 05:23:34 +0200 Received: from nvidia.com (pegasus05.mtr.labs.mlnx [10.210.16.100]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 11E3MYvS008525; Sun, 14 Feb 2021 05:23:33 +0200 From: Xueming Li To: Cc: dev@dpdk.org, Viacheslav Ovsiienko , xuemingl@nvidia.com, Asaf Penso , Bruce Richardson , Thomas Monjalon , Ferruh Yigit , Andrew Rybchenko Date: Sun, 14 Feb 2021 03:21:36 +0000 Message-Id: <1613272907-22563-7-git-send-email-xuemingl@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1613272907-22563-1-git-send-email-xuemingl@nvidia.com> References: <1613272907-22563-1-git-send-email-xuemingl@nvidia.com> In-Reply-To: <1608303356-13089-2-git-send-email-xuemingl@nvidia.com> References: <1608303356-13089-2-git-send-email-xuemingl@nvidia.com> Subject: [dpdk-dev] [PATCH v6 6/9] ethdev: support multi-host in representor X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The NIC can have multiple PCIe links and can be attached to the multiple hosts, for example the same single NIC can be shared for multiple server units in the rack. On each PCIe link NIC can provide multiple PFs and VFs/SFs based on these ones. To provide the unambiguous identification of the PCIe function the controller index is added. The full representor identifier consists of three indices - controller index, PF index, and VF or SF index (if any). This patch introduces controller index to ethdev representor syntax, examples: [[c#]pf#]vf#: VF port representor/s, example: pf0vf1 [[c#]pf#]sf#: SF port representor/s, example: c1pf1sf[0-3] c# is controller(host) ID/range in case of multi-host, optional. For user application (e.g. OVS), PMD is responsible to interpret and locate representor device based on controller ID, PF ID and VF/SF ID in representor syntax. Signed-off-by: Xueming Li Acked-by: Viacheslav Ovsiienko Acked-by: Thomas Monjalon Acked-by: Andrew Rybchenko --- config/rte_config.h | 1 + lib/librte_ethdev/ethdev_driver.h | 4 ++++ lib/librte_ethdev/ethdev_private.c | 25 +++++++++++++++++++++---- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/config/rte_config.h b/config/rte_config.h index 55a2fc50ed..904a40b3c1 100644 --- a/config/rte_config.h +++ b/config/rte_config.h @@ -57,6 +57,7 @@ #define RTE_MAX_QUEUES_PER_PORT 1024 #define RTE_ETHDEV_QUEUE_STAT_CNTRS 16 /* max 256 */ #define RTE_ETHDEV_RXTX_CALLBACKS 1 +#define RTE_MAX_MULTI_HOST_CTRLS 4 /* cryptodev defines */ #define RTE_CRYPTO_MAX_DEVS 64 diff --git a/lib/librte_ethdev/ethdev_driver.h b/lib/librte_ethdev/ethdev_driver.h index d68b8401e7..06ff35266f 100644 --- a/lib/librte_ethdev/ethdev_driver.h +++ b/lib/librte_ethdev/ethdev_driver.h @@ -1222,6 +1222,10 @@ rte_eth_switch_domain_free(uint16_t domain_id); * One type of representor each structure. */ struct rte_eth_devargs { + uint16_t mh_controllers[RTE_MAX_MULTI_HOST_CTRLS]; + /** controller/s number in case of multi-host */ + uint16_t nb_mh_controllers; + /** number of controllers in multi-host controllers field */ uint16_t ports[RTE_MAX_ETHPORTS]; /** port/s number to enable on a multi-port single function */ uint16_t nb_ports; diff --git a/lib/librte_ethdev/ethdev_private.c b/lib/librte_ethdev/ethdev_private.c index eea0686020..5cd62de6f8 100644 --- a/lib/librte_ethdev/ethdev_private.c +++ b/lib/librte_ethdev/ethdev_private.c @@ -118,8 +118,8 @@ rte_eth_devargs_process_list(char *str, uint16_t *list, uint16_t *len_list, * * Representor format: * #: range or single number of VF representor - legacy - * [pf#]vf#: VF port representor/s - * [pf#]sf#: SF port representor/s + * [[c#]pf#]vf#: VF port representor/s + * [[c#]pf#]sf#: SF port representor/s * * Examples of #: * 2 - single @@ -131,6 +131,14 @@ rte_eth_devargs_parse_representor_ports(char *str, void *data) { struct rte_eth_devargs *eth_da = data; + if (str[0] == 'c') { + str += 1; + str = rte_eth_devargs_process_list(str, eth_da->mh_controllers, + ð_da->nb_mh_controllers, + RTE_DIM(eth_da->mh_controllers)); + if (str == NULL) + goto err; + } if (str[0] == 'p' && str[1] == 'f') { eth_da->type = RTE_ETH_REPRESENTOR_PF; str += 2; @@ -146,8 +154,9 @@ rte_eth_devargs_parse_representor_ports(char *str, void *data) eth_da->type = RTE_ETH_REPRESENTOR_SF; str += 2; } else { - /* Don't mix legacy syntax with 'pf' section. */ - if (eth_da->type == RTE_ETH_REPRESENTOR_PF) { + /* Don't mix legacy syntax with 'pf' and 'c' section. */ + if (eth_da->type == RTE_ETH_REPRESENTOR_PF || + eth_da->nb_mh_controllers > 0) { str = NULL; goto err; } @@ -156,6 +165,14 @@ rte_eth_devargs_parse_representor_ports(char *str, void *data) str = rte_eth_devargs_process_list(str, eth_da->representor_ports, ð_da->nb_representor_ports, RTE_DIM(eth_da->representor_ports)); + if (str == NULL) + goto err; + /* "pf" must sit in middle of "c" and "vf"/"sf". */ + if (eth_da->nb_representor_ports > 0 && eth_da->nb_mh_controllers > 0 && + eth_da->nb_ports == 0) { + RTE_LOG(ERR, EAL, "'pf' section missing: %s\n", str); + return -1; + } err: if (str == NULL) RTE_LOG(ERR, EAL, "wrong representor format: %s\n", str); From patchwork Sun Feb 14 03:21:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xueming Li X-Patchwork-Id: 87915 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 7D1B5A0546; Sun, 14 Feb 2021 04:24:06 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id C0BAA22A24F; Sun, 14 Feb 2021 04:23:49 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id AD017227EA5 for ; Sun, 14 Feb 2021 04:23:47 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from xuemingl@nvidia.com) with SMTP; 14 Feb 2021 05:23:44 +0200 Received: from nvidia.com (pegasus05.mtr.labs.mlnx [10.210.16.100]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 11E3MYvT008525; Sun, 14 Feb 2021 05:23:43 +0200 From: Xueming Li To: Cc: dev@dpdk.org, Viacheslav Ovsiienko , xuemingl@nvidia.com, Asaf Penso , Thomas Monjalon , Ferruh Yigit , Andrew Rybchenko , Ray Kinsella , Neil Horman Date: Sun, 14 Feb 2021 03:21:37 +0000 Message-Id: <1613272907-22563-8-git-send-email-xuemingl@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1613272907-22563-1-git-send-email-xuemingl@nvidia.com> References: <1613272907-22563-1-git-send-email-xuemingl@nvidia.com> In-Reply-To: <1608303356-13089-2-git-send-email-xuemingl@nvidia.com> References: <1608303356-13089-2-git-send-email-xuemingl@nvidia.com> Subject: [dpdk-dev] [PATCH v6 7/9] ethdev: new API to get representor info X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The NIC can have multiple PCIe links and can be attached to multiple hosts, for example the same single NIC can be shared for multiple server units in the rack. On each PCIe link NIC can provide multiple PFs and VFs/SFs based on these ones. The full representor identifier consists of three indices - controller index, PF index, and VF or SF index (if any). This patch introduces a new API rte_eth_representor_info_get() to retrieve representor corresponding info mapping: - caller controller index and pf index. - supported representor ID ranges. - type, controller, pf and start vf/sf ID of each range. The API is useful to convert representor from devargs to representor ID. New ethdev callback representor_info_get() is added to retrieve info from PMD driver, optional for PMD that doesn't support new devargs representor syntax. Signed-off-by: Xueming Li --- lib/librte_ethdev/ethdev_driver.h | 6 +++++ lib/librte_ethdev/rte_ethdev.c | 14 ++++++++++ lib/librte_ethdev/rte_ethdev.h | 43 +++++++++++++++++++++++++++++++ lib/librte_ethdev/version.map | 3 +++ 4 files changed, 66 insertions(+) diff --git a/lib/librte_ethdev/ethdev_driver.h b/lib/librte_ethdev/ethdev_driver.h index 06ff35266f..abcbc3112d 100644 --- a/lib/librte_ethdev/ethdev_driver.h +++ b/lib/librte_ethdev/ethdev_driver.h @@ -289,6 +289,10 @@ typedef int (*eth_fw_version_get_t)(struct rte_eth_dev *dev, char *fw_version, size_t fw_size); /**< @internal Get firmware information of an Ethernet device. */ +typedef int (*eth_representor_info_get_t)(struct rte_eth_dev *dev, + struct rte_eth_representor_info *info); +/**< @internal Get representor type and ID range. */ + typedef int (*eth_tx_done_cleanup_t)(void *txq, uint32_t free_cnt); /**< @internal Force mbufs to be from TX ring. */ @@ -823,6 +827,8 @@ struct eth_dev_ops { eth_burst_mode_get_t rx_burst_mode_get; /**< Get RX burst mode */ eth_burst_mode_get_t tx_burst_mode_get; /**< Get TX burst mode */ eth_fw_version_get_t fw_version_get; /**< Get firmware version. */ + eth_representor_info_get_t representor_info_get; + /**< Get representor info. */ eth_dev_supported_ptypes_get_t dev_supported_ptypes_get; /**< Get packet types supported and identified by device. */ eth_dev_ptypes_set_t dev_ptypes_set; diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c index fe9466a03e..07c6debb58 100644 --- a/lib/librte_ethdev/rte_ethdev.c +++ b/lib/librte_ethdev/rte_ethdev.c @@ -3265,6 +3265,20 @@ rte_eth_dev_fw_version_get(uint16_t port_id, char *fw_version, size_t fw_size) fw_version, fw_size)); } +int +rte_eth_representor_info_get(uint16_t port_id, + struct rte_eth_representor_info *info) +{ + struct rte_eth_dev *dev; + + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); + dev = &rte_eth_devices[port_id]; + + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->fw_version_get, -ENOTSUP); + return eth_err(port_id, (*dev->dev_ops->representor_info_get)(dev, + info)); +} + int rte_eth_dev_info_get(uint16_t port_id, struct rte_eth_dev_info *dev_info) { diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h index 9cd519bf59..35eb0a5721 100644 --- a/lib/librte_ethdev/rte_ethdev.h +++ b/lib/librte_ethdev/rte_ethdev.h @@ -1581,6 +1581,30 @@ struct rte_eth_dev_info { void *reserved_ptrs[2]; /**< Reserved for future fields */ }; +/** + * @warning + * @b EXPERIMENTAL: this structure may change without prior notice. + * + * Ethernet device representor information + */ +struct rte_eth_representor_info { + uint16_t controller; /**< Controller ID of caller device. */ + uint16_t pf; /**< Physical function ID of caller device. */ + struct { + enum rte_eth_representor_type type; /**< Representor type */ + int controller; /**< Controller ID, -1 to ignore */ + int pf; /**< Physical function ID, -1 to ignore */ + __extension__ + union { + int vf; /**< VF start index */ + int sf; /**< SF start index */ + }; + uint16_t id_base; /**< Representor ID start index */ + uint16_t id_end; /**< Representor ID end index */ + char name[RTE_DEV_NAME_MAX_LEN]; /**< Representor name */ + } ranges[]; /**< Representor ID range by type */ +}; + /** * Ethernet device RX queue information structure. * Used to retrieve information about configured queue. @@ -3038,6 +3062,25 @@ int rte_eth_macaddr_get(uint16_t port_id, struct rte_ether_addr *mac_addr); */ int rte_eth_dev_info_get(uint16_t port_id, struct rte_eth_dev_info *dev_info); +/** + * Retrieve the representor info of the device. + * + * @param port_id + * The port identifier of the device. + * @param info + * A pointer to a representor info structure. + * NULL to return number of range entries and allocate memory + * for next call to store detail. + * @return + * - (-ENOTSUP) if operation is not supported. + * - (-ENODEV) if *port_id* invalid. + * - (-EIO) if device is removed. + * - (>=0) number of representor range entries supported by device. + */ +__rte_experimental +int rte_eth_representor_info_get(uint16_t port_id, + struct rte_eth_representor_info *info); + /** * Retrieve the firmware version of a device. * diff --git a/lib/librte_ethdev/version.map b/lib/librte_ethdev/version.map index a124e1e370..bb6f7436c2 100644 --- a/lib/librte_ethdev/version.map +++ b/lib/librte_ethdev/version.map @@ -243,6 +243,9 @@ EXPERIMENTAL { # added in 21.02 rte_eth_get_monitor_addr; + + # added in 21.05 + rte_eth_representor_info_get; }; INTERNAL { From patchwork Sun Feb 14 03:21:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xueming Li X-Patchwork-Id: 87916 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 3365DA0546; Sun, 14 Feb 2021 04:24:17 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 6A7CE22A256; Sun, 14 Feb 2021 04:23:54 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id CF74322A25F for ; Sun, 14 Feb 2021 04:23:52 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from xuemingl@nvidia.com) with SMTP; 14 Feb 2021 05:23:47 +0200 Received: from nvidia.com (pegasus05.mtr.labs.mlnx [10.210.16.100]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 11E3MYvU008525; Sun, 14 Feb 2021 05:23:47 +0200 From: Xueming Li To: Cc: dev@dpdk.org, Viacheslav Ovsiienko , xuemingl@nvidia.com, Asaf Penso , Thomas Monjalon , Ferruh Yigit , Andrew Rybchenko , Ray Kinsella , Neil Horman Date: Sun, 14 Feb 2021 03:21:38 +0000 Message-Id: <1613272907-22563-9-git-send-email-xuemingl@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1613272907-22563-1-git-send-email-xuemingl@nvidia.com> References: <1613272907-22563-1-git-send-email-xuemingl@nvidia.com> In-Reply-To: <1608303356-13089-2-git-send-email-xuemingl@nvidia.com> References: <1608303356-13089-2-git-send-email-xuemingl@nvidia.com> Subject: [dpdk-dev] [PATCH v6 8/9] ethdev: representor iterator compare complete info X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The NIC can have multiple PCIe links and can be attached to multiple hosts, for example the same single NIC can be shared for multiple server units in the rack. On each PCIe link NIC can provide multiple PFs and VFs/SFs based on these ones. The full representor identifier consists of three indices - controller index, PF index, and VF or SF index (if any). SR-IOV and SubFunction are created on top of PF. PF index is introduced because there might be multiple PFs in the bonding configuration and only bonding device is probed. In eth representor comparator callback, ethdev representor ID was compared with devarg. Since controller index and PF index not compared, callback returned representor from other PF or controller. This patch adds new API to convert representor controller, pf and vf/sf index to representor ID. Representor comparer callback convert representor info into ID and compare with device representor ID. Signed-off-by: Xueming Li --- lib/librte_ethdev/ethdev_driver.h | 32 ++++++++++++ lib/librte_ethdev/rte_class_eth.c | 38 ++++++++++---- lib/librte_ethdev/rte_ethdev.c | 83 +++++++++++++++++++++++++++++++ lib/librte_ethdev/version.map | 1 + 4 files changed, 145 insertions(+), 9 deletions(-) diff --git a/lib/librte_ethdev/ethdev_driver.h b/lib/librte_ethdev/ethdev_driver.h index abcbc3112d..23342f1be2 100644 --- a/lib/librte_ethdev/ethdev_driver.h +++ b/lib/librte_ethdev/ethdev_driver.h @@ -1243,6 +1243,38 @@ struct rte_eth_devargs { enum rte_eth_representor_type type; /* type of representor */ }; +/** + * PMD helper function to convert representor ID from location detail + * + * Convert representor ID from controller, pf and (sf or vf). + * The mapping is retrieved from rte_eth_representor_info_get(). + * + * If PMD doesn't return representor range info, simply ignore controller + * and pf to keep backward compatibility. + * + * @param ethdev + * Handle of ethdev port. + * @param id + * Pointer to converted representor ID. + * @param type + * Representor type. + * @param controller + * Controller ID, -1 if unspecified. + * @param pf + * PF port ID, -1 if unspecified. + * @param representor_port + * Representor port ID, -1 if unspecified. + * + * @return + * Negative errno value on error, 0 on success. + */ +__rte_internal +int +rte_eth_representor_id_convert(const struct rte_eth_dev *ethdev, + uint16_t *id, + enum rte_eth_representor_type type, + int controller, int pf, int representor_port); + /** * PMD helper function to parse ethdev arguments * diff --git a/lib/librte_ethdev/rte_class_eth.c b/lib/librte_ethdev/rte_class_eth.c index 051c892b40..f7b7e659e7 100644 --- a/lib/librte_ethdev/rte_class_eth.c +++ b/lib/librte_ethdev/rte_class_eth.c @@ -65,9 +65,10 @@ eth_representor_cmp(const char *key __rte_unused, { int ret; char *values; - const struct rte_eth_dev_data *data = opaque; - struct rte_eth_devargs representors; - uint16_t index; + const struct rte_eth_dev *edev = opaque; + const struct rte_eth_dev_data *data = edev->data; + struct rte_eth_devargs eth_da; + uint16_t id, nc, np, nf, i, c, p, f; if ((data->dev_flags & RTE_ETH_DEV_REPRESENTOR) == 0) return -1; /* not a representor port */ @@ -76,17 +77,36 @@ eth_representor_cmp(const char *key __rte_unused, values = strdup(value); if (values == NULL) return -1; - memset(&representors, 0, sizeof(representors)); - ret = rte_eth_devargs_parse_representor_ports(values, &representors); + memset(ð_da, 0, sizeof(eth_da)); + ret = rte_eth_devargs_parse_representor_ports(values, ð_da); free(values); if (ret != 0) return -1; /* invalid devargs value */ + if (eth_da.nb_mh_controllers == 0 && eth_da.nb_ports == 0 && + eth_da.nb_representor_ports == 0) + return -1; + nc = eth_da.nb_mh_controllers > 0 ? eth_da.nb_mh_controllers : 1; + np = eth_da.nb_ports > 0 ? eth_da.nb_ports : 1; + nf = eth_da.nb_representor_ports > 0 ? eth_da.nb_representor_ports : 1; + /* Return 0 if representor id is matching one of the values. */ - for (index = 0; index < representors.nb_representor_ports; index++) - if (data->representor_id == - representors.representor_ports[index]) + for (i = 0; i < nc * np * nf; ++i) { + c = i / (np * nf); + p = (i / nf) % np; + f = i % nf; + if (rte_eth_representor_id_convert(edev, + &id, + eth_da.type, + eth_da.nb_mh_controllers == 0 ? -1 : + eth_da.mh_controllers[c], + eth_da.nb_ports == 0 ? -1 : eth_da.ports[p], + eth_da.nb_representor_ports == 0 ? -1 : + eth_da.representor_ports[f]) < 0) + continue; + if (data->representor_id == id) return 0; + } return -1; /* no match */ } @@ -112,7 +132,7 @@ eth_dev_match(const struct rte_eth_dev *edev, ret = rte_kvargs_process(kvlist, eth_params_keys[RTE_ETH_PARAM_REPRESENTOR], - eth_representor_cmp, edev->data); + eth_representor_cmp, (void *)(uintptr_t)edev); if (ret != 0) return -1; /* search for representor key */ diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c index 07c6debb58..da0cf1a920 100644 --- a/lib/librte_ethdev/rte_ethdev.c +++ b/lib/librte_ethdev/rte_ethdev.c @@ -5617,6 +5617,89 @@ rte_eth_devargs_parse(const char *dargs, struct rte_eth_devargs *eth_da) return result; } +int +rte_eth_representor_id_convert(const struct rte_eth_dev *ethdev, + uint16_t *id, + enum rte_eth_representor_type type, + int controller, int pf, int representor_port) +{ + int ret, n, i, count; + struct rte_eth_representor_info *info = NULL; + size_t size; + + if (type == RTE_ETH_REPRESENTOR_NONE) + return 0; + if (id == NULL) + return -EINVAL; + + /* Get PMD representor range info. */ + ret = rte_eth_representor_info_get(ethdev->data->port_id, NULL); + if (ret < 0) { + /* Fallback to direct mapping for compatibility. */ + *id = representor_port; + } + n = ret; + size = sizeof(*info) + n * sizeof(info->ranges[0]); + info = calloc(1, size); + if (info == NULL) + return -ENOMEM; + ret = rte_eth_representor_info_get(ethdev->data->port_id, info); + if (ret < 0) + goto out; + + /* Default controller and pf to caller. */ + if (controller == -1) + controller = info->controller; + if (pf == -1) + pf = info->pf; + + /* Locate representor ID. */ + for (i = 0; i < n; ++i) { + if (info->ranges[i].type != type) + continue; + /* PMD hit: ignore controller if -1. */ + if (info->ranges[i].controller != -1 && + info->ranges[i].controller != (uint16_t)controller) + continue; + count = info->ranges[i].id_end - info->ranges[i].id_base + 1; + if (info->ranges[i].type == RTE_ETH_REPRESENTOR_PF) { + /* PF. */ + if (pf >= info->ranges[i].pf + count) + continue; + *id = info->ranges[i].id_base + + (pf - info->ranges[i].pf); + goto out; + } + /* VF or SF. */ + /* PMD hit: ignore pf if -1. */ + if (info->ranges[i].pf != -1 && + info->ranges[i].pf != (uint16_t)pf) + continue; + if (info->ranges[i].type == RTE_ETH_REPRESENTOR_VF) { + /* VF. */ + if (representor_port >= info->ranges[i].vf + count) + continue; + *id = info->ranges[i].id_base + + (representor_port - info->ranges[i].vf); + goto out; + } else if (info->ranges[i].type == RTE_ETH_REPRESENTOR_SF) { + /* SF. */ + if (representor_port >= info->ranges[i].sf + count) + continue; + *id = info->ranges[i].id_base + + (representor_port - info->ranges[i].sf); + goto out; + } + } + /* Not matching representor ID range. */ + ret = -ENOENT; + +out: + if (info != NULL) + free(info); + return ret; +} + static int eth_dev_handle_port_list(const char *cmd __rte_unused, const char *params __rte_unused, diff --git a/lib/librte_ethdev/version.map b/lib/librte_ethdev/version.map index bb6f7436c2..2891f5734e 100644 --- a/lib/librte_ethdev/version.map +++ b/lib/librte_ethdev/version.map @@ -268,6 +268,7 @@ INTERNAL { rte_eth_hairpin_queue_peer_bind; rte_eth_hairpin_queue_peer_unbind; rte_eth_hairpin_queue_peer_update; + rte_eth_representor_id_convert; rte_eth_switch_domain_alloc; rte_eth_switch_domain_free; }; From patchwork Sun Feb 14 03:21:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xueming Li X-Patchwork-Id: 87917 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id D82A9A0546; Sun, 14 Feb 2021 04:24:25 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id B258A22A237; Sun, 14 Feb 2021 04:24:04 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id 0DA87406A3 for ; Sun, 14 Feb 2021 04:24:02 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from xuemingl@nvidia.com) with SMTP; 14 Feb 2021 05:24:02 +0200 Received: from nvidia.com (pegasus05.mtr.labs.mlnx [10.210.16.100]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 11E3MYvV008525; Sun, 14 Feb 2021 05:24:02 +0200 From: Xueming Li To: Cc: dev@dpdk.org, Viacheslav Ovsiienko , xuemingl@nvidia.com, Asaf Penso , Olivier Matz Date: Sun, 14 Feb 2021 03:21:39 +0000 Message-Id: <1613272907-22563-10-git-send-email-xuemingl@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1613272907-22563-1-git-send-email-xuemingl@nvidia.com> References: <1613272907-22563-1-git-send-email-xuemingl@nvidia.com> In-Reply-To: <1608303356-13089-2-git-send-email-xuemingl@nvidia.com> References: <1608303356-13089-2-git-send-email-xuemingl@nvidia.com> Subject: [dpdk-dev] [PATCH v6 9/9] kvargs: update parser to support lists X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch updates kvargs parser to support lists on top of range, allow multiple lists or range: k1=a[1,2]b[3-5] Signed-off-by: Xueming Li Acked-by: Viacheslav Ovsiienko Acked-by: Thomas Monjalon --- app/test/test_kvargs.c | 46 +++++++++++++-- lib/librte_kvargs/rte_kvargs.c | 101 +++++++++++++++++++++++---------- 2 files changed, 112 insertions(+), 35 deletions(-) diff --git a/app/test/test_kvargs.c b/app/test/test_kvargs.c index 2a2dae43a0..a91ea8dc47 100644 --- a/app/test/test_kvargs.c +++ b/app/test/test_kvargs.c @@ -35,6 +35,25 @@ static int check_handler(const char *key, const char *value, return 0; } +/* test parsing. */ +static int test_kvargs_parsing(const char *args, unsigned int n) +{ + struct rte_kvargs *kvlist; + + kvlist = rte_kvargs_parse(args, NULL); + if (kvlist == NULL) { + printf("rte_kvargs_parse() error: %s\n", args); + return -1; + } + if (kvlist->count != n) { + printf("invalid count value %d: %s\n", kvlist->count, args); + rte_kvargs_free(kvlist); + return -1; + } + rte_kvargs_free(kvlist); + return 0; +} + /* test a valid case */ static int test_valid_kvargs(void) { @@ -42,6 +61,19 @@ static int test_valid_kvargs(void) const char *args; const char *valid_keys_list[] = { "foo", "check", NULL }; const char **valid_keys; + static const struct { + unsigned int expected; + const char *input; + } valid_inputs[] = { + { 2, "foo=1,foo=" }, + { 2, "foo=1,foo=" }, + { 2, "foo=1,foo" }, + { 2, "foo=1,=2" }, + { 1, "foo=[1,2" }, + { 1, ",=" }, + { 1, "foo=[" }, + }; + unsigned int i; /* empty args is valid */ args = ""; @@ -191,6 +223,14 @@ static int test_valid_kvargs(void) } rte_kvargs_free(kvlist); + valid_keys = NULL; + + for (i = 0; i < RTE_DIM(valid_inputs); ++i) { + args = valid_inputs[i].input; + if (test_kvargs_parsing(args, valid_inputs[i].expected)) + goto fail; + } + return 0; fail: @@ -212,12 +252,6 @@ static int test_invalid_kvargs(void) /* list of argument that should fail */ const char *args_list[] = { "wrong-key=x", /* key not in valid_keys_list */ - "foo=1,foo=", /* empty value */ - "foo=1,foo", /* no value */ - "foo=1,=2", /* no key */ - "foo=[1,2", /* no closing bracket in value */ - ",=", /* also test with a smiley */ - "foo=[", /* no value in list and no closing bracket */ NULL }; const char **args; const char *valid_keys_list[] = { "foo", "check", NULL }; diff --git a/lib/librte_kvargs/rte_kvargs.c b/lib/librte_kvargs/rte_kvargs.c index 285081c86c..ffae8914cf 100644 --- a/lib/librte_kvargs/rte_kvargs.c +++ b/lib/librte_kvargs/rte_kvargs.c @@ -5,6 +5,7 @@ #include #include +#include #include @@ -13,15 +14,19 @@ /* * Receive a string with a list of arguments following the pattern * key=value,key=value,... and insert them into the list. - * strtok() is used so the params string will be copied to be modified. + * Params string will be copied to be modified. + * list "[]" and list element splitter ",", "-" is treated as value. + * Supported examples: + * k1=v1,k2=v2 + * k1 + * k1=x[0-1]y[1,3-5,9]z */ static int rte_kvargs_tokenize(struct rte_kvargs *kvlist, const char *params) { - unsigned i; - char *str; - char *ctx1 = NULL; - char *ctx2 = NULL; + char *str, *start; + bool in_list = false, end_key = false, end_value = false; + bool save = false, end_pair = false; /* Copy the const char *params to a modifiable string * to pass to rte_strsplit @@ -32,36 +37,74 @@ rte_kvargs_tokenize(struct rte_kvargs *kvlist, const char *params) /* browse each key/value pair and add it in kvlist */ str = kvlist->str; - while ((str = strtok_r(str, RTE_KVARGS_PAIRS_DELIM, &ctx1)) != NULL) { + start = str; /* start of current key or value */ + while (1) { + switch (*str) { + case '=': /* End of key. */ + end_key = true; + save = true; + break; + case ',': + /* End of value, skip comma in middle of range */ + if (!in_list) { + if (end_key) + end_value = true; + else + end_key = true; + save = true; + end_pair = true; + } + break; + case '[': /* Start of list. */ + in_list = true; + break; + case ']': /* End of list. */ + if (in_list) + in_list = false; + break; + case '\0': /* End of string */ + if (end_key) + end_value = true; + else + end_key = true; + save = true; + end_pair = true; + break; + default: + break; + } - i = kvlist->count; - if (i >= RTE_KVARGS_MAX) - return -1; + if (!save) { + /* Continue if not end of key or value. */ + str++; + continue; + } - kvlist->pairs[i].key = strtok_r(str, RTE_KVARGS_KV_DELIM, &ctx2); - kvlist->pairs[i].value = strtok_r(NULL, RTE_KVARGS_KV_DELIM, &ctx2); - if (kvlist->pairs[i].key == NULL || - kvlist->pairs[i].value == NULL) + if (kvlist->count >= RTE_KVARGS_MAX) return -1; - /* Detect list [a,b] to skip comma delimiter in list. */ - str = kvlist->pairs[i].value; - if (str[0] == '[') { - /* Find the end of the list. */ - while (str[strlen(str) - 1] != ']') { - /* Restore the comma erased by strtok_r(). */ - if (ctx1 == NULL || ctx1[0] == '\0') - return -1; /* no closing bracket */ - str[strlen(str)] = ','; - /* Parse until next comma. */ - str = strtok_r(NULL, RTE_KVARGS_PAIRS_DELIM, &ctx1); - if (str == NULL) - return -1; /* no closing bracket */ - } + if (end_value) + /* Value parsed */ + kvlist->pairs[kvlist->count].value = start; + else if (end_key) + /* Key parsed. */ + kvlist->pairs[kvlist->count].key = start; + + if (end_pair) { + if (end_value || str != start) + /* Ignore empty pair. */ + kvlist->count++; + end_key = false; + end_value = false; + end_pair = false; } - kvlist->count++; - str = NULL; + if (*str == '\0') /* End of string. */ + break; + *str = '\0'; + str++; + start = str; + save = false; } return 0;