The branch main has been updated by ivy:

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

commit 43ac5806a5a3150f561e14a11866dd56cf1b4d42
Author:     Lexi Winter <i...@freebsd.org>
AuthorDate: 2025-08-10 15:11:32 +0000
Commit:     Lexi Winter <i...@freebsd.org>
CommitDate: 2025-08-10 15:36:40 +0000

    bridge: Divorce ifuntagged from vlanfilter
    
    The ifuntagged option was added as part of the VLAN filtering feature,
    but it's useful on its own to be able to place interface traffic in a
    VLAN without having to configure every interface for VLAN filtering.
    
    Always do the pvid processing in bridge even if IFBRF_VLANFILTER isn't
    enabled, and don't prohibit configuring it.
    
    Add a test for the specific case of setting untagged without vlanfilter.
    
    This has no effect on bridges which don't have at least one interface
    configured with ifuntagged.
    
    Differential Revision:  https://reviews.freebsd.org/D51760
---
 sys/net/if_bridge.c             | 28 ++++++++++++---------
 tests/sys/net/if_bridge_test.sh | 54 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 68 insertions(+), 14 deletions(-)

diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 1e444be93e9f..66555fd1feb5 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -1500,8 +1500,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg)
        bif->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER;
        bif->bif_savedcaps = ifs->if_capenable;
        bif->bif_vlanproto = ETHERTYPE_VLAN;
-       if (sc->sc_flags & IFBRF_VLANFILTER)
-               bif->bif_pvid = sc->sc_defpvid;
+       bif->bif_pvid = sc->sc_defpvid;
        if (sc->sc_flags & IFBRF_DEFQINQ)
                bif->bif_flags |= IFBIF_QINQ;
 
@@ -1970,9 +1969,6 @@ bridge_ioctl_sifpvid(struct bridge_softc *sc, void *arg)
        struct ifbreq *req = arg;
        struct bridge_iflist *bif;
 
-       if ((sc->sc_flags & IFBRF_VLANFILTER) == 0)
-               return (EXTERROR(EINVAL, "VLAN filtering not enabled"));
-
        bif = bridge_lookup_member(sc, req->ifbr_ifsname);
        if (bif == NULL)
                return (EXTERROR(ENOENT, "Interface is not a bridge member"));
@@ -2410,12 +2406,10 @@ bridge_enqueue(struct bridge_softc *sc, struct ifnet 
*dst_ifp, struct mbuf *m,
                mflags = m->m_flags;
 
                /*
-                * If VLAN filtering is enabled, and the native VLAN ID of the
-                * outgoing interface matches the VLAN ID of the frame, remove
-                * the VLAN header.
+                * If the native VLAN ID of the outgoing interface matches the
+                * VLAN ID of the frame, remove the VLAN tag.
                 */
-               if ((sc->sc_flags & IFBRF_VLANFILTER) &&
-                   bif->bif_pvid != DOT1Q_VID_NULL &&
+               if (bif->bif_pvid != DOT1Q_VID_NULL &&
                    VLANTAGOF(m) == bif->bif_pvid) {
                        m->m_flags &= ~M_VLANTAG;
                        m->m_pkthdr.ether_vtag = 0;
@@ -3296,9 +3290,19 @@ bridge_vfilter_in(const struct bridge_iflist *sbif, 
struct mbuf *m)
        if (vlan > DOT1Q_VID_MAX)
                return (false);
 
-       /* If VLAN filtering isn't enabled, pass everything. */
-       if ((sbif->bif_sc->sc_flags & IFBRF_VLANFILTER) == 0)
+       /*
+        * If VLAN filtering isn't enabled, pass everything, but add a tag
+        * if the port has a pvid configured.
+        */
+       if ((sbif->bif_sc->sc_flags & IFBRF_VLANFILTER) == 0) {
+               if (vlan == DOT1Q_VID_NULL &&
+                   sbif->bif_pvid != DOT1Q_VID_NULL) {
+                       m->m_pkthdr.ether_vtag = sbif->bif_pvid;
+                       m->m_flags |= M_VLANTAG;
+               }
+
                return (true);
+       }
 
        /* If Q-in-Q is disabled, check for stacked tags. */
        if ((sbif->bif_flags & IFBIF_QINQ) == 0) {
diff --git a/tests/sys/net/if_bridge_test.sh b/tests/sys/net/if_bridge_test.sh
index 906f586d2483..0c19903714b1 100755
--- a/tests/sys/net/if_bridge_test.sh
+++ b/tests/sys/net/if_bridge_test.sh
@@ -899,7 +899,7 @@ member_ifaddrs_vlan_cleanup()
 atf_test_case "vlan_pvid" "cleanup"
 vlan_pvid_head()
 {
-       atf_set descr 'bridge with two ports with pvid set'
+       atf_set descr 'bridge with two ports with pvid and vlanfilter set'
        atf_set require.user root
 }
 
@@ -1327,6 +1327,56 @@ bridge_svi_in_bridge_cleanup()
        vnet_cleanup
 }
 
+atf_test_case "vlan_untagged" "cleanup"
+vlan_untagged_head()
+{
+       atf_set descr 'bridge with two ports with untagged set'
+       atf_set require.user root
+}
+
+vlan_untagged_body()
+{
+       vnet_init
+       vnet_init_bridge
+
+       epone=$(vnet_mkepair)
+       eptwo=$(vnet_mkepair)
+
+       vnet_mkjail one ${epone}b
+       vnet_mkjail two ${eptwo}b
+
+       jexec one ifconfig ${epone}b 192.0.2.1/24 up
+       jexec two ifconfig ${eptwo}b 192.0.2.2/24 up
+
+       bridge=$(vnet_mkbridge)
+
+       ifconfig ${bridge} up
+       ifconfig ${epone}a up
+       ifconfig ${eptwo}a up
+       ifconfig ${bridge} addm ${epone}a untagged 20
+       ifconfig ${bridge} addm ${eptwo}a untagged 30
+
+       # With two ports on different VLANs, traffic should not be passed.
+       atf_check -s exit:2 -o ignore jexec one ping -c 3 -t 1 192.0.2.2
+       atf_check -s exit:2 -o ignore jexec two ping -c 3 -t 1 192.0.2.1
+
+       # Move the second port to VLAN 20; now traffic should be passed.
+       atf_check -s exit:0 ifconfig ${bridge} ifuntagged ${eptwo}a 20
+       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
+
+       # Remove the first's port untagged config, now traffic should
+       # not pass again.
+       atf_check -s exit:0 ifconfig ${bridge} -ifuntagged ${epone}a
+       atf_check -s exit:2 -o ignore jexec one ping -c 3 -t 1 192.0.2.2
+       atf_check -s exit:2 -o ignore jexec two ping -c 3 -t 1 192.0.2.1
+}
+
+vlan_untagged_cleanup()
+{
+       vnet_cleanup
+}
+
 atf_test_case "vlan_defuntagged" "cleanup"
 vlan_defuntagged_head()
 {
@@ -1340,7 +1390,6 @@ vlan_defuntagged_body()
        vnet_init_bridge
 
        bridge=$(vnet_mkbridge)
-       atf_check -s exit:0 ifconfig ${bridge} vlanfilter
 
        # Invalid VLAN IDs
        atf_check -s exit:1 -ematch:"invalid vlan id: 0" \
@@ -1407,6 +1456,7 @@ atf_init_test_cases()
        atf_add_test_case "vlan_ifconfig_iftagged"
        atf_add_test_case "vlan_svi"
        atf_add_test_case "vlan_qinq"
+       atf_add_test_case "vlan_untagged"
        atf_add_test_case "vlan_defuntagged"
        atf_add_test_case "bridge_svi_in_bridge"
 }

Reply via email to