Module Name: src
Committed By: roy
Date: Wed May 4 18:59:55 UTC 2016
Modified Files:
src/sys/net: if_bridge.c
Log Message:
Allow multicast/broadcast packets from a bridge member to other members.
Note this should just call bridge_broadcast when more locking issues are
resolved.
To generate a diff of this commit:
cvs rdiff -u -r1.121 -r1.122 src/sys/net/if_bridge.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/net/if_bridge.c
diff -u src/sys/net/if_bridge.c:1.121 src/sys/net/if_bridge.c:1.122
--- src/sys/net/if_bridge.c:1.121 Thu Apr 28 01:37:17 2016
+++ src/sys/net/if_bridge.c Wed May 4 18:59:55 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_bridge.c,v 1.121 2016/04/28 01:37:17 knakahara Exp $ */
+/* $NetBSD: if_bridge.c,v 1.122 2016/05/04 18:59:55 roy Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@@ -80,7 +80,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.121 2016/04/28 01:37:17 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.122 2016/05/04 18:59:55 roy Exp $");
#ifdef _KERNEL_OPT
#include "opt_bridge_ipf.h"
@@ -1422,6 +1422,14 @@ bridge_output(struct ifnet *ifp, struct
eh = mtod(m, struct ether_header *);
sc = ifp->if_bridge;
+ if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
+ if (memcmp(etherbroadcastaddr,
+ eh->ether_dhost, ETHER_ADDR_LEN) == 0)
+ m->m_flags |= M_BCAST;
+ else
+ m->m_flags |= M_MCAST;
+ }
+
/*
* If bridge is down, but the original output interface is up,
* go ahead and send out that interface. Otherwise, the packet
@@ -1437,11 +1445,13 @@ bridge_output(struct ifnet *ifp, struct
* If the packet is a multicast, or we don't know a better way to
* get there, send to all interfaces.
*/
- if (ETHER_IS_MULTICAST(eh->ether_dhost))
+ if ((m->m_flags & (M_MCAST | M_BCAST)) != 0)
dst_if = NULL;
else
dst_if = bridge_rtlookup(sc, eh->ether_dhost);
if (dst_if == NULL) {
+ /* XXX Should call bridge_broadcast, but there are locking
+ * issues which need resolving first. */
struct bridge_iflist *bif;
struct mbuf *mc;
bool used = false;
@@ -1474,7 +1484,10 @@ bridge_output(struct ifnet *ifp, struct
}
if (PSLIST_READER_NEXT(bif, struct bridge_iflist,
- bif_next) == NULL) {
+ bif_next) == NULL &&
+ ((m->m_flags & (M_MCAST | M_BCAST)) == 0 ||
+ dst_if == ifp))
+ {
used = true;
mc = m;
} else {
@@ -1492,6 +1505,36 @@ bridge_output(struct ifnet *ifp, struct
#ifndef NET_MPSAFE
splx(s);
#endif
+
+ if ((m->m_flags & (M_MCAST | M_BCAST)) != 0 &&
+ dst_if != ifp)
+ {
+ if (PSLIST_READER_NEXT(bif,
+ struct bridge_iflist, bif_next) == NULL)
+ {
+ used = true;
+ mc = m;
+ } else {
+ mc = m_copym(m, 0, M_COPYALL,
+ M_DONTWAIT);
+ if (mc == NULL) {
+ sc->sc_if.if_oerrors++;
+ goto next;
+ }
+ }
+
+ mc->m_pkthdr.rcvif = dst_if;
+ mc->m_flags &= ~M_PROMISC;
+
+#ifndef NET_MPSAFE
+ s = splnet();
+#endif
+ ether_input(dst_if, mc);
+#ifndef NET_MPSAFE
+ splx(s);
+#endif
+ }
+
next:
BRIDGE_PSZ_RENTER(s);
bridge_release_member(sc, bif, &psref);