1# SPDX-License-Identifier: GPL-2.0
2
3# Test offloading a number of mirrors-to-gretap. The test creates a number of
4# tunnels. Then it adds one flower mirror for each of the tunnels, matching a
5# given host IP. Then it generates traffic at each of the host IPs and checks
6# that the traffic has been mirrored at the appropriate tunnel.
7#
8#   +--------------------------+                   +--------------------------+
9#   | H1                       |                   |                       H2 |
10#   |     + $h1                |                   |                $h2 +     |
11#   |     | 2001:db8:1:X::1/64 |                   | 2001:db8:1:X::2/64 |     |
12#   +-----|--------------------+                   +--------------------|-----+
13#         |                                                             |
14#   +-----|-------------------------------------------------------------|-----+
15#   | SW  o--> mirrors                                                  |     |
16#   | +---|-------------------------------------------------------------|---+ |
17#   | |   + $swp1                    BR                           $swp2 +   | |
18#   | +---------------------------------------------------------------------+ |
19#   |                                                                         |
20#   |     + $swp3                          + gt6-<X> (ip6gretap)              |
21#   |     | 2001:db8:2:X::1/64             : loc=2001:db8:2:X::1              |
22#   |     |                                : rem=2001:db8:2:X::2              |
23#   |     |                                : ttl=100                          |
24#   |     |                                : tos=inherit                      |
25#   |     |                                :                                  |
26#   +-----|--------------------------------:----------------------------------+
27#         |                                :
28#   +-----|--------------------------------:----------------------------------+
29#   | H3  + $h3                            + h3-gt6-<X> (ip6gretap)           |
30#   |       2001:db8:2:X::2/64               loc=2001:db8:2:X::2              |
31#   |                                        rem=2001:db8:2:X::1              |
32#   |                                        ttl=100                          |
33#   |                                        tos=inherit                      |
34#   |                                                                         |
35#   +-------------------------------------------------------------------------+
36
37source ../../../../net/forwarding/mirror_lib.sh
38
39MIRROR_NUM_NETIFS=6
40
41mirror_gre_ipv6_addr()
42{
43	local net=$1; shift
44	local num=$1; shift
45
46	printf "2001:db8:%x:%x" $net $num
47}
48
49mirror_gre_tunnels_create()
50{
51	local count=$1; shift
52	local should_fail=$1; shift
53
54	MIRROR_GRE_BATCH_FILE="$(mktemp)"
55	for ((i=0; i < count; ++i)); do
56		local match_dip=$(mirror_gre_ipv6_addr 1 $i)::2
57		local htun=h3-gt6-$i
58		local tun=gt6-$i
59
60		((mirror_gre_tunnels++))
61
62		ip address add dev $h1 $(mirror_gre_ipv6_addr 1 $i)::1/64
63		ip address add dev $h2 $(mirror_gre_ipv6_addr 1 $i)::2/64
64
65		ip address add dev $swp3 $(mirror_gre_ipv6_addr 2 $i)::1/64
66		ip address add dev $h3 $(mirror_gre_ipv6_addr 2 $i)::2/64
67
68		tunnel_create $tun ip6gretap \
69			      $(mirror_gre_ipv6_addr 2 $i)::1 \
70			      $(mirror_gre_ipv6_addr 2 $i)::2 \
71			      ttl 100 tos inherit allow-localremote
72
73		tunnel_create $htun ip6gretap \
74			      $(mirror_gre_ipv6_addr 2 $i)::2 \
75			      $(mirror_gre_ipv6_addr 2 $i)::1
76		ip link set $htun vrf v$h3
77		matchall_sink_create $htun
78
79		cat >> $MIRROR_GRE_BATCH_FILE <<-EOF
80			filter add dev $swp1 ingress pref 1000 \
81				protocol ipv6 \
82				flower $tcflags dst_ip $match_dip \
83				action mirred egress mirror dev $tun
84		EOF
85	done
86
87	tc -b $MIRROR_GRE_BATCH_FILE
88	check_err_fail $should_fail $? "Mirror rule insertion"
89}
90
91mirror_gre_tunnels_destroy()
92{
93	local count=$1; shift
94
95	for ((i=0; i < count; ++i)); do
96		local htun=h3-gt6-$i
97		local tun=gt6-$i
98
99		ip address del dev $h3 $(mirror_gre_ipv6_addr 2 $i)::2/64
100		ip address del dev $swp3 $(mirror_gre_ipv6_addr 2 $i)::1/64
101
102		ip address del dev $h2 $(mirror_gre_ipv6_addr 1 $i)::2/64
103		ip address del dev $h1 $(mirror_gre_ipv6_addr 1 $i)::1/64
104
105		tunnel_destroy $htun
106		tunnel_destroy $tun
107	done
108}
109
110__mirror_gre_test()
111{
112	local count=$1; shift
113	local should_fail=$1; shift
114
115	mirror_gre_tunnels_create $count $should_fail
116	if ((should_fail)); then
117	    return
118	fi
119
120	sleep 5
121
122	for ((i = 0; i < count; ++i)); do
123		local dip=$(mirror_gre_ipv6_addr 1 $i)::2
124		local htun=h3-gt6-$i
125		local message
126
127		icmp6_capture_install $htun
128		mirror_test v$h1 "" $dip $htun 100 10
129		icmp6_capture_uninstall $htun
130	done
131}
132
133mirror_gre_test()
134{
135	local count=$1; shift
136	local should_fail=$1; shift
137
138	if ! tc_offload_check $TC_FLOWER_NUM_NETIFS; then
139		check_err 1 "Could not test offloaded functionality"
140		return
141	fi
142
143	tcflags="skip_sw"
144	__mirror_gre_test $count $should_fail
145}
146
147mirror_gre_setup_prepare()
148{
149	h1=${NETIFS[p1]}
150	swp1=${NETIFS[p2]}
151
152	swp2=${NETIFS[p3]}
153	h2=${NETIFS[p4]}
154
155	swp3=${NETIFS[p5]}
156	h3=${NETIFS[p6]}
157
158	mirror_gre_tunnels=0
159
160	vrf_prepare
161
162	simple_if_init $h1
163	simple_if_init $h2
164	simple_if_init $h3
165
166	ip link add name br1 type bridge vlan_filtering 1
167	ip link set dev br1 up
168
169	ip link set dev $swp1 master br1
170	ip link set dev $swp1 up
171	tc qdisc add dev $swp1 clsact
172
173	ip link set dev $swp2 master br1
174	ip link set dev $swp2 up
175
176	ip link set dev $swp3 up
177}
178
179mirror_gre_cleanup()
180{
181	mirror_gre_tunnels_destroy $mirror_gre_tunnels
182
183	ip link set dev $swp3 down
184
185	ip link set dev $swp2 down
186
187	tc qdisc del dev $swp1 clsact
188	ip link set dev $swp1 down
189
190	ip link del dev br1
191
192	simple_if_fini $h3
193	simple_if_fini $h2
194	simple_if_fini $h1
195
196	vrf_cleanup
197}
198