[dpdk-dev,RFC] testpmd: handle UFO packets

Message ID 1519464907-133452-1-git-send-email-jianfeng.tan@intel.com (mailing list archive)
State Changes Requested, archived
Headers

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel-compilation success Compilation OK

Commit Message

Jianfeng Tan Feb. 24, 2018, 9:35 a.m. UTC
  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 <jianfeng.tan@intel.com>
---
 app/test-pmd/csumonly.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 98 insertions(+)
  

Comments

Jason Wang Feb. 28, 2018, 2:10 p.m. UTC | #1
On 2018年02月24日 17:35, Jianfeng Tan wrote:
> 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

Just a reminder, UFO was completely removed upstream.

Thanks
  
Jianfeng Tan Feb. 28, 2018, 2:53 p.m. UTC | #2
Hi Jason,


On 2/28/2018 10:10 PM, Jason Wang wrote:
>
>
> On 2018年02月24日 17:35, Jianfeng Tan wrote:
>> 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
>
> Just a reminder, UFO was completely removed upstream.
>

Thank you for the information.

Saw the deprecation patch at Linux v4.16-rc3, wonder what "version+" 
counts "merden kernels" in "modern kernels will no longer generate UFO 
skbs"? And this is mostly for stock VMs with old kernels to help the 
migration from kernel vswitch to user space vswitch.

Will other OSes generate UFO packets, FreeBSD, Windows? Anyone can 
provide such information?

Thanks,
Jianfeng
  
Jason Wang March 1, 2018, 8:36 a.m. UTC | #3
On 2018年02月28日 22:53, Tan, Jianfeng wrote:
> Hi Jason,
>
>
> On 2/28/2018 10:10 PM, Jason Wang wrote:
>>
>>
>> On 2018年02月24日 17:35, Jianfeng Tan wrote:
>>> 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
>>
>> Just a reminder, UFO was completely removed upstream.
>>
>
> Thank you for the information.
>
> Saw the deprecation patch at Linux v4.16-rc3, wonder what "version+" 
> counts "merden kernels" in "modern kernels will no longer generate UFO 
> skbs"? 

git describe d9d30adf56777c402c0027c0e6ae21f17cc0a365
v4.12-11055-gd9d30ad

So I think any Linux version beyond 4.12 won't generate any UFO packets.

> And this is mostly for stock VMs with old kernels to help the 
> migration from kernel vswitch to user space vswitch.
>

Yes, testpmd may still see UFO packets for old kernels. Just a reminder 
in case you miss it.

(Btw, we plan to support UDP tunnel offload for virtio-net.)

> Will other OSes generate UFO packets, FreeBSD, Windows? Anyone can 
> provide such information?

I don't know about them.

Thanks.

>
> Thanks,
> Jianfeng
>
>
  

Patch

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 <rte_flow.h>
 #include <rte_gro.h>
 #include <rte_gso.h>
+#include <rte_ip_frag.h>
 
 #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,