summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
authorjmg <jmg@FreeBSD.org>2003-08-05 07:12:49 +0000
committerjmg <jmg@FreeBSD.org>2003-08-05 07:12:49 +0000
commited1d8121c2d1b33f2c886c475109ef3f556b90c6 (patch)
tree258f37b0d41286f68a5be4b2d848607075e81ff0 /sys/net
parentd0c4c329b1946b004bffc0036516aaf3bcd1d928 (diff)
downloadFreeBSD-src-ed1d8121c2d1b33f2c886c475109ef3f556b90c6.zip
FreeBSD-src-ed1d8121c2d1b33f2c886c475109ef3f556b90c6.tar.gz
add support for using kqueue to watch bpf sockets.
Submitted by: Brian Buchanan of nCircle, Inc. Tested on: i386 and sparc64
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/bpf.c80
-rw-r--r--sys/net/bpfdesc.h6
2 files changed, 77 insertions, 9 deletions
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index 0b6f5e8..ff8112c 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -44,6 +44,7 @@
#include "opt_mac.h"
#include "opt_netgraph.h"
+#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
@@ -58,7 +59,10 @@
#include <sys/ttycom.h>
#include <sys/filedesc.h>
+#include <sys/event.h>
+#include <sys/file.h>
#include <sys/poll.h>
+#include <sys/proc.h>
#include <sys/socket.h>
#include <sys/vnode.h>
@@ -111,6 +115,8 @@ static void reset_d(struct bpf_d *);
static int bpf_setf(struct bpf_d *, struct bpf_program *);
static int bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *);
static int bpf_setdlt(struct bpf_d *, u_int);
+static void filt_bpfdetach(struct knote *);
+static int filt_bpfread(struct knote *, long);
static d_open_t bpfopen;
static d_close_t bpfclose;
@@ -118,6 +124,7 @@ static d_read_t bpfread;
static d_write_t bpfwrite;
static d_ioctl_t bpfioctl;
static d_poll_t bpfpoll;
+static d_kqfilter_t bpfkqfilter;
#define CDEV_MAJOR 23
static struct cdevsw bpf_cdevsw = {
@@ -129,8 +136,11 @@ static struct cdevsw bpf_cdevsw = {
.d_poll = bpfpoll,
.d_name = "bpf",
.d_maj = CDEV_MAJOR,
+ .d_kqfilter = bpfkqfilter,
};
+static struct filterops bpfread_filtops =
+ { 1, NULL, filt_bpfdetach, filt_bpfread };
static int
bpf_movein(uio, linktype, mp, sockp, datlen)
@@ -518,6 +528,7 @@ bpf_wakeup(d)
pgsigio(&d->bd_sigio, d->bd_sig, 0);
selwakeup(&d->bd_sel);
+ KNOTE(&d->bd_sel.si_note, 0);
}
static void
@@ -1046,15 +1057,7 @@ bpfpoll(dev, events, td)
revents = events & (POLLOUT | POLLWRNORM);
BPFD_LOCK(d);
if (events & (POLLIN | POLLRDNORM)) {
- /*
- * An imitation of the FIONREAD ioctl code.
- * XXX not quite. An exact imitation:
- * if (d->b_slen != 0 ||
- * (d->bd_hbuf != NULL && d->bd_hlen != 0)
- */
- if (d->bd_hlen != 0 ||
- ((d->bd_immediate || d->bd_state == BPF_TIMED_OUT) &&
- d->bd_slen != 0))
+ if (bpf_ready(d))
revents |= events & (POLLIN | POLLRDNORM);
else {
selrecord(td, &d->bd_sel);
@@ -1071,6 +1074,65 @@ bpfpoll(dev, events, td)
}
/*
+ * Support for kevent() system call. Register EVFILT_READ filters and
+ * reject all others.
+ */
+int
+bpfkqfilter(dev, kn)
+ dev_t dev;
+ struct knote *kn;
+{
+ struct bpf_d *d = (struct bpf_d *)dev->si_drv1;
+
+ if (kn->kn_filter != EVFILT_READ)
+ return (1);
+
+ kn->kn_fop = &bpfread_filtops;
+ kn->kn_hook = d;
+ BPFD_LOCK(d);
+ SLIST_INSERT_HEAD(&d->bd_sel.si_note, kn, kn_selnext);
+ BPFD_UNLOCK(d);
+
+ return (0);
+}
+
+static void
+filt_bpfdetach(kn)
+ struct knote *kn;
+{
+ struct bpf_d *d = (struct bpf_d *)kn->kn_hook;
+
+ BPFD_LOCK(d);
+ SLIST_REMOVE(&d->bd_sel.si_note, kn, knote, kn_selnext);
+ BPFD_UNLOCK(d);
+}
+
+static int
+filt_bpfread(kn, hint)
+ struct knote *kn;
+ long hint;
+{
+ struct bpf_d *d = (struct bpf_d *)kn->kn_hook;
+ int ready;
+
+ BPFD_LOCK(d);
+ ready = bpf_ready(d);
+ if (ready) {
+ kn->kn_data = d->bd_slen;
+ if (d->bd_hbuf)
+ kn->kn_data += d->bd_hlen;
+ }
+ else 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 (ready);
+}
+
+/*
* Incoming linkage from device drivers. Process the packet pkt, of length
* pktlen, which is stored in a contiguous buffer. The packet is parsed
* by each process' filter, and if accepted, stashed into the corresponding
diff --git a/sys/net/bpfdesc.h b/sys/net/bpfdesc.h
index fe059cd..73dcc90 100644
--- a/sys/net/bpfdesc.h
+++ b/sys/net/bpfdesc.h
@@ -104,6 +104,12 @@ struct bpf_d {
#define BPFD_LOCK(bd) mtx_lock(&(bd)->bd_mtx)
#define BPFD_UNLOCK(bd) mtx_unlock(&(bd)->bd_mtx)
+/* Test whether a BPF is ready for read(). */
+#define bpf_ready(bd) \
+ ((bd)->bd_hlen != 0 || \
+ (((bd)->bd_immediate || (bd)->bd_state == BPF_TIMED_OUT) && \
+ (bd)->bd_slen != 0))
+
/*
* Descriptor associated with each attached hardware interface.
*/
OpenPOWER on IntegriCloud