VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/VBoxLwipCore.cpp@ 48001

Last change on this file since 48001 was 47886, checked in by vboxsync, 12 years ago

export lwip-new to OSE

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.4 KB
Line 
1/* $Id: VBoxLwipCore.cpp 47886 2013-08-20 10:42:22Z vboxsync $ */
2/** @file
3 * VBox Lwip Core Initiatetor/Finilizer.
4 */
5
6/*
7 * Copyright (C) 2012-2013 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 * @todo: this should be somehow shared with with DevINIP, because
20 * we want that every NAT and DevINIP instance uses a initialized LWIP
21 * initialization of LWIP should happen on iLWIPInitiatorCounter 0 -> 1.
22 * see pfnConstruct/Destruct.
23 *
24 * @note: see comment to DevINIP.cpp:DevINIPConfigured
25 * @note: perhaps initilization stuff would be better move out of NAT driver,
26 * because we have to deal with attaching detaching NAT driver at runtime.
27 */
28#include <iprt/types.h>
29#include "VBoxLwipCore.h"
30/* @todo: lwip or nat ? */
31#define LOG_GROUP LOG_GROUP_DRV_NAT
32#include <iprt/critsect.h>
33#include <iprt/timer.h>
34#include <VBox/err.h>
35#include <VBox/log.h>
36
37extern "C" {
38#include "lwip/opt.h"
39#include "lwip/sys.h"
40#include "netif/etharp.h"
41#include "lwip/stats.h"
42#include "lwip/mem.h"
43#include "lwip/memp.h"
44#include "lwip/tcp_impl.h"
45#include "lwip/tcpip.h"
46}
47
48typedef struct {
49 PFNRT1 pfn;
50 void *pvUser;
51} LWIPCOREUSERCALLBACK, *PLWIPCOREUSERCALLBACK;
52
53
54typedef struct LWIPCORE
55{
56 int iLWIPInitiatorCounter;
57 PRTTIMER LwipArpTimer;
58 PRTTIMER LwipTcpFastTimer;
59 PRTTIMER LwipTcpSlowTimer;
60 /* semaphore to coordinate 'tcpip' thread initialization */
61 sys_sem_t LwipTcpIpSem;
62 /* Initalization user defined callback */
63 LWIPCOREUSERCALLBACK userInitClbk;
64 /* Finitialization user defined callback */
65 LWIPCOREUSERCALLBACK userFiniClbk;
66 RTCRITSECT csLwipCore;
67} LWIPCORE;
68
69static LWIPCORE g_LwipCore;
70
71
72/* Lwip Core Timer functions */
73void tmrLwipCoreArp(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
74{
75 lwip_etharp_tmr();
76}
77
78
79void tmrLwipCoreTcpFast(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
80{
81 lwip_tcp_fasttmr();
82}
83
84
85void tmrLwipCoreTcpSlow(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
86{
87 lwip_tcp_slowtmr();
88}
89
90/**
91 * @note: this function executed on TCPIP thread.
92 */
93static DECLCALLBACK(void) lwipCoreInitDone(void *pvArg)
94{
95 sys_sem_t *pLwipSem = (sys_sem_t *)pvArg;
96 LogFlowFunc(("ENTER: pvArg:%p\n", pvArg));
97 AssertPtrReturnVoid(pvArg);
98 lwip_sys_sem_signal(pLwipSem);
99 LogFlowFuncLeave();
100}
101
102/**
103 * @note: this function executed on TCPIP thread.
104 */
105static DECLCALLBACK(void) lwipCoreFiniDone(void *pvArg)
106{
107 sys_sem_t *pLwipSem = (sys_sem_t *)pvArg;
108 LogFlowFunc(("ENTER: pvArg:%p\n", pvArg));
109 AssertPtrReturnVoid(pvArg);
110 lwip_sys_sem_signal(pLwipSem);
111 LogFlowFuncLeave();
112}
113
114/**
115 * @note: this function executed on TCPIP thread.
116 */
117static DECLCALLBACK(void) lwipCoreUserCallback(void *pvArg)
118{
119 PLWIPCOREUSERCALLBACK pUserClbk = (PLWIPCOREUSERCALLBACK)pvArg;
120 LogFlowFunc(("ENTER: pvArg:%p\n", pvArg));
121
122 if (pUserClbk->pfn)
123 pUserClbk->pfn(pUserClbk->pvUser);
124
125 /* we've finished on tcpip thread and want to wake up, waiters on EMT/main */
126 lwip_sys_sem_signal(&g_LwipCore.LwipTcpIpSem);
127 AssertPtrReturnVoid(pvArg);
128 LogFlowFuncLeave();
129}
130
131/**
132 * This function initialize lwip core once
133 * further NAT instancies should just add netifs configured according
134 * their needs.
135 *
136 * We're on EMT-n or main thread of the network service, we want execute
137 * anything on tcpip thread.
138 */
139int vboxLwipCoreInitialize(PFNRT1 pfnCallback, void *pvCallbackArg)
140{
141 int rc = VINF_SUCCESS;
142 int lwipRc = ERR_OK;
143 LogFlowFuncEnter();
144
145 if (!RTCritSectIsInitialized(&g_LwipCore.csLwipCore))
146 {
147 AssertReturn(g_LwipCore.iLWIPInitiatorCounter == 0, VERR_INTERNAL_ERROR);
148 rc = RTCritSectInit(&g_LwipCore.csLwipCore);
149
150 AssertRCReturn(rc, rc);
151 }
152
153 RTCritSectEnter(&g_LwipCore.csLwipCore);
154
155 g_LwipCore.iLWIPInitiatorCounter++;
156
157 if (g_LwipCore.iLWIPInitiatorCounter == 1)
158 {
159 lwipRc = lwip_sys_sem_new(&g_LwipCore.LwipTcpIpSem, 0);
160 /* @todo: VERR_INTERNAL_ERROR perhaps should be replaced with right error code */
161 if (lwipRc != ERR_OK)
162 {
163 rc = VERR_INTERNAL_ERROR;
164 goto done;
165 }
166
167 lwip_tcpip_init(lwipCoreInitDone, &g_LwipCore.LwipTcpIpSem,
168 lwipCoreFiniDone, &g_LwipCore.LwipTcpIpSem);
169 lwip_sys_sem_wait(&g_LwipCore.LwipTcpIpSem, 0);
170 } /* end of if (g_LwipCore.iLWIPInitiatorCounter == 1) */
171
172
173 /* tcpip thread launched */
174 g_LwipCore.userInitClbk.pfn = pfnCallback;
175 g_LwipCore.userInitClbk.pvUser = pvCallbackArg;
176
177 /* _block mean that we might be blocked on post to mailbox and the last 1 is our
178 * agreement with this fact
179 */
180 lwipRc = tcpip_callback_with_block(lwipCoreUserCallback, &g_LwipCore.userInitClbk, 1);
181 if (lwipRc != ERR_OK)
182 {
183 rc = VERR_INTERNAL_ERROR;
184 goto done;
185 }
186
187
188 /* we're waiting the result here */
189 lwipRc = lwip_sys_sem_wait(&g_LwipCore.LwipTcpIpSem, 0);
190 if (lwipRc != ERR_OK)
191 {
192 rc = VERR_INTERNAL_ERROR;
193 goto done;
194 }
195
196done:
197 RTCritSectLeave(&g_LwipCore.csLwipCore);
198 LogFlowFuncLeaveRC(rc);
199 return rc;
200}
201
202/**
203 * This function decrement lwip reference counter
204 * and calls tcpip thread termination function.
205 */
206void vboxLwipCoreFinalize(PFNRT1 pfnCallback, void *pvCallbackArg)
207{
208 int lwipRc = ERR_OK;
209 LogFlowFuncEnter();
210 AssertReleaseReturnVoid( RTCritSectIsInitialized(&g_LwipCore.csLwipCore)
211 && g_LwipCore.iLWIPInitiatorCounter >= 1);
212 RTCritSectEnter(&g_LwipCore.csLwipCore);
213
214 g_LwipCore.iLWIPInitiatorCounter--;
215 g_LwipCore.userFiniClbk.pfn = pfnCallback;
216 g_LwipCore.userFiniClbk.pvUser = pvCallbackArg;
217
218 lwipRc = tcpip_callback_with_block(lwipCoreUserCallback, &g_LwipCore.userFiniClbk, 1);
219
220 if (lwipRc == ERR_OK)
221 lwip_sys_sem_wait(&g_LwipCore.LwipTcpIpSem, 0);
222
223 if (g_LwipCore.iLWIPInitiatorCounter == 0)
224 {
225 tcpip_terminate();
226 RTCritSectLeave(&g_LwipCore.csLwipCore);
227 RTCritSectDelete(&g_LwipCore.csLwipCore);
228 }
229 else
230 RTCritSectLeave(&g_LwipCore.csLwipCore);
231
232 LogFlowFuncLeave();
233}
Note: See TracBrowser for help on using the repository browser.

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