From: Jason Wang <hidden> Date: 2017-08-11 11:42:55
Hi all:
This series tries to implement XDP support for tap. Two path were
implemented:
- fast path: small & non-gso packet, For performance reason we do it
at page level and use build_skb() to create skb if necessary.
- slow path: big or gso packet, we don't want to lose the capability
compared to generic XDP, so we export some generic xdp helpers and
do it after skb was created.
xdp1 shows about 41% improvement, xdp_redirect shows about 60%
improvement.
Changes from V1:
- fix the race between xdp set and free
- don't hold extra refcount
- add XDP_REDIRECT support
Please review.
Jason Wang (3):
tap: use build_skb() for small packet
net: export some generic xdp helpers
tap: XDP support
drivers/net/tun.c | 247 ++++++++++++++++++++++++++++++++++++++++++----
include/linux/netdevice.h | 2 +
net/core/dev.c | 14 +--
3 files changed, 236 insertions(+), 27 deletions(-)
--
2.7.4
From: Jason Wang <hidden> Date: 2017-08-11 11:41:42
This patch tries to export some generic xdp helpers to drivers. This
can let driver to do XDP for a specific skb. This is useful for the
case when the packet is hard to be processed at page level directly
(e.g jumbo/GSO frame).
With this patch, there's no need for driver to forbid the XDP set when
configuration is not suitable. Instead, it can defer the XDP for
packets that is hard to be processed directly after skb is created.
Signed-off-by: Jason Wang <redacted>
---
include/linux/netdevice.h | 2 ++
net/core/dev.c | 14 ++++++++------
2 files changed, 10 insertions(+), 6 deletions(-)
@@ -3920,7 +3920,7 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb,/* When doing generic XDP we have to bypass the qdisc layer and the*networktapsinordertomatchin-driver-XDPbehavior.*/-staticvoidgeneric_xdp_tx(structsk_buff*skb,structbpf_prog*xdp_prog)+voidgeneric_xdp_tx(structsk_buff*skb,structbpf_prog*xdp_prog){structnet_device*dev=skb->dev;structnetdev_queue*txq;
From: Jason Wang <hidden> Date: 2017-08-11 11:41:47
This patch tries to implement XDP for tun. The implementation was
split into two parts:
- fast path: small and no gso packet. We try to do XDP at page level
before build_skb(). For XDP_TX, since creating/destroying queues
were completely under control of userspace, it was implemented
through generic XDP helper after skb has been built. This could be
optimized in the future.
- slow path: big or gso packet. We try to do it after skb was created
through generic XDP helpers.
Test were done through pktgen with small packets.
xdp1 test shows ~41.1% improvement:
Before: ~1.7Mpps
After: ~2.3Mpps
xdp_redirect to ixgbe shows ~60% improvement:
Before: ~0.8Mpps
After: ~1.38Mpps
Suggested-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <redacted>
---
drivers/net/tun.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 142 insertions(+), 7 deletions(-)
@@ -1238,16 +1293,77 @@ static struct sk_buff *tun_build_skb(struct tun_file *tfile,if(copied!=len)returnERR_PTR(-EFAULT);+if(hdr->gso_type)+*generic_xdp=1;+else+*generic_xdp=0;++rcu_read_lock();+xdp_prog=rcu_dereference(tun->xdp_prog);+if(xdp_prog&&!*generic_xdp){+structxdp_buffxdp;+void*orig_data;+u32act;++xdp.data_hard_start=buf;+xdp.data=buf+TUN_RX_PAD;+xdp.data_end=xdp.data+len;+orig_data=xdp.data;+act=bpf_prog_run_xdp(xdp_prog,&xdp);++switch(act){+caseXDP_REDIRECT:+get_page(alloc_frag->page);+alloc_frag->offset+=buflen;+err=xdp_do_redirect(tun->dev,&xdp,xdp_prog);+if(err)+gotoerr_redirect;+returnNULL;+caseXDP_TX:+xdp_xmit=true;+/* fall through */+caseXDP_PASS:+delta=orig_data-xdp.data;+break;+default:+bpf_warn_invalid_xdp_action(act);+/* fall through */+caseXDP_ABORTED:+trace_xdp_exception(tun->dev,xdp_prog,act);+/* fall through */+caseXDP_DROP:+gotoerr_xdp;+}+}+skb=build_skb(buf,buflen);-if(!skb)+if(!skb){+rcu_read_unlock();returnERR_PTR(-ENOMEM);+}-skb_reserve(skb,TUN_RX_PAD);-skb_put(skb,len);+skb_reserve(skb,TUN_RX_PAD-delta);+skb_put(skb,len+delta);get_page(alloc_frag->page);alloc_frag->offset+=buflen;+if(xdp_xmit){+skb->dev=tun->dev;+generic_xdp_tx(skb,xdp_prog);+rcu_read_lock();+returnNULL;+}++rcu_read_unlock();+returnskb;++err_redirect:+put_page(alloc_frag->page);+err_xdp:+rcu_read_unlock();+this_cpu_inc(tun->pcpu_stats->rx_dropped);+returnNULL;}/* Get packet from user space buffer */
From: Jason Wang <hidden> Date: 2017-08-11 11:42:27
We use tun_alloc_skb() which calls sock_alloc_send_pskb() to allocate
skb in the past. This socket based method is not suitable for high
speed userspace like virtualization which usually:
- ignore sk_sndbuf (INT_MAX) and expect to receive the packet as fast as
possible
- don't want to be block at sendmsg()
To eliminate the above overheads, this patch tries to use build_skb()
for small packet. We will do this only when the following conditions
are all met:
- TAP instead of TUN
- sk_sndbuf is INT_MAX
- caller don't want to be blocked
- zerocopy is not used
- packet size is smaller enough to use build_skb()
Pktgen from guest to host shows ~11% improvement for rx pps of tap:
Before: ~1.70Mpps
After : ~1.88Mpps
What's more important, this makes it possible to implement XDP for tap
before creating skbs.
Signed-off-by: Jason Wang <redacted>
---
drivers/net/tun.c | 112 ++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 91 insertions(+), 21 deletions(-)
@@ -105,6 +105,8 @@ do { \}while(0)#endif+#define TUN_RX_PAD (NET_IP_ALIGN + NET_SKB_PAD)+/* TUN device flags *//* IFF_ATTACH_QUEUE is never stored in device flags,
@@ -1190,6 +1195,61 @@ static void tun_rx_batched(struct tun_struct *tun, struct tun_file *tfile,}}+staticbooltun_can_build_skb(structtun_struct*tun,structtun_file*tfile,+intlen,intnoblock,boolzerocopy)+{+if((tun->flags&TUN_TYPE_MASK)!=IFF_TAP)+returnfalse;++if(tfile->socket.sk->sk_sndbuf!=INT_MAX)+returnfalse;++if(!noblock)+returnfalse;++if(zerocopy)+returnfalse;++if(SKB_DATA_ALIGN(len+TUN_RX_PAD)++SKB_DATA_ALIGN(sizeof(structskb_shared_info))>PAGE_SIZE)+returnfalse;++returntrue;+}++staticstructsk_buff*tun_build_skb(structtun_file*tfile,+structiov_iter*from,+intlen)+{+structpage_frag*alloc_frag=&tfile->alloc_frag;+structsk_buff*skb;+intbuflen=SKB_DATA_ALIGN(len+TUN_RX_PAD)++SKB_DATA_ALIGN(sizeof(structskb_shared_info));+char*buf;+size_tcopied;++if(unlikely(!skb_page_frag_refill(buflen,alloc_frag,GFP_KERNEL)))+returnERR_PTR(-ENOMEM);++buf=(char*)page_address(alloc_frag->page)+alloc_frag->offset;+copied=copy_page_from_iter(alloc_frag->page,+alloc_frag->offset+TUN_RX_PAD,+len,from);+if(copied!=len)+returnERR_PTR(-EFAULT);++skb=build_skb(buf,buflen);+if(!skb)+returnERR_PTR(-ENOMEM);++skb_reserve(skb,TUN_RX_PAD);+skb_put(skb,len);+get_page(alloc_frag->page);+alloc_frag->offset+=buflen;++returnskb;+}+/* Get packet from user space buffer */staticssize_ttun_get_user(structtun_struct*tun,structtun_file*tfile,void*msg_control,structiov_iter*from,
From: Jakub Kicinski <hidden> Date: 2017-08-11 23:12:33
On Fri, 11 Aug 2017 19:41:18 +0800, Jason Wang wrote:
This patch tries to implement XDP for tun. The implementation was
split into two parts:
- fast path: small and no gso packet. We try to do XDP at page level
before build_skb(). For XDP_TX, since creating/destroying queues
were completely under control of userspace, it was implemented
through generic XDP helper after skb has been built. This could be
optimized in the future.
- slow path: big or gso packet. We try to do it after skb was created
through generic XDP helpers.
Test were done through pktgen with small packets.
xdp1 test shows ~41.1% improvement:
Before: ~1.7Mpps
After: ~2.3Mpps
xdp_redirect to ixgbe shows ~60% improvement:
Before: ~0.8Mpps
After: ~1.38Mpps
Suggested-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <redacted>
Looks OK to me now :)
Out of curiosity, you say the build_skb() is for "small packets", and it
seems you are always reserving the 256B regardless of XDP being
installed. Does this have no performance impact on non-XDP case?
From: Jason Wang <hidden> Date: 2017-08-12 02:49:00
On 2017年08月12日 07:12, Jakub Kicinski wrote:
On Fri, 11 Aug 2017 19:41:18 +0800, Jason Wang wrote:
quoted
This patch tries to implement XDP for tun. The implementation was
split into two parts:
- fast path: small and no gso packet. We try to do XDP at page level
before build_skb(). For XDP_TX, since creating/destroying queues
were completely under control of userspace, it was implemented
through generic XDP helper after skb has been built. This could be
optimized in the future.
- slow path: big or gso packet. We try to do it after skb was created
through generic XDP helpers.
Test were done through pktgen with small packets.
xdp1 test shows ~41.1% improvement:
Before: ~1.7Mpps
After: ~2.3Mpps
xdp_redirect to ixgbe shows ~60% improvement:
Before: ~0.8Mpps
After: ~1.38Mpps
Suggested-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <redacted>
Looks OK to me now :)
Out of curiosity, you say the build_skb() is for "small packets", and it
seems you are always reserving the 256B regardless of XDP being
installed. Does this have no performance impact on non-XDP case?
Have a test, only less than 1% were noticed which I think could be ignored.
Thanks
From: David Miller <davem@davemloft.net> Date: 2017-08-14 02:56:51
From: Jason Wang <redacted>
Date: Fri, 11 Aug 2017 19:41:15 +0800
Hi all:
This series tries to implement XDP support for tap. Two path were
implemented:
- fast path: small & non-gso packet, For performance reason we do it
at page level and use build_skb() to create skb if necessary.
- slow path: big or gso packet, we don't want to lose the capability
compared to generic XDP, so we export some generic xdp helpers and
do it after skb was created.
xdp1 shows about 41% improvement, xdp_redirect shows about 60%
improvement.
Changes from V1:
- fix the race between xdp set and free
- don't hold extra refcount
- add XDP_REDIRECT support
Please review.
The name generic_xdp is a bit confusing in this context given this
is 'native' XDP, perhaps above if (generic_xdp) should have a comment
explaining semantics for tun and how it relates to actual generic xdp
that sits at dev->xdp_prog, and gets run from netif_rx_ni(). Or just
name the bool xdp_handle_gso with a comment that we let the generic
XDP infrastructure deal with non-linear skbs instead of having to
re-implement the do_xdp_generic() internals, plus a statement that
the actual generic XDP comes a bit later in the path. That would at
least make it more obvious to read, imho.
quoted hunk
+ if (xdp_prog) {+ ret = do_xdp_generic(xdp_prog, skb);+ if (ret != XDP_PASS) {+ rcu_read_unlock();+ return total_len;+ }+ }+ rcu_read_unlock();+ }+ rxhash = __skb_get_hash_symmetric(skb); #ifndef CONFIG_4KSTACKS tun_rx_batched(tun, tfile, skb, more);
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2017-08-14 16:01:11
On Sat, Aug 12, 2017 at 10:48:49AM +0800, Jason Wang wrote:
On 2017年08月12日 07:12, Jakub Kicinski wrote:
quoted
On Fri, 11 Aug 2017 19:41:18 +0800, Jason Wang wrote:
quoted
This patch tries to implement XDP for tun. The implementation was
split into two parts:
- fast path: small and no gso packet. We try to do XDP at page level
before build_skb(). For XDP_TX, since creating/destroying queues
were completely under control of userspace, it was implemented
through generic XDP helper after skb has been built. This could be
optimized in the future.
- slow path: big or gso packet. We try to do it after skb was created
through generic XDP helpers.
Test were done through pktgen with small packets.
xdp1 test shows ~41.1% improvement:
Before: ~1.7Mpps
After: ~2.3Mpps
xdp_redirect to ixgbe shows ~60% improvement:
Before: ~0.8Mpps
After: ~1.38Mpps
Suggested-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <redacted>
Looks OK to me now :)
Out of curiosity, you say the build_skb() is for "small packets", and it
seems you are always reserving the 256B regardless of XDP being
installed. Does this have no performance impact on non-XDP case?
Have a test, only less than 1% were noticed which I think could be ignored.
Thanks
What did you test btw? The biggest issue would be with something like
UDP with short packets.
--
MST
The name generic_xdp is a bit confusing in this context given this
is 'native' XDP, perhaps above if (generic_xdp) should have a comment
explaining semantics for tun and how it relates to actual generic xdp
that sits at dev->xdp_prog, and gets run from netif_rx_ni(). Or just
name the bool xdp_handle_gso with a comment that we let the generic
XDP infrastructure deal with non-linear skbs instead of having to
re-implement the do_xdp_generic() internals, plus a statement that
the actual generic XDP comes a bit later in the path. That would at
least make it more obvious to read, imho.
Ok, since non gso packet (e.g jumbo packet) may go this way too, something like "xdp_handle_skb" is better. Will send a patch.
Thanks
quoted
+ if (xdp_prog) {+ ret = do_xdp_generic(xdp_prog, skb);+ if (ret != XDP_PASS) {+ rcu_read_unlock();+ return total_len;+ }+ }+ rcu_read_unlock();+ }+ rxhash = __skb_get_hash_symmetric(skb); #ifndef CONFIG_4KSTACKS tun_rx_batched(tun, tfile, skb, more);
From: Jason Wang <hidden> Date: 2017-08-15 05:02:14
On 2017年08月15日 00:01, Michael S. Tsirkin wrote:
On Sat, Aug 12, 2017 at 10:48:49AM +0800, Jason Wang wrote:
quoted
On 2017年08月12日 07:12, Jakub Kicinski wrote:
quoted
On Fri, 11 Aug 2017 19:41:18 +0800, Jason Wang wrote:
quoted
This patch tries to implement XDP for tun. The implementation was
split into two parts:
- fast path: small and no gso packet. We try to do XDP at page level
before build_skb(). For XDP_TX, since creating/destroying queues
were completely under control of userspace, it was implemented
through generic XDP helper after skb has been built. This could be
optimized in the future.
- slow path: big or gso packet. We try to do it after skb was created
through generic XDP helpers.
Test were done through pktgen with small packets.
xdp1 test shows ~41.1% improvement:
Before: ~1.7Mpps
After: ~2.3Mpps
xdp_redirect to ixgbe shows ~60% improvement:
Before: ~0.8Mpps
After: ~1.38Mpps
Suggested-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <redacted>
Looks OK to me now :)
Out of curiosity, you say the build_skb() is for "small packets", and it
seems you are always reserving the 256B regardless of XDP being
installed. Does this have no performance impact on non-XDP case?
Have a test, only less than 1% were noticed which I think could be ignored.
Thanks
What did you test btw?
Pktgen
The biggest issue would be with something like
UDP with short packets.
Note that we do this only when sndbuf is INT_MAX. So this is probably not an issue. The only thing matter is more stress to page allocator, but according to the result of pktgen it was very small that could be ignored.
Thanks
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2017-08-16 03:45:40
On Tue, Aug 15, 2017 at 01:02:05PM +0800, Jason Wang wrote:
On 2017年08月15日 00:01, Michael S. Tsirkin wrote:
quoted
On Sat, Aug 12, 2017 at 10:48:49AM +0800, Jason Wang wrote:
quoted
On 2017年08月12日 07:12, Jakub Kicinski wrote:
quoted
On Fri, 11 Aug 2017 19:41:18 +0800, Jason Wang wrote:
quoted
This patch tries to implement XDP for tun. The implementation was
split into two parts:
- fast path: small and no gso packet. We try to do XDP at page level
before build_skb(). For XDP_TX, since creating/destroying queues
were completely under control of userspace, it was implemented
through generic XDP helper after skb has been built. This could be
optimized in the future.
- slow path: big or gso packet. We try to do it after skb was created
through generic XDP helpers.
Test were done through pktgen with small packets.
xdp1 test shows ~41.1% improvement:
Before: ~1.7Mpps
After: ~2.3Mpps
xdp_redirect to ixgbe shows ~60% improvement:
Before: ~0.8Mpps
After: ~1.38Mpps
Suggested-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <redacted>
Looks OK to me now :)
Out of curiosity, you say the build_skb() is for "small packets", and it
seems you are always reserving the 256B regardless of XDP being
installed. Does this have no performance impact on non-XDP case?
Have a test, only less than 1% were noticed which I think could be ignored.
Thanks
What did you test btw?
Pktgen
quoted
The biggest issue would be with something like
UDP with short packets.
Note that we do this only when sndbuf is INT_MAX. So this is probably not an
issue.
I'd expect to see the issue for guest to host when the packets are
queued at a UDP socket in host.
The only thing matter is more stress to page allocator, but according
to the result of pktgen it was very small that could be ignored.
Thanks
Besides guest to host, for bridging in host bigger truesize might affect
byte queue counts as well.
--
MST
From: Eric Dumazet <hidden> Date: 2017-08-16 03:45:49
On Fri, 2017-08-11 at 19:41 +0800, Jason Wang wrote:
We use tun_alloc_skb() which calls sock_alloc_send_pskb() to allocate
skb in the past. This socket based method is not suitable for high
speed userspace like virtualization which usually:
- ignore sk_sndbuf (INT_MAX) and expect to receive the packet as fast as
possible
- don't want to be block at sendmsg()
To eliminate the above overheads, this patch tries to use build_skb()
for small packet. We will do this only when the following conditions
are all met:
- TAP instead of TUN
- sk_sndbuf is INT_MAX
- caller don't want to be blocked
- zerocopy is not used
- packet size is smaller enough to use build_skb()
Pktgen from guest to host shows ~11% improvement for rx pps of tap:
Before: ~1.70Mpps
After : ~1.88Mpps
What's more important, this makes it possible to implement XDP for tap
before creating skbs.
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2017-08-16 03:55:18
On Tue, Aug 15, 2017 at 08:45:20PM -0700, Eric Dumazet wrote:
On Fri, 2017-08-11 at 19:41 +0800, Jason Wang wrote:
quoted
We use tun_alloc_skb() which calls sock_alloc_send_pskb() to allocate
skb in the past. This socket based method is not suitable for high
speed userspace like virtualization which usually:
- ignore sk_sndbuf (INT_MAX) and expect to receive the packet as fast as
possible
- don't want to be block at sendmsg()
To eliminate the above overheads, this patch tries to use build_skb()
for small packet. We will do this only when the following conditions
are all met:
- TAP instead of TUN
- sk_sndbuf is INT_MAX
- caller don't want to be blocked
- zerocopy is not used
- packet size is smaller enough to use build_skb()
Pktgen from guest to host shows ~11% improvement for rx pps of tap:
Before: ~1.70Mpps
After : ~1.88Mpps
What's more important, this makes it possible to implement XDP for tap
before creating skbs.
Well well well.
You do realize that tun_build_skb() is not thread safe ?
The issue is alloc frag, isn't it?
I guess for now we can limit this to XDP mode only, and
just allocate full pages in that mode.
From: Jason Wang <hidden> Date: 2017-08-16 03:56:05
On 2017年08月16日 11:45, Eric Dumazet wrote:
On Fri, 2017-08-11 at 19:41 +0800, Jason Wang wrote:
quoted
We use tun_alloc_skb() which calls sock_alloc_send_pskb() to allocate
skb in the past. This socket based method is not suitable for high
speed userspace like virtualization which usually:
- ignore sk_sndbuf (INT_MAX) and expect to receive the packet as fast as
possible
- don't want to be block at sendmsg()
To eliminate the above overheads, this patch tries to use build_skb()
for small packet. We will do this only when the following conditions
are all met:
- TAP instead of TUN
- sk_sndbuf is INT_MAX
- caller don't want to be blocked
- zerocopy is not used
- packet size is smaller enough to use build_skb()
Pktgen from guest to host shows ~11% improvement for rx pps of tap:
Before: ~1.70Mpps
After : ~1.88Mpps
What's more important, this makes it possible to implement XDP for tap
before creating skbs.
Well well well.
You do realize that tun_build_skb() is not thread safe ?
Ok, I think the issue if skb_page_frag_refill(), need a spinlock probably. Will prepare a patch.
Thanks
From: Jason Wang <hidden> Date: 2017-08-16 03:57:59
On 2017年08月16日 11:55, Michael S. Tsirkin wrote:
On Tue, Aug 15, 2017 at 08:45:20PM -0700, Eric Dumazet wrote:
quoted
On Fri, 2017-08-11 at 19:41 +0800, Jason Wang wrote:
quoted
We use tun_alloc_skb() which calls sock_alloc_send_pskb() to allocate
skb in the past. This socket based method is not suitable for high
speed userspace like virtualization which usually:
- ignore sk_sndbuf (INT_MAX) and expect to receive the packet as fast as
possible
- don't want to be block at sendmsg()
To eliminate the above overheads, this patch tries to use build_skb()
for small packet. We will do this only when the following conditions
are all met:
- TAP instead of TUN
- sk_sndbuf is INT_MAX
- caller don't want to be blocked
- zerocopy is not used
- packet size is smaller enough to use build_skb()
Pktgen from guest to host shows ~11% improvement for rx pps of tap:
Before: ~1.70Mpps
After : ~1.88Mpps
What's more important, this makes it possible to implement XDP for tap
before creating skbs.
Well well well.
You do realize that tun_build_skb() is not thread safe ?
The issue is alloc frag, isn't it?
I guess for now we can limit this to XDP mode only, and
just allocate full pages in that mode.
Limit this to XDP mode only does not prevent user from sending packets to same queue in parallel I think?
Thanks
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2017-08-16 03:59:16
On Wed, Aug 16, 2017 at 11:57:51AM +0800, Jason Wang wrote:
On 2017年08月16日 11:55, Michael S. Tsirkin wrote:
quoted
On Tue, Aug 15, 2017 at 08:45:20PM -0700, Eric Dumazet wrote:
quoted
On Fri, 2017-08-11 at 19:41 +0800, Jason Wang wrote:
quoted
We use tun_alloc_skb() which calls sock_alloc_send_pskb() to allocate
skb in the past. This socket based method is not suitable for high
speed userspace like virtualization which usually:
- ignore sk_sndbuf (INT_MAX) and expect to receive the packet as fast as
possible
- don't want to be block at sendmsg()
To eliminate the above overheads, this patch tries to use build_skb()
for small packet. We will do this only when the following conditions
are all met:
- TAP instead of TUN
- sk_sndbuf is INT_MAX
- caller don't want to be blocked
- zerocopy is not used
- packet size is smaller enough to use build_skb()
Pktgen from guest to host shows ~11% improvement for rx pps of tap:
Before: ~1.70Mpps
After : ~1.88Mpps
What's more important, this makes it possible to implement XDP for tap
before creating skbs.
Well well well.
You do realize that tun_build_skb() is not thread safe ?
The issue is alloc frag, isn't it?
I guess for now we can limit this to XDP mode only, and
just allocate full pages in that mode.
Limit this to XDP mode only does not prevent user from sending packets to
same queue in parallel I think?
Thanks
Yes but then you can just drop the page frag allocator since
XDP is assumed not to care about truesize for most packets.
--
MST
From: Jason Wang <hidden> Date: 2017-08-16 04:07:34
On 2017年08月16日 11:59, Michael S. Tsirkin wrote:
On Wed, Aug 16, 2017 at 11:57:51AM +0800, Jason Wang wrote:
quoted
On 2017年08月16日 11:55, Michael S. Tsirkin wrote:
quoted
On Tue, Aug 15, 2017 at 08:45:20PM -0700, Eric Dumazet wrote:
quoted
On Fri, 2017-08-11 at 19:41 +0800, Jason Wang wrote:
quoted
We use tun_alloc_skb() which calls sock_alloc_send_pskb() to allocate
skb in the past. This socket based method is not suitable for high
speed userspace like virtualization which usually:
- ignore sk_sndbuf (INT_MAX) and expect to receive the packet as fast as
possible
- don't want to be block at sendmsg()
To eliminate the above overheads, this patch tries to use build_skb()
for small packet. We will do this only when the following conditions
are all met:
- TAP instead of TUN
- sk_sndbuf is INT_MAX
- caller don't want to be blocked
- zerocopy is not used
- packet size is smaller enough to use build_skb()
Pktgen from guest to host shows ~11% improvement for rx pps of tap:
Before: ~1.70Mpps
After : ~1.88Mpps
What's more important, this makes it possible to implement XDP for tap
before creating skbs.
Well well well.
You do realize that tun_build_skb() is not thread safe ?
The issue is alloc frag, isn't it?
I guess for now we can limit this to XDP mode only, and
just allocate full pages in that mode.
Limit this to XDP mode only does not prevent user from sending packets to
same queue in parallel I think?
Thanks
Yes but then you can just drop the page frag allocator since
XDP is assumed not to care about truesize for most packets.
Ok, let me do some test to see the numbers between the two methods first.
Thanks
From: Jason Wang <hidden> Date: 2017-08-16 09:17:56
On 2017年08月16日 12:07, Jason Wang wrote:
On 2017年08月16日 11:59, Michael S. Tsirkin wrote:
quoted
On Wed, Aug 16, 2017 at 11:57:51AM +0800, Jason Wang wrote:
quoted
On 2017年08月16日 11:55, Michael S. Tsirkin wrote:
quoted
On Tue, Aug 15, 2017 at 08:45:20PM -0700, Eric Dumazet wrote:
quoted
On Fri, 2017-08-11 at 19:41 +0800, Jason Wang wrote:
quoted
We use tun_alloc_skb() which calls sock_alloc_send_pskb() to allocate
skb in the past. This socket based method is not suitable for high
speed userspace like virtualization which usually:
- ignore sk_sndbuf (INT_MAX) and expect to receive the packet as fast as
possible
- don't want to be block at sendmsg()
To eliminate the above overheads, this patch tries to use build_skb()
for small packet. We will do this only when the following conditions
are all met:
- TAP instead of TUN
- sk_sndbuf is INT_MAX
- caller don't want to be blocked
- zerocopy is not used
- packet size is smaller enough to use build_skb()
Pktgen from guest to host shows ~11% improvement for rx pps of tap:
Before: ~1.70Mpps
After : ~1.88Mpps
What's more important, this makes it possible to implement XDP for tap
before creating skbs.
Well well well.
You do realize that tun_build_skb() is not thread safe ?
The issue is alloc frag, isn't it?
I guess for now we can limit this to XDP mode only, and
just allocate full pages in that mode.
Limit this to XDP mode only does not prevent user from sending packets to
same queue in parallel I think?
Thanks
Yes but then you can just drop the page frag allocator since
XDP is assumed not to care about truesize for most packets.
Ok, let me do some test to see the numbers between the two methods first.
Thanks
It looks like full page allocation just produce too much stress on the page allocator.
I get 1.58Mpps (full page) vs 1.95Mpps (page frag) with the patches attached.
Since non-XDP case can also benefit from build_skb(), I tend to use spinlock instead of full page in this case.
Thanks
From: Eric Dumazet <hidden> Date: 2017-08-16 10:24:49
On Wed, 2017-08-16 at 11:55 +0800, Jason Wang wrote:
On 2017年08月16日 11:45, Eric Dumazet wrote:
quoted
You do realize that tun_build_skb() is not thread safe ?
Ok, I think the issue if skb_page_frag_refill(), need a spinlock
probably. Will prepare a patch.
But since tun is used from process context, why don't you use the
per-thread generator (no lock involved)
tcp_sendmsg() uses this for GFP_KERNEL allocations.
Untested patch :
From: David Miller <davem@davemloft.net> Date: 2017-08-16 16:30:56
From: Jason Wang <redacted>
Date: Wed, 16 Aug 2017 17:17:45 +0800
It looks like full page allocation just produce too much stress on the
page allocator.
I get 1.58Mpps (full page) vs 1.95Mpps (page frag) with the patches
attached.
Yes, this is why drivers doing XDP tend to drift towards implementing
a local cache of pages.