Add support to use "RTE_FLOW_ITEM_TYPE_COMPARE" with
"RTE_FLOW_FIELD_RAMDOM" as an argument.
The random field is supported only when base is an immediate value,
random field cannot be compared with enother field.

Signed-off-by: Michael Baum <michae...@nvidia.com>
Acked-by: Suanming Mou <suanmi...@nvidia.com>
---
 doc/guides/nics/mlx5.rst        |  9 ++++-
 drivers/net/mlx5/mlx5_flow_hw.c | 70 ++++++++++++++++++++++++---------
 2 files changed, 59 insertions(+), 20 deletions(-)

diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index 0d2213497a..c0a5768117 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -431,8 +431,13 @@ Limitations
 
   - Only supported in HW steering(``dv_flow_en`` = 2) mode.
   - Only single flow is supported to the flow table.
-  - Only 32-bit comparison is supported.
-  - Only match with compare result between packet fields is supported.
+  - Only single item is supported per pattern template.
+  - Only 32-bit comparison is supported or 16-bits for random field.
+  - Only supported for ``RTE_FLOW_FIELD_META``, ``RTE_FLOW_FIELD_TAG``,
+    ``RTE_FLOW_FIELD_RANDOM`` and ``RTE_FLOW_FIELD_VALUE``.
+  - The field type ``RTE_FLOW_FIELD_VALUE`` must be the base (``b``) field.
+  - The field type ``RTE_FLOW_FIELD_RANDOM`` can only be compared with
+    ``RTE_FLOW_FIELD_VALUE``.
 
 - No Tx metadata go to the E-Switch steering domain for the Flow group 0.
   The flows within group 0 and set metadata action are rejected by hardware.
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index 0d09c220df..b0e93baaf2 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -6721,18 +6721,55 @@ flow_hw_prepend_item(const struct rte_flow_item *items,
        return copied_items;
 }
 
-static inline bool
-flow_hw_item_compare_field_supported(enum rte_flow_field_id field)
+static int
+flow_hw_item_compare_field_validate(enum rte_flow_field_id arg_field,
+                                   enum rte_flow_field_id base_field,
+                                   struct rte_flow_error *error)
 {
-       switch (field) {
+       switch (arg_field) {
+       case RTE_FLOW_FIELD_TAG:
+       case RTE_FLOW_FIELD_META:
+               break;
+       case RTE_FLOW_FIELD_RANDOM:
+               if (base_field == RTE_FLOW_FIELD_VALUE)
+                       return 0;
+               return rte_flow_error_set(error, EINVAL,
+                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+                                         NULL,
+                                         "compare random is supported only 
with immediate value");
+       default:
+               return rte_flow_error_set(error, ENOTSUP,
+                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+                                         NULL,
+                                         "compare item argument field is not 
supported");
+       }
+       switch (base_field) {
        case RTE_FLOW_FIELD_TAG:
        case RTE_FLOW_FIELD_META:
        case RTE_FLOW_FIELD_VALUE:
-               return true;
+               break;
+       default:
+               return rte_flow_error_set(error, ENOTSUP,
+                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+                                         NULL,
+                                         "compare item base field is not 
supported");
+       }
+       return 0;
+}
+
+static inline uint32_t
+flow_hw_item_compare_width_supported(enum rte_flow_field_id field)
+{
+       switch (field) {
+       case RTE_FLOW_FIELD_TAG:
+       case RTE_FLOW_FIELD_META:
+               return 32;
+       case RTE_FLOW_FIELD_RANDOM:
+               return 16;
        default:
                break;
        }
-       return false;
+       return 0;
 }
 
 static int
@@ -6741,6 +6778,7 @@ flow_hw_validate_item_compare(const struct rte_flow_item 
*item,
 {
        const struct rte_flow_item_compare *comp_m = item->mask;
        const struct rte_flow_item_compare *comp_v = item->spec;
+       int ret;
 
        if (unlikely(!comp_m))
                return rte_flow_error_set(error, EINVAL,
@@ -6752,19 +6790,13 @@ flow_hw_validate_item_compare(const struct 
rte_flow_item *item,
                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
                                   NULL,
                                   "compare item only support full mask");
-       if (!flow_hw_item_compare_field_supported(comp_m->a.field) ||
-           !flow_hw_item_compare_field_supported(comp_m->b.field))
-               return rte_flow_error_set(error, ENOTSUP,
-                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-                                  NULL,
-                                  "compare item field not support");
-       if (comp_m->a.field == RTE_FLOW_FIELD_VALUE &&
-           comp_m->b.field == RTE_FLOW_FIELD_VALUE)
-               return rte_flow_error_set(error, EINVAL,
-                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-                                  NULL,
-                                  "compare between value is not valid");
+       ret = flow_hw_item_compare_field_validate(comp_m->a.field,
+                                                 comp_m->b.field, error);
+       if (ret < 0)
+               return ret;
        if (comp_v) {
+               uint32_t width;
+
                if (comp_v->operation != comp_m->operation ||
                    comp_v->a.field != comp_m->a.field ||
                    comp_v->b.field != comp_m->b.field)
@@ -6772,7 +6804,9 @@ flow_hw_validate_item_compare(const struct rte_flow_item 
*item,
                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
                                           NULL,
                                           "compare item spec/mask not 
matching");
-               if ((comp_v->width & comp_m->width) != 32)
+               width = flow_hw_item_compare_width_supported(comp_v->a.field);
+               MLX5_ASSERT(width > 0);
+               if ((comp_v->width & comp_m->width) != width)
                        return rte_flow_error_set(error, EINVAL,
                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
                                           NULL,
-- 
2.25.1

Reply via email to