summaryrefslogtreecommitdiffstats
path: root/sys/net/bpf.c
diff options
context:
space:
mode:
authorloos <loos@FreeBSD.org>2015-08-17 18:21:18 +0000
committerloos <loos@FreeBSD.org>2015-08-17 18:21:18 +0000
commitf69a7374f02c3d824c60751d6975726b9fb789c1 (patch)
tree290300f1a8d49e15da0a7214c5202044a90c8fb0 /sys/net/bpf.c
parent77458f0d7cb617f5b07d6e249e961647e6ba84e1 (diff)
downloadFreeBSD-src-f69a7374f02c3d824c60751d6975726b9fb789c1.zip
FreeBSD-src-f69a7374f02c3d824c60751d6975726b9fb789c1.tar.gz
MFC r286139:
Do not allocate the buffers at opening of the descriptor, because once the buffer is allocated we are committed to a particular buffer method (BPF_BUFMODE_BUFFER in this case). If we are using zero-copy buffers, the userland program must register its buffers before set the interface. If we are using kernel memory buffers, we can allocate the buffer at the time that the interface is being set. This fix allows the usage of BIOCSETBUFMODE after r235746. Update the comments to reflect the recent changes. Sponsored by: Rubicon Communications (Netgate)
Diffstat (limited to 'sys/net/bpf.c')
-rw-r--r--sys/net/bpf.c43
1 files changed, 30 insertions, 13 deletions
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index c73fbd3..47c0710 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -787,7 +787,7 @@ static int
bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td)
{
struct bpf_d *d;
- int error, size;
+ int error;
d = malloc(sizeof(*d), M_BPF, M_WAITOK | M_ZERO);
error = devfs_set_cdevpriv(d, bpf_dtor);
@@ -817,10 +817,6 @@ bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td)
callout_init_mtx(&d->bd_callout, &d->bd_lock, 0);
knlist_init_mtx(&d->bd_sel.si_note, &d->bd_lock);
- /* Allocate default buffers */
- size = d->bd_bufsize;
- bpf_buffer_ioctl_sblen(d, &size);
-
return (0);
}
@@ -1411,10 +1407,33 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
* Set interface.
*/
case BIOCSETIF:
- BPF_LOCK();
- error = bpf_setif(d, (struct ifreq *)addr);
- BPF_UNLOCK();
- break;
+ {
+ int alloc_buf, size;
+
+ /*
+ * Behavior here depends on the buffering model. If
+ * we're using kernel memory buffers, then we can
+ * allocate them here. If we're using zero-copy,
+ * then the user process must have registered buffers
+ * by the time we get here.
+ */
+ alloc_buf = 0;
+ BPFD_LOCK(d);
+ if (d->bd_bufmode == BPF_BUFMODE_BUFFER &&
+ d->bd_sbuf == NULL)
+ alloc_buf = 1;
+ BPFD_UNLOCK(d);
+ if (alloc_buf) {
+ size = d->bd_bufsize;
+ error = bpf_buffer_ioctl_sblen(d, &size);
+ if (error != 0)
+ break;
+ }
+ BPF_LOCK();
+ error = bpf_setif(d, (struct ifreq *)addr);
+ BPF_UNLOCK();
+ break;
+ }
/*
* Set read timeout.
@@ -1861,10 +1880,8 @@ bpf_setif(struct bpf_d *d, struct ifreq *ifr)
BPFIF_RUNLOCK(bp);
/*
- * Behavior here depends on the buffering model. If we're using
- * kernel memory buffers, then we can allocate them here. If we're
- * using zero-copy, then the user process must have registered
- * buffers by the time we get here. If not, return an error.
+ * At this point, we expect the buffer is already allocated. If not,
+ * return an error.
*/
switch (d->bd_bufmode) {
case BPF_BUFMODE_BUFFER:
OpenPOWER on IntegriCloud