diff options
author | John Polstra <jdp@FreeBSD.org> | 2001-12-14 22:17:54 +0000 |
---|---|---|
committer | John Polstra <jdp@FreeBSD.org> | 2001-12-14 22:17:54 +0000 |
commit | 81bda851dbd39d26e9fa840f5af682743f1009d1 (patch) | |
tree | eeacb40d73299ff032d264a933e2b0b0dc3c2af2 /sys/net/bpf.c | |
parent | eb48892e1dad87056cd96cd8d1f1d70c6997ea29 (diff) | |
download | src-test2-81bda851dbd39d26e9fa840f5af682743f1009d1.tar.gz src-test2-81bda851dbd39d26e9fa840f5af682743f1009d1.zip |
Notes
Diffstat (limited to 'sys/net/bpf.c')
-rw-r--r-- | sys/net/bpf.c | 59 |
1 files changed, 53 insertions, 6 deletions
diff --git a/sys/net/bpf.c b/sys/net/bpf.c index 034ead1731dc..0d93db504eb8 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -100,6 +100,7 @@ static void bpf_mcopy __P((const void *, void *, size_t)); static int bpf_movein __P((struct uio *, int, struct mbuf **, struct sockaddr *, int *)); 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, @@ -343,6 +344,7 @@ bpfopen(dev, flags, fmt, td) d->bd_sig = SIGIO; d->bd_seesent = 1; mtx_init(&d->bd_mtx, devtoname(dev), MTX_DEF); + callout_init(&d->bd_callout, 1); return (0); } @@ -361,6 +363,11 @@ bpfclose(dev, flags, fmt, td) { struct bpf_d *d = dev->si_drv1; + BPFD_LOCK(d); + if (d->bd_state == BPF_WAITING) + callout_stop(&d->bd_callout); + d->bd_state = BPF_IDLE; + BPFD_UNLOCK(d); funsetown(d->bd_sigio); mtx_lock(&bpf_mtx); if (d->bd_bif) @@ -395,6 +402,7 @@ bpfread(dev, uio, ioflag) int ioflag; { struct bpf_d *d = dev->si_drv1; + int timed_out; int error; /* @@ -405,13 +413,17 @@ bpfread(dev, uio, ioflag) return (EINVAL); BPFD_LOCK(d); + 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 && d->bd_slen != 0) { + 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. @@ -493,6 +505,10 @@ static __inline void bpf_wakeup(d) register struct bpf_d *d; { + if (d->bd_state == BPF_WAITING) { + callout_stop(&d->bd_callout); + d->bd_state = BPF_IDLE; + } wakeup((caddr_t)d); if (d->bd_async && d->bd_sig && d->bd_sigio) pgsigio(d->bd_sigio, d->bd_sig, 0); @@ -502,6 +518,21 @@ bpf_wakeup(d) d->bd_sel.si_pid = 0; } +static void +bpf_timed_out(arg) + void *arg; +{ + struct bpf_d *d = (struct bpf_d *)arg; + + BPFD_LOCK(d); + if (d->bd_state == BPF_WAITING) { + d->bd_state = BPF_TIMED_OUT; + if (d->bd_slen != 0) + bpf_wakeup(d); + } + BPFD_UNLOCK(d); +} + static int bpfwrite(dev, uio, ioflag) dev_t dev; @@ -595,6 +626,12 @@ bpfioctl(dev, cmd, addr, flags, td) struct bpf_d *d = dev->si_drv1; int error = 0; + BPFD_LOCK(d); + if (d->bd_state == BPF_WAITING) + callout_stop(&d->bd_callout); + d->bd_state = BPF_IDLE; + BPFD_UNLOCK(d); + switch (cmd) { default: @@ -987,10 +1024,19 @@ bpfpoll(dev, events, td) * if (d->b_slen != 0 || * (d->bd_hbuf != NULL && d->bd_hlen != 0) */ - 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(td, &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; + } + } } BPFD_UNLOCK(d); return (revents); @@ -1133,10 +1179,11 @@ catchpacket(d, pkt, pktlen, snaplen, cpfn) bpf_wakeup(d); curlen = 0; } - else if (d->bd_immediate) + else if (d->bd_immediate || d->bd_state == BPF_TIMED_OUT) /* - * Immediate mode is set. A packet arrived so any - * reads should be woken up. + * 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); |