@@ -2112,6 +2112,10 @@ enum mlx5_ifc_cross_vhca_allowed_objects_types {
MLX5_CROSS_VHCA_ALLOWED_OBJS_RTC = 1 << 0xa,
};
+enum {
+ MLX5_GENERATE_WQE_TYPE_FLOW_UPDATE = 1 << 1,
+};
+
/*
* HCA Capabilities 2
*/
@@ -1928,6 +1928,27 @@ int mlx5dr_definer_get_id(struct mlx5dr_definer *definer)
return definer->obj->id;
}
+static int
+mlx5dr_definer_compare(struct mlx5dr_definer *definer_a,
+ struct mlx5dr_definer *definer_b)
+{
+ int i;
+
+ for (i = 0; i < BYTE_SELECTORS; i++)
+ if (definer_a->byte_selector[i] != definer_b->byte_selector[i])
+ return 1;
+
+ for (i = 0; i < DW_SELECTORS; i++)
+ if (definer_a->dw_selector[i] != definer_b->dw_selector[i])
+ return 1;
+
+ for (i = 0; i < MLX5DR_JUMBO_TAG_SZ; i++)
+ if (definer_a->mask.jumbo[i] != definer_b->mask.jumbo[i])
+ return 1;
+
+ return 0;
+}
+
static int
mlx5dr_definer_calc_layout(struct mlx5dr_matcher *matcher,
struct mlx5dr_definer *match_definer)
@@ -2070,6 +2091,80 @@ mlx5dr_definer_matcher_match_uninit(struct mlx5dr_matcher *matcher)
mlx5dr_definer_free(matcher->mt[i].definer);
}
+static int
+mlx5dr_definer_matcher_hash_init(struct mlx5dr_context *ctx,
+ struct mlx5dr_matcher *matcher)
+{
+ struct mlx5dr_cmd_definer_create_attr def_attr = {0};
+ struct mlx5dr_match_template *mt = matcher->mt;
+ struct ibv_context *ibv_ctx = ctx->ibv_ctx;
+ uint8_t *bit_mask;
+ int i, j;
+
+ for (i = 1; i < matcher->num_of_mt; i++)
+ if (mlx5dr_definer_compare(mt[i].definer, mt[i - 1].definer))
+ matcher->flags |= MLX5DR_MATCHER_FLAGS_HASH_DEFINER;
+
+ if (!(matcher->flags & MLX5DR_MATCHER_FLAGS_HASH_DEFINER))
+ return 0;
+
+ /* Insert by index requires all MT using the same definer */
+ if (matcher->attr.insert_mode == MLX5DR_MATCHER_INSERT_BY_INDEX) {
+ DR_LOG(ERR, "Insert by index not supported with MT combination");
+ rte_errno = EOPNOTSUPP;
+ return rte_errno;
+ }
+
+ matcher->hash_definer = simple_calloc(1, sizeof(*matcher->hash_definer));
+ if (!matcher->hash_definer) {
+ DR_LOG(ERR, "Failed to allocate memory for hash definer");
+ rte_errno = ENOMEM;
+ return rte_errno;
+ }
+
+ /* Calculate intersection between all match templates bitmasks.
+ * We will use mt[0] as reference and intersect it with mt[1..n].
+ * From this we will get:
+ * hash_definer.selectors = mt[0].selecotrs
+ * hash_definer.mask = mt[0].mask & mt[0].mask & ... & mt[n].mask
+ */
+
+ /* Use first definer which should also contain intersection fields */
+ memcpy(matcher->hash_definer, mt->definer, sizeof(struct mlx5dr_definer));
+
+ /* Calculate intersection between first to all match templates bitmasks */
+ for (i = 1; i < matcher->num_of_mt; i++) {
+ bit_mask = (uint8_t *)&mt[i].definer->mask;
+ for (j = 0; j < MLX5DR_JUMBO_TAG_SZ; j++)
+ ((uint8_t *)&matcher->hash_definer->mask)[j] &= bit_mask[j];
+ }
+
+ def_attr.match_mask = matcher->hash_definer->mask.jumbo;
+ def_attr.dw_selector = matcher->hash_definer->dw_selector;
+ def_attr.byte_selector = matcher->hash_definer->byte_selector;
+ matcher->hash_definer->obj = mlx5dr_cmd_definer_create(ibv_ctx, &def_attr);
+ if (!matcher->hash_definer->obj) {
+ DR_LOG(ERR, "Failed to create hash definer");
+ goto free_hash_definer;
+ }
+
+ return 0;
+
+free_hash_definer:
+ simple_free(matcher->hash_definer);
+ return rte_errno;
+}
+
+static void
+mlx5dr_definer_matcher_hash_uninit(struct mlx5dr_matcher *matcher)
+{
+ if (!matcher->hash_definer)
+ return;
+
+ mlx5dr_cmd_destroy_obj(matcher->hash_definer->obj);
+ simple_free(matcher->hash_definer);
+}
+
int mlx5dr_definer_matcher_init(struct mlx5dr_context *ctx,
struct mlx5dr_matcher *matcher)
{
@@ -2093,8 +2188,17 @@ int mlx5dr_definer_matcher_init(struct mlx5dr_context *ctx,
goto free_fc;
}
+ /* Calculate partial hash definer */
+ ret = mlx5dr_definer_matcher_hash_init(ctx, matcher);
+ if (ret) {
+ DR_LOG(ERR, "Failed to init hash definer");
+ goto uninit_match_definer;
+ }
+
return 0;
+uninit_match_definer:
+ mlx5dr_definer_matcher_match_uninit(matcher);
free_fc:
for (i = 0; i < matcher->num_of_mt; i++)
simple_free(matcher->mt[i].fc);
@@ -2109,6 +2213,7 @@ void mlx5dr_definer_matcher_uninit(struct mlx5dr_matcher *matcher)
if (matcher->flags & MLX5DR_MATCHER_FLAGS_COLISION)
return;
+ mlx5dr_definer_matcher_hash_uninit(matcher);
mlx5dr_definer_matcher_match_uninit(matcher);
for (i = 0; i < matcher->num_of_mt; i++)
@@ -337,6 +337,42 @@ static int mlx5dr_matcher_disconnect(struct mlx5dr_matcher *matcher)
return 0;
}
+static bool mlx5dr_matcher_supp_fw_wqe(struct mlx5dr_matcher *matcher)
+{
+ struct mlx5dr_cmd_query_caps *caps = matcher->tbl->ctx->caps;
+
+ if (matcher->flags & MLX5DR_MATCHER_FLAGS_HASH_DEFINER) {
+ if (matcher->hash_definer->type == MLX5DR_DEFINER_TYPE_MATCH &&
+ !IS_BIT_SET(caps->supp_ste_fromat_gen_wqe, MLX5_IFC_RTC_STE_FORMAT_8DW)) {
+ DR_LOG(ERR, "Gen WQE MATCH format not supported");
+ return false;
+ }
+
+ if (matcher->hash_definer->type == MLX5DR_DEFINER_TYPE_JUMBO) {
+ DR_LOG(ERR, "Gen WQE JUMBO format not supported");
+ return false;
+ }
+ }
+
+ if (matcher->attr.insert_mode != MLX5DR_MATCHER_INSERT_BY_HASH ||
+ matcher->attr.distribute_mode != MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) {
+ DR_LOG(ERR, "Gen WQE must be inserted and distribute by hash");
+ return false;
+ }
+
+ if (!(caps->supp_type_gen_wqe & MLX5_GENERATE_WQE_TYPE_FLOW_UPDATE)) {
+ DR_LOG(ERR, "Gen WQE command not supporting GTA");
+ return false;
+ }
+
+ if (!caps->rtc_max_hash_def_gen_wqe) {
+ DR_LOG(ERR, "Hash definer not supported");
+ return false;
+ }
+
+ return true;
+}
+
static void mlx5dr_matcher_set_rtc_attr_sz(struct mlx5dr_matcher *matcher,
struct mlx5dr_cmd_rtc_create_attr *rtc_attr,
enum mlx5dr_matcher_rtc_type rtc_type,
@@ -432,8 +468,16 @@ static int mlx5dr_matcher_create_rtc(struct mlx5dr_matcher *matcher,
if (attr->insert_mode == MLX5DR_MATCHER_INSERT_BY_HASH) {
/* The usual Hash Table */
rtc_attr.update_index_mode = MLX5_IFC_RTC_STE_UPDATE_MODE_BY_HASH;
- /* The first match template is used since all share the same definer */
- rtc_attr.match_definer_0 = mlx5dr_definer_get_id(mt->definer);
+ if (matcher->hash_definer) {
+ /* Specify definer_id_0 is used for hashing */
+ rtc_attr.fw_gen_wqe = true;
+ rtc_attr.num_hash_definer = 1;
+ rtc_attr.match_definer_0 =
+ mlx5dr_definer_get_id(matcher->hash_definer);
+ } else {
+ /* The first mt is used since all share the same definer */
+ rtc_attr.match_definer_0 = mlx5dr_definer_get_id(mt->definer);
+ }
} else if (attr->insert_mode == MLX5DR_MATCHER_INSERT_BY_INDEX) {
rtc_attr.update_index_mode = MLX5_IFC_RTC_STE_UPDATE_MODE_BY_OFFSET;
rtc_attr.num_hash_definer = 1;
@@ -640,6 +684,12 @@ static int mlx5dr_matcher_bind_at(struct mlx5dr_matcher *matcher)
if (!matcher->action_ste.max_stes)
return 0;
+ if (mlx5dr_matcher_req_fw_wqe(matcher)) {
+ DR_LOG(ERR, "FW extended matcher cannot be binded to complex at");
+ rte_errno = ENOTSUP;
+ return rte_errno;
+ }
+
/* Allocate action STE mempool */
pool_attr.table_type = tbl->type;
pool_attr.pool_type = MLX5DR_POOL_TYPE_STE;
@@ -701,13 +751,21 @@ static int mlx5dr_matcher_bind_mt(struct mlx5dr_matcher *matcher)
struct mlx5dr_pool_attr pool_attr = {0};
int ret;
- /* Calculate match definers */
+ /* Calculate match and hash definers */
ret = mlx5dr_definer_matcher_init(ctx, matcher);
if (ret) {
DR_LOG(ERR, "Failed to set matcher templates with match definers");
return ret;
}
+ if (mlx5dr_matcher_req_fw_wqe(matcher) &&
+ !mlx5dr_matcher_supp_fw_wqe(matcher)) {
+ DR_LOG(ERR, "Matcher requires FW WQE which is not supported");
+ rte_errno = ENOTSUP;
+ ret = rte_errno;
+ goto uninit_match_definer;
+ }
+
/* Create an STE pool per matcher*/
pool_attr.table_type = matcher->tbl->type;
pool_attr.pool_type = MLX5DR_POOL_TYPE_STE;
@@ -719,6 +777,7 @@ static int mlx5dr_matcher_bind_mt(struct mlx5dr_matcher *matcher)
matcher->match_ste.pool = mlx5dr_pool_create(ctx, &pool_attr);
if (!matcher->match_ste.pool) {
DR_LOG(ERR, "Failed to allocate matcher STE pool");
+ ret = ENOTSUP;
goto uninit_match_definer;
}
@@ -932,6 +991,7 @@ mlx5dr_matcher_create_col_matcher(struct mlx5dr_matcher *matcher)
col_matcher->at = matcher->at;
col_matcher->num_of_at = matcher->num_of_at;
col_matcher->num_of_mt = matcher->num_of_mt;
+ col_matcher->hash_definer = matcher->hash_definer;
col_matcher->attr.priority = matcher->attr.priority;
col_matcher->flags = matcher->flags;
col_matcher->flags |= MLX5DR_MATCHER_FLAGS_COLISION;
@@ -23,7 +23,8 @@
#define MLX5DR_MATCHER_ASSURED_MAIN_TBL_DEPTH 2
enum mlx5dr_matcher_flags {
- MLX5DR_MATCHER_FLAGS_COLISION = 1 << 0,
+ MLX5DR_MATCHER_FLAGS_HASH_DEFINER = 1 << 0,
+ MLX5DR_MATCHER_FLAGS_COLISION = 1 << 1,
};
struct mlx5dr_match_template {
@@ -69,6 +70,7 @@ struct mlx5dr_matcher {
struct mlx5dr_matcher *col_matcher;
struct mlx5dr_matcher_match_ste match_ste;
struct mlx5dr_matcher_action_ste action_ste;
+ struct mlx5dr_definer *hash_definer;
LIST_ENTRY(mlx5dr_matcher) next;
};
@@ -78,6 +80,12 @@ mlx5dr_matcher_mt_is_jumbo(struct mlx5dr_match_template *mt)
return mlx5dr_definer_is_jumbo(mt->definer);
}
+static inline bool mlx5dr_matcher_req_fw_wqe(struct mlx5dr_matcher *matcher)
+{
+ /* Currently HWS doesn't support hash different from match or range */
+ return unlikely(matcher->flags & MLX5DR_MATCHER_FLAGS_HASH_DEFINER);
+}
+
int mlx5dr_matcher_conv_items_to_prm(uint64_t *match_buf,
struct rte_flow_item *items,
uint8_t *match_criteria,