X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fi40e%2Fi40e_fdir.c;h=d59399afeac1f4a76dcb255760bb49da003653fd;hb=a001f09d11fac91b760c038cf69af7b041bc983c;hp=3d7170d538a0d8039e1e045a37605506ccef0943;hpb=f17ca7870ff29fab42f6743cd2795fd60346f147;p=dpdk.git diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c index 3d7170d538..d59399afea 100644 --- a/drivers/net/i40e/i40e_fdir.c +++ b/drivers/net/i40e/i40e_fdir.c @@ -1,34 +1,5 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2015 Intel Corporation */ #include @@ -40,7 +11,7 @@ #include #include -#include +#include #include #include #include @@ -62,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 @@ -83,6 +58,8 @@ #define I40E_FDIR_GTP_MSG_TYPE_0X01 0x01 #define I40E_FDIR_GTP_MSG_TYPE_0XFF 0xFF +#define I40E_FDIR_ESP_DST_PORT 4500 + /* Wait time for fdir filter programming */ #define I40E_FDIR_MAX_WAIT_US 10000 @@ -95,17 +72,17 @@ #define I40E_COUNTER_INDEX_FDIR(pf_id) (0 + (pf_id) * I40E_COUNTER_PF) #define I40E_FDIR_FLOWS ( \ - (1 << RTE_ETH_FLOW_FRAG_IPV4) | \ - (1 << RTE_ETH_FLOW_NONFRAG_IPV4_UDP) | \ - (1 << RTE_ETH_FLOW_NONFRAG_IPV4_TCP) | \ - (1 << RTE_ETH_FLOW_NONFRAG_IPV4_SCTP) | \ - (1 << RTE_ETH_FLOW_NONFRAG_IPV4_OTHER) | \ - (1 << RTE_ETH_FLOW_FRAG_IPV6) | \ - (1 << RTE_ETH_FLOW_NONFRAG_IPV6_UDP) | \ - (1 << RTE_ETH_FLOW_NONFRAG_IPV6_TCP) | \ - (1 << RTE_ETH_FLOW_NONFRAG_IPV6_SCTP) | \ - (1 << RTE_ETH_FLOW_NONFRAG_IPV6_OTHER) | \ - (1 << RTE_ETH_FLOW_L2_PAYLOAD)) + (1ULL << RTE_ETH_FLOW_FRAG_IPV4) | \ + (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_UDP) | \ + (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_TCP) | \ + (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_SCTP) | \ + (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_OTHER) | \ + (1ULL << RTE_ETH_FLOW_FRAG_IPV6) | \ + (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_UDP) | \ + (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_TCP) | \ + (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_SCTP) | \ + (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_OTHER) | \ + (1ULL << RTE_ETH_FLOW_L2_PAYLOAD)) static int i40e_fdir_filter_programming(struct i40e_pf *pf, enum i40e_filter_pctype pctype, @@ -142,7 +119,7 @@ i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq) #endif rx_ctx.dtype = i40e_header_split_none; rx_ctx.hsplit_0 = I40E_HEADER_SPLIT_NONE; - rx_ctx.rxmax = ETHER_MAX_LEN; + rx_ctx.rxmax = RTE_ETHER_MAX_LEN; rx_ctx.tphrdesc_ena = 1; rx_ctx.tphwdesc_ena = 1; rx_ctx.tphdata_ena = 1; @@ -168,7 +145,6 @@ i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq) rte_wmb(); /* Init the RX tail regieter. */ - I40E_PCI_REG_WRITE(rxq->qrx_tail, 0); I40E_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1); return err; @@ -534,7 +510,7 @@ i40e_set_flx_pld_cfg(struct i40e_pf *pf, { struct i40e_hw *hw = I40E_PF_TO_HW(pf); struct i40e_fdir_flex_pit flex_pit[I40E_MAX_FLXPLD_FIED]; - uint32_t flx_pit; + uint32_t flx_pit, flx_ort; uint16_t num, min_next_off; /* in words */ uint8_t field_idx = 0; uint8_t layer_idx = 0; @@ -548,9 +524,17 @@ i40e_set_flx_pld_cfg(struct i40e_pf *pf, layer_idx = I40E_FLXPLD_L4_IDX; memset(flex_pit, 0, sizeof(flex_pit)); - num = i40e_srcoff_to_flx_pit(cfg->src_offset, flex_pit); + num = RTE_MIN(i40e_srcoff_to_flx_pit(cfg->src_offset, flex_pit), + RTE_DIM(flex_pit)); + + if (num) { + flx_ort = (1 << I40E_GLQF_ORT_FLX_PAYLOAD_SHIFT) | + (num << I40E_GLQF_ORT_FIELD_CNT_SHIFT) | + (layer_idx * I40E_MAX_FLXPLD_FIED); + I40E_WRITE_GLB_REG(hw, I40E_GLQF_ORT(33 + layer_idx), flx_ort); + } - for (i = 0; i < RTE_MIN(num, RTE_DIM(flex_pit)); i++) { + for (i = 0; i < num; i++) { field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i; /* record the info in fdir structure */ pf->fdir.flex_set[field_idx].src_offset = @@ -630,6 +614,23 @@ i40e_set_flex_mask_on_pctype(struct i40e_pf *pf, } } +/* + * Enable/disable flow director RX processing in vector routines. + */ +void +i40e_fdir_rx_proc_enable(struct rte_eth_dev *dev, bool on) +{ + int32_t i; + + for (i = 0; i < dev->data->nb_rx_queues; i++) { + struct i40e_rx_queue *rxq = dev->data->rx_queues[i]; + if (!rxq) + continue; + rxq->fdir_enabled = on; + } + PMD_DRV_LOG(DEBUG, "Flow Director processing on RX set to %d", on); +} + /* * Configure flow director related setting */ @@ -670,24 +671,36 @@ i40e_fdir_configure(struct rte_eth_dev *dev) PMD_DRV_LOG(ERR, " invalid configuration arguments."); return -EINVAL; } - /* configure flex payload */ - for (i = 0; i < conf->nb_payloads; i++) - i40e_set_flx_pld_cfg(pf, &conf->flex_set[i]); - /* configure flex mask*/ - for (i = 0; i < conf->nb_flexmasks; i++) { - if (hw->mac.type == I40E_MAC_X722) { - /* get translated pctype value in fd pctype register */ - pctype = (enum i40e_filter_pctype)i40e_read_rx_ctl( - hw, I40E_GLQF_FD_PCTYPES( - (int)i40e_flowtype_to_pctype(pf->adapter, - conf->flex_mask[i].flow_type))); - } else - pctype = i40e_flowtype_to_pctype(pf->adapter, - conf->flex_mask[i].flow_type); - i40e_set_flex_mask_on_pctype(pf, pctype, &conf->flex_mask[i]); + if (!pf->support_multi_driver) { + /* configure flex payload */ + for (i = 0; i < conf->nb_payloads; i++) + i40e_set_flx_pld_cfg(pf, &conf->flex_set[i]); + /* configure flex mask*/ + for (i = 0; i < conf->nb_flexmasks; i++) { + if (hw->mac.type == I40E_MAC_X722) { + /* get pctype value in fd pctype register */ + pctype = (enum i40e_filter_pctype) + i40e_read_rx_ctl(hw, + I40E_GLQF_FD_PCTYPES( + (int)i40e_flowtype_to_pctype( + pf->adapter, + conf->flex_mask[i].flow_type))); + } else { + pctype = i40e_flowtype_to_pctype(pf->adapter, + conf->flex_mask[i].flow_type); + } + + i40e_set_flex_mask_on_pctype(pf, pctype, + &conf->flex_mask[i]); + } + } else { + PMD_DRV_LOG(ERR, "Not support flexible payload."); } + /* Enable FDIR processing in RX routines */ + i40e_fdir_rx_proc_enable(dev, 1); + return ret; } @@ -698,9 +711,9 @@ i40e_fdir_fill_eth_ip_head(const struct rte_eth_fdir_input *fdir_input, { static uint8_t vlan_frame[] = {0x81, 0, 0, 0}; uint16_t *ether_type; - uint8_t len = 2 * sizeof(struct ether_addr); - struct ipv4_hdr *ip; - struct ipv6_hdr *ip6; + uint8_t len = 2 * sizeof(struct rte_ether_addr); + struct rte_ipv4_hdr *ip; + struct rte_ipv6_hdr *ip6; static const uint8_t next_proto[] = { [RTE_ETH_FLOW_FRAG_IPV4] = IPPROTO_IP, [RTE_ETH_FLOW_NONFRAG_IPV4_TCP] = IPPROTO_TCP, @@ -714,7 +727,7 @@ i40e_fdir_fill_eth_ip_head(const struct rte_eth_fdir_input *fdir_input, [RTE_ETH_FLOW_NONFRAG_IPV6_OTHER] = IPPROTO_NONE, }; - raw_pkt += 2 * sizeof(struct ether_addr); + raw_pkt += 2 * sizeof(struct rte_ether_addr); if (vlan && fdir_input->flow_ext.vlan_tci) { rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame)); rte_memcpy(raw_pkt + sizeof(uint16_t), @@ -736,9 +749,9 @@ i40e_fdir_fill_eth_ip_head(const struct rte_eth_fdir_input *fdir_input, case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP: case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: case RTE_ETH_FLOW_FRAG_IPV4: - ip = (struct ipv4_hdr *)raw_pkt; + ip = (struct rte_ipv4_hdr *)raw_pkt; - *ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); + *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); @@ -756,16 +769,16 @@ i40e_fdir_fill_eth_ip_head(const struct rte_eth_fdir_input *fdir_input, */ ip->src_addr = fdir_input->flow.ip4_flow.dst_ip; ip->dst_addr = fdir_input->flow.ip4_flow.src_ip; - len += sizeof(struct ipv4_hdr); + len += sizeof(struct rte_ipv4_hdr); break; case RTE_ETH_FLOW_NONFRAG_IPV6_TCP: case RTE_ETH_FLOW_NONFRAG_IPV6_UDP: case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP: case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER: case RTE_ETH_FLOW_FRAG_IPV6: - ip6 = (struct ipv6_hdr *)raw_pkt; + ip6 = (struct rte_ipv6_hdr *)raw_pkt; - *ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); + *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 << @@ -789,7 +802,7 @@ i40e_fdir_fill_eth_ip_head(const struct rte_eth_fdir_input *fdir_input, rte_memcpy(&(ip6->dst_addr), &(fdir_input->flow.ipv6_flow.src_ip), IPV6_ADDR_LEN); - len += sizeof(struct ipv6_hdr); + len += sizeof(struct rte_ipv6_hdr); break; default: PMD_DRV_LOG(ERR, "unknown flow type %u.", @@ -812,9 +825,9 @@ i40e_fdir_construct_pkt(struct i40e_pf *pf, unsigned char *raw_pkt) { unsigned char *payload, *ptr; - struct udp_hdr *udp; - struct tcp_hdr *tcp; - struct sctp_hdr *sctp; + struct rte_udp_hdr *udp; + struct rte_tcp_hdr *tcp; + struct rte_sctp_hdr *sctp; uint8_t size, dst = 0; uint8_t i, pit_idx, set_idx = I40E_FLXPLD_L4_IDX; /* use l4 by default*/ int len; @@ -828,8 +841,8 @@ i40e_fdir_construct_pkt(struct i40e_pf *pf, /* fill the L4 head */ switch (fdir_input->flow_type) { case RTE_ETH_FLOW_NONFRAG_IPV4_UDP: - udp = (struct udp_hdr *)(raw_pkt + len); - payload = (unsigned char *)udp + sizeof(struct udp_hdr); + udp = (struct rte_udp_hdr *)(raw_pkt + len); + payload = (unsigned char *)udp + sizeof(struct rte_udp_hdr); /* * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect @@ -841,8 +854,8 @@ i40e_fdir_construct_pkt(struct i40e_pf *pf, break; case RTE_ETH_FLOW_NONFRAG_IPV4_TCP: - tcp = (struct tcp_hdr *)(raw_pkt + len); - payload = (unsigned char *)tcp + sizeof(struct tcp_hdr); + tcp = (struct rte_tcp_hdr *)(raw_pkt + len); + payload = (unsigned char *)tcp + sizeof(struct rte_tcp_hdr); /* * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect @@ -854,8 +867,8 @@ i40e_fdir_construct_pkt(struct i40e_pf *pf, break; case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP: - sctp = (struct sctp_hdr *)(raw_pkt + len); - payload = (unsigned char *)sctp + sizeof(struct sctp_hdr); + sctp = (struct rte_sctp_hdr *)(raw_pkt + len); + payload = (unsigned char *)sctp + sizeof(struct rte_sctp_hdr); /* * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect @@ -873,8 +886,8 @@ i40e_fdir_construct_pkt(struct i40e_pf *pf, break; case RTE_ETH_FLOW_NONFRAG_IPV6_UDP: - udp = (struct udp_hdr *)(raw_pkt + len); - payload = (unsigned char *)udp + sizeof(struct udp_hdr); + udp = (struct rte_udp_hdr *)(raw_pkt + len); + payload = (unsigned char *)udp + sizeof(struct rte_udp_hdr); /* * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect @@ -886,8 +899,8 @@ i40e_fdir_construct_pkt(struct i40e_pf *pf, break; case RTE_ETH_FLOW_NONFRAG_IPV6_TCP: - tcp = (struct tcp_hdr *)(raw_pkt + len); - payload = (unsigned char *)tcp + sizeof(struct tcp_hdr); + tcp = (struct rte_tcp_hdr *)(raw_pkt + len); + payload = (unsigned char *)tcp + sizeof(struct rte_tcp_hdr); /* * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect @@ -899,8 +912,8 @@ i40e_fdir_construct_pkt(struct i40e_pf *pf, break; case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP: - sctp = (struct sctp_hdr *)(raw_pkt + len); - payload = (unsigned char *)sctp + sizeof(struct sctp_hdr); + sctp = (struct rte_sctp_hdr *)(raw_pkt + len); + payload = (unsigned char *)sctp + sizeof(struct rte_sctp_hdr); /* * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect @@ -923,8 +936,8 @@ i40e_fdir_construct_pkt(struct i40e_pf *pf, * starts after the whole ARP header */ if (fdir_input->flow.l2_flow.ether_type == - rte_cpu_to_be_16(ETHER_TYPE_ARP)) - payload += sizeof(struct arp_hdr); + rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP)) + payload += sizeof(struct rte_arp_hdr); set_idx = I40E_FLXPLD_L2_IDX; break; default: @@ -963,6 +976,67 @@ i40e_flow_fdir_find_customized_pctype(struct i40e_pf *pf, uint8_t pctype) return NULL; } +static inline int +fill_ip6_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_ipv6_hdr *ip6; + + 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); + ip6->proto = fdir_input->flow.ipv6_flow.proto ? + fdir_input->flow.ipv6_flow.proto : next_proto; + 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); + + 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, @@ -972,9 +1046,7 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, struct i40e_customized_pctype *cus_pctype = NULL; static uint8_t vlan_frame[] = {0x81, 0, 0, 0}; uint16_t *ether_type; - uint8_t len = 2 * sizeof(struct ether_addr); - struct ipv4_hdr *ip; - struct ipv6_hdr *ip6; + uint8_t len = 2 * sizeof(struct rte_ether_addr); uint8_t pctype = fdir_input->pctype; bool is_customized_pctype = fdir_input->flow_ext.customized_pctype; static const uint8_t next_proto[] = { @@ -990,7 +1062,13 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = IPPROTO_NONE, }; - raw_pkt += 2 * sizeof(struct ether_addr); + rte_memcpy(raw_pkt, &fdir_input->flow.l2_flow.dst, + sizeof(struct rte_ether_addr)); + rte_memcpy(raw_pkt + sizeof(struct rte_ether_addr), + &fdir_input->flow.l2_flow.src, + sizeof(struct rte_ether_addr)); + raw_pkt += 2 * sizeof(struct rte_ether_addr); + if (vlan && fdir_input->flow_ext.vlan_tci) { rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame)); rte_memcpy(raw_pkt + sizeof(uint16_t), @@ -1019,70 +1097,56 @@ 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 || + 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) { - ip = (struct ipv4_hdr *)raw_pkt; - - *ether_type = rte_cpu_to_be_16(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]; - else if (cus_pctype->index == I40E_CUSTOMIZED_GTPC || + 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 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) { - ip6 = (struct ipv6_hdr *)raw_pkt; - - *ether_type = rte_cpu_to_be_16(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); - ip6->proto = fdir_input->flow.ipv6_flow.proto ? - fdir_input->flow.ipv6_flow.proto : - next_proto[fdir_input->pctype]; - 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 ipv6_hdr); + cus_pctype->index == I40E_CUSTOMIZED_GTPU) { + len = fill_ip4_head(fdir_input, raw_pkt, IPPROTO_UDP, + len, ether_type); + } else if (cus_pctype->index == I40E_CUSTOMIZED_IPV4_L2TPV3) { + len = fill_ip4_head(fdir_input, raw_pkt, IPPROTO_L2TP, + len, ether_type); + } else if (cus_pctype->index == I40E_CUSTOMIZED_ESP_IPV4) { + len = fill_ip4_head(fdir_input, raw_pkt, IPPROTO_ESP, + 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_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 (cus_pctype->index == I40E_CUSTOMIZED_IPV6_L2TPV3) + len = fill_ip6_head(fdir_input, raw_pkt, IPPROTO_L2TP, + len, ether_type); } else { - PMD_DRV_LOG(ERR, "unknown pctype %u.", - fdir_input->pctype); + PMD_DRV_LOG(ERR, "unknown pctype %u.", fdir_input->pctype); return -1; } @@ -1102,12 +1166,17 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, { unsigned char *payload = NULL; unsigned char *ptr; - struct udp_hdr *udp; - struct tcp_hdr *tcp; - struct sctp_hdr *sctp; + struct rte_udp_hdr *udp; + struct rte_tcp_hdr *tcp; + struct rte_sctp_hdr *sctp; struct rte_flow_item_gtp *gtp; - struct ipv4_hdr *gtp_ipv4; - struct ipv6_hdr *gtp_ipv6; + struct rte_ipv4_hdr *gtp_ipv4; + struct rte_ipv6_hdr *gtp_ipv6; + struct rte_flow_item_l2tpv3oip *l2tpv3oip; + struct rte_flow_item_esp *esp; + struct rte_ipv4_hdr *esp_ipv4; + struct rte_ipv6_hdr *esp_ipv6; + uint8_t size, dst = 0; uint8_t i, pit_idx, set_idx = I40E_FLXPLD_L4_IDX; /* use l4 by default*/ int len; @@ -1129,8 +1198,8 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, /* fill the L4 head */ if (pctype == I40E_FILTER_PCTYPE_NONF_IPV4_UDP) { - udp = (struct udp_hdr *)(raw_pkt + len); - payload = (unsigned char *)udp + sizeof(struct udp_hdr); + udp = (struct rte_udp_hdr *)(raw_pkt + len); + payload = (unsigned char *)udp + sizeof(struct rte_udp_hdr); /** * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect @@ -1140,8 +1209,8 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, udp->dst_port = fdir_input->flow.udp4_flow.src_port; udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_UDP_DEFAULT_LEN); } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV4_TCP) { - tcp = (struct tcp_hdr *)(raw_pkt + len); - payload = (unsigned char *)tcp + sizeof(struct tcp_hdr); + tcp = (struct rte_tcp_hdr *)(raw_pkt + len); + payload = (unsigned char *)tcp + sizeof(struct rte_tcp_hdr); /** * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect @@ -1151,8 +1220,8 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, tcp->dst_port = fdir_input->flow.tcp4_flow.src_port; tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF; } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) { - sctp = (struct sctp_hdr *)(raw_pkt + len); - payload = (unsigned char *)sctp + sizeof(struct sctp_hdr); + sctp = (struct rte_sctp_hdr *)(raw_pkt + len); + payload = (unsigned char *)sctp + sizeof(struct rte_sctp_hdr); /** * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect @@ -1166,8 +1235,8 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, payload = raw_pkt + len; set_idx = I40E_FLXPLD_L3_IDX; } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV6_UDP) { - udp = (struct udp_hdr *)(raw_pkt + len); - payload = (unsigned char *)udp + sizeof(struct udp_hdr); + udp = (struct rte_udp_hdr *)(raw_pkt + len); + payload = (unsigned char *)udp + sizeof(struct rte_udp_hdr); /** * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect @@ -1177,8 +1246,8 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, udp->dst_port = fdir_input->flow.udp6_flow.src_port; udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN); } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV6_TCP) { - tcp = (struct tcp_hdr *)(raw_pkt + len); - payload = (unsigned char *)tcp + sizeof(struct tcp_hdr); + tcp = (struct rte_tcp_hdr *)(raw_pkt + len); + payload = (unsigned char *)tcp + sizeof(struct rte_tcp_hdr); /** * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect @@ -1188,8 +1257,8 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, tcp->src_port = fdir_input->flow.udp6_flow.dst_port; tcp->dst_port = fdir_input->flow.udp6_flow.src_port; } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) { - sctp = (struct sctp_hdr *)(raw_pkt + len); - payload = (unsigned char *)sctp + sizeof(struct sctp_hdr); + sctp = (struct rte_sctp_hdr *)(raw_pkt + len); + payload = (unsigned char *)sctp + sizeof(struct rte_sctp_hdr); /** * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect @@ -1209,8 +1278,8 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, * starts after the whole ARP header */ if (fdir_input->flow.l2_flow.ether_type == - rte_cpu_to_be_16(ETHER_TYPE_ARP)) - payload += sizeof(struct arp_hdr); + rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP)) + payload += sizeof(struct rte_arp_hdr); set_idx = I40E_FLXPLD_L2_IDX; } else if (fdir_input->flow_ext.customized_pctype) { /* If customized pctype is used */ @@ -1219,12 +1288,13 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, cus_pctype->index == I40E_CUSTOMIZED_GTPU_IPV4 || cus_pctype->index == I40E_CUSTOMIZED_GTPU_IPV6 || cus_pctype->index == I40E_CUSTOMIZED_GTPU) { - udp = (struct udp_hdr *)(raw_pkt + len); + udp = (struct rte_udp_hdr *)(raw_pkt + len); udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_UDP_DEFAULT_LEN); gtp = (struct rte_flow_item_gtp *) - ((unsigned char *)udp + sizeof(struct udp_hdr)); + ((unsigned char *)udp + + sizeof(struct rte_udp_hdr)); gtp->msg_len = rte_cpu_to_be_16(I40E_FDIR_GTP_DEFAULT_LEN); gtp->teid = fdir_input->flow.gtp_flow.teid; @@ -1245,7 +1315,7 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, if (cus_pctype->index == I40E_CUSTOMIZED_GTPU_IPV4) { gtp->msg_type = I40E_FDIR_GTP_MSG_TYPE_0XFF; - gtp_ipv4 = (struct ipv4_hdr *) + gtp_ipv4 = (struct rte_ipv4_hdr *) ((unsigned char *)gtp + sizeof(struct rte_flow_item_gtp)); gtp_ipv4->version_ihl = @@ -1255,11 +1325,11 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, rte_cpu_to_be_16( I40E_FDIR_INNER_IP_DEFAULT_LEN); payload = (unsigned char *)gtp_ipv4 + - sizeof(struct ipv4_hdr); + sizeof(struct rte_ipv4_hdr); } else if (cus_pctype->index == I40E_CUSTOMIZED_GTPU_IPV6) { gtp->msg_type = I40E_FDIR_GTP_MSG_TYPE_0XFF; - gtp_ipv6 = (struct ipv6_hdr *) + gtp_ipv6 = (struct rte_ipv6_hdr *) ((unsigned char *)gtp + sizeof(struct rte_flow_item_gtp)); gtp_ipv6->vtc_flow = @@ -1273,14 +1343,88 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, gtp_ipv6->hop_limits = I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS; payload = (unsigned char *)gtp_ipv6 + - sizeof(struct ipv6_hdr); + sizeof(struct rte_ipv6_hdr); } 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 if (cus_pctype->index == I40E_CUSTOMIZED_ESP_IPV4 || + cus_pctype->index == I40E_CUSTOMIZED_ESP_IPV6 || + cus_pctype->index == I40E_CUSTOMIZED_ESP_IPV4_UDP || + cus_pctype->index == I40E_CUSTOMIZED_ESP_IPV6_UDP) { + if (cus_pctype->index == I40E_CUSTOMIZED_ESP_IPV4) { + esp_ipv4 = (struct rte_ipv4_hdr *) + (raw_pkt + len); + esp = (struct rte_flow_item_esp *)esp_ipv4; + esp->hdr.spi = + fdir_input->flow.esp_ipv4_flow.spi; + payload = (unsigned char *)esp + + sizeof(struct rte_esp_hdr); + len += sizeof(struct rte_esp_hdr); + } else if (cus_pctype->index == + I40E_CUSTOMIZED_ESP_IPV4_UDP) { + esp_ipv4 = (struct rte_ipv4_hdr *) + (raw_pkt + len); + udp = (struct rte_udp_hdr *)esp_ipv4; + udp->dst_port = rte_cpu_to_be_16 + (I40E_FDIR_ESP_DST_PORT); + + udp->dgram_len = rte_cpu_to_be_16 + (I40E_FDIR_UDP_DEFAULT_LEN); + esp = (struct rte_flow_item_esp *) + ((unsigned char *)esp_ipv4 + + sizeof(struct rte_udp_hdr)); + esp->hdr.spi = + fdir_input->flow.esp_ipv4_udp_flow.spi; + payload = (unsigned char *)esp + + sizeof(struct rte_esp_hdr); + len += sizeof(struct rte_udp_hdr) + + sizeof(struct rte_esp_hdr); + } else if (cus_pctype->index == + I40E_CUSTOMIZED_ESP_IPV6) { + esp_ipv6 = (struct rte_ipv6_hdr *) + (raw_pkt + len); + esp = (struct rte_flow_item_esp *)esp_ipv6; + esp->hdr.spi = + fdir_input->flow.esp_ipv6_flow.spi; + payload = (unsigned char *)esp + + sizeof(struct rte_esp_hdr); + len += sizeof(struct rte_esp_hdr); + } else if (cus_pctype->index == + I40E_CUSTOMIZED_ESP_IPV6_UDP) { + esp_ipv6 = (struct rte_ipv6_hdr *) + (raw_pkt + len); + udp = (struct rte_udp_hdr *)esp_ipv6; + udp->dst_port = rte_cpu_to_be_16 + (I40E_FDIR_ESP_DST_PORT); + + udp->dgram_len = rte_cpu_to_be_16 + (I40E_FDIR_UDP_DEFAULT_LEN); + esp = (struct rte_flow_item_esp *) + ((unsigned char *)esp_ipv6 + + sizeof(struct rte_udp_hdr)); + esp->hdr.spi = + fdir_input->flow.esp_ipv6_udp_flow.spi; + payload = (unsigned char *)esp + + sizeof(struct rte_esp_hdr); + len += sizeof(struct rte_udp_hdr) + + sizeof(struct rte_esp_hdr); + } } } else { - PMD_DRV_LOG(ERR, "unknown pctype %u.", - fdir_input->pctype); + PMD_DRV_LOG(ERR, "unknown pctype %u.", fdir_input->pctype); return -1; } @@ -1363,13 +1507,18 @@ i40e_check_fdir_programming_status(struct i40e_rx_queue *rxq) PMD_DRV_LOG(ERR, "invalid programming status" " reported, error = %u.", error); } else - PMD_DRV_LOG(ERR, "unknown programming status" + PMD_DRV_LOG(INFO, "unknown programming status" " reported, len = %d, id = %u.", len, id); rxdp->wb.qword1.status_error_len = 0; rxq->rx_tail++; if (unlikely(rxq->rx_tail == rxq->nb_rx_desc)) rxq->rx_tail = 0; + if (rxq->rx_tail == 0) + I40E_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1); + else + I40E_PCI_REG_WRITE(rxq->qrx_tail, rxq->rx_tail - 1); } + return ret; } @@ -1546,8 +1695,8 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev, struct i40e_fdir_filter check_filter; /* Check if the filter exists */ int ret = 0; - if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT) { - PMD_DRV_LOG(ERR, "FDIR is not enabled, please check the mode in fdir_conf."); + if (pf->fdir.fdir_vsi == NULL) { + PMD_DRV_LOG(ERR, "FDIR is not enabled"); return -ENOTSUP; } @@ -1612,8 +1761,15 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev, if (add) { fdir_filter = rte_zmalloc("fdir_filter", sizeof(*fdir_filter), 0); + if (fdir_filter == NULL) { + PMD_DRV_LOG(ERR, "Failed to alloc memory."); + return -ENOMEM; + } + rte_memcpy(fdir_filter, &check_filter, sizeof(check_filter)); ret = i40e_sw_fdir_filter_insert(pf, fdir_filter); + if (ret < 0) + rte_free(fdir_filter); } else { ret = i40e_sw_fdir_filter_del(pf, &node->fdir.input); } @@ -2020,6 +2176,7 @@ i40e_fdir_info_get(struct rte_eth_dev *dev, struct rte_eth_fdir_info *fdir) struct i40e_hw *hw = I40E_PF_TO_HW(pf); uint16_t num_flex_set = 0; uint16_t num_flex_mask = 0; + uint16_t i; if (dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_PERFECT) fdir->mode = RTE_FDIR_MODE_PERFECT; @@ -2032,6 +2189,8 @@ i40e_fdir_info_get(struct rte_eth_dev *dev, struct rte_eth_fdir_info *fdir) (uint32_t)hw->func_caps.fd_filters_best_effort; fdir->max_flexpayload = I40E_FDIR_MAX_FLEX_LEN; fdir->flow_types_mask[0] = I40E_FDIR_FLOWS; + for (i = 1; i < RTE_FLOW_MASK_ARRAY_SIZE; i++) + fdir->flow_types_mask[i] = 0ULL; fdir->flex_payload_unit = sizeof(uint16_t); fdir->flex_bitmask_unit = sizeof(uint16_t); fdir->max_flex_payload_segment_num = I40E_MAX_FLXPLD_FIED;