From: Gregory Etelson <getelson@nvidia.com>
To: <dev@dpdk.org>
Cc: <getelson@nvidia.com>, <mkashani@nvidia.com>,
<rasland@nvidia.com>, "Ori Kam" <orika@nvidia.com>,
Matan Azrad <matan@nvidia.com>,
Viacheslav Ovsiienko <viacheslavo@nvidia.com>,
Suanming Mou <suanmingm@nvidia.com>
Subject: [PATCH 14/30] net/mlx5: reuse reformat and modify header actions in a table
Date: Sun, 29 Oct 2023 18:31:46 +0200 [thread overview]
Message-ID: <20231029163202.216450-14-getelson@nvidia.com> (raw)
In-Reply-To: <20231029163202.216450-1-getelson@nvidia.com>
If application defined several actions templates with non-shared
reformat or modify headers actions AND used these templates to create
a table, HWS could share reformat or modify headers resources,
instead of creating a resource for each action template.
The patch activates HWS code in a way that provides reformat or
modify header resources sharing.
The patch updates modify field and raw encap template actions
validations:
- modify field does not allow empty action template masks.
- raw encap added action template mask validation.
Signed-off-by: Gregory Etelson <getelson@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
---
drivers/net/mlx5/mlx5_flow.h | 8 +-
drivers/net/mlx5/mlx5_flow_dv.c | 3 +-
drivers/net/mlx5/mlx5_flow_hw.c | 583 ++++++++++++++++++++++++--------
3 files changed, 451 insertions(+), 143 deletions(-)
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 64e2fc6f04..ddb3b7b6fd 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -1368,7 +1368,9 @@ struct mlx5_hw_jump_action {
struct mlx5_hw_encap_decap_action {
struct mlx5dr_action *action; /* Action object. */
/* Is header_reformat action shared across flows in table. */
- bool shared;
+ uint32_t shared:1;
+ uint32_t multi_pattern:1;
+ volatile uint32_t *multi_pattern_refcnt;
size_t data_size; /* Action metadata size. */
uint8_t data[]; /* Action data. */
};
@@ -1382,7 +1384,9 @@ struct mlx5_hw_modify_header_action {
/* Modify header action position in action rule table. */
uint16_t pos;
/* Is MODIFY_HEADER action shared across flows in table. */
- bool shared;
+ uint32_t shared:1;
+ uint32_t multi_pattern:1;
+ volatile uint32_t *multi_pattern_refcnt;
/* Amount of modification commands stored in the precompiled buffer. */
uint32_t mhdr_cmds_num;
/* Precompiled modification commands. */
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index bdc8d0076a..84b94a9815 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -4579,7 +4579,8 @@ flow_dv_convert_encap_data(const struct rte_flow_item *items, uint8_t *buf,
(void *)items->type,
"items total size is too big"
" for encap action");
- rte_memcpy((void *)&buf[temp_size], items->spec, len);
+ if (items->spec)
+ rte_memcpy(&buf[temp_size], items->spec, len);
switch (items->type) {
case RTE_FLOW_ITEM_TYPE_ETH:
eth = (struct rte_ether_hdr *)&buf[temp_size];
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index 6fc649d736..84c78ba19c 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -71,6 +71,95 @@ struct mlx5_indlst_legacy {
enum rte_flow_action_type legacy_type;
};
+#define MLX5_CONST_ENCAP_ITEM(encap_type, ptr) \
+(((const struct encap_type *)(ptr))->definition)
+
+struct mlx5_multi_pattern_ctx {
+ union {
+ struct mlx5dr_action_reformat_header reformat_hdr;
+ struct mlx5dr_action_mh_pattern mh_pattern;
+ };
+ union {
+ /* action template auxiliary structures for object destruction */
+ struct mlx5_hw_encap_decap_action *encap;
+ struct mlx5_hw_modify_header_action *mhdr;
+ };
+ /* multi pattern action */
+ struct mlx5dr_rule_action *rule_action;
+};
+
+#define MLX5_MULTIPATTERN_ENCAP_NUM 4
+
+struct mlx5_tbl_multi_pattern_ctx {
+ struct {
+ uint32_t elements_num;
+ struct mlx5_multi_pattern_ctx ctx[MLX5_HW_TBL_MAX_ACTION_TEMPLATE];
+ } reformat[MLX5_MULTIPATTERN_ENCAP_NUM];
+
+ struct {
+ uint32_t elements_num;
+ struct mlx5_multi_pattern_ctx ctx[MLX5_HW_TBL_MAX_ACTION_TEMPLATE];
+ } mh;
+};
+
+#define MLX5_EMPTY_MULTI_PATTERN_CTX {{{0,}},}
+
+static int
+mlx5_tbl_multi_pattern_process(struct rte_eth_dev *dev,
+ struct rte_flow_template_table *tbl,
+ struct mlx5_tbl_multi_pattern_ctx *mpat,
+ struct rte_flow_error *error);
+
+static __rte_always_inline int
+mlx5_multi_pattern_reformat_to_index(enum mlx5dr_action_type type)
+{
+ switch (type) {
+ case MLX5DR_ACTION_TYP_REFORMAT_TNL_L2_TO_L2:
+ return 0;
+ case MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L2:
+ return 1;
+ case MLX5DR_ACTION_TYP_REFORMAT_TNL_L3_TO_L2:
+ return 2;
+ case MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L3:
+ return 3;
+ default:
+ break;
+ }
+ return -1;
+}
+
+static __rte_always_inline enum mlx5dr_action_type
+mlx5_multi_pattern_reformat_index_to_type(uint32_t ix)
+{
+ switch (ix) {
+ case 0:
+ return MLX5DR_ACTION_TYP_REFORMAT_TNL_L2_TO_L2;
+ case 1:
+ return MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L2;
+ case 2:
+ return MLX5DR_ACTION_TYP_REFORMAT_TNL_L3_TO_L2;
+ case 3:
+ return MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L3;
+ default:
+ break;
+ }
+ return MLX5DR_ACTION_TYP_MAX;
+}
+
+static inline enum mlx5dr_table_type
+get_mlx5dr_table_type(const struct rte_flow_attr *attr)
+{
+ enum mlx5dr_table_type type;
+
+ if (attr->transfer)
+ type = MLX5DR_TABLE_TYPE_FDB;
+ else if (attr->egress)
+ type = MLX5DR_TABLE_TYPE_NIC_TX;
+ else
+ type = MLX5DR_TABLE_TYPE_NIC_RX;
+ return type;
+}
+
struct mlx5_mirror_clone {
enum rte_flow_action_type type;
void *action_ctx;
@@ -462,6 +551,34 @@ flow_hw_ct_compile(struct rte_eth_dev *dev,
return 0;
}
+static void
+flow_hw_template_destroy_reformat_action(struct mlx5_hw_encap_decap_action *encap_decap)
+{
+ if (encap_decap->multi_pattern) {
+ uint32_t refcnt = __atomic_sub_fetch(encap_decap->multi_pattern_refcnt,
+ 1, __ATOMIC_RELAXED);
+ if (refcnt)
+ return;
+ mlx5_free((void *)(uintptr_t)encap_decap->multi_pattern_refcnt);
+ }
+ if (encap_decap->action)
+ mlx5dr_action_destroy(encap_decap->action);
+}
+
+static void
+flow_hw_template_destroy_mhdr_action(struct mlx5_hw_modify_header_action *mhdr)
+{
+ if (mhdr->multi_pattern) {
+ uint32_t refcnt = __atomic_sub_fetch(mhdr->multi_pattern_refcnt,
+ 1, __ATOMIC_RELAXED);
+ if (refcnt)
+ return;
+ mlx5_free((void *)(uintptr_t)mhdr->multi_pattern_refcnt);
+ }
+ if (mhdr->action)
+ mlx5dr_action_destroy(mhdr->action);
+}
+
/**
* Destroy DR actions created by action template.
*
@@ -503,14 +620,12 @@ __flow_hw_action_template_destroy(struct rte_eth_dev *dev,
acts->tir = NULL;
}
if (acts->encap_decap) {
- if (acts->encap_decap->action)
- mlx5dr_action_destroy(acts->encap_decap->action);
+ flow_hw_template_destroy_reformat_action(acts->encap_decap);
mlx5_free(acts->encap_decap);
acts->encap_decap = NULL;
}
if (acts->mhdr) {
- if (acts->mhdr->action)
- mlx5dr_action_destroy(acts->mhdr->action);
+ flow_hw_template_destroy_mhdr_action(acts->mhdr);
mlx5_free(acts->mhdr);
acts->mhdr = NULL;
}
@@ -881,8 +996,6 @@ flow_hw_action_modify_field_is_shared(const struct rte_flow_action *action,
if (v->src.field == RTE_FLOW_FIELD_VALUE) {
uint32_t j;
- if (m == NULL)
- return false;
for (j = 0; j < RTE_DIM(m->src.value); ++j) {
/*
* Immediate value is considered to be masked
@@ -1630,6 +1743,137 @@ table_template_translate_indirect_list(struct rte_eth_dev *dev,
return ret;
}
+static int
+mlx5_tbl_translate_reformat(struct mlx5_priv *priv,
+ const struct rte_flow_template_table_attr *table_attr,
+ struct mlx5_hw_actions *acts,
+ struct rte_flow_actions_template *at,
+ const struct rte_flow_item *enc_item,
+ const struct rte_flow_item *enc_item_m,
+ uint8_t *encap_data, uint8_t *encap_data_m,
+ struct mlx5_tbl_multi_pattern_ctx *mp_ctx,
+ size_t data_size, uint16_t reformat_src,
+ enum mlx5dr_action_type refmt_type,
+ struct rte_flow_error *error)
+{
+ int mp_reformat_ix = mlx5_multi_pattern_reformat_to_index(refmt_type);
+ const struct rte_flow_attr *attr = &table_attr->flow_attr;
+ enum mlx5dr_table_type tbl_type = get_mlx5dr_table_type(attr);
+ struct mlx5dr_action_reformat_header hdr;
+ uint8_t buf[MLX5_ENCAP_MAX_LEN];
+ bool shared_rfmt = false;
+ int ret;
+
+ MLX5_ASSERT(at->reformat_off != UINT16_MAX);
+ if (enc_item) {
+ MLX5_ASSERT(!encap_data);
+ ret = flow_dv_convert_encap_data(enc_item, buf, &data_size, error);
+ if (ret)
+ return ret;
+ encap_data = buf;
+ if (enc_item_m)
+ shared_rfmt = true;
+ } else if (encap_data && encap_data_m) {
+ shared_rfmt = true;
+ }
+ acts->encap_decap = mlx5_malloc(MLX5_MEM_ZERO,
+ sizeof(*acts->encap_decap) + data_size,
+ 0, SOCKET_ID_ANY);
+ if (!acts->encap_decap)
+ return rte_flow_error_set(error, ENOMEM,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, "no memory for reformat context");
+ hdr.sz = data_size;
+ hdr.data = encap_data;
+ if (shared_rfmt || mp_reformat_ix < 0) {
+ uint16_t reformat_ix = at->reformat_off;
+ uint32_t flags = mlx5_hw_act_flag[!!attr->group][tbl_type] |
+ MLX5DR_ACTION_FLAG_SHARED;
+
+ acts->encap_decap->action =
+ mlx5dr_action_create_reformat(priv->dr_ctx, refmt_type,
+ 1, &hdr, 0, flags);
+ if (!acts->encap_decap->action)
+ return -rte_errno;
+ acts->rule_acts[reformat_ix].action = acts->encap_decap->action;
+ acts->rule_acts[reformat_ix].reformat.data = acts->encap_decap->data;
+ acts->rule_acts[reformat_ix].reformat.offset = 0;
+ acts->encap_decap->shared = true;
+ } else {
+ uint32_t ix;
+ typeof(mp_ctx->reformat[0]) *reformat_ctx = mp_ctx->reformat +
+ mp_reformat_ix;
+
+ ix = reformat_ctx->elements_num++;
+ reformat_ctx->ctx[ix].reformat_hdr = hdr;
+ reformat_ctx->ctx[ix].rule_action = &acts->rule_acts[at->reformat_off];
+ reformat_ctx->ctx[ix].encap = acts->encap_decap;
+ acts->rule_acts[at->reformat_off].reformat.hdr_idx = ix;
+ acts->encap_decap_pos = at->reformat_off;
+ acts->encap_decap->data_size = data_size;
+ ret = __flow_hw_act_data_encap_append
+ (priv, acts, (at->actions + reformat_src)->type,
+ reformat_src, at->reformat_off, data_size);
+ if (ret)
+ return -rte_errno;
+ }
+ return 0;
+}
+
+static int
+mlx5_tbl_translate_modify_header(struct rte_eth_dev *dev,
+ const struct mlx5_flow_template_table_cfg *cfg,
+ struct mlx5_hw_actions *acts,
+ struct mlx5_tbl_multi_pattern_ctx *mp_ctx,
+ struct mlx5_hw_modify_header_action *mhdr,
+ struct rte_flow_error *error)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+ const struct rte_flow_template_table_attr *table_attr = &cfg->attr;
+ const struct rte_flow_attr *attr = &table_attr->flow_attr;
+ enum mlx5dr_table_type tbl_type = get_mlx5dr_table_type(attr);
+ uint16_t mhdr_ix = mhdr->pos;
+ struct mlx5dr_action_mh_pattern pattern = {
+ .sz = sizeof(struct mlx5_modification_cmd) * mhdr->mhdr_cmds_num
+ };
+
+ if (flow_hw_validate_compiled_modify_field(dev, cfg, mhdr, error)) {
+ __flow_hw_action_template_destroy(dev, acts);
+ return -rte_errno;
+ }
+ acts->mhdr = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*acts->mhdr),
+ 0, SOCKET_ID_ANY);
+ if (!acts->mhdr)
+ return rte_flow_error_set(error, ENOMEM,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, "translate modify_header: no memory for modify header context");
+ rte_memcpy(acts->mhdr, mhdr, sizeof(*mhdr));
+ pattern.data = (__be64 *)acts->mhdr->mhdr_cmds;
+ if (mhdr->shared) {
+ uint32_t flags = mlx5_hw_act_flag[!!attr->group][tbl_type] |
+ MLX5DR_ACTION_FLAG_SHARED;
+
+ acts->mhdr->action = mlx5dr_action_create_modify_header
+ (priv->dr_ctx, 1, &pattern, 0,
+ flags);
+ if (!acts->mhdr->action)
+ return rte_flow_error_set(error, rte_errno,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, "translate modify_header: failed to create DR action");
+ acts->rule_acts[mhdr_ix].action = acts->mhdr->action;
+ } else {
+ typeof(mp_ctx->mh) *mh = &mp_ctx->mh;
+ uint32_t idx = mh->elements_num;
+ struct mlx5_multi_pattern_ctx *mh_ctx = mh->ctx + mh->elements_num++;
+
+ mh_ctx->mh_pattern = pattern;
+ mh_ctx->mhdr = acts->mhdr;
+ mh_ctx->rule_action = &acts->rule_acts[mhdr_ix];
+ acts->rule_acts[mhdr_ix].modify_header.pattern_idx = idx;
+ }
+ return 0;
+}
+
/**
* Translate rte_flow actions to DR action.
*
@@ -1658,6 +1902,7 @@ __flow_hw_actions_translate(struct rte_eth_dev *dev,
const struct mlx5_flow_template_table_cfg *cfg,
struct mlx5_hw_actions *acts,
struct rte_flow_actions_template *at,
+ struct mlx5_tbl_multi_pattern_ctx *mp_ctx,
struct rte_flow_error *error)
{
struct mlx5_priv *priv = dev->data->dev_private;
@@ -1820,32 +2065,26 @@ __flow_hw_actions_translate(struct rte_eth_dev *dev,
break;
case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
MLX5_ASSERT(!reformat_used);
- enc_item = ((const struct rte_flow_action_vxlan_encap *)
- actions->conf)->definition;
+ enc_item = MLX5_CONST_ENCAP_ITEM(rte_flow_action_vxlan_encap,
+ actions->conf);
if (masks->conf)
- enc_item_m = ((const struct rte_flow_action_vxlan_encap *)
- masks->conf)->definition;
+ enc_item_m = MLX5_CONST_ENCAP_ITEM(rte_flow_action_vxlan_encap,
+ masks->conf);
reformat_used = true;
reformat_src = src_pos;
refmt_type = MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L2;
break;
case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
MLX5_ASSERT(!reformat_used);
- enc_item = ((const struct rte_flow_action_nvgre_encap *)
- actions->conf)->definition;
+ enc_item = MLX5_CONST_ENCAP_ITEM(rte_flow_action_nvgre_encap,
+ actions->conf);
if (masks->conf)
- enc_item_m = ((const struct rte_flow_action_nvgre_encap *)
- masks->conf)->definition;
+ enc_item_m = MLX5_CONST_ENCAP_ITEM(rte_flow_action_nvgre_encap,
+ masks->conf);
reformat_used = true;
reformat_src = src_pos;
refmt_type = MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L2;
break;
- case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
- case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
- MLX5_ASSERT(!reformat_used);
- reformat_used = true;
- refmt_type = MLX5DR_ACTION_TYP_REFORMAT_TNL_L2_TO_L2;
- break;
case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
raw_encap_data =
(const struct rte_flow_action_raw_encap *)
@@ -1869,6 +2108,12 @@ __flow_hw_actions_translate(struct rte_eth_dev *dev,
}
reformat_src = src_pos;
break;
+ case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+ case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
+ MLX5_ASSERT(!reformat_used);
+ reformat_used = true;
+ refmt_type = MLX5DR_ACTION_TYP_REFORMAT_TNL_L2_TO_L2;
+ break;
case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
reformat_used = true;
refmt_type = MLX5DR_ACTION_TYP_REFORMAT_TNL_L2_TO_L2;
@@ -2005,83 +2250,20 @@ __flow_hw_actions_translate(struct rte_eth_dev *dev,
}
}
if (mhdr.pos != UINT16_MAX) {
- struct mlx5dr_action_mh_pattern pattern;
- uint32_t flags;
- uint32_t bulk_size;
- size_t mhdr_len;
-
- if (flow_hw_validate_compiled_modify_field(dev, cfg, &mhdr, error)) {
- __flow_hw_action_template_destroy(dev, acts);
- return -rte_errno;
- }
- acts->mhdr = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*acts->mhdr),
- 0, SOCKET_ID_ANY);
- if (!acts->mhdr)
- goto err;
- rte_memcpy(acts->mhdr, &mhdr, sizeof(*acts->mhdr));
- mhdr_len = sizeof(struct mlx5_modification_cmd) * acts->mhdr->mhdr_cmds_num;
- flags = mlx5_hw_act_flag[!!attr->group][type];
- if (acts->mhdr->shared) {
- flags |= MLX5DR_ACTION_FLAG_SHARED;
- bulk_size = 0;
- } else {
- bulk_size = rte_log2_u32(table_attr->nb_flows);
- }
- pattern.data = (__be64 *)acts->mhdr->mhdr_cmds;
- pattern.sz = mhdr_len;
- acts->mhdr->action = mlx5dr_action_create_modify_header
- (priv->dr_ctx, 1, &pattern,
- bulk_size, flags);
- if (!acts->mhdr->action)
+ ret = mlx5_tbl_translate_modify_header(dev, cfg, acts, mp_ctx,
+ &mhdr, error);
+ if (ret)
goto err;
- acts->rule_acts[acts->mhdr->pos].action = acts->mhdr->action;
}
if (reformat_used) {
- struct mlx5dr_action_reformat_header hdr;
- uint8_t buf[MLX5_ENCAP_MAX_LEN];
- bool shared_rfmt = true;
-
- MLX5_ASSERT(at->reformat_off != UINT16_MAX);
- if (enc_item) {
- MLX5_ASSERT(!encap_data);
- if (flow_dv_convert_encap_data(enc_item, buf, &data_size, error))
- goto err;
- encap_data = buf;
- if (!enc_item_m)
- shared_rfmt = false;
- } else if (encap_data && !encap_data_m) {
- shared_rfmt = false;
- }
- acts->encap_decap = mlx5_malloc(MLX5_MEM_ZERO,
- sizeof(*acts->encap_decap) + data_size,
- 0, SOCKET_ID_ANY);
- if (!acts->encap_decap)
- goto err;
- if (data_size) {
- acts->encap_decap->data_size = data_size;
- memcpy(acts->encap_decap->data, encap_data, data_size);
- }
-
- hdr.sz = data_size;
- hdr.data = encap_data;
- acts->encap_decap->action = mlx5dr_action_create_reformat
- (priv->dr_ctx, refmt_type,
- 1, &hdr,
- shared_rfmt ? 0 : rte_log2_u32(table_attr->nb_flows),
- mlx5_hw_act_flag[!!attr->group][type] |
- (shared_rfmt ? MLX5DR_ACTION_FLAG_SHARED : 0));
- if (!acts->encap_decap->action)
- goto err;
- acts->rule_acts[at->reformat_off].action = acts->encap_decap->action;
- acts->rule_acts[at->reformat_off].reformat.data = acts->encap_decap->data;
- if (shared_rfmt)
- acts->rule_acts[at->reformat_off].reformat.offset = 0;
- else if (__flow_hw_act_data_encap_append(priv, acts,
- (at->actions + reformat_src)->type,
- reformat_src, at->reformat_off, data_size))
+ ret = mlx5_tbl_translate_reformat(priv, table_attr, acts, at,
+ enc_item, enc_item_m,
+ encap_data, encap_data_m,
+ mp_ctx, data_size,
+ reformat_src,
+ refmt_type, error);
+ if (ret)
goto err;
- acts->encap_decap->shared = shared_rfmt;
- acts->encap_decap_pos = at->reformat_off;
}
return 0;
err:
@@ -2110,15 +2292,20 @@ flow_hw_actions_translate(struct rte_eth_dev *dev,
struct rte_flow_template_table *tbl,
struct rte_flow_error *error)
{
+ int ret;
uint32_t i;
+ struct mlx5_tbl_multi_pattern_ctx mpat = MLX5_EMPTY_MULTI_PATTERN_CTX;
for (i = 0; i < tbl->nb_action_templates; i++) {
if (__flow_hw_actions_translate(dev, &tbl->cfg,
&tbl->ats[i].acts,
tbl->ats[i].action_template,
- error))
+ &mpat, error))
goto err;
}
+ ret = mlx5_tbl_multi_pattern_process(dev, tbl, &mpat, error);
+ if (ret)
+ goto err;
return 0;
err:
while (i--)
@@ -3627,6 +3814,143 @@ flow_hw_q_flow_flush(struct rte_eth_dev *dev,
return 0;
}
+static int
+mlx5_tbl_multi_pattern_process(struct rte_eth_dev *dev,
+ struct rte_flow_template_table *tbl,
+ struct mlx5_tbl_multi_pattern_ctx *mpat,
+ struct rte_flow_error *error)
+{
+ uint32_t i;
+ struct mlx5_priv *priv = dev->data->dev_private;
+ const struct rte_flow_template_table_attr *table_attr = &tbl->cfg.attr;
+ const struct rte_flow_attr *attr = &table_attr->flow_attr;
+ enum mlx5dr_table_type type = get_mlx5dr_table_type(attr);
+ uint32_t flags = mlx5_hw_act_flag[!!attr->group][type];
+ struct mlx5dr_action *dr_action;
+ uint32_t bulk_size = rte_log2_u32(table_attr->nb_flows);
+
+ for (i = 0; i < MLX5_MULTIPATTERN_ENCAP_NUM; i++) {
+ uint32_t j;
+ uint32_t *reformat_refcnt;
+ typeof(mpat->reformat[0]) *reformat = mpat->reformat + i;
+ struct mlx5dr_action_reformat_header hdr[MLX5_HW_TBL_MAX_ACTION_TEMPLATE];
+ enum mlx5dr_action_type reformat_type =
+ mlx5_multi_pattern_reformat_index_to_type(i);
+
+ if (!reformat->elements_num)
+ continue;
+ for (j = 0; j < reformat->elements_num; j++)
+ hdr[j] = reformat->ctx[j].reformat_hdr;
+ reformat_refcnt = mlx5_malloc(MLX5_MEM_ZERO, sizeof(uint32_t), 0,
+ rte_socket_id());
+ if (!reformat_refcnt)
+ return rte_flow_error_set(error, ENOMEM,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, "failed to allocate multi-pattern encap counter");
+ *reformat_refcnt = reformat->elements_num;
+ dr_action = mlx5dr_action_create_reformat
+ (priv->dr_ctx, reformat_type, reformat->elements_num, hdr,
+ bulk_size, flags);
+ if (!dr_action) {
+ mlx5_free(reformat_refcnt);
+ return rte_flow_error_set(error, rte_errno,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL,
+ "failed to create multi-pattern encap action");
+ }
+ for (j = 0; j < reformat->elements_num; j++) {
+ reformat->ctx[j].rule_action->action = dr_action;
+ reformat->ctx[j].encap->action = dr_action;
+ reformat->ctx[j].encap->multi_pattern = 1;
+ reformat->ctx[j].encap->multi_pattern_refcnt = reformat_refcnt;
+ }
+ }
+ if (mpat->mh.elements_num) {
+ typeof(mpat->mh) *mh = &mpat->mh;
+ struct mlx5dr_action_mh_pattern pattern[MLX5_HW_TBL_MAX_ACTION_TEMPLATE];
+ uint32_t *mh_refcnt = mlx5_malloc(MLX5_MEM_ZERO, sizeof(uint32_t),
+ 0, rte_socket_id());
+
+ if (!mh_refcnt)
+ return rte_flow_error_set(error, ENOMEM,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, "failed to allocate modify header counter");
+ *mh_refcnt = mpat->mh.elements_num;
+ for (i = 0; i < mpat->mh.elements_num; i++)
+ pattern[i] = mh->ctx[i].mh_pattern;
+ dr_action = mlx5dr_action_create_modify_header
+ (priv->dr_ctx, mpat->mh.elements_num, pattern,
+ bulk_size, flags);
+ if (!dr_action) {
+ mlx5_free(mh_refcnt);
+ return rte_flow_error_set(error, rte_errno,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL,
+ "failed to create multi-pattern header modify action");
+ }
+ for (i = 0; i < mpat->mh.elements_num; i++) {
+ mh->ctx[i].rule_action->action = dr_action;
+ mh->ctx[i].mhdr->action = dr_action;
+ mh->ctx[i].mhdr->multi_pattern = 1;
+ mh->ctx[i].mhdr->multi_pattern_refcnt = mh_refcnt;
+ }
+ }
+
+ return 0;
+}
+
+static int
+mlx5_hw_build_template_table(struct rte_eth_dev *dev,
+ uint8_t nb_action_templates,
+ struct rte_flow_actions_template *action_templates[],
+ struct mlx5dr_action_template *at[],
+ struct rte_flow_template_table *tbl,
+ struct rte_flow_error *error)
+{
+ int ret;
+ uint8_t i;
+ struct mlx5_tbl_multi_pattern_ctx mpat = MLX5_EMPTY_MULTI_PATTERN_CTX;
+
+ for (i = 0; i < nb_action_templates; i++) {
+ uint32_t refcnt = __atomic_add_fetch(&action_templates[i]->refcnt, 1,
+ __ATOMIC_RELAXED);
+
+ if (refcnt <= 1) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ &action_templates[i], "invalid AT refcount");
+ goto at_error;
+ }
+ at[i] = action_templates[i]->tmpl;
+ tbl->ats[i].action_template = action_templates[i];
+ LIST_INIT(&tbl->ats[i].acts.act_list);
+ /* do NOT translate table action if `dev` was not started */
+ if (!dev->data->dev_started)
+ continue;
+ ret = __flow_hw_actions_translate(dev, &tbl->cfg,
+ &tbl->ats[i].acts,
+ action_templates[i],
+ &mpat, error);
+ if (ret) {
+ i++;
+ goto at_error;
+ }
+ }
+ tbl->nb_action_templates = nb_action_templates;
+ ret = mlx5_tbl_multi_pattern_process(dev, tbl, &mpat, error);
+ if (ret)
+ goto at_error;
+ return 0;
+
+at_error:
+ while (i--) {
+ __flow_hw_action_template_destroy(dev, &tbl->ats[i].acts);
+ __atomic_sub_fetch(&action_templates[i]->refcnt,
+ 1, __ATOMIC_RELAXED);
+ }
+ return rte_errno;
+}
+
/**
* Create flow table.
*
@@ -3779,29 +4103,12 @@ flow_hw_table_create(struct rte_eth_dev *dev,
}
tbl->nb_item_templates = nb_item_templates;
/* Build the action template. */
- for (i = 0; i < nb_action_templates; i++) {
- uint32_t ret;
-
- ret = __atomic_fetch_add(&action_templates[i]->refcnt, 1,
- __ATOMIC_RELAXED) + 1;
- if (ret <= 1) {
- rte_errno = EINVAL;
- goto at_error;
- }
- at[i] = action_templates[i]->tmpl;
- tbl->ats[i].action_template = action_templates[i];
- LIST_INIT(&tbl->ats[i].acts.act_list);
- if (!port_started)
- continue;
- err = __flow_hw_actions_translate(dev, &tbl->cfg,
- &tbl->ats[i].acts,
- action_templates[i], &sub_error);
- if (err) {
- i++;
- goto at_error;
- }
+ err = mlx5_hw_build_template_table(dev, nb_action_templates,
+ action_templates, at, tbl, &sub_error);
+ if (err) {
+ i = nb_item_templates;
+ goto it_error;
}
- tbl->nb_action_templates = nb_action_templates;
tbl->matcher = mlx5dr_matcher_create
(tbl->grp->tbl, mt, nb_item_templates, at, nb_action_templates, &matcher_attr);
if (!tbl->matcher)
@@ -3815,7 +4122,7 @@ flow_hw_table_create(struct rte_eth_dev *dev,
LIST_INSERT_HEAD(&priv->flow_hw_tbl_ongo, tbl, next);
return tbl;
at_error:
- while (i--) {
+ for (i = 0; i < nb_action_templates; i++) {
__flow_hw_action_template_destroy(dev, &tbl->ats[i].acts);
__atomic_fetch_sub(&action_templates[i]->refcnt,
1, __ATOMIC_RELAXED);
@@ -4058,6 +4365,10 @@ flow_hw_validate_action_modify_field(struct rte_eth_dev *dev,
const struct rte_flow_action_modify_field *mask_conf = mask->conf;
int ret;
+ if (!mask_conf)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, action,
+ "modify_field mask conf is missing");
if (action_conf->operation != mask_conf->operation)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, action,
@@ -4434,16 +4745,25 @@ flow_hw_validate_action_indirect(struct rte_eth_dev *dev,
* 0 on success, a negative errno value otherwise and rte_errno is set.
*/
static int
-flow_hw_validate_action_raw_encap(struct rte_eth_dev *dev __rte_unused,
- const struct rte_flow_action *action,
+flow_hw_validate_action_raw_encap(const struct rte_flow_action *action,
+ const struct rte_flow_action *mask,
struct rte_flow_error *error)
{
- const struct rte_flow_action_raw_encap *raw_encap_data = action->conf;
+ const struct rte_flow_action_raw_encap *mask_conf = mask->conf;
+ const struct rte_flow_action_raw_encap *action_conf = action->conf;
- if (!raw_encap_data || !raw_encap_data->size || !raw_encap_data->data)
+ if (!mask_conf || !mask_conf->size)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, mask,
+ "raw_encap: size must be masked");
+ if (!action_conf || !action_conf->size)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, action,
- "invalid raw_encap_data");
+ "raw_encap: invalid action configuration");
+ if (mask_conf->data && !action_conf->data)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, action,
+ "raw_encap: masked data is missing");
return 0;
}
@@ -4724,7 +5044,7 @@ mlx5_flow_hw_actions_validate(struct rte_eth_dev *dev,
action_flags |= MLX5_FLOW_ACTION_DECAP;
break;
case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
- ret = flow_hw_validate_action_raw_encap(dev, action, error);
+ ret = flow_hw_validate_action_raw_encap(action, mask, error);
if (ret < 0)
return ret;
action_flags |= MLX5_FLOW_ACTION_ENCAP;
@@ -9599,20 +9919,6 @@ mlx5_hw_mirror_destroy(struct rte_eth_dev *dev, struct mlx5_mirror *mirror)
mlx5_free(mirror);
}
-static inline enum mlx5dr_table_type
-get_mlx5dr_table_type(const struct rte_flow_attr *attr)
-{
- enum mlx5dr_table_type type;
-
- if (attr->transfer)
- type = MLX5DR_TABLE_TYPE_FDB;
- else if (attr->egress)
- type = MLX5DR_TABLE_TYPE_NIC_TX;
- else
- type = MLX5DR_TABLE_TYPE_NIC_RX;
- return type;
-}
-
static __rte_always_inline bool
mlx5_mirror_terminal_action(const struct rte_flow_action *action)
{
@@ -9751,9 +10057,6 @@ mirror_format_port(struct rte_eth_dev *dev,
return 0;
}
-#define MLX5_CONST_ENCAP_ITEM(encap_type, ptr) \
-(((const struct encap_type *)(ptr))->definition)
-
static int
hw_mirror_clone_reformat(const struct rte_flow_action *actions,
struct mlx5dr_action_dest_attr *dest_attr,
--
2.39.2
next prev parent reply other threads:[~2023-10-29 16:34 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-29 16:31 [PATCH 01/30] net/mlx5/hws: Definer, add mlx5dr context to definer_conv_data Gregory Etelson
2023-10-29 16:31 ` [PATCH 02/30] net/mlx5: add flow_hw_get_reg_id_from_ctx() Gregory Etelson
2023-10-29 16:31 ` [PATCH 03/30] net/mlx5/hws: Definer, use flow_hw_get_reg_id_from_ctx function call Gregory Etelson
2023-10-29 16:31 ` [PATCH 04/30] net/mlx5: add rte_device parameter to locate HWS registers Gregory Etelson
2023-11-05 20:27 ` Thomas Monjalon
2023-10-29 16:31 ` [PATCH 05/30] net/mlx5: separate port REG_C registers usage Gregory Etelson
2023-10-29 16:31 ` [PATCH 06/30] net/mlx5: merge REG_C aliases Gregory Etelson
2023-10-29 16:31 ` [PATCH 07/30] net/mlx5: initialize HWS flow tags registers in shared dev context Gregory Etelson
2023-10-29 16:31 ` [PATCH 08/30] net/mlx5/hws: adding method to query rule hash Gregory Etelson
2023-10-29 16:31 ` [PATCH 09/30] net/mlx5: add support for calc hash Gregory Etelson
2023-10-29 16:31 ` [PATCH 10/30] net/mlx5: fix insert by index Gregory Etelson
2023-10-29 16:31 ` [PATCH 11/30] net/mlx5: fix query for NIC flow cap Gregory Etelson
2023-10-29 16:31 ` [PATCH 12/30] net/mlx5: add support for more registers Gregory Etelson
2023-10-29 16:31 ` [PATCH 13/30] net/mlx5: add validation support for tags Gregory Etelson
2023-10-29 16:31 ` Gregory Etelson [this message]
2023-10-29 16:31 ` [PATCH 15/30] net/mlx5/hws: check the rule status on rule update Gregory Etelson
2023-10-29 16:31 ` [PATCH 16/30] net/mlx5/hws: support IPsec encryption/decryption action Gregory Etelson
2023-10-29 16:31 ` [PATCH 17/30] net/mlx5/hws: support ASO IPsec action Gregory Etelson
2023-10-29 16:31 ` [PATCH 18/30] net/mlx5/hws: support reformat trailer action Gregory Etelson
2023-10-29 16:31 ` [PATCH 19/30] net/mlx5/hws: support ASO first hit action Gregory Etelson
2023-10-29 16:31 ` [PATCH 20/30] net/mlx5/hws: support insert header action Gregory Etelson
2023-10-29 16:31 ` [PATCH 21/30] net/mlx5/hws: support remove " Gregory Etelson
2023-10-29 16:31 ` [PATCH 22/30] net/mlx5/hws: allow jump to TIR over FDB Gregory Etelson
2023-10-29 16:31 ` [PATCH 23/30] net/mlx5/hws: support dynamic re-parse Gregory Etelson
2023-10-29 16:31 ` [PATCH 24/30] net/mlx5/hws: dynamic re-parse for modify header Gregory Etelson
2023-10-29 16:31 ` [PATCH 25/30] net/mlx5: sample the srv6 last segment Gregory Etelson
2023-10-29 16:31 ` [PATCH 26/30] net/mlx5/hws: fix potential wrong errno value Gregory Etelson
2023-10-29 16:31 ` [PATCH 27/30] net/mlx5/hws: add IPv6 routing extension push remove actions Gregory Etelson
2023-10-29 16:32 ` [PATCH 28/30] net/mlx5/hws: add setter for IPv6 routing push remove Gregory Etelson
2023-10-29 16:32 ` [PATCH 29/30] net/mlx5: implement " Gregory Etelson
2023-10-29 16:32 ` [PATCH 30/30] net/mlx5/hws: add stc reparse support for srv6 push pop Gregory Etelson
2023-11-05 18:49 ` [PATCH 01/30] net/mlx5/hws: Definer, add mlx5dr context to definer_conv_data Thomas Monjalon
2023-11-06 7:32 ` Etelson, Gregory
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=20231029163202.216450-14-getelson@nvidia.com \
--to=getelson@nvidia.com \
--cc=dev@dpdk.org \
--cc=matan@nvidia.com \
--cc=mkashani@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 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.