From patchwork Thu Mar 4 14:30:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xueming Li X-Patchwork-Id: 88470 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 33A65A0561; Thu, 4 Mar 2021 15:31:02 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id EF37F22A2D2; Thu, 4 Mar 2021 15:31:01 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id EA91140FDF for ; Thu, 4 Mar 2021 15:31:00 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from xuemingl@nvidia.com) with SMTP; 4 Mar 2021 16:30:55 +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 124EUkoP027668; Thu, 4 Mar 2021 16:30:54 +0200 From: Xueming Li To: Andrew Rybchenko 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 Date: Thu, 4 Mar 2021 14:30:17 +0000 Message-Id: <1614868228-13685-2-git-send-email-xuemingl@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1614868228-13685-1-git-send-email-xuemingl@nvidia.com> References: <1614868228-13685-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 v8 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 9824cdb6d8..55110ee984 100644 --- a/drivers/net/bnxt/bnxt_ethdev.c +++ b/drivers/net/bnxt/bnxt_ethdev.c @@ -5646,6 +5646,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 81eb2e4b05..92fa178b46 100644 --- a/drivers/net/mlx5/linux/mlx5_os.c +++ b/drivers/net/mlx5/linux/mlx5_os.c @@ -751,6 +751,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 Thu Mar 4 14:30:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xueming Li X-Patchwork-Id: 88471 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 21A6EA0561; Thu, 4 Mar 2021 15:31:10 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 2AFE922A2DE; Thu, 4 Mar 2021 15:31:07 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id EDCDA22A2DC for ; Thu, 4 Mar 2021 15:31:05 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from xuemingl@nvidia.com) with SMTP; 4 Mar 2021 16:31:04 +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 124EUkoQ027668; Thu, 4 Mar 2021 16:31:03 +0200 From: Xueming Li To: Andrew Rybchenko Cc: dev@dpdk.org, Viacheslav Ovsiienko , xuemingl@nvidia.com, Asaf Penso , Thomas Monjalon , Ferruh Yigit Date: Thu, 4 Mar 2021 14:30:18 +0000 Message-Id: <1614868228-13685-3-git-send-email-xuemingl@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1614868228-13685-1-git-send-email-xuemingl@nvidia.com> References: <1614868228-13685-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 v8 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 Thu Mar 4 14:30:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xueming Li X-Patchwork-Id: 88472 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 5A406A0561; Thu, 4 Mar 2021 15:31:18 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 736A322A2E6; Thu, 4 Mar 2021 15:31:12 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id 0697422A2E2 for ; Thu, 4 Mar 2021 15:31:10 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from xuemingl@nvidia.com) with SMTP; 4 Mar 2021 16:31:05 +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 124EUkoR027668; Thu, 4 Mar 2021 16:31:05 +0200 From: Xueming Li To: Andrew Rybchenko Cc: dev@dpdk.org, Viacheslav Ovsiienko , xuemingl@nvidia.com, Asaf Penso , Thomas Monjalon , Ferruh Yigit Date: Thu, 4 Mar 2021 14:30:19 +0000 Message-Id: <1614868228-13685-4-git-send-email-xuemingl@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1614868228-13685-1-git-send-email-xuemingl@nvidia.com> References: <1614868228-13685-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 v8 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 Thu Mar 4 14:30:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xueming Li X-Patchwork-Id: 88473 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 C38B9A0561; Thu, 4 Mar 2021 15:31:26 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id AC0DC22A2E8; Thu, 4 Mar 2021 15:31:13 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id 276C222A2E3 for ; Thu, 4 Mar 2021 15:31:11 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from xuemingl@nvidia.com) with SMTP; 4 Mar 2021 16:31:07 +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 124EUkoS027668; Thu, 4 Mar 2021 16:31:07 +0200 From: Xueming Li To: Andrew Rybchenko Cc: dev@dpdk.org, Viacheslav Ovsiienko , xuemingl@nvidia.com, Asaf Penso , Thomas Monjalon , Ferruh Yigit Date: Thu, 4 Mar 2021 14:30:20 +0000 Message-Id: <1614868228-13685-5-git-send-email-xuemingl@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1614868228-13685-1-git-send-email-xuemingl@nvidia.com> References: <1614868228-13685-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 v8 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 | 6 +++- .../prog_guide/switch_representation.rst | 35 +++++++++++++------ lib/librte_ethdev/ethdev_private.c | 11 ++++-- lib/librte_ethdev/rte_ethdev.c | 6 ++++ lib/librte_ethdev/rte_ethdev.h | 1 + 5 files changed, 46 insertions(+), 13 deletions(-) diff --git a/doc/guides/prog_guide/poll_mode_drv.rst b/doc/guides/prog_guide/poll_mode_drv.rst index 0117c2af07..063a4680df 100644 --- a/doc/guides/prog_guide/poll_mode_drv.rst +++ b/doc/guides/prog_guide/poll_mode_drv.rst @@ -372,12 +372,16 @@ parameters to those ports. * ``representor`` for a device which supports the creation of representor ports this argument allows user to specify which switch ports to enable port - representors for.:: + representors for. Multiple representors in one device argument is invalid:: -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] + -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.c b/lib/librte_ethdev/rte_ethdev.c index fe9466a03e..60889a8663 100644 --- a/lib/librte_ethdev/rte_ethdev.c +++ b/lib/librte_ethdev/rte_ethdev.c @@ -5589,6 +5589,12 @@ 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) { + if (eth_da->type != RTE_ETH_REPRESENTOR_NONE) { + RTE_LOG(ERR, EAL, "duplicated representor key: %s\n", + dargs); + result = -1; + goto parse_cleanup; + } result = rte_eth_devargs_parse_representor_ports( pair->value, eth_da); if (result < 0) 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 Thu Mar 4 14:30:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xueming Li X-Patchwork-Id: 88474 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 DF6B9A0561; Thu, 4 Mar 2021 15:31:35 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id E4ACA22A2F0; Thu, 4 Mar 2021 15:31:14 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id 4271A22A2E4 for ; Thu, 4 Mar 2021 15:31:11 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from xuemingl@nvidia.com) with SMTP; 4 Mar 2021 16:31:09 +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 124EUkoT027668; Thu, 4 Mar 2021 16:31:08 +0200 From: Xueming Li To: Andrew Rybchenko Cc: dev@dpdk.org, Viacheslav Ovsiienko , xuemingl@nvidia.com, Asaf Penso , Thomas Monjalon , Ferruh Yigit Date: Thu, 4 Mar 2021 14:30:21 +0000 Message-Id: <1614868228-13685-6-git-send-email-xuemingl@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1614868228-13685-1-git-send-email-xuemingl@nvidia.com> References: <1614868228-13685-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 v8 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 | 3 +++ lib/librte_ethdev/ethdev_private.c | 19 +++++++++++++++++-- lib/librte_ethdev/rte_ethdev.h | 1 + 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/doc/guides/prog_guide/poll_mode_drv.rst b/doc/guides/prog_guide/poll_mode_drv.rst index 063a4680df..0d4ac77a7c 100644 --- a/doc/guides/prog_guide/poll_mode_drv.rst +++ b/doc/guides/prog_guide/poll_mode_drv.rst @@ -382,6 +382,9 @@ 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] + -a DBDF,representor=pf1 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..35a57c56ec 100644 --- a/lib/librte_ethdev/ethdev_private.c +++ b/lib/librte_ethdev/ethdev_private.c @@ -118,8 +118,9 @@ 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 + * pf#: PF port representor/s * * Examples of #: * 2 - single @@ -131,6 +132,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 || str[0] == '\0') + goto done; + } if (str[0] == 'v' && str[1] == 'f') { eth_da->type = RTE_ETH_REPRESENTOR_VF; str += 2; @@ -138,11 +147,17 @@ rte_eth_devargs_parse_representor_ports(char *str, void *data) eth_da->type = RTE_ETH_REPRESENTOR_SF; str += 2; } else { + /* 'pf' must followed by 'vf' or 'sf'. */ + if (eth_da->type == RTE_ETH_REPRESENTOR_PF) { + str = NULL; + goto done; + } 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)); +done: 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 Thu Mar 4 14:30:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xueming Li X-Patchwork-Id: 88476 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 40636A0561; Thu, 4 Mar 2021 15:31:54 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id ADF2322A300; Thu, 4 Mar 2021 15:31:18 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id 3B94C22A2FB for ; Thu, 4 Mar 2021 15:31:16 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from xuemingl@nvidia.com) with SMTP; 4 Mar 2021 16:31:11 +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 124EUkoU027668; Thu, 4 Mar 2021 16:31:10 +0200 From: Xueming Li To: Andrew Rybchenko Cc: dev@dpdk.org, Viacheslav Ovsiienko , xuemingl@nvidia.com, Asaf Penso , Bruce Richardson , Thomas Monjalon , Ferruh Yigit Date: Thu, 4 Mar 2021 14:30:22 +0000 Message-Id: <1614868228-13685-7-git-send-email-xuemingl@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1614868228-13685-1-git-send-email-xuemingl@nvidia.com> References: <1614868228-13685-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 v8 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 | 18 +++++++++++++++--- 3 files changed, 20 insertions(+), 3 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 35a57c56ec..012cf73ca2 100644 --- a/lib/librte_ethdev/ethdev_private.c +++ b/lib/librte_ethdev/ethdev_private.c @@ -118,9 +118,9 @@ 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 - * pf#: PF port representor/s + * [[c#]pf#]vf#: VF port representor/s + * [[c#]pf#]sf#: SF port representor/s + * [c#]pf#: PF port representor/s * * Examples of #: * 2 - single @@ -132,6 +132,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 done; + } if (str[0] == 'p' && str[1] == 'f') { eth_da->type = RTE_ETH_REPRESENTOR_PF; str += 2; @@ -139,6 +147,10 @@ rte_eth_devargs_parse_representor_ports(char *str, void *data) ð_da->nb_ports, RTE_DIM(eth_da->ports)); if (str == NULL || str[0] == '\0') goto done; + } else if (eth_da->nb_mh_controllers > 0) { + /* 'c' must followed by 'pf'. */ + str = NULL; + goto done; } if (str[0] == 'v' && str[1] == 'f') { eth_da->type = RTE_ETH_REPRESENTOR_VF; From patchwork Thu Mar 4 14:30:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xueming Li X-Patchwork-Id: 88475 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 B49EAA0561; Thu, 4 Mar 2021 15:31:46 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 7BCCB22A2FB; Thu, 4 Mar 2021 15:31:17 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id 3F03122A2FC for ; Thu, 4 Mar 2021 15:31:16 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from xuemingl@nvidia.com) with SMTP; 4 Mar 2021 16:31:14 +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 124EUkoV027668; Thu, 4 Mar 2021 16:31:14 +0200 From: Xueming Li To: Andrew Rybchenko Cc: dev@dpdk.org, Viacheslav Ovsiienko , xuemingl@nvidia.com, Asaf Penso , Thomas Monjalon , Ferruh Yigit , Ray Kinsella , Neil Horman Date: Thu, 4 Mar 2021 14:30:23 +0000 Message-Id: <1614868228-13685-8-git-send-email-xuemingl@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1614868228-13685-1-git-send-email-xuemingl@nvidia.com> References: <1614868228-13685-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 v8 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 Acked-by: Andrew Rybchenko --- lib/librte_ethdev/ethdev_driver.h | 7 +++++ lib/librte_ethdev/rte_ethdev.c | 14 +++++++++ lib/librte_ethdev/rte_ethdev.h | 51 +++++++++++++++++++++++++++++++ lib/librte_ethdev/version.map | 3 ++ 4 files changed, 75 insertions(+) diff --git a/lib/librte_ethdev/ethdev_driver.h b/lib/librte_ethdev/ethdev_driver.h index 06ff35266f..36e866aa03 100644 --- a/lib/librte_ethdev/ethdev_driver.h +++ b/lib/librte_ethdev/ethdev_driver.h @@ -783,6 +783,10 @@ typedef int (*eth_hairpin_queue_peer_unbind_t) typedef int (*eth_get_monitor_addr_t)(void *rxq, struct rte_power_monitor_cond *pmc); +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. */ + /** * @internal A structure containing the functions exported by an Ethernet driver. */ @@ -940,6 +944,9 @@ struct eth_dev_ops { eth_get_monitor_addr_t get_monitor_addr; /**< Get power monitoring condition for Rx queue. */ + + eth_representor_info_get_t representor_info_get; + /**< Get representor info. */ }; /** diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c index 60889a8663..3d4ec8ad5c 100644 --- a/lib/librte_ethdev/rte_ethdev.c +++ b/lib/librte_ethdev/rte_ethdev.c @@ -5816,6 +5816,20 @@ rte_eth_hairpin_queue_peer_unbind(uint16_t cur_port, uint16_t cur_queue, direction); } +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->representor_info_get, -ENOTSUP); + return eth_err(port_id, (*dev->dev_ops->representor_info_get)(dev, + info)); +} + RTE_LOG_REGISTER(rte_eth_dev_logtype, lib.ethdev, INFO); RTE_INIT(ethdev_init_telemetry) diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h index 9cd519bf59..9c7a80c9b5 100644 --- a/lib/librte_ethdev/rte_ethdev.h +++ b/lib/librte_ethdev/rte_ethdev.h @@ -4791,6 +4791,57 @@ __rte_experimental int rte_eth_dev_hairpin_capability_get(uint16_t port_id, struct rte_eth_hairpin_cap *cap); +/** + * @warning + * @b EXPERIMENTAL: this structure may change without prior notice. + * + * ethernet device representor ID range entry + */ +struct rte_eth_representor_range { + enum rte_eth_representor_type type; /**< Representor type */ + int controller; /**< Controller index */ + int pf; /**< Physical function index */ + __extension__ + union { + int vf; /**< VF start index */ + int sf; /**< SF start index */ + }; + uint32_t id_base; /**< Representor ID start index */ + uint32_t id_end; /**< Representor ID end index */ + char name[RTE_DEV_NAME_MAX_LEN]; /**< Representor name */ +}; + +/** + * @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 rte_eth_representor_range ranges[];/**< Representor ID range. */ +}; + +/** + * 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); + #include /** 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 Thu Mar 4 14:30:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xueming Li X-Patchwork-Id: 88477 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 26DF9A0561; Thu, 4 Mar 2021 15:32:02 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id E06B422A2E7; Thu, 4 Mar 2021 15:31:22 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id 3B44822A2E7 for ; Thu, 4 Mar 2021 15:31:21 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from xuemingl@nvidia.com) with SMTP; 4 Mar 2021 16:31:16 +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 124EUkoW027668; Thu, 4 Mar 2021 16:31:15 +0200 From: Xueming Li To: Andrew Rybchenko Cc: dev@dpdk.org, Viacheslav Ovsiienko , xuemingl@nvidia.com, Asaf Penso , Thomas Monjalon , Ferruh Yigit , Ray Kinsella , Neil Horman Date: Thu, 4 Mar 2021 14:30:24 +0000 Message-Id: <1614868228-13685-9-git-send-email-xuemingl@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1614868228-13685-1-git-send-email-xuemingl@nvidia.com> References: <1614868228-13685-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 v8 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 get representor ID from controller, pf and vf/sf index. Representor comparer callback get representor ID then compare with device representor ID. Signed-off-by: Xueming Li Reviewed-by: Andrew Rybchenko --- lib/librte_ethdev/ethdev_driver.h | 32 +++++++++++ lib/librte_ethdev/rte_class_eth.c | 38 +++++++++---- lib/librte_ethdev/rte_ethdev.c | 88 +++++++++++++++++++++++++++++++ lib/librte_ethdev/version.map | 1 + 4 files changed, 150 insertions(+), 9 deletions(-) diff --git a/lib/librte_ethdev/ethdev_driver.h b/lib/librte_ethdev/ethdev_driver.h index 36e866aa03..abe2738348 100644 --- a/lib/librte_ethdev/ethdev_driver.h +++ b/lib/librte_ethdev/ethdev_driver.h @@ -1244,6 +1244,38 @@ struct rte_eth_devargs { enum rte_eth_representor_type type; /* type of representor */ }; +/** + * PMD helper function to get representor ID from location detail. + * + * Get representor ID from controller, pf and (sf or vf). + * The mapping is retrieved from rte_eth_representor_info_get(). + * + * For backward compatibility, if no representor info, direct + * map legacy VF (no controller and pf). + * + * @param ethdev + * Handle of ethdev port. + * @param type + * Representor type. + * @param controller + * Controller ID, -1 if unspecified. + * @param pf + * PF port ID, -1 if unspecified. + * @param representor_port + * VF or SF representor port number, -1 if unspecified. + * @param repr_id + * Pointer to output representor ID. + * + * @return + * Negative errno value on error, 0 on success. + */ +__rte_internal +int +rte_eth_representor_id_get(const struct rte_eth_dev *ethdev, + enum rte_eth_representor_type type, + int controller, int pf, int representor_port, + uint16_t *repr_id); + /** * 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..1fe5fa1f36 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_get(edev, + 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], + &id) < 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 3d4ec8ad5c..2dc464a7ad 100644 --- a/lib/librte_ethdev/rte_ethdev.c +++ b/lib/librte_ethdev/rte_ethdev.c @@ -5609,6 +5609,94 @@ rte_eth_devargs_parse(const char *dargs, struct rte_eth_devargs *eth_da) return result; } +int +rte_eth_representor_id_get(const struct rte_eth_dev *ethdev, + enum rte_eth_representor_type type, + int controller, int pf, int representor_port, + uint16_t *repr_id) +{ + int ret, n, i, count; + struct rte_eth_representor_info *info = NULL; + size_t size; + + if (type == RTE_ETH_REPRESENTOR_NONE) + return 0; + if (repr_id == NULL) + return -EINVAL; + + /* Get PMD representor range info. */ + ret = rte_eth_representor_info_get(ethdev->data->port_id, NULL); + if (ret < 0) { + if (type == RTE_ETH_REPRESENTOR_VF && controller == -1 && + pf == -1) { + /* Direct mapping for legacy VF representor. */ + *repr_id = representor_port; + return 0; + } else { + return ret; + } + } + 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. */ + ret = -ENOENT; + for (i = 0; i < n; ++i) { + if (info->ranges[i].type != type) + continue; + if (info->ranges[i].controller != controller) + continue; + count = info->ranges[i].id_end - info->ranges[i].id_base + 1; + switch (info->ranges[i].type) { + case RTE_ETH_REPRESENTOR_PF: + if (pf < info->ranges[i].pf || + pf >= info->ranges[i].pf + count) + continue; + *repr_id = info->ranges[i].id_base + + (pf - info->ranges[i].pf); + ret = 0; + goto out; + case RTE_ETH_REPRESENTOR_VF: + if (info->ranges[i].pf != pf) + continue; + if (representor_port < info->ranges[i].vf || + representor_port >= info->ranges[i].vf + count) + continue; + *repr_id = info->ranges[i].id_base + + (representor_port - info->ranges[i].vf); + ret = 0; + goto out; + case RTE_ETH_REPRESENTOR_SF: + if (info->ranges[i].pf != pf) + continue; + if (representor_port < info->ranges[i].sf || + representor_port >= info->ranges[i].sf + count) + continue; + *repr_id = info->ranges[i].id_base + + (representor_port - info->ranges[i].sf); + ret = 0; + goto out; + default: + break; + } + } +out: + 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..93ad388e96 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_get; rte_eth_switch_domain_alloc; rte_eth_switch_domain_free; }; From patchwork Thu Mar 4 14:30:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xueming Li X-Patchwork-Id: 88478 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 B505FA0561; Thu, 4 Mar 2021 15:32:09 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 2147822A318; Thu, 4 Mar 2021 15:31:24 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id 4416D22A2F7 for ; Thu, 4 Mar 2021 15:31:21 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from xuemingl@nvidia.com) with SMTP; 4 Mar 2021 16:31:18 +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 124EUkoX027668; Thu, 4 Mar 2021 16:31:18 +0200 From: Xueming Li To: Andrew Rybchenko Cc: dev@dpdk.org, Viacheslav Ovsiienko , xuemingl@nvidia.com, Asaf Penso , Olivier Matz Date: Thu, 4 Mar 2021 14:30:25 +0000 Message-Id: <1614868228-13685-10-git-send-email-xuemingl@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1614868228-13685-1-git-send-email-xuemingl@nvidia.com> References: <1614868228-13685-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 v8 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;