[v2,6/6] net/iavf: support L2TPv2 for AVF FDIR

Message ID 20220126063016.2384393-7-jie1x.wang@intel.com (mailing list archive)
State Changes Requested, archived
Delegated to: Ferruh Yigit
Headers
Series support L2TPv2 for AVF RSS hash and FDIR |

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel-compilation success Compilation OK
ci/intel-Testing success Testing PASS

Commit Message

Jie Wang Jan. 26, 2022, 6:30 a.m. UTC
  Add support for L2TPv2(include PPP over L2TPv2) protocols FDIR
based on outer MAC src address and L2TPv2 session ID.

Add support for PPPoL2TPv2oUDP protocols FDIR based on inner IP
src/dst address and UDP/TCP src/dst port.

Patterns are listed below:
eth/ipv4(6)/udp/l2tpv2
eth/ipv4(6)/udp/l2tpv2/ppp

eth/ipv4(6)/udp/l2tpv2/ppp/ipv4(6)
eth/ipv4(6)/udp/l2tpv2/ppp/ipv4(6)/udp
eth/ipv4(6)/udp/l2tpv2/ppp/ipv4(6)/tcp

Signed-off-by: Jie Wang <jie1x.wang@intel.com>
---
 doc/guides/rel_notes/release_22_03.rst |   8 +-
 drivers/net/iavf/iavf_fdir.c           | 174 +++++++++++++++++++++----
 drivers/net/iavf/iavf_generic_flow.h   |   4 +
 3 files changed, 156 insertions(+), 30 deletions(-)
  

Patch

diff --git a/doc/guides/rel_notes/release_22_03.rst b/doc/guides/rel_notes/release_22_03.rst
index 0d1e4a0b61..5a73ccc14e 100644
--- a/doc/guides/rel_notes/release_22_03.rst
+++ b/doc/guides/rel_notes/release_22_03.rst
@@ -66,8 +66,12 @@  New Features
 
 * **Updated Intel iavf driver.**
 
-  Added L2TPv2(include PPP over L2TPv2) RSS hash distribute packets
-  based on outer MAC src address and L2TPv2 session ID.
+  * Added L2TPv2(include PPP over L2TPv2) RSS hash distribute packets
+    based on outer MAC src address and L2TPv2 session ID.
+  * Added L2TPv2(include PPP over L2TPv2) FDIR distribute packets
+    based on outer MAC src address and L2TPv2 session ID.
+  * Added PPPoL2TPv2oUDP FDIR distribute packets based on inner IP
+    src/dst address and UDP/TCP src/dst port.
 
 
 Removed Items
diff --git a/drivers/net/iavf/iavf_fdir.c b/drivers/net/iavf/iavf_fdir.c
index b63aaca91d..2583b899aa 100644
--- a/drivers/net/iavf/iavf_fdir.c
+++ b/drivers/net/iavf/iavf_fdir.c
@@ -168,6 +168,31 @@ 
 	IAVF_FDIR_INSET_GRE_IPV6 | IAVF_INSET_TUN_UDP_SRC_PORT | \
 	IAVF_INSET_TUN_UDP_DST_PORT)
 
+#define IAVF_FDIR_INSET_L2TPV2 (\
+	IAVF_INSET_SMAC | IAVF_INSET_L2TPV2)
+
+#define IAVF_FDIR_INSET_L2TPV2_PPP_IPV4 (\
+	IAVF_INSET_TUN_IPV4_SRC | IAVF_INSET_TUN_IPV4_DST)
+
+#define IAVF_FDIR_INSET_L2TPV2_PPP_IPV4_UDP (\
+	IAVF_FDIR_INSET_L2TPV2_PPP_IPV4 | IAVF_INSET_TUN_UDP_SRC_PORT | \
+	IAVF_INSET_TUN_UDP_DST_PORT)
+
+#define IAVF_FDIR_INSET_L2TPV2_PPP_IPV4_TCP (\
+	IAVF_FDIR_INSET_L2TPV2_PPP_IPV4 | IAVF_INSET_TUN_TCP_SRC_PORT | \
+	IAVF_INSET_TUN_TCP_DST_PORT)
+
+#define IAVF_FDIR_INSET_L2TPV2_PPP_IPV6 (\
+	IAVF_INSET_TUN_IPV6_SRC | IAVF_INSET_TUN_IPV6_DST)
+
+#define IAVF_FDIR_INSET_L2TPV2_PPP_IPV6_UDP (\
+	IAVF_FDIR_INSET_L2TPV2_PPP_IPV6 | IAVF_INSET_TUN_UDP_SRC_PORT | \
+	IAVF_INSET_TUN_UDP_DST_PORT)
+
+#define IAVF_FDIR_INSET_L2TPV2_PPP_IPV6_TCP (\
+	IAVF_FDIR_INSET_L2TPV2_PPP_IPV6 | IAVF_INSET_TUN_TCP_SRC_PORT | \
+	IAVF_INSET_TUN_TCP_DST_PORT)
+
 static struct iavf_pattern_match_item iavf_fdir_pattern[] = {
 	{iavf_pattern_ethertype,		 IAVF_FDIR_INSET_ETH,		IAVF_INSET_NONE},
 	{iavf_pattern_eth_ipv4,			 IAVF_FDIR_INSET_ETH_IPV4,	IAVF_INSET_NONE},
@@ -275,6 +300,28 @@  static struct iavf_pattern_match_item iavf_fdir_pattern[] = {
 	{iavf_pattern_eth_ipv6_gre_ipv6,	IAVF_FDIR_INSET_GRE_IPV6,	IAVF_INSET_NONE},
 	{iavf_pattern_eth_ipv6_gre_ipv6_tcp,	IAVF_FDIR_INSET_GRE_IPV6_TCP,	IAVF_INSET_NONE},
 	{iavf_pattern_eth_ipv6_gre_ipv6_udp,	IAVF_FDIR_INSET_GRE_IPV6_UDP,	IAVF_INSET_NONE},
+
+	{iavf_pattern_eth_ipv4_udp_l2tpv2,		IAVF_FDIR_INSET_L2TPV2,			IAVF_INSET_NONE},
+	{iavf_pattern_eth_ipv4_udp_l2tpv2_ppp,		IAVF_FDIR_INSET_L2TPV2,			IAVF_INSET_NONE},
+
+	{iavf_pattern_eth_ipv6_udp_l2tpv2,		IAVF_FDIR_INSET_L2TPV2,			IAVF_INSET_NONE},
+	{iavf_pattern_eth_ipv6_udp_l2tpv2_ppp,		IAVF_FDIR_INSET_L2TPV2,			IAVF_INSET_NONE},
+
+	{iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4,	IAVF_FDIR_INSET_L2TPV2_PPP_IPV4,	IAVF_INSET_NONE},
+	{iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp,	IAVF_FDIR_INSET_L2TPV2_PPP_IPV4_UDP,	IAVF_INSET_NONE},
+	{iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp,	IAVF_FDIR_INSET_L2TPV2_PPP_IPV4_TCP,	IAVF_INSET_NONE},
+
+	{iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4,	IAVF_FDIR_INSET_L2TPV2_PPP_IPV4,	IAVF_INSET_NONE},
+	{iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp,	IAVF_FDIR_INSET_L2TPV2_PPP_IPV4_UDP,	IAVF_INSET_NONE},
+	{iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp,	IAVF_FDIR_INSET_L2TPV2_PPP_IPV4_TCP,	IAVF_INSET_NONE},
+
+	{iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6,	IAVF_FDIR_INSET_L2TPV2_PPP_IPV6,	IAVF_INSET_NONE},
+	{iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp,	IAVF_FDIR_INSET_L2TPV2_PPP_IPV6_UDP,	IAVF_INSET_NONE},
+	{iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp,	IAVF_FDIR_INSET_L2TPV2_PPP_IPV6_TCP,	IAVF_INSET_NONE},
+
+	{iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6,	IAVF_FDIR_INSET_L2TPV2_PPP_IPV6,	IAVF_INSET_NONE},
+	{iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp,	IAVF_FDIR_INSET_L2TPV2_PPP_IPV6_UDP,	IAVF_INSET_NONE},
+	{iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp,	IAVF_FDIR_INSET_L2TPV2_PPP_IPV6_TCP,	IAVF_INSET_NONE},
 };
 
 static struct iavf_flow_parser iavf_fdir_parser;
@@ -694,6 +741,8 @@  iavf_fdir_parse_pattern(__rte_unused struct iavf_adapter *ad,
 	const struct rte_flow_item_pfcp *pfcp_spec, *pfcp_mask;
 	const struct rte_flow_item_ecpri *ecpri_spec, *ecpri_mask;
 	const struct rte_flow_item_gre *gre_spec, *gre_mask;
+	const struct rte_flow_item_l2tpv2 *l2tpv2_spec, *l2tpv2_mask;
+	const struct rte_flow_item_ppp *ppp_spec, *ppp_mask;
 	const struct rte_flow_item *item = pattern;
 	struct virtchnl_proto_hdr *hdr, *hdr1 = NULL;
 	struct rte_ecpri_common_hdr ecpri_common;
@@ -701,7 +750,7 @@  iavf_fdir_parse_pattern(__rte_unused struct iavf_adapter *ad,
 	enum rte_flow_item_type item_type;
 	enum rte_flow_item_type next_type;
 	uint8_t tun_inner = 0;
-	uint16_t ether_type;
+	uint16_t ether_type, flags_version;
 	int layer = 0;
 
 	uint8_t  ipv6_addr_mask[16] = {
@@ -739,37 +788,41 @@  iavf_fdir_parse_pattern(__rte_unused struct iavf_adapter *ad,
 			}
 
 			if (eth_spec && eth_mask) {
-				if (!rte_is_zero_ether_addr(&eth_mask->src) ||
-				    !rte_is_zero_ether_addr(&eth_mask->dst)) {
-					rte_flow_error_set(error, EINVAL,
-						RTE_FLOW_ERROR_TYPE_ITEM, item,
-						"Invalid MAC_addr mask.");
-					return -rte_errno;
-				}
-			}
-
-			if (eth_spec && eth_mask && eth_mask->type) {
-				if (eth_mask->type != RTE_BE16(0xffff)) {
-					rte_flow_error_set(error, EINVAL,
-						RTE_FLOW_ERROR_TYPE_ITEM,
-						item, "Invalid type mask.");
-					return -rte_errno;
+				if (!rte_is_zero_ether_addr(&eth_mask->dst)) {
+					input_set |= IAVF_INSET_DMAC;
+					VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr1,
+									ETH,
+									DST);
+				} else if (!rte_is_zero_ether_addr(&eth_mask->src)) {
+					input_set |= IAVF_INSET_SMAC;
+					VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr1,
+									ETH,
+									SRC);
 				}
 
-				ether_type = rte_be_to_cpu_16(eth_spec->type);
-				if (ether_type == RTE_ETHER_TYPE_IPV4 ||
-					ether_type == RTE_ETHER_TYPE_IPV6) {
-					rte_flow_error_set(error, EINVAL,
-						RTE_FLOW_ERROR_TYPE_ITEM,
-						item,
-						"Unsupported ether_type.");
-					return -rte_errno;
+				if (eth_mask->type) {
+					if (eth_mask->type != RTE_BE16(0xffff)) {
+						rte_flow_error_set(error, EINVAL,
+							RTE_FLOW_ERROR_TYPE_ITEM,
+							item, "Invalid type mask.");
+						return -rte_errno;
+					}
+
+					ether_type = rte_be_to_cpu_16(eth_spec->type);
+					if (ether_type == RTE_ETHER_TYPE_IPV4 ||
+						ether_type == RTE_ETHER_TYPE_IPV6) {
+						rte_flow_error_set(error, EINVAL,
+							RTE_FLOW_ERROR_TYPE_ITEM,
+							item,
+							"Unsupported ether_type.");
+						return -rte_errno;
+					}
+
+					input_set |= IAVF_INSET_ETHERTYPE;
+					VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr1, ETH,
+									ETHERTYPE);
 				}
 
-				input_set |= IAVF_INSET_ETHERTYPE;
-				VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr1, ETH,
-								 ETHERTYPE);
-
 				rte_memcpy(hdr1->buffer, eth_spec,
 					   sizeof(struct rte_ether_hdr));
 			}
@@ -1319,6 +1372,71 @@  iavf_fdir_parse_pattern(__rte_unused struct iavf_adapter *ad,
 			hdrs->count = ++layer;
 			break;
 
+		case RTE_FLOW_ITEM_TYPE_L2TPV2:
+			l2tpv2_spec = item->spec;
+			l2tpv2_mask = item->mask;
+
+			hdr = &hdrs->proto_hdr[layer];
+
+			VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, L2TPV2);
+
+			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 |= IAVF_L2TPV2_SESSION_ID;
+					if (flags_version & IAVF_L2TPV2_FLAGS_LEN)
+						VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr,
+								L2TPV2,
+								LEN_SESS_ID);
+					else
+						VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr,
+								L2TPV2,
+								SESS_ID);
+				}
+
+				rte_memcpy(hdr->buffer, l2tpv2_spec,
+					   sizeof(*l2tpv2_spec));
+			}
+
+			tun_inner = 1;
+
+			hdrs->count = ++layer;
+			break;
+
+		case RTE_FLOW_ITEM_TYPE_PPP:
+			ppp_spec = item->spec;
+			ppp_mask = item->mask;
+
+			hdr = &hdrs->proto_hdr[layer];
+
+			VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, PPP);
+
+			if (ppp_spec && ppp_mask) {
+				rte_memcpy(hdr->buffer, ppp_spec,
+					   sizeof(*ppp_spec));
+			}
+
+			hdrs->count = ++layer;
+			break;
+
 		case RTE_FLOW_ITEM_TYPE_VOID:
 			break;
 
diff --git a/drivers/net/iavf/iavf_generic_flow.h b/drivers/net/iavf/iavf_generic_flow.h
index 107bbc1a23..f6af176073 100644
--- a/drivers/net/iavf/iavf_generic_flow.h
+++ b/drivers/net/iavf/iavf_generic_flow.h
@@ -35,6 +35,7 @@ 
 #define IAVF_PROT_L2TPV3OIP	    (1ULL << 24)
 #define IAVF_PROT_PFCP		    (1ULL << 25)
 #define IAVF_PROT_ECPRI		    (1ULL << 26)
+#define IAVF_PROT_L2TPV2	    (1ULL << 27)
 
 
 /* field */
@@ -62,6 +63,7 @@ 
 #define IAVF_PFCP_SEID		    (1ULL << 43)
 #define IAVF_ECPRI_PC_RTC_ID	    (1ULL << 42)
 #define IAVF_IP_PKID		    (1ULL << 41)
+#define IAVF_L2TPV2_SESSION_ID	    (1ULL << 40)
 
 /* input set */
 
@@ -175,6 +177,8 @@ 
 	(IAVF_PROT_PFCP | IAVF_PFCP_S_FIELD | IAVF_PFCP_SEID)
 #define IAVF_INSET_ECPRI \
 	(IAVF_PROT_ECPRI | IAVF_ECPRI_PC_RTC_ID)
+#define IAVF_INSET_L2TPV2 \
+	(IAVF_PROT_L2TPV2 | IAVF_L2TPV2_SESSION_ID)
 
 /* empty pattern */
 extern enum rte_flow_item_type iavf_pattern_empty[];