VirtualBox

Changeset 39317 in vbox for trunk/src/VBox/Devices/Network


Ignore:
Timestamp:
Nov 15, 2011 8:33:56 PM (13 years ago)
Author:
vboxsync
Message:

e1000: VLAN tag offloading (#4806)

File:
1 edited

Legend:

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

    r39248 r39317  
    1111 *
    1212 * @todo IPv6 checksum offloading support
    13  * @todo VLAN checksum offloading support
    1413 * @todo Flexible Filter / Wakeup (optional?)
    1514 */
     
    227226#define RCTL_BSIZE_SHIFT 16
    228227#define RCTL_VFE         0x00040000
     228#define RCTL_CFIEN       0x00080000
     229#define RCTL_CFI         0x00100000
    229230#define RCTL_BSEX        0x02000000
    230231#define RCTL_SECRC       0x04000000
     
    611612
    612613
     614#define E1K_SPEC_VLAN(s)    (s      & 0xFFF)
     615#define E1K_SPEC_CFI(s) (!!((s>>12) & 0x1))
     616#define E1K_SPEC_PRI(s)    ((s>>13) & 0x7)
     617
    613618struct E1kRxDStatus
    614619{
     
    635640    /** @name Descriptor Special field (3.2.3.3)
    636641     * @{  */
    637     unsigned u12VLAN : 12;                            /**< VLAN identifier. */
    638     unsigned fCFI    : 1;             /**< Canonical form indicator (VLAN). */
    639     unsigned u3PRI   : 3;                        /**< User priority (VLAN). */
     642    unsigned u16Special : 16;      /**< VLAN: Id, Canonical form, Priority. */
    640643    /** @} */
    641644};
     
    685688        unsigned u8CSS     : 8;
    686689        /* Special field*/
    687         unsigned u12VLAN   : 12;
    688         unsigned fCFI      : 1;
    689         unsigned u3PRI     : 3;
     690        unsigned u16Special: 16;
    690691    } dw3;
    691692};
     
    801802         * Requires fEOP, fVLE and CTRL.VME to be set.
    802803         * @{ */
    803         unsigned u12VLAN   : 12;                      /**< VLAN identifier. */
    804         unsigned fCFI      : 1;       /**< Canonical form indicator (VLAN). */
    805         unsigned u3PRI     : 3;                  /**< User priority (VLAN). */
     804        unsigned u16Special: 16;   /**< VLAN: Id, Canonical form, Priority. */
    806805        /** @}  */
    807806    } dw3;
     
    888887
    889888/** The current Saved state version. */
    890 #define E1K_SAVEDSTATE_VERSION          2
     889#define E1K_SAVEDSTATE_VERSION          3
     890/** Saved state version for VirtualBox 4.1 and earlier.
     891 * These did not include VLAN tag fields.  */
     892#define E1K_SAVEDSTATE_VERSION_VBOX_41  2
    891893/** Saved state version for VirtualBox 3.0 and earlier.
    892894 * This did not include the configuration part nor the E1kEEPROM.  */
     
    10281030    /** TX: TCP/UDP checksum has to be inserted if true. */
    10291031    bool        fTCPcsum;
     1032    /** TX: VLAN tag has to be inserted if true. */
     1033    bool        fVTag;
     1034    /** TX: TCI part of VLAN tag to be inserted. */
     1035    uint16_t    u16VTagTCI;
    10301036    /** TX TSE fallback: Number of payload bytes remaining in TSE context. */
    10311037    uint32_t    u32PayRemain;
     
    10381044    /** ?: Emulated controller type. */
    10391045    E1KCHIP     eChip;
    1040     uint32_t    alignmentFix;
    10411046
    10421047    /** EMT: EEPROM emulation */
     
    16401645             pDesc->status.fTCPE ? "TCPE" : "tcpe",
    16411646             pDesc->status.fCE ? "CE" : "ce",
    1642              pDesc->status.fCFI ? "CFI" :"cfi",
    1643              pDesc->status.u12VLAN,
    1644              pDesc->status.u3PRI));
     1647             E1K_SPEC_CFI(pDesc->status.u16Special) ? "CFI" :"cfi",
     1648             E1K_SPEC_VLAN(pDesc->status.u16Special),
     1649             E1K_SPEC_PRI(pDesc->status.u16Special)));
    16451650}
    16461651
     
    16921697                    pDesc->data.dw3.fTXSM? " TXSM":"",
    16931698                    pDesc->data.dw3.fIXSM? " IXSM":"",
    1694                     pDesc->data.dw3.fCFI ? " CFI" :"",
    1695                     pDesc->data.dw3.u12VLAN,
    1696                     pDesc->data.dw3.u3PRI));
     1699                    E1K_SPEC_CFI(pDesc->data.dw3.u16Special) ? "CFI" :"cfi",
     1700                    E1K_SPEC_VLAN(pDesc->data.dw3.u16Special),
     1701                    E1K_SPEC_PRI(pDesc->data.dw3.u16Special)));
    16971702            break;
    16981703        case E1K_DTYP_LEGACY:
     
    17141719                    pDesc->legacy.cmd.u8CSO,
    17151720                    pDesc->legacy.dw3.u8CSS,
    1716                     pDesc->legacy.dw3.fCFI ? " CFI" :"",
    1717                     pDesc->legacy.dw3.u12VLAN,
    1718                     pDesc->legacy.dw3.u3PRI));
     1721                    E1K_SPEC_CFI(pDesc->legacy.dw3.u16Special) ? "CFI" :"cfi",
     1722                    E1K_SPEC_VLAN(pDesc->legacy.dw3.u16Special),
     1723                    E1K_SPEC_PRI(pDesc->legacy.dw3.u16Special)));
    17191724            break;
    17201725        default:
     
    20142019
    20152020    Assert(cb <= E1K_MAX_RX_PKT_SIZE);
    2016     memcpy(rxPacket, pvBuf, cb);
     2021    Assert(cb > 16);
     2022    if (status.fVP && cb > 16)
     2023    {
     2024        uint16_t *u16Ptr = (uint16_t*)pvBuf;
     2025        /* VLAN packet -- strip VLAN tag */
     2026        memcpy(rxPacket, pvBuf, 12); /* Copy src and dst addresses */
     2027        status.u16Special = RT_BE2H_U16(u16Ptr[7]); /* Extract VLAN tag */
     2028        memcpy(rxPacket + 12, (uint8_t*)pvBuf + 16, cb - 16); /* Copy the rest of the packet */
     2029    }
     2030    else
     2031        memcpy(rxPacket, pvBuf, cb);
    20172032    /* Pad short packets */
    20182033    if (cb < 60)
     
    22042219        if (value & CTRL_VME)
    22052220        {
    2206             E1kLog(("%s VLAN Mode is not supported yet!\n", INSTANCE(pState)));
     2221            E1kLog(("%s VLAN Mode Enabled\n", INSTANCE(pState)));
    22072222        }
    22082223        E1kLog(("%s e1kRegWriteCTRL: mdio dir=%s mdc dir=%s mdc=%s mdio=%d\n",
     
    31773192{
    31783193    PPDMSCATTERGATHER   pSg     = pState->CTX_SUFF(pTxSg);
    3179     uint32_t const      cbFrame = pSg ? (uint32_t)pSg->cbUsed : 0;
     3194    uint32_t const      cbFrame = pSg ? ((uint32_t)pSg->cbUsed + (pState->fVTag ? 4 : 0)) : 0;
    31803195    Assert(!pSg || pSg->cSegs == 1);
    31813196
     
    31883203        pState->led.Asserted.s.fWriting = pState->led.Actual.s.fWriting = 1;
    31893204
     3205    /* Add VLAN tag */
     3206    if (cbFrame > 16 && pState->fVTag)
     3207    {
     3208        E1kLog3(("%s Inserting VLAN tag %08x\n",
     3209            INSTANCE(pState), RT_BE2H_U16(VET) | (RT_BE2H_U16(pState->u16VTagTCI) << 16)));
     3210        memmove((uint8_t*)pSg->aSegs[0].pvSeg + 16, (uint8_t*)pSg->aSegs[0].pvSeg + 12, cbFrame - 12);
     3211        *((uint32_t*)pSg->aSegs[0].pvSeg + 3) = RT_BE2H_U16(VET) | (RT_BE2H_U16(pState->u16VTagTCI) << 16);
     3212    }
    31903213    /* Update the stats */
    31913214    E1K_INC_CNT32(TPT);
     
    36173640static void e1kXmitDesc(E1KSTATE* pState, E1KTXDESC* pDesc, RTGCPHYS addr, bool fOnWorkerThread)
    36183641{
     3642    uint32_t cbVTag = 0;
     3643
    36193644    e1kPrintTDesc(pState, pDesc, "vvv");
    36203645
     
    36673692
    36683693            /*
     3694             * The last descriptor of non-TSE packet must contain VLE flag.
     3695             * TSE packets have VLE flag in the first descriptor. The later
     3696             * case is taken care of a bit later when cbVTag gets assigned.
     3697             *
     3698             * 1) pDesc->data.cmd.fEOP && !pDesc->data.cmd.fTSE
     3699             */
     3700            if (pDesc->data.cmd.fEOP && !pDesc->data.cmd.fTSE)
     3701            {
     3702                pState->fVTag      = pDesc->data.cmd.fVLE;
     3703                pState->u16VTagTCI = pDesc->data.dw3.u16Special;
     3704            }
     3705            /*
    36693706             * First fragment: Allocate new buffer and save the IXSM and TXSM
    36703707             * packet options as these are only valid in the first fragment.
     
    36773714                         pState->fIPcsum ? " IP" : "",
    36783715                         pState->fTCPcsum ? " TCP/UDP" : ""));
     3716                if (pDesc->data.cmd.fTSE)
     3717                {
     3718                    /* 2) pDesc->data.cmd.fTSE && pState->u16TxPktLen == 0 */
     3719                    pState->fVTag      = pDesc->data.cmd.fVLE;
     3720                    pState->u16VTagTCI = pDesc->data.dw3.u16Special;
     3721                    cbVTag = pState->fVTag ? 4 : 0;
     3722                }
     3723                else if (pDesc->data.cmd.fEOP)
     3724                    cbVTag = pDesc->data.cmd.fVLE ? 4 : 0;
     3725                else
     3726                    cbVTag = 4;
     3727                E1kLog3(("%s About to allocate TX buffer: cbVTag=%u\n", INSTANCE(pState), cbVTag));
    36793728                if (e1kCanDoGso(&pState->GsoCtx, &pDesc->data, &pState->contextTSE))
    3680                     e1kXmitAllocBuf(pState, pState->contextTSE.dw2.u20PAYLEN + pState->contextTSE.dw3.u8HDRLEN,
     3729                    e1kXmitAllocBuf(pState, pState->contextTSE.dw2.u20PAYLEN + pState->contextTSE.dw3.u8HDRLEN + cbVTag,
    36813730                                    true /*fExactSize*/, true /*fGso*/);
    36823731                else
    3683                     e1kXmitAllocBuf(pState, pState->contextTSE.dw3.u16MSS + pState->contextTSE.dw3.u8HDRLEN,
     3732                    e1kXmitAllocBuf(pState, pState->contextTSE.dw3.u16MSS + pState->contextTSE.dw3.u8HDRLEN + cbVTag,
    36843733                                    pDesc->data.cmd.fTSE  /*fExactSize*/, false /*fGso*/);
    36853734                /** @todo Is there any way to indicating errors other than collisions? Like
     
    37653814            /* First fragment: allocate new buffer. */
    37663815            if (pState->u16TxPktLen == 0)
     3816            {
     3817                if (pDesc->legacy.cmd.fEOP)
     3818                    cbVTag = pDesc->legacy.cmd.fVLE ? 4 : 0;
     3819                else
     3820                    cbVTag = 4;
     3821                E1kLog3(("%s About to allocate TX buffer: cbVTag=%u\n", INSTANCE(pState), cbVTag));
    37673822                /** @todo reset status bits? */
    3768                 e1kXmitAllocBuf(pState, pDesc->legacy.cmd.u16Length, pDesc->legacy.cmd.fEOP, false /*fGso*/);
     3823                e1kXmitAllocBuf(pState, pDesc->legacy.cmd.u16Length + cbVTag, pDesc->legacy.cmd.fEOP, false /*fGso*/);
    37693824                /** @todo Is there any way to indicating errors other than collisions? Like
    37703825                 *        VERR_NET_DOWN. */
     3826            }
    37713827
    37723828            /* Add fragment to frame. */
     
    37783834                if (pDesc->legacy.cmd.fEOP)
    37793835                {
     3836                    pState->fVTag       = pDesc->legacy.cmd.fVLE;
     3837                    pState->u16VTagTCI  = pDesc->legacy.dw3.u16Special;
    37803838                    /** @todo Offload processing goes here. */
    37813839                    e1kTransmitFrame(pState, fOnWorkerThread);
     
    48534911    }
    48544912
     4913    /* Is VLAN filtering enabled? */
     4914    if (RCTL & RCTL_VFE)
     4915    {
     4916        uint16_t *u16Ptr = (uint16_t*)pvBuf;
     4917        /* Compare TPID with VLAN Ether Type */
     4918        if (RT_BE2H_U16(u16Ptr[6]) == VET)
     4919        {
     4920            pStatus->fVP = true;
     4921            /* It is 802.1q packet indeed, let's filter by VID */
     4922            if (RCTL & RCTL_CFIEN)
     4923            {
     4924                E1kLog3(("%s VLAN filter: VLAN=%d CFI=%d RCTL_CFI=%d\n", INSTANCE(pState),
     4925                         E1K_SPEC_VLAN(RT_BE2H_U16(u16Ptr[7])),
     4926                         E1K_SPEC_CFI(RT_BE2H_U16(u16Ptr[7])),
     4927                         !!(RCTL & RCTL_CFI)));
     4928                if (E1K_SPEC_CFI(RT_BE2H_U16(u16Ptr[7])) != !!(RCTL & RCTL_CFI))
     4929                {
     4930                    E1kLog2(("%s Packet filter: CFIs do not match in packet and RCTL (%d!=%d)\n",
     4931                             INSTANCE(pState), E1K_SPEC_CFI(RT_BE2H_U16(u16Ptr[7])), !!(RCTL & RCTL_CFI)));
     4932                    return false;
     4933                }
     4934            }
     4935            else
     4936                E1kLog3(("%s VLAN filter: VLAN=%d\n", INSTANCE(pState),
     4937                         E1K_SPEC_VLAN(RT_BE2H_U16(u16Ptr[7]))));
     4938            if (!ASMBitTest(pState->auVFTA, E1K_SPEC_VLAN(RT_BE2H_U16(u16Ptr[7]))))
     4939            {
     4940                E1kLog2(("%s Packet filter: no VLAN match (id=%d)\n",
     4941                         INSTANCE(pState), E1K_SPEC_VLAN(RT_BE2H_U16(u16Ptr[7]))));
     4942                return false;
     4943            }
     4944        }
     4945    }
    48554946    /* Broadcast filtering */
    48564947    if (e1kIsBroadcast(pvBuf) && (RCTL & RCTL_BAM))
     
    48854976        }
    48864977        E1kLog2(("%s Packet filter: no perfect match\n", INSTANCE(pState)));
    4887     }
    4888     /* Is VLAN filtering enabled? */
    4889     if (RCTL & RCTL_VFE)
    4890     {
    4891         uint16_t *u16Ptr = (uint16_t*)pvBuf;
    4892         /* Compare TPID with VLAN Ether Type */
    4893         if (u16Ptr[6] == VET)
    4894         {
    4895             pStatus->fVP = true;
    4896             /* It is 802.1q packet indeed, let's filter by VID */
    4897             if (ASMBitTest(pState->auVFTA, RT_BE2H_U16(u16Ptr[7]) & 0xFFF))
    4898                 return true;
    4899             E1kLog2(("%s Packet filter: no VLAN match\n", INSTANCE(pState)));
    4900         }
    49014978    }
    49024979    E1kLog2(("%s Packet filter: packet discarded\n", INSTANCE(pState)));
     
    51765253    SSMR3PutMem(pSSM, &pState->contextTSE, sizeof(pState->contextTSE));
    51775254    SSMR3PutMem(pSSM, &pState->contextNormal, sizeof(pState->contextNormal));
     5255    SSMR3PutBool(pSSM, pState->fVTag);
     5256    SSMR3PutU16(pSSM, pState->u16VTagTCI);
    51785257/**@todo GSO requires some more state here. */
    51795258    E1kLog(("%s State has been saved\n", INSTANCE(pState)));
     
    52405319
    52415320    if (    uVersion != E1K_SAVEDSTATE_VERSION
     5321        &&  uVersion != E1K_SAVEDSTATE_VERSION_VBOX_41
    52425322        &&  uVersion != E1K_SAVEDSTATE_VERSION_VBOX_30)
    52435323        return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
     
    52885368        rc = SSMR3GetMem(pSSM, &pState->contextNormal, sizeof(pState->contextNormal));
    52895369        AssertRCReturn(rc, rc);
    5290 
     5370        if (uVersion > E1K_SAVEDSTATE_VERSION_VBOX_41)
     5371        {
     5372            SSMR3GetBool(pSSM, &pState->fVTag);
     5373            rc = SSMR3GetU16(pSSM, &pState->u16VTagTCI);
     5374            AssertRCReturn(rc, rc);
     5375        }
     5376        else
     5377        {
     5378            pState->fVTag      = false;
     5379            pState->u16VTagTCI = 0;
     5380        }
    52915381        /* derived state  */
    52925382        e1kSetupGsoCtx(&pState->GsoCtx, &pState->contextTSE);
     
    55655655{
    55665656    E1KSTATE* pState = PDMINS_2_DATA(pDevIns, E1KSTATE*);
    5567     unsigned    i;
    5568     bool        fRcvRing = false;
    5569     bool        fXmtRing = false;
     5657    unsigned  i;
     5658    // bool        fRcvRing = false;
     5659    // bool        fXmtRing = false;
    55705660
    55715661    /*
    55725662     * Parse args.
    5573      */
    55745663    if (pszArgs)
    55755664    {
     
    55775666        fXmtRing = strstr(pszArgs, "verbose") || strstr(pszArgs, "xmt");
    55785667    }
     5668     */
    55795669
    55805670    /*
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