aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/netfilter/bridge_brouter.sh
blob: 29f3955b9af7e8b357e1b806e7ca496b1c1bc924 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/bin/bash
#
# This test is for bridge 'brouting', i.e. make some packets being routed
# rather than getting bridged even though they arrive on interface that is
# part of a bridge.

#           eth0    br0     eth0
# setup is: ns1 <-> ns0 <-> ns2

# Kselftest framework requirement - SKIP code is 4.
ksft_skip=4
ret=0

ebtables -V > /dev/null 2>&1
if [ $? -ne 0 ];then
	echo "SKIP: Could not run test without ebtables"
	exit $ksft_skip
fi

ip -Version > /dev/null 2>&1
if [ $? -ne 0 ];then
	echo "SKIP: Could not run test without ip tool"
	exit $ksft_skip
fi

ip netns add ns0
ip netns add ns1
ip netns add ns2

ip link add veth0 netns ns0 type veth peer name eth0 netns ns1
if [ $? -ne 0 ]; then
	echo "SKIP: Can't create veth device"
	exit $ksft_skip
fi
ip link add veth1 netns ns0 type veth peer name eth0 netns ns2

ip -net ns0 link set lo up
ip -net ns0 link set veth0 up
ip -net ns0 link set veth1 up

ip -net ns0 link add br0 type bridge
if [ $? -ne 0 ]; then
	echo "SKIP: Can't create bridge br0"
	exit $ksft_skip
fi

ip -net ns0 link set veth0 master br0
ip -net ns0 link set veth1 master br0
ip -net ns0 link set br0 up
ip -net ns0 addr add 10.0.0.1/24 dev br0

# place both in same subnet, ns1 and ns2 connected via ns0:br0
for i in 1 2; do
  ip -net ns$i link set lo up
  ip -net ns$i link set eth0 up
  ip -net ns$i addr add 10.0.0.1$i/24 dev eth0
done

test_ebtables_broute()
{
	local cipt

	# redirect is needed so the dstmac is rewritten to the bridge itself,
	# ip stack won't process OTHERHOST (foreign unicast mac) packets.
	ip netns exec ns0 ebtables -t broute -A BROUTING -p ipv4 --ip-protocol icmp -j redirect --redirect-target=DROP
	if [ $? -ne 0 ]; then
		echo "SKIP: Could not add ebtables broute redirect rule"
		return $ksft_skip
	fi

	# ping netns1, expected to not work (ip forwarding is off)
	ip netns exec ns1 ping -q -c 1 10.0.0.12 > /dev/null 2>&1
	if [ $? -eq 0 ]; then
		echo "ERROR: ping works, should have failed" 1>&2
		return 1
	fi

	# enable forwarding on both interfaces.
	# neither needs an ip address, but at least the bridge needs
	# an ip address in same network segment as ns1 and ns2 (ns0
	# needs to be able to determine route for to-be-forwarded packet).
	ip netns exec ns0 sysctl -q net.ipv4.conf.veth0.forwarding=1
	ip netns exec ns0 sysctl -q net.ipv4.conf.veth1.forwarding=1

	sleep 1

	ip netns exec ns1 ping -q -c 1 10.0.0.12 > /dev/null
	if [ $? -ne 0 ]; then
		echo "ERROR: ping did not work, but it should (broute+forward)" 1>&2
		return 1
	fi

	echo "PASS: ns1/ns2 connectivity with active broute rule"
	ip netns exec ns0 ebtables -t broute -F

	# ping netns1, expected to work (frames are bridged)
	ip netns exec ns1 ping -q -c 1 10.0.0.12 > /dev/null
	if [ $? -ne 0 ]; then
		echo "ERROR: ping did not work, but it should (bridged)" 1>&2
		return 1
	fi

	ip netns exec ns0 ebtables -t filter -A FORWARD -p ipv4 --ip-protocol icmp -j DROP

	# ping netns1, expected to not work (DROP in bridge forward)
	ip netns exec ns1 ping -q -c 1 10.0.0.12 > /dev/null 2>&1
	if [ $? -eq 0 ]; then
		echo "ERROR: ping works, should have failed (icmp forward drop)" 1>&2
		return 1
	fi

	# re-activate brouter
	ip netns exec ns0 ebtables -t broute -A BROUTING -p ipv4 --ip-protocol icmp -j redirect --redirect-target=DROP

	ip netns exec ns2 ping -q -c 1 10.0.0.11 > /dev/null
	if [ $? -ne 0 ]; then
		echo "ERROR: ping did not work, but it should (broute+forward 2)" 1>&2
		return 1
	fi

	echo "PASS: ns1/ns2 connectivity with active broute rule and bridge forward drop"
	return 0
}

# test basic connectivity
ip netns exec ns1 ping -c 1 -q 10.0.0.12 > /dev/null
if [ $? -ne 0 ]; then
    echo "ERROR: Could not reach ns2 from ns1" 1>&2
    ret=1
fi

ip netns exec ns2 ping -c 1 -q 10.0.0.11 > /dev/null
if [ $? -ne 0 ]; then
    echo "ERROR: Could not reach ns1 from ns2" 1>&2
    ret=1
fi

if [ $ret -eq 0 ];then
    echo "PASS: netns connectivity: ns1 and ns2 can reach each other"
fi

test_ebtables_broute
ret=$?
for i in 0 1 2; do ip netns del ns$i;done

exit $ret