dpdk 编译
引用: https://zhuanlan.zhihu.com/p/566700687
20.11 版本
DPDK(Data Plane Development Kit)是数据平面开发工具包,由用于加速在各种CPU架构上运行的数据包处理的库组成。
DPDK需要一定的网卡硬件支持,以Intel为例,支持以下网卡:
下面带大家过一遍编译流程,扫清后续应用的第一道障碍!
一、源码准备
下载dpdk-20.11.tar.xz源码包
采用如下命令命令进行解压
解压后用ls命令再确认一下
发现多了一个dpdk-20.11文件夹,我们进去瞅瞅他的目录结构,发现该有的都有啦。
稍微展开介绍一下几个重要目录:
- lib:DPDK库的源代码
- drivers: DPDK 查询模式驱动源码
- app: DPDK应用源码(自动化测试)
- examples: DPDK应用示例程序源码
- config,buildtools: 框架相关的脚本和配置
二、编译安装DPDK
- 进入dpdk-20.11目录执行meson -Dexamples=helloworld build命令并回车,如下图红色框所示。如对meson命令不熟悉可以瞅瞅编译工具meson+ninja简介(dpdk编译工具)
稍等片刻出现下图所示内容,我们用ls查看发现多出来一个buid文件夹,没错,接下来的故事在build文件夹内展开。
- 进入build文件夹ls命令查看一下上一个命令生成的内容,接着依次执行ninja-build命令、ninja-build install命令,如对ninja相关命令比较陌生,可以瞅瞅编译工具meson+ninja简介(dpdk编译工具)。执行以上命令后效果如下图。
- ninja install命令会拷贝编译后的目标文件到系统范围内可执行的地方,最后执行以下ldconfig命令使ld.so更新它的cache,以便包含刚才生成的目标文件。执行完成以上三步,恭喜你,dpdk就算安装完成了。
三、测试验证
前面执行meson -Dexamples=helloworld build这条命令时不知道大家是否 对-Dexamples=helloworld的用意已理解,这个参数就是告诉meson编译DPDK的同时编译helloworld例程。所以我们可以通过运行这个例程来检验dpdk是否能正常工作。
在运行DPDK应用前咱一般还需要干几件事儿:
- 设置Hugepages
Hugepages是DPDK用于提升性能的重要手段。通过使用Hugepages,可以降低内存页数,减少TLB页表数量,增加TLB hit率。在Linux上设置Hugepages有两种方式:
修改Kernel cmdline(推荐)
修改sysfs节点
a、修改Kernel cmdline(推荐)
通过修改kernel command line可以在kernel初始化时传入Hugepages相关参数并进行配置。具体的操作步骤如下:
修改grub文件
修改/etc/default/grub
文件,在GRUB_CMDLINE_LINUX
中加入如下配置:
default_hugepagesz=1G hugepagesz=1G hugepages=4
该配置表示默认的hugepages的大小为1G,设置的hugepages大小为1G,hugepages的页数为4页,即以4个1G页面的形式保留4G的hugepages内存
修改后的grub文件示例如下:
编译grub配置文件
可以通过命令grub2-mkconfig -o /boot/grub2/grub.cfg
重启
通过reboot
命令重启,随后可以通过cat /proc/cmdline
查看kernel的command line是否包含之前的配置。
也可以通过cat /proc/meminfo | grep Huge
命令查看是否设置成功,若设置成功可以看到如下配置:
DPDK官方建议,64位的应用应配置1GB hugepages。
这种配置方式的优点是可以在系统开机时即配置预留好hugepages,避免系统运行起来后产生内存碎片;另外,对于较大的例如1G pages,是不支持在系统运行起来后配置的,只能通过kernel cmdline的方式进行配置centos7.7,大页为1G 可动态调
注:对于双插槽的NUMA系统(dual-socket NUMA system),预留的hugepages会被均分至两个socket,可以通过lscpu
查看CPU信息:
可见测试主机使用的是双socket的NUMA系统。
b、修改sysfs节点
对于2 MB页面,还可以选择在系统启动后进行分配。这是通过修改 /sys/devices/
中的nr_hugepages
节点来实现的。对于单节点系统,若需要1024个页面,可使用如下命令:
在NUMA机器上,页面的需要明确分配在不同的node上(若只有一个node只需要分配一次):
这种配置方式的优点是配置简单,无需编译、重启,但是无法配置1GB这样的大hugepages。
DPDK使用Hugepages
预留好Hugepages之后,想要让DPDK使用预留的Hugepages,需要进行下述操作:
可以将这个挂载点添加到/etc/fstab
中,这样可以永久生效,即重启后也仍然可以生效:
对于1GB pages,在/etc/fstab
中必须指定page size作为mount选项。添加上面这样一行内容至/etc/fstab
后并重启,可以通过df -a
看到挂载成功:
- 加载内核驱动
DPDK的驱动可以选择UIO也可以选择VFIO,VFIO安全性性能都比UIO好,不过要求肯定也比UIO高,所以一般的建议是有条件尽量用VFIO,用不了再用UIO。
UIO
UIO(Userspace I/O)是运行在用户空间的I/O技术。Linux系统中一般的驱动设备都是运行在内核空间,而在用户空间用应用程序调用即可。
而UIO则是将驱动的很少一部分运行在内核空间,而在用户空间实现驱动的绝大多数功能。
在许多情况下,Linux内核中包含的标准uio_pci_generic模块可以提供uio功能。可以使用以下命令加载此模块:
sudo modprobe uio_pci_generic
除了Linux内核中包含的标准uio_pci_generic模块,DPDK也提供了一个可替代的igb_uio模块,可以在kmod
路径中找到。可以通过以下方法加载igb_uio模块。
sudo modprobe uio
sudo insmod kmod/igb_uio.ko
如果用于DPDK的设备绑定为uio_pci_generic内核模块,需要确保IOMMU已禁用或passthrough。以intel x86_64系统为例,可以在的GRUB_CMDLINE_LINUX
中添加intel_iommu = off
或intel_iommu = on iommu = pt
。
VFIO(推荐)
VFIO与UIO相比,它更加强大和安全,依赖于IOMMU。要使用VFIO,需要:
Linix kernel version>=3.6.0
内核和BIOS必须支持并配置为使用IO virtualization(例如Intel®VT-d)在确认硬件配置支持的情况下,要使用VFIO驱动绑定到NIC必须先使能iommu,否则会导致绑定失败。具体的现象就是查看或修改sysfs节点/sys/bus/pci/drivers/vfio-pci/bind
出现io错误,以及dmesg中出现:
vfio-pci: probe of 0000:05:00.0 failed with error -22
使能iommu的方法也是修改kernel的command line将iommu=pt intel_iommu=on
传入,具体步骤:
a、修改grub文件
修改/etc/default/grub
文件,在GRUB_CMDLINE_LINUX
中加入如下配置:iommu=pt intel_iommu=on
b、编译grub配置文件
可以通过命令grub2-mkconfig -o /boot/grub2/grub.cfg
c、重启
通过reboot
命令重启,随后可以通过cat /proc/cmdline
查看kernel的command line是否包含之前的配置。
d、iommu配置成功后,dmesg中会有iommu配置group的log,可以通过dmesg | grep iommu
查看:
并没有出现类似如下iommu的device加入组的相关信息。[0.594500] iommu: Adding device 0000:05:00.0 to group 18
[0.594512] iommu: Adding device 0000:06:00.0 to group 19
感觉不太妙,不知vfio能否用的起来。
随后需要调用modprobe
来加载VFIO的驱动:
sudo modprobe vfio-pci
lsmod | grep vfio一下,可以看到vfio驱动已经挂载。
为了保险起见,我们把uio的也挂载上吧,如下:
现在uio和vfio的驱动都已成功挂载。
- 应用程序使用的端口应绑定到相应的内核驱动程序(可选)
上面的UIO和VFIO驱动可以加载一项,也可以全都加载。但是在驱动绑定NIC的时候,只能选择一种驱动绑定到NIC,UIO和VFIO该如何选可以回看UIO,IOMMU,VFIO傻傻分不清楚,我们先尝试采用VFIO驱动。可以调用dpdk路径下的usertools/dpdk-devbind.py
实用脚本来进行VFIO驱动与NIC绑定,需要注意的是使用这个脚本进行绑定(bind)动作时是需要root权限的。可以调用脚本传入--status
查看当前的网络端口的状态:
可以看到,当前NIC的状态都是Network devices using kernel driver。
随后可以调用脚本传入--bind
将网卡0b:00.0
,也就是ens192
绑定到VFIO驱动:
结果报错了,看来咱今天演示用的机器是支持不了vfio了,那咱们就只能上uio了,具体如下:
再次调用脚本传入--status
,可以从上图看到设备0b:00.0
已经配置为drv=uio_pci_generic了。
若想要恢复为kernel默认的vmxnet3驱动,则可以继续调用脚本:
python usertools/dpdk-devbind.py --bind=vmxnet3 0b:00.0
不过为了今后的实验,咱还是把0b:00.0设置为uio_pci_generic吧。接下来咱们用前面编译好的helloworld例程看看效果怎么样,具体如下:
输入红色框命令并回车,接下来例程期望的效果真的出现了,惊不惊喜,意不意外~
原文链接 : https://mp.weixin.qq.com/s/kVUFW3yngpFsY5n-bBhnmA
使用修改sysfs节点方法,修改 hugepage 。第一种方法失败了。
设置大页:
绑定网卡:
参考:https://dpdk-docs.readthedocs.io/en/latest/linux_gsg/build_dpdk.html
3.4. 加载模块启动DPDK环境需要的UIO功能
要运行任何的DPDK应用程序,需要将合适的uio模块线加载到当前内核中。在多数情况下,Linux内核包含了标准的 uio_pci_generic
模块就可以提供uio能力。 该模块可以使用命令加载
sudo modprobe uio_pci_generic
区别于 uio_pci_generic
,DPDK提供了一个igb_uio模块(可以在kmod目录下找到)。可以通过如下方式加载:
sudo modprobe uio
sudo insmod kmod/igb_uio.ko
以上加载驱动。
开始绑定网卡:
查看系统中所有网络接口的状态:
./usertools/dpdk-devbind.py --status
Network devices using DPDK-compatible driver
============================================
0000:82:00.0 '82599EB 10-GbE NIC' drv=uio_pci_generic unused=ixgbe
0000:82:00.1 '82599EB 10-GbE NIC' drv=uio_pci_generic unused=ixgbe
Network devices using kernel driver
===================================
0000:04:00.0 'I350 1-GbE NIC' if=em0 drv=igb unused=uio_pci_generic *Active*
0000:04:00.1 'I350 1-GbE NIC' if=eth1 drv=igb unused=uio_pci_generic
0000:04:00.2 'I350 1-GbE NIC' if=eth2 drv=igb unused=uio_pci_generic
0000:04:00.3 'I350 1-GbE NIC' if=eth3 drv=igb unused=uio_pci_generic
Other network devices
=====================
<none>
绑定设备 eth1
,``04:00.1``, 到 uio_pci_generic
驱动:
./usertools/dpdk-devbind.py --bind=uio_pci_generic 04:00.1
或者
./usertools/dpdk-devbind.py --bind=uio_pci_generic eth1
恢复设备 82:00.0
到Linux内核绑定状态:
./usertools/dpdk-devbind.py --bind=ixgbe 82:00.0
./usertools/dpdk-devbind.py --bind= eth1
x86_64 系统运行
没有mount
不会崩溃,可以正常运行
numa与 core 对应关系:
numa 与 网卡对应关系
dpmp 安装问题
https://edc.intel.com/content/www/us/en/design/products/ethernet/config-guide-e810-dpdk/prerequisite-library/
https://www.cnblogs.com/goto2091/p/15939960.html
sudo apt-get install libnuma-dev
or Ubuntu:
sudo apt-get install libnuma-dev
For RHEL:
yum install numactl-devel
安装ninja-build
For Ubuntu:
sudo apt install meson ninja-build
For RHEL:
sudo dnf install meson ninja-build
安装DPDK
首先安装DPDK的必备库。
#!/bin/sh
yum update -y --allowerasing --skip-broken --nobest
yum install -y gcc-toolset-9
yum install -y zlib-devel
yum install -y libnl3-devel
yum install -y boost-devel
yum install -y systemd-devel
yum install -y yasm
yum install -y lz4-devel
yum install -y elfutils-libelf-devel
yum install -y openssl-devel
yum install -y numactl-devel
yum install -y python3
pip3 install mwcp # python3需要安装 mwcp , 才可以继续安装meson build,
pip3 install meson # Build DPDK和DPDK-pktgen的工具
pip3 install ninja # 安装DPDK和DPDK-pktgen的工具
meson 如果安装不上去,
安装Pktgen
Pktgen安装必须要有的库有:
libpcap # 数据包捕获函数库
meson
ninja
pkg-config # 指向头文件和库文件的工具,给编译器使用,类似快捷方式
进入pktgen源文件目录进行安装:
cd pktgen-dpdk
meson build # meson编译时容易报错
ninja
ninja install
参考引用:
https://zhuanlan.zhihu.com/p/566700687
https://dpdk-docs.readthedocs.io/en/latest/linux_gsg/build_dpdk.html
https://blog.csdn.net/jpmsdn/article/details/84561294
https://www.cnblogs.com/goto2091/p/15939960.html