summaryrefslogtreecommitdiffstats
path: root/sys/kern/uipc_mbuf2.c
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2002-10-16 01:54:46 +0000
committersam <sam@FreeBSD.org>2002-10-16 01:54:46 +0000
commit2a86be217a6aed33eda6628df2b175e49172cd9f (patch)
treeb26e1e9f49b40642051748bcd3961cc2a2b5ff1d /sys/kern/uipc_mbuf2.c
parent733bfbdd78ddb9efc129532b2c2239d0bacfaf1a (diff)
downloadFreeBSD-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/uipc_mbuf2.c')
-rw-r--r--sys/kern/uipc_mbuf2.c202
1 files changed, 127 insertions, 75 deletions
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);
}
OpenPOWER on IntegriCloud