VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/DevINIP.cpp@ 26001

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

PDM,*: Redid the PDM structure versions. Check the instance and helper versions in every device and driver constructor.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 23.0 KB
 
1/* $Id: DevINIP.cpp 26001 2010-01-25 14:21:13Z vboxsync $ */
2/** @file
3 * DevINIP - Internal Network IP stack device/service.
4 */
5
6/*
7 * Copyright (C) 2007-2009 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_DEV_INIP
27#include <iprt/cdefs.h> /* include early to allow RT_C_DECLS_BEGIN hack */
28#include <iprt/mem.h> /* include anything of ours that the lwip headers use. */
29#include <iprt/semaphore.h>
30#include <iprt/thread.h>
31#include <iprt/alloca.h>
32/* All lwip header files are not C++ safe. So hack around this. */
33RT_C_DECLS_BEGIN
34#include "lwip/sys.h"
35#include "lwip/stats.h"
36#include "lwip/mem.h"
37#include "lwip/memp.h"
38#include "lwip/pbuf.h"
39#include "lwip/netif.h"
40#include "ipv4/lwip/ip.h"
41#include "lwip/udp.h"
42#include "lwip/tcp.h"
43#include "lwip/tcpip.h"
44#include "lwip/sockets.h"
45#include "netif/etharp.h"
46RT_C_DECLS_END
47#include <VBox/pdmdev.h>
48#include <VBox/tm.h>
49#include <iprt/assert.h>
50#include <iprt/string.h>
51#include <iprt/uuid.h>
52
53#include "../Builtins.h"
54
55
56/*******************************************************************************
57* Macros and Defines *
58*******************************************************************************/
59
60/** Maximum frame size this device can handle. */
61#define DEVINIP_MAX_FRAME 1514
62
63
64/*******************************************************************************
65* Structures and Typedefs *
66*******************************************************************************/
67
68/**
69 * Internal Network IP stack device instance data.
70 *
71 * @implements PDMIBASE
72 * @implements PDMINETWORKPORT
73 */
74typedef struct DEVINTNETIP
75{
76 /** The base interface for LUN\#0. */
77 PDMIBASE IBase;
78 /** The network port this device provides (LUN\#0). */
79 PDMINETWORKPORT INetworkPort;
80 /** The base interface of the network driver below us. */
81 PPDMIBASE pDrvBase;
82 /** The connector of the network driver below us. */
83 PPDMINETWORKCONNECTOR pDrv;
84 /** Pointer to the device instance. */
85 PPDMDEVINSR3 pDevIns;
86 /** MAC adress. */
87 RTMAC MAC;
88 /** Static IP address of the interface. */
89 char *pszIP;
90 /** Netmask of the interface. */
91 char *pszNetmask;
92 /** Gateway for the interface. */
93 char *pszGateway;
94 /** lwIP network interface description. */
95 struct netif IntNetIF;
96 /** lwIP ARP timer. */
97 PTMTIMERR3 ARPTimer;
98 /** lwIP TCP fast timer. */
99 PTMTIMERR3 TCPFastTimer;
100 /** lwIP TCP slow timer. */
101 PTMTIMERR3 TCPSlowTimer;
102 /** lwIP semaphore to coordinate TCPIP init/terminate. */
103 sys_sem_t LWIPTcpInitSem;
104 /** hack: get linking right. remove this eventually, once the device
105 * provides a proper interface to all IP stack functions. */
106 const void *pLinkHack;
107} DEVINTNETIP, *PDEVINTNETIP;
108
109
110/*******************************************************************************
111* Global Variables *
112*******************************************************************************/
113
114/**
115 * Pointer to the (only) instance data in this device.
116 */
117static PDEVINTNETIP g_pDevINIPData = NULL;
118
119/*
120 * really ugly hack to avoid linking problems on unix style platforms
121 * using .a libraries for now.
122 */
123static const PFNRT g_pDevINILinkHack[] =
124{
125 (PFNRT)lwip_socket,
126 (PFNRT)lwip_close,
127 (PFNRT)lwip_setsockopt,
128 (PFNRT)lwip_recv,
129 (PFNRT)lwip_send,
130 (PFNRT)lwip_select
131};
132
133
134/*******************************************************************************
135* Internal Functions *
136*******************************************************************************/
137static DECLCALLBACK(void) devINIPARPTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer);
138static DECLCALLBACK(void) devINIPTCPFastTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer);
139static DECLCALLBACK(void) devINIPTCPSlowTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer);
140static DECLCALLBACK(err_t) devINIPOutput(struct netif *netif, struct pbuf *p,
141 struct ip_addr *ipaddr);
142static DECLCALLBACK(err_t) devINIPOutputRaw(struct netif *netif,
143 struct pbuf *p);
144static DECLCALLBACK(err_t) devINIPInterface(struct netif *netif);
145
146/**
147 * ARP cache timeout handling for lwIP.
148 *
149 * @param pDevIns Device instance.
150 * @param pTimer Pointer to timer.
151 */
152static DECLCALLBACK(void) devINIPARPTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
153{
154 PDEVINTNETIP pThis = (PDEVINTNETIP)pvUser;
155 LogFlow(("%s: pDevIns=%p pTimer=%p\n", __FUNCTION__, pDevIns, pTimer));
156 lwip_etharp_tmr();
157 TMTimerSetMillies(pThis->ARPTimer, ARP_TMR_INTERVAL);
158 LogFlow(("%s: return\n", __FUNCTION__));
159}
160
161/**
162 * TCP fast timer handling for lwIP.
163 *
164 * @param pDevIns Device instance.
165 * @param pTimer Pointer to timer.
166 */
167static DECLCALLBACK(void) devINIPTCPFastTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
168{
169 PDEVINTNETIP pThis = (PDEVINTNETIP)pvUser;
170 LogFlow(("%s: pDevIns=%p pTimer=%p\n", __FUNCTION__, pDevIns, pTimer));
171 lwip_tcp_fasttmr();
172 TMTimerSetMillies(pThis->TCPFastTimer, TCP_FAST_INTERVAL);
173 LogFlow(("%s: return\n", __FUNCTION__));
174}
175
176/**
177 * TCP slow timer handling for lwIP.
178 *
179 * @param pDevIns Device instance.
180 * @param pTimer Pointer to timer.
181 */
182static DECLCALLBACK(void) devINIPTCPSlowTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
183{
184 PDEVINTNETIP pThis = (PDEVINTNETIP)pvUser;
185 LogFlow(("%s: pDevIns=%p pTimer=%p\n", __FUNCTION__, pDevIns, pTimer));
186 lwip_tcp_slowtmr();
187 TMTimerSetMillies(pThis->TCPSlowTimer, TCP_SLOW_INTERVAL);
188 LogFlow(("%s: return\n", __FUNCTION__));
189}
190
191/**
192 * Output a TCP/IP packet on the interface. Uses the generic lwIP ARP
193 * code to resolve the address and call the link-level packet function.
194 *
195 * @returns lwIP error code
196 * @param netif Interface on which to send IP packet.
197 * @param p Packet data.
198 * @param ipaddr Destination IP address.
199 */
200static DECLCALLBACK(err_t) devINIPOutput(struct netif *netif, struct pbuf *p,
201 struct ip_addr *ipaddr)
202{
203 err_t lrc;
204 LogFlow(("%s: netif=%p p=%p ipaddr=%#04x\n", __FUNCTION__, netif, p,
205 ipaddr->addr));
206 lrc = lwip_etharp_output(netif, ipaddr, p);
207 LogFlow(("%s: return %d\n", __FUNCTION__, lrc));
208 return lrc;
209}
210
211/**
212 * Output a raw packet on the interface.
213 *
214 * @returns lwIP error code
215 * @param netif Interface on which to send frame.
216 * @param p Frame data.
217 */
218static DECLCALLBACK(err_t) devINIPOutputRaw(struct netif *netif,
219 struct pbuf *p)
220{
221 uint8_t aFrame[DEVINIP_MAX_FRAME], *pbBuf;
222 size_t cbBuf;
223 struct pbuf *q;
224 int rc = VINF_SUCCESS;
225
226 LogFlow(("%s: netif=%p p=%p\n", __FUNCTION__, netif, p));
227 Assert(g_pDevINIPData);
228 Assert(g_pDevINIPData->pDrv);
229
230 /* Silently ignore packets being sent while lwIP isn't set up. */
231 if (!g_pDevINIPData)
232 goto out;
233
234#if ETH_PAD_SIZE
235 lwip_pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
236#endif
237
238 pbBuf = &aFrame[0];
239 cbBuf = 0;
240 for (q = p; q != NULL; q = q->next)
241 {
242 if (cbBuf + q->len <= DEVINIP_MAX_FRAME)
243 {
244 memcpy(pbBuf, q->payload, q->len);
245 pbBuf += q->len;
246 cbBuf += q->len;
247 }
248 else
249 {
250 LogRel(("INIP: exceeded frame size\n"));
251 break;
252 }
253 }
254 if (cbBuf)
255 rc = g_pDevINIPData->pDrv->pfnSend(g_pDevINIPData->pDrv,
256 &aFrame[0], cbBuf);
257
258#if ETH_PAD_SIZE
259 lwip_pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
260#endif
261
262out:
263 err_t lrc = ERR_OK;
264 if (RT_FAILURE(rc))
265 lrc = ERR_IF;
266 LogFlow(("%s: return %d (vbox: %Rrc)\n", __FUNCTION__, rc, lrc));
267 return lrc;
268}
269
270/**
271 * Implements the ethernet interface backend initialization for lwIP.
272 *
273 * @returns lwIP error code
274 * @param netif Interface to configure.
275 */
276static DECLCALLBACK(err_t) devINIPInterface(struct netif *netif)
277{
278 LogFlow(("%s: netif=%p\n", __FUNCTION__, netif));
279 Assert(g_pDevINIPData != NULL);
280 netif->state = g_pDevINIPData;
281 netif->hwaddr_len = sizeof(g_pDevINIPData->MAC);
282 memcpy(netif->hwaddr, &g_pDevINIPData->MAC, sizeof(g_pDevINIPData->MAC));
283 netif->mtu = DEVINIP_MAX_FRAME;
284 netif->flags = NETIF_FLAG_BROADCAST;
285 netif->output = devINIPOutput;
286 netif->linkoutput = devINIPOutputRaw;
287
288 lwip_etharp_init();
289 TMTimerSetMillies(g_pDevINIPData->ARPTimer, ARP_TMR_INTERVAL);
290 LogFlow(("%s: success\n", __FUNCTION__));
291 return ERR_OK;
292}
293
294/**
295 * Wait until data can be received.
296 *
297 * @returns VBox status code. VINF_SUCCESS means there is at least one receive descriptor available.
298 * @param pInterface PDM network port interface pointer.
299 * @param cMillies Number of milliseconds to wait. 0 means return immediately.
300 */
301static DECLCALLBACK(int) devINIPWaitInputAvail(PPDMINETWORKPORT pInterface, RTMSINTERVAL cMillies)
302{
303 LogFlow(("%s: pInterface=%p\n", __FUNCTION__, pInterface));
304 LogFlow(("%s: return VINF_SUCCESS\n", __FUNCTION__));
305 return VINF_SUCCESS;
306}
307
308/**
309 * Receive data and pass it to lwIP for processing.
310 *
311 * @returns VBox status code
312 * @param pInterface PDM network port interface pointer.
313 * @param pvBuf Pointer to frame data.
314 * @param cb Frame size.
315 */
316static DECLCALLBACK(int) devINIPInput(PPDMINETWORKPORT pInterface,
317 const void *pvBuf, size_t cb)
318{
319 const uint8_t *pbBuf = (const uint8_t *)pvBuf;
320 size_t len = cb;
321 const struct eth_hdr *ethhdr;
322 struct pbuf *p, *q;
323 int rc = VINF_SUCCESS;
324
325 LogFlow(("%s: pInterface=%p pvBuf=%p cb=%lu\n", __FUNCTION__, pInterface,
326 pvBuf, cb));
327 Assert(g_pDevINIPData);
328 Assert(g_pDevINIPData->pDrv);
329
330 /* Silently ignore packets being received while lwIP isn't set up. */
331 if (!g_pDevINIPData)
332 goto out;
333
334#if ETH_PAD_SIZE
335 len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
336#endif
337
338 /* We allocate a pbuf chain of pbufs from the pool. */
339 p = lwip_pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
340 if (p != NULL)
341 {
342#if ETH_PAD_SIZE
343 lwip_pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
344#endif
345
346 for (q = p; q != NULL; q = q->next)
347 {
348 /* Fill the buffers, and clean out unused buffer space. */
349 memcpy(q->payload, pbBuf, RT_MIN(cb, q->len));
350 pbBuf += RT_MIN(cb, q->len);
351 if (q->len > cb)
352 memset(((uint8_t *)q->payload) + cb, '\0', q->len - cb);
353 cb -= RT_MIN(cb, q->len);
354 }
355
356 ethhdr = (const struct eth_hdr *)p->payload;
357 struct netif *iface = &g_pDevINIPData->IntNetIF;
358 err_t lrc;
359 switch (htons(ethhdr->type))
360 {
361 case ETHTYPE_IP: /* IP packet */
362 lwip_pbuf_header(p, -(ssize_t)sizeof(struct eth_hdr));
363 lrc = iface->input(p, iface);
364 if (lrc)
365 rc = VERR_NET_IO_ERROR;
366 break;
367 case ETHTYPE_ARP: /* ARP packet */
368 lwip_etharp_arp_input(iface, (struct eth_addr *)iface->hwaddr, p);
369 break;
370 default:
371 lwip_pbuf_free(p);
372 }
373 }
374
375out:
376 LogFlow(("%s: return %Rrc\n", __FUNCTION__, rc));
377 return rc;
378}
379
380/**
381 * Signals the end of lwIP TCPIP initialization.
382 *
383 * @param arg opaque argument, here the pointer to the semaphore.
384 */
385static DECLCALLBACK(void) devINIPTcpipInitDone(void *arg)
386{
387 sys_sem_t *sem = (sys_sem_t *)arg;
388 lwip_sys_sem_signal(*sem);
389}
390
391/* -=-=-=-=- PDMIBASE -=-=-=-=- */
392
393/**
394 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
395 */
396static DECLCALLBACK(void *) devINIPQueryInterface(PPDMIBASE pInterface,
397 const char *pszIID)
398{
399 PDEVINTNETIP pThis = RT_FROM_MEMBER(pInterface, DEVINTNETIP, IBase);
400 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
401 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKPORT, &pThis->INetworkPort);
402 return NULL;
403}
404
405/* -=-=-=-=- PDMDEVREG -=-=-=-=- */
406
407/**
408 * Destruct a device instance.
409 *
410 * Most VM resources are freed by the VM. This callback is provided so that any non-VM
411 * resources can be freed correctly.
412 *
413 * @returns VBox status.
414 * @param pDevIns The device instance data.
415 */
416static DECLCALLBACK(int) devINIPDestruct(PPDMDEVINS pDevIns)
417{
418 PDEVINTNETIP pThis = PDMINS_2_DATA(pDevIns, PDEVINTNETIP);
419
420 LogFlow(("%s: pDevIns=%p\n", __FUNCTION__, pDevIns));
421 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
422
423 if (g_pDevINIPData != NULL)
424 {
425 netif_set_down(&pThis->IntNetIF);
426 netif_remove(&pThis->IntNetIF);
427 tcpip_terminate();
428 lwip_sys_sem_wait(pThis->LWIPTcpInitSem);
429 lwip_sys_sem_free(pThis->LWIPTcpInitSem);
430 }
431
432 if (pThis->pszIP)
433 MMR3HeapFree(pThis->pszIP);
434 if (pThis->pszNetmask)
435 MMR3HeapFree(pThis->pszNetmask);
436 if (pThis->pszGateway)
437 MMR3HeapFree(pThis->pszGateway);
438
439 LogFlow(("%s: success\n", __FUNCTION__));
440 return VINF_SUCCESS;
441}
442
443
444/**
445 * Construct an internal networking IP stack device instance.
446 *
447 * @returns VBox status.
448 * @param pDevIns The device instance data.
449 * If the registration structure is needed, pDevIns->pDevReg points to it.
450 * @param iInstance Instance number. Use this to figure out which registers
451 * and such to use.
452 * he device number is also found in pDevIns->iInstance, but since it's
453 * likely to be freqently used PDM passes it as parameter.
454 * @param pCfgHandle Configuration node handle for the device. Use this to obtain the configuration
455 * of the device instance. It's also found in pDevIns->pCfgHandle, but like
456 * iInstance it's expected to be used a bit in this function.
457 */
458static DECLCALLBACK(int) devINIPConstruct(PPDMDEVINS pDevIns, int iInstance,
459 PCFGMNODE pCfgHandle)
460{
461 PDEVINTNETIP pThis = PDMINS_2_DATA(pDevIns, PDEVINTNETIP);
462 int rc = VINF_SUCCESS;
463 LogFlow(("%s: pDevIns=%p iInstance=%d pCfgHandle=%p\n", __FUNCTION__,
464 pDevIns, iInstance, pCfgHandle));
465
466 Assert(iInstance == 0);
467 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
468
469 /*
470 * Validate the config.
471 */
472 if (!CFGMR3AreValuesValid(pCfgHandle, "MAC\0IP\0Netmask\0Gateway\0"))
473 {
474 rc = PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
475 N_("Unknown Internal Networking IP configuration option"));
476 goto out;
477 }
478
479 /*
480 * Init the static parts.
481 */
482 pThis->pszIP = NULL;
483 pThis->pszNetmask = NULL;
484 pThis->pszGateway = NULL;
485 /* Pointer to device instance */
486 pThis->pDevIns = pDevIns;
487 /* IBase */
488 pThis->IBase.pfnQueryInterface = devINIPQueryInterface;
489 /* INetworkPort */
490 pThis->INetworkPort.pfnWaitReceiveAvail = devINIPWaitInputAvail;
491 pThis->INetworkPort.pfnReceive = devINIPInput;
492
493 /*
494 * Get the configuration settings.
495 */
496 rc = CFGMR3QueryBytes(pCfgHandle, "MAC", &pThis->MAC, sizeof(pThis->MAC));
497 if (rc == VERR_CFGM_NOT_BYTES)
498 {
499 char szMAC[64];
500 rc = CFGMR3QueryString(pCfgHandle, "MAC", &szMAC[0], sizeof(szMAC));
501 if (RT_SUCCESS(rc))
502 {
503 char *macStr = &szMAC[0];
504 char *pMac = (char *)&pThis->MAC;
505 for (uint32_t i = 0; i < 6; i++)
506 {
507 if ( !*macStr || !*(macStr + 1)
508 || *macStr == ':' || *(macStr + 1) == ':')
509 {
510 rc = PDMDEV_SET_ERROR(pDevIns,
511 VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
512 N_("Configuration error: Invalid \"MAC\" value"));
513 goto out;
514 }
515 char c1 = *macStr++ - '0';
516 if (c1 > 9)
517 c1 -= 7;
518 char c2 = *macStr++ - '0';
519 if (c2 > 9)
520 c2 -= 7;
521 *pMac++ = ((c1 & 0x0f) << 4) | (c2 & 0x0f);
522 if (i != 5 && *macStr == ':')
523 macStr++;
524 }
525 }
526 }
527 if (RT_FAILURE(rc))
528 {
529 PDMDEV_SET_ERROR(pDevIns, rc,
530 N_("Configuration error: Failed to get the \"MAC\" value"));
531 goto out;
532 }
533 rc = CFGMR3QueryStringAlloc(pCfgHandle, "IP", &pThis->pszIP);
534 if (RT_FAILURE(rc))
535 {
536 PDMDEV_SET_ERROR(pDevIns, rc,
537 N_("Configuration error: Failed to get the \"IP\" value"));
538 goto out;
539 }
540 rc = CFGMR3QueryStringAlloc(pCfgHandle, "Netmask", &pThis->pszNetmask);
541 if (RT_FAILURE(rc))
542 {
543 PDMDEV_SET_ERROR(pDevIns, rc,
544 N_("Configuration error: Failed to get the \"Netmask\" value"));
545 goto out;
546 }
547 rc = CFGMR3QueryStringAlloc(pCfgHandle, "Gateway", &pThis->pszGateway);
548 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
549 rc = VINF_SUCCESS;
550 if (RT_FAILURE(rc))
551 {
552 PDMDEV_SET_ERROR(pDevIns, rc,
553 N_("Configuration error: Failed to get the \"Gateway\" value"));
554 goto out;
555 }
556
557 /*
558 * Attach driver and query the network connector interface.
559 */
560 rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase,
561 "Network Port");
562 if (RT_FAILURE(rc))
563 {
564 pThis->pDrvBase = NULL;
565 pThis->pDrv = NULL;
566 goto out;
567 }
568 else
569 {
570 pThis->pDrv = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMINETWORKCONNECTOR);
571 if (!pThis->pDrv)
572 {
573 AssertMsgFailed(("Failed to obtain the PDMINETWORKCONNECTOR interface!\n"));
574 rc = VERR_PDM_MISSING_INTERFACE_BELOW;
575 goto out;
576 }
577 }
578
579 struct ip_addr ipaddr, netmask, gw;
580 struct in_addr ip;
581
582 if (!inet_aton(pThis->pszIP, &ip))
583 {
584 rc = PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
585 N_("Configuration error: Invalid \"IP\" value"));
586 goto out;
587 }
588 memcpy(&ipaddr, &ip, sizeof(ipaddr));
589 if (!inet_aton(pThis->pszNetmask, &ip))
590 {
591 rc = PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
592 N_("Configuration error: Invalid \"Netmask\" value"));
593 goto out;
594 }
595 memcpy(&netmask, &ip, sizeof(netmask));
596 if (pThis->pszGateway)
597 {
598 if (!inet_aton(pThis->pszGateway, &ip))
599 {
600 rc = PDMDEV_SET_ERROR(pDevIns,
601 VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
602 N_("Configuration error: Invalid \"Gateway\" value"));
603 goto out;
604 }
605 memcpy(&gw, &ip, sizeof(gw));
606 }
607 else
608 {
609 inet_aton(pThis->pszIP, &ip);
610 memcpy(&gw, &ip, sizeof(gw));
611 }
612
613 /*
614 * Initialize lwIP.
615 */
616 lwip_stats_init();
617 lwip_sys_init();
618#if MEM_LIBC_MALLOC == 0
619 lwip_mem_init();
620#endif
621 lwip_memp_init();
622 lwip_pbuf_init();
623 lwip_netif_init();
624 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, devINIPARPTimer, pThis,
625 TMTIMER_FLAGS_NO_CRIT_SECT, "lwIP ARP", &pThis->ARPTimer);
626 if (RT_FAILURE(rc))
627 goto out;
628 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, devINIPTCPFastTimer, pThis,
629 TMTIMER_FLAGS_NO_CRIT_SECT, "lwIP fast TCP", &pThis->TCPFastTimer);
630 if (RT_FAILURE(rc))
631 goto out;
632 TMTimerSetMillies(pThis->TCPFastTimer, TCP_FAST_INTERVAL);
633 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, devINIPTCPSlowTimer, pThis,
634 TMTIMER_FLAGS_NO_CRIT_SECT, "lwIP slow TCP", &pThis->TCPSlowTimer);
635 if (RT_FAILURE(rc))
636 goto out;
637 TMTimerSetMillies(pThis->TCPFastTimer, TCP_SLOW_INTERVAL);
638 pThis->LWIPTcpInitSem = lwip_sys_sem_new(0);
639 {
640 lwip_tcpip_init(devINIPTcpipInitDone, &pThis->LWIPTcpInitSem);
641 lwip_sys_sem_wait(pThis->LWIPTcpInitSem);
642 }
643
644 /*
645 * Set up global pointer to interface data.
646 */
647 g_pDevINIPData = pThis;
648
649 struct netif *ret;
650 pThis->IntNetIF.name[0] = 'I';
651 pThis->IntNetIF.name[1] = 'N';
652 ret = netif_add(&pThis->IntNetIF, &ipaddr, &netmask, &gw, NULL,
653 devINIPInterface, lwip_tcpip_input);
654 if (!ret)
655 {
656 rc = VERR_NET_NO_NETWORK;
657 goto out;
658 }
659
660 lwip_netif_set_default(&pThis->IntNetIF);
661 lwip_netif_set_up(&pThis->IntNetIF);
662
663 /* link hack */
664 pThis->pLinkHack = g_pDevINILinkHack;
665
666out:
667 LogFlow(("%s: return %Rrc\n", __FUNCTION__, rc));
668 return rc;
669}
670
671
672/**
673 * Query whether lwIP is initialized or not. Since there is only a single
674 * instance of this device ever for a VM, it can be a global function.
675 *
676 * @returns True if lwIP is initialized.
677 */
678bool DevINIPConfigured(void)
679{
680 return g_pDevINIPData != NULL;
681}
682
683
684/**
685 * Internal network IP stack device registration record.
686 */
687const PDMDEVREG g_DeviceINIP =
688{
689 /* u32Version */
690 PDM_DEVREG_VERSION,
691 /* szDeviceName */
692 "IntNetIP",
693 /* szRCMod/szR0Mod */
694 "",
695 "",
696 /* pszDescription */
697 "Internal Network IP stack device",
698 /* fFlags */
699 PDM_DEVREG_FLAGS_DEFAULT_BITS,
700 /* fClass. As this is used by the storage devices, it must come earlier. */
701 PDM_DEVREG_CLASS_VMM_DEV,
702 /* cMaxInstances */
703 1,
704 /* cbInstance */
705 sizeof(DEVINTNETIP),
706 /* pfnConstruct */
707 devINIPConstruct,
708 /* pfnDestruct */
709 devINIPDestruct,
710 /* pfnRelocate */
711 NULL,
712 /* pfnIOCtl */
713 NULL,
714 /* pfnPowerOn */
715 NULL,
716 /* pfnReset */
717 NULL,
718 /* pfnSuspend */
719 NULL,
720 /* pfnResume */
721 NULL,
722 /* pfnAttach */
723 NULL,
724 /* pfnDetach */
725 NULL,
726 /* pfnQueryInterface */
727 NULL,
728 /* pfnInitComplete */
729 NULL,
730 /* pfnPowerOff */
731 NULL,
732 /* pfnSoftReset */
733 NULL,
734 /* u32VersionEnd */
735 PDM_DEVREG_VERSION
736};
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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