Add support for matching and modifying GENEVE option for
FLEX_PARSER_PROFILE_ENABLE=0.
Before this patch it is supported when FLEX_PARSER_PROFILE_ENABLE=8 in
HW steering and when FLEX_PARSER_PROFILE_ENABLE=0 in SW steering.

Signed-off-by: Michael Baum <michae...@nvidia.com>
Acked-by: Suanming Mou <suanmi...@nvidia.com>
---
 doc/guides/nics/mlx5.rst            |   9 ++-
 doc/guides/platform/mlx5.rst        |   6 +-
 drivers/net/mlx5/mlx5_flow_geneve.c | 114 +++++++++++++++++++++-------
 3 files changed, 95 insertions(+), 34 deletions(-)

diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index 62fd27d859..a6d00ecd2b 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -355,6 +355,7 @@ Limitations
      - Multiple of same Geneve TLV option isn't supported at the same pattern
        template.
      - Supported only when ``FLEX_PARSER_PROFILE_ENABLE`` = 8.
+     - Supported also when ``FLEX_PARSER_PROFILE_ENABLE`` = 0 for single DW 
only.
 
 - VF: flow rules created on VF devices can only match traffic targeted at the
   configured MAC addresses (see ``rte_eth_dev_mac_addr_add()``).
@@ -2445,8 +2446,14 @@ Limitations
 ~~~~~~~~~~~
 
 * Supported only in HW steering (``dv_flow_en`` = 2).
-* Supported only when ``FLEX_PARSER_PROFILE_ENABLE`` = 8.
 * Supported for FW version **xx.37.0142** and above.
+* Parser creation can be done only for E-Switch manager.
+* Supported for multiple DW only when ``FLEX_PARSER_PROFILE_ENABLE`` = 8.
+* Supported for single DW also when ``FLEX_PARSER_PROFILE_ENABLE`` = 0 with 
some limitations:
+
+   - ``sample_len`` must be equal to ``option_len`` and not bigger than 1.
+   - ``match_on_class_mode`` different than 1 is not supported.
+   - ``offset`` must be 0.
 
 
 Testpmd driver specific commands
diff --git a/doc/guides/platform/mlx5.rst b/doc/guides/platform/mlx5.rst
index d16508d0da..a66cf778d1 100644
--- a/doc/guides/platform/mlx5.rst
+++ b/doc/guides/platform/mlx5.rst
@@ -536,12 +536,10 @@ Below are some firmware configurations listed.
    or
    FLEX_PARSER_PROFILE_ENABLE=1
 
-- enable Geneve TLV option flow matching in SW steering::
+- enable Geneve TLV option flow matching::
 
    FLEX_PARSER_PROFILE_ENABLE=0
-
-- enable Geneve TLV option flow matching in HW steering::
-
+   or
    FLEX_PARSER_PROFILE_ENABLE=8
 
 - enable GTP flow matching::
diff --git a/drivers/net/mlx5/mlx5_flow_geneve.c 
b/drivers/net/mlx5/mlx5_flow_geneve.c
index 2c8dc39e74..f3ee414d02 100644
--- a/drivers/net/mlx5/mlx5_flow_geneve.c
+++ b/drivers/net/mlx5/mlx5_flow_geneve.c
@@ -18,6 +18,8 @@
 #define MAX_GENEVE_OPTION_TOTAL_DATA_SIZE \
                (MAX_GENEVE_OPTION_DATA_SIZE * MAX_GENEVE_OPTIONS_RESOURCES)
 
+#define INVALID_SAMPLE_ID (UINT8_MAX)
+
 /**
  * Single DW inside GENEVE TLV option.
  */
@@ -265,6 +267,8 @@ mlx5_geneve_tlv_options_unregister(struct mlx5_priv *priv,
  *   Pointer to header layout structure to update.
  * @param resource
  *   Pointer to single sample context to fill.
+ * @param sample_id
+ *   The flex parser id for single DW or UINT8_MAX for multiple DWs.
  *
  * @return
  *   0 on success, a negative errno otherwise and rte_errno is set.
@@ -274,7 +278,7 @@ mlx5_geneve_tlv_option_create_sample(void *ctx,
                      struct mlx5_devx_geneve_tlv_option_attr *attr,
                      struct mlx5_devx_match_sample_info_query_attr *query_attr,
                      struct mlx5_hl_data *match_data,
-                     struct mlx5_geneve_tlv_resource *resource)
+                     struct mlx5_geneve_tlv_resource *resource, uint8_t 
sample_id)
 {
        struct mlx5_devx_obj *obj;
        int ret;
@@ -282,7 +286,10 @@ mlx5_geneve_tlv_option_create_sample(void *ctx,
        obj = mlx5_devx_cmd_create_geneve_tlv_option(ctx, attr);
        if (obj == NULL)
                return -rte_errno;
-       ret = mlx5_devx_cmd_query_geneve_tlv_option(ctx, obj, query_attr);
+       if (sample_id == INVALID_SAMPLE_ID)
+               ret = mlx5_devx_cmd_query_geneve_tlv_option(ctx, obj, 
query_attr);
+       else
+               ret = mlx5_devx_cmd_match_sample_info_query(ctx, sample_id, 
query_attr);
        if (ret) {
                claim_zero(mlx5_devx_cmd_destroy(obj));
                return ret;
@@ -335,20 +342,22 @@ should_configure_sample_for_dw0(const struct 
rte_pmd_mlx5_geneve_tlv *spec)
  *   Pointer to user configuration.
  * @param option
  *   Pointer to single GENEVE TLV option to fill.
+ * @param sample_id
+ *   The flex parser id for single DW or UINT8_MAX for multiple DWs.
  *
  * @return
  *   0 on success, a negative errno otherwise and rte_errno is set.
  */
 static int
 mlx5_geneve_tlv_option_create(void *ctx, const struct rte_pmd_mlx5_geneve_tlv 
*spec,
-                             struct mlx5_geneve_tlv_option *option)
+                             struct mlx5_geneve_tlv_option *option, uint8_t 
sample_id)
 {
        struct mlx5_devx_geneve_tlv_option_attr attr = {
                .option_class = spec->option_class,
                .option_type = spec->option_type,
                .option_data_len = spec->option_len,
                .option_class_ignore = spec->match_on_class_mode == 1 ? 0 : 1,
-               .offset_valid = 1,
+               .offset_valid = sample_id == INVALID_SAMPLE_ID ? 1 : 0,
        };
        struct mlx5_devx_match_sample_info_query_attr query_attr = {0};
        struct mlx5_geneve_tlv_resource *resource;
@@ -356,12 +365,14 @@ mlx5_geneve_tlv_option_create(void *ctx, const struct 
rte_pmd_mlx5_geneve_tlv *s
        int ret;
 
        if (should_configure_sample_for_dw0(spec)) {
+               MLX5_ASSERT(sample_id == INVALID_SAMPLE_ID);
                attr.sample_offset = 0;
                resource = &option->resources[resource_id];
                ret = mlx5_geneve_tlv_option_create_sample(ctx, &attr,
                                                           &query_attr,
                                                           
&option->match_data[0],
-                                                          resource);
+                                                          resource,
+                                                          INVALID_SAMPLE_ID);
                if (ret)
                        return ret;
                resource_id++;
@@ -379,7 +390,8 @@ mlx5_geneve_tlv_option_create(void *ctx, const struct 
rte_pmd_mlx5_geneve_tlv *s
                ret = mlx5_geneve_tlv_option_create_sample(ctx, &attr,
                                                           &query_attr,
                                                           
&option->match_data[i],
-                                                          resource);
+                                                          resource,
+                                                          sample_id);
                if (ret)
                        goto error;
                resource_id++;
@@ -467,6 +479,8 @@ mlx5_geneve_tlv_option_copy(struct rte_pmd_mlx5_geneve_tlv 
*dst,
  *   A list of GENEVE TLV options to create parser for them.
  * @param nb_options
  *   The number of options in TLV list.
+ * @param sample_id
+ *   The flex parser id for single DW or UINT8_MAX for multiple DWs.
  *
  * @return
  *   A pointer to GENEVE TLV options parser structure on success,
@@ -475,7 +489,7 @@ mlx5_geneve_tlv_option_copy(struct rte_pmd_mlx5_geneve_tlv 
*dst,
 static struct mlx5_geneve_tlv_options *
 mlx5_geneve_tlv_options_create(struct mlx5_dev_ctx_shared *sh,
                               const struct rte_pmd_mlx5_geneve_tlv tlv_list[],
-                              uint8_t nb_options)
+                              uint8_t nb_options, uint8_t sample_id)
 {
        struct mlx5_geneve_tlv_options *options;
        const struct rte_pmd_mlx5_geneve_tlv *spec;
@@ -495,7 +509,7 @@ mlx5_geneve_tlv_options_create(struct mlx5_dev_ctx_shared 
*sh,
        for (i = 0; i < nb_options; ++i) {
                spec = &tlv_list[i];
                ret = mlx5_geneve_tlv_option_create(sh->cdev->ctx, spec,
-                                                   &options->options[i]);
+                                                   &options->options[i], 
sample_id);
                if (ret < 0)
                        goto error;
                /* Copy the user list for comparing future configuration. */
@@ -705,6 +719,12 @@ mlx5_is_same_geneve_tlv_options(const struct 
mlx5_geneve_tlv_options *options,
        return true;
 }
 
+static inline bool
+multiple_dws_supported(struct mlx5_hca_attr *attr)
+{
+       return attr->geneve_tlv_option_offset && attr->geneve_tlv_sample;
+}
+
 void *
 mlx5_geneve_tlv_parser_create(uint16_t port_id,
                              const struct rte_pmd_mlx5_geneve_tlv tlv_list[],
@@ -715,8 +735,7 @@ mlx5_geneve_tlv_parser_create(uint16_t port_id,
        struct rte_eth_dev *dev;
        struct mlx5_priv *priv;
        struct mlx5_hca_attr *attr;
-       uint8_t total_dws = 0;
-       uint8_t i;
+       uint8_t sample_id;
 
        /*
         * Validate the input before taking a lock and before any memory
@@ -742,34 +761,71 @@ mlx5_geneve_tlv_parser_create(uint16_t port_id,
                return NULL;
        }
        attr = &priv->sh->cdev->config.hca_attr;
-       MLX5_ASSERT(MAX_GENEVE_OPTIONS_RESOURCES <=
-                   attr->max_geneve_tlv_options);
-       if (!attr->geneve_tlv_option_offset || !attr->geneve_tlv_sample ||
-           !attr->query_match_sample_info || !attr->geneve_tlv_opt) {
-               DRV_LOG(ERR, "Not enough capabilities to support GENEVE TLV 
parser, maybe old FW version");
+       if (!attr->query_match_sample_info || !attr->geneve_tlv_opt) {
+               DRV_LOG(ERR, "Not enough capabilities to support GENEVE TLV 
parser, is this device eswitch manager?");
                rte_errno = ENOTSUP;
                return NULL;
        }
-       if (nb_options > MAX_GENEVE_OPTIONS_RESOURCES) {
+       DRV_LOG(DEBUG, "Max DWs supported for GENEVE TLV option is %u",
+               attr->max_geneve_tlv_options);
+       if (nb_options > attr->max_geneve_tlv_options) {
                DRV_LOG(ERR,
                        "GENEVE TLV option number (%u) exceeds the limit (%u).",
-                       nb_options, MAX_GENEVE_OPTIONS_RESOURCES);
+                       nb_options, attr->max_geneve_tlv_options);
                rte_errno = EINVAL;
                return NULL;
        }
-       for (i = 0; i < nb_options; ++i) {
-               if (mlx5_geneve_tlv_option_validate(attr, &tlv_list[i]) < 0) {
-                       DRV_LOG(ERR, "GENEVE TLV option %u is invalid.", i);
+       if (multiple_dws_supported(attr)) {
+               uint8_t total_dws = 0;
+               uint8_t i;
+
+               MLX5_ASSERT(attr->max_geneve_tlv_options >= 
MAX_GENEVE_OPTIONS_RESOURCES);
+               for (i = 0; i < nb_options; ++i) {
+                       if (mlx5_geneve_tlv_option_validate(attr, &tlv_list[i]) 
< 0) {
+                               DRV_LOG(ERR, "GENEVE TLV option %u is 
invalid.", i);
+                               return NULL;
+                       }
+                       total_dws += 
mlx5_geneve_tlv_option_get_nb_dws(&tlv_list[i]);
+               }
+               if (total_dws > MAX_GENEVE_OPTIONS_RESOURCES) {
+                       DRV_LOG(ERR,
+                               "Total requested DWs (%u) exceeds the limit 
(%u).",
+                               total_dws, MAX_GENEVE_OPTIONS_RESOURCES);
+                       rte_errno = EINVAL;
                        return NULL;
                }
-               total_dws += mlx5_geneve_tlv_option_get_nb_dws(&tlv_list[i]);
-       }
-       if (total_dws > MAX_GENEVE_OPTIONS_RESOURCES) {
-               DRV_LOG(ERR,
-                       "Total requested DWs (%u) exceeds the limit (%u).",
-                       total_dws, MAX_GENEVE_OPTIONS_RESOURCES);
-               rte_errno = EINVAL;
-               return NULL;
+               /* Multiple DWs is supported, each of the has sample ID given 
later. */
+               sample_id = INVALID_SAMPLE_ID;
+               DRV_LOG(DEBUG, "GENEVE TLV parser supports multiple DWs, 
FLEX_PARSER_PROFILE_ENABLE == 8");
+       } else {
+               const struct rte_pmd_mlx5_geneve_tlv *option = &tlv_list[0];
+
+               if (option->offset != 0) {
+                       DRV_LOG(ERR,
+                               "GENEVE TLV option offset %u is required but 
not supported.",
+                               option->offset);
+                       rte_errno = ENOTSUP;
+                       return NULL;
+               }
+               if (option->sample_len != option->option_len) {
+                       DRV_LOG(ERR,
+                               "GENEVE TLV option length (%u) should be equal 
to sample length (%u).",
+                               option->option_len, option->sample_len);
+                       rte_errno = ENOTSUP;
+                       return NULL;
+               }
+               if (option->match_on_class_mode != 1) {
+                       DRV_LOG(ERR,
+                               "GENEVE TLV option match_on_class_mode %u is 
invalid for flex parser profile 0.",
+                               option->match_on_class_mode);
+                       rte_errno = EINVAL;
+                       return NULL;
+               }
+               if (mlx5_geneve_tlv_option_validate(attr, option) < 0)
+                       return NULL;
+               /* Single DW is supported, its sample ID is given. */
+               sample_id = attr->geneve_tlv_option_sample_id;
+               DRV_LOG(DEBUG, "GENEVE TLV parser supports only single DW, 
FLEX_PARSER_PROFILE_ENABLE == 0");
        }
        /* Take lock for this physical device and manage the options. */
        phdev = mlx5_get_locked_physical_device(priv);
@@ -793,7 +849,7 @@ mlx5_geneve_tlv_parser_create(uint16_t port_id,
                goto exit;
        }
        /* Create GENEVE TLV options for this physical device. */
-       options = mlx5_geneve_tlv_options_create(priv->sh, tlv_list, 
nb_options);
+       options = mlx5_geneve_tlv_options_create(priv->sh, tlv_list, 
nb_options, sample_id);
        if (!options) {
                mlx5_unlock_physical_device();
                return NULL;
-- 
2.25.1

Reply via email to