xref: /haiku/src/libs/compat/freebsd_network/mbuf.c (revision 893988af824e65e49e55f517b157db8386e8002b)
1 /*
2  * Copyright 2007, Hugo Santos. All Rights Reserved.
3  * Copyright 2004, Marcus Overhagen. All Rights Reserved.
4  *
5  * Distributed under the terms of the MIT License.
6  */
7 
8 #include "device.h"
9 
10 #include <stdint.h>
11 #include <string.h>
12 #include <slab/Slab.h>
13 
14 #include <compat/sys/mbuf.h>
15 #include <compat/sys/kernel.h>
16 
17 
18 static object_cache *sMBufCache;
19 static object_cache *sChunkCache;
20 static object_cache *sJumbo9ChunkCache;
21 
22 
23 int max_linkhdr = 16;
24 int max_protohdr = 40 + 20; /* ip6 + tcp */
25 
26 /* max_linkhdr + max_protohdr, but that's not allowed by gcc. */
27 int max_hdr = 16 + 40 + 20;
28 
29 
30 static int
31 m_to_oc_flags(int how)
32 {
33 	if (how & M_NOWAIT)
34 		return CACHE_DONT_SLEEP;
35 
36 	return 0;
37 }
38 
39 
40 static int
41 construct_mbuf(struct mbuf *mb, short type, int flags)
42 {
43 	mb->m_next = NULL;
44 	mb->m_nextpkt = NULL;
45 	mb->m_len = 0;
46 	mb->m_flags = flags;
47 	mb->m_type = type;
48 
49 	if (flags & M_PKTHDR) {
50 		mb->m_data = mb->m_pktdat;
51 		memset(&mb->m_pkthdr, 0, sizeof(mb->m_pkthdr));
52 		/* SLIST_INIT(&m->m_pkthdr.tags); */
53 	} else {
54 		mb->m_data = mb->m_dat;
55 	}
56 
57 	return 0;
58 }
59 
60 
61 static int
62 construct_ext_sized_mbuf(struct mbuf *mb, int how, int size)
63 {
64 	object_cache *cache;
65 	int extType;
66 	if (size != MCLBYTES && size != MJUM9BYTES)
67 		panic("unsupported size");
68 
69 	if (size == MCLBYTES) {
70 		cache = sChunkCache;
71 		extType = EXT_CLUSTER;
72 	} else {
73 		cache = sJumbo9ChunkCache;
74 		extType = EXT_JUMBO9;
75 	}
76 	mb->m_ext.ext_buf = object_cache_alloc(cache, m_to_oc_flags(how));
77 	if (mb->m_ext.ext_buf == NULL)
78 		return B_NO_MEMORY;
79 
80 	mb->m_data = mb->m_ext.ext_buf;
81 	mb->m_flags |= M_EXT;
82 	/* mb->m_ext.ext_free = NULL; */
83 	/* mb->m_ext.ext_args = NULL; */
84 	mb->m_ext.ext_size = size;
85 	mb->m_ext.ext_type = extType;
86 	/* mb->m_ext.ref_cnt = NULL; */
87 
88 	return 0;
89 }
90 
91 
92 static inline int
93 construct_ext_mbuf(struct mbuf *mb, int how)
94 {
95 	return construct_ext_sized_mbuf(mb, how, MCLBYTES);
96 }
97 
98 
99 static int
100 construct_pkt_mbuf(int how, struct mbuf *mb, short type, int flags)
101 {
102 	construct_mbuf(mb, type, flags);
103 	if (construct_ext_mbuf(mb, how) < 0)
104 		return -1;
105 	mb->m_ext.ext_type |= EXT_PACKET;
106 	return 0;
107 }
108 
109 
110 static void
111 destruct_pkt_mbuf(struct mbuf *mb)
112 {
113 	object_cache *cache;
114 	if ((mb->m_ext.ext_type & EXT_CLUSTER) != 0)
115 		cache = sChunkCache;
116 	else if ((mb->m_ext.ext_type & EXT_JUMBO9) != 0)
117 		cache = sJumbo9ChunkCache;
118 	else {
119 		panic("unknown cache");
120 		return;
121 	}
122 
123 	object_cache_free(cache, mb->m_ext.ext_buf);
124 	mb->m_ext.ext_buf = NULL;
125 }
126 
127 
128 struct mbuf *
129 m_getcl(int how, short type, int flags)
130 {
131 	struct mbuf *mb =
132 		(struct mbuf *)object_cache_alloc(sMBufCache, m_to_oc_flags(how));
133 	if (mb == NULL)
134 		return NULL;
135 
136 	if (construct_pkt_mbuf(how, mb, type, flags) < 0) {
137 		object_cache_free(sMBufCache, mb);
138 		return NULL;
139 	}
140 
141 	return mb;
142 }
143 
144 
145 static struct mbuf *
146 _m_get(int how, short type, int flags)
147 {
148 	struct mbuf *mb =
149 		(struct mbuf *)object_cache_alloc(sMBufCache, m_to_oc_flags(how));
150 	if (mb == NULL)
151 		return NULL;
152 
153 	construct_mbuf(mb, type, flags);
154 
155 	return mb;
156 }
157 
158 
159 struct mbuf *
160 m_get(int how, short type)
161 {
162 	return _m_get(how, type, 0);
163 }
164 
165 
166 struct mbuf *
167 m_gethdr(int how, short type)
168 {
169 	return _m_get(how, type, M_PKTHDR);
170 }
171 
172 
173 struct mbuf *
174 m_getjcl(int how, short type, int flags, int size)
175 {
176 	struct mbuf *mb =
177 		(struct mbuf *)object_cache_alloc(sMBufCache, m_to_oc_flags(how));
178 	if (mb == NULL)
179 		return NULL;
180 	if (construct_ext_sized_mbuf(mb, how, size) < 0) {
181 		object_cache_free(sMBufCache, mb);
182 		return NULL;
183 	}
184 	mb->m_flags |= flags;
185 	return mb;
186 }
187 
188 
189 void
190 m_clget(struct mbuf *m, int how)
191 {
192 	m->m_ext.ext_buf = NULL;
193 	/* called checks for errors by looking for M_EXT */
194 	construct_ext_mbuf(m, how);
195 }
196 
197 
198 void *
199 m_cljget(struct mbuf *m, int how, int size)
200 {
201 	if (m == NULL)
202 		panic("m_cljget doesn't support allocate mbuf");
203 	m->m_ext.ext_buf = NULL;
204 	construct_ext_sized_mbuf(m, how, size);
205 	/* shouldn't be used */
206 	return NULL;
207 }
208 
209 
210 void
211 m_freem(struct mbuf *mb)
212 {
213 	while (mb)
214 		mb = m_free(mb);
215 }
216 
217 
218 static void
219 mb_free_ext(struct mbuf *m)
220 {
221 	/*
222 	if (m->m_ext.ref_count != NULL)
223 		panic("unsupported");
224 	*/
225 
226 	if (m->m_ext.ext_type == EXT_PACKET)
227 		destruct_pkt_mbuf(m);
228 	else if (m->m_ext.ext_type == EXT_CLUSTER) {
229 		object_cache_free(sChunkCache, m->m_ext.ext_buf);
230 		m->m_ext.ext_buf = NULL;
231 	} else if (m->m_ext.ext_type == EXT_JUMBO9) {
232 		object_cache_free(sJumbo9ChunkCache, m->m_ext.ext_buf);
233 		m->m_ext.ext_buf = NULL;
234 	} else
235 		panic("unknown type");
236 
237 	object_cache_free(sMBufCache, m);
238 }
239 
240 
241 struct mbuf *
242 m_free(struct mbuf *m)
243 {
244 	struct mbuf *next = m->m_next;
245 
246 	if (m->m_flags & M_EXT)
247 		mb_free_ext(m);
248 	else
249 		object_cache_free(sMBufCache, m);
250 
251 	return next;
252 }
253 
254 
255 void
256 m_extadd(struct mbuf *m, caddr_t buffer, u_int size,
257     void (*freeHook)(void *, void *), void *args, int flags, int type)
258 {
259 	// TODO: implement?
260 	panic("m_extadd() called.");
261 }
262 
263 
264 status_t
265 init_mbufs(void)
266 {
267 	sMBufCache = create_object_cache("mbufs", MSIZE, 8, NULL, NULL, NULL);
268 	if (sMBufCache == NULL)
269 		goto clean;
270 	sChunkCache = create_object_cache("mbuf chunks", MCLBYTES, 0, NULL, NULL,
271 		NULL);
272 	if (sChunkCache == NULL)
273 		goto clean;
274 	sJumbo9ChunkCache = create_object_cache("mbuf jumbo9 chunks", MJUM9BYTES, 0,
275 		NULL, NULL, NULL);
276 	if (sJumbo9ChunkCache == NULL)
277 		goto clean;
278 	return B_OK;
279 
280 clean:
281 	if (sChunkCache != NULL)
282 		delete_object_cache(sChunkCache);
283 	if (sMBufCache != NULL)
284 		delete_object_cache(sMBufCache);
285 	return B_NO_MEMORY;
286 }
287 
288 
289 void
290 uninit_mbufs(void)
291 {
292 	delete_object_cache(sMBufCache);
293 	delete_object_cache(sChunkCache);
294 	delete_object_cache(sJumbo9ChunkCache);
295 }
296 
297