是什么?

  • 高性能的发包工具
  • Linux kernel的一个模块

不是什么?

  • 不是用户态的工具软件(所以不能用敲命令行的方式来运行pktgen)
  • 不是全能的发包工具, 只支持UDP报文

安装

一般来讲, 我们的系统上都有 pktgen 的模块, 只不过没有运行而已.下面介绍几个基本操作

  • ps aux | grep pktgen 查看 pktgen 是否运行
  • lsmod | grep pktgen 查看 pktgen 是否在内核中已经加载
  • modprobe pktgen 加载 pktgen
  • modprobe -r pktgen 卸载 pktgen

如果系统里边没有 pktgen, 可以下载 Linux 内核源码, 使能 CONFIG_NET_PKTGEN 选项进行编译, 推荐编译成内核模块方式, 之后就能使用以上的命令来加载或者卸载 pktgen 了.

使用

内核里的 pktgen.txt 介绍了使用方法以及所有可用的命令, 对命令有任何疑问可以进行参考.

如何控制 pktgen

pktgen 使用虚拟文件系统实现与用户交互的方式, pktgen 启动后, 会在 /proc/net/pktgen 下建立对应的文件, 并实现了文件的读写操作驱动用来和用户交互.

就像使用文件一样, 我们可以从文件里面读数据, 往文件里面写数据, 只不过读数据的时候调用的这个文件系统驱动的 read 函数(就是由 pktgen 实现的), 写数据调用的 write 函数. 这样 pktgen 就可以根据这些操作和用户交互.

比如, 下面的操作就是让 pktgen 开始发包 (当然, 怎样发包还是要配置的)

echo start > /proc/net/pktgen/pgctrl

关键命令

参考 pktgen.txt 中的 Current commands and configuration options, 比较常用的有如下命令:

  • 发送给 /proc/net/pktgen/pgctrl 的
    • start 开始发包
    • stop 停止发包
    • reset 重置 pktgen, 就是将建立的 /proc/net/pktgen/ 下面的网口全都删除
  • 发送给 /proc/net/pktgen/kpktgend_X 的
    • add_device 将当前的 pktgen 线程(kpktgend_X)关联到某个网口, 例如 eth0
    • rem_device_all 移除所有的关联网口, 基本上和 reset 功能相同, 只不过这个是移除当前线程关联的网口, reset 是移除所有网口
  • 发送给关联网口的 /proc/net/pktgen/ethX
    • count 此次发送的包的个数, 0为一直发
    • clone_skb 每次发送的重复包数. 例如为100, 那么就是构造一个包之后, 重复发这个包100次之后, 再构造新的报文
    • pkt_size 每个报文的大小 (网卡会自动加4字节的 CRC 校验)
    • 等等

操作方法

从上面可以看出 pgctrl 控制 kpktgend_X 的启动停止发包, kpktgend_X 控制 ethX 使用网卡进行实际动作.

从 pktgen 加载之后, 使用 ps aux | grep pktgen 可以看到和 CPU 核心数相同的内核线程.

那么要让 pktgen 发包, 可以想象出来, 按照以下的步骤即可:

  1. 内核线程 kpktgend_X 关联网口 (操作 kpktgend_X)
  2. 配置网口发送参数 (操作 ehtX)
  3. 启动发送 (操作pgctl)

pktgen.txt 中给的 ftp://robur.slu.se/pub/Linux/net-development/pktgen-testing/examples/ 已经失效, 可以从作者给的链接中查看例子, 例如: pktgen.conf-1-1

#! /bin/sh
#modprobe pktgen
# 写虚拟文件系统的函数, 每次操作之前, 设置好要操作的设备 $PGDEV 为 pgctl/kpktgend_X/ehtX
function pgset() {
    local result

    echo $1 > $PGDEV

    result=`cat $PGDEV | fgrep "Result: OK:"`
    if [ "$result" = "" ]; then
         cat $PGDEV | fgrep Result:
    fi
}

function pg() {
    echo inject > $PGDEV
    cat $PGDEV
}

# Config Start Here -----------------------------------------------------------


# thread config
# Each CPU has own thread. Two CPU exammple. We add eth1, eth2 respectivly.

# 移除线程中对应的所有网口, 再添加
PGDEV=/proc/net/pktgen/kpktgend_0
  echo "Removing all devices"
 pgset "rem_device_all" 
  echo "Adding eth1"
 pgset "add_device eth1" 
  echo "Setting max_before_softirq 10000"
 pgset "max_before_softirq 10000"


# device config
# ipg is inter packet gap. 0 means maximum speed.

CLONE_SKB="clone_skb 1000000"
# NIC adds 4 bytes CRC
PKT_SIZE="pkt_size 60"

# COUNT 0 means forever
#COUNT="count 0"
COUNT="count 10000000"
# ipg 参数在我实验的时候无效, 我从2.6.32的源码中也没有看到相关的设置, 可以将 ipg 相关的配置删掉
#IPG="ipg 0"

PGDEV=/proc/net/pktgen/eth1
  echo "Configuring $PGDEV"
 pgset "$COUNT"
 pgset "$CLONE_SKB"
 pgset "$PKT_SIZE"
 #pgset "$IPG"
 # 配置目标IP
 pgset "dst 10.10.11.2" 
 # 配置目标MAC
 pgset "dst_mac  00:04:23:08:91:dc"


# Time to run
PGDEV=/proc/net/pktgen/pgctrl
# 发送 start 给 pgctl, 让 pktgen 开始发包
 echo "Running... ctrl^C to stop"
 pgset "start" 
 echo "Done"

# Result can be vieved in /proc/net/pktgen/eth1

到这里, 应该可以自己写脚本来控制 pktgen 发包了

源码分析

pktgen 的源码位于 linux_src/net/core/pktgen.c, 可以在线浏览pktgen.c

参考
pktgen - linuxfoundation
虚拟文件系统-概述

本文地址 pktgen的使用 转载请注明出处