Changeset 28623 in vbox for trunk/src/VBox/Devices/Network/testcase
- Timestamp:
- Apr 23, 2010 12:34:14 AM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 60472
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/testcase/tstIntNetR0.cpp
r28314 r28623 41 41 #include <VBox/sup.h> 42 42 #include <VBox/err.h> 43 #include <iprt/asm.h> 44 #include <iprt/getopt.h> 45 #include <iprt/initterm.h> 46 #include <iprt/mem.h> 47 #include <iprt/mp.h> 43 48 #include <iprt/stream.h> 44 #include <iprt/alloc.h>45 #include <iprt/initterm.h>46 49 #include <iprt/thread.h> 47 50 #include <iprt/time.h> 48 #include <iprt/asm.h> 49 #include <iprt/getopt.h> 51 #include <iprt/test.h> 50 52 51 53 … … 98 100 * Global Variables * 99 101 *******************************************************************************/ 100 /** The error count. */ 101 unsigned g_cErrors = 0; 102 102 /** The test handle.*/ 103 static RTTEST g_hTest = NIL_RTTEST; 104 /** The size (in bytes) of the large transfer tests. */ 105 static uint32_t g_cbTransfer = _1M * 384; 103 106 /** Fake session handle. */ 104 const PSUPDRVSESSION g_pSession = (PSUPDRVSESSION)0xdeadface; 105 106 /** Testframe 0 */ 107 struct TESTFRAME 108 { 109 uint16_t au16[7]; 110 } g_TestFrame0 = { { /* dst:*/ 0xffff, 0xffff, 0xffff, /*src:*/0x8086, 0, 0, 0x0800 } }, 111 g_TestFrame1 = { { /* dst:*/ 0, 0, 0, /*src:*/0x8086, 0, 1, 0x0800 } }; 107 const PSUPDRVSESSION g_pSession = (PSUPDRVSESSION)0xdeadface; 112 108 113 109 114 110 INTNETR3DECL(void *) SUPR0ObjRegister(PSUPDRVSESSION pSession, SUPDRVOBJTYPE enmType, PFNSUPDRVDESTRUCTOR pfnDestructor, void *pvUser1, void *pvUser2) 115 111 { 116 if (pSession != g_pSession) 117 { 118 RTPrintf("tstIntNetR0: Invalid session pointer %p, %s!\n", pSession, __FUNCTION__); 119 g_cErrors++; 120 return NULL; 121 } 122 POBJREF pRef = (POBJREF)RTMemAlloc(sizeof(OBJREF)); 112 RTTEST_CHECK_RET(g_hTest, pSession == g_pSession, NULL); 113 POBJREF pRef = (POBJREF)RTTestGuardedAllocTail(g_hTest, sizeof(OBJREF)); 123 114 if (!pRef) 124 115 return NULL; … … 132 123 INTNETR3DECL(int) SUPR0ObjAddRefEx(void *pvObj, PSUPDRVSESSION pSession, bool fNoBlocking) 133 124 { 134 if (pSession != g_pSession) 135 { 136 RTPrintf("tstIntNetR0: Invalid session pointer %p, %s!\n", pSession, __FUNCTION__); 137 g_cErrors++; 138 return VERR_INVALID_PARAMETER; 139 } 125 RTTEST_CHECK_RET(g_hTest, pSession == g_pSession, VERR_INVALID_PARAMETER); 140 126 POBJREF pRef = (POBJREF)pvObj; 141 127 ASMAtomicIncU32(&pRef->cRefs); … … 150 136 INTNETR3DECL(int) SUPR0ObjRelease(void *pvObj, PSUPDRVSESSION pSession) 151 137 { 152 if (pSession != g_pSession) 153 { 154 RTPrintf("tstIntNetR0: Invalid session pointer %p, %s!\n", pSession, __FUNCTION__); 155 g_cErrors++; 156 return VERR_INVALID_PARAMETER; 157 } 138 RTTEST_CHECK_RET(g_hTest, pSession == g_pSession, VERR_INVALID_PARAMETER); 158 139 POBJREF pRef = (POBJREF)pvObj; 159 140 if (!ASMAtomicDecU32(&pRef->cRefs)) 160 141 { 161 142 pRef->pfnDestructor(pRef, pRef->pvUser1, pRef->pvUser2); 162 RT MemFree(pRef);143 RTTestGuardedFree(g_hTest, pRef); 163 144 return VINF_OBJECT_DESTROYED; 164 145 } … … 168 149 INTNETR3DECL(int) SUPR0ObjVerifyAccess(void *pvObj, PSUPDRVSESSION pSession, const char *pszObjName) 169 150 { 170 if (pSession != g_pSession) 171 { 172 RTPrintf("tstIntNetR0: Invalid session pointer %p, %s!\n", pSession, __FUNCTION__); 173 g_cErrors++; 174 return VERR_INVALID_PARAMETER; 175 } 151 RTTEST_CHECK_RET(g_hTest, pSession == g_pSession, VERR_INVALID_PARAMETER); 176 152 return VINF_SUCCESS; 177 153 } … … 179 155 INTNETR3DECL(int) SUPR0MemAlloc(PSUPDRVSESSION pSession, uint32_t cb, PRTR0PTR ppvR0, PRTR3PTR ppvR3) 180 156 { 181 if (pSession != g_pSession) 182 { 183 RTPrintf("tstIntNetR0: Invalid session pointer %p, %s!\n", pSession, __FUNCTION__); 184 g_cErrors++; 185 return VERR_INVALID_PARAMETER; 186 } 187 void *pv = RTMemAlloc(cb); 157 RTTEST_CHECK_RET(g_hTest, pSession == g_pSession, VERR_INVALID_PARAMETER); 158 void *pv = RTTestGuardedAllocTail(g_hTest, cb); 188 159 if (!pv) 189 160 return VERR_NO_MEMORY; … … 196 167 INTNETR3DECL(int) SUPR0MemFree(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr) 197 168 { 198 if (pSession != g_pSession) 199 { 200 RTPrintf("tstIntNetR0: Invalid session pointer %p, %s!\n", pSession, __FUNCTION__); 201 g_cErrors++; 202 return VERR_INVALID_PARAMETER; 203 } 204 RTMemFree((void *)uPtr); 169 RTTEST_CHECK_RET(g_hTest, pSession == g_pSession, VERR_INVALID_PARAMETER); 170 RTTestGuardedFree(g_hTest, (void *)uPtr); 205 171 return VINF_SUCCESS; 206 172 } 207 173 174 /* Fake non-existing ring-0 APIs. */ 175 #define RTThreadIsInInterrupt(hThread) false 176 #define RTThreadPreemptIsEnabled(hThread) true 177 #define RTMpCpuId() 0 178 179 /* No CLI/POPF, please. */ 180 #define RTSpinlockAcquireNoInts RTSpinlockAcquire 181 #define RTSpinlockReleaseNoInts RTSpinlockRelease 208 182 209 183 … … 230 204 typedef struct MYARGS 231 205 { 232 PINTNET pIntNet;233 PINTNETBUF pBuf;234 INTNETIFHANDLE hIf;235 RTMAC Mac;236 uint64_t u64Start;237 uint64_t u64End;206 PINTNET pIntNet; 207 PINTNETBUF pBuf; 208 INTNETIFHANDLE hIf; 209 RTMAC Mac; 210 uint64_t u64Start; 211 uint64_t u64End; 238 212 } MYARGS, *PMYARGS; 239 213 240 214 241 #define TEST_TRANSFER_SIZE (_1M*384) 215 /** 216 * Frame header used when testing. 217 */ 218 #pragma pack(1) 219 typedef struct MYFRAMEHDR 220 { 221 RTMAC SrcMac; 222 RTMAC DstMac; 223 uint32_t iFrame; 224 uint32_t auEos[3]; 225 } MYFRAMEHDR; 226 #pragma pack() 242 227 243 228 /** … … 248 233 { 249 234 PMYARGS pArgs = (PMYARGS)pvArg; 250 251 /* 252 * Send 64 MB of data. 253 */ 254 uint8_t abBuf[4096] = {0}; 255 PRTMAC pMacSrc = (PRTMAC)&abBuf[0]; 256 PRTMAC pMacDst = pMacSrc + 1; 257 *pMacSrc = pArgs->Mac; 258 *pMacDst = pArgs->Mac; 259 pMacDst->au16[2] = pArgs->Mac.au16[2] ? 0 : 1; 260 unsigned *puFrame = (unsigned *)(pMacDst + 1); 261 unsigned iFrame = 0; 262 uint32_t cbSent = 0; 263 uint32_t cSend = 0; 235 int rc; 236 237 /* 238 * Send g_cbTransfer of data. 239 */ 240 uint8_t abBuf[4096] = {0}; 241 MYFRAMEHDR *pHdr = (MYFRAMEHDR *)&abBuf[0]; 242 uint32_t iFrame = 0; 243 uint32_t cbSent = 0; 244 uint32_t cSend = 0; 245 246 pHdr->SrcMac = pArgs->Mac; 247 pHdr->DstMac = pArgs->Mac; 248 pHdr->DstMac.au16[2] = (pArgs->Mac.au16[2] + 1) % 2; 249 264 250 pArgs->u64Start = RTTimeNanoTS(); 265 for (; cbSent < TEST_TRANSFER_SIZE; iFrame++)266 { 267 const unsigned cb = iFrame % 1519 + 12 + sizeof(unsigned);268 *puFrame = iFrame;251 for (; cbSent < g_cbTransfer; iFrame++) 252 { 253 const unsigned cb = iFrame % 1519 + sizeof(RTMAC) * 2 + sizeof(unsigned); 254 pHdr->iFrame = iFrame; 269 255 270 256 INTNETSG Sg; 271 257 INTNETSgInitTemp(&Sg, abBuf, cb); 272 int rc = intnetR0RingWriteFrame(&pArgs->pBuf->Send, &Sg, NULL);258 RTTEST_CHECK_RC_OK(g_hTest, rc = intnetR0RingWriteFrame(&pArgs->pBuf->Send, &Sg, NULL)); 273 259 if (RT_SUCCESS(rc)) 274 rc = INTNETR0IfSend(pArgs->pIntNet, pArgs->hIf, g_pSession); 275 if (RT_FAILURE(rc)) 276 { 277 g_cErrors++; 278 RTPrintf("tstIntNetR0: Failed sending %d bytes, rc=%Rrc (%d)\n", cb, rc, INTNETRingGetWritable(&pArgs->pBuf->Send)); 279 } 260 RTTEST_CHECK_RC_OK(g_hTest, rc = INTNETR0IfSend(pArgs->pIntNet, pArgs->hIf, g_pSession)); 280 261 cbSent += cb; 281 262 } … … 284 265 * Termination frames. 285 266 */ 286 p uFrame[0]= 0xffffdead;287 p uFrame[1] = 0xffffdead;288 p uFrame[2] = 0xffffdead;289 p uFrame[3] = 0xffffdead;267 pHdr->iFrame = 0xffffdead; 268 pHdr->auEos[0] = 0xffffdead; 269 pHdr->auEos[1] = 0xffffdead; 270 pHdr->auEos[2] = 0xffffdead; 290 271 for (unsigned c = 0; c < 20; c++) 291 272 { 292 int rc = tstIntNetSendBuf(pArgs->pIntNet, &pArgs->pBuf->Send, pArgs->hIf, g_pSession, 293 abBuf, sizeof(RTMAC) * 2 + sizeof(unsigned) * 4); 294 if (RT_FAILURE(rc)) 295 { 296 g_cErrors++; 297 RTPrintf("tstIntNetR0: send failed, rc=%Rrc\n", rc); 298 } 273 RTTEST_CHECK_RC_OK(g_hTest, rc = tstIntNetSendBuf(pArgs->pIntNet, &pArgs->pBuf->Send, pArgs->hIf, g_pSession, 274 abBuf, sizeof(RTMAC) * 2 + sizeof(unsigned) * 4)); 299 275 RTThreadSleep(1); 300 276 } 301 277 302 RTPrintf("tstIntNetR0: sender thread %.6Rhxs terminating.\n" 303 "tstIntNetR0: iFrame=%u cb=%'u\n", 304 &pArgs->Mac, iFrame, cbSent); 278 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, 279 "sender thread %.6Rhxs terminating.\n" 280 "iFrame=%u cb=%'u\n", 281 &pArgs->Mac, iFrame, cbSent); 305 282 return 0; 306 283 } … … 322 299 for (;;) 323 300 { 301 /* 302 * Read data. 303 */ 304 while (INTNETRingHasMoreToRead(&pArgs->pBuf->Recv)) 305 { 306 uint8_t abBuf[16384]; 307 MYFRAMEHDR *pHdr = (MYFRAMEHDR *)&abBuf[0]; 308 uint32_t cb = INTNETRingReadAndSkipFrame(&pArgs->pBuf->Recv, abBuf); 309 310 /* check for termination frame. */ 311 if ( pHdr->iFrame == 0xffffdead 312 && pHdr->auEos[0] == 0xffffdead 313 && pHdr->auEos[1] == 0xffffdead 314 && pHdr->auEos[2] == 0xffffdead) 315 { 316 pArgs->u64End = RTTimeNanoTS(); 317 RTThreadSleep(10); 318 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, 319 "receiver thread %.6Rhxs terminating.\n" 320 " iFrame=%u cb=%'u c=%'u %'uKB/s %'ufps cLost=%'u \n", 321 &pArgs->Mac, iFrame, cbReceived, iFrame - cLostFrames, 322 (unsigned)(cbReceived * 1000000000.0 / 1024 / (pArgs->u64End - pArgs->u64Start)), 323 (unsigned)((iFrame - cLostFrames) * 1000000000.0 / (pArgs->u64End - pArgs->u64Start)), 324 cLostFrames); 325 return VINF_SUCCESS; 326 } 327 328 /* validate frame header */ 329 if ( pHdr->DstMac.au16[0] != pArgs->Mac.au16[0] 330 || pHdr->DstMac.au16[1] != pArgs->Mac.au16[1] 331 || pHdr->DstMac.au16[2] != pArgs->Mac.au16[2] 332 || pHdr->SrcMac.au16[0] != pArgs->Mac.au16[0] 333 || pHdr->SrcMac.au16[1] != pArgs->Mac.au16[1] 334 || pHdr->SrcMac.au16[2] != (pArgs->Mac.au16[2] + 1) % 2) 335 { 336 RTTestFailed(g_hTest, "receiver thread %.6Rhxs received frame header: %.16Rhxs\n", &pArgs->Mac, abBuf); 337 } 338 339 /* frame stuff and stats. */ 340 int32_t off = pHdr->iFrame - (iFrame + 1); 341 if (off) 342 { 343 if (off > 0) 344 { 345 #ifndef IGNORE_LOST_FRAMES 346 RTTestFailed(g_hTest, "receiver thread %.6Rhxs: iFrame=%#x *puFrame=%#x off=%d\n", 347 &pArgs->Mac, iFrame, pHdr->iFrame, off); 348 #endif 349 cLostFrames += off; 350 } 351 else 352 { 353 cLostFrames++; 354 RTTestFailed(g_hTest, "receiver thread %.6Rhxs: iFrame=%#x *puFrame=%#x off=%d\n", 355 &pArgs->Mac, iFrame, pHdr->iFrame, off); 356 } 357 } 358 iFrame = pHdr->iFrame; 359 cbReceived += cb; 360 } 361 324 362 /* 325 363 * Wait for data. … … 332 370 break; 333 371 case VERR_SEM_DESTROYED: 334 RTPrintf("tstIntNetR0: receiver thread %.6Rhxs terminating. iFrame=%u cb=%'u c=%'u cLost=%'u\n", 335 &pArgs->Mac, iFrame, cbReceived, iFrame - cLostFrames, cLostFrames); 372 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, 373 "receiver thread %.6Rhxs terminating. iFrame=%u cb=%'u c=%'u cLost=%'u\n", 374 &pArgs->Mac, iFrame, cbReceived, iFrame - cLostFrames, cLostFrames); 336 375 return VINF_SUCCESS; 337 376 338 377 default: 339 RTPrintf("tstIntNetR0: receiver thread %.6Rhxs got odd return value %Rrc! iFrame=%u cb=%'u c=%'u cLost=%'u\n", 340 &pArgs->Mac, rc, iFrame, cbReceived, iFrame - cLostFrames, cLostFrames); 341 g_cErrors++; 378 RTTestFailed(g_hTest, "receiver thread %.6Rhxs got odd return value %Rrc! iFrame=%u cb=%'u c=%'u cLost=%'u\n", 379 &pArgs->Mac, rc, iFrame, cbReceived, iFrame - cLostFrames, cLostFrames); 342 380 return rc; 343 381 } 344 382 383 } 384 } 385 386 387 /** 388 * Test state. 389 */ 390 typedef struct TSTSTATE 391 { 392 PINTNET pIntNet; 393 394 PINTNETBUF pBuf0; 395 INTNETIFHANDLE hIf0; 396 397 PINTNETBUF pBuf1; 398 INTNETIFHANDLE hIf1; 399 } TSTSTATE; 400 typedef TSTSTATE *PTSTSTATE; 401 402 403 /** 404 * Open two internal network interfaces. 405 * 406 * @returns IPRT status of the first failure. 407 * @param pThis The test instance. 408 */ 409 static int tstOpenInterfaces(PTSTSTATE pThis, const char *pszNetwork, uint32_t cbSend, uint32_t cbRecv) 410 { 411 pThis->hIf0 = INTNET_HANDLE_INVALID; 412 RTTESTI_CHECK_RC_OK_RET(INTNETR0Open(pThis->pIntNet, g_pSession, pszNetwork, kIntNetTrunkType_None, "", 413 0/*fFlags*/, cbSend, cbRecv, &pThis->hIf0), rcCheck); 414 RTTESTI_CHECK_RET(pThis->hIf0 != INTNET_HANDLE_INVALID, VERR_INTERNAL_ERROR); 415 RTTESTI_CHECK_RC_RET(INTNETR0IfGetRing0Buffer(pThis->pIntNet, pThis->hIf0, g_pSession, &pThis->pBuf0), VINF_SUCCESS, rcCheck); 416 RTTESTI_CHECK_RET(pThis->pBuf0, VERR_INTERNAL_ERROR); 417 418 419 pThis->hIf1 = INTNET_HANDLE_INVALID; 420 RTTESTI_CHECK_RC_OK_RET(INTNETR0Open(pThis->pIntNet, g_pSession, pszNetwork, kIntNetTrunkType_None, "", 421 0/*fFlags*/, cbSend, cbRecv, &pThis->hIf1), rcCheck); 422 RTTESTI_CHECK_RET(pThis->hIf1 != INTNET_HANDLE_INVALID, VERR_INTERNAL_ERROR); 423 RTTESTI_CHECK_RC_RET(INTNETR0IfGetRing0Buffer(pThis->pIntNet, pThis->hIf1, g_pSession, &pThis->pBuf1), VINF_SUCCESS, rcCheck); 424 RTTESTI_CHECK_RET(pThis->pBuf1, VERR_INTERNAL_ERROR); 425 426 return VINF_SUCCESS; 427 } 428 429 /** 430 * Close the interfaces. 431 * 432 * @param pThis The test instance. 433 */ 434 static void tstCloseInterfaces(PTSTSTATE pThis) 435 { 436 int rc; 437 RTTESTI_CHECK_RC_OK(rc = INTNETR0IfClose(pThis->pIntNet, pThis->hIf0, g_pSession)); 438 if (RT_SUCCESS(rc)) 439 { 440 pThis->hIf0 = INTNET_HANDLE_INVALID; 441 pThis->pBuf0 = NULL; 442 } 443 444 RTTESTI_CHECK_RC_OK(rc = INTNETR0IfClose(pThis->pIntNet, pThis->hIf1, g_pSession)); 445 if (RT_SUCCESS(rc)) 446 { 447 pThis->hIf1 = INTNET_HANDLE_INVALID; 448 pThis->pBuf1 = NULL; 449 } 450 451 /* The network should be dead now. */ 452 RTTESTI_CHECK(pThis->pIntNet->pNetworks == NULL); 453 } 454 455 /** 456 * Do the bi-directional transfer test. 457 */ 458 static void tstBidirectionalTransfer(PTSTSTATE pThis) 459 { 460 MYARGS Args0; 461 RT_ZERO(Args0); 462 Args0.hIf = pThis->hIf0; 463 Args0.pBuf = pThis->pBuf0; 464 Args0.pIntNet = pThis->pIntNet; 465 Args0.Mac.au16[0] = 0x8086; 466 Args0.Mac.au16[1] = 0; 467 Args0.Mac.au16[2] = 0; 468 469 MYARGS Args1; 470 RT_ZERO(Args1); 471 Args1.hIf = pThis->hIf1; 472 Args1.pBuf = pThis->pBuf1; 473 Args1.pIntNet = pThis->pIntNet; 474 Args1.Mac.au16[0] = 0x8086; 475 Args1.Mac.au16[1] = 0; 476 Args1.Mac.au16[2] = 1; 477 478 RTTHREAD ThreadRecv0 = NIL_RTTHREAD; 479 RTTHREAD ThreadRecv1 = NIL_RTTHREAD; 480 RTTHREAD ThreadSend0 = NIL_RTTHREAD; 481 RTTHREAD ThreadSend1 = NIL_RTTHREAD; 482 RTTESTI_CHECK_RC_OK_RETV(RTThreadCreate(&ThreadRecv0, ReceiveThread, &Args0, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "RECV0")); 483 RTTESTI_CHECK_RC_OK_RETV(RTThreadCreate(&ThreadRecv1, ReceiveThread, &Args1, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "RECV1")); 484 RTTESTI_CHECK_RC_OK_RETV(RTThreadCreate(&ThreadSend0, SendThread, &Args0, 0, RTTHREADTYPE_EMULATION, RTTHREADFLAGS_WAITABLE, "SEND0")); 485 RTTESTI_CHECK_RC_OK_RETV(RTThreadCreate(&ThreadSend1, SendThread, &Args1, 0, RTTHREADTYPE_EMULATION, RTTHREADFLAGS_WAITABLE, "SEND1")); 486 487 int rc2 = VINF_SUCCESS; 488 int rc; 489 RTTESTI_CHECK_RC_OK(rc = RTThreadWait(ThreadSend0, 5*60*1000, &rc2)); 490 if (RT_SUCCESS(rc)) 491 { 492 RTTESTI_CHECK_RC_OK(rc2); 493 ThreadSend0 = NIL_RTTHREAD; 494 RTTESTI_CHECK_RC_OK(rc = RTThreadWait(ThreadSend1, 5*60*1000, RT_SUCCESS(rc2) ? &rc2 : NULL)); 495 if (RT_SUCCESS(rc)) 496 { 497 ThreadSend1 = NIL_RTTHREAD; 498 RTTESTI_CHECK_RC_OK(rc2); 499 } 500 } 501 if (RTTestErrorCount(g_hTest) == 0) 502 { 345 503 /* 346 * Read data.504 * Wait a bit for the receivers to finish up. 347 505 */ 348 while (INTNETRingHasMoreToRead(&pArgs->pBuf->Recv)) 506 unsigned cYields = 100000; 507 while ( ( INTNETRingHasMoreToRead(&pThis->pBuf0->Recv) 508 || INTNETRingHasMoreToRead(&pThis->pBuf1->Recv)) 509 && cYields-- > 0) 510 RTThreadYield(); 511 512 uint64_t u64Elapsed = RT_MAX(Args0.u64End, Args1.u64End) - RT_MIN(Args0.u64Start, Args1.u64Start); 513 uint64_t u64Speed = (uint64_t)((2 * g_cbTransfer / 1024) / (u64Elapsed / 1000000000.0)); 514 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, 515 "transfered %u bytes in %'RU64 ns (%'RU64 KB/s)\n", 516 2 * g_cbTransfer, u64Elapsed, u64Speed); 517 518 /* 519 * Wait for the threads to finish up... 520 */ 521 RTTESTI_CHECK_RC_OK(rc = RTThreadWait(ThreadRecv0, 5000, &rc2)); 522 if (RT_SUCCESS(rc)) 349 523 { 350 uint8_t abBuf[16384]; 351 uint32_t cb = INTNETRingReadAndSkipFrame(&pArgs->pBuf->Recv, abBuf); 352 unsigned *puFrame = (unsigned *)&abBuf[sizeof(RTMAC) * 2]; 353 354 /* check for termination frame. */ 355 if ( cb == sizeof(RTMAC) * 2 + sizeof(unsigned) * 4 356 && puFrame[0] == 0xffffdead 357 && puFrame[1] == 0xffffdead 358 && puFrame[2] == 0xffffdead 359 && puFrame[3] == 0xffffdead) 360 { 361 pArgs->u64End = RTTimeNanoTS(); 362 RTPrintf("tstIntNetR0: receiver thread %.6Rhxs terminating.\n" 363 "tstIntNetR0: iFrame=%u cb=%'u c=%'u %'uKB/s %'ufps cLost=%'u \n", 364 &pArgs->Mac, iFrame, cbReceived, iFrame - cLostFrames, 365 (unsigned)(cbReceived * 1000000000.0 / 1024 / (pArgs->u64End - pArgs->u64Start)), 366 (unsigned)((iFrame - cLostFrames) * 1000000000.0 / (pArgs->u64End - pArgs->u64Start)), 367 cLostFrames); 368 return VINF_SUCCESS; 369 } 370 371 /* validate frame header */ 372 PRTMAC pMacSrc = (PRTMAC)&abBuf[0]; 373 PRTMAC pMacDst = pMacSrc + 1; 374 if ( pMacDst->au16[0] != 0x8086 375 || pMacDst->au16[1] != 0 376 || pMacDst->au16[2] != pArgs->Mac.au16[2] 377 || pMacSrc->au16[0] != 0x8086 378 || pMacSrc->au16[1] != 0 379 || pMacSrc->au16[2] == pArgs->Mac.au16[2]) 380 { 381 RTPrintf("tstIntNetR0: receiver thread %.6Rhxs received frame header: %.16Rhxs\n", 382 &pArgs->Mac, abBuf); 383 g_cErrors++; 384 } 385 386 /* frame stuff and stats. */ 387 int off = iFrame + 1 - *puFrame; 388 if (off) 389 { 390 if (off > 0) 391 { 392 RTPrintf("tstIntNetR0: receiver thread %.6Rhxs: iFrame=%d *puFrame=%d off=%d\n", 393 &pArgs->Mac, iFrame, *puFrame, off); 394 g_cErrors++; 395 cLostFrames++; 396 } 397 else 398 { 399 cLostFrames += -off; 400 #ifndef IGNORE_LOST_FRAMES 401 if (off < 50) 402 { 403 RTPrintf("tstIntNetR0: receiver thread %.6Rhxs: iFrame=%d *puFrame=%d off=%d\n", 404 &pArgs->Mac, iFrame, *puFrame, off); 405 g_cErrors++; 406 } 407 #endif 408 } 409 } 410 iFrame = *puFrame; 411 cbReceived += cb; 524 RTTESTI_CHECK_RC_OK(rc2); 525 ThreadRecv0 = NIL_RTTHREAD; 412 526 } 413 } 414 } 527 528 RTTESTI_CHECK_RC_OK(rc = RTThreadWait(ThreadRecv1, 5000, &rc2)); 529 if (RT_SUCCESS(rc)) 530 { 531 RTTESTI_CHECK_RC_OK(rc2); 532 ThreadRecv1 = NIL_RTTHREAD; 533 } 534 } 535 536 /* 537 * Give them a chance to complete... 538 */ 539 RTThreadWait(ThreadRecv0, 5000, NULL); 540 RTThreadWait(ThreadRecv1, 5000, NULL); 541 RTThreadWait(ThreadSend0, 5000, NULL); 542 RTThreadWait(ThreadSend1, 5000, NULL); 543 544 545 /* 546 * Display statistics. 547 */ 548 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, 549 "Buf0: Yields-OK=%llu Yields-NOK=%llu Lost=%llu Bad=%llu\n", 550 pThis->pBuf0->cStatYieldsOk.c, 551 pThis->pBuf0->cStatYieldsNok.c, 552 pThis->pBuf0->cStatLost.c, 553 pThis->pBuf0->cStatBadFrames.c); 554 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, 555 "Buf0.Recv: Frames=%llu Bytes=%llu Overflows=%llu\n", 556 pThis->pBuf0->Recv.cStatFrames, 557 pThis->pBuf0->Recv.cbStatWritten.c, 558 pThis->pBuf0->Recv.cOverflows.c); 559 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, 560 "Buf0.Send: Frames=%llu Bytes=%llu Overflows=%llu\n", 561 pThis->pBuf0->Send.cStatFrames, 562 pThis->pBuf0->Send.cbStatWritten.c, 563 pThis->pBuf0->Send.cOverflows.c); 564 565 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, 566 "Buf1: Yields-OK=%llu Yields-NOK=%llu Lost=%llu Bad=%llu\n", 567 pThis->pBuf1->cStatYieldsOk.c, 568 pThis->pBuf1->cStatYieldsNok.c, 569 pThis->pBuf1->cStatLost.c, 570 pThis->pBuf1->cStatBadFrames.c); 571 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, 572 "Buf1.Recv: Frames=%llu Bytes=%llu Overflows=%llu\n", 573 pThis->pBuf1->Recv.cStatFrames, 574 pThis->pBuf1->Recv.cbStatWritten.c, 575 pThis->pBuf1->Recv.cOverflows.c); 576 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, 577 "Buf1.Send: Frames=%llu Bytes=%llu Overflows=%llu\n", 578 pThis->pBuf1->Send.cStatFrames, 579 pThis->pBuf1->Send.cbStatWritten.c, 580 pThis->pBuf1->Send.cOverflows.c); 581 582 } 583 584 /** 585 * Performs a simple broadcast test. 586 * 587 * @param pThis The test instance. 588 * @param fHeadGuard Whether to use a head or tail guard. 589 */ 590 static void doBroadcastTest(PTSTSTATE pThis, bool fHeadGuard) 591 { 592 static uint16_t const s_au16Frame[7] = { /* dst:*/ 0xffff, 0xffff, 0xffff, /*src:*/0x8086, 0, 0, 0x0800 }; 593 594 RTTESTI_CHECK_RC_RETV(tstIntNetSendBuf(pThis->pIntNet, &pThis->pBuf0->Send, pThis->hIf0, 595 g_pSession, &s_au16Frame, sizeof(s_au16Frame)), 596 VINF_SUCCESS); 597 598 /* No echo, please */ 599 RTTESTI_CHECK_RC_RETV(INTNETR0IfWait(pThis->pIntNet, pThis->hIf0, g_pSession, 1), VERR_TIMEOUT); 600 601 /* The other interface should see it though. But Wait should only return once, thank you. */ 602 RTTESTI_CHECK_RC_RETV(INTNETR0IfWait(pThis->pIntNet, pThis->hIf1, g_pSession, 1), VINF_SUCCESS); 603 RTTESTI_CHECK_RC_RETV(INTNETR0IfWait(pThis->pIntNet, pThis->hIf1, g_pSession, 0), VERR_TIMEOUT); 604 605 /* Receive the data. */ 606 const unsigned cbExpect = RT_ALIGN(sizeof(s_au16Frame) + sizeof(INTNETHDR), sizeof(INTNETHDR)); 607 RTTESTI_CHECK_MSG(INTNETRingGetReadable(&pThis->pBuf1->Recv) == cbExpect, 608 ("%#x vs. %#x\n", INTNETRingGetReadable(&pThis->pBuf1->Recv), cbExpect)); 609 610 void *pvBuf; 611 RTTESTI_CHECK_RC_OK_RETV(RTTestGuardedAlloc(g_hTest, sizeof(s_au16Frame), 1, fHeadGuard, &pvBuf)); 612 uint32_t cb; 613 RTTESTI_CHECK_MSG_RETV((cb = INTNETRingReadAndSkipFrame(&pThis->pBuf1->Recv, pvBuf)) == sizeof(s_au16Frame), 614 ("%#x vs. %#x\n", cb, sizeof(s_au16Frame))); 615 616 if (memcmp(pvBuf, &s_au16Frame, sizeof(s_au16Frame))) 617 RTTestIFailed("Got invalid data!\n" 618 "received: %.*Rhxs\n" 619 "expected: %.*Rhxs\n", 620 cb, pvBuf, sizeof(s_au16Frame), &s_au16Frame); 621 } 622 623 /** 624 * Performs a simple unicast test. 625 * 626 * @param pThis The test instance. 627 * @param fHeadGuard Whether to use a head or tail guard. 628 */ 629 static void doUnicastTest(PTSTSTATE pThis, bool fHeadGuard) 630 { 631 static uint16_t const s_au16Frame[7] = { /* dst:*/ 0x8086, 0, 0, /*src:*/0x8086, 0, 1, 0x0800 }; 632 633 RTTESTI_CHECK_RC_RETV(tstIntNetSendBuf(pThis->pIntNet, &pThis->pBuf1->Send, pThis->hIf1, 634 g_pSession, s_au16Frame, sizeof(s_au16Frame)), 635 VINF_SUCCESS); 636 637 /* No echo, please */ 638 RTTESTI_CHECK_RC_RETV(INTNETR0IfWait(pThis->pIntNet, pThis->hIf1, g_pSession, 1), VERR_TIMEOUT); 639 640 /* The other interface should see it though. But Wait should only return once, thank you. */ 641 RTTESTI_CHECK_RC_RETV(INTNETR0IfWait(pThis->pIntNet, pThis->hIf0, g_pSession, 1), VINF_SUCCESS); 642 RTTESTI_CHECK_RC_RETV(INTNETR0IfWait(pThis->pIntNet, pThis->hIf0, g_pSession, 0), VERR_TIMEOUT); 643 644 /* Receive the data. */ 645 const unsigned cbExpect = RT_ALIGN(sizeof(s_au16Frame) + sizeof(INTNETHDR), sizeof(INTNETHDR)); 646 RTTESTI_CHECK_MSG(INTNETRingGetReadable(&pThis->pBuf0->Recv) == cbExpect, 647 ("%#x vs. %#x\n", INTNETRingGetReadable(&pThis->pBuf0->Recv), cbExpect)); 648 649 void *pvBuf; 650 RTTESTI_CHECK_RC_OK_RETV(RTTestGuardedAlloc(g_hTest, sizeof(s_au16Frame), 1, fHeadGuard, &pvBuf)); 651 uint32_t cb; 652 RTTESTI_CHECK_MSG_RETV((cb = INTNETRingReadAndSkipFrame(&pThis->pBuf0->Recv, pvBuf)) == sizeof(s_au16Frame), 653 ("%#x vs. %#x\n", cb, sizeof(s_au16Frame))); 654 655 if (memcmp(pvBuf, &s_au16Frame, sizeof(s_au16Frame))) 656 RTTestIFailed("Got invalid data!\n" 657 "received: %.*Rhxs\n" 658 "expected: %.*Rhxs\n", 659 cb, pvBuf, sizeof(s_au16Frame), s_au16Frame); 660 } 661 662 static void doTest(PTSTSTATE pThis, uint32_t cbRecv, uint32_t cbSend) 663 { 664 665 /* 666 * Create an INTNET instance. 667 */ 668 RTTestISub("INTNETR0Create"); 669 RTTESTI_CHECK_RC_RETV(INTNETR0Create(&pThis->pIntNet), VINF_SUCCESS); 670 671 /* 672 * Create two interfaces and activate them. 673 */ 674 RTTestISub("Network creation"); 675 int rc = tstOpenInterfaces(pThis, "test", cbSend, cbRecv); 676 if (RT_FAILURE(rc)) 677 return; 678 RTTESTI_CHECK_RC(INTNETR0IfSetActive(pThis->pIntNet, pThis->hIf0, g_pSession, true), VINF_SUCCESS); 679 RTTESTI_CHECK_RC(INTNETR0IfSetActive(pThis->pIntNet, pThis->hIf1, g_pSession, true), VINF_SUCCESS); 680 681 /* 682 * Test basic waiting. 683 */ 684 RTTestISub("INTNETR0IfWait"); 685 RTTESTI_CHECK_RC(INTNETR0IfWait(pThis->pIntNet, pThis->hIf0, g_pSession, 1), VERR_TIMEOUT); 686 RTTESTI_CHECK_RC(INTNETR0IfWait(pThis->pIntNet, pThis->hIf0, g_pSession, 0), VERR_TIMEOUT); 687 RTTESTI_CHECK_RC(INTNETR0IfWait(pThis->pIntNet, pThis->hIf1, g_pSession, 1), VERR_TIMEOUT); 688 RTTESTI_CHECK_RC(INTNETR0IfWait(pThis->pIntNet, pThis->hIf1, g_pSession, 0), VERR_TIMEOUT); 689 690 /* 691 * Broadcast send and receive. 692 * (This establishes the MAC address of the 1st interface.) 693 */ 694 RTTestISub("Broadcast"); 695 doBroadcastTest(pThis, false /*fHeadGuard*/); 696 doBroadcastTest(pThis, true /*fHeadGuard*/); 697 698 /* 699 * Unicast send and receive. 700 * (This establishes the MAC address of the 2nd interface.) 701 */ 702 RTTestISub("Unicast"); 703 doUnicastTest(pThis, false /*fHeadGuard*/); 704 doUnicastTest(pThis, true /*fHeadGuard*/); 705 706 /* 707 * Do the big bi-directional transfer test if the basics worked out. 708 */ 709 if (!RTTestIErrorCount()) 710 { 711 RTTestISubF("bi-directional benchmark, cbSend=%u, cbRecv=%u, cbTransfer=%u", 712 pThis->pBuf0->cbSend, pThis->pBuf0->cbRecv, g_cbTransfer); 713 tstBidirectionalTransfer(pThis); 714 } 715 716 /* 717 * Destroy the service. 718 */ 719 tstCloseInterfaces(pThis); 720 INTNETR0Destroy(pThis->pIntNet); 721 } 722 415 723 416 724 int main(int argc, char **argv) 417 725 { 418 /* 419 * Init the runtime and parse arguments. 420 */ 421 RTR3Init(); 422 726 int rc = RTTestInitAndCreate("tstIntNetR0", &g_hTest); 727 if (rc) 728 return rc; 729 730 /* 731 * Parse the arguments. 732 */ 423 733 static RTGETOPTDEF const s_aOptions[] = 424 734 { 425 { "--recv-buffer", 'r', RTGETOPT_REQ_UINT32 }, 426 { "--send-buffer", 's', RTGETOPT_REQ_UINT32 }, 735 { "--recv-buffer", 'r', RTGETOPT_REQ_UINT32 }, 736 { "--send-buffer", 's', RTGETOPT_REQ_UINT32 }, 737 { "--transfer-size", 'l', RTGETOPT_REQ_UINT32 }, 427 738 }; 428 739 429 uint32_t cb Recv = 32 * _1K;430 uint32_t cb Send = 1536*2;740 uint32_t cbSend = 1536*2 + 4; 741 uint32_t cbRecv = 0x8000; 431 742 432 743 int ch; … … 437 748 switch (ch) 438 749 { 750 case 'l': 751 g_cbTransfer = Value.u32; 752 break; 753 439 754 case 'r': 440 755 cbRecv = Value.u32; … … 450 765 451 766 /* 452 * Create an INTNET instance. 453 */ 454 RTPrintf("tstIntNetR0: TESTING cbSend=%d cbRecv=%d ...\n", cbSend, cbRecv); 455 PINTNET pIntNet; 456 int rc = INTNETR0Create(&pIntNet); 457 if (RT_FAILURE(rc)) 458 { 459 RTPrintf("tstIntNetR0: INTNETR0Create failed, rc=%Rrc\n"); 460 return 1; 461 } 462 463 /* 464 * Create two interfaces. 465 */ 466 INTNETIFHANDLE hIf0 = INTNET_HANDLE_INVALID; 467 rc = INTNETR0Open(pIntNet, g_pSession, "test", kIntNetTrunkType_None, "", 0, 1536*2 + 4, 0x8000, &hIf0); 468 if (RT_SUCCESS(rc)) 469 { 470 if (hIf0 != INTNET_HANDLE_INVALID) 471 { 472 INTNETIFHANDLE hIf1 = INTNET_HANDLE_INVALID; 473 rc = INTNETR0Open(pIntNet, g_pSession, "test", kIntNetTrunkType_None, NULL, 0, 1536*2 + 4, 0x8000, &hIf1); 474 if (RT_SUCCESS(rc)) 475 { 476 if (hIf1 != INTNET_HANDLE_INVALID) 477 { 478 PINTNETBUF pBuf0; 479 rc = INTNETR0IfGetRing0Buffer(pIntNet, hIf0, g_pSession, &pBuf0); 480 if (RT_FAILURE(rc) || !pBuf0) 481 { 482 RTPrintf("tstIntNetR0: INTNETIfGetRing0Buffer failed! pBuf0=%p rc=%Rrc\n", pBuf0, rc); 483 g_cErrors++; 484 } 485 PINTNETBUF pBuf1; 486 rc = INTNETR0IfGetRing0Buffer(pIntNet, hIf1, g_pSession, &pBuf1); 487 if (RT_FAILURE(rc)) 488 { 489 RTPrintf("tstIntNetR0: INTNETIfGetRing0Buffer failed! pBuf1=%p rc=%Rrc\n", pBuf1, rc); 490 g_cErrors++; 491 } 492 493 rc = INTNETR0IfSetActive(pIntNet, hIf0, g_pSession, true); 494 if (RT_FAILURE(rc)) 495 { 496 RTPrintf("tstIntNetR0: INTNETR0IfSetActive failed! rc=%Rrc\n", rc); 497 g_cErrors++; 498 } 499 rc = INTNETR0IfSetActive(pIntNet, hIf1, g_pSession, true); 500 if (RT_FAILURE(rc)) 501 { 502 RTPrintf("tstIntNetR0: INTNETR0IfSetActive failed! rc=%Rrc\n", rc); 503 g_cErrors++; 504 } 505 506 507 /* 508 * Test basic waiting. 509 */ 510 rc = INTNETR0IfWait(pIntNet, hIf0, g_pSession, 1); 511 if (rc != VERR_TIMEOUT) 512 { 513 RTPrintf("tstIntNetR0: INTNETIfWait returned %Rrc expected VERR_TIMEOUT (hIf0)\n", rc); 514 g_cErrors++; 515 } 516 rc = INTNETR0IfWait(pIntNet, hIf1, g_pSession, 0); 517 if (rc != VERR_TIMEOUT) 518 { 519 RTPrintf("tstIntNetR0: INTNETIfWait returned %Rrc expected VERR_TIMEOUT (hIf1)\n", rc); 520 g_cErrors++; 521 } 522 523 /* 524 * Send and receive. 525 */ 526 rc = tstIntNetSendBuf(pIntNet, &pBuf0->Send, hIf0, g_pSession, &g_TestFrame0, sizeof(g_TestFrame0)); 527 if (RT_SUCCESS(rc)) 528 { 529 rc = INTNETR0IfWait(pIntNet, hIf0, g_pSession, 1); 530 if (rc != VERR_TIMEOUT) 531 { 532 RTPrintf("tstIntNetR0: INTNETIfWait returned %Rrc expected VERR_TIMEOUT (hIf0, 2nd)\n", rc); 533 g_cErrors++; 534 } 535 rc = INTNETR0IfWait(pIntNet, hIf1, g_pSession, 0); 536 if (rc == VINF_SUCCESS) 537 { 538 /* receive it */ 539 uint8_t abBuf[sizeof(g_TestFrame0)]; 540 const unsigned cbExpect = RT_ALIGN(sizeof(g_TestFrame0) + sizeof(INTNETHDR), sizeof(INTNETHDR)); 541 if (INTNETRingGetReadable(&pBuf1->Recv) != cbExpect) 542 { 543 RTPrintf("tstIntNetR0: %d readable bytes, expected %d!\n", INTNETRingGetReadable(&pBuf1->Recv), cbExpect); 544 g_cErrors++; 545 } 546 uint32_t cb = INTNETRingReadAndSkipFrame(&pBuf1->Recv, abBuf); 547 if (cb != sizeof(g_TestFrame0)) 548 { 549 RTPrintf("tstIntNetR0: read %d frame bytes, expected %d!\n", cb, sizeof(g_TestFrame0)); 550 g_cErrors++; 551 } 552 else if (memcmp(abBuf, &g_TestFrame0, sizeof(g_TestFrame0))) 553 { 554 RTPrintf("tstIntNetR0: Got invalid data!\n" 555 "received: %.*Rhxs\n" 556 "expected: %.*Rhxs\n", 557 cb, abBuf, sizeof(g_TestFrame0), &g_TestFrame0); 558 g_cErrors++; 559 } 560 561 /* 562 * Send a packet from If1 just to set its MAC address. 563 */ 564 rc = tstIntNetSendBuf(pIntNet, &pBuf1->Send, hIf1, g_pSession, &g_TestFrame1, sizeof(g_TestFrame1)); 565 if (RT_FAILURE(rc)) 566 { 567 RTPrintf("tstIntNetR0: INTNETIfSend returned %Rrc! (hIf1)\n", rc); 568 g_cErrors++; 569 } 570 571 572 /* 573 * Start threaded testcase. 574 * Give it 5 mins to finish. 575 */ 576 if (!g_cErrors) 577 { 578 MYARGS Args0; 579 RT_ZERO(Args0); 580 Args0.hIf = hIf0; 581 Args0.pBuf = pBuf0; 582 Args0.pIntNet = pIntNet; 583 Args0.Mac.au16[0] = 0x8086; 584 Args0.Mac.au16[1] = 0; 585 Args0.Mac.au16[2] = 0; 586 587 MYARGS Args1; 588 RT_ZERO(Args1); 589 Args1.hIf = hIf1; 590 Args1.pBuf = pBuf1; 591 Args1.pIntNet = pIntNet; 592 Args1.Mac.au16[0] = 0x8086; 593 Args1.Mac.au16[1] = 0; 594 Args1.Mac.au16[2] = 1; 595 596 RTTHREAD ThreadRecv0 = NIL_RTTHREAD; 597 RTTHREAD ThreadRecv1 = NIL_RTTHREAD; 598 RTTHREAD ThreadSend0 = NIL_RTTHREAD; 599 RTTHREAD ThreadSend1 = NIL_RTTHREAD; 600 rc = RTThreadCreate(&ThreadRecv0, ReceiveThread, &Args0, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "RECV0"); 601 if (RT_SUCCESS(rc)) 602 rc = RTThreadCreate(&ThreadRecv1, ReceiveThread, &Args1, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "RECV1"); 603 if (RT_SUCCESS(rc)) 604 rc = RTThreadCreate(&ThreadSend0, SendThread, &Args0, 0, RTTHREADTYPE_EMULATION, RTTHREADFLAGS_WAITABLE, "SEND0"); 605 if (RT_SUCCESS(rc)) 606 rc = RTThreadCreate(&ThreadSend1, SendThread, &Args1, 0, RTTHREADTYPE_EMULATION, RTTHREADFLAGS_WAITABLE, "SEND1"); 607 if (RT_SUCCESS(rc)) 608 { 609 int rc2 = VINF_SUCCESS; 610 rc = RTThreadWait(ThreadSend0, 5*60*1000, &rc2); 611 AssertRC(rc); 612 if (RT_SUCCESS(rc)) 613 { 614 ThreadSend0 = NIL_RTTHREAD; 615 rc = RTThreadWait(ThreadSend1, 5*60*1000, RT_SUCCESS(rc2) ? &rc2 : NULL); 616 AssertRC(rc); 617 if (RT_SUCCESS(rc)) 618 ThreadSend1 = NIL_RTTHREAD; 619 } 620 if ( RT_SUCCESS(rc) 621 && RT_SUCCESS(rc2)) 622 { 623 /* 624 * Wait a bit for the receivers to finish up. 625 */ 626 unsigned cYields = 100000; 627 while ( ( INTNETRingHasMoreToRead(&pBuf0->Recv) 628 || INTNETRingHasMoreToRead(&pBuf1->Recv)) 629 && cYields-- > 0) 630 RTThreadYield(); 631 632 uint64_t u64Elapsed = RT_MAX(Args0.u64End, Args1.u64End) - RT_MIN(Args0.u64Start, Args1.u64Start); 633 uint64_t u64Speed = (uint64_t)((2 * TEST_TRANSFER_SIZE / 1024) / (u64Elapsed / 1000000000.0)); 634 RTPrintf("tstIntNetR0: transfered %d bytes in %'RU64 ns (%'RU64 KB/s)\n", 635 2 * TEST_TRANSFER_SIZE, u64Elapsed, u64Speed); 636 637 /* 638 * Closing time... 639 */ 640 rc = RTThreadWait(ThreadRecv0, 5000, &rc2); 641 if (RT_SUCCESS(rc)) 642 ThreadRecv0 = NIL_RTTHREAD; 643 if (RT_FAILURE(rc) || RT_FAILURE(rc2)) 644 { 645 RTPrintf("tstIntNetR0: Failed waiting on receiver thread 0, rc=%Rrc, rc2=%Rrc\n", rc, rc2); 646 g_cErrors++; 647 } 648 649 rc = RTThreadWait(ThreadRecv1, 5000, &rc2); 650 if (RT_SUCCESS(rc)) 651 ThreadRecv1 = NIL_RTTHREAD; 652 if (RT_FAILURE(rc) || RT_FAILURE(rc2)) 653 { 654 RTPrintf("tstIntNetR0: Failed waiting on receiver thread 1, rc=%Rrc, rc2=%Rrc\n", rc, rc2); 655 g_cErrors++; 656 } 657 658 rc = INTNETR0IfClose(pIntNet, hIf0, g_pSession); 659 if (RT_SUCCESS(rc)) 660 { 661 hIf0 = INTNET_HANDLE_INVALID; 662 pBuf0 = NULL; 663 } 664 else 665 { 666 RTPrintf("tstIntNetR0: INTNETIfClose failed, rc=%Rrc! (hIf0)\n", rc); 667 g_cErrors++; 668 } 669 670 rc = INTNETR0IfClose(pIntNet, hIf1, g_pSession); 671 if (RT_SUCCESS(rc)) 672 { 673 hIf1 = INTNET_HANDLE_INVALID; 674 pBuf1 = NULL; 675 } 676 else 677 { 678 RTPrintf("tstIntNetR0: INTNETIfClose failed, rc=%Rrc! (hIf1)\n", rc); 679 g_cErrors++; 680 } 681 682 683 /* check if the network still exist... */ 684 if (pIntNet->pNetworks) 685 { 686 RTPrintf("tstIntNetR0: The network wasn't deleted! (g_cErrors=%d)\n", g_cErrors); 687 g_cErrors++; 688 } 689 } 690 else 691 { 692 RTPrintf("tstIntNetR0: Waiting on senders failed, rc=%Rrc, rc2=%Rrc\n", rc, rc2); 693 g_cErrors++; 694 } 695 696 /* 697 * Give them a chance to complete... 698 */ 699 RTThreadWait(ThreadRecv0, 5000, NULL); 700 RTThreadWait(ThreadRecv1, 5000, NULL); 701 RTThreadWait(ThreadSend0, 5000, NULL); 702 RTThreadWait(ThreadSend1, 5000, NULL); 703 704 } 705 else 706 { 707 RTPrintf("tstIntNetR0: Failed to create threads, rc=%Rrc\n", rc); 708 g_cErrors++; 709 } 710 } 711 } 712 else 713 { 714 RTPrintf("tstIntNetR0: INTNETIfWait returned %Rrc expected VINF_SUCCESS (hIf1)\n", rc); 715 g_cErrors++; 716 } 717 } 718 else 719 { 720 RTPrintf("tstIntNetR0: INTNETIfSend returned %Rrc! (hIf0)\n", rc); 721 g_cErrors++; 722 } 723 } 724 else 725 { 726 RTPrintf("tstIntNetR0: INTNETOpen returned invalid handle on success! (hIf1)\n"); 727 g_cErrors++; 728 } 729 730 if (hIf1 != INTNET_HANDLE_INVALID) 731 rc = INTNETR0IfClose(pIntNet, hIf1, g_pSession); 732 } 733 else 734 { 735 RTPrintf("tstIntNetR0: INTNETOpen failed for the 2nd interface! rc=%Rrc\n", rc); 736 g_cErrors++; 737 } 738 739 if (hIf0 != INTNET_HANDLE_INVALID) 740 rc = INTNETR0IfClose(pIntNet, hIf0, g_pSession); 741 } 742 else 743 { 744 RTPrintf("tstIntNetR0: INTNETOpen returned invalid handle on success! (hIf0)\n"); 745 g_cErrors++; 746 } 747 } 748 else 749 { 750 RTPrintf("tstIntNetR0: INTNETOpen failed for the 1st interface! rc=%Rrc\n", rc); 751 g_cErrors++; 752 } 753 754 /* 755 * Destroy the service. 756 */ 757 INTNETR0Destroy(pIntNet); 758 759 /* 760 * Summary. 761 */ 762 if (!g_cErrors) 763 RTPrintf("tstIntNetR0: SUCCESS\n"); 764 else 765 RTPrintf("tstIntNetR0: FAILURE - %d errors\n", g_cErrors); 766 767 return !!g_cErrors; 768 } 769 767 * Do the testing and report summary. 768 */ 769 TSTSTATE This; 770 RT_ZERO(This); 771 doTest(&This, cbRecv, cbSend); 772 773 return RTTestSummaryAndDestroy(g_hTest); 774 } 775
Note:
See TracChangeset
for help on using the changeset viewer.