xref: /linux/tools/testing/selftests/net/amt.sh (revision 0a80e38d0fe1fe7b59c1e93ad908c4148a15926a)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# Author: Taehee Yoo <ap420073@gmail.com>
5#
6# This script evaluates the AMT driver.
7# There are four network-namespaces, LISTENER, SOURCE, GATEWAY, RELAY.
8# The role of LISTENER is to listen multicast traffic.
9# In order to do that, it send IGMP group join message.
10# The role of SOURCE is to send multicast traffic to listener.
11# The role of GATEWAY is to work Gateway role of AMT interface.
12# The role of RELAY is to work Relay role of AMT interface.
13#
14#
15#       +------------------------+
16#       |    LISTENER netns      |
17#       |                        |
18#       |  +------------------+  |
19#       |  |       l_gw       |  |
20#       |  |  192.168.0.2/24  |  |
21#       |  |  2001:db8::2/64  |  |
22#       |  +------------------+  |
23#       |            .           |
24#       +------------------------+
25#                    .
26#                    .
27#       +-----------------------------------------------------+
28#       |            .         GATEWAY netns                  |
29#       |            .                                        |
30#       |+---------------------------------------------------+|
31#       ||           .          br0                          ||
32#       || +------------------+       +------------------+   ||
33#       || |       gw_l       |       |       amtg       |   ||
34#       || |  192.168.0.1/24  |       +--------+---------+   ||
35#       || |  2001:db8::1/64  |                |             ||
36#       || +------------------+                |             ||
37#       |+-------------------------------------|-------------+|
38#       |                                      |              |
39#       |                             +--------+---------+    |
40#       |                             |     gw_relay     |    |
41#       |                             |    10.0.0.1/24   |    |
42#       |                             +------------------+    |
43#       |                                      .              |
44#       +-----------------------------------------------------+
45#                                              .
46#                                              .
47#       +-----------------------------------------------------+
48#       |                       RELAY netns    .              |
49#       |                             +------------------+    |
50#       |                             |     relay_gw     |    |
51#       |                             |    10.0.0.2/24   |    |
52#       |                             +--------+---------+    |
53#       |                                      |              |
54#       |                                      |              |
55#       |  +------------------+       +--------+---------+    |
56#       |  |     relay_src    |       |       amtr       |    |
57#       |  |   172.17.0.1/24  |       +------------------+    |
58#       |  | 2001:db8:3::1/64 |                               |
59#       |  +------------------+                               |
60#       |            .                                        |
61#       |            .                                        |
62#       +-----------------------------------------------------+
63#                    .
64#                    .
65#       +------------------------+
66#       |            .           |
67#       |  +------------------+  |
68#       |  |     src_relay    |  |
69#       |  |   172.17.0.2/24  |  |
70#       |  | 2001:db8:3::2/64 |  |
71#       |  +------------------+  |
72#       |      SOURCE netns      |
73#       +------------------------+
74#==============================================================================
75
76source lib.sh
77
78readonly LISTENER=$(mktemp -u listener-XXXXXXXX)
79readonly GATEWAY=$(mktemp -u gateway-XXXXXXXX)
80readonly RELAY=$(mktemp -u relay-XXXXXXXX)
81readonly SOURCE=$(mktemp -u source-XXXXXXXX)
82readonly SMCROUTEDIR="$(mktemp -d)"
83ERR=4
84err=0
85
86exit_cleanup()
87{
88	for ns in "$@"; do
89		ip netns delete "${ns}" 2>/dev/null || true
90	done
91	if [ -f "$SMCROUTEDIR/amt.pid" ]; then
92		smcpid=$(< $SMCROUTEDIR/amt.pid)
93		kill $smcpid
94	fi
95	rm -rf $SMCROUTEDIR
96
97	exit $ERR
98}
99
100create_namespaces()
101{
102	ip netns add "${LISTENER}" || exit_cleanup
103	ip netns add "${GATEWAY}" || exit_cleanup "${LISTENER}"
104	ip netns add "${RELAY}" || exit_cleanup "${LISTENER}" "${GATEWAY}"
105	ip netns add "${SOURCE}" || exit_cleanup "${LISTENER}" "${GATEWAY}" \
106		"${RELAY}"
107}
108
109# The trap function handler
110#
111exit_cleanup_all()
112{
113	exit_cleanup "${LISTENER}" "${GATEWAY}" "${RELAY}" "${SOURCE}"
114}
115
116setup_interface()
117{
118	for ns in "${LISTENER}" "${GATEWAY}" "${RELAY}" "${SOURCE}"; do
119		ip -netns "${ns}" link set dev lo up
120	done;
121
122	ip link add l_gw type veth peer name gw_l
123	ip link add gw_relay type veth peer name relay_gw
124	ip link add relay_src type veth peer name src_relay
125
126	ip link set l_gw netns "${LISTENER}" up
127	ip link set gw_l netns "${GATEWAY}" up
128	ip link set gw_relay netns "${GATEWAY}" up
129	ip link set relay_gw netns "${RELAY}" up
130	ip link set relay_src netns "${RELAY}" up
131	ip link set src_relay netns "${SOURCE}" up mtu 1400
132
133	ip netns exec "${LISTENER}" ip a a 192.168.0.2/24 dev l_gw
134	ip netns exec "${LISTENER}" ip r a default via 192.168.0.1 dev l_gw
135	ip netns exec "${LISTENER}" ip a a 2001:db8::2/64 dev l_gw
136	ip netns exec "${LISTENER}" ip r a default via 2001:db8::1 dev l_gw
137	ip netns exec "${LISTENER}" ip a a 239.0.0.1/32 dev l_gw autojoin
138	ip netns exec "${LISTENER}" ip a a ff0e::5:6/128 dev l_gw autojoin
139
140	ip netns exec "${GATEWAY}" ip a a 192.168.0.1/24 dev gw_l
141	ip netns exec "${GATEWAY}" ip a a 2001:db8::1/64 dev gw_l
142	ip netns exec "${GATEWAY}" ip a a 10.0.0.1/24 dev gw_relay
143	ip netns exec "${GATEWAY}" ip link add br0 type bridge
144	ip netns exec "${GATEWAY}" ip link set br0 up
145	ip netns exec "${GATEWAY}" ip link set gw_l master br0
146	ip netns exec "${GATEWAY}" ip link set gw_l up
147	ip netns exec "${GATEWAY}" ip link add amtg master br0 type amt \
148		mode gateway local 10.0.0.1 discovery 10.0.0.2 dev gw_relay \
149		gateway_port 2268 relay_port 2268
150	ip netns exec "${RELAY}" ip a a 10.0.0.2/24 dev relay_gw
151	ip netns exec "${RELAY}" ip link add amtr type amt mode relay \
152		local 10.0.0.2 dev relay_gw relay_port 2268 max_tunnels 4
153	ip netns exec "${RELAY}" ip a a 172.17.0.1/24 dev relay_src
154	ip netns exec "${RELAY}" ip a a 2001:db8:3::1/64 dev relay_src
155	ip netns exec "${SOURCE}" ip a a 172.17.0.2/24 dev src_relay
156	ip netns exec "${SOURCE}" ip a a 2001:db8:3::2/64 dev src_relay
157	ip netns exec "${SOURCE}" ip r a default via 172.17.0.1 dev src_relay
158	ip netns exec "${SOURCE}" ip r a default via 2001:db8:3::1 dev src_relay
159	ip netns exec "${RELAY}" ip link set amtr up
160	ip netns exec "${GATEWAY}" ip link set amtg up
161}
162
163setup_sysctl()
164{
165	ip netns exec "${RELAY}" sysctl net.ipv4.ip_forward=1 -w -q
166}
167
168setup_iptables()
169{
170	ip netns exec "${RELAY}" iptables -t mangle -I PREROUTING \
171		-d 239.0.0.1 -j TTL --ttl-set 2
172	ip netns exec "${RELAY}" ip6tables -t mangle -I PREROUTING \
173		-j HL --hl-set 2
174}
175
176setup_mcast_routing()
177{
178	ip netns exec "${RELAY}" smcrouted -P $SMCROUTEDIR/amt.pid
179	ip netns exec "${RELAY}" smcroutectl a relay_src \
180		172.17.0.2 239.0.0.1 amtr
181	ip netns exec "${RELAY}" smcroutectl a relay_src \
182		2001:db8:3::2 ff0e::5:6 amtr
183}
184
185test_remote_ip()
186{
187	REMOTE=$(ip netns exec "${GATEWAY}" \
188		ip -d -j link show amtg | jq .[0].linkinfo.info_data.remote)
189	if [ $REMOTE == "\"10.0.0.2\"" ]; then
190		printf "TEST: %-60s  [ OK ]\n" "amt discovery"
191	else
192		printf "TEST: %-60s  [FAIL]\n" "amt discovery"
193		ERR=1
194	fi
195}
196
197send_mcast_torture4()
198{
199	for i in `seq 10`; do
200		ip netns exec "${SOURCE}" bash -c \
201		   'cat /dev/urandom | head -c 100M | nc -w 1 -u 239.0.0.1 4001'
202		echo -n "."
203	done
204}
205
206
207send_mcast_torture6()
208{
209	for i in `seq 10`; do
210		ip netns exec "${SOURCE}" bash -c \
211		   'cat /dev/urandom | head -c 100M | nc -w 1 -u ff0e::5:6 6001'
212		echo -n "."
213	done
214}
215
216check_features()
217{
218        ip link help 2>&1 | grep -q amt
219        if [ $? -ne 0 ]; then
220                echo "Missing amt support in iproute2" >&2
221                exit_cleanup
222        fi
223}
224
225test_ipv4_forward()
226{
227	RESULT4=$(ip netns exec "${LISTENER}" timeout 15 socat - UDP4-LISTEN:4000,readbytes=128 || true)
228	if echo "$RESULT4" | grep -q "172.17.0.2"; then
229		printf "TEST: %-60s  [ OK ]\n" "IPv4 amt multicast forwarding"
230		exit 0
231	else
232		printf "TEST: %-60s  [FAIL]\n" "IPv4 amt multicast forwarding"
233		exit 1
234	fi
235}
236
237test_ipv6_forward()
238{
239	RESULT6=$(ip netns exec "${LISTENER}" timeout 15 socat - UDP6-LISTEN:6000,readbytes=128 || true)
240	if echo "$RESULT6" | grep -q "2001:db8:3::2"; then
241		printf "TEST: %-60s  [ OK ]\n" "IPv6 amt multicast forwarding"
242		exit 0
243	else
244		printf "TEST: %-60s  [FAIL]\n" "IPv6 amt multicast forwarding"
245		exit 1
246	fi
247}
248
249send_mcast4()
250{
251	sleep 5
252	wait_local_port_listen ${LISTENER} 4000 udp
253	ip netns exec "${SOURCE}" bash -c \
254		'printf "%s %128s" 172.17.0.2 | nc -w 1 -u 239.0.0.1 4000' &
255}
256
257send_mcast6()
258{
259	wait_local_port_listen ${LISTENER} 6000 udp
260	ip netns exec "${SOURCE}" bash -c \
261		'printf "%s %128s" 2001:db8:3::2 | nc -w 1 -u ff0e::5:6 6000' &
262}
263
264check_features
265
266create_namespaces
267
268set -e
269trap exit_cleanup_all EXIT
270
271setup_interface
272setup_sysctl
273setup_iptables
274setup_mcast_routing
275test_remote_ip
276test_ipv4_forward &
277pid=$!
278send_mcast4
279wait $pid || err=$?
280if [ $err -eq 1 ]; then
281	ERR=1
282fi
283test_ipv6_forward &
284pid=$!
285send_mcast6
286wait $pid || err=$?
287if [ $err -eq 1 ]; then
288	ERR=1
289fi
290printf "TEST: %-50s" "IPv4 amt traffic forwarding torture"
291send_mcast_torture4
292printf "  [ OK ]\n"
293printf "TEST: %-50s" "IPv6 amt traffic forwarding torture"
294send_mcast_torture6
295printf "  [ OK ]\n"
296sleep 5
297if [ "${ERR}" -eq 1 ]; then
298        echo "Some tests failed." >&2
299else
300        ERR=0
301fi
302