X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fi40e%2Fi40e_fdir.c;h=b83a0cff9b8252b467b46cdab85c2f2593f822d7;hb=1633d3c4c1290eb52f82d5144d4e19fa3d220fae;hp=7b16584bc472207e1d99b67f3e900bfca44deb1b;hpb=4149825bbdb996837a3a73c1467ff93a228358a8;p=dpdk.git diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c index 7b16584bc4..b83a0cff9b 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 @@ -49,6 +20,7 @@ #include #include #include +#include #include "i40e_logs.h" #include "base/i40e_type.h" @@ -71,6 +43,16 @@ #define I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS 0xFF #define I40E_FDIR_IPv6_PAYLOAD_LEN 380 #define I40E_FDIR_UDP_DEFAULT_LEN 400 +#define I40E_FDIR_GTP_DEFAULT_LEN 384 +#define I40E_FDIR_INNER_IP_DEFAULT_LEN 384 +#define I40E_FDIR_INNER_IPV6_DEFAULT_LEN 344 + +#define I40E_FDIR_GTPC_DST_PORT 2123 +#define I40E_FDIR_GTPU_DST_PORT 2152 +#define I40E_FDIR_GTP_VER_FLAG_0X30 0x30 +#define I40E_FDIR_GTP_VER_FLAG_0X32 0x32 +#define I40E_FDIR_GTP_MSG_TYPE_0X01 0x01 +#define I40E_FDIR_GTP_MSG_TYPE_0XFF 0xFF /* Wait time for fdir filter programming */ #define I40E_FDIR_MAX_WAIT_US 10000 @@ -84,17 +66,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, @@ -157,7 +139,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; @@ -254,7 +235,7 @@ i40e_fdir_setup(struct i40e_pf *pf) goto fail_mem; } pf->fdir.prg_pkt = mz->addr; - pf->fdir.dma_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr); + pf->fdir.dma_addr = mz->iova; pf->fdir.match_counter_index = I40E_COUNTER_INDEX_FDIR(hw->pf_id); PMD_DRV_LOG(INFO, "FDIR setup successfully, with programming queue %u.", @@ -523,7 +504,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; @@ -537,9 +518,18 @@ 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_REG(hw, I40E_GLQF_ORT(33 + layer_idx), flx_ort); + i40e_global_cfg_warning(I40E_WARNING_ENA_FLX_PLD); + } - 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 = @@ -659,22 +649,31 @@ 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."); } return ret; @@ -938,16 +937,34 @@ i40e_fdir_construct_pkt(struct i40e_pf *pf, return 0; } +static struct i40e_customized_pctype * +i40e_flow_fdir_find_customized_pctype(struct i40e_pf *pf, uint8_t pctype) +{ + struct i40e_customized_pctype *cus_pctype; + enum i40e_new_pctype i = I40E_CUSTOMIZED_GTPC; + + for (; i < I40E_CUSTOMIZED_MAX; i++) { + cus_pctype = &pf->customized_pctype[i]; + if (pctype == cus_pctype->pctype) + return cus_pctype; + } + return NULL; +} + static inline int -i40e_flow_fdir_fill_eth_ip_head(const struct i40e_fdir_input *fdir_input, +i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, + const struct i40e_fdir_input *fdir_input, unsigned char *raw_pkt, bool vlan) { + 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 pctype = fdir_input->pctype; + bool is_customized_pctype = fdir_input->flow_ext.customized_pctype; static const uint8_t next_proto[] = { [I40E_FILTER_PCTYPE_FRAG_IPV4] = IPPROTO_IP, [I40E_FILTER_PCTYPE_NONF_IPV4_TCP] = IPPROTO_TCP, @@ -974,27 +991,32 @@ i40e_flow_fdir_fill_eth_ip_head(const struct i40e_fdir_input *fdir_input, raw_pkt += sizeof(uint16_t); len += sizeof(uint16_t); - switch (fdir_input->pctype) { - case I40E_FILTER_PCTYPE_L2_PAYLOAD: + if (is_customized_pctype) { + cus_pctype = i40e_flow_fdir_find_customized_pctype(pf, pctype); + if (!cus_pctype) { + PMD_DRV_LOG(ERR, "unknown pctype %u.", + fdir_input->pctype); + return -1; + } + } + + if (pctype == I40E_FILTER_PCTYPE_L2_PAYLOAD) *ether_type = fdir_input->flow.l2_flow.ether_type; - break; - case I40E_FILTER_PCTYPE_NONF_IPV4_TCP: - case I40E_FILTER_PCTYPE_NONF_IPV4_UDP: - case I40E_FILTER_PCTYPE_NONF_IPV4_SCTP: - case I40E_FILTER_PCTYPE_NONF_IPV4_OTHER: - case I40E_FILTER_PCTYPE_FRAG_IPV4: + else 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 || + 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->next_proto_id = fdir_input->flow.ip4_flow.proto ? - fdir_input->flow.ip4_flow.proto : - next_proto[fdir_input->pctype]; ip->time_to_live = fdir_input->flow.ip4_flow.ttl ? - fdir_input->flow.ip4_flow.ttl : - I40E_FDIR_IP_DEFAULT_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 @@ -1003,13 +1025,22 @@ i40e_flow_fdir_fill_eth_ip_head(const struct i40e_fdir_input *fdir_input, */ 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 || + 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); - break; - case I40E_FILTER_PCTYPE_NONF_IPV6_TCP: - case I40E_FILTER_PCTYPE_NONF_IPV6_UDP: - case I40E_FILTER_PCTYPE_NONF_IPV6_SCTP: - case I40E_FILTER_PCTYPE_NONF_IPV6_OTHER: - case I40E_FILTER_PCTYPE_FRAG_IPV6: + } 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); @@ -1020,11 +1051,11 @@ i40e_flow_fdir_fill_eth_ip_head(const struct i40e_fdir_input *fdir_input, 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]; + 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; + 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 @@ -1037,12 +1068,12 @@ i40e_flow_fdir_fill_eth_ip_head(const struct i40e_fdir_input *fdir_input, &fdir_input->flow.ipv6_flow.src_ip, IPV6_ADDR_LEN); len += sizeof(struct ipv6_hdr); - break; - default: + } else { PMD_DRV_LOG(ERR, "unknown pctype %u.", fdir_input->pctype); return -1; } + return len; } @@ -1057,23 +1088,35 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, const struct i40e_fdir_input *fdir_input, unsigned char *raw_pkt) { - unsigned char *payload, *ptr; + unsigned char *payload = NULL; + unsigned char *ptr; struct udp_hdr *udp; struct tcp_hdr *tcp; struct sctp_hdr *sctp; + struct rte_flow_item_gtp *gtp; + struct ipv4_hdr *gtp_ipv4; + struct ipv6_hdr *gtp_ipv6; uint8_t size, dst = 0; uint8_t i, pit_idx, set_idx = I40E_FLXPLD_L4_IDX; /* use l4 by default*/ int len; + uint8_t pctype = fdir_input->pctype; + struct i40e_customized_pctype *cus_pctype; + + /* raw pcket template - just copy contents of the raw packet */ + if (fdir_input->flow_ext.pkt_template) { + memcpy(raw_pkt, fdir_input->flow.raw_flow.packet, + fdir_input->flow.raw_flow.length); + return 0; + } /* fill the ethernet and IP head */ - len = i40e_flow_fdir_fill_eth_ip_head(fdir_input, raw_pkt, + len = i40e_flow_fdir_fill_eth_ip_head(pf, fdir_input, raw_pkt, !!fdir_input->flow_ext.vlan_tci); if (len < 0) return -EINVAL; /* fill the L4 head */ - switch (fdir_input->pctype) { - case I40E_FILTER_PCTYPE_NONF_IPV4_UDP: + if (pctype == I40E_FILTER_PCTYPE_NONF_IPV4_UDP) { udp = (struct udp_hdr *)(raw_pkt + len); payload = (unsigned char *)udp + sizeof(struct udp_hdr); /** @@ -1084,9 +1127,7 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, udp->src_port = fdir_input->flow.udp4_flow.dst_port; udp->dst_port = fdir_input->flow.udp4_flow.src_port; udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_UDP_DEFAULT_LEN); - break; - - case I40E_FILTER_PCTYPE_NONF_IPV4_TCP: + } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV4_TCP) { tcp = (struct tcp_hdr *)(raw_pkt + len); payload = (unsigned char *)tcp + sizeof(struct tcp_hdr); /** @@ -1097,9 +1138,7 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, tcp->src_port = fdir_input->flow.tcp4_flow.dst_port; tcp->dst_port = fdir_input->flow.tcp4_flow.src_port; tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF; - break; - - case I40E_FILTER_PCTYPE_NONF_IPV4_SCTP: + } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) { sctp = (struct sctp_hdr *)(raw_pkt + len); payload = (unsigned char *)sctp + sizeof(struct sctp_hdr); /** @@ -1110,15 +1149,11 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, sctp->src_port = fdir_input->flow.sctp4_flow.dst_port; sctp->dst_port = fdir_input->flow.sctp4_flow.src_port; sctp->tag = fdir_input->flow.sctp4_flow.verify_tag; - break; - - case I40E_FILTER_PCTYPE_NONF_IPV4_OTHER: - case I40E_FILTER_PCTYPE_FRAG_IPV4: + } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV4_OTHER || + pctype == I40E_FILTER_PCTYPE_FRAG_IPV4) { payload = raw_pkt + len; set_idx = I40E_FLXPLD_L3_IDX; - break; - - case I40E_FILTER_PCTYPE_NONF_IPV6_UDP: + } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV6_UDP) { udp = (struct udp_hdr *)(raw_pkt + len); payload = (unsigned char *)udp + sizeof(struct udp_hdr); /** @@ -1129,9 +1164,7 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, udp->src_port = fdir_input->flow.udp6_flow.dst_port; udp->dst_port = fdir_input->flow.udp6_flow.src_port; udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN); - break; - - case I40E_FILTER_PCTYPE_NONF_IPV6_TCP: + } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV6_TCP) { tcp = (struct tcp_hdr *)(raw_pkt + len); payload = (unsigned char *)tcp + sizeof(struct tcp_hdr); /** @@ -1142,9 +1175,7 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF; tcp->src_port = fdir_input->flow.udp6_flow.dst_port; tcp->dst_port = fdir_input->flow.udp6_flow.src_port; - break; - - case I40E_FILTER_PCTYPE_NONF_IPV6_SCTP: + } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) { sctp = (struct sctp_hdr *)(raw_pkt + len); payload = (unsigned char *)sctp + sizeof(struct sctp_hdr); /** @@ -1155,14 +1186,11 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, sctp->src_port = fdir_input->flow.sctp6_flow.dst_port; sctp->dst_port = fdir_input->flow.sctp6_flow.src_port; sctp->tag = fdir_input->flow.sctp6_flow.verify_tag; - break; - - case I40E_FILTER_PCTYPE_NONF_IPV6_OTHER: - case I40E_FILTER_PCTYPE_FRAG_IPV6: + } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV6_OTHER || + pctype == I40E_FILTER_PCTYPE_FRAG_IPV6) { payload = raw_pkt + len; set_idx = I40E_FLXPLD_L3_IDX; - break; - case I40E_FILTER_PCTYPE_L2_PAYLOAD: + } else if (pctype == I40E_FILTER_PCTYPE_L2_PAYLOAD) { payload = raw_pkt + len; /** * ARP packet is a special case on which the payload @@ -1172,10 +1200,76 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, rte_cpu_to_be_16(ETHER_TYPE_ARP)) payload += sizeof(struct arp_hdr); set_idx = I40E_FLXPLD_L2_IDX; - break; - default: - PMD_DRV_LOG(ERR, "unknown pctype %u.", fdir_input->pctype); - return -EINVAL; + } else if (fdir_input->flow_ext.customized_pctype) { + /* If customized pctype is used */ + cus_pctype = i40e_flow_fdir_find_customized_pctype(pf, pctype); + 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) { + udp = (struct 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)); + gtp->msg_len = + rte_cpu_to_be_16(I40E_FDIR_GTP_DEFAULT_LEN); + gtp->teid = fdir_input->flow.gtp_flow.teid; + gtp->msg_type = I40E_FDIR_GTP_MSG_TYPE_0X01; + + /* GTP-C message type is not supported. */ + if (cus_pctype->index == I40E_CUSTOMIZED_GTPC) { + udp->dst_port = + rte_cpu_to_be_16(I40E_FDIR_GTPC_DST_PORT); + gtp->v_pt_rsv_flags = + I40E_FDIR_GTP_VER_FLAG_0X32; + } else { + udp->dst_port = + rte_cpu_to_be_16(I40E_FDIR_GTPU_DST_PORT); + gtp->v_pt_rsv_flags = + I40E_FDIR_GTP_VER_FLAG_0X30; + } + + if (cus_pctype->index == I40E_CUSTOMIZED_GTPU_IPV4) { + gtp->msg_type = I40E_FDIR_GTP_MSG_TYPE_0XFF; + gtp_ipv4 = (struct ipv4_hdr *) + ((unsigned char *)gtp + + sizeof(struct rte_flow_item_gtp)); + gtp_ipv4->version_ihl = + I40E_FDIR_IP_DEFAULT_VERSION_IHL; + gtp_ipv4->next_proto_id = IPPROTO_IP; + gtp_ipv4->total_length = + rte_cpu_to_be_16( + I40E_FDIR_INNER_IP_DEFAULT_LEN); + payload = (unsigned char *)gtp_ipv4 + + sizeof(struct 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 *) + ((unsigned char *)gtp + + sizeof(struct rte_flow_item_gtp)); + gtp_ipv6->vtc_flow = + rte_cpu_to_be_32( + I40E_FDIR_IPv6_DEFAULT_VTC_FLOW | + (0 << I40E_FDIR_IPv6_TC_OFFSET)); + gtp_ipv6->proto = IPPROTO_NONE; + gtp_ipv6->payload_len = + rte_cpu_to_be_16( + I40E_FDIR_INNER_IPV6_DEFAULT_LEN); + gtp_ipv6->hop_limits = + I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS; + payload = (unsigned char *)gtp_ipv6 + + sizeof(struct ipv6_hdr); + } else + payload = (unsigned char *)gtp + + sizeof(struct rte_flow_item_gtp); + } + } else { + PMD_DRV_LOG(ERR, "unknown pctype %u.", + fdir_input->pctype); + return -1; } /* fill the flexbytes to payload */ @@ -1257,13 +1351,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; } @@ -1272,6 +1371,13 @@ i40e_fdir_filter_convert(const struct i40e_fdir_filter_conf *input, struct i40e_fdir_filter *filter) { rte_memcpy(&filter->fdir, input, sizeof(struct i40e_fdir_filter_conf)); + if (input->input.flow_ext.pkt_template) { + filter->fdir.input.flow.raw_flow.packet = NULL; + filter->fdir.input.flow.raw_flow.length = + rte_hash_crc(input->input.flow.raw_flow.packet, + input->input.flow.raw_flow.length, + input->input.flow.raw_flow.pctype); + } return 0; } @@ -1282,7 +1388,13 @@ i40e_sw_fdir_filter_lookup(struct i40e_fdir_info *fdir_info, { int ret; - ret = rte_hash_lookup(fdir_info->hash_table, (const void *)input); + if (input->flow_ext.pkt_template) + ret = rte_hash_lookup_with_hash(fdir_info->hash_table, + (const void *)input, + input->flow.raw_flow.length); + else + ret = rte_hash_lookup(fdir_info->hash_table, + (const void *)input); if (ret < 0) return NULL; @@ -1296,8 +1408,13 @@ i40e_sw_fdir_filter_insert(struct i40e_pf *pf, struct i40e_fdir_filter *filter) struct i40e_fdir_info *fdir_info = &pf->fdir; int ret; - ret = rte_hash_add_key(fdir_info->hash_table, - &filter->fdir.input); + if (filter->fdir.input.flow_ext.pkt_template) + ret = rte_hash_add_key_with_hash(fdir_info->hash_table, + &filter->fdir.input, + filter->fdir.input.flow.raw_flow.length); + else + ret = rte_hash_add_key(fdir_info->hash_table, + &filter->fdir.input); if (ret < 0) { PMD_DRV_LOG(ERR, "Failed to insert fdir filter to hash table %d!", @@ -1319,7 +1436,12 @@ i40e_sw_fdir_filter_del(struct i40e_pf *pf, struct i40e_fdir_input *input) struct i40e_fdir_filter *filter; int ret; - ret = rte_hash_del_key(fdir_info->hash_table, input); + if (input->flow_ext.pkt_template) + ret = rte_hash_del_key_with_hash(fdir_info->hash_table, + input, + input->flow.raw_flow.length); + else + ret = rte_hash_del_key(fdir_info->hash_table, input); if (ret < 0) { PMD_DRV_LOG(ERR, "Failed to delete fdir filter to hash table %d!", @@ -1431,6 +1553,17 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev, PMD_DRV_LOG(ERR, "Invalid VF ID"); return -EINVAL; } + if (filter->input.flow_ext.pkt_template) { + if (filter->input.flow.raw_flow.length > I40E_FDIR_PKT_LEN || + !filter->input.flow.raw_flow.packet) { + PMD_DRV_LOG(ERR, "Invalid raw packet template" + " flow filter parameters!"); + return -EINVAL; + } + pctype = filter->input.flow.raw_flow.pctype; + } else { + pctype = filter->input.pctype; + } /* Check if there is the filter in SW list */ memset(&check_filter, 0, sizeof(check_filter)); @@ -1459,10 +1592,8 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev, 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)filter->input.pctype)); - } else - pctype = filter->input.pctype; + hw, I40E_GLQF_FD_PCTYPES((int)pctype)); + } ret = i40e_flow_fdir_filter_programming(pf, pctype, filter, add); if (ret < 0) { @@ -1474,8 +1605,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); } @@ -1882,6 +2020,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; @@ -1894,6 +2033,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;