Patchwork [4/7] tap: set IFF_ONE_QUEUE per default

login
register
mail settings
Submitter Stefan Hajnoczi
Date Feb. 27, 2013, 3:22 p.m.
Message ID <1361978545-13789-5-git-send-email-stefanha@redhat.com>
Download mbox | patch
Permalink /patch/223637/
State New
Headers show

Comments

Stefan Hajnoczi - Feb. 27, 2013, 3:22 p.m.
From: Peter Lieven <pl@dlhnet.de>

historically the kernel queues packets two times. once
at the device and second in qdisc. this is believed to cause
interface stalls if one of these queues overruns.

setting IFF_ONE_QUEUE is the default in kernels >= 3.8. the
flag is ignored since then. see kernel commit
5d097109257c03a71845729f8db6b5770c4bbedc

Signed-off-by: Peter Lieven <pl@kamp.de>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 net/tap-linux.c | 10 ++++++----
 net/tap-linux.h |  9 +++++----
 2 files changed, 11 insertions(+), 8 deletions(-)

Patch

diff --git a/net/tap-linux.c b/net/tap-linux.c
index a953189..36c09e2 100644
--- a/net/tap-linux.c
+++ b/net/tap-linux.c
@@ -42,6 +42,7 @@  int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
     struct ifreq ifr;
     int fd, ret;
     int len = sizeof(struct virtio_net_hdr);
+    unsigned int features;
 
     TFR(fd = open(PATH_NET_TUN, O_RDWR));
     if (fd < 0) {
@@ -51,9 +52,12 @@  int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
     memset(&ifr, 0, sizeof(ifr));
     ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
 
-    if (*vnet_hdr) {
-        unsigned int features;
+    if (ioctl(fd, TUNGETFEATURES, &features) == 0 &&
+        features & IFF_ONE_QUEUE) {
+        ifr.ifr_flags |= IFF_ONE_QUEUE;
+    }
 
+    if (*vnet_hdr) {
         if (ioctl(fd, TUNGETFEATURES, &features) == 0 &&
             features & IFF_VNET_HDR) {
             *vnet_hdr = 1;
@@ -78,8 +82,6 @@  int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
     }
 
     if (mq_required) {
-        unsigned int features;
-
         if ((ioctl(fd, TUNGETFEATURES, &features) != 0) ||
             !(features & IFF_MULTI_QUEUE)) {
             error_report("multiqueue required, but no kernel "
diff --git a/net/tap-linux.h b/net/tap-linux.h
index 65087e1..1cf35d4 100644
--- a/net/tap-linux.h
+++ b/net/tap-linux.h
@@ -34,10 +34,11 @@ 
 #endif
 
 /* TUNSETIFF ifr flags */
-#define IFF_TAP		0x0002
-#define IFF_NO_PI	0x1000
-#define IFF_VNET_HDR	0x4000
-#define IFF_MULTI_QUEUE 0x0100
+#define IFF_TAP          0x0002
+#define IFF_NO_PI        0x1000
+#define IFF_ONE_QUEUE    0x2000
+#define IFF_VNET_HDR     0x4000
+#define IFF_MULTI_QUEUE  0x0100
 #define IFF_ATTACH_QUEUE 0x0200
 #define IFF_DETACH_QUEUE 0x0400