The branch main has been updated by ivy:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=a5fe142e08447c7116b89159c110d02e860ac6a1

commit a5fe142e08447c7116b89159c110d02e860ac6a1
Author:     Lexi Winter <i...@freebsd.org>
AuthorDate: 2025-06-04 06:05:12 +0000
Commit:     Lexi Winter <i...@freebsd.org>
CommitDate: 2025-06-04 06:05:12 +0000

    bridge: fix vlan(4) on a bridge member
    
    If an interface is a bridge member, and a vlan(4) is also created on
    that interface, and net.link.bridge.member_ifaddrs=0, then vlan(4)
    will never see any incoming frames because bridge doesn't pass them
    to the host for processing.
    
    Work around this by checking for locally-addressed frames using the
    MAC address of the interface we received the frame on, but only if
    the frame has a .1q tag and there's a vlan trunk on the interface.
    
    This behaviour is almost certainly "wrong" and it's not clear if we
    really want to support this, but it did work in the past and the
    member_ifaddrs change was not supposed to break it, so this restores
    the previous behaviour.
    
    PR:     287150
    MFC after:      1 week
    Reviewed by:    kevans, des
    Approved by:    kevans (mentor), des (mentor)
    Differential Revision:  https://reviews.freebsd.org/D50623
---
 sys/net/if_bridge.c             | 23 ++++++++-----------
 tests/sys/net/if_bridge_test.sh | 51 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+), 13 deletions(-)

diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 9338d28437d0..82a530042413 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -2778,22 +2778,19 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
        do { GRAB_OUR_PACKETS(bifp) } while (0);
 
        /*
-        * We only need to check members interfaces if member_ifaddrs is
-        * enabled; otherwise we should have never traffic destined for a
-        * member's lladdr.
+        * Check the interface the packet arrived on.  For tagged frames,
+        * we need to do this even if member_ifaddrs is disabled because
+        * vlan(4) might need to handle the traffic.
         */
-
-       if (V_member_ifaddrs) {
-               /*
-                * Give a chance for ifp at first priority. This will help when
-                * the packet comes through the interface like VLAN's with the
-                * same MACs on several interfaces from the same bridge. This
-                * also will save some CPU cycles in case the destination
-                * interface and the input interface (eq ifp) are the same.
-                */
+       if (V_member_ifaddrs || (vlan && ifp->if_vlantrunk))
                do { GRAB_OUR_PACKETS(ifp) } while (0);
 
-               /* Now check the all bridge members. */
+       /*
+        * We only need to check other members interface if member_ifaddrs
+        * is enabled; otherwise we should have never traffic destined for
+        * a member's lladdr.
+        */
+       if (V_member_ifaddrs) {
                CK_LIST_FOREACH(bif2, &sc->sc_iflist, bif_next) {
                        GRAB_OUR_PACKETS(bif2->bif_ifp)
                }
diff --git a/tests/sys/net/if_bridge_test.sh b/tests/sys/net/if_bridge_test.sh
index f9a36126fe59..2c6b039048e3 100755
--- a/tests/sys/net/if_bridge_test.sh
+++ b/tests/sys/net/if_bridge_test.sh
@@ -779,6 +779,56 @@ member_ifaddrs_disabled_cleanup()
        vnet_cleanup
 }
 
+#
+# Test kern/287150: when member_ifaddrs=0, and a physical interface which is in
+# a bridge also has a vlan(4) on it, tagged packets are not correctly passed to
+# vlan(4).
+atf_test_case "member_ifaddrs_vlan" "cleanup"
+member_ifaddrs_vlan_head()
+{
+       atf_set descr 'kern/287150: vlan and bridge on the same interface'
+       atf_set require.user root
+}
+
+member_ifaddrs_vlan_body()
+{
+       vnet_init
+       vnet_init_bridge
+
+       epone=$(vnet_mkepair)
+       eptwo=$(vnet_mkepair)
+
+       # The first jail has an epair with an IP address on vlan 20.
+       vnet_mkjail one ${epone}a
+       atf_check -s exit:0 jexec one ifconfig ${epone}a up
+       atf_check -s exit:0 jexec one \
+           ifconfig ${epone}a.20 create inet 192.0.2.1/24 up
+
+       # The second jail has an epair with an IP address on vlan 20,
+       # which is also in a bridge.
+       vnet_mkjail two ${epone}b
+
+       jexec two ifconfig
+       atf_check -s exit:0 -o save:bridge jexec two ifconfig bridge create
+       bridge=$(cat bridge)
+       atf_check -s exit:0 jexec two ifconfig ${bridge} addm ${epone}b up
+
+       atf_check -s exit:0 -o ignore jexec two \
+           sysctl net.link.bridge.member_ifaddrs=0
+       atf_check -s exit:0 jexec two ifconfig ${epone}b up
+       atf_check -s exit:0 jexec two \
+           ifconfig ${epone}b.20 create inet 192.0.2.2/24 up
+
+       # Make sure the two jails can communicate over the vlan.
+       atf_check -s exit:0 -o ignore jexec one ping -c 3 -t 1 192.0.2.2
+       atf_check -s exit:0 -o ignore jexec two ping -c 3 -t 1 192.0.2.1
+}
+
+member_ifaddrs_vlan_cleanup()
+{
+       vnet_cleanup
+}
+
 atf_init_test_cases()
 {
        atf_add_test_case "bridge_transmit_ipv4_unicast"
@@ -796,4 +846,5 @@ atf_init_test_cases()
        atf_add_test_case "many_bridge_members"
        atf_add_test_case "member_ifaddrs_enabled"
        atf_add_test_case "member_ifaddrs_disabled"
+       atf_add_test_case "member_ifaddrs_vlan"
 }

Reply via email to