Linux tun/tap 驱动多队列模式(C/C++)

2024-03-04 06:44

本文主要是介绍Linux tun/tap 驱动多队列模式(C/C++),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

LINUX 内核在3.X版本才支持,正式是到 4.1 版本内核才加入到内核之中被支持,所以相对来说距今时间上来说是比较新的一种扩展技术。

多队列模式的 tun/tap 可以显著的提高,单个 tun/tap 网卡的带宽吞吐速度,但肯定没有 DPDK 那种零拷贝不内核切换的效率高。

一般来说,tun/tap 的效率与内核直接处理网卡数据速度,大约差距至少5倍左右,即 1000Mbps,tun/tap 最大用户层可以达到 200Mbps,实际上大多数情况达不到。

以玩客云S805晶片为例,单核拉满在300Mbps 左右,三核拉满达到最大速度就是900Mbps,虽然是1000Mbps 的网卡口子,但是芯片处理不了那么大的数据吞吐量。

四核拉满跑 tun/tap 最大吞吐速度大约在 350Mbps 左右,即双工 160 ~ 170Mbps 下行速度,上传倒是可以爆表达到 190 ~ 200Mbps。

这里是指用多队列模式榨干CPU、并且需要跑AES-256-GCM/CFB这样的加密算法,如果不跑这些会更好一点,可能在 200 ~ 230Mbps 左右。

在这种机子上面 tun/tap 驱动损失的转发效率可能没有那么大,但是一般大约就是五倍的性能差距,反正按着算大体不会差太多。

重点:

1、多队列模式下,可以重复打开相同的 tun/tap 网卡

2、多队列模式下,每个tun/tap 设备句柄会随机收取到内核派发的包

(所以不存在主从这样的接口)

3、多队列模式下,每个 tun/tap 设备句柄可以被 epoll 附加监听读写事件

4、多队列模式下,每个 tun/tap 设备句柄都可以单独设置为 “非阻塞” 或 “阻塞模式”

5、多队列模式下,每个 tun/tap 设备句柄都可以单独被写入IP数据包

每个 tun/tap 设备句柄被单独的 read、write 都涉及到内核加锁的过程,所以如果多线程并行交叉读写这些 tun/tap 设备句柄效率会很低,因为内核会上锁等,所以最好的办法是,一个队列一个 tun/tap io 线程来操作,读写都在同个线程,跨线程会严重影响效率,建议结合 epoll 来用。

每个 tun/tap 设备句柄都应该设置为非阻塞,并且写入不建议用 epoll,直接write向内核写入数据包就行了,同时 tun/tap 驱动在Linux内核,非阻塞只作用在读,写是不存在丢包的,调用一次都会调用到内核驱动的 tun_write 函数,它是无视非阻塞设置的。

源实现:(打开多队列模式的 tun/tap、多队列可以重复打开 tun/tap 句柄)

        int TapLinux::OpenDriver(const char* ifrName) noexcept {if (NULL == ifrName || *ifrName == '\x0') {ifrName = "tun%d";}// __oflagint __open_flags = O_RDWR | O_NONBLOCK;
#if defined(O_CLOEXEC)__open_flags |= O_CLOEXEC;
#endifint tun = open("/dev/tun", __open_flags);if (tun == -1) {tun = open("/dev/net/tun", __open_flags);if (tun == -1) {return -1;}}Socket::SetNonblocking(tun, true);ppp::unix__::UnixAfx::set_fd_cloexec(tun);struct ifreq ifr;memset(&ifr, 0, sizeof(ifr));// By default, try to enable tun/tap-driver multi-queue mode, if not single-queue mode.// https://www.kernel.org/doc/Documentation/networking/tuntap.txtstrncpy(ifr.ifr_name, ifrName, IFNAMSIZ);#if defined(IFF_MULTI_QUEUE)ifr.ifr_flags = IFF_TUN | IFF_NO_PI | IFF_MULTI_QUEUE;bool fails = ioctl(tun, TUNSETIFF, &ifr) < 0;if (fails) {ifr.ifr_flags = IFF_TUN | IFF_NO_PI;fails = ioctl(tun, TUNSETIFF, &ifr) < 0;}
#elseifr.ifr_flags = IFF_TUN | IFF_NO_PI;bool fails = ioctl(tun, TUNSETIFF, &ifr) < 0;
#endifif (fails) {::close(tun);return -1;}else {return tun;}}

这篇关于Linux tun/tap 驱动多队列模式(C/C++)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/772319

相关文章

Oracle数据库定时备份脚本方式(Linux)

《Oracle数据库定时备份脚本方式(Linux)》文章介绍Oracle数据库自动备份方案,包含主机备份传输与备机解压导入流程,强调需提前全量删除原库数据避免报错,并需配置无密传输、定时任务及验证脚本... 目录说明主机脚本备机上自动导库脚本整个自动备份oracle数据库的过程(建议全程用root用户)总结

Linux如何查看文件权限的命令

《Linux如何查看文件权限的命令》Linux中使用ls-R命令递归查看指定目录及子目录下所有文件和文件夹的权限信息,以列表形式展示权限位、所有者、组等详细内容... 目录linux China编程查看文件权限命令输出结果示例这里是查看tomcat文件夹总结Linux 查看文件权限命令ls -l 文件或文件夹

idea的终端(Terminal)cmd的命令换成linux的命令详解

《idea的终端(Terminal)cmd的命令换成linux的命令详解》本文介绍IDEA配置Git的步骤:安装Git、修改终端设置并重启IDEA,强调顺序,作为个人经验分享,希望提供参考并支持脚本之... 目录一编程、设置前二、前置条件三、android设置四、设置后总结一、php设置前二、前置条件

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

C++11右值引用与Lambda表达式的使用

《C++11右值引用与Lambda表达式的使用》C++11引入右值引用,实现移动语义提升性能,支持资源转移与完美转发;同时引入Lambda表达式,简化匿名函数定义,通过捕获列表和参数列表灵活处理变量... 目录C++11新特性右值引用和移动语义左值 / 右值常见的左值和右值移动语义移动构造函数移动复制运算符

Linux系统中查询JDK安装目录的几种常用方法

《Linux系统中查询JDK安装目录的几种常用方法》:本文主要介绍Linux系统中查询JDK安装目录的几种常用方法,方法分别是通过update-alternatives、Java命令、环境变量及目... 目录方法 1:通过update-alternatives查询(推荐)方法 2:检查所有已安装的 JDK方

Linux系统之lvcreate命令使用解读

《Linux系统之lvcreate命令使用解读》lvcreate是LVM中创建逻辑卷的核心命令,支持线性、条带化、RAID、镜像、快照、瘦池和缓存池等多种类型,实现灵活存储资源管理,需注意空间分配、R... 目录lvcreate命令详解一、命令概述二、语法格式三、核心功能四、选项详解五、使用示例1. 创建逻

Linux下在线安装启动VNC教程

《Linux下在线安装启动VNC教程》本文指导在CentOS7上在线安装VNC,包含安装、配置密码、启动/停止、清理重启步骤及注意事项,强调需安装VNC桌面以避免黑屏,并解决端口冲突和目录权限问题... 目录描述安装VNC安装 VNC 桌面可能遇到的问题总结描js述linux中的VNC就类似于Window

linux下shell脚本启动jar包实现过程

《linux下shell脚本启动jar包实现过程》确保APP_NAME和LOG_FILE位于目录内,首次启动前需手动创建log文件夹,否则报错,此为个人经验,供参考,欢迎支持脚本之家... 目录linux下shell脚本启动jar包样例1样例2总结linux下shell脚本启动jar包样例1#!/bin

C++中detach的作用、使用场景及注意事项

《C++中detach的作用、使用场景及注意事项》关于C++中的detach,它主要涉及多线程编程中的线程管理,理解detach的作用、使用场景以及注意事项,对于写出高效、安全的多线程程序至关重要,下... 目录一、什么是join()?它的作用是什么?类比一下:二、join()的作用总结三、join()怎么