1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4ALL_TESTS="reportleave_test"
5NUM_NETIFS=4
6CHECK_TC="yes"
7TEST_GROUP="239.10.10.10"
8TEST_GROUP_MAC="01:00:5e:0a:0a:0a"
9source lib.sh
10
11h1_create()
12{
13	simple_if_init $h1 192.0.2.1/24 2001:db8:1::1/64
14}
15
16h1_destroy()
17{
18	simple_if_fini $h1 192.0.2.1/24 2001:db8:1::1/64
19}
20
21h2_create()
22{
23	simple_if_init $h2 192.0.2.2/24 2001:db8:1::2/64
24}
25
26h2_destroy()
27{
28	simple_if_fini $h2 192.0.2.2/24 2001:db8:1::2/64
29}
30
31switch_create()
32{
33	ip link add dev br0 type bridge mcast_snooping 1 mcast_querier 1
34
35	ip link set dev $swp1 master br0
36	ip link set dev $swp2 master br0
37
38	ip link set dev br0 up
39	ip link set dev $swp1 up
40	ip link set dev $swp2 up
41}
42
43switch_destroy()
44{
45	ip link set dev $swp2 down
46	ip link set dev $swp1 down
47
48	ip link del dev br0
49}
50
51setup_prepare()
52{
53	h1=${NETIFS[p1]}
54	swp1=${NETIFS[p2]}
55
56	swp2=${NETIFS[p3]}
57	h2=${NETIFS[p4]}
58
59	vrf_prepare
60
61	h1_create
62	h2_create
63
64	switch_create
65}
66
67cleanup()
68{
69	pre_cleanup
70
71	switch_destroy
72
73	# Always cleanup the mcast group
74	ip address del dev $h2 $TEST_GROUP/32 2>&1 1>/dev/null
75
76	h2_destroy
77	h1_destroy
78
79	vrf_cleanup
80}
81
82# return 0 if the packet wasn't seen on host2_if or 1 if it was
83mcast_packet_test()
84{
85	local mac=$1
86	local ip=$2
87	local host1_if=$3
88	local host2_if=$4
89	local seen=0
90
91	# Add an ACL on `host2_if` which will tell us whether the packet
92	# was received by it or not.
93	tc qdisc add dev $host2_if ingress
94	tc filter add dev $host2_if ingress protocol ip pref 1 handle 101 \
95		flower dst_mac $mac action drop
96
97	$MZ $host1_if -c 1 -p 64 -b $mac -B $ip -t udp "dp=4096,sp=2048" -q
98	sleep 1
99
100	tc -j -s filter show dev $host2_if ingress \
101		| jq -e ".[] | select(.options.handle == 101) \
102		| select(.options.actions[0].stats.packets == 1)" &> /dev/null
103	if [[ $? -eq 0 ]]; then
104		seen=1
105	fi
106
107	tc filter del dev $host2_if ingress protocol ip pref 1 handle 101 flower
108	tc qdisc del dev $host2_if ingress
109
110	return $seen
111}
112
113reportleave_test()
114{
115	RET=0
116	ip address add dev $h2 $TEST_GROUP/32 autojoin
117	check_err $? "Could not join $TEST_GROUP"
118
119	sleep 5
120	bridge mdb show dev br0 | grep $TEST_GROUP 1>/dev/null
121	check_err $? "Report didn't create mdb entry for $TEST_GROUP"
122
123	mcast_packet_test $TEST_GROUP_MAC $TEST_GROUP $h1 $h2
124	check_fail $? "Traffic to $TEST_GROUP wasn't forwarded"
125
126	log_test "IGMP report $TEST_GROUP"
127
128	RET=0
129	bridge mdb show dev br0 | grep $TEST_GROUP 1>/dev/null
130	check_err $? "mdb entry for $TEST_GROUP is missing"
131
132	ip address del dev $h2 $TEST_GROUP/32
133	check_err $? "Could not leave $TEST_GROUP"
134
135	sleep 5
136	bridge mdb show dev br0 | grep $TEST_GROUP 1>/dev/null
137	check_fail $? "Leave didn't delete mdb entry for $TEST_GROUP"
138
139	mcast_packet_test $TEST_GROUP_MAC $TEST_GROUP $h1 $h2
140	check_err $? "Traffic to $TEST_GROUP was forwarded without mdb entry"
141
142	log_test "IGMP leave $TEST_GROUP"
143}
144
145trap cleanup EXIT
146
147setup_prepare
148setup_wait
149
150tests_run
151
152exit $EXIT_STATUS
153