@@ -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;
+}
@@ -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;
+}
+
@@ -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;
+}
+
@@ -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;
+}
+
@@ -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;
+}
+
@@ -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 */
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> --- net/tap-aix.c | 10 ++++++++++ net/tap-bsd.c | 11 +++++++++++ net/tap-haiku.c | 11 +++++++++++ net/tap-linux.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ net/tap-solaris.c | 11 +++++++++++ net/tap_int.h | 2 ++ 6 files changed, 97 insertions(+), 0 deletions(-)