X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fnet%2Fi40e%2Fi40e_fdir.c;h=c3460739bfd9fa5447cb6e7385e98bf3dc0082cb;hb=89a532ba87ccf64bd53be6f2c384d5747d616612;hp=46dfa79b7f58ee32e38af4f4ab374fa46518bd0f;hpb=f41b5156feb575b9cfeb177974c8e625e09b480f;p=dpdk.git diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c index 46dfa79b7f..c3460739bf 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 @@ -54,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 @@ -608,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 */ @@ -675,6 +698,9 @@ i40e_fdir_configure(struct rte_eth_dev *dev) PMD_DRV_LOG(ERR, "Not support flexible payload."); } + /* Enable FDIR processing in RX routines */ + i40e_fdir_rx_proc_enable(dev, 1); + return ret; } @@ -725,7 +751,7 @@ i40e_fdir_fill_eth_ip_head(const struct rte_eth_fdir_input *fdir_input, case RTE_ETH_FLOW_FRAG_IPV4: ip = (struct rte_ipv4_hdr *)raw_pkt; - *ether_type = rte_cpu_to_be_16(RTE_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); @@ -752,7 +778,7 @@ i40e_fdir_fill_eth_ip_head(const struct rte_eth_fdir_input *fdir_input, case RTE_ETH_FLOW_FRAG_IPV6: ip6 = (struct rte_ipv6_hdr *)raw_pkt; - *ether_type = rte_cpu_to_be_16(RTE_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 << @@ -799,7 +825,7 @@ i40e_fdir_construct_pkt(struct i40e_pf *pf, unsigned char *raw_pkt) { unsigned char *payload, *ptr; - struct udp_hdr *udp; + struct rte_udp_hdr *udp; struct rte_tcp_hdr *tcp; struct rte_sctp_hdr *sctp; uint8_t size, dst = 0; @@ -815,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 @@ -860,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 @@ -950,6 +976,37 @@ 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 i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, const struct i40e_fdir_input *fdir_input, @@ -1006,10 +1063,15 @@ 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); + *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); @@ -1025,33 +1087,54 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, ip->src_addr = fdir_input->flow.ip4_flow.dst_ip; ip->dst_addr = fdir_input->flow.ip4_flow.src_ip; - if (!is_customized_pctype) + 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 || + len += sizeof(struct rte_ipv4_hdr); + } 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) + cus_pctype->index == I40E_CUSTOMIZED_GTPU) { ip->next_proto_id = IPPROTO_UDP; - len += sizeof(struct rte_ipv4_hdr); + len += sizeof(struct rte_ipv4_hdr); + } else if (cus_pctype->index == I40E_CUSTOMIZED_IPV4_L2TPV3) { + ip->next_proto_id = IPPROTO_L2TP; + len += sizeof(struct rte_ipv4_hdr); + } else if (cus_pctype->index == I40E_CUSTOMIZED_ESP_IPV4) { + ip->next_proto_id = IPPROTO_ESP; + len += sizeof(struct rte_ipv4_hdr); + } else if (cus_pctype->index == I40E_CUSTOMIZED_ESP_IPV4_UDP) { + ip->next_proto_id = IPPROTO_UDP; + len += sizeof(struct rte_ipv4_hdr); + } 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) { + 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); + *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[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; @@ -1068,8 +1151,7 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, IPV6_ADDR_LEN); len += sizeof(struct rte_ipv6_hdr); } else { - PMD_DRV_LOG(ERR, "unknown pctype %u.", - fdir_input->pctype); + PMD_DRV_LOG(ERR, "unknown pctype %u.", fdir_input->pctype); return -1; } @@ -1089,12 +1171,17 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, { unsigned char *payload = NULL; unsigned char *ptr; - struct udp_hdr *udp; + struct rte_udp_hdr *udp; struct rte_tcp_hdr *tcp; struct rte_sctp_hdr *sctp; struct rte_flow_item_gtp *gtp; 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; @@ -1116,8 +1203,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 @@ -1153,8 +1240,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 @@ -1206,12 +1293,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; @@ -1264,10 +1352,84 @@ 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 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; }