> Introduces a new structure, rte_eth_devargs, to support generic > ethdev arguments common across NET PMDs, with a new API > rte_eth_devargs_parse API to support PMD parsing these arguments. > > Signed-off-by: Remy Horton <remy.hor...@intel.com> > Signed-off-by: Declan Doherty <declan.dohe...@intel.com> > --- > lib/Makefile | 1 + > lib/librte_ether/rte_ethdev.c | 195 > ++++++++++++++++++++++++++++++++ > lib/librte_ether/rte_ethdev_driver.h | 30 +++++ > lib/librte_ether/rte_ethdev_version.map | 1 + > 4 files changed, 227 insertions(+) > > diff --git a/lib/Makefile b/lib/Makefile > index ec965a606..4144d99f9 100644 > --- a/lib/Makefile > +++ b/lib/Makefile > @@ -21,6 +21,7 @@ DEPDIRS-librte_cmdline := librte_eal > DIRS-$(CONFIG_RTE_LIBRTE_ETHER) += librte_ether > DEPDIRS-librte_ether := librte_net librte_eal librte_mempool librte_ring > DEPDIRS-librte_ether += librte_mbuf > +DEPDIRS-librte_ether += librte_kvargs > DIRS-$(CONFIG_RTE_LIBRTE_BBDEV) += librte_bbdev > DEPDIRS-librte_bbdev := librte_eal librte_mempool librte_mbuf > DIRS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += librte_cryptodev > diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c > index 1d38d8e75..a082b211c 100644 > --- a/lib/librte_ether/rte_ethdev.c > +++ b/lib/librte_ether/rte_ethdev.c > @@ -34,6 +34,7 @@ > #include <rte_errno.h> > #include <rte_spinlock.h> > #include <rte_string_fns.h> > ++#include <rte_kvargs.h> > > #include "rte_ether.h" > #include "rte_ethdev.h" > @@ -4149,6 +4150,200 @@ rte_eth_dev_pool_ops_supported(uint16_t port_id, > const char *pool) > return (*dev->dev_ops->pool_ops_supported)(dev, pool); > } > > +typedef int (*rte_eth_devargs_callback_t)(char *str, void *data); > + > +static int > +rte_eth_devargs_tokenise(struct rte_kvargs *arglist, const char *str_in) > +{ > + int state; > + struct rte_kvargs_pair *pair; > + char *letter;
Hmm, so that extends rte_kvarrgs to be able to parse something like: "key=[val1,val2,...,valn]", right? If so shouldn't it be in rte_kvargs then? BTW, as I remember rte_kvargs allows you to have multiple identical key, i.e: "key=val1,key=val2,...,key=valn". I suppose that approach would allow you to avoid rte_kvargs modifications. > + > + arglist->str = strdup(str_in); Who is going to free it? > + if (arglist->str == NULL) > + return -ENOMEM; > + > + letter = arglist->str; > + state = 0; > + arglist->count = 0; > + pair = &arglist->pairs[0]; > + while (1) { > + switch (state) { > + case 0: /* Initial */ > + if (*letter == '=') > + return -EINVAL; > + else if (*letter == '\0') > + return 0; > + > + state = 1; > + pair->key = letter; > + /* fall-thru */ > + > + case 1: /* Parsing key */ > + if (*letter == '=') { > + *letter = '\0'; > + pair->value = letter + 1; > + state = 2; > + } else if (*letter == ',' || *letter == '\0') > + return -EINVAL; > + break; > + > + > + case 2: /* Parsing value */ > + if (*letter == '[') > + state = 3; > + else if (*letter == ',') { > + *letter = '\0'; > + arglist->count++; > + pair = &arglist->pairs[arglist->count]; > + state = 0; > + } else if (*letter == '\0') { > + letter--; > + arglist->count++; > + pair = &arglist->pairs[arglist->count]; > + state = 0; > + } > + break; > + > + case 3: /* Parsing list */ > + if (*letter == ']') > + state = 2; > + else if (*letter == '\0') > + return -EINVAL; > + break; > + } > + letter++; > + } > +} > + > +static int > +rte_eth_devargs_parse_list(char *str, rte_eth_devargs_callback_t callback, > + void *data) > +{ > + 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 ']'", str); > + return -EINVAL; > + } > + str++; > + *str_start = '\0'; > + > + /* 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++; > + } > + return 0; > +} > + > +static int > +rte_eth_devargs_process_range(char *str, uint16_t *list, uint16_t *len_list, > + const uint16_t max_list) > +{ > + unsigned int lo; > + unsigned int hi; > + unsigned int value; > + int result; > + > + result = sscanf(str, "%u-%u", &lo, &hi); Should probably be %hu. And probably check that lo and hi values are less than MAX_PORTS. > + if (result == 1) { > + if (*len_list >= max_list) > + return -ENOMEM; > + list[(*len_list)++] = lo; > + } else if (result == 2) { > + if (lo >= hi) > + return -EINVAL; > + for (value = lo; value <= hi; value++) { > + if (*len_list >= max_list) > + return -ENOMEM; > + list[(*len_list)++] = value; > + } > + } else > + return -EINVAL; > + return 0; > +} > + > +static int > +rte_eth_devargs_parse_ports(char *str, void *data) > +{ > + struct rte_eth_devargs *eth_da = data; > + > + return rte_eth_devargs_process_range(str, eth_da->ports, > + ð_da->nb_ports, RTE_MAX_ETHPORTS); > +} > + > + > +static int > +rte_eth_devargs_parse_representor_ports(char *str, void *data) > +{ > + struct rte_eth_devargs *eth_da = data; > + > + return rte_eth_devargs_process_range(str, eth_da->representor_ports, > + ð_da->nb_representor_ports, RTE_MAX_ETHPORTS); > +} > + > +int __rte_experimental > +rte_eth_devargs_parse(const char *dargs, struct rte_eth_devargs *eth_da) > +{ > + struct rte_kvargs args; > + struct rte_kvargs_pair *pair; > + unsigned int i; > + int result; > + > + memset(eth_da, 0, sizeof(*eth_da)); > + > + result = rte_eth_devargs_tokenise(&args, dargs); > + if (result < 0) > + return result; > + > + for (i = 0; i < args.count; i++) { > + pair = &args.pairs[i]; > + > + if (strcmp("port", pair->key) == 0) { > + result = rte_eth_devargs_parse_list(pair->value, > + rte_eth_devargs_parse_ports, eth_da); > + if (result < 0) > + return result; > + } else if (strcmp("representor", pair->key) == 0) { > + result = rte_eth_devargs_parse_list(pair->value, > + rte_eth_devargs_parse_representor_ports, > + eth_da); > + if (result < 0) > + return result; > + } > + } > + > + return 0; > +} > + > RTE_INIT(ethdev_init_log); > static void > ethdev_init_log(void) > diff --git a/lib/librte_ether/rte_ethdev_driver.h > b/lib/librte_ether/rte_ethdev_driver.h > index e52add0ad..3bce5747d 100644 > --- a/lib/librte_ether/rte_ethdev_driver.h > +++ b/lib/librte_ether/rte_ethdev_driver.h > @@ -189,6 +189,36 @@ rte_eth_linkstatus_get(const struct rte_eth_dev *dev, > } > > > +/** Generic Ethernet device arguments */ > +struct rte_eth_devargs { > + uint16_t ports[RTE_MAX_ETHPORTS]; > + /** port/s number to enable on a multi-port single function */ > + uint16_t nb_ports; > + /** number of ports in ports field */ > + uint16_t representor_ports[RTE_MAX_ETHPORTS]; > + /** representor port/s identifier to enable on device */ > + uint16_t nb_representor_ports; > + /** number of ports in representor port field */ > +}; > + > +/** > + * @warning > + * @b EXPERIMENTAL: this API may change without prior notice. > + * > + * PMD helper function to parse ethdev arguments > + * > + * @param devargs > + * device arguments > + * @param eth_devargs > + * parsed ethdev specific arguments. > + * > + * @return > + * Negative errno value on error, 0 on success. > + */ > +int __rte_experimental > +rte_eth_devargs_parse(const char *dargs, struct rte_eth_devargs > *eth_devargs); > + > + > typedef int (*ethdev_init_t)(struct rte_eth_dev *ethdev, void *init_params); > typedef int (*ethdev_bus_specific_init)(struct rte_eth_dev *ethdev, > void *bus_specific_init_params); > diff --git a/lib/librte_ether/rte_ethdev_version.map > b/lib/librte_ether/rte_ethdev_version.map > index bd7232923..62ecbdb8a 100644 > --- a/lib/librte_ether/rte_ethdev_version.map > +++ b/lib/librte_ether/rte_ethdev_version.map > @@ -233,6 +233,7 @@ EXPERIMENTAL { > EXPERIMENTAL { > global: > > + rt_eth_devargs_parse; > rte_eth_dev_create; > rte_eth_dev_destroy; > > -- > 2.14.3