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>
This commit is contained in:
parent
5193e5fbb5
commit
94fdc6d030
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user