|
1 /*- |
|
2 * Copyright (c) 1982, 1986, 1988, 1993 |
|
3 * The Regents of the University of California. |
|
4 * All rights reserved. |
|
5 * |
|
6 * Redistribution and use in source and binary forms, with or without |
|
7 * modification, are permitted provided that the following conditions |
|
8 * are met: |
|
9 * 1. Redistributions of source code must retain the above copyright |
|
10 * notice, this list of conditions and the following disclaimer. |
|
11 * 2. Redistributions in binary form must reproduce the above copyright |
|
12 * notice, this list of conditions and the following disclaimer in the |
|
13 * documentation and/or other materials provided with the distribution. |
|
14 * 3. Neither the name of the University nor the names of its contributors |
|
15 * may be used to endorse or promote products derived from this software |
|
16 * without specific prior written permission. |
|
17 * |
|
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
|
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
|
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
28 * SUCH DAMAGE. |
|
29 * |
|
30 */ |
|
31 |
|
32 #ifndef _USER_MBUF_H_ |
|
33 #define _USER_MBUF_H_ |
|
34 |
|
35 /* __Userspace__ header file for mbufs */ |
|
36 #include <stdio.h> |
|
37 #if !defined(SCTP_SIMPLE_ALLOCATOR) |
|
38 #include "umem.h" |
|
39 #endif |
|
40 #include "user_malloc.h" |
|
41 #include "netinet/sctp_os_userspace.h" |
|
42 |
|
43 #define USING_MBUF_CONSTRUCTOR 0 |
|
44 |
|
45 /* For Linux */ |
|
46 #ifndef MSIZE |
|
47 #define MSIZE 256 |
|
48 /* #define MSIZE 1024 */ |
|
49 #endif |
|
50 #ifndef MCLBYTES |
|
51 #define MCLBYTES 2048 |
|
52 #endif |
|
53 |
|
54 struct mbuf * m_gethdr(int how, short type); |
|
55 struct mbuf * m_get(int how, short type); |
|
56 struct mbuf * m_free(struct mbuf *m); |
|
57 void m_clget(struct mbuf *m, int how); |
|
58 |
|
59 |
|
60 /* mbuf initialization function */ |
|
61 void mbuf_init(void *); |
|
62 |
|
63 #define M_MOVE_PKTHDR(to, from) m_move_pkthdr((to), (from)) |
|
64 #define MGET(m, how, type) ((m) = m_get((how), (type))) |
|
65 #define MGETHDR(m, how, type) ((m) = m_gethdr((how), (type))) |
|
66 #define MCLGET(m, how) m_clget((m), (how)) |
|
67 |
|
68 |
|
69 #define M_HDR_PAD ((sizeof(intptr_t)==4) ? 2 : 6) /* modified for __Userspace__ */ |
|
70 |
|
71 /* Length to m_copy to copy all. */ |
|
72 #define M_COPYALL 1000000000 |
|
73 |
|
74 /* umem_cache_t is defined in user_include/umem.h as |
|
75 * typedef struct umem_cache umem_cache_t; |
|
76 * Note:umem_zone_t is a pointer. |
|
77 */ |
|
78 #if defined(SCTP_SIMPLE_ALLOCATOR) |
|
79 typedef size_t sctp_zone_t; |
|
80 #else |
|
81 typedef umem_cache_t *sctp_zone_t; |
|
82 #endif |
|
83 |
|
84 extern sctp_zone_t zone_mbuf; |
|
85 extern sctp_zone_t zone_clust; |
|
86 extern sctp_zone_t zone_ext_refcnt; |
|
87 |
|
88 /*- |
|
89 * Macros for type conversion: |
|
90 * mtod(m, t) -- Convert mbuf pointer to data pointer of correct type. |
|
91 * dtom(x) -- Convert data pointer within mbuf to mbuf pointer (XXX). |
|
92 */ |
|
93 #define mtod(m, t) ((t)((m)->m_data)) |
|
94 #define dtom(x) ((struct mbuf *)((intptr_t)(x) & ~(MSIZE-1))) |
|
95 |
|
96 struct mb_args { |
|
97 int flags; /* Flags for mbuf being allocated */ |
|
98 short type; /* Type of mbuf being allocated */ |
|
99 }; |
|
100 |
|
101 struct clust_args { |
|
102 struct mbuf * parent_mbuf; |
|
103 }; |
|
104 |
|
105 struct mbuf * m_split(struct mbuf *, int, int); |
|
106 void m_cat(struct mbuf *m, struct mbuf *n); |
|
107 void m_adj(struct mbuf *, int); |
|
108 void mb_free_ext(struct mbuf *); |
|
109 void m_freem(struct mbuf *); |
|
110 struct m_tag *m_tag_alloc(u_int32_t, int, int, int); |
|
111 struct mbuf *m_copym(struct mbuf *, int, int, int); |
|
112 void m_copyback(struct mbuf *, int, int, caddr_t); |
|
113 struct mbuf *m_pullup(struct mbuf *, int); |
|
114 struct mbuf *m_pulldown(struct mbuf *, int off, int len, int *offp); |
|
115 int m_dup_pkthdr(struct mbuf *, struct mbuf *, int); |
|
116 struct m_tag *m_tag_copy(struct m_tag *, int); |
|
117 int m_tag_copy_chain(struct mbuf *, struct mbuf *, int); |
|
118 struct mbuf *m_prepend(struct mbuf *, int, int); |
|
119 void m_copydata(const struct mbuf *, int, int, caddr_t); |
|
120 |
|
121 #define MBUF_MEM_NAME "mbuf" |
|
122 #define MBUF_CLUSTER_MEM_NAME "mbuf_cluster" |
|
123 #define MBUF_EXTREFCNT_MEM_NAME "mbuf_ext_refcnt" |
|
124 |
|
125 #define MT_NOINIT 255 /* Not a type but a flag to allocate |
|
126 a non-initialized mbuf */ |
|
127 |
|
128 /* |
|
129 * General mbuf allocator statistics structure. |
|
130 * __Userspace__ mbstat may be useful for gathering statistics. |
|
131 * In the kernel many of these statistics are no longer used as |
|
132 * they track allocator statistics through kernel UMA's built in statistics mechanism. |
|
133 */ |
|
134 struct mbstat { |
|
135 u_long m_mbufs; /* XXX */ |
|
136 u_long m_mclusts; /* XXX */ |
|
137 |
|
138 u_long m_drain; /* times drained protocols for space */ |
|
139 u_long m_mcfail; /* XXX: times m_copym failed */ |
|
140 u_long m_mpfail; /* XXX: times m_pullup failed */ |
|
141 u_long m_msize; /* length of an mbuf */ |
|
142 u_long m_mclbytes; /* length of an mbuf cluster */ |
|
143 u_long m_minclsize; /* min length of data to allocate a cluster */ |
|
144 u_long m_mlen; /* length of data in an mbuf */ |
|
145 u_long m_mhlen; /* length of data in a header mbuf */ |
|
146 |
|
147 /* Number of mbtypes (gives # elems in mbtypes[] array: */ |
|
148 short m_numtypes; |
|
149 |
|
150 /* XXX: Sendfile stats should eventually move to their own struct */ |
|
151 u_long sf_iocnt; /* times sendfile had to do disk I/O */ |
|
152 u_long sf_allocfail; /* times sfbuf allocation failed */ |
|
153 u_long sf_allocwait; /* times sfbuf allocation had to wait */ |
|
154 }; |
|
155 |
|
156 |
|
157 /* |
|
158 * Mbufs are of a single size, MSIZE (sys/param.h), which includes overhead. |
|
159 * An mbuf may add a single "mbuf cluster" of size MCLBYTES (also in |
|
160 * sys/param.h), which has no additional overhead and is used instead of the |
|
161 * internal data area; this is done when at least MINCLSIZE of data must be |
|
162 * stored. Additionally, it is possible to allocate a separate buffer |
|
163 * externally and attach it to the mbuf in a way similar to that of mbuf |
|
164 * clusters. |
|
165 */ |
|
166 #define MLEN ((int)(MSIZE - sizeof(struct m_hdr))) /* normal data len */ |
|
167 #define MHLEN ((int)(MLEN - sizeof(struct pkthdr))) /* data len w/pkthdr */ |
|
168 #define MINCLSIZE ((int)(MHLEN + 1)) /* smallest amount to put in cluster */ |
|
169 #define M_MAXCOMPRESS (MHLEN / 2) /* max amount to copy for compression */ |
|
170 |
|
171 |
|
172 /* |
|
173 * Header present at the beginning of every mbuf. |
|
174 */ |
|
175 struct m_hdr { |
|
176 struct mbuf *mh_next; /* next buffer in chain */ |
|
177 struct mbuf *mh_nextpkt; /* next chain in queue/record */ |
|
178 caddr_t mh_data; /* location of data */ |
|
179 int mh_len; /* amount of data in this mbuf */ |
|
180 int mh_flags; /* flags; see below */ |
|
181 short mh_type; /* type of data in this mbuf */ |
|
182 uint8_t pad[M_HDR_PAD];/* word align */ |
|
183 }; |
|
184 |
|
185 /* |
|
186 * Packet tag structure (see below for details). |
|
187 */ |
|
188 struct m_tag { |
|
189 SLIST_ENTRY(m_tag) m_tag_link; /* List of packet tags */ |
|
190 u_int16_t m_tag_id; /* Tag ID */ |
|
191 u_int16_t m_tag_len; /* Length of data */ |
|
192 u_int32_t m_tag_cookie; /* ABI/Module ID */ |
|
193 void (*m_tag_free)(struct m_tag *); |
|
194 }; |
|
195 |
|
196 /* |
|
197 * Record/packet header in first mbuf of chain; valid only if M_PKTHDR is set. |
|
198 */ |
|
199 struct pkthdr { |
|
200 struct ifnet *rcvif; /* rcv interface */ |
|
201 /* variables for ip and tcp reassembly */ |
|
202 void *header; /* pointer to packet header */ |
|
203 int len; /* total packet length */ |
|
204 /* variables for hardware checksum */ |
|
205 int csum_flags; /* flags regarding checksum */ |
|
206 int csum_data; /* data field used by csum routines */ |
|
207 u_int16_t tso_segsz; /* TSO segment size */ |
|
208 u_int16_t ether_vtag; /* Ethernet 802.1p+q vlan tag */ |
|
209 SLIST_HEAD(packet_tags, m_tag) tags; /* list of packet tags */ |
|
210 }; |
|
211 |
|
212 /* |
|
213 * Description of external storage mapped into mbuf; valid only if M_EXT is |
|
214 * set. |
|
215 */ |
|
216 struct m_ext { |
|
217 caddr_t ext_buf; /* start of buffer */ |
|
218 void (*ext_free) /* free routine if not the usual */ |
|
219 (void *, void *); |
|
220 void *ext_args; /* optional argument pointer */ |
|
221 u_int ext_size; /* size of buffer, for ext_free */ |
|
222 volatile u_int *ref_cnt; /* pointer to ref count info */ |
|
223 int ext_type; /* type of external storage */ |
|
224 }; |
|
225 |
|
226 |
|
227 /* |
|
228 * The core of the mbuf object along with some shortcut defined for practical |
|
229 * purposes. |
|
230 */ |
|
231 struct mbuf { |
|
232 struct m_hdr m_hdr; |
|
233 union { |
|
234 struct { |
|
235 struct pkthdr MH_pkthdr; /* M_PKTHDR set */ |
|
236 union { |
|
237 struct m_ext MH_ext; /* M_EXT set */ |
|
238 char MH_databuf[MHLEN]; |
|
239 } MH_dat; |
|
240 } MH; |
|
241 char M_databuf[MLEN]; /* !M_PKTHDR, !M_EXT */ |
|
242 } M_dat; |
|
243 }; |
|
244 |
|
245 #define m_next m_hdr.mh_next |
|
246 #define m_len m_hdr.mh_len |
|
247 #define m_data m_hdr.mh_data |
|
248 #define m_type m_hdr.mh_type |
|
249 #define m_flags m_hdr.mh_flags |
|
250 #define m_nextpkt m_hdr.mh_nextpkt |
|
251 #define m_act m_nextpkt |
|
252 #define m_pkthdr M_dat.MH.MH_pkthdr |
|
253 #define m_ext M_dat.MH.MH_dat.MH_ext |
|
254 #define m_pktdat M_dat.MH.MH_dat.MH_databuf |
|
255 #define m_dat M_dat.M_databuf |
|
256 |
|
257 |
|
258 /* |
|
259 * mbuf flags. |
|
260 */ |
|
261 #define M_EXT 0x0001 /* has associated external storage */ |
|
262 #define M_PKTHDR 0x0002 /* start of record */ |
|
263 #define M_EOR 0x0004 /* end of record */ |
|
264 #define M_RDONLY 0x0008 /* associated data is marked read-only */ |
|
265 #define M_PROTO1 0x0010 /* protocol-specific */ |
|
266 #define M_PROTO2 0x0020 /* protocol-specific */ |
|
267 #define M_PROTO3 0x0040 /* protocol-specific */ |
|
268 #define M_PROTO4 0x0080 /* protocol-specific */ |
|
269 #define M_PROTO5 0x0100 /* protocol-specific */ |
|
270 #define M_SKIP_FIREWALL 0x4000 /* skip firewall processing */ |
|
271 #define M_FREELIST 0x8000 /* mbuf is on the free list */ |
|
272 |
|
273 |
|
274 /* |
|
275 * Flags copied when copying m_pkthdr. |
|
276 */ |
|
277 #define M_COPYFLAGS (M_PKTHDR|M_EOR|M_RDONLY|M_PROTO1|M_PROTO1|M_PROTO2|\ |
|
278 M_PROTO3|M_PROTO4|M_PROTO5|M_SKIP_FIREWALL|\ |
|
279 M_BCAST|M_MCAST|M_FRAG|M_FIRSTFRAG|M_LASTFRAG|\ |
|
280 M_VLANTAG|M_PROMISC) |
|
281 |
|
282 |
|
283 /* |
|
284 * mbuf pkthdr flags (also stored in m_flags). |
|
285 */ |
|
286 #define M_BCAST 0x0200 /* send/received as link-level broadcast */ |
|
287 #define M_MCAST 0x0400 /* send/received as link-level multicast */ |
|
288 #define M_FRAG 0x0800 /* packet is a fragment of a larger packet */ |
|
289 #define M_FIRSTFRAG 0x1000 /* packet is first fragment */ |
|
290 #define M_LASTFRAG 0x2000 /* packet is last fragment */ |
|
291 #define M_VLANTAG 0x10000 /* ether_vtag is valid */ |
|
292 #define M_PROMISC 0x20000 /* packet was not for us */ |
|
293 #define M_NOFREE 0x40000 /* do not free mbuf - it is embedded in the cluster */ |
|
294 |
|
295 |
|
296 /* |
|
297 * External buffer types: identify ext_buf type. |
|
298 */ |
|
299 #define EXT_CLUSTER 1 /* mbuf cluster */ |
|
300 #define EXT_SFBUF 2 /* sendfile(2)'s sf_bufs */ |
|
301 #define EXT_JUMBOP 3 /* jumbo cluster 4096 bytes */ |
|
302 #define EXT_JUMBO9 4 /* jumbo cluster 9216 bytes */ |
|
303 #define EXT_JUMBO16 5 /* jumbo cluster 16184 bytes */ |
|
304 #define EXT_PACKET 6 /* mbuf+cluster from packet zone */ |
|
305 #define EXT_MBUF 7 /* external mbuf reference (M_IOVEC) */ |
|
306 #define EXT_NET_DRV 100 /* custom ext_buf provided by net driver(s) */ |
|
307 #define EXT_MOD_TYPE 200 /* custom module's ext_buf type */ |
|
308 #define EXT_DISPOSABLE 300 /* can throw this buffer away w/page flipping */ |
|
309 #define EXT_EXTREF 400 /* has externally maintained ref_cnt ptr */ |
|
310 |
|
311 |
|
312 /* |
|
313 * mbuf types. |
|
314 */ |
|
315 #define MT_NOTMBUF 0 /* USED INTERNALLY ONLY! Object is not mbuf */ |
|
316 #define MT_DATA 1 /* dynamic (data) allocation */ |
|
317 #define MT_HEADER MT_DATA /* packet header, use M_PKTHDR instead */ |
|
318 #define MT_SONAME 8 /* socket name */ |
|
319 #define MT_CONTROL 14 /* extra-data protocol message */ |
|
320 #define MT_OOBDATA 15 /* expedited data */ |
|
321 #define MT_NTYPES 16 /* number of mbuf types for mbtypes[] */ |
|
322 |
|
323 #define MT_NOINIT 255 /* Not a type but a flag to allocate |
|
324 a non-initialized mbuf */ |
|
325 |
|
326 /* |
|
327 * __Userspace__ flags like M_NOWAIT are defined in malloc.h |
|
328 * Flags like these are used in functions like uma_zalloc() |
|
329 * but don't have an equivalent in userland umem |
|
330 * Flags specifying how an allocation should be made. |
|
331 * |
|
332 * The flag to use is as follows: |
|
333 * - M_DONTWAIT or M_NOWAIT from an interrupt handler to not block allocation. |
|
334 * - M_WAIT or M_WAITOK or M_TRYWAIT from wherever it is safe to block. |
|
335 * |
|
336 * M_DONTWAIT/M_NOWAIT means that we will not block the thread explicitly and |
|
337 * if we cannot allocate immediately we may return NULL, whereas |
|
338 * M_WAIT/M_WAITOK/M_TRYWAIT means that if we cannot allocate resources we |
|
339 * will block until they are available, and thus never return NULL. |
|
340 * |
|
341 * XXX Eventually just phase this out to use M_WAITOK/M_NOWAIT. |
|
342 */ |
|
343 #define MBTOM(how) (how) |
|
344 |
|
345 void m_tag_delete(struct mbuf *, struct m_tag *); |
|
346 void m_tag_delete_chain(struct mbuf *, struct m_tag *); |
|
347 void m_move_pkthdr(struct mbuf *, struct mbuf *); |
|
348 void m_tag_free_default(struct m_tag *); |
|
349 |
|
350 extern int max_linkhdr; /* Largest link-level header */ |
|
351 extern int max_protohdr; /* Size of largest protocol layer header. See user_mbuf.c */ |
|
352 |
|
353 extern struct mbstat mbstat; /* General mbuf stats/infos */ |
|
354 |
|
355 |
|
356 /* |
|
357 * Evaluate TRUE if it's safe to write to the mbuf m's data region (this can |
|
358 * be both the local data payload, or an external buffer area, depending on |
|
359 * whether M_EXT is set). |
|
360 */ |
|
361 #define M_WRITABLE(m) (!((m)->m_flags & M_RDONLY) && \ |
|
362 (!(((m)->m_flags & M_EXT)) || \ |
|
363 (*((m)->m_ext.ref_cnt) == 1)) ) \ |
|
364 |
|
365 |
|
366 /* |
|
367 * Compute the amount of space available before the current start of data in |
|
368 * an mbuf. |
|
369 * |
|
370 * The M_WRITABLE() is a temporary, conservative safety measure: the burden |
|
371 * of checking writability of the mbuf data area rests solely with the caller. |
|
372 */ |
|
373 #define M_LEADINGSPACE(m) \ |
|
374 ((m)->m_flags & M_EXT ? \ |
|
375 (M_WRITABLE(m) ? (m)->m_data - (m)->m_ext.ext_buf : 0): \ |
|
376 (m)->m_flags & M_PKTHDR ? (m)->m_data - (m)->m_pktdat : \ |
|
377 (m)->m_data - (m)->m_dat) |
|
378 |
|
379 /* |
|
380 * Compute the amount of space available after the end of data in an mbuf. |
|
381 * |
|
382 * The M_WRITABLE() is a temporary, conservative safety measure: the burden |
|
383 * of checking writability of the mbuf data area rests solely with the caller. |
|
384 */ |
|
385 #define M_TRAILINGSPACE(m) \ |
|
386 ((m)->m_flags & M_EXT ? \ |
|
387 (M_WRITABLE(m) ? (m)->m_ext.ext_buf + (m)->m_ext.ext_size \ |
|
388 - ((m)->m_data + (m)->m_len) : 0) : \ |
|
389 &(m)->m_dat[MLEN] - ((m)->m_data + (m)->m_len)) |
|
390 |
|
391 |
|
392 |
|
393 /* |
|
394 * Arrange to prepend space of size plen to mbuf m. If a new mbuf must be |
|
395 * allocated, how specifies whether to wait. If the allocation fails, the |
|
396 * original mbuf chain is freed and m is set to NULL. |
|
397 */ |
|
398 #define M_PREPEND(m, plen, how) do { \ |
|
399 struct mbuf **_mmp = &(m); \ |
|
400 struct mbuf *_mm = *_mmp; \ |
|
401 int _mplen = (plen); \ |
|
402 int __mhow = (how); \ |
|
403 \ |
|
404 if (M_LEADINGSPACE(_mm) >= _mplen) { \ |
|
405 _mm->m_data -= _mplen; \ |
|
406 _mm->m_len += _mplen; \ |
|
407 } else \ |
|
408 _mm = m_prepend(_mm, _mplen, __mhow); \ |
|
409 if (_mm != NULL && _mm->m_flags & M_PKTHDR) \ |
|
410 _mm->m_pkthdr.len += _mplen; \ |
|
411 *_mmp = _mm; \ |
|
412 } while (0) |
|
413 |
|
414 /* |
|
415 * Set the m_data pointer of a newly-allocated mbuf (m_get/MGET) to place an |
|
416 * object of the specified size at the end of the mbuf, longword aligned. |
|
417 */ |
|
418 #define M_ALIGN(m, len) do { \ |
|
419 KASSERT(!((m)->m_flags & (M_PKTHDR|M_EXT)), \ |
|
420 ("%s: M_ALIGN not normal mbuf", __func__)); \ |
|
421 KASSERT((m)->m_data == (m)->m_dat, \ |
|
422 ("%s: M_ALIGN not a virgin mbuf", __func__)); \ |
|
423 (m)->m_data += (MLEN - (len)) & ~(sizeof(long) - 1); \ |
|
424 } while (0) |
|
425 |
|
426 /* |
|
427 * As above, for mbufs allocated with m_gethdr/MGETHDR or initialized by |
|
428 * M_DUP/MOVE_PKTHDR. |
|
429 */ |
|
430 #define MH_ALIGN(m, len) do { \ |
|
431 KASSERT((m)->m_flags & M_PKTHDR && !((m)->m_flags & M_EXT), \ |
|
432 ("%s: MH_ALIGN not PKTHDR mbuf", __func__)); \ |
|
433 KASSERT((m)->m_data == (m)->m_pktdat, \ |
|
434 ("%s: MH_ALIGN not a virgin mbuf", __func__)); \ |
|
435 (m)->m_data += (MHLEN - (len)) & ~(sizeof(long) - 1); \ |
|
436 } while (0) |
|
437 |
|
438 #endif |