From: Qi Zhang <qi.z.zhang@intel.com>
To: qiming.yang@intel.com
Cc: zhichaox.zeng@intel.com, dev@dpdk.org, Qi Zhang <qi.z.zhang@intel.com>
Subject: [PATCH v4 3/5] net/ice: map group to pipeline stage
Date: Mon, 25 Sep 2023 06:33:22 -0400 [thread overview]
Message-ID: <20230925103324.4137053-4-qi.z.zhang@intel.com> (raw)
In-Reply-To: <20230925103324.4137053-1-qi.z.zhang@intel.com>
Mapping rte_flow_attr->group to a specific hardware stage.
Group 0 -> switch filter
Group 1 -> acl filter (dcf mode only)
Group 2 -> fdir filter (pf mode only)
For RSS, it will only be selected if there is a RTE_FLOW_ACTION_RSS
action target no queue group and the group ID is ignored.
Since each flow parser will be selected based on the group, there is no
need to maintain a separate 'parser list' or related APIs for
registering/unregistering parsers.
Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
drivers/net/ice/ice_acl_filter.c | 13 +-
drivers/net/ice/ice_ethdev.h | 2 -
drivers/net/ice/ice_fdir_filter.c | 19 +--
drivers/net/ice/ice_generic_flow.c | 234 +++++++++-------------------
drivers/net/ice/ice_generic_flow.h | 9 +-
drivers/net/ice/ice_hash.c | 16 +-
drivers/net/ice/ice_switch_filter.c | 13 +-
7 files changed, 91 insertions(+), 215 deletions(-)
diff --git a/drivers/net/ice/ice_acl_filter.c b/drivers/net/ice/ice_acl_filter.c
index 51f4feced4..e507bb927a 100644
--- a/drivers/net/ice/ice_acl_filter.c
+++ b/drivers/net/ice/ice_acl_filter.c
@@ -41,8 +41,6 @@
ICE_ACL_INSET_ETH_IPV4 | \
ICE_INSET_SCTP_SRC_PORT | ICE_INSET_SCTP_DST_PORT)
-static struct ice_flow_parser ice_acl_parser;
-
struct acl_rule {
enum ice_fltr_ptype flow_type;
uint64_t entry_id[4];
@@ -993,7 +991,6 @@ ice_acl_init(struct ice_adapter *ad)
int ret = 0;
struct ice_pf *pf = &ad->pf;
struct ice_hw *hw = ICE_PF_TO_HW(pf);
- struct ice_flow_parser *parser = &ice_acl_parser;
ret = ice_acl_prof_alloc(hw);
if (ret) {
@@ -1010,11 +1007,7 @@ ice_acl_init(struct ice_adapter *ad)
if (ret)
return ret;
- ret = ice_acl_prof_init(pf);
- if (ret)
- return ret;
-
- return ice_register_parser(parser, ad);
+ return ice_acl_prof_init(pf);
}
static void
@@ -1037,10 +1030,8 @@ ice_acl_uninit(struct ice_adapter *ad)
{
struct ice_pf *pf = &ad->pf;
struct ice_hw *hw = ICE_PF_TO_HW(pf);
- struct ice_flow_parser *parser = &ice_acl_parser;
if (ad->hw.dcf_enabled) {
- ice_unregister_parser(parser, ad);
ice_deinit_acl(pf);
ice_acl_prof_free(hw);
}
@@ -1056,7 +1047,7 @@ ice_flow_engine ice_acl_engine = {
.type = ICE_FLOW_ENGINE_ACL,
};
-static struct
+struct
ice_flow_parser ice_acl_parser = {
.engine = &ice_acl_engine,
.array = ice_acl_pattern,
diff --git a/drivers/net/ice/ice_ethdev.h b/drivers/net/ice/ice_ethdev.h
index 1f88becd19..abe6dcdc23 100644
--- a/drivers/net/ice/ice_ethdev.h
+++ b/drivers/net/ice/ice_ethdev.h
@@ -541,8 +541,6 @@ struct ice_pf {
bool adapter_stopped;
struct ice_flow_list flow_list;
rte_spinlock_t flow_ops_lock;
- struct ice_parser_list rss_parser_list;
- struct ice_parser_list dist_parser_list;
bool init_link_up;
uint64_t old_rx_bytes;
uint64_t old_tx_bytes;
diff --git a/drivers/net/ice/ice_fdir_filter.c b/drivers/net/ice/ice_fdir_filter.c
index bc43883a92..6afcdf5376 100644
--- a/drivers/net/ice/ice_fdir_filter.c
+++ b/drivers/net/ice/ice_fdir_filter.c
@@ -137,8 +137,6 @@ static struct ice_pattern_match_item ice_fdir_pattern_list[] = {
{pattern_eth_ipv6_gtpu_eh, ICE_FDIR_INSET_IPV6_GTPU_EH, ICE_FDIR_INSET_IPV6_GTPU_EH, ICE_INSET_NONE},
};
-static struct ice_flow_parser ice_fdir_parser;
-
static int
ice_fdir_is_tunnel_profile(enum ice_fdir_tunnel_type tunnel_type);
@@ -1147,31 +1145,18 @@ static int
ice_fdir_init(struct ice_adapter *ad)
{
struct ice_pf *pf = &ad->pf;
- struct ice_flow_parser *parser;
- int ret;
-
- ret = ice_fdir_setup(pf);
- if (ret)
- return ret;
-
- parser = &ice_fdir_parser;
- return ice_register_parser(parser, ad);
+ return ice_fdir_setup(pf);
}
static void
ice_fdir_uninit(struct ice_adapter *ad)
{
- struct ice_flow_parser *parser;
struct ice_pf *pf = &ad->pf;
if (ad->hw.dcf_enabled)
return;
- parser = &ice_fdir_parser;
-
- ice_unregister_parser(parser, ad);
-
ice_fdir_teardown(pf);
}
@@ -2507,7 +2492,7 @@ ice_fdir_parse(struct ice_adapter *ad,
return ret;
}
-static struct ice_flow_parser ice_fdir_parser = {
+struct ice_flow_parser ice_fdir_parser = {
.engine = &ice_fdir_engine,
.array = ice_fdir_pattern_list,
.array_len = RTE_DIM(ice_fdir_pattern_list),
diff --git a/drivers/net/ice/ice_generic_flow.c b/drivers/net/ice/ice_generic_flow.c
index 6695457bbd..e06a1f562a 100644
--- a/drivers/net/ice/ice_generic_flow.c
+++ b/drivers/net/ice/ice_generic_flow.c
@@ -1793,15 +1793,13 @@ enum rte_flow_item_type pattern_eth_ipv6_pfcp[] = {
RTE_FLOW_ITEM_TYPE_END,
};
-
-
-typedef struct ice_flow_engine * (*parse_engine_t)(struct ice_adapter *ad,
- struct rte_flow *flow,
- struct ice_parser_list *parser_list,
- uint32_t priority,
- const struct rte_flow_item pattern[],
- const struct rte_flow_action actions[],
- struct rte_flow_error *error);
+typedef bool (*parse_engine_t)(struct ice_adapter *ad,
+ struct rte_flow *flow,
+ struct ice_flow_parser *parser,
+ uint32_t priority,
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error);
void
ice_register_flow_engine(struct ice_flow_engine *engine)
@@ -1818,8 +1816,6 @@ ice_flow_init(struct ice_adapter *ad)
struct ice_flow_engine *engine;
TAILQ_INIT(&pf->flow_list);
- TAILQ_INIT(&pf->rss_parser_list);
- TAILQ_INIT(&pf->dist_parser_list);
rte_spinlock_init(&pf->flow_ops_lock);
if (ice_parser_create(&ad->hw, &ad->psr) != ICE_SUCCESS)
@@ -1860,7 +1856,6 @@ ice_flow_uninit(struct ice_adapter *ad)
struct ice_pf *pf = &ad->pf;
struct ice_flow_engine *engine;
struct rte_flow *p_flow;
- struct ice_flow_parser_node *p_parser;
void *temp;
RTE_TAILQ_FOREACH_SAFE(engine, &engine_list, node, temp) {
@@ -1881,117 +1876,12 @@ ice_flow_uninit(struct ice_adapter *ad)
rte_free(p_flow);
}
- /* Cleanup parser list */
- while ((p_parser = TAILQ_FIRST(&pf->rss_parser_list))) {
- TAILQ_REMOVE(&pf->rss_parser_list, p_parser, node);
- rte_free(p_parser);
- }
-
- while ((p_parser = TAILQ_FIRST(&pf->dist_parser_list))) {
- TAILQ_REMOVE(&pf->dist_parser_list, p_parser, node);
- rte_free(p_parser);
- }
-
if (ad->psr != NULL) {
ice_parser_destroy(ad->psr);
ad->psr = NULL;
}
}
-static struct ice_parser_list *
-ice_get_parser_list(struct ice_flow_parser *parser,
- struct ice_adapter *ad)
-{
- struct ice_parser_list *list;
- struct ice_pf *pf = &ad->pf;
-
- switch (parser->stage) {
- case ICE_FLOW_STAGE_RSS:
- list = &pf->rss_parser_list;
- break;
- case ICE_FLOW_STAGE_DISTRIBUTOR:
- list = &pf->dist_parser_list;
- break;
- default:
- return NULL;
- }
-
- return list;
-}
-
-int
-ice_register_parser(struct ice_flow_parser *parser,
- struct ice_adapter *ad)
-{
- struct ice_parser_list *list;
- struct ice_flow_parser_node *parser_node;
- struct ice_flow_parser_node *existing_node;
- void *temp;
-
- parser_node = rte_zmalloc("ice_parser", sizeof(*parser_node), 0);
- if (parser_node == NULL) {
- PMD_DRV_LOG(ERR, "Failed to allocate memory.");
- return -ENOMEM;
- }
- parser_node->parser = parser;
-
- list = ice_get_parser_list(parser, ad);
- if (list == NULL)
- return -EINVAL;
-
- if (parser->engine->type == ICE_FLOW_ENGINE_SWITCH) {
- RTE_TAILQ_FOREACH_SAFE(existing_node, list,
- node, temp) {
- if (existing_node->parser->engine->type ==
- ICE_FLOW_ENGINE_ACL) {
- TAILQ_INSERT_AFTER(list, existing_node,
- parser_node, node);
- goto DONE;
- }
- }
- TAILQ_INSERT_HEAD(list, parser_node, node);
- } else if (parser->engine->type == ICE_FLOW_ENGINE_FDIR) {
- RTE_TAILQ_FOREACH_SAFE(existing_node, list,
- node, temp) {
- if (existing_node->parser->engine->type ==
- ICE_FLOW_ENGINE_SWITCH) {
- TAILQ_INSERT_AFTER(list, existing_node,
- parser_node, node);
- goto DONE;
- }
- }
- TAILQ_INSERT_HEAD(list, parser_node, node);
- } else if (parser->engine->type == ICE_FLOW_ENGINE_HASH) {
- TAILQ_INSERT_TAIL(list, parser_node, node);
- } else if (parser->engine->type == ICE_FLOW_ENGINE_ACL) {
- TAILQ_INSERT_HEAD(list, parser_node, node);
- } else {
- return -EINVAL;
- }
-DONE:
- return 0;
-}
-
-void
-ice_unregister_parser(struct ice_flow_parser *parser,
- struct ice_adapter *ad)
-{
- struct ice_parser_list *list;
- struct ice_flow_parser_node *p_parser;
- void *temp;
-
- list = ice_get_parser_list(parser, ad);
- if (list == NULL)
- return;
-
- RTE_TAILQ_FOREACH_SAFE(p_parser, list, node, temp) {
- if (p_parser->parser->engine->type == parser->engine->type) {
- TAILQ_REMOVE(list, p_parser, node);
- rte_free(p_parser);
- }
- }
-}
-
static int
ice_flow_valid_attr(const struct rte_flow_attr *attr,
struct rte_flow_error *error)
@@ -2296,64 +2186,73 @@ ice_search_pattern_match_item(struct ice_adapter *ad,
return NULL;
}
-static struct ice_flow_engine *
+static bool
ice_parse_engine_create(struct ice_adapter *ad,
struct rte_flow *flow,
- struct ice_parser_list *parser_list,
+ struct ice_flow_parser *parser,
uint32_t priority,
const struct rte_flow_item pattern[],
const struct rte_flow_action actions[],
struct rte_flow_error *error)
{
- struct ice_flow_engine *engine = NULL;
- struct ice_flow_parser_node *parser_node;
void *meta = NULL;
- void *temp;
- RTE_TAILQ_FOREACH_SAFE(parser_node, parser_list, node, temp) {
- int ret;
+ if (ICE_FLOW_ENGINE_DISABLED(ad->disabled_engine_mask,
+ parser->engine->type)) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, "engine is not enabled.");
+ return false;
+ }
+
+ if (parser->parse_pattern_action(ad,
+ parser->array,
+ parser->array_len,
+ pattern, actions, priority, &meta, error) < 0)
+ return false;
- if (parser_node->parser->parse_pattern_action(ad,
- parser_node->parser->array,
- parser_node->parser->array_len,
- pattern, actions, priority, &meta, error) < 0)
- continue;
+ RTE_ASSERT(parser->engine->create != NULL);
- engine = parser_node->parser->engine;
- RTE_ASSERT(engine->create != NULL);
- ret = engine->create(ad, flow, meta, error);
- if (ret == 0)
- return engine;
- else if (ret == -EEXIST)
- return NULL;
- }
- return NULL;
+ return parser->engine->create(ad, flow, meta, error) == 0;
}
-static struct ice_flow_engine *
+static bool
ice_parse_engine_validate(struct ice_adapter *ad,
struct rte_flow *flow __rte_unused,
- struct ice_parser_list *parser_list,
+ struct ice_flow_parser *parser,
uint32_t priority,
const struct rte_flow_item pattern[],
const struct rte_flow_action actions[],
struct rte_flow_error *error)
{
- struct ice_flow_engine *engine = NULL;
- struct ice_flow_parser_node *parser_node;
- void *temp;
- RTE_TAILQ_FOREACH_SAFE(parser_node, parser_list, node, temp) {
- if (parser_node->parser->parse_pattern_action(ad,
- parser_node->parser->array,
- parser_node->parser->array_len,
- pattern, actions, priority, NULL, error) < 0)
- continue;
+ if (ICE_FLOW_ENGINE_DISABLED(ad->disabled_engine_mask,
+ parser->engine->type)) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, "engine is not enabled.");
+ return false;
+ }
+
+ return parser->parse_pattern_action(ad,
+ parser->array,
+ parser->array_len,
+ pattern, actions, priority,
+ NULL, error) >= 0;
+}
- engine = parser_node->parser->engine;
- break;
+static struct ice_flow_parser *get_flow_parser(uint32_t group)
+{
+ switch (group) {
+ case 0:
+ return &ice_switch_parser;
+ case 1:
+ return &ice_acl_parser;
+ case 2:
+ return &ice_fdir_parser;
+ default:
+ return NULL;
}
- return engine;
}
static int
@@ -2369,7 +2268,7 @@ ice_flow_process_filter(struct rte_eth_dev *dev,
int ret = ICE_ERR_NOT_SUPPORTED;
struct ice_adapter *ad =
ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
- struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct ice_flow_parser *parser;
if (!pattern) {
rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
@@ -2395,17 +2294,30 @@ ice_flow_process_filter(struct rte_eth_dev *dev,
if (ret)
return ret;
- *engine = ice_parse_engine(ad, flow, &pf->rss_parser_list,
- attr->priority, pattern, actions, error);
- if (*engine != NULL)
+ *engine = NULL;
+ /* always try hash engine first */
+ if (ice_parse_engine(ad, flow, &ice_hash_parser,
+ attr->priority, pattern,
+ actions, error)) {
+ *engine = ice_hash_parser.engine;
return 0;
+ }
- *engine = ice_parse_engine(ad, flow, &pf->dist_parser_list,
- attr->priority, pattern, actions, error);
- if (*engine == NULL)
- return -EINVAL;
+ parser = get_flow_parser(attr->group);
+ if (parser == NULL) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ATTR,
+ NULL, "NULL attribute.");
+ return -rte_errno;
+ }
- return 0;
+ if (ice_parse_engine(ad, flow, parser, attr->priority,
+ pattern, actions, error)) {
+ *engine = parser->engine;
+ return 0;
+ } else {
+ return -rte_errno;
+ }
}
static int
diff --git a/drivers/net/ice/ice_generic_flow.h b/drivers/net/ice/ice_generic_flow.h
index 471f255bd6..391d615b9a 100644
--- a/drivers/net/ice/ice_generic_flow.h
+++ b/drivers/net/ice/ice_generic_flow.h
@@ -515,10 +515,6 @@ struct ice_flow_parser_node {
void ice_register_flow_engine(struct ice_flow_engine *engine);
int ice_flow_init(struct ice_adapter *ad);
void ice_flow_uninit(struct ice_adapter *ad);
-int ice_register_parser(struct ice_flow_parser *parser,
- struct ice_adapter *ad);
-void ice_unregister_parser(struct ice_flow_parser *parser,
- struct ice_adapter *ad);
struct ice_pattern_match_item *
ice_search_pattern_match_item(struct ice_adapter *ad,
const struct rte_flow_item pattern[],
@@ -528,4 +524,9 @@ ice_search_pattern_match_item(struct ice_adapter *ad,
int
ice_flow_redirect(struct ice_adapter *ad,
struct ice_flow_redirect *rd);
+
+extern struct ice_flow_parser ice_switch_parser;
+extern struct ice_flow_parser ice_acl_parser;
+extern struct ice_flow_parser ice_fdir_parser;
+extern struct ice_flow_parser ice_hash_parser;
#endif
diff --git a/drivers/net/ice/ice_hash.c b/drivers/net/ice/ice_hash.c
index 37bee808c6..f923641533 100644
--- a/drivers/net/ice/ice_hash.c
+++ b/drivers/net/ice/ice_hash.c
@@ -572,7 +572,7 @@ static struct ice_flow_engine ice_hash_engine = {
};
/* Register parser for os package. */
-static struct ice_flow_parser ice_hash_parser = {
+struct ice_flow_parser ice_hash_parser = {
.engine = &ice_hash_engine,
.array = ice_hash_pattern_list,
.array_len = RTE_DIM(ice_hash_pattern_list),
@@ -587,13 +587,9 @@ RTE_INIT(ice_hash_engine_init)
}
static int
-ice_hash_init(struct ice_adapter *ad)
+ice_hash_init(struct ice_adapter *ad __rte_unused)
{
- struct ice_flow_parser *parser = NULL;
-
- parser = &ice_hash_parser;
-
- return ice_register_parser(parser, ad);
+ return 0;
}
static int
@@ -1439,12 +1435,8 @@ ice_hash_destroy(struct ice_adapter *ad,
}
static void
-ice_hash_uninit(struct ice_adapter *ad)
+ice_hash_uninit(struct ice_adapter *ad __rte_unused)
{
- if (ad->hw.dcf_enabled)
- return;
-
- ice_unregister_parser(&ice_hash_parser, ad);
}
static void
diff --git a/drivers/net/ice/ice_switch_filter.c b/drivers/net/ice/ice_switch_filter.c
index 88d599068f..8f29326762 100644
--- a/drivers/net/ice/ice_switch_filter.c
+++ b/drivers/net/ice/ice_switch_filter.c
@@ -201,8 +201,6 @@ struct ice_switch_filter_conf {
struct ice_adv_rule_info rule_info;
};
-static struct ice_flow_parser ice_switch_dist_parser;
-
static struct
ice_pattern_match_item ice_switch_pattern_dist_list[] = {
{pattern_any, ICE_INSET_NONE, ICE_INSET_NONE, ICE_INSET_NONE},
@@ -2052,15 +2050,14 @@ ice_switch_redirect(struct ice_adapter *ad,
}
static int
-ice_switch_init(struct ice_adapter *ad)
+ice_switch_init(struct ice_adapter *ad __rte_unused)
{
- return ice_register_parser(&ice_switch_dist_parser, ad);
+ return 0;
}
static void
-ice_switch_uninit(struct ice_adapter *ad)
+ice_switch_uninit(struct ice_adapter *ad __rte_unused)
{
- ice_unregister_parser(&ice_switch_dist_parser, ad);
}
static struct
@@ -2075,8 +2072,8 @@ ice_flow_engine ice_switch_engine = {
.type = ICE_FLOW_ENGINE_SWITCH,
};
-static struct
-ice_flow_parser ice_switch_dist_parser = {
+struct
+ice_flow_parser ice_switch_parser = {
.engine = &ice_switch_engine,
.array = ice_switch_pattern_dist_list,
.array_len = RTE_DIM(ice_switch_pattern_dist_list),
--
2.31.1
next prev parent reply other threads:[~2023-09-25 2:13 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-14 20:26 [PATCH 0/2] refactor rte_flow Qi Zhang
2023-08-14 20:26 ` [PATCH 1/2] net/ice: remove pipeline mode Qi Zhang
2023-08-14 20:26 ` [PATCH 2/2] net/ice: map group to pipeline stage Qi Zhang
2023-09-11 16:51 ` [PATCH v2 0/2] refactor rte_flow Qi Zhang
2023-09-11 16:51 ` [PATCH v2 1/2] net/ice: remove pipeline mode Qi Zhang
2023-09-11 16:51 ` [PATCH v2 2/2] net/ice: map group to pipeline stage Qi Zhang
2023-09-12 10:00 ` [PATCH v3 0/5] refactor rte_flow Qi Zhang
2023-09-12 10:00 ` [PATCH v3 1/5] net/ice: remove pipeline mode Qi Zhang
2023-09-12 10:00 ` [PATCH v3 2/5] net/ice: refine flow engine disabling Qi Zhang
2023-09-12 10:00 ` [PATCH v3 3/5] net/ice: map group to pipeline stage Qi Zhang
2023-09-12 10:00 ` [PATCH v3 4/5] net/ice: refine supported flow pattern name Qi Zhang
2023-09-12 10:00 ` [PATCH v3 5/5] doc: add generic flow doc for ice PMD Qi Zhang
2023-09-25 10:33 ` [PATCH v4 0/5] net/ice: refactor rte_flow Qi Zhang
2023-09-25 10:33 ` [PATCH v4 1/5] net/ice: remove pipeline mode Qi Zhang
2023-09-25 10:33 ` [PATCH v4 2/5] net/ice: refine flow engine disabling Qi Zhang
2023-09-25 10:33 ` Qi Zhang [this message]
2023-09-25 10:33 ` [PATCH v4 4/5] net/ice: refine supported flow pattern name Qi Zhang
2023-09-25 10:33 ` [PATCH v4 5/5] doc: add generic flow doc for ice PMD Qi Zhang
2023-09-26 11:29 ` [PATCH v5 0/5] net/ice: refactor rte_flow Qi Zhang
2023-09-26 11:29 ` [PATCH v5 1/5] net/ice: remove pipeline mode Qi Zhang
2023-09-26 11:29 ` [PATCH v5 2/5] net/ice: refine flow engine disabling Qi Zhang
2023-09-26 11:29 ` [PATCH v5 3/5] net/ice: map group to pipeline stage Qi Zhang
2023-09-26 11:29 ` [PATCH v5 4/5] net/ice: refine supported flow pattern name Qi Zhang
2023-09-26 11:29 ` [PATCH v5 5/5] doc: add generic flow doc for ice PMD Qi Zhang
2023-09-27 2:42 ` Zeng, ZhichaoX
2023-09-27 3:08 ` Zhang, Qi Z
2023-10-13 13:17 ` Thomas Monjalon
2023-10-26 10:43 ` Zhang, Qi Z
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=20230925103324.4137053-4-qi.z.zhang@intel.com \
--to=qi.z.zhang@intel.com \
--cc=dev@dpdk.org \
--cc=qiming.yang@intel.com \
--cc=zhichaox.zeng@intel.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 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).