Changeset 39018 in vbox for trunk/src/VBox/HostDrivers/VBoxNetFlt/linux
- Timestamp:
- Oct 18, 2011 1:38:03 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c
r38549 r39018 52 52 53 53 #define VBOXNETFLT_WITH_FILTER_HOST2GUEST_SKBS_EXPERIMENT 54 #ifdef CONFIG_NET_SCHED55 /*# define VBOXNETFLT_WITH_QDISC Comment this out to disable qdisc support */56 # ifdef VBOXNETFLT_WITH_QDISC57 # include <net/pkt_sched.h>58 # endif /* VBOXNETFLT_WITH_QDISC */59 #endif60 54 61 55 … … 95 89 #endif 96 90 97 #ifdef VBOXNETFLT_WITH_QDISC98 # 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 109 91 #ifndef NET_IP_ALIGN 110 92 # define NET_IP_ALIGN 2 … … 194 176 } 195 177 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12) */ 196 197 198 #ifdef VBOXNETFLT_WITH_QDISC199 //#define QDISC_LOG(x) printk x200 # 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 # else217 # define QDISC_GET(dev) (netdev_get_tx_queue(dev, 0)->qdisc_sleeping)218 # endif219 220 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)221 # define QDISC_SAVED_NUM(dev) 1222 # elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)223 # define QDISC_SAVED_NUM(dev) dev->num_tx_queues224 # else225 # define QDISC_SAVED_NUM(dev) dev->num_tx_queues+1226 # endif227 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 VBoxNetQDiscPriv239 {240 /** Pointer to the single child qdisc. */241 struct Qdisc *pChild;242 /*243 * Technically it is possible to have different qdiscs for different TX244 * 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_ENQUEUE254 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_ENQUEUE260 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 ( pEtherHdr270 && (pSwitchPort = pPriv->pVBoxNetFlt->pSwitchPort) != NULL271 && 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 else297 ++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_ENQUEUE305 --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 ( !pEtherHdr330 || (pSwitchPort = pPriv->pVBoxNetFlt->pSwitchPort) == NULL331 || !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 # endif367 }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_MODULE569 };570 571 /*572 * If our qdisc is already attached to the device (that means the user573 * installed it from command line with 'tc' command) we simply update574 * 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 locks615 * 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 move620 * the pointer and the reference counter of the newly allocated621 * 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 else649 {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 error671 }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 error684 }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 gone732 * unless the user had installed it manually.733 */734 QDISC_LOG(("vboxNetFltLinuxRemoveQdisc: pThis=%p\n", pPriv->pVBoxNetFlt));735 }736 737 #endif /* VBOXNETFLT_WITH_QDISC */738 178 739 179 … … 764 204 if (RT_SUCCESS(rc)) 765 205 { 766 #ifdef VBOXNETFLT_WITH_QDISC767 /*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 */777 206 LogRel(("VBoxNetFlt: Successfully started.\n")); 778 207 return 0; … … 801 230 Assert(vboxNetFltCanUnload(&g_VBoxNetFltGlobals)); 802 231 803 #ifdef VBOXNETFLT_WITH_QDISC804 unregister_qdisc(&g_VBoxNetFltQDiscOps);805 #endif /* VBOXNETFLT_WITH_QDISC */806 232 /* 807 233 * Undo the work done during start (in reverse order). … … 2089 1515 vboxNetFltLinuxHookDev(pThis, pDev); 2090 1516 #endif 2091 #ifdef VBOXNETFLT_WITH_QDISC2092 vboxNetFltLinuxQdiscInstall(pThis, pDev);2093 #endif /* VBOXNETFLT_WITH_QDISC */2094 1517 2095 1518 /* … … 2135 1558 vboxNetFltLinuxUnhookDev(pThis, pDev); 2136 1559 #endif 2137 #ifdef VBOXNETFLT_WITH_QDISC2138 vboxNetFltLinuxQdiscRemove(pThis, pDev);2139 #endif /* VBOXNETFLT_WITH_QDISC */2140 1560 RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); 2141 1561 ASMAtomicUoWriteNullPtr(&pThis->u.s.pDev); … … 2166 1586 vboxNetFltLinuxUnhookDev(pThis, pDev); 2167 1587 #endif 2168 #ifdef VBOXNETFLT_WITH_QDISC2169 vboxNetFltLinuxQdiscRemove(pThis, pDev);2170 #endif /* VBOXNETFLT_WITH_QDISC */2171 1588 2172 1589 RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); … … 2426 1843 int vboxNetFltOsDisconnectIt(PVBOXNETFLTINS pThis) 2427 1844 { 2428 #ifdef VBOXNETFLT_WITH_QDISC2429 vboxNetFltLinuxQdiscRemove(pThis, NULL);2430 #endif /* VBOXNETFLT_WITH_QDISC */2431 1845 /* 2432 1846 * Remove packet handler when we get disconnected from internal switch as
Note:
See TracChangeset
for help on using the changeset viewer.