ethdev: add siblings iterator

Message ID 20181130002716.27325-1-thomas@monjalon.net (mailing list archive)
State Changes Requested, archived
Delegated to: Ferruh Yigit
Headers
Series ethdev: add siblings iterator |

Checks

Context Check Description
ci/Intel-compilation success Compilation OK
ci/mellanox-Performance-Testing success Performance Testing PASS
ci/intel-Performance-Testing success Performance Testing PASS
ci/checkpatch success coding style OK

Commit Message

Thomas Monjalon Nov. 30, 2018, 12:27 a.m. UTC
  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

Ferruh Yigit Dec. 11, 2018, 4:31 p.m. UTC | #1
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;
>
  
Thomas Monjalon Dec. 11, 2018, 6:19 p.m. UTC | #2
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?
  

Patch

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
+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;