uipc_mbuf.c revision 130357
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 * 4. Neither the name of the University nor the names of its contributors
141541Srgrimes *    may be used to endorse or promote products derived from this software
151541Srgrimes *    without specific prior written permission.
161541Srgrimes *
171541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271541Srgrimes * SUCH DAMAGE.
281541Srgrimes *
291541Srgrimes *	@(#)uipc_mbuf.c	8.2 (Berkeley) 1/4/94
301541Srgrimes */
311541Srgrimes
32116182Sobrien#include <sys/cdefs.h>
33116182Sobrien__FBSDID("$FreeBSD: head/sys/kern/uipc_mbuf.c 130357 2004-06-11 18:17:25Z bmilekic $");
34116182Sobrien
35101007Srwatson#include "opt_mac.h"
3677572Sobrien#include "opt_param.h"
37113490Ssilby#include "opt_mbuf_stress_test.h"
38101007Srwatson
391541Srgrimes#include <sys/param.h>
401541Srgrimes#include <sys/systm.h>
4176166Smarkm#include <sys/kernel.h>
42125296Ssilby#include <sys/limits.h>
4376166Smarkm#include <sys/lock.h>
44101173Srwatson#include <sys/mac.h>
4532036Sbde#include <sys/malloc.h>
461541Srgrimes#include <sys/mbuf.h>
4723081Swollman#include <sys/sysctl.h>
481541Srgrimes#include <sys/domain.h>
491541Srgrimes#include <sys/protosw.h>
50125296Ssilby#include <sys/uio.h>
5176166Smarkm
529759Sbdeint	max_linkhdr;
539759Sbdeint	max_protohdr;
549759Sbdeint	max_hdr;
559759Sbdeint	max_datalen;
56116455Ssilby#ifdef MBUF_STRESS_TEST
57112777Ssilbyint	m_defragpackets;
58112777Ssilbyint	m_defragbytes;
59112777Ssilbyint	m_defraguseless;
60112777Ssilbyint	m_defragfailure;
61113490Ssilbyint	m_defragrandomfailures;
62113490Ssilby#endif
631541Srgrimes
6466475Sbmilekic/*
6566475Sbmilekic * sysctl(8) exported objects
6666475Sbmilekic */
6744078SdfrSYSCTL_DECL(_kern_ipc);
6823081SwollmanSYSCTL_INT(_kern_ipc, KIPC_MAX_LINKHDR, max_linkhdr, CTLFLAG_RW,
6923081Swollman	   &max_linkhdr, 0, "");
7023081SwollmanSYSCTL_INT(_kern_ipc, KIPC_MAX_PROTOHDR, max_protohdr, CTLFLAG_RW,
7123081Swollman	   &max_protohdr, 0, "");
7223081SwollmanSYSCTL_INT(_kern_ipc, KIPC_MAX_HDR, max_hdr, CTLFLAG_RW, &max_hdr, 0, "");
7323081SwollmanSYSCTL_INT(_kern_ipc, KIPC_MAX_DATALEN, max_datalen, CTLFLAG_RW,
7423081Swollman	   &max_datalen, 0, "");
75116455Ssilby#ifdef MBUF_STRESS_TEST
76112777SsilbySYSCTL_INT(_kern_ipc, OID_AUTO, m_defragpackets, CTLFLAG_RD,
77112777Ssilby	   &m_defragpackets, 0, "");
78112777SsilbySYSCTL_INT(_kern_ipc, OID_AUTO, m_defragbytes, CTLFLAG_RD,
79112777Ssilby	   &m_defragbytes, 0, "");
80112777SsilbySYSCTL_INT(_kern_ipc, OID_AUTO, m_defraguseless, CTLFLAG_RD,
81112777Ssilby	   &m_defraguseless, 0, "");
82112777SsilbySYSCTL_INT(_kern_ipc, OID_AUTO, m_defragfailure, CTLFLAG_RD,
83112777Ssilby	   &m_defragfailure, 0, "");
84113490SsilbySYSCTL_INT(_kern_ipc, OID_AUTO, m_defragrandomfailures, CTLFLAG_RW,
85113490Ssilby	   &m_defragrandomfailures, 0, "");
86113490Ssilby#endif
8775112Sbmilekic
881541Srgrimes/*
89129906Sbmilekic * Malloc-type for external ext_buf ref counts.
90129906Sbmilekic */
91129906SbmilekicMALLOC_DEFINE(M_MBUF, "mbextcnt", "mbuf external ref counts");
92129906Sbmilekic
93129906Sbmilekic/*
94129906Sbmilekic * Allocate a given length worth of mbufs and/or clusters (whatever fits
95129906Sbmilekic * best) and return a pointer to the top of the allocated chain.  If an
96129906Sbmilekic * existing mbuf chain is provided, then we will append the new chain
97129906Sbmilekic * to the existing one but still return the top of the newly allocated
98129906Sbmilekic * chain.
99129906Sbmilekic */
100129906Sbmilekicstruct mbuf *
101129906Sbmilekicm_getm(struct mbuf *m, int len, int how, short type)
102129906Sbmilekic{
103129906Sbmilekic	struct mbuf *mb, *top, *cur, *mtail;
104129906Sbmilekic	int num, rem;
105129906Sbmilekic	int i;
106129906Sbmilekic
107129906Sbmilekic	KASSERT(len >= 0, ("m_getm(): len is < 0"));
108129906Sbmilekic
109129906Sbmilekic	/* If m != NULL, we will append to the end of that chain. */
110129906Sbmilekic	if (m != NULL)
111129906Sbmilekic		for (mtail = m; mtail->m_next != NULL; mtail = mtail->m_next);
112129906Sbmilekic	else
113129906Sbmilekic		mtail = NULL;
114129906Sbmilekic
115129906Sbmilekic	/*
116129906Sbmilekic	 * Calculate how many mbufs+clusters ("packets") we need and how much
117129906Sbmilekic	 * leftover there is after that and allocate the first mbuf+cluster
118129906Sbmilekic	 * if required.
119129906Sbmilekic	 */
120129906Sbmilekic	num = len / MCLBYTES;
121129906Sbmilekic	rem = len % MCLBYTES;
122129906Sbmilekic	top = cur = NULL;
123129906Sbmilekic	if (num > 0) {
124129906Sbmilekic		if ((top = cur = m_getcl(how, type, 0)) == NULL)
125129906Sbmilekic			goto failed;
126130271Smux		top->m_len = 0;
127129906Sbmilekic	}
128129906Sbmilekic	num--;
129129906Sbmilekic
130129906Sbmilekic	for (i = 0; i < num; i++) {
131129906Sbmilekic		mb = m_getcl(how, type, 0);
132129906Sbmilekic		if (mb == NULL)
133129906Sbmilekic			goto failed;
134129906Sbmilekic		mb->m_len = 0;
135129906Sbmilekic		cur = (cur->m_next = mb);
136129906Sbmilekic	}
137129906Sbmilekic	if (rem > 0) {
138129906Sbmilekic		mb = (rem > MINCLSIZE) ?
139129906Sbmilekic		    m_getcl(how, type, 0) : m_get(how, type);
140129906Sbmilekic		if (mb == NULL)
141129906Sbmilekic			goto failed;
142129906Sbmilekic		mb->m_len = 0;
143129906Sbmilekic		if (cur == NULL)
144129906Sbmilekic			top = mb;
145129906Sbmilekic		else
146129906Sbmilekic			cur->m_next = mb;
147129906Sbmilekic	}
148129906Sbmilekic
149129906Sbmilekic	if (mtail != NULL)
150129906Sbmilekic		mtail->m_next = top;
151129906Sbmilekic	return top;
152129906Sbmilekicfailed:
153129906Sbmilekic	if (top != NULL)
154129906Sbmilekic		m_freem(top);
155129906Sbmilekic	return NULL;
156129906Sbmilekic}
157129906Sbmilekic
158129906Sbmilekic/*
159129906Sbmilekic * Free an entire chain of mbufs and associated external buffers, if
160129906Sbmilekic * applicable.
161129906Sbmilekic */
162129906Sbmilekicvoid
163129906Sbmilekicm_freem(struct mbuf *mb)
164129906Sbmilekic{
165129906Sbmilekic
166129906Sbmilekic	while (mb != NULL)
167129906Sbmilekic		mb = m_free(mb);
168129906Sbmilekic}
169129906Sbmilekic
170129906Sbmilekic/*-
171129906Sbmilekic * Configure a provided mbuf to refer to the provided external storage
172129906Sbmilekic * buffer and setup a reference count for said buffer.  If the setting
173129906Sbmilekic * up of the reference count fails, the M_EXT bit will not be set.  If
174129906Sbmilekic * successfull, the M_EXT bit is set in the mbuf's flags.
175129906Sbmilekic *
176129906Sbmilekic * Arguments:
177129906Sbmilekic *    mb     The existing mbuf to which to attach the provided buffer.
178129906Sbmilekic *    buf    The address of the provided external storage buffer.
179129906Sbmilekic *    size   The size of the provided buffer.
180129906Sbmilekic *    freef  A pointer to a routine that is responsible for freeing the
181129906Sbmilekic *           provided external storage buffer.
182129906Sbmilekic *    args   A pointer to an argument structure (of any type) to be passed
183129906Sbmilekic *           to the provided freef routine (may be NULL).
184129906Sbmilekic *    flags  Any other flags to be passed to the provided mbuf.
185129906Sbmilekic *    type   The type that the external storage buffer should be
186129906Sbmilekic *           labeled with.
187129906Sbmilekic *
188129906Sbmilekic * Returns:
189129906Sbmilekic *    Nothing.
190129906Sbmilekic */
191129906Sbmilekicvoid
192129906Sbmilekicm_extadd(struct mbuf *mb, caddr_t buf, u_int size,
193129906Sbmilekic    void (*freef)(void *, void *), void *args, int flags, int type)
194129906Sbmilekic{
195129906Sbmilekic	u_int *ref_cnt = NULL;
196129906Sbmilekic
197129906Sbmilekic	/* XXX Shouldn't be adding EXT_CLUSTER with this API */
198129906Sbmilekic	if (type == EXT_CLUSTER)
199129906Sbmilekic		ref_cnt = (u_int *)uma_find_refcnt(zone_clust,
200129906Sbmilekic		    mb->m_ext.ext_buf);
201129906Sbmilekic	else if (type == EXT_EXTREF)
202129906Sbmilekic		ref_cnt = mb->m_ext.ref_cnt;
203129906Sbmilekic	mb->m_ext.ref_cnt = (ref_cnt == NULL) ?
204129906Sbmilekic	    malloc(sizeof(u_int), M_MBUF, M_NOWAIT) : (u_int *)ref_cnt;
205129906Sbmilekic	if (mb->m_ext.ref_cnt != NULL) {
206129906Sbmilekic		*(mb->m_ext.ref_cnt) = 1;
207129906Sbmilekic		mb->m_flags |= (M_EXT | flags);
208129906Sbmilekic		mb->m_ext.ext_buf = buf;
209129906Sbmilekic		mb->m_data = mb->m_ext.ext_buf;
210129906Sbmilekic		mb->m_ext.ext_size = size;
211129906Sbmilekic		mb->m_ext.ext_free = freef;
212129906Sbmilekic		mb->m_ext.ext_args = args;
213129906Sbmilekic		mb->m_ext.ext_type = type;
214129906Sbmilekic        }
215129906Sbmilekic}
216129906Sbmilekic
217129906Sbmilekic/*
218129906Sbmilekic * Non-directly-exported function to clean up after mbufs with M_EXT
219129906Sbmilekic * storage attached to them if the reference count hits 0.
220129906Sbmilekic */
221129906Sbmilekicvoid
222129906Sbmilekicmb_free_ext(struct mbuf *m)
223129906Sbmilekic{
224130289Sbmilekic	u_int cnt;
225129906Sbmilekic
226130289Sbmilekic	/*
227130289Sbmilekic	 * This is tricky.  We need to make sure to decrement the
228130289Sbmilekic	 * refcount in a safe way but to also clean up if we're the
229130289Sbmilekic	 * last reference.  This method seems to do it without race.
230130289Sbmilekic	 */
231130289Sbmilekic	do {
232130289Sbmilekic		cnt = *(m->m_ext.ref_cnt);
233130289Sbmilekic		if (atomic_cmpset_int(m->m_ext.ref_cnt, cnt, cnt - 1)) {
234130289Sbmilekic			if (cnt == 1) {
235130289Sbmilekic				/*
236130289Sbmilekic				 * Do the free, should be safe.
237130289Sbmilekic				 */
238130289Sbmilekic				if (m->m_ext.ext_type == EXT_PACKET) {
239130289Sbmilekic					uma_zfree(zone_pack, m);
240130357Sbmilekic					return;
241130289Sbmilekic				} else if (m->m_ext.ext_type == EXT_CLUSTER) {
242130289Sbmilekic					uma_zfree(zone_clust, m->m_ext.ext_buf);
243130289Sbmilekic					m->m_ext.ext_buf = NULL;
244130289Sbmilekic				} else {
245130289Sbmilekic					(*(m->m_ext.ext_free))(m->m_ext.ext_buf,
246130289Sbmilekic					    m->m_ext.ext_args);
247130289Sbmilekic					if (m->m_ext.ext_type != EXT_EXTREF)
248130289Sbmilekic						free(m->m_ext.ref_cnt, M_MBUF);
249130357Sbmilekic					m->m_ext.ext_buf = NULL;
250130289Sbmilekic				}
251130289Sbmilekic			}
252130289Sbmilekic			/* Decrement (and potentially free) done, safely. */
253130289Sbmilekic			break;
254129906Sbmilekic		}
255130289Sbmilekic	} while (1);
256130357Sbmilekic	uma_zfree(zone_mbuf, m);
257129906Sbmilekic}
258129906Sbmilekic
259129906Sbmilekic/*
260108466Ssam * "Move" mbuf pkthdr from "from" to "to".
261100960Srwatson * "from" must have M_PKTHDR set, and "to" must be empty.
262100960Srwatson */
263100960Srwatsonvoid
264108466Ssamm_move_pkthdr(struct mbuf *to, struct mbuf *from)
265100960Srwatson{
266100960Srwatson
267100960Srwatson#if 0
268108466Ssam	/* see below for why these are not enabled */
269113255Sdes	M_ASSERTPKTHDR(to);
270113487Srwatson	/* Note: with MAC, this may not be a good assertion. */
271108466Ssam	KASSERT(SLIST_EMPTY(&to->m_pkthdr.tags),
272108466Ssam	    ("m_move_pkthdr: to has tags"));
273100960Srwatson#endif
274108466Ssam	KASSERT((to->m_flags & M_EXT) == 0, ("m_move_pkthdr: to has cluster"));
275101007Srwatson#ifdef MAC
276113487Srwatson	/*
277113487Srwatson	 * XXXMAC: It could be this should also occur for non-MAC?
278113487Srwatson	 */
279101007Srwatson	if (to->m_flags & M_PKTHDR)
280113487Srwatson		m_tag_delete_chain(to, NULL);
281101007Srwatson#endif
282108466Ssam	to->m_flags = from->m_flags & M_COPYFLAGS;
283100960Srwatson	to->m_data = to->m_pktdat;
284108466Ssam	to->m_pkthdr = from->m_pkthdr;		/* especially tags */
285108466Ssam	SLIST_INIT(&from->m_pkthdr.tags);	/* purge tags from src */
286108466Ssam	from->m_flags &= ~M_PKTHDR;
287108466Ssam}
288108466Ssam
289108466Ssam/*
290108466Ssam * Duplicate "from"'s mbuf pkthdr in "to".
291108466Ssam * "from" must have M_PKTHDR set, and "to" must be empty.
292108466Ssam * In particular, this does a deep copy of the packet tags.
293108466Ssam */
294108466Ssamint
295108466Ssamm_dup_pkthdr(struct mbuf *to, struct mbuf *from, int how)
296108466Ssam{
297108466Ssam
298108466Ssam#if 0
299108466Ssam	/*
300108466Ssam	 * The mbuf allocator only initializes the pkthdr
301108466Ssam	 * when the mbuf is allocated with MGETHDR. Many users
302108466Ssam	 * (e.g. m_copy*, m_prepend) use MGET and then
303108466Ssam	 * smash the pkthdr as needed causing these
304108466Ssam	 * assertions to trip.  For now just disable them.
305108466Ssam	 */
306113255Sdes	M_ASSERTPKTHDR(to);
307113487Srwatson	/* Note: with MAC, this may not be a good assertion. */
308108466Ssam	KASSERT(SLIST_EMPTY(&to->m_pkthdr.tags), ("m_dup_pkthdr: to has tags"));
309108466Ssam#endif
310108466Ssam#ifdef MAC
311108466Ssam	if (to->m_flags & M_PKTHDR)
312113487Srwatson		m_tag_delete_chain(to, NULL);
313108466Ssam#endif
314112733Ssilby	to->m_flags = (from->m_flags & M_COPYFLAGS) | (to->m_flags & M_EXT);
315112733Ssilby	if ((to->m_flags & M_EXT) == 0)
316112733Ssilby		to->m_data = to->m_pktdat;
317100960Srwatson	to->m_pkthdr = from->m_pkthdr;
318108466Ssam	SLIST_INIT(&to->m_pkthdr.tags);
319113480Srwatson	return (m_tag_copy_chain(to, from, MBTOM(how)));
320100960Srwatson}
321100960Srwatson
322100960Srwatson/*
3231541Srgrimes * Lesser-used path for M_PREPEND:
3241541Srgrimes * allocate new mbuf to prepend to chain,
3251541Srgrimes * copy junk along.
3261541Srgrimes */
3271541Srgrimesstruct mbuf *
32872356Sbmilekicm_prepend(struct mbuf *m, int len, int how)
3291541Srgrimes{
3301541Srgrimes	struct mbuf *mn;
3311541Srgrimes
332117770Ssilby	if (m->m_flags & M_PKTHDR)
333117770Ssilby		MGETHDR(mn, how, m->m_type);
334117770Ssilby	else
335117770Ssilby		MGET(mn, how, m->m_type);
33672356Sbmilekic	if (mn == NULL) {
3371541Srgrimes		m_freem(m);
33872356Sbmilekic		return (NULL);
3391541Srgrimes	}
340113487Srwatson	if (m->m_flags & M_PKTHDR)
341108466Ssam		M_MOVE_PKTHDR(mn, m);
3421541Srgrimes	mn->m_next = m;
3431541Srgrimes	m = mn;
3441541Srgrimes	if (len < MHLEN)
3451541Srgrimes		MH_ALIGN(m, len);
3461541Srgrimes	m->m_len = len;
3471541Srgrimes	return (m);
3481541Srgrimes}
3491541Srgrimes
3501541Srgrimes/*
3511541Srgrimes * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
3521541Srgrimes * continuing for "len" bytes.  If len is M_COPYALL, copy to end of mbuf.
353111119Simp * The wait parameter is a choice of M_TRYWAIT/M_DONTWAIT from caller.
35454002Sarchie * Note that the copy is read-only, because clusters are not copied,
35554002Sarchie * only their reference counts are incremented.
3561541Srgrimes */
3571541Srgrimesstruct mbuf *
35872356Sbmilekicm_copym(struct mbuf *m, int off0, int len, int wait)
3591541Srgrimes{
36072356Sbmilekic	struct mbuf *n, **np;
36172356Sbmilekic	int off = off0;
3621541Srgrimes	struct mbuf *top;
3631541Srgrimes	int copyhdr = 0;
3641541Srgrimes
36552201Salfred	KASSERT(off >= 0, ("m_copym, negative off %d", off));
36652201Salfred	KASSERT(len >= 0, ("m_copym, negative len %d", len));
3671541Srgrimes	if (off == 0 && m->m_flags & M_PKTHDR)
3681541Srgrimes		copyhdr = 1;
3691541Srgrimes	while (off > 0) {
37052201Salfred		KASSERT(m != NULL, ("m_copym, offset > size of mbuf chain"));
3711541Srgrimes		if (off < m->m_len)
3721541Srgrimes			break;
3731541Srgrimes		off -= m->m_len;
3741541Srgrimes		m = m->m_next;
3751541Srgrimes	}
3761541Srgrimes	np = &top;
3771541Srgrimes	top = 0;
3781541Srgrimes	while (len > 0) {
37972356Sbmilekic		if (m == NULL) {
38052201Salfred			KASSERT(len == M_COPYALL,
38152201Salfred			    ("m_copym, length > size of mbuf chain"));
3821541Srgrimes			break;
3831541Srgrimes		}
384117770Ssilby		if (copyhdr)
385117770Ssilby			MGETHDR(n, wait, m->m_type);
386117770Ssilby		else
387117770Ssilby			MGET(n, wait, m->m_type);
3881541Srgrimes		*np = n;
38972356Sbmilekic		if (n == NULL)
3901541Srgrimes			goto nospace;
3911541Srgrimes		if (copyhdr) {
392108466Ssam			if (!m_dup_pkthdr(n, m, wait))
393108466Ssam				goto nospace;
3941541Srgrimes			if (len == M_COPYALL)
3951541Srgrimes				n->m_pkthdr.len -= off0;
3961541Srgrimes			else
3971541Srgrimes				n->m_pkthdr.len = len;
3981541Srgrimes			copyhdr = 0;
3991541Srgrimes		}
4001541Srgrimes		n->m_len = min(len, m->m_len - off);
4011541Srgrimes		if (m->m_flags & M_EXT) {
4021541Srgrimes			n->m_data = m->m_data + off;
4031541Srgrimes			n->m_ext = m->m_ext;
4041541Srgrimes			n->m_flags |= M_EXT;
40564837Sdwmalone			MEXT_ADD_REF(m);
4061541Srgrimes		} else
4071541Srgrimes			bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
408103569Sbmilekic			    (u_int)n->m_len);
4091541Srgrimes		if (len != M_COPYALL)
4101541Srgrimes			len -= n->m_len;
4111541Srgrimes		off = 0;
4121541Srgrimes		m = m->m_next;
4131541Srgrimes		np = &n->m_next;
4141541Srgrimes	}
41578592Sbmilekic	if (top == NULL)
41678592Sbmilekic		mbstat.m_mcfail++;	/* XXX: No consistency. */
41778592Sbmilekic
4181541Srgrimes	return (top);
4191541Srgrimesnospace:
4201541Srgrimes	m_freem(top);
42178592Sbmilekic	mbstat.m_mcfail++;	/* XXX: No consistency. */
42272356Sbmilekic	return (NULL);
4231541Srgrimes}
4241541Srgrimes
4251541Srgrimes/*
42615689Swollman * Copy an entire packet, including header (which must be present).
42715689Swollman * An optimization of the common case `m_copym(m, 0, M_COPYALL, how)'.
42854002Sarchie * Note that the copy is read-only, because clusters are not copied,
42954002Sarchie * only their reference counts are incremented.
43072750Sluigi * Preserve alignment of the first mbuf so if the creator has left
43172750Sluigi * some room at the beginning (e.g. for inserting protocol headers)
43272750Sluigi * the copies still have the room available.
43315689Swollman */
43415689Swollmanstruct mbuf *
43572356Sbmilekicm_copypacket(struct mbuf *m, int how)
43615689Swollman{
43715689Swollman	struct mbuf *top, *n, *o;
43815689Swollman
43915689Swollman	MGET(n, how, m->m_type);
44015689Swollman	top = n;
44172356Sbmilekic	if (n == NULL)
44215689Swollman		goto nospace;
44315689Swollman
444108466Ssam	if (!m_dup_pkthdr(n, m, how))
445108466Ssam		goto nospace;
44615689Swollman	n->m_len = m->m_len;
44715689Swollman	if (m->m_flags & M_EXT) {
44815689Swollman		n->m_data = m->m_data;
44915689Swollman		n->m_ext = m->m_ext;
45015689Swollman		n->m_flags |= M_EXT;
45164837Sdwmalone		MEXT_ADD_REF(m);
45215689Swollman	} else {
45372750Sluigi		n->m_data = n->m_pktdat + (m->m_data - m->m_pktdat );
45415689Swollman		bcopy(mtod(m, char *), mtod(n, char *), n->m_len);
45515689Swollman	}
45615689Swollman
45715689Swollman	m = m->m_next;
45815689Swollman	while (m) {
45915689Swollman		MGET(o, how, m->m_type);
46072356Sbmilekic		if (o == NULL)
46115689Swollman			goto nospace;
46215689Swollman
46315689Swollman		n->m_next = o;
46415689Swollman		n = n->m_next;
46515689Swollman
46615689Swollman		n->m_len = m->m_len;
46715689Swollman		if (m->m_flags & M_EXT) {
46815689Swollman			n->m_data = m->m_data;
46915689Swollman			n->m_ext = m->m_ext;
47015689Swollman			n->m_flags |= M_EXT;
47164837Sdwmalone			MEXT_ADD_REF(m);
47215689Swollman		} else {
47315689Swollman			bcopy(mtod(m, char *), mtod(n, char *), n->m_len);
47415689Swollman		}
47515689Swollman
47615689Swollman		m = m->m_next;
47715689Swollman	}
47815689Swollman	return top;
47915689Swollmannospace:
48015689Swollman	m_freem(top);
48178592Sbmilekic	mbstat.m_mcfail++;	/* XXX: No consistency. */
48272356Sbmilekic	return (NULL);
48315689Swollman}
48415689Swollman
48515689Swollman/*
4861541Srgrimes * Copy data from an mbuf chain starting "off" bytes from the beginning,
4871541Srgrimes * continuing for "len" bytes, into the indicated buffer.
4881541Srgrimes */
4891549Srgrimesvoid
49081907Sjulianm_copydata(const struct mbuf *m, int off, int len, caddr_t cp)
4911541Srgrimes{
492103569Sbmilekic	u_int count;
4931541Srgrimes
49452201Salfred	KASSERT(off >= 0, ("m_copydata, negative off %d", off));
49552201Salfred	KASSERT(len >= 0, ("m_copydata, negative len %d", len));
4961541Srgrimes	while (off > 0) {
49752201Salfred		KASSERT(m != NULL, ("m_copydata, offset > size of mbuf chain"));
4981541Srgrimes		if (off < m->m_len)
4991541Srgrimes			break;
5001541Srgrimes		off -= m->m_len;
5011541Srgrimes		m = m->m_next;
5021541Srgrimes	}
5031541Srgrimes	while (len > 0) {
50452201Salfred		KASSERT(m != NULL, ("m_copydata, length > size of mbuf chain"));
5051541Srgrimes		count = min(m->m_len - off, len);
5061541Srgrimes		bcopy(mtod(m, caddr_t) + off, cp, count);
5071541Srgrimes		len -= count;
5081541Srgrimes		cp += count;
5091541Srgrimes		off = 0;
5101541Srgrimes		m = m->m_next;
5111541Srgrimes	}
5121541Srgrimes}
5131541Srgrimes
5141541Srgrimes/*
51554002Sarchie * Copy a packet header mbuf chain into a completely new chain, including
51654002Sarchie * copying any mbuf clusters.  Use this instead of m_copypacket() when
51754002Sarchie * you need a writable copy of an mbuf chain.
51854002Sarchie */
51954002Sarchiestruct mbuf *
52072356Sbmilekicm_dup(struct mbuf *m, int how)
52154002Sarchie{
52254002Sarchie	struct mbuf **p, *top = NULL;
52354002Sarchie	int remain, moff, nsize;
52454002Sarchie
52554002Sarchie	/* Sanity check */
52654002Sarchie	if (m == NULL)
52772356Sbmilekic		return (NULL);
528113255Sdes	M_ASSERTPKTHDR(m);
52954002Sarchie
53054002Sarchie	/* While there's more data, get a new mbuf, tack it on, and fill it */
53154002Sarchie	remain = m->m_pkthdr.len;
53254002Sarchie	moff = 0;
53354002Sarchie	p = &top;
53454002Sarchie	while (remain > 0 || top == NULL) {	/* allow m->m_pkthdr.len == 0 */
53554002Sarchie		struct mbuf *n;
53654002Sarchie
53754002Sarchie		/* Get the next new mbuf */
538129906Sbmilekic		if (remain >= MINCLSIZE) {
539129906Sbmilekic			n = m_getcl(how, m->m_type, 0);
540129906Sbmilekic			nsize = MCLBYTES;
541129906Sbmilekic		} else {
542129906Sbmilekic			n = m_get(how, m->m_type);
543129906Sbmilekic			nsize = MLEN;
544129906Sbmilekic		}
54554002Sarchie		if (n == NULL)
54654002Sarchie			goto nospace;
547129906Sbmilekic
548129906Sbmilekic		if (top == NULL) {		/* First one, must be PKTHDR */
549129906Sbmilekic			if (!m_dup_pkthdr(n, m, how)) {
550129906Sbmilekic				m_free(n);
551108466Ssam				goto nospace;
552129906Sbmilekic			}
55354002Sarchie			nsize = MHLEN;
55454002Sarchie		}
55554002Sarchie		n->m_len = 0;
55654002Sarchie
55754002Sarchie		/* Link it into the new chain */
55854002Sarchie		*p = n;
55954002Sarchie		p = &n->m_next;
56054002Sarchie
56154002Sarchie		/* Copy data from original mbuf(s) into new mbuf */
56254002Sarchie		while (n->m_len < nsize && m != NULL) {
56354002Sarchie			int chunk = min(nsize - n->m_len, m->m_len - moff);
56454002Sarchie
56554002Sarchie			bcopy(m->m_data + moff, n->m_data + n->m_len, chunk);
56654002Sarchie			moff += chunk;
56754002Sarchie			n->m_len += chunk;
56854002Sarchie			remain -= chunk;
56954002Sarchie			if (moff == m->m_len) {
57054002Sarchie				m = m->m_next;
57154002Sarchie				moff = 0;
57254002Sarchie			}
57354002Sarchie		}
57454002Sarchie
57554002Sarchie		/* Check correct total mbuf length */
57654002Sarchie		KASSERT((remain > 0 && m != NULL) || (remain == 0 && m == NULL),
57787594Sobrien		    	("%s: bogus m_pkthdr.len", __func__));
57854002Sarchie	}
57954002Sarchie	return (top);
58054002Sarchie
58154002Sarchienospace:
58254002Sarchie	m_freem(top);
58378592Sbmilekic	mbstat.m_mcfail++;	/* XXX: No consistency. */
58472356Sbmilekic	return (NULL);
58554002Sarchie}
58654002Sarchie
58754002Sarchie/*
5881541Srgrimes * Concatenate mbuf chain n to m.
5891541Srgrimes * Both chains must be of the same type (e.g. MT_DATA).
5901541Srgrimes * Any m_pkthdr is not updated.
5911541Srgrimes */
5921549Srgrimesvoid
59372356Sbmilekicm_cat(struct mbuf *m, struct mbuf *n)
5941541Srgrimes{
5951541Srgrimes	while (m->m_next)
5961541Srgrimes		m = m->m_next;
5971541Srgrimes	while (n) {
5981541Srgrimes		if (m->m_flags & M_EXT ||
5991541Srgrimes		    m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) {
6001541Srgrimes			/* just join the two chains */
6011541Srgrimes			m->m_next = n;
6021541Srgrimes			return;
6031541Srgrimes		}
6041541Srgrimes		/* splat the data from one into the other */
6051541Srgrimes		bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
6061541Srgrimes		    (u_int)n->m_len);
6071541Srgrimes		m->m_len += n->m_len;
6081541Srgrimes		n = m_free(n);
6091541Srgrimes	}
6101541Srgrimes}
6111541Srgrimes
6121549Srgrimesvoid
61372356Sbmilekicm_adj(struct mbuf *mp, int req_len)
6141541Srgrimes{
61572356Sbmilekic	int len = req_len;
61672356Sbmilekic	struct mbuf *m;
61772356Sbmilekic	int count;
6181541Srgrimes
6191541Srgrimes	if ((m = mp) == NULL)
6201541Srgrimes		return;
6211541Srgrimes	if (len >= 0) {
6221541Srgrimes		/*
6231541Srgrimes		 * Trim from head.
6241541Srgrimes		 */
6251541Srgrimes		while (m != NULL && len > 0) {
6261541Srgrimes			if (m->m_len <= len) {
6271541Srgrimes				len -= m->m_len;
6281541Srgrimes				m->m_len = 0;
6291541Srgrimes				m = m->m_next;
6301541Srgrimes			} else {
6311541Srgrimes				m->m_len -= len;
6321541Srgrimes				m->m_data += len;
6331541Srgrimes				len = 0;
6341541Srgrimes			}
6351541Srgrimes		}
6361541Srgrimes		m = mp;
6371541Srgrimes		if (mp->m_flags & M_PKTHDR)
6381541Srgrimes			m->m_pkthdr.len -= (req_len - len);
6391541Srgrimes	} else {
6401541Srgrimes		/*
6411541Srgrimes		 * Trim from tail.  Scan the mbuf chain,
6421541Srgrimes		 * calculating its length and finding the last mbuf.
6431541Srgrimes		 * If the adjustment only affects this mbuf, then just
6441541Srgrimes		 * adjust and return.  Otherwise, rescan and truncate
6451541Srgrimes		 * after the remaining size.
6461541Srgrimes		 */
6471541Srgrimes		len = -len;
6481541Srgrimes		count = 0;
6491541Srgrimes		for (;;) {
6501541Srgrimes			count += m->m_len;
6511541Srgrimes			if (m->m_next == (struct mbuf *)0)
6521541Srgrimes				break;
6531541Srgrimes			m = m->m_next;
6541541Srgrimes		}
6551541Srgrimes		if (m->m_len >= len) {
6561541Srgrimes			m->m_len -= len;
6571541Srgrimes			if (mp->m_flags & M_PKTHDR)
6581541Srgrimes				mp->m_pkthdr.len -= len;
6591541Srgrimes			return;
6601541Srgrimes		}
6611541Srgrimes		count -= len;
6621541Srgrimes		if (count < 0)
6631541Srgrimes			count = 0;
6641541Srgrimes		/*
6651541Srgrimes		 * Correct length for chain is "count".
6661541Srgrimes		 * Find the mbuf with last data, adjust its length,
6671541Srgrimes		 * and toss data from remaining mbufs on chain.
6681541Srgrimes		 */
6691541Srgrimes		m = mp;
6701541Srgrimes		if (m->m_flags & M_PKTHDR)
6711541Srgrimes			m->m_pkthdr.len = count;
6721541Srgrimes		for (; m; m = m->m_next) {
6731541Srgrimes			if (m->m_len >= count) {
6741541Srgrimes				m->m_len = count;
6751541Srgrimes				break;
6761541Srgrimes			}
6771541Srgrimes			count -= m->m_len;
6781541Srgrimes		}
6793308Sphk		while (m->m_next)
6803308Sphk			(m = m->m_next) ->m_len = 0;
6811541Srgrimes	}
6821541Srgrimes}
6831541Srgrimes
6841541Srgrimes/*
6851541Srgrimes * Rearange an mbuf chain so that len bytes are contiguous
6861541Srgrimes * and in the data area of an mbuf (so that mtod and dtom
6871541Srgrimes * will work for a structure of size len).  Returns the resulting
6881541Srgrimes * mbuf chain on success, frees it and returns null on failure.
6891541Srgrimes * If there is room, it will add up to max_protohdr-len extra bytes to the
6901541Srgrimes * contiguous region in an attempt to avoid being called next time.
6911541Srgrimes */
6921541Srgrimesstruct mbuf *
69372356Sbmilekicm_pullup(struct mbuf *n, int len)
6941541Srgrimes{
69572356Sbmilekic	struct mbuf *m;
69672356Sbmilekic	int count;
6971541Srgrimes	int space;
6981541Srgrimes
6991541Srgrimes	/*
7001541Srgrimes	 * If first mbuf has no cluster, and has room for len bytes
7011541Srgrimes	 * without shifting current data, pullup into it,
7021541Srgrimes	 * otherwise allocate a new mbuf to prepend to the chain.
7031541Srgrimes	 */
7041541Srgrimes	if ((n->m_flags & M_EXT) == 0 &&
7051541Srgrimes	    n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
7061541Srgrimes		if (n->m_len >= len)
7071541Srgrimes			return (n);
7081541Srgrimes		m = n;
7091541Srgrimes		n = n->m_next;
7101541Srgrimes		len -= m->m_len;
7111541Srgrimes	} else {
7121541Srgrimes		if (len > MHLEN)
7131541Srgrimes			goto bad;
714111119Simp		MGET(m, M_DONTWAIT, n->m_type);
71572356Sbmilekic		if (m == NULL)
7161541Srgrimes			goto bad;
7171541Srgrimes		m->m_len = 0;
718108466Ssam		if (n->m_flags & M_PKTHDR)
719108466Ssam			M_MOVE_PKTHDR(m, n);
7201541Srgrimes	}
7211541Srgrimes	space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
7221541Srgrimes	do {
7231541Srgrimes		count = min(min(max(len, max_protohdr), space), n->m_len);
7241541Srgrimes		bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
725103569Sbmilekic		  (u_int)count);
7261541Srgrimes		len -= count;
7271541Srgrimes		m->m_len += count;
7281541Srgrimes		n->m_len -= count;
7291541Srgrimes		space -= count;
7301541Srgrimes		if (n->m_len)
7311541Srgrimes			n->m_data += count;
7321541Srgrimes		else
7331541Srgrimes			n = m_free(n);
7341541Srgrimes	} while (len > 0 && n);
7351541Srgrimes	if (len > 0) {
7361541Srgrimes		(void) m_free(m);
7371541Srgrimes		goto bad;
7381541Srgrimes	}
7391541Srgrimes	m->m_next = n;
7401541Srgrimes	return (m);
7411541Srgrimesbad:
7421541Srgrimes	m_freem(n);
74378592Sbmilekic	mbstat.m_mpfail++;	/* XXX: No consistency. */
74472356Sbmilekic	return (NULL);
7451541Srgrimes}
7461541Srgrimes
7471541Srgrimes/*
7481541Srgrimes * Partition an mbuf chain in two pieces, returning the tail --
7491541Srgrimes * all but the first len0 bytes.  In case of failure, it returns NULL and
7501541Srgrimes * attempts to restore the chain to its original state.
75197681Sarchie *
75297681Sarchie * Note that the resulting mbufs might be read-only, because the new
75397681Sarchie * mbuf can end up sharing an mbuf cluster with the original mbuf if
75497681Sarchie * the "breaking point" happens to lie within a cluster mbuf. Use the
75597681Sarchie * M_WRITABLE() macro to check for this case.
7561541Srgrimes */
7571541Srgrimesstruct mbuf *
75872356Sbmilekicm_split(struct mbuf *m0, int len0, int wait)
7591541Srgrimes{
76072356Sbmilekic	struct mbuf *m, *n;
761103569Sbmilekic	u_int len = len0, remain;
7621541Srgrimes
7631541Srgrimes	for (m = m0; m && len > m->m_len; m = m->m_next)
7641541Srgrimes		len -= m->m_len;
76572356Sbmilekic	if (m == NULL)
76672356Sbmilekic		return (NULL);
7671541Srgrimes	remain = m->m_len - len;
7681541Srgrimes	if (m0->m_flags & M_PKTHDR) {
7691541Srgrimes		MGETHDR(n, wait, m0->m_type);
77072356Sbmilekic		if (n == NULL)
77172356Sbmilekic			return (NULL);
7721541Srgrimes		n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
7731541Srgrimes		n->m_pkthdr.len = m0->m_pkthdr.len - len0;
7741541Srgrimes		m0->m_pkthdr.len = len0;
7751541Srgrimes		if (m->m_flags & M_EXT)
7761541Srgrimes			goto extpacket;
7771541Srgrimes		if (remain > MHLEN) {
7781541Srgrimes			/* m can't be the lead packet */
7791541Srgrimes			MH_ALIGN(n, 0);
7801541Srgrimes			n->m_next = m_split(m, len, wait);
78172356Sbmilekic			if (n->m_next == NULL) {
7821541Srgrimes				(void) m_free(n);
78372356Sbmilekic				return (NULL);
78494471Shsu			} else {
78594471Shsu				n->m_len = 0;
7861541Srgrimes				return (n);
78794471Shsu			}
7881541Srgrimes		} else
7891541Srgrimes			MH_ALIGN(n, remain);
7901541Srgrimes	} else if (remain == 0) {
7911541Srgrimes		n = m->m_next;
79272356Sbmilekic		m->m_next = NULL;
7931541Srgrimes		return (n);
7941541Srgrimes	} else {
7951541Srgrimes		MGET(n, wait, m->m_type);
79672356Sbmilekic		if (n == NULL)
79772356Sbmilekic			return (NULL);
7981541Srgrimes		M_ALIGN(n, remain);
7991541Srgrimes	}
8001541Srgrimesextpacket:
8011541Srgrimes	if (m->m_flags & M_EXT) {
8021541Srgrimes		n->m_flags |= M_EXT;
8031541Srgrimes		n->m_ext = m->m_ext;
80464837Sdwmalone		MEXT_ADD_REF(m);
8051541Srgrimes		n->m_data = m->m_data + len;
8061541Srgrimes	} else {
8071541Srgrimes		bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain);
8081541Srgrimes	}
8091541Srgrimes	n->m_len = remain;
8101541Srgrimes	m->m_len = len;
8111541Srgrimes	n->m_next = m->m_next;
81272356Sbmilekic	m->m_next = NULL;
8131541Srgrimes	return (n);
8141541Srgrimes}
8151541Srgrimes/*
8161541Srgrimes * Routine to copy from device local memory into mbufs.
81778508Sbmilekic * Note that `off' argument is offset into first mbuf of target chain from
81878508Sbmilekic * which to begin copying the data to.
8191541Srgrimes */
8201541Srgrimesstruct mbuf *
82178508Sbmilekicm_devget(char *buf, int totlen, int off, struct ifnet *ifp,
82272356Sbmilekic	 void (*copy)(char *from, caddr_t to, u_int len))
8231541Srgrimes{
82472356Sbmilekic	struct mbuf *m;
825129906Sbmilekic	struct mbuf *top = NULL, **mp = &top;
82678508Sbmilekic	int len;
8271541Srgrimes
82878508Sbmilekic	if (off < 0 || off > MHLEN)
82978508Sbmilekic		return (NULL);
83078508Sbmilekic
831129906Sbmilekic	while (totlen > 0) {
832129906Sbmilekic		if (top == NULL) {	/* First one, must be PKTHDR */
833129906Sbmilekic			if (totlen + off >= MINCLSIZE) {
834129906Sbmilekic				m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
835129906Sbmilekic				len = MCLBYTES;
836129906Sbmilekic			} else {
837129906Sbmilekic				m = m_gethdr(M_DONTWAIT, MT_DATA);
838129906Sbmilekic				len = MHLEN;
8391541Srgrimes
840129906Sbmilekic				/* Place initial small packet/header at end of mbuf */
841129906Sbmilekic				if (m && totlen + off + max_linkhdr <= MLEN) {
842129906Sbmilekic					m->m_data += max_linkhdr;
843129906Sbmilekic					len -= max_linkhdr;
844129906Sbmilekic				}
845129906Sbmilekic			}
846129906Sbmilekic			if (m == NULL)
847129906Sbmilekic				return NULL;
848129906Sbmilekic			m->m_pkthdr.rcvif = ifp;
849129906Sbmilekic			m->m_pkthdr.len = totlen;
850129906Sbmilekic		} else {
851129906Sbmilekic			if (totlen + off >= MINCLSIZE) {
852129906Sbmilekic				m = m_getcl(M_DONTWAIT, MT_DATA, 0);
853129906Sbmilekic				len = MCLBYTES;
854129906Sbmilekic			} else {
855129906Sbmilekic				m = m_get(M_DONTWAIT, MT_DATA);
856129906Sbmilekic				len = MLEN;
857129906Sbmilekic			}
85872356Sbmilekic			if (m == NULL) {
8591541Srgrimes				m_freem(top);
860129906Sbmilekic				return NULL;
8611541Srgrimes			}
8621541Srgrimes		}
86378508Sbmilekic		if (off) {
86478508Sbmilekic			m->m_data += off;
86578508Sbmilekic			len -= off;
86678508Sbmilekic			off = 0;
86778508Sbmilekic		}
86878508Sbmilekic		m->m_len = len = min(totlen, len);
8691541Srgrimes		if (copy)
870103569Sbmilekic			copy(buf, mtod(m, caddr_t), (u_int)len);
8711541Srgrimes		else
872103569Sbmilekic			bcopy(buf, mtod(m, caddr_t), (u_int)len);
87378508Sbmilekic		buf += len;
8741541Srgrimes		*mp = m;
8751541Srgrimes		mp = &m->m_next;
8761541Srgrimes		totlen -= len;
8771541Srgrimes	}
8781541Srgrimes	return (top);
8791541Srgrimes}
8803352Sphk
8813352Sphk/*
8823352Sphk * Copy data from a buffer back into the indicated mbuf chain,
8833352Sphk * starting "off" bytes from the beginning, extending the mbuf
8843352Sphk * chain if necessary.
8853352Sphk */
8863352Sphkvoid
887128402Sluigim_copyback(struct mbuf *m0, int off, int len, c_caddr_t cp)
8883352Sphk{
88972356Sbmilekic	int mlen;
89072356Sbmilekic	struct mbuf *m = m0, *n;
8913352Sphk	int totlen = 0;
8923352Sphk
89372356Sbmilekic	if (m0 == NULL)
8943352Sphk		return;
8953352Sphk	while (off > (mlen = m->m_len)) {
8963352Sphk		off -= mlen;
8973352Sphk		totlen += mlen;
89872356Sbmilekic		if (m->m_next == NULL) {
899129906Sbmilekic			n = m_get(M_DONTWAIT, m->m_type);
90072356Sbmilekic			if (n == NULL)
9013352Sphk				goto out;
902129906Sbmilekic			bzero(mtod(n, caddr_t), MLEN);
9033352Sphk			n->m_len = min(MLEN, len + off);
9043352Sphk			m->m_next = n;
9053352Sphk		}
9063352Sphk		m = m->m_next;
9073352Sphk	}
9083352Sphk	while (len > 0) {
9093352Sphk		mlen = min (m->m_len - off, len);
910103569Sbmilekic		bcopy(cp, off + mtod(m, caddr_t), (u_int)mlen);
9113352Sphk		cp += mlen;
9123352Sphk		len -= mlen;
9133352Sphk		mlen += off;
9143352Sphk		off = 0;
9153352Sphk		totlen += mlen;
9163352Sphk		if (len == 0)
9173352Sphk			break;
91872356Sbmilekic		if (m->m_next == NULL) {
919111119Simp			n = m_get(M_DONTWAIT, m->m_type);
92072356Sbmilekic			if (n == NULL)
9213352Sphk				break;
9223352Sphk			n->m_len = min(MLEN, len);
9233352Sphk			m->m_next = n;
9243352Sphk		}
9253352Sphk		m = m->m_next;
9263352Sphk	}
9273352Sphkout:	if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
9283352Sphk		m->m_pkthdr.len = totlen;
9293352Sphk}
93052756Sphk
931123557Sbms/*
932123557Sbms * Apply function f to the data in an mbuf chain starting "off" bytes from
933123557Sbms * the beginning, continuing for "len" bytes.
934123557Sbms */
935123557Sbmsint
936123557Sbmsm_apply(struct mbuf *m, int off, int len,
937123564Sbms    int (*f)(void *, void *, u_int), void *arg)
938123557Sbms{
939123564Sbms	u_int count;
940123557Sbms	int rval;
941123557Sbms
942123557Sbms	KASSERT(off >= 0, ("m_apply, negative off %d", off));
943123557Sbms	KASSERT(len >= 0, ("m_apply, negative len %d", len));
944123557Sbms	while (off > 0) {
945123557Sbms		KASSERT(m != NULL, ("m_apply, offset > size of mbuf chain"));
946123557Sbms		if (off < m->m_len)
947123557Sbms			break;
948123557Sbms		off -= m->m_len;
949123557Sbms		m = m->m_next;
950123557Sbms	}
951123557Sbms	while (len > 0) {
952123557Sbms		KASSERT(m != NULL, ("m_apply, offset > size of mbuf chain"));
953123557Sbms		count = min(m->m_len - off, len);
954123557Sbms		rval = (*f)(arg, mtod(m, caddr_t) + off, count);
955123557Sbms		if (rval)
956123557Sbms			return (rval);
957123557Sbms		len -= count;
958123557Sbms		off = 0;
959123557Sbms		m = m->m_next;
960123557Sbms	}
961123557Sbms	return (0);
962123557Sbms}
963123557Sbms
964123557Sbms/*
965123557Sbms * Return a pointer to mbuf/offset of location in mbuf chain.
966123557Sbms */
967123557Sbmsstruct mbuf *
968123557Sbmsm_getptr(struct mbuf *m, int loc, int *off)
969123557Sbms{
970123557Sbms
971123557Sbms	while (loc >= 0) {
972123564Sbms		/* Normal end of search. */
973123557Sbms		if (m->m_len > loc) {
974123557Sbms			*off = loc;
975123557Sbms			return (m);
976123557Sbms		} else {
977123557Sbms			loc -= m->m_len;
978123557Sbms			if (m->m_next == NULL) {
979123557Sbms				if (loc == 0) {
980123564Sbms					/* Point at the end of valid data. */
981123557Sbms					*off = m->m_len;
982123557Sbms					return (m);
983123564Sbms				}
984123564Sbms				return (NULL);
985123564Sbms			}
986123564Sbms			m = m->m_next;
987123557Sbms		}
988123557Sbms	}
989123557Sbms	return (NULL);
990123557Sbms}
991123557Sbms
99252756Sphkvoid
99352756Sphkm_print(const struct mbuf *m)
99452756Sphk{
99552756Sphk	int len;
99654906Seivind	const struct mbuf *m2;
99752756Sphk
99852756Sphk	len = m->m_pkthdr.len;
99952756Sphk	m2 = m;
100052756Sphk	while (len) {
100152756Sphk		printf("%p %*D\n", m2, m2->m_len, (u_char *)m2->m_data, "-");
100252756Sphk		len -= m2->m_len;
100352756Sphk		m2 = m2->m_next;
100452756Sphk	}
100552756Sphk	return;
100652756Sphk}
1007103540Sphk
1008103569Sbmilekicu_int
1009103540Sphkm_fixhdr(struct mbuf *m0)
1010103540Sphk{
1011103569Sbmilekic	u_int len;
1012103540Sphk
1013103544Sphk	len = m_length(m0, NULL);
1014103544Sphk	m0->m_pkthdr.len = len;
1015103544Sphk	return (len);
1016103544Sphk}
1017103544Sphk
1018103569Sbmilekicu_int
1019103544Sphkm_length(struct mbuf *m0, struct mbuf **last)
1020103544Sphk{
1021103544Sphk	struct mbuf *m;
1022103569Sbmilekic	u_int len;
1023103544Sphk
1024103544Sphk	len = 0;
1025103544Sphk	for (m = m0; m != NULL; m = m->m_next) {
1026103540Sphk		len += m->m_len;
1027103544Sphk		if (m->m_next == NULL)
1028103544Sphk			break;
1029103540Sphk	}
1030103544Sphk	if (last != NULL)
1031103544Sphk		*last = m;
1032103544Sphk	return (len);
1033103540Sphk}
1034112777Ssilby
1035112777Ssilby/*
1036112777Ssilby * Defragment a mbuf chain, returning the shortest possible
1037112777Ssilby * chain of mbufs and clusters.  If allocation fails and
1038112777Ssilby * this cannot be completed, NULL will be returned, but
1039112777Ssilby * the passed in chain will be unchanged.  Upon success,
1040112777Ssilby * the original chain will be freed, and the new chain
1041112777Ssilby * will be returned.
1042112777Ssilby *
1043112777Ssilby * If a non-packet header is passed in, the original
1044112777Ssilby * mbuf (chain?) will be returned unharmed.
1045112777Ssilby */
1046112777Ssilbystruct mbuf *
1047112777Ssilbym_defrag(struct mbuf *m0, int how)
1048112777Ssilby{
1049125472Ssilby	struct mbuf *m_new = NULL, *m_final = NULL;
1050125472Ssilby	int progress = 0, length;
1051112777Ssilby
1052112777Ssilby	if (!(m0->m_flags & M_PKTHDR))
1053112777Ssilby		return (m0);
1054112777Ssilby
1055117770Ssilby	m_fixhdr(m0); /* Needed sanity check */
1056117770Ssilby
1057113490Ssilby#ifdef MBUF_STRESS_TEST
1058113490Ssilby	if (m_defragrandomfailures) {
1059113490Ssilby		int temp = arc4random() & 0xff;
1060113490Ssilby		if (temp == 0xba)
1061113490Ssilby			goto nospace;
1062113490Ssilby	}
1063113490Ssilby#endif
1064112777Ssilby
1065112777Ssilby	if (m0->m_pkthdr.len > MHLEN)
1066112777Ssilby		m_final = m_getcl(how, MT_DATA, M_PKTHDR);
1067112777Ssilby	else
1068112777Ssilby		m_final = m_gethdr(how, MT_DATA);
1069112777Ssilby
1070112777Ssilby	if (m_final == NULL)
1071112777Ssilby		goto nospace;
1072112777Ssilby
1073123740Speter	if (m_dup_pkthdr(m_final, m0, how) == 0)
1074112777Ssilby		goto nospace;
1075112777Ssilby
1076112777Ssilby	m_new = m_final;
1077112777Ssilby
1078112777Ssilby	while (progress < m0->m_pkthdr.len) {
1079112777Ssilby		length = m0->m_pkthdr.len - progress;
1080112777Ssilby		if (length > MCLBYTES)
1081112777Ssilby			length = MCLBYTES;
1082112777Ssilby
1083112777Ssilby		if (m_new == NULL) {
1084112777Ssilby			if (length > MLEN)
1085112777Ssilby				m_new = m_getcl(how, MT_DATA, 0);
1086112777Ssilby			else
1087112777Ssilby				m_new = m_get(how, MT_DATA);
1088112777Ssilby			if (m_new == NULL)
1089112777Ssilby				goto nospace;
1090112777Ssilby		}
1091112777Ssilby
1092112777Ssilby		m_copydata(m0, progress, length, mtod(m_new, caddr_t));
1093112777Ssilby		progress += length;
1094112777Ssilby		m_new->m_len = length;
1095112777Ssilby		if (m_new != m_final)
1096112777Ssilby			m_cat(m_final, m_new);
1097112777Ssilby		m_new = NULL;
1098112777Ssilby	}
1099116455Ssilby#ifdef MBUF_STRESS_TEST
1100112777Ssilby	if (m0->m_next == NULL)
1101112777Ssilby		m_defraguseless++;
1102116455Ssilby#endif
1103112777Ssilby	m_freem(m0);
1104112777Ssilby	m0 = m_final;
1105116455Ssilby#ifdef MBUF_STRESS_TEST
1106112777Ssilby	m_defragpackets++;
1107112777Ssilby	m_defragbytes += m0->m_pkthdr.len;
1108116455Ssilby#endif
1109112777Ssilby	return (m0);
1110112777Ssilbynospace:
1111116455Ssilby#ifdef MBUF_STRESS_TEST
1112112777Ssilby	m_defragfailure++;
1113116455Ssilby#endif
1114112777Ssilby	if (m_new)
1115112777Ssilby		m_free(m_new);
1116112777Ssilby	if (m_final)
1117112777Ssilby		m_freem(m_final);
1118112777Ssilby	return (NULL);
1119112777Ssilby}
1120119644Ssilby
1121119644Ssilby#ifdef MBUF_STRESS_TEST
1122119644Ssilby
1123119644Ssilby/*
1124119644Ssilby * Fragment an mbuf chain.  There's no reason you'd ever want to do
1125119644Ssilby * this in normal usage, but it's great for stress testing various
1126119644Ssilby * mbuf consumers.
1127119644Ssilby *
1128119644Ssilby * If fragmentation is not possible, the original chain will be
1129119644Ssilby * returned.
1130119644Ssilby *
1131119644Ssilby * Possible length values:
1132119644Ssilby * 0	 no fragmentation will occur
1133119644Ssilby * > 0	each fragment will be of the specified length
1134119644Ssilby * -1	each fragment will be the same random value in length
1135119644Ssilby * -2	each fragment's length will be entirely random
1136119644Ssilby * (Random values range from 1 to 256)
1137119644Ssilby */
1138119644Ssilbystruct mbuf *
1139119644Ssilbym_fragment(struct mbuf *m0, int how, int length)
1140119644Ssilby{
1141125472Ssilby	struct mbuf *m_new = NULL, *m_final = NULL;
1142125472Ssilby	int progress = 0;
1143119644Ssilby
1144119644Ssilby	if (!(m0->m_flags & M_PKTHDR))
1145119644Ssilby		return (m0);
1146119644Ssilby
1147119644Ssilby	if ((length == 0) || (length < -2))
1148119644Ssilby		return (m0);
1149119644Ssilby
1150119644Ssilby	m_fixhdr(m0); /* Needed sanity check */
1151119644Ssilby
1152119644Ssilby	m_final = m_getcl(how, MT_DATA, M_PKTHDR);
1153119644Ssilby
1154119644Ssilby	if (m_final == NULL)
1155119644Ssilby		goto nospace;
1156119644Ssilby
1157123823Ssilby	if (m_dup_pkthdr(m_final, m0, how) == 0)
1158119644Ssilby		goto nospace;
1159119644Ssilby
1160119644Ssilby	m_new = m_final;
1161119644Ssilby
1162119644Ssilby	if (length == -1)
1163119644Ssilby		length = 1 + (arc4random() & 255);
1164119644Ssilby
1165119644Ssilby	while (progress < m0->m_pkthdr.len) {
1166119644Ssilby		int fraglen;
1167119644Ssilby
1168119644Ssilby		if (length > 0)
1169119644Ssilby			fraglen = length;
1170119644Ssilby		else
1171119644Ssilby			fraglen = 1 + (arc4random() & 255);
1172119644Ssilby		if (fraglen > m0->m_pkthdr.len - progress)
1173119644Ssilby			fraglen = m0->m_pkthdr.len - progress;
1174119644Ssilby
1175119644Ssilby		if (fraglen > MCLBYTES)
1176119644Ssilby			fraglen = MCLBYTES;
1177119644Ssilby
1178119644Ssilby		if (m_new == NULL) {
1179119644Ssilby			m_new = m_getcl(how, MT_DATA, 0);
1180119644Ssilby			if (m_new == NULL)
1181119644Ssilby				goto nospace;
1182119644Ssilby		}
1183119644Ssilby
1184119644Ssilby		m_copydata(m0, progress, fraglen, mtod(m_new, caddr_t));
1185119644Ssilby		progress += fraglen;
1186119644Ssilby		m_new->m_len = fraglen;
1187119644Ssilby		if (m_new != m_final)
1188119644Ssilby			m_cat(m_final, m_new);
1189119644Ssilby		m_new = NULL;
1190119644Ssilby	}
1191119644Ssilby	m_freem(m0);
1192119644Ssilby	m0 = m_final;
1193119644Ssilby	return (m0);
1194119644Ssilbynospace:
1195119644Ssilby	if (m_new)
1196119644Ssilby		m_free(m_new);
1197119644Ssilby	if (m_final)
1198119644Ssilby		m_freem(m_final);
1199119644Ssilby	/* Return the original chain on failure */
1200119644Ssilby	return (m0);
1201119644Ssilby}
1202119644Ssilby
1203119644Ssilby#endif
1204125296Ssilby
1205125296Ssilbystruct mbuf *
1206125296Ssilbym_uiotombuf(struct uio *uio, int how, int len)
1207125296Ssilby{
1208125472Ssilby	struct mbuf *m_new = NULL, *m_final = NULL;
1209125472Ssilby	int progress = 0, error = 0, length, total;
1210125296Ssilby
1211125296Ssilby	if (len > 0)
1212125296Ssilby		total = min(uio->uio_resid, len);
1213125296Ssilby	else
1214125296Ssilby		total = uio->uio_resid;
1215125296Ssilby	if (total > MHLEN)
1216125296Ssilby		m_final = m_getcl(how, MT_DATA, M_PKTHDR);
1217125296Ssilby	else
1218125296Ssilby		m_final = m_gethdr(how, MT_DATA);
1219125296Ssilby	if (m_final == NULL)
1220125296Ssilby		goto nospace;
1221125296Ssilby	m_new = m_final;
1222125296Ssilby	while (progress < total) {
1223125296Ssilby		length = total - progress;
1224125296Ssilby		if (length > MCLBYTES)
1225125296Ssilby			length = MCLBYTES;
1226125296Ssilby		if (m_new == NULL) {
1227125296Ssilby			if (length > MLEN)
1228125296Ssilby				m_new = m_getcl(how, MT_DATA, 0);
1229125296Ssilby			else
1230125296Ssilby				m_new = m_get(how, MT_DATA);
1231125296Ssilby			if (m_new == NULL)
1232125296Ssilby				goto nospace;
1233125296Ssilby		}
1234125296Ssilby		error = uiomove(mtod(m_new, void *), length, uio);
1235125296Ssilby		if (error)
1236125296Ssilby			goto nospace;
1237125296Ssilby		progress += length;
1238125296Ssilby		m_new->m_len = length;
1239125296Ssilby		if (m_new != m_final)
1240125296Ssilby			m_cat(m_final, m_new);
1241125296Ssilby		m_new = NULL;
1242125296Ssilby	}
1243125296Ssilby	m_fixhdr(m_final);
1244125296Ssilby	return (m_final);
1245125296Ssilbynospace:
1246125296Ssilby	if (m_new)
1247125296Ssilby		m_free(m_new);
1248125296Ssilby	if (m_final)
1249125296Ssilby		m_freem(m_final);
1250125296Ssilby	return (NULL);
1251125296Ssilby}
1252