diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2015-02-07 02:30:01 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2015-02-07 02:30:01 +0000 |
commit | 6a872cb91fb60e8719a83c90b61ae24413498e4a (patch) | |
tree | 5bcadd30b61a39ab34ef034b3cf25b2100f42a7e /sys | |
parent | 5ede4fe071f859c623b30c6244fc142da5a3afdf (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.c | 44 | ||||
-rw-r--r-- | sys/sys/mbuf.h | 6 |
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) |