From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Ananyev, Konstantin" Subject: Re: [PATCH v8 6/9] ethdev: add common devargs parser Date: Thu, 26 Apr 2018 12:03:12 +0000 Message-ID: <2601191342CEEE43887BDE71AB977258AEBD049D@IRSMSX102.ger.corp.intel.com> References: <20180416130605.6509-1-declan.doherty@intel.com> <20180426104105.18342-1-declan.doherty@intel.com> <20180426104105.18342-7-declan.doherty@intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Cc: Adrien Mazarguil , "Yigit, Ferruh" , Thomas Monjalon , "Shahaf Shuler" , "Horton, Remy" To: "Doherty, Declan" , "dev@dpdk.org" Return-path: Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by dpdk.org (Postfix) with ESMTP id 4DE835F29 for ; Thu, 26 Apr 2018 14:03:16 +0200 (CEST) In-Reply-To: <20180426104105.18342-7-declan.doherty@intel.com> Content-Language: en-US List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" > -----Original Message----- > From: Doherty, Declan > Sent: Thursday, April 26, 2018 11:41 AM > To: dev@dpdk.org > Cc: Adrien Mazarguil ; Yigit, Ferruh ; Thomas Monjalon ; > Shahaf Shuler ; Ananyev, Konstantin ; Horton, Remy ; > Doherty, Declan > Subject: [dpdk-dev][PATCH v8 6/9] ethdev: add common devargs parser >=20 > From: Remy Horton >=20 > 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. The > patch add support for a representor argument passed with passed with > the EAL -w option. The representor parameter allows the user to specify > which representor ports to initialise on a device. >=20 > The argument supports passing a single representor port, a list of > port values or a range of port values. >=20 > -w BDF,representor=3D1 # create representor port 1 on pci device BDF > -w BDF,representor=3D[1,2,5,6,10] # create representor ports in list > -w BDF,representor=3D[0-31] # create representor ports in range >=20 > Signed-off-by: Remy Horton > Signed-off-by: Declan Doherty > --- > doc/guides/prog_guide/poll_mode_drv.rst | 19 ++++ > lib/Makefile | 1 + > lib/librte_ether/rte_ethdev.c | 182 ++++++++++++++++++++++++++= ++++++ > lib/librte_ether/rte_ethdev_driver.h | 30 ++++++ > lib/librte_ether/rte_ethdev_version.map | 1 + > 5 files changed, 233 insertions(+) >=20 > diff --git a/doc/guides/prog_guide/poll_mode_drv.rst b/doc/guides/prog_gu= ide/poll_mode_drv.rst > index e5d01874e..09a93baec 100644 > --- a/doc/guides/prog_guide/poll_mode_drv.rst > +++ b/doc/guides/prog_guide/poll_mode_drv.rst > @@ -345,6 +345,25 @@ Ethernet Device API >=20 > The Ethernet device API exported by the Ethernet PMDs is described in th= e *DPDK API Reference*. >=20 > +Ethernet Device Standard Device Arguments > +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > + > +Standard Ethernet device arguments allow for a set of commonly used argu= ments/ > +parameters which are applicable to all Ethernet devices to be available = to for > +specification of specific device and for passing common configuration > +parameters to those ports. > + > +* ``representor`` for a device which supports the creation of represento= r ports > + this argument allows user to specify which switch ports to enable port > + representors for.:: > + > + -w BDBF,representor=3D0 > + -w BDBF,representor=3D[0,4,6,9] > + -w BDBF,representor=3D[0-31] > + > +Note: PMDs are not required to support the standard device arguments and= users > +should consult the relevant PMD documentation to see support devargs. > + > Extended Statistics API > ~~~~~~~~~~~~~~~~~~~~~~~ >=20 > diff --git a/lib/Makefile b/lib/Makefile > index 965be6c8d..536775e59 100644 > --- a/lib/Makefile > +++ b/lib/Makefile > @@ -21,6 +21,7 @@ DEPDIRS-librte_cmdline :=3D librte_eal > DIRS-$(CONFIG_RTE_LIBRTE_ETHER) +=3D librte_ether > DEPDIRS-librte_ether :=3D librte_net librte_eal librte_mempool librte_ri= ng > DEPDIRS-librte_ether +=3D librte_mbuf > +DEPDIRS-librte_ether +=3D librte_kvargs > DIRS-$(CONFIG_RTE_LIBRTE_BBDEV) +=3D librte_bbdev > DEPDIRS-librte_bbdev :=3D librte_eal librte_mempool librte_mbuf > DIRS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) +=3D librte_cryptodev > diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.= c > index 621f8af7f..cb85d8bb7 100644 > --- a/lib/librte_ether/rte_ethdev.c > +++ b/lib/librte_ether/rte_ethdev.c > @@ -34,6 +34,7 @@ > #include > #include > #include > ++#include >=20 > #include "rte_ether.h" > #include "rte_ethdev.h" > @@ -4101,6 +4102,187 @@ rte_eth_dev_pool_ops_supported(uint16_t port_id, = const char *pool) > return (*dev->dev_ops->pool_ops_supported)(dev, pool); > } >=20 > +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) > +{ I still think that if you'd like to extend rte_kvarrgs to be able to parse = something like: "key=3D[val1,val2,...,valn]", you have to make it generic kvargs ability and put it into librte_kvargs, n= ot try to introduce your own new parser here. Imagine that in addition to your 'port=3D[val1,val2, ..valn]' devargs strin= g would contain some extra (let say device specific) parameters. What would happen, when PMD will try to use rte_kvargs_parse() on such stri= ng? My understanding - it would fail, correct? As an alternative - as I remember rte_kvargs allows you to have multiple id= entical key, i.e: "key=3Dval1,key=3Dval2,...,key=3Dvaln". Why not to use that way, if you don't want to introduce extra code in rte_k= vargs? > + int state; > + struct rte_kvargs_pair *pair; > + char *letter; > + > + arglist->str =3D strdup(str_in); > + if (arglist->str =3D=3D NULL) > + return -ENOMEM; > + > + letter =3D arglist->str; > + state =3D 0; > + arglist->count =3D 0; > + pair =3D &arglist->pairs[0]; > + while (1) { > + switch (state) { > + case 0: /* Initial */ > + if (*letter =3D=3D '=3D') > + return -EINVAL; > + else if (*letter =3D=3D '\0') > + return 0; > + > + state =3D 1; > + pair->key =3D letter; > + /* fall-thru */ > + > + case 1: /* Parsing key */ > + if (*letter =3D=3D '=3D') { > + *letter =3D '\0'; > + pair->value =3D letter + 1; > + state =3D 2; > + } else if (*letter =3D=3D ',' || *letter =3D=3D '\0') > + return -EINVAL; > + break; > + > + > + case 2: /* Parsing value */ > + if (*letter =3D=3D '[') > + state =3D 3; > + else if (*letter =3D=3D ',') { > + *letter =3D '\0'; > + arglist->count++; > + pair =3D &arglist->pairs[arglist->count]; > + state =3D 0; > + } else if (*letter =3D=3D '\0') { > + letter--; > + arglist->count++; > + pair =3D &arglist->pairs[arglist->count]; > + state =3D 0; > + } > + break; > + > + case 3: /* Parsing list */ > + if (*letter =3D=3D ']') > + state =3D 2; > + else if (*letter =3D=3D '\0') > + return -EINVAL; > + break; > + } > + letter++; > + } > +} > + > +static int > +rte_eth_devargs_parse_list(char *str, rte_eth_devargs_callback_t callbac= k, > + void *data) > +{ > + char *str_start; > + int state; > + int result; > + > + if (*str !=3D '[') > + /* Single element, not a list */ > + return callback(str, data); > + > + /* Sanity check, then strip the brackets */ > + str_start =3D &str[strlen(str) - 1]; > + if (*str_start !=3D ']') { > + RTE_LOG(ERR, EAL, "(%s): List does not end with ']'", str); > + return -EINVAL; > + } > + str++; > + *str_start =3D '\0'; > + > + /* Process list elements */ > + state =3D 0; > + while (1) { > + if (state =3D=3D 0) { > + if (*str =3D=3D '\0') > + break; > + if (*str !=3D ',') { > + str_start =3D str; > + state =3D 1; > + } > + } else if (state =3D=3D 1) { > + if (*str =3D=3D ',' || *str =3D=3D '\0') { > + if (str > str_start) { > + /* Non-empty string fragment */ > + *str =3D '\0'; > + result =3D callback(str_start, data); > + if (result < 0) > + return result; > + } > + state =3D 0; > + } > + } > + str++; > + } > + return 0; > +} > + > +static int > +rte_eth_devargs_process_range(char *str, uint16_t *list, uint16_t *len_l= ist, > + const uint16_t max_list) > +{ > + uint16_t lo, hi, val; > + int result; > + > + result =3D sscanf(str, "%hu-%hu", &lo, &hi); > + if (result =3D=3D 1) { > + if (*len_list >=3D max_list) > + return -ENOMEM; > + list[(*len_list)++] =3D lo; > + } else if (result =3D=3D 2) { > + if (lo >=3D hi || lo > RTE_MAX_ETHPORTS || hi > RTE_MAX_ETHPORTS) lo > RTE_MAX_ETHPORTS is redundant here. > + return -EINVAL; > + for (val =3D lo; val <=3D hi; val++) { > + if (*len_list >=3D max_list) > + return -ENOMEM; > + list[(*len_list)++] =3D val; > + } > + } else > + return -EINVAL; > + return 0; > +} > + > + > +static int > +rte_eth_devargs_parse_representor_ports(char *str, void *data) > +{ > + struct rte_eth_devargs *eth_da =3D 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 =3D 0; > + > + memset(eth_da, 0, sizeof(*eth_da)); > + > + result =3D rte_eth_devargs_tokenise(&args, dargs); > + if (result < 0) > + goto parse_cleanup; > + > + for (i =3D 0; i < args.count; i++) { > + pair =3D &args.pairs[i]; > + if (strcmp("representor", pair->key) =3D=3D 0) { > + result =3D rte_eth_devargs_parse_list(pair->value, > + rte_eth_devargs_parse_representor_ports, > + eth_da); > + if (result < 0) > + goto parse_cleanup; > + } > + } > + > +parse_cleanup: > + if (args.str) > + free(args.str); > + > + return result; > +} > + > 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 8c61ab2f4..492da754a 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= , > } >=20 >=20 > +/** 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_dev= args); > + > + > typedef int (*ethdev_init_t)(struct rte_eth_dev *ethdev, void *init_para= ms); > 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/r= te_ethdev_version.map > index c4380aa31..41c3d2699 100644 > --- a/lib/librte_ether/rte_ethdev_version.map > +++ b/lib/librte_ether/rte_ethdev_version.map > @@ -206,6 +206,7 @@ DPDK_18.02 { > EXPERIMENTAL { > global: >=20 > + rte_eth_devargs_parse; > rte_eth_dev_count_avail; > rte_eth_dev_count_total; > rte_eth_dev_create; > -- > 2.14.3