From: Maayan Kashani <mkashani@nvidia.com>
To: <dev@dpdk.org>
Cc: <mkashani@nvidia.com>, <dsosnowski@nvidia.com>,
<rasland@nvidia.com>, Gregory Etelson <getelson@nvidia.com>,
Viacheslav Ovsiienko <viacheslavo@nvidia.com>,
Ori Kam <orika@nvidia.com>, Suanming Mou <suanmingm@nvidia.com>,
Matan Azrad <matan@nvidia.com>
Subject: [PATCH v5 2/6] net/mlx5: support RSS expansion in non-template HWS setup
Date: Mon, 10 Jun 2024 11:50:35 +0300 [thread overview]
Message-ID: <20240610085039.146356-2-mkashani@nvidia.com> (raw)
In-Reply-To: <20240610085039.146356-1-mkashani@nvidia.com>
From: Gregory Etelson <getelson@nvidia.com>
The MLX5 PMD expands flow rule with the RSS action in the
non-template environment.
The patch adds RSS flow rule expansion for legacy flow rules in
the template setup.
Signed-off-by: Gregory Etelson <getelson@nvidia.com>
Acked-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
---
drivers/net/mlx5/hws/mlx5dr_definer.c | 2 +
drivers/net/mlx5/meson.build | 1 +
drivers/net/mlx5/mlx5.c | 4 +
drivers/net/mlx5/mlx5.h | 6 +-
drivers/net/mlx5/mlx5_flow.h | 36 +-
drivers/net/mlx5/mlx5_flow_hw.c | 65 +--
| 564 ++++++++++++++++++++++++++
7 files changed, 646 insertions(+), 32 deletions(-)
create mode 100644 drivers/net/mlx5/mlx5_nta_rss.c
diff --git a/drivers/net/mlx5/hws/mlx5dr_definer.c b/drivers/net/mlx5/hws/mlx5dr_definer.c
index 4be9012e25f..9ebda9267da 100644
--- a/drivers/net/mlx5/hws/mlx5dr_definer.c
+++ b/drivers/net/mlx5/hws/mlx5dr_definer.c
@@ -391,6 +391,8 @@ mlx5dr_definer_ptype_l4_set(struct mlx5dr_definer_fc *fc,
l4_type = STE_UDP;
else if (packet_type == (inner ? RTE_PTYPE_INNER_L4_ICMP : RTE_PTYPE_L4_ICMP))
l4_type = STE_ICMP;
+ else if (packet_type == RTE_PTYPE_TUNNEL_ESP)
+ l4_type = STE_ESP;
DR_SET(tag, l4_type, fc->byte_off, fc->bit_off, fc->bit_mask);
}
diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
index d705fe21bbc..b279ddf47c9 100644
--- a/drivers/net/mlx5/meson.build
+++ b/drivers/net/mlx5/meson.build
@@ -42,6 +42,7 @@ sources = files(
'mlx5_vlan.c',
'mlx5_utils.c',
'mlx5_devx.c',
+ 'mlx5_nta_rss.c',
)
if is_linux
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index e41b1e82d7f..997b02c5717 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -2365,6 +2365,10 @@ mlx5_dev_close(struct rte_eth_dev *dev)
claim_zero(mlx5_geneve_tlv_options_destroy(priv->tlv_options, sh->phdev));
priv->tlv_options = NULL;
}
+ if (priv->ptype_rss_groups) {
+ mlx5_ipool_destroy(priv->ptype_rss_groups);
+ priv->ptype_rss_groups = NULL;
+ }
#endif
if (priv->rxq_privs != NULL) {
/* XXX race condition if mlx5_rx_burst() is still running. */
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 159ea10018e..c9a3837bd2b 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -1204,6 +1204,10 @@ struct mlx5_flow_tbl_resource {
#define MLX5_MAX_TABLES_EXTERNAL MLX5_FLOW_TABLE_LEVEL_POLICY
#define MLX5_FLOW_TABLE_HWS_POLICY (MLX5_MAX_TABLES - 10)
#define MLX5_MAX_TABLES_FDB UINT16_MAX
+#define MLX5_FLOW_TABLE_PTYPE_RSS_NUM 1024
+#define MLX5_FLOW_TABLE_PTYPE_RSS_LAST (MLX5_MAX_TABLES - 11)
+#define MLX5_FLOW_TABLE_PTYPE_RSS_BASE \
+(1 + MLX5_FLOW_TABLE_PTYPE_RSS_LAST - MLX5_FLOW_TABLE_PTYPE_RSS_NUM)
#define MLX5_FLOW_TABLE_FACTOR 10
/* ID generation structure. */
@@ -2040,7 +2044,7 @@ struct mlx5_priv {
* Todo: consider to add *_MAX macro.
*/
struct mlx5dr_action *action_nat64[MLX5DR_TABLE_TYPE_MAX][2];
-
+ struct mlx5_indexed_pool *ptype_rss_groups;
#endif
struct rte_eth_dev *shared_host; /* Host device for HW steering. */
RTE_ATOMIC(uint16_t) shared_refcnt; /* HW steering host reference counter. */
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 582d5754cd5..27b746629f3 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -489,6 +489,9 @@ enum mlx5_feature_name {
RTE_ETH_RSS_NONFRAG_IPV4_TCP | RTE_ETH_RSS_NONFRAG_IPV4_UDP | \
RTE_ETH_RSS_NONFRAG_IPV4_OTHER)
+/* Valid L4 RSS types */
+#define MLX5_L4_RSS_TYPES (RTE_ETH_RSS_L4_SRC_ONLY | RTE_ETH_RSS_L4_DST_ONLY)
+
/* IBV hash source bits for IPV4. */
#define MLX5_IPV4_IBV_RX_HASH (IBV_RX_HASH_SRC_IPV4 | IBV_RX_HASH_DST_IPV4)
@@ -1318,6 +1321,8 @@ enum {
#define MLX5_DR_RULE_SIZE 72
+SLIST_HEAD(mlx5_nta_rss_flow_head, rte_flow_hw);
+
/** HWS non template flow data. */
struct rte_flow_nt2hws {
/** BWC rule pointer. */
@@ -1330,7 +1335,10 @@ struct rte_flow_nt2hws {
struct mlx5_flow_dv_modify_hdr_resource *modify_hdr;
/** Encap/decap index. */
uint32_t rix_encap_decap;
-};
+ uint8_t chaned_flow;
+ /** Chain NTA flows. */
+ SLIST_ENTRY(rte_flow_hw) next;
+} __rte_packed;
/** HWS flow struct. */
struct rte_flow_hw {
@@ -3574,7 +3582,6 @@ flow_hw_get_ipv6_route_ext_mod_id_from_ctx(void *dr_ctx, uint8_t idx)
#endif
return 0;
}
-
void
mlx5_indirect_list_handles_release(struct rte_eth_dev *dev);
#ifdef HAVE_MLX5_HWS_SUPPORT
@@ -3587,6 +3594,31 @@ mlx5_destroy_legacy_indirect(struct rte_eth_dev *dev,
void
mlx5_hw_decap_encap_destroy(struct rte_eth_dev *dev,
struct mlx5_indirect_list *reformat);
+int
+flow_hw_create_flow(struct rte_eth_dev *dev, enum mlx5_flow_type type,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item items[],
+ const struct rte_flow_action actions[],
+ uint64_t item_flags, uint64_t action_flags, bool external,
+ struct rte_flow_hw **flow, struct rte_flow_error *error);
+void
+flow_hw_destroy(struct rte_eth_dev *dev, struct rte_flow_hw *flow);
+void
+flow_hw_list_destroy(struct rte_eth_dev *dev, enum mlx5_flow_type type,
+ uintptr_t flow_idx);
+const struct rte_flow_action_rss *
+flow_nta_locate_rss(struct rte_eth_dev *dev,
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error);
+struct rte_flow_hw *
+flow_nta_handle_rss(struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item items[],
+ const struct rte_flow_action actions[],
+ const struct rte_flow_action_rss *rss_conf,
+ uint64_t item_flags, uint64_t action_flags,
+ bool external, enum mlx5_flow_type flow_type,
+ struct rte_flow_error *error);
extern const struct rte_flow_action_raw_decap empty_decap;
extern const struct rte_flow_item_ipv6 nic_ipv6_mask;
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index dd7d1fe8a28..19c7f810285 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -507,7 +507,7 @@ flow_hw_hashfields_set(struct mlx5_flow_rss_desc *rss_desc,
fields |= IBV_RX_HASH_IPSEC_SPI;
if (rss_inner)
fields |= IBV_RX_HASH_INNER;
- *hash_fields = fields;
+ *hash_fields |= fields;
}
/**
@@ -770,9 +770,7 @@ flow_hw_jump_release(struct rte_eth_dev *dev, struct mlx5_hw_jump_action *jump)
static inline struct mlx5_hrxq*
flow_hw_tir_action_register(struct rte_eth_dev *dev,
uint32_t hws_flags,
- const struct rte_flow_action *action,
- uint64_t item_flags,
- bool is_template)
+ const struct rte_flow_action *action)
{
struct mlx5_flow_rss_desc rss_desc = {
.hws_flags = hws_flags,
@@ -795,10 +793,7 @@ flow_hw_tir_action_register(struct rte_eth_dev *dev,
rss_desc.key_len = MLX5_RSS_HASH_KEY_LEN;
rss_desc.types = !rss->types ? RTE_ETH_RSS_IP : rss->types;
rss_desc.symmetric_hash_function = MLX5_RSS_IS_SYMM(rss->func);
- if (is_template)
- flow_hw_hashfields_set(&rss_desc, &rss_desc.hash_fields);
- else
- flow_dv_hashfields_set(item_flags, &rss_desc, &rss_desc.hash_fields);
+ flow_hw_hashfields_set(&rss_desc, &rss_desc.hash_fields);
flow_dv_action_rss_l34_hash_adjust(rss->types,
&rss_desc.hash_fields);
if (rss->level > 1) {
@@ -2541,9 +2536,8 @@ __flow_hw_translate_actions_template(struct rte_eth_dev *dev,
((const struct rte_flow_action_queue *)
masks->conf)->index) {
acts->tir = flow_hw_tir_action_register
- (dev,
- mlx5_hw_act_flag[!!attr->group][type],
- actions, 0, true);
+ (dev, mlx5_hw_act_flag[!!attr->group][type],
+ actions);
if (!acts->tir)
goto err;
acts->rule_acts[dr_pos].action =
@@ -2557,9 +2551,8 @@ __flow_hw_translate_actions_template(struct rte_eth_dev *dev,
case RTE_FLOW_ACTION_TYPE_RSS:
if (actions->conf && masks->conf) {
acts->tir = flow_hw_tir_action_register
- (dev,
- mlx5_hw_act_flag[!!attr->group][type],
- actions, 0, true);
+ (dev, mlx5_hw_act_flag[!!attr->group][type],
+ actions);
if (!acts->tir)
goto err;
acts->rule_acts[dr_pos].action =
@@ -3449,11 +3442,7 @@ flow_hw_actions_construct(struct rte_eth_dev *dev,
break;
case RTE_FLOW_ACTION_TYPE_RSS:
case RTE_FLOW_ACTION_TYPE_QUEUE:
- hrxq = flow_hw_tir_action_register(dev,
- ft_flag,
- action,
- item_flags,
- !flow->nt_rule);
+ hrxq = flow_hw_tir_action_register(dev, ft_flag, action);
if (!hrxq)
goto error;
rule_acts[act_data->action_dst].action = hrxq->action;
@@ -13400,7 +13389,7 @@ static int flow_hw_apply(struct rte_eth_dev *dev __rte_unused,
* @return
* 0 on success, negative errno value otherwise and rte_errno set.
*/
-static int
+int
flow_hw_create_flow(struct rte_eth_dev *dev, enum mlx5_flow_type type,
const struct rte_flow_attr *attr,
const struct rte_flow_item items[],
@@ -13513,7 +13502,7 @@ flow_hw_create_flow(struct rte_eth_dev *dev, enum mlx5_flow_type type,
}
#endif
-static void
+void
flow_hw_destroy(struct rte_eth_dev *dev, struct rte_flow_hw *flow)
{
int ret;
@@ -13568,18 +13557,23 @@ flow_hw_destroy(struct rte_eth_dev *dev, struct rte_flow_hw *flow)
* @param[in] flow_addr
* Address of flow to destroy.
*/
-static void flow_hw_list_destroy(struct rte_eth_dev *dev, enum mlx5_flow_type type,
- uintptr_t flow_addr)
+void
+flow_hw_list_destroy(struct rte_eth_dev *dev, enum mlx5_flow_type type,
+ uintptr_t flow_addr)
{
struct mlx5_priv *priv = dev->data->dev_private;
- /* Get flow via idx */
struct rte_flow_hw *flow = (struct rte_flow_hw *)flow_addr;
+ struct mlx5_nta_rss_flow_head head = { .slh_first = flow };
- if (!flow)
+ if (flow->nt2hws->chaned_flow)
return;
- flow_hw_destroy(dev, flow);
- /* Release flow memory by idx */
- mlx5_ipool_free(priv->flows[type], flow->idx);
+ while (!SLIST_EMPTY(&head)) {
+ flow = SLIST_FIRST(&head);
+ SLIST_REMOVE_HEAD(&head, nt2hws->next);
+ flow_hw_destroy(dev, flow);
+ /* Release flow memory by idx */
+ mlx5_ipool_free(priv->flows[type], flow->idx);
+ }
}
#endif
@@ -13617,6 +13611,19 @@ static uintptr_t flow_hw_list_create(struct rte_eth_dev *dev,
uint64_t item_flags = flow_hw_matching_item_flags_get(items);
uint64_t action_flags = flow_hw_action_flags_get(actions, error);
+
+ if (action_flags & MLX5_FLOW_ACTION_RSS) {
+ const struct rte_flow_action_rss
+ *rss_conf = flow_nta_locate_rss(dev, actions, error);
+ flow = flow_nta_handle_rss(dev, attr, items, actions, rss_conf,
+ item_flags, action_flags, external,
+ type, error);
+ if (flow)
+ return (uintptr_t)flow;
+ if (error->type != RTE_FLOW_ERROR_TYPE_NONE)
+ return 0;
+ /* Fall Through to non-expanded RSS flow */
+ }
/*TODO: Handle split/expand to num_flows. */
/* Create single flow. */
@@ -13776,7 +13783,7 @@ mirror_format_tir(struct rte_eth_dev *dev,
table_type = get_mlx5dr_table_type(&table_cfg->attr.flow_attr);
hws_flags = mlx5_hw_act_flag[MLX5_HW_ACTION_FLAG_NONE_ROOT][table_type];
- tir_ctx = flow_hw_tir_action_register(dev, hws_flags, action, 0, true);
+ tir_ctx = flow_hw_tir_action_register(dev, hws_flags, action);
if (!tir_ctx)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION,
--git a/drivers/net/mlx5/mlx5_nta_rss.c b/drivers/net/mlx5/mlx5_nta_rss.c
new file mode 100644
index 00000000000..1f0085ff069
--- /dev/null
+++ b/drivers/net/mlx5/mlx5_nta_rss.c
@@ -0,0 +1,564 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2024 NVIDIA Corporation & Affiliates
+ */
+
+#include <rte_flow.h>
+
+#include <mlx5_malloc.h>
+#include "mlx5.h"
+#include "mlx5_defs.h"
+#include "mlx5_flow.h"
+#include "mlx5_rx.h"
+#include "rte_common.h"
+
+#ifdef HAVE_MLX5_HWS_SUPPORT
+
+struct mlx5_nta_rss_ctx {
+ struct rte_eth_dev *dev;
+ struct rte_flow_attr *attr;
+ struct rte_flow_item *pattern;
+ struct rte_flow_action *actions;
+ const struct rte_flow_action_rss *rss_conf;
+ struct rte_flow_error *error;
+ struct mlx5_nta_rss_flow_head *head;
+ uint64_t pattern_flags;
+ enum mlx5_flow_type flow_type;
+ bool external;
+};
+
+#define MLX5_RSS_PTYPE_ITEM_INDEX 0
+#ifdef MLX5_RSS_PTYPE_DEBUG
+#define MLX5_RSS_PTYPE_ACTION_INDEX 1
+#else
+#define MLX5_RSS_PTYPE_ACTION_INDEX 0
+#endif
+
+#define MLX5_RSS_PTYPE_ITEMS_NUM (MLX5_RSS_PTYPE_ITEM_INDEX + 2)
+#define MLX5_RSS_PTYPE_ACTIONS_NUM (MLX5_RSS_PTYPE_ACTION_INDEX + 2)
+
+static int
+mlx5_nta_ptype_rss_flow_create(struct mlx5_nta_rss_ctx *ctx,
+ uint32_t ptype, uint64_t rss_type)
+{
+ int ret;
+ struct rte_flow_hw *flow;
+ struct rte_flow_item_ptype *ptype_spec = (void *)(uintptr_t)
+ ctx->pattern[MLX5_RSS_PTYPE_ITEM_INDEX].spec;
+ struct rte_flow_action_rss *rss_conf = (void *)(uintptr_t)
+ ctx->actions[MLX5_RSS_PTYPE_ACTION_INDEX].conf;
+ bool dbg_log = rte_log_can_log(mlx5_logtype, RTE_LOG_DEBUG);
+ uint32_t mark_id = 0;
+#ifdef MLX5_RSS_PTYPE_DEBUG
+ struct rte_flow_action_mark *mark = (void *)(uintptr_t)
+ ctx->actions[MLX5_RSS_PTYPE_ACTION_INDEX - 1].conf;
+
+ /*
+ * Inner L3 and L4 ptype values are too large for 24bit mark
+ */
+ mark->id =
+ ((ptype & (RTE_PTYPE_INNER_L3_MASK | RTE_PTYPE_INNER_L4_MASK)) == ptype) ?
+ ptype >> 20 : ptype;
+ mark_id = mark->id;
+ dbg_log = true;
+#endif
+ ptype_spec->packet_type = ptype;
+ rss_conf->types = rss_type;
+ ret = flow_hw_create_flow(ctx->dev, MLX5_FLOW_TYPE_GEN, ctx->attr,
+ ctx->pattern, ctx->actions,
+ MLX5_FLOW_ITEM_PTYPE, MLX5_FLOW_ACTION_RSS,
+ ctx->external, &flow, ctx->error);
+ if (flow) {
+ SLIST_INSERT_HEAD(ctx->head, flow, nt2hws->next);
+ if (dbg_log) {
+ DRV_LOG(NOTICE,
+ "PTYPE RSS: group %u ptype spec %#x rss types %#lx mark %#x\n",
+ ctx->attr->group, ptype_spec->packet_type,
+ (unsigned long)rss_conf->types, mark_id);
+ }
+ }
+ return ret;
+}
+
+/*
+ * Call conditions:
+ * * Flow pattern did not include outer L3 and L4 items.
+ * * RSS configuration had L3 hash types.
+ */
+static struct rte_flow_hw *
+mlx5_hw_rss_expand_l3(struct mlx5_nta_rss_ctx *rss_ctx)
+{
+ int ret;
+ int ptype_ip4, ptype_ip6;
+ uint64_t rss_types = rte_eth_rss_hf_refine(rss_ctx->rss_conf->types);
+
+ if (rss_ctx->rss_conf->level < 2) {
+ ptype_ip4 = RTE_PTYPE_L3_IPV4;
+ ptype_ip6 = RTE_PTYPE_L3_IPV6;
+ } else {
+ ptype_ip4 = RTE_PTYPE_INNER_L3_IPV4;
+ ptype_ip6 = RTE_PTYPE_INNER_L3_IPV6;
+ }
+ if (rss_types & MLX5_IPV4_LAYER_TYPES) {
+ ret = mlx5_nta_ptype_rss_flow_create
+ (rss_ctx, ptype_ip4, (rss_types & ~MLX5_IPV6_LAYER_TYPES));
+ if (ret)
+ goto error;
+ }
+ if (rss_types & MLX5_IPV6_LAYER_TYPES) {
+ ret = mlx5_nta_ptype_rss_flow_create
+ (rss_ctx, ptype_ip6, rss_types & ~MLX5_IPV4_LAYER_TYPES);
+ if (ret)
+ goto error;
+ }
+ return SLIST_FIRST(rss_ctx->head);
+
+error:
+ flow_hw_list_destroy(rss_ctx->dev, rss_ctx->flow_type,
+ (uintptr_t)SLIST_FIRST(rss_ctx->head));
+ return NULL;
+}
+
+static void
+mlx5_nta_rss_expand_l3_l4(struct mlx5_nta_rss_ctx *rss_ctx,
+ uint64_t rss_types, uint64_t rss_l3_types)
+{
+ int ret;
+ int ptype_l3, ptype_l4_udp, ptype_l4_tcp, ptype_l4_esp = 0;
+ uint64_t rss = rss_types &
+ ~(rss_l3_types == MLX5_IPV4_LAYER_TYPES ?
+ MLX5_IPV6_LAYER_TYPES : MLX5_IPV4_LAYER_TYPES);
+
+
+ if (rss_ctx->rss_conf->level < 2) {
+ ptype_l3 = rss_l3_types == MLX5_IPV4_LAYER_TYPES ?
+ RTE_PTYPE_L3_IPV4 : RTE_PTYPE_L3_IPV6;
+ ptype_l4_esp = RTE_PTYPE_TUNNEL_ESP;
+ ptype_l4_udp = RTE_PTYPE_L4_UDP;
+ ptype_l4_tcp = RTE_PTYPE_L4_TCP;
+ } else {
+ ptype_l3 = rss_l3_types == MLX5_IPV4_LAYER_TYPES ?
+ RTE_PTYPE_INNER_L3_IPV4 : RTE_PTYPE_INNER_L3_IPV6;
+ ptype_l4_udp = RTE_PTYPE_INNER_L4_UDP;
+ ptype_l4_tcp = RTE_PTYPE_INNER_L4_TCP;
+ }
+ if (rss_types & RTE_ETH_RSS_ESP) {
+ ret = mlx5_nta_ptype_rss_flow_create
+ (rss_ctx, ptype_l3 | ptype_l4_esp,
+ rss & ~(RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP));
+ if (ret)
+ goto error;
+ }
+ if (rss_types & RTE_ETH_RSS_UDP) {
+ ret = mlx5_nta_ptype_rss_flow_create(rss_ctx,
+ ptype_l3 | ptype_l4_udp,
+ rss & ~(RTE_ETH_RSS_ESP | RTE_ETH_RSS_TCP));
+ if (ret)
+ goto error;
+ }
+ if (rss_types & RTE_ETH_RSS_TCP) {
+ ret = mlx5_nta_ptype_rss_flow_create(rss_ctx,
+ ptype_l3 | ptype_l4_tcp,
+ rss & ~(RTE_ETH_RSS_ESP | RTE_ETH_RSS_UDP));
+ if (ret)
+ goto error;
+ }
+ return;
+error:
+ flow_hw_list_destroy(rss_ctx->dev, rss_ctx->flow_type,
+ (uintptr_t)SLIST_FIRST(rss_ctx->head));
+}
+
+/*
+ * Call conditions:
+ * * Flow pattern did not include L4 item.
+ * * RSS configuration had L4 hash types.
+ */
+static struct rte_flow_hw *
+mlx5_hw_rss_expand_l4(struct mlx5_nta_rss_ctx *rss_ctx)
+{
+ uint64_t rss_types = rte_eth_rss_hf_refine(rss_ctx->rss_conf->types);
+ uint64_t l3_item = rss_ctx->pattern_flags &
+ (rss_ctx->rss_conf->level < 2 ?
+ MLX5_FLOW_LAYER_OUTER_L3 : MLX5_FLOW_LAYER_INNER_L3);
+
+ if (l3_item) {
+ /*
+ * Outer L3 header was present in the original pattern.
+ * Expand L4 level only.
+ */
+ if (l3_item & MLX5_FLOW_LAYER_L3_IPV4)
+ mlx5_nta_rss_expand_l3_l4(rss_ctx, rss_types, MLX5_IPV4_LAYER_TYPES);
+ else
+ mlx5_nta_rss_expand_l3_l4(rss_ctx, rss_types, MLX5_IPV6_LAYER_TYPES);
+ } else {
+ if (rss_types & (MLX5_IPV4_LAYER_TYPES | MLX5_IPV6_LAYER_TYPES)) {
+ mlx5_hw_rss_expand_l3(rss_ctx);
+ /*
+ * No outer L3 item in application flow pattern.
+ * RSS hash types are L3 and L4.
+ * ** Expand L3 according to RSS configuration and L4.
+ */
+ if (rss_types & MLX5_IPV4_LAYER_TYPES)
+ mlx5_nta_rss_expand_l3_l4(rss_ctx, rss_types,
+ MLX5_IPV4_LAYER_TYPES);
+ if (rss_types & MLX5_IPV6_LAYER_TYPES)
+ mlx5_nta_rss_expand_l3_l4(rss_ctx, rss_types,
+ MLX5_IPV6_LAYER_TYPES);
+ } else {
+ /*
+ * No outer L3 item in application flow pattern,
+ * RSS hash type is L4 only.
+ */
+ mlx5_nta_rss_expand_l3_l4(rss_ctx, rss_types,
+ MLX5_IPV4_LAYER_TYPES);
+ mlx5_nta_rss_expand_l3_l4(rss_ctx, rss_types,
+ MLX5_IPV6_LAYER_TYPES);
+ }
+ }
+ return SLIST_EMPTY(rss_ctx->head) ? NULL : SLIST_FIRST(rss_ctx->head);
+}
+
+static struct mlx5_indexed_pool *
+mlx5_nta_ptype_ipool_create(struct rte_eth_dev *dev)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_indexed_pool_config ipool_cfg = {
+ .size = 1,
+ .trunk_size = 32,
+ .grow_trunk = 5,
+ .grow_shift = 1,
+ .need_lock = 1,
+ .release_mem_en = !!priv->sh->config.reclaim_mode,
+ .malloc = mlx5_malloc,
+ .max_idx = MLX5_FLOW_TABLE_PTYPE_RSS_NUM,
+ .free = mlx5_free,
+ .type = "mlx5_nta_ptype_rss"
+ };
+ return mlx5_ipool_create(&ipool_cfg);
+}
+
+static void
+mlx5_hw_release_rss_ptype_group(struct rte_eth_dev *dev, uint32_t group)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+
+ if (!priv->ptype_rss_groups)
+ return;
+ mlx5_ipool_free(priv->ptype_rss_groups, group);
+}
+
+static uint32_t
+mlx5_hw_get_rss_ptype_group(struct rte_eth_dev *dev)
+{
+ void *obj;
+ uint32_t idx = 0;
+ struct mlx5_priv *priv = dev->data->dev_private;
+
+ if (!priv->ptype_rss_groups) {
+ priv->ptype_rss_groups = mlx5_nta_ptype_ipool_create(dev);
+ if (!priv->ptype_rss_groups) {
+ DRV_LOG(DEBUG, "PTYPE RSS: failed to allocate groups pool");
+ return 0;
+ }
+ }
+ obj = mlx5_ipool_malloc(priv->ptype_rss_groups, &idx);
+ if (!obj) {
+ DRV_LOG(DEBUG, "PTYPE RSS: failed to fetch ptype group from the pool");
+ return 0;
+ }
+ return idx + MLX5_FLOW_TABLE_PTYPE_RSS_BASE;
+}
+
+static struct rte_flow_hw *
+mlx5_hw_rss_ptype_create_miss_flow(struct rte_eth_dev *dev,
+ const struct rte_flow_action_rss *rss_conf,
+ uint32_t ptype_group, bool external,
+ struct rte_flow_error *error)
+{
+ struct rte_flow_hw *flow = NULL;
+ const struct rte_flow_attr miss_attr = {
+ .ingress = 1,
+ .group = ptype_group,
+ .priority = 3
+ };
+ const struct rte_flow_item miss_pattern[2] = {
+ [0] = { .type = RTE_FLOW_ITEM_TYPE_ETH },
+ [1] = { .type = RTE_FLOW_ITEM_TYPE_END }
+ };
+ struct rte_flow_action miss_actions[] = {
+#ifdef MLX5_RSS_PTYPE_DEBUG
+ [MLX5_RSS_PTYPE_ACTION_INDEX - 1] = {
+ .type = RTE_FLOW_ACTION_TYPE_MARK,
+ .conf = &(const struct rte_flow_action_mark){.id = 0xfac}
+ },
+#endif
+ [MLX5_RSS_PTYPE_ACTION_INDEX] = {
+ .type = RTE_FLOW_ACTION_TYPE_RSS,
+ .conf = rss_conf
+ },
+ [MLX5_RSS_PTYPE_ACTION_INDEX + 1] = { .type = RTE_FLOW_ACTION_TYPE_END }
+ };
+
+ flow_hw_create_flow(dev, MLX5_FLOW_TYPE_GEN, &miss_attr,
+ miss_pattern, miss_actions, 0, MLX5_FLOW_ACTION_RSS,
+ external, &flow, error);
+ return flow;
+}
+
+static struct rte_flow_hw *
+mlx5_hw_rss_ptype_create_base_flow(struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_action orig_actions[],
+ uint32_t ptype_group, uint64_t item_flags,
+ uint64_t action_flags, bool external,
+ enum mlx5_flow_type flow_type,
+ struct rte_flow_error *error)
+{
+ int i = 0;
+ struct rte_flow_hw *flow = NULL;
+ struct rte_flow_action actions[MLX5_HW_MAX_ACTS];
+ enum mlx5_indirect_type indirect_type;
+
+ do {
+ switch (orig_actions[i].type) {
+ case RTE_FLOW_ACTION_TYPE_INDIRECT:
+ indirect_type = (typeof(indirect_type))
+ MLX5_INDIRECT_ACTION_TYPE_GET
+ (orig_actions[i].conf);
+ if (indirect_type != MLX5_INDIRECT_ACTION_TYPE_RSS) {
+ actions[i] = orig_actions[i];
+ break;
+ }
+ /* Fall through */
+ case RTE_FLOW_ACTION_TYPE_RSS:
+ actions[i].type = RTE_FLOW_ACTION_TYPE_JUMP;
+ actions[i].conf = &(const struct rte_flow_action_jump) {
+ .group = ptype_group
+ };
+ break;
+ default:
+ actions[i] = orig_actions[i];
+ }
+
+ } while (actions[i++].type != RTE_FLOW_ACTION_TYPE_END);
+ action_flags &= ~MLX5_FLOW_ACTION_RSS;
+ action_flags |= MLX5_FLOW_ACTION_JUMP;
+ flow_hw_create_flow(dev, flow_type, attr, pattern, actions,
+ item_flags, action_flags, external, &flow, error);
+ return flow;
+}
+
+const struct rte_flow_action_rss *
+flow_nta_locate_rss(struct rte_eth_dev *dev,
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error)
+{
+ const struct rte_flow_action *a;
+ const struct rte_flow_action_rss *rss_conf = NULL;
+
+ for (a = actions; a->type != RTE_FLOW_ACTION_TYPE_END; a++) {
+ if (a->type == RTE_FLOW_ACTION_TYPE_RSS) {
+ rss_conf = a->conf;
+ break;
+ }
+ if (a->type == RTE_FLOW_ACTION_TYPE_INDIRECT &&
+ MLX5_INDIRECT_ACTION_TYPE_GET(a->conf) ==
+ MLX5_INDIRECT_ACTION_TYPE_RSS) {
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_shared_action_rss *shared_rss;
+ uint32_t handle = (uint32_t)(uintptr_t)a->conf;
+
+ shared_rss = mlx5_ipool_get
+ (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
+ MLX5_INDIRECT_ACTION_IDX_GET(handle));
+ if (!shared_rss) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION_CONF,
+ a->conf, "invalid shared RSS handle");
+ return NULL;
+ }
+ rss_conf = &shared_rss->origin;
+ break;
+ }
+ }
+ if (a->type == RTE_FLOW_ACTION_TYPE_END) {
+ rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_NONE, NULL, NULL);
+ return NULL;
+ }
+ return rss_conf;
+}
+
+static __rte_always_inline void
+mlx5_nta_rss_init_ptype_ctx(struct mlx5_nta_rss_ctx *rss_ctx,
+ struct rte_eth_dev *dev,
+ struct rte_flow_attr *ptype_attr,
+ struct rte_flow_item *ptype_pattern,
+ struct rte_flow_action *ptype_actions,
+ const struct rte_flow_action_rss *rss_conf,
+ struct mlx5_nta_rss_flow_head *head,
+ struct rte_flow_error *error,
+ uint64_t item_flags,
+ enum mlx5_flow_type flow_type, bool external)
+{
+ rss_ctx->dev = dev;
+ rss_ctx->attr = ptype_attr;
+ rss_ctx->pattern = ptype_pattern;
+ rss_ctx->actions = ptype_actions;
+ rss_ctx->rss_conf = rss_conf;
+ rss_ctx->error = error;
+ rss_ctx->head = head;
+ rss_ctx->pattern_flags = item_flags;
+ rss_ctx->flow_type = flow_type;
+ rss_ctx->external = external;
+}
+
+/*
+ * MLX5 HW hashes IPv4 and IPv6 L3 headers and UDP, TCP, ESP L4 headers.
+ * RSS expansion is required when RSS action was configured to hash
+ * network protocol that was not mentioned in flow pattern.
+ *
+ */
+#define MLX5_PTYPE_RSS_OUTER_MASK (RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L3_IPV6 | \
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_L4_TCP | \
+ RTE_PTYPE_TUNNEL_ESP)
+#define MLX5_PTYPE_RSS_INNER_MASK (RTE_PTYPE_INNER_L3_IPV4 | RTE_PTYPE_INNER_L3_IPV6 | \
+ RTE_PTYPE_INNER_L4_TCP | RTE_PTYPE_INNER_L4_UDP)
+
+struct rte_flow_hw *
+flow_nta_handle_rss(struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item items[],
+ const struct rte_flow_action actions[],
+ const struct rte_flow_action_rss *rss_conf,
+ uint64_t item_flags, uint64_t action_flags,
+ bool external, enum mlx5_flow_type flow_type,
+ struct rte_flow_error *error)
+{
+ struct rte_flow_hw *rss_base = NULL, *rss_next = NULL, *rss_miss = NULL;
+ struct rte_flow_action_rss ptype_rss_conf;
+ struct mlx5_nta_rss_ctx rss_ctx;
+ uint64_t rss_types = rte_eth_rss_hf_refine(rss_conf->types);
+ bool inner_rss = rss_conf->level > 1;
+ bool outer_rss = !inner_rss;
+ bool l3_item = (outer_rss && (item_flags & MLX5_FLOW_LAYER_OUTER_L3)) ||
+ (inner_rss && (item_flags & MLX5_FLOW_LAYER_INNER_L3));
+ bool l4_item = (outer_rss && (item_flags & MLX5_FLOW_LAYER_OUTER_L4)) ||
+ (inner_rss && (item_flags & MLX5_FLOW_LAYER_INNER_L4));
+ bool l3_hash = rss_types & (MLX5_IPV4_LAYER_TYPES | MLX5_IPV6_LAYER_TYPES);
+ bool l4_hash = rss_types & (RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP | RTE_ETH_RSS_ESP);
+ struct mlx5_nta_rss_flow_head expansion_head = SLIST_HEAD_INITIALIZER(0);
+ struct rte_flow_attr ptype_attr = {
+ .ingress = 1
+ };
+ struct rte_flow_item_ptype ptype_spec = { .packet_type = 0 };
+ const struct rte_flow_item_ptype ptype_mask = {
+ .packet_type = outer_rss ?
+ MLX5_PTYPE_RSS_OUTER_MASK : MLX5_PTYPE_RSS_INNER_MASK
+ };
+ struct rte_flow_item ptype_pattern[MLX5_RSS_PTYPE_ITEMS_NUM] = {
+ [MLX5_RSS_PTYPE_ITEM_INDEX] = {
+ .type = RTE_FLOW_ITEM_TYPE_PTYPE,
+ .spec = &ptype_spec,
+ .mask = &ptype_mask
+ },
+ [MLX5_RSS_PTYPE_ITEM_INDEX + 1] = { .type = RTE_FLOW_ITEM_TYPE_END }
+ };
+ struct rte_flow_action ptype_actions[MLX5_RSS_PTYPE_ACTIONS_NUM] = {
+#ifdef MLX5_RSS_PTYPE_DEBUG
+ [MLX5_RSS_PTYPE_ACTION_INDEX - 1] = {
+ .type = RTE_FLOW_ACTION_TYPE_MARK,
+ .conf = &(const struct rte_flow_action_mark) {.id = 101}
+ },
+#endif
+ [MLX5_RSS_PTYPE_ACTION_INDEX] = {
+ .type = RTE_FLOW_ACTION_TYPE_RSS,
+ .conf = &ptype_rss_conf
+ },
+ [MLX5_RSS_PTYPE_ACTION_INDEX + 1] = { .type = RTE_FLOW_ACTION_TYPE_END }
+ };
+
+ if (l4_item) {
+ /*
+ * Original flow pattern extended up to L4 level.
+ * L4 is the maximal expansion level.
+ * Original pattern does not need expansion.
+ */
+ rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_NONE, NULL, NULL);
+ return NULL;
+ }
+ if (!l4_hash) {
+ if (!l3_hash) {
+ /*
+ * RSS action was not configured to hash L3 or L4.
+ * No expansion needed.
+ */
+ rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_NONE, NULL, NULL);
+ return NULL;
+ }
+ if (l3_item) {
+ /*
+ * Original flow pattern extended up to L3 level.
+ * RSS action was not set for L4 hash.
+ * Original pattern does not need expansion.
+ */
+ rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_NONE, NULL, NULL);
+ return NULL;
+ }
+ }
+ /* Create RSS expansions in dedicated PTYPE flow group */
+ ptype_attr.group = mlx5_hw_get_rss_ptype_group(dev);
+ if (!ptype_attr.group) {
+ rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
+ NULL, "cannot get RSS PTYPE group");
+ return NULL;
+ }
+ ptype_rss_conf = *rss_conf;
+ mlx5_nta_rss_init_ptype_ctx(&rss_ctx, dev, &ptype_attr, ptype_pattern,
+ ptype_actions, rss_conf, &expansion_head,
+ error, item_flags, flow_type, external);
+ rss_miss = mlx5_hw_rss_ptype_create_miss_flow(dev, rss_conf, ptype_attr.group,
+ external, error);
+ if (!rss_miss)
+ goto error;
+ if (l4_hash) {
+ rss_next = mlx5_hw_rss_expand_l4(&rss_ctx);
+ if (!rss_next)
+ goto error;
+ } else if (l3_hash) {
+ rss_next = mlx5_hw_rss_expand_l3(&rss_ctx);
+ if (!rss_next)
+ goto error;
+ }
+ rss_base = mlx5_hw_rss_ptype_create_base_flow(dev, attr, items, actions,
+ ptype_attr.group, item_flags,
+ action_flags, external,
+ flow_type, error);
+ if (!rss_base)
+ goto error;
+ SLIST_INSERT_HEAD(&expansion_head, rss_miss, nt2hws->next);
+ SLIST_INSERT_HEAD(&expansion_head, rss_base, nt2hws->next);
+ /**
+ * PMD must return to application a reference to the base flow.
+ * This way RSS expansion could work with counter, meter and other
+ * flow actions.
+ */
+ MLX5_ASSERT(rss_base == SLIST_FIRST(&expansion_head));
+ rss_next = SLIST_NEXT(rss_base, nt2hws->next);
+ while (rss_next) {
+ rss_next->nt2hws->chaned_flow = 1;
+ rss_next = SLIST_NEXT(rss_next, nt2hws->next);
+ }
+ return SLIST_FIRST(&expansion_head);
+
+error:
+ if (rss_miss)
+ flow_hw_list_destroy(dev, flow_type, (uintptr_t)rss_miss);
+ if (rss_next)
+ flow_hw_list_destroy(dev, flow_type, (uintptr_t)rss_next);
+ mlx5_hw_release_rss_ptype_group(dev, ptype_attr.group);
+ return NULL;
+}
+
+#endif
+
--
2.21.0
next prev parent reply other threads:[~2024-06-10 8:51 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-02 10:28 [PATCH 1/6] net/mlx5: update NTA rule pattern and actions flags Maayan Kashani
2024-06-03 8:10 ` [PATCH v2 16/34] " Maayan Kashani
2024-06-03 8:10 ` [PATCH v2 17/34] net/mlx5: support RSS expansion in non-template HWS setup Maayan Kashani
2024-06-03 8:10 ` [PATCH v2 18/34] net/mlx5: support indirect actions in non-template setup Maayan Kashani
2024-06-03 8:10 ` [PATCH v2 19/34] net/mlx5: update ASO resources " Maayan Kashani
2024-06-03 8:10 ` [PATCH v2 20/34] net/mlx5: update HWS ASO actions validation Maayan Kashani
2024-06-03 8:10 ` [PATCH v2 21/34] net/mlx5: support FDB in non-template mode Maayan Kashani
2024-06-03 10:52 ` [PATCH v3 1/6] net/mlx5: update NTA rule pattern and actions flags Maayan Kashani
2024-06-03 10:52 ` [PATCH v3 2/6] net/mlx5: support RSS expansion in non-template HWS setup Maayan Kashani
2024-06-03 10:52 ` [PATCH v3 3/6] net/mlx5: support indirect actions in non-template setup Maayan Kashani
2024-06-03 10:52 ` [PATCH v3 4/6] net/mlx5: update ASO resources " Maayan Kashani
2024-06-03 10:52 ` [PATCH v3 5/6] net/mlx5: update HWS ASO actions validation Maayan Kashani
2024-06-03 10:52 ` [PATCH v3 6/6] net/mlx5: support FDB in non-template mode Maayan Kashani
2024-06-06 10:12 ` [PATCH v4 0/6] non-template pmd advanced Maayan Kashani
2024-06-06 10:12 ` [PATCH v4 1/6] net/mlx5: update NTA rule pattern and actions flags Maayan Kashani
2024-06-06 10:12 ` [PATCH v4 2/6] net/mlx5: support RSS expansion in non-template HWS setup Maayan Kashani
2024-06-06 10:12 ` [PATCH v4 3/6] net/mlx5: support indirect actions in non-template setup Maayan Kashani
2024-06-06 10:12 ` [PATCH v4 4/6] net/mlx5: update ASO resources " Maayan Kashani
2024-06-06 10:12 ` [PATCH v4 5/6] net/mlx5: update HWS ASO actions validation Maayan Kashani
2024-06-06 10:12 ` [PATCH v4 6/6] net/mlx5: support FDB in non-template mode Maayan Kashani
2024-06-10 8:50 ` [PATCH v5 1/6] net/mlx5: update NTA rule pattern and actions flags Maayan Kashani
2024-06-10 8:50 ` Maayan Kashani [this message]
2024-06-10 8:50 ` [PATCH v5 3/6] net/mlx5: support indirect actions in non-template setup Maayan Kashani
2024-06-10 8:50 ` [PATCH v5 4/6] net/mlx5: update ASO resources " Maayan Kashani
2024-06-10 8:50 ` [PATCH v5 5/6] net/mlx5: update HWS ASO actions validation Maayan Kashani
2024-06-10 8:50 ` [PATCH v5 6/6] net/mlx5: support FDB in non-template mode Maayan Kashani
2024-06-11 11:20 ` [PATCH v5 1/6] net/mlx5: update NTA rule pattern and actions flags Raslan Darawsheh
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=20240610085039.146356-2-mkashani@nvidia.com \
--to=mkashani@nvidia.com \
--cc=dev@dpdk.org \
--cc=dsosnowski@nvidia.com \
--cc=getelson@nvidia.com \
--cc=matan@nvidia.com \
--cc=orika@nvidia.com \
--cc=rasland@nvidia.com \
--cc=suanmingm@nvidia.com \
--cc=viacheslavo@nvidia.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).