1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# Test a "one-armed router" [1] scenario. Packets forwarded between H1 and H2
5# should be forwarded by the ASIC, but also trapped so that ICMP redirect
6# packets could be potentially generated.
7#
8# 1. https://en.wikipedia.org/wiki/One-armed_router
9#
10# +---------------------------------+
11# | H1 (vrf)                        |
12# |    + $h1                        |
13# |    | 192.0.2.1/24               |
14# |    | 2001:db8:1::1/64           |
15# |    |                            |
16# |    |  default via 192.0.2.2     |
17# |    |  default via 2001:db8:1::2 |
18# +----|----------------------------+
19#      |
20# +----|----------------------------------------------------------------------+
21# | SW |                                                                      |
22# | +--|--------------------------------------------------------------------+ |
23# | |  + $swp1                   BR0 (802.1d)                               | |
24# | |                                                                       | |
25# | |                            192.0.2.2/24                               | |
26# | |                          2001:db8:1::2/64                             | |
27# | |                           198.51.100.2/24                             | |
28# | |                          2001:db8:2::2/64                             | |
29# | |                                                                       | |
30# | |  + $swp2                                                              | |
31# | +--|--------------------------------------------------------------------+ |
32# |    |                                                                      |
33# +----|----------------------------------------------------------------------+
34#      |
35# +----|----------------------------+
36# |    |  default via 198.51.100.2  |
37# |    |  default via 2001:db8:2::2 |
38# |    |                            |
39# |    | 2001:db8:2::1/64           |
40# |    | 198.51.100.1/24            |
41# |    + $h2                        |
42# | H2 (vrf)                        |
43# +---------------------------------+
44
45lib_dir=$(dirname $0)/../../../net/forwarding
46
47ALL_TESTS="ping_ipv4 ping_ipv6 fwd_mark_ipv4 fwd_mark_ipv6"
48NUM_NETIFS=4
49source $lib_dir/tc_common.sh
50source $lib_dir/lib.sh
51
52h1_create()
53{
54	simple_if_init $h1 192.0.2.1/24 2001:db8:1::1/64
55
56	ip -4 route add default vrf v$h1 nexthop via 192.0.2.2
57	ip -6 route add default vrf v$h1 nexthop via 2001:db8:1::2
58}
59
60h1_destroy()
61{
62	ip -6 route del default vrf v$h1 nexthop via 2001:db8:1::2
63	ip -4 route del default vrf v$h1 nexthop via 192.0.2.2
64
65	simple_if_fini $h1 192.0.2.1/24 2001:db8:1::1/64
66}
67
68h2_create()
69{
70	simple_if_init $h2 198.51.100.1/24 2001:db8:2::1/64
71
72	ip -4 route add default vrf v$h2 nexthop via 198.51.100.2
73	ip -6 route add default vrf v$h2 nexthop via 2001:db8:2::2
74}
75
76h2_destroy()
77{
78	ip -6 route del default vrf v$h2 nexthop via 2001:db8:2::2
79	ip -4 route del default vrf v$h2 nexthop via 198.51.100.2
80
81	simple_if_fini $h2 198.51.100.1/24 2001:db8:2::1/64
82}
83
84switch_create()
85{
86	ip link add name br0 address $(mac_get $swp1) \
87		type bridge mcast_snooping 0
88	ip link set dev br0 up
89
90	ip link set dev $swp1 master br0
91	ip link set dev $swp1 up
92	ip link set dev $swp2 master br0
93	ip link set dev $swp2 up
94
95	tc qdisc add dev $swp1 clsact
96	tc qdisc add dev $swp2 clsact
97
98	__addr_add_del br0 add 192.0.2.2/24 2001:db8:1::2/64
99	__addr_add_del br0 add 198.51.100.2/24 2001:db8:2::2/64
100}
101
102switch_destroy()
103{
104	__addr_add_del br0 del 198.51.100.2/24 2001:db8:2::2/64
105	__addr_add_del br0 del 192.0.2.2/24 2001:db8:1::2/64
106
107	tc qdisc del dev $swp2 clsact
108	tc qdisc del dev $swp1 clsact
109
110	ip link set dev $swp2 down
111	ip link set dev $swp2 nomaster
112	ip link set dev $swp1 down
113	ip link set dev $swp1 nomaster
114
115	ip link set dev br0 down
116	ip link del dev br0
117}
118
119ping_ipv4()
120{
121	ping_test $h1 198.51.100.1 ": h1->h2"
122}
123
124ping_ipv6()
125{
126	ping6_test $h1 2001:db8:2::1 ": h1->h2"
127}
128
129fwd_mark_ipv4()
130{
131	# Transmit packets from H1 to H2 and make sure they are trapped at
132	# swp1 due to loopback error, but only forwarded by the ASIC through
133	# swp2
134
135	tc filter add dev $swp1 ingress protocol ip pref 1 handle 101 flower \
136		skip_hw dst_ip 198.51.100.1 ip_proto udp dst_port 52768 \
137		action pass
138
139	tc filter add dev $swp2 egress protocol ip pref 1 handle 101 flower \
140		skip_hw dst_ip 198.51.100.1 ip_proto udp dst_port 52768 \
141		action pass
142
143	tc filter add dev $swp2 egress protocol ip pref 2 handle 102 flower \
144		skip_sw dst_ip 198.51.100.1 ip_proto udp dst_port 52768 \
145		action pass
146
147	ip vrf exec v$h1 $MZ $h1 -c 10 -d 100msec -p 64 -A 192.0.2.1 \
148		-B 198.51.100.1 -t udp dp=52768,sp=42768 -q
149
150	RET=0
151
152	tc_check_packets "dev $swp1 ingress" 101 10
153	check_err $?
154
155	log_test "fwd mark: trapping IPv4 packets due to LBERROR"
156
157	RET=0
158
159	tc_check_packets "dev $swp2 egress" 101 0
160	check_err $?
161
162	log_test "fwd mark: forwarding IPv4 packets in software"
163
164	RET=0
165
166	tc_check_packets "dev $swp2 egress" 102 10
167	check_err $?
168
169	log_test "fwd mark: forwarding IPv4 packets in hardware"
170
171	tc filter del dev $swp2 egress protocol ip pref 2 handle 102 flower
172	tc filter del dev $swp2 egress protocol ip pref 1 handle 101 flower
173	tc filter del dev $swp1 ingress protocol ip pref 1 handle 101 flower
174}
175
176fwd_mark_ipv6()
177{
178	tc filter add dev $swp1 ingress protocol ipv6 pref 1 handle 101 flower \
179		skip_hw dst_ip 2001:db8:2::1 ip_proto udp dst_port 52768 \
180		action pass
181
182	tc filter add dev $swp2 egress protocol ipv6 pref 1 handle 101 flower \
183		skip_hw dst_ip 2001:db8:2::1 ip_proto udp dst_port 52768 \
184		action pass
185
186	tc filter add dev $swp2 egress protocol ipv6 pref 2 handle 102 flower \
187		skip_sw dst_ip 2001:db8:2::1 ip_proto udp dst_port 52768 \
188		action pass
189
190	ip vrf exec v$h1 $MZ $h1 -6 -c 10 -d 100msec -p 64 -A 2001:db8:1::1 \
191		-B 2001:db8:2::1 -t udp dp=52768,sp=42768 -q
192
193	RET=0
194
195	tc_check_packets "dev $swp1 ingress" 101 10
196	check_err $?
197
198	log_test "fwd mark: trapping IPv6 packets due to LBERROR"
199
200	RET=0
201
202	tc_check_packets "dev $swp2 egress" 101 0
203	check_err $?
204
205	log_test "fwd mark: forwarding IPv6 packets in software"
206
207	RET=0
208
209	tc_check_packets "dev $swp2 egress" 102 10
210	check_err $?
211
212	log_test "fwd mark: forwarding IPv6 packets in hardware"
213
214	tc filter del dev $swp2 egress protocol ipv6 pref 2 handle 102 flower
215	tc filter del dev $swp2 egress protocol ipv6 pref 1 handle 101 flower
216	tc filter del dev $swp1 ingress protocol ipv6 pref 1 handle 101 flower
217}
218
219setup_prepare()
220{
221	h1=${NETIFS[p1]}
222	swp1=${NETIFS[p2]}
223
224	swp2=${NETIFS[p3]}
225	h2=${NETIFS[p4]}
226
227	vrf_prepare
228	forwarding_enable
229
230	sysctl_set net.ipv4.conf.all.accept_redirects 0
231	sysctl_set net.ipv6.conf.all.accept_redirects 0
232
233	h1_create
234	h2_create
235	switch_create
236}
237
238cleanup()
239{
240	pre_cleanup
241
242	switch_destroy
243	h2_destroy
244	h1_destroy
245
246	sysctl_restore net.ipv6.conf.all.accept_redirects
247	sysctl_restore net.ipv4.conf.all.accept_redirects
248
249	forwarding_restore
250	vrf_cleanup
251}
252
253trap cleanup EXIT
254
255setup_prepare
256setup_wait
257
258tests_run
259
260exit $EXIT_STATUS
261