[dpdk-dev] [PATCH v2 2/2] net/i40e: support FDIR for L2TPv3 over IP

Xing, Beilei beilei.xing at intel.com
Wed Dec 25 04:12:11 CET 2019



> -----Original Message-----
> From: Sexton, Rory
> Sent: Monday, December 16, 2019 6:15 PM
> To: dev at dpdk.org; orika at mellanox.com; adrien.mazarguil at 6wind.com; Xing,
> Beilei <beilei.xing at intel.com>; Zhang, Qi Z <qi.z.zhang at intel.com>
> Cc: Sexton, Rory <rory.sexton at intel.com>; Jagus, DariuszX
> <dariuszx.jagus at intel.com>
> Subject: [PATCH v2 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 at intel.com>
> Signed-off-by: Dariusz Jagus <dariuszx.jagus at intel.com>
> ---

Version change is needed here.

>  doc/guides/testpmd_app_ug/testpmd_funcs.rst |  4 ++
>  drivers/net/i40e/i40e_ethdev.c              | 11 +++-
>  drivers/net/i40e/i40e_ethdev.h              | 48 ++++++++++++-----
>  drivers/net/i40e/i40e_fdir.c                | 40 +++++++++++++--
>  drivers/net/i40e/i40e_flow.c                | 57 +++++++++++++++++++++
>  5 files changed, 141 insertions(+), 19 deletions(-)
> 
> diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> index 73ef0b41d..5e6935829 100644
> --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> @@ -3954,6 +3954,10 @@ This section lists supported pattern items and their
> attributes, if any.
> 
>    - ``proto_id {unsigned}``: PPP protocol identifier.
> 
> +- ``l2tpv3oip``: match L2TPv3 over IP header.
> +
> +  - ``session_id {unsigned}``: L2TPv3 over IP session identifier.
> +

It should not be a part of this patch, which is focus on i40e PMD.


>  Actions list
>  ^^^^^^^^^^^^
> 
> 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..5b6d43556 100644
> --- a/drivers/net/i40e/i40e_ethdev.h
> +++ b/drivers/net/i40e/i40e_ethdev.h
> @@ -508,24 +508,43 @@ struct i40e_raw_flow {
>  	uint32_t length;
>  };
> 
> +/* A structure used to define the input for L2TPv3 over IP flow */
> +struct i40e_l2tpv3oip_flow {
> +	uint32_t session_id; /* Session ID in big endian. */ };

Is this structure needed?

> +
> +/* 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 ip6_l2tpv3oip_flow;
> +	struct i40e_ipv6_l2tpv3oip_flow ip4_l2tpv3oip_flow;
>  };
> 
>  enum i40e_fdir_ip_type {
> @@ -542,6 +561,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
> +917,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;
>  		}
> --
> 2.17.1



More information about the dev mailing list