--- if_ethersubr.c.orig Fri Aug 30 07:23:38 2002 +++ usr/src/sys/net/if_ethersubr.c Tue Oct 29 10:39:08 2002 @@ -391,6 +391,23 @@ if (rule) /* packet was already bridged */ goto no_bridge; +{ + struct ether_header *eh = mtod(m, struct ether_header *); + if (ntohs(eh->ether_type) == ETHERTYPE_IPV6) + /* + * Do not bridge IPv6 packets. It will confuse IPv6 neighbor + * discovery, since link-local addresses in the KAME + * implementation are per-interface. The RFCs allow multiple + * interfaces per link, but KAME does not currently implement + * this. + * + * Not bridging IPv6 allows a routed IPv6 configuration to + * coexist with a bridged IPv4 configuration. (While bridging + * IPv6 does not.) + */ + goto no_bridge; +} + if (BDG_ACTIVE(ifp) ) { struct ether_header *eh; /* a ptr suffices */ @@ -587,6 +604,20 @@ return; } + if (ntohs(eh->ether_type) == ETHERTYPE_IPV6) + /* + * Do not bridge IPv6 packets. It will confuse IPv6 neighbor + * discovery, since link-local addresses in the KAME + * implementation are per-interface. The RFCs allow multiple + * interfaces per link, but KAME does not currently implement + * this. + * + * Not bridging IPv6 allows a routed IPv6 configuration to + * coexist with a bridged IPv4 configuration. (While bridging + * IPv6 does not.) + */ + goto recvLocal; + /* Check for bridging mode */ if (BDG_ACTIVE(ifp) ) { struct ifnet *bif; @@ -616,8 +647,33 @@ } if (bif == BDG_LOCAL || bif == BDG_BCAST - || bif == BDG_MCAST) + || bif == BDG_MCAST) { +#define BDG_CLUSTER(ifp) (ifp2sc[ifp->if_index].cluster) + +#define BDG_SAMECLUSTER(ifp,src) \ + (src == NULL || BDG_CLUSTER(ifp) == BDG_CLUSTER(src) ) + + /* + * Deliver a copy of the packet to bpfs attached + * to all interfaces in the cluster that have + * no carrier. + */ + struct ifnet *ifp2; + TAILQ_FOREACH(ifp2, &ifnet, if_link) { + if (BDG_SAMECLUSTER(ifp, ifp2) && + ifp != ifp2 && + (!(ifp2->if_flags & IFF_OACTIVE)) && + ifp2->if_bpf != NULL) { + struct m_hdr mh; + mh.mh_next = m; + mh.mh_data = (char *)eh; + mh.mh_len = ETHER_HDR_LEN; + bpf_mtap(ifp2, (struct mbuf *)&mh); + } + } + goto recvLocal; /* receive locally */ + } /* If not local and not multicast, just drop it */ if (m != NULL) --- /nfs/ruby/larse/if_var.h Sun Oct 27 11:48:06 2002 +++ usr/src/sys/net/if_var.h Sun Oct 27 11:47:47 2002 @@ -272,6 +272,38 @@ int need_if_start = 0; int s = splimp(); + /* + * Drop the packet if the outbound interface has no carrier. + * This prevents the queue from filling up, causing bridging + * to fail, since packets would be dropped before being bridged. + * + * XXX I'd be nice if we could easily peek at the media status + * here. Instead, use a 50% full queue together with the + * interface not sending is an indicator. + */ + if (ifp && (!(ifp->if_flags & IFF_OACTIVE)) && + ifq->ifq_len > ifq->ifq_maxlen / 2) { + /* + * Flush the queue here, otherwise we send out stale + * packets once the interface gets a carrier. + * + * XXX This duplicates ifq_qflush(). + */ + register struct mbuf *m2, *n; + n = ifq->ifq_head; + while ((m2 = n) != 0) { + n = m2->m_act; + m_freem(m2); + } + ifq->ifq_head = 0; + ifq->ifq_tail = 0; + ifq->ifq_len = 0; + + /* Now drop the packet. */ + m_freem(m); + return (0); + } + if (IF_QFULL(ifq)) { IF_DROP(ifq); splx(s);