VirtualBox

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

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

DrvTAP: Increased buffer sizes to 16384 in Windows and OS/2. Increased max MTU size to 16384 in .inf file.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.7 KB
Line 
1/** $Id: DrvTAPOs2.cpp 11448 2008-08-15 18:17:28Z 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 = PDMINS_2_DATA(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[16384];
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 // The following assertion was commented out to support jumbo frames.
256 //AssertMsg(cbRead <= 1536, ("cbRead=%d\n", cbRead));
257
258 /*
259 * Wait for the device to have some room. A return code != VINF_SUCCESS
260 * means that we were woken up during a VM state transition. Drop the
261 * current packet and wait for the next one.
262 */
263 rc = pThis->pPort->pfnWaitReceiveAvail(pThis->pPort, RT_INDEFINITE_WAIT);
264 if (RT_FAILURE(rc))
265 continue;
266
267 /*
268 * Pass the data up.
269 */
270#ifdef LOG_ENABLED
271 uint64_t u64Now = RTTimeProgramNanoTS();
272 LogFlow(("%s: ReceiveThread: %-4d bytes at %RU64 ns deltas: recv=%RU64 xmit=%RU64\n", pThis->szName,
273 cbRead, u64Now, u64Now - pThis->u64LastReceiveTS, u64Now - pThis->u64LastTransferTS));
274 pThis->u64LastReceiveTS = u64Now;
275#endif
276 Log2(("%s: ReceiveThread: cbRead=%#x\n"
277 "%.*Vhxd\n",
278 pThis->szName, cbRead, cbRead, abBuf));
279 STAM_COUNTER_INC(&pThis->StatPktRecv);
280 STAM_COUNTER_ADD(&pThis->StatPktRecvBytes, cbRead);
281 rc = pThis->pPort->pfnReceive(pThis->pPort, abBuf, cbRead);
282 AssertRC(rc);
283 }
284 /* we'll be returning ~1 per second with no data; rc=0 Parm[0] = 1, Parm[1] = 0. */
285 else if (rc)
286 {
287 LogFlow(("%s: ReceiveThread: DoDevIOCtl -> %s Parm={%ld, %ld}\n",
288 pThis->szName, rc, Parm[0], Parm[1]));
289 rc = RTErrConvertFromOS2(rc);
290 if (rc == VERR_INVALID_HANDLE)
291 return rc;
292 RTThreadYield();
293 }
294 }
295
296 /* The thread is being suspended or terminated. */
297 return VINF_SUCCESS;
298}
299
300
301/**
302 * Unblock the send thread so it can respond to a state change.
303 *
304 * @returns VBox status code.
305 * @param pDrvIns The pcnet device instance.
306 * @param pThread The send thread.
307 */
308static DECLCALLBACK(int) drvTAPOs2WakeupReceiveThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
309{
310 PDRVTAPOS2 pThis = PDMINS_2_DATA(pDrvIns, PDRVTAPOS2);
311 LogFlow(("%s: WakeupReceiveThread\n", pThis->szName));
312
313 /* cancel any pending reads */
314 ULONG Parm[2] = { ~0UL, ~0UL }; /* mysterious output */
315 ULONG cbParm = sizeof(Parm);
316 ULONG Data = pThis->iLan; /* right? */
317 ULONG cbData = sizeof(Data);
318 int orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_CANCEL_READ,
319 &Parm[0], cbParm, &cbParm,
320 &Data, cbData, &cbData);
321 AssertMsg(orc == 0, ("%d\n", orc)); NOREF(orc);
322
323 return VINF_SUCCESS;
324}
325
326
327/**
328 * Queries an interface to the driver.
329 *
330 * @returns Pointer to interface.
331 * @returns NULL if the interface was not supported by the driver.
332 * @param pInterface Pointer to this interface structure.
333 * @param enmInterface The requested interface identification.
334 * @thread Any thread.
335 */
336static DECLCALLBACK(void *) drvTAPOs2QueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
337{
338 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
339 PDRVTAPOS2 pThis = PDMINS_2_DATA(pDrvIns, PDRVTAPOS2);
340 switch (enmInterface)
341 {
342 case PDMINTERFACE_BASE:
343 return &pDrvIns->IBase;
344 case PDMINTERFACE_NETWORK_CONNECTOR:
345 return &pThis->INetworkConnector;
346 default:
347 return NULL;
348 }
349}
350
351
352/**
353 * Destruct a driver instance.
354 *
355 * Most VM resources are freed by the VM. This callback is provided so that any non-VM
356 * resources can be freed correctly.
357 *
358 * @param pDrvIns The driver instance data.
359 */
360static DECLCALLBACK(void) drvTAPOs2Destruct(PPDMDRVINS pDrvIns)
361{
362 PDRVTAPOS2 pThis = PDMINS_2_DATA(pDrvIns, PDRVTAPOS2);
363 LogFlow(("%s: Destruct\n", pThis->szName));
364
365 /* PDM will destroy the thread for us, it's suspended right now. */
366
367 /*
368 * Disconnect from the lan if we made a connection and close it.
369 */
370 if (pThis->iConnectedTo != -1)
371 {
372 ULONG Parm[2] = { ~0UL, ~0UL }; /* mysterious output */
373 ULONG cbParm = sizeof(Parm);
374 ULONG Data = pThis->iConnectedTo;
375 ULONG cbData = sizeof(Data);
376 int orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_DISCONNECT_NIC,
377 &Parm, cbParm, &cbParm,
378 &Data, cbData, &cbData);
379 if ( orc
380 || Parm[0])
381 LogRel(("%s: Failed to disconnect %d from %d! orc=%d Parm={%ld,%ld}\n",
382 pThis->szName, pThis->iLan, pThis->iConnectedTo, orc, Parm[0], Parm[1]));
383 pThis->iConnectedTo = -1;
384 }
385
386 if (pThis->hDevice != NIL_RTFILE)
387 {
388 int rc = RTFileClose(pThis->hDevice);
389 AssertRC(rc);
390 pThis->hDevice = NIL_RTFILE;
391 }
392}
393
394
395/**
396 * Construct a TAP network transport driver instance.
397 *
398 * @returns VBox status.
399 * @param pDrvIns The driver instance data.
400 * If the registration structure is needed, pDrvIns->pDrvReg points to it.
401 * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
402 * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
403 * iInstance it's expected to be used a bit in this function.
404 */
405static DECLCALLBACK(int) drvTAPOs2Construct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
406{
407 PDRVTAPOS2 pThis = PDMINS_2_DATA(pDrvIns, PDRVTAPOS2);
408
409 /*
410 * Init the static parts.
411 */
412 pThis->pDrvIns = pDrvIns;
413 pThis->hDevice = NIL_RTFILE;
414 pThis->iLan = -1;
415 pThis->iConnectedTo = -1;
416 pThis->pThread = NULL;
417 RTStrPrintf(pThis->szName, sizeof(pThis->szName), "TAP%d", pDrvIns->iInstance);
418 /* IBase */
419 pDrvIns->IBase.pfnQueryInterface = drvTAPOs2QueryInterface;
420 /* INetwork */
421 pThis->INetworkConnector.pfnSend = drvTAPOs2Send;
422 pThis->INetworkConnector.pfnSetPromiscuousMode = drvTAPOs2SetPromiscuousMode;
423 pThis->INetworkConnector.pfnNotifyLinkChanged = drvTAPOs2NotifyLinkChanged;
424
425 /*
426 * Validate the config.
427 */
428 if (!CFGMR3AreValuesValid(pCfgHandle, "Device\0ConnectTo\0"))
429 return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES, "");
430
431 /*
432 * Check that no-one is attached to us.
433 */
434 int rc = pDrvIns->pDrvHlp->pfnAttach(pDrvIns, NULL);
435 if (rc != VERR_PDM_NO_ATTACHED_DRIVER)
436 return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRVINS_NO_ATTACH,
437 N_("Configuration error: Cannot attach drivers to the TAP driver"));
438
439 /*
440 * Query the network port interface.
441 */
442 pThis->pPort = (PPDMINETWORKPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_NETWORK_PORT);
443 if (!pThis->pPort)
444 return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE,
445 N_("Configuration error: The above device/driver didn't export the network port interface"));
446
447 /*
448 * Read the configuration.
449 */
450 rc = CFGMR3QueryString(pCfgHandle, "Device", &pThis->szDevice[0], sizeof(pThis->szDevice));
451 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
452 strcpy(pThis->szDevice, "\\DEV\\TAP$");
453 else if (RT_FAILURE(rc))
454 return PDMDRV_SET_ERROR(pDrvIns, rc,
455 N_("Configuration error: Query for \"Device\" failed"));
456
457 int32_t iConnectTo;
458 rc = CFGMR3QueryS32(pCfgHandle, "ConnectTo", &iConnectTo);
459 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
460 iConnectTo = -1;
461 else if (RT_FAILURE(rc))
462 return PDMDRV_SET_ERROR(pDrvIns, rc,
463 N_("Configuration error: Query for \"ConnectTo\" failed"));
464
465 /*
466 * Open the device.
467 * Keep in mind that the destructor is always called!
468 */
469 rc = RTFileOpen(&pThis->hDevice, pThis->szDevice, RTFILE_O_DENY_NONE | RTFILE_O_READ);
470 if (RT_FAILURE(rc))
471 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
472 N_("Failed to open tap device '%s'"), pThis->szDevice);
473
474 ULONG Parm[2] = { ~0UL, ~0UL }; /* mysterious output */
475 ULONG cbParm = sizeof(Parm);
476 ULONG Data = ~0UL;
477 ULONG cbData = sizeof(Data);
478 int orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_GET_LAN_NUMBER,
479 &Parm, cbParm, &cbParm,
480 &Data, cbData, &cbData);
481 if (orc)
482 rc = RTErrConvertFromOS2(orc);
483 else if (Parm[0])
484 rc = VERR_GENERAL_FAILURE;
485 if (RT_FAILURE(rc))
486 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
487 N_("Failed to query LanNumber! orc=%d Parm={%ld,%ld}"),
488 orc, Parm[0], Parm[1]);
489 pThis->iLan = (int32_t)Data;
490 Log(("%s: iLan=%d Parm[1]=%ld\n", pThis->szName, pThis->iLan, Parm[1]));
491
492 /*
493 * Connect it requested.
494 */
495 if (iConnectTo != -1)
496 {
497 if (iConnectTo == pThis->iLan)
498 return PDMDrvHlpVMSetError(pDrvIns, VERR_INVALID_PARAMETER, RT_SRC_POS,
499 N_("Cannot connect to ourself (%d)"), iConnectTo);
500
501 Parm[0] = Parm[1] = ~0UL; /* mysterious output */
502 cbParm = sizeof(Parm);
503 Data = iConnectTo;
504 cbData = sizeof(Data);
505 int orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_CONNECT_NIC,
506 &Parm, cbParm, &cbParm,
507 &Data, cbData, &cbData);
508 if (orc)
509 rc = RTErrConvertFromOS2(orc);
510 else if (Parm[0])
511 rc = VERR_GENERAL_FAILURE;
512 if (RT_FAILURE(rc))
513 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
514 N_("Failed to connect %d to %d! orc=%d Parm={%ld,%ld}"),
515 pThis->iLan, iConnectTo, orc, Parm[0], Parm[1]);
516 Log(("%s: Connected to %d\n", pThis->szName, iConnectTo));
517 pThis->iConnectedTo = iConnectTo;
518 }
519
520 /*
521 * Log the config.
522 */
523 Parm[0] = Parm[1] = ~0UL; /* mysterious output */
524 RTMAC Mac;
525 cbParm = sizeof(Parm);
526 cbData = sizeof(Mac);
527 orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_READ_MAC_ADDRESS,
528 &Parm[0], cbParm, &cbParm,
529 &Mac, cbData, &cbData);
530 if ( !orc
531 && !Parm[0]
532 /*&& !Parm[1]?*/)
533 LogRel(("%s: iLan=%d iConnectedTo=%d Mac=%02x:%02x:%02x:%02x:%02x:%02x\n",
534 pThis->szName, pThis->iLan, pThis->iConnectedTo,
535 Mac.au8[0], Mac.au8[1], Mac.au8[2], Mac.au8[3], Mac.au8[4], Mac.au8[5]));
536 else
537 LogRel(("%s: iLan=%d iConnectedTo Mac=failed - orc=%d Parm={%ld,%ld}\n",
538 pThis->szName, pThis->iLan, pThis->iConnectedTo, Parm[0], Parm[1]));
539
540 rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pThread, pThis, drvTAPOs2ReceiveThread, drvTAPOs2WakeupReceiveThread,
541 0, RTTHREADTYPE_IO, pThis->szName);
542 AssertRCReturn(rc, rc);
543
544#ifdef VBOX_WITH_STATISTICS
545 /*
546 * Statistics.
547 */
548 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktSent, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of sent packets.", "/Drivers/TAP%d/Packets/Sent", pDrvIns->iInstance);
549 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktSentBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Number of sent bytes.", "/Drivers/TAP%d/Bytes/Sent", pDrvIns->iInstance);
550 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktRecv, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of received packets.", "/Drivers/TAP%d/Packets/Received", pDrvIns->iInstance);
551 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktRecvBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Number of received bytes.", "/Drivers/TAP%d/Bytes/Received", pDrvIns->iInstance);
552 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatTransmit, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling packet transmit runs.", "/Drivers/TAP%d/Transmit", pDrvIns->iInstance);
553 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatReceive, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling packet receive runs.", "/Drivers/TAP%d/Receive", pDrvIns->iInstance);
554#endif /* VBOX_WITH_STATISTICS */
555
556 return rc;
557}
558
559
560/**
561 * TAP network transport driver registration record.
562 */
563const PDMDRVREG g_DrvHostInterface =
564{
565 /* u32Version */
566 PDM_DRVREG_VERSION,
567 /* szDriverName */
568 "HostInterface",
569 /* pszDescription */
570 "TAP Network Transport Driver",
571 /* fFlags */
572 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
573 /* fClass. */
574 PDM_DRVREG_CLASS_NETWORK,
575 /* cMaxInstances */
576 ~0,
577 /* cbInstance */
578 sizeof(DRVTAPOS2),
579 /* pfnConstruct */
580 drvTAPOs2Construct,
581 /* pfnDestruct */
582 drvTAPOs2Destruct,
583 /* pfnIOCtl */
584 NULL,
585 /* pfnPowerOn */
586 NULL,
587 /* pfnReset */
588 NULL,
589 /* pfnSuspend */
590 NULL,
591 /* pfnResume */
592 NULL,
593 /* pfnDetach */
594 NULL,
595 /* pfnPowerOff */
596 NULL
597};
598
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