Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F138624416
D50503.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
22 KB
Referenced Files
None
Subscribers
None
D50503.diff
View Options
diff --git a/lib/libifconfig/libifconfig.h b/lib/libifconfig/libifconfig.h
--- a/lib/libifconfig/libifconfig.h
+++ b/lib/libifconfig/libifconfig.h
@@ -29,6 +29,7 @@
#include <sys/types.h>
#include <net/if.h>
+#include <net/if_bridgevar.h> /* for ifbvlan_set_t */
#include <netinet/in.h>
#include <netinet/ip_carp.h>
@@ -64,6 +65,7 @@
struct ifconfig_bridge_status {
struct ifbropreq *params; /**< current operational parameters */
struct ifbreq *members; /**< list of bridge members */
+ ifbvlan_set_t *member_vlans; /**< bridge member vlan sets */
size_t members_count; /**< how many member interfaces */
uint32_t cache_size; /**< size of address cache */
uint32_t cache_lifetime; /**< address cache entry lifetime */
diff --git a/lib/libifconfig/libifconfig_bridge.c b/lib/libifconfig/libifconfig_bridge.c
--- a/lib/libifconfig/libifconfig_bridge.c
+++ b/lib/libifconfig/libifconfig_bridge.c
@@ -66,40 +66,37 @@
{
struct ifbifconf members;
struct ifbrparam cache_param;
- struct _ifconfig_bridge_status *bridge;
- char *buf;
+ struct _ifconfig_bridge_status *bridge = NULL;
+ char *buf = NULL;
+ members.ifbic_buf = NULL;
*bridgep = NULL;
bridge = calloc(1, sizeof(struct _ifconfig_bridge_status));
if (bridge == NULL) {
h->error.errtype = OTHER;
h->error.errcode = ENOMEM;
- return (-1);
+ goto err;
}
bridge->inner.params = &bridge->params;
if (ifconfig_bridge_ioctlwrap(h, name, BRDGGCACHE,
&cache_param, sizeof(cache_param), false) != 0) {
- free(bridge);
- return (-1);
+ goto err;
}
bridge->inner.cache_size = cache_param.ifbrp_csize;
if (ifconfig_bridge_ioctlwrap(h, name, BRDGGTO,
&cache_param, sizeof(cache_param), false) != 0) {
- free(bridge);
- return (-1);
+ goto err;
}
bridge->inner.cache_lifetime = cache_param.ifbrp_ctime;
if (ifconfig_bridge_ioctlwrap(h, name, BRDGPARAM,
&bridge->params, sizeof(bridge->params), false) != 0) {
- free(bridge);
- return (-1);
+ goto err;
}
- members.ifbic_buf = NULL;
for (size_t len = 8192;
(buf = realloc(members.ifbic_buf, len)) != NULL;
len *= 2) {
@@ -107,27 +104,52 @@
members.ifbic_len = len;
if (ifconfig_bridge_ioctlwrap(h, name, BRDGGIFS,
&members, sizeof(members), false) != 0) {
- free(buf);
- free(bridge);
- return (-1);
+ goto err;
}
if ((members.ifbic_len + sizeof(*members.ifbic_req)) < len)
break;
}
if (buf == NULL) {
- free(members.ifbic_buf);
- free(bridge);
h->error.errtype = OTHER;
h->error.errcode = ENOMEM;
- return (-1);
+ goto err;
}
bridge->inner.members = members.ifbic_req;
bridge->inner.members_count =
members.ifbic_len / sizeof(*members.ifbic_req);
+ bridge->inner.member_vlans = calloc(bridge->inner.members_count,
+ sizeof(ifbvlan_set_t));
+ if (bridge->inner.member_vlans == NULL) {
+ h->error.errtype = OTHER;
+ h->error.errcode = ENOMEM;
+ goto err;
+ }
+ for (size_t i = 0; i < bridge->inner.members_count; ++i) {
+ struct ifbif_vlan_req vreq;
+ memset(&vreq, 0, sizeof(vreq));
+ strlcpy(vreq.bv_ifname, bridge->inner.members[i].ifbr_ifsname,
+ sizeof(vreq.bv_ifname));
+
+ if (ifconfig_bridge_ioctlwrap(h, name, BRDGGIFVLANSET, &vreq,
+ sizeof(vreq), false) != 0) {
+ goto err;
+ }
+
+ __BIT_COPY(BRVLAN_SETSIZE, &vreq.bv_set,
+ &bridge->inner.member_vlans[i]);
+ }
+
*bridgep = &bridge->inner;
return (0);
+
+err:
+ free(members.ifbic_buf);
+ if (bridge)
+ free(bridge->inner.member_vlans);
+ free(bridge);
+ return (-1);
}
void
diff --git a/sbin/ifconfig/ifbridge.c b/sbin/ifconfig/ifbridge.c
--- a/sbin/ifconfig/ifbridge.c
+++ b/sbin/ifconfig/ifbridge.c
@@ -146,6 +146,36 @@
free(inbuf);
}
+static void
+print_vlans(ifbvlan_set_t *vlans)
+{
+ unsigned printed = 0;
+
+ for (unsigned vlan = DOT1Q_VID_MIN; vlan <= DOT1Q_VID_MAX;) {
+ unsigned last;
+
+ if (!BRVLAN_TEST(vlans, vlan)) {
+ ++vlan;
+ continue;
+ }
+
+ last = vlan;
+ while (last < DOT1Q_VID_MAX && BRVLAN_TEST(vlans, last + 1))
+ ++last;
+
+ if (printed == 0)
+ printf(" tagged ");
+ else
+ printf(",");
+
+ printf("%u", vlan);
+ if (last != vlan)
+ printf("-%u", last);
+ ++printed;
+ vlan = last + 1;
+ }
+}
+
static void
bridge_status(if_ctx *ctx)
{
@@ -213,6 +243,7 @@
}
if (member->ifbr_untagged != 0)
printf(" untagged %u", (unsigned)member->ifbr_untagged);
+ print_vlans(&bridge->member_vlans[i]);
printf("\n");
}
@@ -674,6 +705,97 @@
do_bridgeflag(ctx, val, IFBIF_VLANFILTER, 0);
}
+static int
+parse_vlans(ifbvlan_set_t *set, const char *str)
+{
+ char *s, *token;
+
+ /* "none" means the empty vlan set */
+ if (strcmp(str, "none") == 0) {
+ __BIT_ZERO(BRVLAN_SETSIZE, set);
+ return (0);
+ }
+
+ /* "all" means all vlans, except for 0 and 4095 which are reserved */
+ if (strcmp(str, "all") == 0) {
+ __BIT_FILL(BRVLAN_SETSIZE, set);
+ BRVLAN_CLR(set, DOT1Q_VID_NULL);
+ BRVLAN_CLR(set, DOT1Q_VID_RSVD_IMPL);
+ return (0);
+ }
+
+ if ((s = strdup(str)) == NULL)
+ return (-1);
+
+ while ((token = strsep(&s, ",")) != NULL) {
+ unsigned long first, last;
+ char *p, *lastp;
+
+ if ((lastp = strchr(token, '-')) != NULL)
+ *lastp++ = '\0';
+
+ first = last = strtoul(token, &p, 10);
+ if (*p != '\0')
+ goto err;
+ if (first < DOT1Q_VID_MIN || first > DOT1Q_VID_MAX)
+ goto err;
+
+ if (lastp) {
+ last = strtoul(lastp, &p, 10);
+ if (*p != '\0')
+ goto err;
+ if (last < DOT1Q_VID_MIN || last > DOT1Q_VID_MAX ||
+ last < first)
+ goto err;
+ }
+
+ for (unsigned vlan = first; vlan <= last; ++vlan)
+ BRVLAN_SET(set, vlan);
+ }
+
+ free(s);
+ return (0);
+
+err:
+ free(s);
+ return (-1);
+}
+
+static void
+set_bridge_vlanset(if_ctx *ctx, const char *ifn, const char *vlans, int op)
+{
+ struct ifbif_vlan_req req;
+
+ memset(&req, 0, sizeof(req));
+
+ if (parse_vlans(&req.bv_set, vlans) != 0)
+ errx(1, "invalid vlan set: %s", vlans);
+
+ strlcpy(req.bv_ifname, ifn, sizeof(req.bv_ifname));
+ req.bv_op = op;
+
+ if (do_cmd(ctx, BRDGSIFVLANSET, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGSIFVLANSET %s", vlans);
+}
+
+static void
+setbridge_tagged(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)
+{
+ set_bridge_vlanset(ctx, ifn, vlans, BRDG_VLAN_OP_ADD);
+}
+
+static void
+delbridge_tagged(if_ctx *ctx, const char *ifn, const char *vlans)
+{
+ set_bridge_vlanset(ctx, ifn, vlans, BRDG_VLAN_OP_DEL);
+}
+
static struct cmd bridge_cmds[] = {
DEF_CMD_ARG("addm", setbridge_add),
DEF_CMD_ARG("deletem", setbridge_delete),
@@ -714,6 +836,9 @@
DEF_CMD_ARG("-vlanfilter", unsetbridge_vlanfilter),
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_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
@@ -2714,6 +2714,38 @@
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 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
+or ranges formatted as
+.Ar first-last ,
+the value
+.Dq none
+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
--- a/share/man/man4/bridge.4
+++ b/share/man/man4/bridge.4
@@ -289,7 +289,8 @@
.Cm vlanfilter
option.
When VLAN filtering is enabled, an interface may only send and receive
-untagged frames.
+frames based on its configured VLAN access list.
+.Pp
The interface's untagged VLAN ID may be configured using the
.Xr ifconfig 8
.Cm untagged
@@ -298,6 +299,16 @@
to that VLAN, and the interface may receive outgoing untagged frames
in that VLAN.
.Pp
+The tagged VLAN access list may be configured using the
+.Cm tagged ,
+.Cm +tagged
+and
+.Cm -tagged
+options to
+.Xr ifconfig 8 .
+An interface may send and receive tagged frames for any VLAN in its
+access list.
+.Pp
The bridge will automatically insert or remove 802.1q tags as needed,
based on the interface configuration, when forwarding frames between
interfaces.
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
@@ -255,6 +255,7 @@
uint32_t bif_addrexceeded;/* # of address violations */
struct epoch_context bif_epoch_ctx;
ether_vlanid_t bif_untagged; /* untagged vlan id */
+ ifbvlan_set_t bif_vlan_set; /* allowed tagged vlans */
};
/*
@@ -353,8 +354,9 @@
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_in(const struct bridge_iflist *, struct mbuf *);
static bool bridge_vfilter_out(const struct bridge_iflist *,
- const struct mbuf *, ether_vlanid_t);
+ const struct mbuf *);
static void bridge_rtable_init(struct bridge_softc *);
static void bridge_rtable_fini(struct bridge_softc *);
@@ -403,6 +405,8 @@
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_sifvlanset(struct bridge_softc *, void *);
+static int bridge_ioctl_gifvlanset(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 *);
@@ -623,6 +627,12 @@
{ bridge_ioctl_sifuntagged, sizeof(struct ifbreq),
BC_F_COPYIN|BC_F_SUSER },
+
+ { bridge_ioctl_sifvlanset, sizeof(struct ifbif_vlan_req),
+ BC_F_COPYIN|BC_F_SUSER },
+
+ { bridge_ioctl_gifvlanset, sizeof(struct ifbif_vlan_req),
+ BC_F_COPYIN|BC_F_COPYOUT },
};
static const int bridge_control_table_size = nitems(bridge_control_table);
@@ -959,6 +969,7 @@
struct ifbaconf ifbaconf;
struct ifbrparam ifbrparam;
struct ifbropreq ifbropreq;
+ struct ifbif_vlan_req ifvlanreq;
} args;
struct ifdrv *ifd = (struct ifdrv *) data;
const struct bridge_control *bc;
@@ -1897,6 +1908,65 @@
return (0);
}
+static int
+bridge_ioctl_sifvlanset(struct bridge_softc *sc, void *arg)
+{
+ struct ifbif_vlan_req *req = arg;
+ struct bridge_iflist *bif;
+
+ bif = bridge_lookup_member(sc, req->bv_ifname);
+ if (bif == NULL)
+ return (ENOENT);
+
+ /* Reject invalid VIDs. */
+ if (BRVLAN_TEST(&req->bv_set, DOT1Q_VID_NULL) ||
+ BRVLAN_TEST(&req->bv_set, DOT1Q_VID_RSVD_IMPL))
+ return (EINVAL);
+
+ switch (req->bv_op) {
+ /* Replace the existing vlan set with the new set */
+ case BRDG_VLAN_OP_SET:
+ BIT_COPY(BRVLAN_SETSIZE, &req->bv_set, &bif->bif_vlan_set);
+ break;
+
+ /* Modify the existing vlan set to add the given vlans */
+ case BRDG_VLAN_OP_ADD:
+ BIT_OR(BRVLAN_SETSIZE, &bif->bif_vlan_set, &req->bv_set);
+ break;
+
+ /* Modify the existing vlan set to remove the given vlans */
+ case BRDG_VLAN_OP_DEL:
+ BIT_ANDNOT(BRVLAN_SETSIZE, &bif->bif_vlan_set, &req->bv_set);
+ break;
+
+ /* Invalid or unknown operation */
+ default:
+ return (EINVAL);
+ }
+
+ /*
+ * 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);
+}
+
+static int
+bridge_ioctl_gifvlanset(struct bridge_softc *sc, void *arg)
+{
+ struct ifbif_vlan_req *req = arg;
+ struct bridge_iflist *bif;
+
+ bif = bridge_lookup_member(sc, req->bv_ifname);
+ if (bif == NULL)
+ return (ENOENT);
+
+ BIT_COPY(BRVLAN_SETSIZE, &bif->bif_vlan_set, &req->bv_set);
+ return (0);
+}
+
static int
bridge_ioctl_addspan(struct bridge_softc *sc, void *arg)
{
@@ -2606,7 +2676,7 @@
goto drop;
/* Do VLAN filtering. */
- if (!bridge_vfilter_out(dbif, m, vlan))
+ if (!bridge_vfilter_out(dbif, m))
goto drop;
if ((dbif->bif_flags & IFBIF_STP) &&
@@ -2691,27 +2761,13 @@
}
/* 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;
- m->m_pkthdr.ether_vtag = bif->bif_untagged;
- m->m_flags |= M_VLANTAG;
+ if (!bridge_vfilter_in(bif, m)) {
+ if_inc_counter(sc->sc_ifp, IFCOUNTER_IERRORS, 1);
+ m_freem(m);
+ return (NULL);
}
+ /* bridge_vfilter_in() may add a tag */
+ vlan = VLANTAGOF(m);
bridge_span(sc, m);
@@ -2922,12 +2978,10 @@
struct mbuf *mc;
struct ifnet *dst_if;
int used = 0, i;
- ether_vlanid_t vlan;
NET_EPOCH_ASSERT();
sbif = bridge_lookup_member_if(sc, src_if);
- vlan = VLANTAGOF(m);
/* Filter on the bridge interface before broadcasting */
if (runfilt && PFIL_HOOKED_OUT_46) {
@@ -2947,7 +3001,7 @@
continue;
/* Do VLAN filtering. */
- if (!bridge_vfilter_out(dbif, m, vlan))
+ if (!bridge_vfilter_out(dbif, m))
continue;
if ((dbif->bif_flags & IFBIF_STP) &&
@@ -3033,16 +3087,63 @@
}
}
+/*
+ * Incoming VLAN filtering. Given a frame and the member interface it was
+ * received on, decide whether the port configuration allows it.
+ */
+static bool
+bridge_vfilter_in(const struct bridge_iflist *sbif, struct mbuf *m)
+{
+ ether_vlanid_t vlan;
+
+ vlan = VLANTAGOF(m);
+ /* Make sure the vlan id is reasonable. */
+ if (vlan > DOT1Q_VID_MAX)
+ return (false);
+
+ /* If VLAN filtering isn't enabled, pass everything. */
+ if ((sbif->bif_flags & IFBIF_VLANFILTER) == 0)
+ return (true);
+
+ if (vlan == DOT1Q_VID_NULL) {
+ /*
+ * The frame doesn't have a tag. If the interface does not
+ * have an untagged vlan configured, drop the frame.
+ */
+ if (sbif->bif_untagged == DOT1Q_VID_NULL)
+ return (false);
+
+ /*
+ * Otherwise, insert a new tag based on the interface's
+ * untagged vlan id.
+ */
+ m->m_pkthdr.ether_vtag = sbif->bif_untagged;
+ m->m_flags |= M_VLANTAG;
+ } else {
+ /*
+ * The frame has a tag, so check it matches the interface's
+ * vlan access list. We explicitly do not accept tagged
+ * frames for the untagged vlan id here (unless it's also
+ * in the access list).
+ */
+ if (!BRVLAN_TEST(&sbif->bif_vlan_set, vlan))
+ return (false);
+ }
+
+ /* Accept the frame. */
+ return (true);
+}
+
/*
* 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)
+bridge_vfilter_out(const struct bridge_iflist *dbif, const struct mbuf *m)
{
struct ether_header *eh;
+ ether_vlanid_t vlan;
NET_EPOCH_ASSERT();
@@ -3050,6 +3151,8 @@
if ((dbif->bif_flags & IFBIF_VLANFILTER) == 0)
return (true);
+ vlan = VLANTAGOF(m);
+
/*
* Always allow untagged 802.1D STP frames, even if they would
* otherwise be dropped. This is required for STP to work on
@@ -3072,15 +3175,21 @@
return (false);
/*
- * Make sure the frame's vlan matches the port's untagged vlan.
+ * If the frame's vlan matches the interfaces's untagged vlan,
+ * allow it.
*/
- if (vlan != dbif->bif_untagged)
- return (false);
+ if (vlan == dbif->bif_untagged)
+ return (true);
/*
- * Everything looks fine, so pass this frame.
+ * If the frame's vlan is on the interface's tagged access list,
+ * allow it.
*/
- return (true);
+ if (BRVLAN_TEST(&dbif->bif_vlan_set, vlan))
+ return (true);
+
+ /* The frame was not permitted, so drop it. */
+ return (false);
}
/*
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
@@ -78,6 +78,8 @@
#define _NET_IF_BRIDGEVAR_H_
#include <sys/types.h>
+#include <sys/_bitset.h>
+#include <sys/bitset.h>
#include <sys/callout.h>
#include <sys/queue.h>
#include <sys/condvar.h>
@@ -123,6 +125,8 @@
#define BRDGSTXHC 29 /* set tx hold count (ifbrparam) */
#define BRDGSIFAMAX 30 /* set max interface addrs (ifbreq) */
#define BRDGSIFUNTAGGED 31 /* set if untagged vlan */
+#define BRDGSIFVLANSET 32 /* set if vlan set */
+#define BRDGGIFVLANSET 33 /* get if vlan set */
/*
* Generic bridge control request.
@@ -307,6 +311,26 @@
eaddr[5] = pv >> 0; \
} while (0)
+/*
+ * Bridge VLAN access request.
+ */
+#define BRVLAN_SETSIZE 4096
+typedef __BITSET_DEFINE(ifbvlan_set, BRVLAN_SETSIZE) ifbvlan_set_t;
+
+#define BRVLAN_SET(set, bit) __BIT_SET(BRVLAN_SETSIZE, (bit), set)
+#define BRVLAN_CLR(set, bit) __BIT_CLR(BRVLAN_SETSIZE, (bit), set)
+#define BRVLAN_TEST(set, bit) __BIT_ISSET(BRVLAN_SETSIZE, (bit), set)
+
+#define BRDG_VLAN_OP_SET 1 /* replace current vlan set */
+#define BRDG_VLAN_OP_ADD 2 /* add vlans to current set */
+#define BRDG_VLAN_OP_DEL 3 /* remove vlans from current set */
+
+struct ifbif_vlan_req {
+ char bv_ifname[IFNAMSIZ];
+ uint8_t bv_op;
+ ifbvlan_set_t bv_set;
+};
+
#ifdef _KERNEL
#define BRIDGE_INPUT(_ifp, _m) do { \
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
@@ -997,6 +997,133 @@
vnet_cleanup
}
+#
+# Test vlan filtering.
+#
+atf_test_case "vlan_filtering" "cleanup"
+vlan_filtering_head()
+{
+ atf_set descr 'tagged traffic with filtering'
+ atf_set require.user root
+}
+
+vlan_filtering_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 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 vlanfilter ${epone}a
+ ifconfig ${bridge} addm ${eptwo}a vlanfilter ${eptwo}a
+
+ # Right now there are no VLANs on the access list, so everything
+ # should be blocked.
+ 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
+
+ # 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: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
+
+ # 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 -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: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_filtering_cleanup()
+{
+ vnet_cleanup
+}
+
+#
+# Test the ifconfig 'tagged' option.
+#
+atf_test_case "vlan_ifconfig_tagged" "cleanup"
+vlan_ifconfig_tagged_head()
+{
+ atf_set descr 'test the ifconfig tagged option'
+ atf_set require.user root
+}
+
+vlan_ifconfig_tagged_body()
+{
+ vnet_init
+ vnet_init_bridge
+
+ ep=$(vnet_mkepair)
+ bridge=$(vnet_mkbridge)
+
+ ifconfig ${bridge} addm ${ep}a vlanfilter ${ep}a up
+ ifconfig ${ep}a up
+
+ # To start with, no vlans should be configured.
+ 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 -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 -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 -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 -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 -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"
+ done
+}
+
+vlan_ifconfig_tagged_cleanup()
+{
+ vnet_cleanup
+}
+
atf_init_test_cases()
{
atf_add_test_case "bridge_transmit_ipv4_unicast"
@@ -1019,4 +1146,6 @@
atf_add_test_case "vlan_pvid_1q"
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"
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Dec 4, 1:42 PM (5 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26609868
Default Alt Text
D50503.diff (22 KB)
Attached To
Mode
D50503: bridge: add vlan filtering support
Attached
Detach File
Event Timeline
Log In to Comment