xref: /freebsd/sys/sys/mbuf.h (revision 99e8005137088aafb1350e23b113d69b01b0820f)
1 /*
2  * Copyright (c) 1982, 1986, 1988, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *	@(#)mbuf.h	8.5 (Berkeley) 2/19/95
34  * $FreeBSD$
35  */
36 
37 #ifndef _SYS_MBUF_H_
38 #define	_SYS_MBUF_H_
39 
40 #ifdef _KERNEL
41 #include <sys/condvar.h>	/* XXX */
42 #include <sys/_lock.h>
43 #include <sys/_mutex.h>
44 #endif /* _KERNEL */
45 
46 /*
47  * Mbufs are of a single size, MSIZE (machine/param.h), which
48  * includes overhead.  An mbuf may add a single "mbuf cluster" of size
49  * MCLBYTES (also in machine/param.h), which has no additional overhead
50  * and is used instead of the internal data area; this is done when
51  * at least MINCLSIZE of data must be stored.
52  */
53 
54 #define	MLEN		(MSIZE - sizeof(struct m_hdr))	/* normal data len */
55 #define	MHLEN		(MLEN - sizeof(struct pkthdr))	/* data len w/pkthdr */
56 
57 #define	MINCLSIZE	(MHLEN + 1)	/* smallest amount to put in cluster */
58 #define	M_MAXCOMPRESS	(MHLEN / 2)	/* max amount to copy for compression */
59 
60 /*
61  * Maximum number of allocatable counters for external buffers. This
62  * ensures enough VM address space for the allocation of counters
63  * in the extreme case where all possible external buffers are allocated.
64  *
65  * Note: When new types of external storage are allocated, EXT_COUNTERS
66  * 	 must be tuned accordingly. Practically, this isn't a big deal
67  *	 as each counter is only a word long, so we can fit
68  *	 (PAGE_SIZE / length of word) counters in a single page.
69  *
70  * XXX: Must increase this if using any of if_ti, if_wb, if_sk drivers,
71  *	or any other drivers which may manage their own buffers and
72  *	eventually attach them to mbufs.
73  */
74 #define EXT_COUNTERS (nmbclusters + nsfbufs)
75 
76 #ifdef _KERNEL
77 /*
78  * Macros for type conversion
79  * mtod(m, t)	- convert mbuf pointer to data pointer of correct type
80  * dtom(x)	- convert data pointer within mbuf to mbuf pointer (XXX)
81  */
82 #define	mtod(m, t)	((t)((m)->m_data))
83 #define	dtom(x)		((struct mbuf *)((intptr_t)(x) & ~(MSIZE-1)))
84 #endif /* _KERNEL */
85 
86 /* header at beginning of each mbuf: */
87 struct m_hdr {
88 	struct	mbuf *mh_next;		/* next buffer in chain */
89 	struct	mbuf *mh_nextpkt;	/* next chain in queue/record */
90 	caddr_t	mh_data;		/* location of data */
91 	int	mh_len;			/* amount of data in this mbuf */
92 	short	mh_type;		/* type of data in this mbuf */
93 	short	mh_flags;		/* flags; see below */
94 };
95 
96 /* record/packet header in first mbuf of chain; valid if M_PKTHDR set */
97 struct pkthdr {
98 	struct	ifnet *rcvif;		/* rcv interface */
99 	int	len;			/* total packet length */
100 	/* variables for ip and tcp reassembly */
101 	void	*header;		/* pointer to packet header */
102 	/* variables for hardware checksum */
103 	int	csum_flags;		/* flags regarding checksum */
104 	int	csum_data;		/* data field used by csum routines */
105 	struct	mbuf *aux;		/* extra data buffer; ipsec/others */
106 };
107 
108 /* description of external storage mapped into mbuf, valid if M_EXT set */
109 struct m_ext {
110 	caddr_t	ext_buf;		/* start of buffer */
111 	void	(*ext_free)		/* free routine if not the usual */
112 		    (caddr_t, void *);
113 	void	*ext_args;		/* optional argument pointer */
114 	u_int	ext_size;		/* size of buffer, for ext_free */
115 	union	mext_refcnt *ref_cnt;	/* pointer to ref count info */
116 	int	ext_type;		/* type of external storage */
117 };
118 
119 struct mbuf {
120 	struct	m_hdr m_hdr;
121 	union {
122 		struct {
123 			struct	pkthdr MH_pkthdr;	/* M_PKTHDR set */
124 			union {
125 				struct	m_ext MH_ext;	/* M_EXT set */
126 				char	MH_databuf[MHLEN];
127 			} MH_dat;
128 		} MH;
129 		char	M_databuf[MLEN];		/* !M_PKTHDR, !M_EXT */
130 	} M_dat;
131 };
132 #define	m_next		m_hdr.mh_next
133 #define	m_len		m_hdr.mh_len
134 #define	m_data		m_hdr.mh_data
135 #define	m_type		m_hdr.mh_type
136 #define	m_flags		m_hdr.mh_flags
137 #define	m_nextpkt	m_hdr.mh_nextpkt
138 #define	m_act		m_nextpkt
139 #define	m_pkthdr	M_dat.MH.MH_pkthdr
140 #define	m_ext		M_dat.MH.MH_dat.MH_ext
141 #define	m_pktdat	M_dat.MH.MH_dat.MH_databuf
142 #define	m_dat		M_dat.M_databuf
143 
144 /* mbuf flags */
145 #define	M_EXT		0x0001	/* has associated external storage */
146 #define	M_PKTHDR	0x0002	/* start of record */
147 #define	M_EOR		0x0004	/* end of record */
148 #define M_RDONLY	0x0008	/* associated data is marked read-only */
149 #define	M_PROTO1	0x0010	/* protocol-specific */
150 #define	M_PROTO2	0x0020	/* protocol-specific */
151 #define	M_PROTO3	0x0040	/* protocol-specific */
152 #define	M_PROTO4	0x0080	/* protocol-specific */
153 #define	M_PROTO5	0x0100	/* protocol-specific */
154 
155 /* mbuf pkthdr flags, also in m_flags */
156 #define	M_BCAST		0x0200	/* send/received as link-level broadcast */
157 #define	M_MCAST		0x0400	/* send/received as link-level multicast */
158 #define	M_FRAG		0x0800	/* packet is a fragment of a larger packet */
159 #define	M_FIRSTFRAG	0x1000	/* packet is first fragment */
160 #define	M_LASTFRAG	0x2000	/* packet is last fragment */
161 
162 /* external buffer types: identify ext_buf type */
163 #define	EXT_CLUSTER	1	/* mbuf cluster */
164 #define	EXT_SFBUF	2	/* sendfile(2)'s sf_bufs */
165 #define	EXT_NET_DRV	100	/* custom ext_buf provided by net driver(s) */
166 #define	EXT_MOD_TYPE	200	/* custom module's ext_buf type */
167 
168 /* flags copied when copying m_pkthdr */
169 #define	M_COPYFLAGS	(M_PKTHDR|M_EOR|M_PROTO1|M_PROTO1|M_PROTO2|M_PROTO3 | \
170 			    M_PROTO4|M_PROTO5|M_BCAST|M_MCAST|M_FRAG|M_RDONLY)
171 
172 /* flags indicating hw checksum support and sw checksum requirements */
173 #define CSUM_IP			0x0001		/* will csum IP */
174 #define CSUM_TCP		0x0002		/* will csum TCP */
175 #define CSUM_UDP		0x0004		/* will csum UDP */
176 #define CSUM_IP_FRAGS		0x0008		/* will csum IP fragments */
177 #define CSUM_FRAGMENT		0x0010		/* will do IP fragmentation */
178 
179 #define CSUM_IP_CHECKED		0x0100		/* did csum IP */
180 #define CSUM_IP_VALID		0x0200		/*   ... the csum is valid */
181 #define CSUM_DATA_VALID		0x0400		/* csum_data field is valid */
182 #define CSUM_PSEUDO_HDR		0x0800		/* csum_data has pseudo hdr */
183 
184 #define CSUM_DELAY_DATA		(CSUM_TCP | CSUM_UDP)
185 #define CSUM_DELAY_IP		(CSUM_IP)	/* XXX add ipv6 here too? */
186 
187 /* mbuf types */
188 #define	MT_FREE		0	/* should be on free list */
189 #define	MT_DATA		1	/* dynamic (data) allocation */
190 #define	MT_HEADER	2	/* packet header */
191 #if 0
192 #define	MT_SOCKET	3	/* socket structure */
193 #define	MT_PCB		4	/* protocol control block */
194 #define	MT_RTABLE	5	/* routing tables */
195 #define	MT_HTABLE	6	/* IMP host tables */
196 #define	MT_ATABLE	7	/* address resolution tables */
197 #endif
198 #define	MT_SONAME	8	/* socket name */
199 #if 0
200 #define	MT_SOOPTS	10	/* socket options */
201 #endif
202 #define	MT_FTABLE	11	/* fragment reassembly header */
203 #if 0
204 #define	MT_RIGHTS	12	/* access rights */
205 #define	MT_IFADDR	13	/* interface address */
206 #endif
207 #define	MT_CONTROL	14	/* extra-data protocol message */
208 #define	MT_OOBDATA	15	/* expedited data  */
209 #define	MT_NTYPES	16	/* number of mbuf types for mbtypes[] */
210 
211 /*
212  * mbuf statistics
213  */
214 struct mbstat {
215 	u_long	m_mbufs;	/* # mbufs obtained from page pool */
216 	u_long	m_clusters;	/* # clusters obtained from page pool */
217 	u_long	m_clfree;	/* # clusters on freelist (cache) */
218 	u_long	m_refcnt;	/* # ref counters obtained from page pool */
219 	u_long	m_refree;	/* # ref counters on freelist (cache) */
220 	u_long	m_spare;	/* spare field */
221 	u_long	m_drops;	/* times failed to find space */
222 	u_long	m_wait;		/* times waited for space */
223 	u_long	m_drain;	/* times drained protocols for space */
224 	u_long	m_mcfail;	/* times m_copym failed */
225 	u_long	m_mpfail;	/* times m_pullup failed */
226 	u_long	m_msize;	/* length of an mbuf */
227 	u_long	m_mclbytes;	/* length of an mbuf cluster */
228 	u_long	m_minclsize;	/* min length of data to allocate a cluster */
229 	u_long	m_mlen;		/* length of data in an mbuf */
230 	u_long	m_mhlen;	/* length of data in a header mbuf */
231 };
232 
233 /* flags to m_get/MGET */
234 #define	M_DONTWAIT	1
235 #define	M_TRYWAIT	0
236 #define	M_WAIT		M_TRYWAIT	/* XXX: Deprecated. */
237 
238 /*
239  * Normal mbuf clusters are normally treated as character arrays
240  * after allocation, but use the first word of the buffer as a free list
241  * pointer while on the free list.
242  */
243 union mcluster {
244 	union	mcluster *mcl_next;
245 	char	mcl_buf[MCLBYTES];
246 };
247 
248 /*
249  * The m_ext object reference counter structure.
250  */
251 union mext_refcnt {
252 	union	mext_refcnt *next_ref;
253 	u_int	refcnt;
254 };
255 
256 #ifdef _KERNEL
257 /*
258  * The freelists for mbufs and mbuf clusters include condition variables
259  * that are used in cases of depletion/starvation.
260  * The counter freelist does not require a condition variable as we never
261  * expect to consume more than the reserved address space for counters.
262  * All are presently protected by the mbuf_mtx lock.
263  */
264 struct mbffree_lst {
265 	struct	mbuf *m_head;
266 	struct	cv m_starved;
267 };
268 
269 struct mclfree_lst {
270 	union	mcluster *m_head;
271 	struct	cv m_starved;
272 };
273 
274 struct mcntfree_lst {
275 	union	mext_refcnt *m_head;
276 };
277 
278 /*
279  * Signal a single instance (if any) blocked on a m_starved cv (i.e. an
280  * instance waiting for an {mbuf, cluster} to be freed to the global
281  * cache lists).
282  *
283  * Must be called with mbuf_mtx held.
284  */
285 #define	MBWAKEUP(m_wid, m_cv) do {					\
286 	if ((m_wid) > 0)						\
287 		cv_signal((m_cv));					\
288 } while (0)
289 
290 /*
291  * mbuf external reference count management macros:
292  *
293  * MEXT_IS_REF(m): true if (m) is not the only mbuf referencing
294  *     the external buffer ext_buf
295  * MEXT_REM_REF(m): remove reference to m_ext object
296  * MEXT_ADD_REF(m): add reference to m_ext object already
297  *     referred to by (m)
298  * MEXT_INIT_REF(m): allocate and initialize an external
299  *     object reference counter for (m)
300  */
301 #define MEXT_IS_REF(m) ((m)->m_ext.ref_cnt->refcnt > 1)
302 
303 #define MEXT_REM_REF(m) do {						\
304 	KASSERT((m)->m_ext.ref_cnt->refcnt > 0, ("m_ext refcnt < 0"));	\
305 	atomic_subtract_int(&((m)->m_ext.ref_cnt->refcnt), 1);		\
306 } while(0)
307 
308 #define MEXT_ADD_REF(m) atomic_add_int(&((m)->m_ext.ref_cnt->refcnt), 1)
309 
310 #define _MEXT_ALLOC_CNT(m_cnt, how) do {				\
311 	union mext_refcnt *__mcnt;					\
312 									\
313 	mtx_lock(&mbuf_mtx);						\
314 	if (mcntfree.m_head == NULL)					\
315 		m_alloc_ref(1, (how));					\
316 	__mcnt = mcntfree.m_head;					\
317 	if (__mcnt != NULL) {						\
318 		mcntfree.m_head = __mcnt->next_ref;			\
319 		mbstat.m_refree--;					\
320 		__mcnt->refcnt = 0;					\
321 	}								\
322 	mtx_unlock(&mbuf_mtx);						\
323 	(m_cnt) = __mcnt;						\
324 } while (0)
325 
326 #define _MEXT_DEALLOC_CNT(m_cnt) do {					\
327 	union mext_refcnt *__mcnt = (m_cnt);				\
328 									\
329 	mtx_lock(&mbuf_mtx);						\
330 	__mcnt->next_ref = mcntfree.m_head;				\
331 	mcntfree.m_head = __mcnt;					\
332 	mbstat.m_refree++;						\
333 	mtx_unlock(&mbuf_mtx);						\
334 } while (0)
335 
336 #define MEXT_INIT_REF(m, how) do {					\
337 	struct mbuf *__mmm = (m);					\
338 									\
339 	_MEXT_ALLOC_CNT(__mmm->m_ext.ref_cnt, (how));			\
340 	if (__mmm->m_ext.ref_cnt != NULL)				\
341 		MEXT_ADD_REF(__mmm);					\
342 } while (0)
343 
344 /*
345  * mbuf allocation/deallocation macros:
346  *
347  *	MGET(struct mbuf *m, int how, int type)
348  * allocates an mbuf and initializes it to contain internal data.
349  *
350  *	MGETHDR(struct mbuf *m, int how, int type)
351  * allocates an mbuf and initializes it to contain a packet header
352  * and internal data.
353  */
354 /*
355  * Lower-level macros for MGET(HDR)... Not to be used outside the
356  * subsystem ("non-exportable" macro names are prepended with "_").
357  */
358 #define _MGET_SETUP(m_set, m_set_type) do {				\
359 	(m_set)->m_type = (m_set_type);					\
360 	(m_set)->m_next = NULL;						\
361 	(m_set)->m_nextpkt = NULL;					\
362 	(m_set)->m_data = (m_set)->m_dat;				\
363 	(m_set)->m_flags = 0;						\
364 } while (0)
365 
366 #define	_MGET(m_mget, m_get_how) do {					\
367 	if (mmbfree.m_head == NULL)					\
368 		m_mballoc(1, (m_get_how));				\
369 	(m_mget) = mmbfree.m_head;					\
370 	if ((m_mget) != NULL) {						\
371 		mmbfree.m_head = (m_mget)->m_next;			\
372 		mbtypes[MT_FREE]--;					\
373 	} else {							\
374 		if ((m_get_how) == M_TRYWAIT)				\
375 			(m_mget) = m_mballoc_wait();			\
376 	}								\
377 } while (0)
378 
379 #define MGET(m, how, type) do {						\
380 	struct mbuf *_mm;						\
381 	int _mhow = (how);						\
382 	int _mtype = (type);						\
383 									\
384 	mtx_lock(&mbuf_mtx);						\
385 	_MGET(_mm, _mhow);						\
386 	if (_mm != NULL) {						\
387 		mbtypes[_mtype]++;					\
388 		mtx_unlock(&mbuf_mtx);					\
389 		_MGET_SETUP(_mm, _mtype);				\
390 	} else {							\
391 		mbstat.m_drops++;					\
392 		mtx_unlock(&mbuf_mtx);					\
393 	}								\
394 	(m) = _mm;							\
395 } while (0)
396 
397 #define _MGETHDR_SETUP(m_set, m_set_type) do {				\
398 	(m_set)->m_type = (m_set_type);					\
399 	(m_set)->m_next = NULL;						\
400 	(m_set)->m_nextpkt = NULL;					\
401 	(m_set)->m_data = (m_set)->m_pktdat;				\
402 	(m_set)->m_flags = M_PKTHDR;					\
403 	(m_set)->m_pkthdr.rcvif = NULL;					\
404 	(m_set)->m_pkthdr.csum_flags = 0;				\
405 	(m_set)->m_pkthdr.aux = NULL;					\
406 } while (0)
407 
408 #define MGETHDR(m, how, type) do {					\
409 	struct mbuf *_mm;						\
410 	int _mhow = (how);						\
411 	int _mtype = (type);						\
412 									\
413 	mtx_lock(&mbuf_mtx);						\
414 	_MGET(_mm, _mhow);						\
415 	if (_mm != NULL) {						\
416 		mbtypes[_mtype]++;					\
417 		mtx_unlock(&mbuf_mtx);					\
418 		_MGETHDR_SETUP(_mm, _mtype);				\
419 	} else {							\
420 		mbstat.m_drops++;					\
421 		mtx_unlock(&mbuf_mtx);					\
422 	}								\
423 	(m) = _mm;							\
424 } while (0)
425 
426 /*
427  * mbuf external storage macros:
428  *
429  *   MCLGET allocates and refers an mcluster to an mbuf
430  *   MEXTADD sets up pre-allocated external storage and refers to mbuf
431  *   MEXTFREE removes reference to external object and frees it if
432  *       necessary
433  */
434 #define	_MCLALLOC(p, how) do {						\
435 	caddr_t _mp;							\
436 	int _mhow = (how);						\
437 									\
438 	if (mclfree.m_head == NULL)					\
439 		m_clalloc(1, _mhow);					\
440 	_mp = (caddr_t)mclfree.m_head;					\
441 	if (_mp != NULL) {						\
442 		mbstat.m_clfree--;					\
443 		mclfree.m_head = ((union mcluster *)_mp)->mcl_next;	\
444 	} else {							\
445 		if (_mhow == M_TRYWAIT)					\
446 			_mp = m_clalloc_wait();				\
447 	}								\
448 	(p) = _mp;							\
449 } while (0)
450 
451 #define	MCLGET(m, how) do {						\
452 	struct mbuf *_mm = (m);						\
453 									\
454 	mtx_lock(&mbuf_mtx);						\
455 	_MCLALLOC(_mm->m_ext.ext_buf, (how));				\
456 	if (_mm->m_ext.ext_buf != NULL) {				\
457 		mtx_unlock(&mbuf_mtx);					\
458 		MEXT_INIT_REF(_mm, (how));				\
459 		if (_mm->m_ext.ref_cnt == NULL) {			\
460 			_MCLFREE(_mm->m_ext.ext_buf);			\
461 			_mm->m_ext.ext_buf = NULL;			\
462 		} else {						\
463 			_mm->m_data = _mm->m_ext.ext_buf;		\
464 			_mm->m_flags |= M_EXT;				\
465 			_mm->m_ext.ext_free = NULL;			\
466 			_mm->m_ext.ext_args = NULL;			\
467 			_mm->m_ext.ext_size = MCLBYTES;			\
468 			_mm->m_ext.ext_type = EXT_CLUSTER;		\
469 		}							\
470 	} else {							\
471 		mbstat.m_drops++;					\
472 		mtx_unlock(&mbuf_mtx);					\
473 	}								\
474 } while (0)
475 
476 #define MEXTADD(m, buf, size, free, args, flags, type) do {		\
477 	struct mbuf *_mm = (m);						\
478 									\
479 	MEXT_INIT_REF(_mm, M_TRYWAIT);					\
480 	if (_mm->m_ext.ref_cnt != NULL) {				\
481 		_mm->m_flags |= (M_EXT | (flags));			\
482 		_mm->m_ext.ext_buf = (caddr_t)(buf);			\
483 		_mm->m_data = _mm->m_ext.ext_buf;			\
484 		_mm->m_ext.ext_size = (size);				\
485 		_mm->m_ext.ext_free = (free);				\
486 		_mm->m_ext.ext_args = (args);				\
487 		_mm->m_ext.ext_type = (type);				\
488 	}								\
489 } while (0)
490 
491 #define	_MCLFREE(p) do {						\
492 	union mcluster *_mp = (union mcluster *)(p);			\
493 									\
494 	mtx_lock(&mbuf_mtx);						\
495 	_mp->mcl_next = mclfree.m_head;					\
496 	mclfree.m_head = _mp;						\
497 	mbstat.m_clfree++;						\
498 	MBWAKEUP(m_clalloc_wid, &mclfree.m_starved);			\
499 	mtx_unlock(&mbuf_mtx); 						\
500 } while (0)
501 
502 /* MEXTFREE:
503  * If the atomic_cmpset_int() returns 0, then we effectively do nothing
504  * in terms of "cleaning up" (freeing the ext buf and ref. counter) as
505  * this means that either there are still references, or another thread
506  * is taking care of the clean-up.
507  */
508 #define	MEXTFREE(m) do {						\
509 	struct mbuf *_mmm = (m);					\
510 									\
511 	MEXT_REM_REF(_mmm);						\
512 	if (atomic_cmpset_int(&_mmm->m_ext.ref_cnt->refcnt, 0, 1)) {	\
513 		if (_mmm->m_ext.ext_type != EXT_CLUSTER) {		\
514 			(*(_mmm->m_ext.ext_free))(_mmm->m_ext.ext_buf,	\
515 			    _mmm->m_ext.ext_args);			\
516 		} else							\
517 			_MCLFREE(_mmm->m_ext.ext_buf);			\
518 		_MEXT_DEALLOC_CNT(_mmm->m_ext.ref_cnt);			\
519 	}								\
520 	_mmm->m_flags &= ~M_EXT;					\
521 } while (0)
522 
523 /*
524  * MFREE(struct mbuf *m, struct mbuf *n)
525  * Free a single mbuf and associated external storage.
526  * Place the successor, if any, in n.
527  */
528 #define	MFREE(m, n) do {						\
529 	struct mbuf *_mm = (m);						\
530 									\
531 	KASSERT(_mm->m_type != MT_FREE, ("freeing free mbuf"));		\
532 	if (_mm->m_flags & M_EXT)					\
533 		MEXTFREE(_mm);						\
534 	mtx_lock(&mbuf_mtx);						\
535 	mbtypes[_mm->m_type]--;						\
536 	_mm->m_type = MT_FREE;						\
537 	mbtypes[MT_FREE]++;						\
538 	(n) = _mm->m_next;						\
539 	_mm->m_next = mmbfree.m_head;					\
540 	mmbfree.m_head = _mm;						\
541 	MBWAKEUP(m_mballoc_wid, &mmbfree.m_starved);			\
542 	mtx_unlock(&mbuf_mtx); 						\
543 } while (0)
544 
545 /*
546  * M_WRITABLE(m)
547  * Evaluate TRUE if it's safe to write to the mbuf m's data region (this
548  * can be both the local data payload, or an external buffer area,
549  * depending on whether M_EXT is set).
550  */
551 #define M_WRITABLE(m)	(!((m)->m_flags & M_RDONLY) && (!((m)->m_flags  \
552 			    & M_EXT) || !MEXT_IS_REF(m)))
553 
554 /*
555  * Copy mbuf pkthdr from "from" to "to".
556  * from must have M_PKTHDR set, and to must be empty.
557  * aux pointer will be moved to `to'.
558  */
559 #define	M_COPY_PKTHDR(to, from) do {					\
560 	struct mbuf *_mfrom = (from);					\
561 	struct mbuf *_mto = (to);					\
562 									\
563 	_mto->m_data = _mto->m_pktdat;					\
564 	_mto->m_flags = _mfrom->m_flags & M_COPYFLAGS;			\
565 	_mto->m_pkthdr = _mfrom->m_pkthdr;				\
566 	_mfrom->m_pkthdr.aux = NULL;					\
567 } while (0)
568 
569 /*
570  * Set the m_data pointer of a newly-allocated mbuf (m_get/MGET) to place
571  * an object of the specified size at the end of the mbuf, longword aligned.
572  */
573 #define	M_ALIGN(m, len) do {						\
574 	(m)->m_data += (MLEN - (len)) & ~(sizeof(long) - 1);		\
575 } while (0)
576 
577 /*
578  * As above, for mbufs allocated with m_gethdr/MGETHDR
579  * or initialized by M_COPY_PKTHDR.
580  */
581 #define	MH_ALIGN(m, len) do {						\
582 	(m)->m_data += (MHLEN - (len)) & ~(sizeof(long) - 1);		\
583 } while (0)
584 
585 /*
586  * Compute the amount of space available
587  * before the current start of data in an mbuf.
588  */
589 #define	M_LEADINGSPACE(m)						\
590 	((m)->m_flags & M_EXT ?						\
591 	    /* (m)->m_data - (m)->m_ext.ext_buf */ 0 :			\
592 	    (m)->m_flags & M_PKTHDR ? (m)->m_data - (m)->m_pktdat :	\
593 	    (m)->m_data - (m)->m_dat)
594 
595 /*
596  * Compute the amount of space available
597  * after the end of data in an mbuf.
598  */
599 #define	M_TRAILINGSPACE(m)						\
600 	((m)->m_flags & M_EXT ? (m)->m_ext.ext_buf +			\
601 	    (m)->m_ext.ext_size - ((m)->m_data + (m)->m_len) :		\
602 	    &(m)->m_dat[MLEN] - ((m)->m_data + (m)->m_len))
603 
604 /*
605  * Arrange to prepend space of size plen to mbuf m.
606  * If a new mbuf must be allocated, how specifies whether to wait.
607  * If the allocation fails, the original mbuf chain is freed and m is
608  * set to NULL.
609  */
610 #define	M_PREPEND(m, plen, how) do {					\
611 	struct mbuf **_mmp = &(m);					\
612 	struct mbuf *_mm = *_mmp;					\
613 	int _mplen = (plen);						\
614 	int __mhow = (how);						\
615 									\
616 	if (M_LEADINGSPACE(_mm) >= _mplen) {				\
617 		_mm->m_data -= _mplen;					\
618 		_mm->m_len += _mplen;					\
619 	} else								\
620 		_mm = m_prepend(_mm, _mplen, __mhow);			\
621 	if (_mm != NULL && _mm->m_flags & M_PKTHDR)			\
622 		_mm->m_pkthdr.len += _mplen;				\
623 	*_mmp = _mm;							\
624 } while (0)
625 
626 /*
627  * change mbuf to new type
628  */
629 #define	MCHTYPE(m, t) do {						\
630 	struct mbuf *_mm = (m);						\
631 	int _mt = (t);							\
632 									\
633 	mtx_lock(&mbuf_mtx);						\
634 	mbtypes[_mm->m_type]--;						\
635 	mbtypes[_mt]++;							\
636 	mtx_unlock(&mbuf_mtx);						\
637 	_mm->m_type = (_mt);						\
638 } while (0)
639 
640 /* length to m_copy to copy all */
641 #define	M_COPYALL	1000000000
642 
643 /* compatibility with 4.3 */
644 #define	m_copy(m, o, l)	m_copym((m), (o), (l), M_DONTWAIT)
645 
646 /*
647  * pkthdr.aux type tags.
648  */
649 struct mauxtag {
650 	int	af;
651 	int	type;
652 };
653 
654 extern	u_long		 m_clalloc_wid;	/* mbuf cluster wait count */
655 extern	u_long		 m_mballoc_wid;	/* mbuf wait count */
656 extern	int		 max_datalen;	/* MHLEN - max_hdr */
657 extern	int		 max_hdr;	/* largest link+protocol header */
658 extern	int		 max_linkhdr;	/* largest link-level header */
659 extern	int		 max_protohdr;	/* largest protocol header */
660 extern	struct mbstat	 mbstat;
661 extern	u_long		 mbtypes[MT_NTYPES]; /* per-type mbuf allocations */
662 extern	int		 mbuf_wait;	/* mbuf sleep time */
663 extern	struct mtx	 mbuf_mtx;
664 extern	struct mbuf	*mbutl;		/* virtual address of mclusters */
665 extern	struct mclfree_lst	mclfree;
666 extern	struct mcntfree_lst	mcntfree;
667 extern	struct mbffree_lst	mmbfree;
668 extern	int		 nmbclusters;
669 extern	int		 nmbcnt;
670 extern	int		 nmbufs;
671 extern	int		 nsfbufs;
672 
673 void	m_adj(struct mbuf *, int);
674 int	m_alloc_ref(u_int, int);
675 struct	mbuf *m_aux_add(struct mbuf *, int, int);
676 void	m_aux_delete(struct mbuf *, struct mbuf *);
677 struct	mbuf *m_aux_find(struct mbuf *, int, int);
678 void	m_cat(struct mbuf *, struct mbuf *);
679 int	m_clalloc(int, int);
680 caddr_t	m_clalloc_wait(void);
681 void	m_copyback(struct mbuf *, int, int, caddr_t);
682 void	m_copydata(struct mbuf *, int, int, caddr_t);
683 struct	mbuf *m_copym(struct mbuf *, int, int, int);
684 struct	mbuf *m_copypacket(struct mbuf *, int);
685 struct	mbuf *m_devget(char *, int, int, struct ifnet *,
686     void (*copy)(char *, caddr_t, u_int));
687 struct	mbuf *m_dup(struct mbuf *, int);
688 struct	mbuf *m_free(struct mbuf *);
689 void	m_freem(struct mbuf *);
690 struct	mbuf *m_get(int, int);
691 struct	mbuf *m_getclr(int, int);
692 struct	mbuf *m_gethdr(int, int);
693 struct	mbuf *m_getm(struct mbuf *, int, int, int);
694 int	m_mballoc(int, int);
695 struct	mbuf *m_mballoc_wait(void);
696 struct	mbuf *m_prepend(struct mbuf *, int, int);
697 void	m_print(const struct mbuf *m);
698 struct	mbuf *m_pulldown(struct mbuf *, int, int, int *);
699 struct	mbuf *m_pullup(struct mbuf *, int);
700 struct	mbuf *m_split(struct mbuf *, int, int);
701 #endif /* _KERNEL */
702 
703 #endif /* !_SYS_MBUF_H_ */
704