为什么使用来自多个进程的 tun 接口会导致它卡顿?

Why does using a tun interface from multiple processes cause it to stutter?

提问人:fadedbee 提问时间:11/10/2023 最后编辑:fadedbee 更新时间:11/10/2023 访问量:44

问:

我已经编写了一个有效的用户空间隧道协议,它打开了 tun0。

void peer_tun_open(struct peer *peer) {
    struct ifreq ifr;
    int err;

    proc_assert_master();

    if ((peer->tun_fd = open("/dev/net/tun", O_RDWR)) == -1) {
        LOG_ERROR_1("%s", "open /dev/net/tun");
        exit(1);
    }
    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = IFF_TUN | IFF_NO_PI;

    if ((err = ioctl(peer->tun_fd, TUNSETIFF, (void *) &ifr)) == -1) {
        LOG_ERROR_1("%s", "ioctl TUNSETIFF");
        close(peer->tun_fd);
        exit(1);
    }
    ...

只要我只从一个进程的 epoll 中使用 tun0,一切正常。

(我能够使用来自多个进程的 UDP 套接字,没有问题,带有 SO_REUSEPORT 等。 UDP 端口由子级打开,但 tun 文件描述符是通过 继承的。fork()

当我将 tun0 fd 添加到多个进程的 epoll 中时,100-3000 毫秒的随机延迟会影响到达 tun0 上的所有数据包。

static void proc_epoll_callback(const char *key, void *ob, size_t index, void *extra) {
    struct peer *peer = (struct peer *)ob;
    int epoll_fd = *(int *) extra;
    struct epoll_event event = {0};

    if (peer->worker_id != state.proc_worker_id) return; // only one process must listen to a each tun interface, otherwise 100-3000ms delays occur

    event.events = EPOLLIN;
    event.data.fd = peer->tun_fd;

    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, event.data.fd, &event)) {
        LOG_ERROR_1("failed to add fd: %d to epoll fd: %d for peer %s", event.data.fd, epoll_fd, peer->name);
    } else {
        LOG_DEBUG_1("added fd: %d to epoll fd: %d for peer %s", event.data.fd, epoll_fd, peer->name);
    }
}

是什么导致了这些延误?

如何在没有这些延迟的情况下从多个工作进程中使用 tun0?

C Linux epoll tun

评论

1赞 dimich 11/10/2023
您应该使用多队列 tuntap 接口进行并行(请参阅 docs.kernel.org/networking/tuntap.html)

答: 暂无答案