summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1999-01-07 22:28:02 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1999-01-07 22:28:02 +0000
commit5a66a4f93b5e0b7dde7b9aec9ed0d453feb6671b (patch)
tree4fde488ed5b63adc6a519450ce31fc0a0b7ed45d /sys
parentb9804b73bf42fce25801bd13e1612beb5a858d24 (diff)
new APIs: m_pullup2, m_copym2, m_zero, MCL_ALIGN; NRL/cmetz
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/uipc_mbuf.c178
-rw-r--r--sys/sys/mbuf.h20
2 files changed, 194 insertions, 4 deletions
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index 0bfe0b49bf6..e70679bb0c8 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_mbuf.c,v 1.7 1998/02/03 19:06:27 deraadt Exp $ */
+/* $OpenBSD: uipc_mbuf.c,v 1.8 1999/01/07 22:28:01 deraadt Exp $ */
/* $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $ */
/*
@@ -36,6 +36,18 @@
* @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
*/
+/*
+%%% portions-copyright-nrl-95
+Portions of this software are Copyright 1995-1998 by Randall Atkinson,
+Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights
+Reserved. All rights under this copyright have been assigned to the US
+Naval Research Laboratory (NRL). The NRL Copyright Notice and License
+Agreement Version 1.1 (January 17, 1995) applies to these portions of the
+software.
+You should have received a copy of the license with this software. If you
+didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
+*/
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
@@ -341,6 +353,82 @@ nospace:
}
/*
+ * m_copym2() is like m_copym(), except it COPIES cluster mbufs, instead
+ * of merely bumping the reference count.
+ *
+ * The hope is to obsolete this function someday.
+ */
+struct mbuf *
+m_copym2(m, off0, len, wait)
+ register struct mbuf *m;
+ int off0, wait;
+ register int len;
+{
+ register struct mbuf *n, **np;
+ register int off = off0;
+ struct mbuf *top;
+ int copyhdr = 0;
+
+ if (off < 0 || len < 0)
+ panic("m_copym");
+ if (off == 0 && m->m_flags & M_PKTHDR)
+ copyhdr = 1;
+ while (off > 0) {
+ if (m == 0)
+ panic("m_copym2 (null mbuf)");
+ if (off < m->m_len)
+ break;
+ off -= m->m_len;
+ m = m->m_next;
+ }
+ np = &top;
+ top = 0;
+ while (len > 0) {
+ if (m == 0) {
+ if (len != M_COPYALL)
+ panic("m_copym2 (len != M_COPYALL)");
+ break;
+ }
+ MGET(n, wait, m->m_type);
+ *np = n;
+ if (n == 0)
+ goto nospace;
+ if (copyhdr) {
+ M_COPY_PKTHDR(n, m);
+ if (len == M_COPYALL)
+ n->m_pkthdr.len -= off0;
+ else
+ n->m_pkthdr.len = len;
+ copyhdr = 0;
+ }
+ n->m_len = min(len, m->m_len - off);
+ if ((m->m_flags & M_EXT) && (n->m_len >MHLEN)) {
+ /* This is a cheesy hack. */
+ MCLGET(n,wait);
+ if (n->m_flags & M_EXT)
+ bcopy(mtod(m,caddr_t)+off,mtod(n,caddr_t),
+ (unsigned)n->m_len);
+ else
+ goto nospace;
+ } else
+ bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
+ (unsigned)n->m_len);
+ if (len != M_COPYALL)
+ len -= n->m_len;
+ off = 0;
+ m = m->m_next;
+ np = &n->m_next;
+ }
+ if (top == 0)
+ MCFail++;
+ return (top);
+nospace:
+ m_freem(top);
+ MCFail++;
+ return (0);
+}
+
+/*
* Copy data from an mbuf chain starting "off" bytes from the beginning,
* continuing for "len" bytes, into the indicated buffer.
*/
@@ -545,6 +633,78 @@ bad:
}
/*
+ * m_pullup2() works like m_pullup, save that len can be <= MCLBYTES.
+ * m_pullup2() only works on values of len such that MHLEN < len <= MCLBYTES,
+ * it calls m_pullup() for values <= MHLEN. It also only coagulates the
+ * reqested number of bytes. (For those of us who expect unwieldly option
+ * headers.
+ *
+ * KEBE SAYS: Remember that dtom() calls with data in clusters does not work!
+ */
+struct mbuf *
+m_pullup2(n, len)
+ register struct mbuf *n;
+ int len;
+{
+ register struct mbuf *m;
+ register int count;
+ int space;
+ if (len <= MHLEN)
+ return m_pullup(n, len);
+
+ if ((n->m_flags & M_EXT) != 0 &&
+ n->m_data + len < &n->m_data[MCLBYTES] && n->m_next) {
+ if (n->m_len >= len)
+ return (n);
+ m = n;
+ n = n->m_next;
+ len -= m->m_len;
+ } else {
+ if (len > MCLBYTES)
+ goto bad;
+ MGET(m, M_DONTWAIT, n->m_type);
+ if (m == 0)
+ goto bad;
+ MCLGET(m,M_DONTWAIT);
+ if ((m->m_flags & M_EXT) == 0)
+ goto bad;
+ m->m_len = 0;
+ if (n->m_flags & M_PKTHDR) {
+ /* M_COPY_PKTHDR(m, n);*//* Too many adverse side effects. */
+ m->m_pkthdr = n->m_pkthdr;
+ m->m_flags = (n->m_flags & M_COPYFLAGS) | M_EXT;
+ n->m_flags &= ~M_PKTHDR;
+ /* n->m_data is cool. */
+ }
+ }
+
+ do {
+ count = min(len, n->m_len);
+ bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
+ (unsigned)count);
+ len -= count;
+ m->m_len += count;
+ n->m_len -= count;
+ space -= count;
+ if (n->m_len)
+ n->m_data += count;
+ else
+ n = m_free(n);
+ } while (len > 0 && n);
+ if (len > 0) {
+ (void) m_free(m);
+ goto bad;
+ }
+ m->m_next = n;
+
+ return (m);
+bad:
+ m_freem(n);
+ MPFail++;
+ return (0);
+}
+
+/*
* Partition an mbuf chain in two pieces, returning the tail --
* all but the first len0 bytes. In case of failure, it returns NULL and
* attempts to restore the chain to its original state.
@@ -682,3 +842,19 @@ m_devget(buf, totlen, off0, ifp, copy)
}
return (top);
}
+
+void
+m_zero(m)
+ struct mbuf *m;
+{
+ while (m) {
+ if (m->m_flags & M_PKTHDR)
+ bzero((void *)m + sizeof(struct m_hdr) +
+ sizeof(struct pkthdr), MHLEN);
+ else
+ bzero((void *)m + sizeof(struct m_hdr), MLEN);
+ if (m->m_flags & M_EXT)
+ bzero(m->m_ext.ext_buf, m->m_ext.ext_size);
+ m = m->m_next;
+ }
+}
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index 914c6aedbd3..e48dbb0b36e 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mbuf.h,v 1.7 1998/06/10 23:57:08 provos Exp $ */
+/* $OpenBSD: mbuf.h,v 1.8 1999/01/07 22:28:01 deraadt Exp $ */
/* $NetBSD: mbuf.h,v 1.19 1996/02/09 18:25:14 christos Exp $ */
/*
@@ -71,7 +71,7 @@ struct m_hdr {
struct mbuf *mh_next; /* next buffer in chain */
struct mbuf *mh_nextpkt; /* next chain in queue/record */
caddr_t mh_data; /* location of data */
- int mh_len; /* amount of data in this mbuf */
+ u_int mh_len; /* amount of data in this mbuf */
short mh_type; /* type of data in this mbuf */
short mh_flags; /* flags; see below */
};
@@ -127,8 +127,11 @@ struct mbuf {
#define M_AUTH 0x0800 /* packet was authenticated (AH) */
#define M_TUNNEL 0x1000 /* packet was tunneled */
+#define M_DAD 0x2000 /* Used on outbound packets to indicate that
+ * this is for duplicate address detection */
+
/* flags copied when copying m_pkthdr */
-#define M_COPYFLAGS (M_PKTHDR|M_EOR|M_BCAST|M_MCAST|M_CONF|M_AUTH|M_TUNNEL)
+#define M_COPYFLAGS (M_PKTHDR|M_EOR|M_BCAST|M_MCAST|M_CONF|M_AUTH|M_TUNNEL|M_DAD)
/* mbuf types */
#define MT_FREE 0 /* should be on free list */
@@ -247,6 +250,14 @@ union mcluster {
} \
)
+#ifdef INET6
+/*
+ * For cluster mbufs (regardless of header or not).
+ */
+#define MCL_ALIGN(m, len) \
+ { (m)->m_data += (MCLBYTES - (len)) &~ (sizeof(long) -1); }
+#endif /* INET6 */
+
/*
* MFREE(struct mbuf *m, struct mbuf *n)
* Free a single mbuf and associated external storage.
@@ -374,6 +385,7 @@ extern int needqueuedrain; /* True if allocation failed at */
/* interrupt level */
void mbinit __P((void));
+struct mbuf *m_copym2 __P((struct mbuf *, int, int, int));
struct mbuf *m_copym __P((struct mbuf *, int, int, int));
struct mbuf *m_free __P((struct mbuf *));
struct mbuf *m_get __P((int, int));
@@ -381,6 +393,7 @@ struct mbuf *m_getclr __P((int, int));
struct mbuf *m_gethdr __P((int, int));
struct mbuf *m_prepend __P((struct mbuf *, int, int));
struct mbuf *m_pullup __P((struct mbuf *, int));
+struct mbuf *m_pullup2 __P((struct mbuf *, int));
struct mbuf *m_retry __P((int, int));
struct mbuf *m_retryhdr __P((int, int));
struct mbuf *m_split __P((struct mbuf *, int, int));
@@ -393,6 +406,7 @@ void m_copydata __P((struct mbuf *, int, int, caddr_t));
void m_cat __P((struct mbuf *, struct mbuf *));
struct mbuf *m_devget __P((char *, int, int, struct ifnet *,
void (*) __P((const void *, void *, size_t))));
+void m_zero __P((struct mbuf *));
#ifdef MBTYPES
int mbtypes[] = { /* XXX */