• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# Test for legacy br_netfilter module combined with connection tracking,
5# a combination that doesn't really work.
6# Multicast/broadcast packets race for hash table insertion.
7
8#           eth0    br0     eth0
9# setup is: ns1 <->,ns0 <-> ns3
10#           ns2 <-'    `'-> ns4
11
12source lib.sh
13
14checktool "nft --version" "run test without nft tool"
15
16read t < /proc/sys/kernel/tainted
17if [ "$t" -ne 0 ];then
18	echo SKIP: kernel is tainted
19	exit $ksft_skip
20fi
21
22cleanup() {
23	cleanup_all_ns
24}
25
26trap cleanup EXIT
27
28setup_ns ns0 ns1 ns2 ns3 ns4
29
30ret=0
31
32do_ping()
33{
34	fromns="$1"
35	dstip="$2"
36
37	if ! ip netns exec "$fromns" ping -c 1 -q "$dstip" > /dev/null; then
38		echo "ERROR: ping from $fromns to $dstip"
39		ip netns exec "$ns0" nft list ruleset
40		ret=1
41	fi
42}
43
44bcast_ping()
45{
46	fromns="$1"
47	dstip="$2"
48
49	local packets=500
50
51	[ "$KSFT_MACHINE_SLOW" = yes ] && packets=100
52
53	for i in $(seq 1 $packets); do
54		if ! ip netns exec "$fromns" ping -q -f -b -c 1 -q "$dstip" > /dev/null 2>&1; then
55			echo "ERROR: ping -b from $fromns to $dstip"
56			ip netns exec "$ns0" nft list ruleset
57			ret=1
58			break
59		fi
60	done
61}
62
63ip netns exec "$ns0" sysctl -q net.ipv4.conf.all.rp_filter=0
64ip netns exec "$ns0" sysctl -q net.ipv4.conf.default.rp_filter=0
65
66if ! ip link add veth1 netns "$ns0" type veth peer name eth0 netns "$ns1"; then
67	echo "SKIP: Can't create veth device"
68	exit $ksft_skip
69fi
70
71ip link add veth2 netns "$ns0" type veth peer name eth0 netns "$ns2"
72ip link add veth3 netns "$ns0" type veth peer name eth0 netns "$ns3"
73ip link add veth4 netns "$ns0" type veth peer name eth0 netns "$ns4"
74
75for i in $(seq 1 4); do
76  ip -net "$ns0" link set "veth$i" up
77done
78
79if ! ip -net "$ns0" link add br0 type bridge stp_state 0 forward_delay 0 nf_call_iptables 1 nf_call_ip6tables 1 nf_call_arptables 1; then
80	echo "SKIP: Can't create bridge br0"
81	exit $ksft_skip
82fi
83
84# make veth0,1,2 part of bridge.
85for i in $(seq 1 3); do
86  ip -net "$ns0" link set "veth$i" master br0
87done
88
89# add a macvlan on top of the bridge.
90MACVLAN_ADDR=ba:f3:13:37:42:23
91ip -net "$ns0" link add link br0 name macvlan0 type macvlan mode private
92ip -net "$ns0" link set macvlan0 address ${MACVLAN_ADDR}
93ip -net "$ns0" link set macvlan0 up
94ip -net "$ns0" addr add 10.23.0.1/24 dev macvlan0
95
96# add a macvlan on top of veth4.
97MACVLAN_ADDR=ba:f3:13:37:42:24
98ip -net "$ns0" link add link veth4 name macvlan4 type macvlan mode passthru
99ip -net "$ns0" link set macvlan4 address ${MACVLAN_ADDR}
100ip -net "$ns0" link set macvlan4 up
101
102# make the macvlan part of the bridge.
103# veth4 is not a bridge port, only the macvlan on top of it.
104ip -net "$ns0" link set macvlan4 master br0
105
106ip -net "$ns0" link set br0 up
107ip -net "$ns0" addr add 10.0.0.1/24 dev br0
108
109modprobe -q br_netfilter
110if ! ip netns exec "$ns0" sysctl -q net.bridge.bridge-nf-call-iptables=1; then
111	echo "SKIP: bridge netfilter not available"
112	ret=$ksft_skip
113fi
114
115# for testing, so namespaces will reply to ping -b probes.
116ip netns exec "$ns0" sysctl -q net.ipv4.icmp_echo_ignore_broadcasts=0
117
118# enable conntrack in ns0 and drop broadcast packets in forward to
119# avoid them from getting confirmed in the postrouting hook before
120# the cloned skb is passed up the stack.
121ip netns exec "$ns0" nft -f - <<EOF
122table ip filter {
123	chain input {
124		type filter hook input priority 1; policy accept
125		iifname br0 counter
126		ct state new accept
127	}
128}
129
130table bridge filter {
131	chain forward {
132		type filter hook forward priority 0; policy accept
133		meta pkttype broadcast ip protocol icmp counter drop
134	}
135}
136EOF
137if [ "$?" -ne 0 ];then
138	echo "SKIP: could not add nftables ruleset"
139	exit $ksft_skip
140fi
141
142# place 1, 2 & 3 in same subnet, connected via ns0:br0.
143# ns4 is placed in same subnet as well, but its not
144# part of the bridge: the corresponding veth4 is not
145# part of the bridge, only its macvlan interface.
146for i in $(seq 1 4); do
147  eval ip -net \$ns"$i" link set eth0 up
148done
149for i in $(seq 1 2); do
150  eval ip -net \$ns"$i" addr add "10.0.0.1$i/24" dev eth0
151done
152
153ip -net "$ns3" addr add 10.23.0.13/24 dev eth0
154ip -net "$ns4" addr add 10.23.0.14/24 dev eth0
155
156# test basic connectivity
157do_ping "$ns1" 10.0.0.12
158do_ping "$ns3" 10.23.0.1
159do_ping "$ns4" 10.23.0.1
160
161bcast_ping "$ns1" 10.0.0.255
162
163# This should deliver broadcast to macvlan0, which is on top of ns0:br0.
164bcast_ping "$ns3" 10.23.0.255
165
166# same, this time via veth4:macvlan4.
167bcast_ping "$ns4" 10.23.0.255
168
169read t < /proc/sys/kernel/tainted
170if [ "$t" -eq 0 ];then
171	echo PASS: kernel not tainted
172else
173	echo ERROR: kernel is tainted
174	dmesg
175	ret=1
176fi
177
178exit $ret
179