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