[v3,2/2] net/i40e: support FDIR for L2TPv3 over IP

Message ID 20200107153946.6876-2-rory.sexton@intel.com (mailing list archive)
State Changes Requested, archived
Delegated to: Ferruh Yigit
Headers
Series [v3,1/2] ethdev: add L2TPv3 over IP header to flow API |

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/travis-robot success Travis build: passed
ci/Intel-compilation fail Compilation issues

Commit Message

Sexton, Rory Jan. 7, 2020, 3:39 p.m. UTC
  Adding FDIR support for L2TPv3 over IP header matching and adding
a new customized pctype for l2tpv3 over IP.

Signed-off-by: Rory Sexton <rory.sexton@intel.com>
Signed-off-by: Dariusz Jagus <dariuszx.jagus@intel.com>
---
v3 changes:
* removing testpmd doc update as this patch focus only on i40e PMD
* remove unused structure from i40e_ethdev.h
---
 drivers/net/i40e/i40e_ethdev.c | 11 ++++++-
 drivers/net/i40e/i40e_ethdev.h | 43 +++++++++++++++++--------
 drivers/net/i40e/i40e_fdir.c   | 40 +++++++++++++++++++++---
 drivers/net/i40e/i40e_flow.c   | 57 ++++++++++++++++++++++++++++++++++
 4 files changed, 132 insertions(+), 19 deletions(-)
  

Comments

Ferruh Yigit Jan. 10, 2020, 6:27 p.m. UTC | #1
On 1/7/2020 3:39 PM, Rory Sexton wrote:
> Adding FDIR support for L2TPv3 over IP header matching and adding
> a new customized pctype for l2tpv3 over IP.
> 
> Signed-off-by: Rory Sexton <rory.sexton@intel.com>
> Signed-off-by: Dariusz Jagus <dariuszx.jagus@intel.com>
> ---
> v3 changes:
> * removing testpmd doc update as this patch focus only on i40e PMD
> * remove unused structure from i40e_ethdev.h

Hi Beilei,

Is this version good to go?

Thanks,
ferruh
  
Xing, Beilei Jan. 13, 2020, 3:22 a.m. UTC | #2
> -----Original Message-----
> From: Sexton, Rory
> Sent: Tuesday, January 7, 2020 11:40 PM
> To: dev@dpdk.org; Zhang, Qi Z <qi.z.zhang@intel.com>; Xing, Beilei
> <beilei.xing@intel.com>; adrien.mazarguil@6wind.com; orika@mellanox.com
> Cc: Sexton, Rory <rory.sexton@intel.com>; Jagus, DariuszX
> <dariuszx.jagus@intel.com>
> Subject: [PATCH v3 2/2] net/i40e: support FDIR for L2TPv3 over IP
> 
> Adding FDIR support for L2TPv3 over IP header matching and adding a new
> customized pctype for l2tpv3 over IP.
> 
> Signed-off-by: Rory Sexton <rory.sexton@intel.com>
> Signed-off-by: Dariusz Jagus <dariuszx.jagus@intel.com>

Acked-by: Beilei Xing <beilei.xing@intel.com>
  
Xing, Beilei Jan. 13, 2020, 8:07 a.m. UTC | #3
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Xing, Beilei
> Sent: Monday, January 13, 2020 11:22 AM
> To: Sexton, Rory <rory.sexton@intel.com>; dev@dpdk.org; Zhang, Qi Z
> <qi.z.zhang@intel.com>; adrien.mazarguil@6wind.com; orika@mellanox.com
> Cc: Jagus, DariuszX <dariuszx.jagus@intel.com>
> Subject: Re: [dpdk-dev] [PATCH v3 2/2] net/i40e: support FDIR for L2TPv3 over
> IP
> 
> 
> 
> > -----Original Message-----
> > From: Sexton, Rory
> > Sent: Tuesday, January 7, 2020 11:40 PM
> > To: dev@dpdk.org; Zhang, Qi Z <qi.z.zhang@intel.com>; Xing, Beilei
> > <beilei.xing@intel.com>; adrien.mazarguil@6wind.com;
> > orika@mellanox.com
> > Cc: Sexton, Rory <rory.sexton@intel.com>; Jagus, DariuszX
> > <dariuszx.jagus@intel.com>
> > Subject: [PATCH v3 2/2] net/i40e: support FDIR for L2TPv3 over IP
> >
> > Adding FDIR support for L2TPv3 over IP header matching and adding a
> > new customized pctype for l2tpv3 over IP.
> >
> > Signed-off-by: Rory Sexton <rory.sexton@intel.com>
> > Signed-off-by: Dariusz Jagus <dariuszx.jagus@intel.com>
> 
> Acked-by: Beilei Xing <beilei.xing@intel.com>

Sorry, NACK the patch since there's compilation issue with clang and coding style issue.
Please check http://mails.dpdk.org/archives/test-report/2020-January/112422.html and http://mails.dpdk.org/archives/test-report/2020-January/112412.html
BTW, Doc update is needed in release notes, please also describe what's the supported input set for the new PCTYPE.

Beilei
  
Sexton, Rory Jan. 13, 2020, 10:42 a.m. UTC | #4
Hi Beilei,

PSB

Regards,
Rory

> 
> Sorry, NACK the patch since there's compilation issue with clang and coding style issue.
> Please check http://mails.dpdk.org/archives/test-report/2020-January/112422.html and http://mails.dpdk.org/archives/test-report/2020-January/112412.html
> BTW, Doc update is needed in release notes, please also describe what's the supported input set for the new PCTYPE.
> 
> Beilei
> 

The compilation issue is because for some reason patch 1/2 of this patch-set which affects rte_flow api was not applied before compiling this patch with DPDK test framework.
http://mails.dpdk.org/archives/test-report/2020-January/112422.html
The errors in above would have been avoided if the first patch of this patch-set had been applied before this 2/2 patch. Not sure why this happened.
I've confirmed manually that there are no issues with clang compilation when first patch of set is applied correctly.

As regards coding style issue (http://mails.dpdk.org/archives/test-report/2020-January/112412.html).
CHECK:ASSIGNMENT_CONTINUATIONS: Assignment operator '=' should be on the previous line
#343: FILE: drivers/net/i40e/i40e_flow.c:3059:
+				filter->input.flow.ip4_l2tpv3oip_flow.session_id
+					= l2tpv3oip_spec->session_id;

If the '=' operator is moved to previous line then the line will exceed 80 characters. There are similar cases earlier in this same file which I followed to keep code consistent throughout.
Please advise which style you prefer to be used, line exceeding 80 chars or '=' operator on 2nd line.
See an earlier example for this case in same file, drivers/net/i40e/i40e_flow.c:2900, which I used as example for how to base coding style for such case:
                                                          filter->input.flow.sctp4_flow.verify_tag
                                                                       = sctp_spec->hdr.tag;

I will do DOC update for release notes separately and describe the supported input set for new PCTYPE there.
  

Patch

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 5999c964b..80a46916c 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -12351,6 +12351,14 @@  i40e_update_customized_pctype(struct rte_eth_dev *dev, uint8_t *pkg,
 			new_pctype =
 				i40e_find_customized_pctype(pf,
 						      I40E_CUSTOMIZED_GTPU);
+		else if (!strcmp(name, "IPV4_L2TPV3"))
+			new_pctype =
+				i40e_find_customized_pctype(pf,
+						I40E_CUSTOMIZED_IPV4_L2TPV3);
+		else if (!strcmp(name, "IPV6_L2TPV3"))
+			new_pctype =
+				i40e_find_customized_pctype(pf,
+						I40E_CUSTOMIZED_IPV6_L2TPV3);
 		if (new_pctype) {
 			if (op == RTE_PMD_I40E_PKG_OP_WR_ADD) {
 				new_pctype->pctype = pctype_value;
@@ -12544,7 +12552,8 @@  i40e_update_customized_ptype(struct rte_eth_dev *dev, uint8_t *pkg,
 						RTE_PTYPE_TUNNEL_GRENAT;
 					in_tunnel = true;
 				} else if (!strncasecmp(name, "L2TPV2CTL", 9) ||
-					   !strncasecmp(name, "L2TPV2", 6)) {
+					   !strncasecmp(name, "L2TPV2", 6) ||
+					   !strncasecmp(name, "L2TPV3", 6)) {
 					ptype_mapping[i].sw_ptype |=
 						RTE_PTYPE_TUNNEL_L2TP;
 					in_tunnel = true;
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 295ad593b..bba2b83b4 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -508,24 +508,38 @@  struct i40e_raw_flow {
 	uint32_t length;
 };
 
+/* A structure used to define the input for L2TPv3 over IPv4 flow */
+struct i40e_ipv4_l2tpv3oip_flow {
+	struct rte_eth_ipv4_flow ip4;
+	uint32_t session_id; /* Session ID in big endian. */
+};
+
+/* A structure used to define the input for L2TPv3 over IPv6 flow */
+struct i40e_ipv6_l2tpv3oip_flow {
+	struct rte_eth_ipv6_flow ip6;
+	uint32_t session_id; /* Session ID in big endian. */
+};
+
 /*
  * A union contains the inputs for all types of flow
  * items in flows need to be in big endian
  */
 union i40e_fdir_flow {
-	struct rte_eth_l2_flow     l2_flow;
-	struct rte_eth_udpv4_flow  udp4_flow;
-	struct rte_eth_tcpv4_flow  tcp4_flow;
-	struct rte_eth_sctpv4_flow sctp4_flow;
-	struct rte_eth_ipv4_flow   ip4_flow;
-	struct rte_eth_udpv6_flow  udp6_flow;
-	struct rte_eth_tcpv6_flow  tcp6_flow;
-	struct rte_eth_sctpv6_flow sctp6_flow;
-	struct rte_eth_ipv6_flow   ipv6_flow;
-	struct i40e_gtp_flow       gtp_flow;
-	struct i40e_gtp_ipv4_flow  gtp_ipv4_flow;
-	struct i40e_gtp_ipv6_flow  gtp_ipv6_flow;
-	struct i40e_raw_flow       raw_flow;
+	struct rte_eth_l2_flow          l2_flow;
+	struct rte_eth_udpv4_flow       udp4_flow;
+	struct rte_eth_tcpv4_flow       tcp4_flow;
+	struct rte_eth_sctpv4_flow      sctp4_flow;
+	struct rte_eth_ipv4_flow        ip4_flow;
+	struct rte_eth_udpv6_flow       udp6_flow;
+	struct rte_eth_tcpv6_flow       tcp6_flow;
+	struct rte_eth_sctpv6_flow      sctp6_flow;
+	struct rte_eth_ipv6_flow        ipv6_flow;
+	struct i40e_gtp_flow            gtp_flow;
+	struct i40e_gtp_ipv4_flow       gtp_ipv4_flow;
+	struct i40e_gtp_ipv6_flow       gtp_ipv6_flow;
+	struct i40e_raw_flow            raw_flow;
+	struct i40e_ipv4_l2tpv3oip_flow ip4_l2tpv3oip_flow;
+	struct i40e_ipv6_l2tpv3oip_flow ip6_l2tpv3oip_flow;
 };
 
 enum i40e_fdir_ip_type {
@@ -542,6 +556,7 @@  struct i40e_fdir_flow_ext {
 	uint16_t dst_id; /* VF ID, available when is_vf is 1*/
 	bool inner_ip;   /* If there is inner ip */
 	enum i40e_fdir_ip_type iip_type; /* ip type for inner ip */
+	enum i40e_fdir_ip_type oip_type; /* ip type for outer ip */
 	bool customized_pctype; /* If customized pctype is used */
 	bool pkt_template; /* If raw packet template is used */
 };
@@ -897,6 +912,8 @@  enum i40e_new_pctype {
 	I40E_CUSTOMIZED_GTPU_IPV4,
 	I40E_CUSTOMIZED_GTPU_IPV6,
 	I40E_CUSTOMIZED_GTPU,
+	I40E_CUSTOMIZED_IPV4_L2TPV3,
+	I40E_CUSTOMIZED_IPV6_L2TPV3,
 	I40E_CUSTOMIZED_MAX,
 };
 
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index dee007daa..2fc099517 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -33,6 +33,10 @@ 
 #define IPV6_ADDR_LEN              16
 #endif
 
+#ifndef IPPROTO_L2TP
+#define IPPROTO_L2TP		  115
+#endif
+
 #define I40E_FDIR_PKT_LEN                   512
 #define I40E_FDIR_IP_DEFAULT_LEN            420
 #define I40E_FDIR_IP_DEFAULT_TTL            0x40
@@ -1026,7 +1030,12 @@  i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf,
 		 pctype == I40E_FILTER_PCTYPE_NONF_IPV4_SCTP ||
 		 pctype == I40E_FILTER_PCTYPE_NONF_IPV4_OTHER ||
 		 pctype == I40E_FILTER_PCTYPE_FRAG_IPV4 ||
-		 is_customized_pctype) {
+		 ((is_customized_pctype) &&
+		  ((cus_pctype->index == I40E_CUSTOMIZED_GTPC) ||
+		   (cus_pctype->index == I40E_CUSTOMIZED_GTPU_IPV4) ||
+		   (cus_pctype->index == I40E_CUSTOMIZED_GTPU_IPV6) ||
+		   (cus_pctype->index == I40E_CUSTOMIZED_GTPU) ||
+		   (cus_pctype->index == I40E_CUSTOMIZED_IPV4_L2TPV3)))) {
 		ip = (struct rte_ipv4_hdr *)raw_pkt;
 
 		*ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
@@ -1054,12 +1063,16 @@  i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf,
 			 cus_pctype->index == I40E_CUSTOMIZED_GTPU_IPV6 ||
 			 cus_pctype->index == I40E_CUSTOMIZED_GTPU)
 			ip->next_proto_id = IPPROTO_UDP;
+		else if (cus_pctype->index == I40E_CUSTOMIZED_IPV4_L2TPV3)
+			ip->next_proto_id = IPPROTO_L2TP;
 		len += sizeof(struct rte_ipv4_hdr);
 	} else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV6_TCP ||
 		   pctype == I40E_FILTER_PCTYPE_NONF_IPV6_UDP ||
 		   pctype == I40E_FILTER_PCTYPE_NONF_IPV6_SCTP ||
 		   pctype == I40E_FILTER_PCTYPE_NONF_IPV6_OTHER ||
-		   pctype == I40E_FILTER_PCTYPE_FRAG_IPV6) {
+		   pctype == I40E_FILTER_PCTYPE_FRAG_IPV6 ||
+		   ((is_customized_pctype) &&
+		    (cus_pctype->index == I40E_CUSTOMIZED_IPV6_L2TPV3))) {
 		ip6 = (struct rte_ipv6_hdr *)raw_pkt;
 
 		*ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
@@ -1069,9 +1082,12 @@  i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf,
 					  I40E_FDIR_IPv6_TC_OFFSET));
 		ip6->payload_len =
 			rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN);
-		ip6->proto = fdir_input->flow.ipv6_flow.proto ?
-			fdir_input->flow.ipv6_flow.proto :
-			next_proto[fdir_input->pctype];
+		if (!is_customized_pctype)
+			ip6->proto = fdir_input->flow.ipv6_flow.proto ?
+				fdir_input->flow.ipv6_flow.proto :
+				next_proto[fdir_input->pctype];
+		else if (cus_pctype->index == I40E_CUSTOMIZED_IPV6_L2TPV3)
+			ip6->proto = IPPROTO_L2TP;
 		ip6->hop_limits = fdir_input->flow.ipv6_flow.hop_limits ?
 			fdir_input->flow.ipv6_flow.hop_limits :
 			I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS;
@@ -1115,6 +1131,7 @@  i40e_flow_fdir_construct_pkt(struct i40e_pf *pf,
 	struct rte_flow_item_gtp *gtp;
 	struct rte_ipv4_hdr *gtp_ipv4;
 	struct rte_ipv6_hdr *gtp_ipv6;
+	struct rte_flow_item_l2tpv3oip *l2tpv3oip;
 	uint8_t size, dst = 0;
 	uint8_t i, pit_idx, set_idx = I40E_FLXPLD_L4_IDX; /* use l4 by default*/
 	int len;
@@ -1285,6 +1302,19 @@  i40e_flow_fdir_construct_pkt(struct i40e_pf *pf,
 			} else
 				payload = (unsigned char *)gtp +
 					sizeof(struct rte_flow_item_gtp);
+		} else if (cus_pctype->index == I40E_CUSTOMIZED_IPV4_L2TPV3 ||
+			   cus_pctype->index == I40E_CUSTOMIZED_IPV6_L2TPV3) {
+			l2tpv3oip = (struct rte_flow_item_l2tpv3oip *)(raw_pkt
+								       + len);
+
+			if (cus_pctype->index == I40E_CUSTOMIZED_IPV4_L2TPV3)
+				l2tpv3oip->session_id =
+				 fdir_input->flow.ip4_l2tpv3oip_flow.session_id;
+			else
+				l2tpv3oip->session_id =
+				 fdir_input->flow.ip6_l2tpv3oip_flow.session_id;
+			payload = (unsigned char *)l2tpv3oip +
+				sizeof(struct rte_flow_item_l2tpv3oip);
 		}
 	} else {
 		PMD_DRV_LOG(ERR, "unknown pctype %u.",
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 61021037c..9cb28532e 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -1615,6 +1615,20 @@  static enum rte_flow_item_type pattern_qinq_1[] = {
 	RTE_FLOW_ITEM_TYPE_END,
 };
 
+static enum rte_flow_item_type pattern_fdir_ipv4_l2tpv3oip[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_L2TPV3OIP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_fdir_ipv6_l2tpv3oip[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_L2TPV3OIP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* Ethertype */
 	{ pattern_ethertype, i40e_flow_parse_ethertype_filter },
@@ -1795,6 +1809,9 @@  static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	{ pattern_fdir_ipv6_gtpu, i40e_flow_parse_gtp_filter },
 	/* QINQ */
 	{ pattern_qinq_1, i40e_flow_parse_qinq_filter },
+	/* L2TPv3 over IP */
+	{ pattern_fdir_ipv4_l2tpv3oip, i40e_flow_parse_fdir_filter },
+	{ pattern_fdir_ipv6_l2tpv3oip, i40e_flow_parse_fdir_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -2420,6 +2437,15 @@  i40e_flow_fdir_get_pctype_value(struct i40e_pf *pf,
 			cus_pctype = i40e_find_customized_pctype(pf,
 						 I40E_CUSTOMIZED_GTPU_IPV6);
 		break;
+	case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
+		if (filter->input.flow_ext.oip_type == I40E_FDIR_IPTYPE_IPV4)
+			cus_pctype = i40e_find_customized_pctype(pf,
+						I40E_CUSTOMIZED_IPV4_L2TPV3);
+		else if (filter->input.flow_ext.oip_type ==
+			 I40E_FDIR_IPTYPE_IPV6)
+			cus_pctype = i40e_find_customized_pctype(pf,
+						I40E_CUSTOMIZED_IPV6_L2TPV3);
+		break;
 	default:
 		PMD_DRV_LOG(ERR, "Unsupported item type");
 		break;
@@ -2461,6 +2487,7 @@  i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 	const struct rte_flow_item_gtp *gtp_spec, *gtp_mask;
 	const struct rte_flow_item_raw *raw_spec, *raw_mask;
 	const struct rte_flow_item_vf *vf_spec;
+	const struct rte_flow_item_l2tpv3oip *l2tpv3oip_spec, *l2tpv3oip_mask;
 
 	uint8_t pctype = 0;
 	uint64_t input_set = I40E_INSET_NONE;
@@ -3012,6 +3039,36 @@  i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 				return -rte_errno;
 			}
 			break;
+		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
+			l2tpv3oip_spec = item->spec;
+			l2tpv3oip_mask = item->mask;
+
+			if (!l2tpv3oip_spec || !l2tpv3oip_mask)
+				break;
+
+			if (l2tpv3oip_mask->session_id != UINT32_MAX) {
+				rte_flow_error_set(error, EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM,
+					item,
+					"Invalid L2TPv3 mask");
+				return -rte_errno;
+			}
+
+			if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+				filter->input.flow.ip4_l2tpv3oip_flow.session_id
+					= l2tpv3oip_spec->session_id;
+				filter->input.flow_ext.oip_type =
+					I40E_FDIR_IPTYPE_IPV4;
+			} else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+				filter->input.flow.ip6_l2tpv3oip_flow.session_id
+					= l2tpv3oip_spec->session_id;
+				filter->input.flow_ext.oip_type =
+					I40E_FDIR_IPTYPE_IPV6;
+			}
+
+			filter->input.flow_ext.customized_pctype = true;
+			cus_proto = item_type;
+			break;
 		default:
 			break;
 		}