The branch main has been updated by ivy: URL: https://cgit.FreeBSD.org/src/commit/?id=ce06c1921e0c8f1e7999acdf371c756e80a3c709
commit ce06c1921e0c8f1e7999acdf371c756e80a3c709 Author: Lexi Winter <i...@freebsd.org> AuthorDate: 2025-08-03 22:54:59 +0000 Commit: Lexi Winter <i...@freebsd.org> CommitDate: 2025-08-03 22:55:10 +0000 bridge: Add a vlanfilter bridge option vlanfilter was originally a per-interface flag to allow more flexible configurations where some interfaces had VLAN filtering enabled and some didn't. In practice, this just makes the configuration more confusing without any real benefit, so remove it, and make vlanfilter a bridge flag instead. Add a new bridge option "defuntagged", which sets the automatically assigned PVID for new members. If set to 0 (the default) then no PVID is assigned, which matches the current behaviour. While here, add some more atf_checks to the bridge VLAN tests to make debugging easier. Differential Revision: https://reviews.freebsd.org/D51600 --- lib/libifconfig/libifconfig.h | 2 + lib/libifconfig/libifconfig_bridge.c | 12 +++ sbin/ifconfig/ifbridge.c | 80 +++++++++++++---- sbin/ifconfig/ifconfig.8 | 33 +++---- share/man/man4/bridge.4 | 4 +- sys/net/if_bridge.c | 84 +++++++++++++++--- sys/net/if_bridgevar.h | 21 ++++- tests/sys/net/if_bridge_test.sh | 161 +++++++++++++++++++++++++---------- 8 files changed, 299 insertions(+), 98 deletions(-) diff --git a/lib/libifconfig/libifconfig.h b/lib/libifconfig/libifconfig.h index fc835485a51e..b2f0cf9744ea 100644 --- a/lib/libifconfig/libifconfig.h +++ b/lib/libifconfig/libifconfig.h @@ -69,6 +69,8 @@ struct ifconfig_bridge_status { size_t members_count; /**< how many member interfaces */ uint32_t cache_size; /**< size of address cache */ uint32_t cache_lifetime; /**< address cache entry lifetime */ + ifbr_flags_t flags; /**< bridge flags */ + ether_vlanid_t defpvid; /**< default pvid */ }; struct ifconfig_capabilities { diff --git a/lib/libifconfig/libifconfig_bridge.c b/lib/libifconfig/libifconfig_bridge.c index b4a920f488c5..675bf5dd2ff5 100644 --- a/lib/libifconfig/libifconfig_bridge.c +++ b/lib/libifconfig/libifconfig_bridge.c @@ -92,6 +92,18 @@ ifconfig_bridge_get_bridge_status(ifconfig_handle_t *h, } bridge->inner.cache_lifetime = cache_param.ifbrp_ctime; + if (ifconfig_bridge_ioctlwrap(h, name, BRDGGFLAGS, + &cache_param, sizeof(cache_param), false) != 0) { + goto err; + } + bridge->inner.flags = cache_param.ifbrp_flags; + + if (ifconfig_bridge_ioctlwrap(h, name, BRDGGDEFPVID, + &cache_param, sizeof(cache_param), false) != 0) { + goto err; + } + bridge->inner.defpvid = cache_param.ifbrp_defpvid; + if (ifconfig_bridge_ioctlwrap(h, name, BRDGPARAM, &bridge->params, sizeof(bridge->params), false) != 0) { goto err; diff --git a/sbin/ifconfig/ifbridge.c b/sbin/ifconfig/ifbridge.c index 1a8c4c6e9c3e..335ed9bf513f 100644 --- a/sbin/ifconfig/ifbridge.c +++ b/sbin/ifconfig/ifbridge.c @@ -223,6 +223,11 @@ bridge_status(if_ctx *ctx) params->ifbop_root_path_cost, params->ifbop_root_port & 0xfff); + printb("\tbridge flags", bridge->flags, IFBRFBITS); + if (bridge->defpvid) + printf(" defuntagged=%u", (unsigned) bridge->defpvid); + printf("\n"); + prefix = "\tmember: "; pad = "\t "; for (size_t i = 0; i < bridge->members_count; ++i) { @@ -514,7 +519,6 @@ setbridge_deladdr(if_ctx *ctx, int argc, const char *const *argv) static void setbridge_addr(if_ctx *ctx, const char *val __unused, int dummy __unused) { - bridge_addresses(ctx, ""); } @@ -735,18 +739,6 @@ unsetbridge_private(if_ctx *ctx, const char *val, int dummy __unused) do_bridgeflag(ctx, val, IFBIF_PRIVATE, 0); } -static void -setbridge_vlanfilter(if_ctx *ctx, const char *val, int dummy __unused) -{ - do_bridgeflag(ctx, val, IFBIF_VLANFILTER, 1); -} - -static void -unsetbridge_vlanfilter(if_ctx *ctx, const char *val, int dummy __unused) -{ - do_bridgeflag(ctx, val, IFBIF_VLANFILTER, 0); -} - static int parse_vlans(ifbvlan_set_t *set, const char *str) { @@ -838,6 +830,59 @@ delbridge_tagged(if_ctx *ctx, const char *ifn, const char *vlans) set_bridge_vlanset(ctx, ifn, vlans, BRDG_VLAN_OP_DEL); } +static void +setbridge_flags(if_ctx *ctx, const char *val __unused, int newflags) +{ + struct ifbrparam req; + + if (do_cmd(ctx, BRDGGFLAGS, &req, sizeof(req), 0) < 0) + err(1, "BRDGGFLAGS"); + + req.ifbrp_flags |= (uint32_t)newflags; + + if (do_cmd(ctx, BRDGSFLAGS, &req, sizeof(req), 1) < 0) + err(1, "BRDGSFLAGS"); +} + +static void +unsetbridge_flags(if_ctx *ctx, const char *val __unused, int newflags) +{ + struct ifbrparam req; + + if (do_cmd(ctx, BRDGGFLAGS, &req, sizeof(req), 0) < 0) + err(1, "BRDGGFLAGS"); + + req.ifbrp_flags &= ~(uint32_t)newflags; + + if (do_cmd(ctx, BRDGSFLAGS, &req, sizeof(req), 1) < 0) + err(1, "BRDGSFLAGS"); +} + +static void +setbridge_defuntagged(if_ctx *ctx, const char *arg, int dummy __unused) +{ + struct ifbrparam req; + + memset(&req, 0, sizeof(req)); + if (get_vlan_id(arg, &req.ifbrp_defpvid) < 0) + errx(1, "invalid vlan id: %s", arg); + + if (do_cmd(ctx, BRDGSDEFPVID, &req, sizeof(req), 1) < 0) + err(1, "BRDGSDEFPVID"); +} + +static void +unsetbridge_defuntagged(if_ctx *ctx, const char *val __unused, int dummy __unused) +{ + struct ifbrparam req; + + memset(&req, 0, sizeof(req)); + req.ifbrp_defpvid = 0; + + if (do_cmd(ctx, BRDGSDEFPVID, &req, sizeof(req), 1) < 0) + err(1, "BRDGSDEFPVID"); +} + static struct cmd bridge_cmds[] = { DEF_CMD_ARG("addm", setbridge_add), DEF_CMD_ARG("deletem", setbridge_delete), @@ -874,8 +919,6 @@ 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_ARG("vlanfilter", setbridge_vlanfilter), - DEF_CMD_ARG("-vlanfilter", unsetbridge_vlanfilter), DEF_CMD_ARG2("untagged", setbridge_untagged), DEF_CMD_ARG("-untagged", unsetbridge_untagged), DEF_CMD_ARG2("tagged", setbridge_tagged), @@ -884,7 +927,14 @@ static struct cmd bridge_cmds[] = { DEF_CMD_ARG("timeout", setbridge_timeout), DEF_CMD_ARG("private", setbridge_private), DEF_CMD_ARG("-private", unsetbridge_private), + DEF_CMD("vlanfilter", (int32_t)IFBRF_VLANFILTER, + setbridge_flags), + DEF_CMD("-vlanfilter", (int32_t)IFBRF_VLANFILTER, + unsetbridge_flags), + DEF_CMD_ARG("defuntagged", setbridge_defuntagged), + DEF_CMD("-defuntagged", 0, unsetbridge_defuntagged), }; + static struct afswtch af_bridge = { .af_name = "af_bridge", .af_af = AF_UNSPEC, diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 index 6a50a91880ef..06ec62197fba 100644 --- a/sbin/ifconfig/ifconfig.8 +++ b/sbin/ifconfig/ifconfig.8 @@ -2710,18 +2710,23 @@ The behaviour of these options is described in the section of .Xr bridge 4 . .Bl -tag -width indent -.It Cm vlanfilter Ar interface -Enable VLAN filtering on an interface. -.It Cm -vlanfilter Ar interface -Disable VLAN filtering on an interface. +.It Cm vlanfilter +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 Set the untagged VLAN identifier for an interface. -.Pp -Setting -.Cm untagged -will automatically enable VLAN filtering on the interface. .It Cm -untagged Ar interface Ar vlan-id Clear the untagged VLAN identifier for an interface. +.It Cm defuntagged Ar vlan-id +Enable the +.Cm untagged +option by default on newly added members. +.It Cm -defuntagged +Do not enable the +.Cm untagged +option by default on newly added members. .It Cm tagged 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 @@ -2733,27 +2738,15 @@ meaning the empty set, or the value .Dq all meaning all VLANs (1-4094). -.Pp -Setting -.Cm tagged -will automatically enable VLAN filtering on the interface. .It Cm +tagged 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 . -.Pp -Setting -.Cm +tagged -will automatically enable VLAN filtering on the interface. .It Cm -tagged 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 . -.Pp -Setting -.Cm -tagged -will automatically enable VLAN filtering on the interface. .El .Ss Link Aggregation and Link Failover Parameters The following parameters are specific to lagg interfaces: diff --git a/share/man/man4/bridge.4 b/share/man/man4/bridge.4 index 2dff393ebc29..7048df4593bf 100644 --- a/share/man/man4/bridge.4 +++ b/share/man/man4/bridge.4 @@ -36,7 +36,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd July 5, 2025 +.Dd July 28, 2025 .Dt IF_BRIDGE 4 .Os .Sh NAME @@ -289,7 +289,7 @@ interface on the bridge and (if necessary) assign IP addresses there. By default no access control is enabled, so any interface may participate in any VLAN. .Pp -VLAN filtering may be enabled on an interface using the +VLAN filtering may be enabled on a bridge using the .Xr ifconfig 8 .Cm vlanfilter option. diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 0a35fb4095fb..46e54339a171 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -300,6 +300,8 @@ struct bridge_softc { struct ether_addr sc_defaddr; /* Default MAC address */ if_input_fn_t sc_if_input; /* Saved copy of if_input */ struct epoch_context sc_epoch_ctx; + ifbr_flags_t sc_flags; /* bridge flags */ + ether_vlanid_t sc_defpvid; /* default PVID */ }; VNET_DEFINE_STATIC(struct sx, bridge_list_sx); @@ -417,6 +419,10 @@ static int bridge_ioctl_grte(struct bridge_softc *, void *); static int bridge_ioctl_gifsstp(struct bridge_softc *, void *); static int bridge_ioctl_sproto(struct bridge_softc *, void *); static int bridge_ioctl_stxhc(struct bridge_softc *, void *); +static int bridge_ioctl_gflags(struct bridge_softc *, void *); +static int bridge_ioctl_sflags(struct bridge_softc *, void *); +static int bridge_ioctl_gdefpvid(struct bridge_softc *, void *); +static int bridge_ioctl_sdefpvid(struct bridge_softc *, void *); static int bridge_pfil(struct mbuf **, struct ifnet *, struct ifnet *, int); #ifdef INET @@ -636,6 +642,18 @@ static const struct bridge_control bridge_control_table[] = { { bridge_ioctl_gifvlanset, sizeof(struct ifbif_vlan_req), BC_F_COPYIN|BC_F_COPYOUT }, + + { bridge_ioctl_gflags, sizeof(struct ifbrparam), + BC_F_COPYOUT }, + + { bridge_ioctl_sflags, sizeof(struct ifbrparam), + BC_F_COPYIN|BC_F_SUSER }, + + { bridge_ioctl_gdefpvid, sizeof(struct ifbrparam), + BC_F_COPYOUT }, + + { bridge_ioctl_sdefpvid, sizeof(struct ifbrparam), + BC_F_COPYIN|BC_F_SUSER }, }; static const int bridge_control_table_size = nitems(bridge_control_table); @@ -1476,6 +1494,8 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) bif->bif_ifp = ifs; bif->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER; bif->bif_savedcaps = ifs->if_capenable; + if (sc->sc_flags & IFBRF_VLANFILTER) + bif->bif_pvid = sc->sc_defpvid; /* * Assign the interface's MAC address to the bridge if it's the first @@ -1941,6 +1961,9 @@ 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")); @@ -1948,8 +1971,6 @@ bridge_ioctl_sifpvid(struct bridge_softc *sc, void *arg) if (req->ifbr_pvid > DOT1Q_VID_MAX) return (EXTERROR(EINVAL, "Invalid VLAN ID")); - if (req->ifbr_pvid != DOT1Q_VID_NULL) - bif->bif_flags |= IFBIF_VLANFILTER; bif->bif_pvid = req->ifbr_pvid; return (0); } @@ -1960,6 +1981,9 @@ bridge_ioctl_sifvlanset(struct bridge_softc *sc, void *arg) struct ifbif_vlan_req *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->bv_ifname); if (bif == NULL) return (EXTERROR(ENOENT, "Interface is not a bridge member")); @@ -1991,12 +2015,6 @@ bridge_ioctl_sifvlanset(struct bridge_softc *sc, void *arg) "Unsupported BRDGSIFVLANSET operation")); } - /* - * The only reason to modify the VLAN access list is to use VLAN - * filtering on this interface, so enable it automatically. - */ - bif->bif_flags |= IFBIF_VLANFILTER; - return (0); } @@ -2190,6 +2208,50 @@ bridge_ioctl_stxhc(struct bridge_softc *sc, void *arg) return (bstp_set_holdcount(&sc->sc_stp, param->ifbrp_txhc)); } +static int +bridge_ioctl_gflags(struct bridge_softc *sc, void *arg) +{ + struct ifbrparam *param = arg; + + param->ifbrp_flags = sc->sc_flags; + + return (0); +} + +static int +bridge_ioctl_sflags(struct bridge_softc *sc, void *arg) +{ + struct ifbrparam *param = arg; + + sc->sc_flags = param->ifbrp_flags; + + return (0); +} + +static int +bridge_ioctl_gdefpvid(struct bridge_softc *sc, void *arg) +{ + struct ifbrparam *param = arg; + + param->ifbrp_defpvid = sc->sc_defpvid; + + return (0); +} + +static int +bridge_ioctl_sdefpvid(struct bridge_softc *sc, void *arg) +{ + struct ifbrparam *param = arg; + + /* Reject invalid VIDs, but allow 0 to mean 'none'. */ + if (param->ifbrp_defpvid > DOT1Q_VID_MAX) + return (EINVAL); + + sc->sc_defpvid = param->ifbrp_defpvid; + + return (0); +} + /* * bridge_ifdetach: * @@ -2325,7 +2387,7 @@ bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m, * outgoing interface matches the VLAN ID of the frame, remove * the VLAN header. */ - if ((bif->bif_flags & IFBIF_VLANFILTER) && + if ((sc->sc_flags & IFBRF_VLANFILTER) && bif->bif_pvid != DOT1Q_VID_NULL && VLANTAGOF(m) == bif->bif_pvid) { m->m_flags &= ~M_VLANTAG; @@ -3185,7 +3247,7 @@ bridge_vfilter_in(const struct bridge_iflist *sbif, struct mbuf *m) return (false); /* If VLAN filtering isn't enabled, pass everything. */ - if ((sbif->bif_flags & IFBIF_VLANFILTER) == 0) + if ((sbif->bif_sc->sc_flags & IFBRF_VLANFILTER) == 0) return (true); if (vlan == DOT1Q_VID_NULL) { @@ -3231,7 +3293,7 @@ bridge_vfilter_out(const struct bridge_iflist *dbif, const struct mbuf *m) NET_EPOCH_ASSERT(); /* If VLAN filtering isn't enabled, pass everything. */ - if ((dbif->bif_flags & IFBIF_VLANFILTER) == 0) + if ((dbif->bif_sc->sc_flags & IFBRF_VLANFILTER) == 0) return (true); vlan = VLANTAGOF(m); diff --git a/sys/net/if_bridgevar.h b/sys/net/if_bridgevar.h index c458dcc152a0..6718c5ebcc34 100644 --- a/sys/net/if_bridgevar.h +++ b/sys/net/if_bridgevar.h @@ -127,6 +127,17 @@ #define BRDGSIFPVID 31 /* set if PVID */ #define BRDGSIFVLANSET 32 /* set if vlan set */ #define BRDGGIFVLANSET 33 /* get if vlan set */ +#define BRDGGFLAGS 34 /* get bridge flags (ifbrparam) */ +#define BRDGSFLAGS 35 /* set bridge flags (ifbrparam) */ +#define BRDGGDEFPVID 36 /* get default pvid (ifbrparam) */ +#define BRDGSDEFPVID 37 /* set default pvid (ifbrparam) */ + +/* BRDGSFLAGS, Bridge flags (non-interface-specific) */ +typedef uint32_t ifbr_flags_t; + +#define IFBRF_VLANFILTER (1U<<0) /* VLAN filtering enabled */ + +#define IFBRFBITS "\020\01VLANFILTER" /* * Generic bridge control request. @@ -161,11 +172,12 @@ struct ifbreq { #define IFBIF_BSTP_ADMEDGE 0x0200 /* member stp admin edge enabled */ #define IFBIF_BSTP_ADMCOST 0x0400 /* member stp admin path cost */ #define IFBIF_PRIVATE 0x0800 /* if is a private segment */ -#define IFBIF_VLANFILTER 0x1000 /* if does vlan filtering */ +/* was IFBIF_VLANFILTER 0x1000 */ +#define IFBIF_QINQ 0x2000 /* if allows 802.1ad Q-in-Q */ #define IFBIFBITS "\020\001LEARNING\002DISCOVER\003STP\004SPAN" \ "\005STICKY\014PRIVATE\006EDGE\007AUTOEDGE\010PTP" \ - "\011AUTOPTP\015VLANFILTER" + "\011AUTOPTP" #define IFBIFMASK ~(IFBIF_BSTP_EDGE|IFBIF_BSTP_AUTOEDGE|IFBIF_BSTP_PTP| \ IFBIF_BSTP_AUTOPTP|IFBIF_BSTP_ADMEDGE| \ IFBIF_BSTP_ADMCOST) /* not saved */ @@ -237,7 +249,10 @@ struct ifbrparam { #define ifbrp_fwddelay ifbrp_ifbrpu.ifbrpu_int8 /* fwd time (sec) */ #define ifbrp_maxage ifbrp_ifbrpu.ifbrpu_int8 /* max age (sec) */ #define ifbrp_cexceeded ifbrp_ifbrpu.ifbrpu_int32 /* # of cache dropped - * adresses */ + * addresses */ +#define ifbrp_flags ifbrp_ifbrpu.ifbrpu_int32 /* bridge flags */ +#define ifbrp_defpvid ifbrp_ifbrpu.ifbrpu_int16 /* default pvid */ + /* * Bridge current operational parameters structure. */ diff --git a/tests/sys/net/if_bridge_test.sh b/tests/sys/net/if_bridge_test.sh index 31299c562510..534144f46632 100755 --- a/tests/sys/net/if_bridge_test.sh +++ b/tests/sys/net/if_bridge_test.sh @@ -919,7 +919,7 @@ vlan_pvid_body() bridge=$(vnet_mkbridge) - ifconfig ${bridge} up + ifconfig ${bridge} vlanfilter up ifconfig ${epone}a up ifconfig ${eptwo}a up ifconfig ${bridge} addm ${epone}a untagged ${epone}a 20 @@ -958,16 +958,18 @@ vlan_pvid_filtered_body() 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 + atf_check -s exit:0 jexec one ifconfig ${epone}b 192.0.2.1/24 up + atf_check -s exit:0 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 ${epone}a 20 - ifconfig ${bridge} addm ${eptwo}a untagged ${eptwo}a 30 + 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: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 @@ -997,18 +999,22 @@ vlan_pvid_tagged_body() vnet_mkjail two ${eptwo}b # Create two tagged interfaces on the appropriate VLANs - jexec one ifconfig ${epone}b up - jexec one ifconfig ${epone}b.20 create 192.0.2.1/24 up - jexec two ifconfig ${eptwo}b up - jexec two ifconfig ${eptwo}b.20 create 192.0.2.2/24 up + atf_check -s exit:0 jexec one ifconfig ${epone}b up + atf_check -s exit:0 jexec one ifconfig ${epone}b.20 \ + create 192.0.2.1/24 up + atf_check -s exit:0 jexec two ifconfig ${eptwo}b up + atf_check -s exit:0 jexec two ifconfig ${eptwo}b.20 \ + create 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 ${epone}a 20 - ifconfig ${bridge} addm ${eptwo}a untagged ${eptwo}a 20 + 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 # Tagged frames should not be passed. atf_check -s exit:2 -o ignore jexec one ping -c 3 -t 1 192.0.2.2 @@ -1042,18 +1048,20 @@ vlan_pvid_1q_body() # This forces the bridge to add and remove .1q tags to bridge the # traffic. - jexec one ifconfig ${epone}b 192.0.2.1/24 up - jexec two ifconfig ${eptwo}b up - jexec two ifconfig ${eptwo}b.20 create 192.0.2.2/24 up + atf_check -s exit:0 jexec one ifconfig ${epone}b 192.0.2.1/24 up + atf_check -s exit:0 jexec two ifconfig ${eptwo}b up + atf_check -s exit:0 jexec two ifconfig ${eptwo}b.20 create 192.0.2.2/24 up bridge=$(vnet_mkbridge) - ifconfig ${bridge} addm ${epone}a untagged ${epone}a 20 - ifconfig ${bridge} addm ${eptwo}a + 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 - ifconfig ${bridge} up - ifconfig ${epone}a up - ifconfig ${eptwo}a up + atf_check -s exit:0 ifconfig ${epone}a up + atf_check -s exit:0 ifconfig ${eptwo}a up 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 @@ -1085,18 +1093,20 @@ vlan_filtering_body() vnet_mkjail one ${epone}b vnet_mkjail two ${eptwo}b - jexec one ifconfig ${epone}b up - jexec one ifconfig ${epone}b.20 create 192.0.2.1/24 up - jexec two ifconfig ${eptwo}b up - jexec two ifconfig ${eptwo}b.20 create 192.0.2.2/24 up + atf_check -s exit:0 jexec one ifconfig ${epone}b up + atf_check -s exit:0 jexec one ifconfig ${epone}b.20 \ + create 192.0.2.1/24 up + atf_check -s exit:0 jexec two ifconfig ${eptwo}b up + atf_check -s exit:0 jexec two ifconfig ${eptwo}b.20 \ + create 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 vlanfilter ${epone}a - ifconfig ${bridge} addm ${eptwo}a vlanfilter ${eptwo}a + 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 + atf_check -s exit:0 ifconfig ${bridge} addm ${eptwo}a # Right now there are no VLANs on the access list, so everything # should be blocked. @@ -1116,15 +1126,15 @@ vlan_filtering_body() atf_check -s exit:0 ifconfig ${bridge} -untagged ${eptwo}a # Add VLANs 10-30 to the access list; now access should be allowed. - ifconfig ${bridge} +tagged ${epone}a 10-30 - ifconfig ${bridge} +tagged ${eptwo}a 10-30 + 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 -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. - ifconfig ${bridge} -tagged ${epone}a 20 - ifconfig ${bridge} -tagged ${eptwo}a 20 + 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: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 } @@ -1151,9 +1161,10 @@ vlan_ifconfig_tagged_body() ep=$(vnet_mkepair) bridge=$(vnet_mkbridge) + atf_check -s exit:0 ifconfig ${bridge} vlanfilter up - ifconfig ${bridge} addm ${ep}a vlanfilter ${ep}a up - ifconfig ${ep}a up + atf_check -s exit:0 ifconfig ${bridge} addm ${ep}a + atf_check -s exit:0 ifconfig ${ep}a up # To start with, no vlans should be configured. atf_check -s exit:0 -o not-match:"tagged" ifconfig ${bridge} @@ -1210,18 +1221,20 @@ vlan_svi_body() vnet_mkjail one ${epone}b - jexec one ifconfig ${epone}b up - jexec one ifconfig ${epone}b.20 create 192.0.2.1/24 up + atf_check -s exit:0 jexec one ifconfig ${epone}b up + atf_check -s exit:0 jexec one ifconfig ${epone}b.20 \ + create 192.0.2.1/24 up bridge=$(vnet_mkbridge) - ifconfig ${bridge} up - ifconfig ${epone}a up - ifconfig ${bridge} addm ${epone}a tagged ${epone}a 20 + 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 svi=$(vnet_mkvlan) - ifconfig ${svi} vlan 20 vlandev ${bridge} - ifconfig ${svi} inet 192.0.2.2/24 up + atf_check -s exit:0 ifconfig ${svi} vlan 20 vlandev ${bridge} + atf_check -s exit:0 ifconfig ${svi} inet 192.0.2.2/24 up atf_check -s exit:0 -o ignore ping -c 3 -t 1 192.0.2.1 } @@ -1311,6 +1324,59 @@ bridge_svi_in_bridge_cleanup() vnet_cleanup } +atf_test_case "vlan_defuntagged" "cleanup" +vlan_defuntagged_head() +{ + atf_set descr 'defuntagged (defpvid) bridge option' + atf_set require.user root +} + +vlan_defuntagged_body() +{ + vnet_init + 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" \ + ifconfig ${bridge} defuntagged 0 + atf_check -s exit:1 -ematch:"invalid vlan id: 4095" \ + ifconfig ${bridge} defuntagged 4095 + atf_check -s exit:1 -ematch:"invalid vlan id: 5000" \ + ifconfig ${bridge} defuntagged 5000 + + # Check the bridge option is set and cleared correctly + atf_check -s exit:0 -onot-match:"defuntagged=" \ + ifconfig ${bridge} + + atf_check -s exit:0 ifconfig ${bridge} defuntagged 10 + atf_check -s exit:0 -omatch:"defuntagged=10$" \ + ifconfig ${bridge} + + atf_check -s exit:0 ifconfig ${bridge} -defuntagged + atf_check -s exit:0 -onot-match:"defuntagged=" \ + ifconfig ${bridge} + + # Check the untagged option is correctly set on a member + atf_check -s exit:0 ifconfig ${bridge} defuntagged 10 + + epair=$(vnet_mkepair) + atf_check -s exit:0 ifconfig ${bridge} addm ${epair}a + + tag=$(ifconfig ${bridge} | sed -Ene \ + "/member: ${epair}a/ { N;s/.*untagged ([0-9]+).*/\\1/p;q; }") + if [ "$tag" != "10" ]; then + atf_fail "wrong untagged vlan: ${tag}" + fi +} + +vlan_defuntagged_cleanup() +{ + vnet_cleanup +} + atf_init_test_cases() { atf_add_test_case "bridge_transmit_ipv4_unicast" @@ -1338,5 +1404,6 @@ atf_init_test_cases() atf_add_test_case "vlan_ifconfig_tagged" atf_add_test_case "vlan_svi" atf_add_test_case "vlan_qinq" + atf_add_test_case "vlan_defuntagged" atf_add_test_case "bridge_svi_in_bridge" }