VirtualBox

Changeset 28156 in vbox


Ignore:
Timestamp:
Apr 10, 2010 1:14:10 AM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
59887
Message:

VBoxNetFlt-linux: GSO to host and wire experiment, the former is a success the latter needs more magic.

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/pdmnetinline.h

    r28153 r28156  
    158158 * @param   cbPayload           The amount of payload.
    159159 * @param   cbHdrs              The size of all the headers.
     160 * @param   fPayloadChecksum    Whether to checksum the payload or not.
    160161 * @internal
    161162 */
    162163DECLINLINE(void) pdmNetGsoUpdateUdpHdr(uint32_t u32PseudoSum, uint8_t *pbSegHdrs, uint8_t offUdpHdr,
    163                                        uint8_t const *pbPayload, uint32_t cbPayload, uint8_t cbHdrs)
     164                                       uint8_t const *pbPayload, uint32_t cbPayload, uint8_t cbHdrs, bool fPayloadChecksum)
    164165{
    165166    PRTNETUDP pUdpHdr = (PRTNETUDP)&pbSegHdrs[offUdpHdr];
    166167    pUdpHdr->uh_ulen = cbPayload + cbHdrs - offUdpHdr;
    167     pUdpHdr->uh_sum  = RTNetUDPChecksum(u32PseudoSum, pUdpHdr);
     168    pUdpHdr->uh_sum  = fPayloadChecksum ? RTNetUDPChecksum(u32PseudoSum, pUdpHdr) : 0;
    168169}
    169170
     
    182183 * @param   cbHdrs              The size of all the headers.
    183184 * @param   fLastSeg            Set if this is the last segment.
     185 * @param   fPayloadChecksum    Whether to checksum the payload or not.
    184186 * @internal
    185187 */
    186188DECLINLINE(void) pdmNetGsoUpdateTcpHdr(uint32_t u32PseudoSum, uint8_t *pbSegHdrs, uint8_t offTcpHdr,
    187                                        uint8_t const *pbPayload, uint32_t cbPayload, uint32_t offPayload, uint8_t cbHdrs, bool fLastSeg)
     189                                       uint8_t const *pbPayload, uint32_t cbPayload, uint32_t offPayload, uint8_t cbHdrs,
     190                                       bool fLastSeg, bool fPayloadChecksum)
    188191{
    189192    PRTNETTCP pTcpHdr = (PRTNETTCP)&pbSegHdrs[offTcpHdr];
     
    191194    if (!fLastSeg)
    192195        pTcpHdr->th_flags &= ~(RTNETTCP_F_FIN | RTNETTCP_F_PSH);
    193     pTcpHdr->th_sum = RTNetTCPChecksum(u32PseudoSum, pTcpHdr, pbPayload, cbPayload);
     196    pTcpHdr->th_sum = fPayloadChecksum ? RTNetTCPChecksum(u32PseudoSum, pTcpHdr, pbPayload, cbPayload) : 0;
    194197}
    195198
     
    298301            pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, pGso->cbHdrs),
    299302                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
    300                                   pGso->cbHdrs, iSeg + 1 == cSegs);
     303                                  pGso->cbHdrs, iSeg + 1 == cSegs, true);
    301304            break;
    302305        case PDMNETWORKGSOTYPE_IPV4_UDP:
    303306            pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, pGso->cbHdrs),
    304                                   pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs);
     307                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, true);
    305308            break;
    306309        case PDMNETWORKGSOTYPE_IPV6_TCP:
     
    308311                                                         pGso->offHdr2, RTNETIPV4_PROT_TCP),
    309312                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
    310                                   pGso->cbHdrs, iSeg + 1 == cSegs);
     313                                  pGso->cbHdrs, iSeg + 1 == cSegs, true);
    311314            break;
    312315        case PDMNETWORKGSOTYPE_IPV6_UDP:
    313316            pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, pGso->cbHdrs,
    314317                                                         pGso->offHdr2, RTNETIPV4_PROT_UDP),
    315                                   pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs);
     318                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, true);
    316319            break;
    317320        case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP:
     
    320323                                                         cbSegPayload, pGso->cbHdrs, pGso->offHdr2, RTNETIPV4_PROT_TCP),
    321324                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
    322                                   pGso->cbHdrs, iSeg + 1 == cSegs);
     325                                  pGso->cbHdrs, iSeg + 1 == cSegs, true);
    323326            break;
    324327        case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP:
     
    326329            pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pgmNetGsoCalcIpv6Offset(pbSegHdrs, pGso->offHdr1),
    327330                                                         cbSegPayload, pGso->cbHdrs, pGso->offHdr2, RTNETIPV4_PROT_UDP),
    328                                   pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs);
     331                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, true);
    329332            break;
    330333        case PDMNETWORKGSOTYPE_INVALID:
     
    391394            pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, pGso->cbHdrs),
    392395                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
    393                                   pGso->cbHdrs, iSeg + 1 == cSegs);
     396                                  pGso->cbHdrs, iSeg + 1 == cSegs, true);
    394397            break;
    395398        case PDMNETWORKGSOTYPE_IPV4_UDP:
    396399            pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, pGso->cbHdrs),
    397                                   pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs);
     400                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, true);
    398401            break;
    399402        case PDMNETWORKGSOTYPE_IPV6_TCP:
     
    401404                                                         pGso->offHdr2, RTNETIPV4_PROT_TCP),
    402405                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
    403                                   pGso->cbHdrs, iSeg + 1 == cSegs);
     406                                  pGso->cbHdrs, iSeg + 1 == cSegs, true);
    404407            break;
    405408        case PDMNETWORKGSOTYPE_IPV6_UDP:
    406409            pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, pGso->cbHdrs,
    407410                                                         pGso->offHdr2, RTNETIPV4_PROT_UDP),
    408                                   pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs);
     411                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, true);
    409412            break;
    410413        case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP:
     
    413416                                                         cbSegPayload, pGso->cbHdrs, pGso->offHdr2, RTNETIPV4_PROT_TCP),
    414417                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
    415                                   pGso->cbHdrs, iSeg + 1 == cSegs);
     418                                  pGso->cbHdrs, iSeg + 1 == cSegs, true);
    416419            break;
    417420        case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP:
     
    419422            pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pgmNetGsoCalcIpv6Offset(pbSegHdrs, pGso->offHdr1),
    420423                                                         cbSegPayload, pGso->cbHdrs, pGso->offHdr2, RTNETIPV4_PROT_UDP),
    421                                   pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs);
     424                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, true);
    422425            break;
    423426        case PDMNETWORKGSOTYPE_INVALID:
     
    432435
    433436
    434 
    435 
    436 DECLINLINE(void) PDMNetGsoPrepForDirectUse(PCPDMNETWORKGSO pGso, void *pvFrame, size_t cbFrame,
    437                                            bool fHeaderChecskum, bool fPayloadChecksum)
    438 {
    439 /** @todo Need to implement this eventually, not important yet as it's only use
    440  *        by DHCP where GSO isn't normally used. */
     437/**
     438 * Prepares the GSO frame for direct use without any segmenting.
     439 *
     440 * @param   pGso                The GSO context.
     441 * @param   pvFrame             The frame to prepare.
     442 * @param   cbFrame             The frame size.
     443 * @param   fPayloadChecksum    Whether to checksum payload.
     444 */
     445DECLINLINE(void) PDMNetGsoPrepForDirectUse(PCPDMNETWORKGSO pGso, void *pvFrame, size_t cbFrame, bool fPayloadChecksum)
     446{
     447    /*
     448     * Figure out where the payload is and where the header starts before we
     449     * do the protocol bits.
     450     */
     451    uint8_t * const pbHdrs    = (uint8_t *)pvFrame;
     452    uint8_t * const pbPayload = pbHdrs  + pGso->cbHdrs;
     453    size_t    const cbPayload = cbFrame - pGso->cbHdrs;
     454
     455    /*
     456     * Check assumptions (doing it after declaring the variables because of C).
     457     */
     458    Assert(PDMNetGsoIsValid(pGso, sizeof(*pGso), cbFrame));
     459
     460    /*
     461     * Get down to busienss.
     462     */
     463    switch ((PDMNETWORKGSOTYPE)pGso->u8Type)
     464    {
     465        case PDMNETWORKGSOTYPE_IPV4_TCP:
     466            pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv4Hdr(pbHdrs, pGso->offHdr1, cbFrame - pGso->cbHdrs, 0, pGso->cbHdrs),
     467                                  pbHdrs, pGso->offHdr2, pbPayload, cbPayload, 0, pGso->cbHdrs, true, fPayloadChecksum);
     468            break;
     469        case PDMNETWORKGSOTYPE_IPV4_UDP:
     470            pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv4Hdr(pbHdrs, pGso->offHdr1, cbFrame - pGso->cbHdrs, 0, pGso->cbHdrs),
     471                                  pbHdrs, pGso->offHdr2, pbPayload, cbPayload, pGso->cbHdrs, fPayloadChecksum);
     472            break;
     473        case PDMNETWORKGSOTYPE_IPV6_TCP:
     474            pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pGso->offHdr1, cbPayload, pGso->cbHdrs,
     475                                                         pGso->offHdr2, RTNETIPV4_PROT_TCP),
     476                                  pbHdrs, pGso->offHdr2, pbPayload, cbPayload, 0, pGso->cbHdrs, true, fPayloadChecksum);
     477            break;
     478        case PDMNETWORKGSOTYPE_IPV6_UDP:
     479            pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pGso->offHdr1, cbPayload, pGso->cbHdrs,
     480                                                         pGso->offHdr2, RTNETIPV4_PROT_UDP),
     481                                  pbHdrs, pGso->offHdr2, pbPayload, cbPayload, pGso->cbHdrs, fPayloadChecksum);
     482            break;
     483        case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP:
     484            pdmNetGsoUpdateIPv4Hdr(pbHdrs, pGso->offHdr1, cbPayload, 0, pGso->cbHdrs);
     485            pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pgmNetGsoCalcIpv6Offset(pbHdrs, pGso->offHdr1),
     486                                                         cbPayload, pGso->cbHdrs, pGso->offHdr2, RTNETIPV4_PROT_TCP),
     487                                  pbHdrs, pGso->offHdr2, pbPayload, cbPayload, 0, pGso->cbHdrs, true, fPayloadChecksum);
     488            break;
     489        case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP:
     490            pdmNetGsoUpdateIPv4Hdr(pbHdrs, pGso->offHdr1, cbPayload, 0, pGso->cbHdrs);
     491            pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pgmNetGsoCalcIpv6Offset(pbHdrs, pGso->offHdr1),
     492                                                         cbPayload, pGso->cbHdrs, pGso->offHdr2, RTNETIPV4_PROT_UDP),
     493                                  pbHdrs, pGso->offHdr2, pbPayload, cbPayload, pGso->cbHdrs, fPayloadChecksum);
     494            break;
     495        case PDMNETWORKGSOTYPE_INVALID:
     496        case PDMNETWORKGSOTYPE_END:
     497            /* no default! wnat gcc warnings. */
     498            break;
     499    }
    441500}
    442501
  • trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp

    r28120 r28156  
    16411641    if (fDst == INTNETTRUNKDIR_WIRE)
    16421642        return !!(pThis->fGsoCapabilitesWire & fMask);
    1643     Assert(fDst == (INTNETTRUNKDIR_WIRE == INTNETTRUNKDIR_HOST));
     1643    Assert(fDst == (INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST));
    16441644    return !!(pThis->fGsoCapabilitesHost & pThis->fGsoCapabilitesWire & fMask);
    16451645}
     
    33183318    for (unsigned iBit = PDMNETWORKGSOTYPE_END; iBit < 32; iBit++)
    33193319        Assert(!(fGsoCapabilities & RT_BIT_32(iBit)));
    3320     Assert(fDst & ~INTNETTRUNKDIR_VALID_MASK);
     3320    Assert(!(fDst & ~INTNETTRUNKDIR_VALID_MASK));
    33213321    Assert(fDst);
    33223322
  • trunk/src/VBox/HostDrivers/Support/linux/Makefile

    r26180 r28156  
    100100        r0drv/linux/timer-r0drv-linux.o \
    101101        r0drv/generic/semspinmutex-r0drv-generic.o \
     102        common/checksum/ipv4.o \
     103        common/checksum/ipv6.o \
    102104        common/err/RTErrConvertFromErrno.o \
    103105        common/err/RTErrConvertToErrno.o \
  • trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv

    r26180 r28156  
    7676    ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPDrvInternal.h=>SUPDrvInternal.h \
    7777    ${PATH_ROOT}/src/VBox/Runtime/common/alloc/heapsimple.cpp=>alloc/heapsimple.c \
     78    ${PATH_ROOT}/src/VBox/Runtime/common/checksum/ipv4.cpp=>common/checksum/ipv4.c \
     79    ${PATH_ROOT}/src/VBox/Runtime/common/checksum/ipv6.cpp=>common/checksum/ipv6.c \
    7880    ${PATH_ROOT}/src/VBox/Runtime/common/err/RTErrConvertFromErrno.cpp=>common/err/RTErrConvertFromErrno.c \
    7981    ${PATH_ROOT}/src/VBox/Runtime/common/err/RTErrConvertToErrno.cpp=>common/err/RTErrConvertToErrno.c \
  • trunk/src/VBox/HostDrivers/VBoxNetFlt/linux/Makefile

    r25097 r28156  
    7070        SUPR0IdcClient.o \
    7171        SUPR0IdcClientComponent.o \
    72         SUPR0IdcClient-linux.o \
     72        SUPR0IdcClient-linux.o
    7373
    7474ifeq ($(BUILD_TARGET_ARCH),x86)
  • trunk/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c

    r28153 r28156  
    8484#endif
    8585
    86 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
    87 /** Indicates that the linux kernel may send us GSO frames. */
    88 # define VBOXNETFLT_WITH_GSO  1
    89 #endif
    90 
    9186#ifndef NET_IP_ALIGN
    9287# define NET_IP_ALIGN 2
     
    9792 *  linearize the socket buffer before creating the internal networking SG. */
    9893# define VBOXNETFLT_SG_SUPPORT 1
     94#endif
     95
     96#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
     97/** Indicates that the linux kernel may send us GSO frames. */
     98# define VBOXNETFLT_WITH_GSO  1
     99
     100/** This enables or disables the transmitting of GSO frame from the internal
     101 *  network and to the host.  */
     102# define VBOXNETFLT_WITH_GSO_XMIT_HOST    1
     103
     104# if 0 /** @todo This is currently disable because it causes performance loss of 5-10%.  */
     105/** This enables or disables the transmitting of GSO frame from the internal
     106 *  network and to the wire. */
     107#  define VBOXNETFLT_WITH_GSO_XMIT_WIRE   1
     108# endif
     109
    99110#endif
    100111
     
    292303 * @param   pThis           The instance.
    293304 * @param   pSG             The (scatter/)gather list.
     305 * @param   fDstWire        Set if the destination is the wire.
    294306 */
    295307static struct sk_buff *vboxNetFltLinuxSkBufFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG, bool fDstWire)
     
    297309    struct sk_buff *pPkt;
    298310    struct net_device *pDev;
     311    unsigned fGsoType = 0;
    299312
    300313    if (pSG->cbTotal == 0)
     
    304317    }
    305318
     319    /** @todo We should use fragments mapping the SG buffers with large packets.
     320     *        256 bytes seems to be the a threshold used a lot for this.  It
     321     *        requires some nasty work on the intnet side though...  */
    306322    /*
    307323     * Allocate a packet and copy over the data.
    308324     */
    309325    pDev = (struct net_device *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev);
    310     pPkt = dev_alloc_skb(pSG->cbTotal + NET_IP_ALIGN);
    311     if (RT_UNLIKELY(!pPkt))
    312     {
    313         Log(("vboxNetFltLinuxSkBufFromSG: Failed to allocate sk_buff(%u).\n", pSG->cbTotal));
    314         pSG->pvUserData = NULL;
    315         return NULL;
    316     }
    317 
    318     pPkt->dev = pDev;
    319 
    320     /* Align IP header on 16-byte boundary: 2 + 14 (ethernet hdr size). */
    321     skb_reserve(pPkt, NET_IP_ALIGN);
    322 
    323     /* Copy the segments. */
    324     skb_put(pPkt, pSG->cbTotal);
    325     INTNETSgRead(pSG, pPkt->data);
    326 
    327     /* Set protocol and packet_type fields. */
     326#if 0 /* trying to figure out why submitting GSOs is so darn slow. */
     327    if (   pSG->GsoCtx.u8Type != PDMNETWORKGSOTYPE_INVALID
     328        && pSG->cbTotal > 4096
     329        && fDstWire
     330        && pDev
     331        && (pDev->features & NETIF_F_SG)
     332        )
     333    {
     334        uint32_t off    = 0;
     335        uint32_t cbLeft = pSG->cbTotal;
     336        uint32_t iFrag  = 0;
     337
     338        pPkt = dev_alloc_skb(pSG->GsoCtx.cbHdrs + NET_IP_ALIGN + 64);
     339        if (RT_UNLIKELY(!pPkt))
     340        {
     341            Log(("vboxNetFltLinuxSkBufFromSG: Failed to allocate sk_buff(%u).\n", pSG->cbTotal));
     342            pSG->pvUserData = NULL;
     343            return NULL;
     344        }
     345        pPkt->dev       = pDev;
     346        pPkt->ip_summed = CHECKSUM_NONE;
     347
     348        /* Align IP header on 16-byte boundary: 2 + 14 (ethernet hdr size). */
     349        skb_reserve(pPkt, NET_IP_ALIGN);
     350
     351        /* Copy the headers. */
     352        skb_put(pPkt, pSG->GsoCtx.cbHdrs);
     353        INTNETSgReadEx(pSG, off, pSG->GsoCtx.cbHdrs, pPkt->data);
     354        off    += pSG->GsoCtx.cbHdrs;
     355        cbLeft -= off;
     356
     357        /* Copy the payload into fragments. */
     358        while (cbLeft)
     359        {
     360            void           *pvPage;
     361            uint32_t        cbUsed = RT_MIN(cbLeft, PAGE_SIZE);
     362            struct page    *pPage  = alloc_page(GFP_ATOMIC);
     363            if (!pPage)
     364            {
     365                dev_kfree_skb(pPkt);
     366                return NULL;
     367            }
     368
     369            skb_fill_page_desc(pPkt, iFrag, pPage, 0, cbUsed);
     370
     371            pvPage = kmap(pPage);
     372            INTNETSgReadEx(pSG, off, cbUsed, pvPage);
     373            kunmap(pPage);
     374
     375            /* advance */
     376            iFrag          += 1;
     377            pPkt->len      += cbUsed;
     378            pPkt->data_len += cbUsed;
     379            pPkt->truesize += cbUsed;
     380            off            += cbUsed;
     381            cbLeft         -= cbUsed;
     382        }
     383    }
     384    else
     385#endif
     386    {
     387        pPkt = dev_alloc_skb(pSG->cbTotal + NET_IP_ALIGN);
     388        if (RT_UNLIKELY(!pPkt))
     389        {
     390            Log(("vboxNetFltLinuxSkBufFromSG: Failed to allocate sk_buff(%u).\n", pSG->cbTotal));
     391            pSG->pvUserData = NULL;
     392            return NULL;
     393        }
     394        pPkt->dev       = pDev;
     395        pPkt->ip_summed = CHECKSUM_NONE;
     396
     397        /* Align IP header on 16-byte boundary: 2 + 14 (ethernet hdr size). */
     398        skb_reserve(pPkt, NET_IP_ALIGN);
     399
     400        /* Copy the segments. */
     401        skb_put(pPkt, pSG->cbTotal);
     402        INTNETSgRead(pSG, pPkt->data);
     403    }
     404
     405#if defined(VBOXNETFLT_WITH_GSO_XMIT_WIRE) || defined(VBOXNETFLT_WITH_GSO_XMIT_HOST)
     406    /*
     407     * Setup GSO if used by this packet.
     408     */
     409    switch ((PDMNETWORKGSOTYPE)pSG->GsoCtx.u8Type)
     410    {
     411        default:
     412            AssertMsgFailed(("%u (%s)\n", pSG->GsoCtx.u8Type, PDMNetGsoTypeName((PDMNETWORKGSOTYPE)pSG->GsoCtx.u8Type) ));
     413            /* fall thru */
     414        case PDMNETWORKGSOTYPE_INVALID:
     415            fGsoType = 0;
     416            break;
     417        case PDMNETWORKGSOTYPE_IPV4_TCP:
     418            fGsoType = SKB_GSO_TCPV4;
     419            break;
     420        case PDMNETWORKGSOTYPE_IPV4_UDP:
     421            fGsoType = SKB_GSO_UDP;
     422            break;
     423        case PDMNETWORKGSOTYPE_IPV6_TCP:
     424            fGsoType = SKB_GSO_TCPV6;
     425            break;
     426    }
     427    if (fGsoType)
     428    {
     429        struct skb_shared_info *pShInfo = skb_shinfo(pPkt);
     430
     431        if (!fDstWire)
     432            fGsoType |= SKB_GSO_DODGY;
     433        pShInfo->gso_type = fGsoType;
     434        pShInfo->gso_size = pSG->GsoCtx.cbMaxSeg;
     435        pShInfo->gso_segs = PDMNetGsoCalcSegmentCount(&pSG->GsoCtx, pSG->cbTotal);
     436
     437        /** @todo figure out the checksum bit... We're checksumming way too much here
     438         *        I hope.  */
     439        if (fDstWire)
     440        {
     441            /** @todo check skb_partial_csum_set status code.  */
     442            if (fGsoType & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))
     443                skb_partial_csum_set(pPkt, pSG->GsoCtx.offHdr2, RT_OFFSETOF(RTNETTCP, th_sum));
     444            else
     445                skb_partial_csum_set(pPkt, pSG->GsoCtx.offHdr2, RT_OFFSETOF(RTNETUDP, uh_sum));
     446        }
     447        else
     448        {
     449            pPkt->ip_summed = CHECKSUM_UNNECESSARY;
     450            PDMNetGsoPrepForDirectUse(&pSG->GsoCtx, pPkt->data, pSG->cbTotal, false /*fPayloadChecksum*/);
     451        }
     452    }
     453#endif /* VBOXNETFLT_WITH_GSO_XMIT_WIRE || VBOXNETFLT_WITH_GSO_XMIT_HOST */
     454
     455    /*
     456     * Finish up the socket buffer.
     457     */
    328458    pPkt->protocol = eth_type_trans(pPkt, pDev);
    329     pPkt->ip_summed = CHECKSUM_NONE;
    330459    if (fDstWire)
    331460    {
    332461        VBOX_SKB_RESET_NETWORK_HDR(pPkt);
     462
    333463        /* Restore ethernet header back. */
    334         skb_push(pPkt, ETH_HLEN);
     464        skb_push(pPkt, ETH_HLEN); /** @todo VLAN: +4 if VLAN? */
    335465        VBOX_SKB_RESET_MAC_HDR(pPkt);
    336466    }
     
    557687}
    558688
    559 #ifndef LOG_ENABLED
    560 # define VBOXNETFLT_DUMP_PACKET(a, b, c, d) do {} while (0)
    561 #else
     689#ifdef LOG_ENABLED
     690/**
     691 * Logging helper.
     692 */
    562693static void vboxNetFltDumpPacket(PINTNETSG pSG, bool fEgress, const char *pszWhere, int iIncrement)
    563694{
     
    583714    Log3(("%.*Rhxd\n", pSG->aSegs[0].cb, pSG->aSegs[0].pv));
    584715}
    585 #endif /* LOG_ENABLED */
     716#else
     717# define vboxNetFltDumpPacket(a, b, c, d) do {} while (0)
     718#endif
    586719
    587720#ifdef VBOXNETFLT_WITH_GSO
     
    9751108
    9761109/**
    977  * Internal worker for vboxNetFltOsInitInstance and vboxNetFltOsMaybeRediscovered.
     1110 * Reports the GSO capabilites of the hardware NIC.
     1111 *
     1112 * @param   pThis               The net filter instance.  The caller hold a
     1113 *                              reference to this.
     1114 */
     1115static void vboxNetFltLinuxReportNicGsoCapabilities(PVBOXNETFLTINS pThis)
     1116{
     1117#ifdef VBOXNETFLT_WITH_GSO_XMIT_WIRE
     1118    struct net_device  *pDev;
     1119    PINTNETTRUNKSWPORT  pSwitchPort;
     1120    unsigned int        fFeatures;
     1121    RTSPINLOCKTMP       Tmp = RTSPINLOCKTMP_INITIALIZER;
     1122
     1123    RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
     1124
     1125    pSwitchPort = pThis->pSwitchPort; /* this doesn't need to be here, but it doesn't harm. */
     1126    pDev = (struct net_device *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev);
     1127    if (pDev)
     1128        fFeatures = pDev->features;
     1129    else
     1130        fFeatures = 0;
     1131
     1132    RTSpinlockRelease(pThis->hSpinlock, &Tmp);
     1133
     1134    if (pThis->pSwitchPort)
     1135    {
     1136        /* Set/update the GSO capabilities of the NIC. */
     1137        uint32_t fGsoCapabilites = 0;
     1138        if (fFeatures & NETIF_F_TSO)
     1139            fGsoCapabilites |= RT_BIT_32(PDMNETWORKGSOTYPE_IPV4_TCP);
     1140        if (fFeatures & NETIF_F_TSO6)
     1141            fGsoCapabilites |= RT_BIT_32(PDMNETWORKGSOTYPE_IPV6_TCP);
     1142# if 0 /** @todo GSO: Test UDP offloading (UFO) on linux. */
     1143        if (fFeatures & NETIF_F_UFO)
     1144            fGsoCapabilites |= RT_BIT_32(PDMNETWORKGSOTYPE_IPV4_UDP);
     1145        if (fFeatures & NETIF_F_UFO)
     1146            fGsoCapabilites |= RT_BIT_32(PDMNETWORKGSOTYPE_IPV6_UDP);
     1147# endif
     1148        pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, fGsoCapabilites, INTNETTRUNKDIR_WIRE);
     1149    }
     1150#endif /* VBOXNETFLT_WITH_GSO_XMIT_WIRE */
     1151}
     1152
     1153/**
     1154 * Internal worker for vboxNetFltLinuxNotifierCallback.
    9781155 *
    9791156 * @returns VBox status code.
     
    9841161static int vboxNetFltLinuxAttachToInterface(PVBOXNETFLTINS pThis, struct net_device *pDev)
    9851162{
    986     struct packet_type *pt;
    9871163    RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
    988 
    9891164    LogFlow(("vboxNetFltLinuxAttachToInterface: pThis=%p (%s)\n", pThis, pThis->szName));
    9901165
    991     if (!pDev)
    992     {
    993         Log(("VBoxNetFlt: failed to find device '%s'\n", pThis->szName));
    994         return VERR_INTNET_FLT_IF_NOT_FOUND;
    995     }
    996 
     1166    /*
     1167     * Retain and store the device.
     1168     */
    9971169    dev_hold(pDev);
     1170
    9981171    RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
    9991172    ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.pDev, pDev);
     
    10021175    Log(("vboxNetFltLinuxAttachToInterface: Device %p(%s) retained. ref=%d\n", pDev, pDev->name, atomic_read(&pDev->refcnt)));
    10031176    Log(("vboxNetFltLinuxAttachToInterface: Got pDev=%p pThis=%p pThis->u.s.pDev=%p\n", pDev, pThis, ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev)));
    1004     /*
    1005      * Get the mac address while we still have a valid ifnet reference.
    1006      */
     1177
     1178    /* Get the mac address while we still have a valid net_device reference. */
    10071179    memcpy(&pThis->u.s.Mac, pDev->dev_addr, sizeof(pThis->u.s.Mac));
    10081180
    1009     pt = &pThis->u.s.PacketType;
    1010     pt->type = __constant_htons(ETH_P_ALL);
    1011     pt->dev  = pDev;
    1012     pt->func = vboxNetFltLinuxPacketHandler;
    1013     dev_add_pack(pt);
     1181    /*
     1182     * Install a packet filter for this device with a protocol wildcard (ETH_P_ALL).
     1183     */
     1184    pThis->u.s.PacketType.type = __constant_htons(ETH_P_ALL);
     1185    pThis->u.s.PacketType.dev  = pDev;
     1186    pThis->u.s.PacketType.func = vboxNetFltLinuxPacketHandler;
     1187    dev_add_pack(&pThis->u.s.PacketType);
     1188
     1189    /*
     1190     * Set indicators that require the spinlock. Be abit paranoid about racing
     1191     * the device notification handle.
     1192     */
    10141193    RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
    10151194    pDev = (struct net_device *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev);
     
    10231202    Log(("vboxNetFltLinuxAttachToInterface: this=%p: Packet handler installed.\n", pThis));
    10241203
    1025     /* Release the interface on failure. */
    1026     if (pDev)
     1204    /*
     1205     * If the above succeeded report GSO capabilites,  if not undo and
     1206     * release the device.
     1207     */
     1208    if (!pDev)
     1209        vboxNetFltLinuxReportNicGsoCapabilities(pThis);
     1210    else
    10271211    {
    10281212        RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
     
    10881272}
    10891273
    1090 static int vboxNetFltLinuxNotifierCallback(struct notifier_block *self, unsigned long ulEventType, void *ptr)
    1091 
    1092 {
    1093     int rc = NOTIFY_OK;
    1094 #ifdef DEBUG
    1095     char *pszEvent = "<unknown>";
    1096 #endif
    1097     struct net_device *pDev = (struct net_device *)ptr;
    1098     PVBOXNETFLTINS pThis = VBOX_FLT_NB_TO_INST(self);
    1099 
    1100 #ifdef DEBUG
     1274#ifdef LOG_ENABLED
     1275/** Stringify the NETDEV_XXX constants. */
     1276static const char *vboxNetFltLinuxGetNetDevEventName(unsigned long ulEventType)
     1277{
     1278    const char *pszEvent = "NETDRV_<unknown>";
    11011279    switch (ulEventType)
    11021280    {
     
    11111289        case NETDEV_CHANGEADDR: pszEvent = "NETDEV_CHANGEADDR"; break;
    11121290        case NETDEV_GOING_DOWN: pszEvent = "NETDEV_GOING_DOWN"; break;
    1113     }
     1291# ifdef NETDEV_FEAT_CHANGE
     1292        case NETDEV_FEAT_CHANGE: pszEvent = "NETDEV_FEAT_CHANGE"; break;
     1293# endif
     1294    }
     1295    return pszEvent;
     1296}
     1297#endif /* LOG_ENABLED */
     1298
     1299/**
     1300 * Callback for listening to netdevice events.
     1301 *
     1302 * This works the rediscovery, clean up on unregistration, promiscuity on
     1303 * up/down, and GSO feature changes from ethtool.
     1304 *
     1305 * @returns NOTIFY_OK
     1306 * @param   self                Pointer to our notifier registration block.
     1307 * @param   ulEventType         The event.
     1308 * @param   ptr                 Event specific, but it is usually the device it
     1309 *                              relates to.
     1310 */
     1311static int vboxNetFltLinuxNotifierCallback(struct notifier_block *self, unsigned long ulEventType, void *ptr)
     1312
     1313{
     1314    PVBOXNETFLTINS      pThis = VBOX_FLT_NB_TO_INST(self);
     1315    struct net_device  *pDev  = (struct net_device *)ptr;
     1316    int                 rc    = NOTIFY_OK;
     1317
    11141318    Log(("VBoxNetFlt: got event %s(0x%lx) on %s, pDev=%p pThis=%p pThis->u.s.pDev=%p\n",
    1115          pszEvent, ulEventType, pDev->name, pDev, pThis, ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev)));
    1116 #endif
    1117     if (ulEventType == NETDEV_REGISTER && !strcmp(pDev->name, pThis->szName))
     1319         vboxNetFltLinuxGetNetDevEventName(ulEventType), ulEventType, pDev->name, pDev, pThis, ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev)));
     1320    if (    ulEventType == NETDEV_REGISTER
     1321        && !strcmp(pDev->name, pThis->szName))
    11181322    {
    11191323        vboxNetFltLinuxAttachToInterface(pThis, pDev);
     
    11221326    {
    11231327        pDev = (struct net_device *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev);
    1124         if (pDev != ptr)
    1125             return NOTIFY_OK;
    1126         rc = NOTIFY_OK;
    1127         switch (ulEventType)
    1128         {
    1129             case NETDEV_UNREGISTER:
    1130                 rc = vboxNetFltLinuxUnregisterDevice(pThis, pDev);
    1131                 break;
    1132             case NETDEV_UP:
    1133                 rc = vboxNetFltLinuxDeviceIsUp(pThis, pDev);
    1134                 break;
    1135             case NETDEV_GOING_DOWN:
    1136                 rc = vboxNetFltLinuxDeviceGoingDown(pThis, pDev);
    1137                 break;
    1138             case NETDEV_CHANGENAME:
    1139                 break;
     1328        if (pDev == ptr)
     1329        {
     1330            switch (ulEventType)
     1331            {
     1332                case NETDEV_UNREGISTER:
     1333                    rc = vboxNetFltLinuxUnregisterDevice(pThis, pDev);
     1334                    break;
     1335                case NETDEV_UP:
     1336                    rc = vboxNetFltLinuxDeviceIsUp(pThis, pDev);
     1337                    break;
     1338                case NETDEV_GOING_DOWN:
     1339                    rc = vboxNetFltLinuxDeviceGoingDown(pThis, pDev);
     1340                    break;
     1341                case NETDEV_CHANGENAME:
     1342                    break;
     1343#ifdef NETDEV_FEAT_CHANGE
     1344                case NETDEV_FEAT_CHANGE:
     1345                    vboxNetFltLinuxReportNicGsoCapabilities(pThis);
     1346                    break;
     1347#endif
     1348            }
    11401349        }
    11411350    }
     
    13001509int  vboxNetFltOsConnectIt(PVBOXNETFLTINS pThis)
    13011510{
    1302     /* Nothing to do here. */
     1511    /*
     1512     * Report the GSO capabilities of the host and device (if connected).
     1513     */
     1514#if defined(VBOXNETFLT_WITH_GSO_XMIT_HOST)
     1515    pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort,
     1516                                                 0
     1517                                                 | RT_BIT_32(PDMNETWORKGSOTYPE_IPV4_TCP)
     1518                                                 | RT_BIT_32(PDMNETWORKGSOTYPE_IPV6_TCP)
     1519# if 0 /** @todo GSO: Test UDP offloading (UFO) on linux. */
     1520                                                 | RT_BIT_32(PDMNETWORKGSOTYPE_IPV4_UDP)
     1521                                                 | RT_BIT_32(PDMNETWORKGSOTYPE_IPV6_UDP)
     1522# endif
     1523                                                 , INTNETTRUNKDIR_HOST);
     1524
     1525#endif
     1526    vboxNetFltLinuxReportNicGsoCapabilities(pThis);
     1527
    13031528    return VINF_SUCCESS;
    13041529}
  • trunk/src/VBox/NetworkServices/NetLib/VBoxNetUDP.cpp

    r28025 r28156  
    127127     */
    128128    if (pGso)
    129         PDMNetGsoPrepForDirectUse(pGso, (void *)pvFrame, cbFrame, false /*fHeaderChecskum*/, false /*fPayloadChecksum*/);
     129        PDMNetGsoPrepForDirectUse(pGso, (void *)pvFrame, cbFrame, false /*fPayloadChecksum*/);
    130130
    131131    /*
Note: See TracChangeset for help on using the changeset viewer.

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