public inbox for dev@dpdk.org
 help / color / mirror / Atom feed
* [PATCH v3 0/7] Add support for L2TPV2 over UDP to ICE PMD
  2026-02-02  9:42 [PATCH 0/6] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
@ 2025-08-26 16:26 ` Shaiq Wani
  2025-08-26 16:26   ` [PATCH v4 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
                     ` (6 more replies)
  2025-08-26 17:05 ` [PATCH v5 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                   ` (8 subsequent siblings)
  9 siblings, 7 replies; 56+ messages in thread
From: Shaiq Wani @ 2025-08-26 16:26 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh

This patchset adds L2TPv2 protocol support to the ICE PMD
enabling RSS and Flow Director capabilities for L2TPv2 over UDP traffic.

v4: Version 3 patchset was incomplete due to a server reboot.
    V4 includes all patches for review.

v3: Fixed compilation issues.

v2: Addressed AI generated comments.

Shaiq Wani (7):
  net/ice: add L2TPv2 PPP and PPoE data structures
  net/ice: add L2TPv2 tunnel type definition
  net/ice: add L2TPv2 protocol and field definitions
  net/ice: add L2TPv2 flow patterns and FDIR support
  net/ice: add L2TPv2 hardware packet generation
  net/ice: add L2TPv2 RSS hash support
  doc: update release notes

 doc/guides/rel_notes/release_26_03.rst   |   4 +
 drivers/net/intel/ice/base/ice_fdir.c    |   6 +
 drivers/net/intel/ice/base/ice_fdir.h    |  17 +
 drivers/net/intel/ice/ice_ethdev.h       |   4 +
 drivers/net/intel/ice/ice_fdir_filter.c  | 451 ++++++++++++++++++++---
 drivers/net/intel/ice/ice_generic_flow.c | 177 +++++++++
 drivers/net/intel/ice/ice_generic_flow.h | 129 ++++---
 drivers/net/intel/ice/ice_hash.c         |  25 ++
 8 files changed, 717 insertions(+), 96 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH v4 1/7] net/ice: add L2TPv2 PPP and PPoE data structures
  2025-08-26 16:26 ` [PATCH v3 0/7] " Shaiq Wani
@ 2025-08-26 16:26   ` Shaiq Wani
  2025-08-26 16:26   ` [PATCH v4 2/7] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2025-08-26 16:26 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add data structure definitions for L2TPv2 PPP and
PPoE protocols to support Flow Director (FDIR) filtering.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/base/ice_fdir.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/net/intel/ice/base/ice_fdir.h b/drivers/net/intel/ice/base/ice_fdir.h
index 3dd03f93f7..3d3b05da4a 100644
--- a/drivers/net/intel/ice/base/ice_fdir.h
+++ b/drivers/net/intel/ice/base/ice_fdir.h
@@ -230,6 +230,20 @@ struct ice_fdir_ecpri {
 	__be16 pc_id;
 };
 
+struct ice_fdir_pppoe {
+	u8 rsrvd_ver_type;
+	u8 rsrvd_code;
+	__be16 session_id;
+	__be16 length;
+	__be16 ppp_prot_id; /* control and data only */
+};
+
+struct ice_fdir_ppp {
+	u8 addr;
+	u8 ctrl;
+	__be16 proto_id;
+};
+
 struct ice_fdir_l2tpv2 {
 	__be16 flags_version;
 	__be16 length;
@@ -279,6 +293,9 @@ struct ice_fdir_fltr {
 	struct ice_fdir_ecpri ecpri_data;
 	struct ice_fdir_ecpri ecpri_mask;
 
+	struct ice_fdir_ppp ppp_data;
+	struct ice_fdir_ppp ppp_mask;
+
 	struct ice_fdir_l2tpv2 l2tpv2_data;
 	struct ice_fdir_l2tpv2 l2tpv2_mask;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v4 2/7] net/ice: add L2TPv2 tunnel type definition
  2025-08-26 16:26 ` [PATCH v3 0/7] " Shaiq Wani
  2025-08-26 16:26   ` [PATCH v4 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
@ 2025-08-26 16:26   ` Shaiq Wani
  2025-08-26 16:27   ` [PATCH v4 3/7] net/ice: add L2TPv2 protocol and field definitions Shaiq Wani
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2025-08-26 16:26 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add ICE_FDIR_TUNNEL_TYPE_L2TPV2 to the tunnel type enum and
extend ice_fdir_fltr_pattern structure to include L2TPv2 data and
mask fields.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_ethdev.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/intel/ice/ice_ethdev.h b/drivers/net/intel/ice/ice_ethdev.h
index 9562b2b8f1..4b3718f715 100644
--- a/drivers/net/intel/ice/ice_ethdev.h
+++ b/drivers/net/intel/ice/ice_ethdev.h
@@ -369,6 +369,7 @@ enum ice_fdir_tunnel_type {
 	ICE_FDIR_TUNNEL_TYPE_VXLAN,
 	ICE_FDIR_TUNNEL_TYPE_GTPU,
 	ICE_FDIR_TUNNEL_TYPE_GTPU_EH,
+	ICE_FDIR_TUNNEL_TYPE_L2TPV2,
 };
 
 struct rte_flow;
@@ -405,6 +406,9 @@ struct ice_fdir_fltr_pattern {
 	struct ice_fdir_udp_gtp gtpu_data;
 	struct ice_fdir_udp_gtp gtpu_mask;
 
+	struct ice_fdir_l2tpv2 l2tpv2_data;
+	struct ice_fdir_l2tpv2 l2tpv2_mask;
+
 	struct ice_fdir_extra ext_data;
 	struct ice_fdir_extra ext_mask;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v4 3/7] net/ice: add L2TPv2 protocol and field definitions
  2025-08-26 16:26 ` [PATCH v3 0/7] " Shaiq Wani
  2025-08-26 16:26   ` [PATCH v4 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
  2025-08-26 16:26   ` [PATCH v4 2/7] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
@ 2025-08-26 16:27   ` Shaiq Wani
  2025-08-26 16:27   ` [PATCH v4 4/7] net/ice: add L2TPv2 flow patterns and FDIR support Shaiq Wani
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2025-08-26 16:27 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add L2TPv2 protocol identifier (ICE_PROT_L2TPV2OIP) and session ID
field definition (ICE_L2TPV2OIP_SESSION_ID) to the generic flow header.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_generic_flow.h | 129 ++++++++++++++++-------
 1 file changed, 88 insertions(+), 41 deletions(-)

diff --git a/drivers/net/intel/ice/ice_generic_flow.h b/drivers/net/intel/ice/ice_generic_flow.h
index 54bbb47398..deaf7b66e5 100644
--- a/drivers/net/intel/ice/ice_generic_flow.h
+++ b/drivers/net/intel/ice/ice_generic_flow.h
@@ -9,15 +9,15 @@
 
 /* protocol */
 
-#define ICE_PROT_MAC			BIT_ULL(1)
-#define ICE_PROT_VLAN			BIT_ULL(2)
-#define ICE_PROT_IPV4			BIT_ULL(3)
-#define ICE_PROT_IPV6			BIT_ULL(4)
-#define ICE_PROT_TCP			BIT_ULL(5)
-#define ICE_PROT_UDP			BIT_ULL(6)
-#define ICE_PROT_SCTP			BIT_ULL(7)
-#define ICE_PROT_ICMP4			BIT_ULL(8)
-#define ICE_PROT_ICMP6			BIT_ULL(9)
+#define ICE_PROT_MAC_OUTER		BIT_ULL(1)
+#define ICE_PROT_VLAN_OUTER		BIT_ULL(2)
+#define ICE_PROT_IPV4_OUTER		BIT_ULL(3)
+#define ICE_PROT_IPV6_OUTER		BIT_ULL(4)
+#define ICE_PROT_TCP_OUTER		BIT_ULL(5)
+#define ICE_PROT_UDP_OUTER		BIT_ULL(6)
+#define ICE_PROT_SCTP_OUTER		BIT_ULL(7)
+#define ICE_PROT_ICMP4_OUTER		BIT_ULL(8)
+#define ICE_PROT_ICMP6_OUTER		BIT_ULL(9)
 #define ICE_PROT_VXLAN			BIT_ULL(10)
 #define ICE_PROT_NVGRE			BIT_ULL(11)
 #define ICE_PROT_GTPU			BIT_ULL(12)
@@ -27,6 +27,16 @@
 #define ICE_PROT_L2TPV3OIP		BIT_ULL(16)
 #define ICE_PROT_PFCP			BIT_ULL(17)
 #define ICE_PROT_NAT_T_ESP		BIT_ULL(18)
+#define ICE_PROT_L2TPV2OIP		BIT_ULL(19)
+#define ICE_PROT_MAC_INNER		BIT_ULL(20)
+#define ICE_PROT_VLAN_INNER		BIT_ULL(21)
+#define ICE_PROT_IPV4_INNER		BIT_ULL(22)
+#define ICE_PROT_IPV6_INNER		BIT_ULL(23)
+#define ICE_PROT_TCP_INNER		BIT_ULL(24)
+#define ICE_PROT_UDP_INNER		BIT_ULL(25)
+#define ICE_PROT_SCTP_INNER		BIT_ULL(26)
+#define ICE_PROT_ICMP4_INNER		BIT_ULL(27)
+#define ICE_PROT_ICMP6_INNER		BIT_ULL(28)
 
 /* field */
 
@@ -53,8 +63,9 @@
 #define ICE_L2TPV3OIP_SESSION_ID	BIT_ULL(43)
 #define ICE_PFCP_SEID			BIT_ULL(42)
 #define ICE_PFCP_S_FIELD		BIT_ULL(41)
-#define ICE_IP_PK_ID		    BIT_ULL(40)
+#define ICE_IP_PK_ID			BIT_ULL(40)
 #define ICE_IP_FRAG_OFS			BIT_ULL(39)
+#define ICE_L2TPV2OIP_SESSION_ID	BIT_ULL(38)
 
 /* input set */
 
@@ -62,39 +73,39 @@
 
 #define ICE_INSET_SMAC			(ICE_SMAC)
 #define ICE_INSET_DMAC			(ICE_DMAC)
-#define ICE_INSET_VLAN			(ICE_PROT_VLAN)
-#define ICE_INSET_VLAN_INNER		(ICE_PROT_VLAN)
-#define ICE_INSET_VLAN_OUTER		(ICE_PROT_VLAN)
+#define ICE_INSET_VLAN			(ICE_PROT_VLAN_OUTER)
+#define ICE_INSET_VLAN_INNER		(ICE_PROT_VLAN_OUTER)
+#define ICE_INSET_VLAN_OUTER		(ICE_PROT_VLAN_OUTER)
 #define ICE_INSET_ETHERTYPE		(ICE_ETHERTYPE)
 
-#define ICE_INSET_IPV4_SRC		(ICE_PROT_IPV4 | ICE_IP_SRC)
-#define ICE_INSET_IPV4_DST		(ICE_PROT_IPV4 | ICE_IP_DST)
-#define ICE_INSET_IPV4_TOS		(ICE_PROT_IPV4 | ICE_IP_TOS)
-#define ICE_INSET_IPV4_PROTO		(ICE_PROT_IPV4 | ICE_IP_PROTO)
-#define ICE_INSET_IPV4_TTL		(ICE_PROT_IPV4 | ICE_IP_TTL)
-#define ICE_INSET_IPV4_PKID		(ICE_PROT_IPV4 | ICE_IP_PK_ID)
-#define ICE_INSET_IPV4_FRAG_OFS	(ICE_PROT_IPV4 | ICE_IP_FRAG_OFS)
-#define ICE_INSET_IPV6_SRC		(ICE_PROT_IPV6 | ICE_IP_SRC)
-#define ICE_INSET_IPV6_DST		(ICE_PROT_IPV6 | ICE_IP_DST)
-#define ICE_INSET_IPV6_NEXT_HDR		(ICE_PROT_IPV6 | ICE_IP_PROTO)
-#define ICE_INSET_IPV6_HOP_LIMIT	(ICE_PROT_IPV6 | ICE_IP_TTL)
-#define ICE_INSET_IPV6_TC		(ICE_PROT_IPV6 | ICE_IP_TOS)
-#define ICE_INSET_IPV6_PKID		(ICE_PROT_IPV6 | ICE_IP_PK_ID)
-
-#define ICE_INSET_TCP_SRC_PORT		(ICE_PROT_TCP | ICE_SPORT)
-#define ICE_INSET_TCP_DST_PORT		(ICE_PROT_TCP | ICE_DPORT)
-#define ICE_INSET_UDP_SRC_PORT		(ICE_PROT_UDP | ICE_SPORT)
-#define ICE_INSET_UDP_DST_PORT		(ICE_PROT_UDP | ICE_DPORT)
-#define ICE_INSET_SCTP_SRC_PORT		(ICE_PROT_SCTP | ICE_SPORT)
-#define ICE_INSET_SCTP_DST_PORT		(ICE_PROT_SCTP | ICE_DPORT)
-#define ICE_INSET_ICMP4_SRC_PORT	(ICE_PROT_ICMP4 | ICE_SPORT)
-#define ICE_INSET_ICMP4_DST_PORT	(ICE_PROT_ICMP4 | ICE_DPORT)
-#define ICE_INSET_ICMP6_SRC_PORT	(ICE_PROT_ICMP6 | ICE_SPORT)
-#define ICE_INSET_ICMP6_DST_PORT	(ICE_PROT_ICMP6 | ICE_DPORT)
-#define ICE_INSET_ICMP4_TYPE		(ICE_PROT_ICMP4 | ICE_ICMP_TYPE)
-#define ICE_INSET_ICMP4_CODE		(ICE_PROT_ICMP4 | ICE_ICMP_CODE)
-#define ICE_INSET_ICMP6_TYPE		(ICE_PROT_ICMP6 | ICE_ICMP_TYPE)
-#define ICE_INSET_ICMP6_CODE		(ICE_PROT_ICMP6 | ICE_ICMP_CODE)
+#define ICE_INSET_IPV4_SRC		(ICE_PROT_IPV4_OUTER | ICE_IP_SRC)
+#define ICE_INSET_IPV4_DST		(ICE_PROT_IPV4_OUTER | ICE_IP_DST)
+#define ICE_INSET_IPV4_TOS		(ICE_PROT_IPV4_OUTER | ICE_IP_TOS)
+#define ICE_INSET_IPV4_PROTO		(ICE_PROT_IPV4_OUTER | ICE_IP_PROTO)
+#define ICE_INSET_IPV4_TTL		(ICE_PROT_IPV4_OUTER | ICE_IP_TTL)
+#define ICE_INSET_IPV4_PKID		(ICE_PROT_IPV4_OUTER | ICE_IP_PK_ID)
+#define ICE_INSET_IPV4_FRAG_OFS	(ICE_PROT_IPV4_OUTER | ICE_IP_FRAG_OFS)
+#define ICE_INSET_IPV6_SRC		(ICE_PROT_IPV6_OUTER | ICE_IP_SRC)
+#define ICE_INSET_IPV6_DST		(ICE_PROT_IPV6_OUTER | ICE_IP_DST)
+#define ICE_INSET_IPV6_NEXT_HDR		(ICE_PROT_IPV6_OUTER | ICE_IP_PROTO)
+#define ICE_INSET_IPV6_HOP_LIMIT	(ICE_PROT_IPV6_OUTER | ICE_IP_TTL)
+#define ICE_INSET_IPV6_TC		(ICE_PROT_IPV6_OUTER | ICE_IP_TOS)
+#define ICE_INSET_IPV6_PKID		(ICE_PROT_IPV6_OUTER | ICE_IP_PK_ID)
+
+#define ICE_INSET_TCP_SRC_PORT		(ICE_PROT_TCP_OUTER | ICE_SPORT)
+#define ICE_INSET_TCP_DST_PORT		(ICE_PROT_TCP_OUTER | ICE_DPORT)
+#define ICE_INSET_UDP_SRC_PORT		(ICE_PROT_UDP_OUTER | ICE_SPORT)
+#define ICE_INSET_UDP_DST_PORT		(ICE_PROT_UDP_OUTER | ICE_DPORT)
+#define ICE_INSET_SCTP_SRC_PORT		(ICE_PROT_SCTP_OUTER | ICE_SPORT)
+#define ICE_INSET_SCTP_DST_PORT		(ICE_PROT_SCTP_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP4_SRC_PORT	(ICE_PROT_ICMP4_OUTER | ICE_SPORT)
+#define ICE_INSET_ICMP4_DST_PORT	(ICE_PROT_ICMP4_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP6_SRC_PORT	(ICE_PROT_ICMP6_OUTER | ICE_SPORT)
+#define ICE_INSET_ICMP6_DST_PORT	(ICE_PROT_ICMP6_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP4_TYPE		(ICE_PROT_ICMP4_OUTER | ICE_ICMP_TYPE)
+#define ICE_INSET_ICMP4_CODE		(ICE_PROT_ICMP4_OUTER | ICE_ICMP_CODE)
+#define ICE_INSET_ICMP6_TYPE		(ICE_PROT_ICMP6_OUTER | ICE_ICMP_TYPE)
+#define ICE_INSET_ICMP6_CODE		(ICE_PROT_ICMP6_OUTER | ICE_ICMP_CODE)
 
 /* tunnel */
 
@@ -122,6 +133,24 @@
 	(ICE_PROT_PFCP | ICE_PFCP_S_FIELD | ICE_PFCP_SEID)
 #define ICE_INSET_NAT_T_ESP_SPI \
 	(ICE_PROT_NAT_T_ESP | ICE_ESP_SPI)
+#define ICE_INSET_L2TPV2OIP_SESSION_ID \
+	(ICE_PROT_L2TPV2OIP | ICE_L2TPV2OIP_SESSION_ID)
+#define ICE_INSET_TUN_IPV4_SRC \
+	(ICE_PROT_IPV4_INNER | ICE_IP_SRC)
+#define ICE_INSET_TUN_IPV4_DST \
+	(ICE_PROT_IPV4_INNER | ICE_IP_DST)
+#define ICE_INSET_TUN_UDP_SRC_PORT \
+	(ICE_PROT_UDP_INNER | ICE_SPORT)
+#define ICE_INSET_TUN_UDP_DST_PORT \
+	(ICE_PROT_UDP_INNER | ICE_DPORT)
+#define ICE_INSET_TUN_TCP_SRC_PORT \
+	(ICE_PROT_TCP_INNER | ICE_SPORT)
+#define ICE_INSET_TUN_TCP_DST_PORT \
+	(ICE_PROT_TCP_INNER | ICE_DPORT)
+#define ICE_INSET_TUN_IPV6_SRC \
+	(ICE_PROT_IPV6_INNER | ICE_IP_SRC)
+#define ICE_INSET_TUN_IPV6_DST \
+	(ICE_PROT_IPV6_INNER | ICE_IP_DST)
 
 /* empty pattern */
 extern enum rte_flow_item_type pattern_empty[];
@@ -400,6 +429,24 @@ extern enum rte_flow_item_type pattern_eth_ipv6_udp_ah[];
 /* L2TP */
 extern enum rte_flow_item_type pattern_eth_ipv4_l2tp[];
 extern enum rte_flow_item_type pattern_eth_ipv6_l2tp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv6_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp[];
 
 /* PFCP */
 extern enum rte_flow_item_type pattern_eth_ipv4_pfcp[];
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v4 4/7] net/ice: add L2TPv2 flow patterns and FDIR support
  2025-08-26 16:26 ` [PATCH v3 0/7] " Shaiq Wani
                     ` (2 preceding siblings ...)
  2025-08-26 16:27   ` [PATCH v4 3/7] net/ice: add L2TPv2 protocol and field definitions Shaiq Wani
@ 2025-08-26 16:27   ` Shaiq Wani
  2025-08-26 16:27   ` [PATCH v4 5/7] net/ice: add L2TPv2 hardware packet generation Shaiq Wani
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2025-08-26 16:27 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Implement comprehensive L2TPv2 support for Flow Director
-Flow pattern definitions for different L2TPv2 packet combinations
-FDIR filter parsing logic
-Flow type assignment for proper packet classification

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_fdir_filter.c  | 451 ++++++++++++++++++++---
 drivers/net/intel/ice/ice_generic_flow.c | 177 +++++++++
 2 files changed, 573 insertions(+), 55 deletions(-)

diff --git a/drivers/net/intel/ice/ice_fdir_filter.c b/drivers/net/intel/ice/ice_fdir_filter.c
index f7730ec6ab..6a5d605f03 100644
--- a/drivers/net/intel/ice/ice_fdir_filter.c
+++ b/drivers/net/intel/ice/ice_fdir_filter.c
@@ -107,6 +107,31 @@
 	ICE_INSET_IPV6_SRC | ICE_INSET_IPV6_DST | \
 	ICE_INSET_NAT_T_ESP_SPI)
 
+#define ICE_FDIR_INSET_L2TPV2 (\
+	ICE_INSET_SMAC | ICE_INSET_DMAC | ICE_INSET_L2TPV2OIP_SESSION_ID)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4 (\
+	ICE_INSET_TUN_IPV4_SRC | ICE_INSET_TUN_IPV4_DST)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV4 | ICE_INSET_TUN_UDP_SRC_PORT | \
+	ICE_INSET_TUN_UDP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV4 | ICE_INSET_TUN_TCP_SRC_PORT | \
+	ICE_INSET_TUN_TCP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6 (\
+	ICE_INSET_TUN_IPV6_SRC | ICE_INSET_TUN_IPV6_DST)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV6 | ICE_INSET_TUN_UDP_SRC_PORT | \
+	ICE_INSET_TUN_UDP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV6 | ICE_INSET_TUN_TCP_SRC_PORT | \
+	ICE_INSET_TUN_TCP_DST_PORT)
+
 static struct ice_pattern_match_item ice_fdir_supported_pattern[] = {
 	{pattern_raw,					ICE_INSET_NONE,			ICE_INSET_NONE,			ICE_INSET_NONE},
 	{pattern_ethertype,				ICE_FDIR_INSET_ETH,		ICE_INSET_NONE,			ICE_INSET_NONE},
@@ -132,10 +157,26 @@ static struct ice_pattern_match_item ice_fdir_supported_pattern[] = {
 	{pattern_eth_ipv4_udp_vxlan_eth_ipv4_tcp,	ICE_FDIR_INSET_ETH_IPV4_VXLAN,	ICE_FDIR_INSET_ETH_IPV4_TCP,	ICE_INSET_NONE},
 	{pattern_eth_ipv4_udp_vxlan_eth_ipv4_sctp,	ICE_FDIR_INSET_ETH_IPV4_VXLAN,	ICE_FDIR_INSET_ETH_IPV4_SCTP,	ICE_INSET_NONE},
 	/* duplicated GTPU input set in 3rd column to align with shared code behavior. Ideally, only put GTPU field in 2nd column. */
-	{pattern_eth_ipv4_gtpu,				ICE_FDIR_INSET_IPV4_GTPU,	ICE_FDIR_INSET_IPV4_GTPU,	ICE_INSET_NONE},
-	{pattern_eth_ipv4_gtpu_eh,			ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_INSET_NONE},
-	{pattern_eth_ipv6_gtpu,				ICE_FDIR_INSET_IPV6_GTPU,	ICE_FDIR_INSET_IPV6_GTPU,	ICE_INSET_NONE},
-	{pattern_eth_ipv6_gtpu_eh,			ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_gtpu,				ICE_FDIR_INSET_IPV4_GTPU,	ICE_FDIR_INSET_IPV4_GTPU,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_gtpu_eh,			ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_FDIR_INSET_IPV4_GTPU_EH,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_gtpu,				ICE_FDIR_INSET_IPV6_GTPU,	ICE_FDIR_INSET_IPV6_GTPU,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_gtpu_eh,			ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_FDIR_INSET_IPV6_GTPU_EH,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2,			ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp,		ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2,			ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp,		ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP,	ICE_INSET_NONE},
 };
 
 static int
@@ -957,6 +998,7 @@ ice_fdir_input_set_parse(uint64_t inset, enum ice_flow_field *field)
 		{ICE_INSET_VXLAN_VNI, ICE_FLOW_FIELD_IDX_VXLAN_VNI},
 		{ICE_INSET_ESP_SPI, ICE_FLOW_FIELD_IDX_ESP_SPI},
 		{ICE_INSET_NAT_T_ESP_SPI, ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI},
+		{ICE_INSET_L2TPV2OIP_SESSION_ID, ICE_FLOW_FIELD_IDX_L2TPV2_SESS_ID},
 	};
 
 	for (i = 0, j = 0; i < RTE_DIM(ice_inset_map); i++) {
@@ -1068,6 +1110,43 @@ ice_fdir_input_set_hdrs(enum ice_fltr_ptype flow, struct ice_flow_seg_info *seg)
 				  ICE_FLOW_SEG_HDR_IPV6 |
 				  ICE_FLOW_SEG_HDR_IPV_OTHER);
 		break;
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_IPV6 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_UDP:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_PPP |
+				  ICE_FLOW_SEG_HDR_IPV6 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_IPV4 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_UDP:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_PPP |
+				  ICE_FLOW_SEG_HDR_IPV4 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+
 	default:
 		PMD_DRV_LOG(ERR, "not supported filter type.");
 		break;
@@ -1170,7 +1249,10 @@ ice_fdir_uninit(struct ice_adapter *ad)
 static int
 ice_fdir_is_tunnel_profile(enum ice_fdir_tunnel_type tunnel_type)
 {
-	if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN)
+	if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_GTPU ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_GTPU_EH)
 		return 1;
 	else
 		return 0;
@@ -1239,6 +1321,9 @@ ice_fdir_extract_fltr_key(struct ice_fdir_fltr_pattern *key,
 	rte_memcpy(&key->gtpu_data, &input->gtpu_data, sizeof(key->gtpu_data));
 	rte_memcpy(&key->gtpu_mask, &input->gtpu_mask, sizeof(key->gtpu_mask));
 
+	rte_memcpy(&key->l2tpv2_data, &input->l2tpv2_data, sizeof(key->l2tpv2_data));
+	rte_memcpy(&key->l2tpv2_mask, &input->l2tpv2_mask, sizeof(key->l2tpv2_mask));
+
 	key->tunnel_type = filter->tunnel_type;
 }
 
@@ -1797,16 +1882,22 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 	const struct rte_flow_item_gtp *gtp_spec, *gtp_mask;
 	const struct rte_flow_item_gtp_psc *gtp_psc_spec, *gtp_psc_mask;
 	const struct rte_flow_item_esp *esp_spec, *esp_mask;
+	const struct rte_flow_item_l2tpv2 *l2tpv2_spec, *l2tpv2_mask;
+	const struct rte_flow_item_ppp *ppp_spec, *ppp_mask;
 	uint64_t input_set_i = ICE_INSET_NONE; /* only for tunnel inner */
 	uint64_t input_set_o = ICE_INSET_NONE; /* non-tunnel and tunnel outer */
 	uint64_t *input_set;
 	uint8_t flow_type = ICE_FLTR_PTYPE_NONF_NONE;
+	enum rte_flow_item_type inner_l3 = RTE_FLOW_ITEM_TYPE_END;
+	enum rte_flow_item_type inner_l4 = RTE_FLOW_ITEM_TYPE_END;
+	enum rte_flow_item_type current_l3 = RTE_FLOW_ITEM_TYPE_END;
+	bool ppp_present = false;
 	uint8_t  ipv6_addr_mask[16] = {
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
 	};
 	uint32_t vtc_flow_cpu;
-	uint16_t ether_type;
+	uint16_t ether_type = 0, flags_version = 0;
 	enum rte_flow_item_type next_type;
 	bool is_outer = true;
 	struct ice_fdir_extra *p_ext_data;
@@ -2001,22 +2092,30 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				   &eth_spec->hdr.ether_type, sizeof(eth_spec->hdr.ether_type));
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV4:
-			flow_type = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
-			l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			/* Only set flow_type for outer IPv4, track inner L3 for tunnels */
+			if (is_outer || !tunnel_type) {
+				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
+				l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			} else {
+				inner_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			}
+
 			ipv4_spec = item->spec;
 			ipv4_last = item->last;
 			ipv4_mask = item->mask;
 			p_v4 = (tunnel_type && is_outer) ?
-			       &filter->input.ip_outer.v4 :
-			       &filter->input.ip.v4;
+					&filter->input.ip_outer.v4 :
+					&filter->input.ip.v4;
 
 			if (!(ipv4_spec && ipv4_mask))
 				break;
 
 			/* Check IPv4 mask and update input set */
 			if (ipv4_mask->hdr.version_ihl ||
-			    ipv4_mask->hdr.total_length ||
-			    ipv4_mask->hdr.hdr_checksum) {
+				ipv4_mask->hdr.total_length ||
+				ipv4_mask->hdr.hdr_checksum) {
 				rte_flow_error_set(error, EINVAL,
 						   RTE_FLOW_ERROR_TYPE_ITEM,
 						   item,
@@ -2048,10 +2147,20 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				ipv4_mask->hdr.dst_addr != UINT32_MAX)
 				return -rte_errno;
 
-			if (ipv4_mask->hdr.dst_addr == UINT32_MAX)
-				*input_set |= ICE_INSET_IPV4_DST;
-			if (ipv4_mask->hdr.src_addr == UINT32_MAX)
-				*input_set |= ICE_INSET_IPV4_SRC;
+			if (ipv4_mask->hdr.dst_addr == UINT32_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV4_DST;
+				else
+					*input_set |= ICE_INSET_IPV4_DST;
+			}
+			if (ipv4_mask->hdr.src_addr == UINT32_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV4_SRC;
+				else
+					*input_set |= ICE_INSET_IPV4_SRC;
+			}
 			if (ipv4_mask->hdr.time_to_live == UINT8_MAX)
 				*input_set |= ICE_INSET_IPV4_TTL;
 			if (ipv4_mask->hdr.next_proto_id == UINT8_MAX)
@@ -2092,8 +2201,15 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV6:
-			flow_type = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
-			l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			if (is_outer || !tunnel_type) {
+				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
+				l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			} else {
+				inner_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			}
+
 			ipv6_spec = item->spec;
 			ipv6_mask = item->mask;
 			p_v6 = (tunnel_type && is_outer) ?
@@ -2113,15 +2229,24 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 			}
 
 			if (!memcmp(&ipv6_mask->hdr.src_addr, ipv6_addr_mask,
-				    sizeof(ipv6_mask->hdr.src_addr)))
-				*input_set |= ICE_INSET_IPV6_SRC;
+				    sizeof(ipv6_mask->hdr.src_addr))) {
+				if (tunnel_type && !is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV6_SRC;
+				else
+					*input_set |= ICE_INSET_IPV6_SRC;
+			}
 			if (!memcmp(&ipv6_mask->hdr.dst_addr, ipv6_addr_mask,
-				    sizeof(ipv6_mask->hdr.dst_addr)))
-				*input_set |= ICE_INSET_IPV6_DST;
-
+				    sizeof(ipv6_mask->hdr.dst_addr))) {
+				if (tunnel_type && !is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV6_DST;
+				else
+					*input_set |= ICE_INSET_IPV6_DST;
+			}
 			if ((ipv6_mask->hdr.vtc_flow &
-			     rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
-			    == rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
+			     rte_cpu_to_be_32(ICE_IPV6_TC_MASK)) ==
+			    rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
 				*input_set |= ICE_INSET_IPV6_TC;
 			if (ipv6_mask->hdr.proto == UINT8_MAX)
 				*input_set |= ICE_INSET_IPV6_NEXT_HDR;
@@ -2167,10 +2292,16 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 			break;
 
 		case RTE_FLOW_ITEM_TYPE_TCP:
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
+			if (!is_outer && tunnel_type) {
+				/* For inner TCP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_TCP;
+			} else {
+				/* For outer TCP, update flow_type normally */
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
+			}
 
 			tcp_spec = item->spec;
 			tcp_mask = item->mask;
@@ -2201,28 +2332,44 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				tcp_mask->hdr.dst_port != UINT16_MAX)
 				return -rte_errno;
 
-			if (tcp_mask->hdr.src_port == UINT16_MAX)
-				*input_set |= ICE_INSET_TCP_SRC_PORT;
-			if (tcp_mask->hdr.dst_port == UINT16_MAX)
-				*input_set |= ICE_INSET_TCP_DST_PORT;
+			if (tcp_mask->hdr.src_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_TCP_SRC_PORT;
+				else
+					*input_set |= ICE_INSET_TCP_SRC_PORT;
+			}
+			if (tcp_mask->hdr.dst_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_TCP_DST_PORT;
+				else
+					*input_set |= ICE_INSET_TCP_DST_PORT;
+			}
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = tcp_spec->hdr.dst_port;
 				p_v4->src_port = tcp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->dst_port = tcp_spec->hdr.dst_port;
 				p_v6->src_port = tcp_spec->hdr.src_port;
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_UDP:
-			l4 = RTE_FLOW_ITEM_TYPE_UDP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
+			if (!is_outer && tunnel_type) {
+				/* For inner UDP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_UDP;
+			} else {
+				/* For outer UDP, update flow_type normally */
+				l4 = RTE_FLOW_ITEM_TYPE_UDP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
+			}
 
 			udp_spec = item->spec;
 			udp_mask = item->mask;
@@ -2248,27 +2395,43 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				udp_mask->hdr.dst_port != UINT16_MAX)
 				return -rte_errno;
 
-			if (udp_mask->hdr.src_port == UINT16_MAX)
-				*input_set |= ICE_INSET_UDP_SRC_PORT;
-			if (udp_mask->hdr.dst_port == UINT16_MAX)
-				*input_set |= ICE_INSET_UDP_DST_PORT;
+			if (udp_mask->hdr.src_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_UDP_SRC_PORT;
+				else
+					*input_set |= ICE_INSET_UDP_SRC_PORT;
+			}
+			if (udp_mask->hdr.dst_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_UDP_DST_PORT;
+				else
+					*input_set |= ICE_INSET_UDP_DST_PORT;
+			}
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = udp_spec->hdr.dst_port;
 				p_v4->src_port = udp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->src_port = udp_spec->hdr.src_port;
 				p_v6->dst_port = udp_spec->hdr.dst_port;
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_SCTP:
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
+			if (!is_outer && tunnel_type) {
+				/* For inner SCTP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_SCTP;
+			} else {
+				/* For outer SCTP, update flow_type normally */
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
+			}
 
 			sctp_spec = item->spec;
 			sctp_mask = item->mask;
@@ -2299,11 +2462,11 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				*input_set |= ICE_INSET_SCTP_DST_PORT;
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = sctp_spec->hdr.dst_port;
 				p_v4->src_port = sctp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->dst_port = sctp_spec->hdr.dst_port;
 				p_v6->src_port = sctp_spec->hdr.src_port;
@@ -2406,6 +2569,115 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				filter->input.ip.v6.sec_parm_idx =
 					esp_spec->hdr.spi;
 			break;
+		case RTE_FLOW_ITEM_TYPE_L2TPV2: {
+			struct ice_fdir_l2tpv2 l2tpv2_be;
+
+			l2tpv2_spec = item->spec;
+			l2tpv2_mask = item->mask;
+
+			if (!(l2tpv2_spec && l2tpv2_mask))
+				break;
+
+			flags_version =
+				rte_be_to_cpu_16(l2tpv2_spec->hdr.common.flags_version);
+			if ((flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+			     l2tpv2_mask->hdr.type3.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA &&
+			     l2tpv2_mask->hdr.type7.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L &&
+			     l2tpv2_mask->hdr.type6.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S &&
+			     l2tpv2_mask->hdr.type5.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_O &&
+			     l2tpv2_mask->hdr.type4.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S &&
+			     l2tpv2_mask->hdr.type3.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_O &&
+			     l2tpv2_mask->hdr.type2.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S_O &&
+			     l2tpv2_mask->hdr.type1.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S_O &&
+			     l2tpv2_mask->hdr.type0.session_id == UINT16_MAX)) {
+				input_set_o |= ICE_INSET_L2TPV2OIP_SESSION_ID;
+			}
+
+			tunnel_type = ICE_FDIR_TUNNEL_TYPE_L2TPV2;
+			memset(&l2tpv2_be, 0, sizeof(l2tpv2_be));
+
+			if (flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type7.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type7.session_id);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.session_id);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_O) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.session_id);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_O) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.session_id);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S_O) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.nr);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S_O) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.nr);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.offset_size);
+			}
+
+			/* Copy converted values to filter */
+			filter->input.l2tpv2_data.flags_version = rte_cpu_to_be_16(flags_version);
+			filter->input.l2tpv2_data.length = l2tpv2_be.length;
+			filter->input.l2tpv2_data.tunnel_id = l2tpv2_be.tunnel_id;
+			filter->input.l2tpv2_data.session_id = l2tpv2_be.session_id;
+			filter->input.l2tpv2_data.ns = l2tpv2_be.ns;
+			filter->input.l2tpv2_data.nr = l2tpv2_be.nr;
+			filter->input.l2tpv2_data.offset_size = l2tpv2_be.offset_size;
+			break;
+		}
+		case RTE_FLOW_ITEM_TYPE_PPP:
+			ppp_spec = item->spec;
+			ppp_mask = item->mask;
+
+			/* PPP marks transition from outer to inner in L2TPv2 tunnels */
+			if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2) {
+				is_outer = false;
+				ppp_present = true;
+			}
+
+			if (ppp_spec && ppp_mask) {
+				filter->input.ppp_data.addr = ppp_spec->hdr.addr;
+				filter->input.ppp_data.ctrl = ppp_spec->hdr.ctrl;
+				filter->input.ppp_data.proto_id = ppp_spec->hdr.proto_id;
+			}
+			break;
 		default:
 			rte_flow_error_set(error, EINVAL,
 					   RTE_FLOW_ERROR_TYPE_ITEM,
@@ -2439,6 +2711,74 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN &&
 		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
 		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP_VXLAN_IPV4_OTHER;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP &&
+		flags_version != RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP &&
+		flags_version != RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP &&
+		flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP &&
+		flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL;
+	/* Handle L2TPV2 with PPP and inner protocols */
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		ppp_present &&
+		inner_l3 != RTE_FLOW_ITEM_TYPE_END) {
+		/* L2TPV2 with inner IPv4/IPv6 */
+		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP) {
+			/* Outer IPv4 + inner protocol */
+			if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4;
+			} else if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6;
+			}
+		} else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP) {
+			/* Outer IPv6 + inner protocol */
+			if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4;
+			} else if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6;
+			}
+		}
+	} else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 && ppp_present &&
+		inner_l3 == RTE_FLOW_ITEM_TYPE_END) {
+		/* Handle L2TPV2 with PPP but no inner protocol specified */
+		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP)
+			flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP;
+		else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP)
+			flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP;
+	}
 
 	filter->tunnel_type = tunnel_type;
 	filter->input.flow_type = flow_type;
@@ -2482,9 +2822,10 @@ ice_fdir_parse(struct ice_adapter *ad,
 	input_set = filter->input_set_o | filter->input_set_i;
 	input_set = raw ? ~input_set : input_set;
 
-	if (!input_set || filter->input_set_o &
-	    ~(item->input_set_mask_o | ICE_INSET_ETHERTYPE) ||
-	    filter->input_set_i & ~item->input_set_mask_i) {
+	if (!input_set ||
+	    (filter->input_set_o &
+	     ~(item->input_set_mask_o | ICE_INSET_ETHERTYPE)) ||
+	    (filter->input_set_i & ~item->input_set_mask_i)) {
 		rte_flow_error_set(error, EINVAL,
 				   RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
 				   pattern,
diff --git a/drivers/net/intel/ice/ice_generic_flow.c b/drivers/net/intel/ice/ice_generic_flow.c
index 4049157eab..644958cccf 100644
--- a/drivers/net/intel/ice/ice_generic_flow.c
+++ b/drivers/net/intel/ice/ice_generic_flow.c
@@ -1794,6 +1794,166 @@ enum rte_flow_item_type pattern_eth_ipv6_pfcp[] = {
 	RTE_FLOW_ITEM_TYPE_PFCP,
 	RTE_FLOW_ITEM_TYPE_END,
 };
+enum rte_flow_item_type pattern_eth_ipv4_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+/* PPPoL2TPv2oUDP */
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 
 typedef bool (*parse_engine_t)(struct ice_adapter *ad,
 			       struct rte_flow *flow,
@@ -2021,6 +2181,23 @@ static struct ice_ptype_match ice_ptype_map[] = {
 	{pattern_eth_ipv4_udp_esp,			ICE_MAC_IPV4_NAT_T_ESP},
 	{pattern_eth_ipv4_ah,				ICE_MAC_IPV4_AH},
 	{pattern_eth_ipv4_l2tp,				ICE_MAC_IPV4_L2TPV3},
+	{pattern_eth_ipv4_udp_l2tpv2,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp,	ICE_MAC_IPV6_L2TPV2},
+
 	{pattern_eth_ipv4_pfcp,				ICE_MAC_IPV4_PFCP_SESSION},
 	{pattern_eth_ipv6,				ICE_PTYPE_IPV6_PAY},
 	{pattern_eth_ipv6_udp,				ICE_PTYPE_IPV6_UDP_PAY},
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v4 5/7] net/ice: add L2TPv2 hardware packet generation
  2025-08-26 16:26 ` [PATCH v3 0/7] " Shaiq Wani
                     ` (3 preceding siblings ...)
  2025-08-26 16:27   ` [PATCH v4 4/7] net/ice: add L2TPv2 flow patterns and FDIR support Shaiq Wani
@ 2025-08-26 16:27   ` Shaiq Wani
  2025-08-26 16:27   ` [PATCH v4 6/7] net/ice: add L2TPv2 RSS hash support Shaiq Wani
  2025-08-26 16:27   ` [PATCH v4 7/7] doc: update release notes Shaiq Wani
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2025-08-26 16:27 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add L2TPv2 packet type cases to ice_fdir_get_gen_prgm_pkt() to enable
hardware packet generation for FDIR rule programming.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/base/ice_fdir.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/intel/ice/base/ice_fdir.c b/drivers/net/intel/ice/base/ice_fdir.c
index f62313c559..2c0cb99854 100644
--- a/drivers/net/intel/ice/base/ice_fdir.c
+++ b/drivers/net/intel/ice/base/ice_fdir.c
@@ -4027,6 +4027,9 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
 				   ICE_NONDMA_TO_NONDMA);
 			loc = &pkt[ICE_FDIR_V6_V4_GTPOGRE_EH_PKT_OFF];
 			break;
+		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL:
+		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2:
+		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP:
 		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4:
 		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP:
 		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP:
@@ -4038,6 +4041,9 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
 						      idx, offset, tun);
 			loc = &pkt[pos];
 			break;
+		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL:
+		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2:
+		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP:
 		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4:
 		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP:
 		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP:
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v4 6/7] net/ice: add L2TPv2 RSS hash support
  2025-08-26 16:26 ` [PATCH v3 0/7] " Shaiq Wani
                     ` (4 preceding siblings ...)
  2025-08-26 16:27   ` [PATCH v4 5/7] net/ice: add L2TPv2 hardware packet generation Shaiq Wani
@ 2025-08-26 16:27   ` Shaiq Wani
  2025-08-26 16:27   ` [PATCH v4 7/7] doc: update release notes Shaiq Wani
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2025-08-26 16:27 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add RSS (Receive Side Scaling) hash support for L2TPv2 packets.
define hash templates and patterns for distributing L2TPv2 traffic
across multiple receive queues based on session IDs and inner headers.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_hash.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/net/intel/ice/ice_hash.c b/drivers/net/intel/ice/ice_hash.c
index afdc8f220a..b20103a452 100644
--- a/drivers/net/intel/ice/ice_hash.c
+++ b/drivers/net/intel/ice/ice_hash.c
@@ -305,6 +305,22 @@ struct ice_rss_hash_cfg eth_ipv4_l2tpv3_tmplt = {
 	0
 };
 
+struct ice_rss_hash_cfg eth_ipv4_l2tpv2_tmplt = {
+	ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
+	ICE_FLOW_SEG_HDR_L2TPV2,
+	ICE_FLOW_HASH_L2TPV2_SESS_ID,
+	ICE_RSS_OUTER_HEADERS,
+	0
+};
+
+struct ice_rss_hash_cfg eth_ipv6_l2tpv2_tmplt = {
+	ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_IPV_OTHER |
+	ICE_FLOW_SEG_HDR_L2TPV2,
+	ICE_FLOW_HASH_L2TPV2_SESS_ID,
+	ICE_RSS_OUTER_HEADERS,
+	0
+};
+
 struct ice_rss_hash_cfg eth_ipv4_pfcp_tmplt = {
 	ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
 	ICE_FLOW_SEG_HDR_PFCP_SESSION,
@@ -480,6 +496,8 @@ struct ice_rss_hash_cfg eth_tmplt = {
 #define ICE_RSS_TYPE_IPV6_AH		(RTE_ETH_RSS_AH | RTE_ETH_RSS_IPV6)
 #define ICE_RSS_TYPE_IPV4_L2TPV3	(RTE_ETH_RSS_L2TPV3 | RTE_ETH_RSS_IPV4)
 #define ICE_RSS_TYPE_IPV6_L2TPV3	(RTE_ETH_RSS_L2TPV3 | RTE_ETH_RSS_IPV6)
+#define ICE_RSS_TYPE_IPV4_L2TPV2	(RTE_ETH_RSS_L2TPV2 | RTE_ETH_RSS_IPV4)
+#define ICE_RSS_TYPE_IPV6_L2TPV2	(RTE_ETH_RSS_L2TPV2 | RTE_ETH_RSS_IPV6)
 #define ICE_RSS_TYPE_IPV4_PFCP		(RTE_ETH_RSS_PFCP | RTE_ETH_RSS_IPV4)
 #define ICE_RSS_TYPE_IPV6_PFCP		(RTE_ETH_RSS_PFCP | RTE_ETH_RSS_IPV6)
 
@@ -522,6 +540,8 @@ static struct ice_pattern_match_item ice_hash_pattern_list[] = {
 	{pattern_eth_ipv4_udp_esp,		ICE_RSS_TYPE_IPV4_ESP,		ICE_INSET_NONE,	&eth_ipv4_udp_esp_tmplt},
 	{pattern_eth_ipv4_ah,			ICE_RSS_TYPE_IPV4_AH,		ICE_INSET_NONE,	&eth_ipv4_ah_tmplt},
 	{pattern_eth_ipv4_l2tp,			ICE_RSS_TYPE_IPV4_L2TPV3,	ICE_INSET_NONE,	&eth_ipv4_l2tpv3_tmplt},
+	{pattern_eth_ipv4_l2tpv2,		ICE_RSS_TYPE_IPV4_L2TPV2,	ICE_INSET_NONE,	&eth_ipv4_l2tpv2_tmplt},
+	{pattern_eth_ipv6_l2tpv2,		ICE_RSS_TYPE_IPV6_L2TPV2,	ICE_INSET_NONE,	&eth_ipv6_l2tpv2_tmplt},
 	{pattern_eth_ipv4_pfcp,			ICE_RSS_TYPE_IPV4_PFCP,		ICE_INSET_NONE,	&eth_ipv4_pfcp_tmplt},
 	/* IPV6 */
 	{pattern_eth_ipv6,			ICE_RSS_TYPE_ETH_IPV6,		ICE_INSET_NONE,	&ipv6_tmplt},
@@ -925,6 +945,11 @@ ice_refine_hash_cfg_l234(struct ice_rss_hash_cfg *hash_cfg,
 			*hash_flds &= ~ICE_FLOW_HASH_L2TPV3_SESS_ID;
 	}
 
+	if (*addl_hdrs & ICE_FLOW_SEG_HDR_L2TPV2) {
+		if (!(rss_type & RTE_ETH_RSS_L2TPV2))
+			*hash_flds &= ~ICE_FLOW_HASH_L2TPV2_SESS_ID;
+	}
+
 	if (*addl_hdrs & ICE_FLOW_SEG_HDR_ESP) {
 		if (!(rss_type & RTE_ETH_RSS_ESP))
 			*hash_flds &= ~ICE_FLOW_HASH_ESP_SPI;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v4 7/7] doc: update release notes
  2025-08-26 16:26 ` [PATCH v3 0/7] " Shaiq Wani
                     ` (5 preceding siblings ...)
  2025-08-26 16:27   ` [PATCH v4 6/7] net/ice: add L2TPv2 RSS hash support Shaiq Wani
@ 2025-08-26 16:27   ` Shaiq Wani
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2025-08-26 16:27 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh

Add L2TPv2 over UDP support for ice PMD in the release notes.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
---
 doc/guides/rel_notes/release_26_03.rst | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/doc/guides/rel_notes/release_26_03.rst b/doc/guides/rel_notes/release_26_03.rst
index 5c2a4bb32e..d312c47531 100644
--- a/doc/guides/rel_notes/release_26_03.rst
+++ b/doc/guides/rel_notes/release_26_03.rst
@@ -67,6 +67,10 @@ New Features
 
   * Added support for pre and post VF reset callbacks.
 
+* **Updated Intel ice driver.**
+
+  * Added Flow Director (FDIR) support for L2TPv2 over UDP.
+
 * **Updated ZTE zxdh ethernet driver.**
 
   * Added support for modifying queue depth.
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v5 0/7]  Add support for L2TPV2 over UDP to ICE PMD
  2026-02-02  9:42 [PATCH 0/6] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
  2025-08-26 16:26 ` [PATCH v3 0/7] " Shaiq Wani
@ 2025-08-26 17:05 ` Shaiq Wani
  2025-08-26 17:05   ` [PATCH v5 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
                     ` (6 more replies)
  2026-02-02  9:42 ` [PATCH 1/6] net/ice: add L2TPv2 and PPP data structures Shaiq Wani
                   ` (7 subsequent siblings)
  9 siblings, 7 replies; 56+ messages in thread
From: Shaiq Wani @ 2025-08-26 17:05 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh

This patchset adds L2TPv2 protocol support to the ICE PMD
enabling RSS and Flow Director capabilities for L2TPv2 over UDP traffic.

v5: Resending v4 patches with correct cover letter and threading. 

v4: *Version 3 patchset was incomplete due to a server reboot.
     *V4 includes all patches for review.

v3: Fixed compilation issues.
v2: Addressed AI generated comments.

Shaiq Wani (7):
  net/ice: add L2TPv2 PPP and PPoE data structures
  net/ice: add L2TPv2 tunnel type definition
  net/ice: add L2TPv2 protocol and field definitions
  net/ice: add L2TPv2 flow patterns and FDIR support
  net/ice: add L2TPv2 hardware packet generation
  net/ice: add L2TPv2 RSS hash support
  doc: update release notes

 doc/guides/rel_notes/release_26_03.rst   |   4 +
 drivers/net/intel/ice/base/ice_fdir.c    |   6 +
 drivers/net/intel/ice/base/ice_fdir.h    |  17 +
 drivers/net/intel/ice/ice_ethdev.h       |   4 +
 drivers/net/intel/ice/ice_fdir_filter.c  | 451 ++++++++++++++++++++---
 drivers/net/intel/ice/ice_generic_flow.c | 177 +++++++++
 drivers/net/intel/ice/ice_generic_flow.h | 129 ++++---
 drivers/net/intel/ice/ice_hash.c         |  25 ++
 8 files changed, 717 insertions(+), 96 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH v5 1/7] net/ice: add L2TPv2 PPP and PPoE data structures
  2025-08-26 17:05 ` [PATCH v5 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
@ 2025-08-26 17:05   ` Shaiq Wani
  2025-08-26 17:05   ` [PATCH v5 2/7] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2025-08-26 17:05 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add data structure definitions for L2TPv2 PPP and
PPoE protocols to support Flow Director (FDIR) filtering.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/base/ice_fdir.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/net/intel/ice/base/ice_fdir.h b/drivers/net/intel/ice/base/ice_fdir.h
index 3dd03f93f7..3d3b05da4a 100644
--- a/drivers/net/intel/ice/base/ice_fdir.h
+++ b/drivers/net/intel/ice/base/ice_fdir.h
@@ -230,6 +230,20 @@ struct ice_fdir_ecpri {
 	__be16 pc_id;
 };
 
+struct ice_fdir_pppoe {
+	u8 rsrvd_ver_type;
+	u8 rsrvd_code;
+	__be16 session_id;
+	__be16 length;
+	__be16 ppp_prot_id; /* control and data only */
+};
+
+struct ice_fdir_ppp {
+	u8 addr;
+	u8 ctrl;
+	__be16 proto_id;
+};
+
 struct ice_fdir_l2tpv2 {
 	__be16 flags_version;
 	__be16 length;
@@ -279,6 +293,9 @@ struct ice_fdir_fltr {
 	struct ice_fdir_ecpri ecpri_data;
 	struct ice_fdir_ecpri ecpri_mask;
 
+	struct ice_fdir_ppp ppp_data;
+	struct ice_fdir_ppp ppp_mask;
+
 	struct ice_fdir_l2tpv2 l2tpv2_data;
 	struct ice_fdir_l2tpv2 l2tpv2_mask;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v5 2/7] net/ice: add L2TPv2 tunnel type definition
  2025-08-26 17:05 ` [PATCH v5 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
  2025-08-26 17:05   ` [PATCH v5 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
@ 2025-08-26 17:05   ` Shaiq Wani
  2025-08-26 17:05   ` [PATCH v5 3/7] net/ice: add L2TPv2 protocol and field definitions Shaiq Wani
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2025-08-26 17:05 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add ICE_FDIR_TUNNEL_TYPE_L2TPV2 to the tunnel type enum and
extend ice_fdir_fltr_pattern structure to include L2TPv2 data and
mask fields.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_ethdev.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/intel/ice/ice_ethdev.h b/drivers/net/intel/ice/ice_ethdev.h
index 9562b2b8f1..4b3718f715 100644
--- a/drivers/net/intel/ice/ice_ethdev.h
+++ b/drivers/net/intel/ice/ice_ethdev.h
@@ -369,6 +369,7 @@ enum ice_fdir_tunnel_type {
 	ICE_FDIR_TUNNEL_TYPE_VXLAN,
 	ICE_FDIR_TUNNEL_TYPE_GTPU,
 	ICE_FDIR_TUNNEL_TYPE_GTPU_EH,
+	ICE_FDIR_TUNNEL_TYPE_L2TPV2,
 };
 
 struct rte_flow;
@@ -405,6 +406,9 @@ struct ice_fdir_fltr_pattern {
 	struct ice_fdir_udp_gtp gtpu_data;
 	struct ice_fdir_udp_gtp gtpu_mask;
 
+	struct ice_fdir_l2tpv2 l2tpv2_data;
+	struct ice_fdir_l2tpv2 l2tpv2_mask;
+
 	struct ice_fdir_extra ext_data;
 	struct ice_fdir_extra ext_mask;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v5 3/7] net/ice: add L2TPv2 protocol and field definitions
  2025-08-26 17:05 ` [PATCH v5 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
  2025-08-26 17:05   ` [PATCH v5 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
  2025-08-26 17:05   ` [PATCH v5 2/7] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
@ 2025-08-26 17:05   ` Shaiq Wani
  2026-02-17 17:09     ` Bruce Richardson
  2025-08-26 17:05   ` [PATCH v5 4/7] net/ice: add L2TPv2 flow patterns and FDIR support Shaiq Wani
                     ` (3 subsequent siblings)
  6 siblings, 1 reply; 56+ messages in thread
From: Shaiq Wani @ 2025-08-26 17:05 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add L2TPv2 protocol identifier (ICE_PROT_L2TPV2OIP) and session ID
field definition (ICE_L2TPV2OIP_SESSION_ID) to the generic flow header.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_generic_flow.h | 129 ++++++++++++++++-------
 1 file changed, 88 insertions(+), 41 deletions(-)

diff --git a/drivers/net/intel/ice/ice_generic_flow.h b/drivers/net/intel/ice/ice_generic_flow.h
index 54bbb47398..deaf7b66e5 100644
--- a/drivers/net/intel/ice/ice_generic_flow.h
+++ b/drivers/net/intel/ice/ice_generic_flow.h
@@ -9,15 +9,15 @@
 
 /* protocol */
 
-#define ICE_PROT_MAC			BIT_ULL(1)
-#define ICE_PROT_VLAN			BIT_ULL(2)
-#define ICE_PROT_IPV4			BIT_ULL(3)
-#define ICE_PROT_IPV6			BIT_ULL(4)
-#define ICE_PROT_TCP			BIT_ULL(5)
-#define ICE_PROT_UDP			BIT_ULL(6)
-#define ICE_PROT_SCTP			BIT_ULL(7)
-#define ICE_PROT_ICMP4			BIT_ULL(8)
-#define ICE_PROT_ICMP6			BIT_ULL(9)
+#define ICE_PROT_MAC_OUTER		BIT_ULL(1)
+#define ICE_PROT_VLAN_OUTER		BIT_ULL(2)
+#define ICE_PROT_IPV4_OUTER		BIT_ULL(3)
+#define ICE_PROT_IPV6_OUTER		BIT_ULL(4)
+#define ICE_PROT_TCP_OUTER		BIT_ULL(5)
+#define ICE_PROT_UDP_OUTER		BIT_ULL(6)
+#define ICE_PROT_SCTP_OUTER		BIT_ULL(7)
+#define ICE_PROT_ICMP4_OUTER		BIT_ULL(8)
+#define ICE_PROT_ICMP6_OUTER		BIT_ULL(9)
 #define ICE_PROT_VXLAN			BIT_ULL(10)
 #define ICE_PROT_NVGRE			BIT_ULL(11)
 #define ICE_PROT_GTPU			BIT_ULL(12)
@@ -27,6 +27,16 @@
 #define ICE_PROT_L2TPV3OIP		BIT_ULL(16)
 #define ICE_PROT_PFCP			BIT_ULL(17)
 #define ICE_PROT_NAT_T_ESP		BIT_ULL(18)
+#define ICE_PROT_L2TPV2OIP		BIT_ULL(19)
+#define ICE_PROT_MAC_INNER		BIT_ULL(20)
+#define ICE_PROT_VLAN_INNER		BIT_ULL(21)
+#define ICE_PROT_IPV4_INNER		BIT_ULL(22)
+#define ICE_PROT_IPV6_INNER		BIT_ULL(23)
+#define ICE_PROT_TCP_INNER		BIT_ULL(24)
+#define ICE_PROT_UDP_INNER		BIT_ULL(25)
+#define ICE_PROT_SCTP_INNER		BIT_ULL(26)
+#define ICE_PROT_ICMP4_INNER		BIT_ULL(27)
+#define ICE_PROT_ICMP6_INNER		BIT_ULL(28)
 
 /* field */
 
@@ -53,8 +63,9 @@
 #define ICE_L2TPV3OIP_SESSION_ID	BIT_ULL(43)
 #define ICE_PFCP_SEID			BIT_ULL(42)
 #define ICE_PFCP_S_FIELD		BIT_ULL(41)
-#define ICE_IP_PK_ID		    BIT_ULL(40)
+#define ICE_IP_PK_ID			BIT_ULL(40)
 #define ICE_IP_FRAG_OFS			BIT_ULL(39)
+#define ICE_L2TPV2OIP_SESSION_ID	BIT_ULL(38)
 
 /* input set */
 
@@ -62,39 +73,39 @@
 
 #define ICE_INSET_SMAC			(ICE_SMAC)
 #define ICE_INSET_DMAC			(ICE_DMAC)
-#define ICE_INSET_VLAN			(ICE_PROT_VLAN)
-#define ICE_INSET_VLAN_INNER		(ICE_PROT_VLAN)
-#define ICE_INSET_VLAN_OUTER		(ICE_PROT_VLAN)
+#define ICE_INSET_VLAN			(ICE_PROT_VLAN_OUTER)
+#define ICE_INSET_VLAN_INNER		(ICE_PROT_VLAN_OUTER)
+#define ICE_INSET_VLAN_OUTER		(ICE_PROT_VLAN_OUTER)
 #define ICE_INSET_ETHERTYPE		(ICE_ETHERTYPE)
 
-#define ICE_INSET_IPV4_SRC		(ICE_PROT_IPV4 | ICE_IP_SRC)
-#define ICE_INSET_IPV4_DST		(ICE_PROT_IPV4 | ICE_IP_DST)
-#define ICE_INSET_IPV4_TOS		(ICE_PROT_IPV4 | ICE_IP_TOS)
-#define ICE_INSET_IPV4_PROTO		(ICE_PROT_IPV4 | ICE_IP_PROTO)
-#define ICE_INSET_IPV4_TTL		(ICE_PROT_IPV4 | ICE_IP_TTL)
-#define ICE_INSET_IPV4_PKID		(ICE_PROT_IPV4 | ICE_IP_PK_ID)
-#define ICE_INSET_IPV4_FRAG_OFS	(ICE_PROT_IPV4 | ICE_IP_FRAG_OFS)
-#define ICE_INSET_IPV6_SRC		(ICE_PROT_IPV6 | ICE_IP_SRC)
-#define ICE_INSET_IPV6_DST		(ICE_PROT_IPV6 | ICE_IP_DST)
-#define ICE_INSET_IPV6_NEXT_HDR		(ICE_PROT_IPV6 | ICE_IP_PROTO)
-#define ICE_INSET_IPV6_HOP_LIMIT	(ICE_PROT_IPV6 | ICE_IP_TTL)
-#define ICE_INSET_IPV6_TC		(ICE_PROT_IPV6 | ICE_IP_TOS)
-#define ICE_INSET_IPV6_PKID		(ICE_PROT_IPV6 | ICE_IP_PK_ID)
-
-#define ICE_INSET_TCP_SRC_PORT		(ICE_PROT_TCP | ICE_SPORT)
-#define ICE_INSET_TCP_DST_PORT		(ICE_PROT_TCP | ICE_DPORT)
-#define ICE_INSET_UDP_SRC_PORT		(ICE_PROT_UDP | ICE_SPORT)
-#define ICE_INSET_UDP_DST_PORT		(ICE_PROT_UDP | ICE_DPORT)
-#define ICE_INSET_SCTP_SRC_PORT		(ICE_PROT_SCTP | ICE_SPORT)
-#define ICE_INSET_SCTP_DST_PORT		(ICE_PROT_SCTP | ICE_DPORT)
-#define ICE_INSET_ICMP4_SRC_PORT	(ICE_PROT_ICMP4 | ICE_SPORT)
-#define ICE_INSET_ICMP4_DST_PORT	(ICE_PROT_ICMP4 | ICE_DPORT)
-#define ICE_INSET_ICMP6_SRC_PORT	(ICE_PROT_ICMP6 | ICE_SPORT)
-#define ICE_INSET_ICMP6_DST_PORT	(ICE_PROT_ICMP6 | ICE_DPORT)
-#define ICE_INSET_ICMP4_TYPE		(ICE_PROT_ICMP4 | ICE_ICMP_TYPE)
-#define ICE_INSET_ICMP4_CODE		(ICE_PROT_ICMP4 | ICE_ICMP_CODE)
-#define ICE_INSET_ICMP6_TYPE		(ICE_PROT_ICMP6 | ICE_ICMP_TYPE)
-#define ICE_INSET_ICMP6_CODE		(ICE_PROT_ICMP6 | ICE_ICMP_CODE)
+#define ICE_INSET_IPV4_SRC		(ICE_PROT_IPV4_OUTER | ICE_IP_SRC)
+#define ICE_INSET_IPV4_DST		(ICE_PROT_IPV4_OUTER | ICE_IP_DST)
+#define ICE_INSET_IPV4_TOS		(ICE_PROT_IPV4_OUTER | ICE_IP_TOS)
+#define ICE_INSET_IPV4_PROTO		(ICE_PROT_IPV4_OUTER | ICE_IP_PROTO)
+#define ICE_INSET_IPV4_TTL		(ICE_PROT_IPV4_OUTER | ICE_IP_TTL)
+#define ICE_INSET_IPV4_PKID		(ICE_PROT_IPV4_OUTER | ICE_IP_PK_ID)
+#define ICE_INSET_IPV4_FRAG_OFS	(ICE_PROT_IPV4_OUTER | ICE_IP_FRAG_OFS)
+#define ICE_INSET_IPV6_SRC		(ICE_PROT_IPV6_OUTER | ICE_IP_SRC)
+#define ICE_INSET_IPV6_DST		(ICE_PROT_IPV6_OUTER | ICE_IP_DST)
+#define ICE_INSET_IPV6_NEXT_HDR		(ICE_PROT_IPV6_OUTER | ICE_IP_PROTO)
+#define ICE_INSET_IPV6_HOP_LIMIT	(ICE_PROT_IPV6_OUTER | ICE_IP_TTL)
+#define ICE_INSET_IPV6_TC		(ICE_PROT_IPV6_OUTER | ICE_IP_TOS)
+#define ICE_INSET_IPV6_PKID		(ICE_PROT_IPV6_OUTER | ICE_IP_PK_ID)
+
+#define ICE_INSET_TCP_SRC_PORT		(ICE_PROT_TCP_OUTER | ICE_SPORT)
+#define ICE_INSET_TCP_DST_PORT		(ICE_PROT_TCP_OUTER | ICE_DPORT)
+#define ICE_INSET_UDP_SRC_PORT		(ICE_PROT_UDP_OUTER | ICE_SPORT)
+#define ICE_INSET_UDP_DST_PORT		(ICE_PROT_UDP_OUTER | ICE_DPORT)
+#define ICE_INSET_SCTP_SRC_PORT		(ICE_PROT_SCTP_OUTER | ICE_SPORT)
+#define ICE_INSET_SCTP_DST_PORT		(ICE_PROT_SCTP_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP4_SRC_PORT	(ICE_PROT_ICMP4_OUTER | ICE_SPORT)
+#define ICE_INSET_ICMP4_DST_PORT	(ICE_PROT_ICMP4_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP6_SRC_PORT	(ICE_PROT_ICMP6_OUTER | ICE_SPORT)
+#define ICE_INSET_ICMP6_DST_PORT	(ICE_PROT_ICMP6_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP4_TYPE		(ICE_PROT_ICMP4_OUTER | ICE_ICMP_TYPE)
+#define ICE_INSET_ICMP4_CODE		(ICE_PROT_ICMP4_OUTER | ICE_ICMP_CODE)
+#define ICE_INSET_ICMP6_TYPE		(ICE_PROT_ICMP6_OUTER | ICE_ICMP_TYPE)
+#define ICE_INSET_ICMP6_CODE		(ICE_PROT_ICMP6_OUTER | ICE_ICMP_CODE)
 
 /* tunnel */
 
@@ -122,6 +133,24 @@
 	(ICE_PROT_PFCP | ICE_PFCP_S_FIELD | ICE_PFCP_SEID)
 #define ICE_INSET_NAT_T_ESP_SPI \
 	(ICE_PROT_NAT_T_ESP | ICE_ESP_SPI)
+#define ICE_INSET_L2TPV2OIP_SESSION_ID \
+	(ICE_PROT_L2TPV2OIP | ICE_L2TPV2OIP_SESSION_ID)
+#define ICE_INSET_TUN_IPV4_SRC \
+	(ICE_PROT_IPV4_INNER | ICE_IP_SRC)
+#define ICE_INSET_TUN_IPV4_DST \
+	(ICE_PROT_IPV4_INNER | ICE_IP_DST)
+#define ICE_INSET_TUN_UDP_SRC_PORT \
+	(ICE_PROT_UDP_INNER | ICE_SPORT)
+#define ICE_INSET_TUN_UDP_DST_PORT \
+	(ICE_PROT_UDP_INNER | ICE_DPORT)
+#define ICE_INSET_TUN_TCP_SRC_PORT \
+	(ICE_PROT_TCP_INNER | ICE_SPORT)
+#define ICE_INSET_TUN_TCP_DST_PORT \
+	(ICE_PROT_TCP_INNER | ICE_DPORT)
+#define ICE_INSET_TUN_IPV6_SRC \
+	(ICE_PROT_IPV6_INNER | ICE_IP_SRC)
+#define ICE_INSET_TUN_IPV6_DST \
+	(ICE_PROT_IPV6_INNER | ICE_IP_DST)
 
 /* empty pattern */
 extern enum rte_flow_item_type pattern_empty[];
@@ -400,6 +429,24 @@ extern enum rte_flow_item_type pattern_eth_ipv6_udp_ah[];
 /* L2TP */
 extern enum rte_flow_item_type pattern_eth_ipv4_l2tp[];
 extern enum rte_flow_item_type pattern_eth_ipv6_l2tp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv6_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp[];
 
 /* PFCP */
 extern enum rte_flow_item_type pattern_eth_ipv4_pfcp[];
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v5 4/7] net/ice: add L2TPv2 flow patterns and FDIR support
  2025-08-26 17:05 ` [PATCH v5 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                     ` (2 preceding siblings ...)
  2025-08-26 17:05   ` [PATCH v5 3/7] net/ice: add L2TPv2 protocol and field definitions Shaiq Wani
@ 2025-08-26 17:05   ` Shaiq Wani
  2025-08-26 17:05   ` [PATCH v5 5/7] net/ice: add L2TPv2 hardware packet generation Shaiq Wani
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2025-08-26 17:05 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Implement comprehensive L2TPv2 support for Flow Director
-Flow pattern definitions for different L2TPv2 packet combinations
-FDIR filter parsing logic
-Flow type assignment for proper packet classification

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_fdir_filter.c  | 451 ++++++++++++++++++++---
 drivers/net/intel/ice/ice_generic_flow.c | 177 +++++++++
 2 files changed, 573 insertions(+), 55 deletions(-)

diff --git a/drivers/net/intel/ice/ice_fdir_filter.c b/drivers/net/intel/ice/ice_fdir_filter.c
index f7730ec6ab..6a5d605f03 100644
--- a/drivers/net/intel/ice/ice_fdir_filter.c
+++ b/drivers/net/intel/ice/ice_fdir_filter.c
@@ -107,6 +107,31 @@
 	ICE_INSET_IPV6_SRC | ICE_INSET_IPV6_DST | \
 	ICE_INSET_NAT_T_ESP_SPI)
 
+#define ICE_FDIR_INSET_L2TPV2 (\
+	ICE_INSET_SMAC | ICE_INSET_DMAC | ICE_INSET_L2TPV2OIP_SESSION_ID)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4 (\
+	ICE_INSET_TUN_IPV4_SRC | ICE_INSET_TUN_IPV4_DST)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV4 | ICE_INSET_TUN_UDP_SRC_PORT | \
+	ICE_INSET_TUN_UDP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV4 | ICE_INSET_TUN_TCP_SRC_PORT | \
+	ICE_INSET_TUN_TCP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6 (\
+	ICE_INSET_TUN_IPV6_SRC | ICE_INSET_TUN_IPV6_DST)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV6 | ICE_INSET_TUN_UDP_SRC_PORT | \
+	ICE_INSET_TUN_UDP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV6 | ICE_INSET_TUN_TCP_SRC_PORT | \
+	ICE_INSET_TUN_TCP_DST_PORT)
+
 static struct ice_pattern_match_item ice_fdir_supported_pattern[] = {
 	{pattern_raw,					ICE_INSET_NONE,			ICE_INSET_NONE,			ICE_INSET_NONE},
 	{pattern_ethertype,				ICE_FDIR_INSET_ETH,		ICE_INSET_NONE,			ICE_INSET_NONE},
@@ -132,10 +157,26 @@ static struct ice_pattern_match_item ice_fdir_supported_pattern[] = {
 	{pattern_eth_ipv4_udp_vxlan_eth_ipv4_tcp,	ICE_FDIR_INSET_ETH_IPV4_VXLAN,	ICE_FDIR_INSET_ETH_IPV4_TCP,	ICE_INSET_NONE},
 	{pattern_eth_ipv4_udp_vxlan_eth_ipv4_sctp,	ICE_FDIR_INSET_ETH_IPV4_VXLAN,	ICE_FDIR_INSET_ETH_IPV4_SCTP,	ICE_INSET_NONE},
 	/* duplicated GTPU input set in 3rd column to align with shared code behavior. Ideally, only put GTPU field in 2nd column. */
-	{pattern_eth_ipv4_gtpu,				ICE_FDIR_INSET_IPV4_GTPU,	ICE_FDIR_INSET_IPV4_GTPU,	ICE_INSET_NONE},
-	{pattern_eth_ipv4_gtpu_eh,			ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_INSET_NONE},
-	{pattern_eth_ipv6_gtpu,				ICE_FDIR_INSET_IPV6_GTPU,	ICE_FDIR_INSET_IPV6_GTPU,	ICE_INSET_NONE},
-	{pattern_eth_ipv6_gtpu_eh,			ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_gtpu,				ICE_FDIR_INSET_IPV4_GTPU,	ICE_FDIR_INSET_IPV4_GTPU,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_gtpu_eh,			ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_FDIR_INSET_IPV4_GTPU_EH,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_gtpu,				ICE_FDIR_INSET_IPV6_GTPU,	ICE_FDIR_INSET_IPV6_GTPU,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_gtpu_eh,			ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_FDIR_INSET_IPV6_GTPU_EH,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2,			ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp,		ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2,			ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp,		ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP,	ICE_INSET_NONE},
 };
 
 static int
@@ -957,6 +998,7 @@ ice_fdir_input_set_parse(uint64_t inset, enum ice_flow_field *field)
 		{ICE_INSET_VXLAN_VNI, ICE_FLOW_FIELD_IDX_VXLAN_VNI},
 		{ICE_INSET_ESP_SPI, ICE_FLOW_FIELD_IDX_ESP_SPI},
 		{ICE_INSET_NAT_T_ESP_SPI, ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI},
+		{ICE_INSET_L2TPV2OIP_SESSION_ID, ICE_FLOW_FIELD_IDX_L2TPV2_SESS_ID},
 	};
 
 	for (i = 0, j = 0; i < RTE_DIM(ice_inset_map); i++) {
@@ -1068,6 +1110,43 @@ ice_fdir_input_set_hdrs(enum ice_fltr_ptype flow, struct ice_flow_seg_info *seg)
 				  ICE_FLOW_SEG_HDR_IPV6 |
 				  ICE_FLOW_SEG_HDR_IPV_OTHER);
 		break;
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_IPV6 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_UDP:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_PPP |
+				  ICE_FLOW_SEG_HDR_IPV6 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_IPV4 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_UDP:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_PPP |
+				  ICE_FLOW_SEG_HDR_IPV4 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+
 	default:
 		PMD_DRV_LOG(ERR, "not supported filter type.");
 		break;
@@ -1170,7 +1249,10 @@ ice_fdir_uninit(struct ice_adapter *ad)
 static int
 ice_fdir_is_tunnel_profile(enum ice_fdir_tunnel_type tunnel_type)
 {
-	if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN)
+	if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_GTPU ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_GTPU_EH)
 		return 1;
 	else
 		return 0;
@@ -1239,6 +1321,9 @@ ice_fdir_extract_fltr_key(struct ice_fdir_fltr_pattern *key,
 	rte_memcpy(&key->gtpu_data, &input->gtpu_data, sizeof(key->gtpu_data));
 	rte_memcpy(&key->gtpu_mask, &input->gtpu_mask, sizeof(key->gtpu_mask));
 
+	rte_memcpy(&key->l2tpv2_data, &input->l2tpv2_data, sizeof(key->l2tpv2_data));
+	rte_memcpy(&key->l2tpv2_mask, &input->l2tpv2_mask, sizeof(key->l2tpv2_mask));
+
 	key->tunnel_type = filter->tunnel_type;
 }
 
@@ -1797,16 +1882,22 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 	const struct rte_flow_item_gtp *gtp_spec, *gtp_mask;
 	const struct rte_flow_item_gtp_psc *gtp_psc_spec, *gtp_psc_mask;
 	const struct rte_flow_item_esp *esp_spec, *esp_mask;
+	const struct rte_flow_item_l2tpv2 *l2tpv2_spec, *l2tpv2_mask;
+	const struct rte_flow_item_ppp *ppp_spec, *ppp_mask;
 	uint64_t input_set_i = ICE_INSET_NONE; /* only for tunnel inner */
 	uint64_t input_set_o = ICE_INSET_NONE; /* non-tunnel and tunnel outer */
 	uint64_t *input_set;
 	uint8_t flow_type = ICE_FLTR_PTYPE_NONF_NONE;
+	enum rte_flow_item_type inner_l3 = RTE_FLOW_ITEM_TYPE_END;
+	enum rte_flow_item_type inner_l4 = RTE_FLOW_ITEM_TYPE_END;
+	enum rte_flow_item_type current_l3 = RTE_FLOW_ITEM_TYPE_END;
+	bool ppp_present = false;
 	uint8_t  ipv6_addr_mask[16] = {
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
 	};
 	uint32_t vtc_flow_cpu;
-	uint16_t ether_type;
+	uint16_t ether_type = 0, flags_version = 0;
 	enum rte_flow_item_type next_type;
 	bool is_outer = true;
 	struct ice_fdir_extra *p_ext_data;
@@ -2001,22 +2092,30 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				   &eth_spec->hdr.ether_type, sizeof(eth_spec->hdr.ether_type));
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV4:
-			flow_type = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
-			l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			/* Only set flow_type for outer IPv4, track inner L3 for tunnels */
+			if (is_outer || !tunnel_type) {
+				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
+				l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			} else {
+				inner_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			}
+
 			ipv4_spec = item->spec;
 			ipv4_last = item->last;
 			ipv4_mask = item->mask;
 			p_v4 = (tunnel_type && is_outer) ?
-			       &filter->input.ip_outer.v4 :
-			       &filter->input.ip.v4;
+					&filter->input.ip_outer.v4 :
+					&filter->input.ip.v4;
 
 			if (!(ipv4_spec && ipv4_mask))
 				break;
 
 			/* Check IPv4 mask and update input set */
 			if (ipv4_mask->hdr.version_ihl ||
-			    ipv4_mask->hdr.total_length ||
-			    ipv4_mask->hdr.hdr_checksum) {
+				ipv4_mask->hdr.total_length ||
+				ipv4_mask->hdr.hdr_checksum) {
 				rte_flow_error_set(error, EINVAL,
 						   RTE_FLOW_ERROR_TYPE_ITEM,
 						   item,
@@ -2048,10 +2147,20 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				ipv4_mask->hdr.dst_addr != UINT32_MAX)
 				return -rte_errno;
 
-			if (ipv4_mask->hdr.dst_addr == UINT32_MAX)
-				*input_set |= ICE_INSET_IPV4_DST;
-			if (ipv4_mask->hdr.src_addr == UINT32_MAX)
-				*input_set |= ICE_INSET_IPV4_SRC;
+			if (ipv4_mask->hdr.dst_addr == UINT32_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV4_DST;
+				else
+					*input_set |= ICE_INSET_IPV4_DST;
+			}
+			if (ipv4_mask->hdr.src_addr == UINT32_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV4_SRC;
+				else
+					*input_set |= ICE_INSET_IPV4_SRC;
+			}
 			if (ipv4_mask->hdr.time_to_live == UINT8_MAX)
 				*input_set |= ICE_INSET_IPV4_TTL;
 			if (ipv4_mask->hdr.next_proto_id == UINT8_MAX)
@@ -2092,8 +2201,15 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV6:
-			flow_type = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
-			l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			if (is_outer || !tunnel_type) {
+				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
+				l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			} else {
+				inner_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			}
+
 			ipv6_spec = item->spec;
 			ipv6_mask = item->mask;
 			p_v6 = (tunnel_type && is_outer) ?
@@ -2113,15 +2229,24 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 			}
 
 			if (!memcmp(&ipv6_mask->hdr.src_addr, ipv6_addr_mask,
-				    sizeof(ipv6_mask->hdr.src_addr)))
-				*input_set |= ICE_INSET_IPV6_SRC;
+				    sizeof(ipv6_mask->hdr.src_addr))) {
+				if (tunnel_type && !is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV6_SRC;
+				else
+					*input_set |= ICE_INSET_IPV6_SRC;
+			}
 			if (!memcmp(&ipv6_mask->hdr.dst_addr, ipv6_addr_mask,
-				    sizeof(ipv6_mask->hdr.dst_addr)))
-				*input_set |= ICE_INSET_IPV6_DST;
-
+				    sizeof(ipv6_mask->hdr.dst_addr))) {
+				if (tunnel_type && !is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV6_DST;
+				else
+					*input_set |= ICE_INSET_IPV6_DST;
+			}
 			if ((ipv6_mask->hdr.vtc_flow &
-			     rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
-			    == rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
+			     rte_cpu_to_be_32(ICE_IPV6_TC_MASK)) ==
+			    rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
 				*input_set |= ICE_INSET_IPV6_TC;
 			if (ipv6_mask->hdr.proto == UINT8_MAX)
 				*input_set |= ICE_INSET_IPV6_NEXT_HDR;
@@ -2167,10 +2292,16 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 			break;
 
 		case RTE_FLOW_ITEM_TYPE_TCP:
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
+			if (!is_outer && tunnel_type) {
+				/* For inner TCP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_TCP;
+			} else {
+				/* For outer TCP, update flow_type normally */
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
+			}
 
 			tcp_spec = item->spec;
 			tcp_mask = item->mask;
@@ -2201,28 +2332,44 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				tcp_mask->hdr.dst_port != UINT16_MAX)
 				return -rte_errno;
 
-			if (tcp_mask->hdr.src_port == UINT16_MAX)
-				*input_set |= ICE_INSET_TCP_SRC_PORT;
-			if (tcp_mask->hdr.dst_port == UINT16_MAX)
-				*input_set |= ICE_INSET_TCP_DST_PORT;
+			if (tcp_mask->hdr.src_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_TCP_SRC_PORT;
+				else
+					*input_set |= ICE_INSET_TCP_SRC_PORT;
+			}
+			if (tcp_mask->hdr.dst_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_TCP_DST_PORT;
+				else
+					*input_set |= ICE_INSET_TCP_DST_PORT;
+			}
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = tcp_spec->hdr.dst_port;
 				p_v4->src_port = tcp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->dst_port = tcp_spec->hdr.dst_port;
 				p_v6->src_port = tcp_spec->hdr.src_port;
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_UDP:
-			l4 = RTE_FLOW_ITEM_TYPE_UDP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
+			if (!is_outer && tunnel_type) {
+				/* For inner UDP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_UDP;
+			} else {
+				/* For outer UDP, update flow_type normally */
+				l4 = RTE_FLOW_ITEM_TYPE_UDP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
+			}
 
 			udp_spec = item->spec;
 			udp_mask = item->mask;
@@ -2248,27 +2395,43 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				udp_mask->hdr.dst_port != UINT16_MAX)
 				return -rte_errno;
 
-			if (udp_mask->hdr.src_port == UINT16_MAX)
-				*input_set |= ICE_INSET_UDP_SRC_PORT;
-			if (udp_mask->hdr.dst_port == UINT16_MAX)
-				*input_set |= ICE_INSET_UDP_DST_PORT;
+			if (udp_mask->hdr.src_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_UDP_SRC_PORT;
+				else
+					*input_set |= ICE_INSET_UDP_SRC_PORT;
+			}
+			if (udp_mask->hdr.dst_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_UDP_DST_PORT;
+				else
+					*input_set |= ICE_INSET_UDP_DST_PORT;
+			}
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = udp_spec->hdr.dst_port;
 				p_v4->src_port = udp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->src_port = udp_spec->hdr.src_port;
 				p_v6->dst_port = udp_spec->hdr.dst_port;
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_SCTP:
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
+			if (!is_outer && tunnel_type) {
+				/* For inner SCTP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_SCTP;
+			} else {
+				/* For outer SCTP, update flow_type normally */
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
+			}
 
 			sctp_spec = item->spec;
 			sctp_mask = item->mask;
@@ -2299,11 +2462,11 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				*input_set |= ICE_INSET_SCTP_DST_PORT;
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = sctp_spec->hdr.dst_port;
 				p_v4->src_port = sctp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->dst_port = sctp_spec->hdr.dst_port;
 				p_v6->src_port = sctp_spec->hdr.src_port;
@@ -2406,6 +2569,115 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				filter->input.ip.v6.sec_parm_idx =
 					esp_spec->hdr.spi;
 			break;
+		case RTE_FLOW_ITEM_TYPE_L2TPV2: {
+			struct ice_fdir_l2tpv2 l2tpv2_be;
+
+			l2tpv2_spec = item->spec;
+			l2tpv2_mask = item->mask;
+
+			if (!(l2tpv2_spec && l2tpv2_mask))
+				break;
+
+			flags_version =
+				rte_be_to_cpu_16(l2tpv2_spec->hdr.common.flags_version);
+			if ((flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+			     l2tpv2_mask->hdr.type3.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA &&
+			     l2tpv2_mask->hdr.type7.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L &&
+			     l2tpv2_mask->hdr.type6.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S &&
+			     l2tpv2_mask->hdr.type5.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_O &&
+			     l2tpv2_mask->hdr.type4.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S &&
+			     l2tpv2_mask->hdr.type3.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_O &&
+			     l2tpv2_mask->hdr.type2.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S_O &&
+			     l2tpv2_mask->hdr.type1.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S_O &&
+			     l2tpv2_mask->hdr.type0.session_id == UINT16_MAX)) {
+				input_set_o |= ICE_INSET_L2TPV2OIP_SESSION_ID;
+			}
+
+			tunnel_type = ICE_FDIR_TUNNEL_TYPE_L2TPV2;
+			memset(&l2tpv2_be, 0, sizeof(l2tpv2_be));
+
+			if (flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type7.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type7.session_id);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.session_id);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_O) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.session_id);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_O) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.session_id);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S_O) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.nr);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S_O) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.nr);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.offset_size);
+			}
+
+			/* Copy converted values to filter */
+			filter->input.l2tpv2_data.flags_version = rte_cpu_to_be_16(flags_version);
+			filter->input.l2tpv2_data.length = l2tpv2_be.length;
+			filter->input.l2tpv2_data.tunnel_id = l2tpv2_be.tunnel_id;
+			filter->input.l2tpv2_data.session_id = l2tpv2_be.session_id;
+			filter->input.l2tpv2_data.ns = l2tpv2_be.ns;
+			filter->input.l2tpv2_data.nr = l2tpv2_be.nr;
+			filter->input.l2tpv2_data.offset_size = l2tpv2_be.offset_size;
+			break;
+		}
+		case RTE_FLOW_ITEM_TYPE_PPP:
+			ppp_spec = item->spec;
+			ppp_mask = item->mask;
+
+			/* PPP marks transition from outer to inner in L2TPv2 tunnels */
+			if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2) {
+				is_outer = false;
+				ppp_present = true;
+			}
+
+			if (ppp_spec && ppp_mask) {
+				filter->input.ppp_data.addr = ppp_spec->hdr.addr;
+				filter->input.ppp_data.ctrl = ppp_spec->hdr.ctrl;
+				filter->input.ppp_data.proto_id = ppp_spec->hdr.proto_id;
+			}
+			break;
 		default:
 			rte_flow_error_set(error, EINVAL,
 					   RTE_FLOW_ERROR_TYPE_ITEM,
@@ -2439,6 +2711,74 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN &&
 		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
 		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP_VXLAN_IPV4_OTHER;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP &&
+		flags_version != RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP &&
+		flags_version != RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP &&
+		flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP &&
+		flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL;
+	/* Handle L2TPV2 with PPP and inner protocols */
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		ppp_present &&
+		inner_l3 != RTE_FLOW_ITEM_TYPE_END) {
+		/* L2TPV2 with inner IPv4/IPv6 */
+		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP) {
+			/* Outer IPv4 + inner protocol */
+			if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4;
+			} else if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6;
+			}
+		} else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP) {
+			/* Outer IPv6 + inner protocol */
+			if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4;
+			} else if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6;
+			}
+		}
+	} else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 && ppp_present &&
+		inner_l3 == RTE_FLOW_ITEM_TYPE_END) {
+		/* Handle L2TPV2 with PPP but no inner protocol specified */
+		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP)
+			flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP;
+		else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP)
+			flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP;
+	}
 
 	filter->tunnel_type = tunnel_type;
 	filter->input.flow_type = flow_type;
@@ -2482,9 +2822,10 @@ ice_fdir_parse(struct ice_adapter *ad,
 	input_set = filter->input_set_o | filter->input_set_i;
 	input_set = raw ? ~input_set : input_set;
 
-	if (!input_set || filter->input_set_o &
-	    ~(item->input_set_mask_o | ICE_INSET_ETHERTYPE) ||
-	    filter->input_set_i & ~item->input_set_mask_i) {
+	if (!input_set ||
+	    (filter->input_set_o &
+	     ~(item->input_set_mask_o | ICE_INSET_ETHERTYPE)) ||
+	    (filter->input_set_i & ~item->input_set_mask_i)) {
 		rte_flow_error_set(error, EINVAL,
 				   RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
 				   pattern,
diff --git a/drivers/net/intel/ice/ice_generic_flow.c b/drivers/net/intel/ice/ice_generic_flow.c
index 4049157eab..644958cccf 100644
--- a/drivers/net/intel/ice/ice_generic_flow.c
+++ b/drivers/net/intel/ice/ice_generic_flow.c
@@ -1794,6 +1794,166 @@ enum rte_flow_item_type pattern_eth_ipv6_pfcp[] = {
 	RTE_FLOW_ITEM_TYPE_PFCP,
 	RTE_FLOW_ITEM_TYPE_END,
 };
+enum rte_flow_item_type pattern_eth_ipv4_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+/* PPPoL2TPv2oUDP */
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 
 typedef bool (*parse_engine_t)(struct ice_adapter *ad,
 			       struct rte_flow *flow,
@@ -2021,6 +2181,23 @@ static struct ice_ptype_match ice_ptype_map[] = {
 	{pattern_eth_ipv4_udp_esp,			ICE_MAC_IPV4_NAT_T_ESP},
 	{pattern_eth_ipv4_ah,				ICE_MAC_IPV4_AH},
 	{pattern_eth_ipv4_l2tp,				ICE_MAC_IPV4_L2TPV3},
+	{pattern_eth_ipv4_udp_l2tpv2,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp,	ICE_MAC_IPV6_L2TPV2},
+
 	{pattern_eth_ipv4_pfcp,				ICE_MAC_IPV4_PFCP_SESSION},
 	{pattern_eth_ipv6,				ICE_PTYPE_IPV6_PAY},
 	{pattern_eth_ipv6_udp,				ICE_PTYPE_IPV6_UDP_PAY},
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v5 5/7] net/ice: add L2TPv2 hardware packet generation
  2025-08-26 17:05 ` [PATCH v5 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                     ` (3 preceding siblings ...)
  2025-08-26 17:05   ` [PATCH v5 4/7] net/ice: add L2TPv2 flow patterns and FDIR support Shaiq Wani
@ 2025-08-26 17:05   ` Shaiq Wani
  2025-08-26 17:05   ` [PATCH v5 6/7] net/ice: add L2TPv2 RSS hash support Shaiq Wani
  2025-08-26 17:05   ` [PATCH v5 7/7] doc: update release notes Shaiq Wani
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2025-08-26 17:05 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add L2TPv2 packet type cases to ice_fdir_get_gen_prgm_pkt() to enable
hardware packet generation for FDIR rule programming.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/base/ice_fdir.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/intel/ice/base/ice_fdir.c b/drivers/net/intel/ice/base/ice_fdir.c
index f62313c559..2c0cb99854 100644
--- a/drivers/net/intel/ice/base/ice_fdir.c
+++ b/drivers/net/intel/ice/base/ice_fdir.c
@@ -4027,6 +4027,9 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
 				   ICE_NONDMA_TO_NONDMA);
 			loc = &pkt[ICE_FDIR_V6_V4_GTPOGRE_EH_PKT_OFF];
 			break;
+		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL:
+		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2:
+		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP:
 		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4:
 		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP:
 		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP:
@@ -4038,6 +4041,9 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
 						      idx, offset, tun);
 			loc = &pkt[pos];
 			break;
+		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL:
+		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2:
+		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP:
 		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4:
 		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP:
 		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP:
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v5 6/7] net/ice: add L2TPv2 RSS hash support
  2025-08-26 17:05 ` [PATCH v5 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                     ` (4 preceding siblings ...)
  2025-08-26 17:05   ` [PATCH v5 5/7] net/ice: add L2TPv2 hardware packet generation Shaiq Wani
@ 2025-08-26 17:05   ` Shaiq Wani
  2025-08-26 17:05   ` [PATCH v5 7/7] doc: update release notes Shaiq Wani
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2025-08-26 17:05 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add RSS (Receive Side Scaling) hash support for L2TPv2 packets.
define hash templates and patterns for distributing L2TPv2 traffic
across multiple receive queues based on session IDs and inner headers.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_hash.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/net/intel/ice/ice_hash.c b/drivers/net/intel/ice/ice_hash.c
index afdc8f220a..b20103a452 100644
--- a/drivers/net/intel/ice/ice_hash.c
+++ b/drivers/net/intel/ice/ice_hash.c
@@ -305,6 +305,22 @@ struct ice_rss_hash_cfg eth_ipv4_l2tpv3_tmplt = {
 	0
 };
 
+struct ice_rss_hash_cfg eth_ipv4_l2tpv2_tmplt = {
+	ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
+	ICE_FLOW_SEG_HDR_L2TPV2,
+	ICE_FLOW_HASH_L2TPV2_SESS_ID,
+	ICE_RSS_OUTER_HEADERS,
+	0
+};
+
+struct ice_rss_hash_cfg eth_ipv6_l2tpv2_tmplt = {
+	ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_IPV_OTHER |
+	ICE_FLOW_SEG_HDR_L2TPV2,
+	ICE_FLOW_HASH_L2TPV2_SESS_ID,
+	ICE_RSS_OUTER_HEADERS,
+	0
+};
+
 struct ice_rss_hash_cfg eth_ipv4_pfcp_tmplt = {
 	ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
 	ICE_FLOW_SEG_HDR_PFCP_SESSION,
@@ -480,6 +496,8 @@ struct ice_rss_hash_cfg eth_tmplt = {
 #define ICE_RSS_TYPE_IPV6_AH		(RTE_ETH_RSS_AH | RTE_ETH_RSS_IPV6)
 #define ICE_RSS_TYPE_IPV4_L2TPV3	(RTE_ETH_RSS_L2TPV3 | RTE_ETH_RSS_IPV4)
 #define ICE_RSS_TYPE_IPV6_L2TPV3	(RTE_ETH_RSS_L2TPV3 | RTE_ETH_RSS_IPV6)
+#define ICE_RSS_TYPE_IPV4_L2TPV2	(RTE_ETH_RSS_L2TPV2 | RTE_ETH_RSS_IPV4)
+#define ICE_RSS_TYPE_IPV6_L2TPV2	(RTE_ETH_RSS_L2TPV2 | RTE_ETH_RSS_IPV6)
 #define ICE_RSS_TYPE_IPV4_PFCP		(RTE_ETH_RSS_PFCP | RTE_ETH_RSS_IPV4)
 #define ICE_RSS_TYPE_IPV6_PFCP		(RTE_ETH_RSS_PFCP | RTE_ETH_RSS_IPV6)
 
@@ -522,6 +540,8 @@ static struct ice_pattern_match_item ice_hash_pattern_list[] = {
 	{pattern_eth_ipv4_udp_esp,		ICE_RSS_TYPE_IPV4_ESP,		ICE_INSET_NONE,	&eth_ipv4_udp_esp_tmplt},
 	{pattern_eth_ipv4_ah,			ICE_RSS_TYPE_IPV4_AH,		ICE_INSET_NONE,	&eth_ipv4_ah_tmplt},
 	{pattern_eth_ipv4_l2tp,			ICE_RSS_TYPE_IPV4_L2TPV3,	ICE_INSET_NONE,	&eth_ipv4_l2tpv3_tmplt},
+	{pattern_eth_ipv4_l2tpv2,		ICE_RSS_TYPE_IPV4_L2TPV2,	ICE_INSET_NONE,	&eth_ipv4_l2tpv2_tmplt},
+	{pattern_eth_ipv6_l2tpv2,		ICE_RSS_TYPE_IPV6_L2TPV2,	ICE_INSET_NONE,	&eth_ipv6_l2tpv2_tmplt},
 	{pattern_eth_ipv4_pfcp,			ICE_RSS_TYPE_IPV4_PFCP,		ICE_INSET_NONE,	&eth_ipv4_pfcp_tmplt},
 	/* IPV6 */
 	{pattern_eth_ipv6,			ICE_RSS_TYPE_ETH_IPV6,		ICE_INSET_NONE,	&ipv6_tmplt},
@@ -925,6 +945,11 @@ ice_refine_hash_cfg_l234(struct ice_rss_hash_cfg *hash_cfg,
 			*hash_flds &= ~ICE_FLOW_HASH_L2TPV3_SESS_ID;
 	}
 
+	if (*addl_hdrs & ICE_FLOW_SEG_HDR_L2TPV2) {
+		if (!(rss_type & RTE_ETH_RSS_L2TPV2))
+			*hash_flds &= ~ICE_FLOW_HASH_L2TPV2_SESS_ID;
+	}
+
 	if (*addl_hdrs & ICE_FLOW_SEG_HDR_ESP) {
 		if (!(rss_type & RTE_ETH_RSS_ESP))
 			*hash_flds &= ~ICE_FLOW_HASH_ESP_SPI;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v5 7/7] doc: update release notes
  2025-08-26 17:05 ` [PATCH v5 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                     ` (5 preceding siblings ...)
  2025-08-26 17:05   ` [PATCH v5 6/7] net/ice: add L2TPv2 RSS hash support Shaiq Wani
@ 2025-08-26 17:05   ` Shaiq Wani
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2025-08-26 17:05 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh

Add L2TPv2 over UDP support for ice PMD in the release notes.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
---
 doc/guides/rel_notes/release_26_03.rst | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/doc/guides/rel_notes/release_26_03.rst b/doc/guides/rel_notes/release_26_03.rst
index 5c2a4bb32e..d312c47531 100644
--- a/doc/guides/rel_notes/release_26_03.rst
+++ b/doc/guides/rel_notes/release_26_03.rst
@@ -67,6 +67,10 @@ New Features
 
   * Added support for pre and post VF reset callbacks.
 
+* **Updated Intel ice driver.**
+
+  * Added Flow Director (FDIR) support for L2TPv2 over UDP.
+
 * **Updated ZTE zxdh ethernet driver.**
 
   * Added support for modifying queue depth.
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 0/6] Add support for L2TPV2 over UDP to ICE PMD
@ 2026-02-02  9:42 Shaiq Wani
  2025-08-26 16:26 ` [PATCH v3 0/7] " Shaiq Wani
                   ` (9 more replies)
  0 siblings, 10 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-02  9:42 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh

This patchset adds L2TPv2 protocol support to the ICE PMD
enabling RSS and Flow Director capabilities for L2TPv2 over UDP traffic.


Shaiq Wani (6):
  net/ice: add L2TPv2 and PPP data structures
  net/ice: add L2TPv2 tunnel type definition
  net/ice: add L2TPv2 protocol and field definitions
  net/ice: add L2TPv2 flow patterns and FDIR support
  net/ice: add L2TPv2 hardware packet generation
  net/ice: add L2TPv2 RSS hash support

 drivers/net/intel/ice/base/ice_fdir.c    |   6 +
 drivers/net/intel/ice/base/ice_fdir.h    |  17 +
 drivers/net/intel/ice/ice_ethdev.h       |   4 +
 drivers/net/intel/ice/ice_fdir_filter.c  | 487 +++++++++++++++++++----
 drivers/net/intel/ice/ice_generic_flow.c | 177 ++++++++
 drivers/net/intel/ice/ice_generic_flow.h | 130 ++++--
 drivers/net/intel/ice/ice_hash.c         |  25 ++
 7 files changed, 728 insertions(+), 118 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH 1/6] net/ice: add L2TPv2 and PPP data structures
  2026-02-02  9:42 [PATCH 0/6] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
  2025-08-26 16:26 ` [PATCH v3 0/7] " Shaiq Wani
  2025-08-26 17:05 ` [PATCH v5 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
@ 2026-02-02  9:42 ` Shaiq Wani
  2026-02-18 16:37   ` [PATCH v6 0/8] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
  2026-02-19 11:20   ` [PATCH v7 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
  2026-02-02  9:42 ` [PATCH 2/6] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
                   ` (6 subsequent siblings)
  9 siblings, 2 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-02  9:42 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Jiale Song

Add data structure definitions for L2TPv2 and PPP
protocols to support Flow Director (FDIR) filtering.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Jiale Song <songx.jiale@intel.com>
---
 drivers/net/intel/ice/base/ice_fdir.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/net/intel/ice/base/ice_fdir.h b/drivers/net/intel/ice/base/ice_fdir.h
index 3dd03f93f7..3d3b05da4a 100644
--- a/drivers/net/intel/ice/base/ice_fdir.h
+++ b/drivers/net/intel/ice/base/ice_fdir.h
@@ -230,6 +230,20 @@ struct ice_fdir_ecpri {
 	__be16 pc_id;
 };
 
+struct ice_fdir_pppoe {
+	u8 rsrvd_ver_type;
+	u8 rsrvd_code;
+	__be16 session_id;
+	__be16 length;
+	__be16 ppp_prot_id; /* control and data only */
+};
+
+struct ice_fdir_ppp {
+	u8 addr;
+	u8 ctrl;
+	__be16 proto_id;
+};
+
 struct ice_fdir_l2tpv2 {
 	__be16 flags_version;
 	__be16 length;
@@ -279,6 +293,9 @@ struct ice_fdir_fltr {
 	struct ice_fdir_ecpri ecpri_data;
 	struct ice_fdir_ecpri ecpri_mask;
 
+	struct ice_fdir_ppp ppp_data;
+	struct ice_fdir_ppp ppp_mask;
+
 	struct ice_fdir_l2tpv2 l2tpv2_data;
 	struct ice_fdir_l2tpv2 l2tpv2_mask;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 2/6] net/ice: add L2TPv2 tunnel type definition
  2026-02-02  9:42 [PATCH 0/6] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                   ` (2 preceding siblings ...)
  2026-02-02  9:42 ` [PATCH 1/6] net/ice: add L2TPv2 and PPP data structures Shaiq Wani
@ 2026-02-02  9:42 ` Shaiq Wani
  2026-02-02  9:42 ` [PATCH 3/6] net/ice: add L2TPv2 protocol and field definitions Shaiq Wani
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-02  9:42 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Jiale Song

Add ICE_FDIR_TUNNEL_TYPE_L2TPV2 to the tunnel type enum and
extend ice_fdir_fltr_pattern structure to include L2TPv2 data and
mask fields.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Jiale Song <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_ethdev.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/intel/ice/ice_ethdev.h b/drivers/net/intel/ice/ice_ethdev.h
index 72ed65f13b..a37ed9db71 100644
--- a/drivers/net/intel/ice/ice_ethdev.h
+++ b/drivers/net/intel/ice/ice_ethdev.h
@@ -362,6 +362,7 @@ enum ice_fdir_tunnel_type {
 	ICE_FDIR_TUNNEL_TYPE_VXLAN,
 	ICE_FDIR_TUNNEL_TYPE_GTPU,
 	ICE_FDIR_TUNNEL_TYPE_GTPU_EH,
+	ICE_FDIR_TUNNEL_TYPE_L2TPV2,
 };
 
 struct rte_flow;
@@ -398,6 +399,9 @@ struct ice_fdir_fltr_pattern {
 	struct ice_fdir_udp_gtp gtpu_data;
 	struct ice_fdir_udp_gtp gtpu_mask;
 
+	struct ice_fdir_l2tpv2 l2tpv2_data;
+	struct ice_fdir_l2tpv2 l2tpv2_mask;
+
 	struct ice_fdir_extra ext_data;
 	struct ice_fdir_extra ext_mask;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 3/6] net/ice: add L2TPv2 protocol and field definitions
  2026-02-02  9:42 [PATCH 0/6] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                   ` (3 preceding siblings ...)
  2026-02-02  9:42 ` [PATCH 2/6] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
@ 2026-02-02  9:42 ` Shaiq Wani
  2026-02-02  9:42 ` [PATCH 4/6] net/ice: add L2TPv2 flow patterns and FDIR support Shaiq Wani
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-02  9:42 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Jiale Song

Add L2TPv2 protocol identifier (ICE_PROT_L2TPV2OIP) and session ID
field definition (ICE_L2TPV2OIP_SESSION_ID) to the generic flow header.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Jiale Song <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_generic_flow.h | 130 ++++++++++++++++-------
 1 file changed, 89 insertions(+), 41 deletions(-)

diff --git a/drivers/net/intel/ice/ice_generic_flow.h b/drivers/net/intel/ice/ice_generic_flow.h
index 54bbb47398..233b3d3036 100644
--- a/drivers/net/intel/ice/ice_generic_flow.h
+++ b/drivers/net/intel/ice/ice_generic_flow.h
@@ -9,15 +9,15 @@
 
 /* protocol */
 
-#define ICE_PROT_MAC			BIT_ULL(1)
-#define ICE_PROT_VLAN			BIT_ULL(2)
-#define ICE_PROT_IPV4			BIT_ULL(3)
-#define ICE_PROT_IPV6			BIT_ULL(4)
-#define ICE_PROT_TCP			BIT_ULL(5)
-#define ICE_PROT_UDP			BIT_ULL(6)
-#define ICE_PROT_SCTP			BIT_ULL(7)
-#define ICE_PROT_ICMP4			BIT_ULL(8)
-#define ICE_PROT_ICMP6			BIT_ULL(9)
+#define ICE_PROT_MAC_OUTER		BIT_ULL(1)
+#define ICE_PROT_VLAN_OUTER		BIT_ULL(2)
+#define ICE_PROT_IPV4_OUTER		BIT_ULL(3)
+#define ICE_PROT_IPV6_OUTER		BIT_ULL(4)
+#define ICE_PROT_TCP_OUTER		BIT_ULL(5)
+#define ICE_PROT_UDP_OUTER		BIT_ULL(6)
+#define ICE_PROT_SCTP_OUTER		BIT_ULL(7)
+#define ICE_PROT_ICMP4_OUTER		BIT_ULL(8)
+#define ICE_PROT_ICMP6_OUTER		BIT_ULL(9)
 #define ICE_PROT_VXLAN			BIT_ULL(10)
 #define ICE_PROT_NVGRE			BIT_ULL(11)
 #define ICE_PROT_GTPU			BIT_ULL(12)
@@ -27,6 +27,16 @@
 #define ICE_PROT_L2TPV3OIP		BIT_ULL(16)
 #define ICE_PROT_PFCP			BIT_ULL(17)
 #define ICE_PROT_NAT_T_ESP		BIT_ULL(18)
+#define ICE_PROT_L2TPV2OIP		BIT_ULL(19)
+#define ICE_PROT_MAC_INNER		BIT_ULL(20)
+#define ICE_PROT_VLAN_INNER		BIT_ULL(21)
+#define ICE_PROT_IPV4_INNER		BIT_ULL(22)
+#define ICE_PROT_IPV6_INNER		BIT_ULL(23)
+#define ICE_PROT_TCP_INNER		BIT_ULL(24)
+#define ICE_PROT_UDP_INNER		BIT_ULL(25)
+#define ICE_PROT_SCTP_INNER		BIT_ULL(26)
+#define ICE_PROT_ICMP4_INNER		BIT_ULL(27)
+#define ICE_PROT_ICMP6_INNER		BIT_ULL(28)
 
 /* field */
 
@@ -53,8 +63,9 @@
 #define ICE_L2TPV3OIP_SESSION_ID	BIT_ULL(43)
 #define ICE_PFCP_SEID			BIT_ULL(42)
 #define ICE_PFCP_S_FIELD		BIT_ULL(41)
-#define ICE_IP_PK_ID		    BIT_ULL(40)
+#define ICE_IP_PK_ID			BIT_ULL(40)
 #define ICE_IP_FRAG_OFS			BIT_ULL(39)
+#define ICE_L2TPV2OIP_SESSION_ID	BIT_ULL(38)
 
 /* input set */
 
@@ -62,39 +73,39 @@
 
 #define ICE_INSET_SMAC			(ICE_SMAC)
 #define ICE_INSET_DMAC			(ICE_DMAC)
-#define ICE_INSET_VLAN			(ICE_PROT_VLAN)
-#define ICE_INSET_VLAN_INNER		(ICE_PROT_VLAN)
-#define ICE_INSET_VLAN_OUTER		(ICE_PROT_VLAN)
+#define ICE_INSET_VLAN			(ICE_PROT_VLAN_OUTER)
+#define ICE_INSET_VLAN_INNER		(ICE_PROT_VLAN_OUTER)
+#define ICE_INSET_VLAN_OUTER		(ICE_PROT_VLAN_OUTER)
 #define ICE_INSET_ETHERTYPE		(ICE_ETHERTYPE)
 
-#define ICE_INSET_IPV4_SRC		(ICE_PROT_IPV4 | ICE_IP_SRC)
-#define ICE_INSET_IPV4_DST		(ICE_PROT_IPV4 | ICE_IP_DST)
-#define ICE_INSET_IPV4_TOS		(ICE_PROT_IPV4 | ICE_IP_TOS)
-#define ICE_INSET_IPV4_PROTO		(ICE_PROT_IPV4 | ICE_IP_PROTO)
-#define ICE_INSET_IPV4_TTL		(ICE_PROT_IPV4 | ICE_IP_TTL)
-#define ICE_INSET_IPV4_PKID		(ICE_PROT_IPV4 | ICE_IP_PK_ID)
-#define ICE_INSET_IPV4_FRAG_OFS	(ICE_PROT_IPV4 | ICE_IP_FRAG_OFS)
-#define ICE_INSET_IPV6_SRC		(ICE_PROT_IPV6 | ICE_IP_SRC)
-#define ICE_INSET_IPV6_DST		(ICE_PROT_IPV6 | ICE_IP_DST)
-#define ICE_INSET_IPV6_NEXT_HDR		(ICE_PROT_IPV6 | ICE_IP_PROTO)
-#define ICE_INSET_IPV6_HOP_LIMIT	(ICE_PROT_IPV6 | ICE_IP_TTL)
-#define ICE_INSET_IPV6_TC		(ICE_PROT_IPV6 | ICE_IP_TOS)
-#define ICE_INSET_IPV6_PKID		(ICE_PROT_IPV6 | ICE_IP_PK_ID)
-
-#define ICE_INSET_TCP_SRC_PORT		(ICE_PROT_TCP | ICE_SPORT)
-#define ICE_INSET_TCP_DST_PORT		(ICE_PROT_TCP | ICE_DPORT)
-#define ICE_INSET_UDP_SRC_PORT		(ICE_PROT_UDP | ICE_SPORT)
-#define ICE_INSET_UDP_DST_PORT		(ICE_PROT_UDP | ICE_DPORT)
-#define ICE_INSET_SCTP_SRC_PORT		(ICE_PROT_SCTP | ICE_SPORT)
-#define ICE_INSET_SCTP_DST_PORT		(ICE_PROT_SCTP | ICE_DPORT)
-#define ICE_INSET_ICMP4_SRC_PORT	(ICE_PROT_ICMP4 | ICE_SPORT)
-#define ICE_INSET_ICMP4_DST_PORT	(ICE_PROT_ICMP4 | ICE_DPORT)
-#define ICE_INSET_ICMP6_SRC_PORT	(ICE_PROT_ICMP6 | ICE_SPORT)
-#define ICE_INSET_ICMP6_DST_PORT	(ICE_PROT_ICMP6 | ICE_DPORT)
-#define ICE_INSET_ICMP4_TYPE		(ICE_PROT_ICMP4 | ICE_ICMP_TYPE)
-#define ICE_INSET_ICMP4_CODE		(ICE_PROT_ICMP4 | ICE_ICMP_CODE)
-#define ICE_INSET_ICMP6_TYPE		(ICE_PROT_ICMP6 | ICE_ICMP_TYPE)
-#define ICE_INSET_ICMP6_CODE		(ICE_PROT_ICMP6 | ICE_ICMP_CODE)
+#define ICE_INSET_IPV4_SRC		(ICE_PROT_IPV4_OUTER | ICE_IP_SRC)
+#define ICE_INSET_IPV4_DST		(ICE_PROT_IPV4_OUTER | ICE_IP_DST)
+#define ICE_INSET_IPV4_TOS		(ICE_PROT_IPV4_OUTER | ICE_IP_TOS)
+#define ICE_INSET_IPV4_PROTO		(ICE_PROT_IPV4_OUTER | ICE_IP_PROTO)
+#define ICE_INSET_IPV4_TTL		(ICE_PROT_IPV4_OUTER | ICE_IP_TTL)
+#define ICE_INSET_IPV4_PKID		(ICE_PROT_IPV4_OUTER | ICE_IP_PK_ID)
+#define ICE_INSET_IPV4_FRAG_OFS	(ICE_PROT_IPV4_OUTER | ICE_IP_FRAG_OFS)
+#define ICE_INSET_IPV6_SRC		(ICE_PROT_IPV6_OUTER | ICE_IP_SRC)
+#define ICE_INSET_IPV6_DST		(ICE_PROT_IPV6_OUTER | ICE_IP_DST)
+#define ICE_INSET_IPV6_NEXT_HDR		(ICE_PROT_IPV6_OUTER | ICE_IP_PROTO)
+#define ICE_INSET_IPV6_HOP_LIMIT	(ICE_PROT_IPV6_OUTER | ICE_IP_TTL)
+#define ICE_INSET_IPV6_TC		(ICE_PROT_IPV6_OUTER | ICE_IP_TOS)
+#define ICE_INSET_IPV6_PKID		(ICE_PROT_IPV6_OUTER | ICE_IP_PK_ID)
+
+#define ICE_INSET_TCP_SRC_PORT		(ICE_PROT_TCP_OUTER | ICE_SPORT)
+#define ICE_INSET_TCP_DST_PORT		(ICE_PROT_TCP_OUTER | ICE_DPORT)
+#define ICE_INSET_UDP_SRC_PORT		(ICE_PROT_UDP_OUTER | ICE_SPORT)
+#define ICE_INSET_UDP_DST_PORT		(ICE_PROT_UDP_OUTER | ICE_DPORT)
+#define ICE_INSET_SCTP_SRC_PORT		(ICE_PROT_SCTP_OUTER | ICE_SPORT)
+#define ICE_INSET_SCTP_DST_PORT		(ICE_PROT_SCTP_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP4_SRC_PORT	(ICE_PROT_ICMP4_OUTER | ICE_SPORT)
+#define ICE_INSET_ICMP4_DST_PORT	(ICE_PROT_ICMP4_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP6_SRC_PORT	(ICE_PROT_ICMP6_OUTER | ICE_SPORT)
+#define ICE_INSET_ICMP6_DST_PORT	(ICE_PROT_ICMP6_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP4_TYPE		(ICE_PROT_ICMP4_OUTER | ICE_ICMP_TYPE)
+#define ICE_INSET_ICMP4_CODE		(ICE_PROT_ICMP4_OUTER | ICE_ICMP_CODE)
+#define ICE_INSET_ICMP6_TYPE		(ICE_PROT_ICMP6_OUTER | ICE_ICMP_TYPE)
+#define ICE_INSET_ICMP6_CODE		(ICE_PROT_ICMP6_OUTER | ICE_ICMP_CODE)
 
 /* tunnel */
 
@@ -122,6 +133,25 @@
 	(ICE_PROT_PFCP | ICE_PFCP_S_FIELD | ICE_PFCP_SEID)
 #define ICE_INSET_NAT_T_ESP_SPI \
 	(ICE_PROT_NAT_T_ESP | ICE_ESP_SPI)
+#define ICE_INSET_L2TPV2OIP_SESSION_ID \
+	(ICE_PROT_L2TPV2OIP | ICE_L2TPV2OIP_SESSION_ID)
+#define ICE_INSET_TUN_IPV4_SRC \
+	(ICE_PROT_IPV4_INNER | ICE_IP_SRC)
+#define ICE_INSET_TUN_IPV4_DST \
+	(ICE_PROT_IPV4_INNER | ICE_IP_DST)
+#define ICE_INSET_TUN_UDP_SRC_PORT \
+	(ICE_PROT_UDP_INNER | ICE_SPORT)
+#define ICE_INSET_TUN_UDP_DST_PORT \
+	(ICE_PROT_UDP_INNER | ICE_DPORT)
+#define ICE_INSET_TUN_TCP_SRC_PORT \
+	(ICE_PROT_TCP_INNER | ICE_SPORT)
+#define ICE_INSET_TUN_TCP_DST_PORT \
+	(ICE_PROT_TCP_INNER | ICE_DPORT)
+#define ICE_INSET_TUN_IPV6_SRC \
+	(ICE_PROT_IPV6_INNER | ICE_IP_SRC)
+#define ICE_INSET_TUN_IPV6_DST \
+	(ICE_PROT_IPV6_INNER | ICE_IP_DST)
+
 
 /* empty pattern */
 extern enum rte_flow_item_type pattern_empty[];
@@ -400,6 +430,24 @@ extern enum rte_flow_item_type pattern_eth_ipv6_udp_ah[];
 /* L2TP */
 extern enum rte_flow_item_type pattern_eth_ipv4_l2tp[];
 extern enum rte_flow_item_type pattern_eth_ipv6_l2tp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv6_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp[];
 
 /* PFCP */
 extern enum rte_flow_item_type pattern_eth_ipv4_pfcp[];
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 4/6] net/ice: add L2TPv2 flow patterns and FDIR support
  2026-02-02  9:42 [PATCH 0/6] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                   ` (4 preceding siblings ...)
  2026-02-02  9:42 ` [PATCH 3/6] net/ice: add L2TPv2 protocol and field definitions Shaiq Wani
@ 2026-02-02  9:42 ` Shaiq Wani
  2026-02-02  9:42 ` [PATCH 5/6] net/ice: add L2TPv2 hardware packet generation Shaiq Wani
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-02  9:42 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Jiale Song

Implement comprehensive L2TPv2 support for Flow Director
-Flow pattern definitions for different L2TPv2 packet combinations
-FDIR filter parsing logic
-Flow type assignment for proper packet classification

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Jiale Song <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_fdir_filter.c  | 487 +++++++++++++++++++----
 drivers/net/intel/ice/ice_generic_flow.c | 177 ++++++++
 2 files changed, 587 insertions(+), 77 deletions(-)

diff --git a/drivers/net/intel/ice/ice_fdir_filter.c b/drivers/net/intel/ice/ice_fdir_filter.c
index 9dfe5c02cb..79c9dddae6 100644
--- a/drivers/net/intel/ice/ice_fdir_filter.c
+++ b/drivers/net/intel/ice/ice_fdir_filter.c
@@ -107,6 +107,31 @@
 	ICE_INSET_IPV6_SRC | ICE_INSET_IPV6_DST | \
 	ICE_INSET_NAT_T_ESP_SPI)
 
+#define ICE_FDIR_INSET_L2TPV2 (\
+	ICE_INSET_SMAC | ICE_INSET_DMAC | ICE_INSET_L2TPV2OIP_SESSION_ID)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4 (\
+	ICE_INSET_TUN_IPV4_SRC | ICE_INSET_TUN_IPV4_DST)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV4 | ICE_INSET_TUN_UDP_SRC_PORT | \
+	ICE_INSET_TUN_UDP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV4 | ICE_INSET_TUN_TCP_SRC_PORT | \
+	ICE_INSET_TUN_TCP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6 (\
+	ICE_INSET_TUN_IPV6_SRC | ICE_INSET_TUN_IPV6_DST)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV6 | ICE_INSET_TUN_UDP_SRC_PORT | \
+	ICE_INSET_TUN_UDP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV6 | ICE_INSET_TUN_TCP_SRC_PORT | \
+	ICE_INSET_TUN_TCP_DST_PORT)
+
 static struct ice_pattern_match_item ice_fdir_supported_pattern[] = {
 	{pattern_raw,					ICE_INSET_NONE,			ICE_INSET_NONE,			ICE_INSET_NONE},
 	{pattern_ethertype,				ICE_FDIR_INSET_ETH,		ICE_INSET_NONE,			ICE_INSET_NONE},
@@ -132,10 +157,26 @@ static struct ice_pattern_match_item ice_fdir_supported_pattern[] = {
 	{pattern_eth_ipv4_udp_vxlan_eth_ipv4_tcp,	ICE_FDIR_INSET_ETH_IPV4_VXLAN,	ICE_FDIR_INSET_ETH_IPV4_TCP,	ICE_INSET_NONE},
 	{pattern_eth_ipv4_udp_vxlan_eth_ipv4_sctp,	ICE_FDIR_INSET_ETH_IPV4_VXLAN,	ICE_FDIR_INSET_ETH_IPV4_SCTP,	ICE_INSET_NONE},
 	/* duplicated GTPU input set in 3rd column to align with shared code behavior. Ideally, only put GTPU field in 2nd column. */
-	{pattern_eth_ipv4_gtpu,				ICE_FDIR_INSET_IPV4_GTPU,	ICE_FDIR_INSET_IPV4_GTPU,	ICE_INSET_NONE},
-	{pattern_eth_ipv4_gtpu_eh,			ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_INSET_NONE},
-	{pattern_eth_ipv6_gtpu,				ICE_FDIR_INSET_IPV6_GTPU,	ICE_FDIR_INSET_IPV6_GTPU,	ICE_INSET_NONE},
-	{pattern_eth_ipv6_gtpu_eh,			ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_gtpu,				ICE_FDIR_INSET_IPV4_GTPU,	ICE_FDIR_INSET_IPV4_GTPU,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_gtpu_eh,			ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_FDIR_INSET_IPV4_GTPU_EH,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_gtpu,				ICE_FDIR_INSET_IPV6_GTPU,	ICE_FDIR_INSET_IPV6_GTPU,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_gtpu_eh,			ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_FDIR_INSET_IPV6_GTPU_EH,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2,			ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,				ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp,		ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,				ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2,			ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,				ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp,		ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,				ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP,	ICE_INSET_NONE},
 };
 
 static int
@@ -957,6 +998,7 @@ ice_fdir_input_set_parse(uint64_t inset, enum ice_flow_field *field)
 		{ICE_INSET_VXLAN_VNI, ICE_FLOW_FIELD_IDX_VXLAN_VNI},
 		{ICE_INSET_ESP_SPI, ICE_FLOW_FIELD_IDX_ESP_SPI},
 		{ICE_INSET_NAT_T_ESP_SPI, ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI},
+		{ICE_INSET_L2TPV2OIP_SESSION_ID, ICE_FLOW_FIELD_IDX_L2TPV2_SESS_ID},
 	};
 
 	for (i = 0, j = 0; i < RTE_DIM(ice_inset_map); i++) {
@@ -1068,6 +1110,43 @@ ice_fdir_input_set_hdrs(enum ice_fltr_ptype flow, struct ice_flow_seg_info *seg)
 				  ICE_FLOW_SEG_HDR_IPV6 |
 				  ICE_FLOW_SEG_HDR_IPV_OTHER);
 		break;
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_IPV6 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_UDP:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_PPP |
+				  ICE_FLOW_SEG_HDR_IPV6 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_IPV4 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_UDP:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_PPP |
+				  ICE_FLOW_SEG_HDR_IPV4 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+
 	default:
 		PMD_DRV_LOG(ERR, "not supported filter type.");
 		break;
@@ -1170,7 +1249,10 @@ ice_fdir_uninit(struct ice_adapter *ad)
 static int
 ice_fdir_is_tunnel_profile(enum ice_fdir_tunnel_type tunnel_type)
 {
-	if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN)
+	if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_GTPU ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_GTPU_EH)
 		return 1;
 	else
 		return 0;
@@ -1239,6 +1321,9 @@ ice_fdir_extract_fltr_key(struct ice_fdir_fltr_pattern *key,
 	rte_memcpy(&key->gtpu_data, &input->gtpu_data, sizeof(key->gtpu_data));
 	rte_memcpy(&key->gtpu_mask, &input->gtpu_mask, sizeof(key->gtpu_mask));
 
+	rte_memcpy(&key->l2tpv2_data, &input->l2tpv2_data, sizeof(key->l2tpv2_data));
+	rte_memcpy(&key->l2tpv2_mask, &input->l2tpv2_mask, sizeof(key->l2tpv2_mask));
+
 	key->tunnel_type = filter->tunnel_type;
 }
 
@@ -1797,16 +1882,22 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 	const struct rte_flow_item_gtp *gtp_spec, *gtp_mask;
 	const struct rte_flow_item_gtp_psc *gtp_psc_spec, *gtp_psc_mask;
 	const struct rte_flow_item_esp *esp_spec, *esp_mask;
+	const struct rte_flow_item_l2tpv2 *l2tpv2_spec, *l2tpv2_mask;
+	const struct rte_flow_item_ppp *ppp_spec, *ppp_mask;
 	uint64_t input_set_i = ICE_INSET_NONE; /* only for tunnel inner */
 	uint64_t input_set_o = ICE_INSET_NONE; /* non-tunnel and tunnel outer */
 	uint64_t *input_set;
 	uint8_t flow_type = ICE_FLTR_PTYPE_NONF_NONE;
+	enum rte_flow_item_type inner_l3 = RTE_FLOW_ITEM_TYPE_END;
+	enum rte_flow_item_type inner_l4 = RTE_FLOW_ITEM_TYPE_END;
+	enum rte_flow_item_type current_l3 = RTE_FLOW_ITEM_TYPE_END;
+	bool ppp_present = false;
 	uint8_t  ipv6_addr_mask[16] = {
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
 	};
 	uint32_t vtc_flow_cpu;
-	uint16_t ether_type;
+	uint16_t ether_type = 0, flags_version = 0;
 	enum rte_flow_item_type next_type;
 	bool is_outer = true;
 	struct ice_fdir_extra *p_ext_data;
@@ -1994,22 +2085,30 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				   &eth_spec->hdr.ether_type, sizeof(eth_spec->hdr.ether_type));
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV4:
-			flow_type = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
-			l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			/* Only set flow_type for outer IPv4, track inner L3 for tunnels */
+			if (is_outer || !tunnel_type) {
+				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
+				l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			} else {
+				inner_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			}
+
 			ipv4_spec = item->spec;
 			ipv4_last = item->last;
 			ipv4_mask = item->mask;
 			p_v4 = (tunnel_type && is_outer) ?
-			       &filter->input.ip_outer.v4 :
-			       &filter->input.ip.v4;
+					&filter->input.ip_outer.v4 :
+					&filter->input.ip.v4;
 
 			if (!(ipv4_spec && ipv4_mask))
 				break;
 
 			/* Check IPv4 mask and update input set */
 			if (ipv4_mask->hdr.version_ihl ||
-			    ipv4_mask->hdr.total_length ||
-			    ipv4_mask->hdr.hdr_checksum) {
+				ipv4_mask->hdr.total_length ||
+				ipv4_mask->hdr.hdr_checksum) {
 				rte_flow_error_set(error, EINVAL,
 						   RTE_FLOW_ERROR_TYPE_ITEM,
 						   item,
@@ -2041,10 +2140,18 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				ipv4_mask->hdr.dst_addr != UINT32_MAX)
 				return -rte_errno;
 
-			if (ipv4_mask->hdr.dst_addr == UINT32_MAX)
-				*input_set |= ICE_INSET_IPV4_DST;
-			if (ipv4_mask->hdr.src_addr == UINT32_MAX)
-				*input_set |= ICE_INSET_IPV4_SRC;
+			if (ipv4_mask->hdr.dst_addr == UINT32_MAX) {
+				if (tunnel_type && !is_outer && tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV4_DST;
+				else
+					*input_set |= ICE_INSET_IPV4_DST;
+			}
+			if (ipv4_mask->hdr.src_addr == UINT32_MAX) {
+				if (tunnel_type && !is_outer && tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV4_SRC;
+				else
+					*input_set |= ICE_INSET_IPV4_SRC;
+			}
 			if (ipv4_mask->hdr.time_to_live == UINT8_MAX)
 				*input_set |= ICE_INSET_IPV4_TTL;
 			if (ipv4_mask->hdr.next_proto_id == UINT8_MAX)
@@ -2085,48 +2192,62 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV6:
-			flow_type = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
-			l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			if (is_outer || !tunnel_type) {
+				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
+				l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			} else {
+				inner_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			}
+
 			ipv6_spec = item->spec;
 			ipv6_mask = item->mask;
 			p_v6 = (tunnel_type && is_outer) ?
 			       &filter->input.ip_outer.v6 :
 			       &filter->input.ip.v6;
 
-			if (!(ipv6_spec && ipv6_mask))
-				break;
+		if (!(ipv6_spec && ipv6_mask))
+			break;
 
-			/* Check IPv6 mask and update input set */
-			if (ipv6_mask->hdr.payload_len) {
-				rte_flow_error_set(error, EINVAL,
-						   RTE_FLOW_ERROR_TYPE_ITEM,
-						   item,
-						   "Invalid IPv6 mask");
-				return -rte_errno;
-			}
+		/* Check IPv6 mask and update input set */
+		if (ipv6_mask->hdr.payload_len) {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Invalid IPv6 mask");
+			return -rte_errno;
+		}
 
-			if (!memcmp(&ipv6_mask->hdr.src_addr, ipv6_addr_mask,
-				    sizeof(ipv6_mask->hdr.src_addr)))
+		if (!memcmp(&ipv6_mask->hdr.src_addr, ipv6_addr_mask,
+			    sizeof(ipv6_mask->hdr.src_addr))) {
+			if (tunnel_type && !is_outer && tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+				*input_set |= ICE_INSET_TUN_IPV6_SRC;
+			else
 				*input_set |= ICE_INSET_IPV6_SRC;
-			if (!memcmp(&ipv6_mask->hdr.dst_addr, ipv6_addr_mask,
-				    sizeof(ipv6_mask->hdr.dst_addr)))
+		}
+		if (!memcmp(&ipv6_mask->hdr.dst_addr, ipv6_addr_mask,
+			    sizeof(ipv6_mask->hdr.dst_addr))) {
+			if (tunnel_type && !is_outer && tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+				*input_set |= ICE_INSET_TUN_IPV6_DST;
+			else
 				*input_set |= ICE_INSET_IPV6_DST;
-
-			if ((ipv6_mask->hdr.vtc_flow &
-			     rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
-			    == rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
-				*input_set |= ICE_INSET_IPV6_TC;
-			if (ipv6_mask->hdr.proto == UINT8_MAX)
-				*input_set |= ICE_INSET_IPV6_NEXT_HDR;
-			if (ipv6_mask->hdr.hop_limits == UINT8_MAX)
-				*input_set |= ICE_INSET_IPV6_HOP_LIMIT;
-
-			rte_memcpy(&p_v6->dst_ip, &ipv6_spec->hdr.dst_addr, 16);
-			rte_memcpy(&p_v6->src_ip, &ipv6_spec->hdr.src_addr, 16);
-			vtc_flow_cpu = rte_be_to_cpu_32(ipv6_spec->hdr.vtc_flow);
-			p_v6->tc = (uint8_t)(vtc_flow_cpu >> ICE_FDIR_IPV6_TC_OFFSET);
-			p_v6->proto = ipv6_spec->hdr.proto;
-			p_v6->hlim = ipv6_spec->hdr.hop_limits;
+		}
+		if ((ipv6_mask->hdr.vtc_flow &
+		     rte_cpu_to_be_32(ICE_IPV6_TC_MASK)) ==
+		    rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
+			*input_set |= ICE_INSET_IPV6_TC;
+		if (ipv6_mask->hdr.proto == UINT8_MAX)
+			*input_set |= ICE_INSET_IPV6_NEXT_HDR;
+		if (ipv6_mask->hdr.hop_limits == UINT8_MAX)
+			*input_set |= ICE_INSET_IPV6_HOP_LIMIT;
+
+		rte_memcpy(&p_v6->dst_ip, &ipv6_spec->hdr.dst_addr, 16);
+		rte_memcpy(&p_v6->src_ip, &ipv6_spec->hdr.src_addr, 16);
+		vtc_flow_cpu = rte_be_to_cpu_32(ipv6_spec->hdr.vtc_flow);
+		p_v6->tc = (uint8_t)(vtc_flow_cpu >> ICE_FDIR_IPV6_TC_OFFSET);
+		p_v6->proto = ipv6_spec->hdr.proto;
+		p_v6->hlim = ipv6_spec->hdr.hop_limits;
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT:
 			l3 = RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT;
@@ -2160,10 +2281,16 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 			break;
 
 		case RTE_FLOW_ITEM_TYPE_TCP:
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
+			if (!is_outer && tunnel_type) {
+				/* For inner TCP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_TCP;
+			} else {
+				/* For outer TCP, update flow_type normally */
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
+			}
 
 			tcp_spec = item->spec;
 			tcp_mask = item->mask;
@@ -2194,28 +2321,42 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				tcp_mask->hdr.dst_port != UINT16_MAX)
 				return -rte_errno;
 
-			if (tcp_mask->hdr.src_port == UINT16_MAX)
-				*input_set |= ICE_INSET_TCP_SRC_PORT;
-			if (tcp_mask->hdr.dst_port == UINT16_MAX)
-				*input_set |= ICE_INSET_TCP_DST_PORT;
+			if (tcp_mask->hdr.src_port == UINT16_MAX) {
+				if (tunnel_type && !is_outer && tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_TCP_SRC_PORT;
+				else
+					*input_set |= ICE_INSET_TCP_SRC_PORT;
+			}
+			if (tcp_mask->hdr.dst_port == UINT16_MAX) {
+				if (tunnel_type && !is_outer && tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_TCP_DST_PORT;
+				else
+					*input_set |= ICE_INSET_TCP_DST_PORT;
+			}
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = tcp_spec->hdr.dst_port;
 				p_v4->src_port = tcp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->dst_port = tcp_spec->hdr.dst_port;
 				p_v6->src_port = tcp_spec->hdr.src_port;
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_UDP:
-			l4 = RTE_FLOW_ITEM_TYPE_UDP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
+			if (!is_outer && tunnel_type) {
+				/* For inner UDP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_UDP;
+			} else {
+				/* For outer UDP, update flow_type normally */
+				l4 = RTE_FLOW_ITEM_TYPE_UDP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
+			}
 
 			udp_spec = item->spec;
 			udp_mask = item->mask;
@@ -2241,27 +2382,41 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				udp_mask->hdr.dst_port != UINT16_MAX)
 				return -rte_errno;
 
-			if (udp_mask->hdr.src_port == UINT16_MAX)
-				*input_set |= ICE_INSET_UDP_SRC_PORT;
-			if (udp_mask->hdr.dst_port == UINT16_MAX)
-				*input_set |= ICE_INSET_UDP_DST_PORT;
+			if (udp_mask->hdr.src_port == UINT16_MAX) {
+				if (tunnel_type && !is_outer && tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_UDP_SRC_PORT;
+				else
+					*input_set |= ICE_INSET_UDP_SRC_PORT;
+			}
+			if (udp_mask->hdr.dst_port == UINT16_MAX) {
+				if (tunnel_type && !is_outer && tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_UDP_DST_PORT;
+				else
+					*input_set |= ICE_INSET_UDP_DST_PORT;
+			}
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = udp_spec->hdr.dst_port;
 				p_v4->src_port = udp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->src_port = udp_spec->hdr.src_port;
 				p_v6->dst_port = udp_spec->hdr.dst_port;
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_SCTP:
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
+			if (!is_outer && tunnel_type) {
+				/* For inner SCTP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_SCTP;
+			} else {
+				/* For outer SCTP, update flow_type normally */
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
+			}
 
 			sctp_spec = item->spec;
 			sctp_mask = item->mask;
@@ -2292,11 +2447,11 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				*input_set |= ICE_INSET_SCTP_DST_PORT;
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = sctp_spec->hdr.dst_port;
 				p_v4->src_port = sctp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->dst_port = sctp_spec->hdr.dst_port;
 				p_v6->src_port = sctp_spec->hdr.src_port;
@@ -2399,6 +2554,114 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				filter->input.ip.v6.sec_parm_idx =
 					esp_spec->hdr.spi;
 			break;
+		case RTE_FLOW_ITEM_TYPE_L2TPV2:
+
+			l2tpv2_spec = item->spec;
+			l2tpv2_mask = item->mask;
+
+			if (l2tpv2_spec && l2tpv2_mask) {
+				flags_version =
+					rte_be_to_cpu_16(l2tpv2_spec->hdr.common.flags_version);
+				if ((flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+				     l2tpv2_mask->hdr.type3.session_id == UINT16_MAX) ||
+				    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA &&
+				     l2tpv2_mask->hdr.type7.session_id == UINT16_MAX) ||
+				    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L &&
+				     l2tpv2_mask->hdr.type6.session_id == UINT16_MAX) ||
+				    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S &&
+				     l2tpv2_mask->hdr.type5.session_id == UINT16_MAX) ||
+				    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_O &&
+				     l2tpv2_mask->hdr.type4.session_id == UINT16_MAX) ||
+				    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S &&
+				     l2tpv2_mask->hdr.type3.session_id == UINT16_MAX) ||
+				    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_O &&
+				     l2tpv2_mask->hdr.type2.session_id == UINT16_MAX) ||
+				    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S_O &&
+				     l2tpv2_mask->hdr.type1.session_id == UINT16_MAX) ||
+				    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S_O &&
+				     l2tpv2_mask->hdr.type0.session_id == UINT16_MAX)) {
+					input_set_o |= ICE_INSET_L2TPV2OIP_SESSION_ID;
+				}
+			}
+
+			tunnel_type = ICE_FDIR_TUNNEL_TYPE_L2TPV2;
+
+			struct ice_fdir_l2tpv2 l2tpv2_be;
+			memset(&l2tpv2_be, 0, sizeof(l2tpv2_be));
+
+			if (flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type7.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type7.session_id);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.session_id);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_O) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.session_id);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_O) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.session_id);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S_O) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.nr);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S_O) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.nr);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.offset_size);
+			}
+
+			/* Copy converted values to filter */
+			filter->input.l2tpv2_data.flags_version = rte_cpu_to_be_16(flags_version);
+			filter->input.l2tpv2_data.length = l2tpv2_be.length;
+			filter->input.l2tpv2_data.tunnel_id = l2tpv2_be.tunnel_id;
+			filter->input.l2tpv2_data.session_id = l2tpv2_be.session_id;
+			filter->input.l2tpv2_data.ns = l2tpv2_be.ns;
+			filter->input.l2tpv2_data.nr = l2tpv2_be.nr;
+			filter->input.l2tpv2_data.offset_size = l2tpv2_be.offset_size;
+			break;
+		case RTE_FLOW_ITEM_TYPE_PPP:
+			ppp_spec = item->spec;
+			ppp_mask = item->mask;
+
+			/* PPP marks transition from outer to inner in L2TPv2 tunnels */
+			if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2) {
+				is_outer = false;
+				ppp_present = true;
+			}
+
+			if (ppp_spec && ppp_mask) {
+				filter->input.ppp_data.addr = ppp_spec->hdr.addr;
+				filter->input.ppp_data.ctrl = ppp_spec->hdr.ctrl;
+				filter->input.ppp_data.proto_id = ppp_spec->hdr.proto_id;
+			}
+			break;
 		default:
 			rte_flow_error_set(error, EINVAL,
 					   RTE_FLOW_ERROR_TYPE_ITEM,
@@ -2432,12 +2695,82 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN &&
 		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
 		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP_VXLAN_IPV4_OTHER;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP &&
+		flags_version != RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP &&
+		flags_version != RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP &&
+		flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP &&
+		flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL;
+	/* Handle L2TPV2 with PPP and inner protocols */
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		ppp_present &&
+		inner_l3 != RTE_FLOW_ITEM_TYPE_END) {
+		/* L2TPV2 with inner IPv4/IPv6 */
+		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP) {
+			/* Outer IPv4 + inner protocol */
+			if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4;
+			} else if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6;
+			}
+		} else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP) {
+			/* Outer IPv6 + inner protocol */
+			if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4;
+			} else if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6;
+			}
+		}
+	} else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 && ppp_present &&
+		inner_l3 == RTE_FLOW_ITEM_TYPE_END) {
+		/* Handle L2TPV2 with PPP but no inner protocol specified */
+		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP)
+			flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP;
+		else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP)
+			flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP;
+	}
 
 	filter->tunnel_type = tunnel_type;
 	filter->input.flow_type = flow_type;
 	filter->input_set_o = input_set_o;
 	filter->input_set_i = input_set_i;
 
+
+
 	return 0;
 }
 
@@ -2476,8 +2809,8 @@ ice_fdir_parse(struct ice_adapter *ad,
 	input_set = raw ? ~input_set : input_set;
 
 	if (!input_set || filter->input_set_o &
-	    ~(item->input_set_mask_o | ICE_INSET_ETHERTYPE) ||
-	    filter->input_set_i & ~item->input_set_mask_i) {
+		~(item->input_set_mask_o | ICE_INSET_ETHERTYPE) ||
+		filter->input_set_i & ~item->input_set_mask_i) {
 		rte_flow_error_set(error, EINVAL,
 				   RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
 				   pattern,
diff --git a/drivers/net/intel/ice/ice_generic_flow.c b/drivers/net/intel/ice/ice_generic_flow.c
index 4049157eab..644958cccf 100644
--- a/drivers/net/intel/ice/ice_generic_flow.c
+++ b/drivers/net/intel/ice/ice_generic_flow.c
@@ -1794,6 +1794,166 @@ enum rte_flow_item_type pattern_eth_ipv6_pfcp[] = {
 	RTE_FLOW_ITEM_TYPE_PFCP,
 	RTE_FLOW_ITEM_TYPE_END,
 };
+enum rte_flow_item_type pattern_eth_ipv4_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+/* PPPoL2TPv2oUDP */
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 
 typedef bool (*parse_engine_t)(struct ice_adapter *ad,
 			       struct rte_flow *flow,
@@ -2021,6 +2181,23 @@ static struct ice_ptype_match ice_ptype_map[] = {
 	{pattern_eth_ipv4_udp_esp,			ICE_MAC_IPV4_NAT_T_ESP},
 	{pattern_eth_ipv4_ah,				ICE_MAC_IPV4_AH},
 	{pattern_eth_ipv4_l2tp,				ICE_MAC_IPV4_L2TPV3},
+	{pattern_eth_ipv4_udp_l2tpv2,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp,	ICE_MAC_IPV6_L2TPV2},
+
 	{pattern_eth_ipv4_pfcp,				ICE_MAC_IPV4_PFCP_SESSION},
 	{pattern_eth_ipv6,				ICE_PTYPE_IPV6_PAY},
 	{pattern_eth_ipv6_udp,				ICE_PTYPE_IPV6_UDP_PAY},
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 5/6] net/ice: add L2TPv2 hardware packet generation
  2026-02-02  9:42 [PATCH 0/6] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                   ` (5 preceding siblings ...)
  2026-02-02  9:42 ` [PATCH 4/6] net/ice: add L2TPv2 flow patterns and FDIR support Shaiq Wani
@ 2026-02-02  9:42 ` Shaiq Wani
  2026-02-02  9:42 ` [PATCH 6/6] net/ice: add L2TPv2 RSS hash support Shaiq Wani
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-02  9:42 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Jiale Song

Add L2TPv2 packet type cases to ice_fdir_get_gen_prgm_pkt() to enable
hardware packet generation for FDIR rule programming.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Jiale Song <songx.jiale@intel.com>
---
 drivers/net/intel/ice/base/ice_fdir.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/intel/ice/base/ice_fdir.c b/drivers/net/intel/ice/base/ice_fdir.c
index f62313c559..2c0cb99854 100644
--- a/drivers/net/intel/ice/base/ice_fdir.c
+++ b/drivers/net/intel/ice/base/ice_fdir.c
@@ -4027,6 +4027,9 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
 				   ICE_NONDMA_TO_NONDMA);
 			loc = &pkt[ICE_FDIR_V6_V4_GTPOGRE_EH_PKT_OFF];
 			break;
+		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL:
+		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2:
+		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP:
 		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4:
 		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP:
 		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP:
@@ -4038,6 +4041,9 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
 						      idx, offset, tun);
 			loc = &pkt[pos];
 			break;
+		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL:
+		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2:
+		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP:
 		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4:
 		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP:
 		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP:
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 6/6] net/ice: add L2TPv2 RSS hash support
  2026-02-02  9:42 [PATCH 0/6] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                   ` (6 preceding siblings ...)
  2026-02-02  9:42 ` [PATCH 5/6] net/ice: add L2TPv2 hardware packet generation Shaiq Wani
@ 2026-02-02  9:42 ` Shaiq Wani
  2026-02-02 17:39   ` [REVIEW] " Stephen Hemminger
  2026-02-09 11:56 ` [PATCH v2 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
  2026-02-11  6:09 ` [PATCH v3 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
  9 siblings, 1 reply; 56+ messages in thread
From: Shaiq Wani @ 2026-02-02  9:42 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Jiale Song

Add RSS (Receive Side Scaling) hash support for L2TPv2 packets.
define hash templates and patterns for distributing L2TPv2 traffic
across multiple receive queues based on session IDs and inner headers.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Jiale Song <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_hash.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/net/intel/ice/ice_hash.c b/drivers/net/intel/ice/ice_hash.c
index aa6a21c055..02e15d0bdd 100644
--- a/drivers/net/intel/ice/ice_hash.c
+++ b/drivers/net/intel/ice/ice_hash.c
@@ -305,6 +305,22 @@ struct ice_rss_hash_cfg eth_ipv4_l2tpv3_tmplt = {
 	0
 };
 
+struct ice_rss_hash_cfg eth_ipv4_l2tpv2_tmplt = {
+	ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
+	ICE_FLOW_SEG_HDR_L2TPV2,
+	ICE_FLOW_HASH_L2TPV2_SESS_ID,
+	ICE_RSS_OUTER_HEADERS,
+	0
+};
+
+struct ice_rss_hash_cfg eth_ipv6_l2tpv2_tmplt = {
+	ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_IPV_OTHER |
+	ICE_FLOW_SEG_HDR_L2TPV2,
+	ICE_FLOW_HASH_L2TPV2_SESS_ID,
+	ICE_RSS_OUTER_HEADERS,
+	0
+};
+
 struct ice_rss_hash_cfg eth_ipv4_pfcp_tmplt = {
 	ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
 	ICE_FLOW_SEG_HDR_PFCP_SESSION,
@@ -480,6 +496,8 @@ struct ice_rss_hash_cfg eth_tmplt = {
 #define ICE_RSS_TYPE_IPV6_AH		(RTE_ETH_RSS_AH | RTE_ETH_RSS_IPV6)
 #define ICE_RSS_TYPE_IPV4_L2TPV3	(RTE_ETH_RSS_L2TPV3 | RTE_ETH_RSS_IPV4)
 #define ICE_RSS_TYPE_IPV6_L2TPV3	(RTE_ETH_RSS_L2TPV3 | RTE_ETH_RSS_IPV6)
+#define ICE_RSS_TYPE_IPV4_L2TPV2	(RTE_ETH_RSS_L2TPV2 | RTE_ETH_RSS_IPV4)
+#define ICE_RSS_TYPE_IPV6_L2TPV2	(RTE_ETH_RSS_L2TPV2 | RTE_ETH_RSS_IPV6)
 #define ICE_RSS_TYPE_IPV4_PFCP		(RTE_ETH_RSS_PFCP | RTE_ETH_RSS_IPV4)
 #define ICE_RSS_TYPE_IPV6_PFCP		(RTE_ETH_RSS_PFCP | RTE_ETH_RSS_IPV6)
 
@@ -522,6 +540,8 @@ static struct ice_pattern_match_item ice_hash_pattern_list[] = {
 	{pattern_eth_ipv4_udp_esp,		ICE_RSS_TYPE_IPV4_ESP,		ICE_INSET_NONE,	&eth_ipv4_udp_esp_tmplt},
 	{pattern_eth_ipv4_ah,			ICE_RSS_TYPE_IPV4_AH,		ICE_INSET_NONE,	&eth_ipv4_ah_tmplt},
 	{pattern_eth_ipv4_l2tp,			ICE_RSS_TYPE_IPV4_L2TPV3,	ICE_INSET_NONE,	&eth_ipv4_l2tpv3_tmplt},
+	{pattern_eth_ipv4_l2tpv2,		ICE_RSS_TYPE_IPV4_L2TPV2,	ICE_INSET_NONE,	&eth_ipv4_l2tpv2_tmplt},
+	{pattern_eth_ipv6_l2tpv2,		ICE_RSS_TYPE_IPV6_L2TPV2,	ICE_INSET_NONE,	&eth_ipv6_l2tpv2_tmplt},
 	{pattern_eth_ipv4_pfcp,			ICE_RSS_TYPE_IPV4_PFCP,		ICE_INSET_NONE,	&eth_ipv4_pfcp_tmplt},
 	/* IPV6 */
 	{pattern_eth_ipv6,			ICE_RSS_TYPE_ETH_IPV6,		ICE_INSET_NONE,	&ipv6_tmplt},
@@ -917,6 +937,11 @@ ice_refine_hash_cfg_l234(struct ice_rss_hash_cfg *hash_cfg,
 			*hash_flds &= ~ICE_FLOW_HASH_L2TPV3_SESS_ID;
 	}
 
+	if (*addl_hdrs & ICE_FLOW_SEG_HDR_L2TPV2) {
+		if (!(rss_type & RTE_ETH_RSS_L2TPV2))
+			*hash_flds &= ~ICE_FLOW_HASH_L2TPV2_SESS_ID;
+	}
+
 	if (*addl_hdrs & ICE_FLOW_SEG_HDR_ESP) {
 		if (!(rss_type & RTE_ETH_RSS_ESP))
 			*hash_flds &= ~ICE_FLOW_HASH_ESP_SPI;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [REVIEW] net/ice: add L2TPv2 RSS hash support
  2026-02-02  9:42 ` [PATCH 6/6] net/ice: add L2TPv2 RSS hash support Shaiq Wani
@ 2026-02-02 17:39   ` Stephen Hemminger
  0 siblings, 0 replies; 56+ messages in thread
From: Stephen Hemminger @ 2026-02-02 17:39 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

AI-generated review of bundle-1719-L2TPV2.mbox
Reviewed using Claude (claude-opus-4-5-20251101) on 2026-02-02

This is an automated review. Please verify all suggestions.

---

## Review of DPDK Patch Series: L2TPv2 Support for net/ice

### Overall Summary
This is a 6-patch series adding L2TPv2 and PPP protocol support for Flow Director (FDIR) filtering in the Intel ice driver. The patches are generally well-structured, but there are several issues that need attention.

---

## Patch 1/6: net/ice: add L2TPv2 and PPP data structures

### Errors
None.

### Warnings
1. **Subject line could be more specific**: The subject mentions "L2TPv2 and PPP data structures" but the patch adds PPPoE structure (`ice_fdir_pppoe`) as well as PPP structure. Consider clarifying or keeping just PPP if PPPoE isn't used.

### Info
- The data structures are cleanly defined and follow existing patterns in the file.

---

## Patch 2/6: net/ice: add L2TPv2 tunnel type definition

### Errors
None.

### Warnings
None.

### Info
- Clean addition of the tunnel type enum and pattern structure fields.

---

## Patch 3/6: net/ice: add L2TPv2 protocol and field definitions

### Errors
None.

### Warnings
1. **Renaming existing macros may break compatibility**: This patch renames `ICE_PROT_MAC` to `ICE_PROT_MAC_OUTER`, `ICE_PROT_IPV4` to `ICE_PROT_IPV4_OUTER`, etc. If these macros are used anywhere outside this file, this could break compilation. Verify no external dependencies exist.

2. **Extra blank line at end of file**: There's a double blank line before the closing of the file (line after `ICE_INSET_TUN_IPV6_DST` definition).

### Info
- Good organization of inner/outer protocol definitions for tunnel support.

---

## Patch 4/6: net/ice: add L2TPv2 flow patterns and FDIR support

### Errors
1. **Inconsistent indentation in IPV6 handling block** (around lines 2213-2245): The code block for `RTE_FLOW_ITEM_TYPE_IPV6` has incorrect indentation. After the `p_v6` assignment, the `if (!(ipv6_spec && ipv6_mask))` block and subsequent code uses inconsistent indentation (mix of tabs and spaces not aligned properly). The closing sections starting from `if (!(ipv6_spec && ipv6_mask))` through `p_v6->hlim = ipv6_spec->hdr.hop_limits;` should be indented one level further to align with the case block.

2. **Multiple trailing blank lines at end of function** (line 2806): There are two extra blank lines before the closing of `ice_fdir_parse_pattern()`. Should be at most one.

3. **Missing variable declaration in block scope** (line 2590): `struct ice_fdir_l2tpv2 l2tpv2_be;` is declared in the middle of the switch case after other statements. In C89/C90 style (which DPDK sometimes follows for compatibility), declarations should be at the beginning of a block. This should be moved or the declaration should be in its own block.

### Warnings
1. **Inconsistent alignment in pattern table** (lines 160-176): The new L2TPv2 pattern entries have inconsistent tab alignment compared to the existing GTPU entries. While not breaking, it reduces readability.

2. **Long lines exceeding 100 characters**: Several lines in the L2TPv2 parsing section exceed 100 characters, for example:
   - Line 2148: `if (tunnel_type && !is_outer && tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)`
   - Multiple similar conditional lines in TCP/UDP handling

3. **Potential uninitialized variable**: `flags_version` is initialized to 0 on line 1899, but is used in flow type determination even when `l2tpv2_spec` might be NULL. The logic appears safe due to the `tunnel_type` check, but the flow is not immediately clear.

4. **Inconsistent spacing in conditionals**: Line 2809 has different indentation style:
   ```c
   if (!input_set || filter->input_set_o &
       ~(item->input_set_mask_o | ICE_INSET_ETHERTYPE) ||
   ```
   vs the original code alignment.

### Info
- The patch is large and implements comprehensive L2TPv2 FDIR support. Consider splitting into smaller patches if possible (e.g., pattern definitions separate from parsing logic).

---

## Patch 5/6: net/ice: add L2TPv2 hardware packet generation

### Errors
None.

### Warnings
None.

### Info
- Clean addition of case statements for the new L2TPv2 packet types.

---

## Patch 6/6: net/ice: add L2TPv2 RSS hash support

### Errors
None.

### Warnings
1. **Missing documentation update**: This patch adds new RSS types (`ICE_RSS_TYPE_IPV4_L2TPV2`, `ICE_RSS_TYPE_IPV6_L2TPV2`) but there's no corresponding documentation update for the new feature. Consider adding release notes for the L2TPv2 RSS support.

### Info
- The RSS hash configuration follows the existing pattern for other protocols.

---

## General Issues Across All Patches

### Warnings
1. **Missing release notes**: This feature series adds significant new functionality (L2TPv2 FDIR and RSS support) but no patch updates `doc/guides/rel_notes/`. A release notes entry should be added documenting the new L2TPv2 support.

2. **No test updates**: There are no corresponding test additions in `app/test` for the new L2TPv2 functionality.

### Info
- The series is well-organized with logical progression of changes.
- Each patch compiles independently based on the structure (data types → enums → definitions → implementation → hardware support → RSS).
- The Tested-by tags are present on all patches, indicating the code has been tested.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH v2 0/7] Add support for L2TPV2 over UDP to ICE PMD
  2026-02-02  9:42 [PATCH 0/6] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                   ` (7 preceding siblings ...)
  2026-02-02  9:42 ` [PATCH 6/6] net/ice: add L2TPv2 RSS hash support Shaiq Wani
@ 2026-02-09 11:56 ` Shaiq Wani
  2026-02-09 11:56   ` [PATCH v2 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
                     ` (6 more replies)
  2026-02-11  6:09 ` [PATCH v3 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
  9 siblings, 7 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-09 11:56 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh

This patchset adds L2TPv2 protocol support to the ICE PMD
enabling RSS and Flow Director capabilities for L2TPv2 over UDP traffic.

v2: Addressed AI generated comments.

Shaiq Wani (7):
  net/ice: add L2TPv2 PPP and PPoE data structures
  net/ice: add L2TPv2 tunnel type definition
  net/ice: add L2TPv2 protocol and field definitions
  net/ice: add L2TPv2 flow patterns and FDIR support
  net/ice: add L2TPv2 hardware packet generation
  net/ice: add L2TPv2 RSS hash support
  doc: update release notes

 doc/guides/rel_notes/release_26_03.rst   |   4 +
 drivers/net/intel/ice/base/ice_fdir.c    |   6 +
 drivers/net/intel/ice/base/ice_fdir.h    |  17 +
 drivers/net/intel/ice/ice_ethdev.h       |   4 +
 drivers/net/intel/ice/ice_fdir_filter.c  | 450 ++++++++++++++++++++---
 drivers/net/intel/ice/ice_generic_flow.c | 177 +++++++++
 drivers/net/intel/ice/ice_generic_flow.h | 129 ++++---
 drivers/net/intel/ice/ice_hash.c         |  25 ++
 8 files changed, 716 insertions(+), 96 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH v2 1/7] net/ice: add L2TPv2 PPP and PPoE data structures
  2026-02-09 11:56 ` [PATCH v2 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
@ 2026-02-09 11:56   ` Shaiq Wani
  2026-02-09 11:56   ` [PATCH v2 2/7] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-09 11:56 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add data structure definitions for L2TPv2 PPP and
PPoE protocols to support Flow Director (FDIR) filtering.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/base/ice_fdir.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/net/intel/ice/base/ice_fdir.h b/drivers/net/intel/ice/base/ice_fdir.h
index 3dd03f93f7..3d3b05da4a 100644
--- a/drivers/net/intel/ice/base/ice_fdir.h
+++ b/drivers/net/intel/ice/base/ice_fdir.h
@@ -230,6 +230,20 @@ struct ice_fdir_ecpri {
 	__be16 pc_id;
 };
 
+struct ice_fdir_pppoe {
+	u8 rsrvd_ver_type;
+	u8 rsrvd_code;
+	__be16 session_id;
+	__be16 length;
+	__be16 ppp_prot_id; /* control and data only */
+};
+
+struct ice_fdir_ppp {
+	u8 addr;
+	u8 ctrl;
+	__be16 proto_id;
+};
+
 struct ice_fdir_l2tpv2 {
 	__be16 flags_version;
 	__be16 length;
@@ -279,6 +293,9 @@ struct ice_fdir_fltr {
 	struct ice_fdir_ecpri ecpri_data;
 	struct ice_fdir_ecpri ecpri_mask;
 
+	struct ice_fdir_ppp ppp_data;
+	struct ice_fdir_ppp ppp_mask;
+
 	struct ice_fdir_l2tpv2 l2tpv2_data;
 	struct ice_fdir_l2tpv2 l2tpv2_mask;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 2/7] net/ice: add L2TPv2 tunnel type definition
  2026-02-09 11:56 ` [PATCH v2 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
  2026-02-09 11:56   ` [PATCH v2 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
@ 2026-02-09 11:56   ` Shaiq Wani
  2026-02-09 11:56   ` [PATCH v2 3/7] net/ice: add L2TPv2 protocol and field definitions Shaiq Wani
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-09 11:56 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add ICE_FDIR_TUNNEL_TYPE_L2TPV2 to the tunnel type enum and
extend ice_fdir_fltr_pattern structure to include L2TPv2 data and
mask fields.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_ethdev.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/intel/ice/ice_ethdev.h b/drivers/net/intel/ice/ice_ethdev.h
index 9562b2b8f1..4b3718f715 100644
--- a/drivers/net/intel/ice/ice_ethdev.h
+++ b/drivers/net/intel/ice/ice_ethdev.h
@@ -369,6 +369,7 @@ enum ice_fdir_tunnel_type {
 	ICE_FDIR_TUNNEL_TYPE_VXLAN,
 	ICE_FDIR_TUNNEL_TYPE_GTPU,
 	ICE_FDIR_TUNNEL_TYPE_GTPU_EH,
+	ICE_FDIR_TUNNEL_TYPE_L2TPV2,
 };
 
 struct rte_flow;
@@ -405,6 +406,9 @@ struct ice_fdir_fltr_pattern {
 	struct ice_fdir_udp_gtp gtpu_data;
 	struct ice_fdir_udp_gtp gtpu_mask;
 
+	struct ice_fdir_l2tpv2 l2tpv2_data;
+	struct ice_fdir_l2tpv2 l2tpv2_mask;
+
 	struct ice_fdir_extra ext_data;
 	struct ice_fdir_extra ext_mask;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 3/7] net/ice: add L2TPv2 protocol and field definitions
  2026-02-09 11:56 ` [PATCH v2 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
  2026-02-09 11:56   ` [PATCH v2 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
  2026-02-09 11:56   ` [PATCH v2 2/7] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
@ 2026-02-09 11:56   ` Shaiq Wani
  2026-02-09 11:56   ` [PATCH v2 4/7] net/ice: add L2TPv2 flow patterns and FDIR support Shaiq Wani
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-09 11:56 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add L2TPv2 protocol identifier (ICE_PROT_L2TPV2OIP) and session ID
field definition (ICE_L2TPV2OIP_SESSION_ID) to the generic flow header.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_generic_flow.h | 129 ++++++++++++++++-------
 1 file changed, 88 insertions(+), 41 deletions(-)

diff --git a/drivers/net/intel/ice/ice_generic_flow.h b/drivers/net/intel/ice/ice_generic_flow.h
index 54bbb47398..deaf7b66e5 100644
--- a/drivers/net/intel/ice/ice_generic_flow.h
+++ b/drivers/net/intel/ice/ice_generic_flow.h
@@ -9,15 +9,15 @@
 
 /* protocol */
 
-#define ICE_PROT_MAC			BIT_ULL(1)
-#define ICE_PROT_VLAN			BIT_ULL(2)
-#define ICE_PROT_IPV4			BIT_ULL(3)
-#define ICE_PROT_IPV6			BIT_ULL(4)
-#define ICE_PROT_TCP			BIT_ULL(5)
-#define ICE_PROT_UDP			BIT_ULL(6)
-#define ICE_PROT_SCTP			BIT_ULL(7)
-#define ICE_PROT_ICMP4			BIT_ULL(8)
-#define ICE_PROT_ICMP6			BIT_ULL(9)
+#define ICE_PROT_MAC_OUTER		BIT_ULL(1)
+#define ICE_PROT_VLAN_OUTER		BIT_ULL(2)
+#define ICE_PROT_IPV4_OUTER		BIT_ULL(3)
+#define ICE_PROT_IPV6_OUTER		BIT_ULL(4)
+#define ICE_PROT_TCP_OUTER		BIT_ULL(5)
+#define ICE_PROT_UDP_OUTER		BIT_ULL(6)
+#define ICE_PROT_SCTP_OUTER		BIT_ULL(7)
+#define ICE_PROT_ICMP4_OUTER		BIT_ULL(8)
+#define ICE_PROT_ICMP6_OUTER		BIT_ULL(9)
 #define ICE_PROT_VXLAN			BIT_ULL(10)
 #define ICE_PROT_NVGRE			BIT_ULL(11)
 #define ICE_PROT_GTPU			BIT_ULL(12)
@@ -27,6 +27,16 @@
 #define ICE_PROT_L2TPV3OIP		BIT_ULL(16)
 #define ICE_PROT_PFCP			BIT_ULL(17)
 #define ICE_PROT_NAT_T_ESP		BIT_ULL(18)
+#define ICE_PROT_L2TPV2OIP		BIT_ULL(19)
+#define ICE_PROT_MAC_INNER		BIT_ULL(20)
+#define ICE_PROT_VLAN_INNER		BIT_ULL(21)
+#define ICE_PROT_IPV4_INNER		BIT_ULL(22)
+#define ICE_PROT_IPV6_INNER		BIT_ULL(23)
+#define ICE_PROT_TCP_INNER		BIT_ULL(24)
+#define ICE_PROT_UDP_INNER		BIT_ULL(25)
+#define ICE_PROT_SCTP_INNER		BIT_ULL(26)
+#define ICE_PROT_ICMP4_INNER		BIT_ULL(27)
+#define ICE_PROT_ICMP6_INNER		BIT_ULL(28)
 
 /* field */
 
@@ -53,8 +63,9 @@
 #define ICE_L2TPV3OIP_SESSION_ID	BIT_ULL(43)
 #define ICE_PFCP_SEID			BIT_ULL(42)
 #define ICE_PFCP_S_FIELD		BIT_ULL(41)
-#define ICE_IP_PK_ID		    BIT_ULL(40)
+#define ICE_IP_PK_ID			BIT_ULL(40)
 #define ICE_IP_FRAG_OFS			BIT_ULL(39)
+#define ICE_L2TPV2OIP_SESSION_ID	BIT_ULL(38)
 
 /* input set */
 
@@ -62,39 +73,39 @@
 
 #define ICE_INSET_SMAC			(ICE_SMAC)
 #define ICE_INSET_DMAC			(ICE_DMAC)
-#define ICE_INSET_VLAN			(ICE_PROT_VLAN)
-#define ICE_INSET_VLAN_INNER		(ICE_PROT_VLAN)
-#define ICE_INSET_VLAN_OUTER		(ICE_PROT_VLAN)
+#define ICE_INSET_VLAN			(ICE_PROT_VLAN_OUTER)
+#define ICE_INSET_VLAN_INNER		(ICE_PROT_VLAN_OUTER)
+#define ICE_INSET_VLAN_OUTER		(ICE_PROT_VLAN_OUTER)
 #define ICE_INSET_ETHERTYPE		(ICE_ETHERTYPE)
 
-#define ICE_INSET_IPV4_SRC		(ICE_PROT_IPV4 | ICE_IP_SRC)
-#define ICE_INSET_IPV4_DST		(ICE_PROT_IPV4 | ICE_IP_DST)
-#define ICE_INSET_IPV4_TOS		(ICE_PROT_IPV4 | ICE_IP_TOS)
-#define ICE_INSET_IPV4_PROTO		(ICE_PROT_IPV4 | ICE_IP_PROTO)
-#define ICE_INSET_IPV4_TTL		(ICE_PROT_IPV4 | ICE_IP_TTL)
-#define ICE_INSET_IPV4_PKID		(ICE_PROT_IPV4 | ICE_IP_PK_ID)
-#define ICE_INSET_IPV4_FRAG_OFS	(ICE_PROT_IPV4 | ICE_IP_FRAG_OFS)
-#define ICE_INSET_IPV6_SRC		(ICE_PROT_IPV6 | ICE_IP_SRC)
-#define ICE_INSET_IPV6_DST		(ICE_PROT_IPV6 | ICE_IP_DST)
-#define ICE_INSET_IPV6_NEXT_HDR		(ICE_PROT_IPV6 | ICE_IP_PROTO)
-#define ICE_INSET_IPV6_HOP_LIMIT	(ICE_PROT_IPV6 | ICE_IP_TTL)
-#define ICE_INSET_IPV6_TC		(ICE_PROT_IPV6 | ICE_IP_TOS)
-#define ICE_INSET_IPV6_PKID		(ICE_PROT_IPV6 | ICE_IP_PK_ID)
-
-#define ICE_INSET_TCP_SRC_PORT		(ICE_PROT_TCP | ICE_SPORT)
-#define ICE_INSET_TCP_DST_PORT		(ICE_PROT_TCP | ICE_DPORT)
-#define ICE_INSET_UDP_SRC_PORT		(ICE_PROT_UDP | ICE_SPORT)
-#define ICE_INSET_UDP_DST_PORT		(ICE_PROT_UDP | ICE_DPORT)
-#define ICE_INSET_SCTP_SRC_PORT		(ICE_PROT_SCTP | ICE_SPORT)
-#define ICE_INSET_SCTP_DST_PORT		(ICE_PROT_SCTP | ICE_DPORT)
-#define ICE_INSET_ICMP4_SRC_PORT	(ICE_PROT_ICMP4 | ICE_SPORT)
-#define ICE_INSET_ICMP4_DST_PORT	(ICE_PROT_ICMP4 | ICE_DPORT)
-#define ICE_INSET_ICMP6_SRC_PORT	(ICE_PROT_ICMP6 | ICE_SPORT)
-#define ICE_INSET_ICMP6_DST_PORT	(ICE_PROT_ICMP6 | ICE_DPORT)
-#define ICE_INSET_ICMP4_TYPE		(ICE_PROT_ICMP4 | ICE_ICMP_TYPE)
-#define ICE_INSET_ICMP4_CODE		(ICE_PROT_ICMP4 | ICE_ICMP_CODE)
-#define ICE_INSET_ICMP6_TYPE		(ICE_PROT_ICMP6 | ICE_ICMP_TYPE)
-#define ICE_INSET_ICMP6_CODE		(ICE_PROT_ICMP6 | ICE_ICMP_CODE)
+#define ICE_INSET_IPV4_SRC		(ICE_PROT_IPV4_OUTER | ICE_IP_SRC)
+#define ICE_INSET_IPV4_DST		(ICE_PROT_IPV4_OUTER | ICE_IP_DST)
+#define ICE_INSET_IPV4_TOS		(ICE_PROT_IPV4_OUTER | ICE_IP_TOS)
+#define ICE_INSET_IPV4_PROTO		(ICE_PROT_IPV4_OUTER | ICE_IP_PROTO)
+#define ICE_INSET_IPV4_TTL		(ICE_PROT_IPV4_OUTER | ICE_IP_TTL)
+#define ICE_INSET_IPV4_PKID		(ICE_PROT_IPV4_OUTER | ICE_IP_PK_ID)
+#define ICE_INSET_IPV4_FRAG_OFS	(ICE_PROT_IPV4_OUTER | ICE_IP_FRAG_OFS)
+#define ICE_INSET_IPV6_SRC		(ICE_PROT_IPV6_OUTER | ICE_IP_SRC)
+#define ICE_INSET_IPV6_DST		(ICE_PROT_IPV6_OUTER | ICE_IP_DST)
+#define ICE_INSET_IPV6_NEXT_HDR		(ICE_PROT_IPV6_OUTER | ICE_IP_PROTO)
+#define ICE_INSET_IPV6_HOP_LIMIT	(ICE_PROT_IPV6_OUTER | ICE_IP_TTL)
+#define ICE_INSET_IPV6_TC		(ICE_PROT_IPV6_OUTER | ICE_IP_TOS)
+#define ICE_INSET_IPV6_PKID		(ICE_PROT_IPV6_OUTER | ICE_IP_PK_ID)
+
+#define ICE_INSET_TCP_SRC_PORT		(ICE_PROT_TCP_OUTER | ICE_SPORT)
+#define ICE_INSET_TCP_DST_PORT		(ICE_PROT_TCP_OUTER | ICE_DPORT)
+#define ICE_INSET_UDP_SRC_PORT		(ICE_PROT_UDP_OUTER | ICE_SPORT)
+#define ICE_INSET_UDP_DST_PORT		(ICE_PROT_UDP_OUTER | ICE_DPORT)
+#define ICE_INSET_SCTP_SRC_PORT		(ICE_PROT_SCTP_OUTER | ICE_SPORT)
+#define ICE_INSET_SCTP_DST_PORT		(ICE_PROT_SCTP_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP4_SRC_PORT	(ICE_PROT_ICMP4_OUTER | ICE_SPORT)
+#define ICE_INSET_ICMP4_DST_PORT	(ICE_PROT_ICMP4_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP6_SRC_PORT	(ICE_PROT_ICMP6_OUTER | ICE_SPORT)
+#define ICE_INSET_ICMP6_DST_PORT	(ICE_PROT_ICMP6_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP4_TYPE		(ICE_PROT_ICMP4_OUTER | ICE_ICMP_TYPE)
+#define ICE_INSET_ICMP4_CODE		(ICE_PROT_ICMP4_OUTER | ICE_ICMP_CODE)
+#define ICE_INSET_ICMP6_TYPE		(ICE_PROT_ICMP6_OUTER | ICE_ICMP_TYPE)
+#define ICE_INSET_ICMP6_CODE		(ICE_PROT_ICMP6_OUTER | ICE_ICMP_CODE)
 
 /* tunnel */
 
@@ -122,6 +133,24 @@
 	(ICE_PROT_PFCP | ICE_PFCP_S_FIELD | ICE_PFCP_SEID)
 #define ICE_INSET_NAT_T_ESP_SPI \
 	(ICE_PROT_NAT_T_ESP | ICE_ESP_SPI)
+#define ICE_INSET_L2TPV2OIP_SESSION_ID \
+	(ICE_PROT_L2TPV2OIP | ICE_L2TPV2OIP_SESSION_ID)
+#define ICE_INSET_TUN_IPV4_SRC \
+	(ICE_PROT_IPV4_INNER | ICE_IP_SRC)
+#define ICE_INSET_TUN_IPV4_DST \
+	(ICE_PROT_IPV4_INNER | ICE_IP_DST)
+#define ICE_INSET_TUN_UDP_SRC_PORT \
+	(ICE_PROT_UDP_INNER | ICE_SPORT)
+#define ICE_INSET_TUN_UDP_DST_PORT \
+	(ICE_PROT_UDP_INNER | ICE_DPORT)
+#define ICE_INSET_TUN_TCP_SRC_PORT \
+	(ICE_PROT_TCP_INNER | ICE_SPORT)
+#define ICE_INSET_TUN_TCP_DST_PORT \
+	(ICE_PROT_TCP_INNER | ICE_DPORT)
+#define ICE_INSET_TUN_IPV6_SRC \
+	(ICE_PROT_IPV6_INNER | ICE_IP_SRC)
+#define ICE_INSET_TUN_IPV6_DST \
+	(ICE_PROT_IPV6_INNER | ICE_IP_DST)
 
 /* empty pattern */
 extern enum rte_flow_item_type pattern_empty[];
@@ -400,6 +429,24 @@ extern enum rte_flow_item_type pattern_eth_ipv6_udp_ah[];
 /* L2TP */
 extern enum rte_flow_item_type pattern_eth_ipv4_l2tp[];
 extern enum rte_flow_item_type pattern_eth_ipv6_l2tp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv6_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp[];
 
 /* PFCP */
 extern enum rte_flow_item_type pattern_eth_ipv4_pfcp[];
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 4/7] net/ice: add L2TPv2 flow patterns and FDIR support
  2026-02-09 11:56 ` [PATCH v2 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                     ` (2 preceding siblings ...)
  2026-02-09 11:56   ` [PATCH v2 3/7] net/ice: add L2TPv2 protocol and field definitions Shaiq Wani
@ 2026-02-09 11:56   ` Shaiq Wani
  2026-02-09 11:56   ` [PATCH v2 5/7] net/ice: add L2TPv2 hardware packet generation Shaiq Wani
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-09 11:56 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Implement comprehensive L2TPv2 support for Flow Director
-Flow pattern definitions for different L2TPv2 packet combinations
-FDIR filter parsing logic
-Flow type assignment for proper packet classification

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_fdir_filter.c  | 450 ++++++++++++++++++++---
 drivers/net/intel/ice/ice_generic_flow.c | 177 +++++++++
 2 files changed, 572 insertions(+), 55 deletions(-)

diff --git a/drivers/net/intel/ice/ice_fdir_filter.c b/drivers/net/intel/ice/ice_fdir_filter.c
index f7730ec6ab..ae152eb4ec 100644
--- a/drivers/net/intel/ice/ice_fdir_filter.c
+++ b/drivers/net/intel/ice/ice_fdir_filter.c
@@ -107,6 +107,31 @@
 	ICE_INSET_IPV6_SRC | ICE_INSET_IPV6_DST | \
 	ICE_INSET_NAT_T_ESP_SPI)
 
+#define ICE_FDIR_INSET_L2TPV2 (\
+	ICE_INSET_SMAC | ICE_INSET_DMAC | ICE_INSET_L2TPV2OIP_SESSION_ID)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4 (\
+	ICE_INSET_TUN_IPV4_SRC | ICE_INSET_TUN_IPV4_DST)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV4 | ICE_INSET_TUN_UDP_SRC_PORT | \
+	ICE_INSET_TUN_UDP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV4 | ICE_INSET_TUN_TCP_SRC_PORT | \
+	ICE_INSET_TUN_TCP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6 (\
+	ICE_INSET_TUN_IPV6_SRC | ICE_INSET_TUN_IPV6_DST)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV6 | ICE_INSET_TUN_UDP_SRC_PORT | \
+	ICE_INSET_TUN_UDP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV6 | ICE_INSET_TUN_TCP_SRC_PORT | \
+	ICE_INSET_TUN_TCP_DST_PORT)
+
 static struct ice_pattern_match_item ice_fdir_supported_pattern[] = {
 	{pattern_raw,					ICE_INSET_NONE,			ICE_INSET_NONE,			ICE_INSET_NONE},
 	{pattern_ethertype,				ICE_FDIR_INSET_ETH,		ICE_INSET_NONE,			ICE_INSET_NONE},
@@ -132,10 +157,26 @@ static struct ice_pattern_match_item ice_fdir_supported_pattern[] = {
 	{pattern_eth_ipv4_udp_vxlan_eth_ipv4_tcp,	ICE_FDIR_INSET_ETH_IPV4_VXLAN,	ICE_FDIR_INSET_ETH_IPV4_TCP,	ICE_INSET_NONE},
 	{pattern_eth_ipv4_udp_vxlan_eth_ipv4_sctp,	ICE_FDIR_INSET_ETH_IPV4_VXLAN,	ICE_FDIR_INSET_ETH_IPV4_SCTP,	ICE_INSET_NONE},
 	/* duplicated GTPU input set in 3rd column to align with shared code behavior. Ideally, only put GTPU field in 2nd column. */
-	{pattern_eth_ipv4_gtpu,				ICE_FDIR_INSET_IPV4_GTPU,	ICE_FDIR_INSET_IPV4_GTPU,	ICE_INSET_NONE},
-	{pattern_eth_ipv4_gtpu_eh,			ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_INSET_NONE},
-	{pattern_eth_ipv6_gtpu,				ICE_FDIR_INSET_IPV6_GTPU,	ICE_FDIR_INSET_IPV6_GTPU,	ICE_INSET_NONE},
-	{pattern_eth_ipv6_gtpu_eh,			ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_gtpu,				ICE_FDIR_INSET_IPV4_GTPU,	ICE_FDIR_INSET_IPV4_GTPU,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_gtpu_eh,			ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_FDIR_INSET_IPV4_GTPU_EH,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_gtpu,				ICE_FDIR_INSET_IPV6_GTPU,	ICE_FDIR_INSET_IPV6_GTPU,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_gtpu_eh,			ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_FDIR_INSET_IPV6_GTPU_EH,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2,			ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp,		ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2,			ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp,		ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP,	ICE_INSET_NONE},
 };
 
 static int
@@ -957,6 +998,7 @@ ice_fdir_input_set_parse(uint64_t inset, enum ice_flow_field *field)
 		{ICE_INSET_VXLAN_VNI, ICE_FLOW_FIELD_IDX_VXLAN_VNI},
 		{ICE_INSET_ESP_SPI, ICE_FLOW_FIELD_IDX_ESP_SPI},
 		{ICE_INSET_NAT_T_ESP_SPI, ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI},
+		{ICE_INSET_L2TPV2OIP_SESSION_ID, ICE_FLOW_FIELD_IDX_L2TPV2_SESS_ID},
 	};
 
 	for (i = 0, j = 0; i < RTE_DIM(ice_inset_map); i++) {
@@ -1068,6 +1110,43 @@ ice_fdir_input_set_hdrs(enum ice_fltr_ptype flow, struct ice_flow_seg_info *seg)
 				  ICE_FLOW_SEG_HDR_IPV6 |
 				  ICE_FLOW_SEG_HDR_IPV_OTHER);
 		break;
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_IPV6 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_UDP:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_PPP |
+				  ICE_FLOW_SEG_HDR_IPV6 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_IPV4 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_UDP:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_PPP |
+				  ICE_FLOW_SEG_HDR_IPV4 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+
 	default:
 		PMD_DRV_LOG(ERR, "not supported filter type.");
 		break;
@@ -1170,7 +1249,10 @@ ice_fdir_uninit(struct ice_adapter *ad)
 static int
 ice_fdir_is_tunnel_profile(enum ice_fdir_tunnel_type tunnel_type)
 {
-	if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN)
+	if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_GTPU ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_GTPU_EH)
 		return 1;
 	else
 		return 0;
@@ -1239,6 +1321,9 @@ ice_fdir_extract_fltr_key(struct ice_fdir_fltr_pattern *key,
 	rte_memcpy(&key->gtpu_data, &input->gtpu_data, sizeof(key->gtpu_data));
 	rte_memcpy(&key->gtpu_mask, &input->gtpu_mask, sizeof(key->gtpu_mask));
 
+	rte_memcpy(&key->l2tpv2_data, &input->l2tpv2_data, sizeof(key->l2tpv2_data));
+	rte_memcpy(&key->l2tpv2_mask, &input->l2tpv2_mask, sizeof(key->l2tpv2_mask));
+
 	key->tunnel_type = filter->tunnel_type;
 }
 
@@ -1797,16 +1882,22 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 	const struct rte_flow_item_gtp *gtp_spec, *gtp_mask;
 	const struct rte_flow_item_gtp_psc *gtp_psc_spec, *gtp_psc_mask;
 	const struct rte_flow_item_esp *esp_spec, *esp_mask;
+	const struct rte_flow_item_l2tpv2 *l2tpv2_spec, *l2tpv2_mask;
+	const struct rte_flow_item_ppp *ppp_spec, *ppp_mask;
 	uint64_t input_set_i = ICE_INSET_NONE; /* only for tunnel inner */
 	uint64_t input_set_o = ICE_INSET_NONE; /* non-tunnel and tunnel outer */
 	uint64_t *input_set;
 	uint8_t flow_type = ICE_FLTR_PTYPE_NONF_NONE;
+	enum rte_flow_item_type inner_l3 = RTE_FLOW_ITEM_TYPE_END;
+	enum rte_flow_item_type inner_l4 = RTE_FLOW_ITEM_TYPE_END;
+	enum rte_flow_item_type current_l3 = RTE_FLOW_ITEM_TYPE_END;
+	bool ppp_present = false;
 	uint8_t  ipv6_addr_mask[16] = {
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
 	};
 	uint32_t vtc_flow_cpu;
-	uint16_t ether_type;
+	uint16_t ether_type = 0, flags_version = 0;
 	enum rte_flow_item_type next_type;
 	bool is_outer = true;
 	struct ice_fdir_extra *p_ext_data;
@@ -2001,22 +2092,30 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				   &eth_spec->hdr.ether_type, sizeof(eth_spec->hdr.ether_type));
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV4:
-			flow_type = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
-			l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			/* Only set flow_type for outer IPv4, track inner L3 for tunnels */
+			if (is_outer || !tunnel_type) {
+				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
+				l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			} else {
+				inner_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			}
+
 			ipv4_spec = item->spec;
 			ipv4_last = item->last;
 			ipv4_mask = item->mask;
 			p_v4 = (tunnel_type && is_outer) ?
-			       &filter->input.ip_outer.v4 :
-			       &filter->input.ip.v4;
+					&filter->input.ip_outer.v4 :
+					&filter->input.ip.v4;
 
 			if (!(ipv4_spec && ipv4_mask))
 				break;
 
 			/* Check IPv4 mask and update input set */
 			if (ipv4_mask->hdr.version_ihl ||
-			    ipv4_mask->hdr.total_length ||
-			    ipv4_mask->hdr.hdr_checksum) {
+				ipv4_mask->hdr.total_length ||
+				ipv4_mask->hdr.hdr_checksum) {
 				rte_flow_error_set(error, EINVAL,
 						   RTE_FLOW_ERROR_TYPE_ITEM,
 						   item,
@@ -2048,10 +2147,20 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				ipv4_mask->hdr.dst_addr != UINT32_MAX)
 				return -rte_errno;
 
-			if (ipv4_mask->hdr.dst_addr == UINT32_MAX)
-				*input_set |= ICE_INSET_IPV4_DST;
-			if (ipv4_mask->hdr.src_addr == UINT32_MAX)
-				*input_set |= ICE_INSET_IPV4_SRC;
+			if (ipv4_mask->hdr.dst_addr == UINT32_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV4_DST;
+				else
+					*input_set |= ICE_INSET_IPV4_DST;
+			}
+			if (ipv4_mask->hdr.src_addr == UINT32_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV4_SRC;
+				else
+					*input_set |= ICE_INSET_IPV4_SRC;
+			}
 			if (ipv4_mask->hdr.time_to_live == UINT8_MAX)
 				*input_set |= ICE_INSET_IPV4_TTL;
 			if (ipv4_mask->hdr.next_proto_id == UINT8_MAX)
@@ -2092,8 +2201,15 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV6:
-			flow_type = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
-			l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			if (is_outer || !tunnel_type) {
+				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
+				l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			} else {
+				inner_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			}
+
 			ipv6_spec = item->spec;
 			ipv6_mask = item->mask;
 			p_v6 = (tunnel_type && is_outer) ?
@@ -2113,15 +2229,24 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 			}
 
 			if (!memcmp(&ipv6_mask->hdr.src_addr, ipv6_addr_mask,
-				    sizeof(ipv6_mask->hdr.src_addr)))
-				*input_set |= ICE_INSET_IPV6_SRC;
+				    sizeof(ipv6_mask->hdr.src_addr))) {
+				if (tunnel_type && !is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV6_SRC;
+				else
+					*input_set |= ICE_INSET_IPV6_SRC;
+			}
 			if (!memcmp(&ipv6_mask->hdr.dst_addr, ipv6_addr_mask,
-				    sizeof(ipv6_mask->hdr.dst_addr)))
-				*input_set |= ICE_INSET_IPV6_DST;
-
+				    sizeof(ipv6_mask->hdr.dst_addr))) {
+				if (tunnel_type && !is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV6_DST;
+				else
+					*input_set |= ICE_INSET_IPV6_DST;
+			}
 			if ((ipv6_mask->hdr.vtc_flow &
-			     rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
-			    == rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
+			     rte_cpu_to_be_32(ICE_IPV6_TC_MASK)) ==
+			    rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
 				*input_set |= ICE_INSET_IPV6_TC;
 			if (ipv6_mask->hdr.proto == UINT8_MAX)
 				*input_set |= ICE_INSET_IPV6_NEXT_HDR;
@@ -2167,10 +2292,16 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 			break;
 
 		case RTE_FLOW_ITEM_TYPE_TCP:
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
+			if (!is_outer && tunnel_type) {
+				/* For inner TCP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_TCP;
+			} else {
+				/* For outer TCP, update flow_type normally */
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
+			}
 
 			tcp_spec = item->spec;
 			tcp_mask = item->mask;
@@ -2201,28 +2332,44 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				tcp_mask->hdr.dst_port != UINT16_MAX)
 				return -rte_errno;
 
-			if (tcp_mask->hdr.src_port == UINT16_MAX)
-				*input_set |= ICE_INSET_TCP_SRC_PORT;
-			if (tcp_mask->hdr.dst_port == UINT16_MAX)
-				*input_set |= ICE_INSET_TCP_DST_PORT;
+			if (tcp_mask->hdr.src_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_TCP_SRC_PORT;
+				else
+					*input_set |= ICE_INSET_TCP_SRC_PORT;
+			}
+			if (tcp_mask->hdr.dst_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_TCP_DST_PORT;
+				else
+					*input_set |= ICE_INSET_TCP_DST_PORT;
+			}
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = tcp_spec->hdr.dst_port;
 				p_v4->src_port = tcp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->dst_port = tcp_spec->hdr.dst_port;
 				p_v6->src_port = tcp_spec->hdr.src_port;
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_UDP:
-			l4 = RTE_FLOW_ITEM_TYPE_UDP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
+			if (!is_outer && tunnel_type) {
+				/* For inner UDP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_UDP;
+			} else {
+				/* For outer UDP, update flow_type normally */
+				l4 = RTE_FLOW_ITEM_TYPE_UDP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
+			}
 
 			udp_spec = item->spec;
 			udp_mask = item->mask;
@@ -2248,27 +2395,43 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				udp_mask->hdr.dst_port != UINT16_MAX)
 				return -rte_errno;
 
-			if (udp_mask->hdr.src_port == UINT16_MAX)
-				*input_set |= ICE_INSET_UDP_SRC_PORT;
-			if (udp_mask->hdr.dst_port == UINT16_MAX)
-				*input_set |= ICE_INSET_UDP_DST_PORT;
+			if (udp_mask->hdr.src_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_UDP_SRC_PORT;
+				else
+					*input_set |= ICE_INSET_UDP_SRC_PORT;
+			}
+			if (udp_mask->hdr.dst_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_UDP_DST_PORT;
+				else
+					*input_set |= ICE_INSET_UDP_DST_PORT;
+			}
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = udp_spec->hdr.dst_port;
 				p_v4->src_port = udp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->src_port = udp_spec->hdr.src_port;
 				p_v6->dst_port = udp_spec->hdr.dst_port;
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_SCTP:
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
+			if (!is_outer && tunnel_type) {
+				/* For inner SCTP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_SCTP;
+			} else {
+				/* For outer SCTP, update flow_type normally */
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
+			}
 
 			sctp_spec = item->spec;
 			sctp_mask = item->mask;
@@ -2299,11 +2462,11 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				*input_set |= ICE_INSET_SCTP_DST_PORT;
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = sctp_spec->hdr.dst_port;
 				p_v4->src_port = sctp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->dst_port = sctp_spec->hdr.dst_port;
 				p_v6->src_port = sctp_spec->hdr.src_port;
@@ -2406,6 +2569,114 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				filter->input.ip.v6.sec_parm_idx =
 					esp_spec->hdr.spi;
 			break;
+		case RTE_FLOW_ITEM_TYPE_L2TPV2:
+			struct ice_fdir_l2tpv2 l2tpv2_be;
+
+			l2tpv2_spec = item->spec;
+			l2tpv2_mask = item->mask;
+
+			if (!(l2tpv2_spec && l2tpv2_mask))
+				break;
+
+			flags_version =
+				rte_be_to_cpu_16(l2tpv2_spec->hdr.common.flags_version);
+			if ((flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+			     l2tpv2_mask->hdr.type3.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA &&
+			     l2tpv2_mask->hdr.type7.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L &&
+			     l2tpv2_mask->hdr.type6.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S &&
+			     l2tpv2_mask->hdr.type5.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_O &&
+			     l2tpv2_mask->hdr.type4.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S &&
+			     l2tpv2_mask->hdr.type3.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_O &&
+			     l2tpv2_mask->hdr.type2.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S_O &&
+			     l2tpv2_mask->hdr.type1.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S_O &&
+			     l2tpv2_mask->hdr.type0.session_id == UINT16_MAX)) {
+				input_set_o |= ICE_INSET_L2TPV2OIP_SESSION_ID;
+			}
+
+			tunnel_type = ICE_FDIR_TUNNEL_TYPE_L2TPV2;
+			memset(&l2tpv2_be, 0, sizeof(l2tpv2_be));
+
+			if (flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type7.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type7.session_id);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.session_id);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_O) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.session_id);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_O) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.session_id);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S_O) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.nr);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S_O) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.nr);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.offset_size);
+			}
+
+			/* Copy converted values to filter */
+			filter->input.l2tpv2_data.flags_version = rte_cpu_to_be_16(flags_version);
+			filter->input.l2tpv2_data.length = l2tpv2_be.length;
+			filter->input.l2tpv2_data.tunnel_id = l2tpv2_be.tunnel_id;
+			filter->input.l2tpv2_data.session_id = l2tpv2_be.session_id;
+			filter->input.l2tpv2_data.ns = l2tpv2_be.ns;
+			filter->input.l2tpv2_data.nr = l2tpv2_be.nr;
+			filter->input.l2tpv2_data.offset_size = l2tpv2_be.offset_size;
+			break;
+		case RTE_FLOW_ITEM_TYPE_PPP:
+			ppp_spec = item->spec;
+			ppp_mask = item->mask;
+
+			/* PPP marks transition from outer to inner in L2TPv2 tunnels */
+			if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2) {
+				is_outer = false;
+				ppp_present = true;
+			}
+
+			if (ppp_spec && ppp_mask) {
+				filter->input.ppp_data.addr = ppp_spec->hdr.addr;
+				filter->input.ppp_data.ctrl = ppp_spec->hdr.ctrl;
+				filter->input.ppp_data.proto_id = ppp_spec->hdr.proto_id;
+			}
+			break;
 		default:
 			rte_flow_error_set(error, EINVAL,
 					   RTE_FLOW_ERROR_TYPE_ITEM,
@@ -2439,6 +2710,74 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN &&
 		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
 		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP_VXLAN_IPV4_OTHER;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP &&
+		flags_version != RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP &&
+		flags_version != RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP &&
+		flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP &&
+		flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL;
+	/* Handle L2TPV2 with PPP and inner protocols */
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		ppp_present &&
+		inner_l3 != RTE_FLOW_ITEM_TYPE_END) {
+		/* L2TPV2 with inner IPv4/IPv6 */
+		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP) {
+			/* Outer IPv4 + inner protocol */
+			if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4;
+			} else if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6;
+			}
+		} else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP) {
+			/* Outer IPv6 + inner protocol */
+			if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4;
+			} else if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6;
+			}
+		}
+	} else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 && ppp_present &&
+		inner_l3 == RTE_FLOW_ITEM_TYPE_END) {
+		/* Handle L2TPV2 with PPP but no inner protocol specified */
+		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP)
+			flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP;
+		else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP)
+			flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP;
+	}
 
 	filter->tunnel_type = tunnel_type;
 	filter->input.flow_type = flow_type;
@@ -2482,9 +2821,10 @@ ice_fdir_parse(struct ice_adapter *ad,
 	input_set = filter->input_set_o | filter->input_set_i;
 	input_set = raw ? ~input_set : input_set;
 
-	if (!input_set || filter->input_set_o &
-	    ~(item->input_set_mask_o | ICE_INSET_ETHERTYPE) ||
-	    filter->input_set_i & ~item->input_set_mask_i) {
+	if (!input_set ||
+	    (filter->input_set_o &
+	     ~(item->input_set_mask_o | ICE_INSET_ETHERTYPE)) ||
+	    (filter->input_set_i & ~item->input_set_mask_i)) {
 		rte_flow_error_set(error, EINVAL,
 				   RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
 				   pattern,
diff --git a/drivers/net/intel/ice/ice_generic_flow.c b/drivers/net/intel/ice/ice_generic_flow.c
index 4049157eab..644958cccf 100644
--- a/drivers/net/intel/ice/ice_generic_flow.c
+++ b/drivers/net/intel/ice/ice_generic_flow.c
@@ -1794,6 +1794,166 @@ enum rte_flow_item_type pattern_eth_ipv6_pfcp[] = {
 	RTE_FLOW_ITEM_TYPE_PFCP,
 	RTE_FLOW_ITEM_TYPE_END,
 };
+enum rte_flow_item_type pattern_eth_ipv4_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+/* PPPoL2TPv2oUDP */
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 
 typedef bool (*parse_engine_t)(struct ice_adapter *ad,
 			       struct rte_flow *flow,
@@ -2021,6 +2181,23 @@ static struct ice_ptype_match ice_ptype_map[] = {
 	{pattern_eth_ipv4_udp_esp,			ICE_MAC_IPV4_NAT_T_ESP},
 	{pattern_eth_ipv4_ah,				ICE_MAC_IPV4_AH},
 	{pattern_eth_ipv4_l2tp,				ICE_MAC_IPV4_L2TPV3},
+	{pattern_eth_ipv4_udp_l2tpv2,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp,	ICE_MAC_IPV6_L2TPV2},
+
 	{pattern_eth_ipv4_pfcp,				ICE_MAC_IPV4_PFCP_SESSION},
 	{pattern_eth_ipv6,				ICE_PTYPE_IPV6_PAY},
 	{pattern_eth_ipv6_udp,				ICE_PTYPE_IPV6_UDP_PAY},
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 5/7] net/ice: add L2TPv2 hardware packet generation
  2026-02-09 11:56 ` [PATCH v2 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                     ` (3 preceding siblings ...)
  2026-02-09 11:56   ` [PATCH v2 4/7] net/ice: add L2TPv2 flow patterns and FDIR support Shaiq Wani
@ 2026-02-09 11:56   ` Shaiq Wani
  2026-02-09 11:56   ` [PATCH v2 6/7] net/ice: add L2TPv2 RSS hash support Shaiq Wani
  2026-02-09 11:56   ` [PATCH v2 7/7] doc: update release notes Shaiq Wani
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-09 11:56 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add L2TPv2 packet type cases to ice_fdir_get_gen_prgm_pkt() to enable
hardware packet generation for FDIR rule programming.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/base/ice_fdir.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/intel/ice/base/ice_fdir.c b/drivers/net/intel/ice/base/ice_fdir.c
index f62313c559..2c0cb99854 100644
--- a/drivers/net/intel/ice/base/ice_fdir.c
+++ b/drivers/net/intel/ice/base/ice_fdir.c
@@ -4027,6 +4027,9 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
 				   ICE_NONDMA_TO_NONDMA);
 			loc = &pkt[ICE_FDIR_V6_V4_GTPOGRE_EH_PKT_OFF];
 			break;
+		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL:
+		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2:
+		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP:
 		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4:
 		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP:
 		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP:
@@ -4038,6 +4041,9 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
 						      idx, offset, tun);
 			loc = &pkt[pos];
 			break;
+		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL:
+		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2:
+		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP:
 		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4:
 		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP:
 		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP:
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 6/7] net/ice: add L2TPv2 RSS hash support
  2026-02-09 11:56 ` [PATCH v2 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                     ` (4 preceding siblings ...)
  2026-02-09 11:56   ` [PATCH v2 5/7] net/ice: add L2TPv2 hardware packet generation Shaiq Wani
@ 2026-02-09 11:56   ` Shaiq Wani
  2026-02-09 11:56   ` [PATCH v2 7/7] doc: update release notes Shaiq Wani
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-09 11:56 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add RSS (Receive Side Scaling) hash support for L2TPv2 packets.
define hash templates and patterns for distributing L2TPv2 traffic
across multiple receive queues based on session IDs and inner headers.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_hash.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/net/intel/ice/ice_hash.c b/drivers/net/intel/ice/ice_hash.c
index afdc8f220a..b20103a452 100644
--- a/drivers/net/intel/ice/ice_hash.c
+++ b/drivers/net/intel/ice/ice_hash.c
@@ -305,6 +305,22 @@ struct ice_rss_hash_cfg eth_ipv4_l2tpv3_tmplt = {
 	0
 };
 
+struct ice_rss_hash_cfg eth_ipv4_l2tpv2_tmplt = {
+	ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
+	ICE_FLOW_SEG_HDR_L2TPV2,
+	ICE_FLOW_HASH_L2TPV2_SESS_ID,
+	ICE_RSS_OUTER_HEADERS,
+	0
+};
+
+struct ice_rss_hash_cfg eth_ipv6_l2tpv2_tmplt = {
+	ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_IPV_OTHER |
+	ICE_FLOW_SEG_HDR_L2TPV2,
+	ICE_FLOW_HASH_L2TPV2_SESS_ID,
+	ICE_RSS_OUTER_HEADERS,
+	0
+};
+
 struct ice_rss_hash_cfg eth_ipv4_pfcp_tmplt = {
 	ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
 	ICE_FLOW_SEG_HDR_PFCP_SESSION,
@@ -480,6 +496,8 @@ struct ice_rss_hash_cfg eth_tmplt = {
 #define ICE_RSS_TYPE_IPV6_AH		(RTE_ETH_RSS_AH | RTE_ETH_RSS_IPV6)
 #define ICE_RSS_TYPE_IPV4_L2TPV3	(RTE_ETH_RSS_L2TPV3 | RTE_ETH_RSS_IPV4)
 #define ICE_RSS_TYPE_IPV6_L2TPV3	(RTE_ETH_RSS_L2TPV3 | RTE_ETH_RSS_IPV6)
+#define ICE_RSS_TYPE_IPV4_L2TPV2	(RTE_ETH_RSS_L2TPV2 | RTE_ETH_RSS_IPV4)
+#define ICE_RSS_TYPE_IPV6_L2TPV2	(RTE_ETH_RSS_L2TPV2 | RTE_ETH_RSS_IPV6)
 #define ICE_RSS_TYPE_IPV4_PFCP		(RTE_ETH_RSS_PFCP | RTE_ETH_RSS_IPV4)
 #define ICE_RSS_TYPE_IPV6_PFCP		(RTE_ETH_RSS_PFCP | RTE_ETH_RSS_IPV6)
 
@@ -522,6 +540,8 @@ static struct ice_pattern_match_item ice_hash_pattern_list[] = {
 	{pattern_eth_ipv4_udp_esp,		ICE_RSS_TYPE_IPV4_ESP,		ICE_INSET_NONE,	&eth_ipv4_udp_esp_tmplt},
 	{pattern_eth_ipv4_ah,			ICE_RSS_TYPE_IPV4_AH,		ICE_INSET_NONE,	&eth_ipv4_ah_tmplt},
 	{pattern_eth_ipv4_l2tp,			ICE_RSS_TYPE_IPV4_L2TPV3,	ICE_INSET_NONE,	&eth_ipv4_l2tpv3_tmplt},
+	{pattern_eth_ipv4_l2tpv2,		ICE_RSS_TYPE_IPV4_L2TPV2,	ICE_INSET_NONE,	&eth_ipv4_l2tpv2_tmplt},
+	{pattern_eth_ipv6_l2tpv2,		ICE_RSS_TYPE_IPV6_L2TPV2,	ICE_INSET_NONE,	&eth_ipv6_l2tpv2_tmplt},
 	{pattern_eth_ipv4_pfcp,			ICE_RSS_TYPE_IPV4_PFCP,		ICE_INSET_NONE,	&eth_ipv4_pfcp_tmplt},
 	/* IPV6 */
 	{pattern_eth_ipv6,			ICE_RSS_TYPE_ETH_IPV6,		ICE_INSET_NONE,	&ipv6_tmplt},
@@ -925,6 +945,11 @@ ice_refine_hash_cfg_l234(struct ice_rss_hash_cfg *hash_cfg,
 			*hash_flds &= ~ICE_FLOW_HASH_L2TPV3_SESS_ID;
 	}
 
+	if (*addl_hdrs & ICE_FLOW_SEG_HDR_L2TPV2) {
+		if (!(rss_type & RTE_ETH_RSS_L2TPV2))
+			*hash_flds &= ~ICE_FLOW_HASH_L2TPV2_SESS_ID;
+	}
+
 	if (*addl_hdrs & ICE_FLOW_SEG_HDR_ESP) {
 		if (!(rss_type & RTE_ETH_RSS_ESP))
 			*hash_flds &= ~ICE_FLOW_HASH_ESP_SPI;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 7/7] doc: update release notes
  2026-02-09 11:56 ` [PATCH v2 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                     ` (5 preceding siblings ...)
  2026-02-09 11:56   ` [PATCH v2 6/7] net/ice: add L2TPv2 RSS hash support Shaiq Wani
@ 2026-02-09 11:56   ` Shaiq Wani
  6 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-09 11:56 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh

Documented the new ice driver FDIR support for
L2TPv2 over UDP in the 26.03 release notes.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
---
 doc/guides/rel_notes/release_26_03.rst | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/doc/guides/rel_notes/release_26_03.rst b/doc/guides/rel_notes/release_26_03.rst
index 031eaa657e..5e955a3ec4 100644
--- a/doc/guides/rel_notes/release_26_03.rst
+++ b/doc/guides/rel_notes/release_26_03.rst
@@ -63,6 +63,10 @@ New Features
 
   * Added support for pre and post VF reset callbacks.
 
+* **Updated Intel ice driver.**
+
+  * Added Flow Director (FDIR) support for L2TPv2 over UDP.
+
 
 Removed Items
 -------------
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v3 0/7] Add support for L2TPV2 over UDP to ICE PMD
  2026-02-02  9:42 [PATCH 0/6] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                   ` (8 preceding siblings ...)
  2026-02-09 11:56 ` [PATCH v2 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
@ 2026-02-11  6:09 ` Shaiq Wani
  2026-02-11  6:09   ` [PATCH v3 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
                     ` (3 more replies)
  9 siblings, 4 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-11  6:09 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh

This patchset adds L2TPv2 protocol support to the ICE PMD
enabling RSS and Flow Director capabilities for L2TPv2 over UDP traffic.

v3: Fixed compilation issues.

v2: Addressed AI generated review comments.

Shaiq Wani (7):
  net/ice: add L2TPv2 PPP and PPoE data structures
  net/ice: add L2TPv2 tunnel type definition
  net/ice: add L2TPv2 protocol and field definitions
  net/ice: add L2TPv2 flow patterns and FDIR support
  net/ice: add L2TPv2 hardware packet generation
  net/ice: add L2TPv2 RSS hash support
  doc: update release notes

 doc/guides/rel_notes/release_26_03.rst   |   4 +
 drivers/net/intel/ice/base/ice_fdir.c    |   6 +
 drivers/net/intel/ice/base/ice_fdir.h    |  17 +
 drivers/net/intel/ice/ice_ethdev.h       |   4 +
 drivers/net/intel/ice/ice_fdir_filter.c  | 451 ++++++++++++++++++++---
 drivers/net/intel/ice/ice_generic_flow.c | 177 +++++++++
 drivers/net/intel/ice/ice_generic_flow.h | 129 ++++---
 drivers/net/intel/ice/ice_hash.c         |  25 ++
 8 files changed, 717 insertions(+), 96 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH v3 1/7] net/ice: add L2TPv2 PPP and PPoE data structures
  2026-02-11  6:09 ` [PATCH v3 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
@ 2026-02-11  6:09   ` Shaiq Wani
  2026-02-11  6:09   ` [PATCH v3 2/7] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-11  6:09 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add data structure definitions for L2TPv2 PPP and
PPoE protocols to support Flow Director (FDIR) filtering.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/base/ice_fdir.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/net/intel/ice/base/ice_fdir.h b/drivers/net/intel/ice/base/ice_fdir.h
index 3dd03f93f7..3d3b05da4a 100644
--- a/drivers/net/intel/ice/base/ice_fdir.h
+++ b/drivers/net/intel/ice/base/ice_fdir.h
@@ -230,6 +230,20 @@ struct ice_fdir_ecpri {
 	__be16 pc_id;
 };
 
+struct ice_fdir_pppoe {
+	u8 rsrvd_ver_type;
+	u8 rsrvd_code;
+	__be16 session_id;
+	__be16 length;
+	__be16 ppp_prot_id; /* control and data only */
+};
+
+struct ice_fdir_ppp {
+	u8 addr;
+	u8 ctrl;
+	__be16 proto_id;
+};
+
 struct ice_fdir_l2tpv2 {
 	__be16 flags_version;
 	__be16 length;
@@ -279,6 +293,9 @@ struct ice_fdir_fltr {
 	struct ice_fdir_ecpri ecpri_data;
 	struct ice_fdir_ecpri ecpri_mask;
 
+	struct ice_fdir_ppp ppp_data;
+	struct ice_fdir_ppp ppp_mask;
+
 	struct ice_fdir_l2tpv2 l2tpv2_data;
 	struct ice_fdir_l2tpv2 l2tpv2_mask;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v3 2/7] net/ice: add L2TPv2 tunnel type definition
  2026-02-11  6:09 ` [PATCH v3 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
  2026-02-11  6:09   ` [PATCH v3 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
@ 2026-02-11  6:09   ` Shaiq Wani
  2026-02-11  6:09   ` [PATCH v3 3/7] net/ice: add L2TPv2 protocol and field definitions Shaiq Wani
  2026-02-11  6:09   ` [PATCH v3 4/7] net/ice: add L2TPv2 flow patterns and FDIR support Shaiq Wani
  3 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-11  6:09 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add ICE_FDIR_TUNNEL_TYPE_L2TPV2 to the tunnel type enum and
extend ice_fdir_fltr_pattern structure to include L2TPv2 data and
mask fields.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_ethdev.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/intel/ice/ice_ethdev.h b/drivers/net/intel/ice/ice_ethdev.h
index 9562b2b8f1..4b3718f715 100644
--- a/drivers/net/intel/ice/ice_ethdev.h
+++ b/drivers/net/intel/ice/ice_ethdev.h
@@ -369,6 +369,7 @@ enum ice_fdir_tunnel_type {
 	ICE_FDIR_TUNNEL_TYPE_VXLAN,
 	ICE_FDIR_TUNNEL_TYPE_GTPU,
 	ICE_FDIR_TUNNEL_TYPE_GTPU_EH,
+	ICE_FDIR_TUNNEL_TYPE_L2TPV2,
 };
 
 struct rte_flow;
@@ -405,6 +406,9 @@ struct ice_fdir_fltr_pattern {
 	struct ice_fdir_udp_gtp gtpu_data;
 	struct ice_fdir_udp_gtp gtpu_mask;
 
+	struct ice_fdir_l2tpv2 l2tpv2_data;
+	struct ice_fdir_l2tpv2 l2tpv2_mask;
+
 	struct ice_fdir_extra ext_data;
 	struct ice_fdir_extra ext_mask;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v3 3/7] net/ice: add L2TPv2 protocol and field definitions
  2026-02-11  6:09 ` [PATCH v3 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
  2026-02-11  6:09   ` [PATCH v3 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
  2026-02-11  6:09   ` [PATCH v3 2/7] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
@ 2026-02-11  6:09   ` Shaiq Wani
  2026-02-11  6:09   ` [PATCH v3 4/7] net/ice: add L2TPv2 flow patterns and FDIR support Shaiq Wani
  3 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-11  6:09 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add L2TPv2 protocol identifier (ICE_PROT_L2TPV2OIP) and session ID
field definition (ICE_L2TPV2OIP_SESSION_ID) to the generic flow header.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_generic_flow.h | 129 ++++++++++++++++-------
 1 file changed, 88 insertions(+), 41 deletions(-)

diff --git a/drivers/net/intel/ice/ice_generic_flow.h b/drivers/net/intel/ice/ice_generic_flow.h
index 54bbb47398..deaf7b66e5 100644
--- a/drivers/net/intel/ice/ice_generic_flow.h
+++ b/drivers/net/intel/ice/ice_generic_flow.h
@@ -9,15 +9,15 @@
 
 /* protocol */
 
-#define ICE_PROT_MAC			BIT_ULL(1)
-#define ICE_PROT_VLAN			BIT_ULL(2)
-#define ICE_PROT_IPV4			BIT_ULL(3)
-#define ICE_PROT_IPV6			BIT_ULL(4)
-#define ICE_PROT_TCP			BIT_ULL(5)
-#define ICE_PROT_UDP			BIT_ULL(6)
-#define ICE_PROT_SCTP			BIT_ULL(7)
-#define ICE_PROT_ICMP4			BIT_ULL(8)
-#define ICE_PROT_ICMP6			BIT_ULL(9)
+#define ICE_PROT_MAC_OUTER		BIT_ULL(1)
+#define ICE_PROT_VLAN_OUTER		BIT_ULL(2)
+#define ICE_PROT_IPV4_OUTER		BIT_ULL(3)
+#define ICE_PROT_IPV6_OUTER		BIT_ULL(4)
+#define ICE_PROT_TCP_OUTER		BIT_ULL(5)
+#define ICE_PROT_UDP_OUTER		BIT_ULL(6)
+#define ICE_PROT_SCTP_OUTER		BIT_ULL(7)
+#define ICE_PROT_ICMP4_OUTER		BIT_ULL(8)
+#define ICE_PROT_ICMP6_OUTER		BIT_ULL(9)
 #define ICE_PROT_VXLAN			BIT_ULL(10)
 #define ICE_PROT_NVGRE			BIT_ULL(11)
 #define ICE_PROT_GTPU			BIT_ULL(12)
@@ -27,6 +27,16 @@
 #define ICE_PROT_L2TPV3OIP		BIT_ULL(16)
 #define ICE_PROT_PFCP			BIT_ULL(17)
 #define ICE_PROT_NAT_T_ESP		BIT_ULL(18)
+#define ICE_PROT_L2TPV2OIP		BIT_ULL(19)
+#define ICE_PROT_MAC_INNER		BIT_ULL(20)
+#define ICE_PROT_VLAN_INNER		BIT_ULL(21)
+#define ICE_PROT_IPV4_INNER		BIT_ULL(22)
+#define ICE_PROT_IPV6_INNER		BIT_ULL(23)
+#define ICE_PROT_TCP_INNER		BIT_ULL(24)
+#define ICE_PROT_UDP_INNER		BIT_ULL(25)
+#define ICE_PROT_SCTP_INNER		BIT_ULL(26)
+#define ICE_PROT_ICMP4_INNER		BIT_ULL(27)
+#define ICE_PROT_ICMP6_INNER		BIT_ULL(28)
 
 /* field */
 
@@ -53,8 +63,9 @@
 #define ICE_L2TPV3OIP_SESSION_ID	BIT_ULL(43)
 #define ICE_PFCP_SEID			BIT_ULL(42)
 #define ICE_PFCP_S_FIELD		BIT_ULL(41)
-#define ICE_IP_PK_ID		    BIT_ULL(40)
+#define ICE_IP_PK_ID			BIT_ULL(40)
 #define ICE_IP_FRAG_OFS			BIT_ULL(39)
+#define ICE_L2TPV2OIP_SESSION_ID	BIT_ULL(38)
 
 /* input set */
 
@@ -62,39 +73,39 @@
 
 #define ICE_INSET_SMAC			(ICE_SMAC)
 #define ICE_INSET_DMAC			(ICE_DMAC)
-#define ICE_INSET_VLAN			(ICE_PROT_VLAN)
-#define ICE_INSET_VLAN_INNER		(ICE_PROT_VLAN)
-#define ICE_INSET_VLAN_OUTER		(ICE_PROT_VLAN)
+#define ICE_INSET_VLAN			(ICE_PROT_VLAN_OUTER)
+#define ICE_INSET_VLAN_INNER		(ICE_PROT_VLAN_OUTER)
+#define ICE_INSET_VLAN_OUTER		(ICE_PROT_VLAN_OUTER)
 #define ICE_INSET_ETHERTYPE		(ICE_ETHERTYPE)
 
-#define ICE_INSET_IPV4_SRC		(ICE_PROT_IPV4 | ICE_IP_SRC)
-#define ICE_INSET_IPV4_DST		(ICE_PROT_IPV4 | ICE_IP_DST)
-#define ICE_INSET_IPV4_TOS		(ICE_PROT_IPV4 | ICE_IP_TOS)
-#define ICE_INSET_IPV4_PROTO		(ICE_PROT_IPV4 | ICE_IP_PROTO)
-#define ICE_INSET_IPV4_TTL		(ICE_PROT_IPV4 | ICE_IP_TTL)
-#define ICE_INSET_IPV4_PKID		(ICE_PROT_IPV4 | ICE_IP_PK_ID)
-#define ICE_INSET_IPV4_FRAG_OFS	(ICE_PROT_IPV4 | ICE_IP_FRAG_OFS)
-#define ICE_INSET_IPV6_SRC		(ICE_PROT_IPV6 | ICE_IP_SRC)
-#define ICE_INSET_IPV6_DST		(ICE_PROT_IPV6 | ICE_IP_DST)
-#define ICE_INSET_IPV6_NEXT_HDR		(ICE_PROT_IPV6 | ICE_IP_PROTO)
-#define ICE_INSET_IPV6_HOP_LIMIT	(ICE_PROT_IPV6 | ICE_IP_TTL)
-#define ICE_INSET_IPV6_TC		(ICE_PROT_IPV6 | ICE_IP_TOS)
-#define ICE_INSET_IPV6_PKID		(ICE_PROT_IPV6 | ICE_IP_PK_ID)
-
-#define ICE_INSET_TCP_SRC_PORT		(ICE_PROT_TCP | ICE_SPORT)
-#define ICE_INSET_TCP_DST_PORT		(ICE_PROT_TCP | ICE_DPORT)
-#define ICE_INSET_UDP_SRC_PORT		(ICE_PROT_UDP | ICE_SPORT)
-#define ICE_INSET_UDP_DST_PORT		(ICE_PROT_UDP | ICE_DPORT)
-#define ICE_INSET_SCTP_SRC_PORT		(ICE_PROT_SCTP | ICE_SPORT)
-#define ICE_INSET_SCTP_DST_PORT		(ICE_PROT_SCTP | ICE_DPORT)
-#define ICE_INSET_ICMP4_SRC_PORT	(ICE_PROT_ICMP4 | ICE_SPORT)
-#define ICE_INSET_ICMP4_DST_PORT	(ICE_PROT_ICMP4 | ICE_DPORT)
-#define ICE_INSET_ICMP6_SRC_PORT	(ICE_PROT_ICMP6 | ICE_SPORT)
-#define ICE_INSET_ICMP6_DST_PORT	(ICE_PROT_ICMP6 | ICE_DPORT)
-#define ICE_INSET_ICMP4_TYPE		(ICE_PROT_ICMP4 | ICE_ICMP_TYPE)
-#define ICE_INSET_ICMP4_CODE		(ICE_PROT_ICMP4 | ICE_ICMP_CODE)
-#define ICE_INSET_ICMP6_TYPE		(ICE_PROT_ICMP6 | ICE_ICMP_TYPE)
-#define ICE_INSET_ICMP6_CODE		(ICE_PROT_ICMP6 | ICE_ICMP_CODE)
+#define ICE_INSET_IPV4_SRC		(ICE_PROT_IPV4_OUTER | ICE_IP_SRC)
+#define ICE_INSET_IPV4_DST		(ICE_PROT_IPV4_OUTER | ICE_IP_DST)
+#define ICE_INSET_IPV4_TOS		(ICE_PROT_IPV4_OUTER | ICE_IP_TOS)
+#define ICE_INSET_IPV4_PROTO		(ICE_PROT_IPV4_OUTER | ICE_IP_PROTO)
+#define ICE_INSET_IPV4_TTL		(ICE_PROT_IPV4_OUTER | ICE_IP_TTL)
+#define ICE_INSET_IPV4_PKID		(ICE_PROT_IPV4_OUTER | ICE_IP_PK_ID)
+#define ICE_INSET_IPV4_FRAG_OFS	(ICE_PROT_IPV4_OUTER | ICE_IP_FRAG_OFS)
+#define ICE_INSET_IPV6_SRC		(ICE_PROT_IPV6_OUTER | ICE_IP_SRC)
+#define ICE_INSET_IPV6_DST		(ICE_PROT_IPV6_OUTER | ICE_IP_DST)
+#define ICE_INSET_IPV6_NEXT_HDR		(ICE_PROT_IPV6_OUTER | ICE_IP_PROTO)
+#define ICE_INSET_IPV6_HOP_LIMIT	(ICE_PROT_IPV6_OUTER | ICE_IP_TTL)
+#define ICE_INSET_IPV6_TC		(ICE_PROT_IPV6_OUTER | ICE_IP_TOS)
+#define ICE_INSET_IPV6_PKID		(ICE_PROT_IPV6_OUTER | ICE_IP_PK_ID)
+
+#define ICE_INSET_TCP_SRC_PORT		(ICE_PROT_TCP_OUTER | ICE_SPORT)
+#define ICE_INSET_TCP_DST_PORT		(ICE_PROT_TCP_OUTER | ICE_DPORT)
+#define ICE_INSET_UDP_SRC_PORT		(ICE_PROT_UDP_OUTER | ICE_SPORT)
+#define ICE_INSET_UDP_DST_PORT		(ICE_PROT_UDP_OUTER | ICE_DPORT)
+#define ICE_INSET_SCTP_SRC_PORT		(ICE_PROT_SCTP_OUTER | ICE_SPORT)
+#define ICE_INSET_SCTP_DST_PORT		(ICE_PROT_SCTP_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP4_SRC_PORT	(ICE_PROT_ICMP4_OUTER | ICE_SPORT)
+#define ICE_INSET_ICMP4_DST_PORT	(ICE_PROT_ICMP4_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP6_SRC_PORT	(ICE_PROT_ICMP6_OUTER | ICE_SPORT)
+#define ICE_INSET_ICMP6_DST_PORT	(ICE_PROT_ICMP6_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP4_TYPE		(ICE_PROT_ICMP4_OUTER | ICE_ICMP_TYPE)
+#define ICE_INSET_ICMP4_CODE		(ICE_PROT_ICMP4_OUTER | ICE_ICMP_CODE)
+#define ICE_INSET_ICMP6_TYPE		(ICE_PROT_ICMP6_OUTER | ICE_ICMP_TYPE)
+#define ICE_INSET_ICMP6_CODE		(ICE_PROT_ICMP6_OUTER | ICE_ICMP_CODE)
 
 /* tunnel */
 
@@ -122,6 +133,24 @@
 	(ICE_PROT_PFCP | ICE_PFCP_S_FIELD | ICE_PFCP_SEID)
 #define ICE_INSET_NAT_T_ESP_SPI \
 	(ICE_PROT_NAT_T_ESP | ICE_ESP_SPI)
+#define ICE_INSET_L2TPV2OIP_SESSION_ID \
+	(ICE_PROT_L2TPV2OIP | ICE_L2TPV2OIP_SESSION_ID)
+#define ICE_INSET_TUN_IPV4_SRC \
+	(ICE_PROT_IPV4_INNER | ICE_IP_SRC)
+#define ICE_INSET_TUN_IPV4_DST \
+	(ICE_PROT_IPV4_INNER | ICE_IP_DST)
+#define ICE_INSET_TUN_UDP_SRC_PORT \
+	(ICE_PROT_UDP_INNER | ICE_SPORT)
+#define ICE_INSET_TUN_UDP_DST_PORT \
+	(ICE_PROT_UDP_INNER | ICE_DPORT)
+#define ICE_INSET_TUN_TCP_SRC_PORT \
+	(ICE_PROT_TCP_INNER | ICE_SPORT)
+#define ICE_INSET_TUN_TCP_DST_PORT \
+	(ICE_PROT_TCP_INNER | ICE_DPORT)
+#define ICE_INSET_TUN_IPV6_SRC \
+	(ICE_PROT_IPV6_INNER | ICE_IP_SRC)
+#define ICE_INSET_TUN_IPV6_DST \
+	(ICE_PROT_IPV6_INNER | ICE_IP_DST)
 
 /* empty pattern */
 extern enum rte_flow_item_type pattern_empty[];
@@ -400,6 +429,24 @@ extern enum rte_flow_item_type pattern_eth_ipv6_udp_ah[];
 /* L2TP */
 extern enum rte_flow_item_type pattern_eth_ipv4_l2tp[];
 extern enum rte_flow_item_type pattern_eth_ipv6_l2tp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv6_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp[];
 
 /* PFCP */
 extern enum rte_flow_item_type pattern_eth_ipv4_pfcp[];
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v3 4/7] net/ice: add L2TPv2 flow patterns and FDIR support
  2026-02-11  6:09 ` [PATCH v3 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                     ` (2 preceding siblings ...)
  2026-02-11  6:09   ` [PATCH v3 3/7] net/ice: add L2TPv2 protocol and field definitions Shaiq Wani
@ 2026-02-11  6:09   ` Shaiq Wani
  3 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-11  6:09 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Implement comprehensive L2TPv2 support for Flow Director
-Flow pattern definitions for different L2TPv2 packet combinations
-FDIR filter parsing logic
-Flow type assignment for proper packet classification

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_fdir_filter.c  | 451 ++++++++++++++++++++---
 drivers/net/intel/ice/ice_generic_flow.c | 177 +++++++++
 2 files changed, 573 insertions(+), 55 deletions(-)

diff --git a/drivers/net/intel/ice/ice_fdir_filter.c b/drivers/net/intel/ice/ice_fdir_filter.c
index f7730ec6ab..6a5d605f03 100644
--- a/drivers/net/intel/ice/ice_fdir_filter.c
+++ b/drivers/net/intel/ice/ice_fdir_filter.c
@@ -107,6 +107,31 @@
 	ICE_INSET_IPV6_SRC | ICE_INSET_IPV6_DST | \
 	ICE_INSET_NAT_T_ESP_SPI)
 
+#define ICE_FDIR_INSET_L2TPV2 (\
+	ICE_INSET_SMAC | ICE_INSET_DMAC | ICE_INSET_L2TPV2OIP_SESSION_ID)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4 (\
+	ICE_INSET_TUN_IPV4_SRC | ICE_INSET_TUN_IPV4_DST)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV4 | ICE_INSET_TUN_UDP_SRC_PORT | \
+	ICE_INSET_TUN_UDP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV4 | ICE_INSET_TUN_TCP_SRC_PORT | \
+	ICE_INSET_TUN_TCP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6 (\
+	ICE_INSET_TUN_IPV6_SRC | ICE_INSET_TUN_IPV6_DST)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV6 | ICE_INSET_TUN_UDP_SRC_PORT | \
+	ICE_INSET_TUN_UDP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV6 | ICE_INSET_TUN_TCP_SRC_PORT | \
+	ICE_INSET_TUN_TCP_DST_PORT)
+
 static struct ice_pattern_match_item ice_fdir_supported_pattern[] = {
 	{pattern_raw,					ICE_INSET_NONE,			ICE_INSET_NONE,			ICE_INSET_NONE},
 	{pattern_ethertype,				ICE_FDIR_INSET_ETH,		ICE_INSET_NONE,			ICE_INSET_NONE},
@@ -132,10 +157,26 @@ static struct ice_pattern_match_item ice_fdir_supported_pattern[] = {
 	{pattern_eth_ipv4_udp_vxlan_eth_ipv4_tcp,	ICE_FDIR_INSET_ETH_IPV4_VXLAN,	ICE_FDIR_INSET_ETH_IPV4_TCP,	ICE_INSET_NONE},
 	{pattern_eth_ipv4_udp_vxlan_eth_ipv4_sctp,	ICE_FDIR_INSET_ETH_IPV4_VXLAN,	ICE_FDIR_INSET_ETH_IPV4_SCTP,	ICE_INSET_NONE},
 	/* duplicated GTPU input set in 3rd column to align with shared code behavior. Ideally, only put GTPU field in 2nd column. */
-	{pattern_eth_ipv4_gtpu,				ICE_FDIR_INSET_IPV4_GTPU,	ICE_FDIR_INSET_IPV4_GTPU,	ICE_INSET_NONE},
-	{pattern_eth_ipv4_gtpu_eh,			ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_INSET_NONE},
-	{pattern_eth_ipv6_gtpu,				ICE_FDIR_INSET_IPV6_GTPU,	ICE_FDIR_INSET_IPV6_GTPU,	ICE_INSET_NONE},
-	{pattern_eth_ipv6_gtpu_eh,			ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_gtpu,				ICE_FDIR_INSET_IPV4_GTPU,	ICE_FDIR_INSET_IPV4_GTPU,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_gtpu_eh,			ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_FDIR_INSET_IPV4_GTPU_EH,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_gtpu,				ICE_FDIR_INSET_IPV6_GTPU,	ICE_FDIR_INSET_IPV6_GTPU,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_gtpu_eh,			ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_FDIR_INSET_IPV6_GTPU_EH,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2,			ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp,		ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2,			ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp,		ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP,	ICE_INSET_NONE},
 };
 
 static int
@@ -957,6 +998,7 @@ ice_fdir_input_set_parse(uint64_t inset, enum ice_flow_field *field)
 		{ICE_INSET_VXLAN_VNI, ICE_FLOW_FIELD_IDX_VXLAN_VNI},
 		{ICE_INSET_ESP_SPI, ICE_FLOW_FIELD_IDX_ESP_SPI},
 		{ICE_INSET_NAT_T_ESP_SPI, ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI},
+		{ICE_INSET_L2TPV2OIP_SESSION_ID, ICE_FLOW_FIELD_IDX_L2TPV2_SESS_ID},
 	};
 
 	for (i = 0, j = 0; i < RTE_DIM(ice_inset_map); i++) {
@@ -1068,6 +1110,43 @@ ice_fdir_input_set_hdrs(enum ice_fltr_ptype flow, struct ice_flow_seg_info *seg)
 				  ICE_FLOW_SEG_HDR_IPV6 |
 				  ICE_FLOW_SEG_HDR_IPV_OTHER);
 		break;
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_IPV6 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_UDP:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_PPP |
+				  ICE_FLOW_SEG_HDR_IPV6 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_IPV4 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_UDP:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_PPP |
+				  ICE_FLOW_SEG_HDR_IPV4 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+
 	default:
 		PMD_DRV_LOG(ERR, "not supported filter type.");
 		break;
@@ -1170,7 +1249,10 @@ ice_fdir_uninit(struct ice_adapter *ad)
 static int
 ice_fdir_is_tunnel_profile(enum ice_fdir_tunnel_type tunnel_type)
 {
-	if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN)
+	if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_GTPU ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_GTPU_EH)
 		return 1;
 	else
 		return 0;
@@ -1239,6 +1321,9 @@ ice_fdir_extract_fltr_key(struct ice_fdir_fltr_pattern *key,
 	rte_memcpy(&key->gtpu_data, &input->gtpu_data, sizeof(key->gtpu_data));
 	rte_memcpy(&key->gtpu_mask, &input->gtpu_mask, sizeof(key->gtpu_mask));
 
+	rte_memcpy(&key->l2tpv2_data, &input->l2tpv2_data, sizeof(key->l2tpv2_data));
+	rte_memcpy(&key->l2tpv2_mask, &input->l2tpv2_mask, sizeof(key->l2tpv2_mask));
+
 	key->tunnel_type = filter->tunnel_type;
 }
 
@@ -1797,16 +1882,22 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 	const struct rte_flow_item_gtp *gtp_spec, *gtp_mask;
 	const struct rte_flow_item_gtp_psc *gtp_psc_spec, *gtp_psc_mask;
 	const struct rte_flow_item_esp *esp_spec, *esp_mask;
+	const struct rte_flow_item_l2tpv2 *l2tpv2_spec, *l2tpv2_mask;
+	const struct rte_flow_item_ppp *ppp_spec, *ppp_mask;
 	uint64_t input_set_i = ICE_INSET_NONE; /* only for tunnel inner */
 	uint64_t input_set_o = ICE_INSET_NONE; /* non-tunnel and tunnel outer */
 	uint64_t *input_set;
 	uint8_t flow_type = ICE_FLTR_PTYPE_NONF_NONE;
+	enum rte_flow_item_type inner_l3 = RTE_FLOW_ITEM_TYPE_END;
+	enum rte_flow_item_type inner_l4 = RTE_FLOW_ITEM_TYPE_END;
+	enum rte_flow_item_type current_l3 = RTE_FLOW_ITEM_TYPE_END;
+	bool ppp_present = false;
 	uint8_t  ipv6_addr_mask[16] = {
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
 	};
 	uint32_t vtc_flow_cpu;
-	uint16_t ether_type;
+	uint16_t ether_type = 0, flags_version = 0;
 	enum rte_flow_item_type next_type;
 	bool is_outer = true;
 	struct ice_fdir_extra *p_ext_data;
@@ -2001,22 +2092,30 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				   &eth_spec->hdr.ether_type, sizeof(eth_spec->hdr.ether_type));
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV4:
-			flow_type = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
-			l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			/* Only set flow_type for outer IPv4, track inner L3 for tunnels */
+			if (is_outer || !tunnel_type) {
+				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
+				l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			} else {
+				inner_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			}
+
 			ipv4_spec = item->spec;
 			ipv4_last = item->last;
 			ipv4_mask = item->mask;
 			p_v4 = (tunnel_type && is_outer) ?
-			       &filter->input.ip_outer.v4 :
-			       &filter->input.ip.v4;
+					&filter->input.ip_outer.v4 :
+					&filter->input.ip.v4;
 
 			if (!(ipv4_spec && ipv4_mask))
 				break;
 
 			/* Check IPv4 mask and update input set */
 			if (ipv4_mask->hdr.version_ihl ||
-			    ipv4_mask->hdr.total_length ||
-			    ipv4_mask->hdr.hdr_checksum) {
+				ipv4_mask->hdr.total_length ||
+				ipv4_mask->hdr.hdr_checksum) {
 				rte_flow_error_set(error, EINVAL,
 						   RTE_FLOW_ERROR_TYPE_ITEM,
 						   item,
@@ -2048,10 +2147,20 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				ipv4_mask->hdr.dst_addr != UINT32_MAX)
 				return -rte_errno;
 
-			if (ipv4_mask->hdr.dst_addr == UINT32_MAX)
-				*input_set |= ICE_INSET_IPV4_DST;
-			if (ipv4_mask->hdr.src_addr == UINT32_MAX)
-				*input_set |= ICE_INSET_IPV4_SRC;
+			if (ipv4_mask->hdr.dst_addr == UINT32_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV4_DST;
+				else
+					*input_set |= ICE_INSET_IPV4_DST;
+			}
+			if (ipv4_mask->hdr.src_addr == UINT32_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV4_SRC;
+				else
+					*input_set |= ICE_INSET_IPV4_SRC;
+			}
 			if (ipv4_mask->hdr.time_to_live == UINT8_MAX)
 				*input_set |= ICE_INSET_IPV4_TTL;
 			if (ipv4_mask->hdr.next_proto_id == UINT8_MAX)
@@ -2092,8 +2201,15 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV6:
-			flow_type = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
-			l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			if (is_outer || !tunnel_type) {
+				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
+				l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			} else {
+				inner_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			}
+
 			ipv6_spec = item->spec;
 			ipv6_mask = item->mask;
 			p_v6 = (tunnel_type && is_outer) ?
@@ -2113,15 +2229,24 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 			}
 
 			if (!memcmp(&ipv6_mask->hdr.src_addr, ipv6_addr_mask,
-				    sizeof(ipv6_mask->hdr.src_addr)))
-				*input_set |= ICE_INSET_IPV6_SRC;
+				    sizeof(ipv6_mask->hdr.src_addr))) {
+				if (tunnel_type && !is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV6_SRC;
+				else
+					*input_set |= ICE_INSET_IPV6_SRC;
+			}
 			if (!memcmp(&ipv6_mask->hdr.dst_addr, ipv6_addr_mask,
-				    sizeof(ipv6_mask->hdr.dst_addr)))
-				*input_set |= ICE_INSET_IPV6_DST;
-
+				    sizeof(ipv6_mask->hdr.dst_addr))) {
+				if (tunnel_type && !is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV6_DST;
+				else
+					*input_set |= ICE_INSET_IPV6_DST;
+			}
 			if ((ipv6_mask->hdr.vtc_flow &
-			     rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
-			    == rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
+			     rte_cpu_to_be_32(ICE_IPV6_TC_MASK)) ==
+			    rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
 				*input_set |= ICE_INSET_IPV6_TC;
 			if (ipv6_mask->hdr.proto == UINT8_MAX)
 				*input_set |= ICE_INSET_IPV6_NEXT_HDR;
@@ -2167,10 +2292,16 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 			break;
 
 		case RTE_FLOW_ITEM_TYPE_TCP:
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
+			if (!is_outer && tunnel_type) {
+				/* For inner TCP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_TCP;
+			} else {
+				/* For outer TCP, update flow_type normally */
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
+			}
 
 			tcp_spec = item->spec;
 			tcp_mask = item->mask;
@@ -2201,28 +2332,44 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				tcp_mask->hdr.dst_port != UINT16_MAX)
 				return -rte_errno;
 
-			if (tcp_mask->hdr.src_port == UINT16_MAX)
-				*input_set |= ICE_INSET_TCP_SRC_PORT;
-			if (tcp_mask->hdr.dst_port == UINT16_MAX)
-				*input_set |= ICE_INSET_TCP_DST_PORT;
+			if (tcp_mask->hdr.src_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_TCP_SRC_PORT;
+				else
+					*input_set |= ICE_INSET_TCP_SRC_PORT;
+			}
+			if (tcp_mask->hdr.dst_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_TCP_DST_PORT;
+				else
+					*input_set |= ICE_INSET_TCP_DST_PORT;
+			}
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = tcp_spec->hdr.dst_port;
 				p_v4->src_port = tcp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->dst_port = tcp_spec->hdr.dst_port;
 				p_v6->src_port = tcp_spec->hdr.src_port;
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_UDP:
-			l4 = RTE_FLOW_ITEM_TYPE_UDP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
+			if (!is_outer && tunnel_type) {
+				/* For inner UDP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_UDP;
+			} else {
+				/* For outer UDP, update flow_type normally */
+				l4 = RTE_FLOW_ITEM_TYPE_UDP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
+			}
 
 			udp_spec = item->spec;
 			udp_mask = item->mask;
@@ -2248,27 +2395,43 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				udp_mask->hdr.dst_port != UINT16_MAX)
 				return -rte_errno;
 
-			if (udp_mask->hdr.src_port == UINT16_MAX)
-				*input_set |= ICE_INSET_UDP_SRC_PORT;
-			if (udp_mask->hdr.dst_port == UINT16_MAX)
-				*input_set |= ICE_INSET_UDP_DST_PORT;
+			if (udp_mask->hdr.src_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_UDP_SRC_PORT;
+				else
+					*input_set |= ICE_INSET_UDP_SRC_PORT;
+			}
+			if (udp_mask->hdr.dst_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_UDP_DST_PORT;
+				else
+					*input_set |= ICE_INSET_UDP_DST_PORT;
+			}
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = udp_spec->hdr.dst_port;
 				p_v4->src_port = udp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->src_port = udp_spec->hdr.src_port;
 				p_v6->dst_port = udp_spec->hdr.dst_port;
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_SCTP:
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
+			if (!is_outer && tunnel_type) {
+				/* For inner SCTP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_SCTP;
+			} else {
+				/* For outer SCTP, update flow_type normally */
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
+			}
 
 			sctp_spec = item->spec;
 			sctp_mask = item->mask;
@@ -2299,11 +2462,11 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				*input_set |= ICE_INSET_SCTP_DST_PORT;
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = sctp_spec->hdr.dst_port;
 				p_v4->src_port = sctp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->dst_port = sctp_spec->hdr.dst_port;
 				p_v6->src_port = sctp_spec->hdr.src_port;
@@ -2406,6 +2569,115 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				filter->input.ip.v6.sec_parm_idx =
 					esp_spec->hdr.spi;
 			break;
+		case RTE_FLOW_ITEM_TYPE_L2TPV2: {
+			struct ice_fdir_l2tpv2 l2tpv2_be;
+
+			l2tpv2_spec = item->spec;
+			l2tpv2_mask = item->mask;
+
+			if (!(l2tpv2_spec && l2tpv2_mask))
+				break;
+
+			flags_version =
+				rte_be_to_cpu_16(l2tpv2_spec->hdr.common.flags_version);
+			if ((flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+			     l2tpv2_mask->hdr.type3.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA &&
+			     l2tpv2_mask->hdr.type7.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L &&
+			     l2tpv2_mask->hdr.type6.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S &&
+			     l2tpv2_mask->hdr.type5.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_O &&
+			     l2tpv2_mask->hdr.type4.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S &&
+			     l2tpv2_mask->hdr.type3.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_O &&
+			     l2tpv2_mask->hdr.type2.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S_O &&
+			     l2tpv2_mask->hdr.type1.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S_O &&
+			     l2tpv2_mask->hdr.type0.session_id == UINT16_MAX)) {
+				input_set_o |= ICE_INSET_L2TPV2OIP_SESSION_ID;
+			}
+
+			tunnel_type = ICE_FDIR_TUNNEL_TYPE_L2TPV2;
+			memset(&l2tpv2_be, 0, sizeof(l2tpv2_be));
+
+			if (flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type7.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type7.session_id);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.session_id);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_O) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.session_id);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_O) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.session_id);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S_O) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.nr);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S_O) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.nr);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.offset_size);
+			}
+
+			/* Copy converted values to filter */
+			filter->input.l2tpv2_data.flags_version = rte_cpu_to_be_16(flags_version);
+			filter->input.l2tpv2_data.length = l2tpv2_be.length;
+			filter->input.l2tpv2_data.tunnel_id = l2tpv2_be.tunnel_id;
+			filter->input.l2tpv2_data.session_id = l2tpv2_be.session_id;
+			filter->input.l2tpv2_data.ns = l2tpv2_be.ns;
+			filter->input.l2tpv2_data.nr = l2tpv2_be.nr;
+			filter->input.l2tpv2_data.offset_size = l2tpv2_be.offset_size;
+			break;
+		}
+		case RTE_FLOW_ITEM_TYPE_PPP:
+			ppp_spec = item->spec;
+			ppp_mask = item->mask;
+
+			/* PPP marks transition from outer to inner in L2TPv2 tunnels */
+			if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2) {
+				is_outer = false;
+				ppp_present = true;
+			}
+
+			if (ppp_spec && ppp_mask) {
+				filter->input.ppp_data.addr = ppp_spec->hdr.addr;
+				filter->input.ppp_data.ctrl = ppp_spec->hdr.ctrl;
+				filter->input.ppp_data.proto_id = ppp_spec->hdr.proto_id;
+			}
+			break;
 		default:
 			rte_flow_error_set(error, EINVAL,
 					   RTE_FLOW_ERROR_TYPE_ITEM,
@@ -2439,6 +2711,74 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN &&
 		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
 		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP_VXLAN_IPV4_OTHER;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP &&
+		flags_version != RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP &&
+		flags_version != RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP &&
+		flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP &&
+		flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL;
+	/* Handle L2TPV2 with PPP and inner protocols */
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		ppp_present &&
+		inner_l3 != RTE_FLOW_ITEM_TYPE_END) {
+		/* L2TPV2 with inner IPv4/IPv6 */
+		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP) {
+			/* Outer IPv4 + inner protocol */
+			if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4;
+			} else if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6;
+			}
+		} else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP) {
+			/* Outer IPv6 + inner protocol */
+			if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4;
+			} else if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6;
+			}
+		}
+	} else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 && ppp_present &&
+		inner_l3 == RTE_FLOW_ITEM_TYPE_END) {
+		/* Handle L2TPV2 with PPP but no inner protocol specified */
+		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP)
+			flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP;
+		else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP)
+			flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP;
+	}
 
 	filter->tunnel_type = tunnel_type;
 	filter->input.flow_type = flow_type;
@@ -2482,9 +2822,10 @@ ice_fdir_parse(struct ice_adapter *ad,
 	input_set = filter->input_set_o | filter->input_set_i;
 	input_set = raw ? ~input_set : input_set;
 
-	if (!input_set || filter->input_set_o &
-	    ~(item->input_set_mask_o | ICE_INSET_ETHERTYPE) ||
-	    filter->input_set_i & ~item->input_set_mask_i) {
+	if (!input_set ||
+	    (filter->input_set_o &
+	     ~(item->input_set_mask_o | ICE_INSET_ETHERTYPE)) ||
+	    (filter->input_set_i & ~item->input_set_mask_i)) {
 		rte_flow_error_set(error, EINVAL,
 				   RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
 				   pattern,
diff --git a/drivers/net/intel/ice/ice_generic_flow.c b/drivers/net/intel/ice/ice_generic_flow.c
index 4049157eab..644958cccf 100644
--- a/drivers/net/intel/ice/ice_generic_flow.c
+++ b/drivers/net/intel/ice/ice_generic_flow.c
@@ -1794,6 +1794,166 @@ enum rte_flow_item_type pattern_eth_ipv6_pfcp[] = {
 	RTE_FLOW_ITEM_TYPE_PFCP,
 	RTE_FLOW_ITEM_TYPE_END,
 };
+enum rte_flow_item_type pattern_eth_ipv4_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+/* PPPoL2TPv2oUDP */
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 
 typedef bool (*parse_engine_t)(struct ice_adapter *ad,
 			       struct rte_flow *flow,
@@ -2021,6 +2181,23 @@ static struct ice_ptype_match ice_ptype_map[] = {
 	{pattern_eth_ipv4_udp_esp,			ICE_MAC_IPV4_NAT_T_ESP},
 	{pattern_eth_ipv4_ah,				ICE_MAC_IPV4_AH},
 	{pattern_eth_ipv4_l2tp,				ICE_MAC_IPV4_L2TPV3},
+	{pattern_eth_ipv4_udp_l2tpv2,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp,	ICE_MAC_IPV6_L2TPV2},
+
 	{pattern_eth_ipv4_pfcp,				ICE_MAC_IPV4_PFCP_SESSION},
 	{pattern_eth_ipv6,				ICE_PTYPE_IPV6_PAY},
 	{pattern_eth_ipv6_udp,				ICE_PTYPE_IPV6_UDP_PAY},
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [PATCH v5 3/7] net/ice: add L2TPv2 protocol and field definitions
  2025-08-26 17:05   ` [PATCH v5 3/7] net/ice: add L2TPv2 protocol and field definitions Shaiq Wani
@ 2026-02-17 17:09     ` Bruce Richardson
  0 siblings, 0 replies; 56+ messages in thread
From: Bruce Richardson @ 2026-02-17 17:09 UTC (permalink / raw)
  To: Shaiq Wani; +Cc: dev, aman.deep.singh, Song Jiale

On Tue, Aug 26, 2025 at 10:35:37PM +0530, Shaiq Wani wrote:
> Add L2TPv2 protocol identifier (ICE_PROT_L2TPV2OIP) and session ID
> field definition (ICE_L2TPV2OIP_SESSION_ID) to the generic flow header.
> 
> Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
> Tested-by: Song Jiale <songx.jiale@intel.com>
> ---
>  drivers/net/intel/ice/ice_generic_flow.h | 129 ++++++++++++++++-------
>  1 file changed, 88 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/net/intel/ice/ice_generic_flow.h b/drivers/net/intel/ice/ice_generic_flow.h
> index 54bbb47398..deaf7b66e5 100644
> --- a/drivers/net/intel/ice/ice_generic_flow.h
> +++ b/drivers/net/intel/ice/ice_generic_flow.h
> @@ -9,15 +9,15 @@
>  
>  /* protocol */
>  
> -#define ICE_PROT_MAC			BIT_ULL(1)
> -#define ICE_PROT_VLAN			BIT_ULL(2)
> -#define ICE_PROT_IPV4			BIT_ULL(3)
> -#define ICE_PROT_IPV6			BIT_ULL(4)
> -#define ICE_PROT_TCP			BIT_ULL(5)
> -#define ICE_PROT_UDP			BIT_ULL(6)
> -#define ICE_PROT_SCTP			BIT_ULL(7)
> -#define ICE_PROT_ICMP4			BIT_ULL(8)
> -#define ICE_PROT_ICMP6			BIT_ULL(9)
> +#define ICE_PROT_MAC_OUTER		BIT_ULL(1)
> +#define ICE_PROT_VLAN_OUTER		BIT_ULL(2)
> +#define ICE_PROT_IPV4_OUTER		BIT_ULL(3)
> +#define ICE_PROT_IPV6_OUTER		BIT_ULL(4)
> +#define ICE_PROT_TCP_OUTER		BIT_ULL(5)
> +#define ICE_PROT_UDP_OUTER		BIT_ULL(6)
> +#define ICE_PROT_SCTP_OUTER		BIT_ULL(7)
> +#define ICE_PROT_ICMP4_OUTER		BIT_ULL(8)
> +#define ICE_PROT_ICMP6_OUTER		BIT_ULL(9)
>  #define ICE_PROT_VXLAN			BIT_ULL(10)
>  #define ICE_PROT_NVGRE			BIT_ULL(11)
>  #define ICE_PROT_GTPU			BIT_ULL(12)
> @@ -27,6 +27,16 @@
>  #define ICE_PROT_L2TPV3OIP		BIT_ULL(16)
>  #define ICE_PROT_PFCP			BIT_ULL(17)
>  #define ICE_PROT_NAT_T_ESP		BIT_ULL(18)
> +#define ICE_PROT_L2TPV2OIP		BIT_ULL(19)
> +#define ICE_PROT_MAC_INNER		BIT_ULL(20)
> +#define ICE_PROT_VLAN_INNER		BIT_ULL(21)
> +#define ICE_PROT_IPV4_INNER		BIT_ULL(22)
> +#define ICE_PROT_IPV6_INNER		BIT_ULL(23)
> +#define ICE_PROT_TCP_INNER		BIT_ULL(24)
> +#define ICE_PROT_UDP_INNER		BIT_ULL(25)
> +#define ICE_PROT_SCTP_INNER		BIT_ULL(26)
> +#define ICE_PROT_ICMP4_INNER		BIT_ULL(27)
> +#define ICE_PROT_ICMP6_INNER		BIT_ULL(28)
>  

This patch has a lot of renaming going on and most of the changes are
renames unrelated (as far as I can see) to L2TP as described in the commit
log.

Please split this patch into two, with first patch doing all the renaming
of existing values. Then you can have a second patch that adds the new L2TP
parts.

/Bruce


^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH v6 0/8] Add support for L2TPV2 over UDP to ICE PMD
  2026-02-02  9:42 ` [PATCH 1/6] net/ice: add L2TPv2 and PPP data structures Shaiq Wani
@ 2026-02-18 16:37   ` Shaiq Wani
  2026-02-18 16:37     ` [PATCH v6 1/8] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
                       ` (7 more replies)
  2026-02-19 11:20   ` [PATCH v7 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
  1 sibling, 8 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-18 16:37 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh

This patchset adds L2TPv2 protocol support to the ICE PMD
enabling RSS and Flow Director capabilities for L2TPv2 over UDP traffic.


v6: split patch 3 into 2 seperate patches.
 
v5: Resending v4 patches with correct cover letter and threading.
 
v4: *Version 3 patchset was incomplete due to a server reboot.
    *V4 includes all patches for review.

v3: Fixed compilation issues.

v2: Addressed AI generated comments.


Shaiq Wani (8):
  net/ice: add L2TPv2 PPP and PPoE data structures
  net/ice: add L2TPv2 tunnel type definition
  net/ice: rename protocol identifiers
  net/ice: add L2TPv2 protocol support
  net/ice: add L2TPv2 flow patterns and FDIR support
  net/ice: add L2TPv2 hardware packet generation
  net/ice: add L2TPv2 RSS hash support
  doc: update release notes

 doc/guides/rel_notes/release_26_03.rst   |   4 +
 drivers/net/intel/ice/base/ice_fdir.c    |   6 +
 drivers/net/intel/ice/base/ice_fdir.h    |  17 +
 drivers/net/intel/ice/ice_ethdev.h       |   4 +
 drivers/net/intel/ice/ice_fdir_filter.c  | 451 ++++++++++++++++++++---
 drivers/net/intel/ice/ice_generic_flow.c | 177 +++++++++
 drivers/net/intel/ice/ice_generic_flow.h | 129 ++++---
 drivers/net/intel/ice/ice_hash.c         |  25 ++
 8 files changed, 717 insertions(+), 96 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH v6 1/8] net/ice: add L2TPv2 PPP and PPoE data structures
  2026-02-18 16:37   ` [PATCH v6 0/8] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
@ 2026-02-18 16:37     ` Shaiq Wani
  2026-02-18 16:37     ` [PATCH v6 2/8] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
                       ` (6 subsequent siblings)
  7 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-18 16:37 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add data structure definitions for L2TPv2 PPP and
PPoE protocols to support Flow Director (FDIR) filtering.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/base/ice_fdir.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/net/intel/ice/base/ice_fdir.h b/drivers/net/intel/ice/base/ice_fdir.h
index 3dd03f93f7..3d3b05da4a 100644
--- a/drivers/net/intel/ice/base/ice_fdir.h
+++ b/drivers/net/intel/ice/base/ice_fdir.h
@@ -230,6 +230,20 @@ struct ice_fdir_ecpri {
 	__be16 pc_id;
 };
 
+struct ice_fdir_pppoe {
+	u8 rsrvd_ver_type;
+	u8 rsrvd_code;
+	__be16 session_id;
+	__be16 length;
+	__be16 ppp_prot_id; /* control and data only */
+};
+
+struct ice_fdir_ppp {
+	u8 addr;
+	u8 ctrl;
+	__be16 proto_id;
+};
+
 struct ice_fdir_l2tpv2 {
 	__be16 flags_version;
 	__be16 length;
@@ -279,6 +293,9 @@ struct ice_fdir_fltr {
 	struct ice_fdir_ecpri ecpri_data;
 	struct ice_fdir_ecpri ecpri_mask;
 
+	struct ice_fdir_ppp ppp_data;
+	struct ice_fdir_ppp ppp_mask;
+
 	struct ice_fdir_l2tpv2 l2tpv2_data;
 	struct ice_fdir_l2tpv2 l2tpv2_mask;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v6 2/8] net/ice: add L2TPv2 tunnel type definition
  2026-02-18 16:37   ` [PATCH v6 0/8] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
  2026-02-18 16:37     ` [PATCH v6 1/8] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
@ 2026-02-18 16:37     ` Shaiq Wani
  2026-02-18 16:37     ` [PATCH v6 3/8] net/ice: rename protocol identifiers Shaiq Wani
                       ` (5 subsequent siblings)
  7 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-18 16:37 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add ICE_FDIR_TUNNEL_TYPE_L2TPV2 to the tunnel type enum and
extend ice_fdir_fltr_pattern structure to include L2TPv2 data and
mask fields.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_ethdev.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/intel/ice/ice_ethdev.h b/drivers/net/intel/ice/ice_ethdev.h
index 9562b2b8f1..4b3718f715 100644
--- a/drivers/net/intel/ice/ice_ethdev.h
+++ b/drivers/net/intel/ice/ice_ethdev.h
@@ -369,6 +369,7 @@ enum ice_fdir_tunnel_type {
 	ICE_FDIR_TUNNEL_TYPE_VXLAN,
 	ICE_FDIR_TUNNEL_TYPE_GTPU,
 	ICE_FDIR_TUNNEL_TYPE_GTPU_EH,
+	ICE_FDIR_TUNNEL_TYPE_L2TPV2,
 };
 
 struct rte_flow;
@@ -405,6 +406,9 @@ struct ice_fdir_fltr_pattern {
 	struct ice_fdir_udp_gtp gtpu_data;
 	struct ice_fdir_udp_gtp gtpu_mask;
 
+	struct ice_fdir_l2tpv2 l2tpv2_data;
+	struct ice_fdir_l2tpv2 l2tpv2_mask;
+
 	struct ice_fdir_extra ext_data;
 	struct ice_fdir_extra ext_mask;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v6 3/8] net/ice: rename protocol identifiers
  2026-02-18 16:37   ` [PATCH v6 0/8] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
  2026-02-18 16:37     ` [PATCH v6 1/8] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
  2026-02-18 16:37     ` [PATCH v6 2/8] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
@ 2026-02-18 16:37     ` Shaiq Wani
  2026-02-18 16:37     ` [PATCH v6 4/8] net/ice: add L2TPv2 protocol support Shaiq Wani
                       ` (4 subsequent siblings)
  7 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-18 16:37 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Rename existing protocol identifiers to use _OUTER suffix and add
corresponding _INNER variants to support tunneled packet parsing.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_generic_flow.h | 107 ++++++++++++++---------
 1 file changed, 66 insertions(+), 41 deletions(-)

diff --git a/drivers/net/intel/ice/ice_generic_flow.h b/drivers/net/intel/ice/ice_generic_flow.h
index 54bbb47398..0b282d4ee5 100644
--- a/drivers/net/intel/ice/ice_generic_flow.h
+++ b/drivers/net/intel/ice/ice_generic_flow.h
@@ -9,15 +9,15 @@
 
 /* protocol */
 
-#define ICE_PROT_MAC			BIT_ULL(1)
-#define ICE_PROT_VLAN			BIT_ULL(2)
-#define ICE_PROT_IPV4			BIT_ULL(3)
-#define ICE_PROT_IPV6			BIT_ULL(4)
-#define ICE_PROT_TCP			BIT_ULL(5)
-#define ICE_PROT_UDP			BIT_ULL(6)
-#define ICE_PROT_SCTP			BIT_ULL(7)
-#define ICE_PROT_ICMP4			BIT_ULL(8)
-#define ICE_PROT_ICMP6			BIT_ULL(9)
+#define ICE_PROT_MAC_OUTER		BIT_ULL(1)
+#define ICE_PROT_VLAN_OUTER		BIT_ULL(2)
+#define ICE_PROT_IPV4_OUTER		BIT_ULL(3)
+#define ICE_PROT_IPV6_OUTER		BIT_ULL(4)
+#define ICE_PROT_TCP_OUTER		BIT_ULL(5)
+#define ICE_PROT_UDP_OUTER		BIT_ULL(6)
+#define ICE_PROT_SCTP_OUTER		BIT_ULL(7)
+#define ICE_PROT_ICMP4_OUTER		BIT_ULL(8)
+#define ICE_PROT_ICMP6_OUTER		BIT_ULL(9)
 #define ICE_PROT_VXLAN			BIT_ULL(10)
 #define ICE_PROT_NVGRE			BIT_ULL(11)
 #define ICE_PROT_GTPU			BIT_ULL(12)
@@ -27,6 +27,15 @@
 #define ICE_PROT_L2TPV3OIP		BIT_ULL(16)
 #define ICE_PROT_PFCP			BIT_ULL(17)
 #define ICE_PROT_NAT_T_ESP		BIT_ULL(18)
+#define ICE_PROT_MAC_INNER		BIT_ULL(20)
+#define ICE_PROT_VLAN_INNER		BIT_ULL(21)
+#define ICE_PROT_IPV4_INNER		BIT_ULL(22)
+#define ICE_PROT_IPV6_INNER		BIT_ULL(23)
+#define ICE_PROT_TCP_INNER		BIT_ULL(24)
+#define ICE_PROT_UDP_INNER		BIT_ULL(25)
+#define ICE_PROT_SCTP_INNER		BIT_ULL(26)
+#define ICE_PROT_ICMP4_INNER		BIT_ULL(27)
+#define ICE_PROT_ICMP6_INNER		BIT_ULL(28)
 
 /* field */
 
@@ -53,7 +62,7 @@
 #define ICE_L2TPV3OIP_SESSION_ID	BIT_ULL(43)
 #define ICE_PFCP_SEID			BIT_ULL(42)
 #define ICE_PFCP_S_FIELD		BIT_ULL(41)
-#define ICE_IP_PK_ID		    BIT_ULL(40)
+#define ICE_IP_PK_ID			BIT_ULL(40)
 #define ICE_IP_FRAG_OFS			BIT_ULL(39)
 
 /* input set */
@@ -62,39 +71,39 @@
 
 #define ICE_INSET_SMAC			(ICE_SMAC)
 #define ICE_INSET_DMAC			(ICE_DMAC)
-#define ICE_INSET_VLAN			(ICE_PROT_VLAN)
-#define ICE_INSET_VLAN_INNER		(ICE_PROT_VLAN)
-#define ICE_INSET_VLAN_OUTER		(ICE_PROT_VLAN)
+#define ICE_INSET_VLAN			(ICE_PROT_VLAN_OUTER)
+#define ICE_INSET_VLAN_INNER		(ICE_PROT_VLAN_INNER)
+#define ICE_INSET_VLAN_OUTER		(ICE_PROT_VLAN_OUTER)
 #define ICE_INSET_ETHERTYPE		(ICE_ETHERTYPE)
 
-#define ICE_INSET_IPV4_SRC		(ICE_PROT_IPV4 | ICE_IP_SRC)
-#define ICE_INSET_IPV4_DST		(ICE_PROT_IPV4 | ICE_IP_DST)
-#define ICE_INSET_IPV4_TOS		(ICE_PROT_IPV4 | ICE_IP_TOS)
-#define ICE_INSET_IPV4_PROTO		(ICE_PROT_IPV4 | ICE_IP_PROTO)
-#define ICE_INSET_IPV4_TTL		(ICE_PROT_IPV4 | ICE_IP_TTL)
-#define ICE_INSET_IPV4_PKID		(ICE_PROT_IPV4 | ICE_IP_PK_ID)
-#define ICE_INSET_IPV4_FRAG_OFS	(ICE_PROT_IPV4 | ICE_IP_FRAG_OFS)
-#define ICE_INSET_IPV6_SRC		(ICE_PROT_IPV6 | ICE_IP_SRC)
-#define ICE_INSET_IPV6_DST		(ICE_PROT_IPV6 | ICE_IP_DST)
-#define ICE_INSET_IPV6_NEXT_HDR		(ICE_PROT_IPV6 | ICE_IP_PROTO)
-#define ICE_INSET_IPV6_HOP_LIMIT	(ICE_PROT_IPV6 | ICE_IP_TTL)
-#define ICE_INSET_IPV6_TC		(ICE_PROT_IPV6 | ICE_IP_TOS)
-#define ICE_INSET_IPV6_PKID		(ICE_PROT_IPV6 | ICE_IP_PK_ID)
-
-#define ICE_INSET_TCP_SRC_PORT		(ICE_PROT_TCP | ICE_SPORT)
-#define ICE_INSET_TCP_DST_PORT		(ICE_PROT_TCP | ICE_DPORT)
-#define ICE_INSET_UDP_SRC_PORT		(ICE_PROT_UDP | ICE_SPORT)
-#define ICE_INSET_UDP_DST_PORT		(ICE_PROT_UDP | ICE_DPORT)
-#define ICE_INSET_SCTP_SRC_PORT		(ICE_PROT_SCTP | ICE_SPORT)
-#define ICE_INSET_SCTP_DST_PORT		(ICE_PROT_SCTP | ICE_DPORT)
-#define ICE_INSET_ICMP4_SRC_PORT	(ICE_PROT_ICMP4 | ICE_SPORT)
-#define ICE_INSET_ICMP4_DST_PORT	(ICE_PROT_ICMP4 | ICE_DPORT)
-#define ICE_INSET_ICMP6_SRC_PORT	(ICE_PROT_ICMP6 | ICE_SPORT)
-#define ICE_INSET_ICMP6_DST_PORT	(ICE_PROT_ICMP6 | ICE_DPORT)
-#define ICE_INSET_ICMP4_TYPE		(ICE_PROT_ICMP4 | ICE_ICMP_TYPE)
-#define ICE_INSET_ICMP4_CODE		(ICE_PROT_ICMP4 | ICE_ICMP_CODE)
-#define ICE_INSET_ICMP6_TYPE		(ICE_PROT_ICMP6 | ICE_ICMP_TYPE)
-#define ICE_INSET_ICMP6_CODE		(ICE_PROT_ICMP6 | ICE_ICMP_CODE)
+#define ICE_INSET_IPV4_SRC		(ICE_PROT_IPV4_OUTER | ICE_IP_SRC)
+#define ICE_INSET_IPV4_DST		(ICE_PROT_IPV4_OUTER | ICE_IP_DST)
+#define ICE_INSET_IPV4_TOS		(ICE_PROT_IPV4_OUTER | ICE_IP_TOS)
+#define ICE_INSET_IPV4_PROTO		(ICE_PROT_IPV4_OUTER | ICE_IP_PROTO)
+#define ICE_INSET_IPV4_TTL		(ICE_PROT_IPV4_OUTER | ICE_IP_TTL)
+#define ICE_INSET_IPV4_PKID		(ICE_PROT_IPV4_OUTER | ICE_IP_PK_ID)
+#define ICE_INSET_IPV4_FRAG_OFS	(ICE_PROT_IPV4_OUTER | ICE_IP_FRAG_OFS)
+#define ICE_INSET_IPV6_SRC		(ICE_PROT_IPV6_OUTER | ICE_IP_SRC)
+#define ICE_INSET_IPV6_DST		(ICE_PROT_IPV6_OUTER | ICE_IP_DST)
+#define ICE_INSET_IPV6_NEXT_HDR		(ICE_PROT_IPV6_OUTER | ICE_IP_PROTO)
+#define ICE_INSET_IPV6_HOP_LIMIT	(ICE_PROT_IPV6_OUTER | ICE_IP_TTL)
+#define ICE_INSET_IPV6_TC		(ICE_PROT_IPV6_OUTER | ICE_IP_TOS)
+#define ICE_INSET_IPV6_PKID		(ICE_PROT_IPV6_OUTER | ICE_IP_PK_ID)
+
+#define ICE_INSET_TCP_SRC_PORT		(ICE_PROT_TCP_OUTER | ICE_SPORT)
+#define ICE_INSET_TCP_DST_PORT		(ICE_PROT_TCP_OUTER | ICE_DPORT)
+#define ICE_INSET_UDP_SRC_PORT		(ICE_PROT_UDP_OUTER | ICE_SPORT)
+#define ICE_INSET_UDP_DST_PORT		(ICE_PROT_UDP_OUTER | ICE_DPORT)
+#define ICE_INSET_SCTP_SRC_PORT		(ICE_PROT_SCTP_OUTER | ICE_SPORT)
+#define ICE_INSET_SCTP_DST_PORT		(ICE_PROT_SCTP_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP4_SRC_PORT	(ICE_PROT_ICMP4_OUTER | ICE_SPORT)
+#define ICE_INSET_ICMP4_DST_PORT	(ICE_PROT_ICMP4_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP6_SRC_PORT	(ICE_PROT_ICMP6_OUTER | ICE_SPORT)
+#define ICE_INSET_ICMP6_DST_PORT	(ICE_PROT_ICMP6_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP4_TYPE		(ICE_PROT_ICMP4_OUTER | ICE_ICMP_TYPE)
+#define ICE_INSET_ICMP4_CODE		(ICE_PROT_ICMP4_OUTER | ICE_ICMP_CODE)
+#define ICE_INSET_ICMP6_TYPE		(ICE_PROT_ICMP6_OUTER | ICE_ICMP_TYPE)
+#define ICE_INSET_ICMP6_CODE		(ICE_PROT_ICMP6_OUTER | ICE_ICMP_CODE)
 
 /* tunnel */
 
@@ -122,6 +131,22 @@
 	(ICE_PROT_PFCP | ICE_PFCP_S_FIELD | ICE_PFCP_SEID)
 #define ICE_INSET_NAT_T_ESP_SPI \
 	(ICE_PROT_NAT_T_ESP | ICE_ESP_SPI)
+#define ICE_INSET_TUN_IPV4_SRC \
+	(ICE_PROT_IPV4_INNER | ICE_IP_SRC)
+#define ICE_INSET_TUN_IPV4_DST \
+	(ICE_PROT_IPV4_INNER | ICE_IP_DST)
+#define ICE_INSET_TUN_UDP_SRC_PORT \
+	(ICE_PROT_UDP_INNER | ICE_SPORT)
+#define ICE_INSET_TUN_UDP_DST_PORT \
+	(ICE_PROT_UDP_INNER | ICE_DPORT)
+#define ICE_INSET_TUN_TCP_SRC_PORT \
+	(ICE_PROT_TCP_INNER | ICE_SPORT)
+#define ICE_INSET_TUN_TCP_DST_PORT \
+	(ICE_PROT_TCP_INNER | ICE_DPORT)
+#define ICE_INSET_TUN_IPV6_SRC \
+	(ICE_PROT_IPV6_INNER | ICE_IP_SRC)
+#define ICE_INSET_TUN_IPV6_DST \
+	(ICE_PROT_IPV6_INNER | ICE_IP_DST)
 
 /* empty pattern */
 extern enum rte_flow_item_type pattern_empty[];
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v6 4/8] net/ice: add L2TPv2 protocol support
  2026-02-18 16:37   ` [PATCH v6 0/8] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                       ` (2 preceding siblings ...)
  2026-02-18 16:37     ` [PATCH v6 3/8] net/ice: rename protocol identifiers Shaiq Wani
@ 2026-02-18 16:37     ` Shaiq Wani
  2026-02-18 16:37     ` [PATCH v6 5/8] net/ice: add L2TPv2 flow patterns and FDIR support Shaiq Wani
                       ` (3 subsequent siblings)
  7 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-18 16:37 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add L2TPv2 protocol identifier and session ID field definition
to enable flow classification and filtering for L2TPv2 tunneled
traffic.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_generic_flow.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/net/intel/ice/ice_generic_flow.h b/drivers/net/intel/ice/ice_generic_flow.h
index 0b282d4ee5..1b5514d5df 100644
--- a/drivers/net/intel/ice/ice_generic_flow.h
+++ b/drivers/net/intel/ice/ice_generic_flow.h
@@ -27,6 +27,7 @@
 #define ICE_PROT_L2TPV3OIP		BIT_ULL(16)
 #define ICE_PROT_PFCP			BIT_ULL(17)
 #define ICE_PROT_NAT_T_ESP		BIT_ULL(18)
+#define ICE_PROT_L2TPV2OIP		BIT_ULL(19)
 #define ICE_PROT_MAC_INNER		BIT_ULL(20)
 #define ICE_PROT_VLAN_INNER		BIT_ULL(21)
 #define ICE_PROT_IPV4_INNER		BIT_ULL(22)
@@ -64,6 +65,7 @@
 #define ICE_PFCP_S_FIELD		BIT_ULL(41)
 #define ICE_IP_PK_ID			BIT_ULL(40)
 #define ICE_IP_FRAG_OFS			BIT_ULL(39)
+#define ICE_L2TPV2OIP_SESSION_ID	BIT_ULL(38)
 
 /* input set */
 
@@ -131,6 +133,8 @@
 	(ICE_PROT_PFCP | ICE_PFCP_S_FIELD | ICE_PFCP_SEID)
 #define ICE_INSET_NAT_T_ESP_SPI \
 	(ICE_PROT_NAT_T_ESP | ICE_ESP_SPI)
+#define ICE_INSET_L2TPV2OIP_SESSION_ID \
+	(ICE_PROT_L2TPV2OIP | ICE_L2TPV2OIP_SESSION_ID)
 #define ICE_INSET_TUN_IPV4_SRC \
 	(ICE_PROT_IPV4_INNER | ICE_IP_SRC)
 #define ICE_INSET_TUN_IPV4_DST \
@@ -425,6 +429,24 @@ extern enum rte_flow_item_type pattern_eth_ipv6_udp_ah[];
 /* L2TP */
 extern enum rte_flow_item_type pattern_eth_ipv4_l2tp[];
 extern enum rte_flow_item_type pattern_eth_ipv6_l2tp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv6_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp[];
 
 /* PFCP */
 extern enum rte_flow_item_type pattern_eth_ipv4_pfcp[];
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v6 5/8] net/ice: add L2TPv2 flow patterns and FDIR support
  2026-02-18 16:37   ` [PATCH v6 0/8] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                       ` (3 preceding siblings ...)
  2026-02-18 16:37     ` [PATCH v6 4/8] net/ice: add L2TPv2 protocol support Shaiq Wani
@ 2026-02-18 16:37     ` Shaiq Wani
  2026-02-18 16:37     ` [PATCH v6 6/8] net/ice: add L2TPv2 hardware packet generation Shaiq Wani
                       ` (2 subsequent siblings)
  7 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-18 16:37 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Implement comprehensive L2TPv2 support for Flow Director
-Flow pattern definitions for different L2TPv2 packet combinations
-FDIR filter parsing logic
-Flow type assignment for proper packet classification.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_fdir_filter.c  | 451 ++++++++++++++++++++---
 drivers/net/intel/ice/ice_generic_flow.c | 177 +++++++++
 2 files changed, 573 insertions(+), 55 deletions(-)

diff --git a/drivers/net/intel/ice/ice_fdir_filter.c b/drivers/net/intel/ice/ice_fdir_filter.c
index da22b65a77..1279823b12 100644
--- a/drivers/net/intel/ice/ice_fdir_filter.c
+++ b/drivers/net/intel/ice/ice_fdir_filter.c
@@ -107,6 +107,31 @@
 	ICE_INSET_IPV6_SRC | ICE_INSET_IPV6_DST | \
 	ICE_INSET_NAT_T_ESP_SPI)
 
+#define ICE_FDIR_INSET_L2TPV2 (\
+	ICE_INSET_SMAC | ICE_INSET_DMAC | ICE_INSET_L2TPV2OIP_SESSION_ID)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4 (\
+	ICE_INSET_TUN_IPV4_SRC | ICE_INSET_TUN_IPV4_DST)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV4 | ICE_INSET_TUN_UDP_SRC_PORT | \
+	ICE_INSET_TUN_UDP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV4 | ICE_INSET_TUN_TCP_SRC_PORT | \
+	ICE_INSET_TUN_TCP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6 (\
+	ICE_INSET_TUN_IPV6_SRC | ICE_INSET_TUN_IPV6_DST)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV6 | ICE_INSET_TUN_UDP_SRC_PORT | \
+	ICE_INSET_TUN_UDP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV6 | ICE_INSET_TUN_TCP_SRC_PORT | \
+	ICE_INSET_TUN_TCP_DST_PORT)
+
 static struct ice_pattern_match_item ice_fdir_supported_pattern[] = {
 	{pattern_raw,					ICE_INSET_NONE,			ICE_INSET_NONE,			ICE_INSET_NONE},
 	{pattern_ethertype,				ICE_FDIR_INSET_ETH,		ICE_INSET_NONE,			ICE_INSET_NONE},
@@ -132,10 +157,26 @@ static struct ice_pattern_match_item ice_fdir_supported_pattern[] = {
 	{pattern_eth_ipv4_udp_vxlan_eth_ipv4_tcp,	ICE_FDIR_INSET_ETH_IPV4_VXLAN,	ICE_FDIR_INSET_ETH_IPV4_TCP,	ICE_INSET_NONE},
 	{pattern_eth_ipv4_udp_vxlan_eth_ipv4_sctp,	ICE_FDIR_INSET_ETH_IPV4_VXLAN,	ICE_FDIR_INSET_ETH_IPV4_SCTP,	ICE_INSET_NONE},
 	/* duplicated GTPU input set in 3rd column to align with shared code behavior. Ideally, only put GTPU field in 2nd column. */
-	{pattern_eth_ipv4_gtpu,				ICE_FDIR_INSET_IPV4_GTPU,	ICE_FDIR_INSET_IPV4_GTPU,	ICE_INSET_NONE},
-	{pattern_eth_ipv4_gtpu_eh,			ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_INSET_NONE},
-	{pattern_eth_ipv6_gtpu,				ICE_FDIR_INSET_IPV6_GTPU,	ICE_FDIR_INSET_IPV6_GTPU,	ICE_INSET_NONE},
-	{pattern_eth_ipv6_gtpu_eh,			ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_gtpu,				ICE_FDIR_INSET_IPV4_GTPU,	ICE_FDIR_INSET_IPV4_GTPU,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_gtpu_eh,			ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_FDIR_INSET_IPV4_GTPU_EH,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_gtpu,				ICE_FDIR_INSET_IPV6_GTPU,	ICE_FDIR_INSET_IPV6_GTPU,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_gtpu_eh,			ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_FDIR_INSET_IPV6_GTPU_EH,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2,			ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp,		ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2,			ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp,		ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP,	ICE_INSET_NONE},
 };
 
 static int
@@ -957,6 +998,7 @@ ice_fdir_input_set_parse(uint64_t inset, enum ice_flow_field *field)
 		{ICE_INSET_VXLAN_VNI, ICE_FLOW_FIELD_IDX_VXLAN_VNI},
 		{ICE_INSET_ESP_SPI, ICE_FLOW_FIELD_IDX_ESP_SPI},
 		{ICE_INSET_NAT_T_ESP_SPI, ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI},
+		{ICE_INSET_L2TPV2OIP_SESSION_ID, ICE_FLOW_FIELD_IDX_L2TPV2_SESS_ID},
 	};
 
 	for (i = 0, j = 0; i < RTE_DIM(ice_inset_map); i++) {
@@ -1068,6 +1110,43 @@ ice_fdir_input_set_hdrs(enum ice_fltr_ptype flow, struct ice_flow_seg_info *seg)
 				  ICE_FLOW_SEG_HDR_IPV6 |
 				  ICE_FLOW_SEG_HDR_IPV_OTHER);
 		break;
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_IPV6 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_UDP:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_PPP |
+				  ICE_FLOW_SEG_HDR_IPV6 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_IPV4 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_UDP:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_PPP |
+				  ICE_FLOW_SEG_HDR_IPV4 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+
 	default:
 		PMD_DRV_LOG(ERR, "not supported filter type.");
 		break;
@@ -1170,7 +1249,10 @@ ice_fdir_uninit(struct ice_adapter *ad)
 static int
 ice_fdir_is_tunnel_profile(enum ice_fdir_tunnel_type tunnel_type)
 {
-	if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN)
+	if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_GTPU ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_GTPU_EH)
 		return 1;
 	else
 		return 0;
@@ -1239,6 +1321,9 @@ ice_fdir_extract_fltr_key(struct ice_fdir_fltr_pattern *key,
 	rte_memcpy(&key->gtpu_data, &input->gtpu_data, sizeof(key->gtpu_data));
 	rte_memcpy(&key->gtpu_mask, &input->gtpu_mask, sizeof(key->gtpu_mask));
 
+	rte_memcpy(&key->l2tpv2_data, &input->l2tpv2_data, sizeof(key->l2tpv2_data));
+	rte_memcpy(&key->l2tpv2_mask, &input->l2tpv2_mask, sizeof(key->l2tpv2_mask));
+
 	key->tunnel_type = filter->tunnel_type;
 }
 
@@ -1797,16 +1882,22 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 	const struct rte_flow_item_gtp *gtp_spec, *gtp_mask;
 	const struct rte_flow_item_gtp_psc *gtp_psc_spec, *gtp_psc_mask;
 	const struct rte_flow_item_esp *esp_spec, *esp_mask;
+	const struct rte_flow_item_l2tpv2 *l2tpv2_spec, *l2tpv2_mask;
+	const struct rte_flow_item_ppp *ppp_spec, *ppp_mask;
 	uint64_t input_set_i = ICE_INSET_NONE; /* only for tunnel inner */
 	uint64_t input_set_o = ICE_INSET_NONE; /* non-tunnel and tunnel outer */
 	uint64_t *input_set;
 	uint8_t flow_type = ICE_FLTR_PTYPE_NONF_NONE;
+	enum rte_flow_item_type inner_l3 = RTE_FLOW_ITEM_TYPE_END;
+	enum rte_flow_item_type inner_l4 = RTE_FLOW_ITEM_TYPE_END;
+	enum rte_flow_item_type current_l3 = RTE_FLOW_ITEM_TYPE_END;
+	bool ppp_present = false;
 	uint8_t  ipv6_addr_mask[16] = {
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
 	};
 	uint32_t vtc_flow_cpu;
-	uint16_t ether_type;
+	uint16_t ether_type = 0, flags_version = 0;
 	enum rte_flow_item_type next_type;
 	bool is_outer = true;
 	struct ice_fdir_extra *p_ext_data;
@@ -2001,22 +2092,30 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				   &eth_spec->hdr.ether_type, sizeof(eth_spec->hdr.ether_type));
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV4:
-			flow_type = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
-			l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			/* Only set flow_type for outer IPv4, track inner L3 for tunnels */
+			if (is_outer || !tunnel_type) {
+				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
+				l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			} else {
+				inner_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			}
+
 			ipv4_spec = item->spec;
 			ipv4_last = item->last;
 			ipv4_mask = item->mask;
 			p_v4 = (tunnel_type && is_outer) ?
-			       &filter->input.ip_outer.v4 :
-			       &filter->input.ip.v4;
+					&filter->input.ip_outer.v4 :
+					&filter->input.ip.v4;
 
 			if (!(ipv4_spec && ipv4_mask))
 				break;
 
 			/* Check IPv4 mask and update input set */
 			if (ipv4_mask->hdr.version_ihl ||
-			    ipv4_mask->hdr.total_length ||
-			    ipv4_mask->hdr.hdr_checksum) {
+				ipv4_mask->hdr.total_length ||
+				ipv4_mask->hdr.hdr_checksum) {
 				rte_flow_error_set(error, EINVAL,
 						   RTE_FLOW_ERROR_TYPE_ITEM,
 						   item,
@@ -2048,10 +2147,20 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				ipv4_mask->hdr.dst_addr != UINT32_MAX)
 				return -rte_errno;
 
-			if (ipv4_mask->hdr.dst_addr == UINT32_MAX)
-				*input_set |= ICE_INSET_IPV4_DST;
-			if (ipv4_mask->hdr.src_addr == UINT32_MAX)
-				*input_set |= ICE_INSET_IPV4_SRC;
+			if (ipv4_mask->hdr.dst_addr == UINT32_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV4_DST;
+				else
+					*input_set |= ICE_INSET_IPV4_DST;
+			}
+			if (ipv4_mask->hdr.src_addr == UINT32_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV4_SRC;
+				else
+					*input_set |= ICE_INSET_IPV4_SRC;
+			}
 			if (ipv4_mask->hdr.time_to_live == UINT8_MAX)
 				*input_set |= ICE_INSET_IPV4_TTL;
 			if (ipv4_mask->hdr.next_proto_id == UINT8_MAX)
@@ -2092,8 +2201,15 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV6:
-			flow_type = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
-			l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			if (is_outer || !tunnel_type) {
+				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
+				l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			} else {
+				inner_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			}
+
 			ipv6_spec = item->spec;
 			ipv6_mask = item->mask;
 			p_v6 = (tunnel_type && is_outer) ?
@@ -2113,15 +2229,24 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 			}
 
 			if (!memcmp(&ipv6_mask->hdr.src_addr, ipv6_addr_mask,
-				    sizeof(ipv6_mask->hdr.src_addr)))
-				*input_set |= ICE_INSET_IPV6_SRC;
+				    sizeof(ipv6_mask->hdr.src_addr))) {
+				if (tunnel_type && !is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV6_SRC;
+				else
+					*input_set |= ICE_INSET_IPV6_SRC;
+			}
 			if (!memcmp(&ipv6_mask->hdr.dst_addr, ipv6_addr_mask,
-				    sizeof(ipv6_mask->hdr.dst_addr)))
-				*input_set |= ICE_INSET_IPV6_DST;
-
+				    sizeof(ipv6_mask->hdr.dst_addr))) {
+				if (tunnel_type && !is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV6_DST;
+				else
+					*input_set |= ICE_INSET_IPV6_DST;
+			}
 			if ((ipv6_mask->hdr.vtc_flow &
-			     rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
-			    == rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
+			     rte_cpu_to_be_32(ICE_IPV6_TC_MASK)) ==
+			    rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
 				*input_set |= ICE_INSET_IPV6_TC;
 			if (ipv6_mask->hdr.proto == UINT8_MAX)
 				*input_set |= ICE_INSET_IPV6_NEXT_HDR;
@@ -2167,10 +2292,16 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 			break;
 
 		case RTE_FLOW_ITEM_TYPE_TCP:
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
+			if (!is_outer && tunnel_type) {
+				/* For inner TCP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_TCP;
+			} else {
+				/* For outer TCP, update flow_type normally */
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
+			}
 
 			tcp_spec = item->spec;
 			tcp_mask = item->mask;
@@ -2201,28 +2332,44 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				tcp_mask->hdr.dst_port != UINT16_MAX)
 				return -rte_errno;
 
-			if (tcp_mask->hdr.src_port == UINT16_MAX)
-				*input_set |= ICE_INSET_TCP_SRC_PORT;
-			if (tcp_mask->hdr.dst_port == UINT16_MAX)
-				*input_set |= ICE_INSET_TCP_DST_PORT;
+			if (tcp_mask->hdr.src_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_TCP_SRC_PORT;
+				else
+					*input_set |= ICE_INSET_TCP_SRC_PORT;
+			}
+			if (tcp_mask->hdr.dst_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_TCP_DST_PORT;
+				else
+					*input_set |= ICE_INSET_TCP_DST_PORT;
+			}
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = tcp_spec->hdr.dst_port;
 				p_v4->src_port = tcp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->dst_port = tcp_spec->hdr.dst_port;
 				p_v6->src_port = tcp_spec->hdr.src_port;
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_UDP:
-			l4 = RTE_FLOW_ITEM_TYPE_UDP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
+			if (!is_outer && tunnel_type) {
+				/* For inner UDP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_UDP;
+			} else {
+				/* For outer UDP, update flow_type normally */
+				l4 = RTE_FLOW_ITEM_TYPE_UDP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
+			}
 
 			udp_spec = item->spec;
 			udp_mask = item->mask;
@@ -2248,27 +2395,43 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				udp_mask->hdr.dst_port != UINT16_MAX)
 				return -rte_errno;
 
-			if (udp_mask->hdr.src_port == UINT16_MAX)
-				*input_set |= ICE_INSET_UDP_SRC_PORT;
-			if (udp_mask->hdr.dst_port == UINT16_MAX)
-				*input_set |= ICE_INSET_UDP_DST_PORT;
+			if (udp_mask->hdr.src_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_UDP_SRC_PORT;
+				else
+					*input_set |= ICE_INSET_UDP_SRC_PORT;
+			}
+			if (udp_mask->hdr.dst_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_UDP_DST_PORT;
+				else
+					*input_set |= ICE_INSET_UDP_DST_PORT;
+			}
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = udp_spec->hdr.dst_port;
 				p_v4->src_port = udp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->src_port = udp_spec->hdr.src_port;
 				p_v6->dst_port = udp_spec->hdr.dst_port;
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_SCTP:
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
+			if (!is_outer && tunnel_type) {
+				/* For inner SCTP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_SCTP;
+			} else {
+				/* For outer SCTP, update flow_type normally */
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
+			}
 
 			sctp_spec = item->spec;
 			sctp_mask = item->mask;
@@ -2299,11 +2462,11 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				*input_set |= ICE_INSET_SCTP_DST_PORT;
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = sctp_spec->hdr.dst_port;
 				p_v4->src_port = sctp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->dst_port = sctp_spec->hdr.dst_port;
 				p_v6->src_port = sctp_spec->hdr.src_port;
@@ -2406,6 +2569,115 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				filter->input.ip.v6.sec_parm_idx =
 					esp_spec->hdr.spi;
 			break;
+		case RTE_FLOW_ITEM_TYPE_L2TPV2: {
+			struct ice_fdir_l2tpv2 l2tpv2_be;
+
+			l2tpv2_spec = item->spec;
+			l2tpv2_mask = item->mask;
+
+			if (!(l2tpv2_spec && l2tpv2_mask))
+				break;
+
+			flags_version =
+				rte_be_to_cpu_16(l2tpv2_spec->hdr.common.flags_version);
+			if ((flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+			     l2tpv2_mask->hdr.type3.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA &&
+			     l2tpv2_mask->hdr.type7.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L &&
+			     l2tpv2_mask->hdr.type6.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S &&
+			     l2tpv2_mask->hdr.type5.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_O &&
+			     l2tpv2_mask->hdr.type4.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S &&
+			     l2tpv2_mask->hdr.type3.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_O &&
+			     l2tpv2_mask->hdr.type2.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S_O &&
+			     l2tpv2_mask->hdr.type1.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S_O &&
+			     l2tpv2_mask->hdr.type0.session_id == UINT16_MAX)) {
+				input_set_o |= ICE_INSET_L2TPV2OIP_SESSION_ID;
+			}
+
+			tunnel_type = ICE_FDIR_TUNNEL_TYPE_L2TPV2;
+			memset(&l2tpv2_be, 0, sizeof(l2tpv2_be));
+
+			if (flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type7.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type7.session_id);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.session_id);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_O) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.session_id);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_O) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.session_id);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S_O) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.nr);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S_O) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.nr);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.offset_size);
+			}
+
+			/* Copy converted values to filter */
+			filter->input.l2tpv2_data.flags_version = rte_cpu_to_be_16(flags_version);
+			filter->input.l2tpv2_data.length = l2tpv2_be.length;
+			filter->input.l2tpv2_data.tunnel_id = l2tpv2_be.tunnel_id;
+			filter->input.l2tpv2_data.session_id = l2tpv2_be.session_id;
+			filter->input.l2tpv2_data.ns = l2tpv2_be.ns;
+			filter->input.l2tpv2_data.nr = l2tpv2_be.nr;
+			filter->input.l2tpv2_data.offset_size = l2tpv2_be.offset_size;
+			break;
+		}
+		case RTE_FLOW_ITEM_TYPE_PPP:
+			ppp_spec = item->spec;
+			ppp_mask = item->mask;
+
+			/* PPP marks transition from outer to inner in L2TPv2 tunnels */
+			if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2) {
+				is_outer = false;
+				ppp_present = true;
+			}
+
+			if (ppp_spec && ppp_mask) {
+				filter->input.ppp_data.addr = ppp_spec->hdr.addr;
+				filter->input.ppp_data.ctrl = ppp_spec->hdr.ctrl;
+				filter->input.ppp_data.proto_id = ppp_spec->hdr.proto_id;
+			}
+			break;
 		default:
 			rte_flow_error_set(error, EINVAL,
 					   RTE_FLOW_ERROR_TYPE_ITEM,
@@ -2439,6 +2711,74 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN &&
 		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
 		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP_VXLAN_IPV4_OTHER;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP &&
+		flags_version != RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP &&
+		flags_version != RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP &&
+		flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP &&
+		flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL;
+	/* Handle L2TPV2 with PPP and inner protocols */
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		ppp_present &&
+		inner_l3 != RTE_FLOW_ITEM_TYPE_END) {
+		/* L2TPV2 with inner IPv4/IPv6 */
+		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP) {
+			/* Outer IPv4 + inner protocol */
+			if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4;
+			} else if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6;
+			}
+		} else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP) {
+			/* Outer IPv6 + inner protocol */
+			if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4;
+			} else if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6;
+			}
+		}
+	} else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 && ppp_present &&
+		inner_l3 == RTE_FLOW_ITEM_TYPE_END) {
+		/* Handle L2TPV2 with PPP but no inner protocol specified */
+		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP)
+			flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP;
+		else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP)
+			flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP;
+	}
 
 	filter->tunnel_type = tunnel_type;
 	filter->input.flow_type = flow_type;
@@ -2482,9 +2822,10 @@ ice_fdir_parse(struct ice_adapter *ad,
 	input_set = filter->input_set_o | filter->input_set_i;
 	input_set = raw ? ~input_set : input_set;
 
-	if (!input_set || filter->input_set_o &
-	    ~(item->input_set_mask_o | ICE_INSET_ETHERTYPE) ||
-	    filter->input_set_i & ~item->input_set_mask_i) {
+	if (!input_set ||
+	    (filter->input_set_o &
+	     ~(item->input_set_mask_o | ICE_INSET_ETHERTYPE)) ||
+	    (filter->input_set_i & ~item->input_set_mask_i)) {
 		rte_flow_error_set(error, EINVAL,
 				   RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
 				   pattern,
diff --git a/drivers/net/intel/ice/ice_generic_flow.c b/drivers/net/intel/ice/ice_generic_flow.c
index 4049157eab..644958cccf 100644
--- a/drivers/net/intel/ice/ice_generic_flow.c
+++ b/drivers/net/intel/ice/ice_generic_flow.c
@@ -1794,6 +1794,166 @@ enum rte_flow_item_type pattern_eth_ipv6_pfcp[] = {
 	RTE_FLOW_ITEM_TYPE_PFCP,
 	RTE_FLOW_ITEM_TYPE_END,
 };
+enum rte_flow_item_type pattern_eth_ipv4_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+/* PPPoL2TPv2oUDP */
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 
 typedef bool (*parse_engine_t)(struct ice_adapter *ad,
 			       struct rte_flow *flow,
@@ -2021,6 +2181,23 @@ static struct ice_ptype_match ice_ptype_map[] = {
 	{pattern_eth_ipv4_udp_esp,			ICE_MAC_IPV4_NAT_T_ESP},
 	{pattern_eth_ipv4_ah,				ICE_MAC_IPV4_AH},
 	{pattern_eth_ipv4_l2tp,				ICE_MAC_IPV4_L2TPV3},
+	{pattern_eth_ipv4_udp_l2tpv2,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp,	ICE_MAC_IPV6_L2TPV2},
+
 	{pattern_eth_ipv4_pfcp,				ICE_MAC_IPV4_PFCP_SESSION},
 	{pattern_eth_ipv6,				ICE_PTYPE_IPV6_PAY},
 	{pattern_eth_ipv6_udp,				ICE_PTYPE_IPV6_UDP_PAY},
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v6 6/8] net/ice: add L2TPv2 hardware packet generation
  2026-02-18 16:37   ` [PATCH v6 0/8] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                       ` (4 preceding siblings ...)
  2026-02-18 16:37     ` [PATCH v6 5/8] net/ice: add L2TPv2 flow patterns and FDIR support Shaiq Wani
@ 2026-02-18 16:37     ` Shaiq Wani
  2026-02-18 16:37     ` [PATCH v6 7/8] net/ice: add L2TPv2 RSS hash support Shaiq Wani
  2026-02-18 16:37     ` [PATCH v6 8/8] doc: update release notes Shaiq Wani
  7 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-18 16:37 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add L2TPv2 packet type cases to ice_fdir_get_gen_prgm_pkt() to enable
hardware packet generation for FDIR rule programming.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/base/ice_fdir.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/intel/ice/base/ice_fdir.c b/drivers/net/intel/ice/base/ice_fdir.c
index f62313c559..2c0cb99854 100644
--- a/drivers/net/intel/ice/base/ice_fdir.c
+++ b/drivers/net/intel/ice/base/ice_fdir.c
@@ -4027,6 +4027,9 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
 				   ICE_NONDMA_TO_NONDMA);
 			loc = &pkt[ICE_FDIR_V6_V4_GTPOGRE_EH_PKT_OFF];
 			break;
+		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL:
+		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2:
+		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP:
 		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4:
 		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP:
 		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP:
@@ -4038,6 +4041,9 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
 						      idx, offset, tun);
 			loc = &pkt[pos];
 			break;
+		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL:
+		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2:
+		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP:
 		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4:
 		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP:
 		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP:
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v6 7/8] net/ice: add L2TPv2 RSS hash support
  2026-02-18 16:37   ` [PATCH v6 0/8] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                       ` (5 preceding siblings ...)
  2026-02-18 16:37     ` [PATCH v6 6/8] net/ice: add L2TPv2 hardware packet generation Shaiq Wani
@ 2026-02-18 16:37     ` Shaiq Wani
  2026-02-18 16:37     ` [PATCH v6 8/8] doc: update release notes Shaiq Wani
  7 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-18 16:37 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add RSS (Receive Side Scaling) hash support for L2TPv2 packets.
define hash templates and patterns for distributing L2TPv2 traffic
across multiple receive queues based on session IDs and inner headers.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_hash.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/net/intel/ice/ice_hash.c b/drivers/net/intel/ice/ice_hash.c
index afdc8f220a..b20103a452 100644
--- a/drivers/net/intel/ice/ice_hash.c
+++ b/drivers/net/intel/ice/ice_hash.c
@@ -305,6 +305,22 @@ struct ice_rss_hash_cfg eth_ipv4_l2tpv3_tmplt = {
 	0
 };
 
+struct ice_rss_hash_cfg eth_ipv4_l2tpv2_tmplt = {
+	ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
+	ICE_FLOW_SEG_HDR_L2TPV2,
+	ICE_FLOW_HASH_L2TPV2_SESS_ID,
+	ICE_RSS_OUTER_HEADERS,
+	0
+};
+
+struct ice_rss_hash_cfg eth_ipv6_l2tpv2_tmplt = {
+	ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_IPV_OTHER |
+	ICE_FLOW_SEG_HDR_L2TPV2,
+	ICE_FLOW_HASH_L2TPV2_SESS_ID,
+	ICE_RSS_OUTER_HEADERS,
+	0
+};
+
 struct ice_rss_hash_cfg eth_ipv4_pfcp_tmplt = {
 	ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
 	ICE_FLOW_SEG_HDR_PFCP_SESSION,
@@ -480,6 +496,8 @@ struct ice_rss_hash_cfg eth_tmplt = {
 #define ICE_RSS_TYPE_IPV6_AH		(RTE_ETH_RSS_AH | RTE_ETH_RSS_IPV6)
 #define ICE_RSS_TYPE_IPV4_L2TPV3	(RTE_ETH_RSS_L2TPV3 | RTE_ETH_RSS_IPV4)
 #define ICE_RSS_TYPE_IPV6_L2TPV3	(RTE_ETH_RSS_L2TPV3 | RTE_ETH_RSS_IPV6)
+#define ICE_RSS_TYPE_IPV4_L2TPV2	(RTE_ETH_RSS_L2TPV2 | RTE_ETH_RSS_IPV4)
+#define ICE_RSS_TYPE_IPV6_L2TPV2	(RTE_ETH_RSS_L2TPV2 | RTE_ETH_RSS_IPV6)
 #define ICE_RSS_TYPE_IPV4_PFCP		(RTE_ETH_RSS_PFCP | RTE_ETH_RSS_IPV4)
 #define ICE_RSS_TYPE_IPV6_PFCP		(RTE_ETH_RSS_PFCP | RTE_ETH_RSS_IPV6)
 
@@ -522,6 +540,8 @@ static struct ice_pattern_match_item ice_hash_pattern_list[] = {
 	{pattern_eth_ipv4_udp_esp,		ICE_RSS_TYPE_IPV4_ESP,		ICE_INSET_NONE,	&eth_ipv4_udp_esp_tmplt},
 	{pattern_eth_ipv4_ah,			ICE_RSS_TYPE_IPV4_AH,		ICE_INSET_NONE,	&eth_ipv4_ah_tmplt},
 	{pattern_eth_ipv4_l2tp,			ICE_RSS_TYPE_IPV4_L2TPV3,	ICE_INSET_NONE,	&eth_ipv4_l2tpv3_tmplt},
+	{pattern_eth_ipv4_l2tpv2,		ICE_RSS_TYPE_IPV4_L2TPV2,	ICE_INSET_NONE,	&eth_ipv4_l2tpv2_tmplt},
+	{pattern_eth_ipv6_l2tpv2,		ICE_RSS_TYPE_IPV6_L2TPV2,	ICE_INSET_NONE,	&eth_ipv6_l2tpv2_tmplt},
 	{pattern_eth_ipv4_pfcp,			ICE_RSS_TYPE_IPV4_PFCP,		ICE_INSET_NONE,	&eth_ipv4_pfcp_tmplt},
 	/* IPV6 */
 	{pattern_eth_ipv6,			ICE_RSS_TYPE_ETH_IPV6,		ICE_INSET_NONE,	&ipv6_tmplt},
@@ -925,6 +945,11 @@ ice_refine_hash_cfg_l234(struct ice_rss_hash_cfg *hash_cfg,
 			*hash_flds &= ~ICE_FLOW_HASH_L2TPV3_SESS_ID;
 	}
 
+	if (*addl_hdrs & ICE_FLOW_SEG_HDR_L2TPV2) {
+		if (!(rss_type & RTE_ETH_RSS_L2TPV2))
+			*hash_flds &= ~ICE_FLOW_HASH_L2TPV2_SESS_ID;
+	}
+
 	if (*addl_hdrs & ICE_FLOW_SEG_HDR_ESP) {
 		if (!(rss_type & RTE_ETH_RSS_ESP))
 			*hash_flds &= ~ICE_FLOW_HASH_ESP_SPI;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v6 8/8] doc: update release notes
  2026-02-18 16:37   ` [PATCH v6 0/8] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                       ` (6 preceding siblings ...)
  2026-02-18 16:37     ` [PATCH v6 7/8] net/ice: add L2TPv2 RSS hash support Shaiq Wani
@ 2026-02-18 16:37     ` Shaiq Wani
  7 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-18 16:37 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh

Add L2TPv2 over UDP support for ice PMD in the release notes.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
---
 doc/guides/rel_notes/release_26_03.rst | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/doc/guides/rel_notes/release_26_03.rst b/doc/guides/rel_notes/release_26_03.rst
index b4499ec066..a159f3122e 100644
--- a/doc/guides/rel_notes/release_26_03.rst
+++ b/doc/guides/rel_notes/release_26_03.rst
@@ -77,6 +77,10 @@ New Features
 
   * Added support for pre and post VF reset callbacks.
 
+* **Updated Intel ice driver.**
+
+  * Added Flow Director (FDIR) support for L2TPv2 over UDP.
+
 * **Updated Marvell cnxk net driver.**
 
   * Added out-of-place support for CN20K SoC.
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v7 0/7] Add support for L2TPV2 over UDP to ICE PMD
  2026-02-02  9:42 ` [PATCH 1/6] net/ice: add L2TPv2 and PPP data structures Shaiq Wani
  2026-02-18 16:37   ` [PATCH v6 0/8] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
@ 2026-02-19 11:20   ` Shaiq Wani
  2026-02-19 11:20     ` [PATCH v7 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
                       ` (7 more replies)
  1 sibling, 8 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-19 11:20 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh

This patchset enables L2TPv2 over UDP support in the ice PMD via rte_flow,
allowing flow classification and RSS hashing for L2TPv2 traffic.
  
v7: removed FDIR in doc and commit log titles.

v6: split patch 3 into 2 separate patches.

v5: Resending v4 patches with correct cover letter and threading.
  
v4: *Version 3 patchset was incomplete due to a server reboot.
    *V4 includes all patches for review.
 
v3: Fixed compilation issues.
v2: Addressed AI generated comments.




*** BLURB HERE ***

Shaiq Wani (7):
  net/ice: add L2TPv2 PPP and PPoE data structures
  net/ice: add L2TPv2 tunnel type definition
  net/ice: rename protocol identifiers
  net/ice: add L2TPv2 protocol support
  net/ice: add L2TPv2 flow pattern matching support
  net/ice: add L2TPv2 hardware packet generation
  net/ice: add L2TPv2 RSS hash support

 doc/guides/rel_notes/release_26_03.rst   |   4 +
 drivers/net/intel/ice/base/ice_fdir.c    |   6 +
 drivers/net/intel/ice/base/ice_fdir.h    |  17 +
 drivers/net/intel/ice/ice_ethdev.h       |   4 +
 drivers/net/intel/ice/ice_fdir_filter.c  | 451 ++++++++++++++++++++---
 drivers/net/intel/ice/ice_generic_flow.c | 177 +++++++++
 drivers/net/intel/ice/ice_generic_flow.h | 129 ++++---
 drivers/net/intel/ice/ice_hash.c         |  25 ++
 8 files changed, 717 insertions(+), 96 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH v7 1/7] net/ice: add L2TPv2 PPP and PPoE data structures
  2026-02-19 11:20   ` [PATCH v7 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
@ 2026-02-19 11:20     ` Shaiq Wani
  2026-02-19 11:20     ` [PATCH v7 2/7] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
                       ` (6 subsequent siblings)
  7 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-19 11:20 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add data structure definitions for L2TPv2 PPP and
PPoE protocols to support rte_flow pattern matching.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/base/ice_fdir.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/net/intel/ice/base/ice_fdir.h b/drivers/net/intel/ice/base/ice_fdir.h
index 3dd03f93f7..3d3b05da4a 100644
--- a/drivers/net/intel/ice/base/ice_fdir.h
+++ b/drivers/net/intel/ice/base/ice_fdir.h
@@ -230,6 +230,20 @@ struct ice_fdir_ecpri {
 	__be16 pc_id;
 };
 
+struct ice_fdir_pppoe {
+	u8 rsrvd_ver_type;
+	u8 rsrvd_code;
+	__be16 session_id;
+	__be16 length;
+	__be16 ppp_prot_id; /* control and data only */
+};
+
+struct ice_fdir_ppp {
+	u8 addr;
+	u8 ctrl;
+	__be16 proto_id;
+};
+
 struct ice_fdir_l2tpv2 {
 	__be16 flags_version;
 	__be16 length;
@@ -279,6 +293,9 @@ struct ice_fdir_fltr {
 	struct ice_fdir_ecpri ecpri_data;
 	struct ice_fdir_ecpri ecpri_mask;
 
+	struct ice_fdir_ppp ppp_data;
+	struct ice_fdir_ppp ppp_mask;
+
 	struct ice_fdir_l2tpv2 l2tpv2_data;
 	struct ice_fdir_l2tpv2 l2tpv2_mask;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v7 2/7] net/ice: add L2TPv2 tunnel type definition
  2026-02-19 11:20   ` [PATCH v7 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
  2026-02-19 11:20     ` [PATCH v7 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
@ 2026-02-19 11:20     ` Shaiq Wani
  2026-02-19 11:20     ` [PATCH v7 3/7] net/ice: rename protocol identifiers Shaiq Wani
                       ` (5 subsequent siblings)
  7 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-19 11:20 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add ICE_FDIR_TUNNEL_TYPE_L2TPV2 to the tunnel type enum and
extend ice_fdir_fltr_pattern structure to include L2TPv2 data and
mask fields.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_ethdev.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/intel/ice/ice_ethdev.h b/drivers/net/intel/ice/ice_ethdev.h
index 9562b2b8f1..4b3718f715 100644
--- a/drivers/net/intel/ice/ice_ethdev.h
+++ b/drivers/net/intel/ice/ice_ethdev.h
@@ -369,6 +369,7 @@ enum ice_fdir_tunnel_type {
 	ICE_FDIR_TUNNEL_TYPE_VXLAN,
 	ICE_FDIR_TUNNEL_TYPE_GTPU,
 	ICE_FDIR_TUNNEL_TYPE_GTPU_EH,
+	ICE_FDIR_TUNNEL_TYPE_L2TPV2,
 };
 
 struct rte_flow;
@@ -405,6 +406,9 @@ struct ice_fdir_fltr_pattern {
 	struct ice_fdir_udp_gtp gtpu_data;
 	struct ice_fdir_udp_gtp gtpu_mask;
 
+	struct ice_fdir_l2tpv2 l2tpv2_data;
+	struct ice_fdir_l2tpv2 l2tpv2_mask;
+
 	struct ice_fdir_extra ext_data;
 	struct ice_fdir_extra ext_mask;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v7 3/7] net/ice: rename protocol identifiers
  2026-02-19 11:20   ` [PATCH v7 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
  2026-02-19 11:20     ` [PATCH v7 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
  2026-02-19 11:20     ` [PATCH v7 2/7] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
@ 2026-02-19 11:20     ` Shaiq Wani
  2026-02-19 11:21     ` [PATCH v7 4/7] net/ice: add L2TPv2 protocol support Shaiq Wani
                       ` (4 subsequent siblings)
  7 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-19 11:20 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Rename existing protocol identifiers to use _OUTER suffix and add
corresponding _INNER variants to support tunneled packet parsing.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_generic_flow.h | 107 ++++++++++++++---------
 1 file changed, 66 insertions(+), 41 deletions(-)

diff --git a/drivers/net/intel/ice/ice_generic_flow.h b/drivers/net/intel/ice/ice_generic_flow.h
index 54bbb47398..0b282d4ee5 100644
--- a/drivers/net/intel/ice/ice_generic_flow.h
+++ b/drivers/net/intel/ice/ice_generic_flow.h
@@ -9,15 +9,15 @@
 
 /* protocol */
 
-#define ICE_PROT_MAC			BIT_ULL(1)
-#define ICE_PROT_VLAN			BIT_ULL(2)
-#define ICE_PROT_IPV4			BIT_ULL(3)
-#define ICE_PROT_IPV6			BIT_ULL(4)
-#define ICE_PROT_TCP			BIT_ULL(5)
-#define ICE_PROT_UDP			BIT_ULL(6)
-#define ICE_PROT_SCTP			BIT_ULL(7)
-#define ICE_PROT_ICMP4			BIT_ULL(8)
-#define ICE_PROT_ICMP6			BIT_ULL(9)
+#define ICE_PROT_MAC_OUTER		BIT_ULL(1)
+#define ICE_PROT_VLAN_OUTER		BIT_ULL(2)
+#define ICE_PROT_IPV4_OUTER		BIT_ULL(3)
+#define ICE_PROT_IPV6_OUTER		BIT_ULL(4)
+#define ICE_PROT_TCP_OUTER		BIT_ULL(5)
+#define ICE_PROT_UDP_OUTER		BIT_ULL(6)
+#define ICE_PROT_SCTP_OUTER		BIT_ULL(7)
+#define ICE_PROT_ICMP4_OUTER		BIT_ULL(8)
+#define ICE_PROT_ICMP6_OUTER		BIT_ULL(9)
 #define ICE_PROT_VXLAN			BIT_ULL(10)
 #define ICE_PROT_NVGRE			BIT_ULL(11)
 #define ICE_PROT_GTPU			BIT_ULL(12)
@@ -27,6 +27,15 @@
 #define ICE_PROT_L2TPV3OIP		BIT_ULL(16)
 #define ICE_PROT_PFCP			BIT_ULL(17)
 #define ICE_PROT_NAT_T_ESP		BIT_ULL(18)
+#define ICE_PROT_MAC_INNER		BIT_ULL(20)
+#define ICE_PROT_VLAN_INNER		BIT_ULL(21)
+#define ICE_PROT_IPV4_INNER		BIT_ULL(22)
+#define ICE_PROT_IPV6_INNER		BIT_ULL(23)
+#define ICE_PROT_TCP_INNER		BIT_ULL(24)
+#define ICE_PROT_UDP_INNER		BIT_ULL(25)
+#define ICE_PROT_SCTP_INNER		BIT_ULL(26)
+#define ICE_PROT_ICMP4_INNER		BIT_ULL(27)
+#define ICE_PROT_ICMP6_INNER		BIT_ULL(28)
 
 /* field */
 
@@ -53,7 +62,7 @@
 #define ICE_L2TPV3OIP_SESSION_ID	BIT_ULL(43)
 #define ICE_PFCP_SEID			BIT_ULL(42)
 #define ICE_PFCP_S_FIELD		BIT_ULL(41)
-#define ICE_IP_PK_ID		    BIT_ULL(40)
+#define ICE_IP_PK_ID			BIT_ULL(40)
 #define ICE_IP_FRAG_OFS			BIT_ULL(39)
 
 /* input set */
@@ -62,39 +71,39 @@
 
 #define ICE_INSET_SMAC			(ICE_SMAC)
 #define ICE_INSET_DMAC			(ICE_DMAC)
-#define ICE_INSET_VLAN			(ICE_PROT_VLAN)
-#define ICE_INSET_VLAN_INNER		(ICE_PROT_VLAN)
-#define ICE_INSET_VLAN_OUTER		(ICE_PROT_VLAN)
+#define ICE_INSET_VLAN			(ICE_PROT_VLAN_OUTER)
+#define ICE_INSET_VLAN_INNER		(ICE_PROT_VLAN_INNER)
+#define ICE_INSET_VLAN_OUTER		(ICE_PROT_VLAN_OUTER)
 #define ICE_INSET_ETHERTYPE		(ICE_ETHERTYPE)
 
-#define ICE_INSET_IPV4_SRC		(ICE_PROT_IPV4 | ICE_IP_SRC)
-#define ICE_INSET_IPV4_DST		(ICE_PROT_IPV4 | ICE_IP_DST)
-#define ICE_INSET_IPV4_TOS		(ICE_PROT_IPV4 | ICE_IP_TOS)
-#define ICE_INSET_IPV4_PROTO		(ICE_PROT_IPV4 | ICE_IP_PROTO)
-#define ICE_INSET_IPV4_TTL		(ICE_PROT_IPV4 | ICE_IP_TTL)
-#define ICE_INSET_IPV4_PKID		(ICE_PROT_IPV4 | ICE_IP_PK_ID)
-#define ICE_INSET_IPV4_FRAG_OFS	(ICE_PROT_IPV4 | ICE_IP_FRAG_OFS)
-#define ICE_INSET_IPV6_SRC		(ICE_PROT_IPV6 | ICE_IP_SRC)
-#define ICE_INSET_IPV6_DST		(ICE_PROT_IPV6 | ICE_IP_DST)
-#define ICE_INSET_IPV6_NEXT_HDR		(ICE_PROT_IPV6 | ICE_IP_PROTO)
-#define ICE_INSET_IPV6_HOP_LIMIT	(ICE_PROT_IPV6 | ICE_IP_TTL)
-#define ICE_INSET_IPV6_TC		(ICE_PROT_IPV6 | ICE_IP_TOS)
-#define ICE_INSET_IPV6_PKID		(ICE_PROT_IPV6 | ICE_IP_PK_ID)
-
-#define ICE_INSET_TCP_SRC_PORT		(ICE_PROT_TCP | ICE_SPORT)
-#define ICE_INSET_TCP_DST_PORT		(ICE_PROT_TCP | ICE_DPORT)
-#define ICE_INSET_UDP_SRC_PORT		(ICE_PROT_UDP | ICE_SPORT)
-#define ICE_INSET_UDP_DST_PORT		(ICE_PROT_UDP | ICE_DPORT)
-#define ICE_INSET_SCTP_SRC_PORT		(ICE_PROT_SCTP | ICE_SPORT)
-#define ICE_INSET_SCTP_DST_PORT		(ICE_PROT_SCTP | ICE_DPORT)
-#define ICE_INSET_ICMP4_SRC_PORT	(ICE_PROT_ICMP4 | ICE_SPORT)
-#define ICE_INSET_ICMP4_DST_PORT	(ICE_PROT_ICMP4 | ICE_DPORT)
-#define ICE_INSET_ICMP6_SRC_PORT	(ICE_PROT_ICMP6 | ICE_SPORT)
-#define ICE_INSET_ICMP6_DST_PORT	(ICE_PROT_ICMP6 | ICE_DPORT)
-#define ICE_INSET_ICMP4_TYPE		(ICE_PROT_ICMP4 | ICE_ICMP_TYPE)
-#define ICE_INSET_ICMP4_CODE		(ICE_PROT_ICMP4 | ICE_ICMP_CODE)
-#define ICE_INSET_ICMP6_TYPE		(ICE_PROT_ICMP6 | ICE_ICMP_TYPE)
-#define ICE_INSET_ICMP6_CODE		(ICE_PROT_ICMP6 | ICE_ICMP_CODE)
+#define ICE_INSET_IPV4_SRC		(ICE_PROT_IPV4_OUTER | ICE_IP_SRC)
+#define ICE_INSET_IPV4_DST		(ICE_PROT_IPV4_OUTER | ICE_IP_DST)
+#define ICE_INSET_IPV4_TOS		(ICE_PROT_IPV4_OUTER | ICE_IP_TOS)
+#define ICE_INSET_IPV4_PROTO		(ICE_PROT_IPV4_OUTER | ICE_IP_PROTO)
+#define ICE_INSET_IPV4_TTL		(ICE_PROT_IPV4_OUTER | ICE_IP_TTL)
+#define ICE_INSET_IPV4_PKID		(ICE_PROT_IPV4_OUTER | ICE_IP_PK_ID)
+#define ICE_INSET_IPV4_FRAG_OFS	(ICE_PROT_IPV4_OUTER | ICE_IP_FRAG_OFS)
+#define ICE_INSET_IPV6_SRC		(ICE_PROT_IPV6_OUTER | ICE_IP_SRC)
+#define ICE_INSET_IPV6_DST		(ICE_PROT_IPV6_OUTER | ICE_IP_DST)
+#define ICE_INSET_IPV6_NEXT_HDR		(ICE_PROT_IPV6_OUTER | ICE_IP_PROTO)
+#define ICE_INSET_IPV6_HOP_LIMIT	(ICE_PROT_IPV6_OUTER | ICE_IP_TTL)
+#define ICE_INSET_IPV6_TC		(ICE_PROT_IPV6_OUTER | ICE_IP_TOS)
+#define ICE_INSET_IPV6_PKID		(ICE_PROT_IPV6_OUTER | ICE_IP_PK_ID)
+
+#define ICE_INSET_TCP_SRC_PORT		(ICE_PROT_TCP_OUTER | ICE_SPORT)
+#define ICE_INSET_TCP_DST_PORT		(ICE_PROT_TCP_OUTER | ICE_DPORT)
+#define ICE_INSET_UDP_SRC_PORT		(ICE_PROT_UDP_OUTER | ICE_SPORT)
+#define ICE_INSET_UDP_DST_PORT		(ICE_PROT_UDP_OUTER | ICE_DPORT)
+#define ICE_INSET_SCTP_SRC_PORT		(ICE_PROT_SCTP_OUTER | ICE_SPORT)
+#define ICE_INSET_SCTP_DST_PORT		(ICE_PROT_SCTP_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP4_SRC_PORT	(ICE_PROT_ICMP4_OUTER | ICE_SPORT)
+#define ICE_INSET_ICMP4_DST_PORT	(ICE_PROT_ICMP4_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP6_SRC_PORT	(ICE_PROT_ICMP6_OUTER | ICE_SPORT)
+#define ICE_INSET_ICMP6_DST_PORT	(ICE_PROT_ICMP6_OUTER | ICE_DPORT)
+#define ICE_INSET_ICMP4_TYPE		(ICE_PROT_ICMP4_OUTER | ICE_ICMP_TYPE)
+#define ICE_INSET_ICMP4_CODE		(ICE_PROT_ICMP4_OUTER | ICE_ICMP_CODE)
+#define ICE_INSET_ICMP6_TYPE		(ICE_PROT_ICMP6_OUTER | ICE_ICMP_TYPE)
+#define ICE_INSET_ICMP6_CODE		(ICE_PROT_ICMP6_OUTER | ICE_ICMP_CODE)
 
 /* tunnel */
 
@@ -122,6 +131,22 @@
 	(ICE_PROT_PFCP | ICE_PFCP_S_FIELD | ICE_PFCP_SEID)
 #define ICE_INSET_NAT_T_ESP_SPI \
 	(ICE_PROT_NAT_T_ESP | ICE_ESP_SPI)
+#define ICE_INSET_TUN_IPV4_SRC \
+	(ICE_PROT_IPV4_INNER | ICE_IP_SRC)
+#define ICE_INSET_TUN_IPV4_DST \
+	(ICE_PROT_IPV4_INNER | ICE_IP_DST)
+#define ICE_INSET_TUN_UDP_SRC_PORT \
+	(ICE_PROT_UDP_INNER | ICE_SPORT)
+#define ICE_INSET_TUN_UDP_DST_PORT \
+	(ICE_PROT_UDP_INNER | ICE_DPORT)
+#define ICE_INSET_TUN_TCP_SRC_PORT \
+	(ICE_PROT_TCP_INNER | ICE_SPORT)
+#define ICE_INSET_TUN_TCP_DST_PORT \
+	(ICE_PROT_TCP_INNER | ICE_DPORT)
+#define ICE_INSET_TUN_IPV6_SRC \
+	(ICE_PROT_IPV6_INNER | ICE_IP_SRC)
+#define ICE_INSET_TUN_IPV6_DST \
+	(ICE_PROT_IPV6_INNER | ICE_IP_DST)
 
 /* empty pattern */
 extern enum rte_flow_item_type pattern_empty[];
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v7 4/7] net/ice: add L2TPv2 protocol support
  2026-02-19 11:20   ` [PATCH v7 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                       ` (2 preceding siblings ...)
  2026-02-19 11:20     ` [PATCH v7 3/7] net/ice: rename protocol identifiers Shaiq Wani
@ 2026-02-19 11:21     ` Shaiq Wani
  2026-02-19 11:21     ` [PATCH v7 5/7] net/ice: add L2TPv2 flow pattern matching support Shaiq Wani
                       ` (3 subsequent siblings)
  7 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-19 11:21 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add L2TPv2 protocol identifier and session ID field definition
to enable flow classification and filtering for L2TPv2 tunneled
traffic.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_generic_flow.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/net/intel/ice/ice_generic_flow.h b/drivers/net/intel/ice/ice_generic_flow.h
index 0b282d4ee5..1b5514d5df 100644
--- a/drivers/net/intel/ice/ice_generic_flow.h
+++ b/drivers/net/intel/ice/ice_generic_flow.h
@@ -27,6 +27,7 @@
 #define ICE_PROT_L2TPV3OIP		BIT_ULL(16)
 #define ICE_PROT_PFCP			BIT_ULL(17)
 #define ICE_PROT_NAT_T_ESP		BIT_ULL(18)
+#define ICE_PROT_L2TPV2OIP		BIT_ULL(19)
 #define ICE_PROT_MAC_INNER		BIT_ULL(20)
 #define ICE_PROT_VLAN_INNER		BIT_ULL(21)
 #define ICE_PROT_IPV4_INNER		BIT_ULL(22)
@@ -64,6 +65,7 @@
 #define ICE_PFCP_S_FIELD		BIT_ULL(41)
 #define ICE_IP_PK_ID			BIT_ULL(40)
 #define ICE_IP_FRAG_OFS			BIT_ULL(39)
+#define ICE_L2TPV2OIP_SESSION_ID	BIT_ULL(38)
 
 /* input set */
 
@@ -131,6 +133,8 @@
 	(ICE_PROT_PFCP | ICE_PFCP_S_FIELD | ICE_PFCP_SEID)
 #define ICE_INSET_NAT_T_ESP_SPI \
 	(ICE_PROT_NAT_T_ESP | ICE_ESP_SPI)
+#define ICE_INSET_L2TPV2OIP_SESSION_ID \
+	(ICE_PROT_L2TPV2OIP | ICE_L2TPV2OIP_SESSION_ID)
 #define ICE_INSET_TUN_IPV4_SRC \
 	(ICE_PROT_IPV4_INNER | ICE_IP_SRC)
 #define ICE_INSET_TUN_IPV4_DST \
@@ -425,6 +429,24 @@ extern enum rte_flow_item_type pattern_eth_ipv6_udp_ah[];
 /* L2TP */
 extern enum rte_flow_item_type pattern_eth_ipv4_l2tp[];
 extern enum rte_flow_item_type pattern_eth_ipv6_l2tp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv6_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp[];
 
 /* PFCP */
 extern enum rte_flow_item_type pattern_eth_ipv4_pfcp[];
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v7 5/7] net/ice: add L2TPv2 flow pattern matching support
  2026-02-19 11:20   ` [PATCH v7 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                       ` (3 preceding siblings ...)
  2026-02-19 11:21     ` [PATCH v7 4/7] net/ice: add L2TPv2 protocol support Shaiq Wani
@ 2026-02-19 11:21     ` Shaiq Wani
  2026-02-19 11:21     ` [PATCH v7 6/7] net/ice: add L2TPv2 hardware packet generation Shaiq Wani
                       ` (2 subsequent siblings)
  7 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-19 11:21 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add L2TPv2 support for rte_flow:

-Flow pattern definitions for different L2TPv2 packet combinations
-FDIR filter parsing logic
-Flow type assignment for proper packet classification.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/ice_fdir_filter.c  | 451 ++++++++++++++++++++---
 drivers/net/intel/ice/ice_generic_flow.c | 177 +++++++++
 2 files changed, 573 insertions(+), 55 deletions(-)

diff --git a/drivers/net/intel/ice/ice_fdir_filter.c b/drivers/net/intel/ice/ice_fdir_filter.c
index da22b65a77..1279823b12 100644
--- a/drivers/net/intel/ice/ice_fdir_filter.c
+++ b/drivers/net/intel/ice/ice_fdir_filter.c
@@ -107,6 +107,31 @@
 	ICE_INSET_IPV6_SRC | ICE_INSET_IPV6_DST | \
 	ICE_INSET_NAT_T_ESP_SPI)
 
+#define ICE_FDIR_INSET_L2TPV2 (\
+	ICE_INSET_SMAC | ICE_INSET_DMAC | ICE_INSET_L2TPV2OIP_SESSION_ID)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4 (\
+	ICE_INSET_TUN_IPV4_SRC | ICE_INSET_TUN_IPV4_DST)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV4 | ICE_INSET_TUN_UDP_SRC_PORT | \
+	ICE_INSET_TUN_UDP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV4 | ICE_INSET_TUN_TCP_SRC_PORT | \
+	ICE_INSET_TUN_TCP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6 (\
+	ICE_INSET_TUN_IPV6_SRC | ICE_INSET_TUN_IPV6_DST)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV6 | ICE_INSET_TUN_UDP_SRC_PORT | \
+	ICE_INSET_TUN_UDP_DST_PORT)
+
+#define ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP (\
+	ICE_FDIR_INSET_L2TPV2_PPP_IPV6 | ICE_INSET_TUN_TCP_SRC_PORT | \
+	ICE_INSET_TUN_TCP_DST_PORT)
+
 static struct ice_pattern_match_item ice_fdir_supported_pattern[] = {
 	{pattern_raw,					ICE_INSET_NONE,			ICE_INSET_NONE,			ICE_INSET_NONE},
 	{pattern_ethertype,				ICE_FDIR_INSET_ETH,		ICE_INSET_NONE,			ICE_INSET_NONE},
@@ -132,10 +157,26 @@ static struct ice_pattern_match_item ice_fdir_supported_pattern[] = {
 	{pattern_eth_ipv4_udp_vxlan_eth_ipv4_tcp,	ICE_FDIR_INSET_ETH_IPV4_VXLAN,	ICE_FDIR_INSET_ETH_IPV4_TCP,	ICE_INSET_NONE},
 	{pattern_eth_ipv4_udp_vxlan_eth_ipv4_sctp,	ICE_FDIR_INSET_ETH_IPV4_VXLAN,	ICE_FDIR_INSET_ETH_IPV4_SCTP,	ICE_INSET_NONE},
 	/* duplicated GTPU input set in 3rd column to align with shared code behavior. Ideally, only put GTPU field in 2nd column. */
-	{pattern_eth_ipv4_gtpu,				ICE_FDIR_INSET_IPV4_GTPU,	ICE_FDIR_INSET_IPV4_GTPU,	ICE_INSET_NONE},
-	{pattern_eth_ipv4_gtpu_eh,			ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_INSET_NONE},
-	{pattern_eth_ipv6_gtpu,				ICE_FDIR_INSET_IPV6_GTPU,	ICE_FDIR_INSET_IPV6_GTPU,	ICE_INSET_NONE},
-	{pattern_eth_ipv6_gtpu_eh,			ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_gtpu,				ICE_FDIR_INSET_IPV4_GTPU,	ICE_FDIR_INSET_IPV4_GTPU,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_gtpu_eh,			ICE_FDIR_INSET_IPV4_GTPU_EH,	ICE_FDIR_INSET_IPV4_GTPU_EH,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_gtpu,				ICE_FDIR_INSET_IPV6_GTPU,	ICE_FDIR_INSET_IPV6_GTPU,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_gtpu_eh,			ICE_FDIR_INSET_IPV6_GTPU_EH,	ICE_FDIR_INSET_IPV6_GTPU_EH,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2,			ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp,		ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2,			ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp,		ICE_FDIR_INSET_L2TPV2,		ICE_INSET_NONE,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV4_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6,		ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6,		ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6,		ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_UDP,	ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp,	ICE_FDIR_INSET_L2TPV2,		ICE_FDIR_INSET_L2TPV2_PPP_IPV6_TCP,	ICE_INSET_NONE},
 };
 
 static int
@@ -957,6 +998,7 @@ ice_fdir_input_set_parse(uint64_t inset, enum ice_flow_field *field)
 		{ICE_INSET_VXLAN_VNI, ICE_FLOW_FIELD_IDX_VXLAN_VNI},
 		{ICE_INSET_ESP_SPI, ICE_FLOW_FIELD_IDX_ESP_SPI},
 		{ICE_INSET_NAT_T_ESP_SPI, ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI},
+		{ICE_INSET_L2TPV2OIP_SESSION_ID, ICE_FLOW_FIELD_IDX_L2TPV2_SESS_ID},
 	};
 
 	for (i = 0, j = 0; i < RTE_DIM(ice_inset_map); i++) {
@@ -1068,6 +1110,43 @@ ice_fdir_input_set_hdrs(enum ice_fltr_ptype flow, struct ice_flow_seg_info *seg)
 				  ICE_FLOW_SEG_HDR_IPV6 |
 				  ICE_FLOW_SEG_HDR_IPV_OTHER);
 		break;
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_IPV6 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_UDP:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_PPP |
+				  ICE_FLOW_SEG_HDR_IPV6 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_IPV4 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_UDP:
+		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+				  ICE_FLOW_SEG_HDR_PPP |
+				  ICE_FLOW_SEG_HDR_IPV4 |
+				  ICE_FLOW_SEG_HDR_IPV_OTHER);
+		break;
+
 	default:
 		PMD_DRV_LOG(ERR, "not supported filter type.");
 		break;
@@ -1170,7 +1249,10 @@ ice_fdir_uninit(struct ice_adapter *ad)
 static int
 ice_fdir_is_tunnel_profile(enum ice_fdir_tunnel_type tunnel_type)
 {
-	if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN)
+	if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_GTPU ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_GTPU_EH)
 		return 1;
 	else
 		return 0;
@@ -1239,6 +1321,9 @@ ice_fdir_extract_fltr_key(struct ice_fdir_fltr_pattern *key,
 	rte_memcpy(&key->gtpu_data, &input->gtpu_data, sizeof(key->gtpu_data));
 	rte_memcpy(&key->gtpu_mask, &input->gtpu_mask, sizeof(key->gtpu_mask));
 
+	rte_memcpy(&key->l2tpv2_data, &input->l2tpv2_data, sizeof(key->l2tpv2_data));
+	rte_memcpy(&key->l2tpv2_mask, &input->l2tpv2_mask, sizeof(key->l2tpv2_mask));
+
 	key->tunnel_type = filter->tunnel_type;
 }
 
@@ -1797,16 +1882,22 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 	const struct rte_flow_item_gtp *gtp_spec, *gtp_mask;
 	const struct rte_flow_item_gtp_psc *gtp_psc_spec, *gtp_psc_mask;
 	const struct rte_flow_item_esp *esp_spec, *esp_mask;
+	const struct rte_flow_item_l2tpv2 *l2tpv2_spec, *l2tpv2_mask;
+	const struct rte_flow_item_ppp *ppp_spec, *ppp_mask;
 	uint64_t input_set_i = ICE_INSET_NONE; /* only for tunnel inner */
 	uint64_t input_set_o = ICE_INSET_NONE; /* non-tunnel and tunnel outer */
 	uint64_t *input_set;
 	uint8_t flow_type = ICE_FLTR_PTYPE_NONF_NONE;
+	enum rte_flow_item_type inner_l3 = RTE_FLOW_ITEM_TYPE_END;
+	enum rte_flow_item_type inner_l4 = RTE_FLOW_ITEM_TYPE_END;
+	enum rte_flow_item_type current_l3 = RTE_FLOW_ITEM_TYPE_END;
+	bool ppp_present = false;
 	uint8_t  ipv6_addr_mask[16] = {
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
 	};
 	uint32_t vtc_flow_cpu;
-	uint16_t ether_type;
+	uint16_t ether_type = 0, flags_version = 0;
 	enum rte_flow_item_type next_type;
 	bool is_outer = true;
 	struct ice_fdir_extra *p_ext_data;
@@ -2001,22 +2092,30 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				   &eth_spec->hdr.ether_type, sizeof(eth_spec->hdr.ether_type));
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV4:
-			flow_type = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
-			l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			/* Only set flow_type for outer IPv4, track inner L3 for tunnels */
+			if (is_outer || !tunnel_type) {
+				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
+				l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			} else {
+				inner_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+			}
+
 			ipv4_spec = item->spec;
 			ipv4_last = item->last;
 			ipv4_mask = item->mask;
 			p_v4 = (tunnel_type && is_outer) ?
-			       &filter->input.ip_outer.v4 :
-			       &filter->input.ip.v4;
+					&filter->input.ip_outer.v4 :
+					&filter->input.ip.v4;
 
 			if (!(ipv4_spec && ipv4_mask))
 				break;
 
 			/* Check IPv4 mask and update input set */
 			if (ipv4_mask->hdr.version_ihl ||
-			    ipv4_mask->hdr.total_length ||
-			    ipv4_mask->hdr.hdr_checksum) {
+				ipv4_mask->hdr.total_length ||
+				ipv4_mask->hdr.hdr_checksum) {
 				rte_flow_error_set(error, EINVAL,
 						   RTE_FLOW_ERROR_TYPE_ITEM,
 						   item,
@@ -2048,10 +2147,20 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				ipv4_mask->hdr.dst_addr != UINT32_MAX)
 				return -rte_errno;
 
-			if (ipv4_mask->hdr.dst_addr == UINT32_MAX)
-				*input_set |= ICE_INSET_IPV4_DST;
-			if (ipv4_mask->hdr.src_addr == UINT32_MAX)
-				*input_set |= ICE_INSET_IPV4_SRC;
+			if (ipv4_mask->hdr.dst_addr == UINT32_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV4_DST;
+				else
+					*input_set |= ICE_INSET_IPV4_DST;
+			}
+			if (ipv4_mask->hdr.src_addr == UINT32_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV4_SRC;
+				else
+					*input_set |= ICE_INSET_IPV4_SRC;
+			}
 			if (ipv4_mask->hdr.time_to_live == UINT8_MAX)
 				*input_set |= ICE_INSET_IPV4_TTL;
 			if (ipv4_mask->hdr.next_proto_id == UINT8_MAX)
@@ -2092,8 +2201,15 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV6:
-			flow_type = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
-			l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			if (is_outer || !tunnel_type) {
+				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
+				l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			} else {
+				inner_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+				current_l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+			}
+
 			ipv6_spec = item->spec;
 			ipv6_mask = item->mask;
 			p_v6 = (tunnel_type && is_outer) ?
@@ -2113,15 +2229,24 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 			}
 
 			if (!memcmp(&ipv6_mask->hdr.src_addr, ipv6_addr_mask,
-				    sizeof(ipv6_mask->hdr.src_addr)))
-				*input_set |= ICE_INSET_IPV6_SRC;
+				    sizeof(ipv6_mask->hdr.src_addr))) {
+				if (tunnel_type && !is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV6_SRC;
+				else
+					*input_set |= ICE_INSET_IPV6_SRC;
+			}
 			if (!memcmp(&ipv6_mask->hdr.dst_addr, ipv6_addr_mask,
-				    sizeof(ipv6_mask->hdr.dst_addr)))
-				*input_set |= ICE_INSET_IPV6_DST;
-
+				    sizeof(ipv6_mask->hdr.dst_addr))) {
+				if (tunnel_type && !is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_IPV6_DST;
+				else
+					*input_set |= ICE_INSET_IPV6_DST;
+			}
 			if ((ipv6_mask->hdr.vtc_flow &
-			     rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
-			    == rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
+			     rte_cpu_to_be_32(ICE_IPV6_TC_MASK)) ==
+			    rte_cpu_to_be_32(ICE_IPV6_TC_MASK))
 				*input_set |= ICE_INSET_IPV6_TC;
 			if (ipv6_mask->hdr.proto == UINT8_MAX)
 				*input_set |= ICE_INSET_IPV6_NEXT_HDR;
@@ -2167,10 +2292,16 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 			break;
 
 		case RTE_FLOW_ITEM_TYPE_TCP:
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
+			if (!is_outer && tunnel_type) {
+				/* For inner TCP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_TCP;
+			} else {
+				/* For outer TCP, update flow_type normally */
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
+			}
 
 			tcp_spec = item->spec;
 			tcp_mask = item->mask;
@@ -2201,28 +2332,44 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				tcp_mask->hdr.dst_port != UINT16_MAX)
 				return -rte_errno;
 
-			if (tcp_mask->hdr.src_port == UINT16_MAX)
-				*input_set |= ICE_INSET_TCP_SRC_PORT;
-			if (tcp_mask->hdr.dst_port == UINT16_MAX)
-				*input_set |= ICE_INSET_TCP_DST_PORT;
+			if (tcp_mask->hdr.src_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_TCP_SRC_PORT;
+				else
+					*input_set |= ICE_INSET_TCP_SRC_PORT;
+			}
+			if (tcp_mask->hdr.dst_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_TCP_DST_PORT;
+				else
+					*input_set |= ICE_INSET_TCP_DST_PORT;
+			}
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = tcp_spec->hdr.dst_port;
 				p_v4->src_port = tcp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->dst_port = tcp_spec->hdr.dst_port;
 				p_v6->src_port = tcp_spec->hdr.src_port;
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_UDP:
-			l4 = RTE_FLOW_ITEM_TYPE_UDP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
+			if (!is_outer && tunnel_type) {
+				/* For inner UDP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_UDP;
+			} else {
+				/* For outer UDP, update flow_type normally */
+				l4 = RTE_FLOW_ITEM_TYPE_UDP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
+			}
 
 			udp_spec = item->spec;
 			udp_mask = item->mask;
@@ -2248,27 +2395,43 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				udp_mask->hdr.dst_port != UINT16_MAX)
 				return -rte_errno;
 
-			if (udp_mask->hdr.src_port == UINT16_MAX)
-				*input_set |= ICE_INSET_UDP_SRC_PORT;
-			if (udp_mask->hdr.dst_port == UINT16_MAX)
-				*input_set |= ICE_INSET_UDP_DST_PORT;
+			if (udp_mask->hdr.src_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_UDP_SRC_PORT;
+				else
+					*input_set |= ICE_INSET_UDP_SRC_PORT;
+			}
+			if (udp_mask->hdr.dst_port == UINT16_MAX) {
+				if (!is_outer &&
+				    tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2)
+					*input_set |= ICE_INSET_TUN_UDP_DST_PORT;
+				else
+					*input_set |= ICE_INSET_UDP_DST_PORT;
+			}
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = udp_spec->hdr.dst_port;
 				p_v4->src_port = udp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->src_port = udp_spec->hdr.src_port;
 				p_v6->dst_port = udp_spec->hdr.dst_port;
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_SCTP:
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
-				flow_type = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
+			if (!is_outer && tunnel_type) {
+				/* For inner SCTP in tunnels, track inner_l4 */
+				inner_l4 = RTE_FLOW_ITEM_TYPE_SCTP;
+			} else {
+				/* For outer SCTP, update flow_type normally */
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
+				if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
+			}
 
 			sctp_spec = item->spec;
 			sctp_mask = item->mask;
@@ -2299,11 +2462,11 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				*input_set |= ICE_INSET_SCTP_DST_PORT;
 
 			/* Get filter info */
-			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+			if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
 				assert(p_v4);
 				p_v4->dst_port = sctp_spec->hdr.dst_port;
 				p_v4->src_port = sctp_spec->hdr.src_port;
-			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+			} else if (current_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
 				assert(p_v6);
 				p_v6->dst_port = sctp_spec->hdr.dst_port;
 				p_v6->src_port = sctp_spec->hdr.src_port;
@@ -2406,6 +2569,115 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				filter->input.ip.v6.sec_parm_idx =
 					esp_spec->hdr.spi;
 			break;
+		case RTE_FLOW_ITEM_TYPE_L2TPV2: {
+			struct ice_fdir_l2tpv2 l2tpv2_be;
+
+			l2tpv2_spec = item->spec;
+			l2tpv2_mask = item->mask;
+
+			if (!(l2tpv2_spec && l2tpv2_mask))
+				break;
+
+			flags_version =
+				rte_be_to_cpu_16(l2tpv2_spec->hdr.common.flags_version);
+			if ((flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+			     l2tpv2_mask->hdr.type3.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA &&
+			     l2tpv2_mask->hdr.type7.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L &&
+			     l2tpv2_mask->hdr.type6.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S &&
+			     l2tpv2_mask->hdr.type5.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_O &&
+			     l2tpv2_mask->hdr.type4.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S &&
+			     l2tpv2_mask->hdr.type3.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_O &&
+			     l2tpv2_mask->hdr.type2.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S_O &&
+			     l2tpv2_mask->hdr.type1.session_id == UINT16_MAX) ||
+			    (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S_O &&
+			     l2tpv2_mask->hdr.type0.session_id == UINT16_MAX)) {
+				input_set_o |= ICE_INSET_L2TPV2OIP_SESSION_ID;
+			}
+
+			tunnel_type = ICE_FDIR_TUNNEL_TYPE_L2TPV2;
+			memset(&l2tpv2_be, 0, sizeof(l2tpv2_be));
+
+			if (flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type7.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type7.session_id);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type6.session_id);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type5.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_O) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.session_id);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type4.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type3.nr);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_O) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.session_id);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type2.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_S_O) {
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.nr);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type1.offset_size);
+			} else if (flags_version == RTE_L2TPV2_MSG_TYPE_DATA_L_S_O) {
+				l2tpv2_be.length = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.length);
+				l2tpv2_be.tunnel_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.tunnel_id);
+				l2tpv2_be.session_id = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.session_id);
+				l2tpv2_be.ns = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.ns);
+				l2tpv2_be.nr = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.nr);
+				l2tpv2_be.offset_size = rte_cpu_to_be_16(l2tpv2_spec->hdr.type0.offset_size);
+			}
+
+			/* Copy converted values to filter */
+			filter->input.l2tpv2_data.flags_version = rte_cpu_to_be_16(flags_version);
+			filter->input.l2tpv2_data.length = l2tpv2_be.length;
+			filter->input.l2tpv2_data.tunnel_id = l2tpv2_be.tunnel_id;
+			filter->input.l2tpv2_data.session_id = l2tpv2_be.session_id;
+			filter->input.l2tpv2_data.ns = l2tpv2_be.ns;
+			filter->input.l2tpv2_data.nr = l2tpv2_be.nr;
+			filter->input.l2tpv2_data.offset_size = l2tpv2_be.offset_size;
+			break;
+		}
+		case RTE_FLOW_ITEM_TYPE_PPP:
+			ppp_spec = item->spec;
+			ppp_mask = item->mask;
+
+			/* PPP marks transition from outer to inner in L2TPv2 tunnels */
+			if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2) {
+				is_outer = false;
+				ppp_present = true;
+			}
+
+			if (ppp_spec && ppp_mask) {
+				filter->input.ppp_data.addr = ppp_spec->hdr.addr;
+				filter->input.ppp_data.ctrl = ppp_spec->hdr.ctrl;
+				filter->input.ppp_data.proto_id = ppp_spec->hdr.proto_id;
+			}
+			break;
 		default:
 			rte_flow_error_set(error, EINVAL,
 					   RTE_FLOW_ERROR_TYPE_ITEM,
@@ -2439,6 +2711,74 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_VXLAN &&
 		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
 		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP_VXLAN_IPV4_OTHER;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP &&
+		flags_version != RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP &&
+		flags_version != RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP &&
+		flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL;
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP &&
+		flags_version == RTE_L2TPV2_MSG_TYPE_CONTROL &&
+		!ppp_present)
+		flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL;
+	/* Handle L2TPV2 with PPP and inner protocols */
+	else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 &&
+		ppp_present &&
+		inner_l3 != RTE_FLOW_ITEM_TYPE_END) {
+		/* L2TPV2 with inner IPv4/IPv6 */
+		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP) {
+			/* Outer IPv4 + inner protocol */
+			if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4;
+			} else if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6;
+			}
+		} else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP) {
+			/* Outer IPv6 + inner protocol */
+			if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4;
+			} else if (inner_l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+				if (inner_l4 == RTE_FLOW_ITEM_TYPE_TCP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_TCP;
+				else if (inner_l4 == RTE_FLOW_ITEM_TYPE_UDP)
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_UDP;
+				else
+					flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6;
+			}
+		}
+	} else if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_L2TPV2 && ppp_present &&
+		inner_l3 == RTE_FLOW_ITEM_TYPE_END) {
+		/* Handle L2TPV2 with PPP but no inner protocol specified */
+		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP)
+			flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP;
+		else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP)
+			flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP;
+	}
 
 	filter->tunnel_type = tunnel_type;
 	filter->input.flow_type = flow_type;
@@ -2482,9 +2822,10 @@ ice_fdir_parse(struct ice_adapter *ad,
 	input_set = filter->input_set_o | filter->input_set_i;
 	input_set = raw ? ~input_set : input_set;
 
-	if (!input_set || filter->input_set_o &
-	    ~(item->input_set_mask_o | ICE_INSET_ETHERTYPE) ||
-	    filter->input_set_i & ~item->input_set_mask_i) {
+	if (!input_set ||
+	    (filter->input_set_o &
+	     ~(item->input_set_mask_o | ICE_INSET_ETHERTYPE)) ||
+	    (filter->input_set_i & ~item->input_set_mask_i)) {
 		rte_flow_error_set(error, EINVAL,
 				   RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
 				   pattern,
diff --git a/drivers/net/intel/ice/ice_generic_flow.c b/drivers/net/intel/ice/ice_generic_flow.c
index 4049157eab..644958cccf 100644
--- a/drivers/net/intel/ice/ice_generic_flow.c
+++ b/drivers/net/intel/ice/ice_generic_flow.c
@@ -1794,6 +1794,166 @@ enum rte_flow_item_type pattern_eth_ipv6_pfcp[] = {
 	RTE_FLOW_ITEM_TYPE_PFCP,
 	RTE_FLOW_ITEM_TYPE_END,
 };
+enum rte_flow_item_type pattern_eth_ipv4_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+/* PPPoL2TPv2oUDP */
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_L2TPV2,
+	RTE_FLOW_ITEM_TYPE_PPP,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 
 typedef bool (*parse_engine_t)(struct ice_adapter *ad,
 			       struct rte_flow *flow,
@@ -2021,6 +2181,23 @@ static struct ice_ptype_match ice_ptype_map[] = {
 	{pattern_eth_ipv4_udp_esp,			ICE_MAC_IPV4_NAT_T_ESP},
 	{pattern_eth_ipv4_ah,				ICE_MAC_IPV4_AH},
 	{pattern_eth_ipv4_l2tp,				ICE_MAC_IPV4_L2TPV3},
+	{pattern_eth_ipv4_udp_l2tpv2,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6,		ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp,	ICE_MAC_IPV4_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6,		ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp,	ICE_MAC_IPV6_L2TPV2},
+	{pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp,	ICE_MAC_IPV6_L2TPV2},
+
 	{pattern_eth_ipv4_pfcp,				ICE_MAC_IPV4_PFCP_SESSION},
 	{pattern_eth_ipv6,				ICE_PTYPE_IPV6_PAY},
 	{pattern_eth_ipv6_udp,				ICE_PTYPE_IPV6_UDP_PAY},
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v7 6/7] net/ice: add L2TPv2 hardware packet generation
  2026-02-19 11:20   ` [PATCH v7 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                       ` (4 preceding siblings ...)
  2026-02-19 11:21     ` [PATCH v7 5/7] net/ice: add L2TPv2 flow pattern matching support Shaiq Wani
@ 2026-02-19 11:21     ` Shaiq Wani
  2026-02-19 11:21     ` [PATCH v7 7/7] net/ice: add L2TPv2 RSS hash support Shaiq Wani
  2026-02-19 16:52     ` [PATCH v7 0/7] Add support for L2TPV2 over UDP to ICE PMD Bruce Richardson
  7 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-19 11:21 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add L2TPv2 packet type cases to ice_fdir_get_gen_prgm_pkt() to enable
hardware packet generation for flow rule programming.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 drivers/net/intel/ice/base/ice_fdir.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/intel/ice/base/ice_fdir.c b/drivers/net/intel/ice/base/ice_fdir.c
index f62313c559..2c0cb99854 100644
--- a/drivers/net/intel/ice/base/ice_fdir.c
+++ b/drivers/net/intel/ice/base/ice_fdir.c
@@ -4027,6 +4027,9 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
 				   ICE_NONDMA_TO_NONDMA);
 			loc = &pkt[ICE_FDIR_V6_V4_GTPOGRE_EH_PKT_OFF];
 			break;
+		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL:
+		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2:
+		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP:
 		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4:
 		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP:
 		case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP:
@@ -4038,6 +4041,9 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
 						      idx, offset, tun);
 			loc = &pkt[pos];
 			break;
+		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_CONTROL:
+		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2:
+		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP:
 		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4:
 		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP:
 		case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP:
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v7 7/7] net/ice: add L2TPv2 RSS hash support
  2026-02-19 11:20   ` [PATCH v7 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                       ` (5 preceding siblings ...)
  2026-02-19 11:21     ` [PATCH v7 6/7] net/ice: add L2TPv2 hardware packet generation Shaiq Wani
@ 2026-02-19 11:21     ` Shaiq Wani
  2026-02-19 16:52     ` [PATCH v7 0/7] Add support for L2TPV2 over UDP to ICE PMD Bruce Richardson
  7 siblings, 0 replies; 56+ messages in thread
From: Shaiq Wani @ 2026-02-19 11:21 UTC (permalink / raw)
  To: dev, bruce.richardson, aman.deep.singh; +Cc: Song Jiale

Add RSS (Receive Side Scaling) hash support for L2TPv2 packets.
Add L2TPv2 over UDP support for ice PMD in the release notes.

Signed-off-by: Shaiq Wani <shaiq.wani@intel.com>
Tested-by: Song Jiale <songx.jiale@intel.com>
---
 doc/guides/rel_notes/release_26_03.rst |  4 ++++
 drivers/net/intel/ice/ice_hash.c       | 25 +++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/doc/guides/rel_notes/release_26_03.rst b/doc/guides/rel_notes/release_26_03.rst
index b4499ec066..8ae46e78e7 100644
--- a/doc/guides/rel_notes/release_26_03.rst
+++ b/doc/guides/rel_notes/release_26_03.rst
@@ -77,6 +77,10 @@ New Features
 
   * Added support for pre and post VF reset callbacks.
 
+* **Updated Intel ice driver.**
+
+  * Added rte_flow support for L2TPv2 over UDP.
+
 * **Updated Marvell cnxk net driver.**
 
   * Added out-of-place support for CN20K SoC.
diff --git a/drivers/net/intel/ice/ice_hash.c b/drivers/net/intel/ice/ice_hash.c
index afdc8f220a..b20103a452 100644
--- a/drivers/net/intel/ice/ice_hash.c
+++ b/drivers/net/intel/ice/ice_hash.c
@@ -305,6 +305,22 @@ struct ice_rss_hash_cfg eth_ipv4_l2tpv3_tmplt = {
 	0
 };
 
+struct ice_rss_hash_cfg eth_ipv4_l2tpv2_tmplt = {
+	ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
+	ICE_FLOW_SEG_HDR_L2TPV2,
+	ICE_FLOW_HASH_L2TPV2_SESS_ID,
+	ICE_RSS_OUTER_HEADERS,
+	0
+};
+
+struct ice_rss_hash_cfg eth_ipv6_l2tpv2_tmplt = {
+	ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_IPV_OTHER |
+	ICE_FLOW_SEG_HDR_L2TPV2,
+	ICE_FLOW_HASH_L2TPV2_SESS_ID,
+	ICE_RSS_OUTER_HEADERS,
+	0
+};
+
 struct ice_rss_hash_cfg eth_ipv4_pfcp_tmplt = {
 	ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
 	ICE_FLOW_SEG_HDR_PFCP_SESSION,
@@ -480,6 +496,8 @@ struct ice_rss_hash_cfg eth_tmplt = {
 #define ICE_RSS_TYPE_IPV6_AH		(RTE_ETH_RSS_AH | RTE_ETH_RSS_IPV6)
 #define ICE_RSS_TYPE_IPV4_L2TPV3	(RTE_ETH_RSS_L2TPV3 | RTE_ETH_RSS_IPV4)
 #define ICE_RSS_TYPE_IPV6_L2TPV3	(RTE_ETH_RSS_L2TPV3 | RTE_ETH_RSS_IPV6)
+#define ICE_RSS_TYPE_IPV4_L2TPV2	(RTE_ETH_RSS_L2TPV2 | RTE_ETH_RSS_IPV4)
+#define ICE_RSS_TYPE_IPV6_L2TPV2	(RTE_ETH_RSS_L2TPV2 | RTE_ETH_RSS_IPV6)
 #define ICE_RSS_TYPE_IPV4_PFCP		(RTE_ETH_RSS_PFCP | RTE_ETH_RSS_IPV4)
 #define ICE_RSS_TYPE_IPV6_PFCP		(RTE_ETH_RSS_PFCP | RTE_ETH_RSS_IPV6)
 
@@ -522,6 +540,8 @@ static struct ice_pattern_match_item ice_hash_pattern_list[] = {
 	{pattern_eth_ipv4_udp_esp,		ICE_RSS_TYPE_IPV4_ESP,		ICE_INSET_NONE,	&eth_ipv4_udp_esp_tmplt},
 	{pattern_eth_ipv4_ah,			ICE_RSS_TYPE_IPV4_AH,		ICE_INSET_NONE,	&eth_ipv4_ah_tmplt},
 	{pattern_eth_ipv4_l2tp,			ICE_RSS_TYPE_IPV4_L2TPV3,	ICE_INSET_NONE,	&eth_ipv4_l2tpv3_tmplt},
+	{pattern_eth_ipv4_l2tpv2,		ICE_RSS_TYPE_IPV4_L2TPV2,	ICE_INSET_NONE,	&eth_ipv4_l2tpv2_tmplt},
+	{pattern_eth_ipv6_l2tpv2,		ICE_RSS_TYPE_IPV6_L2TPV2,	ICE_INSET_NONE,	&eth_ipv6_l2tpv2_tmplt},
 	{pattern_eth_ipv4_pfcp,			ICE_RSS_TYPE_IPV4_PFCP,		ICE_INSET_NONE,	&eth_ipv4_pfcp_tmplt},
 	/* IPV6 */
 	{pattern_eth_ipv6,			ICE_RSS_TYPE_ETH_IPV6,		ICE_INSET_NONE,	&ipv6_tmplt},
@@ -925,6 +945,11 @@ ice_refine_hash_cfg_l234(struct ice_rss_hash_cfg *hash_cfg,
 			*hash_flds &= ~ICE_FLOW_HASH_L2TPV3_SESS_ID;
 	}
 
+	if (*addl_hdrs & ICE_FLOW_SEG_HDR_L2TPV2) {
+		if (!(rss_type & RTE_ETH_RSS_L2TPV2))
+			*hash_flds &= ~ICE_FLOW_HASH_L2TPV2_SESS_ID;
+	}
+
 	if (*addl_hdrs & ICE_FLOW_SEG_HDR_ESP) {
 		if (!(rss_type & RTE_ETH_RSS_ESP))
 			*hash_flds &= ~ICE_FLOW_HASH_ESP_SPI;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [PATCH v7 0/7] Add support for L2TPV2 over UDP to ICE PMD
  2026-02-19 11:20   ` [PATCH v7 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
                       ` (6 preceding siblings ...)
  2026-02-19 11:21     ` [PATCH v7 7/7] net/ice: add L2TPv2 RSS hash support Shaiq Wani
@ 2026-02-19 16:52     ` Bruce Richardson
  7 siblings, 0 replies; 56+ messages in thread
From: Bruce Richardson @ 2026-02-19 16:52 UTC (permalink / raw)
  To: Shaiq Wani; +Cc: dev, aman.deep.singh

On Thu, Feb 19, 2026 at 04:50:56PM +0530, Shaiq Wani wrote:
> This patchset enables L2TPv2 over UDP support in the ice PMD via rte_flow,
> allowing flow classification and RSS hashing for L2TPv2 traffic.
>   
> v7: removed FDIR in doc and commit log titles.
> 
> v6: split patch 3 into 2 separate patches.
> 
> v5: Resending v4 patches with correct cover letter and threading.
>   
> v4: *Version 3 patchset was incomplete due to a server reboot.
>     *V4 includes all patches for review.
>  
> v3: Fixed compilation issues.
> v2: Addressed AI generated comments.
> 
> 
Patchset applied to dpdk-next-net-intel,

Thanks,
/Bruce

^ permalink raw reply	[flat|nested] 56+ messages in thread

end of thread, other threads:[~2026-02-19 16:53 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-02  9:42 [PATCH 0/6] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
2025-08-26 16:26 ` [PATCH v3 0/7] " Shaiq Wani
2025-08-26 16:26   ` [PATCH v4 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
2025-08-26 16:26   ` [PATCH v4 2/7] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
2025-08-26 16:27   ` [PATCH v4 3/7] net/ice: add L2TPv2 protocol and field definitions Shaiq Wani
2025-08-26 16:27   ` [PATCH v4 4/7] net/ice: add L2TPv2 flow patterns and FDIR support Shaiq Wani
2025-08-26 16:27   ` [PATCH v4 5/7] net/ice: add L2TPv2 hardware packet generation Shaiq Wani
2025-08-26 16:27   ` [PATCH v4 6/7] net/ice: add L2TPv2 RSS hash support Shaiq Wani
2025-08-26 16:27   ` [PATCH v4 7/7] doc: update release notes Shaiq Wani
2025-08-26 17:05 ` [PATCH v5 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
2025-08-26 17:05   ` [PATCH v5 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
2025-08-26 17:05   ` [PATCH v5 2/7] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
2025-08-26 17:05   ` [PATCH v5 3/7] net/ice: add L2TPv2 protocol and field definitions Shaiq Wani
2026-02-17 17:09     ` Bruce Richardson
2025-08-26 17:05   ` [PATCH v5 4/7] net/ice: add L2TPv2 flow patterns and FDIR support Shaiq Wani
2025-08-26 17:05   ` [PATCH v5 5/7] net/ice: add L2TPv2 hardware packet generation Shaiq Wani
2025-08-26 17:05   ` [PATCH v5 6/7] net/ice: add L2TPv2 RSS hash support Shaiq Wani
2025-08-26 17:05   ` [PATCH v5 7/7] doc: update release notes Shaiq Wani
2026-02-02  9:42 ` [PATCH 1/6] net/ice: add L2TPv2 and PPP data structures Shaiq Wani
2026-02-18 16:37   ` [PATCH v6 0/8] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
2026-02-18 16:37     ` [PATCH v6 1/8] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
2026-02-18 16:37     ` [PATCH v6 2/8] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
2026-02-18 16:37     ` [PATCH v6 3/8] net/ice: rename protocol identifiers Shaiq Wani
2026-02-18 16:37     ` [PATCH v6 4/8] net/ice: add L2TPv2 protocol support Shaiq Wani
2026-02-18 16:37     ` [PATCH v6 5/8] net/ice: add L2TPv2 flow patterns and FDIR support Shaiq Wani
2026-02-18 16:37     ` [PATCH v6 6/8] net/ice: add L2TPv2 hardware packet generation Shaiq Wani
2026-02-18 16:37     ` [PATCH v6 7/8] net/ice: add L2TPv2 RSS hash support Shaiq Wani
2026-02-18 16:37     ` [PATCH v6 8/8] doc: update release notes Shaiq Wani
2026-02-19 11:20   ` [PATCH v7 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
2026-02-19 11:20     ` [PATCH v7 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
2026-02-19 11:20     ` [PATCH v7 2/7] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
2026-02-19 11:20     ` [PATCH v7 3/7] net/ice: rename protocol identifiers Shaiq Wani
2026-02-19 11:21     ` [PATCH v7 4/7] net/ice: add L2TPv2 protocol support Shaiq Wani
2026-02-19 11:21     ` [PATCH v7 5/7] net/ice: add L2TPv2 flow pattern matching support Shaiq Wani
2026-02-19 11:21     ` [PATCH v7 6/7] net/ice: add L2TPv2 hardware packet generation Shaiq Wani
2026-02-19 11:21     ` [PATCH v7 7/7] net/ice: add L2TPv2 RSS hash support Shaiq Wani
2026-02-19 16:52     ` [PATCH v7 0/7] Add support for L2TPV2 over UDP to ICE PMD Bruce Richardson
2026-02-02  9:42 ` [PATCH 2/6] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
2026-02-02  9:42 ` [PATCH 3/6] net/ice: add L2TPv2 protocol and field definitions Shaiq Wani
2026-02-02  9:42 ` [PATCH 4/6] net/ice: add L2TPv2 flow patterns and FDIR support Shaiq Wani
2026-02-02  9:42 ` [PATCH 5/6] net/ice: add L2TPv2 hardware packet generation Shaiq Wani
2026-02-02  9:42 ` [PATCH 6/6] net/ice: add L2TPv2 RSS hash support Shaiq Wani
2026-02-02 17:39   ` [REVIEW] " Stephen Hemminger
2026-02-09 11:56 ` [PATCH v2 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
2026-02-09 11:56   ` [PATCH v2 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
2026-02-09 11:56   ` [PATCH v2 2/7] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
2026-02-09 11:56   ` [PATCH v2 3/7] net/ice: add L2TPv2 protocol and field definitions Shaiq Wani
2026-02-09 11:56   ` [PATCH v2 4/7] net/ice: add L2TPv2 flow patterns and FDIR support Shaiq Wani
2026-02-09 11:56   ` [PATCH v2 5/7] net/ice: add L2TPv2 hardware packet generation Shaiq Wani
2026-02-09 11:56   ` [PATCH v2 6/7] net/ice: add L2TPv2 RSS hash support Shaiq Wani
2026-02-09 11:56   ` [PATCH v2 7/7] doc: update release notes Shaiq Wani
2026-02-11  6:09 ` [PATCH v3 0/7] Add support for L2TPV2 over UDP to ICE PMD Shaiq Wani
2026-02-11  6:09   ` [PATCH v3 1/7] net/ice: add L2TPv2 PPP and PPoE data structures Shaiq Wani
2026-02-11  6:09   ` [PATCH v3 2/7] net/ice: add L2TPv2 tunnel type definition Shaiq Wani
2026-02-11  6:09   ` [PATCH v3 3/7] net/ice: add L2TPv2 protocol and field definitions Shaiq Wani
2026-02-11  6:09   ` [PATCH v3 4/7] net/ice: add L2TPv2 flow patterns and FDIR support Shaiq Wani

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox