Page MenuHomeFreeBSD

D58729.id.diff
No OneTemporary

D58729.id.diff

diff --git a/lib/libifconfig/libifconfig.h b/lib/libifconfig/libifconfig.h
--- a/lib/libifconfig/libifconfig.h
+++ b/lib/libifconfig/libifconfig.h
@@ -73,6 +73,7 @@
uint32_t cache_lifetime; /**< address cache entry lifetime */
ifbr_flags_t flags; /**< bridge flags */
ether_vlanid_t defpvid; /**< default pvid */
+ uint16_t group_fwd_mask; /**< link-local reserved group mask */
};
struct ifconfig_capabilities {
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,6 +66,7 @@
{
struct ifbifconf members;
struct ifbrparam cache_param;
+ struct ifbrparam fwd_mask_param;
struct _ifconfig_bridge_status *bridge = NULL;
char *buf = NULL;
@@ -104,6 +105,12 @@
}
bridge->inner.defpvid = cache_param.ifbrp_defpvid;
+ if (ifconfig_bridge_ioctlwrap(h, name, BRDGGFWDMASK,
+ &fwd_mask_param, sizeof(fwd_mask_param), false) != 0) {
+ goto err;
+ }
+ bridge->inner.group_fwd_mask = fwd_mask_param.ifbrp_group_fwd_mask;
+
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
--- a/sbin/ifconfig/ifbridge.c
+++ b/sbin/ifconfig/ifbridge.c
@@ -235,6 +235,7 @@
stpproto[params->ifbop_protocol],
bridge->cache_size,
bridge->cache_lifetime);
+ printf("\tgroup_fwd_mask 0x%04x\n", bridge->group_fwd_mask);
PV2ID(params->ifbop_designated_root, bprio, lladdr);
printf("\troot id %s priority %d ifcost %u port %u\n",
ether_ntoa((struct ether_addr *)lladdr),
@@ -796,6 +797,21 @@
err(1, "BRDGSTO %s", arg);
}
+static void
+setbridge_group_fwd_mask(if_ctx *ctx, const char *arg, int dummy __unused)
+{
+ struct ifbrparam param;
+ u_long val;
+
+ if (get_val(arg, &val) < 0 || (val & ~0xffff) != 0)
+ errx(1, "invalid value: %s", arg);
+
+ param.ifbrp_group_fwd_mask = val & 0xffff;
+
+ if (do_cmd(ctx, BRDGSFWDMASK, &param, sizeof(param), 1) < 0)
+ err(1, "BRDGSFWDMASK %s", arg);
+}
+
static void
setbridge_private(if_ctx *ctx, const char *val, int dummy __unused)
{
@@ -1028,6 +1044,7 @@
DEF_CMD_ARG2("-iftagged", delbridge_iftagged),
DEF_CMD_ARG2("ifvlanproto", setbridge_ifvlanproto),
DEF_CMD_ARG("timeout", setbridge_timeout),
+ DEF_CMD_ARG("group_fwd_mask", setbridge_group_fwd_mask),
DEF_CMD_ARG("private", setbridge_private),
DEF_CMD_ARG("-private", unsetbridge_private),
DEF_CMD("vlanfilter", (int32_t)IFBRF_VLANFILTER,
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
@@ -121,6 +121,28 @@
For unicast traffic, the bridge learns which MAC addresses are associated
with which interfaces and will forward the traffic selectively.
.Pp
+By default,
+.Nm
+does not forward destination MAC addresses in the reserved link-local range
+.Li 01:80:c2:00:00:00
+through
+.Li 01:80:c2:00:00:0f .
+The
+.Xr ifconfig 8
+command
+.Cm group_fwd_mask
+accepts a 16-bit mask that selectively enables forwarding for this range.
+Bit
+.Ar n
+controls whether frames destined to
+.Li 01:80:c2:00:00:0n
+are forwarded across bridge member ports.
+For example, a mask of
+.Li 0x4000
+allows forwarding of
+.Li 01:80:c2:00:00:0e
+frames while leaving the remaining reserved destinations filtered.
+.Pp
By default the bridge logs MAC address port flapping to
.Xr syslog 3 .
This behavior can be disabled by setting the
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
@@ -286,6 +286,7 @@
LIST_ENTRY(bridge_softc) sc_list;
struct sx sc_sx;
struct mtx sc_rt_mtx;
+ uint16_t sc_group_fwd_mask; /* link-local group fwd mask */
uint32_t sc_brtmax; /* max # of addresses */
uint32_t sc_brtcnt; /* cur. # of addresses */
uint32_t sc_brttimeout; /* rt timeout in seconds */
@@ -425,6 +426,8 @@
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_ioctl_gfwdmask(struct bridge_softc *, void *);
+static int bridge_ioctl_sfwdmask(struct bridge_softc *, void *);
static int bridge_pfil(struct mbuf **, struct ifnet *, struct ifnet *,
int);
#ifdef INET
@@ -437,6 +440,8 @@
#endif /* INET6 */
static void bridge_linkstate(struct ifnet *ifp);
static void bridge_linkcheck(struct bridge_softc *sc);
+static bool bridge_rsvd_link_local_enabled(struct bridge_softc *,
+ const uint8_t *);
/*
* Use the "null" value from IEEE 802.1Q-2014 Table 9-2
@@ -659,6 +664,13 @@
{ bridge_ioctl_svlanproto, sizeof(struct ifbreq),
BC_F_COPYIN|BC_F_SUSER },
+
+ { bridge_ioctl_gfwdmask, sizeof(struct ifbrparam),
+ BC_F_COPYOUT },
+
+ { bridge_ioctl_sfwdmask, sizeof(struct ifbrparam),
+ BC_F_COPYIN|BC_F_SUSER },
+
};
static const int bridge_control_table_size = nitems(bridge_control_table);
@@ -857,6 +869,7 @@
ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
BRIDGE_LOCK_INIT(sc);
+ sc->sc_group_fwd_mask = 0;
sc->sc_brtmax = BRIDGE_RTABLE_MAX;
sc->sc_brttimeout = BRIDGE_RTABLE_TIMEOUT;
@@ -913,6 +926,19 @@
return (0);
}
+static bool
+bridge_rsvd_link_local_enabled(struct bridge_softc *sc, const uint8_t *dst)
+{
+ uint16_t bit;
+
+ if (dst[0] != 0x01 || dst[1] != 0x80 || dst[2] != 0xc2 ||
+ dst[3] != 0x00 || dst[4] != 0x00 || dst[5] > 0x0f)
+ return (false);
+
+ bit = (uint16_t)1 << dst[5];
+ return ((sc->sc_group_fwd_mask & bit) != 0);
+}
+
static void
bridge_clone_destroy_cb(struct epoch_context *ctx)
{
@@ -2219,6 +2245,15 @@
return (0);
}
+static int
+bridge_ioctl_gfwdmask(struct bridge_softc *sc, void *arg)
+{
+ struct ifbrparam *param = arg;
+
+ param->ifbrp_group_fwd_mask = sc->sc_group_fwd_mask;
+ return (0);
+}
+
static int
bridge_ioctl_sflags(struct bridge_softc *sc, void *arg)
{
@@ -2271,6 +2306,14 @@
return (0);
}
+bridge_ioctl_sfwdmask(struct bridge_softc *sc, void *arg)
+{
+ struct ifbrparam *param = arg;
+
+ sc->sc_group_fwd_mask = param->ifbrp_group_fwd_mask;
+ return (0);
+}
+
/*
* bridge_ifdetach:
*
@@ -2761,12 +2804,12 @@
goto drop;
} else {
/*
- * Check if its a reserved multicast address, any address
- * listed in 802.1D section 7.12.6 may not be forwarded by the
- * bridge.
- * This is currently 01-80-C2-00-00-00 to 01-80-C2-00-00-0F
+ * Reserved link-local destinations in the
+ * 01-80-C2-00-00-[00,0F] range are filtered unless the
+ * corresponding bit is enabled in group_fwd_mask.
*/
- if (dst[0] == 0x01 && dst[1] == 0x80 &&
+ if (!bridge_rsvd_link_local_enabled(sc, dst) &&
+ dst[0] == 0x01 && dst[1] == 0x80 &&
dst[2] == 0xc2 && dst[3] == 0x00 &&
dst[4] == 0x00 && dst[5] <= 0x0f)
goto drop;
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
@@ -132,6 +132,8 @@
#define BRDGGDEFPVID 36 /* get default pvid (ifbrparam) */
#define BRDGSDEFPVID 37 /* set default pvid (ifbrparam) */
#define BRDGSIFVLANPROTO 38 /* set if vlan protocol (ifbreq) */
+#define BRDGGFWDMASK 39 /* get group_fwd_mask (ifbrparam) */
+#define BRDGSFWDMASK 40 /* set group_fwd_mask (ifbrparam) */
/* BRDGSFLAGS, Bridge flags (non-interface-specific) */
typedef uint32_t ifbr_flags_t;
@@ -245,6 +247,8 @@
#define ifbrp_csize ifbrp_ifbrpu.ifbrpu_int32 /* cache size */
#define ifbrp_ctime ifbrp_ifbrpu.ifbrpu_int32 /* cache time (sec) */
#define ifbrp_prio ifbrp_ifbrpu.ifbrpu_int16 /* bridge priority */
+#define ifbrp_group_fwd_mask ifbrp_ifbrpu.ifbrpu_int16 /* reserved group
+ * fwd mask */
#define ifbrp_proto ifbrp_ifbrpu.ifbrpu_int8 /* bridge protocol */
#define ifbrp_txhc ifbrp_ifbrpu.ifbrpu_int8 /* bpdu tx holdcount */
#define ifbrp_hellotime ifbrp_ifbrpu.ifbrpu_int8 /* hello time (sec) */
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
@@ -793,6 +793,37 @@
vnet_cleanup
}
+atf_test_case "group_fwd_mask" "cleanup"
+group_fwd_mask_head()
+{
+ atf_set descr 'bridge group_fwd_mask control path'
+ atf_set require.user root
+}
+
+group_fwd_mask_body()
+{
+ vnet_init
+ vnet_init_bridge
+
+ bridge=$(vnet_mkbridge)
+
+ atf_check -s exit:0 -o match:'group_fwd_mask 0x0000' \
+ ifconfig ${bridge}
+ atf_check -s exit:0 ifconfig ${bridge} group_fwd_mask 0x4000
+ atf_check -s exit:0 -o match:'group_fwd_mask 0x4000' \
+ ifconfig ${bridge}
+ atf_check -s exit:0 ifconfig ${bridge} group_fwd_mask 0x8
+ atf_check -s exit:0 -o match:'group_fwd_mask 0x0008' \
+ ifconfig ${bridge}
+ atf_check -s exit:1 -e ignore \
+ ifconfig ${bridge} group_fwd_mask 0x10000
+}
+
+group_fwd_mask_cleanup()
+{
+ vnet_cleanup
+}
+
atf_test_case "member_ifaddrs_enabled" "cleanup"
member_ifaddrs_enabled_head()
{
@@ -1475,6 +1506,7 @@
atf_add_test_case "mtu"
atf_add_test_case "vlan"
atf_add_test_case "many_bridge_members"
+ atf_add_test_case "group_fwd_mask"
atf_add_test_case "member_ifaddrs_enabled"
atf_add_test_case "member_ifaddrs_disabled"
atf_add_test_case "member_ifaddrs_vlan"

File Metadata

Mime Type
text/plain
Expires
Thu, Aug 20, 11:32 AM (4 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36945434
Default Alt Text
D58729.id.diff (9 KB)

Event Timeline