From patchwork Fri Aug 25 07:50:28 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Xing, Beilei" X-Patchwork-Id: 27919 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id D42D07D8B; Fri, 25 Aug 2017 09:51:27 +0200 (CEST) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by dpdk.org (Postfix) with ESMTP id 64B477D56 for ; Fri, 25 Aug 2017 09:51:20 +0200 (CEST) Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 25 Aug 2017 00:51:19 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.41,424,1498546800"; d="scan'208";a="144422398" Received: from unknown (HELO dpdk9.sh.intel.com) ([10.67.119.137]) by fmsmga006.fm.intel.com with ESMTP; 25 Aug 2017 00:51:18 -0700 From: Beilei Xing To: jingjing.wu@intel.com Cc: dev@dpdk.org Date: Fri, 25 Aug 2017 15:50:28 +0800 Message-Id: <1503647430-93905-6-git-send-email-beilei.xing@intel.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1503647430-93905-1-git-send-email-beilei.xing@intel.com> References: <1503647430-93905-1-git-send-email-beilei.xing@intel.com> Subject: [dpdk-dev] [PATCH 5/7] net/i40e: add FDIR support for GTP-C and GTP-U X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch adds FDIR support for GTP-C and GTP-U. Signed-off-by: Beilei Xing --- drivers/net/i40e/i40e_ethdev.c | 2 ++ drivers/net/i40e/i40e_ethdev.h | 9 ++++++++ drivers/net/i40e/i40e_fdir.c | 42 ++++++++++++++++++++++++++++++++++-- drivers/net/i40e/i40e_flow.c | 48 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 98 insertions(+), 3 deletions(-) diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 7c9e5af..d7ef782 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -8228,6 +8228,8 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, [I40E_FILTER_PCTYPE_L2_PAYLOAD] = I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_LAST_ETHER_TYPE, + [I40E_FILTER_PCTYPE_GTPC] = I40E_INSET_GTP_TEID, + [I40E_FILTER_PCTYPE_GTPU] = I40E_INSET_GTP_TEID, }; if (pctype > I40E_FILTER_PCTYPE_L2_PAYLOAD) diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index 6d871e4..1681bad 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -467,6 +467,14 @@ struct i40e_vmdq_info { #define I40E_FDIR_IPv6_TC_OFFSET 20 /** + * A structure used to define the input for IPV4 GTP flow + */ +struct i40e_gtpv4_flow { + struct rte_eth_udpv4_flow udp; /**< IPv4 UDP fields to match. */ + uint32_t teid; /**< TEID in big endian. */ +}; + +/** * A union contains the inputs for all types of flow * Items in flows need to be in big endian */ @@ -480,6 +488,7 @@ union i40e_fdir_flow { struct rte_eth_tcpv6_flow tcp6_flow; struct rte_eth_sctpv6_flow sctp6_flow; struct rte_eth_ipv6_flow ipv6_flow; + struct i40e_gtpv4_flow gtpv4_flow; }; /** diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c index b0ba819..707ab4d 100644 --- a/drivers/net/i40e/i40e_fdir.c +++ b/drivers/net/i40e/i40e_fdir.c @@ -71,6 +71,7 @@ #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 /* Wait time for fdir filter programming */ #define I40E_FDIR_MAX_WAIT_US 10000 @@ -949,6 +950,7 @@ i40e_flow_fdir_fill_eth_ip_head(const struct i40e_fdir_input *fdir_input, uint8_t len = 2 * sizeof(struct ether_addr); struct ipv4_hdr *ip; struct ipv6_hdr *ip6; + uint8_t pctype = fdir_input->pctype; static const uint8_t next_proto[] = { [I40E_FILTER_PCTYPE_FRAG_IPV4] = IPPROTO_IP, [I40E_FILTER_PCTYPE_NONF_IPV4_TCP] = IPPROTO_TCP, @@ -960,6 +962,8 @@ i40e_flow_fdir_fill_eth_ip_head(const struct i40e_fdir_input *fdir_input, [I40E_FILTER_PCTYPE_NONF_IPV6_UDP] = IPPROTO_UDP, [I40E_FILTER_PCTYPE_NONF_IPV6_SCTP] = IPPROTO_SCTP, [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = IPPROTO_NONE, + [I40E_FILTER_PCTYPE_GTPC] = IPPROTO_UDP, + [I40E_FILTER_PCTYPE_GTPU] = IPPROTO_UDP, }; raw_pkt += 2 * sizeof(struct ether_addr); @@ -975,7 +979,7 @@ 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) { + switch (pctype) { case I40E_FILTER_PCTYPE_L2_PAYLOAD: *ether_type = fdir_input->flow.l2_flow.ether_type; break; @@ -984,6 +988,8 @@ i40e_flow_fdir_fill_eth_ip_head(const struct i40e_fdir_input *fdir_input, case I40E_FILTER_PCTYPE_NONF_IPV4_SCTP: case I40E_FILTER_PCTYPE_NONF_IPV4_OTHER: case I40E_FILTER_PCTYPE_FRAG_IPV4: + case I40E_FILTER_PCTYPE_GTPC: + case I40E_FILTER_PCTYPE_GTPU: ip = (struct ipv4_hdr *)raw_pkt; *ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); @@ -1062,9 +1068,11 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, struct udp_hdr *udp; struct tcp_hdr *tcp; struct sctp_hdr *sctp; + struct rte_flow_item_gtp *gtp; 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; /* fill the ethernet and IP head */ len = i40e_flow_fdir_fill_eth_ip_head(fdir_input, raw_pkt, @@ -1073,7 +1081,7 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, return -EINVAL; /* fill the L4 head */ - switch (fdir_input->pctype) { + switch (pctype) { case I40E_FILTER_PCTYPE_NONF_IPV4_UDP: udp = (struct udp_hdr *)(raw_pkt + len); payload = (unsigned char *)udp + sizeof(struct udp_hdr); @@ -1174,6 +1182,36 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, payload += sizeof(struct arp_hdr); set_idx = I40E_FLXPLD_L2_IDX; break; + case I40E_FILTER_PCTYPE_GTPC: + udp = (struct udp_hdr *)(raw_pkt + len); + udp->dst_port = rte_cpu_to_be_16(2123); + 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->v_pt_rsv_flags = 0x30; + gtp->msg_len = rte_cpu_to_be_16(I40E_FDIR_GTP_DEFAULT_LEN); + gtp->teid = fdir_input->flow.gtpv4_flow.teid; + gtp->msg_type = 0xff; + + payload = (unsigned char *)gtp + + sizeof(struct rte_flow_item_gtp); + break; + case I40E_FILTER_PCTYPE_GTPU: + udp = (struct udp_hdr *)(raw_pkt + len); + udp->dst_port = rte_cpu_to_be_16(2152); + 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->v_pt_rsv_flags = 0x30; + gtp->msg_len = rte_cpu_to_be_16(I40E_FDIR_GTP_DEFAULT_LEN); + gtp->teid = fdir_input->flow.gtpv4_flow.teid; + gtp->msg_type = 0xff; + + payload = (unsigned char *)gtp + + sizeof(struct rte_flow_item_gtp); + break; default: PMD_DRV_LOG(ERR, "unknown pctype %u.", fdir_input->pctype); return -EINVAL; diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index 73af7fd..698368e 100644 --- a/drivers/net/i40e/i40e_flow.c +++ b/drivers/net/i40e/i40e_flow.c @@ -189,6 +189,14 @@ static enum rte_flow_item_type pattern_fdir_ipv4_sctp[] = { RTE_FLOW_ITEM_TYPE_END, }; +static enum rte_flow_item_type pattern_fdir_ipv4_gtp[] = { + RTE_FLOW_ITEM_TYPE_ETH, + RTE_FLOW_ITEM_TYPE_IPV4, + RTE_FLOW_ITEM_TYPE_UDP, + RTE_FLOW_ITEM_TYPE_GTP, + RTE_FLOW_ITEM_TYPE_END, +}; + static enum rte_flow_item_type pattern_fdir_ipv6[] = { RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV6, @@ -1576,6 +1584,7 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = { { pattern_fdir_ipv4_udp, i40e_flow_parse_fdir_filter }, { pattern_fdir_ipv4_tcp, i40e_flow_parse_fdir_filter }, { pattern_fdir_ipv4_sctp, i40e_flow_parse_fdir_filter }, + { pattern_fdir_ipv4_gtp, i40e_flow_parse_fdir_filter }, { pattern_fdir_ipv6, i40e_flow_parse_fdir_filter }, { pattern_fdir_ipv6_udp, i40e_flow_parse_fdir_filter }, { pattern_fdir_ipv6_tcp, i40e_flow_parse_fdir_filter }, @@ -2326,10 +2335,11 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, const struct rte_flow_item_tcp *tcp_spec, *tcp_mask; const struct rte_flow_item_udp *udp_spec, *udp_mask; const struct rte_flow_item_sctp *sctp_spec, *sctp_mask; + 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; - enum i40e_filter_pctype pctype = 0; + uint8_t pctype = 0; uint64_t input_set = I40E_INSET_NONE; uint16_t frag_off; enum rte_flow_item_type item_type; @@ -2351,6 +2361,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, uint16_t outer_tpid; uint16_t ether_type; uint32_t vtc_flow_cpu; + uint16_t udp_dst_port = 0; int ret; memset(off_arr, 0, sizeof(off_arr)); @@ -2631,11 +2642,46 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, filter->input.flow.udp6_flow.dst_port = udp_spec->hdr.dst_port; } + + udp_dst_port = udp_spec->hdr.dst_port; } layer_idx = I40E_FLXPLD_L4_IDX; break; + case RTE_FLOW_ITEM_TYPE_GTP: + gtp_spec = (const struct rte_flow_item_gtp *)item->spec; + gtp_mask = (const struct rte_flow_item_gtp *)item->mask; + + if (gtp_spec && gtp_mask) { + if (gtp_mask->v_pt_rsv_flags || + gtp_mask->msg_type || + gtp_mask->msg_len || + gtp_mask->teid != UINT32_MAX) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Invalid GTP mask"); + return -rte_errno; + } + + input_set |= I40E_INSET_GTP_TEID; + filter->input.flow.gtpv4_flow.teid = + gtp_spec->teid; + + if (udp_dst_port == rte_cpu_to_be_16(2123)) + pctype = I40E_FILTER_PCTYPE_GTPC; + else if (udp_dst_port == rte_cpu_to_be_16(2152)) + pctype = I40E_FILTER_PCTYPE_GTPU; + else { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Invalid GTP flow"); + return -rte_errno; + } + } + break; case RTE_FLOW_ITEM_TYPE_SCTP: sctp_spec = (const struct rte_flow_item_sctp *)item->spec;