I debugged this a bit further and figured out what the problem is.
The ISC dhcpd uses a bpf to "listen" on an interface. When a broadcast packet (e.g. DHCP request) comes in on one interface, the bridging code will correctly forward it out all the other interfaces in the cluster, and also deliver it locally. However, it will not send copies of the packet to all bpfs attached to all interfaces in the cluster, only to the one that the packet originally came in on.
This causes the problem decribed in PR kern/41632 (http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/41632), where dhcpd "listens" on interface A which is bridged to interface B. When A has no carrier, DHCP requests arriving on B are ignored. When A has a carrier, dhcp will get a copy of the packet when it is bridge-forwarded out A, so the problem doesn't occur then.
Attached is a rough patch to if_ethersubr.c that fixes the problem. It should probably further be tweaked (there's a chance for duplicates), but I wanted some comments first :-)
Lars
Luigi Rizzo wrote:
I guess the responsible of the problem is this part of code in sys/net/if_ethersubr.c:ether_demux():/* Discard packet if interface is not up */ if ((ifp->if_flags & IFF_UP) == 0) { m_freem(m); return; } which is somewhat funny, because once we have the packet, we might as well process it. Now, one could bypass the test for the bridging case, or remove it altogether... I am not sure which one is the best approach. On Mon, Aug 19, 2002 at 09:52:27AM -0700, Lars Eggert wrote: >I've filed a PR (kern/41632, >http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/41632) on the following >problem: > >FreeBSD box with two Ethernet NICs, e.g. if0 with IP address A and if1 >with IP address B, bridged together: > >net.link.ether.bridge_cfg: if0 if1 >net.link.ether.bridge: 1 > >Interface if0 is plugged in (has carrier), if1 isn't (no carrier). >Packets arriving on if0 for IP address B (or the broadcast address) are >not received by processes running on the bridging machine. > >Any ideas?
-- Lars Eggert <[EMAIL PROTECTED]> USC Information Sciences Institute
--- if_ethersubr.c.old Thu Oct 24 16:19:38 2002 +++ if_ethersubr.c Thu Oct 24 16:42:06 2002 @@ -616,9 +616,32 @@ } if (bif == BDG_LOCAL || bif == BDG_BCAST - || bif == BDG_MCAST) - goto recvLocal; /* receive locally */ + || 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 all bpfs attached + * to interfaces in the cluster. + */ + struct ifnet *ifp2; + TAILQ_FOREACH(ifp2, &ifnet, if_link) { + if (BDG_SAMECLUSTER(ifp, ifp2) && + ifp != ifp2 && + 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) m_freem(m);
smime.p7s
Description: S/MIME Cryptographic Signature