👉点击这里申请火山引擎VIP帐号,立即体验火山引擎产品>>>
本文以三代实例使用Pktgen-DPDK、Kernel Pktgen、iPerf3、ping工具测试网络性能的方法为例,向您介绍如何测试实例的网络PPS、网络带宽和网络时延。
注意事项
本文的测试结果仅作为参考,不代表云服务器的真实最优性能。
为避免数据丢失,建议您在新创建的无数据的实例上参考本文进行网络性能测试。
前提条件
已创建符合测试场景要求的三代ECS实例或三代裸金属实例,具体操作请参见通过向导购买实例。
在同一测试场景下,所有实例必须属于同一个VPC和同一个安全组。
准备环境
不同测试场景下,推荐的实例规格及数量如下表所示。
测试实例的网络PPS( ≤ 600万)、网络带宽、网络时延
说明
测试实例的网络带宽和网络时延对网络PPS大小没有要求,可选择任意实例规格进行测试。详细规格性能请参见实例规格介绍。
测试示例 被测试机器(DUT) 辅助测试机器(Tester) 实例规格 g3i.large g3i.large 镜像 Ubuntu 22.04 Ubuntu 22.04 网卡数量 1 1 实例数量 1 1 测试实例的网络PPS( > 600万)
说明
测试示例 被测试机器(DUT) 辅助测试机器(Tester) 实例规格 g3i.48xlarge g3i.48xlarge 镜像 Ubuntu 22.04 Ubuntu 22.04 网卡数量 2 2 实例数量 1 1 使用Pktgen-DPDK测试时,每台实例需要准备两张网卡,分别用于登录运行命令和DPDK测试使用,注意要将eth1作为DPDK测试网口,eth0作为管理网口,切换eth0到用户态会导致SSH会话断开。
任何网络PPS > 600万的三代实例均可参考本文测试网络PPS,本文选择g3i.48xlarge(192vCPU)实例是为了测试规格中标称的最佳3600万PPS。
操作步骤
测试网络PPS( ≤ 600万)
远程连接被测试机和辅助测试机,具体操作请参见登录实例。
在辅助测试机上,下载pktgen脚本。
确保Linux kernel中包含了pktgen module,执行modprobe pktgen命令,加载模块。
在辅助测试机器,切换到pktgen目录,执行如下命令进行发包。
bash pktgen_sample02_multiqueue.sh -i <网卡设备名称> -d <被测试机器的私网IP地址> -s 64 -m <被测试机器的MAC地址> -c 10 -p 40000-40003 -n 0 -t <网卡队列数>
由于脚本中有如下配置,此时产生的flow总数为:(109 - 9 + 1) * (40003 - 40000 + 1) = 101 * 4 = 404。
# Flow variation random source port between min and max UDP_SRC_MIN=9 UDP_SRC_MAX=109
在被测试机器端执行sar -n DEV 1命令,查看测试结果。
测试网络PPS( > 600万)
远程连接被测试机和辅助测试机,具体操作请参见登录实例。
在被测试机和辅助测试机上,执行以下命令,安装依赖软件和Pktgen-DPDK。
创建down-pktgen.sh脚本,下载DPDK和Pktgen的源代码。
修改pktgen.c收发包引擎,优化pktgen收发包处理。
将./Pktgen-DPDK/app/pktgen.h和./Pktgen-DPDK/lib/common/lscpu.c文件中的3处fclose改为pclose。
修改pktgen支持32 queue。
执行cd /root/;vim down-pktgen.sh命令,创建down-pktgen.sh文件。
按i,进入编辑模式。
在down-pktgen.sh文件中,输入如下内容。
#!/bin/bash # 使用当前目录下载源代码 cur_dir=$(cd $(dirname $0); pwd) # 若dpdk文件夹不存在则下载 cd $cur_dir if [ ! -e $cur_dir/dpdk ] then git clone https://dpdk.org/git/dpdk dpdk ; echo $? fi # 若Pktgen-DPDK文件夹不存在则下载 cd $cur_dir if [ ! -e $cur_dir/Pktgen-DPDK ] then git clone https://github.com/pktgen/Pktgen-DPDK.git Pktgen-DPDK ; echo $? fi # 切换分支到pktgen-21.11.0配套分支 cd $cur_dir/dpdk ; git checkout v21.11 ; cd $cur_dir/Pktgen-DPDK ; git checkout pktgen-21.11.0 ;
按Esc退出编辑模式,输入:wq并按下Enter键,保存并退出文件。
执行chmod +x down-pktgen.sh指令,赋予down-pktgen.sh文件执行权限。
执行bash down-pktgen.sh命令,运行脚本。
执行vim ./Pktgen-DPDK/app/pktgen.c命令,打开pktgen.c文件。
输入/_64,搜索关键字_64。
按i,进入编辑模式。
将代码行info->sizes._64++;替换为如下代码,注释本行代码。
{ //info->sizes._64++; ; }
修改后的代码如下图所示。
按Esc退出编辑模式,输入:wq并按下Enter键,保存并退出文件。
执行vim ./Pktgen-DPDK/app/pktgen.c +341命令,打开pktgen.c文件并跳到341行。
按i,进入编辑模式。
在cnt -= ret;的下一行增加如下代码。
if (cnt != 0) { rte_delay_us(8); }
修改后的代码如下图所示。
按Esc退出编辑模式,输入:wq并按下Enter键,保存并退出文件。
优化pktgen.c发包引擎。
优化pktgen.c收包引擎。
执行以下命令,打开文件。
vim ./Pktgen-DPDK/app/pktgen.h
vim ./Pktgen-DPDK/lib/common/lscpu.c按i,进入编辑模式。
修改fclose为pclose。
./Pktgen-DPDK/app/pktgen.h修改后如下所示。
./Pktgen-DPDK/lib/common/lscpu.c修改后如下所示。按Esc退出编辑模式,输入:wq并按下Enter键,保存并退出文件。
执行vim ./Pktgen-DPDK/app/pktgen-constants.h +34命令,打开./Pktgen-DPDK/app/pktgen-constants.h文件。
按i,进入编辑模式。
修改NUM_Q为32。
修改后的代码如下图所示。按Esc退出编辑模式,输入:wq并按下Enter键,保存并退出文件。
执行以下命令,安装依赖软件。注意需安装Python3.6以上版本,否则会出现Python3和部分软件包不兼容的情况。
apt update apt install -y libpcap-dev apt install -y libnuma-dev apt-get install python3-pip -y apt install -y git pip3 install pyelftools -i https://mirrors.ivolces.com/pypi/simple/ pip3 install ninja -i https://mirrors.ivolces.com/pypi/simple/ pip3 install meson -i https://mirrors.ivolces.com/pypi/simple/
执行以下命令,安装Pktgen-DPDK。
说明
您也可以通过将附录中的patch文件拷贝到/root/Pktgen-DPDK目录,执行如下命令配置git邮箱并直接打入patch,完成步骤ii、步骤iii、步骤iv的操作。
cd /root/Pktgen-DPDK git config --global user.email "you@example.com" git config --global user.name "Your Name" git am --signoff < ./0001-Optimize-performance.patch
执行bash /root/build-dpdk-pktgen.sh命令,编译DPDK和Pktgen的源代码。脚本build-dpdk-pktgen.sh内容如下所示。
#!/bin/bash # build-dpdk-pktgen.sh # 使用当前目录下载源代码 cur_dir=$(cd $(dirname $0); pwd) # 编译安装DPDK cd $cur_dir/dpdk ; meson build cd $cur_dir/dpdk/build ; ninja ; ninja install ; ldconfig # 编译安装Pktgen-DPDK cd $cur_dir/Pktgen-DPDK ; meson build ; ninja -C build # 检查编译结果是否生成可执行文件 ls -l $cur_dir/Pktgen-DPDK/build/app/pktgen
执行如下命令,将DPDK动态库加入到系统配置。
echo "/usr/local/lib/x86_64-linux-gnu/" >> /etc/ld.so.conf /sbin/ldconfig -v
创建bind-igbuio.sh脚本,将测试用网口绑定到igb_uio。
执行ethtool -i eth1命令,获取用于DPDK测试的网卡的PCI地址。本文以DPDK测试网卡为eth1为例,回显信息如下。
执行cd /root/;vim bind-igbuio.sh命令,创建bind-igbuio.sh文件。
按i,进入编辑模式。
在bind-igbuio.sh文件中,输入如下内容,并替换nic_bdf值为步骤a查到的测试网卡PCI地址。
#!/bin/bash # 指定DPDK源代码目录 dpdk_dir=/root/dpdk/ # 指定需要绑定igb_uio的网卡PCI地址 nic_bdf=0000:11:00.0 # 使用当前目录下载dpdk-kmods源代码 cur_dir=$(cd $(dirname $0); pwd) net_str=$(ls -l /sys/class/net/ | grep $nic_bdf) eth_str=${net_str##*/} # 若dpdk-kmods文件夹不存在则下载 if [ ! -e $cur_dir/dpdk-kmods/linux/igb_uio ] then git clone https://dpdk.org/git/dpdk-kmods ; echo $? fi # 编译igb_uio.ko cd $cur_dir/dpdk-kmods/linux/igb_uio/ ; make ; modprobe uio ; insmod igb_uio.ko ; echo $? ifconfig $eth_str down ; echo $? # 绑定网卡到igb_uio cd $dpdk_dir ; ./usertools/dpdk-devbind.py --bind=igb_uio $nic_bdf ; echo $?
按Esc退出编辑模式,输入:wq并按下Enter键,保存并退出文件。
执行chmod +x bind-igbuio.sh指令,赋予bind-igbuio.sh文件执行权限。
执行bash bind-igbuio.sh命令,将测试用网口绑定到igb_uio。
执行lscpu | grep 'NUMA node(s)'命令,查询实例NUMA数;根据实例NUMA数,执行如下命令,配置大页内存。
echo 16384 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages cat /sys/kernel/mm/hugepages/hugepages-2048kB/free_hugepages
echo 16384 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages echo 16384 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages cat /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages cat /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages cat /sys/devices/system/node/node0/hugepages/hugepages-2048kB/free_hugepages cat /sys/devices/system/node/node1/hugepages/hugepages-2048kB/free_hugepages
双NUMA实例
单NUMA实例
在被测试机和辅助测试机上,按如下操作运行Pktgen。
0xffff1:表示进程使用的CPU掩码,其中最低BIT CPU用于shell控制,其他CPU可以用于端口收发包。
[1-32:1-32].0:表示CPU编号,该CPU编号不能超出掩码中用于收发包的CPU范围。
1-32(冒号前):用于收包
1-32(冒号后):用于发包
.0:表示端口为0
执行cd /root/;vim run.sh命令,创建run.sh文件。
按i,进入编辑模式。
在run.sh文件中,输入如下内容。
#!/bin/bash pktgen_dir=/root/Pktgen-DPDK/ # 修改为您服务器上已经编译的Pktgen-DPDK源代码目录 nic_bdf=11:00.0 # 修改为您服务器上已经绑定igb_uio的网卡PCI地址 $pktgen_dir/build/app/pktgen -c 0x1ffffffff -n 4 -a $nic_bdf,speed=100000 -- -P -m "[1-32:1-32].0"
按Esc退出编辑模式,输入:wq并按下Enter键,保存并退出文件。
执行chmod +x run.sh指令,赋予run.sh文件执行权限。
执行bash run.sh命令,启动Pktgen。
在辅助测试机的Pktgen中,执行以下命令,启动发包。
set 0 proto udp range 0 src mac start 00:16:3e:5c:xx:xx #辅助测试机器网络设备MAC地址 range 0 src mac min 00:16:3e:5c:xx:xx #辅助测试机器网络设备MAC地址 range 0 src mac inc 00:00:00:00:00:00 range 0 dst mac start 00:16:3e:3b:xx:xx #被测试机器网络设备MAC地址 range 0 dst mac min 00:16:3e:3b:xx:xx #被测试机器网络设备MAC地址 range 0 dst mac inc 00:00:00:00:00:00 range 0 src port start 10000 range 0 src port min 10000 range 0 src port max 10000 range 0 src port inc 0 range 0 dst port start 2000 range 0 dst port min 2000 range 0 dst port max 2255 range 0 dst port inc 1 range 0 proto udp range 0 src ip start 192.XX.XX.17 #辅助测试机器私网IP range 0 src ip min 192.XX.XX.17 #辅助测试机器私网IP range 0 src ip inc 0.0.0.0 range 0 size start 64 #包大小(最小为64) range 0 size min 64 range 0 size max 64 range 0 size inc 0 range 0 dst ip start 192.XX.XX.143 #被测试机器私网IP range 0 dst ip min 192.XX.XX.143 #被测试机器私网IP range 0 dst ip inc 0.0.0.0 enable all range start 0
按注释说明,将命令行中辅助测试机/被测试机的MAC地址、私网IP地址改为实际测试环境的MAC地址、IP地址。
执行以下命令前,请删除带#的注释,否则可能导致命令执行失败。
在被测试机器Pktgen中观察收包pps和对应的bps。
将端口回绑到virtio-pci。
执行cd /root/;vim bind-virtio.sh命令,创建bind-virtio.sh文件。
按i,进入编辑模式。
在bind-virtio.sh文件中,输入如下内容。
#!/bin/bash dpdk_dir=/root/dpdk/ # 修改为您的云服务器的DPDK源代码目录 nic_bdf=11:00.0 # 需改为您需要绑定igb_uio的网卡PCI地址 cd $dpdk_dir ; ./usertools/dpdk-devbind.py --unbind $nic_bdf ; echo $? rmmod igb_uio ; echo $? cd $dpdk_dir ; ./usertools/dpdk-devbind.py --bind=virtio-pci $nic_bdf ; echo $? eth_int=0 while [ "$eth_int" == "0" ] do eth_int=$(ls -l /sys/class/net/ | grep $nic_bdf | wc -l) done net_str=$(ls -l /sys/class/net/ | grep $nic_bdf) eth_str=${net_str##*/} eth_int=0 while [ "$eth_int" == "0" ] do eth_int=$(ifconfig -a | grep $eth_str | wc -l) done ifconfig $eth_str up; echo $?
按Esc退出编辑模式,输入:wq并按下Enter键,保存并退出文件。
执行chmod +x bind-virtio.sh指令,赋予bind-virtio.sh文件执行权限。
执行bash bind-virtio.sh命令,运行脚本。
测试网络带宽
远程连接被测试机和辅助测试机,具体操作请参见登录实例。
在被测试机和辅助测试机上,执行以下命令安装iperf3。
apt update apt install -y iperf3
在被测试机上创建iperf3-srv.sh文件,并添加可执行权限。
执行命令vim iperf3-srv.sh,创建iperf3-srv.sh文件。
按i,进入编辑模式。
在iperf3-srv.sh文件中,输入如下内容。
#!/bin/bash # iperf3-srv.sh lcore_num=$(lscpu | grep "^CPU(s):" | awk '{ print $2; }') proc_num=$(($lcore_num < 32 ? $lcore_num : 32)) core_sibling=$(cat /sys/devices/system/cpu/cpu0/topology/thread_siblings_list) for ((i = 0; i < $proc_num ; i = i + 1)); do port=$(($i + 5201)) if [[ $lcore_num -gt 96 && $core_sibling == "0-1" ]]; then lcore=$(($i * 2)) else lcore=$(($i % $lcore_num)) fi taskset -c $lcore iperf3 -s -p $port & done
按Esc退出编辑模式,输入:wq并按下Enter键,保存并退出文件。
执行chmod +x iperf3-srv.sh命令,赋予iperf3-srv.sh文件执行权限。
在被测试机上,执行./iperf3-srv.sh命令, 启动iperf3 server进程。
(可选)如果实例的网络带宽是96Gbit/s,即为c3i.48xlarge(邀测)、g3i.48xlarge(邀测)、r3i.48xlarge(邀测)或者三代裸金属实例,还需要在被测试机和辅助测试机上执行如下脚本,中断绑核。
若为其它实例则跳过此步骤。实例网络带宽数据请参见实例规格介绍。#!/bin/bash # bind-intr.sh #stop cloud-monitor-agent service service cloud-monitor-agent stop > /dev/null 2>&1 #stop irqbalance service service irqbalance stop > /dev/null 2>&1 service irqbalance-ng stop > /dev/null 2>&1 a=$(cat /proc/interrupts | grep virtio | grep put | awk -F ':' '{print $1}') MASK="ffffffff" for irq in $a; do echo $MASK > /proc/irq/$irq/smp_affinity done
(可选)如果为搭载了第四代AMD EPYCTM Genoa处理器的裸金属实例,例如ebmg3ad/ebmc3ad,请在辅助测试机上创建如下脚本,使能xps建立txq与cpu一一映射。若为其它实例则跳过本步骤。
执行命令vim xps_setup.sh,创建xps_setup.sh文件并添加如下内容。
#!/bin/bash # xps_setup.sh function usage() { echo "Change setting of XPS txq to CPU mapping via files" echo " /sys/class/net/DEV/queues/tx-*/xps_cpus " echo "" echo "Usage: $0 [-h] --dev ethX --txq N --cpu N" echo " -d | --dev : (\$DEV) Interface/device (required)" echo " --default : (\$DEFAULT) Setup 1:1 mapping TXQ-to-CPU" echo " --disable : (\$DISABLE) Disable XPS via mask 0x00" echo " -v | --verbose : (\$VERBOSE) verbose" echo "" } ## -- General shell logging cmds -- function err() { local exitcode=$1 shift echo -e "ERROR: $@" >&2 exit $exitcode } function info() { if [[ -n "$VERBOSE" ]]; then echo "# $@" fi } function sorted_txq_xps_cpus() { local queues=$(ls /sys/class/net/$DEV/queues/tx-*/xps_cpus | sort --field-separator='-' -k2n) echo $queues } function cpu_to_mask() { local cpu=$1 printf "%X" $((1 << $cpu)) } function xps_setup_1to1_mapping() { local cpu=0 local txq=0 for xps_cpus in $(sorted_txq_xps_cpus); do if [[ "$DISABLE" != "yes" ]]; then # Map the TXQ to CPU number 1-to-1 mask=$(cpu_to_mask $cpu) else # Disable XPS on TXQ mask=0 fi echo $mask > $xps_cpus info "NIC=$DEV TXQ:$txq use CPU $cpu (MQ-leaf :$mqleaf)" let cpu++ let txq++ done } ## --- Parse command line arguments / parameters --- while true; do case "$1" in -d | --dev ) # device export DEV=$2 info "Device set to: DEV=$DEV" >&2 shift 2 ;; -v | --verbose) export VERBOSE=yes # info "Verbose mode: VERBOSE=$VERBOSE" >&2 shift ;; --default ) info "Setup default 1-to-1 mapping TXQ-to-CPUs" >&2 export DEFAULT=yes shift 1 ;; --disable ) info "Disable XPS via mask 0x00" >&2 export DISABLE=yes shift 1 ;; -- ) shift break ;; -h | --help ) usage; exit 0 ;; * ) shift break ;; esac done if [ -z "$DEV" ]; then usage err 2 "Please specify device" fi if [[ -n "$DEFAULT" ]]; then xps_setup_1to1_mapping fi if [[ "$DISABLE" == "yes" ]]; then if [[ -z "$DEFAULT" && -z "$TXQ" ]]; then err 5 "Use --disable together with --default" fi fi
按Esc退出编辑模式,然后输入:wq并回车。
执行命令chmod +x xps_setup.sh,赋予xps_setup.sh文件执行权限。
执行命令./xps_setup.sh -d eth0 --default,使能xps建立txq与cpu一一映射。
在辅助测试机器上创建iperf3-cli.sh文件,并添加可执行权限。
执行vim iperf3-cli.sh命令,创建iperf3-cli.sh文件。
按i,进入编辑模式。
在iperf3-cli.sh文件中,输入如下内容。
#!/bin/bash # iperf3-cli.sh if [ $# -ne 2 ]; then echo $0 "<server_ip> <time_secs>" exit 255 fi lcore_num=$(lscpu | grep "^CPU(s):" | awk '{ print $2; }') proc_num=$(($lcore_num < 32 ? $lcore_num : 32)) core_sibling=$(cat /sys/devices/system/cpu/cpu0/topology/thread_siblings_list) for ((i=0 ; i < $proc_num; i = i + 1)); do port=$(($i + 5201)) #check instance is 192C vm if [[ $lcore_num -gt 96 && $core_sibling == "0-1" ]]; then lcore=$(($i * 2)) else lcore=$(($i % $lcore_num)) fi taskset -c $lcore iperf3 -c $1 -p $port -t $2 -P 4 2>&1 & done
按Esc退出编辑模式,输入:wq并按下Enter键,保存并退出文件。
执行chmod +x iperf3-cli.sh命令,赋予iperf3-cli.sh文件执行权限。
在辅助测试机器执行如下命令,启动iperf3 client进程。
./iperf3-cli.sh <被测机器私有IP> 300
在被测试机器端执行sar -n DEV 1,查看结果,下图中rxkB/s列的数据即为接收带宽。
单位换算: [rxkB/s] * 8 * 1024 / 1000000000=Gbps
测试网络时延
远程连接被测试机和辅助测试机,具体操作请参见登录实例。
(可选)虚机实例可跳过此步骤,裸机实例需执行以下步骤开启cpu performance模式。
在被测试机和辅助测试机上执行以下命令,安装cpupower。
apt update apt install -y linux-intel-iotg-tools-common linux-tools-5.15.0-48-generic
在安装linux-tools-5.15.0-48-generic时,可能会报如下错误信息:
该报错是因为工具/usr/bin/acpidbg在第1个安装包linux-intel-iotg-tools-common已经安装。可执行如下命令(linux-tools-common版本号使用错误提示中的版本号),强制覆盖安装红框的指定的包解决。
dpkg -i --force-overwrite /var/cache/apt/archives/linux-tools-common_5.15.0-66.73_all.deb
在被测试机和辅助测试机上执行以下命令,设置所有CPU为性能模式。
cpupower -c all frequency-set -g performance
在测试机上,执行以下命令,测试网络时延。
min表示最小时延,avg表示平均时延,max表示最大时延,单位为ms。
ping -f -c 10000 <辅助测试机私网IP地址>