From patchwork Tue Sep 12 02:43:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Hu, Jiayu" X-Patchwork-Id: 28604 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id BA9881B19E; Tue, 12 Sep 2017 04:41:01 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 060B87CBD for ; Tue, 12 Sep 2017 04:40:53 +0200 (CEST) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 11 Sep 2017 19:40:51 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos; i="5.42,381,1500966000"; d="scan'208"; a="1194022485" Received: from dpdk15.sh.intel.com ([10.67.111.77]) by fmsmga001.fm.intel.com with ESMTP; 11 Sep 2017 19:40:49 -0700 From: Jiayu Hu To: dev@dpdk.org Cc: konstantin.ananyev@intel.com, mark.b.kavanagh@intel.com, jianfeng.tan@intel.com, Jiayu Hu Date: Tue, 12 Sep 2017 10:43:30 +0800 Message-Id: <1505184211-36728-5-git-send-email-jiayu.hu@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1505184211-36728-1-git-send-email-jiayu.hu@intel.com> References: <1504598270-60080-1-git-send-email-jiayu.hu@intel.com> <1505184211-36728-1-git-send-email-jiayu.hu@intel.com> Subject: [dpdk-dev] [PATCH v3 4/5] gso: add GRE GSO support 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" From: Mark Kavanagh This patch adds GSO support for GRE-tunneled packets. Supported GRE packets must contain an outer IPv4 header, and inner TCP/IPv4 headers. They may also contain a single VLAN tag. GRE GSO assumes that all input packets have correct checksums and doesn't update checksums for output packets. Additionally, it doesn't process IP fragmented packets. As with VxLAN GSO, GRE GSO uses a two-segment MBUF to organize each output packet, which requires multi-segment mbuf support in the TX functions of the NIC driver. Also, if a packet is GSOed, GRE GSO reduces its MBUF refcnt by 1. As a result, when all of its GSOed segments are freed, the packet is freed automatically. Signed-off-by: Mark Kavanagh Signed-off-by: Jiayu Hu --- lib/librte_gso/gso_common.c | 22 ++++++++++++++++++++++ lib/librte_gso/gso_common.h | 19 +++++++++++++++++++ lib/librte_gso/rte_gso.c | 3 ++- 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/lib/librte_gso/gso_common.c b/lib/librte_gso/gso_common.c index c6779d0..bd56924 100644 --- a/lib/librte_gso/gso_common.c +++ b/lib/librte_gso/gso_common.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -237,12 +238,33 @@ update_ipv4_vxlan_tcp4_header(struct rte_mbuf *pkt, uint8_t ipid_delta, update_inner_tcp4_header(pkt, ipid_delta, segs, nb_segs); } +static inline void +update_ipv4_gre_tcp4_header(struct rte_mbuf *pkt, uint8_t ipid_delta, + struct rte_mbuf **segs, uint16_t nb_segs) +{ + struct ipv4_hdr *ipv4_hdr; + uint16_t i, id; + + ipv4_hdr = (struct ipv4_hdr *)(rte_pktmbuf_mtod(pkt, char *) + + pkt->outer_l2_len); + id = rte_be_to_cpu_16(ipv4_hdr->packet_id); + for (i = 0; i < nb_segs; i++) { + update_outer_ipv4_header(segs[i], id); + id += ipid_delta; + } + + /* Update inner TCP/IPv4 headers */ + update_inner_tcp4_header(pkt, ipid_delta, segs, nb_segs); +} + void gso_update_pkt_headers(struct rte_mbuf *pkt, uint8_t ipid_delta, struct rte_mbuf **segs, uint16_t nb_segs) { if (is_ipv4_vxlan_ipv4_tcp(pkt->packet_type)) update_ipv4_vxlan_tcp4_header(pkt, ipid_delta, segs, nb_segs); + else if (is_ipv4_gre_ipv4_tcp(pkt->packet_type)) + update_ipv4_gre_tcp4_header(pkt, ipid_delta, segs, nb_segs); else if (is_ipv4_tcp(pkt->packet_type)) update_inner_tcp4_header(pkt, ipid_delta, segs, nb_segs); } diff --git a/lib/librte_gso/gso_common.h b/lib/librte_gso/gso_common.h index 2377a1d..f6d3238 100644 --- a/lib/librte_gso/gso_common.h +++ b/lib/librte_gso/gso_common.h @@ -89,6 +89,25 @@ static inline uint8_t is_ipv4_vxlan_ipv4_tcp(uint32_t ptype) } } +#define ETHER_GRE_TCP (RTE_PTYPE_L2_ETHER | RTE_PTYPE_TUNNEL_GRE | \ + RTE_PTYPE_INNER_L4_TCP) +#define ETHER_VLAN_GRE_TCP (RTE_PTYPE_L2_ETHER_VLAN | RTE_PTYPE_TUNNEL_GRE | \ + RTE_PTYPE_INNER_L4_TCP) +static inline uint8_t is_ipv4_gre_ipv4_tcp(uint32_t ptype) +{ + uint32_t type; + + type = ptype & (~(RTE_PTYPE_L3_MASK | RTE_PTYPE_INNER_L3_MASK)); + switch (type) { + case ETHER_GRE_TCP: + case ETHER_VLAN_GRE_TCP: + return (RTE_ETH_IS_IPV4_HDR(ptype) > 0) ? + IS_INNER_IPV4_HDR(ptype & RTE_PTYPE_INNER_L3_MASK) : 0; + default: + return 0; + } +} + /** * Internal function which updates relevant packet headers, following * segmentation. This is required to update, for example, the IPv4 diff --git a/lib/librte_gso/rte_gso.c b/lib/librte_gso/rte_gso.c index 226c75a..e0925ae 100644 --- a/lib/librte_gso/rte_gso.c +++ b/lib/librte_gso/rte_gso.c @@ -67,7 +67,8 @@ rte_gso_segment(struct rte_mbuf *pkt, gso_size = gso_ctx.gso_size; ipid_delta = gso_ctx.ipid_flag == RTE_GSO_IPID_INCREASE; - if (is_ipv4_vxlan_ipv4_tcp(pkt->packet_type)) { + if (is_ipv4_vxlan_ipv4_tcp(pkt->packet_type) || + is_ipv4_gre_ipv4_tcp(pkt->packet_type)) { ret = gso_tunnel_tcp4_segment(pkt, gso_size, ipid_delta, direct_pool, indirect_pool, pkts_out, nb_pkts_out);