VirtualBox

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

最後變更 在這個檔案從27797是 27797,由 vboxsync 提交於 15 年 前

misc compiler warning fixes, comment typos and other minor cleanups

  • 屬性 svn:eol-style 設為 native
檔案大小: 9.1 KB
 
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 struct mbuf_zone *mzone;
23 int i;
24 struct mbuf *m;
25 uint8_t *zone = RTMemAlloc(msize * MBUF_ZONE_SIZE);
26 if (zone == NULL)
27 {
28 LogRel(("NAT: can't allocate new zone\n"));
29 return -1;
30 }
31 mzone = RTMemAllocZ(sizeof (struct mbuf_zone));
32 if (mzone == NULL)
33 {
34 RTMemFree(zone);
35 LogRel(("NAT: can't allocate zone descriptor\n"));
36 return -1;
37 }
38
39 for (i = 0; i < MBUF_ZONE_SIZE; ++i)
40 {
41 m = (struct mbuf *)((char *)zone + i*msize);
42 memset(m, 0, sizeof(struct mbuf));
43#ifdef M_BUF_DEBUG
44 m->m_hdr.mh_id = pData->mbuf_zone_count * MBUF_ZONE_SIZE + i;
45#endif
46 insque(pData, m, &m_freelist);
47 }
48 mzone->mbuf_zone_base_addr = zone;
49 LIST_INSERT_HEAD(&pData->mbuf_zone_head, mzone, list);
50 pData->mbuf_zone_count++;
51 pData->mbuf_water_line_limit = pData->mbuf_zone_count * MBUF_ZONE_SIZE;
52 return 0;
53}
54
55void m_fini(PNATState pData)
56{
57 struct mbuf_zone *mz;
58 struct mbuf *m;
59 int i;
60 void *zone;
61 while(!LIST_EMPTY(&pData->mbuf_zone_head))
62 {
63 mz = LIST_FIRST(&pData->mbuf_zone_head);
64 zone = mz->mbuf_zone_base_addr;
65 for (i = 0; i < MBUF_ZONE_SIZE; ++i)
66 {
67 m = (struct mbuf *)((char *)zone + i*msize);
68 if ( (m->m_flags & M_EXT)
69 && m->m_ext != NULL)
70 RTMemFree(m->m_ext);
71 }
72 RTMemFree(zone);
73 LIST_REMOVE(mz, list);
74 RTMemFree(mz);
75 }
76}
77
78void
79m_init(PNATState pData)
80{
81 int rc = 0;
82 m_freelist.m_next = m_freelist.m_prev = &m_freelist;
83 m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist;
84 mbuf_alloced = 0;
85 msize_init(pData);
86#if 1
87 rc = RTCritSectInit(&pData->cs_mbuf_zone);
88 AssertRC(rc);
89 rc = mbuf_zone_init(pData);
90 Assert((rc == 0));
91#endif
92}
93
94void
95msize_init(PNATState pData)
96{
97 /*
98 * Find a nice value for msize
99 */
100 msize = (if_mtu>if_mru ? if_mtu : if_mru)
101 + sizeof(struct m_hdr) + sizeof(void *) /*pointer to the backstore*/
102 + if_maxlinkhdr ;
103}
104#ifdef m_get
105# undef m_get
106#endif
107
108#ifdef m_free
109# undef m_free
110#endif
111/*
112 * Get an mbuf from the free list, if there are none
113 * malloc one
114 *
115 * Because fragmentation can occur if we alloc new mbufs and
116 * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE,
117 * which tells m_free to actually free() it
118 */
119struct mbuf *
120m_get(PNATState pData)
121{
122 register struct mbuf *m;
123 int flags = 0;
124 int rc = 0;
125
126 DEBUG_CALL("m_get");
127
128 rc = RTCritSectEnter(&pData->cs_mbuf_zone);
129 AssertRC(rc);
130
131recheck_zone:
132 if (m_freelist.m_next == &m_freelist)
133 {
134#if 1
135 rc = mbuf_zone_init(pData);
136 if (rc == 0)
137 goto recheck_zone;
138 AssertMsgFailed(("No mbufs on free list\n"));
139 m = NULL;
140 goto end_error;
141#else
142 m = (struct mbuf *)RTMemAlloc(msize);
143 if (m == NULL)
144 goto end_error;
145 mbuf_alloced++;
146 if (mbuf_alloced > mbuf_thresh)
147 flags = M_DOFREE;
148 if (mbuf_alloced > mbuf_max)
149 mbuf_max = mbuf_alloced;
150#endif
151 }
152 else
153 {
154 m = m_freelist.m_next;
155 remque(pData, m);
156 }
157
158 STAM_COUNTER_INC(&pData->StatMBufAllocation);
159 /* Insert it in the used list */
160 mbuf_alloced++;
161#if 0
162 if (mbuf_alloced >= MBUF_ZONE_SIZE/2)
163 {
164 pData->fmbuf_water_line = 1;
165 }
166#endif
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 AssertRC(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 AssertRC(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 AssertRC(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 void *pvNew;
271 datasize = m->m_data - m->m_ext;
272 pvNew = (char *)RTMemRealloc(m->m_ext, size);
273 if (pvNew)
274 return; /** @todo better error reporting. */
275 m->m_ext = (char *)pvNew;
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 (!dat)
284 return; /** @todo better error reporting. */
285 memcpy(dat, m->m_dat, m->m_size);
286
287 m->m_ext = dat;
288 m->m_data = m->m_ext + datasize;
289 m->m_flags |= M_EXT;
290 }
291
292 m->m_size = size;
293}
294
295
296void
297m_adj(struct mbuf *m, int len)
298{
299 if (m == NULL)
300 return;
301 if (len >= 0)
302 {
303 /* Trim from head */
304 m->m_data += len;
305 m->m_len -= len;
306 }
307 else
308 {
309 /* Trim from tail */
310 len = -len;
311 m->m_len -= len;
312 }
313 Assert(m->m_len >= 0);
314}
315
316
317/*
318 * Copy len bytes from m, starting off bytes into n
319 */
320int
321m_copy(struct mbuf *n, struct mbuf *m, int off, int len)
322{
323 if (len > M_FREEROOM(n))
324 return -1;
325
326 memcpy((n->m_data + n->m_len), (m->m_data + off), len);
327 n->m_len += len;
328 return 0;
329}
330
331
332/*
333 * Given a pointer into an mbuf, return the mbuf
334 * XXX This is a kludge, I should eliminate the need for it
335 * Fortunately, it's not used often
336 */
337struct mbuf *
338dtom(PNATState pData, void *dat)
339{
340 struct mbuf *m;
341
342 DEBUG_CALL("dtom");
343 DEBUG_ARG("dat = %lx", (long )dat);
344
345 /* bug corrected for M_EXT buffers */
346 for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next)
347 {
348 if (m->m_flags & M_EXT)
349 {
350 if ( (char *)dat >= m->m_ext
351 && (char *)dat < (m->m_ext + m->m_size))
352 return m;
353 }
354 else
355 {
356 if ( (char *)dat >= m->m_dat
357 && (char *)dat < (m->m_dat + m->m_size))
358 return m;
359 }
360 }
361
362 DEBUG_ERROR((dfd, "dtom failed"));
363
364 return (struct mbuf *)0;
365}
366
367#ifndef VBOX_WITH_SLIRP_BSD_MBUF
368
369/**
370 * Interface that DrvNAT.cpp uses for allocating a buffer.
371 *
372 * @returns Opaque m_buf pointer.
373 *
374 * @param pData The NAT state.
375 * @param cbMin The minimum buffer size.
376 * @param ppvBuf Where to return the pointer to the start of the data
377 * buffer.
378 * @param pcbBuf Where to return the actual buffer size.
379 */
380struct mbuf *slirp_ext_m_get(PNATState pData, size_t cbMin, void **ppvBuf, size_t *pcbBuf)
381{
382 struct mbuf *m = m_get(pData);
383 if (!m)
384 return NULL;
385 if (cbMin > M_FREEROOM(m))
386 {
387 m_inc(m, cbMin);
388 if (RT_UNLIKELY(cbMin > M_FREEROOM(m)))
389 {
390 m_free(pData, m);
391 return NULL;
392 }
393 }
394
395 *ppvBuf = mtod(m, void *);
396 *pcbBuf = M_FREEROOM(m);
397 return m;
398}
399
400void slirp_ext_m_free(PNATState pData, struct mbuf *m)
401{
402 m_free(pData, m);
403}
404
405#endif /* VBOX_WITH_SLIRP_BSD_MBUF */
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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