VirtualBox

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

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

NAT: warnings + NAT/netservice fixes.

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