1 /*	$OpenBSD: mbuf.h,v 1.75 2004/04/25 18:32:43 itojun Exp $	*/
2 /*	$NetBSD: mbuf.h,v 1.19 1996/02/09 18:25:14 christos Exp $	*/
3 
4 /*
5  * Copyright (c) 1982, 1986, 1988, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  *	@(#)mbuf.h	8.5 (Berkeley) 2/19/95
33  */
34 
35 #ifndef _SYS_MALLOC_H_
36 #include <sys/malloc.h>
37 #endif
38 #include <sys/pool.h>
39 #include <sys/queue.h>
40 
41 /*
42  * Mbufs are of a single size, MSIZE (machine/param.h), which
43  * includes overhead.  An mbuf may add a single "mbuf cluster" of size
44  * MCLBYTES (also in machine/param.h), which has no additional overhead
45  * and is used instead of the internal data area; this is done when
46  * at least MINCLSIZE of data must be stored.
47  */
48 
49 #define	MLEN		(MSIZE - sizeof(struct m_hdr))	/* normal data len */
50 #define	MHLEN		(MLEN - sizeof(struct pkthdr))	/* data len w/pkthdr */
51 
52 /* smallest amount to put in cluster */
53 #define	MINCLSIZE	(MHLEN + MLEN + 1)
54 #define	M_MAXCOMPRESS	(MHLEN / 2)	/* max amount to copy for compression */
55 
56 /* Packet tags structure */
57 struct m_tag {
58 	SLIST_ENTRY(m_tag)	m_tag_link;	/* List of packet tags */
59 	u_int16_t		m_tag_id;	/* Tag ID */
60 	u_int16_t		m_tag_len;	/* Length of data */
61 };
62 
63 /*
64  * Macros for type conversion
65  * mtod(m,t) -	convert mbuf pointer to data pointer of correct type
66  */
67 #define	mtod(m,t)	((t)((m)->m_data))
68 
69 /* header at beginning of each mbuf: */
70 struct m_hdr {
71 	struct	mbuf *mh_next;		/* next buffer in chain */
72 	struct	mbuf *mh_nextpkt;	/* next chain in queue/record */
73 	caddr_t	mh_data;		/* location of data */
74 	u_int	mh_len;			/* amount of data in this mbuf */
75 	short	mh_type;		/* type of data in this mbuf */
76 	short	mh_flags;		/* flags; see below */
77 };
78 
79 /* record/packet header in first mbuf of chain; valid if M_PKTHDR set */
80 struct	pkthdr {
81 	struct	ifnet *rcvif;		/* rcv interface */
82 	SLIST_HEAD(packet_tags, m_tag) tags; /* list of packet tags */
83 	int	len;			/* total packet length */
84 	int	csum;			/* Hardware checksum info */
85 };
86 
87 /* description of external storage mapped into mbuf, valid if M_EXT set */
88 struct m_ext {
89 	caddr_t	ext_buf;		/* start of buffer */
90 					/* free routine if not the usual */
91 	void	(*ext_free)(caddr_t, u_int, void *);
92 	void	*ext_arg;		/* argument for ext_free */
93 	u_int	ext_size;		/* size of buffer, for ext_free */
94 	int	ext_type;
95 	struct mbuf *ext_nextref;
96 	struct mbuf *ext_prevref;
97 #ifdef DEBUG
98 	const char *ext_ofile;
99 	const char *ext_nfile;
100 	int ext_oline;
101 	int ext_nline;
102 #endif
103 };
104 
105 struct mbuf {
106 	struct	m_hdr m_hdr;
107 	union {
108 		struct {
109 			struct	pkthdr MH_pkthdr;	/* M_PKTHDR set */
110 			union {
111 				struct	m_ext MH_ext;	/* M_EXT set */
112 				char	MH_databuf[MHLEN];
113 			} MH_dat;
114 		} MH;
115 		char	M_databuf[MLEN];		/* !M_PKTHDR, !M_EXT */
116 	} M_dat;
117 };
118 #define	m_next		m_hdr.mh_next
119 #define	m_len		m_hdr.mh_len
120 #define	m_data		m_hdr.mh_data
121 #define	m_type		m_hdr.mh_type
122 #define	m_flags		m_hdr.mh_flags
123 #define	m_nextpkt	m_hdr.mh_nextpkt
124 #define	m_act		m_nextpkt
125 #define	m_pkthdr	M_dat.MH.MH_pkthdr
126 #define	m_ext		M_dat.MH.MH_dat.MH_ext
127 #define	m_pktdat	M_dat.MH.MH_dat.MH_databuf
128 #define	m_dat		M_dat.M_databuf
129 
130 /* mbuf flags */
131 #define	M_EXT		0x0001	/* has associated external storage */
132 #define	M_PKTHDR	0x0002	/* start of record */
133 #define	M_EOR		0x0004	/* end of record */
134 #define M_CLUSTER	0x0008	/* external storage is a cluster */
135 #define	M_PROTO1	0x0010	/* protocol-specific */
136 
137 /* mbuf pkthdr flags, also in m_flags */
138 #define	M_BCAST		0x0100	/* send/received as link-level broadcast */
139 #define	M_MCAST		0x0200	/* send/received as link-level multicast */
140 #define M_CONF		0x0400  /* payload was encrypted (ESP-transport) */
141 #define M_AUTH		0x0800  /* payload was authenticated (AH or ESP auth) */
142 #define M_COMP		0x1000  /* payload was compressed (IPCOMP) */
143 #define M_AUTH_AH	0x2000  /* header was authenticated (AH) */
144 #define M_TUNNEL	0x4000  /* IP-in-IP added by tunnel mode IPsec */
145 
146 /* Checksumming flags */
147 #define	M_IPV4_CSUM_OUT		0x0001	/* IPv4 checksum needed */
148 #define M_TCPV4_CSUM_OUT	0x0002	/* TCP checksum needed */
149 #define	M_UDPV4_CSUM_OUT	0x0004	/* UDP checksum needed */
150 #define	M_IPV4_CSUM_IN_OK	0x0008	/* IPv4 checksum verified */
151 #define	M_IPV4_CSUM_IN_BAD	0x0010	/* IPv4 checksum bad */
152 #define	M_TCP_CSUM_IN_OK	0x0020	/* TCP/IPv4 checksum verified */
153 #define	M_TCP_CSUM_IN_BAD	0x0040	/* TCP/IPv4 checksum bad */
154 #define	M_UDP_CSUM_IN_OK	0x0080	/* UDP/IPv4 checksum verified */
155 #define	M_UDP_CSUM_IN_BAD	0x0100	/* UDP/IPv4 checksum bad */
156 
157 /* KAME IPv6 */
158 #define M_ANYCAST6	0x4000	/* received as IPv6 anycast */
159 
160 #define M_LOOP		0x0040	/* for Mbuf statistics */
161 
162 /* flags copied when copying m_pkthdr */
163 #define	M_COPYFLAGS	(M_PKTHDR|M_EOR|M_PROTO1|M_BCAST|M_MCAST|M_CONF|\
164 			 M_AUTH|M_COMP|M_ANYCAST6|M_LOOP|M_TUNNEL)
165 
166 /* mbuf types */
167 #define	MT_FREE		0	/* should be on free list */
168 #define	MT_DATA		1	/* dynamic (data) allocation */
169 #define	MT_HEADER	2	/* packet header */
170 #define	MT_SONAME	3	/* socket name */
171 #define	MT_SOOPTS	4	/* socket options */
172 #define	MT_FTABLE	5	/* fragment reassembly header */
173 #define	MT_CONTROL	6	/* extra-data protocol message */
174 #define	MT_OOBDATA	7	/* expedited data  */
175 
176 /* flags to m_get/MGET */
177 #define	M_DONTWAIT	M_NOWAIT
178 #define	M_WAIT		M_WAITOK
179 
180 /*
181  * mbuf utility macros:
182  *
183  *	MBUFLOCK(code)
184  * prevents a section of code from from being interrupted by network
185  * drivers.
186  */
187 #define	MBUFLOCK(code) \
188 	{ int ms = splimp(); \
189 	  { code } \
190 	  splx(ms); \
191 	}
192 
193 /*
194  * mbuf allocation/deallocation macros:
195  *
196  *	MGET(struct mbuf *m, int how, int type)
197  * allocates an mbuf and initializes it to contain internal data.
198  *
199  *	MGETHDR(struct mbuf *m, int how, int type)
200  * allocates an mbuf and initializes it to contain a packet header
201  * and internal data.
202  */
203 #define	_MGET(m, how, type) do { \
204 	MBUFLOCK( \
205 	    	(m) = pool_get(&mbpool, \
206 		    (how) == M_WAIT ? PR_WAITOK|PR_LIMITFAIL : 0); \
207 	); \
208 	if (m) { \
209 		(m)->m_type = (type); \
210 		MBUFLOCK(mbstat.m_mtypes[type]++;) \
211 		(m)->m_next = (struct mbuf *)NULL; \
212 		(m)->m_nextpkt = (struct mbuf *)NULL; \
213 		(m)->m_data = (m)->m_dat; \
214 		(m)->m_flags = 0; \
215 	} \
216 } while(/* CONSTCOND */ 0)
217 
218 #ifdef SMALL_KERNEL
219 struct mbuf *_sk_mget(int, int);
220 #define MGET(m, how, type) { m = _sk_mget(how, type); }
221 #else
222 #define MGET(m, how, type) _MGET(m, how, type)
223 #endif
224 
225 #define	_MGETHDR(m, how, type) do { \
226 	MBUFLOCK( \
227 		(m) = pool_get(&mbpool, \
228 		    (how) == M_WAIT ? PR_WAITOK|PR_LIMITFAIL : 0); \
229 	); \
230 	if (m) { \
231 		(m)->m_type = (type); \
232 		MBUFLOCK(mbstat.m_mtypes[type]++;) \
233 		(m)->m_next = (struct mbuf *)NULL; \
234 		(m)->m_nextpkt = (struct mbuf *)NULL; \
235 		(m)->m_data = (m)->m_pktdat; \
236 		(m)->m_flags = M_PKTHDR; \
237 		SLIST_INIT(&(m)->m_pkthdr.tags); \
238 		(m)->m_pkthdr.csum = 0; \
239 	} \
240 } while (/* CONSTCOND */ 0)
241 
242 #ifdef SMALL_KERNEL
243 struct mbuf *_sk_mgethdr(int, int);
244 #define MGETHDR(m, how, type) { m = _sk_mgethdr(how, type); }
245 #else
246 #define MGETHDR(m, how, type) _MGETHDR(m, how, type)
247 #endif
248 
249 /*
250  * Macros for tracking external storage associated with an mbuf.
251  *
252  * Note: add and delete reference must be called at splvm().
253  */
254 #ifdef DEBUG
255 #define MCLREFDEBUGN(m, file, line) do {				\
256 		(m)->m_ext.ext_nfile = (file);				\
257 		(m)->m_ext.ext_nline = (line);				\
258 	} while (/* CONSTCOND */ 0)
259 #define MCLREFDEBUGO(m, file, line) do {				\
260 		(m)->m_ext.ext_ofile = (file);				\
261 		(m)->m_ext.ext_oline = (line);				\
262 	} while (/* CONSTCOND */ 0)
263 #else
264 #define MCLREFDEBUGN(m, file, line)
265 #define MCLREFDEBUGO(m, file, line)
266 #endif
267 
268 #define	MCLBUFREF(p)
269 #define	MCLISREFERENCED(m)	((m)->m_ext.ext_nextref != (m))
270 #define	_MCLDEREFERENCE(m)	do {					\
271 		(m)->m_ext.ext_nextref->m_ext.ext_prevref =		\
272 			(m)->m_ext.ext_prevref;				\
273 		(m)->m_ext.ext_prevref->m_ext.ext_nextref =		\
274 			(m)->m_ext.ext_nextref;				\
275 	} while (/* CONSTCOND */ 0)
276 #define	_MCLADDREFERENCE(o, n)	do {					\
277 		(n)->m_flags |= ((o)->m_flags & (M_EXT|M_CLUSTER));	\
278 		(n)->m_ext.ext_nextref = (o)->m_ext.ext_nextref;	\
279 		(n)->m_ext.ext_prevref = (o);				\
280 		(o)->m_ext.ext_nextref = (n);				\
281 		(n)->m_ext.ext_nextref->m_ext.ext_prevref = (n);	\
282 		MCLREFDEBUGN((n), __FILE__, __LINE__);			\
283 	} while (/* CONSTCOND */ 0)
284 #define	MCLINITREFERENCE(m)	do {					\
285 		(m)->m_ext.ext_prevref = (m);				\
286 		(m)->m_ext.ext_nextref = (m);				\
287 		MCLREFDEBUGO((m), __FILE__, __LINE__);			\
288 		MCLREFDEBUGN((m), NULL, 0);				\
289 	} while (/* CONSTCOND */ 0)
290 
291 #define	MCLADDREFERENCE(o, n)	MBUFLOCK(_MCLADDREFERENCE((o), (n));)
292 
293 /*
294  * Macros for mbuf external storage.
295  *
296  * MCLGET allocates and adds an mbuf cluster to a normal mbuf;
297  * the flag M_EXT is set upon success.
298  *
299  * MEXTMALLOC allocates external storage and adds it to
300  * a normal mbuf; the flag M_EXT is set upon success.
301  *
302  * MEXTADD adds pre-allocated external storage to
303  * a normal mbuf; the flag M_EXT is set upon success.
304  */
305 #define	_MCLGET(m, how) do { \
306 	MBUFLOCK( \
307 		(m)->m_ext.ext_buf = pool_get(&mclpool, (how) == M_WAIT ? \
308 		    (PR_WAITOK|PR_LIMITFAIL) : 0); \
309 	); \
310 	if ((m)->m_ext.ext_buf != NULL) { \
311 		(m)->m_data = (m)->m_ext.ext_buf; \
312 		(m)->m_flags |= M_EXT|M_CLUSTER; \
313 		(m)->m_ext.ext_size = MCLBYTES;  \
314 		(m)->m_ext.ext_free = NULL;  \
315 		(m)->m_ext.ext_arg = NULL;  \
316 		MCLINITREFERENCE(m); \
317 	} \
318 } while (/* CONSTCOND */ 0)
319 
320 #define	MEXTMALLOC(m, size, how) do { \
321 	(m)->m_ext.ext_buf = \
322 	    (caddr_t)malloc((size), mbtypes[(m)->m_type], (how)); \
323 	if ((m)->m_ext.ext_buf != NULL) { \
324 		(m)->m_data = (m)->m_ext.ext_buf; \
325 		(m)->m_flags |= M_EXT; \
326 		(m)->m_flags &= ~M_CLUSTER; \
327 		(m)->m_ext.ext_size = (size); \
328 		(m)->m_ext.ext_free = NULL; \
329 		(m)->m_ext.ext_arg = NULL; \
330 		(m)->m_ext.ext_type = mbtypes[(m)->m_type]; \
331 		MCLINITREFERENCE(m); \
332 	} \
333 } while (/* CONSTCOND */ 0)
334 
335 #define	MEXTADD(m, buf, size, type, free, arg) do { \
336 	(m)->m_data = (m)->m_ext.ext_buf = (caddr_t)(buf); \
337 	(m)->m_flags |= M_EXT; \
338 	(m)->m_flags &= ~M_CLUSTER; \
339 	(m)->m_ext.ext_size = (size); \
340 	(m)->m_ext.ext_free = (free); \
341 	(m)->m_ext.ext_arg = (arg); \
342 	(m)->m_ext.ext_type = (type); \
343 	MCLINITREFERENCE(m); \
344 } while (/* CONSTCOND */ 0)
345 
346 #define	_MEXTREMOVE(m) do { \
347 	if (MCLISREFERENCED(m)) { \
348 		_MCLDEREFERENCE(m); \
349 	} else if ((m)->m_flags & M_CLUSTER) { \
350 		pool_put(&mclpool, (m)->m_ext.ext_buf); \
351 	} else if ((m)->m_ext.ext_free) { \
352 		(*((m)->m_ext.ext_free))((m)->m_ext.ext_buf, \
353 		    (m)->m_ext.ext_size, (m)->m_ext.ext_arg); \
354 	} else { \
355 		free((m)->m_ext.ext_buf,(m)->m_ext.ext_type); \
356 	} \
357 	(m)->m_flags &= ~(M_CLUSTER|M_EXT); \
358 	(m)->m_ext.ext_size = 0;	/* why ??? */ \
359 } while (/* CONSTCOND */ 0)
360 
361 #define	MEXTREMOVE(m) \
362 	MBUFLOCK(_MEXTREMOVE((m));)
363 
364 /*
365  * Reset the data pointer on an mbuf.
366  */
367 #define	MRESETDATA(m)							\
368 do {									\
369 	if ((m)->m_flags & M_EXT)					\
370 		(m)->m_data = (m)->m_ext.ext_buf;			\
371 	else if ((m)->m_flags & M_PKTHDR)				\
372 		(m)->m_data = (m)->m_pktdat;				\
373 	else								\
374 		(m)->m_data = (m)->m_dat;				\
375 } while (/* CONSTCOND */ 0)
376 
377 #ifdef SMALL_KERNEL
378 void _sk_mclget(struct mbuf *, int);
379 #define MCLGET(m, how) _sk_mclget(m, how)
380 #else
381 #define MCLGET(m, how) _MCLGET(m, how)
382 #endif
383 
384 /*
385  * MFREE(struct mbuf *m, struct mbuf *n)
386  * Free a single mbuf and associated external storage.
387  * Place the successor, if any, in n.
388  */
389 #define	MFREE(m, n) \
390 	MBUFLOCK( \
391 		mbstat.m_mtypes[(m)->m_type]--; \
392 		if ((m)->m_flags & M_PKTHDR) \
393 			m_tag_delete_chain((m), NULL); \
394 		if ((m)->m_flags & M_EXT) { \
395 			_MEXTREMOVE((m)); \
396 		} \
397 		(n) = (m)->m_next; \
398 		pool_put(&mbpool, (m)); \
399 	)
400 
401 /*
402  * Move just m_pkthdr from from to to,
403  * remove M_PKTHDR and clean the tag for from.
404  */
405 #define M_MOVE_HDR(to, from) { \
406 	(to)->m_pkthdr = (from)->m_pkthdr; \
407 	(from)->m_flags &= ~M_PKTHDR; \
408 	SLIST_INIT(&(from)->m_pkthdr.tags); \
409 }
410 
411 /*
412  * Duplicate just m_pkthdr from from to to.
413  */
414 #define M_DUP_HDR(to, from) { \
415 	(to)->m_pkthdr = (from)->m_pkthdr; \
416 	SLIST_INIT(&(to)->m_pkthdr.tags); \
417 	m_tag_copy_chain((to), (from)); \
418 }
419 
420 /*
421  * Duplicate mbuf pkthdr from from to to.
422  * from must have M_PKTHDR set, and to must be empty.
423  */
424 #define M_DUP_PKTHDR(to, from) { \
425 	(to)->m_flags = (from)->m_flags & M_COPYFLAGS; \
426 	M_DUP_HDR((to), (from)); \
427 	(to)->m_data = (to)->m_pktdat; \
428 }
429 
430 /*
431  * MOVE mbuf pkthdr from from to to.
432  * from must have M_PKTHDR set, and to must be empty.
433  */
434 #define	M_MOVE_PKTHDR(to, from) { \
435 	(to)->m_flags = (from)->m_flags & M_COPYFLAGS; \
436 	M_MOVE_HDR((to), (from)); \
437 	(to)->m_data = (to)->m_pktdat; \
438 }
439 
440 /*
441  * Set the m_data pointer of a newly-allocated mbuf (m_get/MGET) to place
442  * an object of the specified size at the end of the mbuf, longword aligned.
443  */
444 #define	M_ALIGN(m, len) \
445 	{ (m)->m_data += (MLEN - (len)) &~ (sizeof(long) - 1); }
446 /*
447  * As above, for mbufs allocated with m_gethdr/MGETHDR
448  * or initialized by M_MOVE_PKTHDR.
449  */
450 #define	MH_ALIGN(m, len) \
451 	{ (m)->m_data += (MHLEN - (len)) &~ (sizeof(long) - 1); }
452 
453 /*
454  * Determine if an mbuf's data area is read-only. This is true for
455  * non-cluster external storage and for clusters that are being
456  * referenced by more than one mbuf.
457  */
458 #define	M_READONLY(m) \
459 	(((m)->m_flags & M_EXT) != 0 &&	\
460 	  (((m)->m_flags & M_CLUSTER) == 0 || MCLISREFERENCED(m)))
461 
462 /*
463  * Compute the amount of space available
464  * before the current start of data in an mbuf.
465  */
466 #define	_M_LEADINGSPACE(m) \
467 	((m)->m_flags & M_EXT ? (m)->m_data - (m)->m_ext.ext_buf : \
468 	 (m)->m_flags & M_PKTHDR ? (m)->m_data - (m)->m_pktdat : \
469 	 (m)->m_data - (m)->m_dat)
470 
471 #define	M_LEADINGSPACE(m)	\
472 	(M_READONLY((m)) ? 0 : _M_LEADINGSPACE((m)))
473 
474 /*
475  * Compute the amount of space available
476  * after the end of data in an mbuf.
477  */
478 #define	_M_TRAILINGSPACE(m) \
479 	((m)->m_flags & M_EXT ? (m)->m_ext.ext_buf + (m)->m_ext.ext_size - \
480 	    ((m)->m_data + (m)->m_len) : \
481 	    &(m)->m_dat[MLEN] - ((m)->m_data + (m)->m_len))
482 
483 #define	M_TRAILINGSPACE(m)	\
484 	(M_READONLY((m)) ? 0 : _M_TRAILINGSPACE((m)))
485 
486 /*
487  * Arrange to prepend space of size plen to mbuf m.
488  * If a new mbuf must be allocated, how specifies whether to wait.
489  * If how is M_DONTWAIT and allocation fails, the original mbuf chain
490  * is freed and m is set to NULL.
491  */
492 #define	M_PREPEND(m, plen, how) { \
493 	if (M_LEADINGSPACE(m) >= (plen)) { \
494 		(m)->m_data -= (plen); \
495 		(m)->m_len += (plen); \
496 	} else \
497 		(m) = m_prepend((m), (plen), (how)); \
498 	if ((m) && (m)->m_flags & M_PKTHDR) \
499 		(m)->m_pkthdr.len += (plen); \
500 }
501 
502 /* change mbuf to new type */
503 #define MCHTYPE(m, t) { \
504 	MBUFLOCK(mbstat.m_mtypes[(m)->m_type]--; mbstat.m_mtypes[t]++;) \
505 	(m)->m_type = t;\
506 }
507 
508 /* length to m_copy to copy all */
509 #define	M_COPYALL	1000000000
510 
511 /* compatibility with 4.3 */
512 #define  m_copy(m, o, l)	m_copym((m), (o), (l), M_DONTWAIT)
513 
514 /*
515  * Mbuf statistics.
516  * For statistics related to mbuf and cluster allocations, see also the
517  * pool headers (mbpool and mclpool).
518  */
519 struct mbstat {
520 	u_long	_m_spare;	/* formerly m_mbufs */
521 	u_long	_m_spare1;	/* formerly m_clusters */
522 	u_long	_m_spare2;	/* spare field */
523 	u_long	_m_spare3;	/* formely m_clfree - free clusters */
524 	u_long	m_drops;	/* times failed to find space */
525 	u_long	m_wait;		/* times waited for space */
526 	u_long	m_drain;	/* times drained protocols for space */
527 	u_short	m_mtypes[256];	/* type specific mbuf allocations */
528 };
529 
530 #ifdef	_KERNEL
531 extern	struct mbstat mbstat;
532 extern	int nmbclust;			/* limit on the # of clusters */
533 extern	int mblowat;			/* mbuf low water mark */
534 extern	int mcllowat;			/* mbuf cluster low water mark */
535 extern	int max_linkhdr;		/* largest link-level header */
536 extern	int max_protohdr;		/* largest protocol header */
537 extern	int max_hdr;			/* largest link+protocol header */
538 extern	int max_datalen;		/* MHLEN - max_hdr */
539 extern	int mbtypes[];			/* XXX */
540 extern struct pool mbpool;
541 extern struct pool mclpool;
542 
543 void	mbinit(void);
544 struct	mbuf *m_copym2(struct mbuf *, int, int, int);
545 struct	mbuf *m_copym(struct mbuf *, int, int, int);
546 struct	mbuf *m_free(struct mbuf *);
547 struct	mbuf *m_get(int, int);
548 struct	mbuf *m_getclr(int, int);
549 struct	mbuf *m_gethdr(int, int);
550 struct	mbuf *m_prepend(struct mbuf *, int, int);
551 struct	mbuf *m_pulldown(struct mbuf *, int, int, int *);
552 struct	mbuf *m_pullup(struct mbuf *, int);
553 struct	mbuf *m_pullup2(struct mbuf *, int);
554 struct	mbuf *m_split(struct mbuf *, int, int);
555 struct  mbuf *m_inject(struct mbuf *, int, int, int);
556 struct  mbuf *m_getptr(struct mbuf *, int, int *);
557 void	m_adj(struct mbuf *, int);
558 int	m_clalloc(int, int);
559 void	m_copyback(struct mbuf *, int, int, const void *);
560 void	m_freem(struct mbuf *);
561 void	m_reclaim(void *, int);
562 void	m_copydata(struct mbuf *, int, int, caddr_t);
563 void	m_cat(struct mbuf *, struct mbuf *);
564 struct mbuf *m_devget(char *, int, int, struct ifnet *,
565 	    void (*)(const void *, void *, size_t));
566 void	m_zero(struct mbuf *);
567 int	m_apply(struct mbuf *, int, int,
568 	    int (*)(caddr_t, caddr_t, unsigned int), caddr_t);
569 
570 /* Packet tag routines */
571 struct m_tag *m_tag_get(int, int, int);
572 void	m_tag_free(struct m_tag *);
573 void	m_tag_prepend(struct mbuf *, struct m_tag *);
574 void	m_tag_unlink(struct mbuf *, struct m_tag *);
575 void	m_tag_delete(struct mbuf *, struct m_tag *);
576 void	m_tag_delete_chain(struct mbuf *, struct m_tag *);
577 struct m_tag *m_tag_find(struct mbuf *, int, struct m_tag *);
578 struct m_tag *m_tag_copy(struct m_tag *);
579 int	m_tag_copy_chain(struct mbuf *, struct mbuf *);
580 void	m_tag_init(struct mbuf *);
581 struct m_tag *m_tag_first(struct mbuf *);
582 struct m_tag *m_tag_next(struct mbuf *, struct m_tag *);
583 
584 /* Packet tag types */
585 #define PACKET_TAG_NONE				0  /* Nadda */
586 #define PACKET_TAG_IPSEC_IN_DONE		1  /* IPsec applied, in */
587 #define PACKET_TAG_IPSEC_OUT_DONE		2  /* IPsec applied, out */
588 #define PACKET_TAG_IPSEC_IN_CRYPTO_DONE		3  /* NIC IPsec crypto done */
589 #define PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED	4  /* NIC IPsec crypto req'ed */
590 #define PACKET_TAG_IPSEC_IN_COULD_DO_CRYPTO	5  /* NIC notifies IPsec */
591 #define PACKET_TAG_IPSEC_PENDING_TDB		6  /* Reminder to do IPsec */
592 #define PACKET_TAG_BRIDGE			7  /* Bridge processing done */
593 #define PACKET_TAG_GIF				8  /* GIF processing done */
594 #define PACKET_TAG_GRE				9  /* GRE processing done */
595 #define PACKET_TAG_IN_PACKET_CHECKSUM		10 /* NIC checksumming done */
596 #define PACKET_TAG_PF_GENERATED			11 /* PF generated, pass always */
597 #define PACKET_TAG_PF_ROUTED			12 /* PF routed, no route loops */
598 #define PACKET_TAG_PF_FRAGCACHE			13 /* PF fragment cached */
599 #define	PACKET_TAG_PF_QID			14 /* PF queue id */
600 #define PACKET_TAG_PF_TAG			15 /* PF tags */
601 #define PACKET_TAG_CARP				16 /* CARP info */
602 #define PACKET_TAG_PF_TRANSLATE_LOCALHOST	17 /* translated to localhost */
603 
604 #ifdef MBTYPES
605 int mbtypes[] = {				/* XXX */
606 	M_FREE,		/* MT_FREE	0	   should be on free list */
607 	M_MBUF,		/* MT_DATA	1	   dynamic (data) allocation */
608 	M_MBUF,		/* MT_HEADER	2	   packet header */
609 	M_MBUF,		/* MT_SONAME	8	   socket name */
610 	M_SOOPTS,	/* MT_SOOPTS	10	   socket options */
611 	M_FTABLE,	/* MT_FTABLE	11	   fragment reassembly header */
612 	M_MBUF,		/* MT_CONTROL	14	   extra-data protocol message */
613 	M_MBUF,		/* MT_OOBDATA	15	   expedited data  */
614 };
615 #endif /* MBTYPES */
616 #endif
617