VirtualBox

Ignore:
Timestamp:
Sep 21, 2008 2:28:03 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
36895
Message:

Solaris/vboxnetflt: Real loopback handling. Disabled.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/VBoxNetFlt/solaris/VBoxNetFlt-solaris.c

    r12618 r12619  
    2929#include <iprt/thread.h>
    3030#include <iprt/spinlock.h>
     31#include <iprt/crc32.h>
    3132
    3233#include <inet/ip.h>
     
    8384#define VBOXNETFLT_IFNAME_LEN           LIFNAMSIZ + 1
    8485
     86/** Maximum loopback packet queue size per interface */
     87#define VBOXNETFLT_LOOPBACK_SIZE        64
    8588
    8689/*******************************************************************************
     
    279282
    280283/**
     284 * loopback packet identifier
     285 */
     286typedef struct VBOXNETFLTPACKETID
     287{
     288    struct VBOXNETFLTPACKETID *pNext;
     289    uint16_t cbPacket;
     290    uint16_t Checksum;
     291    RTMAC SrcMac;
     292    RTMAC DstMac;
     293} VBOXNETFLTPACKETID;
     294typedef struct VBOXNETFLTPACKETID *PVBOXNETFLTPACKETID;
     295
     296
     297/**
    281298 * vboxnetflt_stream_t: per-stream data (multiple streams per interface)
    282299 */
     
    299316    bool fRawMode;                        /* whether raw mode request was successful */
    300317    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 */
    302321} vboxnetflt_promisc_stream_t;
    303322
     
    331350static int vboxNetFltSolarisUnitDataToRaw(PVBOXNETFLTINS pThis, mblk_t *pMsg, mblk_t **ppRawMsg);
    332351static int vboxNetFltSolarisRawToUnitData(mblk_t *pMsg, mblk_t **ppDlpiMsg);
     352
     353static inline void vboxNetFltSolarisInitPacketId(PVBOXNETFLTPACKETID pTag, mblk_t *pMsg);
     354static int vboxNetFltSolarisQueueLoopback(PVBOXNETFLTINS pThis, vboxnetflt_promisc_stream_t *pPromiscStream, mblk_t *pMsg);
     355static bool vboxNetFltSolarisIsOurMBlk(PVBOXNETFLTINS pThis, vboxnetflt_promisc_stream_t *pPromiscStream, mblk_t *pMsg);
    333356
    334357static mblk_t *vboxNetFltSolarisMBlkFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst);
     
    640663    if (pState->CurType == kPromiscStream)
    641664    {
    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));
    643669        if (RT_UNLIKELY(!pPromiscStream))
    644670        {
     
    652678        pPromiscStream->fRawMode = false;
    653679        pPromiscStream->ModeReqId = 0;
    654         bzero(pPromiscStream->aLoopback, sizeof(pPromiscStream->aLoopback));
    655680        pStream = (vboxnetflt_stream_t *)pPromiscStream;
    656681    }
     
    17401765
    17411766/**
    1742  * De-activates the dedicated promiscuous stream.
     1767 * Closes the interface, thereby closing the dedicated stream.
     1768 *
     1769 * @param   pThis       The instance.
    17431770 */
    17441771static void vboxNetFltSolarisCloseStream(PVBOXNETFLTINS pThis)
    17451772{
     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);
    17461793    ldi_close(pThis->u.s.hIface, FREAD | FWRITE, kcred);
    17471794}
     
    23042351
    23052352/**
     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 */
     2359static 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 */
     2381static 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 */
     2477static 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/**
    23062534 * Worker for routing messages from the wire or from the host.
    23072535 *
     
    23122540 * @param   pOrigMsg    Pointer to the message.
    23132541 */
    2314 static int vboxNetFltSolarisRecv(PVBOXNETFLTINS pThis, vboxnetflt_stream_t *pStream, queue_t *pQueue, mblk_t *pOrigMsg)
    2315 {
    2316     LogFlow((DEVICE_NAME ":vboxNetFltSolarisRecv pThis=%p pOrigMsg=%p\n", pThis, pOrigMsg));
     2542static 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));
    23172545
    23182546    AssertCompile(sizeof(struct ether_header) == sizeof(RTNETETHERHDR));
    23192547    Assert(pStream->Type == kPromiscStream);
    2320 
    2321     mblk_t *pMsg = pOrigMsg;
    23222548
    23232549    /*
Note: See TracChangeset for help on using the changeset viewer.

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