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. MFC after: 2 weeks Sponsored by: Rubicon Communications (Netgate)
This commit is contained in:
+26
-9
@@ -862,7 +862,7 @@ static int
|
|||||||
bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td)
|
bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td)
|
||||||
{
|
{
|
||||||
struct bpf_d *d;
|
struct bpf_d *d;
|
||||||
int error, size;
|
int error;
|
||||||
|
|
||||||
d = malloc(sizeof(*d), M_BPF, M_WAITOK | M_ZERO);
|
d = malloc(sizeof(*d), M_BPF, M_WAITOK | M_ZERO);
|
||||||
error = devfs_set_cdevpriv(d, bpf_dtor);
|
error = devfs_set_cdevpriv(d, bpf_dtor);
|
||||||
@@ -892,10 +892,6 @@ bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td)
|
|||||||
callout_init_mtx(&d->bd_callout, &d->bd_lock, 0);
|
callout_init_mtx(&d->bd_callout, &d->bd_lock, 0);
|
||||||
knlist_init_mtx(&d->bd_sel.si_note, &d->bd_lock);
|
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);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1472,10 +1468,33 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
|
|||||||
* Set interface.
|
* Set interface.
|
||||||
*/
|
*/
|
||||||
case BIOCSETIF:
|
case BIOCSETIF:
|
||||||
|
{
|
||||||
|
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();
|
BPF_LOCK();
|
||||||
error = bpf_setif(d, (struct ifreq *)addr);
|
error = bpf_setif(d, (struct ifreq *)addr);
|
||||||
BPF_UNLOCK();
|
BPF_UNLOCK();
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set read timeout.
|
* Set read timeout.
|
||||||
@@ -1912,10 +1931,8 @@ bpf_setif(struct bpf_d *d, struct ifreq *ifr)
|
|||||||
BPFIF_RUNLOCK(bp);
|
BPFIF_RUNLOCK(bp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Behavior here depends on the buffering model. If we're using
|
* At this point, we expect the buffer is already allocated. If not,
|
||||||
* kernel memory buffers, then we can allocate them here. If we're
|
* return an error.
|
||||||
* using zero-copy, then the user process must have registered
|
|
||||||
* buffers by the time we get here. If not, return an error.
|
|
||||||
*/
|
*/
|
||||||
switch (d->bd_bufmode) {
|
switch (d->bd_bufmode) {
|
||||||
case BPF_BUFMODE_BUFFER:
|
case BPF_BUFMODE_BUFFER:
|
||||||
|
|||||||
Reference in New Issue
Block a user