Ticket #3056: VBoxNetFlt-linux.c.patch
| File VBoxNetFlt-linux.c.patch, 12.4 KB (added by , 16 years ago) |
|---|
-
VBoxNetFlt-linux.c
old new 1 /* $Id: VBoxNetFlt-linux.c 41 144 2008-12-17 09:20:11Z frank$ */1 /* $Id: VBoxNetFlt-linux.c 41779 2009-01-20 11:13:08Z aleksey $ */ 2 2 /** @file 3 3 * VBoxNetFlt - Network Filter Driver (Host), Linux Specific Code. 4 4 */ … … 70 70 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10) 71 71 # define VBOX_SKB_CHECKSUM_HELP(skb) skb_checksum_help(skb, 0) 72 72 # else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10) */ 73 # define VBOX_SKB_CHECKSUM_HELP(skb) skb_checksum_help(&skb, 0) 73 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 7) 74 # define VBOX_SKB_CHECKSUM_HELP(skb) skb_checksum_help(&skb, 0) 75 # else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 7) */ 76 # define VBOX_SKB_CHECKSUM_HELP(skb) (!skb_checksum_help(skb)) 77 # endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 7) */ 74 78 # endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10) */ 75 79 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) */ 76 80 … … 83 87 # define VBOX_SKB_GSO_SEGMENT(skb) NULL 84 88 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) */ 85 89 90 #ifndef NET_IP_ALIGN 91 # define NET_IP_ALIGN 2 92 #endif 93 86 94 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12) 87 95 unsigned dev_get_flags(const struct net_device *dev) 88 96 { … … 114 122 /** 115 123 * The (common) global data. 116 124 */ 125 #ifdef RT_ARCH_AMD64 126 /** 127 * Memory for the executable memory heap (in IPRT). 128 */ 129 extern uint8_t g_abExecMemory[1572864]; /* 1.5 MB */ 130 __asm__(".section execmemory, \"awx\", @progbits\n\t" 131 ".align 32\n\t" 132 ".globl g_abExecMemory\n" 133 "g_abExecMemory:\n\t" 134 ".zero 1572864\n\t" 135 ".type g_abExecMemory, @object\n\t" 136 ".size g_abExecMemory, 1572864\n\t" 137 ".text\n\t"); 138 #endif 139 117 140 static VBOXNETFLTGLOBALS g_VBoxNetFltGlobals; 118 141 119 142 module_init(VBoxNetFltLinuxInit); … … 142 165 static int __init VBoxNetFltLinuxInit(void) 143 166 { 144 167 int rc; 145 Log(("VBoxNetFltLinuxInit\n"));146 147 168 /* 148 169 * Initialize IPRT. 149 170 */ 150 171 rc = RTR0Init(0); 151 172 if (RT_SUCCESS(rc)) 152 173 { 174 #ifdef RT_ARCH_AMD64 175 rc = RTR0MemExecDonate(&g_abExecMemory[0], sizeof(g_abExecMemory)); 176 printk("VBoxNetFlt: dbg - g_abExecMemory=%p\n", (void *)&g_abExecMemory[0]); 177 if (RT_FAILURE(rc)) 178 { 179 printk("VBoxNetFlt: failed to donate exec memory, no logging will be available.\n"); 180 } 181 #endif 182 Log(("VBoxNetFltLinuxInit\n")); 183 153 184 /* 154 185 * Initialize the globals and connect to the support driver. 155 186 * … … 259 290 } 260 291 261 292 #define VBOXNETFLT_CB_TAG 0xA1C9D7C3 262 #define VBOXNETFLT_SKB_ CB(skb) (*(uint32_t*)&((skb)->cb[0]))293 #define VBOXNETFLT_SKB_TAG(skb) (*(uint32_t*)&((skb)->cb[sizeof((skb)->cb)-sizeof(uint32_t)])) 263 294 264 295 /** 265 296 * Checks whether this is an mbuf created by vboxNetFltLinuxMBufFromSG, … … 270 301 */ 271 302 DECLINLINE(bool) vboxNetFltLinuxSkBufIsOur(struct sk_buff *pBuf) 272 303 { 273 return VBOXNETFLT_SKB_ CB(pBuf) == VBOXNETFLT_CB_TAG ;304 return VBOXNETFLT_SKB_TAG(pBuf) == VBOXNETFLT_CB_TAG ; 274 305 } 275 306 276 307 … … 322 353 VBOX_SKB_RESET_NETWORK_HDR(pPkt); 323 354 /* Restore ethernet header back. */ 324 355 skb_push(pPkt, ETH_HLEN); 356 VBOX_SKB_RESET_MAC_HDR(pPkt); 325 357 } 326 VBOX_SKB_RESET_MAC_HDR(pPkt); 327 VBOXNETFLT_SKB_CB(pPkt) = VBOXNETFLT_CB_TAG; 358 VBOXNETFLT_SKB_TAG(pPkt) = VBOXNETFLT_CB_TAG; 328 359 329 360 return pPkt; 330 361 } … … 413 444 pSG->cSegsUsed++; 414 445 } 415 446 #endif 416 Log 2(("vboxNetFltLinuxSkBufToSG: allocated=%d, segments=%d frags=%d next=%p frag_list=%p pkt_type=%x fSrc=%x\n",447 Log4(("vboxNetFltLinuxSkBufToSG: allocated=%d, segments=%d frags=%d next=%p frag_list=%p pkt_type=%x fSrc=%x\n", 417 448 pSG->cSegsAlloc, pSG->cSegsUsed, skb_shinfo(pBuf)->nr_frags, pBuf->next, skb_shinfo(pBuf)->frag_list, pBuf->pkt_type, fSrc)); 418 449 for (i = 0; i < pSG->cSegsUsed; i++) 419 Log 2(("vboxNetFltLinuxSkBufToSG: #%d: cb=%d pv=%p\n",450 Log4(("vboxNetFltLinuxSkBufToSG: #%d: cb=%d pv=%p\n", 420 451 i, pSG->aSegs[i].cb, pSG->aSegs[i].pv)); 421 452 } 422 453 … … 430 461 * @param fSrc Where the packet (allegedly) comes from, one INTNETTRUNKDIR_* value. 431 462 * @param eProtocol The protocol. 432 463 */ 464 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) 433 465 static int vboxNetFltLinuxPacketHandler(struct sk_buff *pBuf, 434 466 struct net_device *pSkbDev, 435 467 struct packet_type *pPacketType, 436 468 struct net_device *pOrigDev) 469 #else 470 static int vboxNetFltLinuxPacketHandler(struct sk_buff *pBuf, 471 struct net_device *pSkbDev, 472 struct packet_type *pPacketType) 473 #endif 437 474 { 438 475 PVBOXNETFLTINS pThis; 439 476 struct net_device *pDev; 477 LogFlow(("vboxNetFltLinuxPacketHandler: pBuf=%p pSkbDev=%p pPacketType=%p\n", 478 pBuf, pSkbDev, pPacketType)); 440 479 /* 441 480 * Drop it immediately? 442 481 */ 443 Log2(("vboxNetFltLinuxPacketHandler: pBuf=%p pSkbDev=%p pPacketType=%p pOrigDev=%p\n",444 pBuf, pSkbDev, pPacketType, pOrigDev));445 482 if (!pBuf) 446 483 return 0; 484 447 485 pThis = VBOX_FLT_PT_TO_INST(pPacketType); 448 486 pDev = (struct net_device *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev); 449 487 if (pThis->u.s.pDev != pSkbDev) … … 452 490 return 0; 453 491 } 454 492 493 Log4(("vboxNetFltLinuxPacketHandler: pBuf->cb dump:\n%.*Rhxd\n", sizeof(pBuf->cb), pBuf->cb)); 455 494 if (vboxNetFltLinuxSkBufIsOur(pBuf)) 456 495 { 496 Log2(("vboxNetFltLinuxPacketHandler: got our own sk_buff, drop it.\n")); 457 497 dev_kfree_skb(pBuf); 458 498 return 0; 459 499 } 460 500 501 #ifndef VBOXNETFLT_SG_SUPPORT 502 { 503 /* 504 * Get rid of fragmented packets, they cause too much trouble. 505 */ 506 struct sk_buff *pCopy = skb_copy(pBuf, GFP_ATOMIC); 507 kfree_skb(pBuf); 508 if (!pCopy) 509 { 510 LogRel(("VBoxNetFlt: Failed to allocate packet buffer, dropping the packet.\n")); 511 return 0; 512 } 513 pBuf = pCopy; 514 } 515 #endif 516 461 517 /* Add the packet to transmit queue and schedule the bottom half. */ 462 518 skb_queue_tail(&pThis->u.s.XmitQueue, pBuf); 463 519 schedule_work(&pThis->u.s.XmitTask); 464 Log 2(("vboxNetFltLinuxPacketHandler: scheduled work %p for sk_buff %p\n",520 Log4(("vboxNetFltLinuxPacketHandler: scheduled work %p for sk_buff %p\n", 465 521 &pThis->u.s.XmitTask, pBuf)); 466 522 /* It does not really matter what we return, it is ignored by the kernel. */ 467 523 return 0; … … 500 556 dev_kfree_skb(pBuf); 501 557 } 502 558 559 #ifndef LOG_ENABLED 560 #define vboxNetFltDumpPacket(a, b, c, d) 561 #else 562 static void vboxNetFltDumpPacket(PINTNETSG pSG, bool fEgress, const char *pszWhere, int iIncrement) 563 { 564 uint8_t *pInt, *pExt; 565 static int iPacketNo = 1; 566 iPacketNo += iIncrement; 567 if (fEgress) 568 { 569 pExt = pSG->aSegs[0].pv; 570 pInt = pExt + 6; 571 } 572 else 573 { 574 pInt = pSG->aSegs[0].pv; 575 pExt = pInt + 6; 576 } 577 Log(("VBoxNetFlt: (int)%02x:%02x:%02x:%02x:%02x:%02x" 578 " %s (%s)%02x:%02x:%02x:%02x:%02x:%02x (%u bytes) packet #%u\n", 579 pInt[0], pInt[1], pInt[2], pInt[3], pInt[4], pInt[5], 580 fEgress ? "-->" : "<--", pszWhere, 581 pExt[0], pExt[1], pExt[2], pExt[3], pExt[4], pExt[5], 582 pSG->cbTotal, iPacketNo)); 583 Log3(("%.*Rhxd\n", pSG->aSegs[0].cb, pSG->aSegs[0].pv)); 584 } 585 #endif 586 503 587 static int vboxNetFltLinuxForwardSegment(PVBOXNETFLTINS pThis, struct sk_buff *pBuf, uint32_t fSrc) 504 588 { 505 589 unsigned cSegs = vboxNetFltLinuxSGSegments(pThis, pBuf); … … 515 599 vboxNetFltLinuxSkBufToSG(pThis, pBuf, pSG, cSegs, fSrc); 516 600 517 601 pTmp = pSG->aSegs[0].pv; 518 Log(("VBoxNetFlt: (int)%02x:%02x:%02x:%02x:%02x:%02x" 519 " <-- (%s)%02x:%02x:%02x:%02x:%02x:%02x (%u bytes)\n", 520 pTmp[0], pTmp[1], pTmp[2], pTmp[3], pTmp[4], pTmp[5], 521 (fSrc & INTNETTRUNKDIR_HOST) ? "host" : "wire", 522 pTmp[6], pTmp[7], pTmp[8], pTmp[9], pTmp[10], pTmp[11], 523 pSG->cbTotal)); 602 vboxNetFltDumpPacket(pSG, false, (fSrc & INTNETTRUNKDIR_HOST) ? "host" : "wire", 1); 524 603 pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, fSrc); 525 Log 2(("VBoxNetFlt: Dropping the sk_buff.\n"));604 Log4(("VBoxNetFlt: Dropping the sk_buff.\n")); 526 605 vboxNetFltLinuxFreeSkBuff(pBuf, pSG); 527 606 } 528 607 … … 533 612 { 534 613 uint32_t fSrc = pBuf->pkt_type == PACKET_OUTGOING ? INTNETTRUNKDIR_HOST : INTNETTRUNKDIR_WIRE; 535 614 536 #ifndef VBOXNETFLT_SG_SUPPORT537 /*538 * Get rid of fragmented packets, they cause too much trouble.539 */540 struct sk_buff *pCopy = skb_copy(pBuf, GFP_KERNEL);541 kfree_skb(pBuf);542 if (!pCopy)543 {544 LogRel(("VBoxNetFlt: Failed to allocate packet buffer, dropping the packet.\n"));545 return;546 }547 pBuf = pCopy;548 #endif549 550 615 if (VBOX_SKB_IS_GSO(pBuf)) 551 616 { 552 617 /* Need to segment the packet */ … … 578 643 */ 579 644 } 580 645 646 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) 581 647 static void vboxNetFltLinuxXmitTask(struct work_struct *pWork) 648 #else 649 static void vboxNetFltLinuxXmitTask(void *pWork) 650 #endif 582 651 { 583 652 struct sk_buff *pBuf; 584 653 bool fActive; 585 654 PVBOXNETFLTINS pThis; 586 655 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; 587 656 588 Log 2(("vboxNetFltLinuxXmitTask: Got work %p.\n", pWork));657 Log4(("vboxNetFltLinuxXmitTask: Got work %p.\n", pWork)); 589 658 pThis = VBOX_FLT_XT_TO_INST(pWork); 590 659 /* 591 660 * Active? Retain the instance and increment the busy counter. … … 779 848 return !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost); 780 849 } 781 850 782 783 851 int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst) 784 852 { 785 uint8_t *pTmp;786 853 struct net_device * pDev; 787 854 int err; 788 855 int rc = VINF_SUCCESS; 789 856 790 857 LogFlow(("vboxNetFltPortOsXmit: pThis=%p (%s)\n", pThis, pThis->szName)); 791 858 792 pTmp = pSG->aSegs[0].pv;793 794 859 pDev = vboxNetFltLinuxRetainNetDev(pThis); 795 860 if (pDev) 796 861 { … … 802 867 struct sk_buff *pBuf = vboxNetFltLinuxSkBufFromSG(pThis, pSG, true); 803 868 if (pBuf) 804 869 { 805 Log(("VBoxNetFlt: (int)%02x:%02x:%02x:%02x:%02x:%02x" 806 " --> (wire)%02x:%02x:%02x:%02x:%02x:%02x (%u bytes)\n", 807 pTmp[6], pTmp[7], pTmp[8], pTmp[9], pTmp[10], pTmp[11], 808 pTmp[0], pTmp[1], pTmp[2], pTmp[3], pTmp[4], pTmp[5], 809 pSG->cbTotal)); 870 vboxNetFltDumpPacket(pSG, true, "wire", 1); 871 Log4(("vboxNetFltPortOsXmit: pBuf->cb dump:\n%.*Rhxd\n", sizeof(pBuf->cb), pBuf->cb)); 872 Log4(("vboxNetFltPortOsXmit: dev_queue_xmit(%p)\n", pBuf)); 810 873 err = dev_queue_xmit(pBuf); 811 874 if (err) 812 875 rc = RTErrConvertFromErrno(err); … … 823 886 struct sk_buff *pBuf = vboxNetFltLinuxSkBufFromSG(pThis, pSG, false); 824 887 if (pBuf) 825 888 { 826 Log(("VBoxNetFlt: (int)%02x:%02x:%02x:%02x:%02x:%02x" 827 " --> (host)%02x:%02x:%02x:%02x:%02x:%02x (%u bytes)\n", 828 pTmp[6], pTmp[7], pTmp[8], pTmp[9], pTmp[10], pTmp[11], 829 pTmp[0], pTmp[1], pTmp[2], pTmp[3], pTmp[4], pTmp[5], 830 pSG->cbTotal)); 889 vboxNetFltDumpPacket(pSG, true, "host", (fDst & INTNETTRUNKDIR_WIRE) ? 0 : 1); 890 Log4(("vboxNetFltPortOsXmit: pBuf->cb dump:\n%.*Rhxd\n", sizeof(pBuf->cb), pBuf->cb)); 891 Log4(("vboxNetFltPortOsXmit: netif_rx_ni(%p)\n", pBuf)); 831 892 err = netif_rx_ni(pBuf); 832 893 if (err) 833 894 rc = RTErrConvertFromErrno(err); … … 850 911 if (pDev) 851 912 { 852 913 fRc = !!(pDev->promiscuity - (ASMAtomicUoReadBool(&pThis->u.s.fPromiscuousSet) & 1)); 914 LogFlow(("vboxNetFltPortOsIsPromiscuous: returns %d, pDev->promiscuity=%d, fPromiscuousSet=%d\n", 915 fRc, pDev->promiscuity, pThis->u.s.fPromiscuousSet)); 853 916 vboxNetFltLinuxReleaseNetDev(pThis, pDev); 854 917 } 855 918 return fRc; … … 1028 1091 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) 1029 1092 INIT_WORK(&pThis->u.s.XmitTask, vboxNetFltLinuxXmitTask); 1030 1093 #else 1031 INIT_WORK(&pThis->u.s.XmitTask, vboxNetFltLinuxXmitTask, NULL);1094 INIT_WORK(&pThis->u.s.XmitTask, vboxNetFltLinuxXmitTask, &pThis->u.s.XmitTask); 1032 1095 #endif 1033 1096 1034 1097 return VINF_SUCCESS;

