All of lore.kernel.org
 help / color / mirror / Atom feed
From: Joshua Washington <joshwash@google.com>
To: Junfeng Guo <junfeng.guo@intel.com>,
	Jeroen de Borst <jeroendb@google.com>,
	Rushil Gupta <rushilg@google.com>,
	Joshua Washington <joshwash@google.com>
Cc: dev@dpdk.org, Ferruh Yigit <ferruh.yigit@amd.com>
Subject: [PATCH v3 3/7] net/gve: add gve_rss library for handling RSS-related behaviors
Date: Tue, 23 Jan 2024 16:04:21 -0800	[thread overview]
Message-ID: <20240124000426.418527-4-joshwash@google.com> (raw)
In-Reply-To: <20240124000426.418527-1-joshwash@google.com>

This change includes a number of helper functions to facilitate RSS
configuration on the GVE DPDK driver. These methods are declared in
gve_rss.h.

Signed-off-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Rushil Gupta <rushilg@google.com>
Reviewed-by: Jeroen de Borst <jeroendb@google.com>
---
 drivers/net/gve/base/gve_adminq.h |  10 +-
 drivers/net/gve/gve_ethdev.c      |   2 +-
 drivers/net/gve/gve_ethdev.h      |   4 +-
 drivers/net/gve/gve_rss.c         | 206 ++++++++++++++++++++++++++++++
 drivers/net/gve/gve_rss.h         | 107 ++++++++++++++++
 drivers/net/gve/meson.build       |   1 +
 6 files changed, 319 insertions(+), 11 deletions(-)
 create mode 100644 drivers/net/gve/gve_rss.c
 create mode 100644 drivers/net/gve/gve_rss.h

diff --git a/drivers/net/gve/base/gve_adminq.h b/drivers/net/gve/base/gve_adminq.h
index 95f4960561..24abd945cc 100644
--- a/drivers/net/gve/base/gve_adminq.h
+++ b/drivers/net/gve/base/gve_adminq.h
@@ -378,15 +378,6 @@ struct gve_adminq_get_ptype_map {
 	__be64 ptype_map_addr;
 };
 
-#define GVE_RSS_HASH_IPV4		BIT(0)
-#define GVE_RSS_HASH_TCPV4		BIT(1)
-#define GVE_RSS_HASH_IPV6		BIT(2)
-#define GVE_RSS_HASH_IPV6_EX		BIT(3)
-#define GVE_RSS_HASH_TCPV6		BIT(4)
-#define GVE_RSS_HASH_TCPV6_EX		BIT(5)
-#define GVE_RSS_HASH_UDPV4		BIT(6)
-#define GVE_RSS_HASH_UDPV6		BIT(7)
-#define GVE_RSS_HASH_UDPV6_EX		BIT(8)
 
 /* RSS configuration command */
 struct gve_adminq_configure_rss {
@@ -428,6 +419,7 @@ union gve_adminq_command {
 GVE_CHECK_UNION_LEN(64, gve_adminq_command);
 
 struct gve_priv;
+struct gve_rss_config;
 struct gve_queue_page_list;
 int gve_adminq_alloc(struct gve_priv *priv);
 void gve_adminq_free(struct gve_priv *priv);
diff --git a/drivers/net/gve/gve_ethdev.c b/drivers/net/gve/gve_ethdev.c
index 6acdb4e13b..936ca22cb9 100644
--- a/drivers/net/gve/gve_ethdev.c
+++ b/drivers/net/gve/gve_ethdev.c
@@ -442,7 +442,7 @@ gve_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 		.nb_align = 1,
 	};
 
-	dev_info->flow_type_rss_offloads = GVE_RSS_OFFLOAD_ALL;
+	dev_info->flow_type_rss_offloads = GVE_RTE_RSS_OFFLOAD_ALL;
 
 	return 0;
 }
diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index f7635e829c..bc486cb941 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -33,7 +33,7 @@
 		RTE_MBUF_F_TX_L4_MASK  |	\
 		RTE_MBUF_F_TX_TCP_SEG)
 
-#define GVE_RSS_OFFLOAD_ALL (		\
+#define GVE_RTE_RSS_OFFLOAD_ALL (	\
 	RTE_ETH_RSS_IPV4 |		\
 	RTE_ETH_RSS_NONFRAG_IPV4_TCP |	\
 	RTE_ETH_RSS_IPV6 |		\
@@ -290,6 +290,8 @@ struct gve_priv {
 	const struct rte_memzone *stats_report_mem;
 	uint16_t stats_start_idx; /* start index of array of stats written by NIC */
 	uint16_t stats_end_idx; /* end index of array of stats written by NIC */
+
+	struct gve_rss_config rss_config;
 };
 
 static inline bool
diff --git a/drivers/net/gve/gve_rss.c b/drivers/net/gve/gve_rss.c
new file mode 100644
index 0000000000..931180f8f2
--- /dev/null
+++ b/drivers/net/gve/gve_rss.c
@@ -0,0 +1,206 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2023 Google LLC
+ */
+
+#include "gve_rss.h"
+
+int
+gve_generate_rss_reta(struct rte_eth_dev *dev, struct gve_rss_config *config)
+{
+	int i;
+	if (!config || !config->indir)
+		return -EINVAL;
+
+	for (i = 0; i < config->indir_size; i++)
+		config->indir[i] = i % dev->data->nb_rx_queues;
+
+	return 0;
+}
+
+
+int
+gve_init_rss_config(struct gve_rss_config *gve_rss_conf,
+		uint16_t key_size, uint16_t indir_size)
+{
+	int err;
+
+	gve_rss_conf->alg = GVE_RSS_HASH_TOEPLITZ;
+
+	gve_rss_conf->key_size = key_size;
+	gve_rss_conf->key = rte_zmalloc("rss key",
+		key_size * sizeof(*gve_rss_conf->key),
+		RTE_CACHE_LINE_SIZE);
+	if (!gve_rss_conf->key)
+		return -ENOMEM;
+
+	gve_rss_conf->indir_size = indir_size;
+	gve_rss_conf->indir = rte_zmalloc("rss reta",
+		indir_size * sizeof(*gve_rss_conf->indir),
+		RTE_CACHE_LINE_SIZE);
+	if (!gve_rss_conf->indir) {
+		err = -ENOMEM;
+		goto err_with_key;
+	}
+
+	return 0;
+err_with_key:
+	rte_free(gve_rss_conf->key);
+	return err;
+}
+
+int
+gve_init_rss_config_from_priv(struct gve_priv *priv,
+	struct gve_rss_config *gve_rss_conf)
+{
+	int err = gve_init_rss_config(gve_rss_conf, priv->rss_config.key_size,
+		priv->rss_config.indir_size);
+	if (err)
+		return err;
+
+	gve_rss_conf->hash_types = priv->rss_config.hash_types;
+	gve_rss_conf->alg = priv->rss_config.alg;
+	memcpy(gve_rss_conf->key, priv->rss_config.key,
+		gve_rss_conf->key_size * sizeof(*gve_rss_conf->key));
+	memcpy(gve_rss_conf->indir, priv->rss_config.indir,
+		gve_rss_conf->indir_size * sizeof(*gve_rss_conf->indir));
+
+	return 0;
+}
+
+void
+gve_free_rss_config(struct gve_rss_config *gve_rss_conf)
+{
+	rte_free(gve_rss_conf->indir);
+	gve_rss_conf->indir = NULL;
+	rte_free(gve_rss_conf->key);
+	gve_rss_conf->key = NULL;
+}
+
+int
+gve_update_priv_rss_config(struct gve_priv *priv, struct gve_rss_config *config)
+{
+	struct gve_rss_config *priv_config = &priv->rss_config;
+	int key_bytes, indir_bytes;
+
+	if (!config)
+		return -EINVAL;
+	if (config->key_size == 0 || !config->key)
+		return -EINVAL;
+	if (config->indir_size == 0 || !config->indir)
+		return -EINVAL;
+
+	priv_config->hash_types = config->hash_types;
+	priv_config->alg = config->alg;
+
+	priv_config->key_size = config->key_size;
+	key_bytes = priv_config->key_size * sizeof(*priv_config->key);
+	if (!priv_config->key)
+		priv_config->key = rte_zmalloc("priv rss key", key_bytes,
+			RTE_CACHE_LINE_SIZE);
+	else
+		priv_config->key = rte_realloc(priv_config->key, key_bytes,
+			RTE_CACHE_LINE_SIZE);
+	if (!priv_config->key)
+		return -ENOMEM;
+
+	priv_config->indir_size = config->indir_size;
+	indir_bytes = priv_config->indir_size * sizeof(*priv_config->indir);
+	if (!priv_config->indir)
+		priv_config->indir = rte_zmalloc("priv rss reta", indir_bytes,
+			RTE_CACHE_LINE_SIZE);
+	else
+		priv_config->indir = rte_realloc(priv_config->indir,
+			indir_bytes, RTE_CACHE_LINE_SIZE);
+
+	if (!priv_config->indir)
+		return -ENOMEM;
+
+	memcpy(priv_config->indir, config->indir,
+		config->indir_size * sizeof(*priv_config->indir));
+	memcpy(priv_config->key, config->key,
+		config->key_size * sizeof(*priv_config->key));
+
+	return 0;
+}
+
+int
+gve_update_rss_key(struct gve_priv *priv, struct gve_rss_config *gve_rss_conf,
+	struct rte_eth_rss_conf *rss_conf)
+{
+	if (rss_conf->rss_key_len && rss_conf->rss_key) {
+		gve_rss_conf->key_size = rss_conf->rss_key_len;
+		memcpy(gve_rss_conf->key, rss_conf->rss_key,
+			gve_rss_conf->key_size * sizeof(*gve_rss_conf->key));
+	} else if (priv->rss_config.key_size && priv->rss_config.key) {
+		gve_rss_conf->key_size = priv->rss_config.key_size;
+		memcpy(gve_rss_conf->key, priv->rss_config.key,
+			gve_rss_conf->key_size * sizeof(*gve_rss_conf->key));
+	} else {
+		PMD_DRV_LOG(ERR, "RSS key must be set as part of initial RSS "
+			"configuration.");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+int
+gve_update_rss_hash_types(struct gve_priv *priv,
+	struct gve_rss_config *gve_rss_conf, struct rte_eth_rss_conf *rss_conf)
+{
+	/* Initialize to 0 before modifying. */
+	gve_rss_conf->hash_types = 0;
+	if (rss_conf->rss_hf)
+		rte_to_gve_rss_hf(rss_conf->rss_hf, gve_rss_conf);
+	else if (priv->rss_config.key_size && priv->rss_config.key)
+		gve_rss_conf->hash_types = priv->rss_config.hash_types;
+	else
+		gve_rss_conf->hash_types = GVE_RSS_OFFLOAD_DEFAULT;
+	return 0;
+}
+
+void
+rte_to_gve_rss_hf(uint64_t rte_rss_hf, struct gve_rss_config *gve_rss_conf)
+{
+	if (rte_rss_hf & RTE_ETH_RSS_IPV4)
+		gve_rss_conf->hash_types |= GVE_RSS_HASH_IPV4;
+	if (rte_rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP)
+		gve_rss_conf->hash_types |= GVE_RSS_HASH_TCPV4;
+	if (rte_rss_hf & RTE_ETH_RSS_IPV6)
+		gve_rss_conf->hash_types |= GVE_RSS_HASH_IPV6;
+	if (rte_rss_hf & RTE_ETH_RSS_IPV6_EX)
+		gve_rss_conf->hash_types |= GVE_RSS_HASH_IPV6_EX;
+	if (rte_rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP)
+		gve_rss_conf->hash_types |= GVE_RSS_HASH_TCPV6;
+	if (rte_rss_hf & RTE_ETH_RSS_IPV6_TCP_EX)
+		gve_rss_conf->hash_types |= GVE_RSS_HASH_TCPV6_EX;
+	if (rte_rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP)
+		gve_rss_conf->hash_types |= GVE_RSS_HASH_UDPV4;
+	if (rte_rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP)
+		gve_rss_conf->hash_types |= GVE_RSS_HASH_UDPV6;
+	if (rte_rss_hf & RTE_ETH_RSS_IPV6_UDP_EX)
+		gve_rss_conf->hash_types |= GVE_RSS_HASH_UDPV6_EX;
+}
+
+void
+gve_to_rte_rss_hf(uint16_t gve_rss_types, struct rte_eth_rss_conf *rss_conf)
+{
+	if (gve_rss_types & GVE_RSS_HASH_IPV4)
+		rss_conf->rss_hf |= RTE_ETH_RSS_IPV4;
+	if (gve_rss_types & GVE_RSS_HASH_TCPV4)
+		rss_conf->rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_TCP;
+	if (gve_rss_types & GVE_RSS_HASH_IPV6)
+		rss_conf->rss_hf |= RTE_ETH_RSS_IPV6;
+	if (gve_rss_types & GVE_RSS_HASH_IPV6_EX)
+		rss_conf->rss_hf |= RTE_ETH_RSS_IPV6_EX;
+	if (gve_rss_types & GVE_RSS_HASH_TCPV6)
+		rss_conf->rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_TCP;
+	if (gve_rss_types & GVE_RSS_HASH_TCPV6_EX)
+		rss_conf->rss_hf |= RTE_ETH_RSS_IPV6_TCP_EX;
+	if (gve_rss_types & GVE_RSS_HASH_UDPV4)
+		rss_conf->rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_UDP;
+	if (gve_rss_types & GVE_RSS_HASH_UDPV6)
+		rss_conf->rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_UDP;
+	if (gve_rss_types & GVE_RSS_HASH_UDPV6_EX)
+		rss_conf->rss_hf |= RTE_ETH_RSS_IPV6_UDP_EX;
+}
+
diff --git a/drivers/net/gve/gve_rss.h b/drivers/net/gve/gve_rss.h
new file mode 100644
index 0000000000..0cc235a19a
--- /dev/null
+++ b/drivers/net/gve/gve_rss.h
@@ -0,0 +1,107 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2023 Google LLC
+ */
+
+#include "gve_adminq.h"
+#include "gve_ethdev.h"
+
+#define GVE_RSS_HASH_IPV4		BIT(0)
+#define GVE_RSS_HASH_TCPV4		BIT(1)
+#define GVE_RSS_HASH_IPV6		BIT(2)
+#define GVE_RSS_HASH_IPV6_EX		BIT(3)
+#define GVE_RSS_HASH_TCPV6		BIT(4)
+#define GVE_RSS_HASH_TCPV6_EX		BIT(5)
+#define GVE_RSS_HASH_UDPV4		BIT(6)
+#define GVE_RSS_HASH_UDPV6		BIT(7)
+#define GVE_RSS_HASH_UDPV6_EX		BIT(8)
+
+#define GVE_RSS_OFFLOAD_DEFAULT (	\
+	GVE_RSS_HASH_IPV4 |		\
+	GVE_RSS_HASH_TCPV4 |		\
+	GVE_RSS_HASH_IPV6 |		\
+	GVE_RSS_HASH_IPV6_EX |		\
+	GVE_RSS_HASH_TCPV6 |		\
+	GVE_RSS_HASH_TCPV6_EX |		\
+	GVE_RSS_HASH_UDPV4 |		\
+	GVE_RSS_HASH_UDPV6 |		\
+	GVE_RSS_HASH_UDPV6_EX)
+
+/**
+ * Generates default RSS redirection table based on the number of queues the
+ * device is configured with. This assigns hash values to queues in a
+ * round-robin manner.
+ */
+int
+gve_generate_rss_reta(struct rte_eth_dev *dev, struct gve_rss_config *config);
+
+/**
+ * Initializes `gve_rss_conf`, setting the fields to default values and
+ * allocating memory for the RSS key and redirection table.
+ */
+int
+gve_init_rss_config(struct gve_rss_config *gve_rss_conf,
+		uint16_t key_size, uint16_t indir_size);
+
+/**
+ * Initializes `gve_rss_conf` based on the RSS configuration stored in `priv`.
+ */
+int
+gve_init_rss_config_from_priv(struct gve_priv *priv,
+	struct gve_rss_config *gve_rss_conf);
+
+/**
+ * Frees RSS key and redriection table pointers stored in `gve_rss_conf`.
+ */
+void
+gve_free_rss_config(struct gve_rss_config *gve_rss_conf);
+
+/**
+ * Updates the rss_config stored in `priv` with the contents of `config`.
+ */
+int
+gve_update_priv_rss_config(struct gve_priv *priv,
+			   struct gve_rss_config *config);
+
+/**
+ * Updates the RSS key stored in `gve_rss_conf`. It is prioritized as follows:
+ *	1) retrieve from `rss_conf`, if non-null
+ *	2) retrieve from `priv`, if non-null
+ * If keys from both sources are unset, return -EINVAL.
+ */
+int
+gve_update_rss_key(struct gve_priv *priv, struct gve_rss_config *gve_rss_conf,
+		   struct rte_eth_rss_conf *rss_conf);
+
+/**
+ * Updates the RSS hash types stored in `gve_rss_conf`. It is prioritized as
+ * follows:
+ *	1) retrieve from `rss_conf`, if set
+ *	2) retrieve from priv, if RSS has been configured
+ *	3) set default RSS offload
+ */
+int
+gve_update_rss_hash_types(struct gve_priv *priv,
+	struct gve_rss_config *gve_rss_conf, struct rte_eth_rss_conf *rss_conf);
+
+/**
+ * Ensures that only supported RSS hash fields are set in `rte_rss_hf`.
+ */
+static inline int
+gve_validate_rss_hf(uint64_t rte_rss_hf) {
+	return rte_rss_hf & ~GVE_RTE_RSS_OFFLOAD_ALL;
+}
+
+/**
+ * Converts RSS hash types from RTE values to GVE values, storing them in
+ * `gve_rss_conf`.
+ */
+void
+rte_to_gve_rss_hf(uint64_t rte_rss_hf, struct gve_rss_config *gve_rss_conf);
+
+/**
+ * Converts RSS hash types from GVE values to RTE values, storing them in
+ * `rss_conf`.
+ */
+void
+gve_to_rte_rss_hf(uint16_t gve_rss_types, struct rte_eth_rss_conf *rss_conf);
+
diff --git a/drivers/net/gve/meson.build b/drivers/net/gve/meson.build
index 61d195009c..6da13a8406 100644
--- a/drivers/net/gve/meson.build
+++ b/drivers/net/gve/meson.build
@@ -15,5 +15,6 @@ sources = files(
         'gve_tx_dqo.c',
         'gve_ethdev.c',
         'gve_version.c',
+        'gve_rss.c',
 )
 includes += include_directories('base')
-- 
2.43.0.429.g432eaa2c6b-goog


  parent reply	other threads:[~2024-01-24  0:05 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-23 17:58 [PATCH 0/7] net/gve: RSS Support for GVE Driver Joshua Washington
2024-01-23 17:58 ` [PATCH v2 1/7] net/gve: fully expose RSS offload support in dev_info Joshua Washington
2024-01-23 17:58 ` [PATCH v2 2/7] net/gve: RSS adminq command changes Joshua Washington
2024-01-23 17:58 ` [PATCH v2 3/7] net/gve: add gve_rss library for handling RSS-related behaviors Joshua Washington
2024-01-23 17:58 ` [PATCH v2 4/7] net/gve: RSS configuration update support Joshua Washington
2024-01-23 17:58 ` [PATCH v2 5/7] net/gve: RSS redirection table " Joshua Washington
2024-01-23 17:58 ` [PATCH v2 6/7] net/gve: update gve.ini with RSS capabilities Joshua Washington
2024-01-23 17:58 ` [PATCH v2 7/7] net/gve: update GVE documentation with RSS support Joshua Washington
2024-01-24  0:04 ` [PATCH 0/7] net/gve: RSS Support for GVE Driver Joshua Washington
2024-01-24  0:04   ` [PATCH v3 1/7] net/gve: fully expose RSS offload support in dev_info Joshua Washington
2024-01-24  0:04   ` [PATCH v3 2/7] net/gve: RSS adminq command changes Joshua Washington
2024-01-24  0:04   ` Joshua Washington [this message]
2024-01-24  0:04   ` [PATCH v3 4/7] net/gve: RSS configuration update support Joshua Washington
2024-01-24  0:04   ` [PATCH v3 5/7] net/gve: RSS redirection table " Joshua Washington
2024-01-24  0:04   ` [PATCH v3 6/7] net/gve: update gve.ini with RSS capabilities Joshua Washington
2024-01-24  0:04   ` [PATCH v3 7/7] net/gve: update GVE documentation with RSS support Joshua Washington
2024-01-24  0:09 ` [PATCH 0/7] net/gve: RSS Support for GVE Driver Joshua Washington
2024-01-24  0:13 ` [PATCH v3 " Joshua Washington
2024-01-24  0:14 ` Joshua Washington
2024-01-24  0:14   ` [PATCH v3 1/7] net/gve: fully expose RSS offload support in dev_info Joshua Washington
2024-01-24  0:14   ` [PATCH v3 2/7] net/gve: RSS adminq command changes Joshua Washington
2024-01-24  0:14   ` [PATCH v3 3/7] net/gve: add gve_rss library for handling RSS-related behaviors Joshua Washington
2024-01-24  0:14   ` [PATCH v3 4/7] net/gve: RSS configuration update support Joshua Washington
2024-01-24  0:14   ` [PATCH v3 5/7] net/gve: RSS redirection table " Joshua Washington
2024-01-24  0:14   ` [PATCH v3 6/7] net/gve: update gve.ini with RSS capabilities Joshua Washington
2024-01-24  0:15   ` [PATCH v3 7/7] net/gve: update GVE documentation with RSS support Joshua Washington
     [not found]   ` <20240126173317.2779230-1-joshwash@google.com>
2024-01-26 17:33     ` [PATCH v4 1/7] net/gve: fully expose RSS offload support in dev_info Joshua Washington
2024-01-31 22:13       ` [PATCH v5 0/5] net/gve: RSS Support for GVE Driver Joshua Washington
2024-01-31 22:13         ` [PATCH v5 1/5] net/gve: expose RSS offload support in dev info Joshua Washington
2024-01-31 22:13         ` [PATCH v5 2/5] net/gve: add RSS adminq command Joshua Washington
2024-01-31 22:13         ` [PATCH v5 3/5] net/gve: add gve RSS library Joshua Washington
2024-01-31 22:13         ` [PATCH v5 4/5] net/gve: add RSS configuration update support Joshua Washington
2024-01-31 22:13         ` [PATCH v5 5/5] net/gve: add RSS redirection table " Joshua Washington
2024-02-01 13:28         ` [PATCH v5 0/5] net/gve: RSS Support for GVE Driver Ferruh Yigit
2024-01-26 17:33     ` [PATCH v4 2/7] net/gve: RSS adminq command changes Joshua Washington
2024-01-26 17:33     ` [PATCH v4 3/7] net/gve: add gve_rss library for handling RSS-related behaviors Joshua Washington
2024-01-26 17:33     ` [PATCH v4 4/7] net/gve: RSS configuration update support Joshua Washington
2024-01-26 17:33     ` [PATCH v4 5/7] net/gve: RSS redirection table " Joshua Washington
2024-01-26 17:33     ` [PATCH v4 6/7] net/gve: update gve.ini with RSS capabilities Joshua Washington
2024-01-31 14:48       ` Ferruh Yigit
2024-01-31 14:55         ` Ferruh Yigit
2024-01-26 17:33     ` [PATCH v4 7/7] net/gve: update GVE documentation with RSS support Joshua Washington
2024-01-31 14:50       ` Ferruh Yigit
2024-01-31 14:58     ` 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=20240124000426.418527-4-joshwash@google.com \
    --to=joshwash@google.com \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@amd.com \
    --cc=jeroendb@google.com \
    --cc=junfeng.guo@intel.com \
    --cc=rushilg@google.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.