Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
+64
View File
@@ -0,0 +1,64 @@
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.rst
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. 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
-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
-w : ($DELAY) Tx Delay value (ns)
-a : ($APPEND) Script will not reset generator's state, but will append its config
The global variable being set is also listed. E.g. the required
interface/device parameter "-i" sets variable $DEV.
"-a" parameter may be used to create different flows simultaneously.
In this mode script will keep the existing config, will append its settings.
In this mode you'll have to manually run traffic with "pg_ctrl start".
For example you may use:
source ./samples/pktgen/functions.sh
pg_ctrl reset
# add first device
./pktgen_sample06_numa_awared_queue_irq_affinity.sh -a -i ens1f0 -m 34:80:0d:a3:fc:c9 -t 8
# add second device
./pktgen_sample06_numa_awared_queue_irq_affinity.sh -a -i ens1f1 -m 34:80:0d:a3:fc:c9 -t 8
# run joint traffic on two devs
pg_ctrl start
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.
+340
View File
@@ -0,0 +1,340 @@
#
# Common functions used by pktgen scripts
# - Depending on bash 3 (or higher) syntax
#
# Author: Jesper Dangaaard Brouer
# License: GPL
set -o errexit
## -- 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
local status=0
# 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" || status=$?
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\""
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
}
function trap_exit()
{
# Cleanup pktgen setup on exit if thats not "append mode"
if [[ -z "$APPEND" ]] && [[ $EUID -eq 0 ]]; then
trap 'pg_ctrl "reset"' EXIT
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 -E "$0" "$@"
exit $?
fi
err 4 "cannot perform sudo run of $0"
fi
}
# Exact input device's NUMA node info
function get_iface_node()
{
local node=$(</sys/class/net/$1/device/numa_node)
if [[ $node == -1 ]]; then
echo 0
else
echo $node
fi
}
# Given an Dev/iface, get its queues' irq numbers
function get_iface_irqs()
{
local IFACE=$1
local queues="${IFACE}-.*TxRx"
irqs=$(grep "$queues" /proc/interrupts | cut -f1 -d:)
[ -z "$irqs" ] && irqs=$(grep $IFACE /proc/interrupts | cut -f1 -d:)
[ -z "$irqs" ] && irqs=$(for i in `ls -Ux /sys/class/net/$IFACE/device/msi_irqs` ;\
do grep "$i:.*TxRx" /proc/interrupts | grep -v fdir | cut -f 1 -d : ;\
done)
[ -z "$irqs" ] && err 3 "Could not find interrupts for $IFACE"
echo $irqs
}
# Given a NUMA node, return cpu ids belonging to it.
function get_node_cpus()
{
local node=$1
local node_cpu_list
local node_cpu_range_list=`cut -f1- -d, --output-delimiter=" " \
/sys/devices/system/node/node$node/cpulist`
for cpu_range in $node_cpu_range_list
do
node_cpu_list="$node_cpu_list "`seq -s " " ${cpu_range//-/ }`
done
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=( $(grep -E -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()
{
local port_str=$1
local port_list
local min_port
local max_port
IFS="-" read -ra port_list <<< $port_str
min_port=${port_list[0]}
max_port=${port_list[1]:-$min_port}
echo $min_port $max_port
}
# Given a minimum and maximum port, verify port number.
function validate_ports()
{
local min_port=$1
local max_port=$2
# 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
fi
fi
err 5 "Invalid port(s): $min_port-$max_port"
}
+139
View File
@@ -0,0 +1,139 @@
#
# SPDX-License-Identifier: GPL-2.0
# 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. 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 " -k : (\$UDP_CSUM) enable UDP tx checksum"
echo " -t : (\$THREADS) threads to start"
echo " -f : (\$F_THREAD) index of first thread (zero indexed CPU number)"
echo " -c : (\$SKB_CLONE) SKB clones send before alloc new SKB"
echo " -n : (\$COUNT) num messages to send per thread, 0 means indefinitely"
echo " -b : (\$BURST) HW level bursting of SKBs"
echo " -v : (\$VERBOSE) verbose"
echo " -x : (\$DEBUG) debug"
echo " -6 : (\$IP6) IPv6"
echo " -w : (\$DELAY) Tx Delay value (ns)"
echo " -a : (\$APPEND) Script will not reset generator's state, but will append its config"
echo ""
}
## --- Parse command line arguments / parameters ---
## echo "Commandline options:"
while getopts "s:i:d:m:p:f:t:c:n:b:w:vxh6ak" 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"
;;
p) # PORT
export DST_PORT=$OPTARG
info "Destination PORT set to: DST_PORT=$DST_PORT"
;;
f)
export F_THREAD=$OPTARG
info "Index of first thread (zero indexed CPU number): $F_THREAD"
;;
t)
export THREADS=$OPTARG
info "Number of threads to start: $THREADS"
;;
c)
export CLONE_SKB=$OPTARG
info "CLONE_SKB=$CLONE_SKB"
;;
n)
export COUNT=$OPTARG
info "COUNT=$COUNT"
;;
b)
export BURST=$OPTARG
info "SKB bursting: BURST=$BURST"
;;
w)
export DELAY=$OPTARG
info "DELAY=$DELAY"
;;
v)
export VERBOSE=yes
info "Verbose mode: VERBOSE=$VERBOSE"
;;
x)
export DEBUG=yes
info "Debug mode: DEBUG=$DEBUG"
;;
6)
export IP6=6
info "IP6: IP6=$IP6"
;;
a)
export APPEND=yes
info "Append mode: APPEND=$APPEND"
;;
k)
export UDP_CSUM=yes
info "UDP tx checksum: UDP_CSUM=$UDP_CSUM"
;;
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 "$F_THREAD" ]; then
# First thread (F_THREAD) reference the zero indexed CPU number
export F_THREAD=0
fi
if [ -z "$THREADS" ]; then
export THREADS=1
fi
# default DELAY
[ -z "$DELAY" ] && export DELAY=0 # Zero means max speed
export L_THREAD=$(( THREADS + F_THREAD - 1 ))
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
@@ -0,0 +1,113 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# 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
# Trap EXIT first
trap_exit
# Using invalid DST_MAC will cause the packets to get dropped in
# ip_rcv() which is part of the test
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"
[ -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 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
pg_ctrl "reset"
# Threads are specified with parameter -t value in $THREADS
for ((thread = $F_THREAD; thread <= $L_THREAD; 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${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 $UDP_DST_MIN"
pg_set $dev "udp_dst_max $UDP_DST_MAX"
fi
# 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
# Run if user hits control-c
function print_result() {
# Print results
for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
dev=${DEV}@${thread}
echo "Device: $dev"
cat /proc/net/pktgen/$dev | grep -A2 "Result:"
done
}
# trap keyboard interrupt (Ctrl-C)
trap true SIGINT
# start_run
echo "Running... ctrl^C to stop" >&2
pg_ctrl "start"
echo "Done" >&2
print_result
@@ -0,0 +1,93 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Benchmark script:
# - developed for benchmarking egress qdisc path, derived (more
# like cut'n'pasted) from ingress benchmark script.
#
# Script for injecting packets into egress qdisc path of the stack
# with pktgen "xmit_mode queue_xmit".
#
basedir=`dirname $0`
source ${basedir}/functions.sh
root_check_run_with_sudo "$@"
# Parameter parsing via include
source ${basedir}/parameters.sh
# Trap EXIT first
trap_exit
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"
# Burst greater than 1 are invalid for queue_xmit mode
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 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
pg_ctrl "reset"
# Threads are specified with parameter -t value in $THREADS
for ((thread = $F_THREAD; thread <= $L_THREAD; 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${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 $UDP_DST_MIN"
pg_set $dev "udp_dst_max $UDP_DST_MAX"
fi
# Inject packet into TX qdisc egress path of stack
pg_set $dev "xmit_mode queue_xmit"
done
# Run if user hits control-c
function print_result {
# Print results
for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
dev=${DEV}@${thread}
echo "Device: $dev"
cat /proc/net/pktgen/$dev | grep -A2 "Result:"
done
}
# trap keyboard interrupt (Ctrl-C)
trap true SIGINT
# start_run
echo "Running... ctrl^C to stop" >&2
pg_ctrl "start"
echo "Done" >&2
print_result
+104
View File
@@ -0,0 +1,104 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# 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
# Trap EXIT first
trap_exit
#
# Set some default params, if they didn't get set
if [ -z "$DEST_IP" ]; then
[ -z "$IP6" ] && DEST_IP="198.18.0.42" || DEST_IP="FD00::1"
fi
[ -z "$CLONE_SKB" ] && CLONE_SKB="0"
# 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 UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
validate_ports $UDP_DST_MIN $UDP_DST_MAX
fi
# Flow variation random source port between min and max
UDP_SRC_MIN=9
UDP_SRC_MAX=109
# General cleanup everything since last run
# (especially important if other threads were configured by other scripts)
[ -z "$APPEND" ] && pg_ctrl "reset"
# Add remove all other devices and add_device $DEV to thread 0
thread=0
[ -z "$APPEND" ] && 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${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 $UDP_DST_MIN"
pg_set $DEV "udp_dst_max $UDP_DST_MAX"
fi
[ ! -z "$UDP_CSUM" ] && pg_set $DEV "flag UDPCSUM"
# Setup random UDP port src range
pg_set $DEV "flag UDPSRC_RND"
pg_set $DEV "udp_src_min $UDP_SRC_MIN"
pg_set $DEV "udp_src_max $UDP_SRC_MAX"
# Run if user hits control-c
function print_result() {
# Print results
echo "Result device: $DEV"
cat /proc/net/pktgen/$DEV
}
# trap keyboard interrupt (Ctrl-C)
trap true SIGINT
if [ -z "$APPEND" ]; then
# start_run
echo "Running... ctrl^C to stop" >&2
pg_ctrl "start"
echo "Done" >&2
print_result
else
echo "Append mode: config done. Do more or use 'pg_ctrl start' to run"
fi
+110
View File
@@ -0,0 +1,110 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# 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
# Trap EXIT first
trap_exit
[ -z "$COUNT" ] && COUNT="100000" # Zero means indefinitely
# Base Config
[ -z "$CLONE_SKB" ] && CLONE_SKB="0"
# Flow variation random source port between min and max
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 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
[ -z "$APPEND" ] && pg_ctrl "reset"
# Threads are specified with parameter -t value in $THREADS
for ((thread = $F_THREAD; thread <= $L_THREAD; 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
[ -z "$APPEND" ] && 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${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 $UDP_DST_MIN"
pg_set $dev "udp_dst_max $UDP_DST_MAX"
fi
[ ! -z "$UDP_CSUM" ] && pg_set $dev "flag UDPCSUM"
# Setup random UDP port src range
pg_set $dev "flag UDPSRC_RND"
pg_set $dev "udp_src_min $UDP_SRC_MIN"
pg_set $dev "udp_src_max $UDP_SRC_MAX"
done
# Run if user hits control-c
function print_result() {
# Print results
for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
dev=${DEV}@${thread}
echo "Device: $dev"
cat /proc/net/pktgen/$dev | grep -A2 "Result:"
done
}
# trap keyboard interrupt (Ctrl-C)
trap true SIGINT
if [ -z "$APPEND" ]; then
# start_run
echo "Running... ctrl^C to stop" >&2
pg_ctrl "start"
echo "Done" >&2
print_result
else
echo "Append mode: config done. Do more or use 'pg_ctrl start' to run"
fi
@@ -0,0 +1,110 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# 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
# Trap EXIT first
trap_exit
# Set some default params, if they didn't get set
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"
[ -z "$BURST" ] && BURST=32
[ -z "$CLONE_SKB" ] && CLONE_SKB="0" # No need for clones when bursting
[ -z "$COUNT" ] && COUNT="0" # 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 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
[ -z "$APPEND" ] && pg_ctrl "reset"
# Threads are specified with parameter -t value in $THREADS
for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
dev=${DEV}@${thread}
# Add remove all other devices and add_device $dev to thread
[ -z "$APPEND" ] && 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${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 $UDP_DST_MIN"
pg_set $dev "udp_dst_max $UDP_DST_MAX"
fi
[ ! -z "$UDP_CSUM" ] && pg_set $dev "flag UDPCSUM"
# 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 print_result() {
# Print results
for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
dev=${DEV}@${thread}
echo "Device: $dev"
cat /proc/net/pktgen/$dev | grep -A2 "Result:"
done
}
# trap keyboard interrupt (Ctrl-C)
trap true SIGINT
if [ -z "$APPEND" ]; then
echo "Running... ctrl^C to stop" >&2
pg_ctrl "start"
print_result
else
echo "Append mode: config done. Do more or use 'pg_ctrl start' to run"
fi
+122
View File
@@ -0,0 +1,122 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Script example for many flows testing
#
# Number of simultaneous flows limited by variable $FLOWS
# and number of packets per flow controlled by variable $FLOWLEN
#
basedir=`dirname $0`
source ${basedir}/functions.sh
root_check_run_with_sudo "$@"
# Parameter parsing via include
source ${basedir}/parameters.sh
# Trap EXIT first
trap_exit
# Set some default params, if they didn't get set
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"
[ -z "$CLONE_SKB" ] && CLONE_SKB="0"
[ -z "$COUNT" ] && COUNT="0" # 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 UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
validate_ports $UDP_DST_MIN $UDP_DST_MAX
fi
# NOTICE: Script specific settings
# =======
# Limiting the number of concurrent flows ($FLOWS)
# and also set how many packets each flow contains ($FLOWLEN)
#
[ -z "$FLOWS" ] && FLOWS="8000"
[ -z "$FLOWLEN" ] && FLOWLEN="10"
if [[ -n "$BURST" ]]; then
err 1 "Bursting not supported for this mode"
fi
# 198.18.0.0 / 198.19.255.255
read -r SRC_MIN SRC_MAX <<< $(parse_addr 198.18.0.0/15)
# General cleanup everything since last run
[ -z "$APPEND" ] && pg_ctrl "reset"
# Threads are specified with parameter -t value in $THREADS
for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
dev=${DEV}@${thread}
# Add remove all other devices and add_device $dev to thread
[ -z "$APPEND" ] && 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"
# Single destination
pg_set $dev "dst_mac $DST_MAC"
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 $UDP_DST_MIN"
pg_set $dev "udp_dst_max $UDP_DST_MAX"
fi
[ ! -z "$UDP_CSUM" ] && pg_set $dev "flag UDPCSUM"
# Randomize source IP-addresses
pg_set $dev "flag IPSRC_RND"
pg_set $dev "src_min $SRC_MIN"
pg_set $dev "src_max $SRC_MAX"
# Limit number of flows (max 65535)
pg_set $dev "flows $FLOWS"
#
# How many packets a flow will send, before flow "entry" is
# re-generated/setup.
pg_set $dev "flowlen $FLOWLEN"
#
# Flag FLOW_SEQ will cause $FLOWLEN packets from the same flow
# being send back-to-back, before next flow is selected
# incrementally. This helps lookup caches, and is more realistic.
#
pg_set $dev "flag FLOW_SEQ"
done
# Run if user hits control-c
function print_result() {
# Print results
for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
dev=${DEV}@${thread}
echo "Device: $dev"
cat /proc/net/pktgen/$dev | grep -A2 "Result:"
done
}
# trap keyboard interrupt (Ctrl-C)
trap true SIGINT
if [ -z "$APPEND" ]; then
echo "Running... ctrl^C to stop" >&2
pg_ctrl "start"
print_result
else
echo "Append mode: config done. Do more or use 'pg_ctrl start' to run"
fi
@@ -0,0 +1,106 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Script will generate one flow per thread (-t N)
# - Same destination IP
# - Fake source IPs for each flow (fixed based on thread number)
#
# Useful for scale testing on receiver, to see whether silo'ing flows
# works and scales. For optimal scalability (on receiver) each
# separate-flow should not access shared variables/data. This script
# helps magnify any of these scaling issues by overloading the receiver.
#
basedir=`dirname $0`
source ${basedir}/functions.sh
root_check_run_with_sudo "$@"
# Parameter parsing via include
source ${basedir}/parameters.sh
# Trap EXIT first
trap_exit
# Set some default params, if they didn't get set
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"
[ -z "$CLONE_SKB" ] && CLONE_SKB="0"
[ -z "$BURST" ] && BURST=32
[ -z "$COUNT" ] && COUNT="0" # 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 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
[ -z "$APPEND" ] && pg_ctrl "reset"
# Threads are specified with parameter -t value in $THREADS
for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
dev=${DEV}@${thread}
# Add remove all other devices and add_device $dev to thread
[ -z "$APPEND" ] && 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"
# Single destination
pg_set $dev "dst_mac $DST_MAC"
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 $UDP_DST_MIN"
pg_set $dev "udp_dst_max $UDP_DST_MAX"
fi
[ ! -z "$UDP_CSUM" ] && pg_set $dev "flag UDPCSUM"
# Setup source IP-addresses based on thread number
pg_set $dev "src_min 198.18.$((thread+1)).1"
pg_set $dev "src_max 198.18.$((thread+1)).1"
# 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 print_result() {
# Print results
for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
dev=${DEV}@${thread}
echo "Device: $dev"
cat /proc/net/pktgen/$dev | grep -A2 "Result:"
done
}
# trap keyboard interrupt (Ctrl-C)
trap true SIGINT
if [ -z "$APPEND" ]; then
echo "Running... ctrl^C to stop" >&2
pg_ctrl "start"
print_result
else
echo "Append mode: config done. Do more or use 'pg_ctrl start' to run"
fi
@@ -0,0 +1,128 @@
#!/bin/bash
#
# Multiqueue: Using pktgen threads for sending on multiple CPUs
# * adding devices to kernel threads which are in the same NUMA node
# * bound devices queue's irq affinity to the threads, 1:1 mapping
# * 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
# Trap EXIT first
trap_exit
# Base Config
[ -z "$COUNT" ] && COUNT="20000000" # Zero means indefinitely
[ -z "$CLONE_SKB" ] && CLONE_SKB="0"
# Flow variation random source port between min and max
UDP_SRC_MIN=9
UDP_SRC_MAX=109
node=`get_iface_node $DEV`
irq_array=(`get_iface_irqs $DEV`)
cpu_array=(`get_node_cpus $node`)
[ $THREADS -gt ${#irq_array[*]} -o $THREADS -gt ${#cpu_array[*]} ] && \
err 1 "Thread number $THREADS exceeds: min (${#irq_array[*]},${#cpu_array[*]})"
# (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 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
[ -z "$APPEND" ] && pg_ctrl "reset"
# Threads are specified with parameter -t value in $THREADS
for ((i = 0; i < $THREADS; i++)); do
# The device name is extended with @name, using thread number to
# make then unique, but any name will do.
# Set the queue's irq affinity to this $thread (processor)
# if '-f' is designated, offset cpu id
thread=${cpu_array[$((i+F_THREAD))]}
dev=${DEV}@${thread}
echo $thread > /proc/irq/${irq_array[$i]}/smp_affinity_list
info "irq ${irq_array[$i]} is set affinity to `cat /proc/irq/${irq_array[$i]}/smp_affinity_list`"
# Add remove all other devices and add_device $dev to thread
[ -z "$APPEND" ] && pg_thread $thread "rem_device_all"
pg_thread $thread "add_device" $dev
# select queue and bind the queue and $dev in 1:1 relationship
queue_num=$i
info "queue number is $queue_num"
pg_set $dev "queue_map_min $queue_num"
pg_set $dev "queue_map_max $queue_num"
# 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${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 $UDP_DST_MIN"
pg_set $dev "udp_dst_max $UDP_DST_MAX"
fi
[ ! -z "$UDP_CSUM" ] && pg_set $dev "flag UDPCSUM"
# Setup random UDP port src range
pg_set $dev "flag UDPSRC_RND"
pg_set $dev "udp_src_min $UDP_SRC_MIN"
pg_set $dev "udp_src_max $UDP_SRC_MAX"
done
# Run if user hits control-c
function print_result() {
# Print results
for ((i = 0; i < $THREADS; i++)); do
thread=${cpu_array[$((i+F_THREAD))]}
dev=${DEV}@${thread}
echo "Device: $dev"
cat /proc/net/pktgen/$dev | grep -A2 "Result:"
done
}
# trap keyboard interrupt (Ctrl-C)
trap true SIGINT
# start_run
if [ -z "$APPEND" ]; then
echo "Running... ctrl^C to stop" >&2
pg_ctrl "start"
echo "Done" >&2
print_result
else
echo "Append mode: config done. Do more or use 'pg_ctrl start' to run"
fi