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