]> git.droids-corp.org - dpdk.git/commitdiff
net/mlx5: support matching GRE optional fields
authorSean Zhang <xiazhang@nvidia.com>
Fri, 25 Feb 2022 01:14:17 +0000 (03:14 +0200)
committerThomas Monjalon <thomas@monjalon.net>
Fri, 25 Feb 2022 15:34:08 +0000 (16:34 +0100)
This patch adds matching on the optional fields (checksum/key/sequence)
of GRE header. The matching on checksum and sequence fields requests
support from rdma-core with the capability of misc5 and tunnel_header 0-3.

For patterns without checksum and sequence specified, keep using misc for
matching as before, but for patterns with checksum or sequence, validate
capability first and then use misc5 for the matching.

Signed-off-by: Sean Zhang <xiazhang@nvidia.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
doc/guides/nics/features/mlx5.ini
doc/guides/nics/mlx5.rst
doc/guides/rel_notes/release_22_03.rst
drivers/common/mlx5/mlx5_devx_cmds.c
drivers/net/mlx5/linux/mlx5_os.c
drivers/net/mlx5/mlx5.h
drivers/net/mlx5/mlx5_flow.c
drivers/net/mlx5/mlx5_flow.h
drivers/net/mlx5/mlx5_flow_dv.c

index 845d2d4a97003eca4ac925d7dd7009bcfe7e0cb3..fb5993124da24fe7bbfaf12c86df5396600fed05 100644 (file)
@@ -62,6 +62,7 @@ geneve               = Y
 geneve_opt           = Y
 gre                  = Y
 gre_key              = Y
+gre_option           = Y
 gtp                  = Y
 gtp_psc              = Y
 icmp                 = Y
index 1e9090c4bc4a69383eb51b777d08c0ed298ae5a4..e6f2ec219c928c9fe5a38c957b74b0779427aa9b 100644 (file)
@@ -493,6 +493,17 @@ Limitations
     - Set ``dv_flow_en`` to 2 in order to enable HW steering.
     - Async queue-based ``rte_flow_q`` APIs supported only.
 
+- Match on GRE header supports the following fields:
+
+  - c_rsvd0_v: C bit, K bit, S bit
+  - protocol type
+  - checksum
+  - key
+  - sequence
+
+  Matching on checksum and sequence needs OFED 5.6+.
+
+
 Statistics
 ----------
 
index 40045c3e8854635fdd46a30339f4ec387367496a..27d7aad4b4f10697441c8e3c6a5903a7bda935d2 100644 (file)
@@ -168,6 +168,7 @@ New Features
 
   * Supported ConnectX-7 capability to schedule traffic sending on timestamp.
   * Added WQE based hardware steering support with ``rte_flow_async`` API.
+  * Added GRE optional fields matching.
 
 * **Updated Wangxun ngbe driver.**
 
index 9f1419ded8e8499698e5577bc71b7aa63574cd41..d02ac2a67847ecce18ae5b965027fece9a69014b 100644 (file)
@@ -1044,6 +1044,9 @@ mlx5_devx_cmd_query_hca_attr(void *ctx,
        attr->flow.tunnel_header_0_1 = MLX5_GET
                (flow_table_nic_cap, hcattr,
                 ft_field_support_2_nic_receive.tunnel_header_0_1);
+       attr->flow.tunnel_header_2_3 = MLX5_GET
+               (flow_table_nic_cap, hcattr,
+                ft_field_support_2_nic_receive.tunnel_header_2_3);
        attr->pkt_integrity_match = mlx5_devx_query_pkt_integrity_match(hcattr);
        attr->inner_ipv4_ihl = MLX5_GET
                (flow_table_nic_cap, hcattr,
index 2e1606a7332f5e84c2ec51619bf8a1ad8c5fb075..ac9be14f548f4230cb440e5bd5829f72e2705413 100644 (file)
@@ -1325,6 +1325,8 @@ err_secondary:
                }
                if (hca_attr->flow.tunnel_header_0_1)
                        sh->tunnel_header_0_1 = 1;
+               if (hca_attr->flow.tunnel_header_2_3)
+                       sh->tunnel_header_2_3 = 1;
 #endif
 #ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
                if (hca_attr->flow_hit_aso && priv->mtr_color_reg == REG_C_3) {
index bd69aa2334421ed6998e20b7dab78fc975c2dd3f..c5301921c5ac26dff94be4c7cd895d598f9399b2 100644 (file)
@@ -1186,6 +1186,7 @@ struct mlx5_dev_ctx_shared {
        uint32_t meter_aso_en:1; /* Flow Meter ASO is supported. */
        uint32_t ct_aso_en:1; /* Connection Tracking ASO is supported. */
        uint32_t tunnel_header_0_1:1; /* tunnel_header_0_1 is supported. */
+       uint32_t tunnel_header_2_3:1; /* tunnel_header_2_3 is supported. */
        uint32_t misc5_cap:1; /* misc5 matcher parameter is supported. */
        uint32_t dr_drop_action_en:1; /* Use DR drop action. */
        uint32_t drop_action_check_flag:1; /* Check Flag for drop action. */
index 5a4e000c12a0efff94340270e59724e7903a74dc..b792ddb73ad3ea69de052be79f3265a8ca4b54ee 100644 (file)
@@ -2926,6 +2926,107 @@ mlx5_flow_validate_item_gre_key(const struct rte_flow_item *item,
        return ret;
 }
 
+/**
+ * Validate GRE optional item.
+ *
+ * @param[in] dev
+ *   Pointer to the Ethernet device structure.
+ * @param[in] item
+ *   Item specification.
+ * @param[in] item_flags
+ *   Bit flags to mark detected items.
+ * @param[in] attr
+ *   Flow rule attributes.
+ * @param[in] gre_item
+ *   Pointer to gre_item
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_flow_validate_item_gre_option(struct rte_eth_dev *dev,
+                                  const struct rte_flow_item *item,
+                                  uint64_t item_flags,
+                                  const struct rte_flow_attr *attr,
+                                  const struct rte_flow_item *gre_item,
+                                  struct rte_flow_error *error)
+{
+       const struct rte_flow_item_gre *gre_spec = gre_item->spec;
+       const struct rte_flow_item_gre *gre_mask = gre_item->mask;
+       const struct rte_flow_item_gre_opt *spec = item->spec;
+       const struct rte_flow_item_gre_opt *mask = item->mask;
+       struct mlx5_priv *priv = dev->data->dev_private;
+       int ret = 0;
+       struct rte_flow_item_gre_opt nic_mask = {
+               .checksum_rsvd = {
+                       .checksum = RTE_BE16(UINT16_MAX),
+                       .reserved1 = 0x0,
+               },
+               .key = {
+                       .key = RTE_BE32(UINT32_MAX),
+               },
+               .sequence = {
+                       .sequence = RTE_BE32(UINT32_MAX),
+               },
+       };
+
+       if (!(item_flags & MLX5_FLOW_LAYER_GRE))
+               return rte_flow_error_set(error, ENOTSUP,
+                                         RTE_FLOW_ERROR_TYPE_ITEM, item,
+                                         "No preceding GRE header");
+       if (item_flags & MLX5_FLOW_LAYER_INNER)
+               return rte_flow_error_set(error, ENOTSUP,
+                                         RTE_FLOW_ERROR_TYPE_ITEM, item,
+                                         "GRE option following a wrong item");
+       if (!spec || !mask)
+               return rte_flow_error_set(error, EINVAL,
+                                         RTE_FLOW_ERROR_TYPE_ITEM, item,
+                                         "At least one field gre_option(checksum/key/sequence) must be specified");
+       if (!gre_mask)
+               gre_mask = &rte_flow_item_gre_mask;
+       if (mask->checksum_rsvd.checksum)
+               if (gre_spec && (gre_mask->c_rsvd0_ver & RTE_BE16(0x8000)) &&
+                                !(gre_spec->c_rsvd0_ver & RTE_BE16(0x8000)))
+                       return rte_flow_error_set(error, EINVAL,
+                                                 RTE_FLOW_ERROR_TYPE_ITEM,
+                                                 item,
+                                                 "Checksum bit must be on");
+       if (mask->key.key)
+               if (gre_spec && (gre_mask->c_rsvd0_ver & RTE_BE16(0x2000)) &&
+                                !(gre_spec->c_rsvd0_ver & RTE_BE16(0x2000)))
+                       return rte_flow_error_set(error, EINVAL,
+                                                 RTE_FLOW_ERROR_TYPE_ITEM,
+                                                 item, "Key bit must be on");
+       if (mask->sequence.sequence)
+               if (gre_spec && (gre_mask->c_rsvd0_ver & RTE_BE16(0x1000)) &&
+                                !(gre_spec->c_rsvd0_ver & RTE_BE16(0x1000)))
+                       return rte_flow_error_set(error, EINVAL,
+                                                 RTE_FLOW_ERROR_TYPE_ITEM,
+                                                 item,
+                                                 "Sequence bit must be on");
+       if (mask->checksum_rsvd.checksum || mask->sequence.sequence) {
+               if (priv->sh->steering_format_version ==
+                   MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5 ||
+                   ((attr->group || attr->transfer) &&
+                    !priv->sh->misc5_cap) ||
+                   (!(priv->sh->tunnel_header_0_1 &&
+                      priv->sh->tunnel_header_2_3) &&
+                   !attr->group && !attr->transfer))
+                       return rte_flow_error_set(error, EINVAL,
+                                                 RTE_FLOW_ERROR_TYPE_ITEM,
+                                                 item,
+                                                 "Checksum/Sequence not supported");
+       }
+       ret = mlx5_flow_item_acceptable
+               (item, (const uint8_t *)mask,
+                (const uint8_t *)&nic_mask,
+                sizeof(struct rte_flow_item_gre_opt),
+                MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
+       return ret;
+}
+
 /**
  * Validate GRE item.
  *
index 09f0d7a75dab26f26764d1bdc25aa3fd8acec70c..e510921a3f70fc01a75e6d95252db07c3ae4013d 100644 (file)
@@ -1783,6 +1783,12 @@ int mlx5_flow_validate_item_gre_key(const struct rte_flow_item *item,
                                    uint64_t item_flags,
                                    const struct rte_flow_item *gre_item,
                                    struct rte_flow_error *error);
+int mlx5_flow_validate_item_gre_option(struct rte_eth_dev *dev,
+                                      const struct rte_flow_item *item,
+                                      uint64_t item_flags,
+                                      const struct rte_flow_attr *attr,
+                                      const struct rte_flow_item *gre_item,
+                                      struct rte_flow_error *error);
 int mlx5_flow_validate_item_ipv4(const struct rte_flow_item *item,
                                 uint64_t item_flags,
                                 uint64_t last_item,
index 7a012f7bb948ca8d968a4723c4f7f32270303e72..aca55bbcdbea9418856fa3360dc340f3ed0e2948 100644 (file)
@@ -7109,6 +7109,13 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
                        gre_item = items;
                        last_item = MLX5_FLOW_LAYER_GRE;
                        break;
+               case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
+                       ret = mlx5_flow_validate_item_gre_option(dev, items, item_flags,
+                                                         attr, gre_item, error);
+                       if (ret < 0)
+                               return ret;
+                       last_item = MLX5_FLOW_LAYER_GRE;
+                       break;
                case RTE_FLOW_ITEM_TYPE_NVGRE:
                        ret = mlx5_flow_validate_item_nvgre(items, item_flags,
                                                            next_protocol,
@@ -8829,6 +8836,110 @@ flow_dv_translate_item_gre(void *matcher, void *key,
                 protocol_m & protocol_v);
 }
 
+/**
+ * Add GRE optional items to matcher and to the value.
+ *
+ * @param[in, out] matcher
+ *   Flow matcher.
+ * @param[in, out] key
+ *   Flow matcher value.
+ * @param[in] item
+ *   Flow pattern to translate.
+ * @param[in] gre_item
+ *   Pointer to gre_item.
+ * @param[in] pattern_flags
+ *   Accumulated pattern flags.
+ */
+static void
+flow_dv_translate_item_gre_option(void *matcher, void *key,
+                                 const struct rte_flow_item *item,
+                                 const struct rte_flow_item *gre_item,
+                                 uint64_t pattern_flags)
+{
+       const struct rte_flow_item_gre_opt *option_m = item->mask;
+       const struct rte_flow_item_gre_opt *option_v = item->spec;
+       const struct rte_flow_item_gre *gre_m = gre_item->mask;
+       const struct rte_flow_item_gre *gre_v = gre_item->spec;
+       static const struct rte_flow_item_gre empty_gre = {0};
+       struct rte_flow_item gre_key_item;
+       uint16_t c_rsvd0_ver_m, c_rsvd0_ver_v;
+       uint16_t protocol_m, protocol_v;
+       void *misc5_m;
+       void *misc5_v;
+
+       /*
+        * If only match key field, keep using misc for matching.
+        * If need to match checksum or sequence, using misc5 and do
+        * not need using misc.
+        */
+       if (!(option_m->sequence.sequence ||
+             option_m->checksum_rsvd.checksum)) {
+               flow_dv_translate_item_gre(matcher, key, gre_item,
+                                          pattern_flags);
+               gre_key_item.spec = &option_v->key.key;
+               gre_key_item.mask = &option_m->key.key;
+               flow_dv_translate_item_gre_key(matcher, key, &gre_key_item);
+               return;
+       }
+       if (!gre_v) {
+               gre_v = &empty_gre;
+               gre_m = &empty_gre;
+       } else {
+               if (!gre_m)
+                       gre_m = &rte_flow_item_gre_mask;
+       }
+       protocol_v = gre_v->protocol;
+       protocol_m = gre_m->protocol;
+       if (!protocol_m) {
+               /* Force next protocol to prevent matchers duplication */
+               uint16_t ether_type =
+                       mlx5_translate_tunnel_etypes(pattern_flags);
+               if (ether_type) {
+                       protocol_v = rte_be_to_cpu_16(ether_type);
+                       protocol_m = UINT16_MAX;
+               }
+       }
+       c_rsvd0_ver_v = gre_v->c_rsvd0_ver;
+       c_rsvd0_ver_m = gre_m->c_rsvd0_ver;
+       if (option_m->sequence.sequence) {
+               c_rsvd0_ver_v |= RTE_BE16(0x1000);
+               c_rsvd0_ver_m |= RTE_BE16(0x1000);
+       }
+       if (option_m->key.key) {
+               c_rsvd0_ver_v |= RTE_BE16(0x2000);
+               c_rsvd0_ver_m |= RTE_BE16(0x2000);
+       }
+       if (option_m->checksum_rsvd.checksum) {
+               c_rsvd0_ver_v |= RTE_BE16(0x8000);
+               c_rsvd0_ver_m |= RTE_BE16(0x8000);
+       }
+       /*
+        * Hardware parses GRE optional field into the fixed location,
+        * do not need to adjust the tunnel dword indices.
+        */
+       misc5_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_5);
+       misc5_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters_5);
+       MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_0,
+                rte_be_to_cpu_32((c_rsvd0_ver_v | protocol_v << 16) &
+                                 (c_rsvd0_ver_m | protocol_m << 16)));
+       MLX5_SET(fte_match_set_misc5, misc5_m, tunnel_header_0,
+                rte_be_to_cpu_32(c_rsvd0_ver_m | protocol_m << 16));
+       MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_1,
+                rte_be_to_cpu_32(option_v->checksum_rsvd.checksum &
+                                 option_m->checksum_rsvd.checksum));
+       MLX5_SET(fte_match_set_misc5, misc5_m, tunnel_header_1,
+                rte_be_to_cpu_32(option_m->checksum_rsvd.checksum));
+       MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_2,
+                rte_be_to_cpu_32(option_v->key.key & option_m->key.key));
+       MLX5_SET(fte_match_set_misc5, misc5_m, tunnel_header_2,
+                rte_be_to_cpu_32(option_m->key.key));
+       MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_3,
+                rte_be_to_cpu_32(option_v->sequence.sequence &
+                                 option_m->sequence.sequence));
+       MLX5_SET(fte_match_set_misc5, misc5_m, tunnel_header_3,
+                rte_be_to_cpu_32(option_m->sequence.sequence));
+}
+
 /**
  * Add NVGRE item to matcher and to the value.
  *
@@ -12709,6 +12820,7 @@ flow_dv_translate(struct rte_eth_dev *dev,
        };
        const struct rte_flow_item *integrity_items[2] = {NULL, NULL};
        const struct rte_flow_item *tunnel_item = NULL;
+       const struct rte_flow_item *gre_item = NULL;
 
        if (!wks)
                return rte_flow_error_set(error, ENOMEM,
@@ -13481,12 +13593,18 @@ flow_dv_translate(struct rte_eth_dev *dev,
                        matcher.priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
                        last_item = MLX5_FLOW_LAYER_GRE;
                        tunnel_item = items;
+                       gre_item = items;
                        break;
                case RTE_FLOW_ITEM_TYPE_GRE_KEY:
                        flow_dv_translate_item_gre_key(match_mask,
                                                       match_value, items);
                        last_item = MLX5_FLOW_LAYER_GRE_KEY;
                        break;
+               case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
+                       matcher.priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
+                       last_item = MLX5_FLOW_LAYER_GRE;
+                       tunnel_item = items;
+                       break;
                case RTE_FLOW_ITEM_TYPE_NVGRE:
                        matcher.priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
                        last_item = MLX5_FLOW_LAYER_GRE;
@@ -13645,6 +13763,9 @@ flow_dv_translate(struct rte_eth_dev *dev,
                else if (tunnel_item->type == RTE_FLOW_ITEM_TYPE_NVGRE)
                        flow_dv_translate_item_nvgre(match_mask, match_value,
                                                     tunnel_item, item_flags);
+               else if (tunnel_item->type == RTE_FLOW_ITEM_TYPE_GRE_OPTION)
+                       flow_dv_translate_item_gre_option(match_mask, match_value,
+                                       tunnel_item, gre_item, item_flags);
                else
                        MLX5_ASSERT(false);
        }