@@ -376,7 +376,7 @@ 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. Multiple representors in one device argument is invalid::
+ representors for::
-a DBDF,representor=vf0
-a DBDF,representor=vf[0,4,6,9]
@@ -389,6 +389,8 @@ parameters to those ports.
-a DBDF,representor=pf1vf0
-a DBDF,representor=pf[0-1]sf[0-127]
-a DBDF,representor=pf1
+ -a DBDF,representor=[pf[0-1],pf2vf[0-2],pf3[3,5-8]]
+ (Multiple representors in one device argument can be represented as a list)
Note: PMDs are not required to support the standard device arguments and users
should consult the relevant PMD documentation to see support devargs.
@@ -77,6 +77,7 @@ thought as a software "patch panel" front-end for applications.
-a pci:dbdf,representor=sf1
-a pci:dbdf,representor=sf[0-1023]
-a pci:dbdf,representor=sf[0,2-1023]
+ -a pci:dbdf,representor=[pf[0-1],pf2vf[0-2],pf3[3,5]]
- As virtual devices, they may be more limited than their physical
counterparts, for instance by exposing only a subset of device
@@ -6383,8 +6383,8 @@ static int bnxt_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
if (pci_dev->device.devargs) {
ret = rte_eth_devargs_parse(pci_dev->device.devargs->args,
- ð_da);
- if (ret)
+ ð_da, 1);
+ if (ret < 0)
return ret;
}
@@ -1317,8 +1317,8 @@ static int eth_enic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
ENICPMD_FUNC_TRACE();
if (pci_dev->device.devargs) {
retval = rte_eth_devargs_parse(pci_dev->device.devargs->args,
- ð_da);
- if (retval)
+ ð_da, 1);
+ if (retval < 0)
return retval;
}
if (eth_da.nb_representor_ports > 0 &&
@@ -646,8 +646,8 @@ eth_i40e_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
if (pci_dev->device.devargs) {
retval = rte_eth_devargs_parse(pci_dev->device.devargs->args,
- ð_da);
- if (retval)
+ ð_da, 1);
+ if (retval < 0)
return retval;
}
@@ -2041,8 +2041,8 @@ eth_ice_dcf_pci_probe(__rte_unused struct rte_pci_driver *pci_drv,
if (!ice_devargs_check(pci_dev->device.devargs, ICE_DCF_DEVARG_CAP))
return 1;
- ret = rte_eth_devargs_parse(pci_dev->device.devargs->args, ð_da);
- if (ret)
+ ret = rte_eth_devargs_parse(pci_dev->device.devargs->args, ð_da, 1);
+ if (ret < 0)
return ret;
ret = rte_eth_dev_pci_generic_probe(pci_dev,
@@ -1765,8 +1765,8 @@ eth_ixgbe_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
if (pci_dev->device.devargs) {
retval = rte_eth_devargs_parse(pci_dev->device.devargs->args,
- ð_da);
- if (retval)
+ ð_da, 1);
+ if (retval < 0)
return retval;
} else
memset(ð_da, 0, sizeof(eth_da));
@@ -2733,16 +2733,16 @@ mlx5_os_parse_eth_devargs(struct rte_device *dev,
memset(eth_da, 0, sizeof(*eth_da));
/* Parse representor information first from class argument. */
if (dev->devargs->cls_str)
- ret = rte_eth_devargs_parse(dev->devargs->cls_str, eth_da);
- if (ret != 0) {
+ ret = rte_eth_devargs_parse(dev->devargs->cls_str, eth_da, 1);
+ if (ret < 0) {
DRV_LOG(ERR, "failed to parse device arguments: %s",
dev->devargs->cls_str);
return -rte_errno;
}
if (eth_da->type == RTE_ETH_REPRESENTOR_NONE && dev->devargs->args) {
/* Parse legacy device argument */
- ret = rte_eth_devargs_parse(dev->devargs->args, eth_da);
- if (ret) {
+ ret = rte_eth_devargs_parse(dev->devargs->args, eth_da, 1);
+ if (ret < 0) {
DRV_LOG(ERR, "failed to parse device arguments: %s",
dev->devargs->args);
return -rte_errno;
@@ -792,8 +792,8 @@ nfp_flower_repr_create(struct nfp_app_fw_flower *app_fw_flower)
/* Now parse PCI device args passed for representor info */
if (pci_dev->device.devargs != NULL) {
- ret = rte_eth_devargs_parse(pci_dev->device.devargs->args, ð_da);
- if (ret != 0) {
+ ret = rte_eth_devargs_parse(pci_dev->device.devargs->args, ð_da, 1);
+ if (ret < 0) {
PMD_INIT_LOG(ERR, "devarg parse failed");
return -EINVAL;
}
@@ -3305,8 +3305,8 @@ sfc_parse_rte_devargs(const char *args, struct rte_eth_devargs *devargs)
int rc;
if (args != NULL) {
- rc = rte_eth_devargs_parse(args, ð_da);
- if (rc != 0) {
+ rc = rte_eth_devargs_parse(args, ð_da, 1);
+ if (rc < 0) {
SFC_GENERIC_LOG(ERR,
"Failed to parse generic devargs '%s'",
args);
@@ -2,6 +2,7 @@
* Copyright(c) 2022 Intel Corporation
*/
+#include <ctype.h>
#include <stdlib.h>
#include <pthread.h>
@@ -459,26 +460,157 @@ eth_dev_devargs_tokenise(struct rte_kvargs *arglist, const char *str_in)
break;
case 3: /* Parsing list */
- if (*letter == ']')
- state = 2;
- else if (*letter == '\0')
+ if (*letter == ']') {
+ /* For devargs having singles lists move to state 2 once letter
+ * becomes ']' so each can be considered as different pair key
+ * value. But in nested lists case e.g. multiple representors
+ * case i.e. [pf[0-3],pfvf[3,4-6]], complete nested list should
+ * be considered as one pair value, hence checking if end of outer
+ * list ']' is reached else stay on state 3.
+ */
+ if ((strcmp("representor", pair->key) == 0) &&
+ (*(letter + 1) != '\0' && *(letter + 2) != '\0' &&
+ *(letter + 3) != '\0') &&
+ ((*(letter + 2) == 'p' && *(letter + 3) == 'f') ||
+ (*(letter + 2) == 'v' && *(letter + 3) == 'f') ||
+ (*(letter + 2) == 's' && *(letter + 3) == 'f') ||
+ (*(letter + 2) == 'c' && isdigit(*(letter + 3))) ||
+ (*(letter + 2) == '[' && isdigit(*(letter + 3))) ||
+ (isdigit(*(letter + 2)))))
+ state = 3;
+ else
+ state = 2;
+ } else if (*letter == '\0') {
return -EINVAL;
+ }
break;
}
letter++;
}
}
+static int
+devargs_parse_representor_ports(struct rte_eth_devargs *eth_devargs, char
+ *da_val, unsigned int da_idx, unsigned int nb_da)
+{
+ struct rte_eth_devargs *eth_da;
+ int result = 0;
+
+ if (da_idx + 1 > nb_da) {
+ RTE_ETHDEV_LOG_LINE(ERR, "Devargs parsed %d > max array size %d",
+ da_idx + 1, nb_da);
+ result = -1;
+ goto parse_cleanup;
+ }
+ eth_da = ð_devargs[da_idx];
+ memset(eth_da, 0, sizeof(*eth_da));
+ RTE_ETHDEV_LOG_LINE(DEBUG, " Devargs idx %d value %s", da_idx, da_val);
+ result = rte_eth_devargs_parse_representor_ports(da_val, eth_da);
+
+parse_cleanup:
+ return result;
+}
+
+static int
+eth_dev_tokenise_representor_list(char *p_val, struct rte_eth_devargs *eth_devargs,
+ unsigned int nb_da)
+{
+ char da_val[BUFSIZ], str[BUFSIZ];
+ bool is_rep_portid_list = true;
+ unsigned int devargs = 0;
+ int result = 0, len = 0;
+ int i = 0, j = 0;
+ char *pos;
+
+ pos = p_val;
+ /* Length of consolidated list */
+ while (*pos++ != '\0') {
+ len++;
+ if (isalpha(*pos))
+ is_rep_portid_list = false;
+ }
+
+ /* List of representor portIDs i.e.[1,2,3] should be considered as single representor case*/
+ if (is_rep_portid_list) {
+ result = devargs_parse_representor_ports(eth_devargs, p_val, 0, 1);
+ if (result < 0)
+ return result;
+
+ devargs++;
+ return devargs;
+ }
+
+ memset(str, 0, BUFSIZ);
+ /* Remove the exterior [] of the consolidated list */
+ strncpy(str, &p_val[1], len - 2);
+ while (1) {
+ if (str[i] == '\0') {
+ if (da_val[0] != '\0') {
+ result = devargs_parse_representor_ports(eth_devargs, da_val,
+ devargs, nb_da);
+ if (result < 0)
+ goto parse_cleanup;
+
+ devargs++;
+ }
+ break;
+ }
+ if (str[i] == ',' || str[i] == '[') {
+ if (str[i] == ',') {
+ if (da_val[0] != '\0') {
+ da_val[j + 1] = '\0';
+ result = devargs_parse_representor_ports(eth_devargs,
+ da_val, devargs,
+ nb_da);
+ if (result < 0)
+ goto parse_cleanup;
+
+ devargs++;
+ j = 0;
+ memset(da_val, 0, BUFSIZ);
+ }
+ }
+
+ if (str[i] == '[') {
+ while (str[i] != ']' || isalpha(str[i + 1])) {
+ da_val[j] = str[i];
+ j++;
+ i++;
+ }
+ da_val[j] = ']';
+ da_val[j + 1] = '\0';
+ result = devargs_parse_representor_ports(eth_devargs, da_val,
+ devargs, nb_da);
+ if (result < 0)
+ goto parse_cleanup;
+
+ devargs++;
+ j = 0;
+ memset(da_val, 0, BUFSIZ);
+ }
+ } else {
+ da_val[j] = str[i];
+ j++;
+ }
+ i++;
+ }
+ result = devargs;
+
+parse_cleanup:
+ return result;
+}
+
int
-rte_eth_devargs_parse(const char *dargs, struct rte_eth_devargs *eth_da)
+rte_eth_devargs_parse(const char *dargs, struct rte_eth_devargs *eth_devargs,
+ unsigned int nb_da)
{
- struct rte_kvargs args;
struct rte_kvargs_pair *pair;
+ struct rte_kvargs args;
+ bool dup_rep = false;
+ int devargs = 0;
unsigned int i;
int result = 0;
- memset(eth_da, 0, sizeof(*eth_da));
-
result = eth_dev_devargs_tokenise(&args, dargs);
if (result < 0)
goto parse_cleanup;
@@ -486,18 +618,33 @@ 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_ETHDEV_LOG_LINE(ERR, "duplicated representor key: %s",
- dargs);
+ if (dup_rep) {
+ RTE_ETHDEV_LOG_LINE(ERR, "Duplicated representor key: %s",
+ pair->value);
result = -1;
goto parse_cleanup;
}
- result = rte_eth_devargs_parse_representor_ports(
- pair->value, eth_da);
- if (result < 0)
- goto parse_cleanup;
+
+ RTE_ETHDEV_LOG_LINE(DEBUG, "Devarg pattern: %s", pair->value);
+ if (pair->value[0] == '[') {
+ /* Multiple representor list case */
+ devargs = eth_dev_tokenise_representor_list(pair->value,
+ eth_devargs, nb_da);
+ if (devargs < 0)
+ goto parse_cleanup;
+ } else {
+ /* Single representor case */
+ devargs = devargs_parse_representor_ports(eth_devargs, pair->value,
+ 0, 1);
+ if (devargs < 0)
+ goto parse_cleanup;
+ devargs++;
+ }
+ dup_rep = true;
}
}
+ RTE_ETHDEV_LOG_LINE(DEBUG, "Total devargs parsed %d", devargs);
+ result = devargs;
parse_cleanup:
free(args.str);
@@ -1802,14 +1802,17 @@ rte_eth_representor_id_get(uint16_t port_id,
* @param devargs
* device arguments
* @param eth_devargs
- * parsed ethdev specific arguments.
+ * contiguous memory populated with parsed ethdev specific arguments.
+ * @param nb_da
+ * size of eth_devargs array passed
*
* @return
- * Negative errno value on error, 0 on success.
+ * Negative errno value on error, no of devargs parsed on success.
*/
__rte_internal
int
-rte_eth_devargs_parse(const char *devargs, struct rte_eth_devargs *eth_devargs);
+rte_eth_devargs_parse(const char *devargs, struct rte_eth_devargs *eth_devargs,
+ unsigned int nb_da);
typedef int (*ethdev_init_t)(struct rte_eth_dev *ethdev, void *init_params);