使用amazon linux2 AMI启动一台c5.2xlarge实例,并通过ssh登录。
3.1 设置hugepages
CPU所能支持的hugepages大小可以通过查看CPU的flag确认,如果支持pse,则平台支持2MB的hugepages,如果支持pdpe1gb,则平台支持1GB的hugepages。
查看我们使用的操作系统环境c5.2xlarge。
# cat /proc/cpuinfo |grep -e pse -e pdpe1gb
flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp
可见,c5.2xlarge可以支持2MB的hugepages和1GB的hugepages。 对于不同的hugepages,用不同的方式完成配置。一般来说,对于64-bit的应用,建议使用1GB hugepages。下面我们会分别来进行说明。 针对2M hugepage,设置如下: 在大多数较新的linux发行版,默认已经启用的2M hugepages,并已经通过dev-hugepages.mount服务进行挂载,比如本文所使用的amazon linux2。镜像为amzn2-ami-hvm-2.0.20191116.0-x86_64-gp2 (ami-07539a31f72d244e7),kernel版本4.14.154-128.181.amzn2.x86_64。 更新系统。
查看当前系统对于hugepages分配和支持。
# cat /proc/meminfo |grep Huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
# cat /proc/mounts |grep -i hugepage
hugetlbfs /dev/hugepages hugetlbfs rw,relatime,pagesize=2M 0 0
针对2M hugepages,可以通过不同的方式来进行配置。
设置内核参数的方式。针对grub2引导的发行版,配置如下:
# echo GRUB_CMDLINE_LINUX="hugepages=2048">>/etc/default/grub
# grub2-mkconfig -o /boot/grub2/grub.cfg
重启后可以确认已经生效。
# cat /proc/cmdline | grep hugepages
BOOT_IMAGE=/boot/vmlinuz-4.14.152-127.182.amzn2.x86_64 root=UUID=e8f49d85-e739-436f-82ed-d474016253fe ro hugepages=2048 console=tty0 console=ttyS0,115200n8 net.ifnames=0 biosdevname=0 nvme_core.io_timeout=4294967295 rd.emergency=poweroff rd.shell=0
# cat /proc/meminfo | grep -i hugepage
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 2048
HugePages_Free: 2048
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
临时修改修改内核参数的方式。
# echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
# cat /proc/meminfo |grep Huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 1024
HugePages_Free: 1024
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
对于多节点的NUMA实例,需要显式的设定不同的NUMA节点。
# echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
# echo 1024 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages
当然,上述方式重启丢失需要重新设置,可以通过sysctl.conf配置来配置持久生效。
# echo "vm.nr_hugepages=512" >> /etc/sysctl.conf
# sysctl -p
# cat /proc/meminfo |grep Huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 512
HugePages_Free: 512
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
针对1G hugepages,只能通过配置内核启动参数的方式进行设置。后续的操作会使用1G hugepage来进行。
首先修改/etc/default/grub,增加GRUB_CMDLINE_LINUX=”default_hugepagesz=1G hugepagesz=1G hugepages=4”
# grub2-mkconfig -o /boot/grub2/grub.cfg
重新启动实例。可以查看设置已经生效。
# cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-4.14.152-127.182.amzn2.x86_64 root=UUID=e8f49d85-e739-436f-82ed-d474016253fe ro default_hugepagesz=1G hugepagesz=1G hugepages=4 console=tty0 console=ttyS0,115200n8 net.ifnames=0 biosdevname=0 nvme_core.io_timeout=4294967295 rd.emergency=poweroff rd.shell=0
# cat /proc/meminfo |grep -i hugepage
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 4
HugePages_Free: 4
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 1048576 kB
3.2 安装和配置DPDK
配置编译和使用所需的系统环境。
# yum groupinstall "development tools" -y
# yum install python3 numactl numactl-devel -y
DPDK可以使用meson和ninjia来进行配置,构建和安装,如果使用这种方式请首先安装meson和ninjia。
# pip3 install meson ninja
下面的说明中,我们使用makefile而并没有使用meson和ninjia进行安装。下载DPDK包。
# wget http://fast.dpdk.org/rel/dpdk-19.11.tar.xz
# tar Jxvf dpdk-19.11.tar.xz
# cd dpdk-19.11/
配置和安装。
# export RTE_SDK=/root/dpdk-19.11
# export RTE_TARGET=x86_64-native-linuxapp-gcc
# make config install T=$RTE_TARGET DESTDIR=$RTE_SDK
另外,DPDK提供了安装配置脚本dpdk-19.11/usertools/dpdk-setup.sh,我们也可以使用该脚本进行安装并可以进行后续的配置操作。
基于脚本配置方式如下。
# ./usertools/dpdk-setup.sh
------------------------------------------------------------------------------
RTE_SDK exported as /root/dpdk-19.11.script
------------------------------------------------------------------------------
----------------------------------------------------------
Step 1: Select the DPDK environment to build
----------------------------------------------------------
[1] arm64-armada-linuxapp-gcc
…………
…………
[37] x86_64-native-linuxapp-clang
[38] x86_64-native-linuxapp-gcc
[39] x86_64-native-linuxapp-icc
[40] x86_64-native-linux-clang
[41] x86_64-native-linux-gcc
[42] x86_64-native-linux-icc
[43] x86_x32-native-linuxapp-gcc
[44] x86_x32-native-linux-gcc
----------------------------------------------------------
Step 2: Setup linux environment
----------------------------------------------------------
[45] Insert IGB UIO module
[46] Insert VFIO module
[47] Insert KNI module
[48] Setup hugepage mappings for non-NUMA systems
[49] Setup hugepage mappings for NUMA systems
[50] Display current Ethernet/Baseband/Crypto device settings
[51] Bind Ethernet/Baseband/Crypto device to IGB UIO module
[52] Bind Ethernet/Baseband/Crypto device to VFIO module
[53] Setup VFIO permissions
----------------------------------------------------------
Step 3: Run test application for linux environment
----------------------------------------------------------
[54] Run test application ($RTE_TARGET/app/test)
[55] Run testpmd application in interactive mode ($RTE_TARGET/app/testpmd)
----------------------------------------------------------
Step 4: Other tools
----------------------------------------------------------
[56] List hugepage info from /proc/meminfo
----------------------------------------------------------
Step 5: Uninstall and system cleanup
----------------------------------------------------------
[57] Unbind devices from IGB UIO or VFIO driver
[58] Remove IGB UIO module
[59] Remove VFIO module
[60] Remove KNI module
[61] Remove hugepage mappings
[62] Exit Script
安装完毕之后,创建的目标目录内会包括了所有的lib库,poll-mode驱动和header文件,用以后续构建基于DPDK的应用。此外,该目录还包括一些内置编译完成可用的DPDK应用,可以用于测试。
接下来,我们需要加载相应的驱动来替代默认的ena驱动,以支持DPDK。ENA网卡可以支持UIO模式或者VFIO模式的DPDK驱动,linux的内核已经包含了标准的uio_pic_generic驱动,而刚刚我们编译也获得了DPDK提供的igb_uio驱动,uio_pic_generic对于Virtual functions的支持会有限制,通常在UIO模式下,我们会使用igb_uio。
# modprobe uio
# insmod /root/dpdk-19.11/x86_64-native-linuxapp-gcc/kmod/igb_uio.ko wc_activate=1
对于其他一些实例来说,比如 i3.metal,可以支持IOMMU,需要在内核参数指定。通过类似的方法,修改grub2启动设定。在GRUB_CMDLINE_LINUX中追加iommu=1 intel_iommu=on。然后重新生成引导参数文件。
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
link/ether 0a:ff:5f:49:42:c6 brd ff:ff:ff:ff:ff:ff
inet 172.31.9.193/20 brd 172.31.15.255 scope global dynamic eth0
valid_lft 2820sec preferred_lft 2820sec
inet6 fe80::8ff:5fff:fe49:42c6/64 scope link
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
link/ether 0a:a1:03:74:08:90 brd ff:ff:ff:ff:ff:ff
inet 172.31.3.226/20 brd 172.31.15.255 scope global dynamic eth1
valid_lft 3095sec preferred_lft 3095sec
inet6 fe80::8a1:3ff:fe74:890/64 scope link
valid_lft forever preferred_lft forever
我们将eth1绑定到igb_uio模块,DPDK提供的dpdk-devbind.py脚本可以用来进行绑定,解绑或者状态查看等操作(或者使用dpdk-setup.sh脚本来进行配置)。当前两个ENA设备均使用的ena驱动。
请注意前面设置的RTE_SDK和RTE_RARGET环境变量是否正确。编译一个内嵌的helloworld应用来进行测试。
# cd /root/dpdk-19.11examples/helloworld
# make
# ./build/helloworld
EAL: Detected 8 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: Selected IOVA mode 'PA'
EAL: Probing VFIO support...
EAL: PCI device 0000:00:05.0 on NUMA socket -1
EAL: Invalid NUMA socket, default to 0
EAL: probe driver: 1d0f:ec20 net_ena
EAL: PCI device 0000:00:06.0 on NUMA socket -1
EAL: Invalid NUMA socket, default to 0
EAL: probe driver: 1d0f:ec20 net_ena
Message from syslogd@ip-172-31-9-193 at Dec 18 07:30:15 ...
kernel:do_IRQ: 6.229 No irq handler for vector
EAL: PCI device 0000:00:07.0 on NUMA socket -1
EAL: Invalid NUMA socket, default to 0
EAL: probe driver: 1d0f:ec20 net_ena
hello from core 1
hello from core 2
hello from core 3
hello from core 4
hello from core 5
hello from core 6
hello from core 7
hello from core 0
5 结论
DPDK可以支持AWS ENA和82599网络设备,可以在AWS多种不同的实例上部署DPDK和运行支持DPDK的应用,从而对多种应用场景,比如电信行业虚拟化分组核心等提供更全面的支撑。
另外,DPDK也已经和容器网络有了良好集成,这体现在原生的Docker网络上,也体现在包括kubernetes在内的诸多平台使用的CNI实现中,比如contiv和Vhostuser等都可以支持DPDK。
在后续的文章中,我们会针对AWS上的Docker和容器编排平台使用DPDK来进行进一步说明。
6 参考链接