pktgen
是Linux
内核自带的高性能网络测试工具(高性能发包工具),可实现在内核高速发包。主要用来测试网络驱动与网卡设备,支持多线程,能够产生随机MAC
地址、IP
地址、UDP
端口号的数据包。由于pktgen
是内核内置的,使用内核空间,所以它可以达到高带宽、高发包速率,可用于测试网卡发送速率,也可以用来测试其他网络设备(如路由器和交换机)。
pktgen
的配置与统计信息查看都通过/proc
文件系统完成,/proc
文件系统是一种特殊的,由软件创建的文件系统,内核使用/proc
文件系统向外界导出信息,外界也可以通过它配置内核态的一些进程的参数,如ps、top、 uptime
等Linux
发行版中的很多工具就是通过/proc
实现的。在大多情况下,我们只用/proc
读出数据(用于调试内核驱动等),而在pktgen
中配置命令就用到了/proc
的写入数据功能。
注意:
pktgen
是一个Linux
内核模块,非用户态工具,不能通过命令行的方式直接运行pktgen
。
pktgen
不是全能的发包工具,目前仅支持UDP
报文。
在 Linux
系统中,你并不能直接找到pktgen
命令。因为pktgen
作为一个内核线程来运行,需要你加载pktgen
内核模块后,再通过/proc
文件系统来交互。pktgen
作为内核内置的模块,它的加载有两种方式,一种是在命令行直接通过modprobe
加载,另一种是通过源码编译出pktgen.ko
模块,再insmod
或modprobe
加载。
目前,有些Linux
机器上自带了pktgen.ko
文件,而有些Linux
机器上则没有该文件,网上的说法是如果内核的/boot/config-$(uname -r)
文件中含有CONFIG_NET_PKTGEN=m
,则内核默认会编译出pktgen.ko
文件,但我发现实际却并非如此,也不知道这个说法是怎么来的,果然实践才能出真知。
我们可以直接在命令行执行modprobe pktgen
命令,如果在Linux
系统中自带了pktgen.ko
文件,则可直接加载成功,如果Linux
中没有pktgen.ko
文件,则会直接报找不到该文件的错误。我分别在两个Linux
系统机器中进行了实验,如下:
#机器一
[root@localhost ~]# modprobe pktgen
[root@localhost ~]# lsmod | grep pktgen
pktgen 61440 0
#机器二
[root@localhost ~]# modprobe pktgen
modprobe: FATAL: Module pktgen not found in directory /lib/modules/4.18.0-394.el8.x86_64
注意:
Linux
系统pktgen.ko
文件的默认存放目录/lib/modules/$(uname -r)/kernel/net/core/
,如果在默认存放目录下有pktgen.ko
文件,则可直接modprobe
加载。
如果该Linux
系统中没有自带pktgen.ko
文件,则我们可以通过方法二来自己编译pktgen.ko
文件,然后进行加载安装。
通过yum install kernel-devel-$(uname -r)
命令安装内核开发包。默认安装目录为/usr/src/kernels
。下载pktgen.c(https://github.com/torvalds/linux/blob/master/net/core/pktgen.c)
源码文件,在pktgen.c
文件所在目录创建Makefile
文件,内容如下:
#关闭模块签名验证功能
CONFIG_MODULE_SIG=n
obj-m += pktgen.o
KDIR := /lib/modules/$(shell uname -r)/build
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
注意:动态安装模块的时候可能会出现
insmod error required key not available
,即内核签名问题,因此,建议在Makefile
文件中设置CONFIG_MODULE_SIG=n
。
在pktgen.c
文件所在目录执行make
指令编译内核模块,如下:
[root@localhost pktgen_source]# ls
Makefile pktgen.c
[root@localhost pktgen_source]#
[root@localhost pktgen_source]# make
make -C /lib/modules/4.18.0-500.el8.x86_64/build M=/home/lxy/pktgen_source modules
make[1]: Entering directory '/usr/src/kernels/4.18.0-500.el8.x86_64'
CC [M] /home/lxy/pktgen_source/pktgen.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/lxy/pktgen_source/pktgen.mod.o
LD [M] /home/lxy/pktgen_source/pktgen.ko
make[1]: Leaving directory '/usr/src/kernels/4.18.0-500.el8.x86_64'
[root@localhost pktgen_source]#
[root@localhost pktgen_source]# ls
Makefile modules.order Module.symvers pktgen.c pktgen.ko pktgen.mod.c pktgen.mod.o pktgen.o
[root@localhost pktgen_source]# insmod ./pktgen.ko
[root@localhost pktgen_source]# lsmod | grep pktgen
pktgen 57344 0
[root@localhost pktgen_source]# ls -l /proc/net/pktgen/
total 0
-rw-------. 1 root root 0 Nov 2 17:20 kpktgend_0
-rw-------. 1 root root 0 Nov 2 17:20 kpktgend_1
-rw-------. 1 root root 0 Nov 2 17:20 kpktgend_10
-rw-------. 1 root root 0 Nov 2 17:20 kpktgend_11
-rw-------. 1 root root 0 Nov 2 17:20 kpktgend_12
-rw-------. 1 root root 0 Nov 2 17:20 kpktgend_13
-rw-------. 1 root root 0 Nov 2 17:20 kpktgend_14
-rw-------. 1 root root 0 Nov 2 17:20 kpktgend_15
-rw-------. 1 root root 0 Nov 2 17:20 kpktgend_2
-rw-------. 1 root root 0 Nov 2 17:20 kpktgend_3
-rw-------. 1 root root 0 Nov 2 17:20 kpktgend_4
-rw-------. 1 root root 0 Nov 2 17:20 kpktgend_5
-rw-------. 1 root root 0 Nov 2 17:20 kpktgend_6
-rw-------. 1 root root 0 Nov 2 17:20 kpktgend_7
-rw-------. 1 root root 0 Nov 2 17:20 kpktgend_8
-rw-------. 1 root root 0 Nov 2 17:20 kpktgend_9
-rw-------. 1 root root 0 Nov 2 17:20 pgctrl
加载pktgen.ko
模块后,可以发现/proc/net/pktgen
目录下生成了多个kpktgend_*
文件,其中kpktgen_*
的多少是根据你的CPU
的个数决定的,如我的机子的CPU
数目为16
,则有16
个此文件。kpktgend_*
是内核数据包生产线程, 每个CPU
都会启动一个相应的线程,如果要添加某个测试网卡, 可以通过向该文件节点写入add_device ethX
; pgctrl
用于控制网卡性能测试状态,需要在对应的线程执行网卡的吞吐量测试, 有start
/stop
/reset
三种状态。
通过命令cat /proc/net/pktgen/pgctrl
可以查看pktgen的版本等信息:
[root@localhost pktgen_source]# cat /proc/net/pktgen/pgctrl
Packet Generator for packet performance testing. Version: 2.75
# 构建2个VF
[root@localhost pktgen]# echo 2 > /sys/class/net/ens4f0np0/device/sriov_numvfs
[root@localhost pktgen]# list-iface-info.sh
eno1np0 bnxt_en P 0 p0
ens4f0np0 nfp P 0 p0
ens5f0np0 nfp P 0 p0
eno2np1 bnxt_en P 1 p1
ens4f1np1 nfp P 1 p1
ens5f1np1 nfp P 1 p1
eno3 tg3 PCI 0000:01:00.0
eno4 tg3 PCI 0000:01:00.1
ens4f0v0 nfp_netvf PCI 0000:af:00.4
ens4f0v1 nfp_netvf PCI 0000:af:00.5
# 创建网络命名空间模拟虚拟机
[root@localhost pktgen]# ip netns add ns1
[root@localhost pktgen]# ip netns add ns2
# 添加VF到网络命名空间中
[root@localhost pktgen]# ip link set ens4f0v0 netns ns1
[root@localhost pktgen]# ip link set ens4f0v1 netns ns2
#查看网络命名空间ns1中的网卡
[root@localhost pktgen]# ip netns exec ns1 ip a
1: lo: mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
55: ens4f0v0: mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether ea:0c:48:be:43:09 brd ff:ff:ff:ff:ff:ff
# 配置网络命名空间中网卡的IP地址
[root@localhost pktgen]# ip netns exec ns1 ifconfig ens4f0v0 192.168.1.11/24 up
[root@localhost pktgen]# ip netns exec ns2 ifconfig ens4f0v1 192.168.1.12/24 up
[root@localhost pktgen]#
[root@localhost pktgen]# ip netns exec ns1 ip a
1: lo: mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
55: ens4f0v0: mtu 1500 qdisc mq state UP group default qlen 1000
link/ether ea:0c:48:be:43:09 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.11/24 brd 192.168.1.255 scope global ens4f0v0
valid_lft forever preferred_lft forever
inet6 fe80::e80c:48ff:febe:4309/64 scope link
valid_lft forever preferred_lft forever
[root@localhost pktgen]#
[root@localhost pktgen]# ip netns exec ns2 ip a
1: lo: mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
56: ens4f0v1: mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 7e:6c:0c:13:80:a6 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.12/24 brd 192.168.1.255 scope global ens4f0v1
valid_lft forever preferred_lft forever
inet6 fe80::7c6c:cff:fe13:80a6/64 scope link
valid_lft forever preferred_lft forever
#查看两个网络命名空间是否连通
[root@localhost pktgen]# ip netns exec ns2 ping -I ens4f0v1 192.168.1.11
PING 192.168.1.11 (192.168.1.11) from 192.168.1.12 ens4f0v1: 56(84) bytes of data.
64 bytes from 192.168.1.11: icmp_seq=1 ttl=64 time=0.496 ms
64 bytes from 192.168.1.11: icmp_seq=2 ttl=64 time=0.247 ms
^C
--- 192.168.1.11 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1046ms
rtt min/avg/max/mdev = 0.247/0.371/0.496/0.125 ms
在使用 pktgen
测试网络性能时,需要先给每个内核线程 kpktgend_X
以及测试网卡配置 pktgen
选项,然后再通过 pgctrl
启动测试。将虚拟机ns1
中的网口ens4f0v0
放到对应kpktgend_0
内核线程中,并配置发送报文字段,以发包测试为例,假设发包机器ns1
使用的网卡是 ens4f0v0
,而目标机器的 IP
地址为 192.168.1.12
,MAC
地址为 7e:6c:0c:13:80:a6
。
构造pktgen
配置脚本pktgen_start.sh
如下:
# 定义一个工具函数,方便后面配置各种测试选项
function pgset() {
local result
echo $1 > $PGDEV
result=`cat $PGDEV | fgrep "Result: OK:"`
if [ "$result" = "" ]; then
cat $PGDEV | fgrep Result:
fi
}
# 为0号线程绑定ens4f0v0网卡
PGDEV=/proc/net/pktgen/kpktgend_0
echo "Removing all devices"
pgset "rem_device_all" # 清空网卡绑定
echo "Adding ens4f0v0"
pgset "add_device ens4f0v0" # 添加ens4f0v0网卡
echo "Setting max_before_softirq 10000"
pgset "max_before_softirq 10000"
# 配置ens4f0v0网卡的测试选项
PGDEV=/proc/net/pktgen/ens4f0v0
pgset "count 1000000" # 总发包数量,0 表示一直发送
pgset "delay 5000" # 不同包之间的发送延迟(单位纳秒)
pgset "clone_skb 0" # SKB包复制,表示复制多少数据包,clone_skb=1000,克隆1000报文;clone_skb=0表示不克隆,就是一直发送同一个报文。
pgset "pkt_size 64" # 网络包大小
pgset "dst 192.168.1.12" # 目的IP
pgset "src_mac ea:0c:48:be:43:09" # 源MAC
pgset "dst_mac 7e:6c:0c:13:80:a6" # 目的MAC
# 启动测试
PGDEV=/proc/net/pktgen/pgctrl
echo "Running... ctrl^C to stop"
pgset "start"
echo "Done"
执行pktgen_start.sh
脚本,如下:
[root@localhost pktgen]# ./pktgen_start.sh
Removing all devices
Adding ens4f0v0
Setting max_before_softirq 10000
Running... ctrl^C to stop
Done
等待片刻,测试完成后,结果可以从 /proc
文件系统中获取。通过下面代码段中的内容,我们可以查看到刚才的测试报告:
[root@localhost pktgen]# cat /proc/net/pktgen/ens4f0v0
Params: count 1000000 min_pkt_size: 64 max_pkt_size: 64
frags: 0 delay: 5000 clone_skb: 0 ifname: ens4f0v0
flows: 0 flowlen: 0
queue_map_min: 0 queue_map_max: 0
dst_min: 192.168.1.12 dst_max:
src_min: src_max:
src_mac: ea:0c:48:be:43:09 dst_mac: 7e:6c:0c:13:80:a6
udp_src_min: 9 udp_src_max: 9 udp_dst_min: 9 udp_dst_max: 9
src_mac_count: 0 dst_mac_count: 0
Flags:
Current:
pkts-sofar: 1000000 errors: 0
started: 1910279455101us stopped: 1910284455352us idle: 4381728us
seq_num: 1000001 cur_dst_mac_offset: 0 cur_src_mac_offset: 0
cur_saddr: 192.168.1.11 cur_daddr: 192.168.1.12
cur_udp_dst: 9 cur_udp_src: 9
cur_queue_map: 0
flows: 0
Result: OK: 5000250(c618521+d4381728) usec, 1000000 (64byte,0frags)
199989pps 102Mb/sec (102394368bps) errors: 0
测试报告主要分为三个部分:
Params
是测试选项;Current
是测试进度,其中, packts so far(pkts-sofar)
表示已经发送了 100
万个包,也就表明测试已完成。Result
是测试结果,包含测试所用时间、网络包数量和分片、PPS、吞吐量以及错误数;其中测试用时5000250
纳秒,总共1000000 64
字节包,每秒 199989
包,吞吐量 102Mb/s
,0
错误。构造pktgen
配置脚本pktgen_start.sh
如下:
# 定义一个工具函数,方便后面配置各种测试选项
function pgset() {
local result
echo $1 > $PGDEV
result=`cat $PGDEV | fgrep "Result: OK:"`
if [ "$result" = "" ]; then
cat $PGDEV | fgrep Result:
fi
}
# 为0号线程绑定ens4f0v0网卡
PGDEV=/proc/net/pktgen/kpktgend_0
echo "Removing all devices"
pgset "rem_device_all" # 清空网卡绑定
echo "Adding ens4f0v0"
pgset "add_device ens4f0v0" # 添加ens4f0v0网卡
echo "Setting max_before_softirq 10000"
pgset "max_before_softirq 10000"
# 配置ens4f0v0网卡的测试选项
PGDEV=/proc/net/pktgen/ens4f0v0
pgset "count 0" # 总发包数量,0 表示一直发送
pgset "delay 5000" # 不同包之间的发送延迟(单位纳秒)
pgset "clone_skb 0" # SKB包复制,表示复制多少数据包,clone_skb=1000,克隆1000报文;clone_skb=0表示不克隆,就是一直发送同一个报文。
pgset "pkt_size 64" # 网络包大小
pgset "dst 192.168.1.12" # 目的IP
pgset "src_mac ea:0c:48:be:43:09" # 源MAC
pgset "dst_mac 7e:6c:0c:13:80:a6" # 目的MAC
# 启动测试
PGDEV=/proc/net/pktgen/pgctrl
echo "Running... ctrl^C to stop"
pgset "start"
echo "Done"
执行pktgen_start.sh
脚本,如下:
[root@localhost pktgen]# ./pktgen_start.sh
Removing all devices
Adding ens4f0v0
Setting max_before_softirq 10000
Running... ctrl^C to stop
^C
#注意这里需要进入ns1命名空间,后续top和sar方可生效
[root@localhost ~]# ip netns exec ns1 bash
# top查看kpktgend_0线程,CPU利用率100%
[root@localhost ~]# top
top - 16:51:30 up 22 days, 2:45, 4 users, load average: 0.45, 0.11, 0.04
Tasks: 1154 total, 2 running, 1152 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 1.3 sy, 0.0 ni, 98.2 id, 0.0 wa, 0.0 hi, 0.5 si, 0.0 st
MiB Mem : 95004.3 total, 78765.2 free, 3082.3 used, 13156.7 buff/cache
MiB Swap: 10240.0 total, 10240.0 free, 0.0 used. 91041.1 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1025692 root 20 0 0 0 0 R 100.0 0.0 0:44.83 kpktgend_0
1026886 root 20 0 66672 6180 4160 R 1.0 0.0 0:00.28 top
2257 root 20 0 542808 79216 55736 S 0.3 0.1 20:03.38 tuned
38797 root 20 0 0 0 0 I 0.3 0.0 57:13.30 kworker/43:2-events
737227 root 20 0 0 0 0 I 0.3 0.0 0:00.38 kworker/1:1-events
1025407 root 20 0 0 0 0 S 0.3 0.0 0:00.13 kpktgend_45
1025421 root 20 0 0 0 0 S 0.3 0.0 0:00.09 kpktgend_59
1025837 root 20 0 0 0 0 S 0.3 0.0 0:00.09 kpktgend_64
1026889 setroub+ 20 0 545408 130552 20008 S 0.3 0.1 0:00.86 setroubleshootd
1 root 20 0 240916 13656 8788 S 0.0 0.0 0:42.28 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:01.06 kthreadd
#查看ns1命名空间中,各个端口收发包情况
[root@localhost ~]# sar -n DEV 1
Linux 4.18.0-348.7.1.el8_5.x86_64 (localhost.localdomain) 11/03/2023 _x86_64_ (80 CPU)
08:25:41 PM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil
08:25:42 PM lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
08:25:42 PM ens4f0v0 1.00 200020.00 0.09 12501.25 0.00 0.00 0.00 0.41
08:25:42 PM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil
08:25:43 PM lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
08:25:43 PM ens4f0v0 1.00 200007.00 0.09 12500.44 0.00 0.00 0.00 0.41
08:25:43 PM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil
08:25:44 PM lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
08:25:44 PM ens4f0v0 1.00 200036.00 0.09 12502.25 0.00 0.00 0.00 0.41
等待片刻,通过Ctrl C
终止测试后,结果可以从 /proc
文件系统中获取。通过下面代码段中的内容,我们可以查看到刚才的测试报告:
[root@localhost pktgen]# cat /proc/net/pktgen/ens4f0v0
Params: count 0 min_pkt_size: 64 max_pkt_size: 64
frags: 0 delay: 5000 clone_skb: 0 ifname: ens4f0v0
flows: 0 flowlen: 0
queue_map_min: 0 queue_map_max: 0
dst_min: 192.168.1.12 dst_max:
src_min: src_max:
src_mac: ea:0c:48:be:43:09 dst_mac: 7e:6c:0c:13:80:a6
udp_src_min: 9 udp_src_max: 9 udp_dst_min: 9 udp_dst_max: 9
src_mac_count: 0 dst_mac_count: 0
Flags:
Current:
pkts-sofar: 9637001 errors: 0
started: 1910680695090us stopped: 1910728880086us idle: 42081825us
seq_num: 9637002 cur_dst_mac_offset: 0 cur_src_mac_offset: 0
cur_saddr: 192.168.1.11 cur_daddr: 192.168.1.12
cur_udp_dst: 9 cur_udp_src: 9
cur_queue_map: 0
flows: 0
Result: OK: 48184996(c6103170+d42081825) usec, 9637001 (64byte,0frags)
200000pps 102Mb/sec (102400000bps) errors: 0
测试报告主要分为三个部分:
Params
是测试选项;Current
是测试进度,其中, packts so far(pkts-sofar)
表示终止时已经发送了960
万个包。Result
是测试结果,包含测试所用时间、网络包数量和分片、PPS、吞吐量以及错误数;其中测试用时48184996
纳秒,总共9637001 64
字节包,每秒 200000
包,吞吐量 102Mb/s
,0
错误。根据上面的结果,我们发现,PPS
为 20
万,吞吐量为 102 Mb/s
,没有发生错误。那么20
万的 PPS
好不好呢?作为对比,你可以计算一下千兆交换机的 PPS
。交换机可以达到线速(满负载时,无差错转发),它的 PPS
就是 1000Mbit
除以以太网帧的大小,即 1000Mbps/((64+20)*8bit) = 1.5 Mpps
(其中,20B
为以太网帧前导和帧间距的大小)。
前面的配置稍微有些复杂,可能用起来不是特别的便捷,Linux
内核提供了更为方便的pktgen
的脚本,在Linux
内核源码的linux/samples/pktgen/
目录下,如下所示:
[root@localhost pktgen]# ls -l /linux/samples/pktgen/
total 52
-rw-r--r--. 1 xf xf 8841 Jun 15 14:52 functions.sh
-rw-rw-r--. 1 xf xf 3767 Jun 15 14:52 parameters.sh
-rwxrwxr-x. 1 xf xf 3390 Jun 15 14:52 pktgen_bench_xmit_mode_netif_receive.sh
-rwxrwxr-x. 1 xf xf 2563 Jun 15 14:52 pktgen_bench_xmit_mode_queue_xmit.sh
-rwxrwxr-x. 1 xf xf 2818 Jun 15 14:52 pktgen_sample01_simple.sh
-rwxrwxr-x. 1 xf xf 3145 Jun 15 14:52 pktgen_sample02_multiqueue.sh
-rwxrwxr-x. 1 xf xf 3382 Jun 15 14:52 pktgen_sample03_burst_single_flow.sh
-rwxrwxr-x. 1 xf xf 3418 Jun 15 14:52 pktgen_sample04_many_flows.sh
-rwxrwxr-x. 1 xf xf 3096 Jun 15 14:52 pktgen_sample05_flow_per_thread.sh
-rwxrwxr-x. 1 xf xf 3981 Jun 15 14:52 pktgen_sample06_numa_awared_queue_irq_affinity.sh
-rw-rw-r--. 1 xf xf 2663 Jun 15 14:52 README.rst
注意:可以通过
git clone git@github.com:torvalds/linux.git
,从github
上获得Linux
官方内核源码,其中即含有pktgen_*
系列脚本以供直接使用。
上一节中的配置就可以简单化成一条命令,如下:
./pktgen_sample01_simple.sh -i ens4f0v0 -m 7e:6c:0c:13:80:a6 -d 192.168.1.12 -t 0 -n 1000
该脚本是通用脚本,部分参数不支持,需要做简单修改,参数含义如下:
Usage: ./pktgen_sample01_simple.sh [-vx] -i ethX
-i : ($DEV) output interface/device (required)
-s : ($PKT_SIZE) packet size
-d : ($DEST_IP) destination IP
-m : ($DST_MAC) destination MAC-addr
-t : ($THREADS) threads to start
-f : ($F_THREAD) index of first thread (zero indexed CPU number)
-c : ($SKB_CLONE) SKB clones send before alloc new SKB
-n : ($COUNT) num messages to send per thread, 0 means indefinitely
-b : ($BURST) HW level bursting of SKBs
-v : ($VERBOSE) verbose
-x : ($DEBUG) debug
-6 : ($IP6) IPv6
该命令的执行结果如下:
[root@localhost pktgen]# ./pktgen_sample01_simple.sh -i ens4f0v0 -m 7e:6c:0c:13:80:a6 -d 192.168.1.12 -t 0 -n 1000
Running... ctrl^C to stop
Done
Result device: ens4f0v0
Params: count 1000 min_pkt_size: 60 max_pkt_size: 60
frags: 0 delay: 0 clone_skb: 0 ifname: ens4f0v0
flows: 0 flowlen: 0
queue_map_min: 0 queue_map_max: 0
dst_min: 192.168.1.12 dst_max: 192.168.1.12
src_min: src_max:
src_mac: ea:0c:48:be:43:09 dst_mac: 7e:6c:0c:13:80:a6
udp_src_min: 9 udp_src_max: 109 udp_dst_min: 9 udp_dst_max: 9
src_mac_count: 0 dst_mac_count: 0
Flags: UDPSRC_RND NO_TIMESTAMP
Current:
pkts-sofar: 1000 errors: 0
started: 1929289439111us stopped: 1929289440886us idle: 422us
seq_num: 1001 cur_dst_mac_offset: 0 cur_src_mac_offset: 0
cur_saddr: 192.168.1.11 cur_daddr: 192.168.1.12
cur_udp_dst: 9 cur_udp_src: 51
cur_queue_map: 0
flows: 0
Result: OK: 1774(c1352+d422) usec, 1000 (60byte,0frags)
563629pps 270Mb/sec (270541920bps) errors: 0
是不是比上一节中手动修改脚本方便多了,就是下载这个脚本有些麻烦,如果从github
下载内核整个的源码比较困难,可以直接在github
上把需要的脚本的内容拷贝下来,手动创建相应脚本。
注意:如果是单独复制
pktgen_sample01_simple.sh
脚本,则一定要将该目录下的functions.sh
和parameters.sh
脚本一同复制到同一目录下,否则执行pktgen_sample01_simple.sh
脚本时会出现如下错误:[root@localhost pktgen]# ./pktgen_sample01_simple.sh -i ens4f0v0 -m 7e:6c:0c:13:80:a6 -d 192.168.1.12 -t 0 -n 1000
./pktgen_sample01_simple.sh: line 9: ./functions.sh: No such file or directory
./pktgen_sample01_simple.sh: line 10: root_check_run_with_sudo: command not found
./pktgen_sample01_simple.sh: line 15: ./parameters.sh: No such file or directory
./pktgen_sample01_simple.sh: line 23: usage: command not found
./pktgen_sample01_simple.sh: line 26: validate_addr: command not found
./pktgen_sample01_simple.sh: line 27: parse_addr: command not found
./pktgen_sample01_simple.sh: line 40: pg_ctrl: command not found
./pktgen_sample01_simple.sh: line 44: pg_thread: command not found
./pktgen_sample01_simple.sh: line 45: pg_thread: command not found
./pktgen_sample01_simple.sh: line 48: pg_set: command not found
./pktgen_sample01_simple.sh: line 52: pg_set: command not found
./pktgen_sample01_simple.sh: line 55: pg_set: command not found
./pktgen_sample01_simple.sh: line 58: pg_set: command not found
./pktgen_sample01_simple.sh: line 61: pg_set: command not found
./pktgen_sample01_simple.sh: line 64: pg_set: command not found
./pktgen_sample01_simple.sh: line 65: pg_set: command not found
./pktgen_sample01_simple.sh: line 66: pg_set: command not found
./pktgen_sample01_simple.sh: line 78: pg_set: command not found
./pktgen_sample01_simple.sh: line 79: pg_set: command not found
./pktgen_sample01_simple.sh: line 80: pg_set: command not found
Running... ctrl^C to stop
./pktgen_sample01_simple.sh: line 94: pg_ctrl: command not found
Done
Result device:
cat: /proc/net/pktgen/: Is a directory
这里只演示 pktgen_sample01_simple.sh
脚本的使用方法,其他pktgen_sample*
脚本大家可以自行研究摸索。
名称 | 含义 |
---|---|
start | 所有的线程开始发送 |
stop | 停止 |
名称 | 含义 |
---|---|
add_device | 添加某个网卡到某个线程 |
rem_device_all | 删除绑定在某个线程的所有网卡 |
max_before_softirq | 在最多发送多少个数据包后执行do_softirq() |
名称 | 含义 |
---|---|
count | 发送数据包的个数,0 表示一直发送 |
clone_skb | 对每个skb进行多少个复制,0表示不复制。对于Dos等测试必须至零 |
debug | 调试 |
frags | 数据包的片段数量 |
delay | 发送两个数据包之间的延时 |
src_mac_count | 源mac的数量,从src mac设置的mac开始轮询 |
dst_mac_count | 目的mac的数量,从dst mac设置的mac开始轮询 |
pkt_size | 链路包的大小(前去CRC的值) |
min_pkt_size | 数据包最小值 |
max_pkt_size | 数据包最大值 |
udp_src_min | 最小源udp端口号 |
udp_src_max | 最大源udp端口号 |
udp_dst_min | 最小目的udp端口号 |
udp_dst_max | 最大目的udp端口号 |
flag IPSRC_RND TXSIZE_RND IPDST_RND UDPSRC_RND UDPDST_RND MACSRC_RND MACDST_RND | PSRC_RND 源IP随机发送 |
dst_min | 目的IP的最小值 |
dst_max | 目的IP的最大值 |
src_min | 源IP最小值 |
src_max | 源IP最大值 |
dst_mac | 目的mac |
src_mac | 源mac |
clear_counters | 清空计数器,一般程序自动清空 |
dst6 | 目的IPv6地址 |
src6 | 源IPv6地址 |
flows | 并发流的个数 |
flowlen | 流的长度 |
注意:如果不想使用第三节中提供的
pktgen_start.sh
脚本,则可以自己手动按照如下方式进行设置,这里举两个例子供参考:
添加网卡至线程
echo "add_device eth0" > /proc/net/pktgen/kpktgend_0
添加目的MAC地址
echo "dst_mac aa:bb:cc:dd:ee:ff" > /proc/net/pktgen/eth0
pktgen
测试的组网和iperf
测试基本相同,客户端安装pktgen
来发包,接收端通过sar
命令(Linux
系统)来查看端口统计信息,进而获得测试网络的吞吐和PPS
等性能指标,通过对比收发两端的速率来判断是否有丢包。