Add support for matching metadata in HWS ingress rules.
It using REG_B matching which is supported for each device supports HWS.

Signed-off-by: Michael Baum <michae...@nvidia.com>
---

v2:
 - Rebase.
 - Fix compilation issue.
 - Update documentation.

 doc/guides/nics/mlx5.rst              |   3 +-
 drivers/net/mlx5/hws/mlx5dr.h         |   1 +
 drivers/net/mlx5/hws/mlx5dr_definer.c |  32 ++++---
 drivers/net/mlx5/mlx5_flow.h          | 122 ++++++++++++++------------
 drivers/net/mlx5/mlx5_flow_hw.c       |  10 +--
 5 files changed, 92 insertions(+), 76 deletions(-)

diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index c0294f268d..aea9d95cff 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -1301,7 +1301,8 @@ for an additional list of options shared with other mlx5 
drivers.
     ``META`` related actions and items operate only within NIC Tx and
     NIC Rx steering domains, no ``MARK`` and ``META`` information crosses
     the domain boundaries. The ``MARK`` item is 24 bits wide, the ``META``
-    item is 32 bits wide and match supported on egress only.
+    item is 32 bits wide and match supported on egress only when
+    ``dv_flow_en`` = 1.
 
   - 1, this engages extensive metadata mode, the ``MARK`` and ``META``
     related actions and items operate within all supported steering domains,
diff --git a/drivers/net/mlx5/hws/mlx5dr.h b/drivers/net/mlx5/hws/mlx5dr.h
index 8441ae97e9..59fd61e24b 100644
--- a/drivers/net/mlx5/hws/mlx5dr.h
+++ b/drivers/net/mlx5/hws/mlx5dr.h
@@ -18,6 +18,7 @@ enum mlx5dr_table_type {
        MLX5DR_TABLE_TYPE_NIC_TX,
        MLX5DR_TABLE_TYPE_FDB,
        MLX5DR_TABLE_TYPE_MAX,
+       MLX5DR_TABLE_TYPE_DONTCARE = MLX5DR_TABLE_TYPE_MAX,
 };
 
 enum mlx5dr_matcher_resource_mode {
diff --git a/drivers/net/mlx5/hws/mlx5dr_definer.c 
b/drivers/net/mlx5/hws/mlx5dr_definer.c
index 0e15aafb8a..35a2ed2048 100644
--- a/drivers/net/mlx5/hws/mlx5dr_definer.c
+++ b/drivers/net/mlx5/hws/mlx5dr_definer.c
@@ -1745,6 +1745,7 @@ mlx5dr_definer_conv_item_tag(struct 
mlx5dr_definer_conv_data *cd,
        if (item->type == RTE_FLOW_ITEM_TYPE_TAG)
                reg = flow_hw_get_reg_id_from_ctx(cd->ctx,
                                                  RTE_FLOW_ITEM_TYPE_TAG,
+                                                 MLX5DR_TABLE_TYPE_DONTCARE,
                                                  v->index);
        else
                reg = (int)v->index;
@@ -1805,9 +1806,10 @@ mlx5dr_definer_conv_item_quota(struct 
mlx5dr_definer_conv_data *cd,
                               __rte_unused struct rte_flow_item *item,
                               int item_idx)
 {
-       int mtr_reg =
-       flow_hw_get_reg_id_from_ctx(cd->ctx, RTE_FLOW_ITEM_TYPE_METER_COLOR,
-                                   0);
+       int mtr_reg = flow_hw_get_reg_id_from_ctx(cd->ctx,
+                                                 
RTE_FLOW_ITEM_TYPE_METER_COLOR,
+                                                 MLX5DR_TABLE_TYPE_DONTCARE,
+                                                 0);
        struct mlx5dr_definer_fc *fc;
 
        if (mtr_reg < 0) {
@@ -1826,6 +1828,7 @@ mlx5dr_definer_conv_item_quota(struct 
mlx5dr_definer_conv_data *cd,
 
 static int
 mlx5dr_definer_conv_item_metadata(struct mlx5dr_definer_conv_data *cd,
+                                 enum mlx5dr_table_type table_domain_type,
                                  struct rte_flow_item *item,
                                  int item_idx)
 {
@@ -1837,7 +1840,8 @@ mlx5dr_definer_conv_item_metadata(struct 
mlx5dr_definer_conv_data *cd,
        if (!m)
                return 0;
 
-       reg = flow_hw_get_reg_id_from_ctx(cd->ctx, RTE_FLOW_ITEM_TYPE_META, -1);
+       reg = flow_hw_get_reg_id_from_ctx(cd->ctx, RTE_FLOW_ITEM_TYPE_META,
+                                         table_domain_type, -1);
        if (reg <= 0) {
                DR_LOG(ERR, "Invalid register for item metadata");
                rte_errno = EINVAL;
@@ -2144,8 +2148,9 @@ mlx5dr_definer_conv_item_conntrack(struct 
mlx5dr_definer_conv_data *cd,
        if (!m)
                return 0;
 
-       reg = flow_hw_get_reg_id_from_ctx(cd->ctx, RTE_FLOW_ITEM_TYPE_CONNTRACK,
-                                         -1);
+       reg = flow_hw_get_reg_id_from_ctx(cd->ctx,
+                                         RTE_FLOW_ITEM_TYPE_CONNTRACK,
+                                         MLX5DR_TABLE_TYPE_DONTCARE, -1);
        if (reg <= 0) {
                DR_LOG(ERR, "Invalid register for item conntrack");
                rte_errno = EINVAL;
@@ -2287,7 +2292,8 @@ mlx5dr_definer_conv_item_meter_color(struct 
mlx5dr_definer_conv_data *cd,
                return 0;
 
        reg = flow_hw_get_reg_id_from_ctx(cd->ctx,
-                                         RTE_FLOW_ITEM_TYPE_METER_COLOR, 0);
+                                         RTE_FLOW_ITEM_TYPE_METER_COLOR,
+                                         MLX5DR_TABLE_TYPE_DONTCARE, 0);
        MLX5_ASSERT(reg > 0);
 
        fc = mlx5dr_definer_get_register_fc(cd, reg);
@@ -2882,6 +2888,7 @@ mlx5dr_definer_conv_item_compare_field(const struct 
rte_flow_field_data *f,
                                       const struct rte_flow_field_data 
*other_f,
                                       struct mlx5dr_definer_conv_data *cd,
                                       int item_idx,
+                                      enum mlx5dr_table_type table_domain_type,
                                       enum mlx5dr_definer_compare_dw_selectors 
dw_offset)
 {
        struct mlx5dr_definer_fc *fc = NULL;
@@ -2896,7 +2903,8 @@ mlx5dr_definer_conv_item_compare_field(const struct 
rte_flow_field_data *f,
        switch (f->field) {
        case RTE_FLOW_FIELD_META:
                reg = flow_hw_get_reg_id_from_ctx(cd->ctx,
-                                                 RTE_FLOW_ITEM_TYPE_META, -1);
+                                                 RTE_FLOW_ITEM_TYPE_META,
+                                                 table_domain_type, -1);
                if (reg <= 0) {
                        DR_LOG(ERR, "Invalid register for compare metadata 
field");
                        rte_errno = EINVAL;
@@ -2915,6 +2923,7 @@ mlx5dr_definer_conv_item_compare_field(const struct 
rte_flow_field_data *f,
        case RTE_FLOW_FIELD_TAG:
                reg = flow_hw_get_reg_id_from_ctx(cd->ctx,
                                                  RTE_FLOW_ITEM_TYPE_TAG,
+                                                 MLX5DR_TABLE_TYPE_DONTCARE,
                                                  f->tag_index);
                if (reg <= 0) {
                        DR_LOG(ERR, "Invalid register for compare tag field");
@@ -2970,6 +2979,7 @@ mlx5dr_definer_conv_item_compare_field(const struct 
rte_flow_field_data *f,
 
 static int
 mlx5dr_definer_conv_item_compare(struct mlx5dr_definer_conv_data *cd,
+                                enum mlx5dr_table_type table_domain_type,
                                 struct rte_flow_item *item,
                                 int item_idx)
 {
@@ -2986,11 +2996,13 @@ mlx5dr_definer_conv_item_compare(struct 
mlx5dr_definer_conv_data *cd,
        }
 
        ret = mlx5dr_definer_conv_item_compare_field(a, b, cd, item_idx,
+                                                    table_domain_type,
                                                     
MLX5DR_DEFINER_COMPARE_ARGUMENT_0);
        if (ret)
                return ret;
 
        ret = mlx5dr_definer_conv_item_compare_field(b, NULL, cd, item_idx,
+                                                    table_domain_type,
                                                     
MLX5DR_DEFINER_COMPARE_BASE_0);
        if (ret)
                return ret;
@@ -3086,7 +3098,7 @@ mlx5dr_definer_conv_items_to_hl(struct mlx5dr_context 
*ctx,
                        item_flags |= MLX5_FLOW_ITEM_TAG;
                        break;
                case RTE_FLOW_ITEM_TYPE_META:
-                       ret = mlx5dr_definer_conv_item_metadata(&cd, items, i);
+                       ret = mlx5dr_definer_conv_item_metadata(&cd, 
matcher->tbl->type, items, i);
                        item_flags |= MLX5_FLOW_ITEM_METADATA;
                        break;
                case RTE_FLOW_ITEM_TYPE_GRE:
@@ -3177,7 +3189,7 @@ mlx5dr_definer_conv_items_to_hl(struct mlx5dr_context 
*ctx,
                                DR_LOG(ERR, "Compare matcher not supported for 
more than one item");
                                goto not_supp;
                        }
-                       ret = mlx5dr_definer_conv_item_compare(&cd, items, i);
+                       ret = mlx5dr_definer_conv_item_compare(&cd, 
matcher->tbl->type, items, i);
                        item_flags |= MLX5_FLOW_ITEM_COMPARE;
                        matcher->flags |= MLX5DR_MATCHER_FLAGS_COMPARE;
                        break;
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 7aa24f7c52..28f6e9088e 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -1612,6 +1612,67 @@ mlx5_multi_pattern_segment_find(struct 
rte_flow_template_table *table,
        return NULL;
 }
 
+/*
+ * Convert metadata or tag to the actual register.
+ * META: Fixed C_1 for FDB mode, REG_A for NIC TX and REG_B for NIC RX.
+ * TAG: C_x expect meter color reg and the reserved ones.
+ */
+static __rte_always_inline int
+flow_hw_get_reg_id_by_domain(struct rte_eth_dev *dev,
+                            enum rte_flow_item_type type,
+                            enum mlx5dr_table_type domain_type, uint32_t id)
+{
+       struct mlx5_dev_ctx_shared *sh = MLX5_SH(dev);
+       struct mlx5_dev_registers *reg = &sh->registers;
+
+       switch (type) {
+       case RTE_FLOW_ITEM_TYPE_META:
+               if (sh->config.dv_esw_en &&
+                   sh->config.dv_xmeta_en == MLX5_XMETA_MODE_META32_HWS) {
+                       return REG_C_1;
+               }
+               /*
+                * On root table - PMD allows only egress META matching, thus
+                * REG_A matching is sufficient.
+                *
+                * On non-root tables - REG_A corresponds to 
general_purpose_lookup_field,
+                * which translates to REG_A in NIC TX and to REG_B in NIC RX.
+                * However, current FW does not implement REG_B case right now, 
so
+                * REG_B case is return explicitly by this function for NIC RX.
+                */
+               if (domain_type == MLX5DR_TABLE_TYPE_NIC_RX)
+                       return REG_B;
+               return REG_A;
+       case RTE_FLOW_ITEM_TYPE_CONNTRACK:
+       case RTE_FLOW_ITEM_TYPE_METER_COLOR:
+               return reg->aso_reg;
+       case RTE_FLOW_ITEM_TYPE_TAG:
+               if (id == RTE_PMD_MLX5_LINEAR_HASH_TAG_INDEX)
+                       return REG_C_3;
+               MLX5_ASSERT(id < MLX5_FLOW_HW_TAGS_MAX);
+               return reg->hw_avl_tags[id];
+       default:
+               return REG_NON;
+       }
+}
+
+static __rte_always_inline int
+flow_hw_get_reg_id_from_ctx(void *dr_ctx, enum rte_flow_item_type type,
+                           enum mlx5dr_table_type domain_type, uint32_t id)
+{
+       uint16_t port;
+
+       MLX5_ETH_FOREACH_DEV(port, NULL) {
+               struct mlx5_priv *priv;
+
+               priv = rte_eth_devices[port].data->dev_private;
+               if (priv->dr_ctx == dr_ctx)
+                       return 
flow_hw_get_reg_id_by_domain(&rte_eth_devices[port],
+                                                           type, domain_type, 
id);
+       }
+       return REG_NON;
+}
+
 #endif
 
 /*
@@ -1823,70 +1884,19 @@ flow_hw_get_wire_port(struct ibv_context *ibctx)
 }
 #endif
 
-/*
- * Convert metadata or tag to the actual register.
- * META: Can only be used to match in the FDB in this stage, fixed C_1.
- * TAG: C_x expect meter color reg and the reserved ones.
- */
 static __rte_always_inline int
 flow_hw_get_reg_id(struct rte_eth_dev *dev,
                   enum rte_flow_item_type type, uint32_t id)
 {
-       struct mlx5_dev_ctx_shared *sh = MLX5_SH(dev);
-       struct mlx5_dev_registers *reg = &sh->registers;
-
-       switch (type) {
-       case RTE_FLOW_ITEM_TYPE_META:
-#ifdef HAVE_MLX5_HWS_SUPPORT
-               if (sh->config.dv_esw_en &&
-                   sh->config.dv_xmeta_en == MLX5_XMETA_MODE_META32_HWS) {
-                       return REG_C_1;
-               }
-#endif
-               /*
-                * On root table - PMD allows only egress META matching, thus
-                * REG_A matching is sufficient.
-                *
-                * On non-root tables - REG_A corresponds to 
general_purpose_lookup_field,
-                * which translates to REG_A in NIC TX and to REG_B in NIC RX.
-                * However, current FW does not implement REG_B case right now, 
so
-                * REG_B case should be rejected on pattern template validation.
-                */
-               return REG_A;
-       case RTE_FLOW_ITEM_TYPE_CONNTRACK:
-       case RTE_FLOW_ITEM_TYPE_METER_COLOR:
-               return reg->aso_reg;
-       case RTE_FLOW_ITEM_TYPE_TAG:
-               if (id == RTE_PMD_MLX5_LINEAR_HASH_TAG_INDEX)
-                       return REG_C_3;
-               MLX5_ASSERT(id < MLX5_FLOW_HW_TAGS_MAX);
-               return reg->hw_avl_tags[id];
-       default:
-               return REG_NON;
-       }
-}
-
-static __rte_always_inline int
-flow_hw_get_reg_id_from_ctx(void *dr_ctx,
-                           enum rte_flow_item_type type, uint32_t id)
-{
-#ifdef HAVE_IBV_FLOW_DV_SUPPORT
-       uint16_t port;
-
-       MLX5_ETH_FOREACH_DEV(port, NULL) {
-               struct mlx5_priv *priv;
-
-               priv = rte_eth_devices[port].data->dev_private;
-               if (priv->dr_ctx == dr_ctx)
-                       return flow_hw_get_reg_id(&rte_eth_devices[port],
-                                                 type, id);
-       }
+#if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H)
+       return flow_hw_get_reg_id_by_domain(dev, type,
+                                           MLX5DR_TABLE_TYPE_DONTCARE, id);
 #else
-       RTE_SET_USED(dr_ctx);
+       RTE_SET_USED(dev);
        RTE_SET_USED(type);
        RTE_SET_USED(id);
-#endif
        return REG_NON;
+#endif
 }
 
 /**
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index 9620b7f576..6d176de311 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -7273,15 +7273,7 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
                                                  " when egress attribute is 
set");
                        break;
                case RTE_FLOW_ITEM_TYPE_META:
-                       if (!priv->sh->config.dv_esw_en ||
-                           priv->sh->config.dv_xmeta_en != 
MLX5_XMETA_MODE_META32_HWS) {
-                               if (attr->ingress)
-                                       return rte_flow_error_set(error, EINVAL,
-                                                                 
RTE_FLOW_ERROR_TYPE_ITEM, NULL,
-                                                                 "META item is 
not supported"
-                                                                 " on current 
FW with ingress"
-                                                                 " attribute");
-                       }
+                       /* ingress + group 0 is not supported */
                        break;
                case RTE_FLOW_ITEM_TYPE_METER_COLOR:
                {
-- 
2.25.1

Reply via email to