From patchwork Sat Feb 24 09:35:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jianfeng Tan X-Patchwork-Id: 35381 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 DDC452C24; Sat, 24 Feb 2018 10:33:22 +0100 (CET) Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by dpdk.org (Postfix) with ESMTP id A7136288C for ; Sat, 24 Feb 2018 10:33:20 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 24 Feb 2018 01:33:19 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.47,386,1515484800"; d="scan'208";a="22764253" Received: from dpdk06.sh.intel.com ([10.67.110.196]) by fmsmga002.fm.intel.com with ESMTP; 24 Feb 2018 01:33:18 -0800 From: Jianfeng Tan To: dev@dpdk.org Cc: Jianfeng Tan Date: Sat, 24 Feb 2018 09:35:07 +0000 Message-Id: <1519464907-133452-1-git-send-email-jianfeng.tan@intel.com> X-Mailer: git-send-email 2.7.4 Subject: [dpdk-dev] [RFC] testpmd: handle UFO packets 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" Mostly likely, we will make UFO as a kind of GSO engine. For short term, we can just call APIs in librte_ip_frag to fragment. To test: 1. start testpmd with two vhost port. $ set fwd csum $ start 2. start vm0 connected to vhost0; $ ifconfig xxx 1.1.1.1/24 up $ ethtool -K xxx ufo on 3. start vm1 connected to vhost1; $ ifconfig xxx 1.1.1.2/24 up $ ethtool -K xxx ufo on $ (Fill a large file named 1.txt) $ cat 1.txt | socat - udp-sendto:1.1.1.1:5000 Signed-off-by: Jianfeng Tan --- app/test-pmd/csumonly.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c index 5f5ab64..3e4c414 100644 --- a/app/test-pmd/csumonly.c +++ b/app/test-pmd/csumonly.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "testpmd.h" @@ -574,6 +575,75 @@ pkt_copy_split(const struct rte_mbuf *pkt) return md[0]; } +static inline void +frag_v4_fixup(const struct rte_mbuf *ms, struct rte_mbuf *mf) +{ + struct ipv4_hdr *l3h; + + mf->ol_flags = ms->ol_flags; + mf->tx_offload = ms->tx_offload; + + if ((ms->ol_flags & PKT_TX_IP_CKSUM) == 0) { + l3h = rte_pktmbuf_mtod(mf, struct ipv4_hdr *); + l3h->hdr_checksum = rte_ipv4_cksum(l3h); + } +} + +/* + * Returns negative for failure to fragment or actual number of fragments. + */ +static inline int +fragment(struct rte_mbuf *m, struct rte_mbuf *frag[], uint32_t num) +{ + void *l2; + int l2_len; + int32_t frag_num, i; + uint16_t ether_type; + struct ether_hdr *eth_hdr; + + eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); + ether_type = eth_hdr->ether_type; + m->l2_len = sizeof(*eth_hdr); + if (ether_type == ETHER_TYPE_VLAN) { + struct vlan_hdr *vlan_hdr = (struct vlan_hdr *)(eth_hdr + 1); + ether_type = rte_be_to_cpu_16(vlan_hdr->eth_proto); + m->l2_len += sizeof(struct vlan_hdr); + } + l2_len = m->l2_len; + + /* store the l2 header */ + uint8_t l2_hdr[l2_len]; + rte_memcpy(l2_hdr, eth_hdr, l2_len); + + /* Remove the l2 header from the input packet */ + rte_pktmbuf_adj(m, l2_len); + + if (ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) + frag_num = rte_ipv4_fragment_packet(m, frag, num, + m->tso_segsz, current_fwd_lcore()->mbp, + current_fwd_lcore()->mbp); + else + frag_num = rte_ipv6_fragment_packet(m, frag, num, + m->tso_segsz, current_fwd_lcore()->mbp, + current_fwd_lcore()->mbp); + + if (frag_num > 0) { + for (i = 0; i != frag_num; i++) { + + if (ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) + frag_v4_fixup(m, frag[i]); + + /* Move data_off to include l2 header first */ + l2 = rte_pktmbuf_prepend(frag[i], l2_len); + + /* copy l2 header into fragmented packet */ + rte_memcpy(l2, l2_hdr, l2_len); + } + } + + return frag_num; +} + /* * Receive a burst of packets, and for each packet: * - parse packet, and try to recognize a supported packet type (1) @@ -603,6 +673,7 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct rte_mbuf *gso_segments[GSO_MAX_PKT_BURST]; + struct rte_mbuf *ufo_segments[GSO_MAX_PKT_BURST]; struct rte_gso_ctx *gso_ctx; struct rte_mbuf **tx_pkts_burst; struct rte_port *txp; @@ -656,6 +727,32 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) if (gso_ports[fs->tx_port].enable) info.gso_enable = 1; + nb_segments = 0; + for (i = 0; i < nb_rx; ++i) { + m = pkts_burst[i]; + if (!(m->ol_flags & PKT_TX_UDP_SEG)) { + ufo_segments[nb_segments++] = m; + continue; + } + + ret = fragment(m, &ufo_segments[nb_segments], + RTE_DIM(ufo_segments) - nb_segments); + if (ret <= 0) { + printf("ip frag failed %s\n", strerror(-ret)); + rte_pktmbuf_free(m); + continue; + } + nb_segments += ret; + /* free the original packet */ + rte_pktmbuf_free(m); + } + + nb_rx = RTE_MIN(nb_segments, MAX_PKT_BURST); + for (i = 0; i < nb_rx; i++) + pkts_burst[i] = ufo_segments[i]; + for (i = nb_rx; i < nb_segments; ++i) + rte_pktmbuf_free(ufo_segments[i]); + for (i = 0; i < nb_rx; i++) { if (likely(i < nb_rx - 1)) rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1], @@ -832,6 +929,7 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) } } + nb_segments = 0; if (unlikely(gro_enable)) { if (gro_flush_cycles == GRO_DEFAULT_FLUSH_CYCLES) { nb_rx = rte_gro_reassemble_burst(pkts_burst, nb_rx,