summaryrefslogtreecommitdiff
path: root/sys/net/bpf.c
diff options
context:
space:
mode:
authorJohn Polstra <jdp@FreeBSD.org>2001-12-14 22:17:54 +0000
committerJohn Polstra <jdp@FreeBSD.org>2001-12-14 22:17:54 +0000
commit81bda851dbd39d26e9fa840f5af682743f1009d1 (patch)
treeeeacb40d73299ff032d264a933e2b0b0dc3c2af2 /sys/net/bpf.c
parenteb48892e1dad87056cd96cd8d1f1d70c6997ea29 (diff)
downloadsrc-test2-81bda851dbd39d26e9fa840f5af682743f1009d1.tar.gz
src-test2-81bda851dbd39d26e9fa840f5af682743f1009d1.zip
Notes
Diffstat (limited to 'sys/net/bpf.c')
-rw-r--r--sys/net/bpf.c59
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);