uipc_mbuf.c revision 15543
11541Srgrimes/*
21541Srgrimes * Copyright (c) 1982, 1986, 1988, 1991, 1993
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes *
51541Srgrimes * Redistribution and use in source and binary forms, with or without
61541Srgrimes * modification, are permitted provided that the following conditions
71541Srgrimes * are met:
81541Srgrimes * 1. Redistributions of source code must retain the above copyright
91541Srgrimes *    notice, this list of conditions and the following disclaimer.
101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111541Srgrimes *    notice, this list of conditions and the following disclaimer in the
121541Srgrimes *    documentation and/or other materials provided with the distribution.
131541Srgrimes * 3. All advertising materials mentioning features or use of this software
141541Srgrimes *    must display the following acknowledgement:
151541Srgrimes *	This product includes software developed by the University of
161541Srgrimes *	California, Berkeley and its contributors.
171541Srgrimes * 4. Neither the name of the University nor the names of its contributors
181541Srgrimes *    may be used to endorse or promote products derived from this software
191541Srgrimes *    without specific prior written permission.
201541Srgrimes *
211541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311541Srgrimes * SUCH DAMAGE.
321541Srgrimes *
331541Srgrimes *	@(#)uipc_mbuf.c	8.2 (Berkeley) 1/4/94
3415543Sphk * $Id: uipc_mbuf.c,v 1.17 1995/12/14 08:32:06 phk Exp $
351541Srgrimes */
361541Srgrimes
371541Srgrimes#include <sys/param.h>
381541Srgrimes#include <sys/systm.h>
391541Srgrimes#include <sys/proc.h>
401541Srgrimes#include <sys/malloc.h>
411541Srgrimes#define MBTYPES
421541Srgrimes#include <sys/mbuf.h>
431541Srgrimes#include <sys/kernel.h>
441541Srgrimes#include <sys/syslog.h>
451541Srgrimes#include <sys/domain.h>
461541Srgrimes#include <sys/protosw.h>
471541Srgrimes
481541Srgrimes#include <vm/vm.h>
4912662Sdg#include <vm/vm_param.h>
509759Sbde#include <vm/vm_kern.h>
5112662Sdg#include <vm/vm_extern.h>
521541Srgrimes
5310653Sdgstatic void mbinit __P((void *));
5410358SjulianSYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbinit, NULL)
5510358Sjulian
569759Sbdestruct mbuf *mbutl;
571541Srgrimeschar	*mclrefcnt;
589759Sbdestruct mbstat mbstat;
599759Sbdeunion mcluster *mclfree;
609759Sbdeint	max_linkhdr;
619759Sbdeint	max_protohdr;
629759Sbdeint	max_hdr;
639759Sbdeint	max_datalen;
641541Srgrimes
6512819Sphkstatic void	m_reclaim __P((void));
6612819Sphk
6710358Sjulian/* ARGSUSED*/
6810358Sjulianstatic void
6912569Sbdembinit(dummy)
7012569Sbde	void *dummy;
711541Srgrimes{
721541Srgrimes	int s;
731541Srgrimes
7415543Sphk#if PAGE_SIZE < 4096
7515543Sphk#define NCL_INIT	(4096/PAGE_SIZE)
761541Srgrimes#else
771541Srgrimes#define NCL_INIT	1
781541Srgrimes#endif
791541Srgrimes	s = splimp();
801541Srgrimes	if (m_clalloc(NCL_INIT, M_DONTWAIT) == 0)
811541Srgrimes		goto bad;
821541Srgrimes	splx(s);
831541Srgrimes	return;
841541Srgrimesbad:
851541Srgrimes	panic("mbinit");
861541Srgrimes}
871541Srgrimes
881541Srgrimes/*
891541Srgrimes * Allocate some number of mbuf clusters
901541Srgrimes * and place on cluster free list.
911541Srgrimes * Must be called at splimp.
921541Srgrimes */
931541Srgrimes/* ARGSUSED */
941549Srgrimesint
951541Srgrimesm_clalloc(ncl, nowait)
961541Srgrimes	register int ncl;
971541Srgrimes	int nowait;
981541Srgrimes{
991541Srgrimes	register caddr_t p;
1001541Srgrimes	register int i;
1011541Srgrimes	int npg;
1021541Srgrimes
1037066Sdg	/*
1047066Sdg	 * Once we run out of map space, it will be impossible
1057066Sdg	 * to get any more (nothing is ever freed back to the
1067066Sdg	 * map).
1077066Sdg	 */
1087066Sdg	if (mb_map_full)
1097066Sdg		return (0);
1107066Sdg
11115543Sphk	npg = ncl;
1126191Sbde	p = (caddr_t)kmem_malloc(mb_map, ctob(npg),
1136191Sbde				 nowait ? M_NOWAIT : M_WAITOK);
1147066Sdg	/*
1157066Sdg	 * Either the map is now full, or this is nowait and there
1167066Sdg	 * are no pages left.
1177066Sdg	 */
1187066Sdg	if (p == NULL)
1191541Srgrimes		return (0);
1207066Sdg
12115543Sphk	ncl = ncl * PAGE_SIZE / MCLBYTES;
1221541Srgrimes	for (i = 0; i < ncl; i++) {
1231541Srgrimes		((union mcluster *)p)->mcl_next = mclfree;
1241541Srgrimes		mclfree = (union mcluster *)p;
1251541Srgrimes		p += MCLBYTES;
1261541Srgrimes		mbstat.m_clfree++;
1271541Srgrimes	}
1281541Srgrimes	mbstat.m_clusters += ncl;
1291541Srgrimes	return (1);
1301541Srgrimes}
1311541Srgrimes
1321541Srgrimes/*
1331541Srgrimes * When MGET failes, ask protocols to free space when short of memory,
1341541Srgrimes * then re-attempt to allocate an mbuf.
1351541Srgrimes */
1361541Srgrimesstruct mbuf *
1371541Srgrimesm_retry(i, t)
1381541Srgrimes	int i, t;
1391541Srgrimes{
1401541Srgrimes	register struct mbuf *m;
1411541Srgrimes
1421541Srgrimes	m_reclaim();
1431541Srgrimes#define m_retry(i, t)	(struct mbuf *)0
1441541Srgrimes	MGET(m, i, t);
1451541Srgrimes#undef m_retry
1466669Sdg	if (m != NULL)
1476669Sdg		mbstat.m_wait++;
1486669Sdg	else
1496669Sdg		mbstat.m_drops++;
1501541Srgrimes	return (m);
1511541Srgrimes}
1521541Srgrimes
1531541Srgrimes/*
1541541Srgrimes * As above; retry an MGETHDR.
1551541Srgrimes */
1561541Srgrimesstruct mbuf *
1571541Srgrimesm_retryhdr(i, t)
1581541Srgrimes	int i, t;
1591541Srgrimes{
1601541Srgrimes	register struct mbuf *m;
1611541Srgrimes
1621541Srgrimes	m_reclaim();
1631541Srgrimes#define m_retryhdr(i, t) (struct mbuf *)0
1641541Srgrimes	MGETHDR(m, i, t);
1651541Srgrimes#undef m_retryhdr
1666669Sdg	if (m != NULL)
1676669Sdg		mbstat.m_wait++;
1686669Sdg	else
1696669Sdg		mbstat.m_drops++;
1701541Srgrimes	return (m);
1711541Srgrimes}
1721541Srgrimes
17312819Sphkstatic void
1741541Srgrimesm_reclaim()
1751541Srgrimes{
1761541Srgrimes	register struct domain *dp;
1771541Srgrimes	register struct protosw *pr;
1781541Srgrimes	int s = splimp();
1791541Srgrimes
1801541Srgrimes	for (dp = domains; dp; dp = dp->dom_next)
1811541Srgrimes		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
1821541Srgrimes			if (pr->pr_drain)
1831541Srgrimes				(*pr->pr_drain)();
1841541Srgrimes	splx(s);
1851541Srgrimes	mbstat.m_drain++;
1861541Srgrimes}
1871541Srgrimes
1881541Srgrimes/*
1891541Srgrimes * Space allocation routines.
1901541Srgrimes * These are also available as macros
1911541Srgrimes * for critical paths.
1921541Srgrimes */
1931541Srgrimesstruct mbuf *
1941541Srgrimesm_get(nowait, type)
1951541Srgrimes	int nowait, type;
1961541Srgrimes{
1971541Srgrimes	register struct mbuf *m;
1981541Srgrimes
1991541Srgrimes	MGET(m, nowait, type);
2001541Srgrimes	return (m);
2011541Srgrimes}
2021541Srgrimes
2031541Srgrimesstruct mbuf *
2041541Srgrimesm_gethdr(nowait, type)
2051541Srgrimes	int nowait, type;
2061541Srgrimes{
2071541Srgrimes	register struct mbuf *m;
2081541Srgrimes
2091541Srgrimes	MGETHDR(m, nowait, type);
2101541Srgrimes	return (m);
2111541Srgrimes}
2121541Srgrimes
2131541Srgrimesstruct mbuf *
2141541Srgrimesm_getclr(nowait, type)
2151541Srgrimes	int nowait, type;
2161541Srgrimes{
2171541Srgrimes	register struct mbuf *m;
2181541Srgrimes
2191541Srgrimes	MGET(m, nowait, type);
2201541Srgrimes	if (m == 0)
2211541Srgrimes		return (0);
2221541Srgrimes	bzero(mtod(m, caddr_t), MLEN);
2231541Srgrimes	return (m);
2241541Srgrimes}
2251541Srgrimes
2261541Srgrimesstruct mbuf *
2271541Srgrimesm_free(m)
2281541Srgrimes	struct mbuf *m;
2291541Srgrimes{
2301541Srgrimes	register struct mbuf *n;
2311541Srgrimes
2321541Srgrimes	MFREE(m, n);
2331541Srgrimes	return (n);
2341541Srgrimes}
2351541Srgrimes
2361541Srgrimesvoid
2371541Srgrimesm_freem(m)
2381541Srgrimes	register struct mbuf *m;
2391541Srgrimes{
2401541Srgrimes	register struct mbuf *n;
2411541Srgrimes
2421541Srgrimes	if (m == NULL)
2431541Srgrimes		return;
2441541Srgrimes	do {
2451541Srgrimes		MFREE(m, n);
2463308Sphk		m = n;
2473308Sphk	} while (m);
2481541Srgrimes}
2491541Srgrimes
2501541Srgrimes/*
2511541Srgrimes * Mbuffer utility routines.
2521541Srgrimes */
2531541Srgrimes
2541541Srgrimes/*
2551541Srgrimes * Lesser-used path for M_PREPEND:
2561541Srgrimes * allocate new mbuf to prepend to chain,
2571541Srgrimes * copy junk along.
2581541Srgrimes */
2591541Srgrimesstruct mbuf *
2601541Srgrimesm_prepend(m, len, how)
2611541Srgrimes	register struct mbuf *m;
2621541Srgrimes	int len, how;
2631541Srgrimes{
2641541Srgrimes	struct mbuf *mn;
2651541Srgrimes
2661541Srgrimes	MGET(mn, how, m->m_type);
2671541Srgrimes	if (mn == (struct mbuf *)NULL) {
2681541Srgrimes		m_freem(m);
2691541Srgrimes		return ((struct mbuf *)NULL);
2701541Srgrimes	}
2711541Srgrimes	if (m->m_flags & M_PKTHDR) {
2721541Srgrimes		M_COPY_PKTHDR(mn, m);
2731541Srgrimes		m->m_flags &= ~M_PKTHDR;
2741541Srgrimes	}
2751541Srgrimes	mn->m_next = m;
2761541Srgrimes	m = mn;
2771541Srgrimes	if (len < MHLEN)
2781541Srgrimes		MH_ALIGN(m, len);
2791541Srgrimes	m->m_len = len;
2801541Srgrimes	return (m);
2811541Srgrimes}
2821541Srgrimes
2831541Srgrimes/*
2841541Srgrimes * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
2851541Srgrimes * continuing for "len" bytes.  If len is M_COPYALL, copy to end of mbuf.
2861541Srgrimes * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
2871541Srgrimes */
28812819Sphkstatic int MCFail;
2891541Srgrimes
2901541Srgrimesstruct mbuf *
2911541Srgrimesm_copym(m, off0, len, wait)
2921541Srgrimes	register struct mbuf *m;
2931541Srgrimes	int off0, wait;
2941541Srgrimes	register int len;
2951541Srgrimes{
2961541Srgrimes	register struct mbuf *n, **np;
2971541Srgrimes	register int off = off0;
2981541Srgrimes	struct mbuf *top;
2991541Srgrimes	int copyhdr = 0;
3001541Srgrimes
3011541Srgrimes	if (off < 0 || len < 0)
3021541Srgrimes		panic("m_copym");
3031541Srgrimes	if (off == 0 && m->m_flags & M_PKTHDR)
3041541Srgrimes		copyhdr = 1;
3051541Srgrimes	while (off > 0) {
3061541Srgrimes		if (m == 0)
3071541Srgrimes			panic("m_copym");
3081541Srgrimes		if (off < m->m_len)
3091541Srgrimes			break;
3101541Srgrimes		off -= m->m_len;
3111541Srgrimes		m = m->m_next;
3121541Srgrimes	}
3131541Srgrimes	np = &top;
3141541Srgrimes	top = 0;
3151541Srgrimes	while (len > 0) {
3161541Srgrimes		if (m == 0) {
3171541Srgrimes			if (len != M_COPYALL)
3181541Srgrimes				panic("m_copym");
3191541Srgrimes			break;
3201541Srgrimes		}
3211541Srgrimes		MGET(n, wait, m->m_type);
3221541Srgrimes		*np = n;
3231541Srgrimes		if (n == 0)
3241541Srgrimes			goto nospace;
3251541Srgrimes		if (copyhdr) {
3261541Srgrimes			M_COPY_PKTHDR(n, m);
3271541Srgrimes			if (len == M_COPYALL)
3281541Srgrimes				n->m_pkthdr.len -= off0;
3291541Srgrimes			else
3301541Srgrimes				n->m_pkthdr.len = len;
3311541Srgrimes			copyhdr = 0;
3321541Srgrimes		}
3331541Srgrimes		n->m_len = min(len, m->m_len - off);
3341541Srgrimes		if (m->m_flags & M_EXT) {
3351541Srgrimes			n->m_data = m->m_data + off;
3361541Srgrimes			mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
3371541Srgrimes			n->m_ext = m->m_ext;
3381541Srgrimes			n->m_flags |= M_EXT;
3391541Srgrimes		} else
3401541Srgrimes			bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
3411541Srgrimes			    (unsigned)n->m_len);
3421541Srgrimes		if (len != M_COPYALL)
3431541Srgrimes			len -= n->m_len;
3441541Srgrimes		off = 0;
3451541Srgrimes		m = m->m_next;
3461541Srgrimes		np = &n->m_next;
3471541Srgrimes	}
3481541Srgrimes	if (top == 0)
3491541Srgrimes		MCFail++;
3501541Srgrimes	return (top);
3511541Srgrimesnospace:
3521541Srgrimes	m_freem(top);
3531541Srgrimes	MCFail++;
3541541Srgrimes	return (0);
3551541Srgrimes}
3561541Srgrimes
3571541Srgrimes/*
3581541Srgrimes * Copy data from an mbuf chain starting "off" bytes from the beginning,
3591541Srgrimes * continuing for "len" bytes, into the indicated buffer.
3601541Srgrimes */
3611549Srgrimesvoid
3621541Srgrimesm_copydata(m, off, len, cp)
3631541Srgrimes	register struct mbuf *m;
3641541Srgrimes	register int off;
3651541Srgrimes	register int len;
3661541Srgrimes	caddr_t cp;
3671541Srgrimes{
3681541Srgrimes	register unsigned count;
3691541Srgrimes
3701541Srgrimes	if (off < 0 || len < 0)
3711541Srgrimes		panic("m_copydata");
3721541Srgrimes	while (off > 0) {
3731541Srgrimes		if (m == 0)
3741541Srgrimes			panic("m_copydata");
3751541Srgrimes		if (off < m->m_len)
3761541Srgrimes			break;
3771541Srgrimes		off -= m->m_len;
3781541Srgrimes		m = m->m_next;
3791541Srgrimes	}
3801541Srgrimes	while (len > 0) {
3811541Srgrimes		if (m == 0)
3821541Srgrimes			panic("m_copydata");
3831541Srgrimes		count = min(m->m_len - off, len);
3841541Srgrimes		bcopy(mtod(m, caddr_t) + off, cp, count);
3851541Srgrimes		len -= count;
3861541Srgrimes		cp += count;
3871541Srgrimes		off = 0;
3881541Srgrimes		m = m->m_next;
3891541Srgrimes	}
3901541Srgrimes}
3911541Srgrimes
3921541Srgrimes/*
3931541Srgrimes * Concatenate mbuf chain n to m.
3941541Srgrimes * Both chains must be of the same type (e.g. MT_DATA).
3951541Srgrimes * Any m_pkthdr is not updated.
3961541Srgrimes */
3971549Srgrimesvoid
3981541Srgrimesm_cat(m, n)
3991541Srgrimes	register struct mbuf *m, *n;
4001541Srgrimes{
4011541Srgrimes	while (m->m_next)
4021541Srgrimes		m = m->m_next;
4031541Srgrimes	while (n) {
4041541Srgrimes		if (m->m_flags & M_EXT ||
4051541Srgrimes		    m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) {
4061541Srgrimes			/* just join the two chains */
4071541Srgrimes			m->m_next = n;
4081541Srgrimes			return;
4091541Srgrimes		}
4101541Srgrimes		/* splat the data from one into the other */
4111541Srgrimes		bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
4121541Srgrimes		    (u_int)n->m_len);
4131541Srgrimes		m->m_len += n->m_len;
4141541Srgrimes		n = m_free(n);
4151541Srgrimes	}
4161541Srgrimes}
4171541Srgrimes
4181549Srgrimesvoid
4191541Srgrimesm_adj(mp, req_len)
4201541Srgrimes	struct mbuf *mp;
4211541Srgrimes	int req_len;
4221541Srgrimes{
4231541Srgrimes	register int len = req_len;
4241541Srgrimes	register struct mbuf *m;
4251541Srgrimes	register count;
4261541Srgrimes
4271541Srgrimes	if ((m = mp) == NULL)
4281541Srgrimes		return;
4291541Srgrimes	if (len >= 0) {
4301541Srgrimes		/*
4311541Srgrimes		 * Trim from head.
4321541Srgrimes		 */
4331541Srgrimes		while (m != NULL && len > 0) {
4341541Srgrimes			if (m->m_len <= len) {
4351541Srgrimes				len -= m->m_len;
4361541Srgrimes				m->m_len = 0;
4371541Srgrimes				m = m->m_next;
4381541Srgrimes			} else {
4391541Srgrimes				m->m_len -= len;
4401541Srgrimes				m->m_data += len;
4411541Srgrimes				len = 0;
4421541Srgrimes			}
4431541Srgrimes		}
4441541Srgrimes		m = mp;
4451541Srgrimes		if (mp->m_flags & M_PKTHDR)
4461541Srgrimes			m->m_pkthdr.len -= (req_len - len);
4471541Srgrimes	} else {
4481541Srgrimes		/*
4491541Srgrimes		 * Trim from tail.  Scan the mbuf chain,
4501541Srgrimes		 * calculating its length and finding the last mbuf.
4511541Srgrimes		 * If the adjustment only affects this mbuf, then just
4521541Srgrimes		 * adjust and return.  Otherwise, rescan and truncate
4531541Srgrimes		 * after the remaining size.
4541541Srgrimes		 */
4551541Srgrimes		len = -len;
4561541Srgrimes		count = 0;
4571541Srgrimes		for (;;) {
4581541Srgrimes			count += m->m_len;
4591541Srgrimes			if (m->m_next == (struct mbuf *)0)
4601541Srgrimes				break;
4611541Srgrimes			m = m->m_next;
4621541Srgrimes		}
4631541Srgrimes		if (m->m_len >= len) {
4641541Srgrimes			m->m_len -= len;
4651541Srgrimes			if (mp->m_flags & M_PKTHDR)
4661541Srgrimes				mp->m_pkthdr.len -= len;
4671541Srgrimes			return;
4681541Srgrimes		}
4691541Srgrimes		count -= len;
4701541Srgrimes		if (count < 0)
4711541Srgrimes			count = 0;
4721541Srgrimes		/*
4731541Srgrimes		 * Correct length for chain is "count".
4741541Srgrimes		 * Find the mbuf with last data, adjust its length,
4751541Srgrimes		 * and toss data from remaining mbufs on chain.
4761541Srgrimes		 */
4771541Srgrimes		m = mp;
4781541Srgrimes		if (m->m_flags & M_PKTHDR)
4791541Srgrimes			m->m_pkthdr.len = count;
4801541Srgrimes		for (; m; m = m->m_next) {
4811541Srgrimes			if (m->m_len >= count) {
4821541Srgrimes				m->m_len = count;
4831541Srgrimes				break;
4841541Srgrimes			}
4851541Srgrimes			count -= m->m_len;
4861541Srgrimes		}
4873308Sphk		while (m->m_next)
4883308Sphk			(m = m->m_next) ->m_len = 0;
4891541Srgrimes	}
4901541Srgrimes}
4911541Srgrimes
4921541Srgrimes/*
4931541Srgrimes * Rearange an mbuf chain so that len bytes are contiguous
4941541Srgrimes * and in the data area of an mbuf (so that mtod and dtom
4951541Srgrimes * will work for a structure of size len).  Returns the resulting
4961541Srgrimes * mbuf chain on success, frees it and returns null on failure.
4971541Srgrimes * If there is room, it will add up to max_protohdr-len extra bytes to the
4981541Srgrimes * contiguous region in an attempt to avoid being called next time.
4991541Srgrimes */
50012819Sphkstatic int MPFail;
5011541Srgrimes
5021541Srgrimesstruct mbuf *
5031541Srgrimesm_pullup(n, len)
5041541Srgrimes	register struct mbuf *n;
5051541Srgrimes	int len;
5061541Srgrimes{
5071541Srgrimes	register struct mbuf *m;
5081541Srgrimes	register int count;
5091541Srgrimes	int space;
5101541Srgrimes
5111541Srgrimes	/*
5121541Srgrimes	 * If first mbuf has no cluster, and has room for len bytes
5131541Srgrimes	 * without shifting current data, pullup into it,
5141541Srgrimes	 * otherwise allocate a new mbuf to prepend to the chain.
5151541Srgrimes	 */
5161541Srgrimes	if ((n->m_flags & M_EXT) == 0 &&
5171541Srgrimes	    n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
5181541Srgrimes		if (n->m_len >= len)
5191541Srgrimes			return (n);
5201541Srgrimes		m = n;
5211541Srgrimes		n = n->m_next;
5221541Srgrimes		len -= m->m_len;
5231541Srgrimes	} else {
5241541Srgrimes		if (len > MHLEN)
5251541Srgrimes			goto bad;
5261541Srgrimes		MGET(m, M_DONTWAIT, n->m_type);
5271541Srgrimes		if (m == 0)
5281541Srgrimes			goto bad;
5291541Srgrimes		m->m_len = 0;
5301541Srgrimes		if (n->m_flags & M_PKTHDR) {
5311541Srgrimes			M_COPY_PKTHDR(m, n);
5321541Srgrimes			n->m_flags &= ~M_PKTHDR;
5331541Srgrimes		}
5341541Srgrimes	}
5351541Srgrimes	space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
5361541Srgrimes	do {
5371541Srgrimes		count = min(min(max(len, max_protohdr), space), n->m_len);
5381541Srgrimes		bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
5391541Srgrimes		  (unsigned)count);
5401541Srgrimes		len -= count;
5411541Srgrimes		m->m_len += count;
5421541Srgrimes		n->m_len -= count;
5431541Srgrimes		space -= count;
5441541Srgrimes		if (n->m_len)
5451541Srgrimes			n->m_data += count;
5461541Srgrimes		else
5471541Srgrimes			n = m_free(n);
5481541Srgrimes	} while (len > 0 && n);
5491541Srgrimes	if (len > 0) {
5501541Srgrimes		(void) m_free(m);
5511541Srgrimes		goto bad;
5521541Srgrimes	}
5531541Srgrimes	m->m_next = n;
5541541Srgrimes	return (m);
5551541Srgrimesbad:
5561541Srgrimes	m_freem(n);
5571541Srgrimes	MPFail++;
5581541Srgrimes	return (0);
5591541Srgrimes}
5601541Srgrimes
5611541Srgrimes/*
5621541Srgrimes * Partition an mbuf chain in two pieces, returning the tail --
5631541Srgrimes * all but the first len0 bytes.  In case of failure, it returns NULL and
5641541Srgrimes * attempts to restore the chain to its original state.
5651541Srgrimes */
5661541Srgrimesstruct mbuf *
5671541Srgrimesm_split(m0, len0, wait)
5681541Srgrimes	register struct mbuf *m0;
5691541Srgrimes	int len0, wait;
5701541Srgrimes{
5711541Srgrimes	register struct mbuf *m, *n;
5721541Srgrimes	unsigned len = len0, remain;
5731541Srgrimes
5741541Srgrimes	for (m = m0; m && len > m->m_len; m = m->m_next)
5751541Srgrimes		len -= m->m_len;
5761541Srgrimes	if (m == 0)
5771541Srgrimes		return (0);
5781541Srgrimes	remain = m->m_len - len;
5791541Srgrimes	if (m0->m_flags & M_PKTHDR) {
5801541Srgrimes		MGETHDR(n, wait, m0->m_type);
5811541Srgrimes		if (n == 0)
5821541Srgrimes			return (0);
5831541Srgrimes		n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
5841541Srgrimes		n->m_pkthdr.len = m0->m_pkthdr.len - len0;
5851541Srgrimes		m0->m_pkthdr.len = len0;
5861541Srgrimes		if (m->m_flags & M_EXT)
5871541Srgrimes			goto extpacket;
5881541Srgrimes		if (remain > MHLEN) {
5891541Srgrimes			/* m can't be the lead packet */
5901541Srgrimes			MH_ALIGN(n, 0);
5911541Srgrimes			n->m_next = m_split(m, len, wait);
5921541Srgrimes			if (n->m_next == 0) {
5931541Srgrimes				(void) m_free(n);
5941541Srgrimes				return (0);
5951541Srgrimes			} else
5961541Srgrimes				return (n);
5971541Srgrimes		} else
5981541Srgrimes			MH_ALIGN(n, remain);
5991541Srgrimes	} else if (remain == 0) {
6001541Srgrimes		n = m->m_next;
6011541Srgrimes		m->m_next = 0;
6021541Srgrimes		return (n);
6031541Srgrimes	} else {
6041541Srgrimes		MGET(n, wait, m->m_type);
6051541Srgrimes		if (n == 0)
6061541Srgrimes			return (0);
6071541Srgrimes		M_ALIGN(n, remain);
6081541Srgrimes	}
6091541Srgrimesextpacket:
6101541Srgrimes	if (m->m_flags & M_EXT) {
6111541Srgrimes		n->m_flags |= M_EXT;
6121541Srgrimes		n->m_ext = m->m_ext;
6131541Srgrimes		mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
6141541Srgrimes		m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */
6151541Srgrimes		n->m_data = m->m_data + len;
6161541Srgrimes	} else {
6171541Srgrimes		bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain);
6181541Srgrimes	}
6191541Srgrimes	n->m_len = remain;
6201541Srgrimes	m->m_len = len;
6211541Srgrimes	n->m_next = m->m_next;
6221541Srgrimes	m->m_next = 0;
6231541Srgrimes	return (n);
6241541Srgrimes}
6251541Srgrimes/*
6261541Srgrimes * Routine to copy from device local memory into mbufs.
6271541Srgrimes */
6281541Srgrimesstruct mbuf *
6291541Srgrimesm_devget(buf, totlen, off0, ifp, copy)
6301541Srgrimes	char *buf;
6311541Srgrimes	int totlen, off0;
6321541Srgrimes	struct ifnet *ifp;
63312577Sbde	void (*copy) __P((char *from, caddr_t to, u_int len));
6341541Srgrimes{
6351541Srgrimes	register struct mbuf *m;
6361541Srgrimes	struct mbuf *top = 0, **mp = &top;
6371541Srgrimes	register int off = off0, len;
6381541Srgrimes	register char *cp;
6391541Srgrimes	char *epkt;
6401541Srgrimes
6411541Srgrimes	cp = buf;
6421541Srgrimes	epkt = cp + totlen;
6431541Srgrimes	if (off) {
6441541Srgrimes		cp += off + 2 * sizeof(u_short);
6451541Srgrimes		totlen -= 2 * sizeof(u_short);
6461541Srgrimes	}
6471541Srgrimes	MGETHDR(m, M_DONTWAIT, MT_DATA);
6481541Srgrimes	if (m == 0)
6491541Srgrimes		return (0);
6501541Srgrimes	m->m_pkthdr.rcvif = ifp;
6511541Srgrimes	m->m_pkthdr.len = totlen;
6521541Srgrimes	m->m_len = MHLEN;
6531541Srgrimes
6541541Srgrimes	while (totlen > 0) {
6551541Srgrimes		if (top) {
6561541Srgrimes			MGET(m, M_DONTWAIT, MT_DATA);
6571541Srgrimes			if (m == 0) {
6581541Srgrimes				m_freem(top);
6591541Srgrimes				return (0);
6601541Srgrimes			}
6611541Srgrimes			m->m_len = MLEN;
6621541Srgrimes		}
6631541Srgrimes		len = min(totlen, epkt - cp);
6641541Srgrimes		if (len >= MINCLSIZE) {
6651541Srgrimes			MCLGET(m, M_DONTWAIT);
6661541Srgrimes			if (m->m_flags & M_EXT)
6671541Srgrimes				m->m_len = len = min(len, MCLBYTES);
6681541Srgrimes			else
6691541Srgrimes				len = m->m_len;
6701541Srgrimes		} else {
6711541Srgrimes			/*
6721541Srgrimes			 * Place initial small packet/header at end of mbuf.
6731541Srgrimes			 */
6741541Srgrimes			if (len < m->m_len) {
6751541Srgrimes				if (top == 0 && len + max_linkhdr <= m->m_len)
6761541Srgrimes					m->m_data += max_linkhdr;
6771541Srgrimes				m->m_len = len;
6781541Srgrimes			} else
6791541Srgrimes				len = m->m_len;
6801541Srgrimes		}
6811541Srgrimes		if (copy)
6821541Srgrimes			copy(cp, mtod(m, caddr_t), (unsigned)len);
6831541Srgrimes		else
6841541Srgrimes			bcopy(cp, mtod(m, caddr_t), (unsigned)len);
6851541Srgrimes		cp += len;
6861541Srgrimes		*mp = m;
6871541Srgrimes		mp = &m->m_next;
6881541Srgrimes		totlen -= len;
6891541Srgrimes		if (cp == epkt)
6901541Srgrimes			cp = buf;
6911541Srgrimes	}
6921541Srgrimes	return (top);
6931541Srgrimes}
6943352Sphk
6953352Sphk/*
6963352Sphk * Copy data from a buffer back into the indicated mbuf chain,
6973352Sphk * starting "off" bytes from the beginning, extending the mbuf
6983352Sphk * chain if necessary.
6993352Sphk */
7003352Sphkvoid
7013352Sphkm_copyback(m0, off, len, cp)
7023352Sphk	struct	mbuf *m0;
7033352Sphk	register int off;
7043352Sphk	register int len;
7053352Sphk	caddr_t cp;
7063352Sphk{
7073352Sphk	register int mlen;
7083352Sphk	register struct mbuf *m = m0, *n;
7093352Sphk	int totlen = 0;
7103352Sphk
7113352Sphk	if (m0 == 0)
7123352Sphk		return;
7133352Sphk	while (off > (mlen = m->m_len)) {
7143352Sphk		off -= mlen;
7153352Sphk		totlen += mlen;
7163352Sphk		if (m->m_next == 0) {
7173352Sphk			n = m_getclr(M_DONTWAIT, m->m_type);
7183352Sphk			if (n == 0)
7193352Sphk				goto out;
7203352Sphk			n->m_len = min(MLEN, len + off);
7213352Sphk			m->m_next = n;
7223352Sphk		}
7233352Sphk		m = m->m_next;
7243352Sphk	}
7253352Sphk	while (len > 0) {
7263352Sphk		mlen = min (m->m_len - off, len);
7273352Sphk		bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
7283352Sphk		cp += mlen;
7293352Sphk		len -= mlen;
7303352Sphk		mlen += off;
7313352Sphk		off = 0;
7323352Sphk		totlen += mlen;
7333352Sphk		if (len == 0)
7343352Sphk			break;
7353352Sphk		if (m->m_next == 0) {
7363352Sphk			n = m_get(M_DONTWAIT, m->m_type);
7373352Sphk			if (n == 0)
7383352Sphk				break;
7393352Sphk			n->m_len = min(MLEN, len);
7403352Sphk			m->m_next = n;
7413352Sphk		}
7423352Sphk		m = m->m_next;
7433352Sphk	}
7443352Sphkout:	if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
7453352Sphk		m->m_pkthdr.len = totlen;
7463352Sphk}
747