VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/testcase/tstIntNetR0.cpp@ 4780

Last change on this file since 4780 was 4071, checked in by vboxsync, 18 years ago

Biggest check-in ever. New source code headers for all (C) innotek files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.0 KB
Line 
1/** @file
2 *
3 * VBox - Testcase for the Ring-0 part of internal networking.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define IN_INTNET_TESTCASE
23#define IN_INTNET_R3
24#include <VBox/cdefs.h>
25#undef INTNETR0DECL
26#define INTNETR0DECL INTNETR3DECL
27#include <VBox/intnet.h>
28#include <VBox/sup.h>
29#include <VBox/err.h>
30#include <iprt/stream.h>
31#include <iprt/alloc.h>
32#include <iprt/runtime.h>
33#include <iprt/thread.h>
34#include <iprt/time.h>
35#include <iprt/asm.h>
36
37
38/*******************************************************************************
39* Structures and Typedefs *
40*******************************************************************************/
41/**
42 * Security objectype.
43 */
44typedef enum SUPDRVOBJTYPE
45{
46 /** The usual invalid object. */
47 SUPDRVOBJTYPE_INVALID = 0,
48 /** Internal network. */
49 SUPDRVOBJTYPE_INTERNAL_NETWORK,
50 /** Internal network interface. */
51 SUPDRVOBJTYPE_INTERNAL_NETWORK_INTERFACE,
52 /** The first invalid object type in this end. */
53 SUPDRVOBJTYPE_END,
54 /** The usual 32-bit type size hack. */
55 SUPDRVOBJTYPE_32_BIT_HACK = 0x7ffffff
56} SUPDRVOBJTYPE;
57
58/**
59 * Object destructor callback.
60 * This is called for reference counted objectes when the count reaches 0.
61 *
62 * @param pvObj The object pointer.
63 * @param pvUser1 The first user argument.
64 * @param pvUser2 The second user argument.
65 */
66typedef DECLCALLBACK(void) FNSUPDRVDESTRUCTOR(void *pvObj, void *pvUser1, void *pvUser2);
67/** Pointer to a FNSUPDRVDESTRUCTOR(). */
68typedef FNSUPDRVDESTRUCTOR *PFNSUPDRVDESTRUCTOR;
69
70
71/**
72 * Dummy
73 */
74typedef struct OBJREF
75{
76 PFNSUPDRVDESTRUCTOR pfnDestructor;
77 void *pvUser1;
78 void *pvUser2;
79 uint32_t volatile cRefs;
80} OBJREF, *POBJREF;
81
82/*******************************************************************************
83* Global Variables *
84*******************************************************************************/
85/** The error count. */
86unsigned g_cErrors = 0;
87
88/** Fake session handle. */
89const PSUPDRVSESSION g_pSession = (PSUPDRVSESSION)0xdeadface;
90
91/** Testframe 0 */
92struct TESTFRAME
93{
94 uint16_t au16[6];
95} g_TestFrame0 = { { /* dst:*/ 0xffff, 0xffff, 0xffff, /*src:*/0x8086, 0, 0} },
96 g_TestFrame1 = { { /* dst:*/0, 0, 0, /*src:*/0x8086, 0, 1} };
97
98
99INTNETR3DECL(void *) SUPR0ObjRegister(PSUPDRVSESSION pSession, SUPDRVOBJTYPE enmType, PFNSUPDRVDESTRUCTOR pfnDestructor, void *pvUser1, void *pvUser2)
100{
101 if (pSession != g_pSession)
102 {
103 RTPrintf("tstIntNetR0: Invalid session pointer %p, %s!\n", pSession, __FUNCTION__);
104 g_cErrors++;
105 return NULL;
106 }
107 POBJREF pRef = (POBJREF)RTMemAlloc(sizeof(OBJREF));
108 if (!pRef)
109 return NULL;
110 pRef->cRefs = 1;
111 pRef->pfnDestructor = pfnDestructor;
112 pRef->pvUser1 = pvUser1;
113 pRef->pvUser2 = pvUser2;
114 return pRef;
115}
116
117INTNETR3DECL(int) SUPR0ObjAddRef(void *pvObj, PSUPDRVSESSION pSession)
118{
119 if (pSession != g_pSession)
120 {
121 RTPrintf("tstIntNetR0: Invalid session pointer %p, %s!\n", pSession, __FUNCTION__);
122 g_cErrors++;
123 return VERR_INVALID_PARAMETER;
124 }
125 POBJREF pRef = (POBJREF)pvObj;
126 ASMAtomicIncU32(&pRef->cRefs);
127 return VINF_SUCCESS;
128}
129
130INTNETR3DECL(int) SUPR0ObjRelease(void *pvObj, PSUPDRVSESSION pSession)
131{
132 if (pSession != g_pSession)
133 {
134 RTPrintf("tstIntNetR0: Invalid session pointer %p, %s!\n", pSession, __FUNCTION__);
135 g_cErrors++;
136 return VERR_INVALID_PARAMETER;
137 }
138 POBJREF pRef = (POBJREF)pvObj;
139 if (!ASMAtomicDecU32(&pRef->cRefs))
140 {
141 pRef->pfnDestructor(pRef, pRef->pvUser1, pRef->pvUser2);
142 RTMemFree(pRef);
143 }
144 return VINF_SUCCESS;
145}
146
147INTNETR3DECL(int) SUPR0ObjVerifyAccess(void *pvObj, PSUPDRVSESSION pSession, const char *pszObjName)
148{
149 if (pSession != g_pSession)
150 {
151 RTPrintf("tstIntNetR0: Invalid session pointer %p, %s!\n", pSession, __FUNCTION__);
152 g_cErrors++;
153 return VERR_INVALID_PARAMETER;
154 }
155 return VINF_SUCCESS;
156}
157
158INTNETR3DECL(int) SUPR0MemAlloc(PSUPDRVSESSION pSession, uint32_t cb, PRTR0PTR ppvR0, PRTR3PTR ppvR3)
159{
160 if (pSession != g_pSession)
161 {
162 RTPrintf("tstIntNetR0: Invalid session pointer %p, %s!\n", pSession, __FUNCTION__);
163 g_cErrors++;
164 return VERR_INVALID_PARAMETER;
165 }
166 void *pv = RTMemAlloc(cb);
167 if (!pv)
168 return VERR_NO_MEMORY;
169 *ppvR0 = (RTR0PTR)pv;
170 if (ppvR3)
171 *ppvR3 = pv;
172 return VINF_SUCCESS;
173}
174
175INTNETR3DECL(int) SUPR0MemFree(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr)
176{
177 if (pSession != g_pSession)
178 {
179 RTPrintf("tstIntNetR0: Invalid session pointer %p, %s!\n", pSession, __FUNCTION__);
180 g_cErrors++;
181 return VERR_INVALID_PARAMETER;
182 }
183 RTMemFree((void *)uPtr);
184 return VINF_SUCCESS;
185}
186
187
188
189/* ugly but necessary for making R0 code compilable for R3. */
190#undef LOG_GROUP
191#include "../SrvIntNetR0.cpp"
192
193typedef struct ARGS
194{
195 PINTNET pIntNet;
196 PINTNETBUF pBuf;
197 INTNETIFHANDLE hIf;
198 PDMMAC Mac;
199 uint64_t u64Start;
200 uint64_t u64End;
201} ARGS, *PARGS;
202
203
204#define TEST_TRANSFER_SIZE (_1M*128)
205
206/**
207 * Send thread.
208 * This is constantly broadcasting frames to the network.
209 */
210DECLCALLBACK(int) SendThread(RTTHREAD Thread, void *pvArg)
211{
212 PARGS pArgs = (PARGS)pvArg;
213
214 /*
215 * Send 64 MB of data.
216 */
217 uint8_t abBuf[4096] = {0};
218 PPDMMAC pMacSrc = (PPDMMAC)&abBuf[0];
219 PPDMMAC pMacDst = pMacSrc + 1;
220 *pMacSrc = pArgs->Mac;
221 *pMacDst = pArgs->Mac;
222 pMacDst->au16[2] = pArgs->Mac.au16[2] ? 0 : 1;
223 unsigned *puFrame = (unsigned *)(pMacDst + 1);
224 unsigned iFrame = 0;
225 unsigned cbSent = 0;
226 pArgs->u64Start = RTTimeNanoTS();
227 for (; cbSent < TEST_TRANSFER_SIZE; iFrame++)
228 {
229 const unsigned cb = iFrame % 1519 + 12 + sizeof(unsigned);
230 *puFrame = iFrame;
231 int rc = INTNETR0IfSend(pArgs->pIntNet, pArgs->hIf, abBuf, cb);
232 if (VBOX_FAILURE(rc))
233 {
234 g_cErrors++;
235 RTPrintf("tstIntNetR0: Failed sending %d bytes, rc=%Vrc\n", cb, rc);
236 }
237 cbSent += cb;
238 }
239
240 /*
241 * Termination frames.
242 */
243 puFrame[0] = 0xffffdead;
244 puFrame[1] = 0xffffdead;
245 puFrame[2] = 0xffffdead;
246 puFrame[3] = 0xffffdead;
247 for (unsigned c = 0; c < 20; c++)
248 {
249 int rc = INTNETR0IfSend(pArgs->pIntNet, pArgs->hIf, abBuf, sizeof(PDMMAC) * 2 + sizeof(unsigned) * 4);
250 if (VBOX_FAILURE(rc))
251 {
252 g_cErrors++;
253 RTPrintf("tstIntNetR0: send failed, rc=%Vrc\n", rc);
254 }
255 RTThreadSleep(1);
256 }
257
258 RTPrintf("tstIntNetR0: sender thread %.6Rhxs terminating. iFrame=%d cbSent=%d\n", &pArgs->Mac, iFrame, cbSent);
259 return 0;
260}
261
262
263/** Ignore lost frames. It only makes things worse to bitch about it. */
264#define IGNORE_LOST_FRAMES
265
266/**
267 * Receive thread.
268 * This is reading stuff from the network.
269 */
270DECLCALLBACK(int) ReceiveThread(RTTHREAD Thread, void *pvArg)
271{
272 unsigned cbReceived = 0;
273 unsigned cLostFrames = 0;
274 unsigned iFrame = ~0;
275 PARGS pArgs = (PARGS)pvArg;
276 for (;;)
277 {
278 /*
279 * Wait for data.
280 */
281 int rc = INTNETR0IfWait(pArgs->pIntNet, pArgs->hIf, RT_INDEFINITE_WAIT);
282 switch (rc)
283 {
284 case VERR_INTERRUPTED:
285 case VINF_SUCCESS:
286 break;
287 case VERR_SEM_DESTROYED:
288 RTPrintf("tstIntNetR0: receiver thread %.6Rhxs terminating. cbReceived=%u cLostFrames=%u iFrame=%u\n",
289 &pArgs->Mac, cbReceived, cLostFrames, iFrame);
290 return VINF_SUCCESS;
291
292 default:
293 RTPrintf("tstIntNetR0: receiver thread %.6Rhxs got odd return value %Vrc! cbReceived=%u cLostFrames=%u iFrame=%u\n",
294 &pArgs->Mac, rc, cbReceived, cLostFrames, iFrame);
295 g_cErrors++;
296 return rc;
297 }
298
299 /*
300 * Read data.
301 */
302 while (INTNETRingGetReadable(&pArgs->pBuf->Recv))
303 {
304 uint8_t abBuf[16384];
305 unsigned cb = INTNETRingReadFrame(pArgs->pBuf, &pArgs->pBuf->Recv, abBuf);
306 unsigned *puFrame = (unsigned *)&abBuf[sizeof(PDMMAC) * 2];
307
308 /* check for termination frame. */
309 if ( cb == sizeof(PDMMAC) * 2 + sizeof(unsigned) * 4
310 && puFrame[0] == 0xffffdead
311 && puFrame[1] == 0xffffdead
312 && puFrame[2] == 0xffffdead
313 && puFrame[3] == 0xffffdead)
314 {
315 RTPrintf("tstIntNetR0: receiver thread %.6Rhxs terminating. cbReceived=%u cLostFrames=%u iFrame=%u\n",
316 &pArgs->Mac, cbReceived, cLostFrames, iFrame);
317 pArgs->u64End = RTTimeNanoTS();
318 return VINF_SUCCESS;
319 }
320
321 /* validate frame header */
322 PPDMMAC pMacSrc = (PPDMMAC)&abBuf[0];
323 PPDMMAC pMacDst = pMacSrc + 1;
324 if ( pMacDst->au16[0] != 0x8086
325 || pMacDst->au16[1] != 0
326 || pMacDst->au16[2] != pArgs->Mac.au16[2]
327 || pMacSrc->au16[0] != 0x8086
328 || pMacSrc->au16[1] != 0
329 || pMacSrc->au16[2] == pArgs->Mac.au16[2])
330 {
331 RTPrintf("tstIntNetR0: receiver thread %.6Rhxs received frame header: %.16Rhxs\n",
332 &pArgs->Mac, abBuf);
333 g_cErrors++;
334 }
335
336 /* frame stuff and stats. */
337 int off = iFrame + 1 - *puFrame;
338 if (off)
339 {
340 if (off > 0)
341 {
342 RTPrintf("tstIntNetR0: receiver thread %.6Rhxs: iFrame=%d *puFrame=%d off=%d\n",
343 &pArgs->Mac, iFrame, *puFrame, off);
344 g_cErrors++;
345 cLostFrames++;
346 }
347 else
348 {
349 cLostFrames += -off;
350#ifndef IGNORE_LOST_FRAMES
351 if (off < 50)
352 {
353 RTPrintf("tstIntNetR0: receiver thread %.6Rhxs: iFrame=%d *puFrame=%d off=%d\n",
354 &pArgs->Mac, iFrame, *puFrame, off);
355 g_cErrors++;
356 }
357#endif
358 }
359 }
360 iFrame = *puFrame;
361 cbReceived += cb;
362 }
363 }
364}
365
366int main()
367{
368
369 /*
370 * Init runtime and create an INTNET instance.
371 */
372 RTR3Init();
373 RTPrintf("tstIntNetR0: TESTING...\n");
374 PINTNET pIntNet;
375 int rc = INTNETR0Create(&pIntNet);
376 if (VBOX_FAILURE(rc))
377 {
378 RTPrintf("tstIntNetR0: INTNETR0Create failed, rc=%Vrc\n");
379 return 1;
380 }
381
382 /*
383 * Create two interfaces.
384 */
385 INTNETIFHANDLE hIf0 = INTNET_HANDLE_INVALID;
386 rc = INTNETR0Open(pIntNet, g_pSession, "test", 1536, 0x8000, true, &hIf0);
387 if (VBOX_SUCCESS(rc))
388 {
389 if (hIf0 != INTNET_HANDLE_INVALID)
390 {
391 INTNETIFHANDLE hIf1 = INTNET_HANDLE_INVALID;
392 rc = INTNETR0Open(pIntNet, g_pSession, "test", 1536, 0x8000, true, &hIf1);
393 if (VBOX_SUCCESS(rc))
394 {
395 if (hIf1 != INTNET_HANDLE_INVALID)
396 {
397 PINTNETBUF pBuf0;
398 rc = INTNETR0IfGetRing0Buffer(pIntNet, hIf0, &pBuf0);
399 if (VBOX_FAILURE(rc) || !pBuf0)
400 {
401 RTPrintf("tstIntNetR0: INTNETIfGetRing0Buffer failed! pBuf0=%p rc=%Vrc\n", pBuf0, rc);
402 g_cErrors++;
403 }
404 PINTNETBUF pBuf1;
405 rc = INTNETR0IfGetRing0Buffer(pIntNet, hIf1, &pBuf1);
406 if (VBOX_FAILURE(rc))
407 {
408 RTPrintf("tstIntNetR0: INTNETIfGetRing0Buffer failed! pBuf1=%p rc=%Vrc\n", pBuf1, rc);
409 g_cErrors++;
410 }
411
412 /*
413 * Test basic waiting.
414 */
415 rc = INTNETR0IfWait(pIntNet, hIf0, 1);
416 if (rc != VERR_TIMEOUT)
417 {
418 RTPrintf("tstIntNetR0: INTNETIfWait returned %Vrc expected VERR_TIMEOUT (hIf0)\n", rc);
419 g_cErrors++;
420 }
421 rc = INTNETR0IfWait(pIntNet, hIf1, 0);
422 if (rc != VERR_TIMEOUT)
423 {
424 RTPrintf("tstIntNetR0: INTNETIfWait returned %Vrc expected VERR_TIMEOUT (hIf1)\n", rc);
425 g_cErrors++;
426 }
427
428 /*
429 * Send and receive.
430 */
431 rc = INTNETR0IfSend(pIntNet, hIf0, &g_TestFrame0, sizeof(g_TestFrame0));
432 if (VBOX_SUCCESS(rc))
433 {
434 rc = INTNETR0IfWait(pIntNet, hIf0, 1);
435 if (rc != VERR_TIMEOUT)
436 {
437 RTPrintf("tstIntNetR0: INTNETIfWait returned %Vrc expected VERR_TIMEOUT (hIf0, 2nd)\n", rc);
438 g_cErrors++;
439 }
440 rc = INTNETR0IfWait(pIntNet, hIf1, 0);
441 if (rc == VINF_SUCCESS)
442 {
443 /* receive it */
444 uint8_t abBuf[sizeof(g_TestFrame0)];
445 const unsigned cbExpect = RT_ALIGN(sizeof(g_TestFrame0) + sizeof(INTNETHDR), sizeof(INTNETHDR));
446 if (INTNETRingGetReadable(&pBuf1->Recv) != cbExpect)
447 {
448 RTPrintf("tstIntNetR0: %d readable bytes, expected %d!\n", INTNETRingGetReadable(&pBuf1->Recv), cbExpect);
449 g_cErrors++;
450 }
451 unsigned cb = INTNETRingReadFrame(pBuf1, &pBuf1->Recv, abBuf);
452 if (cb != sizeof(g_TestFrame0))
453 {
454 RTPrintf("tstIntNetR0: read %d frame bytes, expected %d!\n", cb, sizeof(g_TestFrame0));
455 g_cErrors++;
456 }
457 else if (memcmp(abBuf, &g_TestFrame0, sizeof(g_TestFrame0)))
458 {
459 RTPrintf("tstIntNetR0: Got invalid data!\n"
460 "received: %.*Rhxs\n"
461 "expected: %.*Rhxs\n",
462 cb, abBuf, sizeof(g_TestFrame0), &g_TestFrame0);
463 g_cErrors++;
464 }
465
466 /*
467 * Send a packet from If1 just to set its MAC address.
468 */
469 rc = INTNETR0IfSend(pIntNet, hIf1, &g_TestFrame1, sizeof(g_TestFrame1));
470 if (VBOX_FAILURE(rc))
471 {
472 RTPrintf("tstIntNetR0: INTNETIfSend returned %Vrc! (hIf1)\n", rc);
473 g_cErrors++;
474 }
475
476
477 /*
478 * Start threaded testcase.
479 */
480 if (!g_cErrors)
481 {
482 ARGS Args0 = {0};
483 Args0.hIf = hIf0;
484 Args0.pBuf = pBuf0;
485 Args0.pIntNet = pIntNet;
486 Args0.Mac.au16[0] = 0x8086;
487 Args0.Mac.au16[1] = 0;
488 Args0.Mac.au16[2] = 0;
489
490 ARGS Args1 = {0};
491 Args1.hIf = hIf1;
492 Args1.pBuf = pBuf1;
493 Args1.pIntNet = pIntNet;
494 Args1.Mac.au16[0] = 0x8086;
495 Args1.Mac.au16[1] = 0;
496 Args1.Mac.au16[2] = 1;
497
498 RTTHREAD ThreadRecv0 = NIL_RTTHREAD;
499 RTTHREAD ThreadRecv1 = NIL_RTTHREAD;
500 RTTHREAD ThreadSend0 = NIL_RTTHREAD;
501 RTTHREAD ThreadSend1 = NIL_RTTHREAD;
502 rc = RTThreadCreate(&ThreadRecv0, ReceiveThread, &Args0, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "RECV0");
503 if (VBOX_SUCCESS(rc))
504 rc = RTThreadCreate(&ThreadRecv1, ReceiveThread, &Args1, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "RECV1");
505 if (VBOX_SUCCESS(rc))
506 rc = RTThreadCreate(&ThreadSend0, SendThread, &Args0, 0, RTTHREADTYPE_EMULATION, RTTHREADFLAGS_WAITABLE, "SEND0");
507 if (VBOX_SUCCESS(rc))
508 rc = RTThreadCreate(&ThreadSend1, SendThread, &Args1, 0, RTTHREADTYPE_EMULATION, RTTHREADFLAGS_WAITABLE, "SEND1");
509 if (VBOX_SUCCESS(rc))
510 {
511 int rc2 = VINF_SUCCESS;
512 rc = RTThreadWait(ThreadSend0, 30000, &rc2);
513 if ( VBOX_SUCCESS(rc)
514 && VBOX_SUCCESS(rc2))
515 rc = RTThreadWait(ThreadSend1, 30000, &rc2);
516 if ( VBOX_SUCCESS(rc)
517 && VBOX_SUCCESS(rc2))
518 {
519 /*
520 * Wait a bit for the receivers to finish up.
521 */
522 unsigned cYields = 100000;
523 while ( ( INTNETRingGetReadable(&pBuf0->Recv)
524 || INTNETRingGetReadable(&pBuf1->Recv))
525 && cYields-- > 0)
526 RTThreadYield();
527
528 uint64_t u64Elapsed = RT_MAX(Args0.u64End, Args1.u64End) - RT_MIN(Args0.u64Start, Args1.u64Start);
529 uint64_t u64Speed = (uint64_t)((2 * TEST_TRANSFER_SIZE / 1024) / (u64Elapsed / 1000000000.0));
530 RTPrintf("tstIntNetR0: transfered %d bytes in %RU64 ns (%RU64 KB/s)\n",
531 2 * TEST_TRANSFER_SIZE, u64Elapsed, u64Speed);
532
533 /*
534 * Closing time...
535 */
536 rc = INTNETR0IfClose(pIntNet, hIf0);
537 if (VBOX_SUCCESS(rc))
538 {
539 hIf0 = INTNET_HANDLE_INVALID;
540 pBuf0 = NULL;
541 }
542 else
543 {
544 RTPrintf("tstIntNetR0: INTNETIfClose failed, rc=%Vrc! (hIf0)\n", rc);
545 g_cErrors++;
546 }
547 rc = INTNETR0IfClose(pIntNet, hIf1);
548 if (VBOX_SUCCESS(rc))
549 {
550 hIf1 = INTNET_HANDLE_INVALID;
551 pBuf1 = NULL;
552 }
553 else
554 {
555 RTPrintf("tstIntNetR0: INTNETIfClose failed, rc=%Vrc! (hIf1)\n", rc);
556 g_cErrors++;
557 }
558
559 rc = RTThreadWait(ThreadRecv0, 5000, &rc2);
560 if (VBOX_FAILURE(rc) || VBOX_FAILURE(rc2))
561 {
562 RTPrintf("tstIntNetR0: Failed waiting on receiver thread 0, rc=%Vrc, rc2=%Vrc\n", rc, rc2);
563 g_cErrors++;
564 }
565
566 rc = RTThreadWait(ThreadRecv1, 5000, &rc2);
567 if (VBOX_FAILURE(rc) || VBOX_FAILURE(rc2))
568 {
569 RTPrintf("tstIntNetR0: Failed waiting on receiver thread 1, rc=%Vrc, rc2=%Vrc\n", rc, rc2);
570 g_cErrors++;
571 }
572
573 /* check if the network still exist... */
574 if (pIntNet->pNetworks)
575 {
576 RTPrintf("tstIntNetR0: The network wasn't deleted! (g_cErrors=%d)\n", g_cErrors);
577 g_cErrors++;
578 }
579 }
580 else
581 {
582 RTPrintf("tstIntNetR0: Waiting on senders failed, rc=%Vrc, rc2=%Vrc\n", rc, rc2);
583 g_cErrors++;
584 }
585 }
586 else
587 {
588 RTPrintf("tstIntNetR0: Failed to create threads, rc=%Vrc\n", rc);
589 g_cErrors++;
590 }
591 }
592 }
593 else
594 {
595 RTPrintf("tstIntNetR0: INTNETIfWait returned %Vrc expected VINF_SUCCESS (hIf1)\n", rc);
596 g_cErrors++;
597 }
598 }
599 else
600 {
601 RTPrintf("tstIntNetR0: INTNETIfSend returned %Vrc! (hIf0)\n", rc);
602 g_cErrors++;
603 }
604 }
605 else
606 {
607 RTPrintf("tstIntNetR0: INTNETOpen returned invalid handle on success! (hIf1)\n");
608 g_cErrors++;
609 }
610 }
611 else
612 {
613 RTPrintf("tstIntNetR0: INTNETOpen failed for the 2nd interface! rc=%Vrc\n", rc);
614 g_cErrors++;
615 }
616 }
617 else
618 {
619 RTPrintf("tstIntNetR0: INTNETOpen returned invalid handle on success! (hIf0)\n");
620 g_cErrors++;
621 }
622 }
623 else
624 {
625 RTPrintf("tstIntNetR0: INTNETOpen failed for the 1st interface! rc=%Vrc\n", rc);
626 g_cErrors++;
627 }
628
629 /*
630 * Destroy the service.
631 */
632 INTNETR0Destroy(pIntNet);
633
634 /*
635 * Summary.
636 */
637 if (!g_cErrors)
638 RTPrintf("tstIntNetR0: SUCCESS\n");
639 else
640 RTPrintf("tstIntNetR0: FAILURE - %d errors\n", g_cErrors);
641
642 return !!g_cErrors;
643}
644
Note: See TracBrowser for help on using the repository browser.

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