diff options
author | Jason Wang <jasowang@redhat.com> | 2013-01-30 19:12:31 +0800 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2013-02-01 11:03:01 -0600 |
commit | 94fdc6d03034f594c53d5413590e23fcb7ffc268 (patch) | |
tree | cc87baf580b144ee06f8fab9f44963105966ea43 | |
parent | 5193e5fbb52a33f1f684b0d42d29a452dfd29e4a (diff) |
tap: add Linux multiqueue support
This patch add basic multiqueue support for Linux. When multiqueue is needed, we
will first check whether kernel support multiqueue tap before creating more
queues. Two new functions tap_fd_enable() and tap_fd_disable() were introduced
to enable and disable a specific queue. Since the multiqueue is only supported
in Linux, return error on other platforms.
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
-rw-r--r-- | net/tap-aix.c | 10 | ||||
-rw-r--r-- | net/tap-bsd.c | 11 | ||||
-rw-r--r-- | net/tap-haiku.c | 11 | ||||
-rw-r--r-- | net/tap-linux.c | 52 | ||||
-rw-r--r-- | net/tap-solaris.c | 11 | ||||
-rw-r--r-- | net/tap_int.h | 2 |
6 files changed, 97 insertions, 0 deletions
diff --git a/net/tap-aix.c b/net/tap-aix.c index aff6c527e9..66e0574fd7 100644 --- a/net/tap-aix.c +++ b/net/tap-aix.c @@ -59,3 +59,13 @@ void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo) { } + +int tap_fd_enable(int fd) +{ + return -1; +} + +int tap_fd_disable(int fd) +{ + return -1; +} diff --git a/net/tap-bsd.c b/net/tap-bsd.c index 01c705b4c0..cfc7a289f8 100644 --- a/net/tap-bsd.c +++ b/net/tap-bsd.c @@ -145,3 +145,14 @@ void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo) { } + +int tap_fd_enable(int fd) +{ + return -1; +} + +int tap_fd_disable(int fd) +{ + return -1; +} + diff --git a/net/tap-haiku.c b/net/tap-haiku.c index 08cc034cee..664d40fb4d 100644 --- a/net/tap-haiku.c +++ b/net/tap-haiku.c @@ -59,3 +59,14 @@ void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo) { } + +int tap_fd_enable(int fd) +{ + return -1; +} + +int tap_fd_disable(int fd) +{ + return -1; +} + diff --git a/net/tap-linux.c b/net/tap-linux.c index 0a6acc7d5a..bdb0a790c8 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -41,6 +41,7 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required struct ifreq ifr; int fd, ret; int len = sizeof(struct virtio_net_hdr); + int mq_required = 0; TFR(fd = open(PATH_NET_TUN, O_RDWR)); if (fd < 0) { @@ -76,6 +77,20 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required ioctl(fd, TUNSETVNETHDRSZ, &len); } + if (mq_required) { + unsigned int features; + + if ((ioctl(fd, TUNGETFEATURES, &features) != 0) || + !(features & IFF_MULTI_QUEUE)) { + error_report("multiqueue required, but no kernel " + "support for IFF_MULTI_QUEUE available"); + close(fd); + return -1; + } else { + ifr.ifr_flags |= IFF_MULTI_QUEUE; + } + } + if (ifname[0] != '\0') pstrcpy(ifr.ifr_name, IFNAMSIZ, ifname); else @@ -209,3 +224,40 @@ void tap_fd_set_offload(int fd, int csum, int tso4, } } } + +/* Enable a specific queue of tap. */ +int tap_fd_enable(int fd) +{ + struct ifreq ifr; + int ret; + + memset(&ifr, 0, sizeof(ifr)); + + ifr.ifr_flags = IFF_ATTACH_QUEUE; + ret = ioctl(fd, TUNSETQUEUE, (void *) &ifr); + + if (ret != 0) { + error_report("could not enable queue"); + } + + return ret; +} + +/* Disable a specific queue of tap/ */ +int tap_fd_disable(int fd) +{ + struct ifreq ifr; + int ret; + + memset(&ifr, 0, sizeof(ifr)); + + ifr.ifr_flags = IFF_DETACH_QUEUE; + ret = ioctl(fd, TUNSETQUEUE, (void *) &ifr); + + if (ret != 0) { + error_report("could not disable queue"); + } + + return ret; +} + diff --git a/net/tap-solaris.c b/net/tap-solaris.c index 486a7ea838..12cc392c94 100644 --- a/net/tap-solaris.c +++ b/net/tap-solaris.c @@ -225,3 +225,14 @@ void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo) { } + +int tap_fd_enable(int fd) +{ + return -1; +} + +int tap_fd_disable(int fd) +{ + return -1; +} + diff --git a/net/tap_int.h b/net/tap_int.h index 1dffe12a45..ca1c21b451 100644 --- a/net/tap_int.h +++ b/net/tap_int.h @@ -42,5 +42,7 @@ int tap_probe_vnet_hdr_len(int fd, int len); int tap_probe_has_ufo(int fd); void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo); void tap_fd_set_vnet_hdr_len(int fd, int len); +int tap_fd_enable(int fd); +int tap_fd_disable(int fd); #endif /* QEMU_TAP_H */ |