VirtualBox

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

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

NAT: slirp file headers

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.0 KB
Line 
1/* $Id: misc.c 28449 2010-04-19 09:52:59Z vboxsync $ */
2/** @file
3 * NAT - helpers.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22/*
23 * This code is based on:
24 *
25 * Copyright (c) 1995 Danny Gasparovski.
26 *
27 * Please read the file COPYRIGHT for the
28 * terms and conditions of the copyright.
29 */
30
31#define WANT_SYS_IOCTL_H
32#include <slirp.h>
33
34#ifndef HAVE_INET_ATON
35int
36inet_aton(const char *cp, struct in_addr *ia)
37{
38 u_int32_t addr = inet_addr(cp);
39 if (addr == 0xffffffff)
40 return 0;
41 ia->s_addr = addr;
42 return 1;
43}
44#endif
45
46/*
47 * Get our IP address and put it in our_addr
48 */
49void
50getouraddr(PNATState pData)
51{
52 our_addr.s_addr = loopback_addr.s_addr;
53}
54
55struct quehead
56{
57 struct quehead *qh_link;
58 struct quehead *qh_rlink;
59};
60
61void
62insque(PNATState pData, void *a, void *b)
63{
64 register struct quehead *element = (struct quehead *) a;
65 register struct quehead *head = (struct quehead *) b;
66 element->qh_link = head->qh_link;
67 head->qh_link = (struct quehead *)element;
68 element->qh_rlink = (struct quehead *)head;
69 ((struct quehead *)(element->qh_link))->qh_rlink = (struct quehead *)element;
70}
71
72void
73remque(PNATState pData, void *a)
74{
75 register struct quehead *element = (struct quehead *) a;
76 ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
77 ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link;
78 element->qh_rlink = NULL;
79 /* element->qh_link = NULL; TCP FIN1 crashes if you do this. Why ? */
80}
81
82
83/*
84 * Set fd blocking and non-blocking
85 */
86void
87fd_nonblock(int fd)
88{
89#ifdef FIONBIO
90 int opt = 1;
91
92 ioctlsocket(fd, FIONBIO, &opt);
93#else
94 int opt;
95
96 opt = fcntl(fd, F_GETFL, 0);
97 opt |= O_NONBLOCK;
98 fcntl(fd, F_SETFL, opt);
99#endif
100}
101
102void
103fd_block(int fd)
104{
105#ifdef FIONBIO
106 int opt = 0;
107
108 ioctlsocket(fd, FIONBIO, &opt);
109#else
110 int opt;
111
112 opt = fcntl(fd, F_GETFL, 0);
113 opt &= ~O_NONBLOCK;
114 fcntl(fd, F_SETFL, opt);
115#endif
116}
117
118#ifdef VBOX_WITH_SLIRP_BSD_MBUF
119#define ITEM_MAGIC 0xdead0001
120struct item
121{
122 uint32_t magic;
123 uma_zone_t zone;
124 uint32_t ref_count;
125 LIST_ENTRY(item) list;
126};
127
128#define ZONE_MAGIC 0xdead0002
129struct uma_zone
130{
131 uint32_t magic;
132 PNATState pData; /* to minimize changes in the rest of UMA emulation code */
133 RTCRITSECT csZone;
134 const char *name;
135 size_t size; /* item size */
136 ctor_t pfCtor;
137 dtor_t pfDtor;
138 zinit_t pfInit;
139 zfini_t pfFini;
140 uma_alloc_t pfAlloc;
141 uma_free_t pfFree;
142 int max_items;
143 int cur_items;
144 LIST_HEAD(RT_NOTHING, item) used_items;
145 LIST_HEAD(RT_NOTHING, item) free_items;
146 uma_zone_t master_zone;
147 void *area;
148};
149
150
151static void *slirp_uma_alloc(uma_zone_t zone,
152 int size, uint8_t *pflags, int fWait)
153{
154 struct item *it;
155 uint8_t *sub_area;
156 void *ret = NULL;
157
158 RTCritSectEnter(&zone->csZone);
159 for (;;)
160 {
161 if (!LIST_EMPTY(&zone->free_items))
162 {
163 zone->cur_items++;
164 it = LIST_FIRST(&zone->free_items);
165 LIST_REMOVE(it, list);
166 LIST_INSERT_HEAD(&zone->used_items, it, list);
167 if (zone->pfInit)
168 zone->pfInit(zone->pData, (void *)&it[1], zone->size, M_DONTWAIT);
169 ret = (void *)&it[1];
170 break;
171 }
172
173 if (!zone->master_zone)
174 {
175 /* We're on master zone and we cant allocate more */
176 Log2(("NAT: no room on %s zone\n", zone->name));
177 break;
178 }
179
180 /* we're on sub-zone we need get chunk of master zone and split
181 * it for sub-zone conforming chunks.
182 */
183 sub_area = slirp_uma_alloc(zone->master_zone, zone->master_zone->size, NULL, 0);
184 if (!sub_area)
185 {
186 /* No room on master */
187 Log2(("NAT: no room on %s zone for %s zone\n", zone->master_zone->name, zone->name));
188 break;
189 }
190 zone->max_items++;
191 it = &((struct item *)sub_area)[-1];
192 /* it's chunk descriptor of master zone we should remove it
193 * from the master list first
194 */
195 Assert((it->zone && it->zone->magic == ZONE_MAGIC));
196 RTCritSectEnter(&it->zone->csZone);
197 /* @todo should we alter count of master counters? */
198 LIST_REMOVE(it, list);
199 RTCritSectLeave(&it->zone->csZone);
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 return ret;
210}
211
212static void slirp_uma_free(void *item, int size, uint8_t flags)
213{
214 struct item *it;
215 uma_zone_t zone;
216 Assert(item);
217 it = &((struct item *)item)[-1];
218 Assert(it->magic == ITEM_MAGIC);
219 zone = it->zone;
220 /* check bourder magic */
221 Assert((*(uint32_t *)(((uint8_t *)&it[1]) + zone->size) == 0xabadbabe));
222 RTCritSectEnter(&zone->csZone);
223 Assert(zone->magic == ZONE_MAGIC);
224 LIST_REMOVE(it, list);
225 LIST_INSERT_HEAD(&zone->free_items, it, list);
226 zone->cur_items--;
227 RTCritSectLeave(&zone->csZone);
228}
229
230uma_zone_t uma_zcreate(PNATState pData, char *name, size_t size,
231 ctor_t ctor, dtor_t dtor, zinit_t init, zfini_t fini, int flags1, int flags2)
232{
233 uma_zone_t zone = RTMemAllocZ(sizeof(struct uma_zone));
234 Assert((pData));
235 zone->magic = ZONE_MAGIC;
236 zone->pData = pData;
237 zone->name = name;
238 zone->size = size;
239 zone->pfCtor = ctor;
240 zone->pfDtor = dtor;
241 zone->pfInit = init;
242 zone->pfFini = fini;
243 zone->pfAlloc = slirp_uma_alloc;
244 zone->pfFree = slirp_uma_free;
245 RTCritSectInit(&zone->csZone);
246 return zone;
247
248}
249uma_zone_t uma_zsecond_create(char *name, ctor_t ctor,
250 dtor_t dtor, zinit_t init, zfini_t fini, uma_zone_t master)
251{
252 uma_zone_t zone;
253#if 0
254 if (master->pfAlloc != NULL)
255 zone = (uma_zone_t)master->pfAlloc(master, sizeof(struct uma_zone), NULL, 0);
256#endif
257 Assert(master);
258 zone = RTMemAllocZ(sizeof(struct uma_zone));
259 if (zone == NULL)
260 return NULL;
261
262 Assert((master && master->pData));
263 zone->magic = ZONE_MAGIC;
264 zone->pData = master->pData;
265 zone->name = name;
266 zone->pfCtor = ctor;
267 zone->pfDtor = dtor;
268 zone->pfInit = init;
269 zone->pfFini = fini;
270 zone->pfAlloc = slirp_uma_alloc;
271 zone->pfFree = slirp_uma_free;
272 zone->size = master->size;
273 zone->master_zone = master;
274 RTCritSectInit(&zone->csZone);
275 return zone;
276}
277
278void uma_zone_set_max(uma_zone_t zone, int max)
279{
280 int i = 0;
281 struct item *it;
282 zone->max_items = max;
283 zone->area = RTMemAllocZ(max * (sizeof(struct item) + zone->size + sizeof(uint32_t)));
284 for (; i < max; ++i)
285 {
286 it = (struct item *)(((uint8_t *)zone->area) + i*(sizeof(struct item) + zone->size + sizeof(uint32_t)));
287 it->magic = ITEM_MAGIC;
288 it->zone = zone;
289 *(uint32_t *)(((uint8_t *)&it[1]) + zone->size) = 0xabadbabe;
290 LIST_INSERT_HEAD(&zone->free_items, it, list);
291 }
292
293}
294
295void uma_zone_set_allocf(uma_zone_t zone, uma_alloc_t pfAlloc)
296{
297 zone->pfAlloc = pfAlloc;
298}
299
300void uma_zone_set_freef(uma_zone_t zone, uma_free_t pfFree)
301{
302 zone->pfFree = pfFree;
303}
304
305uint32_t *uma_find_refcnt(uma_zone_t zone, void *mem)
306{
307 /*@todo (vvl) this function supposed to work with special zone storing
308 reference counters */
309 struct item *it = (struct item *)mem; /* 1st element */
310 Assert(mem != NULL);
311 Assert(zone->magic == ZONE_MAGIC);
312 /* for returning pointer to counter we need get 0 elemnt */
313 Assert(it[-1].magic == ITEM_MAGIC);
314 return &it[-1].ref_count;
315}
316
317void *uma_zalloc_arg(uma_zone_t zone, void *args, int how)
318{
319 void *mem;
320 Assert(zone->magic == ZONE_MAGIC);
321 if (zone->pfAlloc == NULL)
322 return NULL;
323 RTCritSectEnter(&zone->csZone);
324 mem = zone->pfAlloc(zone, zone->size, NULL, 0);
325 if (zone->pfCtor)
326 zone->pfCtor(zone->pData, mem, zone->size, args, M_DONTWAIT);
327 RTCritSectLeave(&zone->csZone);
328 return mem;
329}
330
331void uma_zfree(uma_zone_t zone, void *item)
332{
333 uma_zfree_arg(zone, item, NULL);
334}
335
336void uma_zfree_arg(uma_zone_t zone, void *mem, void *flags)
337{
338 struct item *it;
339 Assert(zone->magic == ZONE_MAGIC);
340 if (zone->pfFree == NULL)
341 return;
342
343 Assert((mem));
344 RTCritSectEnter(&zone->csZone);
345 it = &((struct item *)mem)[-1];
346 if (it->magic != ITEM_MAGIC)
347 {
348 Log(("NAT:UMA: %p seems to be allocated on heap ... freeing\n", mem));
349 RTMemFree(mem);
350 RTCritSectLeave(&zone->csZone);
351 return;
352 }
353 Assert((zone->magic == ZONE_MAGIC && zone == it->zone));
354
355 if (zone->pfDtor)
356 zone->pfDtor(zone->pData, mem, zone->size, flags);
357 zone->pfFree(mem, 0, 0);
358 RTCritSectLeave(&zone->csZone);
359}
360
361int uma_zone_exhausted_nolock(uma_zone_t zone)
362{
363 return 0;
364}
365
366void zone_drain(uma_zone_t zone)
367{
368}
369
370void slirp_null_arg_free(void *mem, void *arg)
371{
372 /*@todo (r=vvl) make it wiser*/
373 Assert(mem);
374 RTMemFree(mem);
375}
376
377void *uma_zalloc(uma_zone_t zone, int len)
378{
379 return NULL;
380}
381
382struct mbuf *slirp_ext_m_get(PNATState pData, size_t cbMin, void **ppvBuf, size_t *pcbBuf)
383{
384 struct mbuf *m;
385 size_t size = MCLBYTES;
386 if (cbMin < MSIZE)
387 size = MCLBYTES;
388 else if (cbMin < MCLBYTES)
389 size = MCLBYTES;
390 else if (cbMin < MJUM9BYTES)
391 size = MJUM9BYTES;
392 else if (cbMin < MJUM16BYTES)
393 size = MJUM16BYTES;
394 else
395 AssertMsgFailed(("Unsupported size"));
396
397 m = m_getjcl(pData, M_NOWAIT, MT_HEADER, M_PKTHDR, size);
398 m->m_len = size;
399 *ppvBuf = mtod(m, void *);
400 *pcbBuf = size;
401 return m;
402}
403
404void slirp_ext_m_free(PNATState pData, struct mbuf *m)
405{
406 m_free(pData, m);
407}
408
409static void zone_destroy(uma_zone_t zone)
410{
411 RTCritSectEnter(&zone->csZone);
412 LogRel(("NAT: zone(nm:%s, used:%d)\n", zone->name, zone->cur_items));
413 if (zone->master_zone)
414 RTMemFree(zone->area);
415 RTCritSectLeave(&zone->csZone);
416 RTCritSectDelete(&zone->csZone);
417 RTMemFree(zone);
418}
419
420void m_fini(PNATState pData)
421{
422 zone_destroy(pData->zone_mbuf);
423 zone_destroy(pData->zone_clust);
424 zone_destroy(pData->zone_pack);
425 zone_destroy(pData->zone_jumbop);
426 zone_destroy(pData->zone_jumbo9);
427 zone_destroy(pData->zone_jumbo16);
428 /*@todo do finalize here.*/
429}
430#endif /* VBOX_WITH_SLIRP_BSD_MBUF */
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