Lars Eggert wrote:

> 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.

This problem was also solved in the giant patch for network stack virtualization.
As this patch completely removes the ifp2sc array, and instead extends struct
arpcom to hold the bridge cluster association of the interface, it wouldn't make
too much sense to post it here - you can check the entire patch at
http://www.tel.fer.hr/zec/BSD/vimage/
This patch also solves the problem of bpf tapping on the outgoing traffic. Using
the current bridging code, if you tap on a bridged interface that is either
unplugged or actually transmits data over another interface in the cluster, the
outgoing traffic (mbufs) will never reach this interface's outbound queue. As the
bpf tapping on outgoing mbufs is left to the device driver (this is normally done
in if_start routine), a bpf filter active on this interface will never catch such
traffic. This problem is however not critical for normal applications, but can be
very annoying when debugging the network connections, especially in a kernel with
multiple network stack instances.
This patch also ensures no duplicate or unnecessary tapping will occur. However,
note that it currently badly breaks the bridging statistics. I hope to fix that
in the near future...

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

The looping proposed in your patch would be probably OK for BDG_MCAST and
BDG_BCAST traffic, but definitely not for BDG_LOCAL, i think.

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


To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-net" in the body of the message

Reply via email to