net/mlx5: match GRE key and present bits
authorXiaoyu Min <jackmin@mellanox.com>
Tue, 9 Jul 2019 10:59:13 +0000 (18:59 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 23 Jul 2019 12:31:34 +0000 (14:31 +0200)
Support matching on the present bits (C,K,S)
as well as the optional key field.

If the rte_flow_item_gre_key is specified in pattern,
it will set K present match automatically.

Signed-off-by: Xiaoyu Min <jackmin@mellanox.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
doc/guides/rel_notes/release_19_08.rst
drivers/net/mlx5/mlx5_flow.c
drivers/net/mlx5/mlx5_flow.h
drivers/net/mlx5/mlx5_flow_dv.c
drivers/net/mlx5/mlx5_prm.h

index 50c83ce..5ae53c7 100644 (file)
@@ -112,6 +112,7 @@ New Features
   * Updated the packet header modification feature. Added support of TCP header
     sequence number and acknowledgment number modification.
   * Added support for match on ICMP/ICMP6 code and type.
+  * Added support for matching on GRE's key and C,K,S present bits.
 
 * **Updated Solarflare network PMD.**
 
index 626d0f9..c7e034c 100644 (file)
@@ -1666,6 +1666,61 @@ mlx5_flow_validate_item_vxlan_gpe(const struct rte_flow_item *item,
                                          " defined");
        return 0;
 }
+/**
+ * Validate GRE Key item.
+ *
+ * @param[in] item
+ *   Item specification.
+ * @param[in] item_flags
+ *   Bit flags to mark detected items.
+ * @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_key(const struct rte_flow_item *item,
+                               uint64_t item_flags,
+                               const struct rte_flow_item *gre_item,
+                               struct rte_flow_error *error)
+{
+       const rte_be32_t *mask = item->mask;
+       int ret = 0;
+       rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
+       const struct rte_flow_item_gre *gre_spec = gre_item->spec;
+       const struct rte_flow_item_gre *gre_mask = gre_item->mask;
+
+       if (item_flags & MLX5_FLOW_LAYER_GRE_KEY)
+               return rte_flow_error_set(error, ENOTSUP,
+                                         RTE_FLOW_ERROR_TYPE_ITEM, item,
+                                         "Multiple GRE key not support");
+       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 key following a wrong item");
+       if (!gre_mask)
+               gre_mask = &rte_flow_item_gre_mask;
+       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)
+               mask = &gre_key_default_mask;
+       ret = mlx5_flow_item_acceptable
+               (item, (const uint8_t *)mask,
+                (const uint8_t *)&gre_key_default_mask,
+                sizeof(rte_be32_t), error);
+       return ret;
+}
 
 /**
  * Validate GRE item.
@@ -1691,6 +1746,10 @@ mlx5_flow_validate_item_gre(const struct rte_flow_item *item,
        const struct rte_flow_item_gre *spec __rte_unused = item->spec;
        const struct rte_flow_item_gre *mask = item->mask;
        int ret;
+       const struct rte_flow_item_gre nic_mask = {
+               .c_rsvd0_ver = RTE_BE16(0xB000),
+               .protocol = RTE_BE16(UINT16_MAX),
+       };
 
        if (target_protocol != 0xff && target_protocol != IPPROTO_GRE)
                return rte_flow_error_set(error, EINVAL,
@@ -1710,7 +1769,7 @@ mlx5_flow_validate_item_gre(const struct rte_flow_item *item,
                mask = &rte_flow_item_gre_mask;
        ret = mlx5_flow_item_acceptable
                (item, (const uint8_t *)mask,
-                (const uint8_t *)&rte_flow_item_gre_mask,
+                (const uint8_t *)&nic_mask,
                 sizeof(struct rte_flow_item_gre), error);
        if (ret < 0)
                return ret;
index 3d7fcf7..6ccb8a7 100644 (file)
@@ -53,6 +53,7 @@
 /* Pattern MISC bits. */
 #define MLX5_FLOW_LAYER_ICMP (1u << 18)
 #define MLX5_FLOW_LAYER_ICMP6 (1u << 19)
+#define MLX5_FLOW_LAYER_GRE_KEY (1u << 20)
 
 /* Outer Masks. */
 #define MLX5_FLOW_LAYER_OUTER_L3 \
@@ -474,6 +475,10 @@ int mlx5_flow_validate_item_gre(const struct rte_flow_item *item,
                                uint64_t item_flags,
                                uint8_t target_protocol,
                                struct rte_flow_error *error);
+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_ipv4(const struct rte_flow_item *item,
                                 uint64_t item_flags,
                                 const struct rte_flow_item_ipv4 *acc_mask,
index 9cc09e7..676f6e5 100644 (file)
@@ -2294,6 +2294,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
        uint64_t last_item = 0;
        uint8_t next_protocol = 0xff;
        int actions_n = 0;
+       const struct rte_flow_item *gre_item = NULL;
        struct rte_flow_item_tcp nic_tcp_mask = {
                .hdr = {
                        .tcp_flags = 0xFF,
@@ -2403,8 +2404,16 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
                                                          next_protocol, error);
                        if (ret < 0)
                                return ret;
+                       gre_item = items;
                        last_item = MLX5_FLOW_LAYER_GRE;
                        break;
+               case RTE_FLOW_ITEM_TYPE_GRE_KEY:
+                       ret = mlx5_flow_validate_item_gre_key
+                               (items, item_flags, gre_item, error);
+                       if (ret < 0)
+                               return ret;
+                       item_flags |= MLX5_FLOW_LAYER_GRE_KEY;
+                       break;
                case RTE_FLOW_ITEM_TYPE_VXLAN:
                        ret = mlx5_flow_validate_item_vxlan(items, item_flags,
                                                            error);
@@ -3200,6 +3209,45 @@ flow_dv_translate_item_udp(void *matcher, void *key,
                 rte_be_to_cpu_16(udp_v->hdr.dst_port & udp_m->hdr.dst_port));
 }
 
+/**
+ * Add GRE optional Key item 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] inner
+ *   Item is inner pattern.
+ */
+static void
+flow_dv_translate_item_gre_key(void *matcher, void *key,
+                                  const struct rte_flow_item *item)
+{
+       const rte_be32_t *key_m = item->mask;
+       const rte_be32_t *key_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);
+       rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
+
+       if (!key_v)
+               return;
+       if (!key_m)
+               key_m = &gre_key_default_mask;
+       /* GRE K bit must be on and should already be validated */
+       MLX5_SET(fte_match_set_misc, misc_m, gre_k_present, 1);
+       MLX5_SET(fte_match_set_misc, misc_v, gre_k_present, 1);
+       MLX5_SET(fte_match_set_misc, misc_m, gre_key_h,
+                rte_be_to_cpu_32(*key_m) >> 8);
+       MLX5_SET(fte_match_set_misc, misc_v, gre_key_h,
+                rte_be_to_cpu_32((*key_v) & (*key_m)) >> 8);
+       MLX5_SET(fte_match_set_misc, misc_m, gre_key_l,
+                rte_be_to_cpu_32(*key_m) & 0xFF);
+       MLX5_SET(fte_match_set_misc, misc_v, gre_key_l,
+                rte_be_to_cpu_32((*key_v) & (*key_m)) & 0xFF);
+}
+
 /**
  * Add GRE item to matcher and to the value.
  *
@@ -3223,6 +3271,20 @@ flow_dv_translate_item_gre(void *matcher, void *key,
        void *headers_v;
        void *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
        void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
+       struct {
+               union {
+                       __extension__
+                       struct {
+                               uint16_t version:3;
+                               uint16_t rsvd0:9;
+                               uint16_t s_present:1;
+                               uint16_t k_present:1;
+                               uint16_t rsvd_bit1:1;
+                               uint16_t c_present:1;
+                       };
+                       uint16_t value;
+               };
+       } gre_crks_rsvd0_ver_m, gre_crks_rsvd0_ver_v;
 
        if (inner) {
                headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
@@ -3243,6 +3305,23 @@ flow_dv_translate_item_gre(void *matcher, void *key,
                 rte_be_to_cpu_16(gre_m->protocol));
        MLX5_SET(fte_match_set_misc, misc_v, gre_protocol,
                 rte_be_to_cpu_16(gre_v->protocol & gre_m->protocol));
+       gre_crks_rsvd0_ver_m.value = rte_be_to_cpu_16(gre_m->c_rsvd0_ver);
+       gre_crks_rsvd0_ver_v.value = rte_be_to_cpu_16(gre_v->c_rsvd0_ver);
+       MLX5_SET(fte_match_set_misc, misc_m, gre_c_present,
+                gre_crks_rsvd0_ver_m.c_present);
+       MLX5_SET(fte_match_set_misc, misc_v, gre_c_present,
+                gre_crks_rsvd0_ver_v.c_present &
+                gre_crks_rsvd0_ver_m.c_present);
+       MLX5_SET(fte_match_set_misc, misc_m, gre_k_present,
+                gre_crks_rsvd0_ver_m.k_present);
+       MLX5_SET(fte_match_set_misc, misc_v, gre_k_present,
+                gre_crks_rsvd0_ver_v.k_present &
+                gre_crks_rsvd0_ver_m.k_present);
+       MLX5_SET(fte_match_set_misc, misc_m, gre_s_present,
+                gre_crks_rsvd0_ver_m.s_present);
+       MLX5_SET(fte_match_set_misc, misc_v, gre_s_present,
+                gre_crks_rsvd0_ver_v.s_present &
+                gre_crks_rsvd0_ver_m.s_present);
 }
 
 /**
@@ -4390,6 +4469,11 @@ cnt_err:
                                                   items, tunnel);
                        last_item = MLX5_FLOW_LAYER_GRE;
                        break;
+               case RTE_FLOW_ITEM_TYPE_GRE_KEY:
+                       flow_dv_translate_item_gre_key(match_mask,
+                                                      match_value, items);
+                       item_flags |= MLX5_FLOW_LAYER_GRE_KEY;
+                       break;
                case RTE_FLOW_ITEM_TYPE_NVGRE:
                        flow_dv_translate_item_nvgre(match_mask, match_value,
                                                     items, tunnel);
index 7482383..fe171f1 100644 (file)
@@ -428,7 +428,11 @@ typedef uint8_t u8;
 #define MLX5_FLD_SZ_BYTES(typ, fld) (__mlx5_bit_sz(typ, fld) / 8)
 
 struct mlx5_ifc_fte_match_set_misc_bits {
-       u8 reserved_at_0[0x8];
+       u8 gre_c_present[0x1];
+       u8 reserved_at_1[0x1];
+       u8 gre_k_present[0x1];
+       u8 gre_s_present[0x1];
+       u8 source_vhci_port[0x4];
        u8 source_sqn[0x18];
        u8 reserved_at_20[0x10];
        u8 source_port[0x10];