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