1d2329247SHangbin Liu#!/bin/bash
2d2329247SHangbin Liu# SPDX-License-Identifier: GPL-2.0
3d2329247SHangbin Liu#
4d2329247SHangbin Liu# Test topology:
58955c1a3SHangbin Liu#    - - - - - - - - - - - - - - - - - - -
68955c1a3SHangbin Liu#    | veth1         veth2         veth3 |  ns0
7d2329247SHangbin Liu#     - -| - - - - - - | - - - - - - | - -
8d2329247SHangbin Liu#    ---------     ---------     ---------
98955c1a3SHangbin Liu#    | veth0 |     | veth0 |     | veth0 |
10d2329247SHangbin Liu#    ---------     ---------     ---------
11d2329247SHangbin Liu#       ns1           ns2           ns3
12d2329247SHangbin Liu#
13d2329247SHangbin Liu# Test modules:
14d2329247SHangbin Liu# XDP modes: generic, native, native + egress_prog
15d2329247SHangbin Liu#
16d2329247SHangbin Liu# Test cases:
17d2329247SHangbin Liu#   ARP: Testing BPF_F_BROADCAST, the ingress interface also should receive
18d2329247SHangbin Liu#   the redirects.
19d2329247SHangbin Liu#      ns1 -> gw: ns1, ns2, ns3, should receive the arp request
20d2329247SHangbin Liu#   IPv4: Testing BPF_F_BROADCAST | BPF_F_EXCLUDE_INGRESS, the ingress
21d2329247SHangbin Liu#   interface should not receive the redirects.
22d2329247SHangbin Liu#      ns1 -> gw: ns1 should not receive, ns2, ns3 should receive redirects.
23d2329247SHangbin Liu#   IPv6: Testing none flag, all the pkts should be redirected back
24d2329247SHangbin Liu#      ping test: ns1 -> ns2 (block), echo requests will be redirect back
25d2329247SHangbin Liu#   egress_prog:
26d2329247SHangbin Liu#      all src mac should be egress interface's mac
27d2329247SHangbin Liu
28d2329247SHangbin Liu# netns numbers
29d2329247SHangbin LiuNUM=3
30d2329247SHangbin LiuIFACES=""
31d2329247SHangbin LiuDRV_MODE="xdpgeneric xdpdrv xdpegress"
32d2329247SHangbin LiuPASS=0
33d2329247SHangbin LiuFAIL=0
348b4ac13aSHangbin LiuLOG_DIR=$(mktemp -d)
35cec74489SHangbin Liudeclare -a NS
36cec74489SHangbin LiuNS[0]="ns0-$(mktemp -u XXXXXX)"
37cec74489SHangbin LiuNS[1]="ns1-$(mktemp -u XXXXXX)"
38cec74489SHangbin LiuNS[2]="ns2-$(mktemp -u XXXXXX)"
39cec74489SHangbin LiuNS[3]="ns3-$(mktemp -u XXXXXX)"
40d2329247SHangbin Liu
41d2329247SHangbin Liutest_pass()
42d2329247SHangbin Liu{
43d2329247SHangbin Liu	echo "Pass: $@"
44d2329247SHangbin Liu	PASS=$((PASS + 1))
45d2329247SHangbin Liu}
46d2329247SHangbin Liu
47d2329247SHangbin Liutest_fail()
48d2329247SHangbin Liu{
49d2329247SHangbin Liu	echo "fail: $@"
50d2329247SHangbin Liu	FAIL=$((FAIL + 1))
51d2329247SHangbin Liu}
52d2329247SHangbin Liu
53d2329247SHangbin Liuclean_up()
54d2329247SHangbin Liu{
55cec74489SHangbin Liu	for i in $(seq 0 $NUM); do
56cec74489SHangbin Liu		ip netns del ${NS[$i]} 2> /dev/null
57d2329247SHangbin Liu	done
58d2329247SHangbin Liu}
59d2329247SHangbin Liu
60d2329247SHangbin Liu# Kselftest framework requirement - SKIP code is 4.
61d2329247SHangbin Liucheck_env()
62d2329247SHangbin Liu{
63d2329247SHangbin Liu	ip link set dev lo xdpgeneric off &>/dev/null
64d2329247SHangbin Liu	if [ $? -ne 0 ];then
65d2329247SHangbin Liu		echo "selftests: [SKIP] Could not run test without the ip xdpgeneric support"
66d2329247SHangbin Liu		exit 4
67d2329247SHangbin Liu	fi
68d2329247SHangbin Liu
69d2329247SHangbin Liu	which tcpdump &>/dev/null
70d2329247SHangbin Liu	if [ $? -ne 0 ];then
71d2329247SHangbin Liu		echo "selftests: [SKIP] Could not run test without tcpdump"
72d2329247SHangbin Liu		exit 4
73d2329247SHangbin Liu	fi
74d2329247SHangbin Liu}
75d2329247SHangbin Liu
76d2329247SHangbin Liusetup_ns()
77d2329247SHangbin Liu{
78d2329247SHangbin Liu	local mode=$1
79d2329247SHangbin Liu	IFACES=""
80d2329247SHangbin Liu
81d2329247SHangbin Liu	if [ "$mode" = "xdpegress" ]; then
82d2329247SHangbin Liu		mode="xdpdrv"
83d2329247SHangbin Liu	fi
84d2329247SHangbin Liu
85cec74489SHangbin Liu	ip netns add ${NS[0]}
86d2329247SHangbin Liu	for i in $(seq $NUM); do
87cec74489SHangbin Liu	        ip netns add ${NS[$i]}
88cec74489SHangbin Liu		ip -n ${NS[$i]} link add veth0 type veth peer name veth$i netns ${NS[0]}
89cec74489SHangbin Liu		ip -n ${NS[$i]} link set veth0 up
90cec74489SHangbin Liu		ip -n ${NS[0]} link set veth$i up
91d2329247SHangbin Liu
92cec74489SHangbin Liu		ip -n ${NS[$i]} addr add 192.0.2.$i/24 dev veth0
93cec74489SHangbin Liu		ip -n ${NS[$i]} addr add 2001:db8::$i/64 dev veth0
94d2329247SHangbin Liu		# Add a neigh entry for IPv4 ping test
95cec74489SHangbin Liu		ip -n ${NS[$i]} neigh add 192.0.2.253 lladdr 00:00:00:00:00:01 dev veth0
96cec74489SHangbin Liu		ip -n ${NS[$i]} link set veth0 $mode obj \
97*afef88e6SDaniel Müller			xdp_dummy.bpf.o sec xdp &> /dev/null || \
98d2329247SHangbin Liu			{ test_fail "Unable to load dummy xdp" && exit 1; }
99d2329247SHangbin Liu		IFACES="$IFACES veth$i"
100cec74489SHangbin Liu		veth_mac[$i]=$(ip -n ${NS[0]} link show veth$i | awk '/link\/ether/ {print $2}')
101d2329247SHangbin Liu	done
102d2329247SHangbin Liu}
103d2329247SHangbin Liu
104d2329247SHangbin Liudo_egress_tests()
105d2329247SHangbin Liu{
106d2329247SHangbin Liu	local mode=$1
107d2329247SHangbin Liu
108d2329247SHangbin Liu	# mac test
109cec74489SHangbin Liu	ip netns exec ${NS[2]} tcpdump -e -i veth0 -nn -l -e &> ${LOG_DIR}/mac_ns1-2_${mode}.log &
110cec74489SHangbin Liu	ip netns exec ${NS[3]} tcpdump -e -i veth0 -nn -l -e &> ${LOG_DIR}/mac_ns1-3_${mode}.log &
111d2329247SHangbin Liu	sleep 0.5
112cec74489SHangbin Liu	ip netns exec ${NS[1]} ping 192.0.2.254 -i 0.1 -c 4 &> /dev/null
113d2329247SHangbin Liu	sleep 0.5
114648c3677SHangbin Liu	pkill tcpdump
115d2329247SHangbin Liu
116d2329247SHangbin Liu	# mac check
1178b4ac13aSHangbin Liu	grep -q "${veth_mac[2]} > ff:ff:ff:ff:ff:ff" ${LOG_DIR}/mac_ns1-2_${mode}.log && \
118d2329247SHangbin Liu	       test_pass "$mode mac ns1-2" || test_fail "$mode mac ns1-2"
1198b4ac13aSHangbin Liu	grep -q "${veth_mac[3]} > ff:ff:ff:ff:ff:ff" ${LOG_DIR}/mac_ns1-3_${mode}.log && \
120d2329247SHangbin Liu		test_pass "$mode mac ns1-3" || test_fail "$mode mac ns1-3"
121d2329247SHangbin Liu}
122d2329247SHangbin Liu
123d2329247SHangbin Liudo_ping_tests()
124d2329247SHangbin Liu{
125d2329247SHangbin Liu	local mode=$1
126d2329247SHangbin Liu
127d2329247SHangbin Liu	# ping6 test: echo request should be redirect back to itself, not others
128cec74489SHangbin Liu	ip netns exec ${NS[1]} ip neigh add 2001:db8::2 dev veth0 lladdr 00:00:00:00:00:02
129d2329247SHangbin Liu
130cec74489SHangbin Liu	ip netns exec ${NS[1]} tcpdump -i veth0 -nn -l -e &> ${LOG_DIR}/ns1-1_${mode}.log &
131cec74489SHangbin Liu	ip netns exec ${NS[2]} tcpdump -i veth0 -nn -l -e &> ${LOG_DIR}/ns1-2_${mode}.log &
132cec74489SHangbin Liu	ip netns exec ${NS[3]} tcpdump -i veth0 -nn -l -e &> ${LOG_DIR}/ns1-3_${mode}.log &
133d2329247SHangbin Liu	sleep 0.5
134d2329247SHangbin Liu	# ARP test
135cec74489SHangbin Liu	ip netns exec ${NS[1]} arping -q -c 2 -I veth0 192.0.2.254
136d2329247SHangbin Liu	# IPv4 test
137cec74489SHangbin Liu	ip netns exec ${NS[1]} ping 192.0.2.253 -i 0.1 -c 4 &> /dev/null
138d2329247SHangbin Liu	# IPv6 test
139cec74489SHangbin Liu	ip netns exec ${NS[1]} ping6 2001:db8::2 -i 0.1 -c 2 &> /dev/null
140d2329247SHangbin Liu	sleep 0.5
141648c3677SHangbin Liu	pkill tcpdump
142d2329247SHangbin Liu
143d2329247SHangbin Liu	# All netns should receive the redirect arp requests
144f53ea9dbSHangbin Liu	[ $(grep -cF "who-has 192.0.2.254" ${LOG_DIR}/ns1-1_${mode}.log) -eq 4 ] && \
145d2329247SHangbin Liu		test_pass "$mode arp(F_BROADCAST) ns1-1" || \
146d2329247SHangbin Liu		test_fail "$mode arp(F_BROADCAST) ns1-1"
147f53ea9dbSHangbin Liu	[ $(grep -cF "who-has 192.0.2.254" ${LOG_DIR}/ns1-2_${mode}.log) -eq 2 ] && \
148d2329247SHangbin Liu		test_pass "$mode arp(F_BROADCAST) ns1-2" || \
149d2329247SHangbin Liu		test_fail "$mode arp(F_BROADCAST) ns1-2"
150f53ea9dbSHangbin Liu	[ $(grep -cF "who-has 192.0.2.254" ${LOG_DIR}/ns1-3_${mode}.log) -eq 2 ] && \
151d2329247SHangbin Liu		test_pass "$mode arp(F_BROADCAST) ns1-3" || \
152d2329247SHangbin Liu		test_fail "$mode arp(F_BROADCAST) ns1-3"
153d2329247SHangbin Liu
154d2329247SHangbin Liu	# ns1 should not receive the redirect echo request, others should
1558b4ac13aSHangbin Liu	[ $(grep -c "ICMP echo request" ${LOG_DIR}/ns1-1_${mode}.log) -eq 4 ] && \
156d2329247SHangbin Liu		test_pass "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-1" || \
157d2329247SHangbin Liu		test_fail "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-1"
1588b4ac13aSHangbin Liu	[ $(grep -c "ICMP echo request" ${LOG_DIR}/ns1-2_${mode}.log) -eq 4 ] && \
159d2329247SHangbin Liu		test_pass "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-2" || \
160d2329247SHangbin Liu		test_fail "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-2"
1618b4ac13aSHangbin Liu	[ $(grep -c "ICMP echo request" ${LOG_DIR}/ns1-3_${mode}.log) -eq 4 ] && \
162d2329247SHangbin Liu		test_pass "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-3" || \
163d2329247SHangbin Liu		test_fail "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-3"
164d2329247SHangbin Liu
165d2329247SHangbin Liu	# ns1 should receive the echo request, ns2 should not
1668b4ac13aSHangbin Liu	[ $(grep -c "ICMP6, echo request" ${LOG_DIR}/ns1-1_${mode}.log) -eq 4 ] && \
167d2329247SHangbin Liu		test_pass "$mode IPv6 (no flags) ns1-1" || \
168d2329247SHangbin Liu		test_fail "$mode IPv6 (no flags) ns1-1"
1698b4ac13aSHangbin Liu	[ $(grep -c "ICMP6, echo request" ${LOG_DIR}/ns1-2_${mode}.log) -eq 0 ] && \
170d2329247SHangbin Liu		test_pass "$mode IPv6 (no flags) ns1-2" || \
171d2329247SHangbin Liu		test_fail "$mode IPv6 (no flags) ns1-2"
172d2329247SHangbin Liu}
173d2329247SHangbin Liu
174d2329247SHangbin Liudo_tests()
175d2329247SHangbin Liu{
176d2329247SHangbin Liu	local mode=$1
177d2329247SHangbin Liu	local drv_p
178d2329247SHangbin Liu
179d2329247SHangbin Liu	case ${mode} in
180d2329247SHangbin Liu		xdpdrv)  drv_p="-N";;
181d2329247SHangbin Liu		xdpegress) drv_p="-X";;
182d2329247SHangbin Liu		xdpgeneric) drv_p="-S";;
183d2329247SHangbin Liu	esac
184d2329247SHangbin Liu
185cec74489SHangbin Liu	ip netns exec ${NS[0]} ./xdp_redirect_multi $drv_p $IFACES &> ${LOG_DIR}/xdp_redirect_${mode}.log &
186d2329247SHangbin Liu	xdp_pid=$!
187d2329247SHangbin Liu	sleep 1
1888955c1a3SHangbin Liu	if ! ps -p $xdp_pid > /dev/null; then
1898955c1a3SHangbin Liu		test_fail "$mode xdp_redirect_multi start failed"
1908955c1a3SHangbin Liu		return 1
1918955c1a3SHangbin Liu	fi
192d2329247SHangbin Liu
193d2329247SHangbin Liu	if [ "$mode" = "xdpegress" ]; then
194d2329247SHangbin Liu		do_egress_tests $mode
195d2329247SHangbin Liu	else
196d2329247SHangbin Liu		do_ping_tests $mode
197d2329247SHangbin Liu	fi
198d2329247SHangbin Liu
199d2329247SHangbin Liu	kill $xdp_pid
200d2329247SHangbin Liu}
201d2329247SHangbin Liu
202d2329247SHangbin Liucheck_env
203d2329247SHangbin Liu
204cec74489SHangbin Liutrap clean_up EXIT
205cec74489SHangbin Liu
206d2329247SHangbin Liufor mode in ${DRV_MODE}; do
207d2329247SHangbin Liu	setup_ns $mode
208d2329247SHangbin Liu	do_tests $mode
209d2329247SHangbin Liu	clean_up
210d2329247SHangbin Liudone
2118b4ac13aSHangbin Liurm -rf ${LOG_DIR}
212d2329247SHangbin Liu
213d2329247SHangbin Liuecho "Summary: PASS $PASS, FAIL $FAIL"
214d2329247SHangbin Liu[ $FAIL -eq 0 ] && exit 0 || exit 1
215