mbuf.h revision 59382
1193323Sed/*
2193323Sed * Copyright (c) 1982, 1986, 1988, 1993
3193323Sed *	The Regents of the University of California.  All rights reserved.
4193323Sed *
5193323Sed * Redistribution and use in source and binary forms, with or without
6193323Sed * modification, are permitted provided that the following conditions
7193323Sed * are met:
8193323Sed * 1. Redistributions of source code must retain the above copyright
9193323Sed *    notice, this list of conditions and the following disclaimer.
10193323Sed * 2. Redistributions in binary form must reproduce the above copyright
11193323Sed *    notice, this list of conditions and the following disclaimer in the
12193323Sed *    documentation and/or other materials provided with the distribution.
13193323Sed * 3. All advertising materials mentioning features or use of this software
14193323Sed *    must display the following acknowledgement:
15193323Sed *	This product includes software developed by the University of
16198090Srdivacky *	California, Berkeley and its contributors.
17198090Srdivacky * 4. Neither the name of the University nor the names of its contributors
18193323Sed *    may be used to endorse or promote products derived from this software
19193323Sed *    without specific prior written permission.
20193323Sed *
21198090Srdivacky * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22218893Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23193323Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24193323Sed * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25198090Srdivacky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26193323Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27198090Srdivacky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28198090Srdivacky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29218893Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30218893Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31193323Sed * SUCH DAMAGE.
32223017Sdim *
33193323Sed *	@(#)mbuf.h	8.5 (Berkeley) 2/19/95
34193323Sed * $FreeBSD: head/sys/sys/mbuf.h 59382 2000-04-19 01:24:26Z peter $
35193323Sed */
36193323Sed
37193323Sed#ifndef _SYS_MBUF_H_
38193323Sed#define	_SYS_MBUF_H_
39193323Sed
40203954Srdivacky/*
41203954Srdivacky * Mbufs are of a single size, MSIZE (machine/param.h), which
42203954Srdivacky * includes overhead.  An mbuf may add a single "mbuf cluster" of size
43203954Srdivacky * MCLBYTES (also in machine/param.h), which has no additional overhead
44203954Srdivacky * and is used instead of the internal data area; this is done when
45203954Srdivacky * at least MINCLSIZE of data must be stored.
46223017Sdim */
47218893Sdim
48218893Sdim#define	MLEN		(MSIZE - sizeof(struct m_hdr))	/* normal data len */
49218893Sdim#define	MHLEN		(MLEN - sizeof(struct pkthdr))	/* data len w/pkthdr */
50218893Sdim
51218893Sdim#define	MINCLSIZE	(MHLEN + 1)	/* smallest amount to put in cluster */
52218893Sdim#define	M_MAXCOMPRESS	(MHLEN / 2)	/* max amount to copy for compression */
53223017Sdim
54203954Srdivacky/*
55198090Srdivacky * Macros for type conversion
56193323Sed * mtod(m, t) -	convert mbuf pointer to data pointer of correct type
57203954Srdivacky * dtom(x) -	convert data pointer within mbuf to mbuf pointer (XXX)
58198090Srdivacky * mtocl(x) -	convert pointer within cluster to cluster index #
59218893Sdim * cltom(x) -	convert cluster # to ptr to beginning of cluster
60218893Sdim */
61218893Sdim#define	mtod(m, t)	((t)((m)->m_data))
62198892Srdivacky#define	dtom(x)		((struct mbuf *)((intptr_t)(x) & ~(MSIZE-1)))
63193323Sed#define	mtocl(x)	(((uintptr_t)(x) - (uintptr_t)mbutl) >> MCLSHIFT)
64193323Sed#define	cltom(x)	((caddr_t)((uintptr_t)mbutl + \
65203954Srdivacky			    ((uintptr_t)(x) << MCLSHIFT)))
66203954Srdivacky
67193323Sed/* header at beginning of each mbuf: */
68193323Sedstruct m_hdr {
69193323Sed	struct	mbuf *mh_next;		/* next buffer in chain */
70193323Sed	struct	mbuf *mh_nextpkt;	/* next chain in queue/record */
71193323Sed	caddr_t	mh_data;		/* location of data */
72193323Sed	int	mh_len;			/* amount of data in this mbuf */
73193323Sed	short	mh_type;		/* type of data in this mbuf */
74193323Sed	short	mh_flags;		/* flags; see below */
75218893Sdim};
76218893Sdim
77221345Sdim/* record/packet header in first mbuf of chain; valid if M_PKTHDR set */
78221345Sdimstruct pkthdr {
79221345Sdim	struct	ifnet *rcvif;		/* rcv interface */
80221345Sdim	int	len;			/* total packet length */
81218893Sdim	/* variables for ip and tcp reassembly */
82218893Sdim	caddr_t	header;			/* pointer to packet header */
83218893Sdim	/* variables for hardware checksum */
84218893Sdim	int	csum_flags;		/* flags regarding checksum */
85206083Srdivacky	int	csum_data;		/* data field used by csum routines */
86218893Sdim};
87218893Sdim
88206083Srdivacky/* description of external storage mapped into mbuf, valid if M_EXT set */
89206083Srdivackystruct m_ext {
90206083Srdivacky	caddr_t	ext_buf;		/* start of buffer */
91206083Srdivacky	void	(*ext_free)		/* free routine if not the usual */
92206083Srdivacky		__P((caddr_t, u_int));
93218893Sdim	u_int	ext_size;		/* size of buffer, for ext_free */
94218893Sdim	void	(*ext_ref)		/* add a reference to the ext object */
95206083Srdivacky		__P((caddr_t, u_int));
96206083Srdivacky};
97206083Srdivacky
98206083Srdivackystruct mbuf {
99206083Srdivacky	struct	m_hdr m_hdr;
100206083Srdivacky	union {
101206083Srdivacky		struct {
102206083Srdivacky			struct	pkthdr MH_pkthdr;	/* M_PKTHDR set */
103206083Srdivacky			union {
104206083Srdivacky				struct	m_ext MH_ext;	/* M_EXT set */
105206083Srdivacky				char	MH_databuf[MHLEN];
106206083Srdivacky			} MH_dat;
107206083Srdivacky		} MH;
108206083Srdivacky		char	M_databuf[MLEN];		/* !M_PKTHDR, !M_EXT */
109206083Srdivacky	} M_dat;
110206083Srdivacky};
111206083Srdivacky#define	m_next		m_hdr.mh_next
112206083Srdivacky#define	m_len		m_hdr.mh_len
113206083Srdivacky#define	m_data		m_hdr.mh_data
114206083Srdivacky#define	m_type		m_hdr.mh_type
115206083Srdivacky#define	m_flags		m_hdr.mh_flags
116218893Sdim#define	m_nextpkt	m_hdr.mh_nextpkt
117206083Srdivacky#define	m_act		m_nextpkt
118193323Sed#define	m_pkthdr	M_dat.MH.MH_pkthdr
119193323Sed#define	m_ext		M_dat.MH.MH_dat.MH_ext
120203954Srdivacky#define	m_pktdat	M_dat.MH.MH_dat.MH_databuf
121218893Sdim#define	m_dat		M_dat.M_databuf
122193323Sed
123203954Srdivacky/* mbuf flags */
124203954Srdivacky#define	M_EXT		0x0001	/* has associated external storage */
125193323Sed#define	M_PKTHDR	0x0002	/* start of record */
126203954Srdivacky#define	M_EOR		0x0004	/* end of record */
127203954Srdivacky#define	M_PROTO1	0x0008	/* protocol-specific */
128193323Sed#define	M_PROTO2	0x0010	/* protocol-specific */
129193323Sed#define	M_PROTO3	0x0020	/* protocol-specific */
130203954Srdivacky#define	M_PROTO4	0x0040	/* protocol-specific */
131193323Sed#define	M_PROTO5	0x0080	/* protocol-specific */
132193323Sed
133193323Sed/* mbuf pkthdr flags, also in m_flags */
134193323Sed#define	M_BCAST		0x0100	/* send/received as link-level broadcast */
135203954Srdivacky#define	M_MCAST		0x0200	/* send/received as link-level multicast */
136193323Sed#define	M_FRAG		0x0400	/* packet is a fragment of a larger packet */
137193323Sed#define	M_FIRSTFRAG	0x0800	/* packet is first fragment */
138193323Sed#define	M_LASTFRAG	0x1000	/* packet is last fragment */
139193323Sed
140193323Sed/* flags copied when copying m_pkthdr */
141193323Sed#define	M_COPYFLAGS	(M_PKTHDR|M_EOR|M_PROTO1|M_PROTO1|M_PROTO2|M_PROTO3 | \
142218893Sdim			    M_PROTO4|M_PROTO5|M_BCAST|M_MCAST|M_FRAG)
143218893Sdim
144198892Srdivacky/* flags indicating hw checksum support and sw checksum requirements */
145198090Srdivacky#define CSUM_IP			0x0001		/* will csum IP */
146218893Sdim#define CSUM_TCP		0x0002		/* will csum TCP */
147218893Sdim#define CSUM_UDP		0x0004		/* will csum UDP */
148218893Sdim#define CSUM_IP_FRAGS		0x0008		/* will csum IP fragments */
149198090Srdivacky#define CSUM_FRAGMENT		0x0010		/* will do IP fragmentation */
150198090Srdivacky
151198090Srdivacky#define CSUM_IP_CHECKED		0x0100		/* did csum IP */
152198090Srdivacky#define CSUM_IP_VALID		0x0200		/*   ... the csum is valid */
153198090Srdivacky#define CSUM_DATA_VALID		0x0400		/* csum_data field is valid */
154198090Srdivacky#define CSUM_PSEUDO_HDR		0x0800		/* csum_data has pseudo hdr */
155198090Srdivacky
156198090Srdivacky#define CSUM_DELAY_DATA		(CSUM_TCP | CSUM_UDP)
157198090Srdivacky#define CSUM_DELAY_IP		(CSUM_IP)	/* XXX add ipv6 here too? */
158198090Srdivacky
159198090Srdivacky/* mbuf types */
160193323Sed#define	MT_FREE		0	/* should be on free list */
161193323Sed#define	MT_DATA		1	/* dynamic (data) allocation */
162193323Sed#define	MT_HEADER	2	/* packet header */
163218893Sdim#if 0
164198090Srdivacky#define	MT_SOCKET	3	/* socket structure */
165198892Srdivacky#define	MT_PCB		4	/* protocol control block */
166193323Sed#define	MT_RTABLE	5	/* routing tables */
167193323Sed#define	MT_HTABLE	6	/* IMP host tables */
168218893Sdim#define	MT_ATABLE	7	/* address resolution tables */
169218893Sdim#endif
170198090Srdivacky#define	MT_SONAME	8	/* socket name */
171198090Srdivacky#if 0
172198090Srdivacky#define	MT_SOOPTS	10	/* socket options */
173193323Sed#endif
174193323Sed#define	MT_FTABLE	11	/* fragment reassembly header */
175193323Sed#if 0
176193323Sed#define	MT_RIGHTS	12	/* access rights */
177193323Sed#define	MT_IFADDR	13	/* interface address */
178193323Sed#endif
179193323Sed#define	MT_CONTROL	14	/* extra-data protocol message */
180218893Sdim#define	MT_OOBDATA	15	/* expedited data  */
181198090Srdivacky
182198090Srdivacky/*
183193323Sed * mbuf statistics
184193323Sed */
185193323Sedstruct mbstat {
186193323Sed	u_long	m_mbufs;	/* mbufs obtained from page pool */
187218893Sdim	u_long	m_clusters;	/* clusters obtained from page pool */
188218893Sdim	u_long	m_spare;	/* spare field */
189198090Srdivacky	u_long	m_clfree;	/* free clusters */
190218893Sdim	u_long	m_drops;	/* times failed to find space */
191218893Sdim	u_long	m_wait;		/* times waited for space */
192198090Srdivacky	u_long	m_drain;	/* times drained protocols for space */
193193323Sed	u_short	m_mtypes[256];	/* type specific mbuf allocations */
194193323Sed	u_long	m_mcfail;	/* times m_copym failed */
195193323Sed	u_long	m_mpfail;	/* times m_pullup failed */
196193323Sed	u_long	m_msize;	/* length of an mbuf */
197193323Sed	u_long	m_mclbytes;	/* length of an mbuf cluster */
198198892Srdivacky	u_long	m_minclsize;	/* min length of data to allocate a cluster */
199198090Srdivacky	u_long	m_mlen;		/* length of data in an mbuf */
200193323Sed	u_long	m_mhlen;	/* length of data in a header mbuf */
201193323Sed};
202218893Sdim
203198090Srdivacky/* flags to m_get/MGET */
204218893Sdim#define	M_DONTWAIT	1
205198892Srdivacky#define	M_WAIT		0
206193323Sed
207193323Sed/* Freelists:
208198090Srdivacky *
209198090Srdivacky * Normal mbuf clusters are normally treated as character arrays
210193323Sed * after allocation, but use the first word of the buffer as a free list
211218893Sdim * pointer while on the free list.
212218893Sdim */
213198090Srdivackyunion mcluster {
214198090Srdivacky	union	mcluster *mcl_next;
215198090Srdivacky	char	mcl_buf[MCLBYTES];
216193323Sed};
217193323Sed
218193323Sed
219193323Sed/*
220193323Sed * These are identifying numbers passed to the m_mballoc_wait function,
221193323Sed * allowing us to determine whether the call came from an MGETHDR or
222193323Sed * an MGET.
223193323Sed */
224218893Sdim#define	MGETHDR_C      1
225198892Srdivacky#define	MGET_C         2
226198892Srdivacky
227198090Srdivacky/*
228193323Sed * Wake up the next instance (if any) of m_mballoc_wait() which is
229193323Sed * waiting for an mbuf to be freed.  This should be called at splimp().
230193323Sed *
231193323Sed * XXX: If there is another free mbuf, this routine will be called [again]
232193323Sed * from the m_mballoc_wait routine in order to wake another sleep instance.
233193323Sed */
234198090Srdivacky#define	MMBWAKEUP() do {						\
235198892Srdivacky	if (m_mballoc_wid) {						\
236198090Srdivacky		m_mballoc_wid--;					\
237198090Srdivacky		wakeup_one(&m_mballoc_wid); 				\
238218893Sdim	}								\
239218893Sdim} while (0)
240193323Sed
241193323Sed/*
242198090Srdivacky * Same as above, but for mbuf cluster(s).
243198090Srdivacky */
244198090Srdivacky#define	MCLWAKEUP() do {						\
245193323Sed	if (m_clalloc_wid) {						\
246193323Sed		m_clalloc_wid--;					\
247206083Srdivacky		wakeup_one(&m_clalloc_wid);				\
248206083Srdivacky	}								\
249206083Srdivacky} while (0)
250206083Srdivacky
251206083Srdivacky/*
252206083Srdivacky * mbuf utility macros:
253206083Srdivacky *
254206083Srdivacky *	MBUFLOCK(code)
255206083Srdivacky * prevents a section of code from from being interrupted by network
256206083Srdivacky * drivers.
257206083Srdivacky */
258206083Srdivacky#define	MBUFLOCK(code) do {						\
259206083Srdivacky	int _ms = splimp();						\
260206083Srdivacky									\
261206083Srdivacky	{ code }							\
262206083Srdivacky	splx(_ms);							\
263206083Srdivacky} while (0)
264206083Srdivacky
265206083Srdivacky/*
266206083Srdivacky * mbuf allocation/deallocation macros:
267206083Srdivacky *
268206083Srdivacky *	MGET(struct mbuf *m, int how, int type)
269206083Srdivacky * allocates an mbuf and initializes it to contain internal data.
270206083Srdivacky *
271193323Sed *	MGETHDR(struct mbuf *m, int how, int type)
272206083Srdivacky * allocates an mbuf and initializes it to contain a packet header
273193323Sed * and internal data.
274206083Srdivacky */
275198090Srdivacky#define	MGET(m, how, type) do {						\
276193323Sed	struct mbuf *_mm;						\
277193323Sed	int _mhow = (how);						\
278193323Sed	int _mtype = (type);						\
279193323Sed	int _ms = splimp();						\
280206083Srdivacky									\
281202375Srdivacky	if (mmbfree == NULL)						\
282193323Sed		(void)m_mballoc(1, _mhow);				\
283193323Sed	_mm = mmbfree;							\
284193323Sed	if (_mm != NULL) {						\
285193323Sed		mmbfree = _mm->m_next;					\
286206083Srdivacky		mbstat.m_mtypes[MT_FREE]--;				\
287206083Srdivacky		_mm->m_type = _mtype;					\
288193323Sed		mbstat.m_mtypes[_mtype]++;				\
289193323Sed		_mm->m_next = NULL;					\
290193323Sed		_mm->m_nextpkt = NULL;					\
291193323Sed		_mm->m_data = _mm->m_dat;				\
292193323Sed		_mm->m_flags = 0;					\
293206083Srdivacky		(m) = _mm;						\
294193323Sed		splx(_ms);						\
295206083Srdivacky	} else {							\
296193323Sed		splx(_ms);						\
297193323Sed		_mm = m_retry(_mhow, _mtype);				\
298198090Srdivacky		if (_mm == NULL && _mhow == M_WAIT)			\
299198090Srdivacky			(m) = m_mballoc_wait(MGET_C, _mtype);		\
300193323Sed		else							\
301218893Sdim			(m) = _mm;					\
302193323Sed	}								\
303218893Sdim} while (0)
304218893Sdim
305218893Sdim#define	MGETHDR(m, how, type) do {					\
306218893Sdim	struct mbuf *_mm;						\
307218893Sdim	int _mhow = (how);						\
308218893Sdim	int _mtype = (type);						\
309221345Sdim	int _ms = splimp();						\
310218893Sdim									\
311221345Sdim	if (mmbfree == NULL)						\
312221345Sdim		(void)m_mballoc(1, _mhow);				\
313221345Sdim	_mm = mmbfree;							\
314218893Sdim	if (_mm != NULL) {						\
315221345Sdim		mmbfree = _mm->m_next;					\
316221345Sdim		mbstat.m_mtypes[MT_FREE]--;				\
317221345Sdim		_mm->m_type = _mtype;					\
318218893Sdim		mbstat.m_mtypes[_mtype]++;				\
319218893Sdim		_mm->m_next = NULL;					\
320218893Sdim		_mm->m_nextpkt = NULL;					\
321221345Sdim		_mm->m_data = _mm->m_pktdat;				\
322218893Sdim		_mm->m_flags = M_PKTHDR;				\
323218893Sdim		_mm->m_pkthdr.rcvif = NULL;				\
324218893Sdim		_mm->m_pkthdr.csum_flags = 0;				\
325218893Sdim		(m) = _mm;						\
326218893Sdim		splx(_ms);						\
327218893Sdim	} else {							\
328218893Sdim		splx(_ms);						\
329218893Sdim		_mm = m_retryhdr(_mhow, _mtype);			\
330218893Sdim		if (_mm == NULL && _mhow == M_WAIT)			\
331218893Sdim			(m) = m_mballoc_wait(MGETHDR_C, _mtype);	\
332218893Sdim		else							\
333218893Sdim			(m) = _mm;					\
334218893Sdim	}								\
335218893Sdim} while (0)
336193323Sed
337193323Sed/*
338193323Sed * Mbuf cluster macros.
339193323Sed * MCLALLOC(caddr_t p, int how) allocates an mbuf cluster.
340218893Sdim * MCLGET adds such clusters to a normal mbuf;
341218893Sdim * the flag M_EXT is set upon success.
342193323Sed * MCLFREE releases a reference to a cluster allocated by MCLALLOC,
343193323Sed * freeing the cluster if the reference count has reached 0.
344193323Sed */
345193323Sed#define	MCLALLOC(p, how) do {						\
346193323Sed	caddr_t _mp;							\
347193323Sed	int _mhow = (how);						\
348193323Sed	int _ms = splimp();						\
349193323Sed									\
350193323Sed	if (mclfree == NULL)						\
351193323Sed		(void)m_clalloc(1, _mhow);				\
352193323Sed	_mp = (caddr_t)mclfree;						\
353193323Sed	if (_mp != NULL) {						\
354193323Sed		mclrefcnt[mtocl(_mp)]++;				\
355193323Sed		mbstat.m_clfree--;					\
356193323Sed		mclfree = ((union mcluster *)_mp)->mcl_next;		\
357193323Sed		(p) = _mp;						\
358193323Sed		splx(_ms);						\
359193323Sed	} else {							\
360193323Sed		splx(_ms);						\
361193323Sed		if (_mhow == M_WAIT)					\
362193323Sed			(p) = m_clalloc_wait();				\
363193323Sed		else							\
364193323Sed			(p) = NULL;					\
365202375Srdivacky	}								\
366218893Sdim} while (0)
367218893Sdim
368218893Sdim#define	MCLGET(m, how) do {						\
369218893Sdim	struct mbuf *_mm = (m);						\
370218893Sdim									\
371218893Sdim	MCLALLOC(_mm->m_ext.ext_buf, (how));				\
372218893Sdim	if (_mm->m_ext.ext_buf != NULL) {				\
373218893Sdim		_mm->m_data = _mm->m_ext.ext_buf;			\
374218893Sdim		_mm->m_flags |= M_EXT;					\
375218893Sdim		_mm->m_ext.ext_free = NULL;				\
376218893Sdim		_mm->m_ext.ext_ref = NULL;				\
377218893Sdim		_mm->m_ext.ext_size = MCLBYTES;				\
378218893Sdim	}								\
379218893Sdim} while (0)
380206083Srdivacky
381206083Srdivacky#define	MCLFREE1(p) do {						\
382193323Sed	union mcluster *_mp = (union mcluster *)(p);			\
383193323Sed									\
384193323Sed	if (--mclrefcnt[mtocl(_mp)] == 0) {				\
385198090Srdivacky		_mp->mcl_next = mclfree;				\
386206083Srdivacky		mclfree = _mp;						\
387193323Sed		mbstat.m_clfree++;					\
388193323Sed		MCLWAKEUP();						\
389193323Sed	}								\
390193323Sed} while (0)
391193323Sed
392193323Sed#define	MCLFREE(p) MBUFLOCK(						\
393198090Srdivacky	MCLFREE1(p);							\
394206083Srdivacky)
395193323Sed
396193323Sed#define	MEXTFREE1(m) do {						\
397193323Sed		struct mbuf *_mm = (m);					\
398218893Sdim									\
399193323Sed		if (_mm->m_ext.ext_free != NULL)			\
400193323Sed			(*_mm->m_ext.ext_free)(_mm->m_ext.ext_buf,	\
401193323Sed		    	    _mm->m_ext.ext_size);			\
402203954Srdivacky		else							\
403193323Sed			MCLFREE1(_mm->m_ext.ext_buf);			\
404193323Sed} while (0)
405198090Srdivacky
406198090Srdivacky#define	MEXTFREE(m) MBUFLOCK(						\
407203954Srdivacky	MEXTFREE1(m);							\
408198090Srdivacky)
409198090Srdivacky
410198090Srdivacky/*
411198090Srdivacky * MFREE(struct mbuf *m, struct mbuf *n)
412198090Srdivacky * Free a single mbuf and associated external storage.
413198090Srdivacky * Place the successor, if any, in n.
414198090Srdivacky */
415198090Srdivacky#define	MFREE(m, n) MBUFLOCK(						\
416193323Sed	struct mbuf *_mm = (m);						\
417223017Sdim									\
418223017Sdim	mbstat.m_mtypes[_mm->m_type]--;					\
419223017Sdim	if (_mm->m_flags & M_EXT)					\
420223017Sdim		MEXTFREE1(m);						\
421223017Sdim	(n) = _mm->m_next;						\
422223017Sdim	_mm->m_type = MT_FREE;						\
423223017Sdim	mbstat.m_mtypes[MT_FREE]++;					\
424223017Sdim	_mm->m_next = mmbfree;						\
425223017Sdim	mmbfree = _mm;							\
426223017Sdim	MMBWAKEUP();							\
427223017Sdim)
428223017Sdim
429223017Sdim/*
430223017Sdim * Copy mbuf pkthdr from "from" to "to".
431223017Sdim * from must have M_PKTHDR set, and to must be empty.
432223017Sdim */
433223017Sdim#define	M_COPY_PKTHDR(to, from) do {					\
434223017Sdim	struct mbuf *_mfrom = (from);					\
435223017Sdim	struct mbuf *_mto = (to);					\
436223017Sdim									\
437223017Sdim	_mto->m_data = _mto->m_pktdat;					\
438223017Sdim	_mto->m_flags = _mfrom->m_flags & M_COPYFLAGS;			\
439223017Sdim	_mto->m_pkthdr = _mfrom->m_pkthdr;				\
440223017Sdim} while (0)
441223017Sdim
442223017Sdim/*
443223017Sdim * Set the m_data pointer of a newly-allocated mbuf (m_get/MGET) to place
444223017Sdim * an object of the specified size at the end of the mbuf, longword aligned.
445223017Sdim */
446198090Srdivacky#define	M_ALIGN(m, len) do {						\
447193323Sed	(m)->m_data += (MLEN - (len)) & ~(sizeof(long) - 1);		\
448193323Sed} while (0)
449193323Sed
450193323Sed/*
451193323Sed * As above, for mbufs allocated with m_gethdr/MGETHDR
452198090Srdivacky * or initialized by M_COPY_PKTHDR.
453198090Srdivacky */
454198090Srdivacky#define	MH_ALIGN(m, len) do {						\
455198090Srdivacky	(m)->m_data += (MHLEN - (len)) & ~(sizeof(long) - 1);		\
456198090Srdivacky} while (0)
457198090Srdivacky
458198090Srdivacky/*
459198090Srdivacky * Compute the amount of space available
460198090Srdivacky * before the current start of data in an mbuf.
461198090Srdivacky */
462198090Srdivacky#define	M_LEADINGSPACE(m)						\
463198090Srdivacky	((m)->m_flags & M_EXT ?						\
464193323Sed	    /* (m)->m_data - (m)->m_ext.ext_buf */ 0 :			\
465198090Srdivacky	    (m)->m_flags & M_PKTHDR ? (m)->m_data - (m)->m_pktdat :	\
466198090Srdivacky	    (m)->m_data - (m)->m_dat)
467198090Srdivacky
468223017Sdim/*
469223017Sdim * Compute the amount of space available
470223017Sdim * after the end of data in an mbuf.
471223017Sdim */
472223017Sdim#define	M_TRAILINGSPACE(m)						\
473223017Sdim	((m)->m_flags & M_EXT ? (m)->m_ext.ext_buf +			\
474223017Sdim	    (m)->m_ext.ext_size - ((m)->m_data + (m)->m_len) :		\
475223017Sdim	    &(m)->m_dat[MLEN] - ((m)->m_data + (m)->m_len))
476223017Sdim
477223017Sdim/*
478223017Sdim * Arrange to prepend space of size plen to mbuf m.
479223017Sdim * If a new mbuf must be allocated, how specifies whether to wait.
480223017Sdim * If how is M_DONTWAIT and allocation fails, the original mbuf chain
481223017Sdim * is freed and m is set to NULL.
482223017Sdim */
483198090Srdivacky#define	M_PREPEND(m, plen, how) do {					\
484198090Srdivacky	struct mbuf **_mmp = &(m);					\
485193323Sed	struct mbuf *_mm = *_mmp;					\
486198090Srdivacky	int _mplen = (plen);						\
487198090Srdivacky	int __mhow = (how);						\
488198090Srdivacky									\
489198090Srdivacky	if (_mm == NULL) {						\
490203954Srdivacky		MGET(_mm, __mhow, MT_DATA);				\
491198090Srdivacky		if (_mm == NULL)					\
492198090Srdivacky			break;						\
493198090Srdivacky	}								\
494198090Srdivacky	if (M_LEADINGSPACE(_mm) >= _mplen) {				\
495193323Sed		_mm->m_data -= _mplen;					\
496198090Srdivacky		_mm->m_len += _mplen;					\
497198090Srdivacky	} else								\
498198090Srdivacky		_mm = m_prepend(_mm, _mplen, __mhow);			\
499218893Sdim	if (_mm != NULL && _mm->m_flags & M_PKTHDR)			\
500218893Sdim		_mm->m_pkthdr.len += _mplen;				\
501198090Srdivacky	*_mmp = _mm;							\
502193323Sed} while (0)
503193323Sed
504193323Sed/* change mbuf to new type */
505193323Sed#define	MCHTYPE(m, t) do {						\
506193323Sed	struct mbuf *_mm = (m);						\
507193323Sed	int _mt = (t);							\
508193323Sed	int _ms = splimp();						\
509218893Sdim									\
510218893Sdim	mbstat.m_mtypes[_mm->m_type]--;					\
511193323Sed	mbstat.m_mtypes[_mt]++;						\
512193323Sed	splx(_ms);							\
513193323Sed	_mm->m_type = (_mt);						\
514193323Sed} while (0)
515193323Sed
516193323Sed/* length to m_copy to copy all */
517198090Srdivacky#define	M_COPYALL	1000000000
518218893Sdim
519198892Srdivacky/* compatibility with 4.3 */
520193323Sed#define	m_copy(m, o, l)	m_copym((m), (o), (l), M_DONTWAIT)
521193323Sed
522218893Sdim#ifdef _KERNEL
523218893Sdimextern	u_int		 m_clalloc_wid;	/* mbuf cluster wait count */
524193323Sedextern	u_int		 m_mballoc_wid;	/* mbuf wait count */
525193323Sedextern	int		 max_linkhdr;	/* largest link-level header */
526202375Srdivackyextern	int		 max_protohdr;	/* largest protocol header */
527202375Srdivackyextern	int		 max_hdr;	/* largest link+protocol header */
528202375Srdivackyextern	int		 max_datalen;	/* MHLEN - max_hdr */
529202375Srdivackyextern	struct mbstat	 mbstat;
530202375Srdivackyextern	int		 mbuf_wait;	/* mbuf sleep time */
531202375Srdivackyextern	struct mbuf	*mbutl;		/* virtual address of mclusters */
532202375Srdivackyextern	char		*mclrefcnt;	/* cluster reference counts */
533202375Srdivackyextern	union mcluster	*mclfree;
534202375Srdivackyextern	struct mbuf	*mmbfree;
535202375Srdivackyextern	int		 nmbclusters;
536202375Srdivackyextern	int		 nmbufs;
537202375Srdivackyextern	int		 nsfbufs;
538202375Srdivacky
539202375Srdivackyvoid	m_adj __P((struct mbuf *, int));
540202375Srdivackyvoid	m_cat __P((struct mbuf *,struct mbuf *));
541202375Srdivackyint	m_clalloc __P((int, int));
542193323Sedcaddr_t	m_clalloc_wait __P((void));
543218893Sdimvoid	m_copyback __P((struct mbuf *, int, int, caddr_t));
544193323Sedvoid	m_copydata __P((struct mbuf *,int,int,caddr_t));
545193323Sedstruct	mbuf *m_copym __P((struct mbuf *, int, int, int));
546193323Sedstruct	mbuf *m_copypacket __P((struct mbuf *, int));
547193323Sedstruct	mbuf *m_devget __P((char *, int, int, struct ifnet *,
548218893Sdim    void (*copy)(char *, caddr_t, u_int)));
549193323Sedstruct	mbuf *m_dup __P((struct mbuf *, int));
550193323Sedstruct	mbuf *m_free __P((struct mbuf *));
551193323Sedvoid	m_freem __P((struct mbuf *));
552193323Sedstruct	mbuf *m_get __P((int, int));
553193323Sedstruct	mbuf *m_getclr __P((int, int));
554193323Sedstruct	mbuf *m_gethdr __P((int, int));
555193323Sedint	m_mballoc __P((int, int));
556193323Sedstruct	mbuf *m_mballoc_wait __P((int, int));
557193323Sedstruct	mbuf *m_prepend __P((struct mbuf *,int,int));
558193323Sedvoid	m_print __P((const struct mbuf *m));
559193323Sedstruct	mbuf *m_pullup __P((struct mbuf *, int));
560193323Sedstruct	mbuf *m_retry __P((int, int));
561193323Sedstruct	mbuf *m_retryhdr __P((int, int));
562193323Sedstruct	mbuf *m_split __P((struct mbuf *,int,int));
563193323Sed#endif /* _KERNEL */
564193323Sed
565193323Sed#endif /* !_SYS_MBUF_H_ */
566193323Sed