@@ -130,6 +130,14 @@ enum mlx5dr_matcher_distribute_mode {
MLX5DR_MATCHER_DISTRIBUTE_BY_LINEAR = 0x1,
};
+/* Match mode describes the behavior of the matcher STE's when a packet arrives */
+enum mlx5dr_matcher_match_mode {
+ /* Packet arriving at this matcher STE's will match according it's tag and match definer */
+ MLX5DR_MATCHER_MATCH_MODE_DEFAULT = 0x0,
+ /* Packet arriving at this matcher STE's will always hit and perform the actions */
+ MLX5DR_MATCHER_MATCH_MODE_ALWAYS_HIT = 0x1,
+};
+
enum mlx5dr_rule_hash_calc_mode {
MLX5DR_RULE_HASH_CALC_MODE_RAW,
MLX5DR_RULE_HASH_CALC_MODE_IDX,
@@ -144,11 +152,14 @@ struct mlx5dr_matcher_attr {
enum mlx5dr_matcher_resource_mode mode;
/* Optimize insertion in case packet origin is the same for all rules */
enum mlx5dr_matcher_flow_src optimize_flow_src;
- /* Define the insertion and distribution modes for this matcher */
+ /* Define the insertion, distribution and match modes for this matcher */
enum mlx5dr_matcher_insert_mode insert_mode;
enum mlx5dr_matcher_distribute_mode distribute_mode;
+ enum mlx5dr_matcher_match_mode match_mode;
/* Define whether the created matcher supports resizing into a bigger matcher */
bool resizable;
+ /* This will imply that this matcher is not part of the matchers chain of parent table */
+ bool isolated;
union {
struct {
uint8_t sz_row_log;
@@ -182,7 +182,7 @@ mlx5dr_debug_dump_matcher_attr(FILE *f, struct mlx5dr_matcher *matcher)
struct mlx5dr_matcher_attr *attr = &matcher->attr;
int ret;
- ret = fprintf(f, "%d,0x%" PRIx64 ",%d,%d,%d,%d,%d,%d,%d,%d\n",
+ ret = fprintf(f, "%d,0x%" PRIx64 ",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
MLX5DR_DEBUG_RES_TYPE_MATCHER_ATTR,
(uint64_t)(uintptr_t)matcher,
attr->priority,
@@ -192,7 +192,9 @@ mlx5dr_debug_dump_matcher_attr(FILE *f, struct mlx5dr_matcher *matcher)
attr->optimize_using_rule_idx,
attr->optimize_flow_src,
attr->insert_mode,
- attr->distribute_mode);
+ attr->distribute_mode,
+ attr->match_mode,
+ attr->isolated);
if (ret < 0) {
rte_errno = EINVAL;
return rte_errno;
@@ -377,6 +379,12 @@ static int mlx5dr_debug_dump_table(FILE *f, struct mlx5dr_table *tbl)
return ret;
}
+ LIST_FOREACH(matcher, &tbl->isolated_matchers, next) {
+ ret = mlx5dr_debug_dump_matcher(f, matcher);
+ if (ret)
+ return ret;
+ }
+
return 0;
out_err:
@@ -198,6 +198,18 @@ static int mlx5dr_matcher_connect(struct mlx5dr_matcher *matcher)
struct mlx5dr_matcher *tmp_matcher;
int ret;
+ if (matcher->attr.isolated) {
+ LIST_INSERT_HEAD(&tbl->isolated_matchers, matcher, next);
+ ret = mlx5dr_table_connect_src_ft_to_miss_table(tbl, matcher->end_ft,
+ tbl->default_miss.miss_tbl);
+ if (ret) {
+ DR_LOG(ERR, "Failed to connect the new matcher to the miss_tbl");
+ goto remove_from_list;
+ }
+
+ return 0;
+ }
+
/* Find location in matcher list */
if (LIST_EMPTY(&tbl->head)) {
LIST_INSERT_HEAD(&tbl->head, matcher, next);
@@ -230,7 +242,7 @@ static int mlx5dr_matcher_connect(struct mlx5dr_matcher *matcher)
}
} else {
/* Connect last matcher to next miss_tbl if exists */
- ret = mlx5dr_table_connect_to_miss_table(tbl, tbl->default_miss.miss_tbl);
+ ret = mlx5dr_table_connect_to_miss_table(tbl, tbl->default_miss.miss_tbl, true);
if (ret) {
DR_LOG(ERR, "Failed connect new matcher to miss_tbl");
goto remove_from_list;
@@ -284,6 +296,11 @@ static int mlx5dr_matcher_disconnect(struct mlx5dr_matcher *matcher)
struct mlx5dr_matcher *next;
int ret;
+ if (matcher->attr.isolated) {
+ LIST_REMOVE(matcher, next);
+ return 0;
+ }
+
prev_ft = tbl->ft;
prev_matcher = LIST_FIRST(&tbl->head);
LIST_FOREACH(tmp_matcher, &tbl->head, next) {
@@ -309,7 +326,7 @@ static int mlx5dr_matcher_disconnect(struct mlx5dr_matcher *matcher)
goto matcher_reconnect;
}
} else {
- ret = mlx5dr_table_connect_to_miss_table(tbl, tbl->default_miss.miss_tbl);
+ ret = mlx5dr_table_connect_to_miss_table(tbl, tbl->default_miss.miss_tbl, true);
if (ret) {
DR_LOG(ERR, "Failed to disconnect last matcher");
goto matcher_reconnect;
@@ -518,14 +535,17 @@ static int mlx5dr_matcher_create_rtc(struct mlx5dr_matcher *matcher,
}
} 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;
if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) {
/* Hash Split Table */
+ if (mlx5dr_matcher_is_always_hit(matcher))
+ rtc_attr.num_hash_definer = 1;
+
rtc_attr.access_index_mode = MLX5_IFC_RTC_STE_ACCESS_MODE_BY_HASH;
rtc_attr.match_definer_0 = mlx5dr_definer_get_id(mt->definer);
} else if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_LINEAR) {
/* Linear Lookup Table */
+ rtc_attr.num_hash_definer = 1;
rtc_attr.access_index_mode = MLX5_IFC_RTC_STE_ACCESS_MODE_LINEAR;
rtc_attr.match_definer_0 = ctx->caps->linear_match_definer;
}
@@ -973,10 +993,17 @@ mlx5dr_matcher_validate_insert_mode(struct mlx5dr_cmd_query_caps *caps,
if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) {
/* Hash Split Table */
- if (!caps->rtc_hash_split_table) {
+ if (attr->match_mode == MLX5DR_MATCHER_MATCH_MODE_ALWAYS_HIT &&
+ !caps->rtc_hash_split_table) {
DR_LOG(ERR, "FW doesn't support insert by index and hash distribute");
goto not_supported;
}
+
+ if (attr->match_mode == MLX5DR_MATCHER_MATCH_MODE_DEFAULT &&
+ !attr->isolated) {
+ DR_LOG(ERR, "STE array matcher supported only as an isolated matcher");
+ goto not_supported;
+ }
} else if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_LINEAR) {
/* Linear Lookup Table */
if (!caps->rtc_linear_lookup_table ||
@@ -991,6 +1018,12 @@ mlx5dr_matcher_validate_insert_mode(struct mlx5dr_cmd_query_caps *caps,
MLX5_IFC_RTC_LINEAR_LOOKUP_TBL_LOG_MAX);
goto not_supported;
}
+
+ if (attr->match_mode != MLX5DR_MATCHER_MATCH_MODE_ALWAYS_HIT) {
+ DR_LOG(ERR, "Linear lookup tables will always hit, given match mode is not supported %d\n",
+ attr->match_mode);
+ goto not_supported;
+ }
} else {
DR_LOG(ERR, "Matcher has unsupported distribute mode");
goto not_supported;
@@ -1032,6 +1065,11 @@ mlx5dr_matcher_process_attr(struct mlx5dr_cmd_query_caps *caps,
DR_LOG(ERR, "Root matcher does not support resizing");
goto not_supported;
}
+ if (attr->isolated) {
+ DR_LOG(ERR, "Root matcher can not be isolated");
+ goto not_supported;
+ }
+
return 0;
}
@@ -1045,6 +1083,18 @@ mlx5dr_matcher_process_attr(struct mlx5dr_cmd_query_caps *caps,
attr->insert_mode == MLX5DR_MATCHER_INSERT_BY_HASH)
attr->table.sz_col_log = mlx5dr_matcher_rules_to_tbl_depth(attr->rule.num_log);
+ if (attr->isolated) {
+ if (attr->insert_mode != MLX5DR_MATCHER_INSERT_BY_INDEX ||
+ attr->distribute_mode != MLX5DR_MATCHER_DISTRIBUTE_BY_HASH ||
+ attr->match_mode != MLX5DR_MATCHER_MATCH_MODE_DEFAULT) {
+ DR_LOG(ERR, "Isolated matcher only supported for STE array matcher");
+ goto not_supported;
+ }
+
+ /* We reach here only in case of STE array */
+ matcher->flags |= MLX5DR_MATCHER_FLAGS_STE_ARRAY;
+ }
+
matcher->flags |= attr->resizable ? MLX5DR_MATCHER_FLAGS_RESIZABLE : 0;
return mlx5dr_matcher_check_attr_sz(caps, attr);
@@ -28,6 +28,7 @@ enum mlx5dr_matcher_flags {
MLX5DR_MATCHER_FLAGS_COLLISION = 1 << 2,
MLX5DR_MATCHER_FLAGS_RESIZABLE = 1 << 3,
MLX5DR_MATCHER_FLAGS_COMPARE = 1 << 4,
+ MLX5DR_MATCHER_FLAGS_STE_ARRAY = 1 << 5,
};
struct mlx5dr_match_template {
@@ -146,6 +147,11 @@ static inline bool mlx5dr_matcher_is_insert_by_idx(struct mlx5dr_matcher *matche
return matcher->attr.insert_mode == MLX5DR_MATCHER_INSERT_BY_INDEX;
}
+static inline bool mlx5dr_matcher_is_always_hit(struct mlx5dr_matcher *matcher)
+{
+ return matcher->attr.match_mode == MLX5DR_MATCHER_MATCH_MODE_ALWAYS_HIT;
+}
+
int mlx5dr_matcher_free_rtc_pointing(struct mlx5dr_context *ctx,
uint32_t fw_ft_type,
enum mlx5dr_table_type type,
@@ -539,7 +539,7 @@ static int mlx5dr_rule_create_hws(struct mlx5dr_rule *rule,
* will always match and perform the specified actions, which
* makes the tag irrelevant.
*/
- if (likely(!mlx5dr_matcher_is_insert_by_idx(matcher) && !is_update))
+ if (likely(!mlx5dr_matcher_is_always_hit(matcher) && !is_update))
mlx5dr_definer_create_tag(items, mt->fc, mt->fc_sz,
(uint8_t *)dep_wqe->wqe_data.action);
else if (unlikely(is_update))
@@ -429,7 +429,7 @@ int mlx5dr_table_destroy(struct mlx5dr_table *tbl)
{
struct mlx5dr_context *ctx = tbl->ctx;
pthread_spin_lock(&ctx->ctrl_lock);
- if (!LIST_EMPTY(&tbl->head)) {
+ if (!LIST_EMPTY(&tbl->head) || !LIST_EMPTY(&tbl->isolated_matchers)) {
DR_LOG(ERR, "Cannot destroy table containing matchers");
rte_errno = EBUSY;
goto unlock_err;
@@ -531,7 +531,7 @@ int mlx5dr_table_update_connected_miss_tables(struct mlx5dr_table *dst_tbl)
return 0;
LIST_FOREACH(src_tbl, &dst_tbl->default_miss.head, default_miss.next) {
- ret = mlx5dr_table_connect_to_miss_table(src_tbl, dst_tbl);
+ ret = mlx5dr_table_connect_to_miss_table(src_tbl, dst_tbl, false);
if (ret) {
DR_LOG(ERR, "Failed to update source miss table, unexpected behavior");
return ret;
@@ -541,34 +541,32 @@ int mlx5dr_table_update_connected_miss_tables(struct mlx5dr_table *dst_tbl)
return 0;
}
-int mlx5dr_table_connect_to_miss_table(struct mlx5dr_table *src_tbl,
- struct mlx5dr_table *dst_tbl)
+int mlx5dr_table_connect_src_ft_to_miss_table(struct mlx5dr_table *src_tbl,
+ struct mlx5dr_devx_obj *ft,
+ struct mlx5dr_table *dst_tbl)
{
- struct mlx5dr_devx_obj *last_ft;
struct mlx5dr_matcher *matcher;
int ret;
- last_ft = mlx5dr_table_get_last_ft(src_tbl);
-
if (dst_tbl) {
if (LIST_EMPTY(&dst_tbl->head)) {
- /* Connect src_tbl last_ft to dst_tbl start anchor */
- ret = mlx5dr_table_ft_set_next_ft(last_ft,
+ /* Connect src_tbl ft to dst_tbl start anchor */
+ ret = mlx5dr_table_ft_set_next_ft(ft,
src_tbl->fw_ft_type,
dst_tbl->ft->id);
if (ret)
return ret;
- /* Reset last_ft RTC to default RTC */
- ret = mlx5dr_table_ft_set_next_rtc(last_ft,
+ /* Reset ft RTC to default RTC */
+ ret = mlx5dr_table_ft_set_next_rtc(ft,
src_tbl->fw_ft_type,
NULL, NULL);
if (ret)
return ret;
} else {
- /* Connect src_tbl last_ft to first matcher RTC */
+ /* Connect src_tbl ft to first matcher RTC */
matcher = LIST_FIRST(&dst_tbl->head);
- ret = mlx5dr_table_ft_set_next_rtc(last_ft,
+ ret = mlx5dr_table_ft_set_next_rtc(ft,
src_tbl->fw_ft_type,
matcher->match_ste.rtc_0,
matcher->match_ste.rtc_1);
@@ -576,24 +574,51 @@ int mlx5dr_table_connect_to_miss_table(struct mlx5dr_table *src_tbl,
return ret;
/* Reset next miss FT to default */
- ret = mlx5dr_table_ft_set_default_next_ft(src_tbl, last_ft);
+ ret = mlx5dr_table_ft_set_default_next_ft(src_tbl, ft);
if (ret)
return ret;
}
} else {
/* Reset next miss FT to default */
- ret = mlx5dr_table_ft_set_default_next_ft(src_tbl, last_ft);
+ ret = mlx5dr_table_ft_set_default_next_ft(src_tbl, ft);
if (ret)
return ret;
- /* Reset last_ft RTC to default RTC */
- ret = mlx5dr_table_ft_set_next_rtc(last_ft,
+ /* Reset ft RTC to default RTC */
+ ret = mlx5dr_table_ft_set_next_rtc(ft,
src_tbl->fw_ft_type,
NULL, NULL);
if (ret)
return ret;
}
+ return 0;
+}
+
+int mlx5dr_table_connect_to_miss_table(struct mlx5dr_table *src_tbl,
+ struct mlx5dr_table *dst_tbl,
+ bool only_update_last_ft)
+{
+ struct mlx5dr_matcher *matcher;
+ struct mlx5dr_devx_obj *ft;
+ int ret;
+
+ /* Connect last FT in the src_tbl matchers chain */
+ ft = mlx5dr_table_get_last_ft(src_tbl);
+ ret = mlx5dr_table_connect_src_ft_to_miss_table(src_tbl, ft, dst_tbl);
+ if (ret)
+ return ret;
+
+ if (!only_update_last_ft) {
+ /* Connect isolated matchers FT */
+ LIST_FOREACH(matcher, &src_tbl->isolated_matchers, next) {
+ ft = matcher->end_ft;
+ ret = mlx5dr_table_connect_src_ft_to_miss_table(src_tbl, ft, dst_tbl);
+ if (ret)
+ return ret;
+ }
+ }
+
src_tbl->default_miss.miss_tbl = dst_tbl;
return 0;
@@ -633,7 +658,7 @@ int mlx5dr_table_set_default_miss(struct mlx5dr_table *tbl,
pthread_spin_lock(&ctx->ctrl_lock);
old_miss_tbl = tbl->default_miss.miss_tbl;
- ret = mlx5dr_table_connect_to_miss_table(tbl, miss_tbl);
+ ret = mlx5dr_table_connect_to_miss_table(tbl, miss_tbl, false);
if (ret)
goto out;
@@ -23,6 +23,7 @@ struct mlx5dr_table {
uint32_t fw_ft_type;
uint32_t level;
LIST_HEAD(matcher_head, mlx5dr_matcher) head;
+ LIST_HEAD(isolated_matchers_head, mlx5dr_matcher) isolated_matchers;
LIST_ENTRY(mlx5dr_table) next;
struct mlx5dr_default_miss default_miss;
};
@@ -54,7 +55,8 @@ void mlx5dr_table_destroy_default_ft(struct mlx5dr_table *tbl,
struct mlx5dr_devx_obj *ft_obj);
int mlx5dr_table_connect_to_miss_table(struct mlx5dr_table *src_tbl,
- struct mlx5dr_table *dst_tbl);
+ struct mlx5dr_table *dst_tbl,
+ bool only_update_last_ft);
int mlx5dr_table_update_connected_miss_tables(struct mlx5dr_table *dst_tbl);
@@ -66,4 +68,8 @@ int mlx5dr_table_ft_set_next_rtc(struct mlx5dr_devx_obj *ft,
struct mlx5dr_devx_obj *rtc_0,
struct mlx5dr_devx_obj *rtc_1);
+int mlx5dr_table_connect_src_ft_to_miss_table(struct mlx5dr_table *src_tbl,
+ struct mlx5dr_devx_obj *ft,
+ struct mlx5dr_table *dst_tbl);
+
#endif /* MLX5DR_TABLE_H_ */
@@ -5157,6 +5157,8 @@ flow_hw_table_create(struct rte_eth_dev *dev,
matcher_attr.optimize_using_rule_idx = true;
matcher_attr.mode = MLX5DR_MATCHER_RESOURCE_MODE_RULE;
matcher_attr.insert_mode = flow_hw_matcher_insert_mode_get(attr->insertion_type);
+ if (matcher_attr.insert_mode == MLX5DR_MATCHER_INSERT_BY_INDEX)
+ matcher_attr.match_mode = MLX5DR_MATCHER_MATCH_MODE_ALWAYS_HIT;
if (attr->hash_func == RTE_FLOW_TABLE_HASH_FUNC_CRC16) {
DRV_LOG(ERR, "16-bit checksum hash type is not supported");
rte_errno = ENOTSUP;