From: Alvin Zhang <alvinx.zh...@intel.com>

Add definitions, trainer packets and routine path for IPv4 GRE tunnel.
Ref:
https://www.ietf.org/rfc/rfc1701.html

Signed-off-by: Junfeng Guo <junfeng....@intel.com>
Signed-off-by: Alvin Zhang <alvinx.zh...@intel.com>
Signed-off-by: Kevin Liu <kevinx....@intel.com>
---
 drivers/net/ice/base/ice_flex_pipe.c     |  37 ++-
 drivers/net/ice/base/ice_flex_pipe.h     |   3 +-
 drivers/net/ice/base/ice_protocol_type.h |  15 ++
 drivers/net/ice/base/ice_switch.c        | 304 ++++++++++++++++++++++-
 4 files changed, 332 insertions(+), 27 deletions(-)

diff --git a/drivers/net/ice/base/ice_flex_pipe.c 
b/drivers/net/ice/base/ice_flex_pipe.c
index f6a29f87c5..8672c41c69 100644
--- a/drivers/net/ice/base/ice_flex_pipe.c
+++ b/drivers/net/ice/base/ice_flex_pipe.c
@@ -1851,6 +1851,7 @@ ice_get_sw_fv_bitmap(struct ice_hw *hw, enum 
ice_prof_type req_profs,
  * @ids_cnt: lookup/protocol count
  * @bm: bitmap of field vectors to consider
  * @fv_list: Head of a list
+ * @lkup_exts: lookup elements
  *
  * Finds all the field vector entries from switch block that contain
  * a given protocol ID and returns a list of structures of type
@@ -1861,7 +1862,8 @@ ice_get_sw_fv_bitmap(struct ice_hw *hw, enum 
ice_prof_type req_profs,
  */
 enum ice_status
 ice_get_sw_fv_list(struct ice_hw *hw, u8 *prot_ids, u16 ids_cnt,
-                  ice_bitmap_t *bm, struct LIST_HEAD_TYPE *fv_list)
+                  ice_bitmap_t *bm, struct LIST_HEAD_TYPE *fv_list,
+                  struct ice_prot_lkup_ext *lkup_exts)
 {
        struct ice_sw_fv_list_entry *fvl;
        struct ice_sw_fv_list_entry *tmp;
@@ -1892,29 +1894,26 @@ ice_get_sw_fv_list(struct ice_hw *hw, u8 *prot_ids, u16 
ids_cnt,
                if (!ice_is_bit_set(bm, (u16)offset))
                        continue;
 
-               for (i = 0; i < ids_cnt; i++) {
+               int found = 1;
+               for (i = 0; i < lkup_exts->n_val_words; i++) {
                        int j;
 
-                       /* This code assumes that if a switch field vector line
-                        * has a matching protocol, then this line will contain
-                        * the entries necessary to represent every field in
-                        * that protocol header.
-                        */
                        for (j = 0; j < hw->blk[ICE_BLK_SW].es.fvw; j++)
-                               if (fv->ew[j].prot_id == prot_ids[i])
+                               if (fv->ew[j].prot_id ==
+                                   lkup_exts->fv_words[i].prot_id &&
+                                   fv->ew[j].off == lkup_exts->fv_words[i].off)
                                        break;
                        if (j >= hw->blk[ICE_BLK_SW].es.fvw)
-                               break;
-                       if (i + 1 == ids_cnt) {
-                               fvl = (struct ice_sw_fv_list_entry *)
-                                       ice_malloc(hw, sizeof(*fvl));
-                               if (!fvl)
-                                       goto err;
-                               fvl->fv_ptr = fv;
-                               fvl->profile_id = offset;
-                               LIST_ADD(&fvl->list_entry, fv_list);
-                               break;
-                       }
+                               found = 0;
+               }
+               if (found) {
+                       fvl = (struct ice_sw_fv_list_entry *)
+                               ice_malloc(hw, sizeof(*fvl));
+                       if (!fvl)
+                               goto err;
+                       fvl->fv_ptr = fv;
+                       fvl->profile_id = offset;
+                       LIST_ADD(&fvl->list_entry, fv_list);
                }
        } while (fv);
        if (LIST_EMPTY(fv_list))
diff --git a/drivers/net/ice/base/ice_flex_pipe.h 
b/drivers/net/ice/base/ice_flex_pipe.h
index 23ba45564a..a22d66f3cf 100644
--- a/drivers/net/ice/base/ice_flex_pipe.h
+++ b/drivers/net/ice/base/ice_flex_pipe.h
@@ -37,7 +37,8 @@ void
 ice_init_prof_result_bm(struct ice_hw *hw);
 enum ice_status
 ice_get_sw_fv_list(struct ice_hw *hw, u8 *prot_ids, u16 ids_cnt,
-                  ice_bitmap_t *bm, struct LIST_HEAD_TYPE *fv_list);
+                  ice_bitmap_t *bm, struct LIST_HEAD_TYPE *fv_list,
+                  struct ice_prot_lkup_ext *lkup_exts);
 enum ice_status
 ice_pkg_buf_unreserve_section(struct ice_buf_build *bld, u16 count);
 u16 ice_pkg_buf_get_free_space(struct ice_buf_build *bld);
diff --git a/drivers/net/ice/base/ice_protocol_type.h 
b/drivers/net/ice/base/ice_protocol_type.h
index eec9f27823..ffd34606e0 100644
--- a/drivers/net/ice/base/ice_protocol_type.h
+++ b/drivers/net/ice/base/ice_protocol_type.h
@@ -67,6 +67,7 @@ enum ice_sw_tunnel_type {
        ICE_SW_TUN_VXLAN,       /* VXLAN matches only non-VLAN pkts */
        ICE_SW_TUN_VXLAN_VLAN,  /* VXLAN matches both VLAN and non-VLAN pkts */
        ICE_SW_TUN_NVGRE,
+       ICE_SW_TUN_GRE,
        ICE_SW_TUN_UDP, /* This means all "UDP" tunnel types: VXLAN-GPE, VXLAN
                         * and GENEVE
                         */
@@ -231,6 +232,10 @@ enum ice_prot_id {
 #define ICE_TUN_FLAG_VLAN_MASK 0x01
 #define ICE_TUN_FLAG_FV_IND 2
 
+#define ICE_GRE_FLAG_MDID 22
+#define ICE_GRE_FLAG_MDID_OFF (ICE_MDID_SIZE * ICE_GRE_FLAG_MDID)
+#define ICE_GRE_FLAG_MASK 0x01C0
+
 #define ICE_PROTOCOL_MAX_ENTRIES 16
 
 /* Mapping of software defined protocol ID to hardware defined protocol ID */
@@ -371,6 +376,15 @@ struct ice_nvgre {
        __be32 tni_flow;
 };
 
+struct ice_gre {
+       __be16 flags;
+       __be16 protocol;
+       __be16 chksum;
+       __be16 offset;
+       __be32 key;
+       __be32 seqnum;
+};
+
 union ice_prot_hdr {
        struct ice_ether_hdr eth_hdr;
        struct ice_ethtype_hdr ethertype;
@@ -381,6 +395,7 @@ union ice_prot_hdr {
        struct ice_sctp_hdr sctp_hdr;
        struct ice_udp_tnl_hdr tnl_hdr;
        struct ice_nvgre nvgre_hdr;
+       struct ice_gre gre_hdr;
        struct ice_udp_gtp_hdr gtp_hdr;
        struct ice_pppoe_hdr pppoe_hdr;
        struct ice_pfcp_hdr pfcp_hdr;
diff --git a/drivers/net/ice/base/ice_switch.c 
b/drivers/net/ice/base/ice_switch.c
index c742dba138..1b51cd4321 100644
--- a/drivers/net/ice/base/ice_switch.c
+++ b/drivers/net/ice/base/ice_switch.c
@@ -12,6 +12,7 @@
 #define ICE_MAX_VLAN_ID                        0xFFF
 #define ICE_IPV6_ETHER_ID              0x86DD
 #define ICE_IPV4_NVGRE_PROTO_ID                0x002F
+#define ICE_IPV4_GRE_PROTO_ID          0x002F
 #define ICE_IPV6_GRE_PROTO_ID          0x002F
 #define ICE_PPP_IPV6_PROTO_ID          0x0057
 #define ICE_TCP_PROTO_ID               0x06
@@ -158,6 +159,188 @@ static const u8 dummy_ipv6_gre_udp_packet[] = {
        0xff, 0xd8, 0x00, 0x00,
 };
 
+static const struct ice_dummy_pkt_offsets
+dummy_gre_rfc1701_c1k1_tcp_packet_offsets[] = {
+       { ICE_MAC_OFOS,         0 },
+       { ICE_ETYPE_OL,         12 },
+       { ICE_IPV4_OFOS,        14 },
+       { ICE_GRE,              34 },
+       { ICE_IPV4_IL,          50 },
+       { ICE_TCP_IL,           70 },
+       { ICE_PROTOCOL_LAST,    0 },
+};
+
+static const u8 dummy_gre_rfc1701_c1k1_tcp_packet[] = {
+       0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+
+       0x08, 0x00,             /* ICE_ETYPE_OL 12 */
+
+       0x45, 0x00, 0x00, 0x4e, /* ICE_IPV4_OFOS 14 */
+       0x00, 0x01, 0x00, 0x00,
+       0x40, 0x2f, 0x7c, 0x7e,
+       0x7f, 0x00, 0x00, 0x01,
+       0x7f, 0x00, 0x00, 0x01,
+
+       0xb0, 0x00, 0x08, 0x00, /* ICE_GRE 34 */
+       0x46, 0x1e, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+
+       0x45, 0x00, 0x00, 0x2a, /* ICE_IPV4_IL 50 */
+       0x00, 0x01, 0x00, 0x00,
+       0x40, 0x06, 0x7c, 0xcb,
+       0x7f, 0x00, 0x00, 0x01,
+       0x7f, 0x00, 0x00, 0x01,
+
+       0x00, 0x14, 0x00, 0x50, /* ICE_TCP_IL 70 */
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x50, 0x02, 0x20, 0x00,
+       0x91, 0x7a, 0x00, 0x00,
+
+       0x00, 0x00,
+};
+
+static const struct ice_dummy_pkt_offsets
+dummy_gre_rfc1701_c1k1_udp_packet_offsets[] = {
+       { ICE_MAC_OFOS,         0 },
+       { ICE_ETYPE_OL,         12 },
+       { ICE_IPV4_OFOS,        14 },
+       { ICE_GRE,              34 },
+       { ICE_IPV4_IL,          50 },
+       { ICE_UDP_ILOS,         70 },
+       { ICE_PROTOCOL_LAST,    0 },
+};
+
+static const u8 dummy_gre_rfc1701_c1k1_udp_packet[] = {
+       0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+
+       0x08, 0x00,             /* ICE_ETYPE_OL 12 */
+
+       0x45, 0x00, 0x00, 0x42, /* ICE_IPV4_OFOS 14 */
+       0x00, 0x01, 0x00, 0x00,
+       0x40, 0x2f, 0x7c, 0x8a,
+       0x7f, 0x00, 0x00, 0x01,
+       0x7f, 0x00, 0x00, 0x01,
+
+       0xb0, 0x00, 0x08, 0x00, /* ICE_GRE 34 */
+       0x46, 0x1d, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+
+       0x45, 0x00, 0x00, 0x1e, /* ICE_IPV4_IL 50 */
+       0x00, 0x01, 0x00, 0x00,
+       0x40, 0x11, 0x7c, 0xcc,
+       0x7f, 0x00, 0x00, 0x01,
+       0x7f, 0x00, 0x00, 0x01,
+
+       0x00, 0x35, 0x00, 0x35, /* ICE_UDP_ILOS 70 */
+       0x00, 0x0a, 0x01, 0x6e,
+
+       0x00, 0x00,
+};
+
+static const struct ice_dummy_pkt_offsets
+dummy_gre_rfc1701_c0k1_tcp_packet_offsets[] = {
+       { ICE_MAC_OFOS,         0 },
+       { ICE_ETYPE_OL,         12 },
+       { ICE_IPV4_OFOS,        14 },
+       { ICE_GRE,              34 },
+       { ICE_IPV4_IL,          46 },
+       { ICE_TCP_IL,           66 },
+       { ICE_PROTOCOL_LAST,    0 },
+};
+
+static const u8 dummy_gre_rfc1701_c0k1_tcp_packet[] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
+       0x00, 0x4a, 0x00, 0x01, 0x00, 0x00, 0x40, 0x2f,
+       0x7c, 0x82, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00,
+       0x00, 0x01, 0x30, 0x00, 0x08, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00,
+       0x00, 0x2a, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06,
+       0x7c, 0xcb, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00,
+       0x00, 0x01, 0x00, 0x14, 0x00, 0x50, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02,
+       0x20, 0x00, 0x91, 0x7a, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const struct ice_dummy_pkt_offsets
+dummy_gre_rfc1701_c0k1_udp_packet_offsets[] = {
+       { ICE_MAC_OFOS,         0 },
+       { ICE_ETYPE_OL,         12 },
+       { ICE_IPV4_OFOS,        14 },
+       { ICE_GRE,              34 },
+       { ICE_IPV4_IL,          46 },
+       { ICE_UDP_ILOS,         66 },
+       { ICE_PROTOCOL_LAST,    0 },
+};
+
+static const u8 dummy_gre_rfc1701_c0k1_udp_packet[] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
+       0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x40, 0x2f,
+       0x7c, 0x8e, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00,
+       0x00, 0x01, 0x30, 0x00, 0x08, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00,
+       0x00, 0x1e, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11,
+       0x7c, 0xcc, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00,
+       0x00, 0x01, 0x00, 0x35, 0x00, 0x35, 0x00, 0x0a,
+       0x01, 0x6e, 0x00, 0x00,
+};
+
+static const struct ice_dummy_pkt_offsets
+dummy_gre_rfc1701_c0k0_tcp_packet_offsets[] = {
+       { ICE_MAC_OFOS,         0 },
+       { ICE_ETYPE_OL,         12 },
+       { ICE_IPV4_OFOS,        14 },
+       { ICE_GRE,              34 },
+       { ICE_IPV4_IL,          42 },
+       { ICE_TCP_IL,           62 },
+       { ICE_PROTOCOL_LAST,    0 },
+};
+
+static const u8 dummy_gre_rfc1701_c0k0_tcp_packet[] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
+       0x00, 0x46, 0x00, 0x01, 0x00, 0x00, 0x40, 0x2f,
+       0x7c, 0x86, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00,
+       0x00, 0x01, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x45, 0x00, 0x00, 0x2a, 0x00, 0x01,
+       0x00, 0x00, 0x40, 0x06, 0x7c, 0xcb, 0x7f, 0x00,
+       0x00, 0x01, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x14,
+       0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x50, 0x02, 0x20, 0x00, 0x91, 0x7a,
+       0x00, 0x00, 0x00, 0x00,
+};
+
+static const struct ice_dummy_pkt_offsets
+dummy_gre_rfc1701_c0k0_udp_packet_offsets[] = {
+       { ICE_MAC_OFOS,         0 },
+       { ICE_ETYPE_OL,         12 },
+       { ICE_IPV4_OFOS,        14 },
+       { ICE_GRE,              34 },
+       { ICE_IPV4_IL,          42 },
+       { ICE_UDP_ILOS,         62 },
+       { ICE_PROTOCOL_LAST,    0 },
+};
+
+static const u8 dummy_gre_rfc1701_c0k0_udp_packet[] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
+       0x00, 0x3a, 0x00, 0x01, 0x00, 0x00, 0x40, 0x2f,
+       0x7c, 0x92, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00,
+       0x00, 0x01, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x45, 0x00, 0x00, 0x1e, 0x00, 0x01,
+       0x00, 0x00, 0x40, 0x11, 0x7c, 0xcc, 0x7f, 0x00,
+       0x00, 0x01, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x35,
+       0x00, 0x35, 0x00, 0x0a, 0x01, 0x6e, 0x00, 0x00,
+};
+
 static const struct ice_dummy_pkt_offsets dummy_udp_tun_tcp_packet_offsets[] = 
{
        { ICE_MAC_OFOS,         0 },
        { ICE_ETYPE_OL,         12 },
@@ -173,7 +356,7 @@ static const struct ice_dummy_pkt_offsets 
dummy_udp_tun_tcp_packet_offsets[] = {
 };
 
 static const u8 dummy_udp_tun_tcp_packet[] = {
-       0x00, 0x00, 0x00, 0x00,  /* ICE_MAC_OFOS 0 */
+       0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
 
@@ -224,7 +407,7 @@ static const struct ice_dummy_pkt_offsets 
dummy_udp_tun_udp_packet_offsets[] = {
 };
 
 static const u8 dummy_udp_tun_udp_packet[] = {
-       0x00, 0x00, 0x00, 0x00,  /* ICE_MAC_OFOS 0 */
+       0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
 
@@ -6892,6 +7075,7 @@ static const struct ice_prot_ext_tbl_entry 
ice_prot_ext[ICE_PROTOCOL_LAST] = {
        { ICE_GENEVE,           { 8, 10, 12, 14 } },
        { ICE_VXLAN_GPE,        { 8, 10, 12, 14 } },
        { ICE_NVGRE,            { 0, 2, 4, 6 } },
+       { ICE_GRE,              { 0, 2, 4, 6, 8, 10, 12, 14 } },
        { ICE_GTP,              { 8, 10, 12, 14, 16, 18, 20, 22 } },
        { ICE_PPPOE,            { 0, 2, 4, 6 } },
        { ICE_PFCP,             { 8, 10, 12, 14, 16, 18, 20, 22 } },
@@ -6927,6 +7111,7 @@ static struct ice_protocol_entry 
ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
        { ICE_GENEVE,           ICE_UDP_OF_HW },
        { ICE_VXLAN_GPE,        ICE_UDP_OF_HW },
        { ICE_NVGRE,            ICE_GRE_OF_HW },
+       { ICE_GRE,              ICE_GRE_OF_HW },
        { ICE_GTP,              ICE_UDP_OF_HW },
        { ICE_PPPOE,            ICE_PPPOE_HW },
        { ICE_PFCP,             ICE_UDP_ILOS_HW },
@@ -7065,6 +7250,7 @@ ice_fill_valid_words(struct ice_adv_lkup_elem *rule,
                     struct ice_prot_lkup_ext *lkup_exts)
 {
        u8 j, word, prot_id, ret_val;
+       u8 extra_byte = 0;
 
        if (!ice_prot_type_to_id(rule->type, &prot_id))
                return 0;
@@ -7077,8 +7263,15 @@ ice_fill_valid_words(struct ice_adv_lkup_elem *rule,
                        /* No more space to accommodate */
                        if (word >= ICE_MAX_CHAIN_WORDS)
                                return 0;
+                       if (rule->type == ICE_GRE) {
+                               if (ice_prot_ext[rule->type].offs[j] == 0) {
+                                       if (((u16 *)&rule->h_u)[j] == 0x20)
+                                               extra_byte = 4;
+                                       continue;
+                               }
+                       }
                        lkup_exts->fv_words[word].off =
-                               ice_prot_ext[rule->type].offs[j];
+                               ice_prot_ext[rule->type].offs[j] - extra_byte;
                        lkup_exts->fv_words[word].prot_id =
                                ice_prot_id_tbl[rule->type].protocol_id;
                        lkup_exts->field_mask[word] =
@@ -7622,10 +7815,12 @@ ice_create_recipe_group(struct ice_hw *hw, struct 
ice_sw_recipe *rm,
  * @lkups_cnt: number of protocols
  * @bm: bitmap of field vectors to consider
  * @fv_list: pointer to a list that holds the returned field vectors
+ * @lkup_exts: lookup elements
  */
 static enum ice_status
 ice_get_fv(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
-          ice_bitmap_t *bm, struct LIST_HEAD_TYPE *fv_list)
+          ice_bitmap_t *bm, struct LIST_HEAD_TYPE *fv_list,
+          struct ice_prot_lkup_ext *lkup_exts)
 {
        enum ice_status status;
        u8 *prot_ids;
@@ -7645,7 +7840,8 @@ ice_get_fv(struct ice_hw *hw, struct ice_adv_lkup_elem 
*lkups, u16 lkups_cnt,
                }
 
        /* Find field vectors that include all specified protocol types */
-       status = ice_get_sw_fv_list(hw, prot_ids, lkups_cnt, bm, fv_list);
+       status = ice_get_sw_fv_list(hw, prot_ids, lkups_cnt, bm, fv_list,
+                                   lkup_exts);
 
 free_mem:
        ice_free(hw, prot_ids);
@@ -7681,6 +7877,10 @@ static bool ice_tun_type_match_word(enum 
ice_sw_tunnel_type tun_type, u16 *mask)
                *mask = ICE_TUN_FLAG_MASK;
                return true;
 
+       case ICE_SW_TUN_GRE:
+               *mask = ICE_GRE_FLAG_MASK;
+               return true;
+
        case ICE_SW_TUN_GENEVE_VLAN:
        case ICE_SW_TUN_VXLAN_VLAN:
                *mask = ICE_TUN_FLAG_MASK & ~ICE_TUN_FLAG_VLAN_MASK;
@@ -7702,6 +7902,12 @@ ice_add_special_words(struct ice_adv_rule_info *rinfo,
                      struct ice_prot_lkup_ext *lkup_exts)
 {
        u16 mask;
+       u8 has_gre_key = 0;
+       u8 i;
+
+       for (i = 0; i < lkup_exts->n_val_words; i++)
+               if (lkup_exts->fv_words[i].prot_id == 0x40)
+                       has_gre_key = 1;
 
        /* If this is a tunneled packet, then add recipe index to match the
         * tunnel bit in the packet metadata flags.
@@ -7713,6 +7919,13 @@ ice_add_special_words(struct ice_adv_rule_info *rinfo,
                        lkup_exts->fv_words[word].prot_id = ICE_META_DATA_ID_HW;
                        lkup_exts->fv_words[word].off = ICE_TUN_FLAG_MDID_OFF;
                        lkup_exts->field_mask[word] = mask;
+
+                       if (rinfo->tun_type == ICE_SW_TUN_GRE)
+                               lkup_exts->fv_words[word].off =
+                                               ICE_GRE_FLAG_MDID_OFF;
+
+                       if (!has_gre_key)
+                               lkup_exts->field_mask[word] = 0x0140;
                } else {
                        return ICE_ERR_MAX_LIMIT;
                }
@@ -7754,6 +7967,9 @@ ice_get_compat_fv_bitmap(struct ice_hw *hw, struct 
ice_adv_rule_info *rinfo,
        case ICE_SW_TUN_NVGRE:
                prof_type = ICE_PROF_TUN_GRE;
                break;
+       case ICE_SW_TUN_GRE:
+               prof_type = ICE_PROF_TUN_GRE;
+               break;
        case ICE_SW_TUN_PPPOE:
        case ICE_SW_TUN_PPPOE_QINQ:
                prof_type = ICE_PROF_TUN_PPPOE;
@@ -8079,7 +8295,8 @@ ice_add_adv_recipe(struct ice_hw *hw, struct 
ice_adv_lkup_elem *lkups,
         */
        ice_get_compat_fv_bitmap(hw, rinfo, fv_bitmap);
 
-       status = ice_get_fv(hw, lkups, lkups_cnt, fv_bitmap, &rm->fv_list);
+       status = ice_get_fv(hw, lkups, lkups_cnt, fv_bitmap, &rm->fv_list,
+                           lkup_exts);
        if (status)
                goto err_unroll;
 
@@ -8228,6 +8445,8 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, 
u16 lkups_cnt,
                      const struct ice_dummy_pkt_offsets **offsets)
 {
        bool tcp = false, udp = false, ipv6 = false, vlan = false;
+       bool gre_c_bit = false;
+       bool gre_k_bit = false;
        bool gre = false, mpls = false;
        u16 i;
 
@@ -8245,6 +8464,17 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, 
u16 lkups_cnt,
                }
                else if (lkups[i].type == ICE_VLAN_OFOS)
                        vlan = true;
+               else if (lkups[i].type == ICE_GRE) {
+                       if (lkups[i].h_u.gre_hdr.flags & 0x20)
+                               gre_k_bit = true;
+                       if (lkups[i].h_u.gre_hdr.flags & 0x80)
+                               gre_c_bit = true;
+               } else if (lkups[i].type == ICE_IPV4_OFOS &&
+                        lkups[i].h_u.ipv4_hdr.protocol ==
+                               ICE_IPV4_GRE_PROTO_ID &&
+                        lkups[i].m_u.ipv4_hdr.protocol ==
+                               0xFF)
+                       gre = true;
                else if (lkups[i].type == ICE_ETYPE_OL &&
                         lkups[i].h_u.ethertype.ethtype_id ==
                                CPU_TO_BE16(ICE_IPV6_ETHER_ID) &&
@@ -8650,6 +8880,46 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, 
u16 lkups_cnt,
                return;
        }
 
+       if (tun_type == ICE_SW_TUN_GRE && tcp) {
+               if (gre_c_bit && gre_k_bit) {
+                       *pkt = dummy_gre_rfc1701_c1k1_tcp_packet;
+                       *pkt_len = sizeof(dummy_gre_rfc1701_c1k1_tcp_packet);
+                       *offsets = dummy_gre_rfc1701_c1k1_tcp_packet_offsets;
+                       return;
+               }
+               if (!gre_c_bit && gre_k_bit) {
+                       *pkt = dummy_gre_rfc1701_c0k1_tcp_packet;
+                       *pkt_len = sizeof(dummy_gre_rfc1701_c0k1_tcp_packet);
+                       *offsets = dummy_gre_rfc1701_c0k1_tcp_packet_offsets;
+                       return;
+               }
+
+               *pkt = dummy_gre_rfc1701_c0k0_tcp_packet;
+               *pkt_len = sizeof(dummy_gre_rfc1701_c0k0_tcp_packet);
+               *offsets = dummy_gre_rfc1701_c0k0_tcp_packet_offsets;
+               return;
+       }
+
+       if (tun_type == ICE_SW_TUN_GRE) {
+               if (gre_c_bit && gre_k_bit) {
+                       *pkt = dummy_gre_rfc1701_c1k1_udp_packet;
+                       *pkt_len = sizeof(dummy_gre_rfc1701_c1k1_udp_packet);
+                       *offsets = dummy_gre_rfc1701_c1k1_udp_packet_offsets;
+                       return;
+               }
+               if (!gre_c_bit && gre_k_bit) {
+                       *pkt = dummy_gre_rfc1701_c0k1_udp_packet;
+                       *pkt_len = sizeof(dummy_gre_rfc1701_c0k1_udp_packet);
+                       *offsets = dummy_gre_rfc1701_c0k1_udp_packet_offsets;
+                       return;
+               }
+
+               *pkt = dummy_gre_rfc1701_c0k0_udp_packet;
+               *pkt_len = sizeof(dummy_gre_rfc1701_c0k0_udp_packet);
+               *offsets = dummy_gre_rfc1701_c0k0_udp_packet_offsets;
+               return;
+       }
+
        if (tun_type == ICE_SW_TUN_VXLAN || tun_type == ICE_SW_TUN_GENEVE ||
            tun_type == ICE_SW_TUN_VXLAN_GPE || tun_type == ICE_SW_TUN_UDP ||
            tun_type == ICE_SW_TUN_PROFID_IPV4_VXLAN ||
@@ -8800,6 +9070,9 @@ ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem 
*lkups, u16 lkups_cnt,
                case ICE_NVGRE:
                        len = sizeof(struct ice_nvgre);
                        break;
+               case ICE_GRE:
+                       len = sizeof(struct ice_gre);
+                       break;
                case ICE_VXLAN:
                case ICE_GENEVE:
                case ICE_VXLAN_GPE:
@@ -8833,6 +9106,20 @@ ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem 
*lkups, u16 lkups_cnt,
                if (len % ICE_BYTES_PER_WORD)
                        return ICE_ERR_CFG;
 
+               if (lkups[i].type == ICE_GRE) {
+                       if (lkups[i].h_u.gre_hdr.flags == 0x20)
+                               offset -= 4;
+
+                       for (j = 1; j < len / sizeof(u16); j++)
+                               if (((u16 *)&lkups[i].m_u)[j])
+                                       ((u16 *)(pkt + offset))[j] =
+                                               (((u16 *)(pkt + offset))[j] &
+                                                ~((u16 *)&lkups[i].m_u)[j]) |
+                                               (((u16 *)&lkups[i].h_u)[j] &
+                                                ((u16 *)&lkups[i].m_u)[j]);
+                       continue;
+               }
+
                /* We have the offset to the header start, the length, the
                 * caller's header values and mask. Use this information to
                 * copy the data into the dummy packet appropriately based on
@@ -9420,8 +9707,11 @@ ice_rem_adv_rule(struct ice_hw *hw, struct 
ice_adv_lkup_elem *lkups,
                        return ICE_ERR_CFG;
 
                count = ice_fill_valid_words(&lkups[i], &lkup_exts);
-               if (!count)
+               if (!count) {
+                       if (lkups[i].type == ICE_GRE)
+                               continue;
                        return ICE_ERR_CFG;
+               }
        }
 
        /* Create any special protocol/offset pairs, such as looking at tunnel
-- 
2.33.1

Reply via email to