[LOR] carp vs bridge

Xin LI delphij at delphij.net
Wed Jul 15 08:07:29 UTC 2009


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Here is a brute-force workaround for the issue, basically this would
convert the hard deadlock into another problem (no multicast/broadcast
being done on bridge, if CARP is enabled).  It's good enough for my
usage but is of course far from ideal.

As I am not sure how much I could step further on a real fix due to
$REALJOB, I'd like to share some further analysis for the problem.
Basically, it was caused by CARP's use of locking and bridge's locking,
the former would acquire CARP interface's mutex, while holding the
mutex, it tries to indirectly call ether_output which, in turn, calls
bridge_output if the CARP enabled interface is also part of a bridge.
Since the bridge_output wants to acquire lock for the bridge's member
interface, which is potentially parent for CARP interface, the order
constraint is violated and thus a deadlock could happen.

I think there is no obvious clean solution to break the dependency
without weakening the realtimeness of sending the required multicast at
this point.  Will think again about it when I got some spare time.

Cheers,
- --
Xin LI <delphij at delphij.net>	http://www.delphij.net/
FreeBSD - The Power to Serve!
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.12 (FreeBSD)

iEYEARECAAYFAkpdjfAACgkQi+vbBBjt66BxsACgggT8vhXo62V7Sh+2uAA0re2c
dmEAnix+ax16obT2+neW7Iw0/P12cBVp
=IM/r
-----END PGP SIGNATURE-----
-------------- next part --------------
Index: if_ethersubr.c
===================================================================
--- if_ethersubr.c	(revision 195705)
+++ if_ethersubr.c	(working copy)
@@ -394,8 +394,18 @@
 	* Bridges require special output handling.
 	*/
 	if (ifp->if_bridge) {
+#if defined(INET) || defined(INET6)
+#ifdef DEV_CARP
+		if ((m->m_flags & ~(M_MCAST | M_BCAST)) == m->m_flags) {
+#endif
+#endif
 		BRIDGE_OUTPUT(ifp, m, error);
 		return (error);
+#if defined(INET) || defined(INET6)
+#ifdef DEV_CARP
+		}
+#endif
+#endif
 	}
 
 #if defined(INET) || defined(INET6)


More information about the freebsd-net mailing list