mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-22 08:49:45 +00:00
Merge branch 'pktgen-new-scripts'
Jesper Dangaard Brouer says: ==================== pktgen: cleanups and introducing new samples/pktgen scripts v3: - Aborted v2 send due it was not generating diff stat (this is a bug in stg-mail, if not in the root directory) v2: address nitpicks from Cong Wang - Remove useless cat's, but keep them for old pgset() - Comment on: Due to pgctrl, cannot use exit code $? from grep - Use arithmetic compare in pktgen_sample03_burst_single_flow.sh This patchset is focused on making pktgen easier to use and better documented. It contains a number of documentation updates and minor changes to pktgen. The major contribution is introduction of common helper function for sample scripts. Instead of the old pgset() function, three new shell functions for configuring the different components of pktgen are introduced: pg_ctrl(), pg_thread() and pg_set(). The new functions correspond to pktgens different components. * pg_ctrl() control "pgctrl" (/proc/net/pktgen/pgctrl) * pg_thread() control the kernel threads and binding to devices * pg_set() control setup of individual devices Helpers also provide consistent parameter parsing across the sample scripts. Usage example: ./pktgen_sample01_simple.sh -i eth41 -m 00:12:C0:02:AC:5A -d 192.168.41.2 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 -c : ($SKB_CLONE) SKB clones send before alloc new SKB -b : ($BURST) HW level bursting of SKBs -v : ($VERBOSE) verbose -x : ($DEBUG) debug These scripts are borrowed from: https://github.com/netoptimizer/network-testing/tree/master/pktgen ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
fa7912be96
12 changed files with 678 additions and 242 deletions
|
@ -1,6 +1,6 @@
|
|||
|
||||
|
||||
HOWTO for the linux packet generator
|
||||
HOWTO for the linux packet generator
|
||||
------------------------------------
|
||||
|
||||
Enable CONFIG_NET_PKTGEN to compile and build pktgen either in-kernel
|
||||
|
@ -50,17 +50,33 @@ For ixgbe use e.g. "30" resulting in approx 33K interrupts/sec (1/30*10^6):
|
|||
# ethtool -C ethX rx-usecs 30
|
||||
|
||||
|
||||
Viewing threads
|
||||
===============
|
||||
/proc/net/pktgen/kpktgend_0
|
||||
Name: kpktgend_0 max_before_softirq: 10000
|
||||
Running:
|
||||
Stopped: eth1
|
||||
Result: OK: max_before_softirq=10000
|
||||
Kernel threads
|
||||
==============
|
||||
Pktgen creates a thread for each CPU with affinity to that CPU.
|
||||
Which is controlled through procfile /proc/net/pktgen/kpktgend_X.
|
||||
|
||||
Most important are the devices assigned to the thread. Note that a
|
||||
device can only belong to one thread.
|
||||
Example: /proc/net/pktgen/kpktgend_0
|
||||
|
||||
Running:
|
||||
Stopped: eth4@0
|
||||
Result: OK: add_device=eth4@0
|
||||
|
||||
Most important are the devices assigned to the thread.
|
||||
|
||||
The two basic thread commands are:
|
||||
* add_device DEVICE@NAME -- adds a single device
|
||||
* rem_device_all -- remove all associated devices
|
||||
|
||||
When adding a device to a thread, a corrosponding procfile is created
|
||||
which is used for configuring this device. Thus, device names need to
|
||||
be unique.
|
||||
|
||||
To support adding the same device to multiple threads, which is useful
|
||||
with multi queue NICs, a the device naming scheme is extended with "@":
|
||||
device@something
|
||||
|
||||
The part after "@" can be anything, but it is custom to use the thread
|
||||
number.
|
||||
|
||||
Viewing devices
|
||||
===============
|
||||
|
@ -69,29 +85,32 @@ The Params section holds configured information. The Current section
|
|||
holds running statistics. The Result is printed after a run or after
|
||||
interruption. Example:
|
||||
|
||||
/proc/net/pktgen/eth1
|
||||
/proc/net/pktgen/eth4@0
|
||||
|
||||
Params: count 10000000 min_pkt_size: 60 max_pkt_size: 60
|
||||
frags: 0 delay: 0 clone_skb: 1000000 ifname: eth1
|
||||
Params: count 100000 min_pkt_size: 60 max_pkt_size: 60
|
||||
frags: 0 delay: 0 clone_skb: 64 ifname: eth4@0
|
||||
flows: 0 flowlen: 0
|
||||
dst_min: 10.10.11.2 dst_max:
|
||||
src_min: src_max:
|
||||
src_mac: 00:00:00:00:00:00 dst_mac: 00:04:23:AC:FD:82
|
||||
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: 10000000 errors: 39664
|
||||
started: 1103053986245187us stopped: 1103053999346329us idle: 880401us
|
||||
seq_num: 10000011 cur_dst_mac_offset: 0 cur_src_mac_offset: 0
|
||||
cur_saddr: 0x10a0a0a cur_daddr: 0x20b0a0a
|
||||
cur_udp_dst: 9 cur_udp_src: 9
|
||||
queue_map_min: 0 queue_map_max: 0
|
||||
dst_min: 192.168.81.2 dst_max:
|
||||
src_min: src_max:
|
||||
src_mac: 90:e2:ba:0a:56:b4 dst_mac: 00:1b:21:3c:9d:f8
|
||||
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 QUEUE_MAP_CPU
|
||||
Current:
|
||||
pkts-sofar: 100000 errors: 0
|
||||
started: 623913381008us stopped: 623913396439us idle: 25us
|
||||
seq_num: 100001 cur_dst_mac_offset: 0 cur_src_mac_offset: 0
|
||||
cur_saddr: 192.168.8.3 cur_daddr: 192.168.81.2
|
||||
cur_udp_dst: 9 cur_udp_src: 42
|
||||
cur_queue_map: 0
|
||||
flows: 0
|
||||
Result: OK: 13101142(c12220741+d880401) usec, 10000000 (60byte,0frags)
|
||||
763292pps 390Mb/sec (390805504bps) errors: 39664
|
||||
Result: OK: 15430(c15405+d25) usec, 100000 (60byte,0frags)
|
||||
6480562pps 3110Mb/sec (3110669760bps) errors: 0
|
||||
|
||||
Configuring threads and devices
|
||||
================================
|
||||
|
||||
Configuring devices
|
||||
===================
|
||||
This is done via the /proc interface, and most easily done via pgset
|
||||
as defined in the sample scripts.
|
||||
|
||||
|
@ -126,7 +145,7 @@ Examples:
|
|||
To select queue 1 of a given device,
|
||||
use queue_map_min=1 and queue_map_max=1
|
||||
|
||||
pgset "src_mac_count 1" Sets the number of MACs we'll range through.
|
||||
pgset "src_mac_count 1" Sets the number of MACs we'll range through.
|
||||
The 'minimum' MAC is what you set with srcmac.
|
||||
|
||||
pgset "dst_mac_count 1" Sets the number of MACs we'll range through.
|
||||
|
@ -200,21 +219,36 @@ Examples:
|
|||
Sample scripts
|
||||
==============
|
||||
|
||||
A collection of small tutorial scripts for pktgen is in the
|
||||
samples/pktgen directory:
|
||||
A collection of tutorial scripts and helpers for pktgen is in the
|
||||
samples/pktgen directory. The helper parameters.sh file support easy
|
||||
and consistant parameter parsing across the sample scripts.
|
||||
|
||||
Usage example and help:
|
||||
./pktgen_sample01_simple.sh -i eth4 -m 00:1B:21:3C:9D:F8 -d 192.168.8.2
|
||||
|
||||
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
|
||||
-c : ($SKB_CLONE) SKB clones send before alloc new SKB
|
||||
-b : ($BURST) HW level bursting of SKBs
|
||||
-v : ($VERBOSE) verbose
|
||||
-x : ($DEBUG) debug
|
||||
|
||||
The global variables being set are also listed. E.g. the required
|
||||
interface/device parameter "-i" sets variable $DEV. Copy the
|
||||
pktgen_sampleXX scripts and modify them to fit your own needs.
|
||||
|
||||
The old scripts:
|
||||
|
||||
pktgen.conf-1-1 # 1 CPU 1 dev
|
||||
pktgen.conf-1-2 # 1 CPU 2 dev
|
||||
pktgen.conf-2-1 # 2 CPU's 1 dev
|
||||
pktgen.conf-2-2 # 2 CPU's 2 dev
|
||||
pktgen.conf-1-1-rdos # 1 CPU 1 dev w. route DoS
|
||||
pktgen.conf-1-1-ip6 # 1 CPU 1 dev ipv6
|
||||
pktgen.conf-1-1-ip6-rdos # 1 CPU 1 dev ipv6 w. route DoS
|
||||
pktgen.conf-1-1-flows # 1 CPU 1 dev multiple flows.
|
||||
|
||||
Run in shell: ./pktgen.conf-X-Y
|
||||
This does all the setup including sending.
|
||||
|
||||
|
||||
Interrupt affinity
|
||||
===================
|
||||
|
@ -222,6 +256,9 @@ Note that when adding devices to a specific CPU it is a good idea to
|
|||
also assign /proc/irq/XX/smp_affinity so that the TX interrupts are bound
|
||||
to the same CPU. This reduces cache bouncing when freeing skbs.
|
||||
|
||||
Plus using the device flag QUEUE_MAP_CPU, which maps the SKBs TX queue
|
||||
to the running threads CPU (directly from smp_processor_id()).
|
||||
|
||||
Enable IPsec
|
||||
============
|
||||
Default IPsec transformation with ESP encapsulation plus transport mode
|
||||
|
@ -242,18 +279,19 @@ Current commands and configuration options
|
|||
|
||||
start
|
||||
stop
|
||||
reset
|
||||
|
||||
** Thread commands:
|
||||
|
||||
add_device
|
||||
rem_device_all
|
||||
max_before_softirq
|
||||
|
||||
|
||||
** Device commands:
|
||||
|
||||
count
|
||||
clone_skb
|
||||
burst
|
||||
debug
|
||||
|
||||
frags
|
||||
|
@ -262,10 +300,17 @@ delay
|
|||
src_mac_count
|
||||
dst_mac_count
|
||||
|
||||
pkt_size
|
||||
pkt_size
|
||||
min_pkt_size
|
||||
max_pkt_size
|
||||
|
||||
queue_map_min
|
||||
queue_map_max
|
||||
skb_priority
|
||||
|
||||
tos (ipv4)
|
||||
traffic_class (ipv6)
|
||||
|
||||
mpls
|
||||
|
||||
udp_src_min
|
||||
|
@ -274,6 +319,8 @@ udp_src_max
|
|||
udp_dst_min
|
||||
udp_dst_max
|
||||
|
||||
node
|
||||
|
||||
flag
|
||||
IPSRC_RND
|
||||
IPDST_RND
|
||||
|
@ -294,6 +341,8 @@ flag
|
|||
NODE_ALLOC
|
||||
NO_TIMESTAMP
|
||||
|
||||
spi (ipsec)
|
||||
|
||||
dst_min
|
||||
dst_max
|
||||
|
||||
|
@ -305,8 +354,10 @@ src_mac
|
|||
|
||||
clear_counters
|
||||
|
||||
dst6
|
||||
src6
|
||||
dst6
|
||||
dst6_max
|
||||
dst6_min
|
||||
|
||||
flows
|
||||
flowlen
|
||||
|
@ -316,6 +367,14 @@ ratep
|
|||
|
||||
xmit_mode <start_xmit|netif_receive>
|
||||
|
||||
vlan_cfi
|
||||
vlan_id
|
||||
vlan_p
|
||||
|
||||
svlan_cfi
|
||||
svlan_id
|
||||
svlan_p
|
||||
|
||||
|
||||
References:
|
||||
ftp://robur.slu.se/pub/Linux/net-development/pktgen-testing/
|
||||
|
|
|
@ -177,7 +177,7 @@
|
|||
#include <asm/dma.h>
|
||||
#include <asm/div64.h> /* do_div */
|
||||
|
||||
#define VERSION "2.74"
|
||||
#define VERSION "2.75"
|
||||
#define IP_NAME_SZ 32
|
||||
#define MAX_MPLS_LABELS 16 /* This is the max label stack depth */
|
||||
#define MPLS_STACK_BOTTOM htonl(0x00000100)
|
||||
|
@ -512,7 +512,7 @@ static ssize_t pgctrl_write(struct file *file, const char __user *buf,
|
|||
pktgen_reset_all_threads(pn);
|
||||
|
||||
else
|
||||
pr_warn("Unknown command: %s\n", data);
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -572,7 +572,7 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
|
|||
" dst_min: %s dst_max: %s\n",
|
||||
pkt_dev->dst_min, pkt_dev->dst_max);
|
||||
seq_printf(seq,
|
||||
" src_min: %s src_max: %s\n",
|
||||
" src_min: %s src_max: %s\n",
|
||||
pkt_dev->src_min, pkt_dev->src_max);
|
||||
}
|
||||
|
||||
|
|
43
samples/pktgen/README.rst
Normal file
43
samples/pktgen/README.rst
Normal file
|
@ -0,0 +1,43 @@
|
|||
Sample and benchmark scripts for pktgen (packet generator)
|
||||
==========================================================
|
||||
This directory contains some pktgen sample and benchmark scripts, that
|
||||
can easily be copied and adjusted for your own use-case.
|
||||
|
||||
General doc is located in kernel: Documentation/networking/pktgen.txt
|
||||
|
||||
Helper include files
|
||||
====================
|
||||
This directory contains two helper shell files, that can be "included"
|
||||
by shell source'ing. Namely "functions.sh" and "parameters.sh".
|
||||
|
||||
Common parameters
|
||||
-----------------
|
||||
The parameters.sh file support easy and consistant parameter parsing
|
||||
across the sample scripts. Usage example is printed on errors::
|
||||
|
||||
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
|
||||
-c : ($SKB_CLONE) SKB clones send before alloc new SKB
|
||||
-b : ($BURST) HW level bursting of SKBs
|
||||
-v : ($VERBOSE) verbose
|
||||
-x : ($DEBUG) debug
|
||||
|
||||
The global variable being set is also listed. E.g. the required
|
||||
interface/device parameter "-i" sets variable $DEV.
|
||||
|
||||
Common functions
|
||||
----------------
|
||||
The functions.sh file provides; Three different shell functions for
|
||||
configuring the different components of pktgen: pg_ctrl(), pg_thread()
|
||||
and pg_set().
|
||||
|
||||
These functions correspond to pktgens different components.
|
||||
* pg_ctrl() control "pgctrl" (/proc/net/pktgen/pgctrl)
|
||||
* pg_thread() control the kernel threads and binding to devices
|
||||
* pg_set() control setup of individual devices
|
||||
|
||||
See sample scripts for usage examples.
|
121
samples/pktgen/functions.sh
Normal file
121
samples/pktgen/functions.sh
Normal file
|
@ -0,0 +1,121 @@
|
|||
#
|
||||
# Common functions used by pktgen scripts
|
||||
# - Depending on bash 3 (or higher) syntax
|
||||
#
|
||||
# Author: Jesper Dangaaard Brouer
|
||||
# License: GPL
|
||||
|
||||
## -- General shell logging cmds --
|
||||
function err() {
|
||||
local exitcode=$1
|
||||
shift
|
||||
echo "ERROR: $@" >&2
|
||||
exit $exitcode
|
||||
}
|
||||
|
||||
function warn() {
|
||||
echo "WARN : $@" >&2
|
||||
}
|
||||
|
||||
function info() {
|
||||
if [[ -n "$VERBOSE" ]]; then
|
||||
echo "INFO : $@" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
## -- Pktgen proc config commands -- ##
|
||||
export PROC_DIR=/proc/net/pktgen
|
||||
#
|
||||
# Three different shell functions for configuring the different
|
||||
# components of pktgen:
|
||||
# pg_ctrl(), pg_thread() and pg_set().
|
||||
#
|
||||
# These functions correspond to pktgens different components.
|
||||
# * pg_ctrl() control "pgctrl" (/proc/net/pktgen/pgctrl)
|
||||
# * pg_thread() control the kernel threads and binding to devices
|
||||
# * pg_set() control setup of individual devices
|
||||
function pg_ctrl() {
|
||||
local proc_file="pgctrl"
|
||||
proc_cmd ${proc_file} "$@"
|
||||
}
|
||||
|
||||
function pg_thread() {
|
||||
local thread=$1
|
||||
local proc_file="kpktgend_${thread}"
|
||||
shift
|
||||
proc_cmd ${proc_file} "$@"
|
||||
}
|
||||
|
||||
function pg_set() {
|
||||
local dev=$1
|
||||
local proc_file="$dev"
|
||||
shift
|
||||
proc_cmd ${proc_file} "$@"
|
||||
}
|
||||
|
||||
# More generic replacement for pgset(), that does not depend on global
|
||||
# variable for proc file.
|
||||
function proc_cmd() {
|
||||
local result
|
||||
local proc_file=$1
|
||||
# after shift, the remaining args are contained in $@
|
||||
shift
|
||||
local proc_ctrl=${PROC_DIR}/$proc_file
|
||||
if [[ ! -e "$proc_ctrl" ]]; then
|
||||
err 3 "proc file:$proc_ctrl does not exists (dev added to thread?)"
|
||||
else
|
||||
if [[ ! -w "$proc_ctrl" ]]; then
|
||||
err 4 "proc file:$proc_ctrl not writable, not root?!"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$DEBUG" == "yes" ]]; then
|
||||
echo "cmd: $@ > $proc_ctrl"
|
||||
fi
|
||||
# Quoting of "$@" is important for space expansion
|
||||
echo "$@" > "$proc_ctrl"
|
||||
local status=$?
|
||||
|
||||
result=$(grep "Result: OK:" $proc_ctrl)
|
||||
# Due to pgctrl, cannot use exit code $? from grep
|
||||
if [[ "$result" == "" ]]; then
|
||||
grep "Result:" $proc_ctrl >&2
|
||||
fi
|
||||
if (( $status != 0 )); then
|
||||
err 5 "Write error($status) occurred cmd: \"$@ > $proc_ctrl\""
|
||||
fi
|
||||
}
|
||||
|
||||
# Old obsolete "pgset" function, with slightly improved err handling
|
||||
function pgset() {
|
||||
local result
|
||||
|
||||
if [[ "$DEBUG" == "yes" ]]; then
|
||||
echo "cmd: $1 > $PGDEV"
|
||||
fi
|
||||
echo $1 > $PGDEV
|
||||
local status=$?
|
||||
|
||||
result=`cat $PGDEV | fgrep "Result: OK:"`
|
||||
if [[ "$result" == "" ]]; then
|
||||
cat $PGDEV | fgrep Result:
|
||||
fi
|
||||
if (( $status != 0 )); then
|
||||
err 5 "Write error($status) occurred cmd: \"$1 > $PGDEV\""
|
||||
fi
|
||||
}
|
||||
|
||||
## -- General shell tricks --
|
||||
|
||||
function root_check_run_with_sudo() {
|
||||
# Trick so, program can be run as normal user, will just use "sudo"
|
||||
# call as root_check_run_as_sudo "$@"
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
if [ -x $0 ]; then # Directly executable use sudo
|
||||
info "Not root, running with sudo"
|
||||
sudo "$0" "$@"
|
||||
exit $?
|
||||
fi
|
||||
err 4 "cannot perform sudo run of $0"
|
||||
fi
|
||||
}
|
97
samples/pktgen/parameters.sh
Normal file
97
samples/pktgen/parameters.sh
Normal file
|
@ -0,0 +1,97 @@
|
|||
#
|
||||
# Common parameter parsing for pktgen scripts
|
||||
#
|
||||
|
||||
function usage() {
|
||||
echo ""
|
||||
echo "Usage: $0 [-vx] -i ethX"
|
||||
echo " -i : (\$DEV) output interface/device (required)"
|
||||
echo " -s : (\$PKT_SIZE) packet size"
|
||||
echo " -d : (\$DEST_IP) destination IP"
|
||||
echo " -m : (\$DST_MAC) destination MAC-addr"
|
||||
echo " -t : (\$THREADS) threads to start"
|
||||
echo " -c : (\$SKB_CLONE) SKB clones send before alloc new SKB"
|
||||
echo " -b : (\$BURST) HW level bursting of SKBs"
|
||||
echo " -v : (\$VERBOSE) verbose"
|
||||
echo " -x : (\$DEBUG) debug"
|
||||
echo ""
|
||||
}
|
||||
|
||||
## --- Parse command line arguments / parameters ---
|
||||
## echo "Commandline options:"
|
||||
while getopts "s:i:d:m:t:c:b:vxh" option; do
|
||||
case $option in
|
||||
i) # interface
|
||||
export DEV=$OPTARG
|
||||
info "Output device set to: DEV=$DEV"
|
||||
;;
|
||||
s)
|
||||
export PKT_SIZE=$OPTARG
|
||||
info "Packet size set to: PKT_SIZE=$PKT_SIZE bytes"
|
||||
;;
|
||||
d) # destination IP
|
||||
export DEST_IP=$OPTARG
|
||||
info "Destination IP set to: DEST_IP=$DEST_IP"
|
||||
;;
|
||||
m) # MAC
|
||||
export DST_MAC=$OPTARG
|
||||
info "Destination MAC set to: DST_MAC=$DST_MAC"
|
||||
;;
|
||||
t)
|
||||
export THREADS=$OPTARG
|
||||
export CPU_THREADS=$OPTARG
|
||||
let "CPU_THREADS -= 1"
|
||||
info "Number of threads to start: $THREADS (0 to $CPU_THREADS)"
|
||||
;;
|
||||
c)
|
||||
export CLONE_SKB=$OPTARG
|
||||
info "CLONE_SKB=$CLONE_SKB"
|
||||
;;
|
||||
b)
|
||||
export BURST=$OPTARG
|
||||
info "SKB bursting: BURST=$BURST"
|
||||
;;
|
||||
v)
|
||||
export VERBOSE=yes
|
||||
info "Verbose mode: VERBOSE=$VERBOSE"
|
||||
;;
|
||||
x)
|
||||
export DEBUG=yes
|
||||
info "Debug mode: DEBUG=$DEBUG"
|
||||
;;
|
||||
h|?|*)
|
||||
usage;
|
||||
err 2 "[ERROR] Unknown parameters!!!"
|
||||
esac
|
||||
done
|
||||
shift $(( $OPTIND - 1 ))
|
||||
|
||||
if [ -z "$PKT_SIZE" ]; then
|
||||
# NIC adds 4 bytes CRC
|
||||
export PKT_SIZE=60
|
||||
info "Default packet size set to: set to: $PKT_SIZE bytes"
|
||||
fi
|
||||
|
||||
if [ -z "$THREADS" ]; then
|
||||
# Zero CPU threads means one thread, because CPU numbers are zero indexed
|
||||
export CPU_THREADS=0
|
||||
export THREADS=1
|
||||
fi
|
||||
|
||||
if [ -z "$DEV" ]; then
|
||||
usage
|
||||
err 2 "Please specify output device"
|
||||
fi
|
||||
|
||||
if [ -z "$DST_MAC" ]; then
|
||||
warn "Missing destination MAC address"
|
||||
fi
|
||||
|
||||
if [ -z "$DEST_IP" ]; then
|
||||
warn "Missing destination IP address"
|
||||
fi
|
||||
|
||||
if [ ! -d /proc/net/pktgen ]; then
|
||||
info "Loading kernel module: pktgen"
|
||||
modprobe pktgen
|
||||
fi
|
|
@ -1,59 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
#modprobe pktgen
|
||||
|
||||
|
||||
function pgset() {
|
||||
local result
|
||||
|
||||
echo $1 > $PGDEV
|
||||
|
||||
result=`cat $PGDEV | fgrep "Result: OK:"`
|
||||
if [ "$result" = "" ]; then
|
||||
cat $PGDEV | fgrep Result:
|
||||
fi
|
||||
}
|
||||
|
||||
# Config Start Here -----------------------------------------------------------
|
||||
|
||||
|
||||
# thread config
|
||||
# Each CPU has its own thread. One CPU example. We add eth1.
|
||||
|
||||
PGDEV=/proc/net/pktgen/kpktgend_0
|
||||
echo "Removing all devices"
|
||||
pgset "rem_device_all"
|
||||
echo "Adding eth1"
|
||||
pgset "add_device eth1"
|
||||
|
||||
|
||||
# device config
|
||||
# delay 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"
|
||||
DELAY="delay 0"
|
||||
|
||||
PGDEV=/proc/net/pktgen/eth1
|
||||
echo "Configuring $PGDEV"
|
||||
pgset "$COUNT"
|
||||
pgset "$CLONE_SKB"
|
||||
pgset "$PKT_SIZE"
|
||||
pgset "$DELAY"
|
||||
pgset "dst 10.10.11.2"
|
||||
pgset "dst_mac 00:04:23:08:91:dc"
|
||||
|
||||
|
||||
# Time to run
|
||||
PGDEV=/proc/net/pktgen/pgctrl
|
||||
|
||||
echo "Running... ctrl^C to stop"
|
||||
trap true INT
|
||||
pgset "start"
|
||||
echo "Done"
|
||||
cat /proc/net/pktgen/eth1
|
|
@ -1,66 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
#modprobe pktgen
|
||||
|
||||
|
||||
function pgset() {
|
||||
local result
|
||||
|
||||
echo $1 > $PGDEV
|
||||
|
||||
result=`cat $PGDEV | fgrep "Result: OK:"`
|
||||
if [ "$result" = "" ]; then
|
||||
cat $PGDEV | fgrep Result:
|
||||
fi
|
||||
}
|
||||
|
||||
# Config Start Here -----------------------------------------------------------
|
||||
|
||||
|
||||
# thread config
|
||||
# Each CPU has its own thread. Two CPU example. We add eth1 to the first
|
||||
# and leave the second idle.
|
||||
|
||||
PGDEV=/proc/net/pktgen/kpktgend_0
|
||||
echo "Removing all devices"
|
||||
pgset "rem_device_all"
|
||||
echo "Adding eth1"
|
||||
pgset "add_device eth1"
|
||||
|
||||
# We need to remove old config since we dont use this thread. We can only
|
||||
# one NIC on one CPU due to affinity reasons.
|
||||
|
||||
PGDEV=/proc/net/pktgen/kpktgend_1
|
||||
echo "Removing all devices"
|
||||
pgset "rem_device_all"
|
||||
|
||||
# device config
|
||||
# delay 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"
|
||||
DELAY="delay 0"
|
||||
|
||||
PGDEV=/proc/net/pktgen/eth1
|
||||
echo "Configuring $PGDEV"
|
||||
pgset "$COUNT"
|
||||
pgset "$CLONE_SKB"
|
||||
pgset "$PKT_SIZE"
|
||||
pgset "$DELAY"
|
||||
pgset "dst 10.10.11.2"
|
||||
pgset "dst_mac 00:04:23:08:91:dc"
|
||||
|
||||
|
||||
# Time to run
|
||||
PGDEV=/proc/net/pktgen/pgctrl
|
||||
|
||||
echo "Running... ctrl^C to stop"
|
||||
trap true INT
|
||||
pgset "start"
|
||||
echo "Done"
|
||||
cat /proc/net/pktgen/eth1
|
|
@ -1,73 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
#modprobe pktgen
|
||||
|
||||
|
||||
function pgset() {
|
||||
local result
|
||||
|
||||
echo $1 > $PGDEV
|
||||
|
||||
result=`cat $PGDEV | fgrep "Result: OK:"`
|
||||
if [ "$result" = "" ]; then
|
||||
cat $PGDEV | fgrep Result:
|
||||
fi
|
||||
}
|
||||
|
||||
# Config Start Here -----------------------------------------------------------
|
||||
|
||||
|
||||
# thread config
|
||||
# Each CPU has its own thread. Two CPU example. We add eth1, eth2 respectively.
|
||||
|
||||
PGDEV=/proc/net/pktgen/kpktgend_0
|
||||
echo "Removing all devices"
|
||||
pgset "rem_device_all"
|
||||
echo "Adding eth1"
|
||||
pgset "add_device eth1"
|
||||
|
||||
PGDEV=/proc/net/pktgen/kpktgend_1
|
||||
echo "Removing all devices"
|
||||
pgset "rem_device_all"
|
||||
echo "Adding eth2"
|
||||
pgset "add_device eth2"
|
||||
|
||||
|
||||
# device config
|
||||
# delay 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"
|
||||
DELAY="delay 0"
|
||||
|
||||
PGDEV=/proc/net/pktgen/eth1
|
||||
echo "Configuring $PGDEV"
|
||||
pgset "$COUNT"
|
||||
pgset "$CLONE_SKB"
|
||||
pgset "$PKT_SIZE"
|
||||
pgset "$DELAY"
|
||||
pgset "dst 10.10.11.2"
|
||||
pgset "dst_mac 00:04:23:08:91:dc"
|
||||
|
||||
PGDEV=/proc/net/pktgen/eth2
|
||||
echo "Configuring $PGDEV"
|
||||
pgset "$COUNT"
|
||||
pgset "$CLONE_SKB"
|
||||
pgset "$PKT_SIZE"
|
||||
pgset "$DELAY"
|
||||
pgset "dst 192.168.2.2"
|
||||
pgset "dst_mac 00:04:23:08:91:de"
|
||||
|
||||
# Time to run
|
||||
PGDEV=/proc/net/pktgen/pgctrl
|
||||
|
||||
echo "Running... ctrl^C to stop"
|
||||
trap true INT
|
||||
pgset "start"
|
||||
echo "Done"
|
||||
cat /proc/net/pktgen/eth1 /proc/net/pktgen/eth2
|
86
samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh
Executable file
86
samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh
Executable file
|
@ -0,0 +1,86 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Benchmark script:
|
||||
# - developed for benchmarking ingress qdisc path
|
||||
#
|
||||
# Script for injecting packets into RX path of the stack with pktgen
|
||||
# "xmit_mode netif_receive". With an invalid dst_mac this will only
|
||||
# measure the ingress code path as packets gets dropped in ip_rcv().
|
||||
#
|
||||
# This script don't really need any hardware. It benchmarks software
|
||||
# RX path just after NIC driver level. With bursting is also
|
||||
# "removes" the SKB alloc/free overhead.
|
||||
#
|
||||
# Setup scenarios for measuring ingress qdisc (with invalid dst_mac):
|
||||
# ------------------------------------------------------------------
|
||||
# (1) no ingress (uses static_key_false(&ingress_needed))
|
||||
#
|
||||
# (2) ingress on other dev (change ingress_needed and calls
|
||||
# handle_ing() but exit early)
|
||||
#
|
||||
# config: tc qdisc add dev $SOMEDEV handle ffff: ingress
|
||||
#
|
||||
# (3) ingress on this dev, handle_ing() -> tc_classify()
|
||||
#
|
||||
# config: tc qdisc add dev $DEV handle ffff: ingress
|
||||
#
|
||||
# (4) ingress on this dev + drop at u32 classifier/action.
|
||||
#
|
||||
basedir=`dirname $0`
|
||||
source ${basedir}/functions.sh
|
||||
root_check_run_with_sudo "$@"
|
||||
|
||||
# Parameter parsing via include
|
||||
source ${basedir}/parameters.sh
|
||||
# Using invalid DST_MAC will cause the packets to get dropped in
|
||||
# ip_rcv() which is part of the test
|
||||
[ -z "$DEST_IP" ] && DEST_IP="198.18.0.42"
|
||||
[ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff"
|
||||
[ -z "$BURST" ] && BURST=1024
|
||||
|
||||
# Base Config
|
||||
DELAY="0" # Zero means max speed
|
||||
COUNT="10000000" # Zero means indefinitely
|
||||
|
||||
# General cleanup everything since last run
|
||||
pg_ctrl "reset"
|
||||
|
||||
# Threads are specified with parameter -t value in $THREADS
|
||||
for ((thread = 0; thread < $THREADS; thread++)); do
|
||||
# The device name is extended with @name, using thread number to
|
||||
# make then unique, but any name will do.
|
||||
dev=${DEV}@${thread}
|
||||
|
||||
# Add remove all other devices and add_device $dev to thread
|
||||
pg_thread $thread "rem_device_all"
|
||||
pg_thread $thread "add_device" $dev
|
||||
|
||||
# Base config of dev
|
||||
pg_set $dev "flag QUEUE_MAP_CPU"
|
||||
pg_set $dev "count $COUNT"
|
||||
pg_set $dev "pkt_size $PKT_SIZE"
|
||||
pg_set $dev "delay $DELAY"
|
||||
pg_set $dev "flag NO_TIMESTAMP"
|
||||
|
||||
# Destination
|
||||
pg_set $dev "dst_mac $DST_MAC"
|
||||
pg_set $dev "dst $DEST_IP"
|
||||
|
||||
# Inject packet into RX path of stack
|
||||
pg_set $dev "xmit_mode netif_receive"
|
||||
|
||||
# Burst allow us to avoid measuring SKB alloc/free overhead
|
||||
pg_set $dev "burst $BURST"
|
||||
done
|
||||
|
||||
# start_run
|
||||
echo "Running... ctrl^C to stop" >&2
|
||||
pg_ctrl "start"
|
||||
echo "Done" >&2
|
||||
|
||||
# Print results
|
||||
for ((thread = 0; thread < $THREADS; thread++)); do
|
||||
dev=${DEV}@${thread}
|
||||
echo "Device: $dev"
|
||||
cat /proc/net/pktgen/$dev | grep -A2 "Result:"
|
||||
done
|
71
samples/pktgen/pktgen_sample01_simple.sh
Executable file
71
samples/pktgen/pktgen_sample01_simple.sh
Executable file
|
@ -0,0 +1,71 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Simple example:
|
||||
# * pktgen sending with single thread and single interface
|
||||
# * flow variation via random UDP source port
|
||||
#
|
||||
basedir=`dirname $0`
|
||||
source ${basedir}/functions.sh
|
||||
root_check_run_with_sudo "$@"
|
||||
|
||||
# Parameter parsing via include
|
||||
# - go look in parameters.sh to see which setting are avail
|
||||
# - required param is the interface "-i" stored in $DEV
|
||||
source ${basedir}/parameters.sh
|
||||
#
|
||||
# Set some default params, if they didn't get set
|
||||
[ -z "$DEST_IP" ] && DEST_IP="198.18.0.42"
|
||||
[ -z "$CLONE_SKB" ] && CLONE_SKB="0"
|
||||
# Example enforce param "-m" for dst_mac
|
||||
[ -z "$DST_MAC" ] && usage && err 2 "Must specify -m dst_mac"
|
||||
|
||||
# Base Config
|
||||
DELAY="0" # Zero means max speed
|
||||
COUNT="100000" # Zero means indefinitely
|
||||
|
||||
# Flow variation random source port between min and max
|
||||
UDP_MIN=9
|
||||
UDP_MAX=109
|
||||
|
||||
# General cleanup everything since last run
|
||||
# (especially important if other threads were configured by other scripts)
|
||||
pg_ctrl "reset"
|
||||
|
||||
# Add remove all other devices and add_device $DEV to thread 0
|
||||
thread=0
|
||||
pg_thread $thread "rem_device_all"
|
||||
pg_thread $thread "add_device" $DEV
|
||||
|
||||
# How many packets to send (zero means indefinitely)
|
||||
pg_set $DEV "count $COUNT"
|
||||
|
||||
# Reduce alloc cost by sending same SKB many times
|
||||
# - this obviously affects the randomness within the packet
|
||||
pg_set $DEV "clone_skb $CLONE_SKB"
|
||||
|
||||
# Set packet size
|
||||
pg_set $DEV "pkt_size $PKT_SIZE"
|
||||
|
||||
# Delay between packets (zero means max speed)
|
||||
pg_set $DEV "delay $DELAY"
|
||||
|
||||
# Flag example disabling timestamping
|
||||
pg_set $DEV "flag NO_TIMESTAMP"
|
||||
|
||||
# Destination
|
||||
pg_set $DEV "dst_mac $DST_MAC"
|
||||
pg_set $DEV "dst $DEST_IP"
|
||||
|
||||
# Setup random UDP port src range
|
||||
pg_set $DEV "flag UDPSRC_RND"
|
||||
pg_set $DEV "udp_src_min $UDP_MIN"
|
||||
pg_set $DEV "udp_src_max $UDP_MAX"
|
||||
|
||||
# start_run
|
||||
echo "Running... ctrl^C to stop" >&2
|
||||
pg_ctrl "start"
|
||||
echo "Done" >&2
|
||||
|
||||
# Print results
|
||||
echo "Result device: $DEV"
|
||||
cat /proc/net/pktgen/$DEV
|
75
samples/pktgen/pktgen_sample02_multiqueue.sh
Executable file
75
samples/pktgen/pktgen_sample02_multiqueue.sh
Executable file
|
@ -0,0 +1,75 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Multiqueue: Using pktgen threads for sending on multiple CPUs
|
||||
# * adding devices to kernel threads
|
||||
# * notice the naming scheme for keeping device names unique
|
||||
# * nameing scheme: dev@thread_number
|
||||
# * flow variation via random UDP source port
|
||||
#
|
||||
basedir=`dirname $0`
|
||||
source ${basedir}/functions.sh
|
||||
root_check_run_with_sudo "$@"
|
||||
#
|
||||
# Required param: -i dev in $DEV
|
||||
source ${basedir}/parameters.sh
|
||||
|
||||
# Base Config
|
||||
DELAY="0" # Zero means max speed
|
||||
COUNT="100000" # Zero means indefinitely
|
||||
[ -z "$CLONE_SKB" ] && CLONE_SKB="0"
|
||||
|
||||
# Flow variation random source port between min and max
|
||||
UDP_MIN=9
|
||||
UDP_MAX=109
|
||||
|
||||
# (example of setting default params in your script)
|
||||
[ -z "$DEST_IP" ] && DEST_IP="198.18.0.42"
|
||||
[ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff"
|
||||
|
||||
# General cleanup everything since last run
|
||||
pg_ctrl "reset"
|
||||
|
||||
# Threads are specified with parameter -t value in $THREADS
|
||||
for ((thread = 0; thread < $THREADS; thread++)); do
|
||||
# The device name is extended with @name, using thread number to
|
||||
# make then unique, but any name will do.
|
||||
dev=${DEV}@${thread}
|
||||
|
||||
# Add remove all other devices and add_device $dev to thread
|
||||
pg_thread $thread "rem_device_all"
|
||||
pg_thread $thread "add_device" $dev
|
||||
|
||||
# Notice config queue to map to cpu (mirrors smp_processor_id())
|
||||
# It is beneficial to map IRQ /proc/irq/*/smp_affinity 1:1 to CPU number
|
||||
pg_set $dev "flag QUEUE_MAP_CPU"
|
||||
|
||||
# Base config of dev
|
||||
pg_set $dev "count $COUNT"
|
||||
pg_set $dev "clone_skb $CLONE_SKB"
|
||||
pg_set $dev "pkt_size $PKT_SIZE"
|
||||
pg_set $dev "delay $DELAY"
|
||||
|
||||
# Flag example disabling timestamping
|
||||
pg_set $dev "flag NO_TIMESTAMP"
|
||||
|
||||
# Destination
|
||||
pg_set $dev "dst_mac $DST_MAC"
|
||||
pg_set $dev "dst $DEST_IP"
|
||||
|
||||
# Setup random UDP port src range
|
||||
pg_set $dev "flag UDPSRC_RND"
|
||||
pg_set $dev "udp_src_min $UDP_MIN"
|
||||
pg_set $dev "udp_src_max $UDP_MAX"
|
||||
done
|
||||
|
||||
# start_run
|
||||
echo "Running... ctrl^C to stop" >&2
|
||||
pg_ctrl "start"
|
||||
echo "Done" >&2
|
||||
|
||||
# Print results
|
||||
for ((thread = 0; thread < $THREADS; thread++)); do
|
||||
dev=${DEV}@${thread}
|
||||
echo "Device: $dev"
|
||||
cat /proc/net/pktgen/$dev | grep -A2 "Result:"
|
||||
done
|
82
samples/pktgen/pktgen_sample03_burst_single_flow.sh
Executable file
82
samples/pktgen/pktgen_sample03_burst_single_flow.sh
Executable file
|
@ -0,0 +1,82 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Script for max single flow performance
|
||||
# - If correctly tuned[1], single CPU 10G wirespeed small pkts is possible[2]
|
||||
#
|
||||
# Using pktgen "burst" option (use -b $N)
|
||||
# - To boost max performance
|
||||
# - Avail since: kernel v3.18
|
||||
# * commit 38b2cf2982dc73 ("net: pktgen: packet bursting via skb->xmit_more")
|
||||
# - This avoids writing the HW tailptr on every driver xmit
|
||||
# - The performance boost is impressive, see commit and blog [2]
|
||||
#
|
||||
# Notice: On purpose generates a single (UDP) flow towards target,
|
||||
# reason behind this is to only overload/activate a single CPU on
|
||||
# target host. And no randomness for pktgen also makes it faster.
|
||||
#
|
||||
# Tuning see:
|
||||
# [1] http://netoptimizer.blogspot.dk/2014/06/pktgen-for-network-overload-testing.html
|
||||
# [2] http://netoptimizer.blogspot.dk/2014/10/unlocked-10gbps-tx-wirespeed-smallest.html
|
||||
#
|
||||
basedir=`dirname $0`
|
||||
source ${basedir}/functions.sh
|
||||
root_check_run_with_sudo "$@"
|
||||
|
||||
# Parameter parsing via include
|
||||
source ${basedir}/parameters.sh
|
||||
# Set some default params, if they didn't get set
|
||||
[ -z "$DEST_IP" ] && DEST_IP="198.18.0.42"
|
||||
[ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff"
|
||||
[ -z "$BURST" ] && BURST=32
|
||||
[ -z "$CLONE_SKB" ] && CLONE_SKB="100000"
|
||||
|
||||
# Base Config
|
||||
DELAY="0" # Zero means max speed
|
||||
COUNT="0" # Zero means indefinitely
|
||||
|
||||
# General cleanup everything since last run
|
||||
pg_ctrl "reset"
|
||||
|
||||
# Threads are specified with parameter -t value in $THREADS
|
||||
for ((thread = 0; thread < $THREADS; thread++)); do
|
||||
dev=${DEV}@${thread}
|
||||
|
||||
# Add remove all other devices and add_device $dev to thread
|
||||
pg_thread $thread "rem_device_all"
|
||||
pg_thread $thread "add_device" $dev
|
||||
|
||||
# Base config
|
||||
pg_set $dev "flag QUEUE_MAP_CPU"
|
||||
pg_set $dev "count $COUNT"
|
||||
pg_set $dev "clone_skb $CLONE_SKB"
|
||||
pg_set $dev "pkt_size $PKT_SIZE"
|
||||
pg_set $dev "delay $DELAY"
|
||||
pg_set $dev "flag NO_TIMESTAMP"
|
||||
|
||||
# Destination
|
||||
pg_set $dev "dst_mac $DST_MAC"
|
||||
pg_set $dev "dst $DEST_IP"
|
||||
|
||||
# Setup burst, for easy testing -b 0 disable bursting
|
||||
# (internally in pktgen default and minimum burst=1)
|
||||
if [[ ${BURST} -ne 0 ]]; then
|
||||
pg_set $dev "burst $BURST"
|
||||
else
|
||||
info "$dev: Not using burst"
|
||||
fi
|
||||
done
|
||||
|
||||
# Run if user hits control-c
|
||||
function control_c() {
|
||||
# Print results
|
||||
for ((thread = 0; thread < $THREADS; thread++)); do
|
||||
dev=${DEV}@${thread}
|
||||
echo "Device: $dev"
|
||||
cat /proc/net/pktgen/$dev | grep -A2 "Result:"
|
||||
done
|
||||
}
|
||||
# trap keyboard interrupt (Ctrl-C)
|
||||
trap control_c SIGINT
|
||||
|
||||
echo "Running... ctrl^C to stop" >&2
|
||||
pg_ctrl "start"
|
Loading…
Reference in a new issue