VirtualBox

Ignore:
Timestamp:
Jul 17, 2008 10:42:30 PM (16 years ago)
Author:
vboxsync
Message:

intnet: Converted the internal frame handling to use the scatter/gatter list created for the trunk port (INTNETSG). Implemented the trunk receive path.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp

    r10711 r10733  
    110110    /** Whether to supply physical addresses with the outbound SGs. */
    111111    bool volatile           fPhysSG;
     112    /** Set if the 'wire' is in promiscuous mode.
     113     * The state of the 'host' is queried each time. */
     114    bool                    fPromiscuousWire;
    112115} INTNETTRUNKIF;
    113116/** Pointer to a trunk interface. */
     
    388391
    389392
     393/**
     394 * Initializes a scatter / gather buffer from a simple linear buffer.
     395 *
     396 * @returns Pointer to the start of the frame.
     397 * @param   pSG         Pointer to the scatter / gather structure.
     398 *                      (The pvOwnerData, fFlags, cUsers, and cSegsAlloc members are left untouched.)
     399 * @param   pvFrame     Pointer to the frame
     400 * @param   cbFrame     The size of the frame.
     401 */
     402DECLINLINE(void) intnetR0SgInitTemp(PINTNETSG pSG, void *pvFrame, uint32_t cbFrame)
     403{
     404    pSG->pvOwnerData = NULL;
     405    pSG->pvUserData = NULL;
     406    pSG->pvUserData2 = NULL;
     407    pSG->cbTotal = cbFrame;
     408    pSG->cUsers = 1;
     409    pSG->fFlags = INTNETSG_FLAGS_TEMP;
     410    pSG->cSegsAlloc = 1;
     411    pSG->cSegsUsed = 1;
     412    pSG->aSegs[0].Phys = NIL_RTHCPHYS;
     413    pSG->aSegs[0].pv = pvFrame;
     414    pSG->aSegs[0].cb = cbFrame;
     415}
     416
     417
     418/**
     419 * Initializes a scatter / gather buffer from a internal networking packet.
     420 *
     421 * @returns Pointer to the start of the frame.
     422 * @param   pSG         Pointer to the scatter / gather structure.
     423 *                      (The pvOwnerData, fFlags, cUsers, and cSegsAlloc members are left untouched.)
     424 * @param   pHdr        Pointer to the packet header.
     425 * @param   pBuf        The buffer the header is within. Only used in strict builds.
     426 */
     427DECLINLINE(void) intnetR0SgInitFromPkt(PINTNETSG pSG, PCINTNETHDR pPktHdr, PCINTNETBUF pBuf)
     428{
     429    pSG->cSegsUsed = 1;
     430    pSG->cbTotal = pSG->aSegs[0].cb = pPktHdr->cbFrame;
     431    pSG->aSegs[0].pv = INTNETHdrGetFramePtr(pPktHdr, pBuf);
     432    pSG->aSegs[0].Phys = NIL_RTHCPHYS;
     433}
     434
     435
    390436#ifdef IN_INTNET_TESTCASE
    391437/**
     
    423469
    424470/**
     471 * Reads an entire SG into a fittingly size buffer.
     472 *
     473 * @param   pSG         The SG list to read.
     474 * @param   pvBuf       The buffer to read into (at least pSG->cbTotal in size).
     475 */
     476DECLINLINE(void) intnetR0SgRead(PCINTNETSG pSG, void *pvBuf)
     477{
     478    if (pSG->cSegsUsed == 1)
     479    {
     480        Assert(pSG->cbTotal == pSG->aSegs[0].cb);
     481        memcpy(pvBuf, pSG->aSegs[0].pv, pSG->cbTotal);
     482    }
     483    else
     484    {
     485        uint8_t       *pbDst = (uint8_t *)pvBuf;
     486        unsigned const cSegs = pSG->cSegsUsed; Assert(cSegs == pSG->cSegsUsed);
     487        for (unsigned iSeg = 0; iSeg < cSegs; iSeg++)
     488        {
     489            uint32_t cbSeg = pSG->aSegs[iSeg].cb;
     490            Assert(cbSeg <= pSG->cbTotal && (uintptr_t)(pbDst - (uint8_t *)pvBuf) + cbSeg <= pSG->cbTotal);
     491            memcpy(pbDst, pSG->aSegs[iSeg].pv, cbSeg);
     492            pbDst += cbSeg;
     493        }
     494    }
     495}
     496
     497
     498/**
    425499 * Writes a frame packet to the buffer.
    426500 *
     
    428502 * @param   pBuf        The buffer.
    429503 * @param   pRingBuf    The ring buffer to read from.
    430  * @param   pvFrame     The frame to write.
    431  * @param   cbFrame     The size of the frame.
    432  */
    433 static int intnetR0RingWriteFrame(PINTNETBUF pBuf, PINTNETRINGBUF pRingBuf, const void *pvFrame, uint32_t cbFrame)
     504 * @param   pSG         The gatter list.
     505 */
     506static int intnetR0RingWriteFrame(PINTNETBUF pBuf, PINTNETRINGBUF pRingBuf, PCINTNETSG pSG)
    434507{
    435508    /*
    436509     * Validate input.
    437510     */
    438     Assert(pBuf);
    439     Assert(pRingBuf);
    440     Assert(pvFrame);
    441     Assert(cbFrame >= sizeof(PDMMAC) * 2);
     511    AssertPtr(pBuf);
     512    AssertPtr(pRingBuf);
     513    AssertPtr(pSG);
     514    Assert(pSG->cbTotal >= sizeof(PDMMAC) * 2);
    442515    uint32_t offWrite = pRingBuf->offWrite;
    443516    Assert(offWrite == RT_ALIGN_32(offWrite, sizeof(INTNETHDR)));
     
    445518    Assert(offRead == RT_ALIGN_32(offRead, sizeof(INTNETHDR)));
    446519
    447     const uint32_t cb = RT_ALIGN_32(cbFrame, sizeof(INTNETHDR));
     520    const uint32_t cb = RT_ALIGN_32(pSG->cbTotal, sizeof(INTNETHDR));
    448521    if (offRead <= offWrite)
    449522    {
     
    455528            PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pBuf + offWrite);
    456529            pHdr->u16Type  = INTNETHDR_TYPE_FRAME;
    457             pHdr->cbFrame  = cbFrame;
     530            pHdr->cbFrame  = pSG->cbTotal;
    458531            pHdr->offFrame = sizeof(INTNETHDR);
    459532
    460             memcpy(pHdr + 1, pvFrame, cbFrame);
     533            intnetR0SgRead(pSG, pHdr + 1);
    461534
    462535            offWrite += cb + sizeof(INTNETHDR);
     
    479552            void       *pvFrameOut = (PINTNETHDR)((uint8_t *)pBuf + pRingBuf->offStart);
    480553            pHdr->u16Type  = INTNETHDR_TYPE_FRAME;
    481             pHdr->cbFrame  = cbFrame;
     554            pHdr->cbFrame  = pSG->cbTotal;
    482555            pHdr->offFrame = (intptr_t)pvFrameOut - (intptr_t)pHdr;
    483556
    484             memcpy(pvFrameOut, pvFrame, cbFrame);
     557            intnetR0SgRead(pSG, pvFrameOut);
    485558
    486559            offWrite = pRingBuf->offStart + cb;
     
    497570        PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pBuf + offWrite);
    498571        pHdr->u16Type  = INTNETHDR_TYPE_FRAME;
    499         pHdr->cbFrame  = cbFrame;
     572        pHdr->cbFrame  = pSG->cbTotal;
    500573        pHdr->offFrame = sizeof(INTNETHDR);
    501574
    502         memcpy(pHdr + 1, pvFrame, cbFrame);
     575        intnetR0SgRead(pSG, pHdr + 1);
    503576
    504577        offWrite += cb + sizeof(INTNETHDR);
     
    525598#pragma pack()
    526599typedef INTNETETHERHDR *PINTNETETHERHDR;
     600typedef INTNETETHERHDR const *PCINTNETETHERHDR;
    527601
    528602
     
    531605 *
    532606 * @param   pIf         The interface.
    533  * @param   pvFrame     The frame data.
    534  * @param   cbFrame     The size of the frame.
    535  */
    536 static void intnetR0IfSend(PINTNETIF pIf, const void *pvFrame, unsigned cbFrame)
     607 * @param   pSG         The gather buffer which data is being sent to the interface.
     608 */
     609static void intnetR0IfSend(PINTNETIF pIf, PINTNETSG pSG)
    537610{
    538611    LogFlow(("intnetR0IfSend: pIf=%p:{.hIf=%RX32}\n", pIf, pIf->hIf));
    539     int rc = intnetR0RingWriteFrame(pIf->pIntBuf, &pIf->pIntBuf->Recv, pvFrame, cbFrame);
     612    int rc = intnetR0RingWriteFrame(pIf->pIntBuf, &pIf->pIntBuf->Recv, pSG);
    540613    if (RT_SUCCESS(rc))
    541614    {
    542615        pIf->cYields = 0;
    543616        STAM_REL_COUNTER_INC(&pIf->pIntBuf->cStatRecvs);
    544         STAM_REL_COUNTER_ADD(&pIf->pIntBuf->cbStatRecv, cbFrame);
     617        STAM_REL_COUNTER_ADD(&pIf->pIntBuf->cbStatRecv, pSG->cbTotal);
    545618        RTSemEventSignal(pIf->Event);
    546619        return;
    547620    }
    548621
     622/** @todo we'll have to drop this I'm afraid since it'll screw up the host networking otherwise... */
    549623    /*
    550624     * Retry a few times, yielding the CPU in between.
     
    558632            RTSemEventSignal(pIf->Event);
    559633            RTThreadYield();
    560             rc = intnetR0RingWriteFrame(pIf->pIntBuf, &pIf->pIntBuf->Recv, pvFrame, cbFrame);
     634            rc = intnetR0RingWriteFrame(pIf->pIntBuf, &pIf->pIntBuf->Recv, pSG);
    561635            if (RT_SUCCESS(rc))
    562636            {
    563637                STAM_REL_COUNTER_INC(&pIf->pIntBuf->cStatYieldsOk);
    564638                STAM_REL_COUNTER_INC(&pIf->pIntBuf->cStatRecvs);
    565                 STAM_REL_COUNTER_ADD(&pIf->pIntBuf->cbStatRecv, cbFrame);
     639                STAM_REL_COUNTER_ADD(&pIf->pIntBuf->cbStatRecv, pSG->cbTotal);
    566640                RTSemEventSignal(pIf->Event);
    567641                return;
     
    579653
    580654/**
     655 * Sends a frame down the trunk.
     656 *
     657 * The caller must own the network mutex, might be abandond temporarily.
     658 * The fTrunkLock parameter indicates whether the trunk lock is held.
     659 *
     660 * @param   pThis           The trunk.
     661 * @param   pNetwork        The network the frame is being sent to.
     662 * @param   fDst            The destination flags.
     663 * @param   pSG             Pointer to the gather list.
     664 * @param   fTrunkLocked    Whether the caller owns the out-bound trunk lock.
     665 */
     666static void intnetR0TrunkIfSend(PINTNETTRUNKIF pThis, PINTNETNETWORK pNetwork, uint32_t fDst, PINTNETSG pSG, bool fTrunkLocked)
     667{
     668    Assert(fTrunkLocked);
     669    /** @todo implement + move?  */
     670}
     671
     672
     673/**
     674 * Sends a broadcast frame.
     675 *
     676 * The caller must own the network mutex, might be abandond temporarily.
     677 * When pIfSender is not NULL, the caller must also own the trunk semaphore.
     678 *
     679 * @returns true if it's addressed to someone on the network, otherwise false.
     680 * @param   pNetwork        The network the frame is being sent to.
     681 * @param   pIfSender       The interface sending the frame. This is NULL if it's the trunk.
     682 * @param   fSrc            The source flags. This 0 if it's not from the trunk.
     683 * @param   pSG             Pointer to the gather list.
     684 * @param   fTrunkLocked    Whether the caller owns the out-bound trunk lock.
     685 */
     686static bool intnetR0NetworkSendBroadcast(PINTNETNETWORK pNetwork, PINTNETIF pIfSender, PINTNETSG pSG, bool fTrunkLocked)
     687{
     688    /*
     689     * This is a broadcast or multicast address. For the present we treat those
     690     * two as the same - investigating multicast is left for later.
     691     *
     692     * Write the packet to all the interfaces and signal them.
     693     */
     694    Log2(("Broadcast\n"));
     695    for (PINTNETIF pIf = pNetwork->pIFs; pIf; pIf = pIf->pNext)
     696        if (pIf != pIfSender)
     697            intnetR0IfSend(pIf, pSG);
     698
     699    /*
     700     * Unless the trunk is the origin, broadcast it to both the wire
     701     * and the host as well.
     702     */
     703    PINTNETTRUNKIF pTrunkIf = pNetwork->pTrunkIF;
     704    if (    pIfSender
     705        &&  pTrunkIf)
     706        intnetR0TrunkIfSend(pTrunkIf, pNetwork, INTNETTRUNKDIR_HOST | INTNETTRUNKDIR_WIRE, pSG, fTrunkLocked);
     707    return false; /* broadcast frames are never dropped */
     708}
     709
     710
     711/**
     712 * Sends a multicast frame.
     713 *
     714 * The caller must own the network mutex, might be abandond temporarily.
     715 *
     716 * @returns true if it's addressed to someone on the network, otherwise false.
     717 * @param   pNetwork        The network the frame is being sent to.
     718 * @param   pIfSender       The interface sending the frame. This is NULL if it's the trunk.
     719 * @param   fSrc            The source flags. This 0 if it's not from the trunk.
     720 * @param   pSG             Pointer to the gather list.
     721 * @param   fTrunkLocked    Whether the caller owns the out-bound trunk lock.
     722 * @param   pEthHdr         Pointer to the ethernet header.
     723 */
     724static bool intnetR0NetworkSendMulticast(PINTNETNETWORK pNetwork, PINTNETIF pIfSender, uint32_t fSrc, PINTNETSG pSG, bool fTrunkLocked, PCINTNETETHERHDR pEthHdr)
     725{
     726    /** @todo implement multicast */
     727    return intnetR0NetworkSendBroadcast(pNetwork, pIfSender, pSG, fTrunkLocked);
     728}
     729
     730
     731/**
     732 * Sends a unicast frame.
     733 *
     734 * The caller must own the network mutex, might be abandond temporarily.
     735 *
     736 * @returns true if it's addressed to someone on the network, otherwise false.
     737 * @param   pNetwork        The network the frame is being sent to.
     738 * @param   pIfSender       The interface sending the frame. This is NULL if it's the trunk.
     739 * @param   fSrc            The source flags. This 0 if it's not from the trunk.
     740 * @param   pSG             Pointer to the gather list.
     741 * @param   fTrunkLocked    Whether the caller owns the out-bound trunk lock.
     742 * @param   pEthHdr         Pointer to the ethernet header.
     743 */
     744static bool intnetR0NetworkSendUnicast(PINTNETNETWORK pNetwork, PINTNETIF pIfSender, uint32_t fSrc, PINTNETSG pSG, bool fTrunkLocked, PCINTNETETHERHDR pEthHdr)
     745{
     746    /*
     747     * Only send to the interfaces with matching a MAC address.
     748     */
     749    Log2(("Dst=%.6Rhxs\n", &pEthHdr->MacDst));
     750    bool fExactIntNetRecipient = false;
     751    for (PINTNETIF pIf = pNetwork->pIFs; pIf; pIf = pIf->pNext)
     752    {
     753        Log2(("Dst=%.6Rhxs ?==? %.6Rhxs\n", &pEthHdr->MacDst, &pIf->Mac));
     754        bool fIt = false;
     755        if (    (   !pIf->fMacSet
     756                 || (fIt = !memcmp(&pIf->Mac, &pEthHdr->MacDst, sizeof(pIf->Mac))) )
     757            ||  (   pIf->fPromiscuous
     758                 && !(pNetwork->fFlags & (INTNET_OPEN_FLAGS_IGNORE_PROMISC | INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC))
     759                 && pIf != pIfSender /* promiscuous mode: omit the sender */))
     760        {
     761            fExactIntNetRecipient |= fIt;
     762            intnetR0IfSend(pIf, pSG);
     763        }
     764    }
     765
     766    /*
     767     * Send it to the trunk? Only consider this if we didn't find an recipient
     768     * or if the trunk is in some form or promiscuous mode.
     769     */
     770    PINTNETTRUNKIF pTrunkIf = pNetwork->pTrunkIF;
     771    if (    pIfSender
     772        &&  pTrunkIf
     773        &&  pTrunkIf->pIfPort)
     774    {
     775        uint32_t fDst = 0;
     776        if (    pTrunkIf->fPromiscuousWire
     777            &&  !(pNetwork->fFlags & (INTNET_OPEN_FLAGS_IGNORE_PROMISC | INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC | INTNET_OPEN_FLAGS_IGNORE_PROMISC_TRUNK_WIRE | INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC_TRUNK_WIRE)) )
     778            fDst |= INTNETTRUNKDIR_WIRE;
     779        if (    !(pNetwork->fFlags & (INTNET_OPEN_FLAGS_IGNORE_PROMISC | INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC | INTNET_OPEN_FLAGS_IGNORE_PROMISC_TRUNK_HOST | INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC_TRUNK_HOST))
     780            ||  pTrunkIf->pIfPort->pfnIsPromiscuous(pTrunkIf->pIfPort) )
     781            fDst |= INTNETTRUNKDIR_HOST;
     782        else if (   !fExactIntNetRecipient      /* if you have duplicate mac addresses, you're screwed. */
     783                 && pTrunkIf->pIfPort->pfnIsHostMac(pTrunkIf->pIfPort, &pEthHdr->MacDst))
     784            fDst |= INTNETTRUNKDIR_HOST;
     785        if (fDst)
     786            intnetR0TrunkIfSend(pTrunkIf, pNetwork, fDst, pSG, fTrunkLocked);
     787    }
     788
     789    return fExactIntNetRecipient;
     790}
     791
     792
     793/**
    581794 * Sends a frame.
    582795 *
     
    586799 * The caller must own the network mutex.
    587800 *
    588  * @param   pNetwork    The network the frame is being sent to.
    589  * @param   pIfSender   The interface sending the frame.
    590  * @param   pvFrame     The frame data.
    591  * @param   cbFrame     The size of the frame.
    592  */
    593 static void intnetR0NetworkSend(PINTNETNETWORK pNetwork, PINTNETIF pIfSender, const void *pvFrame, unsigned cbFrame)
    594 {
     801 * @returns true if it's addressed to someone on the network, otherwise false.
     802 * @param   pNetwork        The network the frame is being sent to.
     803 * @param   pIfSender       The interface sending the frame. This is NULL if it's the trunk.
     804 * @param   fSrc            The source flags. This 0 if it's not from the trunk.
     805 * @param   pSG             Pointer to the gather list.
     806 * @param   fTrunkLocked    Whether the caller owns the out-bound trunk lock.
     807 */
     808static bool intnetR0NetworkSend(PINTNETNETWORK pNetwork, PINTNETIF pIfSender, uint32_t fSrc, PINTNETSG pSG, bool fTrunkLocked)
     809{
     810    bool fRc = false;
     811
    595812    /*
    596813     * Assert reality.
    597814     */
    598     Assert(pNetwork);
    599     Assert(pIfSender);
     815    AssertPtr(pNetwork);
     816    AssertPtrNull(pIfSender);
     817    Assert(pIfSender ? fSrc == 0 : fSrc != 0);
    600818    Assert(pNetwork == pIfSender->pNetwork);
    601     Assert(pvFrame);
    602     if (cbFrame < sizeof(PDMMAC) * 2)
    603         return;
     819    AssertPtr(pSG);
     820    Assert(pSG->cSegsUsed >= 1);
     821    Assert(pSG->cSegsUsed <= pSG->cSegsAlloc);
     822    if (pSG->cbTotal < sizeof(INTNETETHERHDR))
     823        return fRc;
    604824
    605825    /*
     
    607827     */
    608828    STAM_REL_COUNTER_INC(&pIfSender->pIntBuf->cStatSends);
    609     STAM_REL_COUNTER_ADD(&pIfSender->pIntBuf->cbStatSend, cbFrame);
     829    STAM_REL_COUNTER_ADD(&pIfSender->pIntBuf->cbStatSend, pSG->cbTotal);
     830
     831    /*
     832     * Get the ethernet header (might theoretically involve multiple segments).
     833     */
     834    INTNETETHERHDR EthHdr;
     835    if (RT_LIKELY(pSG->aSegs[0].cb >= sizeof(EthHdr)))
     836        EthHdr = *(PCINTNETETHERHDR)pSG->aSegs[0].pv;
     837    else
     838    {
     839        uint8_t *pbDst = (uint8_t *)&EthHdr;
     840        size_t   cbLeft = sizeof(EthHdr);
     841        for (unsigned iSeg = 0; cbLeft && iSeg < pSG->cSegsUsed; iSeg++)
     842        {
     843            size_t cb = RT_MIN(cbLeft, pSG->aSegs[iSeg].cb);
     844            memcpy(pbDst, pSG->aSegs[iSeg].pv, cb);
     845            pbDst += cb;
     846            cbLeft -= cb;
     847        }
     848        AssertReturn(!cbLeft, false);
     849    }
    610850
    611851    /*
    612852     * Inspect the header updating the mac address of the sender in the process.
    613853     */
    614     PINTNETETHERHDR pEthHdr = (PINTNETETHERHDR)pvFrame;
    615     if (memcmp(&pEthHdr->MacSrc, &pIfSender->Mac, sizeof(pIfSender->Mac)))
     854    if (    pIfSender
     855        &&  memcmp(&EthHdr.MacSrc, &pIfSender->Mac, sizeof(pIfSender->Mac)))
    616856    {
    617857        /** @todo stats */
    618         Log2(("IF MAC: %.6Rhxs -> %.6Rhxs\n", &pIfSender->Mac, &pEthHdr->MacSrc));
    619         pIfSender->Mac = pEthHdr->MacSrc;
     858        Log2(("IF MAC: %.6Rhxs -> %.6Rhxs\n", &pIfSender->Mac, &EthHdr.MacSrc));
     859        pIfSender->Mac = EthHdr.MacSrc;
    620860        pIfSender->fMacSet = true;
    621861    }
    622862
    623     if (    (pEthHdr->MacDst.au8[0] & 1) /* multicast address */
    624         ||  (   pEthHdr->MacDst.au16[0] == 0xffff /* broadcast address. s*/
    625              && pEthHdr->MacDst.au16[1] == 0xffff
    626              && pEthHdr->MacDst.au16[2] == 0xffff)
    627         )
    628     {
    629         /*
    630          * This is a broadcast or multicast address. For the present we treat those
    631          * two as the same - investigating multicast is left for later.
    632          *
    633          * Write the packet to all the interfaces and signal them.
    634          */
    635         Log2(("Broadcast\n"));
    636         for (PINTNETIF pIf = pNetwork->pIFs; pIf; pIf = pIf->pNext)
    637             if (pIf != pIfSender)
    638                 intnetR0IfSend(pIf, pvFrame, cbFrame);
    639     }
     863    /*
     864     * Distribute the frame.
     865     */
     866    if (RT_UNLIKELY(EthHdr.MacDst.au8[0] & 1))      /* multicast address */
     867        fRc = intnetR0NetworkSendMulticast(pNetwork, pIfSender, fSrc, pSG, fTrunkLocked, &EthHdr);
     868    else if (   EthHdr.MacDst.au16[0] == 0xffff     /* broadcast address. */
     869             && EthHdr.MacDst.au16[1] == 0xffff
     870             && EthHdr.MacDst.au16[2] == 0xffff)
     871        fRc = intnetR0NetworkSendBroadcast(pNetwork, pIfSender, pSG, fTrunkLocked);
    640872    else
    641     {
    642         /*
    643          * Only send to the interfaces with matching a MAC address.
    644          */
    645         Log2(("Dst=%.6Rhxs\n", &pEthHdr->MacDst));
    646         for (PINTNETIF pIf = pNetwork->pIFs; pIf; pIf = pIf->pNext)
    647         {
    648             Log2(("Dst=%.6Rhxs ?==? %.6Rhxs\n", &pEthHdr->MacDst, &pIf->Mac));
    649             if (    (   !pIf->fMacSet
    650                      || !memcmp(&pIf->Mac, &pEthHdr->MacDst, sizeof(pIf->Mac)))
    651                 ||  (   pIf->fPromiscuous
    652                      && pIf != pIfSender /* promiscuous mode: omit the sender */))
    653                 intnetR0IfSend(pIf, pvFrame, cbFrame);
    654         }
    655     }
     873        fRc = intnetR0NetworkSendUnicast(pNetwork, pIfSender, fSrc, pSG, fTrunkLocked, &EthHdr);
     874    return fRc;
    656875}
    657876
     
    668887 * @param   pIntNet     The instance data.
    669888 * @param   hIf         The interface handle.
    670  * @param   pvFrame     Pointer to the frame.
    671  * @param   cbFrame     Size of the frame.
     889 * @param   pvFrame     Pointer to the frame. Optional, please don't use.
     890 * @param   cbFrame     Size of the frame. Optional, please don't use.
    672891 */
    673892INTNETR0DECL(int) INTNETR0IfSend(PINTNET pIntNet, INTNETIFHANDLE hIf, const void *pvFrame, unsigned cbFrame)
     
    676895
    677896    /*
    678      * Validate input.
    679      */
     897     * Validate input and translate the handle.
     898     */
     899    /** @todo add an exctra reference to the interface! */
    680900    AssertReturn(pIntNet, VERR_INVALID_PARAMETER);
    681901    PINTNETIF pIf = intnetR0Handle2IFPtr(&pIntNet->IfHandles, hIf);
     
    692912    }
    693913
    694     int rc = RTSemFastMutexRequest(pIf->pNetwork->FastMutex);
     914    /*
     915     * Lock the network. If there is a trunk retain it and grab its
     916     * out-bound lock (this requires leaving the network lock first).
     917     * Grabbing the out-bound lock here simplifies things quite a bit
     918     * later on, so while this is excessive and a bit expensive it's
     919     * not worth caring about right now.
     920     */
     921    PINTNETNETWORK pNetwork = pIf->pNetwork;
     922    int rc = RTSemFastMutexRequest(pNetwork->FastMutex);
    695923    if (RT_FAILURE(rc))
    696924        return rc;
     925    PINTNETTRUNKIF pTrunkIf = intnetR0TrunkIfRetain(pNetwork->pTrunkIF);
     926    if (pTrunkIf)
     927    {
     928        RTSemFastMutexRelease(pIf->pNetwork->FastMutex);
     929
     930        if (!intnetR0TrunkIfOutLock(pTrunkIf))
     931        {
     932            intnetR0TrunkIfRelease(pTrunkIf);
     933            return VERR_SEM_DESTROYED;
     934        }
     935
     936        rc = RTSemFastMutexRequest(pNetwork->FastMutex);
     937        if (RT_FAILURE(rc))
     938        {
     939            intnetR0TrunkIfOutUnlock(pTrunkIf);
     940            intnetR0TrunkIfRelease(pTrunkIf);
     941            return rc;
     942        }
     943    }
     944
     945    INTNETSG Sg; /** @todo this will have to be changed if we're going to use async sending
     946                  * with buffer sharing for some OS or service. Darwin copies everything so
     947                  * I won't bother allocating and managing SGs rigth now. Sorry. */
    697948
    698949    /*
     
    700951     */
    701952    if (pvFrame && cbFrame)
    702         intnetR0NetworkSend(pIf->pNetwork, pIf, pvFrame, cbFrame);
     953    {
     954        intnetR0SgInitTemp(&Sg, (void *)pvFrame, cbFrame);
     955        intnetR0NetworkSend(pIf->pNetwork, pIf, 0, &Sg, !!pTrunkIf);
     956    }
    703957
    704958    /*
     
    713967            void *pvCurFrame = INTNETHdrGetFramePtr(pHdr, pIf->pIntBuf);
    714968            if (pvCurFrame)
    715                 intnetR0NetworkSend(pIf->pNetwork, pIf, pvCurFrame, pHdr->cbFrame);
     969            {
     970                intnetR0SgInitTemp(&Sg, pvCurFrame, pHdr->cbFrame);
     971                intnetR0NetworkSend(pIf->pNetwork, pIf, 0, &Sg, !!pTrunkIf);
     972            }
    716973        }
    717974        /* else: ignore the frame */
     
    721978    }
    722979
    723     return RTSemFastMutexRelease(pIf->pNetwork->FastMutex);
     980    /*
     981     * Release the semaphore(s) and release references.
     982     */
     983    rc = RTSemFastMutexRelease(pIf->pNetwork->FastMutex);
     984    if (pTrunkIf)
     985    {
     986        intnetR0TrunkIfOutUnlock(pTrunkIf);
     987        intnetR0TrunkIfRelease(pTrunkIf);
     988    }
     989
     990    return rc;
    724991}
    725992
     
    14201687
    14211688    /*
    1422      *
    1423      */
    1424 
    1425 
    1426     return false;
     1689     * Lock the network and send the frame to it.
     1690     */
     1691    int rc = RTSemFastMutexRequest(pNetwork->FastMutex);
     1692    AssertRCReturn(rc, false);
     1693
     1694    bool fRc;
     1695    if (RT_LIKELY(pNetwork->cActiveIFs > 0))
     1696        fRc = intnetR0NetworkSend(pNetwork, NULL, fSrc, pSG, false /* fTrunkLocked */);
     1697    else
     1698        fRc = false; /* don't drop it */
     1699
     1700    rc = RTSemFastMutexRelease(pNetwork->FastMutex);
     1701    AssertRC(rc);
     1702
     1703    return fRc;
    14271704}
    14281705
     
    14701747 * Retain the trunk interface.
    14711748 *
    1472  * @returns pThis.
     1749 * @returns pThis if retained.
    14731750 *
    14741751 * @param   pThis       The trunk.
     
    14791756{
    14801757    if (pThis && pThis->pIfPort)
     1758    {
    14811759        pThis->pIfPort->pfnRetain(pThis->pIfPort);
    1482     return pThis;
     1760        return pThis;
     1761    }
     1762    return NULL;
    14831763}
    14841764
     
    16811961    pTrunkIF->pNetwork = pNetwork;
    16821962    //pTrunkIF->fPhysSG = false;
     1963    //pTrunkIF->fPromiscuousWire = false;
    16831964    int rc = RTSemFastMutexCreate(&pTrunkIF->FastMutex);
    16841965    if (RT_SUCCESS(rc))
     
    18402121    Assert(enmTrunkType > kIntNetTrunkType_Invalid && enmTrunkType < kIntNetTrunkType_End);
    18412122    AssertPtr(pszTrunk);
    1842     Assert(!(fFlags & ~(INTNET_OPEN_FLAGS_PUBLIC)));
     2123    Assert(!(fFlags & ~(INTNET_OPEN_FLAGS_MASK)));
    18432124    AssertPtr(ppNetwork);
    18442125    *ppNetwork = NULL;
     
    18662147                     && !strcmp(pCur->szTrunk, pszTrunk)))
    18672148            {
    1868                 if (!((pCur->fFlags ^ fFlags) & (INTNET_OPEN_FLAGS_PUBLIC)))
     2149                if (!((pCur->fFlags ^ fFlags) & INTNET_OPEN_FLAGS_SECURITY_XOR_MASK))
    18692150                {
    18702151
     
    18792160                            rc = SUPR0ObjVerifyAccess(pCur->pvObj, pSession, pCur->szName);
    18802161                        if (RT_SUCCESS(rc))
     2162                        {
     2163                            pCur->fFlags |= fFlags & INTNET_OPEN_FLAGS_SECURITY_OR_MASK;
     2164
    18812165                            *ppNetwork = pCur;
     2166                        }
    18822167                        else
    18832168                            SUPR0ObjRelease(pCur->pvObj, pSession);
     
    19322217    Assert(enmTrunkType > kIntNetTrunkType_Invalid && enmTrunkType < kIntNetTrunkType_End);
    19332218    AssertPtr(pszTrunk);
    1934     Assert(!(fFlags & ~(INTNET_OPEN_FLAGS_PUBLIC)));
     2219    Assert(!(fFlags & ~INTNET_OPEN_FLAGS_MASK));
    19352220    AssertPtr(ppNetwork);
    19362221    *ppNetwork = NULL;
     
    20682353    }
    20692354
    2070     AssertMsgReturn(!(fFlags & ~(INTNET_OPEN_FLAGS_PUBLIC)), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
     2355    AssertMsgReturn(!(fFlags & ~INTNET_OPEN_FLAGS_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
    20712356    AssertPtrReturn(phIf, VERR_INVALID_PARAMETER);
    20722357
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