VirtualBox

Ignore:
Timestamp:
Oct 18, 2011 1:38:03 PM (13 years ago)
Author:
vboxsync
Message:

netflt: code cleanup, removed qdisc alternative

File:
1 edited

Legend:

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

    r38549 r39018  
    5252
    5353#define VBOXNETFLT_WITH_FILTER_HOST2GUEST_SKBS_EXPERIMENT
    54 #ifdef CONFIG_NET_SCHED
    55 /*# define VBOXNETFLT_WITH_QDISC  Comment this out to disable qdisc support */
    56 # ifdef VBOXNETFLT_WITH_QDISC
    57 # include <net/pkt_sched.h>
    58 # endif /* VBOXNETFLT_WITH_QDISC */
    59 #endif
    6054
    6155
     
    9589#endif
    9690
    97 #ifdef VBOXNETFLT_WITH_QDISC
    98 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
    99 static inline int qdisc_drop(struct sk_buff *skb, struct Qdisc *sch)
    100 {
    101     kfree_skb(skb);
    102     sch->stats.drops++;
    103 
    104     return NET_XMIT_DROP;
    105 }
    106 # endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13) */
    107 #endif /* VBOXNETFLT_WITH_QDISC */
    108 
    10991#ifndef NET_IP_ALIGN
    11092# define NET_IP_ALIGN 2
     
    194176}
    195177#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12) */
    196 
    197 
    198 #ifdef VBOXNETFLT_WITH_QDISC
    199 //#define QDISC_LOG(x) printk x
    200 # define QDISC_LOG(x) do { } while (0)
    201 
    202 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
    203 #  define QDISC_CREATE(dev, queue, ops, parent) qdisc_create_dflt(dev, ops)
    204 # elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
    205 #  define QDISC_CREATE(dev, queue, ops, parent) qdisc_create_dflt(dev, ops, parent)
    206 # elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
    207 #  define QDISC_CREATE(dev, queue, ops, parent) qdisc_create_dflt(dev, queue, ops, parent)
    208 # else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) */
    209 #  define QDISC_CREATE(dev, queue, ops, parent) qdisc_create_dflt(queue, ops, parent)
    210 # endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) */
    211 
    212 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
    213 #  define qdisc_dev(qdisc) (qdisc->dev)
    214 #  define qdisc_pkt_len(skb) (skb->len)
    215 #  define QDISC_GET(dev) (dev->qdisc_sleeping)
    216 # else
    217 #  define QDISC_GET(dev) (netdev_get_tx_queue(dev, 0)->qdisc_sleeping)
    218 # endif
    219 
    220 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
    221 #  define QDISC_SAVED_NUM(dev) 1
    222 # elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
    223 #  define QDISC_SAVED_NUM(dev) dev->num_tx_queues
    224 # else
    225 #  define QDISC_SAVED_NUM(dev) dev->num_tx_queues+1
    226 # endif
    227 
    228 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
    229 #  define QDISC_IS_BUSY(dev, qdisc)  test_bit(__LINK_STATE_SCHED, &dev->state)
    230 # elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
    231 #  define QDISC_IS_BUSY(dev, qdisc) (test_bit(__QDISC_STATE_RUNNING, &qdisc->state) || \
    232                                     test_bit(__QDISC_STATE_SCHED, &qdisc->state))
    233 # else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) */
    234 #  define QDISC_IS_BUSY(dev, qdisc) (qdisc_is_running(qdisc) || \
    235                                     test_bit(__QDISC_STATE_SCHED, &qdisc->state))
    236 # endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) */
    237 
    238 struct VBoxNetQDiscPriv
    239 {
    240     /** Pointer to the single child qdisc. */
    241     struct Qdisc     *pChild;
    242     /*
    243      * Technically it is possible to have different qdiscs for different TX
    244      * queues so we have to save them all.
    245      */
    246     /** Pointer to the array of saved qdiscs. */
    247     struct Qdisc    **ppSaved;
    248     /** Pointer to the net filter instance. */
    249     PVBOXNETFLTINS    pVBoxNetFlt;
    250 };
    251 typedef struct VBoxNetQDiscPriv *PVBOXNETQDISCPRIV;
    252 
    253 //#define VBOXNETFLT_QDISC_ENQUEUE
    254 static int vboxNetFltQdiscEnqueue(struct sk_buff *skb, struct Qdisc *sch)
    255 {
    256     PVBOXNETQDISCPRIV   pPriv = qdisc_priv(sch);
    257     int                 rc;
    258 
    259 # ifdef VBOXNETFLT_QDISC_ENQUEUE
    260     if (VALID_PTR(pPriv->pVBoxNetFlt))
    261     {
    262         uint8_t              abHdrBuf[sizeof(RTNETETHERHDR) + sizeof(uint32_t) + RTNETIPV4_MIN_LEN];
    263         PCRTNETETHERHDR      pEtherHdr;
    264         PINTNETTRUNKSWPORT   pSwitchPort;
    265         uint32_t             cbHdrs = skb_headlen(skb);
    266 
    267         cbHdrs = RT_MIN(cbHdrs, sizeof(abHdrBuf));
    268         pEtherHdr = (PCRTNETETHERHDR)skb_header_pointer(skb, 0, cbHdrs, &abHdrBuf[0]);
    269         if (   pEtherHdr
    270             && (pSwitchPort = pPriv->pVBoxNetFlt->pSwitchPort) != NULL
    271             && VALID_PTR(pSwitchPort)
    272             && cbHdrs >= 6)
    273         {
    274             /** @todo consider reference counting, etc. */
    275             INTNETSWDECISION enmDecision = pSwitchPort->pfnPreRecv(pSwitchPort, pEtherHdr, cbHdrs, INTNETTRUNKDIR_HOST);
    276             if (enmDecision == INTNETSWDECISION_INTNET)
    277             {
    278                 struct sk_buff *pBuf = skb_copy(skb, GFP_ATOMIC);
    279                 pBuf->pkt_type = PACKET_OUTGOING;
    280                 vboxNetFltLinuxForwardToIntNet(pPriv->pVBoxNetFlt, pBuf);
    281                 qdisc_drop(skb, sch);
    282                 ++sch->bstats.packets;
    283                 sch->bstats.bytes += qdisc_pkt_len(skb);
    284                 return NET_XMIT_SUCCESS;
    285             }
    286         }
    287     }
    288 # endif /* VBOXNETFLT_QDISC_ENQUEUE */
    289     rc = pPriv->pChild->enqueue(skb, pPriv->pChild);
    290     if (rc == NET_XMIT_SUCCESS)
    291     {
    292         ++sch->q.qlen;
    293         ++sch->bstats.packets;
    294         sch->bstats.bytes += qdisc_pkt_len(skb);
    295     }
    296     else
    297         ++sch->qstats.drops;
    298     return rc;
    299 }
    300 
    301 static struct sk_buff *vboxNetFltQdiscDequeue(struct Qdisc *sch)
    302 {
    303     PVBOXNETQDISCPRIV    pPriv = qdisc_priv(sch);
    304 # ifdef VBOXNETFLT_QDISC_ENQUEUE
    305     --sch->q.qlen;
    306     return pPriv->pChild->dequeue(pPriv->pChild);
    307 # else /*  VBOXNETFLT_QDISC_ENQUEUE */
    308     uint8_t              abHdrBuf[sizeof(RTNETETHERHDR) + sizeof(uint32_t) + RTNETIPV4_MIN_LEN];
    309     PCRTNETETHERHDR      pEtherHdr;
    310     PINTNETTRUNKSWPORT   pSwitchPort;
    311     struct sk_buff      *pSkb;
    312 
    313     QDISC_LOG(("vboxNetFltDequeue: Enter pThis=%p\n", pPriv->pVBoxNetFlt));
    314 
    315     while ((pSkb = pPriv->pChild->dequeue(pPriv->pChild)) != NULL)
    316     {
    317         struct sk_buff     *pBuf;
    318         INTNETSWDECISION    enmDecision;
    319         uint32_t            cbHdrs;
    320 
    321         --sch->q.qlen;
    322 
    323         if (!VALID_PTR(pPriv->pVBoxNetFlt))
    324             break;
    325 
    326         cbHdrs = skb_headlen(pSkb);
    327         cbHdrs = RT_MIN(cbHdrs, sizeof(abHdrBuf));
    328         pEtherHdr = (PCRTNETETHERHDR)skb_header_pointer(pSkb, 0, cbHdrs, &abHdrBuf[0]);
    329         if (   !pEtherHdr
    330             || (pSwitchPort = pPriv->pVBoxNetFlt->pSwitchPort) == NULL
    331             || !VALID_PTR(pSwitchPort)
    332             || cbHdrs < 6)
    333             break;
    334 
    335         /** @todo consider reference counting, etc. */
    336         enmDecision = pSwitchPort->pfnPreRecv(pSwitchPort, pEtherHdr, cbHdrs, INTNETTRUNKDIR_HOST);
    337         if (enmDecision != INTNETSWDECISION_INTNET)
    338             break;
    339 
    340         pBuf = skb_copy(pSkb, GFP_ATOMIC);
    341         pBuf->pkt_type = PACKET_OUTGOING;
    342         QDISC_LOG(("vboxNetFltDequeue: pThis=%p\n", pPriv->pVBoxNetFlt));
    343         vboxNetFltLinuxForwardToIntNet(pPriv->pVBoxNetFlt, pBuf);
    344         qdisc_drop(pSkb, sch);
    345         QDISC_LOG(("VBoxNetFlt: Packet for %02x:%02x:%02x:%02x:%02x:%02x dropped\n",
    346                    pSkb->data[0], pSkb->data[1], pSkb->data[2],
    347                    pSkb->data[3], pSkb->data[4], pSkb->data[5]));
    348     }
    349 
    350     return pSkb;
    351 # endif /*  VBOXNETFLT_QDISC_ENQUEUE */
    352 }
    353 
    354 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
    355 static int vboxNetFltQdiscRequeue(struct sk_buff *skb, struct Qdisc *sch)
    356 {
    357     int rc;
    358     PVBOXNETQDISCPRIV pPriv = qdisc_priv(sch);
    359 
    360     rc = pPriv->pChild->ops->requeue(skb, pPriv->pChild);
    361     if (rc == 0)
    362     {
    363         sch->q.qlen++;
    364 #  if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
    365         sch->qstats.requeues++;
    366 #  endif
    367     }
    368 
    369     return rc;
    370 }
    371 # endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) */
    372 
    373 static unsigned int vboxNetFltQdiscDrop(struct Qdisc *sch)
    374 {
    375     PVBOXNETQDISCPRIV pPriv = qdisc_priv(sch);
    376     unsigned int cbLen;
    377 
    378     if (pPriv->pChild->ops->drop)
    379     {
    380         cbLen = pPriv->pChild->ops->drop(pPriv->pChild);
    381         if (cbLen != 0)
    382         {
    383             ++sch->qstats.drops;
    384             --sch->q.qlen;
    385             return cbLen;
    386         }
    387     }
    388 
    389     return 0;
    390 }
    391 
    392 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
    393 static int vboxNetFltQdiscInit(struct Qdisc *sch, struct rtattr *opt)
    394 # else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) */
    395 static int vboxNetFltQdiscInit(struct Qdisc *sch, struct nlattr *opt)
    396 # endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) */
    397 {
    398     PVBOXNETQDISCPRIV pPriv = qdisc_priv(sch);
    399     struct net_device *pDev = qdisc_dev(sch);
    400 
    401     pPriv->pVBoxNetFlt = NULL;
    402 
    403     pPriv->ppSaved = kcalloc(QDISC_SAVED_NUM(pDev), sizeof(pPriv->ppSaved[0]),
    404                              GFP_KERNEL);
    405     if (!pPriv->ppSaved)
    406         return -ENOMEM;
    407 
    408     pPriv->pChild = QDISC_CREATE(pDev, netdev_get_tx_queue(pDev, 0),
    409                                  &pfifo_qdisc_ops,
    410                                  TC_H_MAKE(TC_H_MAJ(sch->handle),
    411                                            TC_H_MIN(1)));
    412     if (!pPriv->pChild)
    413     {
    414         kfree(pPriv->ppSaved);
    415         pPriv->ppSaved = NULL;
    416         return -ENOMEM;
    417     }
    418 
    419     return 0;
    420 }
    421 
    422 static void vboxNetFltQdiscReset(struct Qdisc *sch)
    423 {
    424     PVBOXNETQDISCPRIV pPriv = qdisc_priv(sch);
    425 
    426     qdisc_reset(pPriv->pChild);
    427     sch->q.qlen = 0;
    428     sch->qstats.backlog = 0;
    429 }
    430 
    431 static void vboxNetFltQdiscDestroy(struct Qdisc* sch)
    432 {
    433     PVBOXNETQDISCPRIV pPriv = qdisc_priv(sch);
    434     struct net_device *pDev = qdisc_dev(sch);
    435 
    436     qdisc_destroy(pPriv->pChild);
    437     pPriv->pChild = NULL;
    438 
    439     if (pPriv->ppSaved)
    440     {
    441         int i;
    442         for (i = 0; i < QDISC_SAVED_NUM(pDev); i++)
    443             if (pPriv->ppSaved[i])
    444                 qdisc_destroy(pPriv->ppSaved[i]);
    445         kfree(pPriv->ppSaved);
    446         pPriv->ppSaved = NULL;
    447     }
    448 }
    449 
    450 static int vboxNetFltClassGraft(struct Qdisc *sch, unsigned long arg, struct Qdisc *pNew,
    451                                 struct Qdisc **ppOld)
    452 {
    453     PVBOXNETQDISCPRIV pPriv = qdisc_priv(sch);
    454 
    455     if (pNew == NULL)
    456         pNew = &noop_qdisc;
    457 
    458     sch_tree_lock(sch);
    459     *ppOld = pPriv->pChild;
    460     pPriv->pChild = pNew;
    461 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
    462     sch->q.qlen = 0;
    463 # else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) */
    464     qdisc_tree_decrease_qlen(*ppOld, (*ppOld)->q.qlen);
    465 # endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) */
    466     qdisc_reset(*ppOld);
    467     sch_tree_unlock(sch);
    468 
    469     return 0;
    470 }
    471 
    472 static struct Qdisc *vboxNetFltClassLeaf(struct Qdisc *sch, unsigned long arg)
    473 {
    474     PVBOXNETQDISCPRIV pPriv = qdisc_priv(sch);
    475     return pPriv->pChild;
    476 }
    477 
    478 static unsigned long vboxNetFltClassGet(struct Qdisc *sch, u32 classid)
    479 {
    480     return 1;
    481 }
    482 
    483 static void vboxNetFltClassPut(struct Qdisc *sch, unsigned long arg)
    484 {
    485 }
    486 
    487 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
    488 static int vboxNetFltClassChange(struct Qdisc *sch, u32 classid, u32 parentid,
    489                                  struct rtattr **tca, unsigned long *arg)
    490 # else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) */
    491 static int vboxNetFltClassChange(struct Qdisc *sch, u32 classid, u32 parentid,
    492                                  struct nlattr **tca, unsigned long *arg)
    493 # endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) */
    494 {
    495     return -ENOSYS;
    496 }
    497 
    498 static int vboxNetFltClassDelete(struct Qdisc *sch, unsigned long arg)
    499 {
    500     return -ENOSYS;
    501 }
    502 
    503 static void vboxNetFltClassWalk(struct Qdisc *sch, struct qdisc_walker *walker)
    504 {
    505     if (!walker->stop) {
    506         if (walker->count >= walker->skip)
    507             if (walker->fn(sch, 1, walker) < 0) {
    508                 walker->stop = 1;
    509                 return;
    510             }
    511         walker->count++;
    512     }
    513 }
    514 
    515 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
    516 static struct tcf_proto **vboxNetFltClassFindTcf(struct Qdisc *sch, unsigned long cl)
    517 {
    518     return NULL;
    519 }
    520 # endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32) */
    521 
    522 static int vboxNetFltClassDump(struct Qdisc *sch, unsigned long cl,
    523                                struct sk_buff *skb, struct tcmsg *tcm)
    524 {
    525     PVBOXNETQDISCPRIV pPriv = qdisc_priv(sch);
    526 
    527     if (cl != 1)
    528         return -ENOENT;
    529 
    530     tcm->tcm_handle |= TC_H_MIN(1);
    531     tcm->tcm_info = pPriv->pChild->handle;
    532 
    533     return 0;
    534 }
    535 
    536 
    537 static struct Qdisc_class_ops g_VBoxNetFltClassOps =
    538 {
    539     .graft     = vboxNetFltClassGraft,
    540     .leaf      = vboxNetFltClassLeaf,
    541     .get       = vboxNetFltClassGet,
    542     .put       = vboxNetFltClassPut,
    543     .change    = vboxNetFltClassChange,
    544     .delete    = vboxNetFltClassDelete,
    545     .walk      = vboxNetFltClassWalk,
    546 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
    547     .tcf_chain = vboxNetFltClassFindTcf,
    548 # endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32) */
    549     .dump      = vboxNetFltClassDump,
    550 };
    551 
    552 
    553 static struct Qdisc_ops g_VBoxNetFltQDiscOps = {
    554     .cl_ops    = &g_VBoxNetFltClassOps,
    555     .id        = "vboxnetflt",
    556     .priv_size = sizeof(struct VBoxNetQDiscPriv),
    557     .enqueue   = vboxNetFltQdiscEnqueue,
    558     .dequeue   = vboxNetFltQdiscDequeue,
    559 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
    560     .requeue   = vboxNetFltQdiscRequeue,
    561 # else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) */
    562     .peek      = qdisc_peek_dequeued,
    563 # endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) */
    564     .drop      = vboxNetFltQdiscDrop,
    565     .init      = vboxNetFltQdiscInit,
    566     .reset     = vboxNetFltQdiscReset,
    567     .destroy   = vboxNetFltQdiscDestroy,
    568     .owner     = THIS_MODULE
    569 };
    570 
    571 /*
    572  * If our qdisc is already attached to the device (that means the user
    573  * installed it from command line with 'tc' command) we simply update
    574  * the pointer to vboxnetflt instance in qdisc's private structure.
    575  * Otherwise we need to take some additional steps:
    576  * - Create our qdisc;
    577  * - Save all references to qdiscs;
    578  * - Replace our child with the first qdisc reference;
    579  * - Replace all references so they point to our qdisc.
    580  */
    581 static void vboxNetFltLinuxQdiscInstall(PVBOXNETFLTINS pThis, struct net_device *pDev)
    582 {
    583 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
    584     int i;
    585 # endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */
    586     PVBOXNETQDISCPRIV pPriv;
    587 
    588     struct Qdisc *pExisting = QDISC_GET(pDev);
    589     /* Do not install our qdisc for devices with no TX queues */
    590     if (!pExisting->enqueue)
    591         return;
    592     if (strcmp(pExisting->ops->id, "vboxnetflt"))
    593     {
    594         /* The existing qdisc is different from ours, let's create new one. */
    595         struct Qdisc *pNew = QDISC_CREATE(pDev, netdev_get_tx_queue(pDev, 0),
    596                                           &g_VBoxNetFltQDiscOps, TC_H_ROOT);
    597         if (!pNew)
    598             return; // TODO: Error?
    599 
    600         if (!try_module_get(THIS_MODULE))
    601         {
    602             /*
    603              * This may cause a memory leak but calling qdisc_destroy()
    604              * is not an option as it will call module_put().
    605              */
    606             return;
    607         }
    608         pPriv = qdisc_priv(pNew);
    609 
    610         qdisc_destroy(pPriv->pChild);
    611         pPriv->pChild = QDISC_GET(pDev);
    612         atomic_inc(&pPriv->pChild->refcnt);
    613         /*
    614          * There is no need in deactivating the device or acquiring any locks
    615          * prior changing qdiscs since we do not destroy the old qdisc.
    616          * Atomic replacement of pointers is enough.
    617          */
    618         /*
    619          * No need to change reference counters here as we merely move
    620          * the pointer and the reference counter of the newly allocated
    621          * qdisc is already 1.
    622          */
    623 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
    624         pPriv->ppSaved[0] = pDev->qdisc_sleeping;
    625         ASMAtomicWritePtr(&pDev->qdisc_sleeping, pNew);
    626         ASMAtomicWritePtr(&pDev->qdisc, pNew);
    627 # else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */
    628         for (i = 0; i < pDev->num_tx_queues; i++)
    629         {
    630             struct netdev_queue *pQueue = netdev_get_tx_queue(pDev, i);
    631 
    632             pPriv->ppSaved[i] = pQueue->qdisc_sleeping;
    633             ASMAtomicWritePtr(&pQueue->qdisc_sleeping, pNew);
    634             ASMAtomicWritePtr(&pQueue->qdisc, pNew);
    635             if (i)
    636                 atomic_inc(&pNew->refcnt);
    637         }
    638         /* Newer kernels store root qdisc in netdev structure as well. */
    639 #  if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
    640         pPriv->ppSaved[pDev->num_tx_queues] = pDev->qdisc;
    641         ASMAtomicWritePtr(&pDev->qdisc, pNew);
    642         atomic_inc(&pNew->refcnt);
    643 #  endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) */
    644 # endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */
    645         /* Sync the queue len with our child */
    646         pNew->q.qlen = pPriv->pChild->q.qlen;
    647     }
    648     else
    649     {
    650         /* We already have vboxnetflt qdisc, let's use it. */
    651         pPriv = qdisc_priv(pExisting);
    652     }
    653     ASMAtomicWritePtr(&pPriv->pVBoxNetFlt, pThis);
    654     QDISC_LOG(("vboxNetFltLinuxInstallQdisc: pThis=%p\n", pPriv->pVBoxNetFlt));
    655 }
    656 
    657 static void vboxNetFltLinuxQdiscRemove(PVBOXNETFLTINS pThis, struct net_device *pDev)
    658 {
    659 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
    660     int i;
    661 # endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */
    662     PVBOXNETQDISCPRIV pPriv;
    663     struct Qdisc *pQdisc, *pChild;
    664     if (!pDev)
    665         pDev = ASMAtomicUoReadPtrT(&pThis->u.s.pDev, struct net_device *);
    666     if (!VALID_PTR(pDev))
    667     {
    668         printk("VBoxNetFlt: Failed to detach qdisc, invalid device pointer: %p\n",
    669                pDev);
    670         return; // TODO: Consider returing an error
    671     }
    672 
    673 
    674     pQdisc = QDISC_GET(pDev);
    675     if (strcmp(pQdisc->ops->id, "vboxnetflt"))
    676     {
    677         if (pQdisc->enqueue)
    678         {
    679             /* Looks like the user has replaced our qdisc manually. */
    680             printk("VBoxNetFlt: Failed to detach qdisc, wrong qdisc: %s\n",
    681                    pQdisc->ops->id);
    682         }
    683         return; // TODO: Consider returing an error
    684     }
    685 
    686     pPriv = qdisc_priv(pQdisc);
    687     Assert(pPriv->pVBoxNetFlt == pThis);
    688     ASMAtomicWriteNullPtr(&pPriv->pVBoxNetFlt);
    689     pChild = ASMAtomicXchgPtrT(&pPriv->pChild, &noop_qdisc, struct Qdisc *);
    690     qdisc_destroy(pChild); /* It won't be the last reference. */
    691 
    692     QDISC_LOG(("vboxNetFltLinuxQdiscRemove: refcnt=%d num_tx_queues=%d\n",
    693                atomic_read(&pQdisc->refcnt), pDev->num_tx_queues));
    694 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
    695     /* Play it safe, make sure the qdisc is not being used. */
    696     if (pPriv->ppSaved[0])
    697     {
    698         ASMAtomicWritePtr(&pDev->qdisc_sleeping, pPriv->ppSaved[0]);
    699         ASMAtomicWritePtr(&pDev->qdisc, pPriv->ppSaved[0]);
    700         pPriv->ppSaved[0] = NULL;
    701         while (QDISC_IS_BUSY(pDev, pQdisc))
    702             yield();
    703         qdisc_destroy(pQdisc); /* Destroy reference */
    704     }
    705 # else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */
    706     for (i = 0; i < pDev->num_tx_queues; i++)
    707     {
    708         struct netdev_queue *pQueue = netdev_get_tx_queue(pDev, i);
    709         if (pPriv->ppSaved[i])
    710         {
    711             Assert(pQueue->qdisc_sleeping == pQdisc);
    712             ASMAtomicWritePtr(&pQueue->qdisc_sleeping, pPriv->ppSaved[i]);
    713             ASMAtomicWritePtr(&pQueue->qdisc, pPriv->ppSaved[i]);
    714             pPriv->ppSaved[i] = NULL;
    715             while (QDISC_IS_BUSY(pDev, pQdisc))
    716                 yield();
    717             qdisc_destroy(pQdisc); /* Destroy reference */
    718         }
    719     }
    720     /* Newer kernels store root qdisc in netdev structure as well. */
    721 #  if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
    722     ASMAtomicWritePtr(&pDev->qdisc, pPriv->ppSaved[pDev->num_tx_queues]);
    723     pPriv->ppSaved[pDev->num_tx_queues] = NULL;
    724     while (QDISC_IS_BUSY(pDev, pQdisc))
    725         yield();
    726     qdisc_destroy(pQdisc); /* Destroy reference */
    727 #  endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) */
    728 # endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */
    729 
    730     /*
    731      * At this point all references to our qdisc should be gone
    732      * unless the user had installed it manually.
    733      */
    734     QDISC_LOG(("vboxNetFltLinuxRemoveQdisc: pThis=%p\n", pPriv->pVBoxNetFlt));
    735 }
    736 
    737 #endif /* VBOXNETFLT_WITH_QDISC */
    738178
    739179
     
    764204        if (RT_SUCCESS(rc))
    765205        {
    766 #ifdef VBOXNETFLT_WITH_QDISC
    767             /*memcpy(&g_VBoxNetFltQDiscOps, &pfifo_qdisc_ops, sizeof(g_VBoxNetFltQDiscOps));
    768             strcpy(g_VBoxNetFltQDiscOps.id, "vboxnetflt");
    769             g_VBoxNetFltQDiscOps.owner = THIS_MODULE;*/
    770             rc = register_qdisc(&g_VBoxNetFltQDiscOps);
    771             if (rc)
    772             {
    773                 LogRel(("VBoxNetFlt: Failed to registered qdisc: %d\n", rc));
    774                 return rc;
    775             }
    776 #endif /* VBOXNETFLT_WITH_QDISC */
    777206            LogRel(("VBoxNetFlt: Successfully started.\n"));
    778207            return 0;
     
    801230    Assert(vboxNetFltCanUnload(&g_VBoxNetFltGlobals));
    802231
    803 #ifdef VBOXNETFLT_WITH_QDISC
    804     unregister_qdisc(&g_VBoxNetFltQDiscOps);
    805 #endif /* VBOXNETFLT_WITH_QDISC */
    806232    /*
    807233     * Undo the work done during start (in reverse order).
     
    20891515    vboxNetFltLinuxHookDev(pThis, pDev);
    20901516#endif
    2091 #ifdef VBOXNETFLT_WITH_QDISC
    2092     vboxNetFltLinuxQdiscInstall(pThis, pDev);
    2093 #endif /* VBOXNETFLT_WITH_QDISC */
    20941517
    20951518    /*
     
    21351558        vboxNetFltLinuxUnhookDev(pThis, pDev);
    21361559#endif
    2137 #ifdef VBOXNETFLT_WITH_QDISC
    2138         vboxNetFltLinuxQdiscRemove(pThis, pDev);
    2139 #endif /* VBOXNETFLT_WITH_QDISC */
    21401560        RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp);
    21411561        ASMAtomicUoWriteNullPtr(&pThis->u.s.pDev);
     
    21661586    vboxNetFltLinuxUnhookDev(pThis, pDev);
    21671587#endif
    2168 #ifdef VBOXNETFLT_WITH_QDISC
    2169     vboxNetFltLinuxQdiscRemove(pThis, pDev);
    2170 #endif /* VBOXNETFLT_WITH_QDISC */
    21711588
    21721589    RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp);
     
    24261843int vboxNetFltOsDisconnectIt(PVBOXNETFLTINS pThis)
    24271844{
    2428 #ifdef VBOXNETFLT_WITH_QDISC
    2429     vboxNetFltLinuxQdiscRemove(pThis, NULL);
    2430 #endif /* VBOXNETFLT_WITH_QDISC */
    24311845    /*
    24321846     * Remove packet handler when we get disconnected from internal switch as
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