Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 29 Mar 2023 13:05:08 +0800
From:      Zhenlei Huang <zlei@FreeBSD.org>
To:        overwatch@lab.kyngin.net
Cc:        freebsd-net@freebsd.org
Subject:   Re: Help testing patch that may help diagnosing the PR 240106
Message-ID:  <4416034C-237B-4D8F-B04E-A22F2D56BF9C@FreeBSD.org>
In-Reply-To: <4431A103-64AA-4EDF-9830-ED320161B75C@FreeBSD.org>
References:  <4431A103-64AA-4EDF-9830-ED320161B75C@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]


> On Mar 29, 2023, at 1:03 PM, Zhenlei Huang <zlei@FreeBSD.org> wrote:
> 
> Hi,
> 
> I write here so that the original PR 240106 is not polluted.
> 
> Can you please test the attached patch with bridge / lagg setup?
> 
> For long:
> 
> In https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=240106#c28 you encountered
> problem and I said:
> 
>> The IF_BRIDGE(4) seems to hide some thing to protect itself get confused.
> Actually IF_BRIDGE(4) has a learning mode. You can `man ifconfig` and refer the
> `Bridge Interface Parameters` section.
> 
> By default the learning mode of all bridge members is on, and the bridge will
> insert or update an entry to its (internal) forwarding table. When unicast packets
> come to the bridge member, the bridge will check if it is for itself, if not then
> the packets will be forwarded to one bridge member if a forwarding entry is found.
> While the magic is, if the bridge member to be forwarded is the receiving one, then
> the packets are silently discarded.
> 
> That's perfect fine, but will be hard to diagnose if user has wrong network setup,
> bridge loops e.g., or some other ones set duplicated ether address for their nic,
> or some bad guys / virus / trojans send spoofed packets on the wire. Those are common
> and I think it will be good if IF_BRIDGE(4) can emit logs so that the symptoms will
> be obvious and it will be easy to diagnose.
> 
>> If you can confirm, then please config you switch properly. The two ports cc0 and cc1 connected should be in same link aggregation group.
> 
> If two ports (on physical switch), say 1 and 2, are not in same link aggregation group,
> then packets (typically broadcast ones) received on 1 will be forwarded to 2, and
> the lagg interface will be bounce-backed (from port 2) the packets it send (to port 1).
> If the lagg happenly be the member of IF_BRIDGE(4), then the bridge will update
> its forwarding entry as it learn mac address from lagg interface.
> 
> Here is a simple diagram, the arrow shows the flow of ARP request from epair0a.
> 
> 11:22:33:44:55:66         [1]                  -> cc0 ->  port 1 -> 
>       epair0a -> epair0b -> bridge0 -> lagg0                        physical-switch <-> host0
>                                     <-        <- cc1 <-  port 2 <-  
>                                     [2]                          
> 
> On [1] bridge0 will learn MAC 11:22:33:44:55:66 on port member epair0b and add entry,
> after [2] it will learn same MAC on port member lagg0 and update the entry. Then
> subsequent ARP reply (to 11:22:33:44:55:66, epair0a i.e.) sent from host0 reach bridge0
> via lagg0.
> 
> Apparently bridge0 will dropped the ARP reply as it believes 11:22:33:44:55:66 (epair0a) is
> within segment of lagg0.
> 
>> I'll see if I can teach IF_BRIDGE(4) to emit warnings in case it get ARP request packet sent from it self.
> 
> Attached patch will enable IF_BRIDGE(4) to emit logs about MAC address port flapping.
> Various hardware vendors have similar facilities.
> 
> 
> Best regards,
> Zhenlei
> 

Sorry forgot the patch.


[-- Attachment #2 --]
From 787c9eb9d8065f85643ad32f2322e660ca897dfa Mon Sep 17 00:00:00 2001
From: Zhenlei Huang <zlei@FreeBSD.org>
Date: Mon, 27 Mar 2023 23:59:20 +0800
Subject: [PATCH] bridge: Log MAC address port flapping

---
 sys/net/if_bridge.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 60a1683c74ae..41e009f19e87 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -460,6 +460,13 @@ SYSCTL_INT(_net_link_bridge, OID_AUTO, allow_llz_overlap,
     "Allow overlap of link-local scope "
     "zones of a bridge interface and the member interfaces");
 
+/* log MAC port flapping */
+VNET_DEFINE_STATIC(int, log_mac_flap) = 1;
+#define	V_log_mac_flap	VNET(log_mac_flap)
+SYSCTL_INT(_net_link_bridge, OID_AUTO, log_mac_flap,
+    CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(log_mac_flap), 0,
+    "Log MAC port flapping");
+
 struct bridge_control {
 	int	(*bc_func)(struct bridge_softc *, void *);
 	int	bc_argsize;
@@ -2773,6 +2780,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_rtnode *brt;
+	struct bridge_iflist *obif;
 	int error;
 
 	BRIDGE_LOCK_OR_NET_EPOCH_ASSERT(sc);
@@ -2796,7 +2804,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
 		 * 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);
 			return (0);
 		}
@@ -2844,13 +2852,24 @@ bridge_rtupdate(struct bridge_softc *sc, const uint8_t *dst, uint16_t vlan,
 		BRIDGE_RT_UNLOCK(sc);
 	}
 
+
 	if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC &&
-	    brt->brt_dst != bif) {
+	    (obif = brt->brt_dst) != bif) {
 		BRIDGE_RT_LOCK(sc);
 		brt->brt_dst->bif_addrcnt--;
 		brt->brt_dst = bif;
 		brt->brt_dst->bif_addrcnt++;
 		BRIDGE_RT_UNLOCK(sc);
+
+		/* TODO also log aging time ?  need (time_uptime - brt_create_time) */
+		if (V_log_mac_flap)
+			log(LOG_NOTICE, "%s: mac address %02x:%02x:%02x:%02x:%02x:%02x vlan %d flaps from %s to %s\n",
+			    sc->sc_ifp->if_xname,
+			    brt->brt_addr[0], brt->brt_addr[1], brt->brt_addr[2],
+			    brt->brt_addr[3], brt->brt_addr[4], brt->brt_addr[5],
+			    brt->brt_vlan,
+			    obif->bif_ifp->if_xname,
+			    bif->bif_ifp->if_xname);
 	}
 
 	if ((flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC)
-- 
2.24.3 (Apple Git-128)


[-- Attachment #3 --]





Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4416034C-237B-4D8F-B04E-A22F2D56BF9C>