Commit 94fdc6d0 authored by Jason Wang's avatar Jason Wang Committed by Anthony Liguori
Browse files

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: default avatarJason Wang <jasowang@redhat.com>
Signed-off-by: default avatarAnthony Liguori <aliguori@us.ibm.com>
parent 5193e5fb
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -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;
}
+11 −0
Original line number Diff line number Diff line
@@ -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;
}
+11 −0
Original line number Diff line number Diff line
@@ -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;
}
+52 −0
Original line number Diff line number Diff line
@@ -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;
}
+11 −0
Original line number Diff line number Diff line
@@ -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;
}
Loading