Changeset 4642 in vbox for trunk/src/VBox/Devices/Network
- Timestamp:
- Sep 10, 2007 1:38:09 AM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DrvTAPOs2.cpp
r4372 r4642 32 32 #include "Builtins.h" 33 33 34 #define INCL_BASE 35 #include <os2.h> 36 #include "DrvTAPOs2.h" 37 34 38 35 39 … … 50 54 PPDMDRVINS pDrvIns; 51 55 /** TAP device file handle. */ 52 RTFILE FileDevice; 56 RTFILE hDevice; 57 /** Out LAN number. */ 58 int32_t iLan; 59 /** The LAN number we're connected to. -1 if not connected. */ 60 int32_t iConnectedTo; 53 61 /** Receiver thread. */ 54 62 PPDMTHREAD pThread; 55 /** We are waiting for more receive buffers. */56 uint32_t volatile fOutOfSpace;57 63 /** Event semaphore for blocking on receive. */ 58 64 RTSEMEVENT EventOutOfSpace; 65 /** We are checking or waiting for more receive buffers. */ 66 bool volatile fMaybeOutOfSpace; 67 /** Set if the link is down. 68 * When the link is down all incoming packets will be dropped. */ 69 bool volatile fLinkDown; 70 /** The log and thread name. */ 71 char szName[16]; 72 /** The \DEV\TAP$ device name. */ 73 char szDevice[32]; 59 74 60 75 #ifdef VBOX_WITH_STATISTICS … … 98 113 static DECLCALLBACK(int) drvTAPOs2Send(PPDMINETWORKCONNECTOR pInterface, const void *pvBuf, size_t cb) 99 114 { 100 PDRVTAPOS2 p Data= PDMINETWORKCONNECTOR_2_DRVTAPOS2(pInterface);101 STAM_COUNTER_INC(&p Data->StatPktSent);102 STAM_COUNTER_ADD(&p Data->StatPktSentBytes, cb);103 STAM_PROFILE_START(&p Data->StatTransmit, a);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); 104 119 105 120 #ifdef LOG_ENABLED 106 121 uint64_t u64Now = RTTimeProgramNanoTS(); 107 LogFlow((" drvTAPOs2Send: %-4d bytes at %llu ns deltas: r=%llu t=%llu\n",108 cb, u64Now, u64Now - p Data->u64LastReceiveTS, u64Now - pData->u64LastTransferTS));109 p Data->u64LastTransferTS = u64Now;122 LogFlow(("%s: Send: %-4d bytes at %RU64 ns deltas: recv=%RU64 xmit=%RU64\n", pThis->szName, 123 cb, u64Now, u64Now - pThis->u64LastReceiveTS, u64Now - pThis->u64LastTransferTS)); 124 pThis->u64LastTransferTS = u64Now; 110 125 #endif 111 Log2((" drvTAPOs2Send: pvBuf=%p cb=%#x\n"126 Log2(("%s Send: pvBuf=%p cb=%#zx\n" 112 127 "%.*Vhxd\n", 113 p vBuf, cb, cb, pvBuf));114 115 ULONG UnusedParms[10] = { 0,0,0,0, 0,0,0,0, 0,0 };116 ULONG cbParm s = sizeof(UnusedParms);128 pThis->szName, pvBuf, cb, cb, pvBuf)); 129 130 ULONG Parm[2] = { ~0UL, ~0UL }; /* mysterious output */ 131 ULONG cbParm = sizeof(Parm); 117 132 ULONG cbData = cb; 118 int rc = DosDevIOCtl(pData->FileDevice, PROT_CATEGORY, TAP_WRITE_PACKET, 119 &UnusedParms[0], cbParms, &cbParms, 120 pvBuf, cbData, &cbData); 121 if (rc) 122 rc = RTErrConvertFromOS2(rc); 123 124 STAM_PROFILE_STOP(&pData->StatTransmit, a); 133 int rc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_WRITE_PACKET, 134 &Parm[0], cbParm, &cbParm, 135 (void *)pvBuf, cbData, &cbData); 136 if (RT_UNLIKELY(rc || Parm[0])) 137 { 138 static unsigned cComplaints = 0; 139 if (cComplaints++ < 256) 140 LogRel(("%s: send failed. rc=%d Parm={%ld,%ld} cb=%d\n", 141 pThis->szName, rc, Parm[0], Parm[1], cb)); 142 if (rc) 143 rc = RTErrConvertFromOS2(rc); 144 else 145 rc = VERR_IO_GEN_FAILURE; 146 } 147 Log3(("%s: Send completed %d ns\n", pThis->szName, RTTimeProgramNanoTS() - pThis->u64LastTransferTS)); 148 149 STAM_PROFILE_STOP(&pThis->StatTransmit, a); 125 150 AssertRC(rc); 126 151 return rc; … … 140 165 static DECLCALLBACK(void) drvTAPOs2SetPromiscuousMode(PPDMINETWORKCONNECTOR pInterface, bool fPromiscuous) 141 166 { 142 LogFlow(("drvTAPOs2SetPromiscuousMode: fPromiscuous=%d\n", fPromiscuous)); 143 /* nothing to do */ 167 PDRVTAPOS2 pThis = PDMINETWORKCONNECTOR_2_DRVTAPOS2(pInterface); 168 LogFlow(("%s: SetPromiscuousMode: fPromiscuous=%d\n", pThis->szName, fPromiscuous)); 169 NOREF(pThis); 170 /** @todo is it always in promiscuous mode? */ 144 171 } 145 172 … … 154 181 static DECLCALLBACK(void) drvTAPOs2NotifyLinkChanged(PPDMINETWORKCONNECTOR pInterface, PDMNETWORKLINKSTATE enmLinkState) 155 182 { 156 LogFlow(("drvNATNotifyLinkChanged: enmLinkState=%d\n", enmLinkState)); 157 /** @todo take action on link down and up. Stop the polling and such like. */ 183 PDRVTAPOS2 pThis = PDMINETWORKCONNECTOR_2_DRVTAPOS2(pInterface); 184 bool fLinkDown; 185 switch (enmLinkState) 186 { 187 case PDMNETWORKLINKSTATE_DOWN: 188 case PDMNETWORKLINKSTATE_DOWN_RESUME: 189 fLinkDown = true; 190 break; 191 default: 192 AssertMsgFailed(("enmLinkState=%d\n", enmLinkState)); 193 case PDMNETWORKLINKSTATE_UP: 194 fLinkDown = false; 195 break; 196 } 197 LogFlow(("%s: NotifyLinkChanged: enmLinkState=%d %d->%d\n", pThis->szName, pThis->fLinkDown, fLinkDown)); 198 ASMAtomicXchgBool(&pThis->fLinkDown, fLinkDown); 158 199 } 159 200 … … 169 210 static DECLCALLBACK(void) drvTAPOs2NotifyCanReceive(PPDMINETWORKCONNECTOR pInterface) 170 211 { 171 PDRVTAPOS2 pData = PDMINETWORKCONNECTOR_2_DRVTAPOS2(pInterface); 172 173 LogFlow(("drvTAPOs2NotifyCanReceive:\n")); 174 /* ensure we wake up only once */ 175 if (ASMAtomicXchgU32(&pData->fOutOfSpace, false)) 176 RTSemEventSignal(pData->EventOutOfSpace); 177 } 178 179 180 /** 181 * Asynchronous I/O thread for handling receive. 182 * 183 * @returns VINF_SUCCESS (ignored). 184 * @param pDrvIns The driver instance. 185 * @param pThread The PDM thread structure. 186 */ 187 static DECLCALLBACK(int) drvTAPOs2AsyncIoThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread) 188 { 189 PDRVTAPOS2 pData = PDMINS2DATA(pDrvIns, PDRVTAPOS2); 190 LogFlow(("drvTAPOs2AsyncIoThread: pData=%p\n", pData)); 191 Assert(pThread->enmState == PDMTHREADSTATE_INITIALIZING); 192 193 194 /* 195 * Outer loop. 196 */ 197 for (;;) 212 PDRVTAPOS2 pThis = PDMINETWORKCONNECTOR_2_DRVTAPOS2(pInterface); 213 214 /* don't waste time signalling the semaphore unnecessary */ 215 if (!pThis->fMaybeOutOfSpace) 216 LogFlow(("%s: NotifyCanReceive: fMaybeOutOfSpace=false\n", pThis->szName)); 217 else 218 { 219 LogFlow(("%s: NotifyCanReceive: fMaybeOutOfSpace=true\n", pThis->szName)); 220 RTSemEventSignal(pThis->EventOutOfSpace); 221 } 222 } 223 224 225 /** 226 * Receiver thread. 227 * 228 * @returns VBox status code. Returning failure will naturally terminate the thread. 229 * @param pDrvIns The pcnet device instance. 230 * @param pThread The thread. 231 */ 232 static DECLCALLBACK(int) drvTAPOs2ReceiveThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread) 233 { 234 PDRVTAPOS2 pThis = PDMINS2DATA(pDrvIns, PDRVTAPOS2); 235 236 /* 237 * No initialization work to do, just return immediately. 238 */ 239 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING) 240 return VINF_SUCCESS; 241 Assert(pThread->enmState == PDMTHREADSTATE_RESUMING); 242 243 /* 244 * Loop while the thread is running, quit immediately when 245 * we're supposed to suspend or terminate. 246 */ 247 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 198 248 { 199 249 /* 200 * 250 * Read a frame, this will block for a while if nothing to read. 201 251 */ 202 PDMR3ThreadSuspend(pThread); 203 if (pThread->enmState != PDMTHREADSTATE_RESUMING) 252 char abBuf[4096]; 253 ULONG Parm[2] = { ~0UL, ~0UL }; /* mysterious output */ 254 ULONG cbParm = sizeof(Parm); /* this one is actually ignored... */ 255 ULONG cbBuf = sizeof(abBuf); 256 257 int rc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_READ_PACKET, 258 &Parm[0], cbParm, &cbParm, 259 &abBuf[0], cbBuf, &cbBuf); 260 if (pThread->enmState != PDMTHREADSTATE_RUNNING) 204 261 break; 205 206 { 207 } 208 } 209 210 211 212 213 STAM_PROFILE_ADV_START(&pData->StatReceive, a); 214 215 /* 216 * Polling loop. 217 */ 218 for (;;) 219 { 220 /* 221 * Read/wait the frame. 222 */ 223 char achBuf[4096]; 224 ULONG cbParm = ; 225 ULONG cbRead = 0; 226 int LanNumber; 227 228 int rc = DosDevIOCtl(pData->FileDevice, PROT_CATEGORY, TAP_CANCEL_READ, 229 &UnusedParms[0], cbParm, &cbParm, 230 &achBuf[0], cbRead, &cbRead); 231 if (rc == NO_ERROR) 262 const size_t cbRead = Parm[1]; 263 if ( !rc 264 && !Parm[0] 265 && cbRead > 0 /* cbRead */) 232 266 { 233 267 AssertMsg(cbRead <= 1536, ("cbRead=%d\n", cbRead)); 234 268 235 269 /* 236 * Wait for the device to have spacefor this frame.270 * Wait for the device to have room for this frame. 237 271 */ 238 size_t cbMax = pData->pPort->pfnCanReceive(pData->pPort); 272 ASMAtomicXchgBool(&pThis->fMaybeOutOfSpace, true); 273 size_t cbMax = pThis->pPort->pfnCanReceive(pThis->pPort); 239 274 if (cbMax < cbRead) 240 275 { 241 /** @todo receive overflow handling needs serious improving! */ 242 STAM_PROFILE_ADV_STOP(&pData->StatReceive, a); 243 STAM_PROFILE_START(&pData->StatRecvOverflows, b); 276 STAM_PROFILE_ADV_STOP(&pThis->StatReceive, a); 277 STAM_PROFILE_START(&pThis->StatRecvOverflows, b); 244 278 while ( cbMax < cbRead 245 && p Data->enmState != ASYNCSTATE_TERMINATE)279 && pThread->enmState == PDMTHREADSTATE_RUNNING) 246 280 { 247 LogFlow(("drvTAPOs2AsyncIoThread: cbMax=%d cbRead=%d waiting...\n", cbMax, cbRead)); 248 #if 1 249 /* We get signalled by the network driver. 50ms is just for sanity */ 250 ASMAtomicXchgU32(&pData->fOutOfSpace, true); 251 RTSemEventWait(pData->EventOutOfSpace, 50); 252 #else 253 RTThreadSleep(1); 254 #endif 255 cbMax = pData->pPort->pfnCanReceive(pData->pPort); 281 LogFlow(("%s: ReceiveThread: cbMax=%d cbRead=%d waiting...\n", pThis->szName, cbMax, cbRead)); 282 RTSemEventWait(pThis->EventOutOfSpace, 50); 283 cbMax = pThis->pPort->pfnCanReceive(pThis->pPort); 256 284 } 257 ASMAtomicXchgU32(&pData->fOutOfSpace, false); 258 STAM_PROFILE_STOP(&pData->StatRecvOverflows, b); 259 STAM_PROFILE_ADV_START(&pData->StatReceive, a); 260 if (pData->enmState == ASYNCSTATE_TERMINATE) 261 break; 285 STAM_PROFILE_STOP(&pThis->StatRecvOverflows, b); 286 STAM_PROFILE_ADV_START(&pThis->StatReceive, a); 262 287 } 288 ASMAtomicXchgBool(&pThis->fMaybeOutOfSpace, false); 289 if (pThread->enmState != PDMTHREADSTATE_RUNNING) 290 break; /* just drop it, no big deal. */ 263 291 264 292 /* … … 267 295 #ifdef LOG_ENABLED 268 296 uint64_t u64Now = RTTimeProgramNanoTS(); 269 LogFlow((" drvTAPOs2AsyncIoThread: %-4d bytes at %llu ns deltas: r=%llu t=%llu\n",270 cbRead, u64Now, u64Now - p Data->u64LastReceiveTS, u64Now - pData->u64LastTransferTS));271 p Data->u64LastReceiveTS = u64Now;297 LogFlow(("%s: ReceiveThread: %-4d bytes at %RU64 ns deltas: recv=%RU64 xmit=%RU64\n", pThis->szName, 298 cbRead, u64Now, u64Now - pThis->u64LastReceiveTS, u64Now - pThis->u64LastTransferTS)); 299 pThis->u64LastReceiveTS = u64Now; 272 300 #endif 273 Log2((" drvTAPOs2AsyncIoThread: cbRead=%#x\n"301 Log2(("%s: ReceiveThread: cbRead=%#x\n" 274 302 "%.*Vhxd\n", 275 cbRead, cbRead, achBuf));276 STAM_COUNTER_INC(&p Data->StatPktRecv);277 STAM_COUNTER_ADD(&p Data->StatPktRecvBytes, cbRead);278 rc = p Data->pPort->pfnReceive(pData->pPort, achBuf, cbRead);303 pThis->szName, cbRead, cbRead, abBuf)); 304 STAM_COUNTER_INC(&pThis->StatPktRecv); 305 STAM_COUNTER_ADD(&pThis->StatPktRecvBytes, cbRead); 306 rc = pThis->pPort->pfnReceive(pThis->pPort, abBuf, cbRead); 279 307 AssertRC(rc); 280 308 } 281 else 309 /* we'll be returning ~1 per second with no data; rc=0 Parm[0] = 1, Parm[1] = 0. */ 310 else if (rc) 282 311 { 283 LogFlow(("drvTAPOs2AsyncIoThread: DoDevIOCtl -> %Vrc\n", rc)); 312 LogFlow(("%s: ReceiveThread: DoDevIOCtl -> %s Parm={%ld, %ld}\n", 313 pThis->szName, rc, Parm[0], Parm[1])); 314 rc = RTErrConvertFromOS2(rc); 284 315 if (rc == VERR_INVALID_HANDLE) 285 break;316 return rc; 286 317 RTThreadYield(); 287 318 } 288 319 } 289 320 290 LogFlow(("drvTAPOs2AsyncIoThread: returns %Vrc\n", VINF_SUCCESS)); 291 STAM_PROFILE_ADV_STOP(&pData->StatReceive, a); 321 /* The thread is being suspended or terminated. */ 322 return VINF_SUCCESS; 323 } 324 325 326 /** 327 * Unblock the send thread so it can respond to a state change. 328 * 329 * @returns VBox status code. 330 * @param pDrvIns The pcnet device instance. 331 * @param pThread The send thread. 332 */ 333 static DECLCALLBACK(int) drvTAPOs2WakeupReceiveThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread) 334 { 335 PDRVTAPOS2 pThis = PDMINS2DATA(pDrvIns, PDRVTAPOS2); 336 LogFlow(("%s: WakeupReceiveThread\n", pThis->szName)); 337 338 /* cancel any pending reads */ 339 ULONG Parm[2] = { ~0UL, ~0UL }; /* mysterious output */ 340 ULONG cbParm = sizeof(Parm); 341 ULONG Data = pThis->iLan; /* right? */ 342 ULONG cbData = sizeof(Data); 343 int orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_CANCEL_READ, 344 &Parm[0], cbParm, &cbParm, 345 &Data, cbData, &cbData); 346 AssertMsg(orc == 0, ("%d\n", orc)); NOREF(orc); 347 348 /* wake it up if it's waiting for receive buffers. */ 349 if (pThis->fMaybeOutOfSpace) 350 RTSemEventSignal(pThis->EventOutOfSpace); 351 292 352 return VINF_SUCCESS; 293 353 } … … 306 366 { 307 367 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface); 308 PDRVTAPOS2 p Data= PDMINS2DATA(pDrvIns, PDRVTAPOS2);368 PDRVTAPOS2 pThis = PDMINS2DATA(pDrvIns, PDRVTAPOS2); 309 369 switch (enmInterface) 310 370 { … … 312 372 return &pDrvIns->IBase; 313 373 case PDMINTERFACE_NETWORK_CONNECTOR: 314 return &p Data->INetworkConnector;374 return &pThis->INetworkConnector; 315 375 default: 316 376 return NULL; … … 329 389 static DECLCALLBACK(void) drvTAPOs2Destruct(PPDMDRVINS pDrvIns) 330 390 { 331 LogFlow(("drvTAPOs2Destruct\n")); 332 PDRVTAPOS2 pData = PDMINS2DATA(pDrvIns, PDRVTAPOS2); 333 334 /* 335 * Destroy the event semaphore. 336 */ 337 if (pData->EventOutOfSpace != NIL_RTSEMEVENTMULTI) 338 { 339 rc = RTSemEventDestroy(pData->EventOutOfSpace); 391 PDRVTAPOS2 pThis = PDMINS2DATA(pDrvIns, PDRVTAPOS2); 392 LogFlow(("%s: Destruct\n", pThis->szName)); 393 394 /* PDM will destroy the thread for us, it's suspended right now. */ 395 396 /* 397 * Destroy the out-of-space event semaphore. 398 */ 399 if (pThis->EventOutOfSpace != NIL_RTSEMEVENTMULTI) 400 { 401 int rc = RTSemEventDestroy(pThis->EventOutOfSpace); 340 402 AssertRC(rc); 341 pData->EventOutOfSpace = NIL_RTSEMEVENTMULTI; 403 pThis->EventOutOfSpace = NIL_RTSEMEVENTMULTI; 404 } 405 406 /* 407 * Disconnect from the lan if we made a connection and close it. 408 */ 409 if (pThis->iConnectedTo != -1) 410 { 411 ULONG Parm[2] = { ~0UL, ~0UL }; /* mysterious output */ 412 ULONG cbParm = sizeof(Parm); 413 ULONG Data = pThis->iConnectedTo; 414 ULONG cbData = sizeof(Data); 415 int orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_DISCONNECT_NIC, 416 &Parm, cbParm, &cbParm, 417 &Data, cbData, &cbData); 418 if ( orc 419 || Parm[0]) 420 LogRel(("%s: Failed to disconnect %d from %d! orc=%d Parm={%ld,%ld}\n", 421 pThis->szName, pThis->iLan, pThis->iConnectedTo, orc, Parm[0], Parm[1])); 422 pThis->iConnectedTo = -1; 423 } 424 425 if (pThis->hDevice != NIL_RTFILE) 426 { 427 int rc = RTFileClose(pThis->hDevice); 428 AssertRC(rc); 429 pThis->hDevice = NIL_RTFILE; 342 430 } 343 431 } … … 356 444 static DECLCALLBACK(int) drvTAPOs2Construct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle) 357 445 { 358 PDRVTAPOS2 p Data= PDMINS2DATA(pDrvIns, PDRVTAPOS2);446 PDRVTAPOS2 pThis = PDMINS2DATA(pDrvIns, PDRVTAPOS2); 359 447 360 448 /* 361 449 * Init the static parts. 362 450 */ 363 pData->pDrvIns = pDrvIns; 364 pData->FileDevice = NIL_RTFILE; 365 pData->Thread = NIL_RTTHREAD; 366 pData->enmState = ASYNCSTATE_RUNNING; 451 pThis->pDrvIns = pDrvIns; 452 pThis->hDevice = NIL_RTFILE; 453 pThis->iLan = -1; 454 pThis->iConnectedTo = -1; 455 pThis->pThread = NULL; 456 RTStrPrintf(pThis->szName, sizeof(pThis->szName), "TAP%d", pDrvIns->iInstance); 367 457 /* IBase */ 368 458 pDrvIns->IBase.pfnQueryInterface = drvTAPOs2QueryInterface; 369 459 /* INetwork */ 370 p Data->INetworkConnector.pfnSend = drvTAPOs2Send;371 p Data->INetworkConnector.pfnSetPromiscuousMode = drvTAPOs2SetPromiscuousMode;372 p Data->INetworkConnector.pfnNotifyLinkChanged = drvTAPOs2NotifyLinkChanged;373 p Data->INetworkConnector.pfnNotifyCanReceive = drvTAPOs2NotifyCanReceive;460 pThis->INetworkConnector.pfnSend = drvTAPOs2Send; 461 pThis->INetworkConnector.pfnSetPromiscuousMode = drvTAPOs2SetPromiscuousMode; 462 pThis->INetworkConnector.pfnNotifyLinkChanged = drvTAPOs2NotifyLinkChanged; 463 pThis->INetworkConnector.pfnNotifyCanReceive = drvTAPOs2NotifyCanReceive; 374 464 375 465 /* 376 466 * Validate the config. 377 467 */ 378 if (!CFGMR3AreValuesValid(pCfgHandle, "Device\0 InitProg\0TermProg\0FileHandle\0"))468 if (!CFGMR3AreValuesValid(pCfgHandle, "Device\0LanNumber\0ConnectTo\0")) 379 469 return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES, ""); 380 470 … … 390 480 * Query the network port interface. 391 481 */ 392 p Data->pPort = (PPDMINETWORKPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_NETWORK_PORT);393 if (!p Data->pPort)482 pThis->pPort = (PPDMINETWORKPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_NETWORK_PORT); 483 if (!pThis->pPort) 394 484 return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE, 395 485 N_("Configuration error: The above device/driver didn't export the network port interface!")); … … 398 488 * Read the configuration. 399 489 */ 400 int32_t iFile; 401 rc = CFGMR3QueryS32(pCfgHandle, "FileHandle", &iFile); 490 rc = CFGMR3QueryString(pCfgHandle, "Device", &pThis->szDevice[0], sizeof(pThis->szDevice)); 491 if (rc == VERR_CFGM_VALUE_NOT_FOUND) 492 strcpy(pThis->szDevice, "\\DEV\\TAP$"); 493 else if (VBOX_FAILURE(rc)) 494 return PDMDRV_SET_ERROR(pDrvIns, rc, 495 N_("Configuration error: Query for \"Device\" failed!")); 496 497 int32_t iConnectTo; 498 rc = CFGMR3QueryS32(pCfgHandle, "ConnectTo", &iConnectTo); 499 if (rc == VERR_CFGM_VALUE_NOT_FOUND) 500 iConnectTo = -1; 501 else if (VBOX_FAILURE(rc)) 502 return PDMDRV_SET_ERROR(pDrvIns, rc, 503 N_("Configuration error: Query for \"ConnectTo\" failed!")); 504 505 /* 506 * Open the device. 507 * Keep in mind that the destructor is always called! 508 */ 509 rc = RTFileOpen(&pThis->hDevice, pThis->szDevice, RTFILE_O_DENY_NONE | RTFILE_O_READ); 402 510 if (VBOX_FAILURE(rc)) 403 return PDMDRV_SET_ERROR(pDrvIns, rc, 404 N_("Configuration error: Query for \"FileHandle\" 32-bit signed integer failed!")); 405 pData->FileDevice = (RTFILE)iFile; 406 if (!RTFileIsValid(pData->FileDevice)) 407 return PDMDrvHlpVMSetError(pDrvIns, VERR_INVALID_HANDLE, RT_SRC_POS, 408 N_("The TAP file handle %RTfile is not valid!"), pData->FileDevice); 409 410 /* 411 * Make sure the descriptor is non-blocking and valid. 412 * 413 * We should actually query if it's a TAP device, but I haven't 414 * found any way to do that. 415 */ 416 if (fcntl(pData->FileDevice, F_SETFL, O_NONBLOCK) == -1) 417 return PDMDrvHlpVMSetError(pDrvIns, VERR_HOSTIF_IOCTL, RT_SRC_POS, 418 N_("Configuration error: Failed to configure /dev/net/tun. errno=%d"), errno); 419 Log(("drvTAPOs2Contruct: %d (from fd)\n", pData->FileDevice)); 420 rc = VINF_SUCCESS; 511 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, 512 N_("Failed to open tap device '%s'!"), pThis->szDevice); 513 514 ULONG Parm[2] = { ~0UL, ~0UL }; /* mysterious output */ 515 ULONG cbParm = sizeof(Parm); 516 ULONG Data = ~0UL; 517 ULONG cbData = sizeof(Data); 518 int orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_GET_LAN_NUMBER, 519 &Parm, cbParm, &cbParm, 520 &Data, cbData, &cbData); 521 if (orc) 522 rc = RTErrConvertFromOS2(orc); 523 else if (Parm[0]) 524 rc = VERR_GENERAL_FAILURE; 525 if (VBOX_FAILURE(rc)) 526 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, 527 N_("Failed to query LanNumber! orc=%d Parm={%ld,%ld}\n"), 528 orc, Parm[0], Parm[1]); 529 pThis->iLan = (int32_t)Data; 530 Log(("%s: iLan=%d Parm[1]=%ld\n", pThis->szName, pThis->iLan, Parm[1])); 531 532 /* 533 * Connect it requested. 534 */ 535 if (iConnectTo != -1) 536 { 537 if (iConnectTo == pThis->iLan) 538 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, 539 N_("Cannot connect to ourself (%d)"), iConnectTo); 540 541 Parm[0] = Parm[1] = ~0UL; /* mysterious output */ 542 cbParm = sizeof(Parm); 543 Data = iConnectTo; 544 cbData = sizeof(Data); 545 int orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_CONNECT_NIC, 546 &Parm, cbParm, &cbParm, 547 &Data, cbData, &cbData); 548 if (orc) 549 rc = RTErrConvertFromOS2(orc); 550 else if (Parm[0]) 551 rc = VERR_GENERAL_FAILURE; 552 if (VBOX_FAILURE(rc)) 553 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, 554 N_("Failed to connect %d to %d! orc=%d Parm={%ld,%ld}\n"), 555 pThis->iLan, iConnectTo, orc, Parm[0], Parm[1]); 556 Log(("%s: Connected to %d\n", pThis->szName, iConnectTo)); 557 pThis->iConnectedTo = iConnectTo; 558 } 559 560 /* 561 * Log the config. 562 */ 563 Parm[0] = Parm[1] = ~0UL; /* mysterious output */ 564 PDMMAC Mac; 565 cbParm = sizeof(Parm); 566 cbData = sizeof(Mac); 567 orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_READ_MAC_ADDRESS, 568 &Parm[0], cbParm, &cbParm, 569 &Mac, cbData, &cbData); 570 if ( !orc 571 && !Parm[0] 572 /*&& !Parm[1]?*/) 573 LogRel(("%s: iLan=%d iConnectedTo=%d Mac=%02x:%02x:%02x:%02x:%02x:%02x\n", 574 pThis->szName, pThis->iLan, pThis->iConnectedTo, 575 Mac.au8[0], Mac.au8[1], Mac.au8[2], Mac.au8[3], Mac.au8[4], Mac.au8[5])); 576 else 577 LogRel(("%s: iLan=%d iConnectedTo Mac=failed - orc=%d Parm={%ld,%ld}\n", 578 pThis->szName, pThis->iLan, pThis->iConnectedTo, Parm[0], Parm[1])); 421 579 422 580 /* 423 581 * Create the out-of-space semaphore and the async receiver thread. 424 582 */ 425 rc = RTSemEventCreate(&p Data->EventOutOfSpace);583 rc = RTSemEventCreate(&pThis->EventOutOfSpace); 426 584 AssertRCReturn(rc, rc); 427 585 428 rc = PDMDrvHlp ThreadCreate(pDrvIns, &pData->pThread, pData, drvTAPOs2AsyncIoThread, drvTAPOs2WakeupThread,429 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "TAP");586 rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pThread, pThis, drvTAPOs2ReceiveThread, drvTAPOs2WakeupReceiveThread, 587 0, RTTHREADTYPE_IO, pThis->szName); 430 588 AssertRCReturn(rc, rc); 431 589 … … 434 592 * Statistics. 435 593 */ 436 PDMDrvHlpSTAMRegisterF(pDrvIns, &p Data->StatPktSent, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of sent packets.", "/Drivers/TAP%d/Packets/Sent", pDrvIns->iInstance);437 PDMDrvHlpSTAMRegisterF(pDrvIns, &p Data->StatPktSentBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Number of sent bytes.", "/Drivers/TAP%d/Bytes/Sent", pDrvIns->iInstance);438 PDMDrvHlpSTAMRegisterF(pDrvIns, &p Data->StatPktRecv, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of received packets.", "/Drivers/TAP%d/Packets/Received", pDrvIns->iInstance);439 PDMDrvHlpSTAMRegisterF(pDrvIns, &p Data->StatPktRecvBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Number of received bytes.", "/Drivers/TAP%d/Bytes/Received", pDrvIns->iInstance);440 PDMDrvHlpSTAMRegisterF(pDrvIns, &p Data->StatTransmit, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling packet transmit runs.", "/Drivers/TAP%d/Transmit", pDrvIns->iInstance);441 PDMDrvHlpSTAMRegisterF(pDrvIns, &p Data->StatReceive, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling packet receive runs.", "/Drivers/TAP%d/Receive", pDrvIns->iInstance);442 PDMDrvHlpSTAMRegisterF(pDrvIns, &p Data->StatRecvOverflows, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, "Profiling packet receive overflows.", "/Drivers/TAP%d/RecvOverflows", pDrvIns->iInstance);594 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktSent, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of sent packets.", "/Drivers/TAP%d/Packets/Sent", pDrvIns->iInstance); 595 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktSentBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Number of sent bytes.", "/Drivers/TAP%d/Bytes/Sent", pDrvIns->iInstance); 596 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktRecv, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of received packets.", "/Drivers/TAP%d/Packets/Received", pDrvIns->iInstance); 597 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktRecvBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Number of received bytes.", "/Drivers/TAP%d/Bytes/Received", pDrvIns->iInstance); 598 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatTransmit, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling packet transmit runs.", "/Drivers/TAP%d/Transmit", pDrvIns->iInstance); 599 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatReceive, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling packet receive runs.", "/Drivers/TAP%d/Receive", pDrvIns->iInstance); 600 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatRecvOverflows, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, "Profiling packet receive overflows.", "/Drivers/TAP%d/RecvOverflows", pDrvIns->iInstance); 443 601 #endif /* VBOX_WITH_STATISTICS */ 444 602 … … 485 643 NULL 486 644 }; 645
Note:
See TracChangeset
for help on using the changeset viewer.