VirtualBox

Changeset 28159 in vbox


Ignore:
Timestamp:
Apr 10, 2010 8:06:17 PM (15 years ago)
Author:
vboxsync
Message:

VBoxNetFlt-linux.c: Experimenting with filtering out traffic from the host to the internal network (disabled).

File:
1 edited

Legend:

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

    r28157 r28159  
    220220    Log(("VBoxNetFltLinuxUnload - done\n"));
    221221}
     222
     223/**
     224 * Experiment where we filter trafic from the host to the internal network
     225 * before it reaches the NIC driver.
     226 *
     227 * The current code uses a very ugly hack and only works on kernels using the
     228 * net_device_ops (2.6.30 or something).  It has been shown to give us a
     229 * performance boost of 60-100% though.  So, we have to find some less hacky way
     230 * of getting this job done eventually.
     231 *
     232 * #define VBOXNETFLT_WITH_FILTER_HOST2GUEST_SKBS_EXPERIMENT
     233 */
     234#ifdef VBOXNETFLT_WITH_FILTER_HOST2GUEST_SKBS_EXPERIMENT
     235
     236/**
     237 * The overridden net_device_ops of the device we're attached to.
     238 *
     239 * Requires Linux 2.6.30 or something.
     240 *
     241 * This is a very dirty hack that was create to explore how much we can improve
     242 * the host to guest transfers by not CC'ing the NIC.
     243 */
     244typedef struct VBoxNetDeviceOpsOverride
     245{
     246    /** Our overridden ops. */
     247    struct net_device_ops           Ops;
     248    /** Pointer to the original ops. */
     249    struct net_device_ops const    *pOrgOps;
     250    /** Magic word. */
     251    uint32_t                        u32Magic;
     252    /** The number of filtered packages. */
     253    uint64_t                        cFiltered;
     254    /** The total number of packets */
     255    uint64_t                        cTotal;
     256} VBOXNETDEVICEOPSOVERRIDE, *PVBOXNETDEVICEOPSOVERRIDE;
     257/** VBOXNETDEVICEOPSOVERRIDE::u32Magic value. */
     258#define VBOXNETDEVICEOPSOVERRIDE_MAGIC  UINT32_C(0x00c0ffee)
     259
     260/**
     261 * ndo_start_xmit wrapper that drops packets that shouldn't go to the wire
     262 * because they belong on the internal network.
     263 *
     264 * @returns NETDEV_TX_XXX.
     265 * @param   pSkb                The socket buffer to transmit.
     266 * @param   pDev                The net device.
     267 */
     268static int vboxNetFltLinuxStartXmitFilter(struct sk_buff *pSkb, struct net_device *pDev)
     269{
     270    PVBOXNETDEVICEOPSOVERRIDE   pOverride = (PVBOXNETDEVICEOPSOVERRIDE)pDev->netdev_ops;
     271    RTNETETHERHDR               EtherHdrBuf;
     272    PCRTNETETHERHDR             pEtherHdr;
     273
     274    /*
     275     * Validate the override structure.
     276     *
     277     * Note! We're racing vboxNetFltLinuxUnhookDev here.  If this was supposed
     278     *       to be production quality code, we would have to be much more
     279     *       careful here and avoid the race.
     280     */
     281    if (   !VALID_PTR(pOverride)
     282        || pOverride->u32Magic != VBOXNETDEVICEOPSOVERRIDE_MAGIC
     283        || !VALID_PTR(pOverride->pOrgOps))
     284    {
     285        printk("vboxNetFltLinuxStartXmitFilter: bad override %p\n", pOverride);
     286        dev_kfree_skb(pSkb);
     287        return NETDEV_TX_OK;
     288    }
     289    pOverride->cTotal++;
     290
     291    /*
     292     * Do the filtering base on the defaul OUI of our virtual NICs
     293     *
     294     * Note! In a real solution, we would ask the switch whether the
     295     *       destination MAC is 100% to be on the internal network and then
     296     *       drop it.
     297     */
     298    pEtherHdr = (PCRTNETETHERHDR)skb_header_pointer(pSkb, 0, sizeof(EtherHdrBuf), &EtherHdrBuf);
     299    if (    pEtherHdr
     300        &&  pEtherHdr->DstMac.au8[0] == 0x08
     301        &&  pEtherHdr->DstMac.au8[1] == 0x00
     302        &&  pEtherHdr->DstMac.au8[2] == 0x27
     303       )
     304    {
     305        dev_kfree_skb(pSkb);
     306        pOverride->cFiltered++;
     307        return NETDEV_TX_OK;
     308    }
     309
     310    return pOverride->pOrgOps->ndo_start_xmit(pSkb, pDev);
     311}
     312
     313/**
     314 * Hooks the device ndo_start_xmit operation of the device.
     315 *
     316 * @param   pThis               The net filter instance.
     317 * @param   pDev                The net device.
     318 */
     319static void vboxNetFltLinuxHookDev(PVBOXNETFLTINS pThis, struct net_device *pDev)
     320{
     321    PVBOXNETDEVICEOPSOVERRIDE   pOverride;
     322    RTSPINLOCKTMP               Tmp = RTSPINLOCKTMP_INITIALIZER;
     323
     324    pOverride = RTMemAlloc(sizeof(*pOverride));
     325    if (!pOverride)
     326        return;
     327    pOverride->pOrgOps              = pDev->netdev_ops;
     328    pOverride->Ops                  = *pDev->netdev_ops;
     329    pOverride->Ops.ndo_start_xmit   = vboxNetFltLinuxStartXmitFilter;
     330    pOverride->u32Magic             = VBOXNETDEVICEOPSOVERRIDE_MAGIC;
     331
     332    RTSpinlockAcquire(pThis->hSpinlock, &Tmp); /* (this isn't necessary, but so what) */
     333    ASMAtomicXchgPtr((void * volatile *)&pDev->netdev_ops, pOverride);
     334    RTSpinlockRelease(pThis->hSpinlock, &Tmp);
     335}
     336
     337/**
     338 * Undos what vboxNetFltLinuxHookDev did.
     339 *
     340 * @param   pThis               The net filter instance.
     341 * @param   pDev                The net device.  Can be NULL, in which case
     342 *                              we'll try retrieve it from @a pThis.
     343 */
     344static void vboxNetFltLinuxUnhookDev(PVBOXNETFLTINS pThis, struct net_device *pDev)
     345{
     346    PVBOXNETDEVICEOPSOVERRIDE   pOverride;
     347    RTSPINLOCKTMP               Tmp = RTSPINLOCKTMP_INITIALIZER;
     348
     349    RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
     350    if (!pDev)
     351        pDev = (struct net_device *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev);
     352    if (VALID_PTR(pDev))
     353    {
     354        pOverride = (PVBOXNETDEVICEOPSOVERRIDE)pDev->netdev_ops;
     355        if (    VALID_PTR(pOverride)
     356            &&  pOverride->u32Magic == VBOXNETDEVICEOPSOVERRIDE_MAGIC
     357            &&  VALID_PTR(pOverride->pOrgOps)
     358           )
     359        {
     360            ASMAtomicXchgPtr((void * volatile *)&pDev->netdev_ops, pOverride->pOrgOps);
     361            ASMAtomicWriteU32(&pOverride->u32Magic, 0);
     362        }
     363        else
     364            pOverride = NULL;
     365    }
     366    else
     367        pOverride = NULL;
     368    RTSpinlockRelease(pThis->hSpinlock, &Tmp);
     369
     370    if (pOverride)
     371    {
     372        printk("vboxnetflt: dropped %llu out of %llu packets\n", pOverride->cFiltered, pOverride->cTotal);
     373        RTMemFree(pOverride);
     374    }
     375}
     376
     377#endif /* VBOXNETFLT_WITH_FILTER_HOST2GUEST_SKBS_EXPERIMENT */
    222378
    223379
     
    11251281    dev_add_pack(&pThis->u.s.PacketType);
    11261282
     1283#ifdef VBOXNETFLT_WITH_FILTER_HOST2GUEST_SKBS_EXPERIMENT
     1284    vboxNetFltLinuxHookDev(pThis, pDev);
     1285#endif
     1286
    11271287    /*
    11281288     * Set indicators that require the spinlock. Be abit paranoid about racing
     
    11481308    else
    11491309    {
     1310#ifdef VBOXNETFLT_WITH_FILTER_HOST2GUEST_SKBS_EXPERIMENT
     1311        vboxNetFltLinuxUnhookDev(pThis, pDev);
     1312#endif
    11501313        RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
    11511314        ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.pDev, NULL);
     
    11651328
    11661329    Assert(!pThis->fDisconnectedFromHost);
     1330
     1331#ifdef VBOXNETFLT_WITH_FILTER_HOST2GUEST_SKBS_EXPERIMENT
     1332    vboxNetFltLinuxUnhookDev(pThis, pDev);
     1333#endif
     1334
    11671335    RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
    11681336    ASMAtomicWriteBool(&pThis->u.s.fRegistered, false);
     
    14701638void vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis)
    14711639{
    1472     struct net_device *pDev;
    1473     bool fRegistered;
    1474     RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
     1640    struct net_device  *pDev;
     1641    bool                fRegistered;
     1642    RTSPINLOCKTMP       Tmp = RTSPINLOCKTMP_INITIALIZER;
     1643
     1644#ifdef VBOXNETFLT_WITH_FILTER_HOST2GUEST_SKBS_EXPERIMENT
     1645    vboxNetFltLinuxUnhookDev(pThis, NULL);
     1646#endif
     1647
     1648    /** @todo This code may race vboxNetFltLinuxUnregisterDevice (very very
     1649     *        unlikely, but none the less).  Since it doesn't actually update the
     1650     *        state (just reads it), it is likely to panic in some interesting
     1651     *        ways. */
    14751652
    14761653    RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
     
    14781655    fRegistered = ASMAtomicUoReadBool(&pThis->u.s.fRegistered);
    14791656    RTSpinlockRelease(pThis->hSpinlock, &Tmp);
     1657
    14801658    if (fRegistered)
    14811659    {
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