From patchwork Mon Jan 26 03:43:25 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jijiang Liu X-Patchwork-Id: 2520 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 25A1C5ABF; Mon, 26 Jan 2015 04:43:56 +0100 (CET) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 670EE5A9E for ; Mon, 26 Jan 2015 04:43:46 +0100 (CET) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga103.fm.intel.com with ESMTP; 25 Jan 2015 19:37:45 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.09,466,1418112000"; d="scan'208";a="675811322" Received: from shvmail01.sh.intel.com ([10.239.29.42]) by orsmga002.jf.intel.com with ESMTP; 25 Jan 2015 19:43:45 -0800 Received: from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com [10.239.29.89]) by shvmail01.sh.intel.com with ESMTP id t0Q3hgRM026654; Mon, 26 Jan 2015 11:43:42 +0800 Received: from shecgisg004.sh.intel.com (localhost [127.0.0.1]) by shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP id t0Q3hedn011063; Mon, 26 Jan 2015 11:43:42 +0800 Received: (from jijiangl@localhost) by shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id t0Q3hebX011059; Mon, 26 Jan 2015 11:43:40 +0800 From: Jijiang Liu To: dev@dpdk.org Date: Mon, 26 Jan 2015 11:43:25 +0800 Message-Id: <1422243805-10906-7-git-send-email-jijiang.liu@intel.com> X-Mailer: git-send-email 1.7.12.2 In-Reply-To: <1422243805-10906-1-git-send-email-jijiang.liu@intel.com> References: <1422243805-10906-1-git-send-email-jijiang.liu@intel.com> Subject: [dpdk-dev] [PATCH 6/6] app/testpmd:test NVGRE Tx checksum offload X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Enhance csum fwd engine and command lines based on current TX checksum framework in order to test TX Checksum offload for NVGRE packet. It includes: - IPv4 and IPv6 packet - outer L3, inner L3 and L4 checksum offload for Tx side. Note: The patch will need to be reworked after Olivier's patch set for enhancing checksum offload API is applied. Signed-off-by: Jijiang Liu --- app/test-pmd/cmdline.c | 19 +++++-- app/test-pmd/csumonly.c | 105 ++++++++++++++++++++++++++++---------- app/test-pmd/testpmd.h | 4 +- lib/librte_pmd_i40e/i40e_rxtx.c | 2 + 4 files changed, 94 insertions(+), 36 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index ab25e24..54e0774 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -316,7 +316,7 @@ static void cmd_help_long_parsed(void *parsed_result, " Disable hardware insertion of a VLAN header in" " packets sent on a port.\n\n" - "tx_cksum set (ip|udp|tcp|sctp|vxlan) (hw|sw) (port_id)\n" + "tx_cksum set (ip|udp|tcp|sctp|vxlan|nvgre) (hw|sw) (port_id)\n" " Select hardware or software calculation of the" " checksum with when transmitting a packet using the" " csum forward engine.\n" @@ -2899,8 +2899,9 @@ cmd_tx_cksum_parsed(void *parsed_result, mask = TESTPMD_TX_OFFLOAD_TCP_CKSUM; } else if (!strcmp(res->proto, "sctp")) { mask = TESTPMD_TX_OFFLOAD_SCTP_CKSUM; - } else if (!strcmp(res->proto, "vxlan")) { - mask = TESTPMD_TX_OFFLOAD_VXLAN_CKSUM; + } else if (!strcmp(res->proto, "vxlan") || + !strcmp(res->proto, "nvgre")) { + mask = TESTPMD_TX_OFFLOAD_TUNNEL_CKSUM; } if (hw) @@ -2918,8 +2919,14 @@ cmd_tx_cksum_parsed(void *parsed_result, (ol_flags & TESTPMD_TX_OFFLOAD_TCP_CKSUM) ? "hw" : "sw"); printf("SCTP checksum offload is %s\n", (ol_flags & TESTPMD_TX_OFFLOAD_SCTP_CKSUM) ? "hw" : "sw"); - printf("VxLAN checksum offload is %s\n", - (ol_flags & TESTPMD_TX_OFFLOAD_VXLAN_CKSUM) ? "hw" : "sw"); + + if (!strcmp(res->proto, "vxlan")) { + printf("VxLAN checksum offload is %s\n", + (ol_flags & TESTPMD_TX_OFFLOAD_TUNNEL_CKSUM) ? "hw" : "sw"); + } else if (!strcmp(res->proto, "nvgre")) { + printf("NVGRE checksum offload is %s\n", + (ol_flags & TESTPMD_TX_OFFLOAD_TUNNEL_CKSUM) ? "hw" : "sw"); + } /* display warnings if configuration is not supported by the NIC */ rte_eth_dev_info_get(res->port_id, &dev_info); @@ -2953,7 +2960,7 @@ cmdline_parse_token_string_t cmd_tx_cksum_mode = mode, "set"); cmdline_parse_token_string_t cmd_tx_cksum_proto = TOKEN_STRING_INITIALIZER(struct cmd_tx_cksum_result, - proto, "ip#tcp#udp#sctp#vxlan"); + proto, "ip#tcp#udp#sctp#vxlan#nvgre"); cmdline_parse_token_string_t cmd_tx_cksum_hwsw = TOKEN_STRING_INITIALIZER(struct cmd_tx_cksum_result, hwsw, "hw#sw"); diff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c index 41711fd..8a87fbb 100644 --- a/app/test-pmd/csumonly.c +++ b/app/test-pmd/csumonly.c @@ -86,6 +86,12 @@ #define _htons(x) (x) #endif +/* simplified GRE header */ +struct simple_gre_hdr { + uint16_t flags; + uint16_t proto; +}; + static uint16_t get_psd_sum(void *l3_hdr, uint16_t ethertype, uint64_t ol_flags) { @@ -244,42 +250,42 @@ process_inner_cksums(void *l3_hdr, uint16_t ethertype, uint16_t l3_len, return ol_flags; } -/* Calculate the checksum of outer header (only vxlan is supported, - * meaning IP + UDP). The caller already checked that it's a vxlan +/* Calculate the checksum of outer header (only vxlan/nvgre is supported, + * meaning IP + UDP/GRE). The caller already checked that it's a vxlan/NVGRE * packet */ static uint64_t process_outer_cksums(void *outer_l3_hdr, uint16_t outer_ethertype, - uint16_t outer_l3_len, uint16_t testpmd_ol_flags) + uint16_t outer_l3_len, uint16_t testpmd_ol_flags, uint16_t l4_prot) { struct ipv4_hdr *ipv4_hdr = outer_l3_hdr; struct ipv6_hdr *ipv6_hdr = outer_l3_hdr; struct udp_hdr *udp_hdr; uint64_t ol_flags = 0; - if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_VXLAN_CKSUM) - ol_flags |= PKT_TX_UDP_TUNNEL_PKT; - if (outer_ethertype == _htons(ETHER_TYPE_IPv4)) { ipv4_hdr->hdr_checksum = 0; - if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_VXLAN_CKSUM) + if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_TUNNEL_CKSUM) ol_flags |= PKT_TX_OUTER_IP_CKSUM; else ipv4_hdr->hdr_checksum = rte_ipv4_cksum(ipv4_hdr); - } else if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_VXLAN_CKSUM) + } else if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_TUNNEL_CKSUM) ol_flags |= PKT_TX_OUTER_IPV6; - udp_hdr = (struct udp_hdr *)((char *)outer_l3_hdr + outer_l3_len); - /* do not recalculate udp cksum if it was 0 */ - if (udp_hdr->dgram_cksum != 0) { - udp_hdr->dgram_cksum = 0; - if (outer_ethertype == _htons(ETHER_TYPE_IPv4)) - udp_hdr->dgram_cksum = - rte_ipv4_udptcp_cksum(ipv4_hdr, udp_hdr); - else - udp_hdr->dgram_cksum = - rte_ipv6_udptcp_cksum(ipv6_hdr, udp_hdr); - } + if (l4_prot == IPPROTO_UDP) { + udp_hdr = (struct udp_hdr *)((char *)outer_l3_hdr + + outer_l3_len); + /* do not recalculate udp cksum if it was 0 */ + if (udp_hdr->dgram_cksum != 0) { + udp_hdr->dgram_cksum = 0; + if (outer_ethertype == _htons(ETHER_TYPE_IPv4)) + udp_hdr->dgram_cksum = + rte_ipv4_udptcp_cksum(ipv4_hdr, udp_hdr); + else + udp_hdr->dgram_cksum = + rte_ipv6_udptcp_cksum(ipv6_hdr, udp_hdr); + } + } /* else if (l4_proto == IPPROTO_GRE), nothing to do here*/ return ol_flags; } @@ -299,12 +305,15 @@ process_outer_cksums(void *outer_l3_hdr, uint16_t outer_ethertype, * Ether / (vlan) / IP|IP6 / UDP|TCP|SCTP . * Ether / (vlan) / outer IP|IP6 / outer UDP / VxLAN / Ether / IP|IP6 / * UDP|TCP|SCTP + * Ether / (vlan) / outer IP|IP6 / GRE / Ether / IP|IP6 / + * UDP|TCP|SCTP * * The testpmd command line for this forward engine sets the flags * TESTPMD_TX_OFFLOAD_* in ports[tx_port].tx_ol_flags. They control * wether a checksum must be calculated in software or in hardware. The * IP, UDP, TCP and SCTP flags always concern the inner layer. The - * VxLAN flag concerns the outer IP (if packet is recognized as a vxlan packet). + * TUNNEL flag concerns the outer IP (if packet is recognized as a vxlan/nvgre + * packet). */ static void pkt_burst_checksum_forward(struct fwd_stream *fs) @@ -315,6 +324,7 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) struct ether_hdr *eth_hdr; void *l3_hdr = NULL, *outer_l3_hdr = NULL; /* can be IPv4 or IPv6 */ struct udp_hdr *udp_hdr; + struct simple_gre_hdr *gre_hdr; uint16_t nb_rx; uint16_t nb_tx; uint16_t i; @@ -386,17 +396,20 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) tunnel = 1; /* currently, this flag is set by i40e only if the - * packet is vxlan */ + * packet is tunneled packet */ } else if (m->ol_flags & (PKT_RX_TUNNEL_IPV4_HDR | PKT_RX_TUNNEL_IPV6_HDR)) tunnel = 1; if (tunnel == 1) { + if (testpmd_ol_flags & + TESTPMD_TX_OFFLOAD_TUNNEL_CKSUM) + ol_flags |= PKT_TX_UDP_TUNNEL_PKT; + outer_ethertype = ethertype; outer_l2_len = l2_len; outer_l3_len = l3_len; outer_l3_hdr = l3_hdr; - eth_hdr = (struct ether_hdr *)((char *)udp_hdr + sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr)); @@ -407,6 +420,35 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) } } + if ((l4_proto == IPPROTO_GRE) + && ((m->ol_flags & (PKT_RX_TUNNEL_IPV4_HDR | + PKT_RX_TUNNEL_IPV6_HDR)))) { + gre_hdr = (struct simple_gre_hdr *)((char *)l3_hdr + l3_len); + if (gre_hdr->proto == _htons(ETHER_TYPE_TEB)) { + l4_tun_len = sizeof(struct nvgre_hdr); + tunnel = 1; + } + + if (tunnel == 1) { + if (testpmd_ol_flags & + TESTPMD_TX_OFFLOAD_TUNNEL_CKSUM) + ol_flags |= PKT_TX_GRE_TUNNEL_PKT; + + outer_ethertype = ethertype; + outer_l2_len = l2_len; + outer_l3_len = l3_len; + outer_l3_hdr = l3_hdr; + + /* currently, only NVGRE packet is supported */ + eth_hdr = (struct ether_hdr *)((char *)gre_hdr + + sizeof(struct nvgre_hdr)); + parse_ethernet(eth_hdr, ðertype, &l2_len, + &l3_len, &l4_proto, &l4_len); + l3_hdr = (char *)eth_hdr + l2_len; + } + + } + /* step 2: change all source IPs (v4 or v6) so we need * to recompute the chksums even if they were correct */ @@ -428,13 +470,14 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) * processed in hardware. */ if (tunnel == 1) { ol_flags |= process_outer_cksums(outer_l3_hdr, - outer_ethertype, outer_l3_len, testpmd_ol_flags); + outer_ethertype, outer_l3_len, testpmd_ol_flags, + l4_proto); } /* step 4: fill the mbuf meta data (flags and header lengths) */ if (tunnel == 1) { - if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_VXLAN_CKSUM) { + if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_TUNNEL_CKSUM) { m->outer_l2_len = outer_l2_len; m->outer_l3_len = outer_l3_len; m->l2_len = l4_tun_len + l2_len; @@ -446,9 +489,15 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) we changed the ip, but it shows that we can process the inner header cksum in the nic */ - m->l2_len = outer_l2_len + outer_l3_len + - sizeof(struct udp_hdr) + - sizeof(struct vxlan_hdr) + l2_len; + if (l4_proto == IPPROTO_UDP) + m->l2_len = outer_l2_len + outer_l3_len + + sizeof(struct udp_hdr) + + sizeof(struct vxlan_hdr) + l2_len; + + /* currently, only NVGRE is supported */ + else if (l4_proto == IPPROTO_GRE) + m->l2_len = outer_l2_len + outer_l3_len + + sizeof(struct nvgre_hdr) + l2_len; m->l3_len = l3_len; m->l4_len = l4_len; } @@ -505,7 +554,7 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) "m->l4_len=%d\n", m->l2_len, m->l3_len, m->l4_len); if ((tunnel == 1) && - (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_VXLAN_CKSUM)) + (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_TUNNEL_CKSUM)) printf("tx: m->outer_l2_len=%d m->outer_l3_len=%d\n", m->outer_l2_len, m->outer_l3_len); if (tso_segsz != 0) diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index f8b0740..528457b 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -125,8 +125,8 @@ struct fwd_stream { #define TESTPMD_TX_OFFLOAD_TCP_CKSUM 0x0004 /** Offload SCTP checksum in csum forward engine */ #define TESTPMD_TX_OFFLOAD_SCTP_CKSUM 0x0008 -/** Offload VxLAN checksum in csum forward engine */ -#define TESTPMD_TX_OFFLOAD_VXLAN_CKSUM 0x0010 +/** Offload tunneled packet checksum in csum forward engine */ +#define TESTPMD_TX_OFFLOAD_TUNNEL_CKSUM 0x0010 /** Insert VLAN header in forward engine */ #define TESTPMD_TX_OFFLOAD_INSERT_VLAN 0x0020 diff --git a/lib/librte_pmd_i40e/i40e_rxtx.c b/lib/librte_pmd_i40e/i40e_rxtx.c index 6c1e324..bf6c17c 100644 --- a/lib/librte_pmd_i40e/i40e_rxtx.c +++ b/lib/librte_pmd_i40e/i40e_rxtx.c @@ -1169,6 +1169,8 @@ i40e_calc_context_desc(uint64_t flags) if (flags | PKT_TX_UDP_TUNNEL_PKT) mask |= PKT_TX_UDP_TUNNEL_PKT; + if (flags | PKT_TX_GRE_TUNNEL_PKT) + mask |= PKT_TX_GRE_TUNNEL_PKT; #ifdef RTE_LIBRTE_IEEE1588 mask |= PKT_TX_IEEE1588_TMST;