summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2015-02-07 02:30:01 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2015-02-07 02:30:01 +0000
commit6a872cb91fb60e8719a83c90b61ae24413498e4a (patch)
tree5bcadd30b61a39ab34ef034b3cf25b2100f42a7e /sys
parent5ede4fe071f859c623b30c6244fc142da5a3afdf (diff)
add ml_filter and mq_filter functions to the mbuf list and queue apis.
this lets you run a filter function against each mbuf on a list or queue. if the filter matches on an mbuf, it can return non-zero to have ml_filter or mq_filter remove the mbuf and return it as part of a chain of mbufs. ok mpi@ claudio@ henning@ and s2k15 generally.
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/uipc_mbuf.c44
-rw-r--r--sys/sys/mbuf.h6
2 files changed, 48 insertions, 2 deletions
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index 1552168123e..b61159729f6 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_mbuf.c,v 1.199 2014/12/11 19:21:57 tedu Exp $ */
+/* $OpenBSD: uipc_mbuf.c,v 1.200 2015/02/07 02:30:00 dlg Exp $ */
/* $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $ */
/*
@@ -1309,6 +1309,35 @@ ml_dechain(struct mbuf_list *ml)
return (m0);
}
+struct mbuf *
+ml_filter(struct mbuf_list *ml,
+ int (*filter)(void *, const struct mbuf *), void *ctx)
+{
+ struct mbuf_list matches = MBUF_LIST_INITIALIZER();
+ struct mbuf *m, *n;
+ struct mbuf **mp;
+
+ mp = &ml->ml_head;
+
+ for (m = ml->ml_head; m != NULL; m = n) {
+ n = m->m_nextpkt;
+ if ((*filter)(ctx, m)) {
+ *mp = n;
+ ml_enqueue(&matches, m);
+ } else {
+ mp = &m->m_nextpkt;
+ ml->ml_tail = m;
+ }
+ }
+
+ /* fixup ml */
+ if (ml->ml_head == NULL)
+ ml->ml_tail = NULL;
+ ml->ml_len -= ml_len(&matches);
+
+ return (matches.ml_head); /* ml_dechain */
+}
+
/*
* mbuf queues
*/
@@ -1386,3 +1415,16 @@ mq_dechain(struct mbuf_queue *mq)
return (m0);
}
+
+struct mbuf *
+mq_filter(struct mbuf_queue *mq,
+ int (*filter)(void *, const struct mbuf *), void *ctx)
+{
+ struct mbuf *m0;
+
+ mtx_enter(&mq->mq_mtx);
+ m0 = ml_filter(&mq->mq_list, filter, ctx);
+ mtx_leave(&mq->mq_mtx);
+
+ return (m0);
+}
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index f5136e5995e..bccdc0db655 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mbuf.h,v 1.184 2015/01/20 18:12:49 deraadt Exp $ */
+/* $OpenBSD: mbuf.h,v 1.185 2015/02/07 02:30:00 dlg Exp $ */
/* $NetBSD: mbuf.h,v 1.19 1996/02/09 18:25:14 christos Exp $ */
/*
@@ -500,6 +500,8 @@ void ml_init(struct mbuf_list *);
void ml_enqueue(struct mbuf_list *, struct mbuf *);
struct mbuf * ml_dequeue(struct mbuf_list *);
struct mbuf * ml_dechain(struct mbuf_list *);
+struct mbuf * ml_filter(struct mbuf_list *,
+ int (*)(void *, const struct mbuf *), void *);
#define ml_len(_ml) ((_ml)->ml_len)
#define ml_empty(_ml) ((_ml)->ml_len == 0)
@@ -527,6 +529,8 @@ struct mbuf * mq_dequeue(struct mbuf_queue *);
int mq_enlist(struct mbuf_queue *, struct mbuf_list *);
void mq_delist(struct mbuf_queue *, struct mbuf_list *);
struct mbuf * mq_dechain(struct mbuf_queue *);
+struct mbuf * mq_filter(struct mbuf_queue *,
+ int (*)(void *, const struct mbuf *), void *);
#define mq_len(_mq) ml_len(&(_mq)->mq_list)
#define mq_empty(_mq) ml_empty(&(_mq)->mq_list)