xref: /aosp_15_r20/external/linux-kselftest/tools/testing/selftests/net/toeplitz.sh (revision 053f45be4e351dfd5e965df293cd45b779f579ee)
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