From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 70C67A3168 for ; Thu, 17 Oct 2019 10:26:14 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 859A81E888; Thu, 17 Oct 2019 10:26:13 +0200 (CEST) Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by dpdk.org (Postfix) with ESMTP id 137411E886 for ; Thu, 17 Oct 2019 10:26:10 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Oct 2019 01:26:09 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.67,307,1566889200"; d="scan'208";a="371064876" Received: from dpdk-xuting-main.sh.intel.com ([10.67.117.83]) by orsmga005.jf.intel.com with ESMTP; 17 Oct 2019 01:26:08 -0700 From: Ting Xu To: dev@dpdk.org Cc: wenzhuo.lu@intel.com, jingjing.wu@intel.com, bernard.iremonger@intel.com, qi.z.zhang@intel.com Date: Thu, 17 Oct 2019 15:26:48 +0000 Message-Id: <20191017152648.18947-1-ting.xu@intel.com> X-Mailer: git-send-email 2.17.1 Subject: [dpdk-dev] [PATCH v1] app/testpmd: enable GTP header parse and Tx checksum offload 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 enables testpmd to forward GTP packet in csum fwd mode. GTP header structure (without optional fields and extension header) and parser function are added. GTPU and GTPC packets are both supported, with respective UDP destination port and GTP message type. Currently, packet with outer IPv6 is not available. Signed-off-by: Ting Xu --- app/test-pmd/csumonly.c | 109 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 100 insertions(+), 9 deletions(-) diff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c index e1cb7fb70..00f099482 100644 --- a/app/test-pmd/csumonly.c +++ b/app/test-pmd/csumonly.c @@ -179,6 +179,84 @@ parse_ethernet(struct rte_ether_hdr *eth_hdr, struct testpmd_offload_info *info) } } +/* + * Parse a GTP protocol header. + * No optional fields and next extension header type. + */ +struct rte_gtp_hdr { + uint8_t gtp_hdr_info; + uint8_t msg_type; + uint16_t msg_len; + uint32_t teid; +} __attribute__((__packed__)); + +/* GTP header length */ +#define RTE_ETHER_GTP_HLEN \ + (sizeof(struct rte_udp_hdr) + sizeof(struct rte_gtp_hdr)) +/* GTP next protocal type */ +#define RTE_GTP_TYPE_IPV4 0x40 +#define RTE_GTP_TYPE_IPV6 0x60 + +static void +parse_gtp(struct rte_udp_hdr *udp_hdr, + struct testpmd_offload_info *info) +{ + struct rte_ipv4_hdr *ipv4_hdr; + struct rte_ipv6_hdr *ipv6_hdr; + struct rte_gtp_hdr *gtp_hdr; + uint8_t gtp_len = sizeof(*gtp_hdr); + uint8_t ip_ver; + /* GTP destination port number */ + uint16_t gtp_udpc_port = 2123; + uint16_t gtp_udpu_port = 2152; + + /* Check udp destination port. */ + if (udp_hdr->dst_port != _htons(gtp_udpc_port) && + udp_hdr->src_port != _htons(gtp_udpc_port) && + udp_hdr->dst_port != _htons(gtp_udpu_port)) + return; + + info->is_tunnel = 1; + info->outer_ethertype = info->ethertype; + info->outer_l2_len = info->l2_len; + info->outer_l3_len = info->l3_len; + info->outer_l4_proto = info->l4_proto; + info->l2_len = 0; + + gtp_hdr = (struct rte_gtp_hdr *)((char *)udp_hdr + + sizeof(struct rte_udp_hdr)); + + /* + * Check message type. If message type is 0xff, it is + * a GTP data packet. If not, it is a GTP control packet + */ + if (gtp_hdr->msg_type == 0xff) { + ip_ver = *(uint8_t *)((char *)udp_hdr + + sizeof(struct rte_udp_hdr) + + sizeof(struct rte_gtp_hdr)); + ip_ver = (ip_ver) & 0xf0; + + if (ip_ver == RTE_GTP_TYPE_IPV4) { + ipv4_hdr = (struct rte_ipv4_hdr *)((char *)gtp_hdr + + gtp_len); + info->ethertype = _htons(RTE_ETHER_TYPE_IPV4); + parse_ipv4(ipv4_hdr, info); + } else if (ip_ver == RTE_GTP_TYPE_IPV6) { + ipv6_hdr = (struct rte_ipv6_hdr *)((char *)gtp_hdr + + gtp_len); + info->ethertype = _htons(RTE_ETHER_TYPE_IPV6); + parse_ipv6(ipv6_hdr, info); + } + } else { + info->ethertype = 0; + info->l4_len = 0; + info->l3_len = 0; + info->l4_proto = 0; + } + + info->l2_len += RTE_ETHER_GTP_HLEN; +} + /* Parse a vxlan header */ static void parse_vxlan(struct rte_udp_hdr *udp_hdr, @@ -478,15 +556,22 @@ process_outer_cksums(void *outer_l3_hdr, struct testpmd_offload_info *info, if (info->outer_l4_proto != IPPROTO_UDP) return ol_flags; + udp_hdr = (struct rte_udp_hdr *) + ((char *)outer_l3_hdr + info->outer_l3_len); + /* Skip SW outer UDP checksum generation if HW supports it */ if (tx_offloads & DEV_TX_OFFLOAD_OUTER_UDP_CKSUM) { + if (info->outer_ethertype == _htons(RTE_ETHER_TYPE_IPV4)) + udp_hdr->dgram_cksum + = rte_ipv4_phdr_cksum(ipv4_hdr, ol_flags); + else + udp_hdr->dgram_cksum + = rte_ipv6_phdr_cksum(ipv6_hdr, ol_flags); + ol_flags |= PKT_TX_OUTER_UDP_CKSUM; return ol_flags; } - udp_hdr = (struct rte_udp_hdr *) - ((char *)outer_l3_hdr + info->outer_l3_len); - /* outer UDP checksum is done in software. In the other side, for * UDP tunneling, like VXLAN or Geneve, outer UDP checksum can be * set to zero. @@ -679,6 +764,7 @@ pkt_copy_split(const struct rte_mbuf *pkt) * UDP|TCP|SCTP * Ether / (vlan) / outer IP|IP6 / outer UDP / VXLAN-GPE / IP|IP6 / * UDP|TCP|SCTP + * Ether / (vlan) / outer IP / outer UDP / GTP / IP|IP6 / UDP|TCP|SCTP * Ether / (vlan) / outer IP|IP6 / GRE / Ether / IP|IP6 / UDP|TCP|SCTP * Ether / (vlan) / outer IP|IP6 / GRE / IP|IP6 / UDP|TCP|SCTP * Ether / (vlan) / outer IP|IP6 / IP|IP6 / UDP|TCP|SCTP @@ -784,18 +870,23 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) if (txp->parse_tunnel) { if (info.l4_proto == IPPROTO_UDP) { struct rte_udp_hdr *udp_hdr; - udp_hdr = (struct rte_udp_hdr *) ((char *)l3_hdr + info.l3_len); - parse_vxlan_gpe(udp_hdr, &info); + parse_gtp(udp_hdr, &info); if (info.is_tunnel) { - tx_ol_flags |= PKT_TX_TUNNEL_VXLAN_GPE; + tx_ol_flags |= PKT_TX_TUNNEL_GTP; } else { - parse_vxlan(udp_hdr, &info, - m->packet_type); - if (info.is_tunnel) + parse_vxlan_gpe(udp_hdr, &info); + if (info.is_tunnel) { tx_ol_flags |= + PKT_TX_TUNNEL_VXLAN_GPE; + } else { + parse_vxlan(udp_hdr, &info, + m->packet_type); + if (info.is_tunnel) + tx_ol_flags |= PKT_TX_TUNNEL_VXLAN; + } } } else if (info.l4_proto == IPPROTO_GRE) { struct simple_gre_hdr *gre_hdr; -- 2.17.1