VirtualBox

Changeset 30029 in vbox


Ignore:
Timestamp:
Jun 4, 2010 11:39:56 AM (14 years ago)
Author:
vboxsync
Message:

#4814: vboxnetflt qdisc: Drop host->guest packets on linux.

Location:
trunk/src/VBox
Files:
2 edited

Legend:

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

    r30004 r30029  
    44664466    AssertReturn(pNetwork->hEvtBusyIf != NIL_RTSEMEVENT, INTNETSWDECISION_TRUNK);
    44674467    AssertPtr(pvSrc);
    4468     AssertPtr(cbSrc >= 6);
     4468    Assert(cbSrc >= 6);
    44694469    Assert(fSrc);
    44704470
  • trunk/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c

    r29662 r30029  
    5151#include "../VBoxNetFltInternal.h"
    5252
     53/*
     54 * Uncomment the following line to enable qdisc support.
     55 */
     56//#define VBOXNETFLT_WITH_QDISC
     57#ifdef VBOXNETFLT_WITH_QDISC
     58#include <net/pkt_sched.h>
     59#endif /* VBOXNETFLT_WITH_QDISC */
     60
    5361
    5462/*******************************************************************************
     
    161169
    162170
     171#ifdef VBOXNETFLT_WITH_QDISC
     172//#define QDISC_LOG(x) printk x
     173#define QDISC_LOG(x)
     174
     175#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
     176#define QDISC_CREATE(dev, queue, ops, parent) qdisc_create_dflt(dev, ops)
     177#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
     178#define QDISC_CREATE(dev, queue, ops, parent) qdisc_create_dflt(dev, ops, parent)
     179#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */
     180#define QDISC_CREATE(dev, queue, ops, parent) qdisc_create_dflt(dev, queue, ops, parent)
     181#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */
     182
     183#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
     184#define QDISC_GET(dev) (dev->qdisc_sleeping)
     185#else
     186#define QDISC_GET(dev) (netdev_get_tx_queue(dev, 0)->qdisc_sleeping)
     187#endif
     188
     189#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
     190#define QDISC_SAVED_NUM(dev) 1
     191#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
     192#define QDISC_SAVED_NUM(dev) dev->num_tx_queues
     193#else
     194#define QDISC_SAVED_NUM(dev) dev->num_tx_queues+1
     195#endif
     196
     197#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
     198#define QDISC_IS_BUSY(dev, qdisc)  test_bit(__LINK_STATE_SCHED, &dev->state))
     199#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */
     200#define QDISC_IS_BUSY(dev, qdisc) (test_bit(__QDISC_STATE_RUNNING, &qdisc->state) || \
     201                                   test_bit(__QDISC_STATE_SCHED, &qdisc->state))
     202#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */
     203
     204struct VBoxNetQDiscPriv
     205{
     206    /** Pointer to the single child qdisc. */
     207    struct Qdisc     *pChild;
     208    /*
     209     * Technically it is possible to have different qdiscs for different TX
     210     * queues so we have to save them all.
     211     */
     212    /** Pointer to the array of saved qdiscs. */
     213    struct Qdisc    **ppSaved;
     214    /** Pointer to the net filter instance. */
     215    PVBOXNETFLTINS    pVBoxNetFlt;
     216};
     217typedef struct VBoxNetQDiscPriv *PVBOXNETQDISCPRIV;
     218
     219//#define VBOXNETFLT_QDISC_ENQUEUE
     220static int vboxNetFltQdiscEnqueue(struct sk_buff *skb, struct Qdisc *sch)
     221{
     222    int rc;
     223    PVBOXNETQDISCPRIV pPriv = qdisc_priv(sch);
     224#ifdef VBOXNETFLT_QDISC_ENQUEUE
     225    if (VALID_PTR(pPriv->pVBoxNetFlt))
     226    {
     227        uint8_t              abHdrBuf[sizeof(RTNETETHERHDR) + sizeof(uint32_t) + RTNETIPV4_MIN_LEN];
     228        PCRTNETETHERHDR      pEtherHdr;
     229        PINTNETTRUNKSWPORT   pSwitchPort;
     230
     231        pEtherHdr = (PCRTNETETHERHDR)skb_header_pointer(skb, 0, sizeof(abHdrBuf), &abHdrBuf[0]);
     232        if (   pEtherHdr
     233            && (pSwitchPort = pPriv->pVBoxNetFlt->pSwitchPort) != NULL
     234            && VALID_PTR(pSwitchPort)
     235            )
     236        {
     237            struct sk_buff      *pBuf;
     238            INTNETSWDECISION    enmDecision;
     239            uint32_t            cbHdrs = skb_headlen(skb);
     240            cbHdrs = RT_MAX(cbHdrs, sizeof(abHdrBuf));
     241
     242#if 1
     243            /* Test stub due to missing implementation of pfnPreRecv */
     244            static uint8_t       tmpAddr[] = { 0x08, 0x00, 0x27, 0xBB, 0x1E, 0xA0 };
     245            if (memcmp(pEtherHdr, tmpAddr, 6) != 0)
     246                enmDecision = INTNETSWDECISION_BROADCAST;
     247            else
     248                enmDecision = INTNETSWDECISION_INTNET;
     249#else
     250            enmDecision = pSwitchPort->pfnPreRecv(pSwitchPort, pEtherHdr, cbHdrs, INTNETTRUNKDIR_HOST);
     251#endif
     252            if (enmDecision == INTNETSWDECISION_INTNET)
     253            {
     254                pBuf = skb_copy(skb, GFP_ATOMIC);
     255                pBuf->pkt_type = PACKET_OUTGOING;
     256                vboxNetFltLinuxForwardToIntNet(pPriv->pVBoxNetFlt, pBuf);
     257                qdisc_drop(skb, sch);
     258                ++sch->bstats.packets;
     259                sch->bstats.bytes += qdisc_pkt_len(skb);
     260                return NET_XMIT_SUCCESS;
     261            }
     262        }
     263    }
     264#endif /* VBOXNETFLT_QDISC_ENQUEUE */
     265    rc = pPriv->pChild->enqueue(skb, pPriv->pChild);
     266    if (rc == NET_XMIT_SUCCESS)
     267    {
     268        ++sch->q.qlen;
     269        ++sch->bstats.packets;
     270        sch->bstats.bytes += qdisc_pkt_len(skb);
     271    }
     272    else
     273        ++sch->qstats.drops;
     274    return rc;
     275}
     276
     277static struct sk_buff *vboxNetFltQdiscDequeue(struct Qdisc *sch)
     278{
     279    PVBOXNETQDISCPRIV    pPriv = qdisc_priv(sch);
     280#ifdef VBOXNETFLT_QDISC_ENQUEUE
     281    --sch->q.qlen;
     282    return pPriv->pChild->dequeue(pPriv->pChild);
     283#else /*  VBOXNETFLT_QDISC_ENQUEUE */
     284    uint8_t              abHdrBuf[sizeof(RTNETETHERHDR) + sizeof(uint32_t) + RTNETIPV4_MIN_LEN];
     285    PCRTNETETHERHDR      pEtherHdr;
     286    PINTNETTRUNKSWPORT   pSwitchPort;
     287    struct sk_buff      *pSkb;
     288
     289    QDISC_LOG(("vboxNetFltDequeue: Enter pThis=%p\n", pPriv->pVBoxNetFlt));
     290
     291    while ((pSkb = pPriv->pChild->dequeue(pPriv->pChild)) != NULL)
     292    {
     293        struct sk_buff *pBuf;
     294        INTNETSWDECISION    enmDecision;
     295        uint32_t            cbHdrs = skb_headlen(pSkb);
     296
     297        --sch->q.qlen;
     298
     299        if (!VALID_PTR(pPriv->pVBoxNetFlt))
     300            break;
     301
     302        pEtherHdr = (PCRTNETETHERHDR)skb_header_pointer(pSkb, 0, sizeof(abHdrBuf), &abHdrBuf[0]);
     303        if (   !pEtherHdr
     304            || (pSwitchPort = pPriv->pVBoxNetFlt->pSwitchPort) == NULL
     305            || !VALID_PTR(pSwitchPort)
     306            )
     307            break;
     308
     309        cbHdrs = RT_MAX(cbHdrs, sizeof(abHdrBuf));
     310
     311#if 1
     312        /* Test stub due to missing implementation of pfnPreRecv */
     313        static uint8_t       tmpAddr[] = { 0x08, 0x00, 0x27, 0xBB, 0x1E, 0xA0 };
     314        if (memcmp(pEtherHdr, tmpAddr, 6) != 0)
     315            enmDecision = INTNETSWDECISION_BROADCAST;
     316        else
     317            enmDecision = INTNETSWDECISION_INTNET;
     318#else
     319        enmDecision = pSwitchPort->pfnPreRecv(pSwitchPort, pEtherHdr, cbHdrs, INTNETTRUNKDIR_HOST);
     320#endif
     321        if (enmDecision != INTNETSWDECISION_INTNET)
     322            break;
     323
     324        pBuf = skb_copy(pSkb, GFP_ATOMIC);
     325        pBuf->pkt_type = PACKET_OUTGOING;
     326        QDISC_LOG(("vboxNetFltDequeue: pThis=%p\n", pPriv->pVBoxNetFlt));
     327        vboxNetFltLinuxForwardToIntNet(pPriv->pVBoxNetFlt, pBuf);
     328        qdisc_drop(pSkb, sch);
     329        QDISC_LOG(("VBoxNetFlt: Packet for %02x:%02x:%02x:%02x:%02x:%02x dropped\n",
     330                   pSkb->data[0], pSkb->data[1], pSkb->data[2],
     331                   pSkb->data[3], pSkb->data[4], pSkb->data[5]));
     332    }
     333
     334    return pSkb;
     335#endif /*  VBOXNETFLT_QDISC_ENQUEUE */
     336}
     337
     338static unsigned int vboxNetFltQdiscDrop(struct Qdisc *sch)
     339{
     340    PVBOXNETQDISCPRIV pPriv = qdisc_priv(sch);
     341
     342    ++sch->qstats.drops;
     343    --sch->q.qlen;
     344    if (pPriv->pChild->ops->drop)
     345        return pPriv->pChild->ops->drop(pPriv->pChild);
     346
     347    return 0;
     348}
     349
     350static int vboxNetFltQdiscInit(struct Qdisc *sch, struct nlattr *opt)
     351{
     352    PVBOXNETQDISCPRIV pPriv = qdisc_priv(sch);
     353    struct net_device *pDev = qdisc_dev(sch);
     354
     355    pPriv->pVBoxNetFlt = NULL;
     356
     357    pPriv->ppSaved = kcalloc(QDISC_SAVED_NUM(pDev), sizeof(pPriv->ppSaved[0]),
     358                             GFP_KERNEL);
     359    if (!pPriv->ppSaved)
     360        return -ENOMEM;
     361
     362    pPriv->pChild = QDISC_CREATE(pDev, netdev_get_tx_queue(pDev, 0),
     363                                 &pfifo_qdisc_ops,
     364                                 TC_H_MAKE(TC_H_MAJ(sch->handle),
     365                                           TC_H_MIN(1)));
     366    if (!pPriv->pChild)
     367    {
     368        kfree(pPriv->ppSaved);
     369        pPriv->ppSaved = NULL;
     370        return -ENOMEM;
     371    }
     372
     373    return 0;
     374}
     375
     376static void vboxNetFltQdiscReset(struct Qdisc *sch)
     377{
     378    PVBOXNETQDISCPRIV pPriv = qdisc_priv(sch);
     379
     380    qdisc_reset(pPriv->pChild);
     381    sch->q.qlen = 0;
     382    sch->qstats.backlog = 0;
     383}
     384
     385static void vboxNetFltQdiscDestroy(struct Qdisc* sch)
     386{
     387    PVBOXNETQDISCPRIV pPriv = qdisc_priv(sch);
     388    struct net_device *pDev = qdisc_dev(sch);
     389
     390    qdisc_destroy(pPriv->pChild);
     391    pPriv->pChild = NULL;
     392
     393    if (pPriv->ppSaved)
     394    {
     395        int i;
     396        for (i = 0; i < QDISC_SAVED_NUM(pDev); i++)
     397            if (pPriv->ppSaved[i])
     398                qdisc_destroy(pPriv->ppSaved[i]);
     399        kfree(pPriv->ppSaved);
     400        pPriv->ppSaved = NULL;
     401    }
     402}
     403
     404static int vboxNetFltClassGraft(struct Qdisc *sch, unsigned long arg, struct Qdisc *pNew,
     405                                struct Qdisc **ppOld)
     406{
     407    PVBOXNETQDISCPRIV pPriv = qdisc_priv(sch);
     408
     409    if (pNew == NULL)
     410        pNew = &noop_qdisc;
     411
     412    sch_tree_lock(sch);
     413    *ppOld = pPriv->pChild;
     414    pPriv->pChild = pNew;
     415    qdisc_tree_decrease_qlen(*ppOld, (*ppOld)->q.qlen);
     416    qdisc_reset(*ppOld);
     417    sch_tree_unlock(sch);
     418
     419    return 0;
     420}
     421
     422static struct Qdisc *vboxNetFltClassLeaf(struct Qdisc *sch, unsigned long arg)
     423{
     424    PVBOXNETQDISCPRIV pPriv = qdisc_priv(sch);
     425    return pPriv->pChild;
     426}
     427
     428static unsigned long vboxNetFltClassGet(struct Qdisc *sch, u32 classid)
     429{
     430    return 1;
     431}
     432
     433static void vboxNetFltClassPut(struct Qdisc *sch, unsigned long arg)
     434{
     435}
     436
     437static int vboxNetFltClassChange(struct Qdisc *sch, u32 classid, u32 parentid,
     438                                 struct nlattr **tca, unsigned long *arg)
     439{
     440    return -ENOSYS;
     441}
     442
     443static int vboxNetFltClassDelete(struct Qdisc *sch, unsigned long arg)
     444{
     445    return -ENOSYS;
     446}
     447
     448static void vboxNetFltClassWalk(struct Qdisc *sch, struct qdisc_walker *walker)
     449{
     450    if (!walker->stop) {
     451        if (walker->count >= walker->skip)
     452            if (walker->fn(sch, 1, walker) < 0) {
     453                walker->stop = 1;
     454                return;
     455            }
     456        walker->count++;
     457    }
     458}
     459
     460static struct tcf_proto **vboxNetFltClassFindTcf(struct Qdisc *sch, unsigned long cl)
     461{
     462    return NULL;
     463}
     464
     465static int vboxNetFltClassDump(struct Qdisc *sch, unsigned long cl,
     466                               struct sk_buff *skb, struct tcmsg *tcm)
     467{
     468    PVBOXNETQDISCPRIV pPriv = qdisc_priv(sch);
     469
     470    if (cl != 1)
     471        return -ENOENT;
     472
     473    tcm->tcm_handle |= TC_H_MIN(1);
     474    tcm->tcm_info = pPriv->pChild->handle;
     475
     476    return 0;
     477}
     478
     479
     480static const struct Qdisc_class_ops g_VBoxNetFltClassOps =
     481{
     482    .graft     = vboxNetFltClassGraft,
     483    .leaf      = vboxNetFltClassLeaf,
     484    .get       = vboxNetFltClassGet,
     485    .put       = vboxNetFltClassPut,
     486    .change    = vboxNetFltClassChange,
     487    .delete    = vboxNetFltClassDelete,
     488    .walk      = vboxNetFltClassWalk,
     489    .tcf_chain = vboxNetFltClassFindTcf,
     490    .dump      = vboxNetFltClassDump,
     491};
     492
     493
     494struct Qdisc_ops g_VBoxNetFltQDiscOps = {
     495    .cl_ops    = &g_VBoxNetFltClassOps,
     496    .id        = "vboxnetflt",
     497    .priv_size = sizeof(struct VBoxNetQDiscPriv),
     498    .enqueue   = vboxNetFltQdiscEnqueue,
     499    .dequeue   = vboxNetFltQdiscDequeue,
     500    .peek      = qdisc_peek_dequeued,
     501    .drop      = vboxNetFltQdiscDrop,
     502    .init      = vboxNetFltQdiscInit,
     503    .reset     = vboxNetFltQdiscReset,
     504    .destroy   = vboxNetFltQdiscDestroy,
     505    .owner     = THIS_MODULE
     506};
     507
     508/*
     509 * If our qdisc is already attached to the device (that means the user
     510 * installed it from command line with 'tc' command) we simply update
     511 * the pointer to vboxnetflt instance in qdisc's private structure.
     512 * Otherwise we need to take some additional steps:
     513 * - Create our qdisc;
     514 * - Save all references to qdiscs;
     515 * - Replace our child with the first qdisc reference;
     516 * - Replace all references so they point to our qdisc.
     517 */
     518static void vboxNetFltLinuxQdiscInstall(PVBOXNETFLTINS pThis, struct net_device *pDev)
     519{
     520    int i;
     521    PVBOXNETQDISCPRIV pPriv;
     522
     523    struct Qdisc *pExisting = QDISC_GET(pDev);
     524    if (strcmp(pExisting->ops->id, "vboxnetflt"))
     525    {
     526        /* The existing qdisc is different from ours, let's create new one. */
     527        struct Qdisc *pNew = QDISC_CREATE(pDev, netdev_get_tx_queue(pDev, 0),
     528                                          &g_VBoxNetFltQDiscOps, TC_H_ROOT);
     529        if (!pNew)
     530            return; // TODO: Error?
     531
     532        if (!try_module_get(THIS_MODULE))
     533        {
     534            /*
     535             * This may cause a memory leak but calling qdisc_destroy()
     536             * is not an option as it will call module_put().
     537             */
     538            return;
     539        }
     540        pPriv = qdisc_priv(pNew);
     541
     542        qdisc_destroy(pPriv->pChild);
     543        pPriv->pChild = QDISC_GET(pDev);
     544        atomic_inc(&pPriv->pChild->refcnt);
     545        /*
     546         * There is no need in deactivating the device or acquiring any locks
     547         * prior changing qdiscs since we do not destroy the old qdisc.
     548         * Atomic replacement of pointers is enough.
     549         */
     550        /*
     551         * No need to change reference counters here as we merely move
     552         * the pointer and the reference counter of the newly allocated
     553         * qdisc is already 1.
     554         */
     555#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
     556        pPriv->ppSaved[0] = pDev->qdisc_sleeping;
     557        ASMAtomicWritePtr((void * volatile *)&pDev->qdisc_sleeping, pNew);
     558        ASMAtomicWritePtr((void * volatile *)&pDev->qdisc, pNew);
     559#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */
     560        for (i = 0; i < pDev->num_tx_queues; i++)
     561        {
     562            struct netdev_queue *pQueue = netdev_get_tx_queue(pDev, i);
     563
     564            pPriv->ppSaved[i] = pQueue->qdisc_sleeping;
     565            ASMAtomicWritePtr((void * volatile *)&pQueue->qdisc_sleeping, pNew);
     566            ASMAtomicWritePtr((void * volatile *)&pQueue->qdisc, pNew);
     567            if (i)
     568                atomic_inc(&pNew->refcnt);
     569        }
     570        /* Newer kernels store root qdisc in netdev structure as well. */
     571# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
     572        pPriv->ppSaved[pDev->num_tx_queues] = pDev->qdisc;
     573        ASMAtomicWritePtr((void * volatile *)&pDev->qdisc, pNew);
     574        atomic_inc(&pNew->refcnt);
     575# endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) */
     576#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */
     577    }
     578    else
     579    {
     580        /* We already have vboxnetflt qdisc, let's use it. */
     581        pPriv = qdisc_priv(pExisting);
     582    }
     583    ASMAtomicWritePtr((void * volatile *)&pPriv->pVBoxNetFlt, pThis);
     584    QDISC_LOG(("vboxNetFltLinuxInstallQdisc: pThis=%p\n", pPriv->pVBoxNetFlt));
     585}
     586
     587static void vboxNetFltLinuxQdiscRemove(PVBOXNETFLTINS pThis, struct net_device *pDev)
     588{
     589    int i;
     590    PVBOXNETQDISCPRIV pPriv;
     591    struct Qdisc *pQdisc;
     592    if (!pDev)
     593        pDev = (struct net_device *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev);
     594    if (!VALID_PTR(pDev))
     595    {
     596        printk("VBoxNetFlt: Failed to detach qdisc, invalid device pointer: %p\n",
     597               pDev);
     598        return; // TODO: Consider returing an error
     599    }
     600
     601
     602    pQdisc = QDISC_GET(pDev);
     603    if (strcmp(pQdisc->ops->id, "vboxnetflt"))
     604    {
     605        /* Looks like the user has replaced our qdisc manually. */
     606        printk("VBoxNetFlt: Failed to detach qdisc, wrong qdisc: %s\n",
     607               pQdisc->ops->id);
     608        return; // TODO: Consider returing an error
     609    }
     610
     611    pPriv = qdisc_priv(pQdisc);
     612    Assert(pPriv->pVBoxNetFlt == pThis);
     613    ASMAtomicWritePtr((void * volatile *)&pPriv->pVBoxNetFlt, NULL);
     614
     615    QDISC_LOG(("vboxNetFltLinuxQdiscRemove: refcnt=%d num_tx_queues=%d\n",
     616               atomic_read(&pQdisc->refcnt), pDev->num_tx_queues));
     617#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
     618    /* Play it safe, make sure the qdisc is not being used. */
     619    if (pPriv->ppSaved[0])
     620    {
     621        ASMAtomicWritePtr((void * volatile *)&pDev->qdisc_sleeping,
     622                          pPriv->ppSaved[0]);
     623        ASMAtomicWritePtr((void * volatile *)&pDev->qdisc,
     624                          pPriv->ppSaved[0]);
     625        pPriv->ppSaved[0] = NULL;
     626        while (QDISC_IS_BUSY(pDev, pQdisc))
     627            yield();
     628        qdisc_destroy(pQdisc); /* Destroy reference */
     629    }
     630#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */
     631    for (i = 0; i < pDev->num_tx_queues; i++)
     632    {
     633        struct netdev_queue *pQueue = netdev_get_tx_queue(pDev, i);
     634        if (pPriv->ppSaved[i])
     635        {
     636            Assert(pQueue->qdisc_sleeping == pQdisc);
     637            ASMAtomicWritePtr((void * volatile *)&pQueue->qdisc_sleeping,
     638                              pPriv->ppSaved[i]);
     639            ASMAtomicWritePtr((void * volatile *)&pQueue->qdisc,
     640                              pPriv->ppSaved[i]);
     641            pPriv->ppSaved[i] = NULL;
     642            while (QDISC_IS_BUSY(pDev, pQdisc))
     643                yield();
     644            qdisc_destroy(pQdisc); /* Destroy reference */
     645        }
     646    }
     647    /* Newer kernels store root qdisc in netdev structure as well. */
     648#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
     649    ASMAtomicWritePtr((void * volatile *)&pDev->qdisc,
     650                      pPriv->ppSaved[pDev->num_tx_queues]);
     651    pPriv->ppSaved[pDev->num_tx_queues] = NULL;
     652    while (QDISC_IS_BUSY(pDev, pQdisc))
     653        yield();
     654    qdisc_destroy(pQdisc); /* Destroy reference */
     655#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) */
     656#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */
     657
     658    /*
     659     * At this point all references to our qdisc should be gone
     660     * unless the user had installed it manually.
     661     */
     662    QDISC_LOG(("vboxNetFltLinuxRemoveQdisc: pThis=%p\n", pPriv->pVBoxNetFlt));
     663}
     664
     665#endif /* VBOXNETFLT_WITH_QDISC */
     666
     667
    163668/**
    164669 * Initialize module.
     
    187692        if (RT_SUCCESS(rc))
    188693        {
     694#ifdef VBOXNETFLT_WITH_QDISC
     695            /*memcpy(&g_VBoxNetFltQDiscOps, &pfifo_qdisc_ops, sizeof(g_VBoxNetFltQDiscOps));
     696            strcpy(g_VBoxNetFltQDiscOps.id, "vboxnetflt");
     697            g_VBoxNetFltQDiscOps.owner = THIS_MODULE;*/
     698            rc = register_qdisc(&g_VBoxNetFltQDiscOps);
     699            if (rc)
     700            {
     701                LogRel(("VBoxNetFlt: Failed to registed qdisc: %d\n", rc));
     702                return rc;
     703            }
     704#endif /* VBOXNETFLT_WITH_QDISC */
    189705            LogRel(("VBoxNetFlt: Successfully started.\n"));
    190706            return 0;
     
    213729    Assert(vboxNetFltCanUnload(&g_VBoxNetFltGlobals));
    214730
     731#ifdef VBOXNETFLT_WITH_QDISC
     732    unregister_qdisc(&g_VBoxNetFltQDiscOps);
     733#endif /* VBOXNETFLT_WITH_QDISC */
    215734    /*
    216735     * Undo the work done during start (in reverse order).
     
    225744    Log(("VBoxNetFltLinuxUnload - done\n"));
    226745}
     746
    227747
    228748/**
     
    13471867    vboxNetFltLinuxHookDev(pThis, pDev);
    13481868#endif
     1869#ifdef VBOXNETFLT_WITH_QDISC
     1870    vboxNetFltLinuxQdiscInstall(pThis, pDev);
     1871#endif /* VBOXNETFLT_WITH_QDISC */
    13491872
    13501873    /*
     
    13841907        vboxNetFltLinuxUnhookDev(pThis, pDev);
    13851908#endif
     1909#ifdef VBOXNETFLT_WITH_QDISC
     1910        vboxNetFltLinuxQdiscRemove(pThis, pDev);
     1911#endif /* VBOXNETFLT_WITH_QDISC */
    13861912        RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp);
    13871913        ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.pDev, NULL);
     
    14051931    vboxNetFltLinuxUnhookDev(pThis, pDev);
    14061932#endif
     1933#ifdef VBOXNETFLT_WITH_QDISC
     1934    vboxNetFltLinuxQdiscRemove(pThis, pDev);
     1935#endif /* VBOXNETFLT_WITH_QDISC */
    14071936
    14081937    RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp);
     
    16952224    vboxNetFltLinuxUnhookDev(pThis, NULL);
    16962225#endif
     2226#ifdef VBOXNETFLT_WITH_QDISC
     2227    vboxNetFltLinuxQdiscRemove(pThis, NULL);
     2228#endif /* VBOXNETFLT_WITH_QDISC */
    16972229
    16982230    /** @todo This code may race vboxNetFltLinuxUnregisterDevice (very very
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