xref: /haiku/src/libs/compat/freebsd_network/mbuf.c (revision e6b30aee0fd7a23d6a6baab9f3718945a0cd838a)
1 /*
2  * Copyright 2007, Hugo Santos. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *      Hugo Santos, hugosantos@gmail.com
7  *
8  * Some of this code is based on previous work by Marcus Overhagen.
9  *
10  * `m_defrag' and friends are straight from FreeBSD 6.2.
11  */
12 
13 #include "device.h"
14 
15 #include <stdint.h>
16 #include <string.h>
17 #include <slab/Slab.h>
18 
19 #include <compat/sys/mbuf.h>
20 #include <compat/sys/kernel.h>
21 
22 static object_cache *sMBufCache;
23 static object_cache *sChunkCache;
24 
25 int max_linkhdr = 16;
26 int max_protohdr = 40 + 20; /* ip6 + tcp */
27 
28 
29 static int
30 m_to_oc_flags(int how)
31 {
32 	if (how & M_NOWAIT)
33 		return CACHE_DONT_SLEEP;
34 
35 	return 0;
36 }
37 
38 
39 static int
40 construct_mbuf(struct mbuf *mb, short type, int flags)
41 {
42 	mb->m_next = NULL;
43 	mb->m_nextpkt = NULL;
44 	mb->m_len = 0;
45 	mb->m_flags = flags;
46 	mb->m_type = type;
47 
48 	if (flags & M_PKTHDR) {
49 		mb->m_data = mb->m_pktdat;
50 		memset(&mb->m_pkthdr, 0, sizeof(mb->m_pkthdr));
51 		/* SLIST_INIT(&m->m_pkthdr.tags); */
52 	} else {
53 		mb->m_data = mb->m_dat;
54 	}
55 
56 	return 0;
57 }
58 
59 
60 static int
61 construct_ext_mbuf(struct mbuf *mb, int how)
62 {
63 	mb->m_ext.ext_buf = object_cache_alloc(sChunkCache, m_to_oc_flags(how));
64 	if (mb->m_ext.ext_buf == NULL)
65 		return B_NO_MEMORY;
66 
67 	mb->m_data = mb->m_ext.ext_buf;
68 	mb->m_flags |= M_EXT;
69 	/* mb->m_ext.ext_free = NULL; */
70 	/* mb->m_ext.ext_args = NULL; */
71 	mb->m_ext.ext_size = MCLBYTES;
72 	mb->m_ext.ext_type = EXT_CLUSTER;
73 	/* mb->m_ext.ref_cnt = NULL; */
74 
75 	return 0;
76 }
77 
78 
79 static int
80 construct_pkt_mbuf(int how, struct mbuf *mb, short type, int flags)
81 {
82 	construct_mbuf(mb, type, flags);
83 	if (construct_ext_mbuf(mb, how) < 0)
84 		return -1;
85 	mb->m_ext.ext_type = EXT_PACKET;
86 	return 0;
87 }
88 
89 
90 static void
91 destruct_pkt_mbuf(struct mbuf *mb)
92 {
93 	object_cache_free(sChunkCache, mb->m_ext.ext_buf);
94 	mb->m_ext.ext_buf = NULL;
95 }
96 
97 
98 struct mbuf *
99 m_getcl(int how, short type, int flags)
100 {
101 	struct mbuf *mb =
102 		(struct mbuf *)object_cache_alloc(sMBufCache, m_to_oc_flags(how));
103 	if (mb == NULL)
104 		return NULL;
105 
106 	if (construct_pkt_mbuf(how, mb, type, flags) < 0) {
107 		object_cache_free(sMBufCache, mb);
108 		return NULL;
109 	}
110 
111 	return mb;
112 }
113 
114 
115 static struct mbuf *
116 _m_get(int how, short type, int flags)
117 {
118 	struct mbuf *mb =
119 		(struct mbuf *)object_cache_alloc(sMBufCache, m_to_oc_flags(how));
120 	if (mb == NULL)
121 		return NULL;
122 
123 	construct_mbuf(mb, type, flags);
124 
125 	return mb;
126 }
127 
128 
129 struct mbuf *
130 m_get(int how, short type)
131 {
132 	return _m_get(how, type, 0);
133 }
134 
135 
136 struct mbuf *
137 m_gethdr(int how, short type)
138 {
139 	return _m_get(how, type, M_PKTHDR);
140 }
141 
142 
143 void
144 m_clget(struct mbuf *m, int how)
145 {
146 	m->m_ext.ext_buf = NULL;
147 	/* called checks for errors by looking for M_EXT */
148 	construct_ext_mbuf(m, how);
149 }
150 
151 
152 void
153 m_freem(struct mbuf *mb)
154 {
155 	while (mb)
156 		mb = m_free(mb);
157 }
158 
159 
160 static void
161 mb_free_ext(struct mbuf *m)
162 {
163 	/*
164 	if (m->m_ext.ref_count != NULL)
165 		panic("unsupported");
166 		*/
167 
168 	if (m->m_ext.ext_type == EXT_PACKET)
169 		destruct_pkt_mbuf(m);
170 	else if (m->m_ext.ext_type == EXT_CLUSTER) {
171 		object_cache_free(sChunkCache, m->m_ext.ext_buf);
172 		m->m_ext.ext_buf = NULL;
173 	} else
174 		panic("unknown type");
175 
176 	object_cache_free(sMBufCache, m);
177 }
178 
179 
180 struct mbuf *
181 m_free(struct mbuf *m)
182 {
183 	struct mbuf *next = m->m_next;
184 
185 	if (m->m_flags & M_EXT)
186 		mb_free_ext(m);
187 	else
188 		object_cache_free(sMBufCache, m);
189 
190 	return next;
191 }
192 
193 
194 void
195 m_extadd(struct mbuf *m, caddr_t buffer, u_int size,
196     void (*freeHook)(void *, void *), void *args, int flags, int type)
197 {
198 	// TODO: implement?
199 	panic("m_extadd() called.");
200 }
201 
202 
203 status_t
204 init_mbufs()
205 {
206 	sMBufCache = create_object_cache("mbufs", MSIZE, 8, NULL, NULL, NULL);
207 	if (sMBufCache == NULL)
208 		return B_NO_MEMORY;
209 
210 	sChunkCache = create_object_cache("mbuf chunks", MCLBYTES, 0, NULL, NULL,
211 		NULL);
212 	if (sChunkCache == NULL) {
213 		delete_object_cache(sMBufCache);
214 		return B_NO_MEMORY;
215 	}
216 
217 	return B_OK;
218 }
219 
220 
221 void
222 uninit_mbufs()
223 {
224 	delete_object_cache(sMBufCache);
225 	delete_object_cache(sChunkCache);
226 }
227 
228