Skip to content

Commit

Permalink
Merge branch 'samples-pktgen-allow-to-specify-destination-IP-range'
Browse files Browse the repository at this point in the history
Daniel T. Lee says:

====================
samples: pktgen: allow to specify destination IP range

Currently, pktgen script supports specify destination port range.

To further extend the capabilities, this commit allows to specify destination
IP range with CIDR when running pktgen script.

Specifying destination IP range will be useful on various situation such as
testing RSS/RPS with randomizing n-tuple.

This patchset fixes the problem with checking the command result on proc_cmd,
and add feature to allow destination IP range.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Oct 7, 2019
2 parents db7fe42 + 40f843e commit 9b75803
Show file tree
Hide file tree
Showing 11 changed files with 244 additions and 65 deletions.
2 changes: 1 addition & 1 deletion samples/pktgen/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ 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
-d : ($DEST_IP) destination IP. CIDR (e.g. 198.18.0.0/15) is also allowed
-m : ($DST_MAC) destination MAC-addr
-p : ($DST_PORT) destination PORT range (e.g. 433-444) is also allowed
-t : ($THREADS) threads to start
Expand Down
154 changes: 145 additions & 9 deletions samples/pktgen/functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
# Author: Jesper Dangaaard Brouer
# License: GPL

set -o errexit

## -- General shell logging cmds --
function err() {
local exitcode=$1
Expand Down Expand Up @@ -58,6 +60,7 @@ function pg_set() {
function proc_cmd() {
local result
local proc_file=$1
local status=0
# after shift, the remaining args are contained in $@
shift
local proc_ctrl=${PROC_DIR}/$proc_file
Expand All @@ -73,13 +76,13 @@ function proc_cmd() {
echo "cmd: $@ > $proc_ctrl"
fi
# Quoting of "$@" is important for space expansion
echo "$@" > "$proc_ctrl"
local status=$?
echo "$@" > "$proc_ctrl" || status=$?

result=$(grep "Result: OK:" $proc_ctrl)
# Due to pgctrl, cannot use exit code $? from grep
if [[ "$result" == "" ]]; then
grep "Result:" $proc_ctrl >&2
if [[ "$proc_file" != "pgctrl" ]]; then
result=$(grep "Result: OK:" $proc_ctrl) || true
if [[ "$result" == "" ]]; then
grep "Result:" $proc_ctrl >&2
fi
fi
if (( $status != 0 )); then
err 5 "Write error($status) occurred cmd: \"$@ > $proc_ctrl\""
Expand All @@ -105,6 +108,8 @@ function pgset() {
fi
}

[[ $EUID -eq 0 ]] && trap 'pg_ctrl "reset"' EXIT

## -- General shell tricks --

function root_check_run_with_sudo() {
Expand Down Expand Up @@ -163,6 +168,137 @@ function get_node_cpus()
echo $node_cpu_list
}

# Check $1 is in between $2, $3 ($2 <= $1 <= $3)
function in_between() { [[ ($1 -ge $2) && ($1 -le $3) ]] ; }

# Extend shrunken IPv6 address.
# fe80::42:bcff:fe84:e10a => fe80:0:0:0:42:bcff:fe84:e10a
function extend_addr6()
{
local addr=$1
local sep=: sep2=::
local sep_cnt=$(tr -cd $sep <<< $1 | wc -c)
local shrink

# separator count should be (2 <= $sep_cnt <= 7)
if ! (in_between $sep_cnt 2 7); then
err 5 "Invalid IP6 address: $1"
fi

# if shrink '::' occurs multiple, it's malformed.
shrink=( $(egrep -o "$sep{2,}" <<< $addr) )
if [[ ${#shrink[@]} -ne 0 ]]; then
if [[ ${#shrink[@]} -gt 1 || ( ${shrink[0]} != $sep2 ) ]]; then
err 5 "Invalid IP6 address: $1"
fi
fi

# add 0 at begin & end, and extend addr by adding :0
[[ ${addr:0:1} == $sep ]] && addr=0${addr}
[[ ${addr: -1} == $sep ]] && addr=${addr}0
echo "${addr/$sep2/$(printf ':0%.s' $(seq $[8-sep_cnt])):}"
}

# Given a single IP(v4/v6) address, whether it is valid.
function validate_addr()
{
# check function is called with (funcname)6
[[ ${FUNCNAME[1]: -1} == 6 ]] && local IP6=6
local bitlen=$[ IP6 ? 128 : 32 ]
local len=$[ IP6 ? 8 : 4 ]
local max=$[ 2**(len*2)-1 ]
local net prefix
local addr sep

IFS='/' read net prefix <<< $1
[[ $IP6 ]] && net=$(extend_addr6 $net)

# if prefix exists, check (0 <= $prefix <= $bitlen)
if [[ -n $prefix ]]; then
if ! (in_between $prefix 0 $bitlen); then
err 5 "Invalid prefix: /$prefix"
fi
fi

# set separator for each IP(v4/v6)
[[ $IP6 ]] && sep=: || sep=.
IFS=$sep read -a addr <<< $net

# array length
if [[ ${#addr[@]} != $len ]]; then
err 5 "Invalid IP$IP6 address: $1"
fi

# check each digit (0 <= $digit <= $max)
for digit in "${addr[@]}"; do
[[ $IP6 ]] && digit=$[ 16#$digit ]
if ! (in_between $digit 0 $max); then
err 5 "Invalid IP$IP6 address: $1"
fi
done

return 0
}

function validate_addr6() { validate_addr $@ ; }

# Given a single IP(v4/v6) or CIDR, return minimum and maximum IP addr.
function parse_addr()
{
# check function is called with (funcname)6
[[ ${FUNCNAME[1]: -1} == 6 ]] && local IP6=6
local net prefix
local min_ip max_ip

IFS='/' read net prefix <<< $1
[[ $IP6 ]] && net=$(extend_addr6 $net)

if [[ -z $prefix ]]; then
min_ip=$net
max_ip=$net
else
# defining array for converting Decimal 2 Binary
# 00000000 00000001 00000010 00000011 00000100 ...
local d2b='{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}'
[[ $IP6 ]] && d2b+=$d2b
eval local D2B=($d2b)

local bitlen=$[ IP6 ? 128 : 32 ]
local remain=$[ bitlen-prefix ]
local octet=$[ IP6 ? 16 : 8 ]
local min_mask max_mask
local min max
local ip_bit
local ip sep

# set separator for each IP(v4/v6)
[[ $IP6 ]] && sep=: || sep=.
IFS=$sep read -ra ip <<< $net

min_mask="$(printf '1%.s' $(seq $prefix))$(printf '0%.s' $(seq $remain))"
max_mask="$(printf '0%.s' $(seq $prefix))$(printf '1%.s' $(seq $remain))"

# calculate min/max ip with &,| operator
for i in "${!ip[@]}"; do
digit=$[ IP6 ? 16#${ip[$i]} : ${ip[$i]} ]
ip_bit=${D2B[$digit]}

idx=$[ octet*i ]
min[$i]=$[ 2#$ip_bit & 2#${min_mask:$idx:$octet} ]
max[$i]=$[ 2#$ip_bit | 2#${max_mask:$idx:$octet} ]
[[ $IP6 ]] && { min[$i]=$(printf '%X' ${min[$i]});
max[$i]=$(printf '%X' ${max[$i]}); }
done

min_ip=$(IFS=$sep; echo "${min[*]}")
max_ip=$(IFS=$sep; echo "${max[*]}")
fi

echo $min_ip $max_ip
}

function parse_addr6() { parse_addr $@ ; }

# Given a single or range of port(s), return minimum and maximum port number.
function parse_ports()
{
Expand All @@ -185,9 +321,9 @@ function validate_ports()
local min_port=$1
local max_port=$2

# 0 < port < 65536
if [[ $min_port -gt 0 && $min_port -lt 65536 ]]; then
if [[ $max_port -gt 0 && $max_port -lt 65536 ]]; then
# 1 <= port <= 65535
if (in_between $min_port 1 65535); then
if (in_between $max_port 1 65535); then
if [[ $min_port -le $max_port ]]; then
return 0
fi
Expand Down
2 changes: 1 addition & 1 deletion samples/pktgen/parameters.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ function usage() {
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 " -d : (\$DEST_IP) destination IP. CIDR (e.g. 198.18.0.0/15) is also allowed"
echo " -m : (\$DST_MAC) destination MAC-addr"
echo " -p : (\$DST_PORT) destination PORT range (e.g. 433-444) is also allowed"
echo " -t : (\$THREADS) threads to start"
Expand Down
15 changes: 10 additions & 5 deletions samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,13 @@ fi
[ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff"
[ -z "$BURST" ] && BURST=1024
[ -z "$COUNT" ] && COUNT="10000000" # Zero means indefinitely
if [ -n "$DEST_IP" ]; then
validate_addr${IP6} $DEST_IP
read -r DST_MIN DST_MAX <<< $(parse_addr${IP6} $DEST_IP)
fi
if [ -n "$DST_PORT" ]; then
read -r DST_MIN DST_MAX <<< $(parse_ports $DST_PORT)
validate_ports $DST_MIN $DST_MAX
read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
validate_ports $UDP_DST_MIN $UDP_DST_MAX
fi

# Base Config
Expand Down Expand Up @@ -71,13 +75,14 @@ for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do

# Destination
pg_set $dev "dst_mac $DST_MAC"
pg_set $dev "dst$IP6 $DEST_IP"
pg_set $dev "dst${IP6}_min $DST_MIN"
pg_set $dev "dst${IP6}_max $DST_MAX"

if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
pg_set $dev "flag UDPDST_RND"
pg_set $dev "udp_dst_min $DST_MIN"
pg_set $dev "udp_dst_max $DST_MAX"
pg_set $dev "udp_dst_min $UDP_DST_MIN"
pg_set $dev "udp_dst_max $UDP_DST_MAX"
fi

# Inject packet into RX path of stack
Expand Down
15 changes: 10 additions & 5 deletions samples/pktgen/pktgen_bench_xmit_mode_queue_xmit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,13 @@ if [[ -n "$BURST" ]]; then
err 1 "Bursting not supported for this mode"
fi
[ -z "$COUNT" ] && COUNT="10000000" # Zero means indefinitely
if [ -n "$DEST_IP" ]; then
validate_addr${IP6} $DEST_IP
read -r DST_MIN DST_MAX <<< $(parse_addr${IP6} $DEST_IP)
fi
if [ -n "$DST_PORT" ]; then
read -r DST_MIN DST_MAX <<< $(parse_ports $DST_PORT)
validate_ports $DST_MIN $DST_MAX
read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
validate_ports $UDP_DST_MIN $UDP_DST_MAX
fi

# Base Config
Expand Down Expand Up @@ -54,13 +58,14 @@ for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do

# Destination
pg_set $dev "dst_mac $DST_MAC"
pg_set $dev "dst$IP6 $DEST_IP"
pg_set $dev "dst${IP6}_min $DST_MIN"
pg_set $dev "dst${IP6}_max $DST_MAX"

if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
pg_set $dev "flag UDPDST_RND"
pg_set $dev "udp_dst_min $DST_MIN"
pg_set $dev "udp_dst_max $DST_MAX"
pg_set $dev "udp_dst_min $UDP_DST_MIN"
pg_set $dev "udp_dst_max $UDP_DST_MAX"
fi

# Inject packet into TX qdisc egress path of stack
Expand Down
23 changes: 14 additions & 9 deletions samples/pktgen/pktgen_sample01_simple.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,21 @@ fi
# Example enforce param "-m" for dst_mac
[ -z "$DST_MAC" ] && usage && err 2 "Must specify -m dst_mac"
[ -z "$COUNT" ] && COUNT="100000" # Zero means indefinitely
if [ -n "$DEST_IP" ]; then
validate_addr${IP6} $DEST_IP
read -r DST_MIN DST_MAX <<< $(parse_addr${IP6} $DEST_IP)
fi
if [ -n "$DST_PORT" ]; then
read -r DST_MIN DST_MAX <<< $(parse_ports $DST_PORT)
validate_ports $DST_MIN $DST_MAX
read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
validate_ports $UDP_DST_MIN $UDP_DST_MAX
fi

# Base Config
DELAY="0" # Zero means max speed

# Flow variation random source port between min and max
UDP_MIN=9
UDP_MAX=109
UDP_SRC_MIN=9
UDP_SRC_MAX=109

# General cleanup everything since last run
# (especially important if other threads were configured by other scripts)
Expand Down Expand Up @@ -61,19 +65,20 @@ pg_set $DEV "flag NO_TIMESTAMP"

# Destination
pg_set $DEV "dst_mac $DST_MAC"
pg_set $DEV "dst$IP6 $DEST_IP"
pg_set $DEV "dst${IP6}_min $DST_MIN"
pg_set $DEV "dst${IP6}_max $DST_MAX"

if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
pg_set $DEV "flag UDPDST_RND"
pg_set $DEV "udp_dst_min $DST_MIN"
pg_set $DEV "udp_dst_max $DST_MAX"
pg_set $DEV "udp_dst_min $UDP_DST_MIN"
pg_set $DEV "udp_dst_max $UDP_DST_MAX"
fi

# 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"
pg_set $DEV "udp_src_min $UDP_SRC_MIN"
pg_set $DEV "udp_src_max $UDP_SRC_MAX"

# start_run
echo "Running... ctrl^C to stop" >&2
Expand Down
23 changes: 14 additions & 9 deletions samples/pktgen/pktgen_sample02_multiqueue.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,21 @@ DELAY="0" # Zero means max speed
[ -z "$CLONE_SKB" ] && CLONE_SKB="0"

# Flow variation random source port between min and max
UDP_MIN=9
UDP_MAX=109
UDP_SRC_MIN=9
UDP_SRC_MAX=109

# (example of setting default params in your script)
if [ -z "$DEST_IP" ]; then
[ -z "$IP6" ] && DEST_IP="198.18.0.42" || DEST_IP="FD00::1"
fi
[ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff"
if [ -n "$DEST_IP" ]; then
validate_addr${IP6} $DEST_IP
read -r DST_MIN DST_MAX <<< $(parse_addr${IP6} $DEST_IP)
fi
if [ -n "$DST_PORT" ]; then
read -r DST_MIN DST_MAX <<< $(parse_ports $DST_PORT)
validate_ports $DST_MIN $DST_MAX
read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
validate_ports $UDP_DST_MIN $UDP_DST_MAX
fi

# General cleanup everything since last run
Expand Down Expand Up @@ -62,19 +66,20 @@ for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do

# Destination
pg_set $dev "dst_mac $DST_MAC"
pg_set $dev "dst$IP6 $DEST_IP"
pg_set $dev "dst${IP6}_min $DST_MIN"
pg_set $dev "dst${IP6}_max $DST_MAX"

if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
pg_set $dev "flag UDPDST_RND"
pg_set $dev "udp_dst_min $DST_MIN"
pg_set $dev "udp_dst_max $DST_MAX"
pg_set $dev "udp_dst_min $UDP_DST_MIN"
pg_set $dev "udp_dst_max $UDP_DST_MAX"
fi

# 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"
pg_set $dev "udp_src_min $UDP_SRC_MIN"
pg_set $dev "udp_src_max $UDP_SRC_MAX"
done

# start_run
Expand Down
Loading

0 comments on commit 9b75803

Please sign in to comment.