前言
说到互联网,大家很容易想到的有 CPU、服务器、操作系统、应用程序(App)、小程序、网页(html)等。然而,还有一个要素是很容易被忽略的,却是最重要的,那就是网卡。如果没有网卡,那么所有的主机将会是孤立的,没法实现相互间通信,也就不存在互联网了。两台主机之间要实现通信,互相收发报文,最底层的基础设施,除了传输链路(光纤、网线等),就是安装在主机上的网卡了,它将主机上应用软件产生的数据打包,然后从物理链路上发送出去,同理,它还可以从物理链路上接收报文,送往主机上的应用程序。
在这篇文章中,你将会了解到什么是中断,什么是 PCIe,什么是 uio,什么是 igb_uio,什么是 pmd,什么是 DPDK 等一系列与网卡相关的概念及网卡工作的原理。
物理网卡
这里以 Intel 网卡为例,有 10G、25G、100G 等,表示最大的传输速度,单位 Gbit/s。网卡可以有一个端口,也可以有多个端口。
网卡驱动知多少
假如我们从 Intel 买回来一张网卡,是不是直接插到电脑上,就可以用呢?答案是否定的。从一张物理网卡到真正能够实现收发报文,中间可是有一堆工作要做的。
PCIe 是一种高速串行点对点双通道高带宽、计算机扩展总线标准,现在已经发展到第四代了。简单理解,就是计算机主板上用来插网卡的槽位。当网卡插入主板上的槽位时,一块网卡上的每个端口都对应了一个 PCIe ID,这是网卡端口的物理身份标识。这里提一句,PCI 是 PCIe 的上一个形态。
首先,你要明确一点:网卡收发报通过中断实现。什么是中断呢?
所谓中断,就是外部设备向处理器发起的请求事件,但这还不够本质。更本质的理解是处理器对外开放的实时受控接口。中断绝对不是硬件代替软件去轮询,而是硬件的结构决定了,当某个管脚电平变低(或者变高)的时候,CPU 就会被打断,并从特定地址开始执行。比如,当 CPU 的 RESET 被拉低的时候一定会复位并从某个特定地址重新开始执行,这是由硬件的结构决定的。
uio,是一个内核框架(操作系统提供的内核模块),作用就是支持用户空间的 I/O 技术。而大家所熟知的 DPDK 开源组件就是实现用户态 I/O 技术,它依赖内核空间的 uio 框架。
pmd(poll mode driver,轮询模式驱动)是 DPDK 在用户态实现的网卡驱动程序,准确来说,它应该是个接口,它可以把 Intel 各种网卡的真正驱动程序加载到用户态。
pmd 有哪些功能呢?比如对网卡硬件进行一些配置,例如设置网卡接收缓冲区,发送缓冲区的大小。所谓对网卡进行配置, 也就是对网卡寄存器进行配置。每个网卡都有自己的配置空间,对应了很多寄存器,每种寄存器各自负责不同的功能。比如接收控制寄存器,用于对网卡收发包的一些设置; 中断寄存器,用于设置允许哪里产生中断事件,例如链路中断。
igb_uio(也就是 DPDK 提供的 igb_uio.ko),是 DPDK 用于与 uio 交互的内核模块,通过 igb_uio 来 bind 指定的 PCI 网卡设备给到用户态的 pmd 使用。igb_uio 借助 uio 技术来截获中断,并重设中断回调行为,从而绕过内核协议栈后续的处理流程。并且 igb_uio 会在内核初始化的过程中将网卡硬件寄存器映射到用户态。
i40e 驱动对应 Intel x700 系列网卡,这是由 Intel 提供的,是网卡真正的驱动,需要加载 i40e.ko 到内核,linux 操作系统才能识别这张物理网卡。而 ixgbe 是 Intel 82599 系列网卡驱动。
这个概念是伴随着 vm(虚拟机)的产生而出现的,就是虚拟机上的网卡。我们可以将它和 host(物理机)上的物理网卡进行绑定。
总结
我们拿到 Intel 的一张网卡时,一般加载其对应的网卡驱动就可以使用了,比如 i40e、ixgbe 等。但如果我们要用 DPDK 实现用户态网卡收发包,就需要下载 Intel 等开源代码 - DPDK,内核需要加载 igb_uio,用户态 pmd 驱动框架需要加载 librte_i40e.so 等。
Linux 系统中 DPDK 编程常用命令
ifconfig
/sys/config/net-scripts/ 下的文件可以用来配置 eth 口的 ip 地址等
ip link show
lspci // 有很多可选参数
lsmod
su modprobe uio
su insmod igb_uio
dpdk主目录/usrtools/ 下的 dpdk-devbind.py、dpdk-setup.sh 等自带脚本
linux 用户空间和内核空间通信通过 sysfs 实现