The branch main has been updated by ivy:

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

commit 7d99569d40510b627f0790c2b9630b5903e926b9
Author:     Lexi Winter <i...@freebsd.org>
AuthorDate: 2025-08-05 18:18:52 +0000
Commit:     Lexi Winter <i...@freebsd.org>
CommitDate: 2025-08-05 18:35:30 +0000

    bridge: Make the vlan(4) shunt more robust
    
    When bridge(4) and vlan(4) are both configured on the same physical
    interface, bridge handles incoming packets first and needs to shunt
    some packets to vlan(4).  Right now, that shunt is done if the packet
    is destined for the Ethernet address of the member interface it was
    received on, and has a vlan tag.
    
    This is not ideal for two reasons:
    
    * It leaks some of the "special" behaviour of member_ifaddrs=1 even
      when member_ifaddrs is set to 0.
    
    * It means the vlan interface only receives locally-destined traffic,
      so anything that needs to receive other traffic won't work.
    
    Change the behaviour so that if a member interface has a vlan trunk
    configured, *all* tagged packets are unconditionally passed back to
    ether_input, which will send them to vlan(4).
    
    This somewhat changes the observable behaviour of vlan(4): since
    bridge(4) places all member interfaces in promiscuous mode, the
    vlan interface will now receive all traffic on that vlan.  This
    shouldn't break any real-world configurations because it's only
    receiving more traffic; any traffic that was previously received
    is still received.
    
    Configuring both vlan(4) and bridge(4) on the same interface is
    probably not something we want to support long term, but for now
    this makes the code cleaner and the user-visible behaviour simpler
    and more predictable.
    
    Differential Revision:  https://reviews.freebsd.org/D51677
---
 sys/net/if_bridge.c | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 945318c5af1a..3aed54c58e04 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -2871,6 +2871,16 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
        eh = mtod(m, struct ether_header *);
        vlan = VLANTAGOF(m);
 
+       /*
+        * If this frame has a VLAN tag and the receiving interface has a
+        * vlan(4) trunk, then it is is destined for vlan(4), not for us.
+        * This means if vlan(4) and bridge(4) are configured on the same
+        * interface, vlan(4) is preferred, which is what users typically
+        * expect.
+        */
+       if (vlan != DOT1Q_VID_NULL && ifp->if_vlantrunk != NULL)
+               return (m);
+
        bif = ifp->if_bridge;
        if (bif)
                sc = bif->bif_sc;
@@ -3071,19 +3081,13 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
        do { GRAB_OUR_PACKETS(bifp) } while (0);
 
        /*
-        * 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 member_ifaddrs is enabled, see if the packet is destined for
+        * one of the members' addresses.
         */
-       if (V_member_ifaddrs || (vlan && ifp->if_vlantrunk))
+       if (V_member_ifaddrs) {
+               /* Check the interface the packet arrived on. */
                do { GRAB_OUR_PACKETS(ifp) } while (0);
 
-       /*
-        * 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)
                }

Reply via email to