dpdk:vfio-pci模式下iommu(N+Y)-Huge配置-numa配置

本文介绍DPDK的大内存页配置方法及驱动绑定过程,包括Hugepages的设置、vfio-pci驱动的使用以及numa编译选项的启用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DPDK大内存页Hugepages配置:

Hugepages是DPDK用于提升性能的重要手段。 通过使用Hugepages,可以降低内存页数,减少TLB页表数量,增加TLB hit率。

在Linux上设置Hugepages有两种方式:

  • 修改Kernel cmdline(推荐)
  • 修改sysfs节点

1. 系统一般都支持大页内存,目前大部分都是将2M作为默认配置页,使用默认大页配置,设置巨页
分配巨页1024*2M=2G并查看大页分配数目

echo 2048 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
cat /proc/meminfo| grep Huge

对于2 MB页面,还可以选择在系统启动后进行分配。 这是通过修改 /sys/devices/中的nr_hugepages节点来实现的。 对于单节点系统,若需要1024个页面,可使用如下命令:

echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

在NUMA机器上,页面的需要明确分配在不同的node上(若只有一个node只需要分配一次):

echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
echo 1024 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages

这种配置方式的优点是配置简单,无需编译、重启,但是无法配置1GB这样的大hugepages。

 

2. 启用1G内存页,一般64位机器均推荐1G大内存页,启用方式如下:

通过修改kernel command line可以在kernel初始化时传入Hugepages相关参数并进行配置。
具体的操作步骤如下:

  1. 修改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_TIMEOUT=5
    GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
    GRUB_DEFAULT=saved
    GRUB_DISABLE_SUBMENU=true
    GRUB_TERMINAL_OUTPUT="console"
    GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap default_hugepagesz=1G hugepagesz=1G hugepages=4 rhgb quiet"
    GRUB_DISABLE_RECOVERY="true"
    
  2. 编译grub配置文件
    可以通过命令grub2-mkconfig -o /boot/grub2/grub.cfg
  3. 重启
    通过reboot命令重启,随后可以通过cat /proc/cmdline查看kernel的command line是否包含之前的配置。
    也可以通过cat /proc/meminfo | grep Huge命令查看是否设置成功,若设置成功可以看到如下配置:
     HugePages_Total:       4
     HugePages_Free:        4
     Hugepagesize:    1048576 kB
    

DPDK官方建议,64位的应用应配置1GB hugepages。

这种配置方式的优点是可以在系统开机时即配置预留好hugepages,避免系统运行起来后产生内存碎片;另外,对于较大的例如1G pages,是不支持在系统运行起来后配置的,只能通过kernel cmdline的方式进行配置。

注:对于双插槽的NUMA系统(dual-socket NUMA system),预留的hugepages会被均分至两个socket,可以通过lscpu查看CPU信息:

Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                4
On-line CPU(s) list:   0-3
Thread(s) per core:    1
Core(s) per socket:    4
socket(s):            1
NUMA node(s):          1

可见测试主机使用的是单socket的NUMA系统。DPDK使用Hugepages

预留好Hugepages之后,想要让DPDK使用预留的Hugepages,需要进行下述操作:

mkdir /mnt/huge
mount -t hugetlbfs nodev /mnt/huge

可以将这个挂载点添加到/etc/fstab中,这样可以永久生效,即重启后也仍然可以生效:

nodev /mnt/huge hugetlbfs defaults 0 0

对于1GB pages,在/etc/fstab中必须指定page size作为mount选项。

nodev /mnt/huge_1GB hugetlbfs pagesize=1GB 0 0

添加上面这样一行内容至/etc/fstab后并重启,可以通过df -a看到挂载成功:

nodev                           0       0         0     - /mnt/huge_1GB

 

===========================DPDK驱动VFIO-PCI==============================

DPDK 驱动加载有三种方式:

uio、vfio-pci+iommu禁用、vfio+iommu启用

不同的PMD需要不同的内核驱动程序才能正常工作。 取决于正在使用的PMD,应加载相应的内核驱动程序并绑定到网络端口。

一、 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 = offintel_iommu = on iommu = pt

 

2、 l2fwd运行绑定网卡方式:(启用vfio-pci、iommu禁用)

 PS:以挂载ens7 网卡,pci 0000:02:05.0 为例

  1.  关闭计划用dpdk接管的网卡接口,并查询其pci端口号,可以通过lspci |grep Ethernet查看。此时需要确认本机物理网卡或虚拟网卡为DPDK支持类型,查询网址https://core.dpdk.org/supported/

 ifconfig ens37 down

2. 安装NIC网卡驱动模块并启动非安全NOIOMMU模式

modprobe vfio-pci
echo Y | sudo tee /sys/module/vfio/parameters/enable_unsafe_noiommu_mode

注意事项:

  1. 如果,发现dpdk 没有挂载上网卡那请手动绑定一下,手动执行在第2步之后

/opt/vpp/external/x86_64/share/dpdk/usertools/dpdk-devbind.py --bind=vfio-pci 0000:02:05.0

 

三、 l2fwd运行绑定网卡方式:(启用vfio-pci、iommu启用)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传入,具体步骤:

  1. 修改grub文件
    修改/etc/default/grub文件,在GRUB_CMDLINE_LINUX中加入如下配置:
    iommu=pt intel_iommu=on
    
  2. 编译grub配置文件
    可以通过命令grub2-mkconfig -o /boot/grub2/grub.cfg
  3. 重启
    通过reboot命令重启,随后可以通过cat /proc/cmdline查看kernel的command line是否包含之前的配置。

iommu配置成功后,dmesg中会有iommu配置group的log,可以通过dmesg | grep iommu查看:

[    0.594500] iommu: Adding device 0000:05:00.0 to group 18
[    0.594512] iommu: Adding device 0000:06:00.0 to group 19

即表示iommu使能成功。
随后需要调用modprobe来加载VFIO的驱动:

sudo modprobe vfio-pci

 驱动绑定NIC

上述的UIO和VFIO驱动可以加载一项,也可以全都加载。但是在驱动绑定NIC的时候,只能选择一种驱动绑定到NIC,这里采用VFIO驱动。

可以调用dpdk路径下的usertools/dpdk-devbind.py实用脚本来进行VFIO驱动与NIC绑定,需要注意的是使用这个脚本进行绑定(bind)动作时是需要root权限的。
可以调用脚本传入--status查看当前的网络端口的状态:

python usertools/dpdk-devbind.py --status

Network devices using kernel driver
===================================
0000:03:00.0 'I210 Gigabit Network Connection 1533' if=enp3s0 drv=igb unused=vfio-pci *Active*
0000:04:00.0 'I210 Gigabit Network Connection 1533' if=enp4s0 drv=igb unused=vfio-pci *Active*
0000:05:00.0 'I210 Gigabit Network Connection 1533' if=enp5s0 drv=igb unused=vfio-pci 
0000:06:00.0 'I210 Gigabit Network Connection 1533' if=enp6s0 drv=igb unused=vfio-pci 

可以看到,当前NIC的状态都是Network devices using kernel driver,使用的是kernel的igb驱动drv=igb
随后可以调用脚本传入--bind将网卡05:00.0,也就是enp5s0绑定到VFIO驱动:

python usertools/dpdk-devbind.py --bind=vfio-pci 05:00.0

再次调用脚本传入--status,可以看到:

Network devices using DPDK-compatible driver
============================================
0000:05:00.0 'I210 Gigabit Network Connection 1533' drv=vfio-pci unused=igb

Network devices using kernel driver
===================================
0000:03:00.0 'I210 Gigabit Network Connection 1533' if=enp3s0 drv=igb unused=vfio-pci *Active*
0000:04:00.0 'I210 Gigabit Network Connection 1533' if=enp4s0 drv=igb unused=vfio-pci *Active*
0000:06:00.0 'I210 Gigabit Network Connection 1533' if=enp6s0 drv=igb unused=vfio-pci 

设备05:00.0已经配置为drv=vfio-pci,若想要恢复为kernel默认的igb驱动,则可以继续调用脚本:

python usertools/dpdk-devbind.py --bind=igb 05:00.0

至此,DPDK的部署就算完成了,接下来可以尝试编译和运行
基于DPDK的简单应用了。

基于DPDK的简单应用编译与运行方法可以查看:

==================启用numa编译选项===============================

又踩了一个坑,在编译启用numa时候,若直接编译,dpdk是启用不了numa的,需要安装一些基础库

yum install numactl
yum install numactl-libs
yum install numactl-devel

需要安装完上面这些库,才能编译出带numa的dpdk库

如上,若按照默认编译选项,则编译完成程序是没有启用numa的,若需要启用numa功能,需要在编译时加上编译选项:

编译时启用numa选项:
meson -DCONFIG_RTE_LIBRTE_VHOST_NUMA=y -Dexamples=all build
cd build
ninja
删掉原来编译后的库(对应的是pkgconfig的库)
find / -name libdpdk*
rm /usr/local/lib64/pkgconfig/libdpdk* -rf
重新install,生成相应库
ninja install
更新so库的目录,原来so库目录更新为新库目录
ldconfig
ldconfig -p
ldconfig -p|grep rte
ls -lah /usr/local/src/dpdk/dpdk-21.02/build/lib/librte_eventdev.so
cat /etc/ld.so.conf.d/dpdk-ling.conf 
vim  /etc/ld.so.conf.d/dpdk-ling.conf 
ldconfig
确认so库目录是否更改成功
ldconfig -p |grep rte

l2fwd编译:
export PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig
meson build
cd build/
ninja
cat /proc/meminfo 
lscpu
./l2fwd -l 0-9 -n 4 -- -q 1 -p 3
看是否还有numa未编译提示,应该是没有了

备注:

numa需要加深认识,留待以后详细了解,较好的文档如下:

ovs+dpdk numa感知特性验证:
https://blog.csdn.net/weixin_30478757/article/details/99426913

结合使用带有Open vSwitch *的数据平面开发套件来创建vHost用户非统一内存访问意识:
https://software.intel.com/content/www/us/en/develop/articles/vhost-user-numa-awareness-in-open-vswitch-with-dpdk.html

 

 

 

 


 

<think>好的,我现在需要解决用户提出的关于DPDK pktgen核绑定时端口绑定失败的问题。首先,我得回顾一下DPDK和pktgen的基本知识,以及核绑定和端口绑定的常见问题和解决方法。 用户提到了几个引用,其中引用1到5都是关于DPDK和pktgen的安装、编译和使用。可能的问题可能涉及到环境配置、绑定驱动是否正确、参数设置是否有误等。我需要从这些方面入手分析。 首先,核绑定失败可能是指无法将pktgen的线程绑定到指定的CPU核心上。端口绑定失败则可能是在绑定网卡时出现问题,比如驱动未加载或网卡已经被其他进程占用。 接下来,我需要考虑可能的错误原因。例如,是否在启动pktgen时正确指定了核心列表?DPDK的环境是否配置正确,比如大页内存是否设置,驱动程序是否绑定到UIO或vfio-pci?还有可能是PCI地址输入错误,或者网卡状态未被正确识别。 解决方案方面,可能需要检查以下几个方面: 1. 确认DPDK环境配置正确,包括大页内存的设置,驱动模块的加载(如igb_uio或vfio-pci),以及设备绑定是否正确。 2. 检查pktgen启动参数中的核心绑定是否正确,比如使用-l参数指定核心列表,-n参数指定内存通道数。 3. 确认网卡的PCI地址是否正确,并且已经绑定到了DPDK兼容的驱动。 4. 查看系统日志或pktgen的错误输出,确认是否有更详细的错误信息。 5. 确保没有其他进程占用网卡,比如NetworkManager或其他DPDK应用。 可能还需要参考用户提供的引用,比如引用3中提到编译DPDK的步骤,是否正确生成了所需的目录和文件。引用2中的环境变量设置是否正确,比如RTE_SDK和RTE_TARGET是否指向正确的路径。 此外,引用5提到如果配置选项不正确,可以参考特定博客,可能涉及到更详细的配置步骤或解决特定环境下的问题。 在思考过程中,可能还需要考虑不同版本的DPDK和pktgen之间的兼容性问题,以及Linux内核版本的影响。例如,某些驱动可能在较新的内核中存在问题,或者需要特定的补丁。 总结可能的原因和解决步骤后,需要将这些整理成用户能够理解的解决方案,分点说明错误原因和对应的解决方法,并给出示例命令和检查点,帮助用户逐步排查问题。</think>### DPDK pktgen核绑定与端口绑定失败解决方案 #### 错误原因分析 1. **DPDK环境配置错误** - 未正确设置大页内存或驱动绑定,导致无法访问网卡资源[^3]。 - 网卡未绑定到`vfio-pci`或`igb_uio`驱动,仍被内核占用[^5]。 2. **核绑定参数错误** - 核心列表(`-l`参数)格式错误,例如未包含主核或超线程配置冲突。 - 内存通道数(`-n`参数)与实际硬件不匹配。 3. **端口绑定问题** - PCI地址输入错误(如格式`0000:01:00.0`)或网卡已被其他进程占用[^1][^4]。 - 网卡驱动未正确加载,导致DPDK无法识别设备。 4. **权限问题** - 未以`root`权限运行pktgen,导致无法操作网卡或绑定核心。 --- #### 解决方案与步骤 ##### 1. 检查DPDK环境配置 - **大页内存设置** 执行以下命令分配大页内存(示例为1GB大页): ```bash echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages mkdir -p /mnt/huge mount -t hugetlbfs nodev /mnt/huge ``` - **绑定网卡驱动** 使用`dpdk-devbind.py`工具将网卡绑定到DPDK兼容驱动: ```bash modprobe vfio-pci dpdk-devbind.py --bind=vfio-pci 0000:01:00.0 # 替换为实际PCI地址 dpdk-devbind.py --status # 确认绑定状态 ``` ##### 2. 核绑定参数调整 - **正确指定核心列表** 使用`-l`参数指定主核和从核,例如: ```bash ./pktgen -l 0-3 --master-lcore 0 -n 4 -- -P -m "1.0,2.1" # 主核0,端口0绑定核心1,端口1绑定核心2 ``` - `--master-lcore`必须为逻辑核心列表中的第一个。 - `-m`参数格式为`<port>.<core>`,需避免核心重复绑定[^4]。 ##### 3. 端口绑定验证 - **检查PCI地址与端口状态** 在pktgen命令行中执行`show port stats all`,确认端口状态为`Enabled`。 ```bash Pktgen:/> show port stats all ``` 若显示`Port 0: Down`,需重新绑定驱动或检查物理连接。 - **避免端口冲突** 关闭NetworkManager等可能占用网卡的服务: ```bash systemctl stop NetworkManager ``` ##### 4. 权限与日志排查 - **以root权限运行** ```bash sudo -E ./pktgen [参数] ``` - **查看详细错误日志** 在pktgen启动命令中添加`--log-level=debug`,分析具体错误位置。 --- #### 示例完整启动命令 ```bash ./pktgen -l 0-3 -n 4 --master-lcore 0 --socket-mem=1024,0 \ -a 0000:01:00.0 -a 0000:01:00.1 \ # 指定PCI地址 --file-prefix=pg \ # 避免内存前缀冲突 -- -P -m "1.0,2.1" # 启用所有端口并绑定核心 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值