Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 20 Mar 2000 15:11:13 +0300
From:      Kurakin Roman <rik@cronyx.ru>
To:        Robert Watson <robert+freebsd@cyrus.watson.org>
Cc:        freebsd-net@FreeBSD.ORG
Subject:   Re: Patch to introduce bpfdetach(), Re: BPF question (FreeBSD 40)
Message-ID:  <38D61561.EADEDB6A@cronyx.ru>
References:  <Pine.NEB.3.96L.1000318204927.3649A-300000@fledge.watson.org>

next in thread | previous in thread | raw e-mail | index | archive | help


Robert Watson wrote:

> On Sat, 18 Mar 2000, Kurakin Roman wrote:
>
> >     I have question about using bpf in my KLD module driver. At attach I
> > call
> > bpfattach function. What should I call at detach?
> > Could some one describe to me how bpf is work (function calls, not bpf
> > as pf :)).
>
> I noticed the same behavior a few weeks ago when using tcpdump in wi0 and
> ejecting the card.  This occurs if there are open bpf descriptors for the
> device, and ifdetach is called (freeing the ifnet structure), at the
> bp_bif pointer is not set to NULL.

So, the problems would be if bpf was opened while we tried to detach driver?
If so, I have another solution. Driver should return EBUSY, if bpf is open at
the moment
we try to detach driver. User should close all references to the device before
its unloading.
But I don't know what would be if I try to open bpf after I removed my driver
from the kernel.
At this moment I can only give some ideas. I never worked with bpf as user :(

Thank you for your answer.

    Kurakin Roman


> I've been running a bpf patch for the last few hours that attempts to
> clean this behavior up.  It introduces a bpfdetach(ifp), which should be
> called just prior to ifdetach(ifp).  If there are any open descriptors on
> the interface, it sets the bif pointer to NULL, and wakes up listeners.
> In the bpfread loop, if there are no remaining buffers on the bpf
> descriptor, and it sees a bp_bif of NULL, it now returns ENXIO to the
> caller.  The remaining fd calls already appeared to have NULL checks for
> bp_bif, just not bpfread in its wait loop.  After this, it frees the
> bpf_desc structure.
>
> It appears to clean up the wi0 tcpdump crash, but I haven't tested it much
> more than that.  Needless to say, any location where ifdetach() is called
> (that had a matching bpfattach) should now also call bpfdetach().  I have
> only updated if_wi.c in my patch, as that's all I have on hand right now.
>
> Pccard drivers such as ep0 don't require the patch, as they never
> ifdetach(), leaving the ifnet epX around but unbound.
>
> One file attached patches src/sys/net to add the bpfdetach code
> (bpfdetach.diff).  The other patch patches if_wi.c to call bpfdetach
> (if_wi.diff)  Once it's adequately tested (volunteers welcome), I'll
> commit it to 5.0-CURRENT.
>
> > Hi,
> >
> >   Kurakin Roman
> >
> >
> >
> >
> > To Unsubscribe: send mail to majordomo@FreeBSD.org
> > with "unsubscribe freebsd-net" in the body of the message
> >
>
>   Robert N M Watson
>
> robert@fledge.watson.org              http://www.watson.org/~robert/
> PGP key fingerprint: AF B5 5F FF A6 4A 79 37  ED 5F 55 E9 58 04 6A B1
> TIS Labs at Network Associates, Safeport Network Services
>
>   ------------------------------------------------------------------------
> Only in /data/fbsd-commit/src/sys/net: CVS
> diff -u /data/fbsd-commit/src/sys/net/bpf.c ./bpf.c
> --- /data/fbsd-commit/src/sys/net/bpf.c Sat Mar 18 01:30:41 2000
> +++ ./bpf.c     Sat Mar 18 21:17:20 2000
> @@ -477,6 +477,18 @@
>                         ROTATE_BUFFERS(d);
>                         break;
>                 }
> +
> +               /*
> +                * No data is available, check to see if the bpf device
> +                * is still pointed at a real interface.  If not, return
> +                * ENXIO so that the userland process knows to rebind
> +                * it before using it again.
> +                */
> +               if (d->bd_bif == NULL) {
> +                       splx(s);
> +                       return (ENXIO);
> +               }
> +
>                 if (ioflag & IO_NDELAY)
>                         error = EWOULDBLOCK;
>                 else
> @@ -1285,6 +1297,60 @@
>
>         if (bootverbose)
>                 printf("bpf: %s%d attached\n", ifp->if_name, ifp->if_unit);
> +}
> +
> +/*
> + * Detach bpf from an interface.  This involves detaching each descriptor
> + * associated with the interface, and leaving bd_bif NULL.  Notify each
> + * descriptor as it's detached so that any sleepers wake up and get
> + * ENXIO.
> + */
> +void
> +bpfdetach(ifp)
> +       struct ifnet *ifp;
> +{
> +       struct bpf_if   *bp, *bp_prev;
> +       struct bpf_d    *d;
> +       int     s;
> +
> +       printf("bpfdetach: %s%d is being detached\n", ifp->if_name,
> +           ifp->if_unit);
> +
> +       /* XXX is this needed?  Is it right? */
> +       s = splimp();
> +
> +       /* Locate BPF interface information */
> +       bp_prev = NULL;
> +       for (bp = bpf_iflist; bp != NULL; bp = bp->bif_next) {
> +               if (ifp == bp->bif_ifp)
> +                       break;
> +               bp_prev = bp;
> +       }
> +
> +       /* Interface wasn't attached */
> +       if (bp->bif_ifp == NULL) {
> +               splx(s);
> +               printf("bpfdetach: %s%d was not attached\n", ifp->if_name,
> +                   ifp->if_unit);
> +               return;
> +       }
> +
> +       while ((d = bp->bif_dlist) != NULL) {
> +               bpf_detachd(d);
> +               bpf_wakeup(d);
> +       }
> +
> +       if (bp_prev) {
> +               bp_prev->bif_next = bp->bif_next;
> +       } else {
> +               bpf_iflist = bp->bif_next;
> +       }
> +
> +       free(bp, M_BPF);
> +
> +       splx(s);
> +
> +       printf("bpfdetach: %s%d is detached\n", ifp->if_name, ifp->if_unit);
>  }
>
>  static void bpf_drvinit __P((void *unused));
> diff -u /data/fbsd-commit/src/sys/net/bpf.h ./bpf.h
> --- /data/fbsd-commit/src/sys/net/bpf.h Sat Mar 18 01:30:42 2000
> +++ ./bpf.h     Sat Mar 18 21:16:33 2000
> @@ -232,6 +232,8 @@
>  void    bpf_tap __P((struct ifnet *, u_char *, u_int));
>  void    bpf_mtap __P((struct ifnet *, struct mbuf *));
>  void    bpfattach __P((struct ifnet *, u_int, u_int));
> +void    bpfdetach __P((struct ifnet *));
> +
>  void    bpfilterattach __P((int));
>  u_int   bpf_filter __P((const struct bpf_insn *, u_char *, u_int, u_int));
>  #endif
>
>   ------------------------------------------------------------------------
> --- if_wi.c     Wed Feb  2 12:59:12 2000
> +++ /tmp/if_wi.c        Sat Mar 18 21:19:39 2000
> @@ -214,6 +214,8 @@
>         }
>
>         wi_stop(sc);
> +
> +       bpfdetach(ifp);
>         if_detach(ifp);
>         bus_teardown_intr(dev, sc->irq, sc->wi_intrhand);
>         wi_free(dev);



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?38D61561.EADEDB6A>