From 2a86be217a6aed33eda6628df2b175e49172cd9f Mon Sep 17 00:00:00 2001 From: sam Date: Wed, 16 Oct 2002 01:54:46 +0000 Subject: Replace aux mbufs with packet tags: o instead of a list of mbufs use a list of m_tag structures a la openbsd o for netgraph et. al. extend the stock openbsd m_tag to include a 32-bit ABI/module number cookie o for openbsd compatibility define a well-known cookie MTAG_ABI_COMPAT and use this in defining openbsd-compatible m_tag_find and m_tag_get routines o rewrite KAME use of aux mbufs in terms of packet tags o eliminate the most heavily used aux mbufs by adding an additional struct inpcb parameter to ip_output and ip6_output to allow the IPsec code to locate the security policy to apply to outbound packets o bump __FreeBSD_version so code can be conditionalized o fixup ipfilter's call to ip_output based on __FreeBSD_version Reviewed by: julian, luigi (silent), -arch, -net, darren Approved by: julian, silence from everyone else Obtained from: openbsd (mostly) MFC after: 1 month --- sys/kern/uipc_mbuf2.c | 202 +++++++++++++++++++++++++++++++------------------- 1 file changed, 127 insertions(+), 75 deletions(-) (limited to 'sys/kern/uipc_mbuf2.c') diff --git a/sys/kern/uipc_mbuf2.c b/sys/kern/uipc_mbuf2.c index 37ee53e..b3f053d 100644 --- a/sys/kern/uipc_mbuf2.c +++ b/sys/kern/uipc_mbuf2.c @@ -70,11 +70,14 @@ #include #include +#include #include #include #include #include +MALLOC_DEFINE(M_PACKET_TAGS, "tag", "packet-attached information"); + /* can't call it m_dup(), as freebsd[34] uses m_dup() with different arg */ static struct mbuf *m_dup1(struct mbuf *, int, int, int); @@ -301,104 +304,153 @@ m_dup1(struct mbuf *m, int off, int len, int wait) return n; } -/* - * pkthdr.aux chain manipulation. - * we don't allow clusters at this moment. - */ -struct mbuf * -m_aux_add2(struct mbuf *m, int af, int type, void *p) +/* Get a packet tag structure along with specified data following. */ +struct m_tag * +m_tag_alloc(u_int32_t cookie, int type, int len, int wait) { - struct mbuf *n; - struct mauxtag *t; + struct m_tag *t; - if ((m->m_flags & M_PKTHDR) == 0) + if (len < 0) + return NULL; + t = malloc(len + sizeof(struct m_tag), M_PACKET_TAGS, wait); + if (t == NULL) return NULL; + t->m_tag_id = type; + t->m_tag_len = len; + t->m_tag_cookie = cookie; + return t; +} - n = m_aux_find(m, af, type); - if (n) - return n; +/* Free a packet tag. */ +void +m_tag_free(struct m_tag *t) +{ + free(t, M_PACKET_TAGS); +} - MGET(n, M_DONTWAIT, m->m_type); - if (n == NULL) - return NULL; +/* Prepend a packet tag. */ +void +m_tag_prepend(struct mbuf *m, struct m_tag *t) +{ + KASSERT(m && t, ("m_tag_prepend: null argument, m %p t %p", m, t)); + SLIST_INSERT_HEAD(&m->m_pkthdr.tags, t, m_tag_link); +} - t = mtod(n, struct mauxtag *); - bzero(t, sizeof(*t)); - t->af = af; - t->type = type; - t->p = p; - n->m_data += sizeof(struct mauxtag); - n->m_len = 0; - n->m_next = m->m_pkthdr.aux; - m->m_pkthdr.aux = n; - return n; +/* Unlink a packet tag. */ +void +m_tag_unlink(struct mbuf *m, struct m_tag *t) +{ + KASSERT(m && t, ("m_tag_unlink: null argument, m %p t %p", m, t)); + SLIST_REMOVE(&m->m_pkthdr.tags, t, m_tag, m_tag_link); } -struct mbuf * -m_aux_find2(struct mbuf *m, int af, int type, void *p) +/* Unlink and free a packet tag. */ +void +m_tag_delete(struct mbuf *m, struct m_tag *t) { - struct mbuf *n; - struct mauxtag *t; + KASSERT(m && t, ("m_tag_delete: null argument, m %p t %p", m, t)); + m_tag_unlink(m, t); + m_tag_free(t); +} - if ((m->m_flags & M_PKTHDR) == 0) - return NULL; +/* Unlink and free a packet tag chain, starting from given tag. */ +void +m_tag_delete_chain(struct mbuf *m, struct m_tag *t) +{ + struct m_tag *p, *q; + + KASSERT(m, ("m_tag_delete_chain: null mbuf")); + if (t != NULL) + p = t; + else + p = SLIST_FIRST(&m->m_pkthdr.tags); + if (p == NULL) + return; + while ((q = SLIST_NEXT(p, m_tag_link)) != NULL) + m_tag_delete(m, q); + m_tag_delete(m, p); +} - for (n = m->m_pkthdr.aux; n; n = n->m_next) { - t = (struct mauxtag *)n->m_dat; - if (n->m_data != ((caddr_t)t) + sizeof(struct mauxtag)) { - printf("m_aux_find: invalid m_data for mbuf=%p (%p %p)\n", n, t, n->m_data); - continue; - } - if (t->af == af && t->type == type && t->p == p) - return n; +/* Find a tag, starting from a given position. */ +struct m_tag * +m_tag_locate(struct mbuf *m, u_int32_t cookie, int type, struct m_tag *t) +{ + struct m_tag *p; + + KASSERT(m, ("m_tag_find: null mbuf")); + if (t == NULL) + p = SLIST_FIRST(&m->m_pkthdr.tags); + else + p = SLIST_NEXT(t, m_tag_link); + while (p != NULL) { + if (p->m_tag_cookie == cookie && p->m_tag_id == type) + return p; + p = SLIST_NEXT(p, m_tag_link); } return NULL; } -struct mbuf * -m_aux_find(struct mbuf *m, int af, int type) +/* Copy a single tag. */ +struct m_tag * +m_tag_copy(struct m_tag *t) { - - return m_aux_find2(m, af, type, NULL); + struct m_tag *p; + + KASSERT(t, ("m_tag_copy: null tag")); + p = m_tag_alloc(t->m_tag_cookie, t->m_tag_id, t->m_tag_len, M_NOWAIT); + if (p == NULL) + return (NULL); + bcopy(t + 1, p + 1, t->m_tag_len); /* Copy the data */ + return p; } -struct mbuf * -m_aux_add(struct mbuf *m, int af, int type) +/* + * Copy two tag chains. The destination mbuf (to) loses any attached + * tags even if the operation fails. This should not be a problem, as + * m_tag_copy_chain() is typically called with a newly-allocated + * destination mbuf. + */ +int +m_tag_copy_chain(struct mbuf *to, struct mbuf *from) { - - return m_aux_add2(m, af, type, NULL); + struct m_tag *p, *t, *tprev = NULL; + + KASSERT(to && from, + ("m_tag_copy: null argument, to %p from %p", to, from)); + m_tag_delete_chain(to, NULL); + SLIST_FOREACH(p, &from->m_pkthdr.tags, m_tag_link) { + t = m_tag_copy(p); + if (t == NULL) { + m_tag_delete_chain(to, NULL); + return 0; + } + if (tprev == NULL) + SLIST_INSERT_HEAD(&to->m_pkthdr.tags, t, m_tag_link); + else { + SLIST_INSERT_AFTER(tprev, t, m_tag_link); + tprev = t; + } + } + return 1; } +/* Initialize tags on an mbuf. */ void -m_aux_delete(struct mbuf *m, struct mbuf *victim) +m_tag_init(struct mbuf *m) { - struct mbuf *n, *prev, *next; - struct mauxtag *t; + SLIST_INIT(&m->m_pkthdr.tags); +} - if ((m->m_flags & M_PKTHDR) == 0) - return; +/* Get first tag in chain. */ +struct m_tag * +m_tag_first(struct mbuf *m) +{ + return SLIST_FIRST(&m->m_pkthdr.tags); +} - prev = NULL; - n = m->m_pkthdr.aux; - while (n) { - t = (struct mauxtag *)n->m_dat; - next = n->m_next; - if (n->m_data != ((caddr_t)t) + sizeof(struct mauxtag)) { - printf("m_aux_delete: invalid m_data for mbuf=%p (%p %p)\n", n, t, n->m_data); - prev = n; - n = next; - continue; - } - if (n == victim) { - if (prev) - prev->m_next = n->m_next; - else - m->m_pkthdr.aux = n->m_next; - n->m_next = NULL; - m_free(n); - return; - } else - prev = n; - n = next; - } +/* Get next tag in chain. */ +struct m_tag * +m_tag_next(struct mbuf *m, struct m_tag *t) +{ + return SLIST_NEXT(t, m_tag_link); } -- cgit v1.1