Add a pktgen sample script of NUMA awareness
Subsystems (2)
v2 cover Add a pktgen sample script of NUMA awareness
From: Robert Hoo <[email protected]>
It's hard to benchmark 40G+ network bandwidth using ordinary tools like iperf, netperf (see reference 1).
Pktgen, packet generator from Kernel sapce, shall be a candidate. I derived this NUMA awared irq affinity sample script from multi-queue sample02, successfully benchmarked 40G link. I think this can also be useful for 100G reference, though I haven't got device to test yet.
This script simply does:
Detect $DEV's NUMA node belonging.
Bind each thread (processor of NUMA locality) with each $DEV queue's irq affinity, 1:1 mapping.
How many '-t' threads input determines how many queues will be utilized.
If '-f' designates first cpu id, then offset in the NUMA node's cpu list.
Tested with Intel XL710 NIC with Cisco 3172 switch.
Referrences:
https://people.netfilter.org/hawk/presentations/LCA2015/net_stack_challenges_100G_LCA2015.pdf
http://www.intel.cn/content/dam/www/public/us/en/documents/reference-guides/xl710-x710-performance-tuning-linux-guide.pdf
Change log
v2:
Rebased to https://github.com/netoptimizer/network-testing/tree/master/pktgen
Move helper functions to functions.sh
More concise shell grammar usage
Take '-f' parameter into consideration. If the first CPU is designaed,
offset in the NUMA-aware CPU list.
Use err(), info() helper functions for such outputs.
Robert Hoo (2):
Add some helper functions
Add pktgen script: pktgen_sample06_numa_awared_queue_irq_affinity.sh
pktgen/functions.sh | 44 ++++++++++ ...tgen_sample06_numa_awared_queue_irq_affinity.sh | 97 ++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100755 pktgen/pktgen_sample06_numa_awared_queue_irq_affinity.sh
Signature · 1 line
1.8.3.1
PATCH v2 1/2 Add some helper functions
From: Robert Hoo <[email protected]>
1. given a device, get its NUMA belongings
2. given a device, get its queues' irq numbers.
3. given a NUMA node, get its cpu id list.
--- pktgen/functions.sh | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
pktgen/functions.sh +44 -0
@@ -119,3 +119,47 @@ function root_check_run_with_sudo() { 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 +} +
Signature · 1 line
1.8.3.1
PATCH v2 2/2 Add pktgen script: pktgen_sample06_numa_awared_queue_irq_affinity.sh
In reply to Robert HooFrom: Robert Hoo <[email protected]>
This script simply does:
Detect $DEV's NUMA node belonging.
Bind each thread (processor of NUMA locality) with each $DEV queue's irq affinity, 1:1 mapping.
How many '-t' threads input determines how many queues will be utilized.
If '-f' designates first cpu id, then offset in the NUMA node's cpu list.
--- ...tgen_sample06_numa_awared_queue_irq_affinity.sh | 97 ++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100755 pktgen/pktgen_sample06_numa_awared_queue_irq_affinity.sh
pktgen/pktgen_sample06_numa_awared_queue_irq_affinity.sh new file +97 -0
@@ -0,0 +1,97 @@ +#!/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 + +# Base Config +DELAY="0" # Zero means max speed +COUNT="20000000" # Zero means indefinitely +[ -z "$CLONE_SKB" ] && CLONE_SKB="0" + +# Flow variation random source port between min and max +UDP_MIN=9 +UDP_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" + +# General cleanup everything since last run +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 + 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 $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 ((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
Signature · 1 line
1.8.3.1
Quoted 3 lines · On Sun, 17 Sep 2017 20:36:36 +0800 Robert Hoo <[email protected]> wrote:
Change log
v2:
Rebased to https://github.com/netoptimizer/network-testing/tree/master/pktgen
Hi Robert,
Thank you for submitting this against my git tree[1]. I skimmed the patches and they looked okay. I'll give them a test run, before I accept them into my tree.
Later I'll synchronize my pktgen scripts/git-tree with the kernel via regular patches against DaveM's net-next tree[2] (and I'll try to remember to give you author credit).
[1] https://github.com/netoptimizer/network-testing/tree/master/pktgen
[2] https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git/tree/samples/pktgen
Signature · 4 lines
Best regards, Jesper Dangaard Brouer MSc.CS, Principal Kernel Engineer at Red Hat LinkedIn: http://www.linkedin.com/in/brouer
Quoted 12 lines · On Mon, 18 Sep 2017 11:06:21 +0200 Jesper Dangaard Brouer <[email protected]>…
Quoted 3 lines · On Sun, 17 Sep 2017 20:36:36 +0800 Robert Hoo <[email protected]> wrote:
Change log
v2:
Rebased to https://github.com/netoptimizer/network-testing/tree/master/pktgenHi Robert,
Thank you for submitting this against my git tree[1]. I skimmed the patches and they looked okay. I'll give them a test run, before I accept them into my tree.
Quoted 6 lines
Later I'll synchronize my pktgen
scripts/git-treewith the kernel via regular patches against DaveM's net-next tree[2] (and I'll try to remember to give you author credit).[1] https://github.com/netoptimizer/network-testing/tree/master/pktgen
[2] https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git/tree/samples/pktgen
FYI, I've applied and pushed these patches to my tree.
https://github.com/netoptimizer/network-testing/commits?author=robert-hoo
https://github.com/netoptimizer/network-testing/commit/1b9b4b797a4f112
https://github.com/netoptimizer/network-testing/commit/65efc2352f63dde
https://github.com/netoptimizer/network-testing/commit/54eb5178aaf4031
I fixed the description a bit, and only made one simple change:
https://github.com/netoptimizer/network-testing/commit/9ff58568b3f8c91
Thanks for working on improving the pktgen scripts :-)
Signature · 4 lines
Best regards, Jesper Dangaard Brouer MSc.CS, Principal Kernel Engineer at Red Hat LinkedIn: http://www.linkedin.com/in/brouer