VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/slirp/misc.c@ 41210

Last change on this file since 41210 was 40423, checked in by vboxsync, 13 years ago

NAT: warnings [-Wunused-macros]

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.4 KB
Line 
1/* $Id: misc.c 40423 2012-03-11 03:22:22Z vboxsync $ */
2/** @file
3 * NAT - helpers.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/*
19 * This code is based on:
20 *
21 * Copyright (c) 1995 Danny Gasparovski.
22 *
23 * Please read the file COPYRIGHT for the
24 * terms and conditions of the copyright.
25 */
26
27#include <slirp.h>
28#include "zone.h"
29
30#ifndef HAVE_INET_ATON
31int
32inet_aton(const char *cp, struct in_addr *ia)
33{
34 u_int32_t addr = inet_addr(cp);
35 if (addr == 0xffffffff)
36 return 0;
37 ia->s_addr = addr;
38 return 1;
39}
40#endif
41
42/*
43 * Get our IP address and put it in our_addr
44 */
45void
46getouraddr(PNATState pData)
47{
48 our_addr.s_addr = loopback_addr.s_addr;
49}
50
51struct quehead
52{
53 struct quehead *qh_link;
54 struct quehead *qh_rlink;
55};
56
57void
58insque(PNATState pData, void *a, void *b)
59{
60 register struct quehead *element = (struct quehead *) a;
61 register struct quehead *head = (struct quehead *) b;
62 NOREF(pData);
63 element->qh_link = head->qh_link;
64 head->qh_link = (struct quehead *)element;
65 element->qh_rlink = (struct quehead *)head;
66 ((struct quehead *)(element->qh_link))->qh_rlink = (struct quehead *)element;
67}
68
69void
70remque(PNATState pData, void *a)
71{
72 register struct quehead *element = (struct quehead *) a;
73 NOREF(pData);
74 ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
75 ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link;
76 element->qh_rlink = NULL;
77 /* element->qh_link = NULL; TCP FIN1 crashes if you do this. Why ? */
78}
79
80
81/*
82 * Set fd blocking and non-blocking
83 */
84void
85fd_nonblock(int fd)
86{
87#ifdef FIONBIO
88 int opt = 1;
89
90 ioctlsocket(fd, FIONBIO, &opt);
91#else
92 int opt;
93
94 opt = fcntl(fd, F_GETFL, 0);
95 opt |= O_NONBLOCK;
96 fcntl(fd, F_SETFL, opt);
97#endif
98}
99
100#if !defined(VBOX_NAT_MEM_DEBUG) && defined(LOG_ENABLED)
101# undef LogFlowFunc
102# define LogFlowFunc(x)
103
104# undef LogFlowFuncEnter
105# define LogFlowFuncEnter()
106
107# undef LogFlowFuncLeave
108# define LogFlowFuncLeave()
109
110# undef Log2
111# define Log2(x)
112#else
113# define NAT_MEM_LOG_ENABLED
114#endif
115
116
117/**
118 * Called when memory becomes available, works pfnXmitPending.
119 *
120 * @note This will LEAVE the critical section of the zone and RE-ENTER it
121 * again. Changes to the zone data should be expected across calls to
122 * this function!
123 *
124 * @param zone The zone.
125 */
126DECLINLINE(void) slirp_zone_check_and_send_pending(uma_zone_t zone)
127{
128 LogFlowFunc(("ENTER: zone:%R[mzone]\n", zone));
129 if ( zone->fDoXmitPending
130 && zone->master_zone == NULL)
131 {
132 int rc2;
133 zone->fDoXmitPending = false;
134 rc2 = RTCritSectLeave(&zone->csZone); AssertRC(rc2);
135
136 slirp_output_pending(zone->pData->pvUser);
137
138 rc2 = RTCritSectEnter(&zone->csZone); AssertRC(rc2);
139 }
140 LogFlowFuncLeave();
141}
142
143static void *slirp_uma_alloc(uma_zone_t zone,
144 int size, uint8_t *pflags, int fWait)
145{
146 struct item *it;
147 uint8_t *sub_area;
148 void *ret = NULL;
149 int rc;
150
151 LogFlowFunc(("ENTER: %R[mzone], size:%d, pflags:%p, %RTbool\n", zone, size, pflags, fWait));
152#ifndef NAT_MEM_LOG_ENABLED
153 NOREF(size);
154 NOREF(pflags);
155 NOREF(fWait);
156#endif
157 RTCritSectEnter(&zone->csZone);
158 for (;;)
159 {
160 if (!LIST_EMPTY(&zone->free_items))
161 {
162 it = LIST_FIRST(&zone->free_items);
163 Assert(it->magic == ITEM_MAGIC);
164 rc = 0;
165 if (zone->pfInit)
166 rc = zone->pfInit(zone->pData, (void *)&it[1], zone->size, M_DONTWAIT);
167 if (rc == 0)
168 {
169 zone->cur_items++;
170 LIST_REMOVE(it, list);
171 LIST_INSERT_HEAD(&zone->used_items, it, list);
172 slirp_zone_check_and_send_pending(zone); /* may exit+enter the cs! */
173 ret = (void *)&it[1];
174 }
175 else
176 {
177 AssertMsgFailed(("NAT: item initialization failed for zone %s\n", zone->name));
178 ret = NULL;
179 }
180 break;
181 }
182
183 if (!zone->master_zone)
184 {
185 /* We're on the master zone and we can't allocate more. */
186 Log2(("NAT: no room on %s zone\n", zone->name));
187 /* AssertMsgFailed(("NAT: OOM!")); */
188 zone->fDoXmitPending = true;
189 break;
190 }
191
192 /* we're on a sub-zone, we need get a chunk from the master zone and split
193 * it into sub-zone conforming chunks.
194 */
195 sub_area = slirp_uma_alloc(zone->master_zone, zone->master_zone->size, NULL, 0);
196 if (!sub_area)
197 {
198 /* No room on master */
199 Log2(("NAT: no room on %s zone for %s zone\n", zone->master_zone->name, zone->name));
200 break;
201 }
202 zone->max_items++;
203 it = &((struct item *)sub_area)[-1];
204 /* It's the chunk descriptor of the master zone, we should remove it
205 * from the master list first.
206 */
207 Assert((it->zone && it->zone->magic == ZONE_MAGIC));
208 RTCritSectEnter(&it->zone->csZone);
209 /** @todo should we alter count of master counters? */
210 LIST_REMOVE(it, list);
211 RTCritSectLeave(&it->zone->csZone);
212
213 /** @todo '+ zone->size' should be depend on flag */
214 memset(it, 0, sizeof(struct item));
215 it->zone = zone;
216 it->magic = ITEM_MAGIC;
217 LIST_INSERT_HEAD(&zone->free_items, it, list);
218 if (zone->cur_items >= zone->max_items)
219 LogRel(("NAT: zone(%s) has reached it maximum\n", zone->name));
220 }
221 RTCritSectLeave(&zone->csZone);
222 LogFlowFunc(("LEAVE: %p\n", ret));
223 return ret;
224}
225
226static void slirp_uma_free(void *item, int size, uint8_t flags)
227{
228 struct item *it;
229 uma_zone_t zone;
230#ifndef NAT_MEM_LOG_ENABLED
231 NOREF(size);
232 NOREF(flags);
233#endif
234
235 Assert(item);
236 it = &((struct item *)item)[-1];
237 LogFlowFunc(("ENTER: item:%p(%R[mzoneitem]), size:%d, flags:%RX8\n", item, it, size, flags));
238 Assert(it->magic == ITEM_MAGIC);
239 zone = it->zone;
240 /* check border magic */
241 Assert((*(uint32_t *)(((uint8_t *)&it[1]) + zone->size) == 0xabadbabe));
242
243 RTCritSectEnter(&zone->csZone);
244 Assert(zone->magic == ZONE_MAGIC);
245 LIST_REMOVE(it, list);
246 if (zone->pfFini)
247 {
248 zone->pfFini(zone->pData, item, zone->size);
249 }
250 if (zone->pfDtor)
251 {
252 zone->pfDtor(zone->pData, item, zone->size, NULL);
253 }
254 LIST_INSERT_HEAD(&zone->free_items, it, list);
255 zone->cur_items--;
256 slirp_zone_check_and_send_pending(zone); /* may exit+enter the cs! */
257 RTCritSectLeave(&zone->csZone);
258 LogFlowFuncLeave();
259}
260
261uma_zone_t uma_zcreate(PNATState pData, char *name, size_t size,
262 ctor_t ctor, dtor_t dtor, zinit_t init, zfini_t fini, int flags1, int flags2)
263{
264 uma_zone_t zone = NULL;
265#ifndef NAT_MEM_LOG_ENABLED
266 NOREF(flags1);
267 NOREF(flags2);
268#endif
269 LogFlowFunc(("ENTER: name:%s size:%d, ctor:%p, dtor:%p, init:%p, fini:%p, flags1:%RX32, flags2:%RX32\n",
270 name, ctor, dtor, init, fini, flags1, flags2));
271 zone = RTMemAllocZ(sizeof(struct uma_zone));
272 Assert((pData));
273 zone->magic = ZONE_MAGIC;
274 zone->pData = pData;
275 zone->name = name;
276 zone->size = size;
277 zone->pfCtor = ctor;
278 zone->pfDtor = dtor;
279 zone->pfInit = init;
280 zone->pfFini = fini;
281 zone->pfAlloc = slirp_uma_alloc;
282 zone->pfFree = slirp_uma_free;
283 RTCritSectInit(&zone->csZone);
284 LogFlowFunc(("LEAVE: %R[mzone]\n", zone));
285 return zone;
286
287}
288uma_zone_t uma_zsecond_create(char *name, ctor_t ctor,
289 dtor_t dtor, zinit_t init, zfini_t fini, uma_zone_t master)
290{
291 uma_zone_t zone;
292 Assert(master);
293 LogFlowFunc(("ENTER: name:%s ctor:%p, dtor:%p, init:%p, fini:%p, master:%R[mzone]\n",
294 name, ctor, dtor, init, fini, master));
295 zone = RTMemAllocZ(sizeof(struct uma_zone));
296 if (zone == NULL)
297 {
298 LogFlowFunc(("LEAVE: %R[mzone]\n", NULL));
299 return NULL;
300 }
301
302 Assert((master && master->pData));
303 zone->magic = ZONE_MAGIC;
304 zone->pData = master->pData;
305 zone->name = name;
306 zone->pfCtor = ctor;
307 zone->pfDtor = dtor;
308 zone->pfInit = init;
309 zone->pfFini = fini;
310 zone->pfAlloc = slirp_uma_alloc;
311 zone->pfFree = slirp_uma_free;
312 zone->size = master->size;
313 zone->master_zone = master;
314 RTCritSectInit(&zone->csZone);
315 LogFlowFunc(("LEAVE: %R[mzone]\n", zone));
316 return zone;
317}
318
319void uma_zone_set_max(uma_zone_t zone, int max)
320{
321 int i = 0;
322 struct item *it;
323 LogFlowFunc(("ENTER: zone:%R[mzone], max:%d\n", zone, max));
324 zone->max_items = max;
325 zone->area = RTMemAllocZ(max * (sizeof(struct item) + zone->size + sizeof(uint32_t)));
326 for (; i < max; ++i)
327 {
328 it = (struct item *)(((uint8_t *)zone->area) + i*(sizeof(struct item) + zone->size + sizeof(uint32_t)));
329 it->magic = ITEM_MAGIC;
330 it->zone = zone;
331 *(uint32_t *)(((uint8_t *)&it[1]) + zone->size) = 0xabadbabe;
332 LIST_INSERT_HEAD(&zone->free_items, it, list);
333 }
334 LogFlowFuncLeave();
335}
336
337void uma_zone_set_allocf(uma_zone_t zone, uma_alloc_t pfAlloc)
338{
339 LogFlowFunc(("ENTER: zone:%R[mzone], pfAlloc:%Rfn\n", zone, pfAlloc));
340 zone->pfAlloc = pfAlloc;
341 LogFlowFuncLeave();
342}
343
344void uma_zone_set_freef(uma_zone_t zone, uma_free_t pfFree)
345{
346 LogFlowFunc(("ENTER: zone:%R[mzone], pfAlloc:%Rfn\n", zone, pfFree));
347 zone->pfFree = pfFree;
348 LogFlowFuncLeave();
349}
350
351uint32_t *uma_find_refcnt(uma_zone_t zone, void *mem)
352{
353 /** @todo (vvl) this function supposed to work with special zone storing
354 reference counters */
355 struct item *it = NULL;
356#ifndef NAT_MEM_LOG_ENABLED
357 NOREF(zone);
358#endif
359 LogFlowFunc(("ENTER: zone:%R[mzone], mem:%p\n", zone, mem));
360 it = (struct item *)mem; /* 1st element */
361 Assert(mem != NULL);
362 Assert(zone->magic == ZONE_MAGIC);
363 /* for returning pointer to counter we need get 0 elemnt */
364 Assert(it[-1].magic == ITEM_MAGIC);
365 LogFlowFunc(("LEAVE: %p\n", &it[-1].ref_count));
366 return &it[-1].ref_count;
367}
368
369void *uma_zalloc_arg(uma_zone_t zone, void *args, int how)
370{
371 void *mem;
372#ifndef NAT_MEM_LOG_ENABLED
373 NOREF(how);
374#endif
375 Assert(zone->magic == ZONE_MAGIC);
376 LogFlowFunc(("ENTER: zone:%R[mzone], args:%p, how:%RX32\n", zone, args, how));
377 if (zone->pfAlloc == NULL)
378 {
379 LogFlowFunc(("LEAVE: NULL\n"));
380 return NULL;
381 }
382 RTCritSectEnter(&zone->csZone);
383 mem = zone->pfAlloc(zone, zone->size, NULL, 0);
384 if (mem != NULL)
385 {
386 if (zone->pfCtor)
387 zone->pfCtor(zone->pData, mem, zone->size, args, M_DONTWAIT);
388 }
389 RTCritSectLeave(&zone->csZone);
390 LogFlowFunc(("LEAVE: %p\n", mem));
391 return mem;
392}
393
394void uma_zfree(uma_zone_t zone, void *item)
395{
396 LogFlowFunc(("ENTER: zone:%R[mzone], item:%p\n", zone, item));
397 uma_zfree_arg(zone, item, NULL);
398 LogFlowFuncLeave();
399}
400
401void uma_zfree_arg(uma_zone_t zone, void *mem, void *flags)
402{
403 struct item *it;
404 Assert(zone->magic == ZONE_MAGIC);
405 Assert((zone->pfFree));
406 Assert((mem));
407 LogFlowFunc(("ENTER: zone:%R[mzone], mem:%p, flags:%p\n", zone, mem, flags));
408#ifndef NAT_MEM_LOG_ENABLED
409 NOREF(flags);
410#endif
411
412 RTCritSectEnter(&zone->csZone);
413 it = &((struct item *)mem)[-1];
414 Assert((it->magic == ITEM_MAGIC));
415 Assert((zone->magic == ZONE_MAGIC && zone == it->zone));
416
417 zone->pfFree(mem, 0, 0);
418 RTCritSectLeave(&zone->csZone);
419 LogFlowFuncLeave();
420}
421
422int uma_zone_exhausted_nolock(uma_zone_t zone)
423{
424 int fExhausted;
425 LogFlowFunc(("ENTER: zone:%R[mzone]\n", zone));
426 RTCritSectEnter(&zone->csZone);
427 fExhausted = (zone->cur_items == zone->max_items);
428 RTCritSectLeave(&zone->csZone);
429 LogFlowFunc(("LEAVE: %RTbool\n", fExhausted));
430 return fExhausted;
431}
432
433void zone_drain(uma_zone_t zone)
434{
435 struct item *it;
436 uma_zone_t master_zone;
437
438 /* vvl: Huh? What to do with zone which hasn't got backstore ? */
439 Assert((zone->master_zone));
440 LogFlowFunc(("ENTER: zone:%R[mzone]\n", zone));
441 master_zone = zone->master_zone;
442 while (!LIST_EMPTY(&zone->free_items))
443 {
444 it = LIST_FIRST(&zone->free_items);
445 Assert((it->magic == ITEM_MAGIC));
446
447 RTCritSectEnter(&zone->csZone);
448 LIST_REMOVE(it, list);
449 zone->max_items--;
450 RTCritSectLeave(&zone->csZone);
451
452 it->zone = master_zone;
453
454 RTCritSectEnter(&master_zone->csZone);
455 LIST_INSERT_HEAD(&master_zone->free_items, it, list);
456 master_zone->cur_items--;
457 slirp_zone_check_and_send_pending(master_zone); /* may exit+enter the cs! */
458 RTCritSectLeave(&master_zone->csZone);
459 }
460 LogFlowFuncLeave();
461}
462
463void slirp_null_arg_free(void *mem, void *arg)
464{
465 /** @todo (vvl) make it wiser */
466 LogFlowFunc(("ENTER: mem:%p, arg:%p\n", mem, arg));
467 Assert(mem);
468#ifndef NAT_MEM_LOG_ENABLED
469 NOREF(arg);
470#endif
471 RTMemFree(mem);
472 LogFlowFuncLeave();
473}
474
475void *uma_zalloc(uma_zone_t zone, int len)
476{
477#ifndef NAT_MEM_LOG_ENABLED
478 NOREF(zone);
479 NOREF(len);
480#endif
481 LogFlowFunc(("ENTER: zone:%R[mzone], len:%d\n", zone, len));
482 LogFlowFunc(("LEAVE: NULL"));
483 return NULL;
484}
485
486struct mbuf *slirp_ext_m_get(PNATState pData, size_t cbMin, void **ppvBuf, size_t *pcbBuf)
487{
488 struct mbuf *m;
489 size_t size = MCLBYTES;
490 LogFlowFunc(("ENTER: cbMin:%d, ppvBuf:%p, pcbBuf:%p\n", cbMin, ppvBuf, pcbBuf));
491 if (cbMin < MSIZE)
492 size = MCLBYTES;
493 else if (cbMin < MCLBYTES)
494 size = MCLBYTES;
495 else if (cbMin < MJUM9BYTES)
496 size = MJUM9BYTES;
497 else if (cbMin < MJUM16BYTES)
498 size = MJUM16BYTES;
499 else
500 AssertMsgFailed(("Unsupported size"));
501
502 m = m_getjcl(pData, M_NOWAIT, MT_HEADER, M_PKTHDR, size);
503 if (m == NULL)
504 {
505 *ppvBuf = NULL;
506 *pcbBuf = 0;
507 LogFlowFunc(("LEAVE: NULL\n"));
508 return NULL;
509 }
510 m->m_len = size;
511 *ppvBuf = mtod(m, void *);
512 *pcbBuf = size;
513 LogFlowFunc(("LEAVE: %p\n", m));
514 return m;
515}
516
517void slirp_ext_m_free(PNATState pData, struct mbuf *m, uint8_t *pu8Buf)
518{
519
520 LogFlowFunc(("ENTER: m:%p, pu8Buf:%p\n", m, pu8Buf));
521 if ( !pu8Buf
522 && pu8Buf != mtod(m, uint8_t *))
523 RTMemFree(pu8Buf); /* This buffer was allocated on heap */
524 m_freem(pData, m);
525 LogFlowFuncLeave();
526}
527
528static void zone_destroy(uma_zone_t zone)
529{
530 RTCritSectEnter(&zone->csZone);
531 LogFlowFunc(("ENTER: zone:%R[mzone]\n", zone));
532 LogRel(("NAT: zone(nm:%s, used:%d)\n", zone->name, zone->cur_items));
533 if (zone->master_zone)
534 RTMemFree(zone->area);
535 RTCritSectLeave(&zone->csZone);
536 RTCritSectDelete(&zone->csZone);
537 RTMemFree(zone);
538 LogFlowFuncLeave();
539}
540
541void m_fini(PNATState pData)
542{
543 LogFlowFuncEnter();
544#define ZONE_DESTROY(zone) do { zone_destroy((zone)); (zone) = NULL;} while (0)
545 ZONE_DESTROY(pData->zone_clust);
546 ZONE_DESTROY(pData->zone_pack);
547 ZONE_DESTROY(pData->zone_mbuf);
548 ZONE_DESTROY(pData->zone_jumbop);
549 ZONE_DESTROY(pData->zone_jumbo9);
550 ZONE_DESTROY(pData->zone_jumbo16);
551#undef ZONE_DESTROY
552 /** @todo do finalize here.*/
553 LogFlowFuncLeave();
554}
555
556void
557if_init(PNATState pData)
558{
559 /* 14 for ethernet */
560 if_maxlinkhdr = 14;
561 if_comp = IF_AUTOCOMP;
562 if_mtu = 1500;
563 if_mru = 1500;
564}
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