From: Hamdan Igbaria <hamd...@nvidia.com>

introduce STE array matcher, where this matcher can only
be isolated under a parent table and not chained to the
table matchers chain.

Signed-off-by: Hamdan Igbaria <hamd...@nvidia.com>
---
 drivers/net/mlx5/hws/mlx5dr.h         | 13 +++++-
 drivers/net/mlx5/hws/mlx5dr_debug.c   | 12 +++++-
 drivers/net/mlx5/hws/mlx5dr_matcher.c | 58 +++++++++++++++++++++++--
 drivers/net/mlx5/hws/mlx5dr_matcher.h |  6 +++
 drivers/net/mlx5/hws/mlx5dr_rule.c    |  2 +-
 drivers/net/mlx5/hws/mlx5dr_table.c   | 61 +++++++++++++++++++--------
 drivers/net/mlx5/hws/mlx5dr_table.h   |  8 +++-
 drivers/net/mlx5/mlx5_flow_hw.c       |  2 +
 8 files changed, 135 insertions(+), 27 deletions(-)

diff --git a/drivers/net/mlx5/hws/mlx5dr.h b/drivers/net/mlx5/hws/mlx5dr.h
index 0fe39e9c76..8a1a389a3f 100644
--- a/drivers/net/mlx5/hws/mlx5dr.h
+++ b/drivers/net/mlx5/hws/mlx5dr.h
@@ -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;
diff --git a/drivers/net/mlx5/hws/mlx5dr_debug.c 
b/drivers/net/mlx5/hws/mlx5dr_debug.c
index 741a725842..f15ad96598 100644
--- a/drivers/net/mlx5/hws/mlx5dr_debug.c
+++ b/drivers/net/mlx5/hws/mlx5dr_debug.c
@@ -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:
diff --git a/drivers/net/mlx5/hws/mlx5dr_matcher.c 
b/drivers/net/mlx5/hws/mlx5dr_matcher.c
index dfa2cd435c..54460cc82b 100644
--- a/drivers/net/mlx5/hws/mlx5dr_matcher.c
+++ b/drivers/net/mlx5/hws/mlx5dr_matcher.c
@@ -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);
diff --git a/drivers/net/mlx5/hws/mlx5dr_matcher.h 
b/drivers/net/mlx5/hws/mlx5dr_matcher.h
index ca6a5298d9..ef42b7de6b 100644
--- a/drivers/net/mlx5/hws/mlx5dr_matcher.h
+++ b/drivers/net/mlx5/hws/mlx5dr_matcher.h
@@ -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,
diff --git a/drivers/net/mlx5/hws/mlx5dr_rule.c 
b/drivers/net/mlx5/hws/mlx5dr_rule.c
index 5d66d81ea5..519328ccf3 100644
--- a/drivers/net/mlx5/hws/mlx5dr_rule.c
+++ b/drivers/net/mlx5/hws/mlx5dr_rule.c
@@ -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))
diff --git a/drivers/net/mlx5/hws/mlx5dr_table.c 
b/drivers/net/mlx5/hws/mlx5dr_table.c
index ab73017ade..634b484a94 100644
--- a/drivers/net/mlx5/hws/mlx5dr_table.c
+++ b/drivers/net/mlx5/hws/mlx5dr_table.c
@@ -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;
 
diff --git a/drivers/net/mlx5/hws/mlx5dr_table.h 
b/drivers/net/mlx5/hws/mlx5dr_table.h
index b2fbb47416..32f2574a97 100644
--- a/drivers/net/mlx5/hws/mlx5dr_table.h
+++ b/drivers/net/mlx5/hws/mlx5dr_table.h
@@ -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_ */
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index c5ddd1d404..b9807f347d 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -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;
-- 
2.18.2

Reply via email to