diff options
author | sam <sam@FreeBSD.org> | 2002-10-16 01:54:46 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2002-10-16 01:54:46 +0000 |
commit | 2a86be217a6aed33eda6628df2b175e49172cd9f (patch) | |
tree | b26e1e9f49b40642051748bcd3961cc2a2b5ff1d /sys/kern | |
parent | 733bfbdd78ddb9efc129532b2c2239d0bacfaf1a (diff) | |
download | FreeBSD-src-2a86be217a6aed33eda6628df2b175e49172cd9f.zip FreeBSD-src-2a86be217a6aed33eda6628df2b175e49172cd9f.tar.gz |
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
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/subr_mbuf.c | 21 | ||||
-rw-r--r-- | sys/kern/uipc_mbuf.c | 2 | ||||
-rw-r--r-- | sys/kern/uipc_mbuf2.c | 202 |
3 files changed, 135 insertions, 90 deletions
diff --git a/sys/kern/subr_mbuf.c b/sys/kern/subr_mbuf.c index b8dc867..87b9da6 100644 --- a/sys/kern/subr_mbuf.c +++ b/sys/kern/subr_mbuf.c @@ -1037,7 +1037,7 @@ mb_reclaim(void) (m)->m_flags = M_PKTHDR; \ (m)->m_pkthdr.rcvif = NULL; \ (m)->m_pkthdr.csum_flags = 0; \ - (m)->m_pkthdr.aux = NULL; \ + SLIST_INIT(&(m)->m_pkthdr.tags); \ } while (0) #define _mcl_setup(m) do { \ @@ -1333,11 +1333,8 @@ m_free(struct mbuf *mb) int cchnum; short persist = 0; - /* XXX: This check is bogus... please fix (see KAME). */ - if ((mb->m_flags & M_PKTHDR) != 0 && mb->m_pkthdr.aux) { - m_freem(mb->m_pkthdr.aux); - mb->m_pkthdr.aux = NULL; - } + if ((mb->m_flags & M_PKTHDR) != 0) + m_tag_delete_chain(mb, NULL); #ifdef MAC if ((mb->m_flags & M_PKTHDR) && (mb->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED)) @@ -1371,8 +1368,7 @@ m_free(struct mbuf *mb) * we'll eventually be holding the lock across more than merely two * consecutive frees but right now this is hard to implement because of * things like _mext_dealloc_ref (may do a free()) and atomic ops in the - * loop, as well as the fact that we may recurse on m_freem() in - * m_pkthdr.aux != NULL cases. + * loop. * * - mb: the mbuf chain to free. */ @@ -1384,11 +1380,8 @@ m_freem(struct mbuf *mb) short persist; while (mb != NULL) { - /* XXX: This check is bogus... please fix (see KAME). */ - if ((mb->m_flags & M_PKTHDR) != 0 && mb->m_pkthdr.aux) { - m_freem(mb->m_pkthdr.aux); - mb->m_pkthdr.aux = NULL; - } + if ((mb->m_flags & M_PKTHDR) != 0) + m_tag_delete_chain(mb, NULL); #ifdef MAC if ((mb->m_flags & M_PKTHDR) && (mb->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED)) @@ -1448,7 +1441,7 @@ m_getcl(int how, short type, int flags) mb->m_nextpkt = NULL; mb->m_pkthdr.rcvif = NULL; mb->m_pkthdr.csum_flags = 0; - mb->m_pkthdr.aux = NULL; + SLIST_INIT(&mb->m_pkthdr.tags); } mb->m_ext.ext_buf = (caddr_t)mb_alloc(&mb_list_clust, how, diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index cad6d3e..6aedd11 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -89,7 +89,7 @@ m_copy_pkthdr(struct mbuf *to, struct mbuf *from) mac_init_mbuf(to, 1); /* XXXMAC no way to fail */ mac_create_mbuf_from_mbuf(from, to); #endif - from->m_pkthdr.aux = NULL; + SLIST_INIT(&from->m_pkthdr.tags); } /* 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 <sys/param.h> #include <sys/systm.h> +#include <sys/kernel.h> #include <sys/lock.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/mutex.h> +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); } |