VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/slirp/mbuf.c@ 23930

Last change on this file since 23930 was 23490, checked in by vboxsync, 15 years ago

NAT: init mbuf header while initialization of mbuf_zone.

  • Property svn:eol-style set to native
File size: 8.7 KB
Line 
1/*
2 * Copyright (c) 1995 Danny Gasparovski
3 *
4 * Please read the file COPYRIGHT for the
5 * terms and conditions of the copyright.
6 */
7
8/*
9 * mbuf's in SLiRP are much simpler than the real mbufs in
10 * FreeBSD. They are fixed size, determined by the MTU,
11 * so that one whole packet can fit. Mbuf's cannot be
12 * chained together. If there's more data than the mbuf
13 * could hold, an external malloced buffer is pointed to
14 * by m_ext (and the data pointers) and M_EXT is set in
15 * the flags
16 */
17#include <slirp.h>
18
19#define MBUF_ZONE_SIZE 100
20static int mbuf_zone_init(PNATState pData)
21{
22 int limit;
23 struct mbuf_zone *mzone;
24 int i;
25 struct mbuf *m;
26 uint8_t *zone = RTMemAlloc(msize * MBUF_ZONE_SIZE);
27 if (zone == NULL)
28 {
29 LogRel(("NAT: can't allocate new zone\n"));
30 return -1;
31 }
32 mzone = RTMemAllocZ(sizeof (struct mbuf_zone));
33 if (mzone == NULL)
34 {
35 RTMemFree(zone);
36 LogRel(("NAT: can't allocate zone descriptor\n"));
37 return -1;
38 }
39
40 for(i = 0; i < MBUF_ZONE_SIZE; ++i)
41 {
42 m = (struct mbuf *)((char *)zone + i*msize);
43 memset(m, 0, sizeof(struct mbuf));
44#ifdef M_BUF_DEBUG
45 m->m_hdr.mh_id = pData->mbuf_zone_count * MBUF_ZONE_SIZE + i;
46#endif
47 insque(pData, m, &m_freelist);
48 }
49 mzone->mbuf_zone_base_addr = zone;
50 LIST_INSERT_HEAD(&pData->mbuf_zone_head, mzone, list);
51 pData->mbuf_zone_count++;
52 pData->mbuf_water_line_limit = pData->mbuf_zone_count * MBUF_ZONE_SIZE;
53 return 0;
54}
55
56void m_fini(PNATState pData)
57{
58 struct mbuf_zone *mz;
59 struct mbuf *m;
60 int i;
61 void *zone;
62 while(!LIST_EMPTY(&pData->mbuf_zone_head))
63 {
64 mz = LIST_FIRST(&pData->mbuf_zone_head);
65 zone = mz->mbuf_zone_base_addr;
66 for(i = 0; i < MBUF_ZONE_SIZE; ++i)
67 {
68 m = (struct mbuf *)((char *)zone + i*msize);
69 if ( (m->m_flags & M_EXT)
70 && m->m_ext != NULL)
71 RTMemFree(m->m_ext);
72 }
73 RTMemFree(zone);
74 LIST_REMOVE(mz, list);
75 RTMemFree(mz);
76 }
77}
78
79void
80m_init(PNATState pData)
81{
82 int i;
83 struct mbuf *m;
84 int rc = 0;
85 m_freelist.m_next = m_freelist.m_prev = &m_freelist;
86 m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist;
87 mbuf_alloced = 0;
88 msize_init(pData);
89#if 1
90 rc = RTCritSectInit(&pData->cs_mbuf_zone);
91 AssertReleaseRC(rc);
92 rc = mbuf_zone_init(pData);
93 Assert((rc == 0));
94#endif
95}
96
97void
98msize_init(PNATState pData)
99{
100 /*
101 * Find a nice value for msize
102 */
103 msize = (if_mtu>if_mru ? if_mtu : if_mru)
104 + sizeof(struct m_hdr) + sizeof(void *) /*pointer to the backstore*/
105 + if_maxlinkhdr ;
106}
107#ifdef m_get
108# undef m_get
109#endif
110
111#ifdef m_free
112# undef m_free
113#endif
114/*
115 * Get an mbuf from the free list, if there are none
116 * malloc one
117 *
118 * Because fragmentation can occur if we alloc new mbufs and
119 * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE,
120 * which tells m_free to actually free() it
121 */
122struct mbuf *
123m_get(PNATState pData)
124{
125 register struct mbuf *m;
126 int flags = 0;
127 int rc = 0;
128
129 DEBUG_CALL("m_get");
130
131 rc = RTCritSectEnter(&pData->cs_mbuf_zone);
132 AssertReleaseRC(rc);
133
134recheck_zone:
135 if (m_freelist.m_next == &m_freelist)
136 {
137#if 1
138 int rc = mbuf_zone_init(pData);
139 if (rc == 0)
140 goto recheck_zone;
141 AssertMsgFailed(("No mbufs on free list\n"));
142 return NULL;
143#else
144 m = (struct mbuf *)RTMemAlloc(msize);
145 if (m == NULL)
146 goto end_error;
147 mbuf_alloced++;
148 if (mbuf_alloced > mbuf_thresh)
149 flags = M_DOFREE;
150 if (mbuf_alloced > mbuf_max)
151 mbuf_max = mbuf_alloced;
152#endif
153 }
154 else
155 {
156 m = m_freelist.m_next;
157 remque(pData, m);
158 }
159
160 STAM_COUNTER_INC(&pData->StatMBufAllocation);
161 /* Insert it in the used list */
162 mbuf_alloced++;
163 if (mbuf_alloced >= MBUF_ZONE_SIZE/2)
164 {
165 pData->fmbuf_water_line = 1;
166 }
167 insque(pData, m, &m_usedlist);
168 m->m_flags = (flags | M_USEDLIST);
169
170 /* Initialise it */
171 m->m_size = msize - sizeof(struct m_hdr);
172 m->m_data = m->m_dat;
173 m->m_len = 0;
174 m->m_nextpkt = 0;
175 m->m_prevpkt = 0;
176 m->m_la = NULL;
177 memset(m->m_data, 0, if_maxlinkhdr); /*initialization of ether area */
178
179end_error:
180 DEBUG_ARG("m = %lx", (long )m);
181 rc = RTCritSectLeave(&pData->cs_mbuf_zone);
182 AssertReleaseRC(rc);
183 return m;
184}
185
186void
187m_free(PNATState pData, struct mbuf *m)
188{
189 int rc;
190 DEBUG_CALL("m_free");
191 DEBUG_ARG("m = %lx", (long )m);
192
193 rc = RTCritSectEnter(&pData->cs_mbuf_zone);
194 AssertReleaseRC(rc);
195 mbuf_alloced--;
196 if(m)
197 {
198 /* Remove from m_usedlist */
199 if (m->m_flags & M_USEDLIST)
200 remque(pData, m);
201
202 /* If it's M_EXT, free() it */
203 if (m->m_flags & M_EXT)
204 RTMemFree(m->m_ext);
205
206 /*
207 * Either free() it or put it on the free list
208 */
209 if (m->m_flags & M_DOFREE)
210 {
211#if 1
212 if ((m->m_flags & M_EXT) == 0)
213 memset(m->m_dat, 0, if_mtu);
214 insque(pData, m, &m_freelist);
215 m->m_flags = M_FREELIST; /* Clobber other flags */
216#else
217 RTMemFree(m);
218#endif
219 mbuf_alloced--;
220 }
221 else if ((m->m_flags & M_FREELIST) == 0)
222 {
223 insque(pData, m,&m_freelist);
224 m->m_flags = M_FREELIST; /* Clobber other flags */
225 }
226 STAM_COUNTER_INC(&pData->StatMBufAllocation);
227 } /* if(m) */
228 rc = RTCritSectLeave(&pData->cs_mbuf_zone);
229 AssertReleaseRC(rc);
230}
231
232/* update macros for m_get/m_free*/
233#undef m_get
234#undef m_free
235#include "mbuf.h"
236
237/*
238 * Copy data from one mbuf to the end of
239 * the other.. if result is too big for one mbuf, malloc()
240 * an M_EXT data segment
241 */
242void
243m_cat(PNATState pData, register struct mbuf *m, register struct mbuf *n)
244{
245 /*
246 * If there's no room, realloc
247 */
248 if (M_FREEROOM(m) < n->m_len)
249 m_inc(m,m->m_size+MINCSIZE);
250
251 memcpy(m->m_data+m->m_len, n->m_data, n->m_len);
252 m->m_len += n->m_len;
253
254 m_free(pData, n);
255}
256
257
258/* make m size bytes large */
259void
260m_inc(struct mbuf *m, int size)
261{
262 int datasize;
263
264 /* some compiles throw up on gotos. This one we can fake. */
265 if (m->m_size > size)
266 return;
267
268 if (m->m_flags & M_EXT)
269 {
270 datasize = m->m_data - m->m_ext;
271 m->m_ext = (char *)RTMemRealloc(m->m_ext, size);
272#if 0
273 if (m->m_ext == NULL)
274 return (struct mbuf *)NULL;
275#endif
276 m->m_data = m->m_ext + datasize;
277 }
278 else
279 {
280 char *dat;
281 datasize = m->m_data - m->m_dat;
282 dat = (char *)RTMemAlloc(size);
283#if 0
284 if (dat == NULL)
285 return (struct mbuf *)NULL;
286#endif
287 memcpy(dat, m->m_dat, m->m_size);
288
289 m->m_ext = dat;
290 m->m_data = m->m_ext + datasize;
291 m->m_flags |= M_EXT;
292 }
293
294 m->m_size = size;
295}
296
297
298void
299m_adj(struct mbuf *m, int len)
300{
301 if (m == NULL)
302 return;
303 if (len >= 0)
304 {
305 /* Trim from head */
306 m->m_data += len;
307 m->m_len -= len;
308 }
309 else
310 {
311 /* Trim from tail */
312 len = -len;
313 m->m_len -= len;
314 }
315 Assert(m->m_len >= 0);
316}
317
318
319/*
320 * Copy len bytes from m, starting off bytes into n
321 */
322int
323m_copy(struct mbuf *n, struct mbuf *m, int off, int len)
324{
325 if (len > M_FREEROOM(n))
326 return -1;
327
328 memcpy((n->m_data + n->m_len), (m->m_data + off), len);
329 n->m_len += len;
330 return 0;
331}
332
333
334/*
335 * Given a pointer into an mbuf, return the mbuf
336 * XXX This is a kludge, I should eliminate the need for it
337 * Fortunately, it's not used often
338 */
339struct mbuf *
340dtom(PNATState pData, void *dat)
341{
342 struct mbuf *m;
343
344 DEBUG_CALL("dtom");
345 DEBUG_ARG("dat = %lx", (long )dat);
346
347 /* bug corrected for M_EXT buffers */
348 for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next)
349 {
350 if (m->m_flags & M_EXT)
351 {
352 if ( (char *)dat >= m->m_ext
353 && (char *)dat < (m->m_ext + m->m_size))
354 return m;
355 }
356 else
357 {
358 if ( (char *)dat >= m->m_dat
359 && (char *)dat < (m->m_dat + m->m_size))
360 return m;
361 }
362 }
363
364 DEBUG_ERROR((dfd, "dtom failed"));
365
366 return (struct mbuf *)0;
367}
368#ifndef VBOX_WITH_SLIRP_BSD_MBUF
369void *slirp_ext_m_get(PNATState pData)
370{
371 return (void *)m_get(pData);
372}
373
374void slirp_ext_m_free(PNATState pData, void *arg)
375{
376 struct mbuf *m = (struct mbuf *)arg;
377 m_free(pData, m);
378}
379void slirp_ext_m_append(PNATState pData, void *arg, uint8_t *pu8Buf, size_t cbBuf)
380{
381 char *c;
382 struct mbuf *m = (struct mbuf *)arg;
383 if (cbBuf > M_FREEROOM(m))
384 {
385 m_inc(m, cbBuf);
386 }
387 c = mtod(m, char *);
388 memcpy(c, pu8Buf, cbBuf);
389 m->m_len = cbBuf;
390}
391#endif
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette