1*053f45beSAndroid Build Coastguard Worker#!/bin/bash 2*053f45beSAndroid Build Coastguard Worker# SPDX-License-Identifier: GPL-2.0 3*053f45beSAndroid Build Coastguard Worker# 4*053f45beSAndroid Build Coastguard Worker# extended toeplitz test: test rxhash plus, optionally, either (1) rss mapping 5*053f45beSAndroid Build Coastguard Worker# from rxhash to rx queue ('-rss') or (2) rps mapping from rxhash to cpu 6*053f45beSAndroid Build Coastguard Worker# ('-rps <rps_map>') 7*053f45beSAndroid Build Coastguard Worker# 8*053f45beSAndroid Build Coastguard Worker# irq-pattern-prefix can be derived from /sys/kernel/irq/*/action, 9*053f45beSAndroid Build Coastguard Worker# which is a driver-specific encoding. 10*053f45beSAndroid Build Coastguard Worker# 11*053f45beSAndroid Build Coastguard Worker# invoke as ./toeplitz.sh (-i <iface>) -u|-t -4|-6 \ 12*053f45beSAndroid Build Coastguard Worker# [(-rss -irq_prefix <irq-pattern-prefix>)|(-rps <rps_map>)] 13*053f45beSAndroid Build Coastguard Worker 14*053f45beSAndroid Build Coastguard Workersource setup_loopback.sh 15*053f45beSAndroid Build Coastguard Workerreadonly SERVER_IP4="192.168.1.200/24" 16*053f45beSAndroid Build Coastguard Workerreadonly SERVER_IP6="fda8::1/64" 17*053f45beSAndroid Build Coastguard Workerreadonly SERVER_MAC="aa:00:00:00:00:02" 18*053f45beSAndroid Build Coastguard Worker 19*053f45beSAndroid Build Coastguard Workerreadonly CLIENT_IP4="192.168.1.100/24" 20*053f45beSAndroid Build Coastguard Workerreadonly CLIENT_IP6="fda8::2/64" 21*053f45beSAndroid Build Coastguard Workerreadonly CLIENT_MAC="aa:00:00:00:00:01" 22*053f45beSAndroid Build Coastguard Worker 23*053f45beSAndroid Build Coastguard WorkerPORT=8000 24*053f45beSAndroid Build Coastguard WorkerKEY="$(</proc/sys/net/core/netdev_rss_key)" 25*053f45beSAndroid Build Coastguard WorkerTEST_RSS=false 26*053f45beSAndroid Build Coastguard WorkerRPS_MAP="" 27*053f45beSAndroid Build Coastguard WorkerPROTO_FLAG="" 28*053f45beSAndroid Build Coastguard WorkerIP_FLAG="" 29*053f45beSAndroid Build Coastguard WorkerDEV="eth0" 30*053f45beSAndroid Build Coastguard Worker 31*053f45beSAndroid Build Coastguard Worker# Return the number of rxqs among which RSS is configured to spread packets. 32*053f45beSAndroid Build Coastguard Worker# This is determined by reading the RSS indirection table using ethtool. 33*053f45beSAndroid Build Coastguard Workerget_rss_cfg_num_rxqs() { 34*053f45beSAndroid Build Coastguard Worker echo $(ethtool -x "${DEV}" | 35*053f45beSAndroid Build Coastguard Worker grep -E [[:space:]]+[0-9]+:[[:space:]]+ | 36*053f45beSAndroid Build Coastguard Worker cut -d: -f2- | 37*053f45beSAndroid Build Coastguard Worker awk '{$1=$1};1' | 38*053f45beSAndroid Build Coastguard Worker tr ' ' '\n' | 39*053f45beSAndroid Build Coastguard Worker sort -u | 40*053f45beSAndroid Build Coastguard Worker wc -l) 41*053f45beSAndroid Build Coastguard Worker} 42*053f45beSAndroid Build Coastguard Worker 43*053f45beSAndroid Build Coastguard Worker# Return a list of the receive irq handler cpus. 44*053f45beSAndroid Build Coastguard Worker# The list is ordered by the irqs, so first rxq-0 cpu, then rxq-1 cpu, etc. 45*053f45beSAndroid Build Coastguard Worker# Reads /sys/kernel/irq/ in order, so algorithm depends on 46*053f45beSAndroid Build Coastguard Worker# irq_{rxq-0} < irq_{rxq-1}, etc. 47*053f45beSAndroid Build Coastguard Workerget_rx_irq_cpus() { 48*053f45beSAndroid Build Coastguard Worker CPUS="" 49*053f45beSAndroid Build Coastguard Worker # sort so that irq 2 is read before irq 10 50*053f45beSAndroid Build Coastguard Worker SORTED_IRQS=$(for i in /sys/kernel/irq/*; do echo $i; done | sort -V) 51*053f45beSAndroid Build Coastguard Worker # Consider only as many queues as RSS actually uses. We assume that 52*053f45beSAndroid Build Coastguard Worker # if RSS_CFG_NUM_RXQS=N, then RSS uses rxqs 0-(N-1). 53*053f45beSAndroid Build Coastguard Worker RSS_CFG_NUM_RXQS=$(get_rss_cfg_num_rxqs) 54*053f45beSAndroid Build Coastguard Worker RXQ_COUNT=0 55*053f45beSAndroid Build Coastguard Worker 56*053f45beSAndroid Build Coastguard Worker for i in ${SORTED_IRQS} 57*053f45beSAndroid Build Coastguard Worker do 58*053f45beSAndroid Build Coastguard Worker [[ "${RXQ_COUNT}" -lt "${RSS_CFG_NUM_RXQS}" ]] || break 59*053f45beSAndroid Build Coastguard Worker # lookup relevant IRQs by action name 60*053f45beSAndroid Build Coastguard Worker [[ -e "$i/actions" ]] || continue 61*053f45beSAndroid Build Coastguard Worker cat "$i/actions" | grep -q "${IRQ_PATTERN}" || continue 62*053f45beSAndroid Build Coastguard Worker irqname=$(<"$i/actions") 63*053f45beSAndroid Build Coastguard Worker 64*053f45beSAndroid Build Coastguard Worker # does the IRQ get called 65*053f45beSAndroid Build Coastguard Worker irqcount=$(cat "$i/per_cpu_count" | tr -d '0,') 66*053f45beSAndroid Build Coastguard Worker [[ -n "${irqcount}" ]] || continue 67*053f45beSAndroid Build Coastguard Worker 68*053f45beSAndroid Build Coastguard Worker # lookup CPU 69*053f45beSAndroid Build Coastguard Worker irq=$(basename "$i") 70*053f45beSAndroid Build Coastguard Worker cpu=$(cat "/proc/irq/$irq/smp_affinity_list") 71*053f45beSAndroid Build Coastguard Worker 72*053f45beSAndroid Build Coastguard Worker if [[ -z "${CPUS}" ]]; then 73*053f45beSAndroid Build Coastguard Worker CPUS="${cpu}" 74*053f45beSAndroid Build Coastguard Worker else 75*053f45beSAndroid Build Coastguard Worker CPUS="${CPUS},${cpu}" 76*053f45beSAndroid Build Coastguard Worker fi 77*053f45beSAndroid Build Coastguard Worker RXQ_COUNT=$((RXQ_COUNT+1)) 78*053f45beSAndroid Build Coastguard Worker done 79*053f45beSAndroid Build Coastguard Worker 80*053f45beSAndroid Build Coastguard Worker echo "${CPUS}" 81*053f45beSAndroid Build Coastguard Worker} 82*053f45beSAndroid Build Coastguard Worker 83*053f45beSAndroid Build Coastguard Workerget_disable_rfs_cmd() { 84*053f45beSAndroid Build Coastguard Worker echo "echo 0 > /proc/sys/net/core/rps_sock_flow_entries;" 85*053f45beSAndroid Build Coastguard Worker} 86*053f45beSAndroid Build Coastguard Worker 87*053f45beSAndroid Build Coastguard Workerget_set_rps_bitmaps_cmd() { 88*053f45beSAndroid Build Coastguard Worker CMD="" 89*053f45beSAndroid Build Coastguard Worker for i in /sys/class/net/${DEV}/queues/rx-*/rps_cpus 90*053f45beSAndroid Build Coastguard Worker do 91*053f45beSAndroid Build Coastguard Worker CMD="${CMD} echo $1 > ${i};" 92*053f45beSAndroid Build Coastguard Worker done 93*053f45beSAndroid Build Coastguard Worker 94*053f45beSAndroid Build Coastguard Worker echo "${CMD}" 95*053f45beSAndroid Build Coastguard Worker} 96*053f45beSAndroid Build Coastguard Worker 97*053f45beSAndroid Build Coastguard Workerget_disable_rps_cmd() { 98*053f45beSAndroid Build Coastguard Worker echo "$(get_set_rps_bitmaps_cmd 0)" 99*053f45beSAndroid Build Coastguard Worker} 100*053f45beSAndroid Build Coastguard Worker 101*053f45beSAndroid Build Coastguard Workerdie() { 102*053f45beSAndroid Build Coastguard Worker echo "$1" 103*053f45beSAndroid Build Coastguard Worker exit 1 104*053f45beSAndroid Build Coastguard Worker} 105*053f45beSAndroid Build Coastguard Worker 106*053f45beSAndroid Build Coastguard Workercheck_nic_rxhash_enabled() { 107*053f45beSAndroid Build Coastguard Worker local -r pattern="receive-hashing:\ on" 108*053f45beSAndroid Build Coastguard Worker 109*053f45beSAndroid Build Coastguard Worker ethtool -k "${DEV}" | grep -q "${pattern}" || die "rxhash must be enabled" 110*053f45beSAndroid Build Coastguard Worker} 111*053f45beSAndroid Build Coastguard Worker 112*053f45beSAndroid Build Coastguard Workerparse_opts() { 113*053f45beSAndroid Build Coastguard Worker local prog=$0 114*053f45beSAndroid Build Coastguard Worker shift 1 115*053f45beSAndroid Build Coastguard Worker 116*053f45beSAndroid Build Coastguard Worker while [[ "$1" =~ "-" ]]; do 117*053f45beSAndroid Build Coastguard Worker if [[ "$1" = "-irq_prefix" ]]; then 118*053f45beSAndroid Build Coastguard Worker shift 119*053f45beSAndroid Build Coastguard Worker IRQ_PATTERN="^$1-[0-9]*$" 120*053f45beSAndroid Build Coastguard Worker elif [[ "$1" = "-u" || "$1" = "-t" ]]; then 121*053f45beSAndroid Build Coastguard Worker PROTO_FLAG="$1" 122*053f45beSAndroid Build Coastguard Worker elif [[ "$1" = "-4" ]]; then 123*053f45beSAndroid Build Coastguard Worker IP_FLAG="$1" 124*053f45beSAndroid Build Coastguard Worker SERVER_IP="${SERVER_IP4}" 125*053f45beSAndroid Build Coastguard Worker CLIENT_IP="${CLIENT_IP4}" 126*053f45beSAndroid Build Coastguard Worker elif [[ "$1" = "-6" ]]; then 127*053f45beSAndroid Build Coastguard Worker IP_FLAG="$1" 128*053f45beSAndroid Build Coastguard Worker SERVER_IP="${SERVER_IP6}" 129*053f45beSAndroid Build Coastguard Worker CLIENT_IP="${CLIENT_IP6}" 130*053f45beSAndroid Build Coastguard Worker elif [[ "$1" = "-rss" ]]; then 131*053f45beSAndroid Build Coastguard Worker TEST_RSS=true 132*053f45beSAndroid Build Coastguard Worker elif [[ "$1" = "-rps" ]]; then 133*053f45beSAndroid Build Coastguard Worker shift 134*053f45beSAndroid Build Coastguard Worker RPS_MAP="$1" 135*053f45beSAndroid Build Coastguard Worker elif [[ "$1" = "-i" ]]; then 136*053f45beSAndroid Build Coastguard Worker shift 137*053f45beSAndroid Build Coastguard Worker DEV="$1" 138*053f45beSAndroid Build Coastguard Worker else 139*053f45beSAndroid Build Coastguard Worker die "Usage: ${prog} (-i <iface>) -u|-t -4|-6 \ 140*053f45beSAndroid Build Coastguard Worker [(-rss -irq_prefix <irq-pattern-prefix>)|(-rps <rps_map>)]" 141*053f45beSAndroid Build Coastguard Worker fi 142*053f45beSAndroid Build Coastguard Worker shift 143*053f45beSAndroid Build Coastguard Worker done 144*053f45beSAndroid Build Coastguard Worker} 145*053f45beSAndroid Build Coastguard Worker 146*053f45beSAndroid Build Coastguard Workersetup() { 147*053f45beSAndroid Build Coastguard Worker setup_loopback_environment "${DEV}" 148*053f45beSAndroid Build Coastguard Worker 149*053f45beSAndroid Build Coastguard Worker # Set up server_ns namespace and client_ns namespace 150*053f45beSAndroid Build Coastguard Worker setup_macvlan_ns "${DEV}" server_ns server \ 151*053f45beSAndroid Build Coastguard Worker "${SERVER_MAC}" "${SERVER_IP}" 152*053f45beSAndroid Build Coastguard Worker setup_macvlan_ns "${DEV}" client_ns client \ 153*053f45beSAndroid Build Coastguard Worker "${CLIENT_MAC}" "${CLIENT_IP}" 154*053f45beSAndroid Build Coastguard Worker} 155*053f45beSAndroid Build Coastguard Worker 156*053f45beSAndroid Build Coastguard Workercleanup() { 157*053f45beSAndroid Build Coastguard Worker cleanup_macvlan_ns server_ns server client_ns client 158*053f45beSAndroid Build Coastguard Worker cleanup_loopback "${DEV}" 159*053f45beSAndroid Build Coastguard Worker} 160*053f45beSAndroid Build Coastguard Worker 161*053f45beSAndroid Build Coastguard Workerparse_opts $0 $@ 162*053f45beSAndroid Build Coastguard Worker 163*053f45beSAndroid Build Coastguard Workersetup 164*053f45beSAndroid Build Coastguard Workertrap cleanup EXIT 165*053f45beSAndroid Build Coastguard Worker 166*053f45beSAndroid Build Coastguard Workercheck_nic_rxhash_enabled 167*053f45beSAndroid Build Coastguard Worker 168*053f45beSAndroid Build Coastguard Worker# Actual test starts here 169*053f45beSAndroid Build Coastguard Workerif [[ "${TEST_RSS}" = true ]]; then 170*053f45beSAndroid Build Coastguard Worker # RPS/RFS must be disabled because they move packets between cpus, 171*053f45beSAndroid Build Coastguard Worker # which breaks the PACKET_FANOUT_CPU identification of RSS decisions. 172*053f45beSAndroid Build Coastguard Worker eval "$(get_disable_rfs_cmd) $(get_disable_rps_cmd)" \ 173*053f45beSAndroid Build Coastguard Worker ip netns exec server_ns ./toeplitz "${IP_FLAG}" "${PROTO_FLAG}" \ 174*053f45beSAndroid Build Coastguard Worker -d "${PORT}" -i "${DEV}" -k "${KEY}" -T 1000 \ 175*053f45beSAndroid Build Coastguard Worker -C "$(get_rx_irq_cpus)" -s -v & 176*053f45beSAndroid Build Coastguard Workerelif [[ ! -z "${RPS_MAP}" ]]; then 177*053f45beSAndroid Build Coastguard Worker eval "$(get_disable_rfs_cmd) $(get_set_rps_bitmaps_cmd ${RPS_MAP})" \ 178*053f45beSAndroid Build Coastguard Worker ip netns exec server_ns ./toeplitz "${IP_FLAG}" "${PROTO_FLAG}" \ 179*053f45beSAndroid Build Coastguard Worker -d "${PORT}" -i "${DEV}" -k "${KEY}" -T 1000 \ 180*053f45beSAndroid Build Coastguard Worker -r "0x${RPS_MAP}" -s -v & 181*053f45beSAndroid Build Coastguard Workerelse 182*053f45beSAndroid Build Coastguard Worker ip netns exec server_ns ./toeplitz "${IP_FLAG}" "${PROTO_FLAG}" \ 183*053f45beSAndroid Build Coastguard Worker -d "${PORT}" -i "${DEV}" -k "${KEY}" -T 1000 -s -v & 184*053f45beSAndroid Build Coastguard Workerfi 185*053f45beSAndroid Build Coastguard Worker 186*053f45beSAndroid Build Coastguard Workerserver_pid=$! 187*053f45beSAndroid Build Coastguard Worker 188*053f45beSAndroid Build Coastguard Workerip netns exec client_ns ./toeplitz_client.sh "${PROTO_FLAG}" \ 189*053f45beSAndroid Build Coastguard Worker "${IP_FLAG}" "${SERVER_IP%%/*}" "${PORT}" & 190*053f45beSAndroid Build Coastguard Worker 191*053f45beSAndroid Build Coastguard Workerclient_pid=$! 192*053f45beSAndroid Build Coastguard Worker 193*053f45beSAndroid Build Coastguard Workerwait "${server_pid}" 194*053f45beSAndroid Build Coastguard Workerexit_code=$? 195*053f45beSAndroid Build Coastguard Workerkill -9 "${client_pid}" 196*053f45beSAndroid Build Coastguard Workerif [[ "${exit_code}" -eq 0 ]]; then 197*053f45beSAndroid Build Coastguard Worker echo "Test Succeeded!" 198*053f45beSAndroid Build Coastguard Workerfi 199*053f45beSAndroid Build Coastguard Workerexit "${exit_code}" 200