[4/5] net/ena: add support for ena-express metrics

Message ID 20231024102128.16832-5-shaibran@amazon.com (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series net/ena: v2.8.0 driver release |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Brandes, Shai Oct. 24, 2023, 10:21 a.m. UTC
  From: Shai Brandes <shaibran@amazon.com>

ENA-express is powered by AWS scalable reliable datagram (SRD)
technology. SRD is a high performance network transport protocol
that uses dynamic routing to increase throughput and minimize
tail latency.

The driver expose the following ENA-express metrics via xstats:
* ena_srd_mode – Describes which ENA-express features are enabled
* ena_srd_eligible_tx_pkts – The number of network packets sent
  within a given time period that meet SRD requirements for
  eligibility
* ena_srd_tx_pkts – The number of SRD packets transmitted within
  a given time period.
* ena_srd_rx_pkts – The number of SRD packets received within
  a given time period.
* ena_srd_resource_utilization – The percentage of the maximum
  allowed memory utilization for concurrent SRD connections
  that the instance has consumed.

Probing the ENA Express metrics is performed via an admin command.
Thus, a multi-process proxy handler was added.

Signed-off-by: Shai Brandes <shaibran@amazon.com>
Reviewed-by: Amit Bernstein <amitbern@amazon.com>
---
 doc/guides/rel_notes/release_23_11.rst |   1 +
 drivers/net/ena/ena_ethdev.c           | 105 ++++++++++++++++++++++++-
 drivers/net/ena/ena_ethdev.h           |  18 +++++
 3 files changed, 123 insertions(+), 1 deletion(-)
  

Comments

Stephen Hemminger Oct. 24, 2023, 3:26 p.m. UTC | #1
On Tue, 24 Oct 2023 13:21:27 +0300
<shaibran@amazon.com> wrote:

>  struct ena_offloads {
>  	uint32_t tx_offloads;
>  	uint32_t rx_offloads;
> @@ -329,6 +346,7 @@ struct ena_adapter {
>  	 */
>  	uint64_t metrics_stats[ENA_MAX_CUSTOMER_METRICS] __rte_cache_aligned;
>  	uint16_t metrics_num;
> +	struct ena_stats_srd srd_stats __rte_cache_aligned;
>  };
 
If metrics_num was before the metrics_stats[] you would save some space.
  
Brandes, Shai Oct. 24, 2023, 3:55 p.m. UTC | #2
On Tue, 24 Oct 2023 13:21:27 +0300
<shaibran@amazon.com> wrote:

>>  struct ena_offloads {
>>       uint32_t tx_offloads;
>>       uint32_t rx_offloads;
>> @@ -329,6 +346,7 @@ struct ena_adapter {
>>        */
>>       uint64_t metrics_stats[ENA_MAX_CUSTOMER_METRICS] __rte_cache_aligned;
>>       uint16_t metrics_num;
>> +     struct ena_stats_srd srd_stats __rte_cache_aligned;
>>  };

> If metrics_num was before the metrics_stats[] you would save some space.
Thank you for the review! My reasoning was that the metrics_num should reside in the same cache line as the metrics_stats (metrics_stats can contain up to 6 metrics so its max length is 48B).
In addition, the  struct ena_stats_srd was added in a later patch, so I will run pahole and verify which order of these three fields gives the best results.
BTW, we are starting a cache optimization task now that should address all these issues, this is indeed one of our main structures, so it will definitely get modified later.
  
Brandes, Shai Oct. 25, 2023, 12:34 p.m. UTC | #3
On Tue, 24 Oct 2023 13:21:27 +0300
<shaibran@amazon.com> wrote:

>>  struct ena_offloads {
>>       uint32_t tx_offloads;
>>       uint32_t rx_offloads;
>> @@ -329,6 +346,7 @@ struct ena_adapter {
>>        */
>>       uint64_t metrics_stats[ENA_MAX_CUSTOMER_METRICS] __rte_cache_aligned;
>>       uint16_t metrics_num;
>> +     struct ena_stats_srd srd_stats __rte_cache_aligned;
>>  };

> If metrics_num was before the metrics_stats[] you would save some space.
Hi, I checked it with pahole and both ways provide same structure size and overall same padding size (14B):

        uint64_t                   metrics_stats[6] __attribute__((__aligned__(64))); /* 181952    48 */
        uint16_t                   metrics_num;          /* 182000     2 */

        /* XXX 14 bytes hole, try to pack */

        /* --- cacheline 2844 boundary (182016 bytes) --- */
        struct ena_stats_srd       srd_stats __attribute__((__aligned__(64))); /* 182016    40 */

        /* size: 182080, cachelines: 2845, members: 40 */
        /* sum members: 181910, holes: 9, sum holes: 146 */

Vs:

        uint16_t                   metrics_num __attribute__((__aligned__(64))); /* 181952     2 */

        /* XXX 6 bytes hole, try to pack */

        uint64_t                   metrics_stats[6];     /* 181960    48 */

        /* XXX 8 bytes hole, try to pack */

        /* --- cacheline 2844 boundary (182016 bytes) --- */
        struct ena_stats_srd       srd_stats __attribute__((__aligned__(64))); /* 182016    40 */

        /* size: 182080, cachelines: 2845, members: 40 */
        /* sum members: 181910, holes: 10, sum holes: 146 */
  

Patch

diff --git a/doc/guides/rel_notes/release_23_11.rst b/doc/guides/rel_notes/release_23_11.rst
index f622d93384..7aaa78e6c9 100644
--- a/doc/guides/rel_notes/release_23_11.rst
+++ b/doc/guides/rel_notes/release_23_11.rst
@@ -149,6 +149,7 @@  New Features
   * Upgraded ENA HAL to latest version.
   * Added support for connection tracking allowance utilization metric.
   * Added support for reporting rx overrun errors in xstats.
+  * Added support for ENA-express metrics.
 
 * **Updated Solarflare net driver.**
 
diff --git a/drivers/net/ena/ena_ethdev.c b/drivers/net/ena/ena_ethdev.c
index b3ebda6049..59cb2792d4 100644
--- a/drivers/net/ena/ena_ethdev.c
+++ b/drivers/net/ena/ena_ethdev.c
@@ -66,6 +66,9 @@  struct ena_stats {
 #define ENA_STAT_GLOBAL_ENTRY(stat) \
 	ENA_STAT_ENTRY(stat, dev)
 
+#define ENA_STAT_ENA_SRD_ENTRY(stat) \
+	ENA_STAT_ENTRY(stat, srd)
+
 /* Device arguments */
 #define ENA_DEVARG_LARGE_LLQ_HDR "large_llq_hdr"
 /* Timeout in seconds after which a single uncompleted Tx packet should be
@@ -106,6 +109,14 @@  static struct ena_stats ena_stats_metrics_strings[] = {
 	ENA_STAT_METRICS_ENTRY(conntrack_allowance_available),
 };
 
+static const struct ena_stats ena_stats_srd_strings[] = {
+	ENA_STAT_ENA_SRD_ENTRY(ena_srd_mode),
+	ENA_STAT_ENA_SRD_ENTRY(ena_srd_tx_pkts),
+	ENA_STAT_ENA_SRD_ENTRY(ena_srd_eligible_tx_pkts),
+	ENA_STAT_ENA_SRD_ENTRY(ena_srd_rx_pkts),
+	ENA_STAT_ENA_SRD_ENTRY(ena_srd_resource_utilization),
+};
+
 static const struct ena_stats ena_stats_tx_strings[] = {
 	ENA_STAT_TX_ENTRY(cnt),
 	ENA_STAT_TX_ENTRY(bytes),
@@ -132,9 +143,11 @@  static const struct ena_stats ena_stats_rx_strings[] = {
 #define ENA_STATS_ARRAY_GLOBAL	ARRAY_SIZE(ena_stats_global_strings)
 #define ENA_STATS_ARRAY_METRICS	ARRAY_SIZE(ena_stats_metrics_strings)
 #define ENA_STATS_ARRAY_METRICS_LEGACY	(ENA_STATS_ARRAY_METRICS - 1)
+#define ENA_STATS_ARRAY_ENA_SRD	ARRAY_SIZE(ena_stats_srd_strings)
 #define ENA_STATS_ARRAY_TX	ARRAY_SIZE(ena_stats_tx_strings)
 #define ENA_STATS_ARRAY_RX	ARRAY_SIZE(ena_stats_rx_strings)
 
+
 #define QUEUE_OFFLOADS (RTE_ETH_TX_OFFLOAD_TCP_CKSUM |\
 			RTE_ETH_TX_OFFLOAD_UDP_CKSUM |\
 			RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |\
@@ -272,6 +285,8 @@  static int ena_parse_devargs(struct ena_adapter *adapter,
 static void ena_copy_customer_metrics(struct ena_adapter *adapter,
 					uint64_t *buf,
 					size_t buf_size);
+static void ena_copy_ena_srd_info(struct ena_adapter *adapter,
+				  struct ena_stats_srd *srd_info);
 static int ena_setup_rx_intr(struct rte_eth_dev *dev);
 static int ena_rx_queue_intr_enable(struct rte_eth_dev *dev,
 				    uint16_t queue_id);
@@ -324,6 +339,7 @@  enum ena_mp_req {
 	ENA_MP_IND_TBL_GET,
 	ENA_MP_IND_TBL_SET,
 	ENA_MP_CUSTOMER_METRICS_GET,
+	ENA_MP_SRD_STATS_GET,
 };
 
 /** Proxy message body. Shared between requests and responses. */
@@ -581,6 +597,22 @@  ENA_PROXY_DESC(ena_com_get_customer_metrics, ENA_MP_CUSTOMER_METRICS_GET,
 }),
 	struct ena_com_dev *ena_dev, char *buf, size_t buf_size);
 
+ENA_PROXY_DESC(ena_com_get_ena_srd_info, ENA_MP_SRD_STATS_GET,
+({
+	ENA_TOUCH(adapter);
+	ENA_TOUCH(req);
+	ENA_TOUCH(ena_dev);
+	ENA_TOUCH(info);
+}),
+({
+	ENA_TOUCH(rsp);
+	ENA_TOUCH(ena_dev);
+	if ((struct ena_stats_srd *)info != &adapter->srd_stats)
+		rte_memcpy((struct ena_stats_srd *)info,
+				&adapter->srd_stats,
+				sizeof(struct ena_stats_srd));
+}),
+	struct ena_com_dev *ena_dev, struct ena_admin_ena_srd_info *info);
 
 static inline void ena_trigger_reset(struct ena_adapter *adapter,
 				     enum ena_regs_reset_reason_types reason)
@@ -787,6 +819,7 @@  static unsigned int ena_xstats_calc_num(struct rte_eth_dev_data *data)
 
 	return ENA_STATS_ARRAY_GLOBAL +
 		adapter->metrics_num +
+		ENA_STATS_ARRAY_ENA_SRD +
 		(data->nb_tx_queues * ENA_STATS_ARRAY_TX) +
 		(data->nb_rx_queues * ENA_STATS_ARRAY_RX);
 }
@@ -3238,6 +3271,27 @@  static void ena_copy_customer_metrics(struct ena_adapter *adapter, uint64_t *buf
 	}
 }
 
+static void ena_copy_ena_srd_info(struct ena_adapter *adapter,
+		struct ena_stats_srd *srd_info)
+{
+	int rc;
+
+	if (!ena_com_get_cap(&adapter->ena_dev, ENA_ADMIN_ENA_SRD_INFO))
+		return;
+
+	rte_spinlock_lock(&adapter->admin_lock);
+	rc = ENA_PROXY(adapter,
+		       ena_com_get_ena_srd_info,
+		       &adapter->ena_dev,
+		       (struct ena_admin_ena_srd_info *)srd_info);
+	rte_spinlock_unlock(&adapter->admin_lock);
+	if (rc != ENA_COM_OK && rc != ENA_COM_UNSUPPORTED) {
+		PMD_DRV_LOG(WARNING,
+				"Failed to get ENA express srd info, rc: %d\n", rc);
+		return;
+	}
+}
+
 /**
  * DPDK callback to retrieve names of extended device statistics
  *
@@ -3271,6 +3325,11 @@  static int ena_xstats_get_names(struct rte_eth_dev *dev,
 			    ena_stats_metrics_strings[stat].name,
 			    RTE_ETH_XSTATS_NAME_SIZE);
 
+	for (stat = 0; stat < ENA_STATS_ARRAY_ENA_SRD; stat++, count++)
+		rte_strscpy(xstats_names[count].name,
+			    ena_stats_srd_strings[stat].name,
+			    RTE_ETH_XSTATS_NAME_SIZE);
+
 	for (stat = 0; stat < ENA_STATS_ARRAY_RX; stat++)
 		for (i = 0; i < dev->data->nb_rx_queues; i++, count++)
 			snprintf(xstats_names[count].name,
@@ -3341,6 +3400,15 @@  static int ena_xstats_get_names_by_id(struct rte_eth_dev *dev,
 		}
 
 		id -= adapter->metrics_num;
+
+		if (id < ENA_STATS_ARRAY_ENA_SRD) {
+			rte_strscpy(xstats_names[i].name,
+				    ena_stats_srd_strings[id].name,
+				    RTE_ETH_XSTATS_NAME_SIZE);
+			continue;
+		}
+		id -= ENA_STATS_ARRAY_ENA_SRD;
+
 		if (id < ENA_STATS_ARRAY_RX) {
 			qid = id / dev->data->nb_rx_queues;
 			id %= dev->data->nb_rx_queues;
@@ -3392,6 +3460,7 @@  static int ena_xstats_get(struct rte_eth_dev *dev,
 	int stat_offset;
 	void *stats_begin;
 	uint64_t metrics_stats[ENA_MAX_CUSTOMER_METRICS];
+	struct ena_stats_srd srd_info = {0};
 
 	if (n < xstats_count)
 		return xstats_count;
@@ -3418,6 +3487,15 @@  static int ena_xstats_get(struct rte_eth_dev *dev,
 		    ((char *)stats_begin + stat_offset));
 	}
 
+	ena_copy_ena_srd_info(adapter, &srd_info);
+	stats_begin = &srd_info;
+	for (stat = 0; stat < ENA_STATS_ARRAY_ENA_SRD; stat++, count++) {
+		stat_offset = ena_stats_srd_strings[stat].stat_offset;
+		xstats[count].id = count;
+		xstats[count].value = *((uint64_t *)
+		    ((char *)stats_begin + stat_offset));
+	}
+
 	for (stat = 0; stat < ENA_STATS_ARRAY_RX; stat++) {
 		for (i = 0; i < dev->data->nb_rx_queues; i++, count++) {
 			stat_offset = ena_stats_rx_strings[stat].stat_offset;
@@ -3455,7 +3533,9 @@  static int ena_xstats_get_by_id(struct rte_eth_dev *dev,
 	int qid;
 	int valid = 0;
 	bool were_metrics_copied = false;
+	bool was_srd_info_copied = false;
 	uint64_t metrics_stats[ENA_MAX_CUSTOMER_METRICS];
+	struct ena_stats_srd srd_info = {0};
 
 	for (i = 0; i < n; ++i) {
 		id = ids[i];
@@ -3485,8 +3565,27 @@  static int ena_xstats_get_by_id(struct rte_eth_dev *dev,
 			continue;
 		}
 
-		/* Check if id belongs to rx queue statistics */
+		/* Check if id belongs to SRD info statistics */
 		id -= adapter->metrics_num;
+
+		if (id < ENA_STATS_ARRAY_ENA_SRD) {
+			/*
+			 * Avoid reading srd info multiple times in a single
+			 * function call, as it requires communication with the
+			 * admin queue.
+			 */
+			if (!was_srd_info_copied) {
+				was_srd_info_copied = true;
+				ena_copy_ena_srd_info(adapter, &srd_info);
+			}
+			values[i] = *((uint64_t *)&adapter->srd_stats + id);
+			++valid;
+			continue;
+		}
+
+		/* Check if id belongs to rx queue statistics */
+		id -= ENA_STATS_ARRAY_ENA_SRD;
+
 		rx_entries = ENA_STATS_ARRAY_RX * dev->data->nb_rx_queues;
 		if (id < rx_entries) {
 			qid = id % dev->data->nb_rx_queues;
@@ -3981,6 +4080,10 @@  ena_mp_primary_handle(const struct rte_mp_msg *mp_msg, const void *peer)
 				(char *)adapter->metrics_stats,
 				sizeof(uint64_t) * adapter->metrics_num);
 		break;
+	case ENA_MP_SRD_STATS_GET:
+		res = ena_com_get_ena_srd_info(ena_dev,
+				(struct ena_admin_ena_srd_info *)&adapter->srd_stats);
+		break;
 	default:
 		PMD_DRV_LOG(ERR, "Unknown request type %d\n", req->type);
 		res = -EINVAL;
diff --git a/drivers/net/ena/ena_ethdev.h b/drivers/net/ena/ena_ethdev.h
index 3f29764ca6..4988fbffb5 100644
--- a/drivers/net/ena/ena_ethdev.h
+++ b/drivers/net/ena/ena_ethdev.h
@@ -252,6 +252,23 @@  struct ena_stats_metrics {
 	uint64_t conntrack_allowance_available;
 };
 
+struct ena_stats_srd {
+	/* Describes which ENA Express features are enabled */
+	uint64_t ena_srd_mode;
+
+	/* Number of packets transmitted over ENA SRD */
+	uint64_t ena_srd_tx_pkts;
+
+	/* Number of packets transmitted or could have been transmitted over ENA SRD */
+	uint64_t ena_srd_eligible_tx_pkts;
+
+	/* Number of packets received over ENA SRD */
+	uint64_t ena_srd_rx_pkts;
+
+	/* Percentage of the ENA SRD resources that is in use */
+	uint64_t ena_srd_resource_utilization;
+};
+
 struct ena_offloads {
 	uint32_t tx_offloads;
 	uint32_t rx_offloads;
@@ -329,6 +346,7 @@  struct ena_adapter {
 	 */
 	uint64_t metrics_stats[ENA_MAX_CUSTOMER_METRICS] __rte_cache_aligned;
 	uint16_t metrics_num;
+	struct ena_stats_srd srd_stats __rte_cache_aligned;
 };
 
 int ena_mp_indirect_table_set(struct ena_adapter *adapter);