ethdev: add siblings iterator
Checks
Commit Message
If multiple ports share the same hardware device (rte_device),
they are siblings and can be found thanks to the new function
and loop macro.
The ownership is not checked because siblings may have
different owners.
Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
lib/librte_ethdev/rte_ethdev.c | 15 +++++++++++++++
lib/librte_ethdev/rte_ethdev.h | 23 +++++++++++++++++++++++
lib/librte_ethdev/rte_ethdev_version.map | 1 +
3 files changed, 39 insertions(+)
Comments
On 11/30/2018 12:27 AM, Thomas Monjalon wrote:
> If multiple ports share the same hardware device (rte_device),
> they are siblings and can be found thanks to the new function
> and loop macro.
>
> The ownership is not checked because siblings may have
> different owners.
Looks good on its own, but I think now we require an implementation of any new
API, so it can be good to have:
- a sample implementation of this new API and the macro
- an unit test for the API and the macro
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> ---
> lib/librte_ethdev/rte_ethdev.c | 15 +++++++++++++++
> lib/librte_ethdev/rte_ethdev.h | 23 +++++++++++++++++++++++
> lib/librte_ethdev/rte_ethdev_version.map | 1 +
> 3 files changed, 39 insertions(+)
>
> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> index 5f858174b..11e0ade6e 100644
> --- a/lib/librte_ethdev/rte_ethdev.c
> +++ b/lib/librte_ethdev/rte_ethdev.c
> @@ -341,6 +341,21 @@ rte_eth_find_next(uint16_t port_id)
> return port_id;
> }
>
> +uint16_t __rte_experimental
I think __rte_experimental tag only in header file is sufficient
> +rte_eth_find_next_sibling(uint16_t port_id, uint16_t ref)
> +{
> + while (port_id < RTE_MAX_ETHPORTS &&
> + rte_eth_devices[port_id].state == RTE_ETH_DEV_UNUSED &&
> + rte_eth_devices[port_id].device !=
> + rte_eth_devices[ref].device)
> + port_id++;
> +
> + if (port_id >= RTE_MAX_ETHPORTS)
> + return RTE_MAX_ETHPORTS;
> +
> + return port_id;
> +}
> +
> static void
> rte_eth_dev_shared_data_prepare(void)
> {
> diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
> index 1960f3a2d..647e6634d 100644
> --- a/lib/librte_ethdev/rte_ethdev.h
> +++ b/lib/librte_ethdev/rte_ethdev.h
> @@ -1383,6 +1383,29 @@ uint16_t rte_eth_find_next(uint16_t port_id);
> #define RTE_ETH_FOREACH_DEV(p) \
> RTE_ETH_FOREACH_DEV_OWNED_BY(p, RTE_ETH_DEV_NO_OWNER)
>
> +/**
> + * Iterates over sibling ethdev ports (i.e. sharing the same rte_device).
> + *
> + * @param port_id_start
> + * The id of the next possible valid sibling port.
> + * @param ref
> + * The id of a reference port to compare rte_device with.
> + * @return
> + * Next sibling port id (or ref itself), RTE_MAX_ETHPORTS if there is none.
> + */
> +__rte_experimental
> +uint16_t rte_eth_find_next_sibling(uint16_t port_id_start, uint16_t ref);
> +
> +/**
> + * Macro to iterate over all ethdev ports sharing the same rte_device
> + * as the specified port.
> + * Note: the specified port is part of the loop iterations.
> + */
> +#define RTE_ETH_FOREACH_DEV_SIBLING(p, ref) \
> + for (p = rte_eth_find_next_sibling(0, ref); \
> + p < RTE_MAX_ETHPORTS; \
> + p = rte_eth_find_next_sibling(p + 1, ref))
> +
>
> /**
> * @warning
> diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
> index 92ac3de25..a0c930d04 100644
> --- a/lib/librte_ethdev/rte_ethdev_version.map
> +++ b/lib/librte_ethdev/rte_ethdev_version.map
> @@ -245,6 +245,7 @@ EXPERIMENTAL {
> rte_eth_dev_owner_set;
> rte_eth_dev_owner_unset;
> rte_eth_dev_rx_intr_ctl_q_get_fd;
> + rte_eth_find_next_sibling;
> rte_eth_switch_domain_alloc;
> rte_eth_switch_domain_free;
> rte_flow_conv;
>
11/12/2018 17:31, Ferruh Yigit:
> On 11/30/2018 12:27 AM, Thomas Monjalon wrote:
> > If multiple ports share the same hardware device (rte_device),
> > they are siblings and can be found thanks to the new function
> > and loop macro.
> >
> > The ownership is not checked because siblings may have
> > different owners.
>
> Looks good on its own, but I think now we require an implementation of any new
> API, so it can be good to have:
> - a sample implementation of this new API and the macro
> - an unit test for the API and the macro
Yes sure.
I should have added "RFC" in the title.
v2 will have some usage of this API.
About the unit test, I'm really not sure whether we should test the ehtdev
API in test/test/ or just inside testpmd. We used to implement ethdev tests
only in testpmd. Opinions?
@@ -341,6 +341,21 @@ rte_eth_find_next(uint16_t port_id)
return port_id;
}
+uint16_t __rte_experimental
+rte_eth_find_next_sibling(uint16_t port_id, uint16_t ref)
+{
+ while (port_id < RTE_MAX_ETHPORTS &&
+ rte_eth_devices[port_id].state == RTE_ETH_DEV_UNUSED &&
+ rte_eth_devices[port_id].device !=
+ rte_eth_devices[ref].device)
+ port_id++;
+
+ if (port_id >= RTE_MAX_ETHPORTS)
+ return RTE_MAX_ETHPORTS;
+
+ return port_id;
+}
+
static void
rte_eth_dev_shared_data_prepare(void)
{
@@ -1383,6 +1383,29 @@ uint16_t rte_eth_find_next(uint16_t port_id);
#define RTE_ETH_FOREACH_DEV(p) \
RTE_ETH_FOREACH_DEV_OWNED_BY(p, RTE_ETH_DEV_NO_OWNER)
+/**
+ * Iterates over sibling ethdev ports (i.e. sharing the same rte_device).
+ *
+ * @param port_id_start
+ * The id of the next possible valid sibling port.
+ * @param ref
+ * The id of a reference port to compare rte_device with.
+ * @return
+ * Next sibling port id (or ref itself), RTE_MAX_ETHPORTS if there is none.
+ */
+__rte_experimental
+uint16_t rte_eth_find_next_sibling(uint16_t port_id_start, uint16_t ref);
+
+/**
+ * Macro to iterate over all ethdev ports sharing the same rte_device
+ * as the specified port.
+ * Note: the specified port is part of the loop iterations.
+ */
+#define RTE_ETH_FOREACH_DEV_SIBLING(p, ref) \
+ for (p = rte_eth_find_next_sibling(0, ref); \
+ p < RTE_MAX_ETHPORTS; \
+ p = rte_eth_find_next_sibling(p + 1, ref))
+
/**
* @warning
@@ -245,6 +245,7 @@ EXPERIMENTAL {
rte_eth_dev_owner_set;
rte_eth_dev_owner_unset;
rte_eth_dev_rx_intr_ctl_q_get_fd;
+ rte_eth_find_next_sibling;
rte_eth_switch_domain_alloc;
rte_eth_switch_domain_free;
rte_flow_conv;