diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1999-01-07 22:28:02 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1999-01-07 22:28:02 +0000 |
commit | 5a66a4f93b5e0b7dde7b9aec9ed0d453feb6671b (patch) | |
tree | 4fde488ed5b63adc6a519450ce31fc0a0b7ed45d /sys | |
parent | b9804b73bf42fce25801bd13e1612beb5a858d24 (diff) |
new APIs: m_pullup2, m_copym2, m_zero, MCL_ALIGN; NRL/cmetz
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/uipc_mbuf.c | 178 | ||||
-rw-r--r-- | sys/sys/mbuf.h | 20 |
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 = 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 */ |