uipc_mbuf.c revision 64837
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
3450477Speter * $FreeBSD: head/sys/kern/uipc_mbuf.c 64837 2000-08-19 08:32:59Z dwmalone $
351541Srgrimes */
361541Srgrimes
3748579Smsmith#include "opt_param.h"
381541Srgrimes#include <sys/param.h>
391541Srgrimes#include <sys/systm.h>
4032036Sbde#include <sys/malloc.h>
411541Srgrimes#include <sys/mbuf.h>
421541Srgrimes#include <sys/kernel.h>
4323081Swollman#include <sys/sysctl.h>
441541Srgrimes#include <sys/domain.h>
451541Srgrimes#include <sys/protosw.h>
461541Srgrimes
471541Srgrimes#include <vm/vm.h>
489759Sbde#include <vm/vm_kern.h>
4912662Sdg#include <vm/vm_extern.h>
501541Srgrimes
5154478Sgreen#ifdef INVARIANTS
5254478Sgreen#include <machine/cpu.h>
5354478Sgreen#endif
5454478Sgreen
5510653Sdgstatic void mbinit __P((void *));
5610358SjulianSYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbinit, NULL)
5710358Sjulian
589759Sbdestruct mbuf *mbutl;
599759Sbdestruct mbstat mbstat;
6063203Salfredu_long	mbtypes[MT_NTYPES];
6115689Swollmanstruct mbuf *mmbfree;
629759Sbdeunion mcluster *mclfree;
6364837Sdwmaloneunion mext_refcnt *mext_refcnt_free;
649759Sbdeint	max_linkhdr;
659759Sbdeint	max_protohdr;
669759Sbdeint	max_hdr;
679759Sbdeint	max_datalen;
6848579Smsmithint	nmbclusters;
6948579Smsmithint	nmbufs;
7054584Sgreenu_int	m_mballoc_wid = 0;
7154584Sgreenu_int	m_clalloc_wid = 0;
721541Srgrimes
7344078SdfrSYSCTL_DECL(_kern_ipc);
7423081SwollmanSYSCTL_INT(_kern_ipc, KIPC_MAX_LINKHDR, max_linkhdr, CTLFLAG_RW,
7523081Swollman	   &max_linkhdr, 0, "");
7623081SwollmanSYSCTL_INT(_kern_ipc, KIPC_MAX_PROTOHDR, max_protohdr, CTLFLAG_RW,
7723081Swollman	   &max_protohdr, 0, "");
7823081SwollmanSYSCTL_INT(_kern_ipc, KIPC_MAX_HDR, max_hdr, CTLFLAG_RW, &max_hdr, 0, "");
7923081SwollmanSYSCTL_INT(_kern_ipc, KIPC_MAX_DATALEN, max_datalen, CTLFLAG_RW,
8023081Swollman	   &max_datalen, 0, "");
8154478SgreenSYSCTL_INT(_kern_ipc, OID_AUTO, mbuf_wait, CTLFLAG_RW,
8254478Sgreen	   &mbuf_wait, 0, "");
8364048SalfredSYSCTL_STRUCT(_kern_ipc, KIPC_MBSTAT, mbstat, CTLFLAG_RD, &mbstat, mbstat, "");
8463203SalfredSYSCTL_OPAQUE(_kern_ipc, OID_AUTO, mbtypes, CTLFLAG_RD, mbtypes,
8563203Salfred	   sizeof(mbtypes), "LU", "");
8648579SmsmithSYSCTL_INT(_kern_ipc, KIPC_NMBCLUSTERS, nmbclusters, CTLFLAG_RD,
8755171Smsmith	   &nmbclusters, 0, "Maximum number of mbuf clusters available");
8855171SmsmithSYSCTL_INT(_kern_ipc, OID_AUTO, nmbufs, CTLFLAG_RD, &nmbufs, 0,
8955171Smsmith	   "Maximum number of mbufs available");
9048579Smsmith#ifndef NMBCLUSTERS
9148579Smsmith#define NMBCLUSTERS	(512 + MAXUSERS * 16)
9248579Smsmith#endif
9348579SmsmithTUNABLE_INT_DECL("kern.ipc.nmbclusters", NMBCLUSTERS, nmbclusters);
9455171SmsmithTUNABLE_INT_DECL("kern.ipc.nmbufs", NMBCLUSTERS * 4, nmbufs);
9523081Swollman
9612819Sphkstatic void	m_reclaim __P((void));
9712819Sphk
9864837Sdwmalone#define NCL_INIT	2
9915744Sphk#define NMB_INIT	16
10064837Sdwmalone#define REF_INIT	(NMBCLUSTERS * 2)
10115744Sphk
10210358Sjulian/* ARGSUSED*/
10310358Sjulianstatic void
10412569Sbdembinit(dummy)
10512569Sbde	void *dummy;
1061541Srgrimes{
1071541Srgrimes	int s;
1081541Srgrimes
10964837Sdwmalone	mmbfree = NULL;
11064837Sdwmalone	mclfree = NULL;
11164837Sdwmalone	mext_refcnt_free = NULL;
11264837Sdwmalone
11323081Swollman	mbstat.m_msize = MSIZE;
11423081Swollman	mbstat.m_mclbytes = MCLBYTES;
11523081Swollman	mbstat.m_minclsize = MINCLSIZE;
11623081Swollman	mbstat.m_mlen = MLEN;
11723081Swollman	mbstat.m_mhlen = MHLEN;
11823081Swollman
1191541Srgrimes	s = splimp();
12064837Sdwmalone	if (m_alloc_ref(REF_INIT) == 0)
12164837Sdwmalone		goto bad;
12215689Swollman	if (m_mballoc(NMB_INIT, M_DONTWAIT) == 0)
12315689Swollman		goto bad;
12422671Swollman#if MCLBYTES <= PAGE_SIZE
1251541Srgrimes	if (m_clalloc(NCL_INIT, M_DONTWAIT) == 0)
1261541Srgrimes		goto bad;
12722671Swollman#else
12822671Swollman	/* It's OK to call contigmalloc in this context. */
12932036Sbde	if (m_clalloc(16, M_WAIT) == 0)
13022671Swollman		goto bad;
13122671Swollman#endif
1321541Srgrimes	splx(s);
1331541Srgrimes	return;
1341541Srgrimesbad:
13564837Sdwmalone	panic("mbinit: failed to initialize mbuf subsystem!");
1361541Srgrimes}
1371541Srgrimes
1381541Srgrimes/*
13964837Sdwmalone * Allocate at least nmb reference count structs and place them
14064837Sdwmalone * on the ref cnt free list.
14164837Sdwmalone * Must be called at splimp.
14264837Sdwmalone */
14364837Sdwmaloneint
14464837Sdwmalonem_alloc_ref(nmb)
14564837Sdwmalone	u_int nmb;
14664837Sdwmalone{
14764837Sdwmalone	caddr_t p;
14864837Sdwmalone	u_int nbytes;
14964837Sdwmalone	int i;
15064837Sdwmalone
15164837Sdwmalone	/*
15264837Sdwmalone	 * XXX:
15364837Sdwmalone	 * We don't cap the amount of memory that can be used
15464837Sdwmalone	 * by the reference counters, like we do for mbufs and
15564837Sdwmalone	 * mbuf clusters. The reason is that we don't really expect
15664837Sdwmalone	 * to have to be allocating too many of these guys with m_alloc_ref(),
15764837Sdwmalone	 * and if we are, we're probably not out of the woods anyway,
15864837Sdwmalone	 * so leave this way for now.
15964837Sdwmalone	 */
16064837Sdwmalone
16164837Sdwmalone	if (mb_map_full)
16264837Sdwmalone		return (0);
16364837Sdwmalone
16464837Sdwmalone	nbytes = round_page(nmb * sizeof(union mext_refcnt));
16564837Sdwmalone	if ((p = (caddr_t)kmem_malloc(mb_map, nbytes, M_NOWAIT)) == NULL)
16664837Sdwmalone		return (0);
16764837Sdwmalone	nmb = nbytes / sizeof(union mext_refcnt);
16864837Sdwmalone
16964837Sdwmalone	for (i = 0; i < nmb; i++) {
17064837Sdwmalone		((union mext_refcnt *)p)->next_ref = mext_refcnt_free;
17164837Sdwmalone		mext_refcnt_free = (union mext_refcnt *)p;
17264837Sdwmalone		p += sizeof(union mext_refcnt);
17364837Sdwmalone		mbstat.m_refree++;
17464837Sdwmalone	}
17564837Sdwmalone	mbstat.m_refcnt += nmb;
17664837Sdwmalone
17764837Sdwmalone	return (1);
17864837Sdwmalone}
17964837Sdwmalone
18064837Sdwmalone/*
18115689Swollman * Allocate at least nmb mbufs and place on mbuf free list.
18215689Swollman * Must be called at splimp.
18315689Swollman */
18415689Swollman/* ARGSUSED */
18515689Swollmanint
18632036Sbdem_mballoc(nmb, how)
18715689Swollman	register int nmb;
18832036Sbde	int how;
18915689Swollman{
19015689Swollman	register caddr_t p;
19115689Swollman	register int i;
19215689Swollman	int nbytes;
19315689Swollman
19454478Sgreen	/*
19555171Smsmith	 * If we've hit the mbuf limit, stop allocating from mb_map,
19655171Smsmith	 * (or trying to) in order to avoid dipping into the section of
19755171Smsmith	 * mb_map which we've "reserved" for clusters.
19855171Smsmith	 */
19955171Smsmith	if ((nmb + mbstat.m_mbufs) > nmbufs)
20055171Smsmith		return (0);
20155171Smsmith
20255171Smsmith	/*
20354478Sgreen	 * Once we run out of map space, it will be impossible to get
20454478Sgreen	 * any more (nothing is ever freed back to the map)
20554478Sgreen	 * -- however you are not dead as m_reclaim might
20654478Sgreen	 * still be able to free a substantial amount of space.
20754478Sgreen	 *
20854478Sgreen	 * XXX Furthermore, we can also work with "recycled" mbufs (when
20954478Sgreen	 * we're calling with M_WAIT the sleep procedure will be woken
21054478Sgreen	 * up when an mbuf is freed. See m_mballoc_wait()).
21115689Swollman	 */
21215689Swollman	if (mb_map_full)
21315689Swollman		return (0);
21415689Swollman
21515689Swollman	nbytes = round_page(nmb * MSIZE);
21622899Swollman	p = (caddr_t)kmem_malloc(mb_map, nbytes, M_NOWAIT);
21732036Sbde	if (p == 0 && how == M_WAIT) {
21822899Swollman		mbstat.m_wait++;
21922899Swollman		p = (caddr_t)kmem_malloc(mb_map, nbytes, M_WAITOK);
22022899Swollman	}
22122899Swollman
22215689Swollman	/*
22332036Sbde	 * Either the map is now full, or `how' is M_NOWAIT and there
22415689Swollman	 * are no pages left.
22515689Swollman	 */
22615689Swollman	if (p == NULL)
22715689Swollman		return (0);
22815689Swollman
22915689Swollman	nmb = nbytes / MSIZE;
23015689Swollman	for (i = 0; i < nmb; i++) {
23115689Swollman		((struct mbuf *)p)->m_next = mmbfree;
23215689Swollman		mmbfree = (struct mbuf *)p;
23315689Swollman		p += MSIZE;
23415689Swollman	}
23515689Swollman	mbstat.m_mbufs += nmb;
23663203Salfred	mbtypes[MT_FREE] += nmb;
23715689Swollman	return (1);
23815689Swollman}
23915689Swollman
24054478Sgreen/*
24154478Sgreen * Once the mb_map has been exhausted and if the call to the allocation macros
24254478Sgreen * (or, in some cases, functions) is with M_WAIT, then it is necessary to rely
24354478Sgreen * solely on reclaimed mbufs. Here we wait for an mbuf to be freed for a
24454478Sgreen * designated (mbuf_wait) time.
24554478Sgreen */
24654478Sgreenstruct mbuf *
24754478Sgreenm_mballoc_wait(int caller, int type)
24854478Sgreen{
24954478Sgreen	struct mbuf *p;
25054478Sgreen	int s;
25154478Sgreen
25254478Sgreen	m_mballoc_wid++;
25354478Sgreen	if ((tsleep(&m_mballoc_wid, PVM, "mballc", mbuf_wait)) == EWOULDBLOCK)
25454478Sgreen		m_mballoc_wid--;
25554478Sgreen
25654478Sgreen	/*
25754478Sgreen	 * Now that we (think) that we've got something, we will redo an
25854478Sgreen	 * MGET, but avoid getting into another instance of m_mballoc_wait()
25954478Sgreen	 * XXX: We retry to fetch _even_ if the sleep timed out. This is left
26054478Sgreen	 *      this way, purposely, in the [unlikely] case that an mbuf was
26154478Sgreen	 *      freed but the sleep was not awakened in time.
26254478Sgreen	 */
26354478Sgreen	p = NULL;
26454478Sgreen	switch (caller) {
26554478Sgreen	case MGET_C:
26654478Sgreen		MGET(p, M_DONTWAIT, type);
26754478Sgreen		break;
26854478Sgreen	case MGETHDR_C:
26954478Sgreen		MGETHDR(p, M_DONTWAIT, type);
27054478Sgreen		break;
27154478Sgreen	default:
27254478Sgreen		panic("m_mballoc_wait: invalid caller (%d)", caller);
27354478Sgreen	}
27454478Sgreen
27554478Sgreen	s = splimp();
27654478Sgreen	if (p != NULL) {		/* We waited and got something... */
27754478Sgreen		mbstat.m_wait++;
27854478Sgreen		/* Wake up another if we have more free. */
27954478Sgreen		if (mmbfree != NULL)
28054787Sgreen			MMBWAKEUP();
28154478Sgreen	}
28254478Sgreen	splx(s);
28354478Sgreen	return (p);
28454478Sgreen}
28554478Sgreen
28622671Swollman#if MCLBYTES > PAGE_SIZE
28722899Swollmanstatic int i_want_my_mcl;
28822671Swollman
28922899Swollmanstatic void
29022671Swollmankproc_mclalloc(void)
29122671Swollman{
29222671Swollman	int status;
29322671Swollman
29422671Swollman	while (1) {
29522671Swollman		tsleep(&i_want_my_mcl, PVM, "mclalloc", 0);
29622671Swollman
29722671Swollman		for (; i_want_my_mcl; i_want_my_mcl--) {
29832036Sbde			if (m_clalloc(1, M_WAIT) == 0)
29922671Swollman				printf("m_clalloc failed even in process context!\n");
30022671Swollman		}
30122671Swollman	}
30222671Swollman}
30322671Swollman
30422671Swollmanstatic struct proc *mclallocproc;
30522671Swollmanstatic struct kproc_desc mclalloc_kp = {
30622671Swollman	"mclalloc",
30722671Swollman	kproc_mclalloc,
30822671Swollman	&mclallocproc
30922671Swollman};
31048391SpeterSYSINIT(mclallocproc, SI_SUB_KTHREAD_UPDATE, SI_ORDER_ANY, kproc_start,
31122671Swollman	   &mclalloc_kp);
31222671Swollman#endif
31322671Swollman
31415689Swollman/*
3151541Srgrimes * Allocate some number of mbuf clusters
3161541Srgrimes * and place on cluster free list.
3171541Srgrimes * Must be called at splimp.
3181541Srgrimes */
3191541Srgrimes/* ARGSUSED */
3201549Srgrimesint
32132036Sbdem_clalloc(ncl, how)
3221541Srgrimes	register int ncl;
32332036Sbde	int how;
3241541Srgrimes{
3251541Srgrimes	register caddr_t p;
3261541Srgrimes	register int i;
3271541Srgrimes	int npg;
3281541Srgrimes
3297066Sdg	/*
33055171Smsmith	 * If we've hit the mcluster number limit, stop allocating from
33155171Smsmith	 * mb_map, (or trying to) in order to avoid dipping into the section
33255171Smsmith	 * of mb_map which we've "reserved" for mbufs.
33355171Smsmith	 */
33455171Smsmith	if ((ncl + mbstat.m_clusters) > nmbclusters) {
33555171Smsmith		mbstat.m_drops++;
33655171Smsmith		return (0);
33755171Smsmith	}
33855171Smsmith
33955171Smsmith	/*
3407066Sdg	 * Once we run out of map space, it will be impossible
3417066Sdg	 * to get any more (nothing is ever freed back to the
34254478Sgreen	 * map). From this point on, we solely rely on freed
34354478Sgreen	 * mclusters.
3447066Sdg	 */
34522899Swollman	if (mb_map_full) {
34622899Swollman		mbstat.m_drops++;
3477066Sdg		return (0);
34822899Swollman	}
3497066Sdg
35022671Swollman#if MCLBYTES > PAGE_SIZE
35132036Sbde	if (how != M_WAIT) {
35222671Swollman		i_want_my_mcl += ncl;
35322671Swollman		wakeup(&i_want_my_mcl);
35422899Swollman		mbstat.m_wait++;
35522671Swollman		p = 0;
35622671Swollman	} else {
35722671Swollman		p = contigmalloc1(MCLBYTES * ncl, M_DEVBUF, M_WAITOK, 0ul,
35822671Swollman				  ~0ul, PAGE_SIZE, 0, mb_map);
35922671Swollman	}
36022671Swollman#else
36115543Sphk	npg = ncl;
36221737Sdg	p = (caddr_t)kmem_malloc(mb_map, ctob(npg),
36332036Sbde				 how != M_WAIT ? M_NOWAIT : M_WAITOK);
36422671Swollman	ncl = ncl * PAGE_SIZE / MCLBYTES;
36522671Swollman#endif
3667066Sdg	/*
36732036Sbde	 * Either the map is now full, or `how' is M_NOWAIT and there
3687066Sdg	 * are no pages left.
3697066Sdg	 */
37022899Swollman	if (p == NULL) {
37122899Swollman		mbstat.m_drops++;
3721541Srgrimes		return (0);
37322899Swollman	}
3747066Sdg
3751541Srgrimes	for (i = 0; i < ncl; i++) {
3761541Srgrimes		((union mcluster *)p)->mcl_next = mclfree;
3771541Srgrimes		mclfree = (union mcluster *)p;
3781541Srgrimes		p += MCLBYTES;
3791541Srgrimes		mbstat.m_clfree++;
3801541Srgrimes	}
3811541Srgrimes	mbstat.m_clusters += ncl;
3821541Srgrimes	return (1);
3831541Srgrimes}
3841541Srgrimes
3851541Srgrimes/*
38654478Sgreen * Once the mb_map submap has been exhausted and the allocation is called with
38754478Sgreen * M_WAIT, we rely on the mclfree union pointers. If nothing is free, we will
38854478Sgreen * sleep for a designated amount of time (mbuf_wait) or until we're woken up
38954478Sgreen * due to sudden mcluster availability.
39054478Sgreen */
39154478Sgreencaddr_t
39254478Sgreenm_clalloc_wait(void)
39354478Sgreen{
39454478Sgreen	caddr_t p;
39554478Sgreen	int s;
39654478Sgreen
39754478Sgreen#ifdef __i386__
39854478Sgreen	/* If in interrupt context, and INVARIANTS, maintain sanity and die. */
39954478Sgreen	KASSERT(intr_nesting_level == 0, ("CLALLOC: CANNOT WAIT IN INTERRUPT"));
40054478Sgreen#endif
40154478Sgreen
40254478Sgreen	/* Sleep until something's available or until we expire. */
40354478Sgreen	m_clalloc_wid++;
40454478Sgreen	if ((tsleep(&m_clalloc_wid, PVM, "mclalc", mbuf_wait)) == EWOULDBLOCK)
40554478Sgreen		m_clalloc_wid--;
40654478Sgreen
40754478Sgreen	/*
40854478Sgreen	 * Now that we (think) that we've got something, we will redo and
40954478Sgreen	 * MGET, but avoid getting into another instance of m_clalloc_wait()
41054478Sgreen	 */
41154478Sgreen	p = NULL;
41264837Sdwmalone	_MCLALLOC(p, M_DONTWAIT);
41354478Sgreen
41454478Sgreen	s = splimp();
41554478Sgreen	if (p != NULL) {	/* We waited and got something... */
41654478Sgreen		mbstat.m_wait++;
41754478Sgreen		/* Wake up another if we have more free. */
41854478Sgreen		if (mclfree != NULL)
41954787Sgreen			MCLWAKEUP();
42054478Sgreen	}
42154478Sgreen
42254478Sgreen	splx(s);
42354478Sgreen	return (p);
42454478Sgreen}
42554478Sgreen
42654478Sgreen/*
42745615Sdes * When MGET fails, ask protocols to free space when short of memory,
4281541Srgrimes * then re-attempt to allocate an mbuf.
4291541Srgrimes */
4301541Srgrimesstruct mbuf *
4311541Srgrimesm_retry(i, t)
4321541Srgrimes	int i, t;
4331541Srgrimes{
4341541Srgrimes	register struct mbuf *m;
4351541Srgrimes
43637878Sdg	/*
43737878Sdg	 * Must only do the reclaim if not in an interrupt context.
43837878Sdg	 */
43954478Sgreen	if (i == M_WAIT) {
44054478Sgreen#ifdef __i386__
44154478Sgreen		KASSERT(intr_nesting_level == 0,
44254478Sgreen		    ("MBALLOC: CANNOT WAIT IN INTERRUPT"));
44354478Sgreen#endif
44437878Sdg		m_reclaim();
44554478Sgreen	}
44654478Sgreen
44754478Sgreen	/*
44854478Sgreen	 * Both m_mballoc_wait and m_retry must be nulled because
44954478Sgreen	 * when the MGET macro is run from here, we deffinately do _not_
45054478Sgreen	 * want to enter an instance of m_mballoc_wait() or m_retry() (again!)
45154478Sgreen	 */
45254478Sgreen#define m_mballoc_wait(caller,type)    (struct mbuf *)0
4531541Srgrimes#define m_retry(i, t)	(struct mbuf *)0
4541541Srgrimes	MGET(m, i, t);
4551541Srgrimes#undef m_retry
45654478Sgreen#undef m_mballoc_wait
45754478Sgreen
45854478Sgreen	if (m != NULL)
4596669Sdg		mbstat.m_wait++;
46054478Sgreen	else
46154478Sgreen		mbstat.m_drops++;
46254478Sgreen
4631541Srgrimes	return (m);
4641541Srgrimes}
4651541Srgrimes
4661541Srgrimes/*
4671541Srgrimes * As above; retry an MGETHDR.
4681541Srgrimes */
4691541Srgrimesstruct mbuf *
4701541Srgrimesm_retryhdr(i, t)
4711541Srgrimes	int i, t;
4721541Srgrimes{
4731541Srgrimes	register struct mbuf *m;
4741541Srgrimes
47537878Sdg	/*
47637878Sdg	 * Must only do the reclaim if not in an interrupt context.
47737878Sdg	 */
47854478Sgreen	if (i == M_WAIT) {
47954478Sgreen#ifdef __i386__
48054478Sgreen		KASSERT(intr_nesting_level == 0,
48154478Sgreen		    ("MBALLOC: CANNOT WAIT IN INTERRUPT"));
48254478Sgreen#endif
48337878Sdg		m_reclaim();
48454478Sgreen	}
48554478Sgreen
48654478Sgreen#define m_mballoc_wait(caller,type)    (struct mbuf *)0
4871541Srgrimes#define m_retryhdr(i, t) (struct mbuf *)0
4881541Srgrimes	MGETHDR(m, i, t);
4891541Srgrimes#undef m_retryhdr
49054478Sgreen#undef m_mballoc_wait
49154478Sgreen
49254478Sgreen	if (m != NULL)
4936669Sdg		mbstat.m_wait++;
49454478Sgreen	else
49554478Sgreen		mbstat.m_drops++;
49654478Sgreen
4971541Srgrimes	return (m);
4981541Srgrimes}
4991541Srgrimes
50012819Sphkstatic void
5011541Srgrimesm_reclaim()
5021541Srgrimes{
5031541Srgrimes	register struct domain *dp;
5041541Srgrimes	register struct protosw *pr;
5051541Srgrimes	int s = splimp();
5061541Srgrimes
5071541Srgrimes	for (dp = domains; dp; dp = dp->dom_next)
5081541Srgrimes		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
5091541Srgrimes			if (pr->pr_drain)
5101541Srgrimes				(*pr->pr_drain)();
5111541Srgrimes	splx(s);
5121541Srgrimes	mbstat.m_drain++;
5131541Srgrimes}
5141541Srgrimes
5151541Srgrimes/*
5161541Srgrimes * Space allocation routines.
5171541Srgrimes * These are also available as macros
5181541Srgrimes * for critical paths.
5191541Srgrimes */
5201541Srgrimesstruct mbuf *
52132036Sbdem_get(how, type)
52232036Sbde	int how, type;
5231541Srgrimes{
5241541Srgrimes	register struct mbuf *m;
5251541Srgrimes
52632036Sbde	MGET(m, how, type);
5271541Srgrimes	return (m);
5281541Srgrimes}
5291541Srgrimes
5301541Srgrimesstruct mbuf *
53132036Sbdem_gethdr(how, type)
53232036Sbde	int how, type;
5331541Srgrimes{
5341541Srgrimes	register struct mbuf *m;
5351541Srgrimes
53632036Sbde	MGETHDR(m, how, type);
5371541Srgrimes	return (m);
5381541Srgrimes}
5391541Srgrimes
5401541Srgrimesstruct mbuf *
54132036Sbdem_getclr(how, type)
54232036Sbde	int how, type;
5431541Srgrimes{
5441541Srgrimes	register struct mbuf *m;
5451541Srgrimes
54632036Sbde	MGET(m, how, type);
5471541Srgrimes	if (m == 0)
5481541Srgrimes		return (0);
5491541Srgrimes	bzero(mtod(m, caddr_t), MLEN);
5501541Srgrimes	return (m);
5511541Srgrimes}
5521541Srgrimes
5531541Srgrimesstruct mbuf *
5541541Srgrimesm_free(m)
5551541Srgrimes	struct mbuf *m;
5561541Srgrimes{
5571541Srgrimes	register struct mbuf *n;
5581541Srgrimes
5591541Srgrimes	MFREE(m, n);
5601541Srgrimes	return (n);
5611541Srgrimes}
5621541Srgrimes
5631541Srgrimesvoid
5641541Srgrimesm_freem(m)
5651541Srgrimes	register struct mbuf *m;
5661541Srgrimes{
5671541Srgrimes	register struct mbuf *n;
5681541Srgrimes
5691541Srgrimes	if (m == NULL)
5701541Srgrimes		return;
5711541Srgrimes	do {
57262587Sitojun		/*
57362587Sitojun		 * we do need to check non-first mbuf, since some of existing
57462587Sitojun		 * code does not call M_PREPEND properly.
57562587Sitojun		 * (example: call to bpf_mtap from drivers)
57662587Sitojun		 */
57762587Sitojun		if ((m->m_flags & M_PKTHDR) != 0 && m->m_pkthdr.aux) {
57862587Sitojun			m_freem(m->m_pkthdr.aux);
57962587Sitojun			m->m_pkthdr.aux = NULL;
58062587Sitojun		}
5811541Srgrimes		MFREE(m, n);
5823308Sphk		m = n;
5833308Sphk	} while (m);
5841541Srgrimes}
5851541Srgrimes
5861541Srgrimes/*
5871541Srgrimes * Mbuffer utility routines.
5881541Srgrimes */
5891541Srgrimes
5901541Srgrimes/*
5911541Srgrimes * Lesser-used path for M_PREPEND:
5921541Srgrimes * allocate new mbuf to prepend to chain,
5931541Srgrimes * copy junk along.
5941541Srgrimes */
5951541Srgrimesstruct mbuf *
5961541Srgrimesm_prepend(m, len, how)
5971541Srgrimes	register struct mbuf *m;
5981541Srgrimes	int len, how;
5991541Srgrimes{
6001541Srgrimes	struct mbuf *mn;
6011541Srgrimes
6021541Srgrimes	MGET(mn, how, m->m_type);
6031541Srgrimes	if (mn == (struct mbuf *)NULL) {
6041541Srgrimes		m_freem(m);
6051541Srgrimes		return ((struct mbuf *)NULL);
6061541Srgrimes	}
6071541Srgrimes	if (m->m_flags & M_PKTHDR) {
6081541Srgrimes		M_COPY_PKTHDR(mn, m);
6091541Srgrimes		m->m_flags &= ~M_PKTHDR;
6101541Srgrimes	}
6111541Srgrimes	mn->m_next = m;
6121541Srgrimes	m = mn;
6131541Srgrimes	if (len < MHLEN)
6141541Srgrimes		MH_ALIGN(m, len);
6151541Srgrimes	m->m_len = len;
6161541Srgrimes	return (m);
6171541Srgrimes}
6181541Srgrimes
6191541Srgrimes/*
6201541Srgrimes * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
6211541Srgrimes * continuing for "len" bytes.  If len is M_COPYALL, copy to end of mbuf.
6221541Srgrimes * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
62354002Sarchie * Note that the copy is read-only, because clusters are not copied,
62454002Sarchie * only their reference counts are incremented.
6251541Srgrimes */
62623081Swollman#define MCFail (mbstat.m_mcfail)
6271541Srgrimes
6281541Srgrimesstruct mbuf *
6291541Srgrimesm_copym(m, off0, len, wait)
6301541Srgrimes	register struct mbuf *m;
6311541Srgrimes	int off0, wait;
6321541Srgrimes	register int len;
6331541Srgrimes{
6341541Srgrimes	register struct mbuf *n, **np;
6351541Srgrimes	register int off = off0;
6361541Srgrimes	struct mbuf *top;
6371541Srgrimes	int copyhdr = 0;
6381541Srgrimes
63952201Salfred	KASSERT(off >= 0, ("m_copym, negative off %d", off));
64052201Salfred	KASSERT(len >= 0, ("m_copym, negative len %d", len));
6411541Srgrimes	if (off == 0 && m->m_flags & M_PKTHDR)
6421541Srgrimes		copyhdr = 1;
6431541Srgrimes	while (off > 0) {
64452201Salfred		KASSERT(m != NULL, ("m_copym, offset > size of mbuf chain"));
6451541Srgrimes		if (off < m->m_len)
6461541Srgrimes			break;
6471541Srgrimes		off -= m->m_len;
6481541Srgrimes		m = m->m_next;
6491541Srgrimes	}
6501541Srgrimes	np = &top;
6511541Srgrimes	top = 0;
6521541Srgrimes	while (len > 0) {
6531541Srgrimes		if (m == 0) {
65452201Salfred			KASSERT(len == M_COPYALL,
65552201Salfred			    ("m_copym, length > size of mbuf chain"));
6561541Srgrimes			break;
6571541Srgrimes		}
6581541Srgrimes		MGET(n, wait, m->m_type);
6591541Srgrimes		*np = n;
6601541Srgrimes		if (n == 0)
6611541Srgrimes			goto nospace;
6621541Srgrimes		if (copyhdr) {
6631541Srgrimes			M_COPY_PKTHDR(n, m);
6641541Srgrimes			if (len == M_COPYALL)
6651541Srgrimes				n->m_pkthdr.len -= off0;
6661541Srgrimes			else
6671541Srgrimes				n->m_pkthdr.len = len;
6681541Srgrimes			copyhdr = 0;
6691541Srgrimes		}
6701541Srgrimes		n->m_len = min(len, m->m_len - off);
6711541Srgrimes		if (m->m_flags & M_EXT) {
6721541Srgrimes			n->m_data = m->m_data + off;
6731541Srgrimes			n->m_ext = m->m_ext;
6741541Srgrimes			n->m_flags |= M_EXT;
67564837Sdwmalone			MEXT_ADD_REF(m);
6761541Srgrimes		} else
6771541Srgrimes			bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
6781541Srgrimes			    (unsigned)n->m_len);
6791541Srgrimes		if (len != M_COPYALL)
6801541Srgrimes			len -= n->m_len;
6811541Srgrimes		off = 0;
6821541Srgrimes		m = m->m_next;
6831541Srgrimes		np = &n->m_next;
6841541Srgrimes	}
6851541Srgrimes	if (top == 0)
6861541Srgrimes		MCFail++;
6871541Srgrimes	return (top);
6881541Srgrimesnospace:
6891541Srgrimes	m_freem(top);
6901541Srgrimes	MCFail++;
6911541Srgrimes	return (0);
6921541Srgrimes}
6931541Srgrimes
6941541Srgrimes/*
69515689Swollman * Copy an entire packet, including header (which must be present).
69615689Swollman * An optimization of the common case `m_copym(m, 0, M_COPYALL, how)'.
69754002Sarchie * Note that the copy is read-only, because clusters are not copied,
69854002Sarchie * only their reference counts are incremented.
69915689Swollman */
70015689Swollmanstruct mbuf *
70115689Swollmanm_copypacket(m, how)
70215689Swollman	struct mbuf *m;
70315689Swollman	int how;
70415689Swollman{
70515689Swollman	struct mbuf *top, *n, *o;
70615689Swollman
70715689Swollman	MGET(n, how, m->m_type);
70815689Swollman	top = n;
70915689Swollman	if (!n)
71015689Swollman		goto nospace;
71115689Swollman
71215689Swollman	M_COPY_PKTHDR(n, m);
71315689Swollman	n->m_len = m->m_len;
71415689Swollman	if (m->m_flags & M_EXT) {
71515689Swollman		n->m_data = m->m_data;
71615689Swollman		n->m_ext = m->m_ext;
71715689Swollman		n->m_flags |= M_EXT;
71864837Sdwmalone		MEXT_ADD_REF(m);
71915689Swollman	} else {
72015689Swollman		bcopy(mtod(m, char *), mtod(n, char *), n->m_len);
72115689Swollman	}
72215689Swollman
72315689Swollman	m = m->m_next;
72415689Swollman	while (m) {
72515689Swollman		MGET(o, how, m->m_type);
72615689Swollman		if (!o)
72715689Swollman			goto nospace;
72815689Swollman
72915689Swollman		n->m_next = o;
73015689Swollman		n = n->m_next;
73115689Swollman
73215689Swollman		n->m_len = m->m_len;
73315689Swollman		if (m->m_flags & M_EXT) {
73415689Swollman			n->m_data = m->m_data;
73515689Swollman			n->m_ext = m->m_ext;
73615689Swollman			n->m_flags |= M_EXT;
73764837Sdwmalone			MEXT_ADD_REF(m);
73815689Swollman		} else {
73915689Swollman			bcopy(mtod(m, char *), mtod(n, char *), n->m_len);
74015689Swollman		}
74115689Swollman
74215689Swollman		m = m->m_next;
74315689Swollman	}
74415689Swollman	return top;
74515689Swollmannospace:
74615689Swollman	m_freem(top);
74715689Swollman	MCFail++;
74815689Swollman	return 0;
74915689Swollman}
75015689Swollman
75115689Swollman/*
7521541Srgrimes * Copy data from an mbuf chain starting "off" bytes from the beginning,
7531541Srgrimes * continuing for "len" bytes, into the indicated buffer.
7541541Srgrimes */
7551549Srgrimesvoid
7561541Srgrimesm_copydata(m, off, len, cp)
7571541Srgrimes	register struct mbuf *m;
7581541Srgrimes	register int off;
7591541Srgrimes	register int len;
7601541Srgrimes	caddr_t cp;
7611541Srgrimes{
7621541Srgrimes	register unsigned count;
7631541Srgrimes
76452201Salfred	KASSERT(off >= 0, ("m_copydata, negative off %d", off));
76552201Salfred	KASSERT(len >= 0, ("m_copydata, negative len %d", len));
7661541Srgrimes	while (off > 0) {
76752201Salfred		KASSERT(m != NULL, ("m_copydata, offset > size of mbuf chain"));
7681541Srgrimes		if (off < m->m_len)
7691541Srgrimes			break;
7701541Srgrimes		off -= m->m_len;
7711541Srgrimes		m = m->m_next;
7721541Srgrimes	}
7731541Srgrimes	while (len > 0) {
77452201Salfred		KASSERT(m != NULL, ("m_copydata, length > size of mbuf chain"));
7751541Srgrimes		count = min(m->m_len - off, len);
7761541Srgrimes		bcopy(mtod(m, caddr_t) + off, cp, count);
7771541Srgrimes		len -= count;
7781541Srgrimes		cp += count;
7791541Srgrimes		off = 0;
7801541Srgrimes		m = m->m_next;
7811541Srgrimes	}
7821541Srgrimes}
7831541Srgrimes
7841541Srgrimes/*
78554002Sarchie * Copy a packet header mbuf chain into a completely new chain, including
78654002Sarchie * copying any mbuf clusters.  Use this instead of m_copypacket() when
78754002Sarchie * you need a writable copy of an mbuf chain.
78854002Sarchie */
78954002Sarchiestruct mbuf *
79054002Sarchiem_dup(m, how)
79154002Sarchie	struct mbuf *m;
79254002Sarchie	int how;
79354002Sarchie{
79454002Sarchie	struct mbuf **p, *top = NULL;
79554002Sarchie	int remain, moff, nsize;
79654002Sarchie
79754002Sarchie	/* Sanity check */
79854002Sarchie	if (m == NULL)
79954002Sarchie		return (0);
80054002Sarchie	KASSERT((m->m_flags & M_PKTHDR) != 0, ("%s: !PKTHDR", __FUNCTION__));
80154002Sarchie
80254002Sarchie	/* While there's more data, get a new mbuf, tack it on, and fill it */
80354002Sarchie	remain = m->m_pkthdr.len;
80454002Sarchie	moff = 0;
80554002Sarchie	p = &top;
80654002Sarchie	while (remain > 0 || top == NULL) {	/* allow m->m_pkthdr.len == 0 */
80754002Sarchie		struct mbuf *n;
80854002Sarchie
80954002Sarchie		/* Get the next new mbuf */
81054002Sarchie		MGET(n, how, m->m_type);
81154002Sarchie		if (n == NULL)
81254002Sarchie			goto nospace;
81354002Sarchie		if (top == NULL) {		/* first one, must be PKTHDR */
81454002Sarchie			M_COPY_PKTHDR(n, m);
81554002Sarchie			nsize = MHLEN;
81654002Sarchie		} else				/* not the first one */
81754002Sarchie			nsize = MLEN;
81854002Sarchie		if (remain >= MINCLSIZE) {
81954002Sarchie			MCLGET(n, how);
82054002Sarchie			if ((n->m_flags & M_EXT) == 0) {
82154002Sarchie				(void)m_free(n);
82254002Sarchie				goto nospace;
82354002Sarchie			}
82454002Sarchie			nsize = MCLBYTES;
82554002Sarchie		}
82654002Sarchie		n->m_len = 0;
82754002Sarchie
82854002Sarchie		/* Link it into the new chain */
82954002Sarchie		*p = n;
83054002Sarchie		p = &n->m_next;
83154002Sarchie
83254002Sarchie		/* Copy data from original mbuf(s) into new mbuf */
83354002Sarchie		while (n->m_len < nsize && m != NULL) {
83454002Sarchie			int chunk = min(nsize - n->m_len, m->m_len - moff);
83554002Sarchie
83654002Sarchie			bcopy(m->m_data + moff, n->m_data + n->m_len, chunk);
83754002Sarchie			moff += chunk;
83854002Sarchie			n->m_len += chunk;
83954002Sarchie			remain -= chunk;
84054002Sarchie			if (moff == m->m_len) {
84154002Sarchie				m = m->m_next;
84254002Sarchie				moff = 0;
84354002Sarchie			}
84454002Sarchie		}
84554002Sarchie
84654002Sarchie		/* Check correct total mbuf length */
84754002Sarchie		KASSERT((remain > 0 && m != NULL) || (remain == 0 && m == NULL),
84854002Sarchie		    	("%s: bogus m_pkthdr.len", __FUNCTION__));
84954002Sarchie	}
85054002Sarchie	return (top);
85154002Sarchie
85254002Sarchienospace:
85354002Sarchie	m_freem(top);
85454002Sarchie	MCFail++;
85554002Sarchie	return (0);
85654002Sarchie}
85754002Sarchie
85854002Sarchie/*
8591541Srgrimes * Concatenate mbuf chain n to m.
8601541Srgrimes * Both chains must be of the same type (e.g. MT_DATA).
8611541Srgrimes * Any m_pkthdr is not updated.
8621541Srgrimes */
8631549Srgrimesvoid
8641541Srgrimesm_cat(m, n)
8651541Srgrimes	register struct mbuf *m, *n;
8661541Srgrimes{
8671541Srgrimes	while (m->m_next)
8681541Srgrimes		m = m->m_next;
8691541Srgrimes	while (n) {
8701541Srgrimes		if (m->m_flags & M_EXT ||
8711541Srgrimes		    m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) {
8721541Srgrimes			/* just join the two chains */
8731541Srgrimes			m->m_next = n;
8741541Srgrimes			return;
8751541Srgrimes		}
8761541Srgrimes		/* splat the data from one into the other */
8771541Srgrimes		bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
8781541Srgrimes		    (u_int)n->m_len);
8791541Srgrimes		m->m_len += n->m_len;
8801541Srgrimes		n = m_free(n);
8811541Srgrimes	}
8821541Srgrimes}
8831541Srgrimes
8841549Srgrimesvoid
8851541Srgrimesm_adj(mp, req_len)
8861541Srgrimes	struct mbuf *mp;
8871541Srgrimes	int req_len;
8881541Srgrimes{
8891541Srgrimes	register int len = req_len;
8901541Srgrimes	register struct mbuf *m;
89133678Sbde	register int count;
8921541Srgrimes
8931541Srgrimes	if ((m = mp) == NULL)
8941541Srgrimes		return;
8951541Srgrimes	if (len >= 0) {
8961541Srgrimes		/*
8971541Srgrimes		 * Trim from head.
8981541Srgrimes		 */
8991541Srgrimes		while (m != NULL && len > 0) {
9001541Srgrimes			if (m->m_len <= len) {
9011541Srgrimes				len -= m->m_len;
9021541Srgrimes				m->m_len = 0;
9031541Srgrimes				m = m->m_next;
9041541Srgrimes			} else {
9051541Srgrimes				m->m_len -= len;
9061541Srgrimes				m->m_data += len;
9071541Srgrimes				len = 0;
9081541Srgrimes			}
9091541Srgrimes		}
9101541Srgrimes		m = mp;
9111541Srgrimes		if (mp->m_flags & M_PKTHDR)
9121541Srgrimes			m->m_pkthdr.len -= (req_len - len);
9131541Srgrimes	} else {
9141541Srgrimes		/*
9151541Srgrimes		 * Trim from tail.  Scan the mbuf chain,
9161541Srgrimes		 * calculating its length and finding the last mbuf.
9171541Srgrimes		 * If the adjustment only affects this mbuf, then just
9181541Srgrimes		 * adjust and return.  Otherwise, rescan and truncate
9191541Srgrimes		 * after the remaining size.
9201541Srgrimes		 */
9211541Srgrimes		len = -len;
9221541Srgrimes		count = 0;
9231541Srgrimes		for (;;) {
9241541Srgrimes			count += m->m_len;
9251541Srgrimes			if (m->m_next == (struct mbuf *)0)
9261541Srgrimes				break;
9271541Srgrimes			m = m->m_next;
9281541Srgrimes		}
9291541Srgrimes		if (m->m_len >= len) {
9301541Srgrimes			m->m_len -= len;
9311541Srgrimes			if (mp->m_flags & M_PKTHDR)
9321541Srgrimes				mp->m_pkthdr.len -= len;
9331541Srgrimes			return;
9341541Srgrimes		}
9351541Srgrimes		count -= len;
9361541Srgrimes		if (count < 0)
9371541Srgrimes			count = 0;
9381541Srgrimes		/*
9391541Srgrimes		 * Correct length for chain is "count".
9401541Srgrimes		 * Find the mbuf with last data, adjust its length,
9411541Srgrimes		 * and toss data from remaining mbufs on chain.
9421541Srgrimes		 */
9431541Srgrimes		m = mp;
9441541Srgrimes		if (m->m_flags & M_PKTHDR)
9451541Srgrimes			m->m_pkthdr.len = count;
9461541Srgrimes		for (; m; m = m->m_next) {
9471541Srgrimes			if (m->m_len >= count) {
9481541Srgrimes				m->m_len = count;
9491541Srgrimes				break;
9501541Srgrimes			}
9511541Srgrimes			count -= m->m_len;
9521541Srgrimes		}
9533308Sphk		while (m->m_next)
9543308Sphk			(m = m->m_next) ->m_len = 0;
9551541Srgrimes	}
9561541Srgrimes}
9571541Srgrimes
9581541Srgrimes/*
9591541Srgrimes * Rearange an mbuf chain so that len bytes are contiguous
9601541Srgrimes * and in the data area of an mbuf (so that mtod and dtom
9611541Srgrimes * will work for a structure of size len).  Returns the resulting
9621541Srgrimes * mbuf chain on success, frees it and returns null on failure.
9631541Srgrimes * If there is room, it will add up to max_protohdr-len extra bytes to the
9641541Srgrimes * contiguous region in an attempt to avoid being called next time.
9651541Srgrimes */
96623081Swollman#define MPFail (mbstat.m_mpfail)
9671541Srgrimes
9681541Srgrimesstruct mbuf *
9691541Srgrimesm_pullup(n, len)
9701541Srgrimes	register struct mbuf *n;
9711541Srgrimes	int len;
9721541Srgrimes{
9731541Srgrimes	register struct mbuf *m;
9741541Srgrimes	register int count;
9751541Srgrimes	int space;
9761541Srgrimes
9771541Srgrimes	/*
9781541Srgrimes	 * If first mbuf has no cluster, and has room for len bytes
9791541Srgrimes	 * without shifting current data, pullup into it,
9801541Srgrimes	 * otherwise allocate a new mbuf to prepend to the chain.
9811541Srgrimes	 */
9821541Srgrimes	if ((n->m_flags & M_EXT) == 0 &&
9831541Srgrimes	    n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
9841541Srgrimes		if (n->m_len >= len)
9851541Srgrimes			return (n);
9861541Srgrimes		m = n;
9871541Srgrimes		n = n->m_next;
9881541Srgrimes		len -= m->m_len;
9891541Srgrimes	} else {
9901541Srgrimes		if (len > MHLEN)
9911541Srgrimes			goto bad;
9921541Srgrimes		MGET(m, M_DONTWAIT, n->m_type);
9931541Srgrimes		if (m == 0)
9941541Srgrimes			goto bad;
9951541Srgrimes		m->m_len = 0;
9961541Srgrimes		if (n->m_flags & M_PKTHDR) {
9971541Srgrimes			M_COPY_PKTHDR(m, n);
9981541Srgrimes			n->m_flags &= ~M_PKTHDR;
9991541Srgrimes		}
10001541Srgrimes	}
10011541Srgrimes	space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
10021541Srgrimes	do {
10031541Srgrimes		count = min(min(max(len, max_protohdr), space), n->m_len);
10041541Srgrimes		bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
10051541Srgrimes		  (unsigned)count);
10061541Srgrimes		len -= count;
10071541Srgrimes		m->m_len += count;
10081541Srgrimes		n->m_len -= count;
10091541Srgrimes		space -= count;
10101541Srgrimes		if (n->m_len)
10111541Srgrimes			n->m_data += count;
10121541Srgrimes		else
10131541Srgrimes			n = m_free(n);
10141541Srgrimes	} while (len > 0 && n);
10151541Srgrimes	if (len > 0) {
10161541Srgrimes		(void) m_free(m);
10171541Srgrimes		goto bad;
10181541Srgrimes	}
10191541Srgrimes	m->m_next = n;
10201541Srgrimes	return (m);
10211541Srgrimesbad:
10221541Srgrimes	m_freem(n);
10231541Srgrimes	MPFail++;
10241541Srgrimes	return (0);
10251541Srgrimes}
10261541Srgrimes
10271541Srgrimes/*
10281541Srgrimes * Partition an mbuf chain in two pieces, returning the tail --
10291541Srgrimes * all but the first len0 bytes.  In case of failure, it returns NULL and
10301541Srgrimes * attempts to restore the chain to its original state.
10311541Srgrimes */
10321541Srgrimesstruct mbuf *
10331541Srgrimesm_split(m0, len0, wait)
10341541Srgrimes	register struct mbuf *m0;
10351541Srgrimes	int len0, wait;
10361541Srgrimes{
10371541Srgrimes	register struct mbuf *m, *n;
10381541Srgrimes	unsigned len = len0, remain;
10391541Srgrimes
10401541Srgrimes	for (m = m0; m && len > m->m_len; m = m->m_next)
10411541Srgrimes		len -= m->m_len;
10421541Srgrimes	if (m == 0)
10431541Srgrimes		return (0);
10441541Srgrimes	remain = m->m_len - len;
10451541Srgrimes	if (m0->m_flags & M_PKTHDR) {
10461541Srgrimes		MGETHDR(n, wait, m0->m_type);
10471541Srgrimes		if (n == 0)
10481541Srgrimes			return (0);
10491541Srgrimes		n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
10501541Srgrimes		n->m_pkthdr.len = m0->m_pkthdr.len - len0;
10511541Srgrimes		m0->m_pkthdr.len = len0;
10521541Srgrimes		if (m->m_flags & M_EXT)
10531541Srgrimes			goto extpacket;
10541541Srgrimes		if (remain > MHLEN) {
10551541Srgrimes			/* m can't be the lead packet */
10561541Srgrimes			MH_ALIGN(n, 0);
10571541Srgrimes			n->m_next = m_split(m, len, wait);
10581541Srgrimes			if (n->m_next == 0) {
10591541Srgrimes				(void) m_free(n);
10601541Srgrimes				return (0);
10611541Srgrimes			} else
10621541Srgrimes				return (n);
10631541Srgrimes		} else
10641541Srgrimes			MH_ALIGN(n, remain);
10651541Srgrimes	} else if (remain == 0) {
10661541Srgrimes		n = m->m_next;
10671541Srgrimes		m->m_next = 0;
10681541Srgrimes		return (n);
10691541Srgrimes	} else {
10701541Srgrimes		MGET(n, wait, m->m_type);
10711541Srgrimes		if (n == 0)
10721541Srgrimes			return (0);
10731541Srgrimes		M_ALIGN(n, remain);
10741541Srgrimes	}
10751541Srgrimesextpacket:
10761541Srgrimes	if (m->m_flags & M_EXT) {
10771541Srgrimes		n->m_flags |= M_EXT;
10781541Srgrimes		n->m_ext = m->m_ext;
107964837Sdwmalone		MEXT_ADD_REF(m);
10801541Srgrimes		m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */
10811541Srgrimes		n->m_data = m->m_data + len;
10821541Srgrimes	} else {
10831541Srgrimes		bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain);
10841541Srgrimes	}
10851541Srgrimes	n->m_len = remain;
10861541Srgrimes	m->m_len = len;
10871541Srgrimes	n->m_next = m->m_next;
10881541Srgrimes	m->m_next = 0;
10891541Srgrimes	return (n);
10901541Srgrimes}
10911541Srgrimes/*
10921541Srgrimes * Routine to copy from device local memory into mbufs.
10931541Srgrimes */
10941541Srgrimesstruct mbuf *
10951541Srgrimesm_devget(buf, totlen, off0, ifp, copy)
10961541Srgrimes	char *buf;
10971541Srgrimes	int totlen, off0;
10981541Srgrimes	struct ifnet *ifp;
109912577Sbde	void (*copy) __P((char *from, caddr_t to, u_int len));
11001541Srgrimes{
11011541Srgrimes	register struct mbuf *m;
11021541Srgrimes	struct mbuf *top = 0, **mp = &top;
11031541Srgrimes	register int off = off0, len;
11041541Srgrimes	register char *cp;
11051541Srgrimes	char *epkt;
11061541Srgrimes
11071541Srgrimes	cp = buf;
11081541Srgrimes	epkt = cp + totlen;
11091541Srgrimes	if (off) {
11101541Srgrimes		cp += off + 2 * sizeof(u_short);
11111541Srgrimes		totlen -= 2 * sizeof(u_short);
11121541Srgrimes	}
11131541Srgrimes	MGETHDR(m, M_DONTWAIT, MT_DATA);
11141541Srgrimes	if (m == 0)
11151541Srgrimes		return (0);
11161541Srgrimes	m->m_pkthdr.rcvif = ifp;
11171541Srgrimes	m->m_pkthdr.len = totlen;
11181541Srgrimes	m->m_len = MHLEN;
11191541Srgrimes
11201541Srgrimes	while (totlen > 0) {
11211541Srgrimes		if (top) {
11221541Srgrimes			MGET(m, M_DONTWAIT, MT_DATA);
11231541Srgrimes			if (m == 0) {
11241541Srgrimes				m_freem(top);
11251541Srgrimes				return (0);
11261541Srgrimes			}
11271541Srgrimes			m->m_len = MLEN;
11281541Srgrimes		}
11291541Srgrimes		len = min(totlen, epkt - cp);
11301541Srgrimes		if (len >= MINCLSIZE) {
11311541Srgrimes			MCLGET(m, M_DONTWAIT);
11321541Srgrimes			if (m->m_flags & M_EXT)
11331541Srgrimes				m->m_len = len = min(len, MCLBYTES);
11341541Srgrimes			else
11351541Srgrimes				len = m->m_len;
11361541Srgrimes		} else {
11371541Srgrimes			/*
11381541Srgrimes			 * Place initial small packet/header at end of mbuf.
11391541Srgrimes			 */
11401541Srgrimes			if (len < m->m_len) {
11411541Srgrimes				if (top == 0 && len + max_linkhdr <= m->m_len)
11421541Srgrimes					m->m_data += max_linkhdr;
11431541Srgrimes				m->m_len = len;
11441541Srgrimes			} else
11451541Srgrimes				len = m->m_len;
11461541Srgrimes		}
11471541Srgrimes		if (copy)
11481541Srgrimes			copy(cp, mtod(m, caddr_t), (unsigned)len);
11491541Srgrimes		else
11501541Srgrimes			bcopy(cp, mtod(m, caddr_t), (unsigned)len);
11511541Srgrimes		cp += len;
11521541Srgrimes		*mp = m;
11531541Srgrimes		mp = &m->m_next;
11541541Srgrimes		totlen -= len;
11551541Srgrimes		if (cp == epkt)
11561541Srgrimes			cp = buf;
11571541Srgrimes	}
11581541Srgrimes	return (top);
11591541Srgrimes}
11603352Sphk
11613352Sphk/*
11623352Sphk * Copy data from a buffer back into the indicated mbuf chain,
11633352Sphk * starting "off" bytes from the beginning, extending the mbuf
11643352Sphk * chain if necessary.
11653352Sphk */
11663352Sphkvoid
11673352Sphkm_copyback(m0, off, len, cp)
11683352Sphk	struct	mbuf *m0;
11693352Sphk	register int off;
11703352Sphk	register int len;
11713352Sphk	caddr_t cp;
11723352Sphk{
11733352Sphk	register int mlen;
11743352Sphk	register struct mbuf *m = m0, *n;
11753352Sphk	int totlen = 0;
11763352Sphk
11773352Sphk	if (m0 == 0)
11783352Sphk		return;
11793352Sphk	while (off > (mlen = m->m_len)) {
11803352Sphk		off -= mlen;
11813352Sphk		totlen += mlen;
11823352Sphk		if (m->m_next == 0) {
11833352Sphk			n = m_getclr(M_DONTWAIT, m->m_type);
11843352Sphk			if (n == 0)
11853352Sphk				goto out;
11863352Sphk			n->m_len = min(MLEN, len + off);
11873352Sphk			m->m_next = n;
11883352Sphk		}
11893352Sphk		m = m->m_next;
11903352Sphk	}
11913352Sphk	while (len > 0) {
11923352Sphk		mlen = min (m->m_len - off, len);
11933352Sphk		bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
11943352Sphk		cp += mlen;
11953352Sphk		len -= mlen;
11963352Sphk		mlen += off;
11973352Sphk		off = 0;
11983352Sphk		totlen += mlen;
11993352Sphk		if (len == 0)
12003352Sphk			break;
12013352Sphk		if (m->m_next == 0) {
12023352Sphk			n = m_get(M_DONTWAIT, m->m_type);
12033352Sphk			if (n == 0)
12043352Sphk				break;
12053352Sphk			n->m_len = min(MLEN, len);
12063352Sphk			m->m_next = n;
12073352Sphk		}
12083352Sphk		m = m->m_next;
12093352Sphk	}
12103352Sphkout:	if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
12113352Sphk		m->m_pkthdr.len = totlen;
12123352Sphk}
121352756Sphk
121452756Sphkvoid
121552756Sphkm_print(const struct mbuf *m)
121652756Sphk{
121752756Sphk	int len;
121854906Seivind	const struct mbuf *m2;
121952756Sphk
122052756Sphk	len = m->m_pkthdr.len;
122152756Sphk	m2 = m;
122252756Sphk	while (len) {
122352756Sphk		printf("%p %*D\n", m2, m2->m_len, (u_char *)m2->m_data, "-");
122452756Sphk		len -= m2->m_len;
122552756Sphk		m2 = m2->m_next;
122652756Sphk	}
122752756Sphk	return;
122852756Sphk}
1229