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 75cc861e93..b367efaf02 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 },
@@ -7113,6 +7298,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;
@@ -7125,8 +7311,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] =
@@ -7670,10 +7863,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;
@@ -7693,7 +7888,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);
@@ -7729,6 +7925,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;
@@ -7750,6 +7950,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.
@@ -7761,6 +7967,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;
 		}
@@ -7802,6 +8015,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;
@@ -8127,7 +8343,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;
 
@@ -8276,6 +8493,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;
 
@@ -8293,6 +8512,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) &&
@@ -8698,6 +8928,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 ||
@@ -8848,6 +9118,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:
@@ -8881,6 +9154,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
@@ -9468,8 +9755,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
