xref: /386bsd/usr/include/nonstd/bsd/sys/mbuf.h (revision a2142627)
1 /*
2  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
3  * 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	7.14 (Berkeley) 12/5/90
34  */
35 
36 #ifndef M_WAITOK
37 #include "malloc.h"
38 #endif
39 
40 /*
41  * Mbufs are of a single size, MSIZE (machine/machparam.h), which
42  * includes overhead.  An mbuf may add a single "mbuf cluster" of size
43  * MCLBYTES (also in machine/machparam.h), which has no additional overhead
44  * and is used instead of the internal data area; this is done when
45  * at least MINCLSIZE of data must be stored.
46  */
47 
48 #define	MLEN		(MSIZE - sizeof(struct m_hdr))	/* normal data len */
49 #define	MHLEN		(MLEN - sizeof(struct pkthdr))	/* data len w/pkthdr */
50 
51 #define	MINCLSIZE	(MHLEN + MLEN)	/* smallest amount to put in cluster */
52 #define	M_MAXCOMPRESS	(MHLEN / 2)	/* max amount to copy for compression */
53 
54 /*
55  * Macros for type conversion
56  * mtod(m,t) -	convert mbuf pointer to data pointer of correct type
57  * dtom(x) -	convert data pointer within mbuf to mbuf pointer (XXX)
58  * mtocl(x) -	convert pointer within cluster to cluster index #
59  * cltom(x) -	convert cluster # to ptr to beginning of cluster
60  */
61 #define mtod(m,t)	((t)((m)->m_data))
62 #define	dtom(x)		((struct mbuf *)((int)(x) & ~(MSIZE-1)))
63 #define	mtocl(x)	(((u_int)(x) - (u_int)mbutl) >> MCLSHIFT)
64 #define	cltom(x)	((caddr_t)((u_int)mbutl + ((u_int)(x) >> MCLSHIFT)))
65 
66 /* header at beginning of each mbuf: */
67 struct m_hdr {
68 	struct	mbuf *mh_next;		/* next buffer in chain */
69 	struct	mbuf *mh_nextpkt;	/* next chain in queue/record */
70 	int	mh_len;			/* amount of data in this mbuf */
71 	caddr_t	mh_data;		/* location of data */
72 	short	mh_type;		/* type of data in this mbuf */
73 	short	mh_flags;		/* flags; see below */
74 };
75 
76 /* record/packet header in first mbuf of chain; valid if M_PKTHDR set */
77 struct	pkthdr {
78 	int	len;		/* total packet length */
79 	struct	ifnet *rcvif;	/* rcv interface */
80 #ifdef	PKT_TRACE
81 	unsigned long time;	/* time header generated */
82 #ifdef	nope
83 	unsigned short ary[16];	/* it's */
84 	unsigned char tag[16];	/* tag */
85 	unsigned char idx;
86 #endif
87 #endif
88 };
89 
90 /* description of external storage mapped into mbuf, valid if M_EXT set */
91 struct m_ext {
92 	caddr_t	ext_buf;		/* start of buffer */
93 	void	(*ext_free)();		/* free routine if not the usual */
94 	u_int	ext_size;		/* size of buffer, for ext_free */
95 };
96 
97 struct mbuf {
98 	struct	m_hdr m_hdr;
99 	union {
100 		struct {
101 			struct	pkthdr MH_pkthdr;	/* M_PKTHDR set */
102 			union {
103 				struct	m_ext MH_ext;	/* M_EXT set */
104 				char	MH_databuf[MHLEN];
105 			} MH_dat;
106 		} MH;
107 		char	M_databuf[MLEN];		/* !M_PKTHDR, !M_EXT */
108 	} M_dat;
109 };
110 #define	m_next		m_hdr.mh_next
111 #define	m_len		m_hdr.mh_len
112 #define	m_data		m_hdr.mh_data
113 #define	m_type		m_hdr.mh_type
114 #define	m_flags		m_hdr.mh_flags
115 #define	m_nextpkt	m_hdr.mh_nextpkt
116 #define	m_act		m_nextpkt
117 #define	m_pkthdr	M_dat.MH.MH_pkthdr
118 #define	m_ext		M_dat.MH.MH_dat.MH_ext
119 #define	m_pktdat	M_dat.MH.MH_dat.MH_databuf
120 #define	m_dat		M_dat.M_databuf
121 
122 /* mbuf flags */
123 #define	M_EXT		0x0001	/* has associated external storage */
124 #define	M_PKTHDR	0x0002	/* start of record */
125 #define	M_EOR		0x0004	/* end of record */
126 
127 /* mbuf pkthdr flags, also in m_flags */
128 #define	M_BCAST		0x0100	/* send/received as link-level broadcast */
129 #define	M_MCAST		0x0200	/* send/received as link-level multicast */
130 
131 /* flags copied when copying m_pkthdr */
132 #define	M_COPYFLAGS	(M_PKTHDR|M_EOR|M_BCAST|M_MCAST)
133 
134 /* mbuf types */
135 #define	MT_FREE		0	/* should be on free list */
136 #define	MT_DATA		1	/* dynamic (data) allocation */
137 #define	MT_HEADER	2	/* packet header */
138 #define	MT_SOCKET	3	/* socket structure */
139 #define	MT_PCB		4	/* protocol control block */
140 #define	MT_RTABLE	5	/* routing tables */
141 #define	MT_HTABLE	6	/* IMP host tables */
142 #define	MT_ATABLE	7	/* address resolution tables */
143 #define	MT_SONAME	8	/* socket name */
144 #define	MT_SOOPTS	10	/* socket options */
145 #define	MT_FTABLE	11	/* fragment reassembly header */
146 #define	MT_RIGHTS	12	/* access rights */
147 #define	MT_IFADDR	13	/* interface address */
148 #define MT_CONTROL	14	/* extra-data protocol message */
149 #define MT_OOBDATA	15	/* expedited data  */
150 
151 /* flags to m_get/MGET */
152 #define	M_DONTWAIT	M_NOWAIT
153 #define	M_WAIT		M_WAITOK
154 
155 /*
156  * mbuf allocation/deallocation macros:
157  *
158  *	MGET(struct mbuf *m, int how, int type)
159  * allocates an mbuf and initializes it to contain internal data.
160  *
161  *	MGETHDR(struct mbuf *m, int how, int type)
162  * allocates an mbuf and initializes it to contain a packet header
163  * and internal data.
164  */
165 #define	MGET(m, how, type) { \
166 	MALLOC((m), struct mbuf *, MSIZE, mbtypes[type], (how)); \
167 	if (m) { \
168 		(m)->m_type = (type); \
169 		mbstat.m_mtypes[type]++; \
170 		(m)->m_next = (struct mbuf *)NULL; \
171 		(m)->m_nextpkt = (struct mbuf *)NULL; \
172 		(m)->m_data = (m)->m_dat; \
173 		(m)->m_flags = 0; \
174 	} else \
175 		(m) = m_retry((how), (type)); \
176 }
177 
178 #ifdef PKT_TRACE
179 #define	MGETHDRT(m, how, type) { \
180 	MALLOC((m), struct mbuf *, MSIZE, mbtypes[type], (how)); \
181 	if (m) { \
182 		(m)->m_type = (type); \
183 		mbstat.m_mtypes[type]++; \
184 		(m)->m_next = (struct mbuf *)NULL; \
185 		(m)->m_nextpkt = (struct mbuf *)NULL; \
186 		(m)->m_data = (m)->m_pktdat; \
187 		(m)->m_flags = M_PKTHDR; \
188 		(m)->m_pkthdr.time = getticks(); \
189 	} else \
190 		(m) = m_retryhdrt((how), (type)); \
191 }
192 #define	MGETHDR(m, how, type) { \
193 	MALLOC((m), struct mbuf *, MSIZE, mbtypes[type], (how)); \
194 	if (m) { \
195 		(m)->m_type = (type); \
196 		mbstat.m_mtypes[type]++; \
197 		(m)->m_next = (struct mbuf *)NULL; \
198 		(m)->m_nextpkt = (struct mbuf *)NULL; \
199 		(m)->m_data = (m)->m_pktdat; \
200 		(m)->m_flags = M_PKTHDR; \
201 		(m)->m_pkthdr.time = 0; \
202 	} else \
203 		(m) = m_retryhdr((how), (type)); \
204 }
205 #else
206 #define	MGETHDR(m, how, type) { \
207 	MALLOC((m), struct mbuf *, MSIZE, mbtypes[type], (how)); \
208 	if (m) { \
209 		(m)->m_type = (type); \
210 		mbstat.m_mtypes[type]++; \
211 		(m)->m_next = (struct mbuf *)NULL; \
212 		(m)->m_nextpkt = (struct mbuf *)NULL; \
213 		(m)->m_data = (m)->m_pktdat; \
214 		(m)->m_flags = M_PKTHDR; \
215 	} else \
216 		(m) = m_retryhdr((how), (type)); \
217 }
218 #endif
219 
220 /*
221  * Mbuf cluster macros.
222  * MCLALLOC(caddr_t p, int how) allocates an mbuf cluster.
223  * MCLGET adds such clusters to a normal mbuf;
224  * the flag M_EXT is set upon success.
225  * MCLFREE releases a reference to a cluster allocated by MCLALLOC,
226  * freeing the cluster if the reference count has reached 0.
227  *
228  * Normal mbuf clusters are normally treated as character arrays
229  * after allocation, but use the first word of the buffer as a free list
230  * pointer while on the free list.
231  */
232 union mcluster {
233 	union	mcluster *mcl_next;
234 	char	mcl_buf[MCLBYTES];
235 };
236 
237 #define	MCLALLOC(p, how) \
238 	{ int ms = splimp(); \
239 	  if (mclfree == 0) \
240 		(void)m_clalloc(1, (how)); \
241 	  if ((p) = (caddr_t)mclfree) { \
242 		++mclrefcnt[mtocl(p)]; \
243 		mbstat.m_clfree--; \
244 		mclfree = ((union mcluster *)(p))->mcl_next; \
245 	  } \
246 	  splx(ms); \
247 	}
248 
249 #define	MCLGET(m, how) \
250 	{ MCLALLOC((m)->m_ext.ext_buf, (how)); \
251 	  if ((m)->m_ext.ext_buf != NULL) { \
252 		(m)->m_data = (m)->m_ext.ext_buf; \
253 		(m)->m_flags |= M_EXT; \
254 		(m)->m_ext.ext_size = MCLBYTES;  \
255 	  } \
256 	}
257 
258 #define	MCLFREE(p) \
259 	{ int ms = splimp(); \
260 	  if (--mclrefcnt[mtocl(p)] == 0) { \
261 		((union mcluster *)(p))->mcl_next = mclfree; \
262 		mclfree = (union mcluster *)(p); \
263 		mbstat.m_clfree++; \
264 	  } \
265 	  splx(ms); \
266 	}
267 
268 /*
269  * MFREE(struct mbuf *m, struct mbuf *n)
270  * Free a single mbuf and associated external storage.
271  * Place the successor, if any, in n.
272  */
273 #ifdef notyet
274 #define	MFREE(m, n) \
275 	{ mbstat.m_mtypes[(m)->m_type]--; \
276 	  if ((m)->m_flags & M_EXT) { \
277 		if ((m)->m_ext.ext_free) \
278 			(*((m)->m_ext.ext_free))((m)->m_ext.ext_buf, \
279 			    (m)->m_ext.ext_size); \
280 		else \
281 			MCLFREE((m)->m_ext.ext_buf); \
282 	  } \
283 	  (n) = (m)->m_next; \
284 	  FREE((m), mbtypes[(m)->m_type]); \
285 	}
286 #else /* notyet */
287 #ifdef PKT_TRACE
288 #define	MFREE(m, nn) \
289 	{ mbstat.m_mtypes[(m)->m_type]--; \
290 	  if ((m)->m_flags & M_PKTHDR) { \
291 		m_trace(m); \
292 	  } \
293 	  if ((m)->m_flags & M_EXT) { \
294 		MCLFREE((m)->m_ext.ext_buf); \
295 	  } \
296 	  (nn) = (m)->m_next; \
297 	  FREE((m), mbtypes[(m)->m_type]); \
298 	}
299 #else
300 #define	MFREE(m, nn) \
301 	{ mbstat.m_mtypes[(m)->m_type]--; \
302 	  if ((m)->m_flags & M_EXT) { \
303 		MCLFREE((m)->m_ext.ext_buf); \
304 	  } \
305 	  (nn) = (m)->m_next; \
306 	  FREE((m), mbtypes[(m)->m_type]); \
307 	}
308 #endif
309 #endif
310 
311 /*
312  * Copy mbuf pkthdr from from to to.
313  * from must have M_PKTHDR set, and to must be empty.
314  */
315 #define	M_COPY_PKTHDR(to, from) { \
316 	(to)->m_pkthdr = (from)->m_pkthdr; \
317 	(to)->m_flags = (from)->m_flags & M_COPYFLAGS; \
318 	(to)->m_data = (to)->m_pktdat; \
319 }
320 
321 /*
322  * Set the m_data pointer of a newly-allocated mbuf (m_get/MGET) to place
323  * an object of the specified size at the end of the mbuf, longword aligned.
324  */
325 #define	M_ALIGN(m, len) \
326 	{ (m)->m_data += (MLEN - (len)) &~ (sizeof(long) - 1); }
327 /*
328  * As above, for mbufs allocated with m_gethdr/MGETHDR
329  * or initialized by M_COPY_PKTHDR.
330  */
331 #define	MH_ALIGN(m, len) \
332 	{ (m)->m_data += (MHLEN - (len)) &~ (sizeof(long) - 1); }
333 
334 /*
335  * Compute the amount of space available
336  * before the current start of data in an mbuf.
337  */
338 #define	M_LEADINGSPACE(m) \
339 	((m)->m_flags & M_EXT ? /* (m)->m_data - (m)->m_ext.ext_buf */ 0 : \
340 	    (m)->m_flags & M_PKTHDR ? (m)->m_data - (m)->m_pktdat : \
341 	    (m)->m_data - (m)->m_dat)
342 
343 /*
344  * Compute the amount of space available
345  * after the end of data in an mbuf.
346  */
347 #define	M_TRAILINGSPACE(m) \
348 	((m)->m_flags & M_EXT ? (m)->m_ext.ext_buf + (m)->m_ext.ext_size - \
349 	    ((m)->m_data + (m)->m_len) : \
350 	    &(m)->m_dat[MLEN] - ((m)->m_data + (m)->m_len))
351 
352 /*
353  * Arrange to prepend space of size plen to mbuf m.
354  * If a new mbuf must be allocated, how specifies whether to wait.
355  * If how is M_DONTWAIT and allocation fails, the original mbuf chain
356  * is freed and m is set to NULL.
357  */
358 #define	M_PREPEND(m, plen, how) { \
359 	if (M_LEADINGSPACE(m) >= (plen)) { \
360 		(m)->m_data -= (plen); \
361 		(m)->m_len += (plen); \
362 	} else \
363 		(m) = m_prepend((m), (plen), (how)); \
364 	if ((m) && (m)->m_flags & M_PKTHDR) \
365 		(m)->m_pkthdr.len += (plen); \
366 }
367 
368 /* change mbuf to new type */
369 #define MCHTYPE(m, t) { \
370 	mbstat.m_mtypes[(m)->m_type]--; \
371 	mbstat.m_mtypes[t]++; \
372 	(m)->m_type = t;\
373 }
374 
375 /* length to m_copy to copy all */
376 #define	M_COPYALL	1000000000
377 
378 /* compatiblity with 4.3 */
379 #define  m_copy(m, o, l)	m_copym((m), (o), (l), M_DONTWAIT)
380 
381 /*
382  * Mbuf statistics.
383  */
384 struct mbstat {
385 	u_long	m_mbufs;	/* mbufs obtained from page pool */
386 	u_long	m_clusters;	/* clusters obtained from page pool */
387 	u_long	m_spare;	/* spare field */
388 	u_long	m_clfree;	/* free clusters */
389 	u_long	m_drops;	/* times failed to find space */
390 	u_long	m_wait;		/* times waited for space */
391 	u_long	m_drain;	/* times drained protocols for space */
392 	u_short	m_mtypes[256];	/* type specific mbuf allocations */
393 };
394 
395 #ifdef	KERNEL
396 extern	struct mbuf *mbutl;		/* virtual address of mclusters */
397 extern	char *mclrefcnt;		/* cluster reference counts */
398 extern struct mbstat mbstat;
399 extern int nmbclusters;
400 extern union mcluster *mclfree;
401 extern int max_linkhdr;			/* largest link-level header */
402 extern int max_protohdr;		/* largest protocol header */
403 extern int max_hdr;			/* largest link+protocol header */
404 extern int max_datalen;			/* MHLEN - max_hdr */
405 #ifdef PKT_TRACE
406 struct	mbuf *m_retryhdrt();
407 #endif
408 int	m_adj(struct mbuf *mp, int req_len);
409 int	m_clalloc (int, int);
410 struct	mbuf *m_copym(struct mbuf *, int, int, int);
411 struct	mbuf *m_free(struct mbuf *);
412 struct	mbuf *m_get(int, int);
413 struct	mbuf *m_getclr(int, int);
414 struct	mbuf *m_gethdr(int, int);
415 struct	mbuf *m_prepend(struct mbuf *, int, int);
416 struct	mbuf *m_pullup(struct mbuf *, int);
417 struct	mbuf *m_retry(int, int);
418 struct	mbuf *m_retryhdr(int, int);
419 void	m_cat(struct mbuf *m, struct mbuf *n);
420 void	m_copydata(struct mbuf *m, int off, int len, caddr_t cp);
421 void	m_freem(struct mbuf *);
422 void	m_reclaim(void);
423 void	mbinit(void);
424 extern	int mbtypes[];			/* XXX */
425 
426 #ifdef MBTYPES
427 int mbtypes[] = {				/* XXX */
428 	M_FREE,		/* MT_FREE	0	/* should be on free list */
429 	M_MBUF,		/* MT_DATA	1	/* dynamic (data) allocation */
430 	M_MBUF,		/* MT_HEADER	2	/* packet header */
431 	M_SOCKET,	/* MT_SOCKET	3	/* socket structure */
432 	M_PCB,		/* MT_PCB	4	/* protocol control block */
433 	M_RTABLE,	/* MT_RTABLE	5	/* routing tables */
434 	M_HTABLE,	/* MT_HTABLE	6	/* IMP host tables */
435 	0,		/* MT_ATABLE	7	/* address resolution tables */
436 	M_MBUF,		/* MT_SONAME	8	/* socket name */
437 	0,		/* 		9 */
438 	M_SOOPTS,	/* MT_SOOPTS	10	/* socket options */
439 	M_FTABLE,	/* MT_FTABLE	11	/* fragment reassembly header */
440 	M_MBUF,		/* MT_RIGHTS	12	/* access rights */
441 	M_IFADDR,	/* MT_IFADDR	13	/* interface address */
442 	M_MBUF,		/* MT_CONTROL	14	/* extra-data protocol message */
443 	M_MBUF,		/* MT_OOBDATA	15	/* expedited data  */
444 #ifdef DATAKIT
445 	25, 26, 27, 28, 29, 30, 31, 32		/* datakit ugliness */
446 #endif
447 };
448 #endif
449 #endif
450