The branch main has been updated by ivy:

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

commit c41469a89f74e921ccbab09074c7b24edacbcc85
Author:     Lexi Winter <i...@freebsd.org>
AuthorDate: 2025-08-05 18:27:09 +0000
Commit:     Lexi Winter <i...@freebsd.org>
CommitDate: 2025-08-05 19:25:37 +0000

    ifconfig: Improve bridge vlan filtering syntax
    
    The current syntax to add an interface to a filtering bridge requires
    repeating the interface name up to three times:
    
            ifconfig bridge0 addm ix0 untagged ix0 10 tagged ix0 100-199
    
    Since at least one of these options nearly always needs to be set,
    this results in excessively verbose configuration.
    
    Extend "addm" to support optional arguments, and add two arguments,
    "untagged" and "tagged", which infer the interface name from the
    addm command.  Now the interface only has to be given once:
    
            ifconfig bridge0 addm ix0 untagged 10 tagged 100-199
    
    To avoid confusion with the existing untagged and tagged commands,
    rename those to ifuntagged and iftagged.
    
    In future, this syntax will make it possible to add an interface and
    set its vlan configuration atomically (once the API supports that),
    but switching to the new syntax now means we don't need to change it
    after 15.0.
    
    Differential Revision:  https://reviews.freebsd.org/D51707
---
 sbin/ifconfig/ifbridge.c        | 81 +++++++++++++++++++++++++++++++++--------
 sbin/ifconfig/ifconfig.8        | 31 ++++++++++++----
 tests/sys/net/if_bridge_test.sh | 73 +++++++++++++++++--------------------
 3 files changed, 122 insertions(+), 63 deletions(-)

diff --git a/sbin/ifconfig/ifbridge.c b/sbin/ifconfig/ifbridge.c
index d02d92d10b59..eff443447c13 100644
--- a/sbin/ifconfig/ifbridge.c
+++ b/sbin/ifconfig/ifbridge.c
@@ -60,6 +60,10 @@
 
 #include "ifconfig.h"
 
+static int     parse_vlans(ifbvlan_set_t *set, const char *str);
+static int     get_val(const char *cp, u_long *valp);
+static int     get_vlan_id(const char *cp, ether_vlanid_t *valp);
+
 static const char *stpstates[] = { STP_STATES };
 static const char *stpproto[] = { STP_PROTOS };
 static const char *stproles[] = { STP_ROLES };
@@ -288,15 +292,62 @@ bridge_status(if_ctx *ctx)
        ifconfig_bridge_free_bridge_status(bridge);
 }
 
-static void
-setbridge_add(if_ctx *ctx, const char *val, int dummy __unused)
+static int
+setbridge_add(if_ctx *ctx, int argc, const char *const *argv)
 {
        struct ifbreq req;
+       struct ifbif_vlan_req vlreq;
+       int oargc = argc;
 
        memset(&req, 0, sizeof(req));
-       strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
+       memset(&vlreq, 0, sizeof(vlreq));
+
+       if (argc < 1)
+               errx(1, "usage: addm <interface> [opts ...]");
+
+       strlcpy(req.ifbr_ifsname, argv[0], sizeof(req.ifbr_ifsname));
+       --argc; ++argv;
+
+       while (argc) {
+               if (strcmp(argv[0], "untagged") == 0) {
+                       if (argc < 2)
+                               errx(1, "usage: untagged <vlan id>");
+
+                       if (get_vlan_id(argv[1], &req.ifbr_pvid) < 0)
+                               errx(1, "invalid VLAN identifier: %s", argv[1]);
+
+                       argc -= 2;
+                       argv += 2;
+               } else if (strcmp(argv[0], "tagged") == 0) {
+                       if (argc < 2)
+                               errx(1, "usage: tagged <vlan set>");
+
+                       vlreq.bv_op = BRDG_VLAN_OP_SET;
+                       strlcpy(vlreq.bv_ifname, req.ifbr_ifsname,
+                           sizeof(vlreq.bv_ifname));
+                       if (parse_vlans(&vlreq.bv_set, argv[1]) != 0)
+                               errx(1, "invalid vlan set: %s", argv[1]);
+
+                       argc -= 2;
+                       argv += 2;
+               } else {
+                       break;
+               }
+       }
+
        if (do_cmd(ctx, BRDGADD, &req, sizeof(req), 1) < 0)
-               err(1, "BRDGADD %s",  val);
+               err(1, "BRDGADD %s", req.ifbr_ifsname);
+
+       if (req.ifbr_pvid != 0 &&
+           do_cmd(ctx, BRDGSIFPVID, &req, sizeof(req), 1) < 0)
+               err(1, "BRDGSIFPVID %s %u", req.ifbr_ifsname,
+                   (unsigned)req.ifbr_pvid);
+
+       if (vlreq.bv_op != 0 &&
+           do_cmd(ctx, BRDGSIFVLANSET, &vlreq, sizeof(vlreq), 1) < 0)
+               err(1, "BRDGSIFVLANSET %s", req.ifbr_ifsname);
+
+       return (oargc - argc);
 }
 
 static void
@@ -684,7 +735,7 @@ setbridge_ifpathcost(if_ctx *ctx, const char *ifn, const 
char *cost)
 }
 
 static void
-setbridge_untagged(if_ctx *ctx, const char *ifn, const char *vlanid)
+setbridge_ifuntagged(if_ctx *ctx, const char *ifn, const char *vlanid)
 {
        struct ifbreq req;
 
@@ -699,7 +750,7 @@ setbridge_untagged(if_ctx *ctx, const char *ifn, const char 
*vlanid)
 }
 
 static void
-unsetbridge_untagged(if_ctx *ctx, const char *ifn, int dummy __unused)
+unsetbridge_ifuntagged(if_ctx *ctx, const char *ifn, int dummy __unused)
 {
        struct ifbreq req;
 
@@ -831,19 +882,19 @@ set_bridge_vlanset(if_ctx *ctx, const char *ifn, const 
char *vlans, int op)
 }
 
 static void
-setbridge_tagged(if_ctx *ctx, const char *ifn, const char *vlans)
+setbridge_iftagged(if_ctx *ctx, const char *ifn, const char *vlans)
 {
        set_bridge_vlanset(ctx, ifn, vlans, BRDG_VLAN_OP_SET);
 }
 
 static void
-addbridge_tagged(if_ctx *ctx, const char *ifn, const char *vlans)
+addbridge_iftagged(if_ctx *ctx, const char *ifn, const char *vlans)
 {
        set_bridge_vlanset(ctx, ifn, vlans, BRDG_VLAN_OP_ADD);
 }
 
 static void
-delbridge_tagged(if_ctx *ctx, const char *ifn, const char *vlans)
+delbridge_iftagged(if_ctx *ctx, const char *ifn, const char *vlans)
 {
        set_bridge_vlanset(ctx, ifn, vlans, BRDG_VLAN_OP_DEL);
 }
@@ -933,7 +984,7 @@ setbridge_ifvlanproto(if_ctx *ctx, const char *ifname, 
const char *proto)
 }
 
 static struct cmd bridge_cmds[] = {
-       DEF_CMD_ARG("addm",             setbridge_add),
+       DEF_CMD_VARG("addm",            setbridge_add),
        DEF_CMD_ARG("deletem",          setbridge_delete),
        DEF_CMD_ARG("discover",         setbridge_discover),
        DEF_CMD_ARG("-discover",        unsetbridge_discover),
@@ -968,11 +1019,11 @@ static struct cmd bridge_cmds[] = {
        DEF_CMD_ARG2("ifpriority",      setbridge_ifpriority),
        DEF_CMD_ARG2("ifpathcost",      setbridge_ifpathcost),
        DEF_CMD_ARG2("ifmaxaddr",       setbridge_ifmaxaddr),
-       DEF_CMD_ARG2("untagged",        setbridge_untagged),
-       DEF_CMD_ARG("-untagged",        unsetbridge_untagged),
-       DEF_CMD_ARG2("tagged",          setbridge_tagged),
-       DEF_CMD_ARG2("+tagged",         addbridge_tagged),
-       DEF_CMD_ARG2("-tagged",         delbridge_tagged),
+       DEF_CMD_ARG2("ifuntagged",      setbridge_ifuntagged),
+       DEF_CMD_ARG("-ifuntagged",      unsetbridge_ifuntagged),
+       DEF_CMD_ARG2("iftagged",        setbridge_iftagged),
+       DEF_CMD_ARG2("+iftagged",       addbridge_iftagged),
+       DEF_CMD_ARG2("-iftagged",       delbridge_iftagged),
        DEF_CMD_ARG2("ifvlanproto",     setbridge_ifvlanproto),
        DEF_CMD_ARG("timeout",          setbridge_timeout),
        DEF_CMD_ARG("private",          setbridge_private),
diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8
index d7b2570ab20d..b562f9e4c0c5 100644
--- a/sbin/ifconfig/ifconfig.8
+++ b/sbin/ifconfig/ifconfig.8
@@ -2494,12 +2494,27 @@ compatibility.
 .Ss Bridge Interface Parameters
 The following parameters are specific to bridge interfaces:
 .Bl -tag -width indent
-.It Cm addm Ar interface
+.It Cm addm Ar interface Op Ar options ...
 Add the interface named by
 .Ar interface
 as a member of the bridge.
 The interface is put into promiscuous mode
 so that it can receive every packet sent on the network.
+.Pp
+The interface name may be followed by one or more of the following
+.Ar options :
+.Bl -tag -width ".Cm untagged Ar vlan-id"
+.It Cm untagged Ar vlan-id
+Set the untagged VLAN identifier for the interface.
+This is equivalent to the
+.Cm ifuntagged
+command.
+.It Cm tagged Ar vlan-set
+Set the allowed VLAN list for the interface.
+This is equivalent to the
+.Cm iftagged
+command.
+.El
 .It Cm deletem Ar interface
 Remove the interface named by
 .Ar interface
@@ -2715,9 +2730,9 @@ Enable VLAN filtering on the bridge.
 .It Cm -vlanfilter
 Disable VLAN filtering on the bridge.
 This is the default.
-.It Cm untagged Ar interface Ar vlan-id
+.It Cm ifuntagged Ar interface Ar vlan-id
 Set the untagged VLAN identifier for an interface.
-.It Cm -untagged Ar interface Ar vlan-id
+.It Cm -ifuntagged Ar interface Ar vlan-id
 Clear the untagged VLAN identifier for an interface.
 .It Cm defuntagged Ar vlan-id
 Enable the
@@ -2727,7 +2742,7 @@ option by default on newly added members.
 Do not enable the
 .Cm untagged
 option by default on newly added members.
-.It Cm tagged Ar interface Ar vlan-list
+.It Cm iftagged Ar interface Ar vlan-list
 Set the interface's VLAN access list to the provided list of VLANs.
 The list should be a comma-separated list of one or more VLAN IDs
 or ranges formatted as
@@ -2738,15 +2753,15 @@ meaning the empty set,
 or the value
 .Dq all
 meaning all VLANs (1-4094).
-.It Cm +tagged Ar interface Ar vlan-list
+.It Cm +iftagged Ar interface Ar vlan-list
 Add the provided list of VLAN IDs to the interface's VLAN access list.
 The list should be formatted as described for
-.Cm tagged .
-.It Cm -tagged Ar interface Ar vlan-list
+.Cm iftagged .
+.It Cm -iftagged Ar interface Ar vlan-list
 Remove the provided list of VLAN IDs from the interface's VLAN access
 list.
 The list should be formatted as described for
-.Cm tagged .
+.Cm iftagged .
 .It Cm qinq Ar interface
 Allow this interface to send 802.1ad
 .Dq Q-in-Q
diff --git a/tests/sys/net/if_bridge_test.sh b/tests/sys/net/if_bridge_test.sh
index 8a6c730014ce..906f586d2483 100755
--- a/tests/sys/net/if_bridge_test.sh
+++ b/tests/sys/net/if_bridge_test.sh
@@ -922,15 +922,15 @@ vlan_pvid_body()
        ifconfig ${bridge} vlanfilter up
        ifconfig ${epone}a up
        ifconfig ${eptwo}a up
-       ifconfig ${bridge} addm ${epone}a untagged ${epone}a 20
-       ifconfig ${bridge} addm ${eptwo}a untagged ${eptwo}a 20
+       ifconfig ${bridge} addm ${epone}a untagged 20
+       ifconfig ${bridge} addm ${eptwo}a untagged 20
 
        # With VLAN filtering enabled, traffic should be passed.
        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
 
        # Removed the untagged VLAN on one port; traffic should not be passed.
-       ifconfig ${bridge} -untagged ${epone}a
+       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
 }
@@ -966,10 +966,8 @@ vlan_pvid_filtered_body()
        atf_check -s exit:0 ifconfig ${bridge} vlanfilter up
        atf_check -s exit:0 ifconfig ${epone}a up
        atf_check -s exit:0 ifconfig ${eptwo}a up
-       atf_check -s exit:0 ifconfig ${bridge} \
-           addm ${epone}a untagged ${epone}a 20
-       atf_check -s exit:0 ifconfig ${bridge} \
-           addm ${eptwo}a untagged ${eptwo}a 30
+       atf_check -s exit:0 ifconfig ${bridge} addm ${epone}a untagged 20
+       atf_check -s exit:0 ifconfig ${bridge} addm ${eptwo}a untagged 30
 
        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
@@ -1011,10 +1009,8 @@ vlan_pvid_tagged_body()
        atf_check -s exit:0 ifconfig ${bridge} vlanfilter up
        atf_check -s exit:0 ifconfig ${epone}a up
        atf_check -s exit:0 ifconfig ${eptwo}a up
-       atf_check -s exit:0 ifconfig ${bridge} \
-           addm ${epone}a untagged ${epone}a 20
-       atf_check -s exit:0 ifconfig ${bridge} \
-           addm ${eptwo}a untagged ${eptwo}a 20
+       atf_check -s exit:0 ifconfig ${bridge} addm ${epone}a untagged 20
+       atf_check -s exit:0 ifconfig ${bridge} addm ${eptwo}a untagged 20
 
        # Tagged frames should not be passed.
        atf_check -s exit:2 -o ignore jexec one ping -c 3 -t 1 192.0.2.2
@@ -1055,10 +1051,8 @@ vlan_pvid_1q_body()
        bridge=$(vnet_mkbridge)
 
        atf_check -s exit:0 ifconfig ${bridge} vlanfilter up
-       atf_check -s exit:0 ifconfig ${bridge} \
-           addm ${epone}a untagged ${epone}a 20
-       atf_check -s exit:0 ifconfig ${bridge} addm ${eptwo}a \
-           tagged ${eptwo}a 20
+       atf_check -s exit:0 ifconfig ${bridge} addm ${epone}a untagged 20
+       atf_check -s exit:0 ifconfig ${bridge} addm ${eptwo}a tagged 20
 
        atf_check -s exit:0 ifconfig ${epone}a up
        atf_check -s exit:0 ifconfig ${eptwo}a up
@@ -1116,25 +1110,25 @@ vlan_filtering_body()
        # Set the untagged vlan on both ports to 20 and make sure traffic is
        # still blocked.  We intentionally do not pass tagged traffic for the
        # untagged vlan.
-       atf_check -s exit:0 ifconfig ${bridge} untagged ${epone}a 20
-       atf_check -s exit:0 ifconfig ${bridge} untagged ${eptwo}a 20
+       atf_check -s exit:0 ifconfig ${bridge} ifuntagged ${epone}a 20
+       atf_check -s exit:0 ifconfig ${bridge} ifuntagged ${eptwo}a 20
 
        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
 
-       atf_check -s exit:0 ifconfig ${bridge} -untagged ${epone}a
-       atf_check -s exit:0 ifconfig ${bridge} -untagged ${eptwo}a
+       atf_check -s exit:0 ifconfig ${bridge} -ifuntagged ${epone}a
+       atf_check -s exit:0 ifconfig ${bridge} -ifuntagged ${eptwo}a
 
        # Add VLANs 10-30 to the access list; now access should be allowed.
-       atf_check -s exit:0 ifconfig ${bridge} +tagged ${epone}a 10-30
-       atf_check -s exit:0 ifconfig ${bridge} +tagged ${eptwo}a 10-30
+       atf_check -s exit:0 ifconfig ${bridge} +iftagged ${epone}a 10-30
+       atf_check -s exit:0 ifconfig ${bridge} +iftagged ${eptwo}a 10-30
        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 vlan 20 from the access list, now access should be blocked
        # again.
-       atf_check -s exit:0 ifconfig ${bridge} -tagged ${epone}a 20
-       atf_check -s exit:0 ifconfig ${bridge} -tagged ${eptwo}a 20
+       atf_check -s exit:0 ifconfig ${bridge} -iftagged ${epone}a 20
+       atf_check -s exit:0 ifconfig ${bridge} -iftagged ${eptwo}a 20
        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
 }
@@ -1145,16 +1139,16 @@ vlan_filtering_cleanup()
 }
 
 #
-# Test the ifconfig 'tagged' option.
+# Test the ifconfig 'iftagged' option.
 #
-atf_test_case "vlan_ifconfig_tagged" "cleanup"
-vlan_ifconfig_tagged_head()
+atf_test_case "vlan_ifconfig_iftagged" "cleanup"
+vlan_ifconfig_iftagged_head()
 {
-       atf_set descr 'test the ifconfig tagged option'
+       atf_set descr 'test the ifconfig iftagged option'
        atf_set require.user root
 }
 
-vlan_ifconfig_tagged_body()
+vlan_ifconfig_iftagged_body()
 {
        vnet_init
        vnet_init_bridge
@@ -1170,34 +1164,34 @@ vlan_ifconfig_tagged_body()
        atf_check -s exit:0 -o not-match:"tagged" ifconfig ${bridge}
 
        # Add vlans 100-149.
-       atf_check -s exit:0 ifconfig ${bridge} tagged ${ep}a 100-149
+       atf_check -s exit:0 ifconfig ${bridge} iftagged ${ep}a 100-149
        atf_check -s exit:0 -o match:"tagged 100-149" ifconfig ${bridge}
 
        # Replace the vlan list with 139-199.
-       atf_check -s exit:0 ifconfig ${bridge} tagged ${ep}a 139-199
+       atf_check -s exit:0 ifconfig ${bridge} iftagged ${ep}a 139-199
        atf_check -s exit:0 -o match:"tagged 139-199" ifconfig ${bridge}
 
        # Add vlans 100-170.
-       atf_check -s exit:0 ifconfig ${bridge} +tagged ${ep}a 100-170
+       atf_check -s exit:0 ifconfig ${bridge} +iftagged ${ep}a 100-170
        atf_check -s exit:0 -o match:"tagged 100-199" ifconfig ${bridge}
 
        # Remove vlans 104, 105, and 150-159
-       atf_check -s exit:0 ifconfig ${bridge} -tagged ${ep}a 104,105,150-159
+       atf_check -s exit:0 ifconfig ${bridge} -iftagged ${ep}a 104,105,150-159
        atf_check -s exit:0 -o match:"tagged 100-103,106-149,160-199" \
            ifconfig ${bridge}
 
        # Remove the entire vlan list.
-       atf_check -s exit:0 ifconfig ${bridge} tagged ${ep}a none
+       atf_check -s exit:0 ifconfig ${bridge} iftagged ${ep}a none
        atf_check -s exit:0 -o not-match:"tagged" ifconfig ${bridge}
 
        # Test some invalid vlans sets.
        for bad_vlan in -1 0 4096 4097 foo 0-10 4000-5000 foo-40 40-foo; do
                atf_check -s exit:1 -e ignore \
-                   ifconfig ${bridge} tagged "$bad_vlan"
+                   ifconfig ${bridge} iftagged "$bad_vlan"
        done
 }
 
-vlan_ifconfig_tagged_cleanup()
+vlan_ifconfig_iftagged_cleanup()
 {
        vnet_cleanup
 }
@@ -1229,8 +1223,7 @@ vlan_svi_body()
 
        atf_check -s exit:0 ifconfig ${bridge} vlanfilter up
        atf_check -s exit:0 ifconfig ${epone}a up
-       atf_check -s exit:0 ifconfig ${bridge} addm ${epone}a \
-           tagged ${epone}a 20
+       atf_check -s exit:0 ifconfig ${bridge} addm ${epone}a tagged 20
 
        svi=$(vnet_mkvlan)
        atf_check -s exit:0 ifconfig ${svi} vlan 20 vlandev ${bridge}
@@ -1294,8 +1287,8 @@ vlan_qinq_body()
        atf_check -s exit:2 -o ignore jexec two ping -c 3 -t 1 192.0.2.1
 
        # Add the provider tag to the access list; now traffic should be passed.
-       atf_check -s exit:0 ifconfig ${bridge} +tagged ${epone}a 5
-       atf_check -s exit:0 ifconfig ${bridge} +tagged ${eptwo}a 5
+       atf_check -s exit:0 ifconfig ${bridge} +iftagged ${epone}a 5
+       atf_check -s exit:0 ifconfig ${bridge} +iftagged ${eptwo}a 5
        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
 
@@ -1411,7 +1404,7 @@ atf_init_test_cases()
        atf_add_test_case "vlan_pvid_filtered"
        atf_add_test_case "vlan_pvid_tagged"
        atf_add_test_case "vlan_filtering"
-       atf_add_test_case "vlan_ifconfig_tagged"
+       atf_add_test_case "vlan_ifconfig_iftagged"
        atf_add_test_case "vlan_svi"
        atf_add_test_case "vlan_qinq"
        atf_add_test_case "vlan_defuntagged"

Reply via email to