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模擬虛擬機的網卡,網絡拓撲圖如上圖所示。其中,ens4f0v0和ens4f0v1為物理網卡ens4f0np0虛擬出的兩個VF,通過命令行添加到網絡命名空間ns1和ns2中,如下:# 構建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等性能指標,通過對比收發兩端的速率來判斷是否有丟包。