bridge: Log MAC address port flapping
MAC flapping occurs when a bridge receives packets with the same source MAC address on different member interfaces. The common reasons are: - user roams from one bridge port to another - user has wrong network setup, bridge loops e.g. - someone set duplicated ethernet address on his/her nic - some bad guy / virus / trojan send spoofed packets if_bridge currently updates the bridge routing entry silently hence it is hard to diagnose. Emit logs when MAC address port flapping occurs to make it easier to diagnose. Reviewed by: kp MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D39375
This commit is contained in:
parent
09e5e3d598
commit
2d3614fb13
@ -460,6 +460,21 @@ SYSCTL_INT(_net_link_bridge, OID_AUTO, allow_llz_overlap,
|
|||||||
"Allow overlap of link-local scope "
|
"Allow overlap of link-local scope "
|
||||||
"zones of a bridge interface and the member interfaces");
|
"zones of a bridge interface and the member interfaces");
|
||||||
|
|
||||||
|
/* log MAC address port flapping */
|
||||||
|
VNET_DEFINE_STATIC(bool, log_mac_flap) = true;
|
||||||
|
#define V_log_mac_flap VNET(log_mac_flap)
|
||||||
|
SYSCTL_BOOL(_net_link_bridge, OID_AUTO, log_mac_flap,
|
||||||
|
CTLFLAG_RW | CTLFLAG_VNET, &VNET_NAME(log_mac_flap), true,
|
||||||
|
"Log MAC address port flapping");
|
||||||
|
|
||||||
|
VNET_DEFINE_STATIC(int, log_interval) = 5;
|
||||||
|
VNET_DEFINE_STATIC(int, log_count) = 0;
|
||||||
|
VNET_DEFINE_STATIC(struct timeval, log_last) = { 0 };
|
||||||
|
|
||||||
|
#define V_log_interval VNET(log_interval)
|
||||||
|
#define V_log_count VNET(log_count)
|
||||||
|
#define V_log_last VNET(log_last)
|
||||||
|
|
||||||
struct bridge_control {
|
struct bridge_control {
|
||||||
int (*bc_func)(struct bridge_softc *, void *);
|
int (*bc_func)(struct bridge_softc *, void *);
|
||||||
int bc_argsize;
|
int bc_argsize;
|
||||||
@ -2768,6 +2783,7 @@ bridge_rtupdate(struct bridge_softc *sc, const uint8_t *dst, uint16_t vlan,
|
|||||||
struct bridge_iflist *bif, int setflags, uint8_t flags)
|
struct bridge_iflist *bif, int setflags, uint8_t flags)
|
||||||
{
|
{
|
||||||
struct bridge_rtnode *brt;
|
struct bridge_rtnode *brt;
|
||||||
|
struct bridge_iflist *obif;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
BRIDGE_LOCK_OR_NET_EPOCH_ASSERT(sc);
|
BRIDGE_LOCK_OR_NET_EPOCH_ASSERT(sc);
|
||||||
@ -2791,7 +2807,7 @@ bridge_rtupdate(struct bridge_softc *sc, const uint8_t *dst, uint16_t vlan,
|
|||||||
|
|
||||||
/* Check again, now that we have the lock. There could have
|
/* Check again, now that we have the lock. There could have
|
||||||
* been a race and we only want to insert this once. */
|
* been a race and we only want to insert this once. */
|
||||||
if ((brt = bridge_rtnode_lookup(sc, dst, vlan)) != NULL) {
|
if (bridge_rtnode_lookup(sc, dst, vlan) != NULL) {
|
||||||
BRIDGE_RT_UNLOCK(sc);
|
BRIDGE_RT_UNLOCK(sc);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -2840,12 +2856,24 @@ bridge_rtupdate(struct bridge_softc *sc, const uint8_t *dst, uint16_t vlan,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC &&
|
if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC &&
|
||||||
brt->brt_dst != bif) {
|
(obif = brt->brt_dst) != bif) {
|
||||||
BRIDGE_RT_LOCK(sc);
|
BRIDGE_RT_LOCK(sc);
|
||||||
brt->brt_dst->bif_addrcnt--;
|
brt->brt_dst->bif_addrcnt--;
|
||||||
brt->brt_dst = bif;
|
brt->brt_dst = bif;
|
||||||
brt->brt_dst->bif_addrcnt++;
|
brt->brt_dst->bif_addrcnt++;
|
||||||
BRIDGE_RT_UNLOCK(sc);
|
BRIDGE_RT_UNLOCK(sc);
|
||||||
|
|
||||||
|
if (V_log_mac_flap &&
|
||||||
|
ppsratecheck(&V_log_last, &V_log_count, V_log_interval)) {
|
||||||
|
uint8_t *addr = &brt->brt_addr[0];
|
||||||
|
log(LOG_NOTICE,
|
||||||
|
"%s: mac address %02x:%02x:%02x:%02x:%02x:%02x vlan %d moved from %s to %s\n",
|
||||||
|
sc->sc_ifp->if_xname,
|
||||||
|
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
|
||||||
|
brt->brt_vlan,
|
||||||
|
obif->bif_ifp->if_xname,
|
||||||
|
bif->bif_ifp->if_xname);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC)
|
if ((flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC)
|
||||||
|
Loading…
Reference in New Issue
Block a user