a) 服务器:Sugon W560-G20 workstation
b) 处理器:Intel Xeno E5 -2660 V3处理器(2.60GHz) 20 CPU cores*2 NUMA nodes
c) 内存:128G,2*32GB DIMMs * 2NUMA nodes 2133MHz
d) 主板:S7070A2NR-B,PCIe_4x16(CPU0),PCIe_2x16(CPU1)
e) 网卡:Mellanox ConnectX-4 Lx 25GbE网卡
a) 操作系统:RedHat Linux 7.1
(default_hugepage_size=2G)
b) BIOS:AMI v7.102.R01 2016/3/30
(Power Profile PERFORMANCE; C-states OFF; P-states OFF;TurboBoost ON; HyperThreading OFF; Virt OFF; VTd OFF; SR-IOV OFF; SMI OFFIONonPostedPrefetching OFF;)
c) 内核版本:3.10.0-229.el7.x86_64
d) 网卡固件版本:14.18.2000
e) 网卡驱动版本:MLNX_OFED_LINUX-4.1-1.0.2.0-rhel7.1-x86_64
f) DPDK版本:MellanoxDPDK 16.11_3.0
(启用mlx5 PMD,CONFIG_RTE_LIBRTE_MLX5_PMD=y)
图1 DPDK性能测试环境
如上图所示,TestPMD应用程序把两个以太网端口连成环回模式。这样可以在没有外部流量发生器的情况下检查网络设备的接收和传输功能。发送的数据包为UDP数据包。
使用Mellanox DPDK 16.11_3.0内提供的测试工具Testpmd。
网卡收发报文速率统计脚本eth_stat.sh
#!/bin/bash
# By [email protected]
IFG_PLUS_PREAMBLE=20 # IFG 12B + Preamble 8B
update_stats () { # $name $index
TS_LAST[$2]=${TS[$2]}
R_PKT_LAST[$2]=${R_PKT[$2]}
R_BYTE_LAST[$2]=${R_BYTE[$2]}
T_PKT_LAST[$2]=${T_PKT[$2]}
T_BYTE_LAST[$2]=${T_BYTE[$2]}
ETHTOOL=($(ethtool -S $1 | awk '/tx_packets_phy/{print $2} /rx_packets_phy/{print $2} /tx_bytes_phy/{print $2} /rx_bytes_phy/{print$2}'))
if [ -z "$ETHTOOL" ]; then
ETHTOOL=($(ethtool -S $1 | awk '/tx_packets/{print $2} /rx_packets/{print $2} /tx_bytes/{print $2} /rx_bytes/{print$2}'))
fi
TS[$2]=$(date +%s%6N) # in usec
T_PKT[$2]=${ETHTOOL[0]}
R_PKT[$2]=${ETHTOOL[1]}
T_BYTE[$2]=${ETHTOOL[2]}
R_BYTE[$2]=${ETHTOOL[3]}
}
if [ -z $1 ] && [ -x /usr/bin/ibdev2netdev ]; then
NETIF=$(ibdev2netdev | awk '/mlx/{print $5}')
else
NETIF=$@
fi
if [ -z "$NETIF" ]; then
printf "No interface can't be found\n"
exit 1
fi
# set initial value
index=0
for name in $NETIF; do
update_stats $name $index
((index++))
done
index=0
for name in $NETIF; do
R_PKT_INIT[$index]=${R_PKT[$index]}
T_PKT_INIT[$index]=${T_PKT[$index]}
R_BYTE_INIT[$index]=${R_BYTE[$index]}
T_BYTE_INIT[$index]=${T_BYTE[$index]}
((index++))
done
sleep 1
while true; do
index=0
for name in $NETIF; do
update_stats $name $index
TS_DIFF=$((${TS[$index]} - ${TS_LAST[$index]}))
R_PKT_DELTA=$(( ${R_PKT[$index]} - ${R_PKT_LAST[$index]} ))
R_PKT_RATE=$(( $R_PKT_DELTA * 1000000 / $TS_DIFF))
R_BIT_DELTA=$(( (${R_BYTE[$index]} - ${R_BYTE_LAST[$index]} + $IFG_PLUS_PREAMBLE * $R_PKT_DELTA) * 8 ))
R_BIT_RATE=$(( $R_BIT_DELTA * 1000000 / $TS_DIFF))
T_PKT_DELTA=$(( ${T_PKT[$index]} - ${T_PKT_LAST[$index]} ))
T_PKT_RATE=$(( $T_PKT_DELTA * 1000000 / $TS_DIFF))
T_BIT_DELTA=$(( (${T_BYTE[$index]} - ${T_BYTE_LAST[$index]} + $IFG_PLUS_PREAMBLE * $T_PKT_DELTA) * 8 ))
T_BIT_RATE=$(( $T_BIT_DELTA * 1000000 / $TS_DIFF))
R_PKT_TOTAL=$(( ${R_PKT[$index]} - ${R_PKT_INIT[$index]} ))
T_PKT_TOTAL=$(( ${T_PKT[$index]} - ${T_PKT_INIT[$index]} ))
R_BYTE_TOTAL=$(( ${R_BYTE[$index]} - ${R_BYTE_INIT[$index]} ))
T_BYTE_TOTAL=$(( ${T_BYTE[$index]} - ${T_BYTE_INIT[$index]} ))
printf "[%'9s Rx]: %'16d pkts %'16d pps | %'20d bytes %'16d bps \n" $name $R_PKT_TOTAL $R_PKT_RATE $R_BYTE_TOTAL $R_BIT_RATE
printf "[%'9s Tx]: %'16d pkts %'16d pps | %'20d bytes %'16d bps \n" $name $T_PKT_TOTAL $T_PKT_RATE $T_BYTE_TOTAL $T_BIT_RATE
((index++))
done
printf "\n"
sleep 1
done
表1 Testpmd测试结果
序号 |
Pkt_data_len |
DEF_PKT_BURST |
nbcore |
nb_rxq/txq |
RTE_TEST_RX_DESC_DEFAULT |
RTE_TEST_TX_DESC_DEFAULT |
Gbps |
1 |
64 |
32 |
1 |
1 |
128 |
512 |
5.6 |
2 |
128 |
32 |
1 |
1 |
128 |
512 |
9.7 |
3 |
256 |
32 |
1 |
1 |
128 |
512 |
10 |
4 |
64 |
64 |
1 |
1 |
128 |
512 |
7.4 |
5 |
64 |
128 |
1 |
1 |
128 |
512 |
7.5 |
6 |
64 |
256 |
1 |
1 |
128 |
512 |
7.5 |
7 |
64 |
256 |
1 |
1 |
512 |
1024 |
7.5 |
8 |
64 |
32 |
2 |
1 |
128 |
512 |
5.9 |
9 |
64 |
32 |
3 |
1 |
128 |
512 |
5.9 |
10 |
64 |
32 |
1 |
2 |
128 |
512 |
7.3 |
11 |
64 |
32 |
2 |
2 |
128 |
512 |
9.3 |
12 |
64 |
64 |
1 |
2 |
128 |
512 |
7.5 |
13 |
64 |
64 |
2 |
2 |
128 |
512 |
9.5 |
14 |
64 |
128 |
1 |
2 |
128 |
512 |
7.2 |
15 |
64 |
128 |
3 |
2 |
128 |
512 |
9.5 |
16 |
128 |
32 |
1 |
2 |
128 |
512 |
9.9 |
17 |
64 |
32 |
1 |
3 |
128 |
512 |
7.2 |
18 |
64 |
32 |
2 |
3 |
128 |
512 |
9.9 |
19 |
64 |
64 |
1 |
3 |
128 |
512 |
7.7 |
20 |
64 |
64 |
2 |
3 |
128 |
512 |
9.6 |
21 |
64 |
128 |
2 |
3 |
128 |
512 |
9.5 |
22 |
128 |
32 |
1 |
3 |
128 |
512 |
9.9 |
23 |
64 |
32 |
1 |
4 |
128 |
512 |
6.9 |
24 |
64 |
32 |
2 |
4 |
128 |
512 |
9.6 |
25 |
64 |
64 |
1 |
4 |
128 |
512 |
7.1 |
26 |
64 |
64 |
2 |
4 |
128 |
512 |
9.6 |
27 |
64 |
128 |
1 |
4 |
128 |
512 |
7.1 |
28 |
64 |
128 |
2 |
4 |
128 |
512 |
9.6 |
29 |
64 |
32 |
1 |
5 |
128 |
512 |
6.8 |
30 |
64 |
32 |
2 |
5 |
128 |
512 |
9.6 |
31 |
64 |
64 |
1 |
5 |
128 |
512 |
7.3 |
32 |
64 |
64 |
2 |
5 |
128 |
512 |
9.6 |
33 |
64 |
128 |
1 |
5 |
128 |
512 |
7.0 |
34 |
64 |
32 |
1 |
6 |
128 |
512 |
6.7 |
35 |
64 |
32 |
2 |
6 |
128 |
512 |
9.6 |
36 |
64 |
64 |
1 |
6 |
128 |
512 |
7.2 |
37 |
64 |
128 |
1 |
6 |
128 |
512 |
6.9 |
38 |
64 |
32 |
1 |
7 |
128 |
512 |
6.5 |
39 |
64 |
32 |
2 |
7 |
128 |
512 |
9.6 |
40 |
64 |
64 |
1 |
7 |
128 |
512 |
7.2 |
41 |
64 |
128 |
1 |
7 |
128 |
512 |
6.9 |
42 |
64 |
32 |
1 |
8 |
128 |
512 |
6.4 |
43 |
64 |
64 |
1 |
8 |
128 |
512 |
6.8 |
44 |
64 |
128 |
1 |
8 |
128 |
512 |
6.7 |
45 |
64 |
128 |
2 |
8 |
128 |
512 |
9.7 |
表1中,各字段含义如下:
Pkt_data_len:报文长度,单位字节
DEF_PKT_BURST:一次发送报文的数量
Nbcore:处理报文的CPU核数目
nb_rxq/txq:报文接收队列,发送队列数目
RTE_TEST_RX_DESC_DEFAULT:收包队列长度
RTE_TEST_TX_DESC_DEFAULT:发包队列长度
Gbps:网卡数据包通过率 Gbit/sec
表1中列出了除硬件和软件环境外影响网卡收发包性能的6个因素。分析如下:
1、 数据包大小对网卡速率影响最大,当数据包大小达到128字节后,速率能到10Gbps以上(目前光模块只支持到10G)。
2、 在数据包大小为64字节时,一次发送报文的数量越多,通过率越大。
3、 处理报文的CPU核数目越多,通过率越大。
4、 在处理报文的CPU核数目较多的情况下增加报文接收发送队列数目能显著提高通过率,但是如果CPU核数目较少,增加报文接收发送队列数目会带来CPU在处理多个队列时切换开销较大,从而降低通过率。
5、 收包队列长度和发包队列长度对网卡速率影响较小,其中收包队列长度为128,发包队列长度为512能满足大部分场景的应用。