13f189349SFlorian Westphal#!/bin/bash 23f189349SFlorian Westphal# SPDX-License-Identifier: GPL-2.0 33f189349SFlorian Westphal# 41286e106SFlorian Westphal# Test for legacy br_netfilter module combined with connection tracking, 51286e106SFlorian Westphal# a combination that doesn't really work. 61286e106SFlorian Westphal# Multicast/broadcast packets race for hash table insertion. 73f189349SFlorian Westphal 83f189349SFlorian Westphal# eth0 br0 eth0 93f189349SFlorian Westphal# setup is: ns1 <->,ns0 <-> ns3 103f189349SFlorian Westphal# ns2 <-' `'-> ns4 113f189349SFlorian Westphal 121286e106SFlorian Westphalsource lib.sh 133f189349SFlorian Westphal 1410e2ed3fSFlorian Westphalchecktool "nft --version" "run test without nft tool" 153f189349SFlorian Westphal 163f189349SFlorian Westphalcleanup() { 171286e106SFlorian Westphal cleanup_all_ns 183f189349SFlorian Westphal} 193f189349SFlorian Westphal 203f189349SFlorian Westphaltrap cleanup EXIT 213f189349SFlorian Westphal 221286e106SFlorian Westphalsetup_ns ns0 ns1 ns2 ns3 ns4 231286e106SFlorian Westphal 241286e106SFlorian Westphalret=0 251286e106SFlorian Westphal 263f189349SFlorian Westphaldo_ping() 273f189349SFlorian Westphal{ 283f189349SFlorian Westphal fromns="$1" 293f189349SFlorian Westphal dstip="$2" 303f189349SFlorian Westphal 311286e106SFlorian Westphal if ! ip netns exec "$fromns" ping -c 1 -q "$dstip" > /dev/null; then 323f189349SFlorian Westphal echo "ERROR: ping from $fromns to $dstip" 331286e106SFlorian Westphal ip netns exec "$ns0" nft list ruleset 343f189349SFlorian Westphal ret=1 353f189349SFlorian Westphal fi 363f189349SFlorian Westphal} 373f189349SFlorian Westphal 383f189349SFlorian Westphalbcast_ping() 393f189349SFlorian Westphal{ 403f189349SFlorian Westphal fromns="$1" 413f189349SFlorian Westphal dstip="$2" 423f189349SFlorian Westphal 43*f581bcf0SFlorian Westphal local packets=500 44*f581bcf0SFlorian Westphal 45*f581bcf0SFlorian Westphal [ "$KSFT_MACHINE_SLOW" = yes ] && packets=100 46*f581bcf0SFlorian Westphal 47*f581bcf0SFlorian Westphal for i in $(seq 1 $packets); do 481286e106SFlorian Westphal if ! ip netns exec "$fromns" ping -q -f -b -c 1 -q "$dstip" > /dev/null 2>&1; then 493f189349SFlorian Westphal echo "ERROR: ping -b from $fromns to $dstip" 501286e106SFlorian Westphal ip netns exec "$ns0" nft list ruleset 511286e106SFlorian Westphal ret=1 521286e106SFlorian Westphal break 533f189349SFlorian Westphal fi 543f189349SFlorian Westphal done 553f189349SFlorian Westphal} 563f189349SFlorian Westphal 571286e106SFlorian Westphalip netns exec "$ns0" sysctl -q net.ipv4.conf.all.rp_filter=0 581286e106SFlorian Westphalip netns exec "$ns0" sysctl -q net.ipv4.conf.default.rp_filter=0 591286e106SFlorian Westphal 601286e106SFlorian Westphalif ! ip link add veth1 netns "$ns0" type veth peer name eth0 netns "$ns1"; then 613f189349SFlorian Westphal echo "SKIP: Can't create veth device" 623f189349SFlorian Westphal exit $ksft_skip 633f189349SFlorian Westphalfi 643f189349SFlorian Westphal 651286e106SFlorian Westphalip link add veth2 netns "$ns0" type veth peer name eth0 netns "$ns2" 661286e106SFlorian Westphalip link add veth3 netns "$ns0" type veth peer name eth0 netns "$ns3" 671286e106SFlorian Westphalip link add veth4 netns "$ns0" type veth peer name eth0 netns "$ns4" 683f189349SFlorian Westphal 693f189349SFlorian Westphalfor i in $(seq 1 4); do 701286e106SFlorian Westphal ip -net "$ns0" link set "veth$i" up 713f189349SFlorian Westphaldone 723f189349SFlorian Westphal 731286e106SFlorian Westphalif ! 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 743f189349SFlorian Westphal echo "SKIP: Can't create bridge br0" 753f189349SFlorian Westphal exit $ksft_skip 763f189349SFlorian Westphalfi 773f189349SFlorian Westphal 783f189349SFlorian Westphal# make veth0,1,2 part of bridge. 793f189349SFlorian Westphalfor i in $(seq 1 3); do 801286e106SFlorian Westphal ip -net "$ns0" link set "veth$i" master br0 813f189349SFlorian Westphaldone 823f189349SFlorian Westphal 833f189349SFlorian Westphal# add a macvlan on top of the bridge. 843f189349SFlorian WestphalMACVLAN_ADDR=ba:f3:13:37:42:23 851286e106SFlorian Westphalip -net "$ns0" link add link br0 name macvlan0 type macvlan mode private 861286e106SFlorian Westphalip -net "$ns0" link set macvlan0 address ${MACVLAN_ADDR} 871286e106SFlorian Westphalip -net "$ns0" link set macvlan0 up 881286e106SFlorian Westphalip -net "$ns0" addr add 10.23.0.1/24 dev macvlan0 893f189349SFlorian Westphal 903f189349SFlorian Westphal# add a macvlan on top of veth4. 913f189349SFlorian WestphalMACVLAN_ADDR=ba:f3:13:37:42:24 921286e106SFlorian Westphalip -net "$ns0" link add link veth4 name macvlan4 type macvlan mode passthru 931286e106SFlorian Westphalip -net "$ns0" link set macvlan4 address ${MACVLAN_ADDR} 941286e106SFlorian Westphalip -net "$ns0" link set macvlan4 up 953f189349SFlorian Westphal 963f189349SFlorian Westphal# make the macvlan part of the bridge. 973f189349SFlorian Westphal# veth4 is not a bridge port, only the macvlan on top of it. 981286e106SFlorian Westphalip -net "$ns0" link set macvlan4 master br0 993f189349SFlorian Westphal 1001286e106SFlorian Westphalip -net "$ns0" link set br0 up 1011286e106SFlorian Westphalip -net "$ns0" addr add 10.0.0.1/24 dev br0 1021286e106SFlorian Westphal 1031286e106SFlorian Westphalmodprobe -q br_netfilter 1041286e106SFlorian Westphalif ! ip netns exec "$ns0" sysctl -q net.bridge.bridge-nf-call-iptables=1; then 1053f189349SFlorian Westphal echo "SKIP: bridge netfilter not available" 1063f189349SFlorian Westphal ret=$ksft_skip 1073f189349SFlorian Westphalfi 1083f189349SFlorian Westphal 1093f189349SFlorian Westphal# for testing, so namespaces will reply to ping -b probes. 1101286e106SFlorian Westphalip netns exec "$ns0" sysctl -q net.ipv4.icmp_echo_ignore_broadcasts=0 1113f189349SFlorian Westphal 1123f189349SFlorian Westphal# enable conntrack in ns0 and drop broadcast packets in forward to 1133f189349SFlorian Westphal# avoid them from getting confirmed in the postrouting hook before 1143f189349SFlorian Westphal# the cloned skb is passed up the stack. 1151286e106SFlorian Westphalip netns exec "$ns0" nft -f - <<EOF 1163f189349SFlorian Westphaltable ip filter { 1173f189349SFlorian Westphal chain input { 1183f189349SFlorian Westphal type filter hook input priority 1; policy accept 1193f189349SFlorian Westphal iifname br0 counter 1203f189349SFlorian Westphal ct state new accept 1213f189349SFlorian Westphal } 1223f189349SFlorian Westphal} 1233f189349SFlorian Westphal 1243f189349SFlorian Westphaltable bridge filter { 1253f189349SFlorian Westphal chain forward { 1263f189349SFlorian Westphal type filter hook forward priority 0; policy accept 1273f189349SFlorian Westphal meta pkttype broadcast ip protocol icmp counter drop 1283f189349SFlorian Westphal } 1293f189349SFlorian Westphal} 1303f189349SFlorian WestphalEOF 131bb0ee78fSFlorian Westphalif [ "$?" -ne 0 ];then 132bb0ee78fSFlorian Westphal echo "SKIP: could not add nftables ruleset" 133bb0ee78fSFlorian Westphal exit $ksft_skip 134bb0ee78fSFlorian Westphalfi 1353f189349SFlorian Westphal 1363f189349SFlorian Westphal# place 1, 2 & 3 in same subnet, connected via ns0:br0. 1373f189349SFlorian Westphal# ns4 is placed in same subnet as well, but its not 1383f189349SFlorian Westphal# part of the bridge: the corresponding veth4 is not 1393f189349SFlorian Westphal# part of the bridge, only its macvlan interface. 1403f189349SFlorian Westphalfor i in $(seq 1 4); do 1411286e106SFlorian Westphal eval ip -net \$ns"$i" link set eth0 up 1423f189349SFlorian Westphaldone 1433f189349SFlorian Westphalfor i in $(seq 1 2); do 1441286e106SFlorian Westphal eval ip -net \$ns"$i" addr add "10.0.0.1$i/24" dev eth0 1453f189349SFlorian Westphaldone 1463f189349SFlorian Westphal 1471286e106SFlorian Westphalip -net "$ns3" addr add 10.23.0.13/24 dev eth0 1481286e106SFlorian Westphalip -net "$ns4" addr add 10.23.0.14/24 dev eth0 1493f189349SFlorian Westphal 1503f189349SFlorian Westphal# test basic connectivity 1511286e106SFlorian Westphaldo_ping "$ns1" 10.0.0.12 1521286e106SFlorian Westphaldo_ping "$ns3" 10.23.0.1 1531286e106SFlorian Westphaldo_ping "$ns4" 10.23.0.1 1543f189349SFlorian Westphal 1551286e106SFlorian Westphalbcast_ping "$ns1" 10.0.0.255 1563f189349SFlorian Westphal 1573f189349SFlorian Westphal# This should deliver broadcast to macvlan0, which is on top of ns0:br0. 1581286e106SFlorian Westphalbcast_ping "$ns3" 10.23.0.255 1593f189349SFlorian Westphal 1603f189349SFlorian Westphal# same, this time via veth4:macvlan4. 1611286e106SFlorian Westphalbcast_ping "$ns4" 10.23.0.255 1623f189349SFlorian Westphal 1633f189349SFlorian Westphalread t < /proc/sys/kernel/tainted 1641286e106SFlorian Westphalif [ "$t" -eq 0 ];then 1653f189349SFlorian Westphal echo PASS: kernel not tainted 1663f189349SFlorian Westphalelse 1673f189349SFlorian Westphal echo ERROR: kernel is tainted 1683f189349SFlorian Westphal ret=1 1693f189349SFlorian Westphalfi 1703f189349SFlorian Westphal 1713f189349SFlorian Westphalexit $ret 172