1# SPDX-License-Identifier: GPL-2.0
2
3mirror_install()
4{
5	local from_dev=$1; shift
6	local direction=$1; shift
7	local to_dev=$1; shift
8	local filter=$1; shift
9
10	tc filter add dev $from_dev $direction \
11	   pref 1000 $filter \
12	   action mirred egress mirror dev $to_dev
13}
14
15mirror_uninstall()
16{
17	local from_dev=$1; shift
18	local direction=$1; shift
19
20	tc filter del dev $swp1 $direction pref 1000
21}
22
23is_ipv6()
24{
25	local addr=$1; shift
26
27	[[ -z ${addr//[0-9a-fA-F:]/} ]]
28}
29
30mirror_test()
31{
32	local vrf_name=$1; shift
33	local sip=$1; shift
34	local dip=$1; shift
35	local dev=$1; shift
36	local pref=$1; shift
37	local expect=$1; shift
38
39	if is_ipv6 $dip; then
40		local proto=-6
41		local type="icmp6 type=128" # Echo request.
42	else
43		local proto=
44		local type="icmp echoreq"
45	fi
46
47	local t0=$(tc_rule_stats_get $dev $pref)
48	$MZ $proto $vrf_name ${sip:+-A $sip} -B $dip -a own -b bc -q \
49	    -c 10 -d 100msec -t $type
50	sleep 0.5
51	local t1=$(tc_rule_stats_get $dev $pref)
52	local delta=$((t1 - t0))
53	# Tolerate a couple stray extra packets.
54	((expect <= delta && delta <= expect + 2))
55	check_err $? "Expected to capture $expect packets, got $delta."
56}
57
58do_test_span_dir_ips()
59{
60	local expect=$1; shift
61	local dev=$1; shift
62	local direction=$1; shift
63	local ip1=$1; shift
64	local ip2=$1; shift
65
66	icmp_capture_install $dev
67	mirror_test v$h1 $ip1 $ip2 $dev 100 $expect
68	mirror_test v$h2 $ip2 $ip1 $dev 100 $expect
69	icmp_capture_uninstall $dev
70}
71
72quick_test_span_dir_ips()
73{
74	do_test_span_dir_ips 10 "$@"
75}
76
77fail_test_span_dir_ips()
78{
79	do_test_span_dir_ips 0 "$@"
80}
81
82test_span_dir_ips()
83{
84	local dev=$1; shift
85	local direction=$1; shift
86	local forward_type=$1; shift
87	local backward_type=$1; shift
88	local ip1=$1; shift
89	local ip2=$1; shift
90
91	quick_test_span_dir_ips "$dev" "$direction" "$ip1" "$ip2"
92
93	icmp_capture_install $dev "type $forward_type"
94	mirror_test v$h1 $ip1 $ip2 $dev 100 10
95	icmp_capture_uninstall $dev
96
97	icmp_capture_install $dev "type $backward_type"
98	mirror_test v$h2 $ip2 $ip1 $dev 100 10
99	icmp_capture_uninstall $dev
100}
101
102fail_test_span_dir()
103{
104	fail_test_span_dir_ips "$@" 192.0.2.1 192.0.2.2
105}
106
107test_span_dir()
108{
109	test_span_dir_ips "$@" 192.0.2.1 192.0.2.2
110}
111
112do_test_span_vlan_dir_ips()
113{
114	local expect=$1; shift
115	local dev=$1; shift
116	local vid=$1; shift
117	local direction=$1; shift
118	local ip1=$1; shift
119	local ip2=$1; shift
120
121	# Install the capture as skip_hw to avoid double-counting of packets.
122	# The traffic is meant for local box anyway, so will be trapped to
123	# kernel.
124	vlan_capture_install $dev "skip_hw vlan_id $vid vlan_ethtype ip"
125	mirror_test v$h1 $ip1 $ip2 $dev 100 $expect
126	mirror_test v$h2 $ip2 $ip1 $dev 100 $expect
127	vlan_capture_uninstall $dev
128}
129
130quick_test_span_vlan_dir_ips()
131{
132	do_test_span_vlan_dir_ips 10 "$@"
133}
134
135fail_test_span_vlan_dir_ips()
136{
137	do_test_span_vlan_dir_ips 0 "$@"
138}
139
140quick_test_span_vlan_dir()
141{
142	quick_test_span_vlan_dir_ips "$@" 192.0.2.1 192.0.2.2
143}
144
145fail_test_span_vlan_dir()
146{
147	fail_test_span_vlan_dir_ips "$@" 192.0.2.1 192.0.2.2
148}
149