From nobody Tue Aug 5 19:26:02 2025 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4bxNgt70f9z63cBl; Tue, 05 Aug 2025 19:26:02 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4bxNgt5zq5z3qQl; Tue, 05 Aug 2025 19:26:02 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1754421962; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=3c07bxxsj3IWtkziecwKTLCjPayxVeMNhXHr72uj9qs=; b=KrZj7Nf98wcG10PQKTC3875iYbmiAcCY7npzYeWcSEpH4Ge7kgVcDMVqqYkvLKx65PAqZL 1//1Jhx95537g7umNM29FIdWHsyoOuJKXb3ib84V33QxpkvQfKJzpq6JShI2ygaWBGSFGu n0Y/6gcWt6fc0833wpqPCcZqVxuj1V1KU6rUO/VFoWa/lqvtBmNKoVHDaJxcS1N4OnfoQi 8cgvVzcV/QMGfVPPKc0rnQIGv88QGsmvm+cOJ09DXJCoJ1GUv+NypKU0JqOb+oPfXpu0mA U/6s9VwaryYgfnneQJXo4eMBSLkDqlILl4pE4wzoJAKjYhhHGcoU/NVHZRFhOA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1754421962; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=3c07bxxsj3IWtkziecwKTLCjPayxVeMNhXHr72uj9qs=; b=IOTt+Rm0mugZz0kfBUNhfRWGkQgf7LqHJL2/66/XiuTJI1Bd3OHp8jOkSEadfsBWYV/Fy0 eppTpQvVNuf56rQKUsyyDUJYSpkWe2s8MxBLaxLmUmftkATKZYvrSgLr9Pa3+T96KgkJhb B9dJcjY9ui9lu9/ScKpeo4mltAY5Yv/8mL7/Pn+lx+OJjRha6yM2M3pjkdQveIIuf5qOAH HbIq7GeYUS3SQgIJmMGLJghslk+f5ucKZohIfkYN01XHY5QNkl68MFsid3ymBO9i3rxPh+ 0wW7sM0jhw2r1y2qK05rE0+Yggy8j9gUFKrOlteacY3XkzTjZTxA/cyDAtKNQQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1754421962; a=rsa-sha256; cv=none; b=Dd/1QE99DC7Qrv01ryYMImUESvYXm7vSddyXKhCXziDsqShpHPBhRkGF/KqLpWHeKfgHff Kgj/H/sh2xZXyJBnaCYiHtUBuUYihsNerwSjC2dTlvs8ikKZeQJ64PFFlEqELs8xMeC7oI mzvcc73QjWAaC6lmrG3kVWQrABaolobh4oVEf5Ao2ab7WeVvSJx038+37336FikXu9stuk jyM63/rsWLnkAr+OKU1Ska7GyfZzqCzrAdYfAwKvUQUnVBVZY5sDi6I1X8pQPuXq5YjnUc yanVHYHntWQVtiN0btOyaHS3QMHOiyhDdh+wPCUyQ7XiUhdXFP7+0nXrfnDHxw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4bxNgt5WtWzp0h; Tue, 05 Aug 2025 19:26:02 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 575JQ2LK074600; Tue, 5 Aug 2025 19:26:02 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 575JQ2fJ074597; Tue, 5 Aug 2025 19:26:02 GMT (envelope-from git) Date: Tue, 5 Aug 2025 19:26:02 GMT Message-Id: <202508051926.575JQ2fJ074597@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Lexi Winter Subject: git: f94c370de6e7 - main - bridge: Allow VLAN protocol to be configured List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: ivy X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: f94c370de6e7d32cd3b635893870438b744214e7 Auto-Submitted: auto-generated The branch main has been updated by ivy: URL: https://cgit.FreeBSD.org/src/commit/?id=f94c370de6e7d32cd3b635893870438b744214e7 commit f94c370de6e7d32cd3b635893870438b744214e7 Author: Lexi Winter AuthorDate: 2025-08-05 17:51:11 +0000 Commit: Lexi Winter CommitDate: 2025-08-05 18:35:30 +0000 bridge: Allow VLAN protocol to be configured Add a new per-interface option "ifvlanproto", which can be either "802.1q" (the default) or "802.1ad". This controls what type of tag we attach to outgoing packets on the interface. Reviewed by: pauamma_gundo.com (manpages) Differential Revision: https://reviews.freebsd.org/D51231 --- sbin/ifconfig/ifbridge.c | 38 ++++++++++++++++++++++++++++++++++++++ sbin/ifconfig/ifconfig.8 | 11 +++++++++++ sys/net/if_bridge.c | 36 ++++++++++++++++++++++++++++++++---- sys/net/if_bridgevar.h | 3 +++ 4 files changed, 84 insertions(+), 4 deletions(-) diff --git a/sbin/ifconfig/ifbridge.c b/sbin/ifconfig/ifbridge.c index 3566acdcf54c..d02d92d10b59 100644 --- a/sbin/ifconfig/ifbridge.c +++ b/sbin/ifconfig/ifbridge.c @@ -190,6 +190,21 @@ print_vlans(ifbvlan_set_t *vlans) } } +static char const * +vlan_proto_name(uint16_t proto) +{ + switch (proto) { + case 0: + return "none"; + case ETHERTYPE_VLAN: + return "802.1q"; + case ETHERTYPE_QINQ: + return "802.1ad"; + default: + return "unknown"; + } +} + static void bridge_status(if_ctx *ctx) { @@ -261,6 +276,9 @@ bridge_status(if_ctx *ctx) else printf(" ", state); } + if (member->ifbr_vlanproto != 0) + printf(" vlan protocol %s", + vlan_proto_name(member->ifbr_vlanproto)); if (member->ifbr_pvid != 0) printf(" untagged %u", (unsigned)member->ifbr_pvid); print_vlans(&bridge->member_vlans[i]); @@ -895,6 +913,25 @@ unsetbridge_qinq(if_ctx *ctx, const char *val, int dummy __unused) do_bridgeflag(ctx, val, IFBIF_QINQ, 0); } +static void +setbridge_ifvlanproto(if_ctx *ctx, const char *ifname, const char *proto) +{ + struct ifbreq req; + + memset(&req, 0, sizeof(req)); + strlcpy(req.ifbr_ifsname, ifname, sizeof(req.ifbr_ifsname)); + + if (strcmp(proto, "802.1q") == 0) + req.ifbr_vlanproto = ETHERTYPE_VLAN; + else if (strcmp(proto, "802.1ad") == 0) + req.ifbr_vlanproto = ETHERTYPE_QINQ; + else + errx(1, "unrecognised VLAN protocol: %s", proto); + + if (do_cmd(ctx, BRDGSIFVLANPROTO, &req, sizeof(req), 1) < 0) + err(1, "BRDGSIFVLANPROTO"); +} + static struct cmd bridge_cmds[] = { DEF_CMD_ARG("addm", setbridge_add), DEF_CMD_ARG("deletem", setbridge_delete), @@ -936,6 +973,7 @@ static struct cmd bridge_cmds[] = { DEF_CMD_ARG2("tagged", setbridge_tagged), DEF_CMD_ARG2("+tagged", addbridge_tagged), DEF_CMD_ARG2("-tagged", delbridge_tagged), + DEF_CMD_ARG2("ifvlanproto", setbridge_ifvlanproto), DEF_CMD_ARG("timeout", setbridge_timeout), DEF_CMD_ARG("private", setbridge_private), DEF_CMD_ARG("-private", unsetbridge_private), diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 index 69a81f72421f..d7b2570ab20d 100644 --- a/sbin/ifconfig/ifconfig.8 +++ b/sbin/ifconfig/ifconfig.8 @@ -2765,6 +2765,17 @@ Do not enable the .Cm qinq option by default on newly added members. This is the default behavior. +.It Cm ifvlanproto Ar interface Ar proto +Set the VLAN encapsulation protocol on +.Ar interface +to +.Ar proto , +which must be either +.Dq 802.1q +or +.Dq 802.1ad . +The default is +.Dq 802.1q . .El .Ss Link Aggregation and Link Failover Parameters The following parameters are specific to lagg interfaces: diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 26ea4400e67d..945318c5af1a 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -259,6 +259,7 @@ struct bridge_iflist { struct epoch_context bif_epoch_ctx; ether_vlanid_t bif_pvid; /* port vlan id */ ifbvlan_set_t bif_vlan_set; /* if allowed tagged vlans */ + uint16_t bif_vlanproto; /* vlan protocol */ }; /* @@ -423,6 +424,7 @@ 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_ioctl_svlanproto(struct bridge_softc *, void *); static int bridge_pfil(struct mbuf **, struct ifnet *, struct ifnet *, int); #ifdef INET @@ -654,6 +656,9 @@ static const struct bridge_control bridge_control_table[] = { { bridge_ioctl_sdefpvid, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER }, + + { bridge_ioctl_svlanproto, sizeof(struct ifbreq), + BC_F_COPYIN|BC_F_SUSER }, }; static const int bridge_control_table_size = nitems(bridge_control_table); @@ -1494,6 +1499,7 @@ 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; + bif->bif_vlanproto = ETHERTYPE_VLAN; if (sc->sc_flags & IFBRF_VLANFILTER) bif->bif_pvid = sc->sc_defpvid; if (sc->sc_flags & IFBRF_DEFQINQ) @@ -1579,6 +1585,7 @@ bridge_ioctl_gifflags(struct bridge_softc *sc, void *arg) req->ifbr_addrmax = bif->bif_addrmax; req->ifbr_addrexceeded = bif->bif_addrexceeded; req->ifbr_pvid = bif->bif_pvid; + req->ifbr_vlanproto = bif->bif_vlanproto; /* Copy STP state options as flags */ if (bp->bp_operedge) @@ -2254,6 +2261,24 @@ bridge_ioctl_sdefpvid(struct bridge_softc *sc, void *arg) return (0); } +static int +bridge_ioctl_svlanproto(struct bridge_softc *sc, void *arg) +{ + struct ifbreq *req = arg; + struct bridge_iflist *bif; + + bif = bridge_lookup_member(sc, req->ifbr_ifsname); + if (bif == NULL) + return (EXTERROR(ENOENT, "Interface is not a bridge member")); + + if (req->ifbr_vlanproto != ETHERTYPE_VLAN && + req->ifbr_vlanproto != ETHERTYPE_QINQ) + return (EXTERROR(EINVAL, "Invalid VLAN protocol")); + + bif->bif_vlanproto = req->ifbr_vlanproto; + + return (0); +} /* * bridge_ifdetach: * @@ -2397,12 +2422,15 @@ bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m, } /* - * If underlying interface can not do VLAN tag insertion itself - * then attach a packet tag that holds it. + * There are two cases where we have to insert our own tag: + * if the member interface doesn't support hardware tagging, + * or if the tag proto is not 802.1q. */ if ((m->m_flags & M_VLANTAG) && - (dst_ifp->if_capenable & IFCAP_VLAN_HWTAGGING) == 0) { - m = ether_vlanencap(m, m->m_pkthdr.ether_vtag); + ((dst_ifp->if_capenable & IFCAP_VLAN_HWTAGGING) == 0 || + bif->bif_vlanproto != ETHERTYPE_VLAN)) { + m = ether_vlanencap_proto(m, m->m_pkthdr.ether_vtag, + bif->bif_vlanproto); if (m == NULL) { if_printf(dst_ifp, "unable to prepend VLAN header\n"); diff --git a/sys/net/if_bridgevar.h b/sys/net/if_bridgevar.h index 15194fecff7c..b0f579f688ac 100644 --- a/sys/net/if_bridgevar.h +++ b/sys/net/if_bridgevar.h @@ -131,6 +131,7 @@ #define BRDGSFLAGS 35 /* set bridge flags (ifbrparam) */ #define BRDGGDEFPVID 36 /* get default pvid (ifbrparam) */ #define BRDGSDEFPVID 37 /* set default pvid (ifbrparam) */ +#define BRDGSIFVLANPROTO 38 /* set if vlan protocol (ifbreq) */ /* BRDGSFLAGS, Bridge flags (non-interface-specific) */ typedef uint32_t ifbr_flags_t; @@ -157,6 +158,7 @@ struct ifbreq { uint32_t ifbr_addrmax; /* member if addr max */ uint32_t ifbr_addrexceeded; /* member if addr violations */ ether_vlanid_t ifbr_pvid; /* member if PVID */ + uint16_t ifbr_vlanproto; /* member if VLAN protocol */ uint8_t pad[32]; }; @@ -252,6 +254,7 @@ struct ifbrparam { * addresses */ #define ifbrp_flags ifbrp_ifbrpu.ifbrpu_int32 /* bridge flags */ #define ifbrp_defpvid ifbrp_ifbrpu.ifbrpu_int16 /* default pvid */ +#define ifbrp_vlanproto ifbrp_ifbrpu.ifbrpu_int8 /* vlan protocol */ /* * Bridge current operational parameters structure.