#
什么是dpdk?
dpdk是intel开源的一个网络加速工具包,目的是在IA平台上解决高性能网络数据包处理的问题。
传统网络包处理的过程是:
- 网卡收到数据包
- 网卡将帧DMA到内存
- 网卡发送硬中断
- cpu响应中断,调用对应函数进行收包
- 将ring buffer保存到skb
- 内核协议栈处理帧
- 用户进程处理报文
因为传统网络包处理是中断驱动的,所以在大量网络请求下会出现irq风暴,降低处理性能。除此之外还涉及到多次用户态和内核态数据拷贝,降低性能。当时流行的做法是通过硬件来加速网络包处理,但是dpdk的产生证明了通用化硬件在软件极致优化的情况下也能做到达到io的极限。
基于IA处理器的DPDK技术,很好地解决高性能数据包处理的问题,这些技术包括:
- 通过轮询来处理数据包,避免中断上下文切换的开销
- 使用用户态驱动,避免内核态到用户态不必要的内存拷贝和系统调用
- 设置cpu亲和性与独占,避免线程在不同核心间频繁切换; 限制某些核心不参与Linux系统调试, 可使线程独占该核心
- 利用大页内存降低TLB miss
#
dpdk安装
环境:Mac m1,Vmware Fusion 虚拟机,Ubuntu 20.04
版本:dpdk 22.11.4
因为ubuntu已经有了dpdk的二进制源,直接安装即可,如果需要二进制安装,可参考官方文档:
1
|
apt install -yq dpdk dpdk-dev dpdk-doc gcc g++
|
#
配置环境
dpdk环境最好配置2张网卡,一个选择桥接,用来配置dpdk开发,一个选择NAT,用来和宿主机连接。cpu选择4核,内存选择8G,按宿主机资源即可。
启动dpdk环境需要3步:
- 安装uio启动
- 将网卡和dpdk绑定
- 设置内存大页
#
安装驱动
dpdk一般多采用两种驱动:vfio-pci和igb_uio。
vfio-pci:
1
2
3
4
|
sudo modprobe vfio && \
sudo modprobe vfio-pci
# 配置noiommu_mode。
sudo bash -c 'echo 1 > /sys/module/vfio/parameters/enable_unsafe_noiommu_mode'
|
igb_uio: ``
1
|
git clone https://dpdk.org/git/dpdk-kmods
|
下载以后make安装即可
1
2
3
4
|
pushd dpdk-kmods/linux/igb_uio
sudo make
sudo depmod && sudo insmod igb_uio.ko
popd
|
或者直接apt install dpdk-kmods-dkms
#
绑定网卡
使用dpdk安装自带了工具`dpdk-devbind.py直接配置:
1
2
|
dpdk-devbind.py -s # 查看网卡绑定状态
dpdk-devbind.py -b vfio-pci 0000:03:00.0 # 将0000:03:00.0网卡绑到vfio-pci驱动
|
#
设置hugepage
x86架构CPU支持2M和1G大小的pagesize,一般linux默认配置了2M的大小,通过cat /proc/meminfo|grep -i huge
来查看。
1
2
3
4
5
6
|
# 挂载1G的hugepage
sudo mkdir /mnt/huge
sudo mount -t hugetlbfs -o pagesize=1G none /mnt/huge
# 设置巨页数量 以下都是在numa节点0上设置 如果设置其他节点可修改路径
sudo bash -c 'echo 2 > /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages'
sudo bash -c 'echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages'
|
方便起见,写一个init脚本,方便快速拉起dpdk环境:
1
2
3
4
5
6
7
8
|
modprobe vfio
modprobe vfio-pci
echo 1 > /sys/module/vfio/parameters/enable_unsafe_noiommu_mode
dpdk-devbind.py -b vfio-pci 0000:03:00.0
dpdk-devbind.py -b vfio-pci 0000:1a:00.0
mount -t hugetlbfs -o pagesize=1G none /mnt/huge
echo 2 > /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages
echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
|
#
第一个测试程序
测试程序使用dpdk官方提供的testpmd,测试dpdk网卡绑定 。
测试环境: 两台虚拟机,要求都已经安装了dpdk的环境。
#
安装pktgen
1
2
3
4
5
6
7
|
git clone git://dpdk.org/apps/pktgen-dpdk
cd pktgen-dpdk/
meson build
cd build
ninja
# app/pktgen 编译出的程序
mv app/pktgen /usr/local/bin
|
#
开始测试
node1 node2 mac信息
1
2
3
4
5
6
|
node1
绑定接口名称: ens161, MAC地址: 00:0c:29:a5:21:1e, IP地址: 未分配
绑定接口名称: ens256, MAC地址: 00:0c:29:a5:21:14, IP地址: 未分配
node2
绑定接口名称: ens161, MAC地址: 00:0c:29:57:f0:2f, IP地址: 未分配
绑定接口名称: ens256, MAC地址: 00:0c:29:57:f0:25, IP地址: 未分配
|
- 在node1 上运行testpmd:
1
|
dpdk-testpmd -l 0-1 -n 1 -- -i
|
- 将网卡设为只读模式、非混杂模式(这样就只收pktgen发来的包)后开始收包
1
2
3
4
|
set fwd rxonly
set promisc all off
show port stats all
start
|
- 在node2 运行pktgen 进行发包
1
|
pktgen -l 0-1 -n 3 -- -P -m "[1].0"
|
- 设置目的mac,发送100个包
1
2
3
|
set 0 dst mac 00:0c:29:a5:21:1e
set 0 count 100
start 0
|
在node1上执行 show port stats all
,此时可以发现其中一张网卡多了6400,pktgen发包默认大小64字节。
执行quit
退出
测试符合预期,环境搭建完成。