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 type bridge mcast_snooping 0
87	ip link set dev br0 up
88
89	ip link set dev $swp1 master br0
90	ip link set dev $swp1 up
91	ip link set dev $swp2 master br0
92	ip link set dev $swp2 up
93
94	tc qdisc add dev $swp1 clsact
95	tc qdisc add dev $swp2 clsact
96
97	__addr_add_del br0 add 192.0.2.2/24 2001:db8:1::2/64
98	__addr_add_del br0 add 198.51.100.2/24 2001:db8:2::2/64
99}
100
101switch_destroy()
102{
103	__addr_add_del br0 del 198.51.100.2/24 2001:db8:2::2/64
104	__addr_add_del br0 del 192.0.2.2/24 2001:db8:1::2/64
105
106	tc qdisc del dev $swp2 clsact
107	tc qdisc del dev $swp1 clsact
108
109	ip link set dev $swp2 down
110	ip link set dev $swp2 nomaster
111	ip link set dev $swp1 down
112	ip link set dev $swp1 nomaster
113
114	ip link set dev br0 down
115	ip link del dev br0
116}
117
118ping_ipv4()
119{
120	ping_test $h1 198.51.100.1 ": h1->h2"
121}
122
123ping_ipv6()
124{
125	ping6_test $h1 2001:db8:2::1 ": h1->h2"
126}
127
128fwd_mark_ipv4()
129{
130	# Transmit packets from H1 to H2 and make sure they are trapped at
131	# swp1 due to loopback error, but only forwarded by the ASIC through
132	# swp2
133
134	tc filter add dev $swp1 ingress protocol ip pref 1 handle 101 flower \
135		skip_hw dst_ip 198.51.100.1 ip_proto udp dst_port 52768 \
136		action pass
137
138	tc filter add dev $swp2 egress protocol ip pref 1 handle 101 flower \
139		skip_hw dst_ip 198.51.100.1 ip_proto udp dst_port 52768 \
140		action pass
141
142	tc filter add dev $swp2 egress protocol ip pref 2 handle 102 flower \
143		skip_sw dst_ip 198.51.100.1 ip_proto udp dst_port 52768 \
144		action pass
145
146	ip vrf exec v$h1 $MZ $h1 -c 10 -d 100msec -p 64 -A 192.0.2.1 \
147		-B 198.51.100.1 -t udp dp=52768,sp=42768 -q
148
149	RET=0
150
151	tc_check_packets "dev $swp1 ingress" 101 10
152	check_err $?
153
154	log_test "fwd mark: trapping IPv4 packets due to LBERROR"
155
156	RET=0
157
158	tc_check_packets "dev $swp2 egress" 101 0
159	check_err $?
160
161	log_test "fwd mark: forwarding IPv4 packets in software"
162
163	RET=0
164
165	tc_check_packets "dev $swp2 egress" 102 10
166	check_err $?
167
168	log_test "fwd mark: forwarding IPv4 packets in hardware"
169
170	tc filter del dev $swp2 egress protocol ip pref 2 handle 102 flower
171	tc filter del dev $swp2 egress protocol ip pref 1 handle 101 flower
172	tc filter del dev $swp1 ingress protocol ip pref 1 handle 101 flower
173}
174
175fwd_mark_ipv6()
176{
177	tc filter add dev $swp1 ingress protocol ipv6 pref 1 handle 101 flower \
178		skip_hw dst_ip 2001:db8:2::1 ip_proto udp dst_port 52768 \
179		action pass
180
181	tc filter add dev $swp2 egress protocol ipv6 pref 1 handle 101 flower \
182		skip_hw dst_ip 2001:db8:2::1 ip_proto udp dst_port 52768 \
183		action pass
184
185	tc filter add dev $swp2 egress protocol ipv6 pref 2 handle 102 flower \
186		skip_sw dst_ip 2001:db8:2::1 ip_proto udp dst_port 52768 \
187		action pass
188
189	ip vrf exec v$h1 $MZ $h1 -6 -c 10 -d 100msec -p 64 -A 2001:db8:1::1 \
190		-B 2001:db8:2::1 -t udp dp=52768,sp=42768 -q
191
192	RET=0
193
194	tc_check_packets "dev $swp1 ingress" 101 10
195	check_err $?
196
197	log_test "fwd mark: trapping IPv6 packets due to LBERROR"
198
199	RET=0
200
201	tc_check_packets "dev $swp2 egress" 101 0
202	check_err $?
203
204	log_test "fwd mark: forwarding IPv6 packets in software"
205
206	RET=0
207
208	tc_check_packets "dev $swp2 egress" 102 10
209	check_err $?
210
211	log_test "fwd mark: forwarding IPv6 packets in hardware"
212
213	tc filter del dev $swp2 egress protocol ipv6 pref 2 handle 102 flower
214	tc filter del dev $swp2 egress protocol ipv6 pref 1 handle 101 flower
215	tc filter del dev $swp1 ingress protocol ipv6 pref 1 handle 101 flower
216}
217
218setup_prepare()
219{
220	h1=${NETIFS[p1]}
221	swp1=${NETIFS[p2]}
222
223	swp2=${NETIFS[p3]}
224	h2=${NETIFS[p4]}
225
226	vrf_prepare
227	forwarding_enable
228
229	sysctl_set net.ipv4.conf.all.accept_redirects 0
230	sysctl_set net.ipv6.conf.all.accept_redirects 0
231
232	h1_create
233	h2_create
234	switch_create
235}
236
237cleanup()
238{
239	pre_cleanup
240
241	switch_destroy
242	h2_destroy
243	h1_destroy
244
245	sysctl_restore net.ipv6.conf.all.accept_redirects
246	sysctl_restore net.ipv4.conf.all.accept_redirects
247
248	forwarding_restore
249	vrf_cleanup
250}
251
252trap cleanup EXIT
253
254setup_prepare
255setup_wait
256
257tests_run
258
259exit $EXIT_STATUS
260