Skip to content

Commit

Permalink
pktgen*: add three scripts to play with pktgen module
Browse files Browse the repository at this point in the history
These three scripts come from Linux kernel repository:

  samples/pktgen/pktgen_sample01_simple.sh

With my own modifications.

Signed-off-by: Peter Xu <[email protected]>
  • Loading branch information
xzpeter committed Jul 13, 2016
1 parent 8cc1ce6 commit 8005cf1
Show file tree
Hide file tree
Showing 3 changed files with 301 additions and 0 deletions.
121 changes: 121 additions & 0 deletions pktgen-functions.sh
Original file line number Diff line number Diff line change
@@ -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
}
109 changes: 109 additions & 0 deletions pktgen-parameters.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#
# 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
echo "Extra parameters:"
echo " -C : (\$COUNT) number of packets to send"
echo " -D : (\$DELAY) delay between packets"
echo ""
}

## --- Parse command line arguments / parameters ---
## echo "Commandline options:"
while getopts "s:i:d:m:t:c:b:vxhC:D:" 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"
;;
C)
export COUNT=$OPTARG
info "Packet count: COUNT=$COUNT"
;;
D)
export DELAY=$OPTARG
info "Packet delay: DELAY=$DELAY"
;;
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
71 changes: 71 additions & 0 deletions pktgen_run
Original file line number Diff line number Diff line change
@@ -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}/pktgen-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}/pktgen-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
[ -z "$DELAY" ] && DELAY="0" # Zero means max speed
[ -z "$COUNT" ] && 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

0 comments on commit 8005cf1

Please sign in to comment.