net/mlx5: add GENEVE TLV option flow translation
authorShiri Kuzin <shirik@nvidia.com>
Sun, 17 Jan 2021 10:21:22 +0000 (12:21 +0200)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 19 Jan 2021 02:30:16 +0000 (03:30 +0100)
The GENEVE TLV option matching flows must be created
using a translation function.

This function checks whether we already created a Devx
object for the matching and either creates the objects
or updates the reference counter.

Signed-off-by: Shiri Kuzin <shirik@nvidia.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
doc/guides/nics/mlx5.rst
drivers/net/mlx5/mlx5_flow.h
drivers/net/mlx5/mlx5_flow_dv.c

index db0c8b6..b8f80ac 100644 (file)
@@ -99,6 +99,7 @@ Features
 - Hairpin.
 - Multiple-thread flow insertion.
 - Matching on GTP extension header with raw encap/decap action.
+- Matching on Geneve TLV option header with raw encap/decap action.
 
 Limitations
 -----------
@@ -186,7 +187,19 @@ Limitations
      - OAM
      - protocol type
      - options length
-       Currently, the only supported options length value is 0.
+
+- Match on Geneve TLV option is supported on the following fields:
+
+     - Class
+     - Type
+     - Length
+     - Data
+
+  Only one Class/Type/Length Geneve TLV option is supported per shared device.
+  Class/Type/Length fields must be specified as well as masks.
+  Class/Type/Length specified masks must be full.
+  Matching Geneve TLV option without specifying data is not supported.
+  Matching Geneve TLV option with ``data & mask == 0`` is not supported.
 
 - VF: flow rules created on VF devices can only match traffic targeted at the
   configured MAC addresses (see ``rte_eth_dev_mac_addr_add()``).
@@ -1019,6 +1032,10 @@ Below are some firmware configurations listed.
    or
    FLEX_PARSER_PROFILE_ENABLE=1
 
+- enable Geneve TLV option flow matching::
+
+   FLEX_PARSER_PROFILE_ENABLE=0
+
 - enable GTP flow matching::
 
    FLEX_PARSER_PROFILE_ENABLE=3
@@ -1540,6 +1557,11 @@ Supported hardware offloads
    |                       | |  rdma-core 35 | | rdma-core 35  |
    |                       | |  ConnectX-6 Dx| | ConnectX-6 Dx |
    +-----------------------+-----------------+-----------------+
+   | Encapsulation         | | DPDK 21.02    | | DPDK 21.02    |
+   | GENEVE TLV option     | | OFED 5.2      | | OFED 5.2      |
+   |                       | | rdma-core 34  | | rdma-core 34  |
+   |                       | | ConnectX-6 Dx | | ConnectX-6 Dx |
+   +-----------------------+-----------------+-----------------+
 
 Notes for metadata
 ------------------
index 4c68c65..a9e33b8 100644 (file)
@@ -330,7 +330,7 @@ enum mlx5_feature_name {
 #define MLX5_GENEVE_VER_VAL(a) \
                (((a) >> (MLX5_GENEVE_VER_SHIFT)) & (MLX5_GENEVE_VER_MASK))
 #define MLX5_GENEVE_OPTLEN_MASK 0x3F
-#define MLX5_GENEVE_OPTLEN_SHIFT 7
+#define MLX5_GENEVE_OPTLEN_SHIFT 8
 #define MLX5_GENEVE_OPTLEN_VAL(a) \
            (((a) >> (MLX5_GENEVE_OPTLEN_SHIFT)) & (MLX5_GENEVE_OPTLEN_MASK))
 #define MLX5_GENEVE_OAMF_MASK 0x1
index 86c9d2c..936ddfa 100644 (file)
@@ -7416,6 +7416,80 @@ exit:
        return ret;
 }
 
+/**
+ * Add Geneve TLV option item to matcher.
+ *
+ * @param[in, out] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in, out] matcher
+ *   Flow matcher.
+ * @param[in, out] key
+ *   Flow matcher value.
+ * @param[in] item
+ *   Flow pattern to translate.
+ * @param[out] error
+ *   Pointer to error structure.
+ */
+static int
+flow_dv_translate_item_geneve_opt(struct rte_eth_dev *dev, void *matcher,
+                                 void *key, const struct rte_flow_item *item,
+                                 struct rte_flow_error *error)
+{
+       const struct rte_flow_item_geneve_opt *geneve_opt_m = item->mask;
+       const struct rte_flow_item_geneve_opt *geneve_opt_v = item->spec;
+       void *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
+       void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
+       void *misc3_m = MLX5_ADDR_OF(fte_match_param, matcher,
+                       misc_parameters_3);
+       void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
+       rte_be32_t opt_data_key = 0, opt_data_mask = 0;
+       int ret = 0;
+
+       if (!geneve_opt_v)
+               return -1;
+       if (!geneve_opt_m)
+               geneve_opt_m = &rte_flow_item_geneve_opt_mask;
+       ret = flow_dev_geneve_tlv_option_resource_register(dev, item,
+                                                          error);
+       if (ret) {
+               DRV_LOG(ERR, "Failed to create geneve_tlv_obj");
+               return ret;
+       }
+       /*
+        * Set the option length in GENEVE header if not requested.
+        * The GENEVE TLV option length is expressed by the option length field
+        * in the GENEVE header.
+        * If the option length was not requested but the GENEVE TLV option item
+        * is present we set the option length field implicitly.
+        */
+       if (!MLX5_GET16(fte_match_set_misc, misc_m, geneve_opt_len)) {
+               MLX5_SET(fte_match_set_misc, misc_m, geneve_opt_len,
+                        MLX5_GENEVE_OPTLEN_MASK);
+               MLX5_SET(fte_match_set_misc, misc_v, geneve_opt_len,
+                        geneve_opt_v->option_len + 1);
+       }
+       /* Set the data. */
+       if (geneve_opt_v->data) {
+               memcpy(&opt_data_key, geneve_opt_v->data,
+                       RTE_MIN((uint32_t)(geneve_opt_v->option_len * 4),
+                               sizeof(opt_data_key)));
+               MLX5_ASSERT((uint32_t)(geneve_opt_v->option_len * 4) <=
+                               sizeof(opt_data_key));
+               memcpy(&opt_data_mask, geneve_opt_m->data,
+                       RTE_MIN((uint32_t)(geneve_opt_v->option_len * 4),
+                               sizeof(opt_data_mask)));
+               MLX5_ASSERT((uint32_t)(geneve_opt_v->option_len * 4) <=
+                               sizeof(opt_data_mask));
+               MLX5_SET(fte_match_set_misc3, misc3_m,
+                               geneve_tlv_option_0_data,
+                               rte_be_to_cpu_32(opt_data_mask));
+               MLX5_SET(fte_match_set_misc3, misc3_v,
+                               geneve_tlv_option_0_data,
+                       rte_be_to_cpu_32(opt_data_key & opt_data_mask));
+       }
+       return ret;
+}
+
 /**
  * Add MPLS item to matcher and to the value.
  *
@@ -10739,6 +10813,17 @@ flow_dv_translate(struct rte_eth_dev *dev,
                        matcher.priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
                        last_item = MLX5_FLOW_LAYER_GENEVE;
                        break;
+               case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
+                       ret = flow_dv_translate_item_geneve_opt(dev, match_mask,
+                                                         match_value,
+                                                         items, error);
+                       if (ret)
+                               return rte_flow_error_set(error, -ret,
+                                       RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+                                       "cannot create GENEVE TLV option");
+                       flow->geneve_tlv_option = 1;
+                       last_item = MLX5_FLOW_LAYER_GENEVE_OPT;
+                       break;
                case RTE_FLOW_ITEM_TYPE_MPLS:
                        flow_dv_translate_item_mpls(match_mask, match_value,
                                                    items, last_item, tunnel);