DPDK patches and discussions
 help / color / mirror / Atom feed
From: Andrew Rybchenko <arybchenko@solarflare.com>
To: Thomas Monjalon <thomas@monjalon.net>, <dev@dpdk.org>
Cc: <gaetan.rivet@6wind.com>, <ophirmu@mellanox.com>,
	<ferruh.yigit@intel.com>
Subject: Re: [dpdk-dev] [PATCH 2/5] ethdev: add an iterator to match some devargs input
Date: Mon, 8 Oct 2018 10:06:30 +0300	[thread overview]
Message-ID: <8689ac9f-c5dd-aa29-8f8b-e32674338160@solarflare.com> (raw)
In-Reply-To: <20181007222554.4886-3-thomas@monjalon.net>

On 10/8/18 1:25 AM, Thomas Monjalon wrote:
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> ---
>   lib/librte_eal/common/include/rte_common.h |  6 ++
>   lib/librte_ethdev/ethdev_private.c         | 10 ++-
>   lib/librte_ethdev/ethdev_private.h         |  6 ++
>   lib/librte_ethdev/rte_ethdev.c             | 87 ++++++++++++++++++++++
>   lib/librte_ethdev/rte_ethdev.h             | 56 ++++++++++++++
>   lib/librte_ethdev/rte_ethdev_version.map   |  2 +
>   6 files changed, 166 insertions(+), 1 deletion(-)
>
> diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
> index 069c13ec7..2269e5456 100644
> --- a/lib/librte_eal/common/include/rte_common.h
> +++ b/lib/librte_eal/common/include/rte_common.h
> @@ -164,6 +164,12 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
>    */
>   #define RTE_PTR_DIFF(ptr1, ptr2) ((uintptr_t)(ptr1) - (uintptr_t)(ptr2))
>   
> +/**
> + * Workaround to cast a const field of a structure to non-const type.
> + */
> +#define RTE_CAST_FIELD(var,field,type) \

Missing space after each comma.

> +	(*(type*)((uintptr_t)(var) + offsetof(typeof(*(var)), field)))
> +

In general it is bad symptom that we need it. I'd think more that twice
before adding it :)

>   /*********** Macros/static functions for doing alignment ********/
>   
>   
> diff --git a/lib/librte_ethdev/ethdev_private.c b/lib/librte_ethdev/ethdev_private.c
> index 768c8b2ed..acc787dba 100644
> --- a/lib/librte_ethdev/ethdev_private.c
> +++ b/lib/librte_ethdev/ethdev_private.c
> @@ -5,6 +5,14 @@
>   #include "rte_ethdev.h"
>   #include "ethdev_private.h"
>   
> +uint16_t
> +eth_dev_to_id(const struct rte_eth_dev *dev)
> +{
> +	if (dev == NULL)
> +		return RTE_MAX_ETHPORTS;
> +	return dev - rte_eth_devices;
> +}
> +
>   struct rte_eth_dev *
>   eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
>   		const void *data)
> @@ -18,7 +26,7 @@ eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
>   	     start > &rte_eth_devices[RTE_MAX_ETHPORTS]))
>   		return NULL;
>   	if (start != NULL)
> -		idx = start - &rte_eth_devices[0] + 1;
> +		idx = eth_dev_to_id(start) + 1;
>   	else
>   		idx = 0;
>   	for (; idx < RTE_MAX_ETHPORTS; idx++) {
> diff --git a/lib/librte_ethdev/ethdev_private.h b/lib/librte_ethdev/ethdev_private.h
> index 0f5c6d5c4..e67cf6831 100644
> --- a/lib/librte_ethdev/ethdev_private.h
> +++ b/lib/librte_ethdev/ethdev_private.h
> @@ -11,6 +11,12 @@
>   extern "C" {
>   #endif
>   
> +/*
> + * Convert rte_eth_dev pointer to port id.
> + * NULL will be translated to RTE_MAX_ETHPORTS.
> + */
> +uint16_t eth_dev_to_id(const struct rte_eth_dev *dev);
> +
>   /* Generic rte_eth_dev comparison function. */
>   typedef int (*rte_eth_cmp_t)(const struct rte_eth_dev *, const void *);
>   
> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> index ef99f7068..83ab28c23 100644
> --- a/lib/librte_ethdev/rte_ethdev.c
> +++ b/lib/librte_ethdev/rte_ethdev.c
> @@ -36,11 +36,13 @@
>   #include <rte_spinlock.h>
>   #include <rte_string_fns.h>
>   #include <rte_kvargs.h>
> +#include <rte_class.h>
>   
>   #include "rte_ether.h"
>   #include "rte_ethdev.h"
>   #include "rte_ethdev_driver.h"
>   #include "ethdev_profile.h"
> +#include "ethdev_private.h"
>   
>   int rte_eth_dev_logtype;
>   
> @@ -181,6 +183,91 @@ enum {
>   	STAT_QMAP_RX
>   };
>   
> +int __rte_experimental
> +rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
> +{
> +#define iter_anybus_str "class=eth,"
> +	int ret;
> +	struct rte_devargs devargs;
> +	const char *bus_param_key;
> +	char *bus_str;
> +	size_t bus_str_size;
> +
> +	memset(iter, 0, sizeof(*iter));
> +
> +	/*
> +	 * The devargs string may use various syntaxes:
> +	 *   - 0000:08:00.0,representor=[1-3]
> +	 *   - pci:0000:06:00.0,representor=[0,5]
> +	 * A new syntax is in development (not yet supported):
> +	 *   - bus=X,paramX=x/class=Y,paramY=y/driver=Z,paramZ=z
> +	 */
> +
> +	/* Split bus, device and parameters. */
> +	ret = rte_devargs_parse(&devargs, devargs_str);

rte_devargs_parse() does strdup() for args. It requires free() in the 
function
if devargs parsed successfully, but init fails.
In the case of success it is moved to cls_str which is 'const' and I see
not code which frees it as well.

> +	if (ret != 0)
> +		return ret;
> +
> +	/* Assume parameters of old syntax can match only at ethdev level. */
> +	iter->cls_str = devargs.args;
> +
> +	iter->bus = devargs.bus;
> +	if (iter->bus->dev_iterate == NULL)
> +		ret = -ENOTSUP; /* share error log with below */
> +
> +	/* Convert bus args to new syntax for use with new API dev_iterate. */
> +	if (strcmp(iter->bus->name, "vdev") == 0)
> +		bus_param_key = "name";
> +	else if (strcmp(iter->bus->name, "pci") == 0)
> +		bus_param_key = "addr";
> +	else
> +		ret = -ENOTSUP;
> +	if (ret < 0) {
> +		RTE_LOG(ERR, EAL, "Bus %s does not support iterating.\n",
> +				iter->bus->name);
> +		return -ENOTSUP;
> +	}
> +	bus_str_size = strlen(bus_param_key) + strlen(devargs.name) + 2;
> +	bus_str = malloc(bus_str_size);
> +	if (bus_str == NULL)
> +		return -ENOMEM;
> +	ret = snprintf(bus_str, bus_str_size, "%s=%s",
> +			bus_param_key, devargs.name);
> +	if (ret < 0) {
> +		free(bus_str);
> +		return -EINVAL;
> +	}
> +	iter->bus_str = bus_str;
> +
> +	iter->cls = rte_class_find_by_name("eth");
> +	return 0;
> +}
> +
> +uint16_t __rte_experimental
> +rte_eth_iterator_next(struct rte_dev_iterator *iter)
> +{
> +	if (iter->cls == NULL) /* invalid ethdev iterator */
> +		return RTE_MAX_ETHPORTS;
> +
> +	do { /* loop for matching rte_device */
> +		if (iter->class_device == NULL) {
> +			iter->device = iter->bus->dev_iterate(
> +					iter->device, iter->bus_str, iter);
> +			if (iter->device == NULL)
> +				break;
> +		}
> +		iter->class_device = iter->cls->dev_iterate(
> +				iter->class_device, iter->cls_str, iter);
> +		if (iter->class_device != NULL)
> +			return eth_dev_to_id(iter->class_device);
> +	} while (iter->class_device == NULL);

It is non-obvious what is happening above. It would be very useful to
add comments which explains it. May be just hints.

> +
> +	/* No more ethdev port to iterate. */
> +	free(RTE_CAST_FIELD(iter, bus_str, char *)); /* workaround const */
> +	iter->bus_str = NULL;

Who does it if RTE_ETH_FOREACH_MATCHING_DEV caller breaks
the loop before reaching maximum?

> +	return RTE_MAX_ETHPORTS;
> +}
> +
>   uint16_t
>   rte_eth_find_next(uint16_t port_id)
>   {
> diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
> index 012577b0a..d5a457216 100644
> --- a/lib/librte_ethdev/rte_ethdev.h
> +++ b/lib/librte_ethdev/rte_ethdev.h
> @@ -166,6 +166,62 @@ extern int rte_eth_dev_logtype;
>   
>   struct rte_mbuf;
>   
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice.
> + *
> + * Initializes a device iterator.
> + *
> + * This iterator allows accessing a list of devices matching some devargs.
> + *
> + * @param iter
> + *   Device iterator handle initialized by the function.
> + *   The field bus_str is dynamically allocated and must be freed.
> + *
> + * @param devargs
> + *   Device description string.
> + *
> + * @return
> + *   0 on successful initialization, negative otherwise.
> + */
> +__rte_experimental
> +int rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs);
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice.
> + *
> + * Iterates on devices with devargs filter.
> + * The ownership is not checked.
> + *
> + * The next port id is returned, and the iterator is updated.
> + *
> + * @param iter
> + *   Device iterator handle initialized by rte_eth_iterator_init().
> + *   The field bus_str is freed when no more port is found.
> + *
> + * @return
> + *   A port id if found, RTE_MAX_ETHPORTS otherwise.
> + */
> +__rte_experimental
> +uint16_t rte_eth_iterator_next(struct rte_dev_iterator *iter);
> +
> +/**
> + * Macro to iterate over all ethdev ports matching some devargs.
> + *
> + * @param id
> + *   Iterated port id of type uint16_t.
> + * @param devargs
> + *   Device parameters input as string of type char*.
> + * @param iter
> + *   Iterator handle of type struct rte_dev_iterator, used internally.
> + */
> +#define RTE_ETH_FOREACH_MATCHING_DEV(id, devargs, iter) \
> +	for (rte_eth_iterator_init(iter, devargs), \
> +	     id = rte_eth_iterator_next(iter); \
> +	     id != RTE_MAX_ETHPORTS; \
> +	     id = rte_eth_iterator_next(iter))
> +

Such iterators are very convenient, but in this particular case
it is a source of non-obvious memory leaks and necessity
of the hack to discard 'const'.

May be iterator free callback with its own opaque data
can help to avoid these hacks with const discard?
I.e. rte_eth_iterator_free() which does the job and mentioned
in the rte_eth_iterator_init() and the macro description.

>   /**
>    * A structure used to retrieve statistics for an Ethernet port.
>    * Not all statistics fields in struct rte_eth_stats are supported
> diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
> index 38f117f01..e009988fd 100644
> --- a/lib/librte_ethdev/rte_ethdev_version.map
> +++ b/lib/librte_ethdev/rte_ethdev_version.map
> @@ -237,6 +237,8 @@ EXPERIMENTAL {
>   	rte_eth_dev_owner_unset;
>   	rte_eth_dev_rx_offload_name;
>   	rte_eth_dev_tx_offload_name;
> +	rte_eth_iterator_init;
> +	rte_eth_iterator_next;
>   	rte_eth_switch_domain_alloc;
>   	rte_eth_switch_domain_free;
>   	rte_flow_expand_rss;

  reply	other threads:[~2018-10-08  7:07 UTC|newest]

Thread overview: 82+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-10-07 22:25 [dpdk-dev] [PATCH 0/5] replace attach/detach functions Thomas Monjalon
2018-10-07 22:25 ` [dpdk-dev] [PATCH 1/5] bus/vdev: add iteration filter on name Thomas Monjalon
2018-10-08  6:46   ` Andrew Rybchenko
2018-10-08  7:47     ` Thomas Monjalon
2018-10-07 22:25 ` [dpdk-dev] [PATCH 2/5] ethdev: add an iterator to match some devargs input Thomas Monjalon
2018-10-08  7:06   ` Andrew Rybchenko [this message]
2018-10-08  7:58     ` Thomas Monjalon
2018-10-07 22:25 ` [dpdk-dev] [PATCH 3/5] ethdev: allow iterating with only class filter Thomas Monjalon
2018-10-08  7:20   ` Andrew Rybchenko
2018-10-08  8:07     ` Thomas Monjalon
2018-10-08  9:13       ` Andrew Rybchenko
2018-10-07 22:25 ` [dpdk-dev] [PATCH 4/5] ethdev: remove deprecated attach/detach functions Thomas Monjalon
2018-10-08  7:28   ` Andrew Rybchenko
2018-10-08  8:09     ` Thomas Monjalon
2018-10-07 22:25 ` [dpdk-dev] [PATCH 5/5] eal: " Thomas Monjalon
2018-10-09  0:16 ` [dpdk-dev] [PATCH v2 0/6] replace " Thomas Monjalon
2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 1/6] bus/vdev: add iteration filter on name Thomas Monjalon
2018-10-09  9:17     ` Andrew Rybchenko
2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 2/6] ethdev: add iterator to match devargs input Thomas Monjalon
2018-10-09  9:31     ` Andrew Rybchenko
2018-10-09  9:49       ` Thomas Monjalon
2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 3/6] ethdev: allow iterating with pure class filter Thomas Monjalon
2018-10-09  9:40     ` Andrew Rybchenko
2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 4/6] doc: replace doxygen example in contribution guide Thomas Monjalon
2018-10-09  9:41     ` Andrew Rybchenko
2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 5/6] ethdev: remove deprecated attach/detach functions Thomas Monjalon
2018-10-09  9:43     ` Andrew Rybchenko
2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 6/6] eal: " Thomas Monjalon
2018-10-09  9:44     ` Andrew Rybchenko
2018-10-09 13:34 ` [dpdk-dev] [PATCH v3 0/6] replace " Thomas Monjalon
2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 1/6] bus/vdev: add iteration filter on name Thomas Monjalon
2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 2/6] ethdev: add iterator to match devargs input Thomas Monjalon
2018-10-09 14:17     ` Thomas Monjalon
2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 3/6] ethdev: allow iterating with pure class filter Thomas Monjalon
2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 4/6] doc: replace doxygen example in contribution guide Thomas Monjalon
2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 5/6] ethdev: remove deprecated attach/detach functions Thomas Monjalon
2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 6/6] eal: " Thomas Monjalon
2018-10-09 22:33 ` [dpdk-dev] [PATCH v4 0/6] replace " Thomas Monjalon
2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 1/6] bus/vdev: add iteration filter on name Thomas Monjalon
2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 2/6] ethdev: add iterator to match devargs input Thomas Monjalon
2018-10-16 10:58     ` Ferruh Yigit
2018-10-16 12:06       ` Thomas Monjalon
2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 3/6] ethdev: allow iterating with pure class filter Thomas Monjalon
2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 4/6] doc: replace doxygen example in contribution guide Thomas Monjalon
2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 5/6] ethdev: remove deprecated attach/detach functions Thomas Monjalon
2018-10-16 11:03     ` Ferruh Yigit
2018-10-16 12:12       ` Thomas Monjalon
2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 6/6] eal: " Thomas Monjalon
2018-10-18  1:35 ` [dpdk-dev] [PATCH v5 0/7] replace " Thomas Monjalon
2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 1/7] bus/vdev: add iteration filter on name Thomas Monjalon
2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 2/7] ethdev: add iterator to match devargs input Thomas Monjalon
2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 3/7] ethdev: allow iterating with pure class filter Thomas Monjalon
2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 4/7] doc: replace doxygen example in contribution guide Thomas Monjalon
2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 5/7] ethdev: remove deprecated attach/detach functions Thomas Monjalon
2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 6/7] eal: " Thomas Monjalon
2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 7/7] app/testpmd: check not detaching device twice Thomas Monjalon
2018-10-18  1:45     ` Thomas Monjalon
2018-10-22 12:31 ` [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions Thomas Monjalon
2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 1/7] bus/vdev: add iteration filter on name Thomas Monjalon
2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 2/7] ethdev: add iterator to match devargs input Thomas Monjalon
2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 3/7] ethdev: allow iterating with pure class filter Thomas Monjalon
2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 4/7] doc: replace doxygen example in contribution guide Thomas Monjalon
2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 5/7] ethdev: remove deprecated attach/detach functions Thomas Monjalon
2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 6/7] eal: " Thomas Monjalon
2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 7/7] app/testpmd: check not detaching device twice Thomas Monjalon
2018-10-22 15:11   ` [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions Iremonger, Bernard
2018-10-22 15:38     ` Thomas Monjalon
2018-10-23  8:28 ` [dpdk-dev] [PATCH v7 " Thomas Monjalon
2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 1/7] bus/vdev: add iteration filter on name Thomas Monjalon
2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 2/7] ethdev: add iterator to match devargs input Thomas Monjalon
2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 3/7] ethdev: allow iterating with pure class filter Thomas Monjalon
2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 4/7] doc: replace doxygen example in contribution guide Thomas Monjalon
2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 5/7] ethdev: remove deprecated attach/detach functions Thomas Monjalon
2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 6/7] eal: " Thomas Monjalon
2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 7/7] app/testpmd: check not detaching device twice Thomas Monjalon
2018-10-23 10:01     ` Iremonger, Bernard
2018-10-23 12:03       ` Thomas Monjalon
2018-10-23 12:13         ` Thomas Monjalon
2018-10-23 12:37           ` Thomas Monjalon
2018-10-23 14:06             ` Ferruh Yigit
2018-10-23 12:39           ` Iremonger, Bernard
2018-10-23 14:06   ` [dpdk-dev] [PATCH v7 0/7] replace attach/detach functions Ferruh Yigit

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8689ac9f-c5dd-aa29-8f8b-e32674338160@solarflare.com \
    --to=arybchenko@solarflare.com \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@intel.com \
    --cc=gaetan.rivet@6wind.com \
    --cc=ophirmu@mellanox.com \
    --cc=thomas@monjalon.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).