xref: /OK3568_Linux_fs/kernel/tools/testing/selftests/bpf/test_tc_edt.sh (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/bin/bash
2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0
3*4882a593Smuzhiyun#
4*4882a593Smuzhiyun# This test installs a TC bpf program that throttles a TCP flow
5*4882a593Smuzhiyun# with dst port = 9000 down to 5MBps. Then it measures actual
6*4882a593Smuzhiyun# throughput of the flow.
7*4882a593Smuzhiyun
8*4882a593Smuzhiyunif [[ $EUID -ne 0 ]]; then
9*4882a593Smuzhiyun	echo "This script must be run as root"
10*4882a593Smuzhiyun	echo "FAIL"
11*4882a593Smuzhiyun	exit 1
12*4882a593Smuzhiyunfi
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun# check that nc, dd, and timeout are present
15*4882a593Smuzhiyuncommand -v nc >/dev/null 2>&1 || \
16*4882a593Smuzhiyun	{ echo >&2 "nc is not available"; exit 1; }
17*4882a593Smuzhiyuncommand -v dd >/dev/null 2>&1 || \
18*4882a593Smuzhiyun	{ echo >&2 "nc is not available"; exit 1; }
19*4882a593Smuzhiyuncommand -v timeout >/dev/null 2>&1 || \
20*4882a593Smuzhiyun	{ echo >&2 "timeout is not available"; exit 1; }
21*4882a593Smuzhiyun
22*4882a593Smuzhiyunreadonly NS_SRC="ns-src-$(mktemp -u XXXXXX)"
23*4882a593Smuzhiyunreadonly NS_DST="ns-dst-$(mktemp -u XXXXXX)"
24*4882a593Smuzhiyun
25*4882a593Smuzhiyunreadonly IP_SRC="172.16.1.100"
26*4882a593Smuzhiyunreadonly IP_DST="172.16.2.100"
27*4882a593Smuzhiyun
28*4882a593Smuzhiyuncleanup()
29*4882a593Smuzhiyun{
30*4882a593Smuzhiyun	ip netns del ${NS_SRC}
31*4882a593Smuzhiyun	ip netns del ${NS_DST}
32*4882a593Smuzhiyun}
33*4882a593Smuzhiyun
34*4882a593Smuzhiyuntrap cleanup EXIT
35*4882a593Smuzhiyun
36*4882a593Smuzhiyunset -e  # exit on error
37*4882a593Smuzhiyun
38*4882a593Smuzhiyunip netns add "${NS_SRC}"
39*4882a593Smuzhiyunip netns add "${NS_DST}"
40*4882a593Smuzhiyunip link add veth_src type veth peer name veth_dst
41*4882a593Smuzhiyunip link set veth_src netns ${NS_SRC}
42*4882a593Smuzhiyunip link set veth_dst netns ${NS_DST}
43*4882a593Smuzhiyun
44*4882a593Smuzhiyunip -netns ${NS_SRC} addr add ${IP_SRC}/24  dev veth_src
45*4882a593Smuzhiyunip -netns ${NS_DST} addr add ${IP_DST}/24  dev veth_dst
46*4882a593Smuzhiyun
47*4882a593Smuzhiyunip -netns ${NS_SRC} link set dev veth_src up
48*4882a593Smuzhiyunip -netns ${NS_DST} link set dev veth_dst up
49*4882a593Smuzhiyun
50*4882a593Smuzhiyunip -netns ${NS_SRC} route add ${IP_DST}/32  dev veth_src
51*4882a593Smuzhiyunip -netns ${NS_DST} route add ${IP_SRC}/32  dev veth_dst
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun# set up TC on TX
54*4882a593Smuzhiyunip netns exec ${NS_SRC} tc qdisc add dev veth_src root fq
55*4882a593Smuzhiyunip netns exec ${NS_SRC} tc qdisc add dev veth_src clsact
56*4882a593Smuzhiyunip netns exec ${NS_SRC} tc filter add dev veth_src egress \
57*4882a593Smuzhiyun	bpf da obj test_tc_edt.o sec cls_test
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun# start the listener
61*4882a593Smuzhiyunip netns exec ${NS_DST} bash -c \
62*4882a593Smuzhiyun	"nc -4 -l -p 9000 >/dev/null &"
63*4882a593Smuzhiyundeclare -i NC_PID=$!
64*4882a593Smuzhiyunsleep 1
65*4882a593Smuzhiyun
66*4882a593Smuzhiyundeclare -ir TIMEOUT=20
67*4882a593Smuzhiyundeclare -ir EXPECTED_BPS=5000000
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun# run the load, capture RX bytes on DST
70*4882a593Smuzhiyundeclare -ir RX_BYTES_START=$( ip netns exec ${NS_DST} \
71*4882a593Smuzhiyun	cat /sys/class/net/veth_dst/statistics/rx_bytes )
72*4882a593Smuzhiyun
73*4882a593Smuzhiyunset +e
74*4882a593Smuzhiyunip netns exec ${NS_SRC} bash -c "timeout ${TIMEOUT} dd if=/dev/zero \
75*4882a593Smuzhiyun	bs=1000 count=1000000 > /dev/tcp/${IP_DST}/9000 2>/dev/null"
76*4882a593Smuzhiyunset -e
77*4882a593Smuzhiyun
78*4882a593Smuzhiyundeclare -ir RX_BYTES_END=$( ip netns exec ${NS_DST} \
79*4882a593Smuzhiyun	cat /sys/class/net/veth_dst/statistics/rx_bytes )
80*4882a593Smuzhiyun
81*4882a593Smuzhiyundeclare -ir ACTUAL_BPS=$(( ($RX_BYTES_END - $RX_BYTES_START) / $TIMEOUT ))
82*4882a593Smuzhiyun
83*4882a593Smuzhiyunecho $TIMEOUT $ACTUAL_BPS $EXPECTED_BPS | \
84*4882a593Smuzhiyun	awk '{printf "elapsed: %d sec; bps difference: %.2f%%\n",
85*4882a593Smuzhiyun		$1, ($2-$3)*100.0/$3}'
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun# Pass the test if the actual bps is within 1% of the expected bps.
88*4882a593Smuzhiyun# The difference is usually about 0.1% on a 20-sec test, and ==> zero
89*4882a593Smuzhiyun# the longer the test runs.
90*4882a593Smuzhiyundeclare -ir RES=$( echo $ACTUAL_BPS $EXPECTED_BPS | \
91*4882a593Smuzhiyun	 awk 'function abs(x){return ((x < 0.0) ? -x : x)}
92*4882a593Smuzhiyun	      {if (abs(($1-$2)*100.0/$2) > 1.0) { print "1" }
93*4882a593Smuzhiyun		else { print "0"} }' )
94*4882a593Smuzhiyunif [ "${RES}" == "0" ] ; then
95*4882a593Smuzhiyun	echo "PASS"
96*4882a593Smuzhiyunelse
97*4882a593Smuzhiyun	echo "FAIL"
98*4882a593Smuzhiyun	exit 1
99*4882a593Smuzhiyunfi
100