uipc_mbuf.c revision 7066
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
347066Sdg * $Id: uipc_mbuf.c,v 1.8 1995/02/23 19:10:21 davidg 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>
491541Srgrimes
501541Srgrimesextern	vm_map_t mb_map;
511541Srgrimesstruct	mbuf *mbutl;
521541Srgrimeschar	*mclrefcnt;
537066Sdgint	mb_map_full;
541541Srgrimes
551549Srgrimesvoid
561541Srgrimesmbinit()
571541Srgrimes{
581541Srgrimes	int s;
591541Srgrimes
601541Srgrimes#if CLBYTES < 4096
611541Srgrimes#define NCL_INIT	(4096/CLBYTES)
621541Srgrimes#else
631541Srgrimes#define NCL_INIT	1
641541Srgrimes#endif
651541Srgrimes	s = splimp();
661541Srgrimes	if (m_clalloc(NCL_INIT, M_DONTWAIT) == 0)
671541Srgrimes		goto bad;
681541Srgrimes	splx(s);
691541Srgrimes	return;
701541Srgrimesbad:
711541Srgrimes	panic("mbinit");
721541Srgrimes}
731541Srgrimes
741541Srgrimes/*
751541Srgrimes * Allocate some number of mbuf clusters
761541Srgrimes * and place on cluster free list.
771541Srgrimes * Must be called at splimp.
781541Srgrimes */
791541Srgrimes/* ARGSUSED */
801549Srgrimesint
811541Srgrimesm_clalloc(ncl, nowait)
821541Srgrimes	register int ncl;
831541Srgrimes	int nowait;
841541Srgrimes{
851541Srgrimes	static int logged;
861541Srgrimes	register caddr_t p;
871541Srgrimes	register int i;
881541Srgrimes	int npg;
891541Srgrimes
907066Sdg	/*
917066Sdg	 * Once we run out of map space, it will be impossible
927066Sdg	 * to get any more (nothing is ever freed back to the
937066Sdg	 * map).
947066Sdg	 */
957066Sdg	if (mb_map_full)
967066Sdg		return (0);
977066Sdg
981541Srgrimes	npg = ncl * CLSIZE;
996191Sbde	p = (caddr_t)kmem_malloc(mb_map, ctob(npg),
1006191Sbde				 nowait ? M_NOWAIT : M_WAITOK);
1017066Sdg	/*
1027066Sdg	 * Either the map is now full, or this is nowait and there
1037066Sdg	 * are no pages left.
1047066Sdg	 */
1057066Sdg	if (p == NULL)
1061541Srgrimes		return (0);
1077066Sdg
1081541Srgrimes	ncl = ncl * CLBYTES / MCLBYTES;
1091541Srgrimes	for (i = 0; i < ncl; i++) {
1101541Srgrimes		((union mcluster *)p)->mcl_next = mclfree;
1111541Srgrimes		mclfree = (union mcluster *)p;
1121541Srgrimes		p += MCLBYTES;
1131541Srgrimes		mbstat.m_clfree++;
1141541Srgrimes	}
1151541Srgrimes	mbstat.m_clusters += ncl;
1161541Srgrimes	return (1);
1171541Srgrimes}
1181541Srgrimes
1191541Srgrimes/*
1201541Srgrimes * When MGET failes, ask protocols to free space when short of memory,
1211541Srgrimes * then re-attempt to allocate an mbuf.
1221541Srgrimes */
1231541Srgrimesstruct mbuf *
1241541Srgrimesm_retry(i, t)
1251541Srgrimes	int i, t;
1261541Srgrimes{
1271541Srgrimes	register struct mbuf *m;
1281541Srgrimes
1291541Srgrimes	m_reclaim();
1301541Srgrimes#define m_retry(i, t)	(struct mbuf *)0
1311541Srgrimes	MGET(m, i, t);
1321541Srgrimes#undef m_retry
1336669Sdg	if (m != NULL)
1346669Sdg		mbstat.m_wait++;
1356669Sdg	else
1366669Sdg		mbstat.m_drops++;
1371541Srgrimes	return (m);
1381541Srgrimes}
1391541Srgrimes
1401541Srgrimes/*
1411541Srgrimes * As above; retry an MGETHDR.
1421541Srgrimes */
1431541Srgrimesstruct mbuf *
1441541Srgrimesm_retryhdr(i, t)
1451541Srgrimes	int i, t;
1461541Srgrimes{
1471541Srgrimes	register struct mbuf *m;
1481541Srgrimes
1491541Srgrimes	m_reclaim();
1501541Srgrimes#define m_retryhdr(i, t) (struct mbuf *)0
1511541Srgrimes	MGETHDR(m, i, t);
1521541Srgrimes#undef m_retryhdr
1536669Sdg	if (m != NULL)
1546669Sdg		mbstat.m_wait++;
1556669Sdg	else
1566669Sdg		mbstat.m_drops++;
1571541Srgrimes	return (m);
1581541Srgrimes}
1591541Srgrimes
1601549Srgrimesvoid
1611541Srgrimesm_reclaim()
1621541Srgrimes{
1631541Srgrimes	register struct domain *dp;
1641541Srgrimes	register struct protosw *pr;
1651541Srgrimes	int s = splimp();
1661541Srgrimes
1671541Srgrimes	for (dp = domains; dp; dp = dp->dom_next)
1681541Srgrimes		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
1691541Srgrimes			if (pr->pr_drain)
1701541Srgrimes				(*pr->pr_drain)();
1711541Srgrimes	splx(s);
1721541Srgrimes	mbstat.m_drain++;
1731541Srgrimes}
1741541Srgrimes
1751541Srgrimes/*
1761541Srgrimes * Space allocation routines.
1771541Srgrimes * These are also available as macros
1781541Srgrimes * for critical paths.
1791541Srgrimes */
1801541Srgrimesstruct mbuf *
1811541Srgrimesm_get(nowait, type)
1821541Srgrimes	int nowait, type;
1831541Srgrimes{
1841541Srgrimes	register struct mbuf *m;
1851541Srgrimes
1861541Srgrimes	MGET(m, nowait, type);
1871541Srgrimes	return (m);
1881541Srgrimes}
1891541Srgrimes
1901541Srgrimesstruct mbuf *
1911541Srgrimesm_gethdr(nowait, type)
1921541Srgrimes	int nowait, type;
1931541Srgrimes{
1941541Srgrimes	register struct mbuf *m;
1951541Srgrimes
1961541Srgrimes	MGETHDR(m, nowait, type);
1971541Srgrimes	return (m);
1981541Srgrimes}
1991541Srgrimes
2001541Srgrimesstruct mbuf *
2011541Srgrimesm_getclr(nowait, type)
2021541Srgrimes	int nowait, type;
2031541Srgrimes{
2041541Srgrimes	register struct mbuf *m;
2051541Srgrimes
2061541Srgrimes	MGET(m, nowait, type);
2071541Srgrimes	if (m == 0)
2081541Srgrimes		return (0);
2091541Srgrimes	bzero(mtod(m, caddr_t), MLEN);
2101541Srgrimes	return (m);
2111541Srgrimes}
2121541Srgrimes
2131541Srgrimesstruct mbuf *
2141541Srgrimesm_free(m)
2151541Srgrimes	struct mbuf *m;
2161541Srgrimes{
2171541Srgrimes	register struct mbuf *n;
2181541Srgrimes
2191541Srgrimes	MFREE(m, n);
2201541Srgrimes	return (n);
2211541Srgrimes}
2221541Srgrimes
2231541Srgrimesvoid
2241541Srgrimesm_freem(m)
2251541Srgrimes	register struct mbuf *m;
2261541Srgrimes{
2271541Srgrimes	register struct mbuf *n;
2281541Srgrimes
2291541Srgrimes	if (m == NULL)
2301541Srgrimes		return;
2311541Srgrimes	do {
2321541Srgrimes		MFREE(m, n);
2333308Sphk		m = n;
2343308Sphk	} while (m);
2351541Srgrimes}
2361541Srgrimes
2371541Srgrimes/*
2381541Srgrimes * Mbuffer utility routines.
2391541Srgrimes */
2401541Srgrimes
2411541Srgrimes/*
2421541Srgrimes * Lesser-used path for M_PREPEND:
2431541Srgrimes * allocate new mbuf to prepend to chain,
2441541Srgrimes * copy junk along.
2451541Srgrimes */
2461541Srgrimesstruct mbuf *
2471541Srgrimesm_prepend(m, len, how)
2481541Srgrimes	register struct mbuf *m;
2491541Srgrimes	int len, how;
2501541Srgrimes{
2511541Srgrimes	struct mbuf *mn;
2521541Srgrimes
2531541Srgrimes	MGET(mn, how, m->m_type);
2541541Srgrimes	if (mn == (struct mbuf *)NULL) {
2551541Srgrimes		m_freem(m);
2561541Srgrimes		return ((struct mbuf *)NULL);
2571541Srgrimes	}
2581541Srgrimes	if (m->m_flags & M_PKTHDR) {
2591541Srgrimes		M_COPY_PKTHDR(mn, m);
2601541Srgrimes		m->m_flags &= ~M_PKTHDR;
2611541Srgrimes	}
2621541Srgrimes	mn->m_next = m;
2631541Srgrimes	m = mn;
2641541Srgrimes	if (len < MHLEN)
2651541Srgrimes		MH_ALIGN(m, len);
2661541Srgrimes	m->m_len = len;
2671541Srgrimes	return (m);
2681541Srgrimes}
2691541Srgrimes
2701541Srgrimes/*
2711541Srgrimes * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
2721541Srgrimes * continuing for "len" bytes.  If len is M_COPYALL, copy to end of mbuf.
2731541Srgrimes * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
2741541Srgrimes */
2751541Srgrimesint MCFail;
2761541Srgrimes
2771541Srgrimesstruct mbuf *
2781541Srgrimesm_copym(m, off0, len, wait)
2791541Srgrimes	register struct mbuf *m;
2801541Srgrimes	int off0, wait;
2811541Srgrimes	register int len;
2821541Srgrimes{
2831541Srgrimes	register struct mbuf *n, **np;
2841541Srgrimes	register int off = off0;
2851541Srgrimes	struct mbuf *top;
2861541Srgrimes	int copyhdr = 0;
2871541Srgrimes
2881541Srgrimes	if (off < 0 || len < 0)
2891541Srgrimes		panic("m_copym");
2901541Srgrimes	if (off == 0 && m->m_flags & M_PKTHDR)
2911541Srgrimes		copyhdr = 1;
2921541Srgrimes	while (off > 0) {
2931541Srgrimes		if (m == 0)
2941541Srgrimes			panic("m_copym");
2951541Srgrimes		if (off < m->m_len)
2961541Srgrimes			break;
2971541Srgrimes		off -= m->m_len;
2981541Srgrimes		m = m->m_next;
2991541Srgrimes	}
3001541Srgrimes	np = &top;
3011541Srgrimes	top = 0;
3021541Srgrimes	while (len > 0) {
3031541Srgrimes		if (m == 0) {
3041541Srgrimes			if (len != M_COPYALL)
3051541Srgrimes				panic("m_copym");
3061541Srgrimes			break;
3071541Srgrimes		}
3081541Srgrimes		MGET(n, wait, m->m_type);
3091541Srgrimes		*np = n;
3101541Srgrimes		if (n == 0)
3111541Srgrimes			goto nospace;
3121541Srgrimes		if (copyhdr) {
3131541Srgrimes			M_COPY_PKTHDR(n, m);
3141541Srgrimes			if (len == M_COPYALL)
3151541Srgrimes				n->m_pkthdr.len -= off0;
3161541Srgrimes			else
3171541Srgrimes				n->m_pkthdr.len = len;
3181541Srgrimes			copyhdr = 0;
3191541Srgrimes		}
3201541Srgrimes		n->m_len = min(len, m->m_len - off);
3211541Srgrimes		if (m->m_flags & M_EXT) {
3221541Srgrimes			n->m_data = m->m_data + off;
3231541Srgrimes			mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
3241541Srgrimes			n->m_ext = m->m_ext;
3251541Srgrimes			n->m_flags |= M_EXT;
3261541Srgrimes		} else
3271541Srgrimes			bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
3281541Srgrimes			    (unsigned)n->m_len);
3291541Srgrimes		if (len != M_COPYALL)
3301541Srgrimes			len -= n->m_len;
3311541Srgrimes		off = 0;
3321541Srgrimes		m = m->m_next;
3331541Srgrimes		np = &n->m_next;
3341541Srgrimes	}
3351541Srgrimes	if (top == 0)
3361541Srgrimes		MCFail++;
3371541Srgrimes	return (top);
3381541Srgrimesnospace:
3391541Srgrimes	m_freem(top);
3401541Srgrimes	MCFail++;
3411541Srgrimes	return (0);
3421541Srgrimes}
3431541Srgrimes
3441541Srgrimes/*
3451541Srgrimes * Copy data from an mbuf chain starting "off" bytes from the beginning,
3461541Srgrimes * continuing for "len" bytes, into the indicated buffer.
3471541Srgrimes */
3481549Srgrimesvoid
3491541Srgrimesm_copydata(m, off, len, cp)
3501541Srgrimes	register struct mbuf *m;
3511541Srgrimes	register int off;
3521541Srgrimes	register int len;
3531541Srgrimes	caddr_t cp;
3541541Srgrimes{
3551541Srgrimes	register unsigned count;
3561541Srgrimes
3571541Srgrimes	if (off < 0 || len < 0)
3581541Srgrimes		panic("m_copydata");
3591541Srgrimes	while (off > 0) {
3601541Srgrimes		if (m == 0)
3611541Srgrimes			panic("m_copydata");
3621541Srgrimes		if (off < m->m_len)
3631541Srgrimes			break;
3641541Srgrimes		off -= m->m_len;
3651541Srgrimes		m = m->m_next;
3661541Srgrimes	}
3671541Srgrimes	while (len > 0) {
3681541Srgrimes		if (m == 0)
3691541Srgrimes			panic("m_copydata");
3701541Srgrimes		count = min(m->m_len - off, len);
3711541Srgrimes		bcopy(mtod(m, caddr_t) + off, cp, count);
3721541Srgrimes		len -= count;
3731541Srgrimes		cp += count;
3741541Srgrimes		off = 0;
3751541Srgrimes		m = m->m_next;
3761541Srgrimes	}
3771541Srgrimes}
3781541Srgrimes
3791541Srgrimes/*
3801541Srgrimes * Concatenate mbuf chain n to m.
3811541Srgrimes * Both chains must be of the same type (e.g. MT_DATA).
3821541Srgrimes * Any m_pkthdr is not updated.
3831541Srgrimes */
3841549Srgrimesvoid
3851541Srgrimesm_cat(m, n)
3861541Srgrimes	register struct mbuf *m, *n;
3871541Srgrimes{
3881541Srgrimes	while (m->m_next)
3891541Srgrimes		m = m->m_next;
3901541Srgrimes	while (n) {
3911541Srgrimes		if (m->m_flags & M_EXT ||
3921541Srgrimes		    m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) {
3931541Srgrimes			/* just join the two chains */
3941541Srgrimes			m->m_next = n;
3951541Srgrimes			return;
3961541Srgrimes		}
3971541Srgrimes		/* splat the data from one into the other */
3981541Srgrimes		bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
3991541Srgrimes		    (u_int)n->m_len);
4001541Srgrimes		m->m_len += n->m_len;
4011541Srgrimes		n = m_free(n);
4021541Srgrimes	}
4031541Srgrimes}
4041541Srgrimes
4051549Srgrimesvoid
4061541Srgrimesm_adj(mp, req_len)
4071541Srgrimes	struct mbuf *mp;
4081541Srgrimes	int req_len;
4091541Srgrimes{
4101541Srgrimes	register int len = req_len;
4111541Srgrimes	register struct mbuf *m;
4121541Srgrimes	register count;
4131541Srgrimes
4141541Srgrimes	if ((m = mp) == NULL)
4151541Srgrimes		return;
4161541Srgrimes	if (len >= 0) {
4171541Srgrimes		/*
4181541Srgrimes		 * Trim from head.
4191541Srgrimes		 */
4201541Srgrimes		while (m != NULL && len > 0) {
4211541Srgrimes			if (m->m_len <= len) {
4221541Srgrimes				len -= m->m_len;
4231541Srgrimes				m->m_len = 0;
4241541Srgrimes				m = m->m_next;
4251541Srgrimes			} else {
4261541Srgrimes				m->m_len -= len;
4271541Srgrimes				m->m_data += len;
4281541Srgrimes				len = 0;
4291541Srgrimes			}
4301541Srgrimes		}
4311541Srgrimes		m = mp;
4321541Srgrimes		if (mp->m_flags & M_PKTHDR)
4331541Srgrimes			m->m_pkthdr.len -= (req_len - len);
4341541Srgrimes	} else {
4351541Srgrimes		/*
4361541Srgrimes		 * Trim from tail.  Scan the mbuf chain,
4371541Srgrimes		 * calculating its length and finding the last mbuf.
4381541Srgrimes		 * If the adjustment only affects this mbuf, then just
4391541Srgrimes		 * adjust and return.  Otherwise, rescan and truncate
4401541Srgrimes		 * after the remaining size.
4411541Srgrimes		 */
4421541Srgrimes		len = -len;
4431541Srgrimes		count = 0;
4441541Srgrimes		for (;;) {
4451541Srgrimes			count += m->m_len;
4461541Srgrimes			if (m->m_next == (struct mbuf *)0)
4471541Srgrimes				break;
4481541Srgrimes			m = m->m_next;
4491541Srgrimes		}
4501541Srgrimes		if (m->m_len >= len) {
4511541Srgrimes			m->m_len -= len;
4521541Srgrimes			if (mp->m_flags & M_PKTHDR)
4531541Srgrimes				mp->m_pkthdr.len -= len;
4541541Srgrimes			return;
4551541Srgrimes		}
4561541Srgrimes		count -= len;
4571541Srgrimes		if (count < 0)
4581541Srgrimes			count = 0;
4591541Srgrimes		/*
4601541Srgrimes		 * Correct length for chain is "count".
4611541Srgrimes		 * Find the mbuf with last data, adjust its length,
4621541Srgrimes		 * and toss data from remaining mbufs on chain.
4631541Srgrimes		 */
4641541Srgrimes		m = mp;
4651541Srgrimes		if (m->m_flags & M_PKTHDR)
4661541Srgrimes			m->m_pkthdr.len = count;
4671541Srgrimes		for (; m; m = m->m_next) {
4681541Srgrimes			if (m->m_len >= count) {
4691541Srgrimes				m->m_len = count;
4701541Srgrimes				break;
4711541Srgrimes			}
4721541Srgrimes			count -= m->m_len;
4731541Srgrimes		}
4743308Sphk		while (m->m_next)
4753308Sphk			(m = m->m_next) ->m_len = 0;
4761541Srgrimes	}
4771541Srgrimes}
4781541Srgrimes
4791541Srgrimes/*
4801541Srgrimes * Rearange an mbuf chain so that len bytes are contiguous
4811541Srgrimes * and in the data area of an mbuf (so that mtod and dtom
4821541Srgrimes * will work for a structure of size len).  Returns the resulting
4831541Srgrimes * mbuf chain on success, frees it and returns null on failure.
4841541Srgrimes * If there is room, it will add up to max_protohdr-len extra bytes to the
4851541Srgrimes * contiguous region in an attempt to avoid being called next time.
4861541Srgrimes */
4871541Srgrimesint MPFail;
4881541Srgrimes
4891541Srgrimesstruct mbuf *
4901541Srgrimesm_pullup(n, len)
4911541Srgrimes	register struct mbuf *n;
4921541Srgrimes	int len;
4931541Srgrimes{
4941541Srgrimes	register struct mbuf *m;
4951541Srgrimes	register int count;
4961541Srgrimes	int space;
4971541Srgrimes
4981541Srgrimes	/*
4991541Srgrimes	 * If first mbuf has no cluster, and has room for len bytes
5001541Srgrimes	 * without shifting current data, pullup into it,
5011541Srgrimes	 * otherwise allocate a new mbuf to prepend to the chain.
5021541Srgrimes	 */
5031541Srgrimes	if ((n->m_flags & M_EXT) == 0 &&
5041541Srgrimes	    n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
5051541Srgrimes		if (n->m_len >= len)
5061541Srgrimes			return (n);
5071541Srgrimes		m = n;
5081541Srgrimes		n = n->m_next;
5091541Srgrimes		len -= m->m_len;
5101541Srgrimes	} else {
5111541Srgrimes		if (len > MHLEN)
5121541Srgrimes			goto bad;
5131541Srgrimes		MGET(m, M_DONTWAIT, n->m_type);
5141541Srgrimes		if (m == 0)
5151541Srgrimes			goto bad;
5161541Srgrimes		m->m_len = 0;
5171541Srgrimes		if (n->m_flags & M_PKTHDR) {
5181541Srgrimes			M_COPY_PKTHDR(m, n);
5191541Srgrimes			n->m_flags &= ~M_PKTHDR;
5201541Srgrimes		}
5211541Srgrimes	}
5221541Srgrimes	space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
5231541Srgrimes	do {
5241541Srgrimes		count = min(min(max(len, max_protohdr), space), n->m_len);
5251541Srgrimes		bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
5261541Srgrimes		  (unsigned)count);
5271541Srgrimes		len -= count;
5281541Srgrimes		m->m_len += count;
5291541Srgrimes		n->m_len -= count;
5301541Srgrimes		space -= count;
5311541Srgrimes		if (n->m_len)
5321541Srgrimes			n->m_data += count;
5331541Srgrimes		else
5341541Srgrimes			n = m_free(n);
5351541Srgrimes	} while (len > 0 && n);
5361541Srgrimes	if (len > 0) {
5371541Srgrimes		(void) m_free(m);
5381541Srgrimes		goto bad;
5391541Srgrimes	}
5401541Srgrimes	m->m_next = n;
5411541Srgrimes	return (m);
5421541Srgrimesbad:
5431541Srgrimes	m_freem(n);
5441541Srgrimes	MPFail++;
5451541Srgrimes	return (0);
5461541Srgrimes}
5471541Srgrimes
5481541Srgrimes/*
5491541Srgrimes * Partition an mbuf chain in two pieces, returning the tail --
5501541Srgrimes * all but the first len0 bytes.  In case of failure, it returns NULL and
5511541Srgrimes * attempts to restore the chain to its original state.
5521541Srgrimes */
5531541Srgrimesstruct mbuf *
5541541Srgrimesm_split(m0, len0, wait)
5551541Srgrimes	register struct mbuf *m0;
5561541Srgrimes	int len0, wait;
5571541Srgrimes{
5581541Srgrimes	register struct mbuf *m, *n;
5591541Srgrimes	unsigned len = len0, remain;
5601541Srgrimes
5611541Srgrimes	for (m = m0; m && len > m->m_len; m = m->m_next)
5621541Srgrimes		len -= m->m_len;
5631541Srgrimes	if (m == 0)
5641541Srgrimes		return (0);
5651541Srgrimes	remain = m->m_len - len;
5661541Srgrimes	if (m0->m_flags & M_PKTHDR) {
5671541Srgrimes		MGETHDR(n, wait, m0->m_type);
5681541Srgrimes		if (n == 0)
5691541Srgrimes			return (0);
5701541Srgrimes		n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
5711541Srgrimes		n->m_pkthdr.len = m0->m_pkthdr.len - len0;
5721541Srgrimes		m0->m_pkthdr.len = len0;
5731541Srgrimes		if (m->m_flags & M_EXT)
5741541Srgrimes			goto extpacket;
5751541Srgrimes		if (remain > MHLEN) {
5761541Srgrimes			/* m can't be the lead packet */
5771541Srgrimes			MH_ALIGN(n, 0);
5781541Srgrimes			n->m_next = m_split(m, len, wait);
5791541Srgrimes			if (n->m_next == 0) {
5801541Srgrimes				(void) m_free(n);
5811541Srgrimes				return (0);
5821541Srgrimes			} else
5831541Srgrimes				return (n);
5841541Srgrimes		} else
5851541Srgrimes			MH_ALIGN(n, remain);
5861541Srgrimes	} else if (remain == 0) {
5871541Srgrimes		n = m->m_next;
5881541Srgrimes		m->m_next = 0;
5891541Srgrimes		return (n);
5901541Srgrimes	} else {
5911541Srgrimes		MGET(n, wait, m->m_type);
5921541Srgrimes		if (n == 0)
5931541Srgrimes			return (0);
5941541Srgrimes		M_ALIGN(n, remain);
5951541Srgrimes	}
5961541Srgrimesextpacket:
5971541Srgrimes	if (m->m_flags & M_EXT) {
5981541Srgrimes		n->m_flags |= M_EXT;
5991541Srgrimes		n->m_ext = m->m_ext;
6001541Srgrimes		mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
6011541Srgrimes		m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */
6021541Srgrimes		n->m_data = m->m_data + len;
6031541Srgrimes	} else {
6041541Srgrimes		bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain);
6051541Srgrimes	}
6061541Srgrimes	n->m_len = remain;
6071541Srgrimes	m->m_len = len;
6081541Srgrimes	n->m_next = m->m_next;
6091541Srgrimes	m->m_next = 0;
6101541Srgrimes	return (n);
6111541Srgrimes}
6121541Srgrimes/*
6131541Srgrimes * Routine to copy from device local memory into mbufs.
6141541Srgrimes */
6151541Srgrimesstruct mbuf *
6161541Srgrimesm_devget(buf, totlen, off0, ifp, copy)
6171541Srgrimes	char *buf;
6181541Srgrimes	int totlen, off0;
6191541Srgrimes	struct ifnet *ifp;
6201541Srgrimes	void (*copy)();
6211541Srgrimes{
6221541Srgrimes	register struct mbuf *m;
6231541Srgrimes	struct mbuf *top = 0, **mp = &top;
6241541Srgrimes	register int off = off0, len;
6251541Srgrimes	register char *cp;
6261541Srgrimes	char *epkt;
6271541Srgrimes
6281541Srgrimes	cp = buf;
6291541Srgrimes	epkt = cp + totlen;
6301541Srgrimes	if (off) {
6311541Srgrimes		cp += off + 2 * sizeof(u_short);
6321541Srgrimes		totlen -= 2 * sizeof(u_short);
6331541Srgrimes	}
6341541Srgrimes	MGETHDR(m, M_DONTWAIT, MT_DATA);
6351541Srgrimes	if (m == 0)
6361541Srgrimes		return (0);
6371541Srgrimes	m->m_pkthdr.rcvif = ifp;
6381541Srgrimes	m->m_pkthdr.len = totlen;
6391541Srgrimes	m->m_len = MHLEN;
6401541Srgrimes
6411541Srgrimes	while (totlen > 0) {
6421541Srgrimes		if (top) {
6431541Srgrimes			MGET(m, M_DONTWAIT, MT_DATA);
6441541Srgrimes			if (m == 0) {
6451541Srgrimes				m_freem(top);
6461541Srgrimes				return (0);
6471541Srgrimes			}
6481541Srgrimes			m->m_len = MLEN;
6491541Srgrimes		}
6501541Srgrimes		len = min(totlen, epkt - cp);
6511541Srgrimes		if (len >= MINCLSIZE) {
6521541Srgrimes			MCLGET(m, M_DONTWAIT);
6531541Srgrimes			if (m->m_flags & M_EXT)
6541541Srgrimes				m->m_len = len = min(len, MCLBYTES);
6551541Srgrimes			else
6561541Srgrimes				len = m->m_len;
6571541Srgrimes		} else {
6581541Srgrimes			/*
6591541Srgrimes			 * Place initial small packet/header at end of mbuf.
6601541Srgrimes			 */
6611541Srgrimes			if (len < m->m_len) {
6621541Srgrimes				if (top == 0 && len + max_linkhdr <= m->m_len)
6631541Srgrimes					m->m_data += max_linkhdr;
6641541Srgrimes				m->m_len = len;
6651541Srgrimes			} else
6661541Srgrimes				len = m->m_len;
6671541Srgrimes		}
6681541Srgrimes		if (copy)
6691541Srgrimes			copy(cp, mtod(m, caddr_t), (unsigned)len);
6701541Srgrimes		else
6711541Srgrimes			bcopy(cp, mtod(m, caddr_t), (unsigned)len);
6721541Srgrimes		cp += len;
6731541Srgrimes		*mp = m;
6741541Srgrimes		mp = &m->m_next;
6751541Srgrimes		totlen -= len;
6761541Srgrimes		if (cp == epkt)
6771541Srgrimes			cp = buf;
6781541Srgrimes	}
6791541Srgrimes	return (top);
6801541Srgrimes}
6813352Sphk
6823352Sphk/*
6833352Sphk * Copy data from a buffer back into the indicated mbuf chain,
6843352Sphk * starting "off" bytes from the beginning, extending the mbuf
6853352Sphk * chain if necessary.
6863352Sphk */
6873352Sphkvoid
6883352Sphkm_copyback(m0, off, len, cp)
6893352Sphk	struct	mbuf *m0;
6903352Sphk	register int off;
6913352Sphk	register int len;
6923352Sphk	caddr_t cp;
6933352Sphk{
6943352Sphk	register int mlen;
6953352Sphk	register struct mbuf *m = m0, *n;
6963352Sphk	int totlen = 0;
6973352Sphk
6983352Sphk	if (m0 == 0)
6993352Sphk		return;
7003352Sphk	while (off > (mlen = m->m_len)) {
7013352Sphk		off -= mlen;
7023352Sphk		totlen += mlen;
7033352Sphk		if (m->m_next == 0) {
7043352Sphk			n = m_getclr(M_DONTWAIT, m->m_type);
7053352Sphk			if (n == 0)
7063352Sphk				goto out;
7073352Sphk			n->m_len = min(MLEN, len + off);
7083352Sphk			m->m_next = n;
7093352Sphk		}
7103352Sphk		m = m->m_next;
7113352Sphk	}
7123352Sphk	while (len > 0) {
7133352Sphk		mlen = min (m->m_len - off, len);
7143352Sphk		bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
7153352Sphk		cp += mlen;
7163352Sphk		len -= mlen;
7173352Sphk		mlen += off;
7183352Sphk		off = 0;
7193352Sphk		totlen += mlen;
7203352Sphk		if (len == 0)
7213352Sphk			break;
7223352Sphk		if (m->m_next == 0) {
7233352Sphk			n = m_get(M_DONTWAIT, m->m_type);
7243352Sphk			if (n == 0)
7253352Sphk				break;
7263352Sphk			n->m_len = min(MLEN, len);
7273352Sphk			m->m_next = n;
7283352Sphk		}
7293352Sphk		m = m->m_next;
7303352Sphk	}
7313352Sphkout:	if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
7323352Sphk		m->m_pkthdr.len = totlen;
7333352Sphk}
734