VirtualBox

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


Ignore:
Timestamp:
Aug 18, 2010 12:01:40 PM (14 years ago)
Author:
vboxsync
Message:

virtio-net: TSO4, TSO6 and UFO support (#4807)

File:
1 edited

Legend:

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

    r30219 r31755  
    1919#define LOG_GROUP LOG_GROUP_DEV_VIRTIO_NET
    2020#define VNET_GC_SUPPORT
     21//#define VNET_WITH_GSO
    2122
    2223#include <VBox/pdmdev.h>
    2324#include <VBox/pdmnetifs.h>
    2425#include <iprt/asm.h>
     26#include <iprt/net.h>
    2527#include <iprt/semaphore.h>
    2628#ifdef IN_RING3
     
    190192    STAMCOUNTER             StatReceiveBytes;
    191193    STAMCOUNTER             StatTransmitBytes;
     194    STAMCOUNTER             StatReceiveGSO;
     195    STAMCOUNTER             StatTransmitPackets;
     196    STAMCOUNTER             StatTransmitGSO;
     197    STAMCOUNTER             StatTransmitCSum;
    192198#if defined(VBOX_WITH_STATISTICS)
    193199    STAMPROFILE             StatReceive;
     
    205211#ifndef VBOX_DEVICE_STRUCT_TESTCASE
    206212
    207 #define VNETHDR_GSO_NONE 0
     213#define VNETHDR_F_NEEDS_CSUM     1       // Use u16CSumStart, u16CSumOffset
     214
     215#define VNETHDR_GSO_NONE         0       // Not a GSO frame
     216#define VNETHDR_GSO_TCPV4        1       // GSO frame, IPv4 TCP (TSO)
     217#define VNETHDR_GSO_UDP          3       // GSO frame, IPv4 UDP (UFO)
     218#define VNETHDR_GSO_TCPV6        4       // GSO frame, IPv6 TCP
     219#define VNETHDR_GSO_ECN          0x80    // TCP has ECN set
    208220
    209221struct VNetHdr
     
    304316        | VNET_F_CTRL_VQ
    305317        | VNET_F_CTRL_RX
    306         | VNET_F_CTRL_VLAN;
     318        | VNET_F_CTRL_VLAN
     319#ifdef VNET_WITH_GSO
     320        | VNET_F_CSUM
     321        | VNET_F_HOST_TSO4
     322        | VNET_F_HOST_TSO6
     323        | VNET_F_HOST_UFO
     324#endif
     325        ;
    307326}
    308327
     
    831850    Log(("%s Receive buffers has been added, waking up receive thread.\n", INSTANCE(pState)));
    832851    vnetWakeupReceive(pState->VPCI.CTX_SUFF(pDevIns));
     852}
     853
     854/**
     855 * Sets up the GSO context according to the Virtio header.
     856 *
     857 * @param   pGso                The GSO context to setup.
     858 * @param   pCtx                The context descriptor.
     859 */
     860DECLINLINE(PPDMNETWORKGSO) vnetSetupGsoCtx(PPDMNETWORKGSO pGso, VNETHDR const *pHdr)
     861{
     862    pGso->u8Type = PDMNETWORKGSOTYPE_INVALID;
     863
     864    if (pHdr->u8GSOType & VNETHDR_GSO_ECN)
     865    {
     866        AssertMsgFailed(("Unsupported flag in virtio header: ECN\n"));
     867        return NULL;
     868    }
     869    switch (pHdr->u8GSOType & ~VNETHDR_GSO_ECN)
     870    {
     871        case VNETHDR_GSO_TCPV4:
     872            pGso->u8Type = PDMNETWORKGSOTYPE_IPV4_TCP;
     873            break;
     874        case VNETHDR_GSO_TCPV6:
     875            pGso->u8Type = PDMNETWORKGSOTYPE_IPV6_TCP;
     876            break;
     877        case VNETHDR_GSO_UDP:
     878            pGso->u8Type = PDMNETWORKGSOTYPE_IPV4_UDP;
     879            break;
     880        default:
     881            return NULL;
     882    }
     883    if (pHdr->u8Flags & VNETHDR_F_NEEDS_CSUM)
     884        pGso->offHdr2  = pHdr->u16CSumStart;
     885    else
     886    {
     887        AssertMsgFailed(("GSO without checksum offloading!\n"));
     888        return NULL;
     889    }
     890    pGso->offHdr1  = sizeof(RTNETETHERHDR);
     891    pGso->cbHdrs   = pHdr->u16HdrLen;
     892    pGso->cbMaxSeg = pHdr->u16GSOSize;
     893    return pGso;
     894}
     895
     896DECLINLINE(uint16_t) vnetCSum16(const void *pvBuf, size_t cb)
     897{
     898    uint32_t  csum = 0;
     899    uint16_t *pu16 = (uint16_t *)pvBuf;
     900
     901    while (cb > 1)
     902    {
     903        csum += *pu16++;
     904        cb -= 2;
     905    }
     906    if (cb)
     907        csum += *(uint8_t*)pu16;
     908    while (csum >> 16)
     909        csum = (csum >> 16) + (csum & 0xFFFF);
     910    return ~csum;
     911}
     912
     913DECLINLINE(void) vnetCompleteChecksum(uint8_t *pBuf, unsigned cbSize, uint16_t uStart, uint16_t uOffset)
     914{
     915    *(uint16_t*)(pBuf + uStart + uOffset) = vnetCSum16(pBuf + uStart, cbSize - uStart);
    833916}
    834917
     
    895978            if (pState->pDrv)
    896979            {
     980                VNETHDR Hdr;
     981                PDMNETWORKGSO Gso, *pGso;
     982
     983                PDMDevHlpPhysRead(pState->VPCI.CTX_SUFF(pDevIns), elem.aSegsOut[0].addr,
     984                                  &Hdr, sizeof(Hdr));
     985
     986                STAM_REL_COUNTER_INC(&pState->StatTransmitPackets);
     987
    897988                vnetPacketDump(pState, pState->pTxBuf, uOffset, "--> Outgoing");
    898989
    899990                STAM_PROFILE_START(&pState->StatTransmitSend, a);
    900991
     992                pGso = vnetSetupGsoCtx(&Gso, &Hdr);
     993                if (pGso)
     994                    STAM_REL_COUNTER_INC(&pState->StatTransmitGSO);
     995                else if (Hdr.u8Flags & VNETHDR_F_NEEDS_CSUM)
     996                {
     997                    STAM_REL_COUNTER_INC(&pState->StatTransmitCSum);
     998                    /*
     999                     * This is not GSO frame but checksum offloading is requested.
     1000                     */
     1001                    vnetCompleteChecksum(pState->pTxBuf, uOffset, Hdr.u16CSumStart, Hdr.u16CSumOffset);
     1002                }
    9011003                /** @todo Optimize away the extra copying! (lazy bird) */
    9021004                PPDMSCATTERGATHER pSgBuf;
    903                 int rc = pState->pDrv->pfnAllocBuf(pState->pDrv, uOffset, NULL /*pGso*/, &pSgBuf);
     1005                int rc = pState->pDrv->pfnAllocBuf(pState->pDrv, uOffset, pGso, &pSgBuf);
    9041006                if (RT_SUCCESS(rc))
    9051007                {
     
    18051907    AssertRC(rc);
    18061908
    1807     PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatReceiveBytes,       STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,          "Amount of data received",            "/Devices/VNet%d/ReceiveBytes", iInstance);
    1808     PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatTransmitBytes,      STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,          "Amount of data transmitted",         "/Devices/VNet%d/TransmitBytes", iInstance);
     1909    PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatReceiveBytes,       STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,          "Amount of data received",            "/Devices/VNet%d/Bytes/Receive", iInstance);
     1910    PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatTransmitBytes,      STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,          "Amount of data transmitted",         "/Devices/VNet%d/Bytes/Transmit", iInstance);
     1911    PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatReceiveGSO,         STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,          "Number of received GSO packets",     "/Devices/VNet%d/Packets/ReceiveGSO", iInstance);
     1912    PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatTransmitPackets,    STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,          "Number of sent packets",             "/Devices/VNet%d/Packets/Transmit", iInstance);
     1913    PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatTransmitGSO,        STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,          "Number of sent GSO packets",         "/Devices/VNet%d/Packets/Transmit-Gso", iInstance);
     1914    PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatTransmitCSum,       STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,          "Number of completed TX checksums",   "/Devices/VNet%d/Packets/Transmit-Csum", iInstance);
    18091915#if defined(VBOX_WITH_STATISTICS)
    18101916    PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatReceive,            STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling receive",                  "/Devices/VNet%d/Receive/Total", iInstance);
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