tech-net archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
SOLVED: Multicast problems with bridge(4) ports
Hi all,
I have found the bug that causes this and I've got a fix.
The problem is that bridge_broadcast() only puts broadcast packets onto the
output queue of the interfaces it is broadcasting the packet to and doesn't put
a copy onto their input queues. I just added a small lump of code to copy the
packet appropriately and I used M_LINK2 to avoid broadcasting packets that have
already been broadcast.
The NetBSD bridge(4) code for handling unicast packets has a short circuit in
it that allows an input packet to be switched onto another interface as
ether_input() passes it up the protocol stack, but this can't be done for
broadcasts because each interface needs its own copy of the packet.
I'll raise a PR for this, and here's the code I'll be submitting with it. I'll
also copy my test configuration into the PR for reference. I'm more than happy
to take suggestions on better ways to fix this.
Cheers,
Lloyd
Index: sys/net/if_bridge.c
===================================================================
RCS file: /vol/src/rsync-src/src/sys/net/if_bridge.c,v
retrieving revision 1.74
diff -u -r1.74 if_bridge.c
--- sys/net/if_bridge.c 19 Nov 2011 22:51:25 -0000 1.74
+++ sys/net/if_bridge.c 5 Aug 2013 00:05:32 -0000
@@ -1633,6 +1633,13 @@
}
bridge_enqueue(sc, dst_if, mc, 1);
+ mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
+ if (mc == NULL) {
+ sc->sc_if.if_oerrors++;
+ continue;
+ }
+ mc->m_pkthdr.rcvif = dst_if;
+ (*dst_if->if_input)(dst_if, mc);
}
if (used == 0)
m_freem(m);
Index: sys/net/if_ethersubr.c
===================================================================
RCS file: /vol/src/rsync-src/src/sys/net/if_ethersubr.c,v
retrieving revision 1.188.8.3
diff -u -r1.188.8.3 if_ethersubr.c
--- sys/net/if_ethersubr.c 31 Oct 2012 16:07:46 -0000 1.188.8.3
+++ sys/net/if_ethersubr.c 4 Aug 2013 06:53:32 -0000
@@ -703,7 +703,8 @@
* will always return the original packet if we need to
* process it locally.
*/
- if (ifp->if_bridge) {
+ if (ifp->if_bridge && (m->m_flags & M_LINK2) == 0) {
+ m->m_flags |= M_LINK2;
/* clear M_PROMISC, in case the packets comes from a vlan */
m->m_flags &= ~M_PROMISC;
m = bridge_input(ifp, m);
Home |
Main Index |
Thread Index |
Old Index