Changeset 12619 in vbox for trunk/src/VBox/HostDrivers/VBoxNetFlt/solaris
- Timestamp:
- Sep 21, 2008 2:28:03 PM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 36895
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/VBoxNetFlt/solaris/VBoxNetFlt-solaris.c
r12618 r12619 29 29 #include <iprt/thread.h> 30 30 #include <iprt/spinlock.h> 31 #include <iprt/crc32.h> 31 32 32 33 #include <inet/ip.h> … … 83 84 #define VBOXNETFLT_IFNAME_LEN LIFNAMSIZ + 1 84 85 86 /** Maximum loopback packet queue size per interface */ 87 #define VBOXNETFLT_LOOPBACK_SIZE 64 85 88 86 89 /******************************************************************************* … … 279 282 280 283 /** 284 * loopback packet identifier 285 */ 286 typedef struct VBOXNETFLTPACKETID 287 { 288 struct VBOXNETFLTPACKETID *pNext; 289 uint16_t cbPacket; 290 uint16_t Checksum; 291 RTMAC SrcMac; 292 RTMAC DstMac; 293 } VBOXNETFLTPACKETID; 294 typedef struct VBOXNETFLTPACKETID *PVBOXNETFLTPACKETID; 295 296 297 /** 281 298 * vboxnetflt_stream_t: per-stream data (multiple streams per interface) 282 299 */ … … 299 316 bool fRawMode; /* whether raw mode request was successful */ 300 317 uint32_t ModeReqId; /* track MIOCTLs for swallowing our fake request acknowledgements */ 301 uint32_t aLoopback[64]; /* loopback CRC buffer */ 318 PVBOXNETFLTPACKETID pLoopbackHead; /* loopback packet identifier head */ 319 PVBOXNETFLTPACKETID pLoopbackTail; /* loopback packet identifier tail */ 320 size_t cLoopback; /* loopback queue size list */ 302 321 } vboxnetflt_promisc_stream_t; 303 322 … … 331 350 static int vboxNetFltSolarisUnitDataToRaw(PVBOXNETFLTINS pThis, mblk_t *pMsg, mblk_t **ppRawMsg); 332 351 static int vboxNetFltSolarisRawToUnitData(mblk_t *pMsg, mblk_t **ppDlpiMsg); 352 353 static inline void vboxNetFltSolarisInitPacketId(PVBOXNETFLTPACKETID pTag, mblk_t *pMsg); 354 static int vboxNetFltSolarisQueueLoopback(PVBOXNETFLTINS pThis, vboxnetflt_promisc_stream_t *pPromiscStream, mblk_t *pMsg); 355 static bool vboxNetFltSolarisIsOurMBlk(PVBOXNETFLTINS pThis, vboxnetflt_promisc_stream_t *pPromiscStream, mblk_t *pMsg); 333 356 334 357 static mblk_t *vboxNetFltSolarisMBlkFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst); … … 640 663 if (pState->CurType == kPromiscStream) 641 664 { 642 vboxnetflt_promisc_stream_t *pPromiscStream = RTMemAlloc(sizeof(vboxnetflt_promisc_stream_t)); 665 /* 666 * Careful; Use RTMemAllocZ here to zero-out uninitialized fields. 667 */ 668 vboxnetflt_promisc_stream_t *pPromiscStream = RTMemAllocZ(sizeof(vboxnetflt_promisc_stream_t)); 643 669 if (RT_UNLIKELY(!pPromiscStream)) 644 670 { … … 652 678 pPromiscStream->fRawMode = false; 653 679 pPromiscStream->ModeReqId = 0; 654 bzero(pPromiscStream->aLoopback, sizeof(pPromiscStream->aLoopback));655 680 pStream = (vboxnetflt_stream_t *)pPromiscStream; 656 681 } … … 1740 1765 1741 1766 /** 1742 * De-activates the dedicated promiscuous stream. 1767 * Closes the interface, thereby closing the dedicated stream. 1768 * 1769 * @param pThis The instance. 1743 1770 */ 1744 1771 static void vboxNetFltSolarisCloseStream(PVBOXNETFLTINS pThis) 1745 1772 { 1773 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; 1774 RTSpinlockAcquire(pThis->hSpinlock, &Tmp); 1775 1776 vboxnetflt_promisc_stream_t *pPromiscStream = (vboxnetflt_promisc_stream_t *)pThis->u.s.pvPromiscStream; 1777 if (pPromiscStream) 1778 { 1779 /* 1780 * Free-up loopback buffers. 1781 */ 1782 PVBOXNETFLTPACKETID pCur = pPromiscStream->pLoopbackHead; 1783 while (pCur) 1784 { 1785 PVBOXNETFLTPACKETID pNext = pCur->pNext; 1786 RTMemFree(pCur); 1787 pCur = pNext; 1788 } 1789 pPromiscStream->cLoopback = 0; 1790 } 1791 1792 RTSpinlockRelease(pThis->hSpinlock, &Tmp); 1746 1793 ldi_close(pThis->u.s.hIface, FREAD | FWRITE, kcred); 1747 1794 } … … 2304 2351 2305 2352 /** 2353 * Initializes a packet identifier. 2354 * 2355 * @param pMsg Pointer to the message. 2356 * 2357 * @remarks Warning!!! This function assumes 'pMsg' is an unchained message. 2358 */ 2359 static inline void vboxNetFltSolarisInitPacketId(PVBOXNETFLTPACKETID pTag, mblk_t *pMsg) 2360 { 2361 PCRTNETETHERHDR pEthHdr = (PCRTNETETHERHDR)pMsg->b_rptr; 2362 size_t cbMsg = MBLKL(pMsg); 2363 2364 AssertRelease(cbMsg > 0); /** Yeah, die otherwise! */ 2365 pTag->pNext = NULL; 2366 pTag->cbPacket = cbMsg; 2367 pTag->Checksum = RTCrc32(pMsg->b_rptr, cbMsg); 2368 bcopy(&pEthHdr->SrcMac, &pTag->SrcMac, sizeof(RTMAC)); 2369 bcopy(&pEthHdr->DstMac, &pTag->DstMac, sizeof(RTMAC)); 2370 } 2371 2372 2373 /** 2374 * Queues a packet for loopback elimination. 2375 * 2376 * @returns VBox status code. 2377 * @param pThis The instance. 2378 * @param pPromiscStream Pointer to the promiscuous stream. 2379 * @param pMsg Pointer to the message. 2380 */ 2381 static int vboxNetFltSolarisQueueLoopback(PVBOXNETFLTINS pThis, vboxnetflt_promisc_stream_t *pPromiscStream, mblk_t *pMsg) 2382 { 2383 Assert(pThis); 2384 Assert(pMsg); 2385 Assert(DB_TYPE(pMsg) == M_DATA); 2386 Assert(pPromiscStream); 2387 2388 LogFlow((DEVICE_NAME ":vboxNetFltSolarisQueueLoopback pThis=%p pPromiscStream=%p pMsg=%p\n", pThis, pPromiscStream, pMsg)); 2389 2390 size_t cbMsg = MBLKL(pMsg); 2391 if (cbMsg < sizeof(RTNETETHERHDR)) 2392 return VERR_NET_MSG_SIZE; 2393 2394 if (pMsg->b_cont) 2395 { 2396 /* @todo -XXX- handle chained messages */ 2397 return VERR_NOT_IMPLEMENTED; 2398 } 2399 2400 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; 2401 RTSpinlockAcquire(pThis->hSpinlock, &Tmp); 2402 2403 PCRTNETETHERHDR pEthHdr = (PCRTNETETHERHDR)pMsg->b_rptr; 2404 PVBOXNETFLTPACKETID pHead = pPromiscStream->pLoopbackHead; 2405 PVBOXNETFLTPACKETID pTail = pPromiscStream->pLoopbackTail; 2406 PVBOXNETFLTPACKETID pCur = NULL; 2407 int rc = VINF_SUCCESS; 2408 if (pPromiscStream->cLoopback < VBOXNETFLT_LOOPBACK_SIZE) 2409 { 2410 do 2411 { 2412 if (!pHead) 2413 { 2414 pCur = RTMemAllocZ(sizeof(VBOXNETFLTPACKETID)); 2415 if (RT_UNLIKELY(!pCur)) 2416 { 2417 rc = VERR_NO_MEMORY; 2418 break; 2419 } 2420 2421 vboxNetFltSolarisInitPacketId(pCur, pMsg); 2422 2423 pHead = pCur; 2424 pTail = pHead; 2425 pPromiscStream->cLoopback++; 2426 break; 2427 } 2428 2429 if ( pTail 2430 && pTail->cbPacket == 0) 2431 { 2432 pCur = pTail; 2433 vboxNetFltSolarisInitPacketId(pCur, pMsg); 2434 break; 2435 } 2436 2437 pCur = RTMemAllocZ(sizeof(VBOXNETFLTPACKETID)); 2438 if (RT_UNLIKELY(!pCur)) 2439 { 2440 rc = VERR_NO_MEMORY; 2441 break; 2442 } 2443 2444 pTail->pNext = pCur; 2445 vboxNetFltSolarisInitPacketId(pCur, pMsg); 2446 pPromiscStream->cLoopback++; 2447 break; 2448 } while (0); 2449 } 2450 else 2451 { 2452 /* 2453 * Maximum loopback queue size reached. Re-use head as tail. 2454 */ 2455 PVBOXNETFLTPACKETID pCur = pHead; 2456 pHead = pHead->pNext; 2457 pTail->pNext = pCur; 2458 pTail = pCur; 2459 2460 pCur->pNext = NULL; 2461 vboxNetFltSolarisInitPacketId(pCur, pMsg); 2462 } 2463 2464 RTSpinlockRelease(pThis->hSpinlock, &Tmp); 2465 return rc; 2466 } 2467 2468 2469 /** 2470 * Checks if the packet is enqueued for loopback as our own packet. 2471 * 2472 * @returns If it's our packet, returns true after dequeuing it, otherwise false. 2473 * @param pThis The instance. 2474 * @param pPromiscStream Pointer to the promiscuous stream. 2475 * @param pMsg Pointer to the message. 2476 */ 2477 static bool vboxNetFltSolarisIsOurMBlk(PVBOXNETFLTINS pThis, vboxnetflt_promisc_stream_t *pPromiscStream, mblk_t *pMsg) 2478 { 2479 Assert(pThis); 2480 Assert(pPromiscStream); 2481 Assert(pMsg); 2482 Assert(DB_TYPE(pMsg) == M_DATA); 2483 2484 LogFlow((DEVICE_NAME ":vboxNetFltSolarisIsOurMBlk pThis=%p pMsg=%p\n", pThis, pMsg)); 2485 2486 if (pMsg->b_cont) 2487 { 2488 /** @todo -XXX- implement chained message handling. */ 2489 return false; 2490 } 2491 2492 size_t cbMsg = MBLKL(pMsg); 2493 if (cbMsg < sizeof(RTNETETHERHDR)) 2494 return false; 2495 2496 PVBOXNETFLTPACKETID pCur = pPromiscStream->pLoopbackHead; 2497 while (pCur) 2498 { 2499 if (pCur->cbPacket != cbMsg) 2500 return false; 2501 2502 PCRTNETETHERHDR pEthHdr = (PCRTNETETHERHDR)pMsg->b_rptr; 2503 if ( pCur->SrcMac.au8[0] != pEthHdr->SrcMac.au8[0] 2504 || pCur->SrcMac.au8[1] != pEthHdr->SrcMac.au8[1] 2505 || pCur->SrcMac.au8[2] != pEthHdr->SrcMac.au8[2] 2506 || pCur->SrcMac.au8[3] != pEthHdr->SrcMac.au8[3] 2507 || pCur->SrcMac.au8[4] != pEthHdr->SrcMac.au8[4] 2508 || pCur->SrcMac.au8[5] != pEthHdr->SrcMac.au8[5] 2509 || pCur->DstMac.au8[0] != pEthHdr->DstMac.au8[0] 2510 || pCur->DstMac.au8[1] != pEthHdr->DstMac.au8[1] 2511 || pCur->DstMac.au8[2] != pEthHdr->DstMac.au8[2] 2512 || pCur->DstMac.au8[3] != pEthHdr->DstMac.au8[3] 2513 || pCur->DstMac.au8[4] != pEthHdr->DstMac.au8[4] 2514 || pCur->DstMac.au8[5] != pEthHdr->DstMac.au8[5]) 2515 { 2516 return false; 2517 } 2518 2519 uint16_t Checksum = RTCrc32(pMsg->b_rptr, cbMsg); 2520 if (pCur->Checksum != Checksum) 2521 return false; 2522 2523 /* 2524 * Yes, it really is our own packet. 2525 */ 2526 return true; 2527 } 2528 2529 return false; 2530 } 2531 2532 2533 /** 2306 2534 * Worker for routing messages from the wire or from the host. 2307 2535 * … … 2312 2540 * @param pOrigMsg Pointer to the message. 2313 2541 */ 2314 static int vboxNetFltSolarisRecv(PVBOXNETFLTINS pThis, vboxnetflt_stream_t *pStream, queue_t *pQueue, mblk_t *p OrigMsg)2315 { 2316 LogFlow((DEVICE_NAME ":vboxNetFltSolarisRecv pThis=%p p OrigMsg=%p\n", pThis, pOrigMsg));2542 static int vboxNetFltSolarisRecv(PVBOXNETFLTINS pThis, vboxnetflt_stream_t *pStream, queue_t *pQueue, mblk_t *pMsg) 2543 { 2544 LogFlow((DEVICE_NAME ":vboxNetFltSolarisRecv pThis=%p pMsg=%p\n", pThis, pMsg)); 2317 2545 2318 2546 AssertCompile(sizeof(struct ether_header) == sizeof(RTNETETHERHDR)); 2319 2547 Assert(pStream->Type == kPromiscStream); 2320 2321 mblk_t *pMsg = pOrigMsg;2322 2548 2323 2549 /*
Note:
See TracChangeset
for help on using the changeset viewer.