当尝试从tun接口获取超过8个队列文件描述符时,ioctl失败。

3

当我得知,在内核版本3.8之后,Linux通过使用标志IFF_MULTI_QUEUE为tun tap设备添加了多队列功能后,我将我的内核升级到了3.10,并将其头文件放在了/usr/src中。然后,我修改了我的c代码,以便在需要时开启一个新的队列文件描述符的线程。但是,该线程只能打开8个队列(早期版本低于3.8的内核根本无法打开队列),在此之后,我遇到了来自ioctl的“参数过长”错误。

ioctl(fd, TUNSETIFF, (void *)&ifr)

然后我写了另一个程序来测试在我的Ubuntu 12.10 Linux系统中可以打开多少个队列fd,代码如下:

uname -r
3.10.0-031000-generic 

在一个更简单的程序中,内核版本。

//essential
#include <net/if.h>
#include <linux/if_tun.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <arpa/inet.h>
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h> 
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
#include <stdarg.h>

#include <netdb.h>

#define IFF_MULTI_QUEUE 0x0100
int tun_alloc_mq(char *dev, int queues, int *fds)
{
    struct ifreq ifr;
    int fd, err=-1, i;
    char *clonedev = "/dev/net/tun";

    if (!dev){
        printf("dev");
        return -1;
    }

    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_MULTI_QUEUE;
    strcpy(ifr.ifr_name, dev);
    int error=0;

    for (i = 0; i < queues; i++) {

        printf("loop %d\n",i);

        if( (fd = open(clonedev , O_RDWR)) < 0 ) {
            perror("Opening /dev/net/tun");
            error=1;
            break;
          }

          if(ioctl(fd, TUNSETIFF, (void *)&ifr) < 0 ) {
            printf("first error\n");
            error=1;
            close(fd);
            break;
          } 
    }
    if(error==1)
        return -1;
    return 0;
}
int main(int argc, char *argv[])
{

    int* fdsx;
    if(tun_alloc_mq("testmqtun0",20,fdsx)<0)
    {
        perror("tun");
        exit(1);
    }
    return 0;
}

结果发现这也被限制在8个字符之内。以下是输出内容:

loop 0
loop 1
loop 2
loop 3
loop 4
loop 5
loop 6
loop 7
loop 8
first error
tun: Argument list too long

我在另一台Linux机器上测试了它,输出结果相同。 那么从内核中的tun设备打开超过8个队列是否有限制? 如果有限制,应该如何解决? 请帮助我解决这个问题。

2个回答

3

如果想要从一个tun接口获得超过8个队列文件描述符,可以将您的Linux内核升级到4.0+版本,它支持256个队列。


1

从tun驱动程序中我们可以看到以下内容

112 /* DEFAULT_MAX_NUM_RSS_QUEUES were choosed to let the rx/tx queues allocated for
113  * the netdevice to be fit in one page. So we can make sure the success of
114  * memory allocation. TODO: increase the limit. */
115 #define MAX_TAP_QUEUES DEFAULT_MAX_NUM_RSS_QUEUES
    [...]
500 static int tun_attach(struct tun_struct *tun, struct file *file)
501 {
    [...]
518         if (!tfile->detached &&
519             tun->numqueues + tun->numdisabled == MAX_TAP_QUEUES)
520                 goto out;
    [...]

DEFAULT_MAX_NUM_RSS_QUEUESlinux/netdevice.h 中被定义为:

2187 #define DEFAULT_MAX_NUM_RSS_QUEUES      (8)

所以,8是默认值。

抱歉晚了,感谢回复,现在我明白了。但是即使没有那个额外的8个队列,TUN也运行得很好。无论如何,对于我的情况,我放弃了这个队列的想法,使用了老式的TUN分配方式。 - madz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接