Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F143924551
D49993.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
17 KB
Referenced Files
None
Subscribers
None
D49993.id.diff
View Options
diff --git a/sbin/ifconfig/ifbridge.c b/sbin/ifconfig/ifbridge.c
--- a/sbin/ifconfig/ifbridge.c
+++ b/sbin/ifconfig/ifbridge.c
@@ -211,6 +211,8 @@
else
printf(" <unknown state %d>", state);
}
+ if (member->ifbr_untagged != 0)
+ printf(" untagged %u", (unsigned)member->ifbr_untagged);
printf("\n");
}
@@ -576,6 +578,45 @@
err(1, "BRDGSIFCOST %s", cost);
}
+static void
+setbridge_untagged(if_ctx *ctx, const char *ifn, const char *vlanid)
+{
+ struct ifbreq req;
+ u_long val;
+
+ memset(&req, 0, sizeof(req));
+
+ if (get_val(vlanid, &val) < 0)
+ errx(1, "invalid VLAN identifier: %s", vlanid);
+
+ /*
+ * Reject vlan 0, since it's not a valid vlan identifier and has a
+ * special meaning in the kernel interface.
+ */
+ if (val == 0)
+ errx(1, "invalid VLAN identifier: %lu", val);
+
+ strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
+ req.ifbr_untagged = val;
+
+ if (do_cmd(ctx, BRDGSIFUNTAGGED, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGSIFUNTAGGED %s", vlanid);
+}
+
+static void
+unsetbridge_untagged(if_ctx *ctx, const char *ifn, int dummy __unused)
+{
+ struct ifbreq req;
+
+ memset(&req, 0, sizeof(req));
+
+ strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
+ req.ifbr_untagged = 0;
+
+ if (do_cmd(ctx, BRDGSIFUNTAGGED, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGSIFUNTAGGED");
+}
+
static void
setbridge_ifmaxaddr(if_ctx *ctx, const char *ifn, const char *arg)
{
@@ -612,17 +653,27 @@
static void
setbridge_private(if_ctx *ctx, const char *val, int dummy __unused)
{
-
do_bridgeflag(ctx, val, IFBIF_PRIVATE, 1);
}
static void
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 struct cmd bridge_cmds[] = {
DEF_CMD_ARG("addm", setbridge_add),
DEF_CMD_ARG("deletem", setbridge_delete),
@@ -659,6 +710,10 @@
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_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
--- a/sbin/ifconfig/ifconfig.8
+++ b/sbin/ifconfig/ifconfig.8
@@ -28,7 +28,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd April 24, 2025
+.Dd July 5, 2025
.Dt IFCONFIG 8
.Os
.Sh NAME
@@ -2696,6 +2696,25 @@
removed.
Set to 0 to disable.
.El
+.Ss Bridge VLAN Filtering Parameters
+The behaviour of these options is described in the
+.Dq VLAN SUPPORT
+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 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.
+.El
.Ss Link Aggregation and Link Failover Parameters
The following parameters are specific to lagg interfaces:
.Bl -tag -width indent
diff --git a/share/man/man4/bridge.4 b/share/man/man4/bridge.4
--- 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 May 28, 2025
+.Dd July 5, 2025
.Dt IF_BRIDGE 4
.Os
.Sh NAME
@@ -271,6 +271,35 @@
.Va net.link.bridge.log_stp
node using
.Xr sysctl 8 .
+.Sh VLAN SUPPORT
+The
+.Nm
+driver has limited support for virtual LANs (VLANs).
+The bridge implements independent VLAN learning, i.e. MAC addresses are
+learned on a per-VLAN basis, and the same MAC address may be learned on
+multiple interfaces on different VLANs.
+Incoming frames with an 802.1Q tag will be assigned to the appropriate
+VLAN.
+.Pp
+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
+.Xr ifconfig 8
+.Cm vlanfilter
+option.
+When VLAN filtering is enabled, an interface may only send and receive
+untagged frames.
+The interface's untagged VLAN ID may be configured using the
+.Xr ifconfig 8
+.Cm untagged
+option.
+If an untagged VLAN ID is configured, incoming frames will be assigned
+to that VLAN, and the interface may receive outgoing untagged frames
+in that VLAN.
+.Pp
+There is no support for adding or removing 802.1Q tags from frames
+processed by the bridge.
.Sh PACKET FILTERING
Packet filtering can be used with any firewall package that hooks in via the
.Xr pfil 9
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -254,6 +254,7 @@
uint32_t bif_addrcnt; /* cur. # of addresses */
uint32_t bif_addrexceeded;/* # of address violations */
struct epoch_context bif_epoch_ctx;
+ ether_vlanid_t bif_untagged; /* untagged vlan id */
};
/*
@@ -335,13 +336,12 @@
static void bridge_rtdelete(struct bridge_softc *, struct ifnet *ifp, int);
static void bridge_forward(struct bridge_softc *, struct bridge_iflist *,
- struct mbuf *m);
+ struct mbuf *m, ether_vlanid_t vlan);
static bool bridge_member_ifaddrs(void);
-
static void bridge_timer(void *);
static void bridge_broadcast(struct bridge_softc *, struct ifnet *,
- struct mbuf *, int);
+ struct mbuf *, int, ether_vlanid_t);
static void bridge_span(struct bridge_softc *, struct mbuf *);
static int bridge_rtupdate(struct bridge_softc *, const uint8_t *,
@@ -353,6 +353,8 @@
static void bridge_rtflush(struct bridge_softc *, int);
static int bridge_rtdaddr(struct bridge_softc *, const uint8_t *,
ether_vlanid_t);
+static bool bridge_vfilter_out(const struct bridge_iflist *,
+ const struct mbuf *, ether_vlanid_t);
static void bridge_rtable_init(struct bridge_softc *);
static void bridge_rtable_fini(struct bridge_softc *);
@@ -400,6 +402,7 @@
static int bridge_ioctl_sifprio(struct bridge_softc *, void *);
static int bridge_ioctl_sifcost(struct bridge_softc *, void *);
static int bridge_ioctl_sifmaxaddr(struct bridge_softc *, void *);
+static int bridge_ioctl_sifuntagged(struct bridge_softc *, void *);
static int bridge_ioctl_addspan(struct bridge_softc *, void *);
static int bridge_ioctl_delspan(struct bridge_softc *, void *);
static int bridge_ioctl_gbparam(struct bridge_softc *, void *);
@@ -618,6 +621,8 @@
{ bridge_ioctl_sifmaxaddr, sizeof(struct ifbreq),
BC_F_COPYIN|BC_F_SUSER },
+ { bridge_ioctl_sifuntagged, sizeof(struct ifbreq),
+ BC_F_COPYIN|BC_F_SUSER },
};
static const int bridge_control_table_size = nitems(bridge_control_table);
@@ -1495,6 +1500,7 @@
req->ifbr_addrcnt = bif->bif_addrcnt;
req->ifbr_addrmax = bif->bif_addrmax;
req->ifbr_addrexceeded = bif->bif_addrexceeded;
+ req->ifbr_untagged = bif->bif_untagged;
/* Copy STP state options as flags */
if (bp->bp_operedge)
@@ -1872,6 +1878,25 @@
return (0);
}
+static int
+bridge_ioctl_sifuntagged(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 (ENOENT);
+
+ if (req->ifbr_untagged > DOT1Q_VID_MAX)
+ return (EINVAL);
+
+ if (req->ifbr_untagged != DOT1Q_VID_NULL)
+ bif->bif_flags |= IFBIF_VLANFILTER;
+ bif->bif_untagged = req->ifbr_untagged;
+ return (0);
+}
+
static int
bridge_ioctl_addspan(struct bridge_softc *sc, void *arg)
{
@@ -2376,7 +2401,7 @@
NULL) {
error = bridge_enqueue(sc, dst_if, m);
} else
- bridge_broadcast(sc, ifp, m, 0);
+ bridge_broadcast(sc, ifp, m, 0, DOT1Q_VID_NULL);
return (error);
}
@@ -2430,12 +2455,11 @@
*/
static void
bridge_forward(struct bridge_softc *sc, struct bridge_iflist *sbif,
- struct mbuf *m)
+ struct mbuf *m, ether_vlanid_t vlan)
{
struct bridge_iflist *dbif;
struct ifnet *src_if, *dst_if, *ifp;
struct ether_header *eh;
- uint16_t vlan;
uint8_t *dst;
int error;
@@ -2446,7 +2470,6 @@
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len);
- vlan = VLANTAGOF(m);
if ((sbif->bif_flags & IFBIF_STP) &&
sbif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING)
@@ -2535,7 +2558,7 @@
}
if (dst_if == NULL) {
- bridge_broadcast(sc, src_if, m, 1);
+ bridge_broadcast(sc, src_if, m, 1, vlan);
return;
}
@@ -2555,6 +2578,10 @@
if (sbif->bif_flags & dbif->bif_flags & IFBIF_PRIVATE)
goto drop;
+ /* Do VLAN filtering. */
+ if (!bridge_vfilter_out(dbif, m, vlan))
+ goto drop;
+
if ((dbif->bif_flags & IFBIF_STP) &&
dbif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING)
goto drop;
@@ -2636,6 +2663,27 @@
return (NULL);
}
+ /* Do VLAN filtering. */
+ if (bif->bif_flags & IFBIF_VLANFILTER) {
+ /*
+ * If the frame was received with a tag, drop it, since we only
+ * support untagged ports which shouldn't be receiving tagged
+ * frames.
+ *
+ * If the frame was received without a tag, and the port doesn't
+ * have an untagged vlan configured, drop it.
+ */
+ if (vlan != DOT1Q_VID_NULL ||
+ bif->bif_untagged == DOT1Q_VID_NULL) {
+ if_inc_counter(sc->sc_ifp, IFCOUNTER_IERRORS, 1);
+ m_freem(m);
+ return (NULL);
+ }
+
+ /* Otherwise, assign the untagged frame to the correct vlan. */
+ vlan = bif->bif_untagged;
+ }
+
bridge_span(sc, m);
if (m->m_flags & (M_BCAST|M_MCAST)) {
@@ -2662,7 +2710,7 @@
}
/* Perform the bridge forwarding function with the copy. */
- bridge_forward(sc, bif, mc);
+ bridge_forward(sc, bif, mc, vlan);
#ifdef DEV_NETMAP
/*
@@ -2801,7 +2849,7 @@
#undef GRAB_OUR_PACKETS
/* Perform the bridge forwarding function. */
- bridge_forward(sc, bif, m);
+ bridge_forward(sc, bif, m, vlan);
return (NULL);
}
@@ -2839,7 +2887,7 @@
*/
static void
bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if,
- struct mbuf *m, int runfilt)
+ struct mbuf *m, int runfilt, ether_vlanid_t vlan)
{
struct bridge_iflist *dbif, *sbif;
struct mbuf *mc;
@@ -2867,6 +2915,10 @@
if (sbif && (sbif->bif_flags & dbif->bif_flags & IFBIF_PRIVATE))
continue;
+ /* Do VLAN filtering. */
+ if (!bridge_vfilter_out(dbif, m, vlan))
+ continue;
+
if ((dbif->bif_flags & IFBIF_STP) &&
dbif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING)
continue;
@@ -2950,6 +3002,67 @@
}
}
+/*
+ * Outgoing VLAN filtering. Given a frame, its vlan, and the member interface
+ * we intend to send it to, decide whether the port configuration allows it to
+ * be sent.
+ */
+static bool
+bridge_vfilter_out(const struct bridge_iflist *dbif, const struct mbuf *m,
+ ether_vlanid_t vlan)
+{
+ struct ether_header *eh;
+
+ NET_EPOCH_ASSERT();
+
+ /* If VLAN filtering isn't enabled, pass everything. */
+ if ((dbif->bif_flags & IFBIF_VLANFILTER) == 0)
+ return (true);
+
+ /*
+ * Always allow untagged 802.1D STP frames, even if they would
+ * otherwise be dropped. This is required for STP to work on
+ * a filtering bridge.
+ *
+ * Tagged STP (Cisco PVST+) is a non-standard extension, so
+ * handle those frames via the normal filtering path.
+ */
+ eh = mtod(m, struct ether_header *);
+ if (vlan == DOT1Q_VID_NULL &&
+ memcmp(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN) == 0)
+ return (true);
+
+ /*
+ * If the frame wasn't assigned to a vlan at ingress, drop it.
+ * We can't forward these frames to filtering ports because we
+ * don't know what VLAN they're supposed to be in.
+ */
+ if (vlan == DOT1Q_VID_NULL)
+ return (false);
+
+ /*
+ * If the frame was received with a vlan tag then drop it,
+ * since we only support untagged ports.
+ *
+ * If the egress port doesn't have an untagged vlan configured,
+ * it doesn't want untagged frames, so drop it.
+ */
+ if (VLANTAGOF(m) != DOT1Q_VID_NULL ||
+ dbif->bif_untagged == DOT1Q_VID_NULL)
+ return (false);
+
+ /*
+ * Make sure the frame's vlan matches the port's untagged vlan.
+ */
+ if (vlan != dbif->bif_untagged)
+ return (false);
+
+ /*
+ * Everything looks fine, so pass this frame.
+ */
+ return (true);
+}
+
/*
* bridge_rtupdate:
*
diff --git a/sys/net/if_bridgevar.h b/sys/net/if_bridgevar.h
--- a/sys/net/if_bridgevar.h
+++ b/sys/net/if_bridgevar.h
@@ -122,6 +122,7 @@
#define BRDGSPROTO 28 /* set protocol (ifbrparam) */
#define BRDGSTXHC 29 /* set tx hold count (ifbrparam) */
#define BRDGSIFAMAX 30 /* set max interface addrs (ifbreq) */
+#define BRDGSIFUNTAGGED 31 /* set if untagged vlan */
/*
* Generic bridge control request.
@@ -139,6 +140,7 @@
uint32_t ifbr_addrcnt; /* member if addr number */
uint32_t ifbr_addrmax; /* member if addr max */
uint32_t ifbr_addrexceeded; /* member if addr violations */
+ ether_vlanid_t ifbr_untagged; /* member if untagged vlan */
uint8_t pad[32];
};
@@ -155,10 +157,11 @@
#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 */
#define IFBIFBITS "\020\001LEARNING\002DISCOVER\003STP\004SPAN" \
"\005STICKY\014PRIVATE\006EDGE\007AUTOEDGE\010PTP" \
- "\011AUTOPTP"
+ "\011AUTOPTP\015VLANFILTER"
#define IFBIFMASK ~(IFBIF_BSTP_EDGE|IFBIF_BSTP_AUTOEDGE|IFBIF_BSTP_PTP| \
IFBIF_BSTP_AUTOPTP|IFBIF_BSTP_ADMEDGE| \
IFBIF_BSTP_ADMCOST) /* not saved */
diff --git a/sys/sys/param.h b/sys/sys/param.h
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -74,7 +74,7 @@
* cannot include sys/param.h and should only be updated here.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1500050
+#define __FreeBSD_version 1500051
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
diff --git a/tests/sys/net/if_bridge_test.sh b/tests/sys/net/if_bridge_test.sh
--- a/tests/sys/net/if_bridge_test.sh
+++ b/tests/sys/net/if_bridge_test.sh
@@ -829,6 +829,129 @@
vnet_cleanup
}
+atf_test_case "vlan_pvid" "cleanup"
+vlan_pvid_head()
+{
+ atf_set descr 'bridge with two ports with pvid set'
+ atf_set require.user root
+}
+
+vlan_pvid_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 ${epone}a 20
+ ifconfig ${bridge} addm ${eptwo}a untagged ${eptwo}a 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
+ 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_pvid_cleanup()
+{
+ vnet_cleanup
+}
+
+atf_test_case "vlan_pvid_filtered" "cleanup"
+vlan_pvid_filtered_head()
+{
+ atf_set descr 'bridge with two ports with different pvids'
+ atf_set require.user root
+}
+
+vlan_pvid_filtered_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 ${epone}a 20
+ 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
+}
+
+vlan_pvid_filtered_cleanup()
+{
+ vnet_cleanup
+}
+
+atf_test_case "vlan_pvid_tagged" "cleanup"
+vlan_pvid_tagged_head()
+{
+ atf_set descr 'bridge pvid with tagged frames for pvid'
+ atf_set require.user root
+}
+
+vlan_pvid_tagged_body()
+{
+ vnet_init
+ vnet_init_bridge
+
+ epone=$(vnet_mkepair)
+ eptwo=$(vnet_mkepair)
+
+ vnet_mkjail one ${epone}b
+ 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
+
+ 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
+
+ # Tagged frames 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
+}
+
+vlan_pvid_tagged_cleanup()
+{
+ vnet_cleanup
+}
atf_init_test_cases()
{
atf_add_test_case "bridge_transmit_ipv4_unicast"
@@ -847,4 +970,7 @@
atf_add_test_case "member_ifaddrs_enabled"
atf_add_test_case "member_ifaddrs_disabled"
atf_add_test_case "member_ifaddrs_vlan"
+ atf_add_test_case "vlan_pvid"
+ atf_add_test_case "vlan_pvid_filtered"
+ atf_add_test_case "vlan_pvid_tagged"
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Feb 3, 1:41 AM (14 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28419264
Default Alt Text
D49993.id.diff (17 KB)
Attached To
Mode
D49993: bridge(4): allow member interface vlan to be configured
Attached
Detach File
Event Timeline
Log In to Comment