net/i40e: fix ESP flow creation

Merge of ESP and L2TP code in i40e_fdir.c added checks on
cus_pctype->index which caused flow creation for ESP to fail.

Added fill_ipv4_function()
Refactored code to have one path for customized and non customized
pctype's.

Fixes: c5f8365bc8 ("net/i40e: support flow director for L2TPv3 over IP")

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Rory Sexton <rory.sexton@intel.com>
This commit is contained in:
Bernard Iremonger 2020-01-28 13:48:45 +00:00 committed by Ferruh Yigit
parent 1b473b28dc
commit 2ab5c84605

View File

@ -1007,6 +1007,36 @@ fill_ip6_head(const struct i40e_fdir_input *fdir_input, unsigned char *raw_pkt,
return len;
}
static inline int
fill_ip4_head(const struct i40e_fdir_input *fdir_input, unsigned char *raw_pkt,
uint8_t next_proto, uint8_t len, uint16_t *ether_type)
{
struct rte_ipv4_hdr *ip4;
ip4 = (struct rte_ipv4_hdr *)raw_pkt;
*ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
ip4->version_ihl = I40E_FDIR_IP_DEFAULT_VERSION_IHL;
/* set len to by default */
ip4->total_length = rte_cpu_to_be_16(I40E_FDIR_IP_DEFAULT_LEN);
ip4->time_to_live = fdir_input->flow.ip4_flow.ttl ?
fdir_input->flow.ip4_flow.ttl :
I40E_FDIR_IP_DEFAULT_TTL;
ip4->type_of_service = fdir_input->flow.ip4_flow.tos;
ip4->next_proto_id = fdir_input->flow.ip4_flow.proto ?
fdir_input->flow.ip4_flow.proto : next_proto;
/**
* The source and destination fields in the transmitted packet
* need to be presented in a reversed order with respect
* to the expected received packets.
*/
ip4->src_addr = fdir_input->flow.ip4_flow.dst_ip;
ip4->dst_addr = fdir_input->flow.ip4_flow.src_ip;
len += sizeof(struct rte_ipv4_hdr);
return len;
}
static inline int
i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf,
const struct i40e_fdir_input *fdir_input,
@ -1017,8 +1047,6 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf,
static uint8_t vlan_frame[] = {0x81, 0, 0, 0};
uint16_t *ether_type;
uint8_t len = 2 * sizeof(struct rte_ether_addr);
struct rte_ipv4_hdr *ip;
struct rte_ipv6_hdr *ip6;
uint8_t pctype = fdir_input->pctype;
bool is_customized_pctype = fdir_input->flow_ext.customized_pctype;
static const uint8_t next_proto[] = {
@ -1063,93 +1091,54 @@ 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) &&
((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);
ip->version_ihl = I40E_FDIR_IP_DEFAULT_VERSION_IHL;
/* set len to by default */
ip->total_length = rte_cpu_to_be_16(I40E_FDIR_IP_DEFAULT_LEN);
ip->time_to_live = fdir_input->flow.ip4_flow.ttl ?
fdir_input->flow.ip4_flow.ttl :
I40E_FDIR_IP_DEFAULT_TTL;
ip->type_of_service = fdir_input->flow.ip4_flow.tos;
/**
* The source and destination fields in the transmitted packet
* need to be presented in a reversed order with respect
* to the expected received packets.
*/
ip->src_addr = fdir_input->flow.ip4_flow.dst_ip;
ip->dst_addr = fdir_input->flow.ip4_flow.src_ip;
if (!is_customized_pctype) {
ip->next_proto_id = fdir_input->flow.ip4_flow.proto ?
fdir_input->flow.ip4_flow.proto :
next_proto[fdir_input->pctype];
len += sizeof(struct rte_ipv4_hdr);
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 ||
is_customized_pctype) {
if (pctype == I40E_FILTER_PCTYPE_NONF_IPV4_TCP ||
pctype == I40E_FILTER_PCTYPE_NONF_IPV4_UDP ||
pctype == I40E_FILTER_PCTYPE_NONF_IPV4_SCTP ||
pctype == I40E_FILTER_PCTYPE_NONF_IPV4_OTHER ||
pctype == I40E_FILTER_PCTYPE_FRAG_IPV4) {
len = fill_ip4_head(fdir_input, raw_pkt,
next_proto[pctype], len, ether_type);
} 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) {
len = fill_ip6_head(fdir_input, raw_pkt,
next_proto[pctype], len,
ether_type);
} else if (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) {
ip->next_proto_id = IPPROTO_UDP;
len += sizeof(struct rte_ipv4_hdr);
len = fill_ip4_head(fdir_input, raw_pkt, IPPROTO_UDP,
len, ether_type);
} else if (cus_pctype->index == I40E_CUSTOMIZED_IPV4_L2TPV3) {
ip->next_proto_id = IPPROTO_L2TP;
len += sizeof(struct rte_ipv4_hdr);
len = fill_ip4_head(fdir_input, raw_pkt, IPPROTO_L2TP,
len, ether_type);
} else if (cus_pctype->index == I40E_CUSTOMIZED_ESP_IPV4) {
ip->next_proto_id = IPPROTO_ESP;
len += sizeof(struct rte_ipv4_hdr);
len = fill_ip4_head(fdir_input, raw_pkt, IPPROTO_ESP,
len, ether_type);
} else if (cus_pctype->index == I40E_CUSTOMIZED_ESP_IPV4_UDP) {
ip->next_proto_id = IPPROTO_UDP;
len += sizeof(struct rte_ipv4_hdr);
len = fill_ip4_head(fdir_input, raw_pkt, IPPROTO_UDP,
len, ether_type);
} else if (cus_pctype->index == I40E_CUSTOMIZED_ESP_IPV4_UDP) {
len = fill_ip4_head(fdir_input, raw_pkt, IPPROTO_UDP,
len, ether_type);
} else if (cus_pctype->index == I40E_CUSTOMIZED_ESP_IPV6)
len = fill_ip6_head(fdir_input, raw_pkt, IPPROTO_ESP,
len, ether_type);
else if (cus_pctype->index == I40E_CUSTOMIZED_ESP_IPV6_UDP)
len = fill_ip6_head(fdir_input, raw_pkt, IPPROTO_UDP,
len, ether_type);
} 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 ||
((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);
ip6->vtc_flow =
rte_cpu_to_be_32(I40E_FDIR_IPv6_DEFAULT_VTC_FLOW |
(fdir_input->flow.ipv6_flow.tc <<
I40E_FDIR_IPv6_TC_OFFSET));
ip6->payload_len =
rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN);
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;
/**
* The source and destination fields in the transmitted packet
* need to be presented in a reversed order with respect
* to the expected received packets.
*/
rte_memcpy(&ip6->src_addr,
&fdir_input->flow.ipv6_flow.dst_ip,
IPV6_ADDR_LEN);
rte_memcpy(&ip6->dst_addr,
&fdir_input->flow.ipv6_flow.src_ip,
IPV6_ADDR_LEN);
len += sizeof(struct rte_ipv6_hdr);
len = fill_ip6_head(fdir_input, raw_pkt, IPPROTO_L2TP,
len, ether_type);
} else {
PMD_DRV_LOG(ERR, "unknown pctype %u.", fdir_input->pctype);
return -1;