Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/net Fix bpf so that select will return for a timeout (fr...



details:   https://anonhg.NetBSD.org/src/rev/4862f12d9b3a
branches:  trunk
changeset: 565514:4862f12d9b3a
user:      darrenr <darrenr%NetBSD.org@localhost>
date:      Sat Apr 10 23:31:51 2004 +0000

description:
Fix bpf so that select will return for a timeout (from FreeBSD.)

Fix the behaviour of BIOCIMMEDIATE (fix from LBL BPF code via FreeBSD.)

In bpf_mtap(), optimise the calling of bpf_filter() and catchpacket()
based on whether or not the entire packet is in one mbuf (based on
similar change FreeBSD but fixes BIOC*SEESENT issue with that.)

Copy the implementation of BIOCSSEESENT, BIOCGSEESENT by FreeBSD.

Review Assistance: Guy Harris

PRs: kern/8674, kern/12170

diffstat:

 sys/net/bpf.c     |  115 +++++++++++++++++++++++++++++++++++++++++------------
 sys/net/bpf.h     |   22 +++++----
 sys/net/bpfdesc.h |   11 ++++-
 3 files changed, 111 insertions(+), 37 deletions(-)

diffs (truncated from 324 to 300 lines):

diff -r 17d9f0d58682 -r 4862f12d9b3a sys/net/bpf.c
--- a/sys/net/bpf.c     Sat Apr 10 23:31:41 2004 +0000
+++ b/sys/net/bpf.c     Sat Apr 10 23:31:51 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bpf.c,v 1.90 2004/03/24 15:34:54 atatat Exp $  */
+/*     $NetBSD: bpf.c,v 1.91 2004/04/10 23:31:51 darrenr Exp $ */
 
 /*
  * Copyright (c) 1990, 1991, 1993
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bpf.c,v 1.90 2004/03/24 15:34:54 atatat Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bpf.c,v 1.91 2004/04/10 23:31:51 darrenr Exp $");
 
 #include "bpfilter.h"
 
@@ -114,6 +114,7 @@
 static void    bpf_attachd __P((struct bpf_d *, struct bpf_if *));
 static void    bpf_detachd __P((struct bpf_d *));
 static int     bpf_setif __P((struct bpf_d *, struct ifreq *));
+static void    bpf_timed_out __P((void *));
 static __inline void
                bpf_wakeup __P((struct bpf_d *));
 static void    catchpacket __P((struct bpf_d *, u_char *, u_int, u_int,
@@ -380,6 +381,8 @@
        /* Mark "free" and do most initialization. */
        memset((char *)d, 0, sizeof(*d));
        d->bd_bufsize = bpf_bufsize;
+       d->bd_seesent = 1;
+       callout_init(&d->bd_callout);
 
        return (0);
 }
@@ -400,6 +403,9 @@
        int s;
 
        s = splnet();
+       if (d->bd_state == BPF_WAITING)
+               callout_stop(&d->bd_callout);
+       d->bd_state = BPF_IDLE;
        if (d->bd_bif)
                bpf_detachd(d);
        splx(s);
@@ -429,6 +435,7 @@
        int ioflag;
 {
        struct bpf_d *d = &bpf_dtab[minor(dev)];
+       int timed_out;
        int error;
        int s;
 
@@ -440,17 +447,17 @@
                return (EINVAL);
 
        s = splnet();
+       if (d->bd_state == BPF_WAITING)
+               callout_stop(&d->bd_callout);
+       timed_out = (d->bd_state == BPF_TIMED_OUT);
+       d->bd_state = BPF_IDLE;
        /*
         * If the hold buffer is empty, then do a timed sleep, which
         * ends when the timeout expires or when enough packets
         * have arrived to fill the store buffer.
         */
        while (d->bd_hbuf == 0) {
-               if (d->bd_immediate) {
-                       if (d->bd_slen == 0) {
-                               splx(s);
-                               return (EWOULDBLOCK);
-                       }
+               if ((d->bd_immediate || timed_out) && d->bd_slen != 0) {
                        /*
                         * A packet(s) either arrived since the previous
                         * read or arrived while we were asleep.
@@ -463,11 +470,8 @@
                        error = tsleep((caddr_t)d, PRINET|PCATCH, "bpf",
                                          d->bd_rtout);
                else {
-                       if (d->bd_rtout == -1) {
-                               /* User requested non-blocking I/O */
-                               error = EWOULDBLOCK;
-                       } else
-                               error = 0;
+                       /* User requested non-blocking I/O */
+                       error = EWOULDBLOCK;
                }
                if (error == EINTR || error == ERESTART) {
                        splx(s);
@@ -535,6 +539,24 @@
        d->bd_sel.sel_pid = 0;
 }
 
+
+static void
+bpf_timed_out(arg)
+       void *arg;
+{
+       struct bpf_d *d = (struct bpf_d *)arg;
+       int s;
+
+       s = splnet();
+       if (d->bd_state == BPF_WAITING) {
+               d->bd_state = BPF_TIMED_OUT;
+               if (d->bd_slen != 0)
+                       bpf_wakeup(d);
+       }
+       splx(s);
+}
+
+
 int
 bpfwrite(dev, uio, ioflag)
        dev_t dev;
@@ -631,6 +653,12 @@
        struct bpf_insn **p;
 #endif
 
+       s = splnet();
+       if (d->bd_state == BPF_WAITING)
+               callout_stop(&d->bd_callout);
+       d->bd_state = BPF_IDLE;
+       splx(s);
+
        switch (cmd) {
 
        default:
@@ -853,6 +881,20 @@
                d->bd_hdrcmplt = *(u_int *)addr ? 1 : 0;
                break;
 
+       /*
+        * Get "see sent packets" flag
+        */
+       case BIOCGSEESENT:
+               *(u_int *)addr = d->bd_seesent;
+               break;
+
+       /*
+        * Set "see sent" packets flag
+        */
+       case BIOCSSEESENT:
+               d->bd_seesent = *(u_int *)addr;
+               break;
+
        case FIONBIO:           /* Non-blocking I/O */
                if (*(int *)addr)
                        d->bd_rtout = -1;
@@ -1040,10 +1082,19 @@
                /*
                 * An imitation of the FIONREAD ioctl code.
                 */
-               if (d->bd_hlen != 0 || (d->bd_immediate && d->bd_slen != 0))
+               if (d->bd_hlen != 0 ||
+                   ((d->bd_immediate || d->bd_state == BPF_TIMED_OUT) &&
+                    d->bd_slen != 0))
                        revents |= events & (POLLIN | POLLRDNORM);
-               else
+               else {
                        selrecord(p, &d->bd_sel);
+                       /* Start the read timeout if necessary */
+                       if (d->bd_rtout > 0 && d->bd_state == BPF_IDLE) {
+                               callout_reset(&d->bd_callout, d->bd_rtout,
+                                             bpf_timed_out, d);
+                               d->bd_state = BPF_WAITING;
+                       }
+               }
        }
 
        splx(s);
@@ -1168,20 +1219,34 @@
        caddr_t arg;
        struct mbuf *m;
 {
+       void *(*cpfn) __P((void *, const void *, size_t));
        struct bpf_if *bp = (struct bpf_if *)arg;
        struct bpf_d *d;
-       u_int pktlen, slen;
+       u_int pktlen, slen, buflen;
        struct mbuf *m0;
+       void *marg;
 
        pktlen = 0;
        for (m0 = m; m0 != 0; m0 = m0->m_next)
                pktlen += m0->m_len;
 
+       if (pktlen == m->m_len) {
+               cpfn = memcpy;
+               marg = mtod(m, void *);
+               buflen = pktlen;
+       } else {
+               cpfn = bpf_mcpy;
+               marg = m;
+               buflen = 0;
+       }
+
        for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
+               if (!d->bd_seesent && (m->m_pkthdr.rcvif == NULL))
+                       continue;
                ++d->bd_rcount;
-               slen = bpf_filter(d->bd_filter, (u_char *)m, pktlen, 0);
+               slen = bpf_filter(d->bd_filter, marg, pktlen, buflen);
                if (slen != 0)
-                       catchpacket(d, (u_char *)m, pktlen, slen, bpf_mcpy);
+                       catchpacket(d, marg, pktlen, slen, cpfn);
        }
 }
 
@@ -1234,7 +1299,13 @@
                ROTATE_BUFFERS(d);
                bpf_wakeup(d);
                curlen = 0;
-       }
+       } else if (d->bd_immediate || d->bd_state == BPF_TIMED_OUT)
+               /*
+                * Immediate mode is set, or the read timeout has
+                * already expired during a select call.  A packet
+                * arrived, so the reader should be woken up.
+                */
+               bpf_wakeup(d);
 
        /*
         * Append the bpf header.
@@ -1248,14 +1319,6 @@
         */
        (*cpfn)((u_char *)hp + hdrlen, pkt, (hp->bh_caplen = totlen - hdrlen));
        d->bd_slen = curlen + totlen;
-
-       if (d->bd_immediate) {
-               /*
-                * Immediate mode is set.  A packet arrived so any
-                * reads should be woken up.
-                */
-               bpf_wakeup(d);
-       }
 }
 
 /*
diff -r 17d9f0d58682 -r 4862f12d9b3a sys/net/bpf.h
--- a/sys/net/bpf.h     Sat Apr 10 23:31:41 2004 +0000
+++ b/sys/net/bpf.h     Sat Apr 10 23:31:51 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bpf.h,v 1.33 2004/01/22 00:32:41 jonathan Exp $        */
+/*     $NetBSD: bpf.h,v 1.34 2004/04/10 23:31:52 darrenr Exp $ */
 
 /*
  * Copyright (c) 1990, 1991, 1993
@@ -102,12 +102,12 @@
  * header files.  If your using gcc, we assume that you
  * have run fixincludes so the latter set should work.
  */
-#define        BIOCGBLEN        _IOR('B',102, u_int)
-#define        BIOCSBLEN       _IOWR('B',102, u_int)
-#define        BIOCSETF         _IOW('B',103, struct bpf_program)
-#define        BIOCFLUSH         _IO('B',104)
+#define BIOCGBLEN       _IOR('B',102, u_int)
+#define BIOCSBLEN      _IOWR('B',102, u_int)
+#define BIOCSETF        _IOW('B',103, struct bpf_program)
+#define BIOCFLUSH        _IO('B',104)
 #define BIOCPROMISC      _IO('B',105)
-#define        BIOCGDLT         _IOR('B',106, u_int)
+#define BIOCGDLT        _IOR('B',106, u_int)
 #define BIOCGETIF       _IOR('B',107, struct ifreq)
 #define BIOCSETIF       _IOW('B',108, struct ifreq)
 #define BIOCSRTIMEOUT   _IOW('B',109, struct timeval)
@@ -117,10 +117,12 @@
 #define BIOCVERSION     _IOR('B',113, struct bpf_version)
 #define BIOCSTCPF       _IOW('B',114, struct bpf_program)
 #define BIOCSUDPF       _IOW('B',115, struct bpf_program)
-#define        BIOCGHDRCMPLT    _IOR('B',116, u_int)
-#define        BIOCSHDRCMPLT    _IOW('B',117, u_int)
-#define        BIOCSDLT         _IOW('B',118, u_int)
-#define        BIOCGDLTLIST    _IOWR('B',119, struct bpf_dltlist)
+#define BIOCGHDRCMPLT   _IOR('B',116, u_int)
+#define BIOCSHDRCMPLT   _IOW('B',117, u_int)
+#define BIOCSDLT        _IOW('B',118, u_int)
+#define BIOCGDLTLIST   _IOWR('B',119, struct bpf_dltlist)
+#define BIOCGSEESENT    _IOR('B',120, u_int)
+#define BIOCSSEESENT    _IOW('B',121, u_int)
 
 /*
  * Structure prepended to each packet.
diff -r 17d9f0d58682 -r 4862f12d9b3a sys/net/bpfdesc.h
--- a/sys/net/bpfdesc.h Sat Apr 10 23:31:41 2004 +0000
+++ b/sys/net/bpfdesc.h Sat Apr 10 23:31:51 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bpfdesc.h,v 1.16 2003/08/07 16:32:48 agc Exp $ */
+/*     $NetBSD: bpfdesc.h,v 1.17 2004/04/10 23:31:52 darrenr Exp $     */
 
 /*
  * Copyright (c) 1990, 1991, 1993
@@ -41,6 +41,7 @@
 #ifndef _NET_BPFDESC_H_
 #define _NET_BPFDESC_H_
 
+#include <sys/callout.h>
 #include <sys/select.h>
 
 /*



Home | Main Index | Thread Index | Old Index