VirtualBox

Ignore:
Timestamp:
Jul 2, 2013 12:59:56 PM (11 years ago)
Author:
vboxsync
Message:

IntNet, VirtioNet, NetFilter: Large frame support + drop oversized + UFO fix (#6821)

File:
1 edited

Legend:

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

    r44528 r46904  
    542542
    543543/**
     544 * Checks whether this SG list contains a GSO packet.
     545 *
     546 * @returns true / false accordingly.
     547 * @param   pSG             The (scatter/)gather list.
     548 */
     549DECLINLINE(bool) vboxNetFltLinuxIsGso(PINTNETSG pSG)
     550{
     551#if defined(VBOXNETFLT_WITH_GSO_XMIT_WIRE) || defined(VBOXNETFLT_WITH_GSO_XMIT_HOST)
     552    return !((PDMNETWORKGSOTYPE)pSG->GsoCtx.u8Type == PDMNETWORKGSOTYPE_INVALID);
     553#else /* !VBOXNETFLT_WITH_GSO_XMIT_WIRE && !VBOXNETFLT_WITH_GSO_XMIT_HOST */
     554    return false;
     555#endif /* !VBOXNETFLT_WITH_GSO_XMIT_WIRE && !VBOXNETFLT_WITH_GSO_XMIT_HOST */
     556}
     557
     558
     559/**
     560 * Find out the frame size (of a single segment in case of GSO frames).
     561 *
     562 * @returns the frame size.
     563 * @param   pSG             The (scatter/)gather list.
     564 */
     565DECLINLINE(uint32_t) vboxNetFltLinuxFrameSize(PINTNETSG pSG)
     566{
     567    RTNETETHERHDR EthHdr;
     568    uint16_t      u16Type = 0;
     569    uint32_t      cbVlanTag = 0;
     570    if (pSG->aSegs[0].cb >= sizeof(EthHdr))
     571        u16Type = RT_BE2H_U16(((PCRTNETETHERHDR)pSG->aSegs[0].pv)->EtherType);
     572    else if (pSG->cbTotal >= sizeof(EthHdr))
     573    {
     574        uint32_t i, uOffset = RT_OFFSETOF(RTNETETHERHDR, EtherType);
     575        for (i = 0; i < pSG->cSegsUsed; ++i)
     576        {
     577            if (uOffset > pSG->aSegs[i].cb)
     578            {
     579                uOffset -= pSG->aSegs[i].cb;
     580                continue;
     581            }
     582            if (uOffset + sizeof(uint16_t) > pSG->aSegs[i].cb)
     583            {
     584                if (i + 1 < pSG->cSegsUsed)
     585                    u16Type = RT_BE2H_U16(  ((uint16_t)( ((uint8_t*)pSG->aSegs[i].pv)[uOffset] ) << 8)
     586                                          + *(uint8_t*)pSG->aSegs[i + 1].pv);
     587            }
     588            else
     589                u16Type = RT_BE2H_U16(*(uint16_t*)((uint8_t*)pSG->aSegs[i].pv + uOffset));
     590        }
     591    }
     592    if (u16Type == RTNET_ETHERTYPE_VLAN)
     593        cbVlanTag = 4;
     594    return (vboxNetFltLinuxIsGso(pSG) ? (uint32_t)pSG->GsoCtx.cbMaxSeg + pSG->GsoCtx.cbHdrsTotal : pSG->cbTotal) - cbVlanTag;
     595}
     596
     597
     598/**
    544599 * Internal worker that create a linux sk_buff for a
    545600 * (scatter/)gather list.
     
    559614    {
    560615        LogRel(("VBoxNetFlt: Dropped empty packet coming from internal network.\n"));
     616        return NULL;
     617    }
     618    Log5(("VBoxNetFlt: Packet to %s of %d bytes (frame=%d).\n", fDstWire?"wire":"host", pSG->cbTotal, vboxNetFltLinuxFrameSize(pSG)));
     619    if (fDstWire && (vboxNetFltLinuxFrameSize(pSG) > ASMAtomicReadU32(&pThis->u.s.cbMtu) + 14))
     620    {
     621        static bool fOnce = true;
     622        if (fOnce)
     623        {
     624            fOnce = false;
     625            printk("VBoxNetFlt: Dropped over-sized packet (%d bytes) coming from internal network.\n", vboxNetFltLinuxFrameSize(pSG));
     626        }
    561627        return NULL;
    562628    }
     
    15301596    /* Get the mac address while we still have a valid net_device reference. */
    15311597    memcpy(&pThis->u.s.MacAddr, pDev->dev_addr, sizeof(pThis->u.s.MacAddr));
     1598    /* Initialize MTU */
     1599    pThis->u.s.cbMtu = pDev->mtu;
    15321600
    15331601    /*
     
    16771745    else
    16781746        Log(("vboxNetFltLinuxDeviceGoingDown: no need to disable promiscuous mode on %s (%d)\n", pThis->szName, pDev->promiscuity));
     1747    return NOTIFY_OK;
     1748}
     1749
     1750/**
     1751 * Callback for listening to MTU change event.
     1752 *
     1753 * We need to track changes of host's inteface MTU to discard over-sized frames
     1754 * coming from the internal network as they may hang the TX queue of host's
     1755 * adapter.
     1756 *
     1757 * @returns NOTIFY_OK
     1758 * @param   pThis               The netfilter instance.
     1759 * @param   pDev                Pointer to device structure of host's interface.
     1760 */
     1761static int vboxNetFltLinuxDeviceMtuChange(PVBOXNETFLTINS pThis, struct net_device *pDev)
     1762{
     1763    ASMAtomicWriteU32(&pThis->u.s.cbMtu, pDev->mtu);
     1764    Log(("vboxNetFltLinuxDeviceMtuChange: set MTU for %s to %d\n", pThis->szName, pDev->mtu));
    16791765    return NOTIFY_OK;
    16801766}
     
    17471833                    rc = vboxNetFltLinuxDeviceGoingDown(pThis, pDev);
    17481834                    break;
     1835                case NETDEV_CHANGEMTU:
     1836                    rc = vboxNetFltLinuxDeviceMtuChange(pThis, pDev);
     1837                    break;
    17491838                case NETDEV_CHANGENAME:
    17501839                    break;
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