VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/DrvTAPOs2.cpp@ 8610

Last change on this file since 8610 was 8610, checked in by vboxsync, 17 years ago

PCNet: completed fix for broken hostif with certain guests. Make sure the PCNet poll timer is actually running if fMaybeOutOfSpace is set. Never exit the TAP recv thread if pfnWaitReceiveAvail() as this means we were woken up during a VM state transition.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.6 KB
Line 
1/** $Id: DrvTAPOs2.cpp 8610 2008-05-05 20:09:26Z vboxsync $ */
2/** @file
3 * VBox network devices: OS/2 TAP network transport driver.
4 */
5
6/*
7 *
8 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_DRV_TUN
27#include <VBox/pdmdrv.h>
28
29#include <iprt/assert.h>
30#include <iprt/file.h>
31#include <iprt/string.h>
32#include <iprt/thread.h>
33#include <iprt/alloca.h>
34#include <iprt/asm.h>
35#include <iprt/semaphore.h>
36
37#include "Builtins.h"
38
39#define INCL_BASE
40#include <os2.h>
41#include "DrvTAPOs2.h"
42
43
44
45/*******************************************************************************
46* Structures and Typedefs *
47*******************************************************************************/
48
49/**
50 * Block driver instance data.
51 */
52typedef struct DRVTAPOS2
53{
54 /** The network interface. */
55 PDMINETWORKCONNECTOR INetworkConnector;
56 /** The network interface. */
57 PPDMINETWORKPORT pPort;
58 /** Pointer to the driver instance. */
59 PPDMDRVINS pDrvIns;
60 /** TAP device file handle. */
61 RTFILE hDevice;
62 /** Out LAN number. */
63 int32_t iLan;
64 /** The LAN number we're connected to. -1 if not connected. */
65 int32_t iConnectedTo;
66 /** Receiver thread. */
67 PPDMTHREAD pThread;
68 /** Set if the link is down.
69 * When the link is down all incoming packets will be dropped. */
70 bool volatile fLinkDown;
71 /** The log and thread name. */
72 char szName[16];
73 /** The \DEV\TAP$ device name. */
74 char szDevice[32];
75
76#ifdef VBOX_WITH_STATISTICS
77 /** Number of sent packets. */
78 STAMCOUNTER StatPktSent;
79 /** Number of sent bytes. */
80 STAMCOUNTER StatPktSentBytes;
81 /** Number of received packets. */
82 STAMCOUNTER StatPktRecv;
83 /** Number of received bytes. */
84 STAMCOUNTER StatPktRecvBytes;
85 /** Profiling packet transmit runs. */
86 STAMPROFILE StatTransmit;
87 /** Profiling packet receive runs. */
88 STAMPROFILEADV StatReceive;
89#endif /* VBOX_WITH_STATISTICS */
90
91#ifdef LOG_ENABLED
92 /** The nano ts of the last transfer. */
93 uint64_t u64LastTransferTS;
94 /** The nano ts of the last receive. */
95 uint64_t u64LastReceiveTS;
96#endif
97} DRVTAPOS2, *PDRVTAPOS2;
98
99
100/** Converts a pointer to TAP::INetworkConnector to a PRDVTAP. */
101#define PDMINETWORKCONNECTOR_2_DRVTAPOS2(pInterface) ( (PDRVTAPOS2)((uintptr_t)pInterface - RT_OFFSETOF(DRVTAPOS2, INetworkConnector)) )
102
103
104/**
105 * Send data to the network.
106 *
107 * @returns VBox status code.
108 * @param pInterface Pointer to the interface structure containing the called function pointer.
109 * @param pvBuf Data to send.
110 * @param cb Number of bytes to send.
111 * @thread EMT
112 */
113static DECLCALLBACK(int) drvTAPOs2Send(PPDMINETWORKCONNECTOR pInterface, const void *pvBuf, size_t cb)
114{
115 PDRVTAPOS2 pThis = PDMINETWORKCONNECTOR_2_DRVTAPOS2(pInterface);
116 STAM_COUNTER_INC(&pThis->StatPktSent);
117 STAM_COUNTER_ADD(&pThis->StatPktSentBytes, cb);
118 STAM_PROFILE_START(&pThis->StatTransmit, a);
119
120 /*
121 * If the pvBuf is a high address, we'll have to copy it onto a
122 * stack buffer of the tap driver will trap.
123 */
124 if ((uintptr_t)pvBuf >= _1M*512)
125 {
126 void *pvBufCopy = alloca(cb);
127 memcpy(pvBufCopy, pvBuf, cb);
128 pvBuf = pvBufCopy;
129 }
130
131#ifdef LOG_ENABLED
132 uint64_t u64Now = RTTimeProgramNanoTS();
133 LogFlow(("%s: Send: %-4d bytes at %RU64 ns deltas: recv=%RU64 xmit=%RU64\n", pThis->szName,
134 cb, u64Now, u64Now - pThis->u64LastReceiveTS, u64Now - pThis->u64LastTransferTS));
135 pThis->u64LastTransferTS = u64Now;
136 Log2(("%s Send: pvBuf=%p cb=%#zx\n"
137 "%.*Vhxd\n",
138 pThis->szName, pvBuf, cb, cb, pvBuf));
139#endif
140
141 ULONG Parm[2] = { ~0UL, ~0UL }; /* mysterious output */
142 ULONG cbParm = sizeof(Parm);
143 ULONG cbData = cb;
144 int rc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_WRITE_PACKET,
145 &Parm[0], cbParm, &cbParm,
146 (void *)pvBuf, cbData, &cbData);
147 if (RT_UNLIKELY(rc || Parm[0]))
148 {
149 static unsigned cComplaints = 0;
150 if (cComplaints++ < 256)
151 LogRel(("%s: send failed. rc=%d Parm={%ld,%ld} cb=%d\n",
152 pThis->szName, rc, Parm[0], Parm[1], cb));
153 if (rc)
154 rc = RTErrConvertFromOS2(rc);
155 else
156 rc = VERR_IO_GEN_FAILURE;
157 }
158 Log3(("%s: Send completed %d ns\n", pThis->szName, RTTimeProgramNanoTS() - pThis->u64LastTransferTS));
159
160 STAM_PROFILE_STOP(&pThis->StatTransmit, a);
161 AssertRC(rc);
162 return rc;
163}
164
165
166/**
167 * Set promiscuous mode.
168 *
169 * This is called when the promiscuous mode is set. This means that there doesn't have
170 * to be a mode change when it's called.
171 *
172 * @param pInterface Pointer to the interface structure containing the called function pointer.
173 * @param fPromiscuous Set if the adaptor is now in promiscuous mode. Clear if it is not.
174 * @thread EMT
175 */
176static DECLCALLBACK(void) drvTAPOs2SetPromiscuousMode(PPDMINETWORKCONNECTOR pInterface, bool fPromiscuous)
177{
178 PDRVTAPOS2 pThis = PDMINETWORKCONNECTOR_2_DRVTAPOS2(pInterface);
179 LogFlow(("%s: SetPromiscuousMode: fPromiscuous=%d\n", pThis->szName, fPromiscuous));
180 NOREF(pThis);
181 /** @todo is it always in promiscuous mode? */
182}
183
184
185/**
186 * Notification on link status changes.
187 *
188 * @param pInterface Pointer to the interface structure containing the called function pointer.
189 * @param enmLinkState The new link state.
190 * @thread EMT
191 */
192static DECLCALLBACK(void) drvTAPOs2NotifyLinkChanged(PPDMINETWORKCONNECTOR pInterface, PDMNETWORKLINKSTATE enmLinkState)
193{
194 PDRVTAPOS2 pThis = PDMINETWORKCONNECTOR_2_DRVTAPOS2(pInterface);
195 bool fLinkDown;
196 switch (enmLinkState)
197 {
198 case PDMNETWORKLINKSTATE_DOWN:
199 case PDMNETWORKLINKSTATE_DOWN_RESUME:
200 fLinkDown = true;
201 break;
202 default:
203 AssertMsgFailed(("enmLinkState=%d\n", enmLinkState));
204 case PDMNETWORKLINKSTATE_UP:
205 fLinkDown = false;
206 break;
207 }
208 LogFlow(("%s: NotifyLinkChanged: enmLinkState=%d %d->%d\n", pThis->szName, pThis->fLinkDown, fLinkDown));
209 ASMAtomicXchgBool(&pThis->fLinkDown, fLinkDown);
210}
211
212
213/**
214 * Receiver thread.
215 *
216 * @returns VBox status code. Returning failure will naturally terminate the thread.
217 * @param pDrvIns The pcnet device instance.
218 * @param pThread The thread.
219 */
220static DECLCALLBACK(int) drvTAPOs2ReceiveThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
221{
222 PDRVTAPOS2 pThis = PDMINS2DATA(pDrvIns, PDRVTAPOS2);
223
224 /*
225 * No initialization work to do, just return immediately.
226 */
227 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
228 return VINF_SUCCESS;
229 Assert(pThread->enmState == PDMTHREADSTATE_RUNNING);
230
231 /*
232 * Loop while the thread is running, quit immediately when
233 * we're supposed to suspend or terminate.
234 */
235 while (pThread->enmState == PDMTHREADSTATE_RUNNING)
236 {
237 /*
238 * Read a frame, this will block for a while if nothing to read.
239 */
240 char abBuf[4096];
241 ULONG Parm[2] = { ~0UL, ~0UL }; /* mysterious output */
242 ULONG cbParm = sizeof(Parm); /* this one is actually ignored... */
243 ULONG cbBuf = sizeof(abBuf);
244
245 int rc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_READ_PACKET,
246 &Parm[0], cbParm, &cbParm,
247 &abBuf[0], cbBuf, &cbBuf);
248 if (pThread->enmState != PDMTHREADSTATE_RUNNING)
249 break;
250 const size_t cbRead = Parm[1];
251 if ( !rc
252 && !Parm[0]
253 && cbRead > 0 /* cbRead */)
254 {
255 AssertMsg(cbRead <= 1536, ("cbRead=%d\n", cbRead));
256
257 /*
258 * Wait for the device to have some room. A return code != VINF_SUCCESS
259 * means that we were woken up during a VM state transition. Drop the
260 * current packet and wait for the next one.
261 */
262 rc = pThis->pPort->pfnWaitReceiveAvail(pThis->pPort, RT_INDEFINITE_WAIT);
263 if (RT_FAILURE(rc))
264 continue;
265
266 /*
267 * Pass the data up.
268 */
269#ifdef LOG_ENABLED
270 uint64_t u64Now = RTTimeProgramNanoTS();
271 LogFlow(("%s: ReceiveThread: %-4d bytes at %RU64 ns deltas: recv=%RU64 xmit=%RU64\n", pThis->szName,
272 cbRead, u64Now, u64Now - pThis->u64LastReceiveTS, u64Now - pThis->u64LastTransferTS));
273 pThis->u64LastReceiveTS = u64Now;
274#endif
275 Log2(("%s: ReceiveThread: cbRead=%#x\n"
276 "%.*Vhxd\n",
277 pThis->szName, cbRead, cbRead, abBuf));
278 STAM_COUNTER_INC(&pThis->StatPktRecv);
279 STAM_COUNTER_ADD(&pThis->StatPktRecvBytes, cbRead);
280 rc = pThis->pPort->pfnReceive(pThis->pPort, abBuf, cbRead);
281 AssertRC(rc);
282 }
283 /* we'll be returning ~1 per second with no data; rc=0 Parm[0] = 1, Parm[1] = 0. */
284 else if (rc)
285 {
286 LogFlow(("%s: ReceiveThread: DoDevIOCtl -> %s Parm={%ld, %ld}\n",
287 pThis->szName, rc, Parm[0], Parm[1]));
288 rc = RTErrConvertFromOS2(rc);
289 if (rc == VERR_INVALID_HANDLE)
290 return rc;
291 RTThreadYield();
292 }
293 }
294
295 /* The thread is being suspended or terminated. */
296 return VINF_SUCCESS;
297}
298
299
300/**
301 * Unblock the send thread so it can respond to a state change.
302 *
303 * @returns VBox status code.
304 * @param pDrvIns The pcnet device instance.
305 * @param pThread The send thread.
306 */
307static DECLCALLBACK(int) drvTAPOs2WakeupReceiveThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
308{
309 PDRVTAPOS2 pThis = PDMINS2DATA(pDrvIns, PDRVTAPOS2);
310 LogFlow(("%s: WakeupReceiveThread\n", pThis->szName));
311
312 /* cancel any pending reads */
313 ULONG Parm[2] = { ~0UL, ~0UL }; /* mysterious output */
314 ULONG cbParm = sizeof(Parm);
315 ULONG Data = pThis->iLan; /* right? */
316 ULONG cbData = sizeof(Data);
317 int orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_CANCEL_READ,
318 &Parm[0], cbParm, &cbParm,
319 &Data, cbData, &cbData);
320 AssertMsg(orc == 0, ("%d\n", orc)); NOREF(orc);
321
322 return VINF_SUCCESS;
323}
324
325
326/**
327 * Queries an interface to the driver.
328 *
329 * @returns Pointer to interface.
330 * @returns NULL if the interface was not supported by the driver.
331 * @param pInterface Pointer to this interface structure.
332 * @param enmInterface The requested interface identification.
333 * @thread Any thread.
334 */
335static DECLCALLBACK(void *) drvTAPOs2QueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
336{
337 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
338 PDRVTAPOS2 pThis = PDMINS2DATA(pDrvIns, PDRVTAPOS2);
339 switch (enmInterface)
340 {
341 case PDMINTERFACE_BASE:
342 return &pDrvIns->IBase;
343 case PDMINTERFACE_NETWORK_CONNECTOR:
344 return &pThis->INetworkConnector;
345 default:
346 return NULL;
347 }
348}
349
350
351/**
352 * Destruct a driver instance.
353 *
354 * Most VM resources are freed by the VM. This callback is provided so that any non-VM
355 * resources can be freed correctly.
356 *
357 * @param pDrvIns The driver instance data.
358 */
359static DECLCALLBACK(void) drvTAPOs2Destruct(PPDMDRVINS pDrvIns)
360{
361 PDRVTAPOS2 pThis = PDMINS2DATA(pDrvIns, PDRVTAPOS2);
362 LogFlow(("%s: Destruct\n", pThis->szName));
363
364 /* PDM will destroy the thread for us, it's suspended right now. */
365
366 /*
367 * Disconnect from the lan if we made a connection and close it.
368 */
369 if (pThis->iConnectedTo != -1)
370 {
371 ULONG Parm[2] = { ~0UL, ~0UL }; /* mysterious output */
372 ULONG cbParm = sizeof(Parm);
373 ULONG Data = pThis->iConnectedTo;
374 ULONG cbData = sizeof(Data);
375 int orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_DISCONNECT_NIC,
376 &Parm, cbParm, &cbParm,
377 &Data, cbData, &cbData);
378 if ( orc
379 || Parm[0])
380 LogRel(("%s: Failed to disconnect %d from %d! orc=%d Parm={%ld,%ld}\n",
381 pThis->szName, pThis->iLan, pThis->iConnectedTo, orc, Parm[0], Parm[1]));
382 pThis->iConnectedTo = -1;
383 }
384
385 if (pThis->hDevice != NIL_RTFILE)
386 {
387 int rc = RTFileClose(pThis->hDevice);
388 AssertRC(rc);
389 pThis->hDevice = NIL_RTFILE;
390 }
391}
392
393
394/**
395 * Construct a TAP network transport driver instance.
396 *
397 * @returns VBox status.
398 * @param pDrvIns The driver instance data.
399 * If the registration structure is needed, pDrvIns->pDrvReg points to it.
400 * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
401 * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
402 * iInstance it's expected to be used a bit in this function.
403 */
404static DECLCALLBACK(int) drvTAPOs2Construct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
405{
406 PDRVTAPOS2 pThis = PDMINS2DATA(pDrvIns, PDRVTAPOS2);
407
408 /*
409 * Init the static parts.
410 */
411 pThis->pDrvIns = pDrvIns;
412 pThis->hDevice = NIL_RTFILE;
413 pThis->iLan = -1;
414 pThis->iConnectedTo = -1;
415 pThis->pThread = NULL;
416 RTStrPrintf(pThis->szName, sizeof(pThis->szName), "TAP%d", pDrvIns->iInstance);
417 /* IBase */
418 pDrvIns->IBase.pfnQueryInterface = drvTAPOs2QueryInterface;
419 /* INetwork */
420 pThis->INetworkConnector.pfnSend = drvTAPOs2Send;
421 pThis->INetworkConnector.pfnSetPromiscuousMode = drvTAPOs2SetPromiscuousMode;
422 pThis->INetworkConnector.pfnNotifyLinkChanged = drvTAPOs2NotifyLinkChanged;
423
424 /*
425 * Validate the config.
426 */
427 if (!CFGMR3AreValuesValid(pCfgHandle, "Device\0ConnectTo\0"))
428 return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES, "");
429
430 /*
431 * Check that no-one is attached to us.
432 */
433 int rc = pDrvIns->pDrvHlp->pfnAttach(pDrvIns, NULL);
434 if (rc != VERR_PDM_NO_ATTACHED_DRIVER)
435 return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRVINS_NO_ATTACH,
436 N_("Configuration error: Cannot attach drivers to the TAP driver"));
437
438 /*
439 * Query the network port interface.
440 */
441 pThis->pPort = (PPDMINETWORKPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_NETWORK_PORT);
442 if (!pThis->pPort)
443 return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE,
444 N_("Configuration error: The above device/driver didn't export the network port interface"));
445
446 /*
447 * Read the configuration.
448 */
449 rc = CFGMR3QueryString(pCfgHandle, "Device", &pThis->szDevice[0], sizeof(pThis->szDevice));
450 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
451 strcpy(pThis->szDevice, "\\DEV\\TAP$");
452 else if (VBOX_FAILURE(rc))
453 return PDMDRV_SET_ERROR(pDrvIns, rc,
454 N_("Configuration error: Query for \"Device\" failed"));
455
456 int32_t iConnectTo;
457 rc = CFGMR3QueryS32(pCfgHandle, "ConnectTo", &iConnectTo);
458 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
459 iConnectTo = -1;
460 else if (VBOX_FAILURE(rc))
461 return PDMDRV_SET_ERROR(pDrvIns, rc,
462 N_("Configuration error: Query for \"ConnectTo\" failed"));
463
464 /*
465 * Open the device.
466 * Keep in mind that the destructor is always called!
467 */
468 rc = RTFileOpen(&pThis->hDevice, pThis->szDevice, RTFILE_O_DENY_NONE | RTFILE_O_READ);
469 if (VBOX_FAILURE(rc))
470 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
471 N_("Failed to open tap device '%s'"), pThis->szDevice);
472
473 ULONG Parm[2] = { ~0UL, ~0UL }; /* mysterious output */
474 ULONG cbParm = sizeof(Parm);
475 ULONG Data = ~0UL;
476 ULONG cbData = sizeof(Data);
477 int orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_GET_LAN_NUMBER,
478 &Parm, cbParm, &cbParm,
479 &Data, cbData, &cbData);
480 if (orc)
481 rc = RTErrConvertFromOS2(orc);
482 else if (Parm[0])
483 rc = VERR_GENERAL_FAILURE;
484 if (VBOX_FAILURE(rc))
485 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
486 N_("Failed to query LanNumber! orc=%d Parm={%ld,%ld}"),
487 orc, Parm[0], Parm[1]);
488 pThis->iLan = (int32_t)Data;
489 Log(("%s: iLan=%d Parm[1]=%ld\n", pThis->szName, pThis->iLan, Parm[1]));
490
491 /*
492 * Connect it requested.
493 */
494 if (iConnectTo != -1)
495 {
496 if (iConnectTo == pThis->iLan)
497 return PDMDrvHlpVMSetError(pDrvIns, VERR_INVALID_PARAMETER, RT_SRC_POS,
498 N_("Cannot connect to ourself (%d)"), iConnectTo);
499
500 Parm[0] = Parm[1] = ~0UL; /* mysterious output */
501 cbParm = sizeof(Parm);
502 Data = iConnectTo;
503 cbData = sizeof(Data);
504 int orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_CONNECT_NIC,
505 &Parm, cbParm, &cbParm,
506 &Data, cbData, &cbData);
507 if (orc)
508 rc = RTErrConvertFromOS2(orc);
509 else if (Parm[0])
510 rc = VERR_GENERAL_FAILURE;
511 if (VBOX_FAILURE(rc))
512 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
513 N_("Failed to connect %d to %d! orc=%d Parm={%ld,%ld}"),
514 pThis->iLan, iConnectTo, orc, Parm[0], Parm[1]);
515 Log(("%s: Connected to %d\n", pThis->szName, iConnectTo));
516 pThis->iConnectedTo = iConnectTo;
517 }
518
519 /*
520 * Log the config.
521 */
522 Parm[0] = Parm[1] = ~0UL; /* mysterious output */
523 PDMMAC Mac;
524 cbParm = sizeof(Parm);
525 cbData = sizeof(Mac);
526 orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_READ_MAC_ADDRESS,
527 &Parm[0], cbParm, &cbParm,
528 &Mac, cbData, &cbData);
529 if ( !orc
530 && !Parm[0]
531 /*&& !Parm[1]?*/)
532 LogRel(("%s: iLan=%d iConnectedTo=%d Mac=%02x:%02x:%02x:%02x:%02x:%02x\n",
533 pThis->szName, pThis->iLan, pThis->iConnectedTo,
534 Mac.au8[0], Mac.au8[1], Mac.au8[2], Mac.au8[3], Mac.au8[4], Mac.au8[5]));
535 else
536 LogRel(("%s: iLan=%d iConnectedTo Mac=failed - orc=%d Parm={%ld,%ld}\n",
537 pThis->szName, pThis->iLan, pThis->iConnectedTo, Parm[0], Parm[1]));
538
539 rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pThread, pThis, drvTAPOs2ReceiveThread, drvTAPOs2WakeupReceiveThread,
540 0, RTTHREADTYPE_IO, pThis->szName);
541 AssertRCReturn(rc, rc);
542
543#ifdef VBOX_WITH_STATISTICS
544 /*
545 * Statistics.
546 */
547 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktSent, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of sent packets.", "/Drivers/TAP%d/Packets/Sent", pDrvIns->iInstance);
548 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktSentBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Number of sent bytes.", "/Drivers/TAP%d/Bytes/Sent", pDrvIns->iInstance);
549 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktRecv, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of received packets.", "/Drivers/TAP%d/Packets/Received", pDrvIns->iInstance);
550 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktRecvBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Number of received bytes.", "/Drivers/TAP%d/Bytes/Received", pDrvIns->iInstance);
551 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatTransmit, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling packet transmit runs.", "/Drivers/TAP%d/Transmit", pDrvIns->iInstance);
552 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatReceive, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling packet receive runs.", "/Drivers/TAP%d/Receive", pDrvIns->iInstance);
553#endif /* VBOX_WITH_STATISTICS */
554
555 return rc;
556}
557
558
559/**
560 * TAP network transport driver registration record.
561 */
562const PDMDRVREG g_DrvHostInterface =
563{
564 /* u32Version */
565 PDM_DRVREG_VERSION,
566 /* szDriverName */
567 "HostInterface",
568 /* pszDescription */
569 "TAP Network Transport Driver",
570 /* fFlags */
571 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
572 /* fClass. */
573 PDM_DRVREG_CLASS_NETWORK,
574 /* cMaxInstances */
575 ~0,
576 /* cbInstance */
577 sizeof(DRVTAPOS2),
578 /* pfnConstruct */
579 drvTAPOs2Construct,
580 /* pfnDestruct */
581 drvTAPOs2Destruct,
582 /* pfnIOCtl */
583 NULL,
584 /* pfnPowerOn */
585 NULL,
586 /* pfnReset */
587 NULL,
588 /* pfnSuspend */
589 NULL,
590 /* pfnResume */
591 NULL,
592 /* pfnDetach */
593 NULL,
594 /* pfnPowerOff */
595 NULL
596};
597
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