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);