summaryrefslogtreecommitdiff
path: root/sys/net/bpf.c
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2015-08-23 10:14:26 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2015-08-23 10:14:26 +0000
commitc756429ca277d578c46bb00e63e8e30bf5f2d93d (patch)
tree8e4a88fe41ee4bc3b068ba988723477122a286d8 /sys/net/bpf.c
parent458736aa1abd8594826e97f0f2a8ec8b8f3185fc (diff)
back out bpf+srp. its blowing up in a bridge setup.
ill debug this out of the tree.
Diffstat (limited to 'sys/net/bpf.c')
-rw-r--r--sys/net/bpf.c202
1 files changed, 61 insertions, 141 deletions
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index e8611a91f28..55c2796cc91 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bpf.c,v 1.121 2015/08/16 12:17:16 dlg Exp $ */
+/* $OpenBSD: bpf.c,v 1.122 2015/08/23 10:14:25 dlg Exp $ */
/* $NetBSD: bpf.c,v 1.33 1997/02/21 23:59:35 thorpej Exp $ */
/*
@@ -54,8 +54,6 @@
#include <sys/kernel.h>
#include <sys/sysctl.h>
#include <sys/rwlock.h>
-#include <sys/atomic.h>
-#include <sys/srp.h>
#include <net/if.h>
#include <net/bpf.h>
@@ -118,21 +116,6 @@ struct bpf_d *bpfilter_lookup(int);
struct bpf_d *bpfilter_create(int);
void bpfilter_destroy(struct bpf_d *);
-/*
- * Reference count access to descriptor buffers
- */
-#define D_GET(d) ((d)->bd_ref++)
-#define D_PUT(d) bpf_freed(d)
-
-/*
- * garbage collector srps
- */
-
-void bpf_d_dtor(void *, void *);
-struct srp_gc bpf_d_gc = SRP_GC_INITIALIZER(bpf_d_dtor, NULL);
-void bpf_insn_dtor(void *, void *);
-struct srp_gc bpf_insn_gc = SRP_GC_INITIALIZER(bpf_insn_dtor, NULL);
-
int
bpf_movein(struct uio *uio, u_int linktype, struct mbuf **mp,
struct sockaddr *sockp, struct bpf_insn *filter)
@@ -261,25 +244,14 @@ bpf_movein(struct uio *uio, u_int linktype, struct mbuf **mp,
void
bpf_attachd(struct bpf_d *d, struct bpf_if *bp)
{
- struct bpf_d *head;
-
/*
* Point d at bp, and add d to the interface's list of listeners.
* Finally, point the driver's bpf cookie at the interface so
* it will divert packets to bpf.
*/
-
d->bd_bif = bp;
- srp_init(&d->bd_next);
-
- KERNEL_ASSERT_LOCKED();
- head = srp_get_locked(&bp->bif_dlist);
- if (head != NULL) {
- D_GET(head);
- srp_update_locked(&bpf_d_gc, &d->bd_next, head);
- }
- D_GET(d);
- srp_update_locked(&bpf_d_gc, &bp->bif_dlist, d);
+ d->bd_next = bp->bif_dlist;
+ bp->bif_dlist = d;
*bp->bif_driverp = bp;
}
@@ -290,8 +262,7 @@ bpf_attachd(struct bpf_d *d, struct bpf_if *bp)
void
bpf_detachd(struct bpf_d *d)
{
- struct srp *dref;
- struct bpf_d *p, *next;
+ struct bpf_d **p;
struct bpf_if *bp;
bp = d->bd_bif;
@@ -312,36 +283,28 @@ bpf_detachd(struct bpf_d *d)
*/
panic("bpf: ifpromisc failed");
}
-
/* Remove d from the interface's descriptor list. */
- KERNEL_ASSERT_LOCKED();
- dref = &bp->bif_dlist;
- for (;;) {
- p = srp_get_locked(dref);
- if (p == NULL)
+ p = &bp->bif_dlist;
+ while (*p != d) {
+ p = &(*p)->bd_next;
+ if (*p == 0)
panic("bpf_detachd: descriptor not in list");
- if (d == p)
- break;
-
- dref = &p->bd_next;
}
-
- next = srp_get_locked(&d->bd_next);
- if (next != NULL)
- D_GET(next);
- srp_update_locked(&bpf_d_gc, dref, next);
- srp_update_locked(&bpf_d_gc, &d->bd_next, NULL);
-
- if (srp_get_locked(&bp->bif_dlist) == NULL) {
+ *p = (*p)->bd_next;
+ if (bp->bif_dlist == 0)
/*
* Let the driver know that there are no more listeners.
*/
*d->bd_bif->bif_driverp = 0;
- }
-
d->bd_bif = NULL;
}
+/*
+ * Reference count access to descriptor buffers
+ */
+#define D_GET(d) ((d)->bd_ref++)
+#define D_PUT(d) bpf_freed(d)
+
/* ARGSUSED */
void
bpfilterattach(int n)
@@ -563,9 +526,8 @@ bpfwrite(dev_t dev, struct uio *uio, int ioflag)
if (uio->uio_resid == 0)
return (0);
- KERNEL_ASSERT_LOCKED(); /* for accessing bd_wfilter */
error = bpf_movein(uio, d->bd_bif->bif_dlt, &m,
- (struct sockaddr *)&dst, srp_get_locked(&d->bd_wfilter));
+ (struct sockaddr *)&dst, d->bd_wfilter);
if (error)
return (error);
@@ -941,21 +903,22 @@ bpfioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
int
bpf_setf(struct bpf_d *d, struct bpf_program *fp, int wf)
{
- struct srp *filter;
- struct bpf_insn *fcode;
+ struct bpf_insn *fcode, *old;
u_int flen, size;
int s;
- KERNEL_ASSERT_LOCKED();
- filter = wf ? &d->bd_wfilter : &d->bd_rfilter;
-
+ old = wf ? d->bd_wfilter : d->bd_rfilter;
if (fp->bf_insns == 0) {
if (fp->bf_len != 0)
return (EINVAL);
- srp_update_locked(&bpf_insn_gc, filter, NULL);
s = splnet();
+ if (wf)
+ d->bd_wfilter = NULL;
+ else
+ d->bd_rfilter = NULL;
bpf_reset_d(d);
splx(s);
+ free(old, M_DEVBUF, 0);
return (0);
}
flen = fp->bf_len;
@@ -964,12 +927,17 @@ bpf_setf(struct bpf_d *d, struct bpf_program *fp, int wf)
fcode = mallocarray(flen, sizeof(*fp->bf_insns), M_DEVBUF, M_WAITOK);
size = flen * sizeof(*fp->bf_insns);
- if (copyin(fp->bf_insns, fcode, size) == 0 &&
+ if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) == 0 &&
bpf_validate(fcode, (int)flen)) {
- srp_update_locked(&bpf_insn_gc, filter, fcode);
s = splnet();
+ if (wf)
+ d->bd_wfilter = fcode;
+ else
+ d->bd_rfilter = fcode;
bpf_reset_d(d);
splx(s);
+ free(old, M_DEVBUF, 0);
+
return (0);
}
free(fcode, M_DEVBUF, size);
@@ -1145,46 +1113,32 @@ filt_bpfread(struct knote *kn, long hint)
int
bpf_tap(caddr_t arg, u_char *pkt, u_int pktlen, u_int direction)
{
- struct bpf_if *bp = (struct bpf_if *)arg;
- struct srp *dref, *nref;
- struct bpf_d *d, *next;
+ struct bpf_if *bp;
+ struct bpf_d *d;
size_t slen;
struct timeval tv;
int drop = 0, gottime = 0;
- dref = &bp->bif_dlist;
- d = srp_enter(dref);
- while (d != NULL) {
- atomic_inc_long(&d->bd_rcount);
-
+ /*
+ * Note that the ipl does not have to be raised at this point.
+ * The only problem that could arise here is that if two different
+ * interfaces shared any data. This is not the case.
+ */
+ bp = (struct bpf_if *)arg;
+ for (d = bp->bif_dlist; d != NULL; d = d->bd_next) {
+ ++d->bd_rcount;
if ((direction & d->bd_dirfilt) != 0)
slen = 0;
- else {
- struct bpf_insn *fcode;
- fcode = srp_enter(&d->bd_rfilter);
- slen = bpf_filter(fcode, pkt, pktlen, 0);
- srp_leave(&d->bd_rfilter, fcode);
- }
-
- if (slen > 0) {
+ else
+ slen = bpf_filter(d->bd_rfilter, pkt, pktlen, pktlen);
+ if (slen != 0) {
if (!gottime++)
microtime(&tv);
-
- KERNEL_LOCK();
bpf_catchpacket(d, pkt, pktlen, slen, bcopy, &tv);
- KERNEL_UNLOCK();
-
if (d->bd_fildrop)
drop++;
}
-
- nref = &d->bd_next;
- next = srp_enter(nref);
- srp_leave(dref, d);
- dref = nref;
- d = next;
}
- srp_leave(dref, d);
return (drop);
}
@@ -1221,8 +1175,7 @@ _bpf_mtap(caddr_t arg, struct mbuf *m, u_int direction,
void (*cpfn)(const void *, void *, size_t))
{
struct bpf_if *bp = (struct bpf_if *)arg;
- struct srp *dref, *nref;
- struct bpf_d *d, *next;
+ struct bpf_d *d;
size_t pktlen, slen;
struct mbuf *m0;
struct timeval tv;
@@ -1238,42 +1191,25 @@ _bpf_mtap(caddr_t arg, struct mbuf *m, u_int direction,
for (m0 = m; m0 != NULL; m0 = m0->m_next)
pktlen += m0->m_len;
- dref = &bp->bif_dlist;
- d = srp_enter(dref);
- while (d != NULL) {
- atomic_inc_long(&d->bd_rcount);
-
+ for (d = bp->bif_dlist; d != NULL; d = d->bd_next) {
+ ++d->bd_rcount;
if ((direction & d->bd_dirfilt) != 0)
slen = 0;
else if (d->bd_queue && m->m_pkthdr.pf.qid != d->bd_queue)
slen = 0;
- else {
- struct bpf_insn *fcode;
- fcode = srp_enter(&d->bd_rfilter);
- slen = bpf_filter(fcode, (u_char *)m, pktlen, 0);
- srp_leave(&d->bd_rfilter, fcode);
- }
-
- if (slen > 0) {
- if (!gottime++)
- microtime(&tv);
-
- KERNEL_LOCK();
- bpf_catchpacket(d, (u_char *)m, pktlen, slen,
- cpfn, &tv);
- KERNEL_UNLOCK();
+ else
+ slen = bpf_filter(d->bd_rfilter, (u_char *)m,
+ pktlen, 0);
- if (d->bd_fildrop)
- m->m_flags |= M_FILDROP;
- }
+ if (slen == 0)
+ continue;
- nref = &d->bd_next;
- next = srp_enter(nref);
- srp_leave(dref, d);
- dref = nref;
- d = next;
+ if (!gottime++)
+ microtime(&tv);
+ bpf_catchpacket(d, (u_char *)m, pktlen, slen, cpfn, &tv);
+ if (d->bd_fildrop)
+ m->m_flags |= M_FILDROP;
}
- srp_leave(dref, d);
}
/*
@@ -1480,9 +1416,8 @@ bpf_freed(struct bpf_d *d)
free(d->bd_sbuf, M_DEVBUF, 0);
free(d->bd_hbuf, M_DEVBUF, 0);
free(d->bd_fbuf, M_DEVBUF, 0);
- KERNEL_ASSERT_LOCKED();
- srp_update_locked(&bpf_insn_gc, &d->bd_rfilter, NULL);
- srp_update_locked(&bpf_insn_gc, &d->bd_wfilter, NULL);
+ free(d->bd_rfilter, M_DEVBUF, 0);
+ free(d->bd_wfilter, M_DEVBUF, 0);
bpfilter_destroy(d);
}
@@ -1499,7 +1434,7 @@ bpfattach(caddr_t *driverp, struct ifnet *ifp, u_int dlt, u_int hdrlen)
if ((bp = malloc(sizeof(*bp), M_DEVBUF, M_NOWAIT)) == NULL)
panic("bpfattach");
- srp_init(&bp->bif_dlist);
+ bp->bif_dlist = 0;
bp->bif_driverp = (struct bpf_if **)driverp;
bp->bif_ifp = ifp;
bp->bif_dlt = dlt;
@@ -1526,8 +1461,6 @@ bpfdetach(struct ifnet *ifp)
struct bpf_d *bd;
int maj;
- KERNEL_ASSERT_LOCKED();
-
for (bp = bpf_iflist; bp; bp = nbp) {
nbp= bp->bif_next;
if (bp->bif_ifp == ifp) {
@@ -1538,8 +1471,7 @@ bpfdetach(struct ifnet *ifp)
if (cdevsw[maj].d_open == bpfopen)
break;
- for (bd = srp_get_locked(&bp->bif_dlist);
- bd != NULL; bd = srp_get_locked(&bp->bif_dlist)) {
+ for (bd = bp->bif_dlist; bd; bd = bp->bif_dlist) {
struct bpf_d *d;
/*
@@ -1706,15 +1638,3 @@ bpf_setdlt(struct bpf_d *d, u_int dlt)
splx(s);
return (0);
}
-
-void
-bpf_d_dtor(void *null, void *d)
-{
- D_PUT(d);
-}
-
-void
-bpf_insn_dtor(void *null, void *fcode)
-{
- free(fcode, M_DEVBUF, 0);
-}