netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Florian Westphal <fw@strlen.de>
To: netdev@vger.kernel.org
Cc: Florian Westphal <fw@strlen.de>
Subject: [PATCH -next] tun: stop tx queue when limit is hit
Date: Sun, 20 Jul 2014 20:51:25 +0200	[thread overview]
Message-ID: <1405882285-3072-1-git-send-email-fw@strlen.de> (raw)

Currently tun just frees the skb and returns NETDEV_TX_OK
when queue length exceeds txqlen.

This causes severe packetloss and unneeded resource
consumption on host when sending to vm connected via tun.

Instead, lets stop the transmit queue and start it once
packets are consumed from the queue.  This allows the network
stack to control applications that send data via tun device.

Before:
time netperf -H 10.1.1.2 -t UDP_STREAM -- -m 1024
Socket  Message  Elapsed      Messages
Size    Size     Time         Okay Errors   Throughput
bytes   bytes    secs            #      #   10^6bits/sec

212992    1024   10.00     5712540      0    4679.65
212992           10.00      804441            658.99
0.40s user 9.62s system 71% cpu 14.030 total

After:
time netperf -H 10.1.1.2 -t UDP_STREAM -- -m 1024
Socket  Message  Elapsed      Messages
Size    Size     Time         Okay Errors   Throughput
bytes   bytes    secs            #      #   10^6bits/sec
212992    1024   10.00     2060473      0    1687.92
212992           10.00      904187            740.70
0.18s user 5.14s system 37% cpu 14.028 total

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 drivers/net/tun.c | 42 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 36 insertions(+), 6 deletions(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index acaaf67..c020215 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -733,6 +733,24 @@ static int tun_net_close(struct net_device *dev)
 	return 0;
 }
 
+static unsigned long tun_queue_len(const struct tun_file *tfile, u32 numqueues)
+{
+	return skb_queue_len(&tfile->socket.sk->sk_receive_queue) * numqueues;
+}
+
+static bool tun_queue_should_stop(const struct net_device *dev,
+				  const struct tun_file *tfile, u32 numqueues)
+{
+	return tun_queue_len(tfile, numqueues) > dev->tx_queue_len;
+}
+
+static bool tun_queue_should_wake(const struct net_device *dev,
+				  const struct tun_file *tfile, u32 numqueues)
+{
+	return !tun_queue_should_stop(dev, tfile, numqueues);
+}
+
+
 /* Net device start xmit */
 static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
 {
@@ -779,12 +797,19 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
 	    sk_filter(tfile->socket.sk, skb))
 		goto drop;
 
-	/* Limit the number of packets queued by dividing txq length with the
-	 * number of queues.
-	 */
-	if (skb_queue_len(&tfile->socket.sk->sk_receive_queue) * numqueues
-			  >= dev->tx_queue_len)
-		goto drop;
+	if (tun_queue_should_stop(dev, tfile, numqueues)) {
+		if (netif_subqueue_stopped(dev, skb))
+			goto drop;
+
+		netif_stop_subqueue(dev, txq);
+
+		/* concurrent reader must not miss 'stopped queue' */
+		smp_mb__after_atomic();
+
+		/* reader might have drained queue before stop_subqueue */
+		if (tun_queue_should_wake(dev, tfile, numqueues))
+			netif_start_subqueue(dev, txq);
+	}
 
 	if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
 		goto drop;
@@ -1346,6 +1371,11 @@ static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,
 				  &peeked, &off, &err);
 	if (skb) {
 		ret = tun_put_user(tun, tfile, skb, iv, len);
+
+		if (netif_subqueue_stopped(tun->dev, skb) &&
+		    tun_queue_should_wake(tun->dev, tfile, tun->numqueues))
+			netif_wake_subqueue(tun->dev, skb->queue_mapping);
+
 		kfree_skb(skb);
 	} else
 		ret = err;
-- 
1.8.1.5

             reply	other threads:[~2014-07-20 18:58 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-20 18:51 Florian Westphal [this message]
2014-07-21  5:33 ` [PATCH -next] tun: stop tx queue when limit is hit David Miller
2014-07-21  6:54   ` Florian Westphal
2014-07-21  8:31     ` Florian Westphal
2014-07-21  8:56       ` Eric Dumazet
2014-07-21  9:19         ` Florian Westphal

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1405882285-3072-1-git-send-email-fw@strlen.de \
    --to=fw@strlen.de \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).