Changeset 33325 in vbox
- Timestamp:
- Oct 21, 2010 8:34:14 PM (14 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/pdmnetifs.h
r28800 r33325 138 138 139 139 /** 140 * Receive data with segmentation context from the network. 141 * 142 * @returns VBox status code. 143 * @param pInterface Pointer to the interface structure containing the called function pointer. 144 * @param pvBuf The available data. 145 * @param cb Number of bytes available in the buffer. 146 * @param pGso Segmentation context. 147 * 148 * @thread Non-EMT. 149 */ 150 DECLR3CALLBACKMEMBER(int, pfnReceiveGso,(PPDMINETWORKDOWN pInterface, const void *pvBuf, size_t cb, PCPDMNETWORKGSO pGso)); 151 152 /** 140 153 * Do pending transmit work on the leaf driver's XMIT thread. 141 154 * -
trunk/src/VBox/Devices/Network/DevVirtioNet.cpp
r31767 r33325 19 19 #define LOG_GROUP LOG_GROUP_DEV_VIRTIO_NET 20 20 #define VNET_GC_SUPPORT 21 //#define VNET_WITH_GSO 21 #define VNET_WITH_GSO 22 #define VNET_WITH_MERGEABLE_RX_BUFS 22 23 23 24 #include <VBox/pdmdev.h> … … 228 229 AssertCompileSize(VNETHDR, 10); 229 230 231 struct VNetHdrMrx 232 { 233 VNETHDR Hdr; 234 uint16_t u16NumBufs; 235 }; 236 typedef struct VNetHdrMrx VNETHDRMRX; 237 typedef VNETHDRMRX *PVNETHDRMRX; 238 AssertCompileSize(VNETHDRMRX, 12); 239 230 240 AssertCompileMemberOffset(VNETSTATE, VPCI, 0); 231 241 … … 255 265 AssertCompileSize(VNETCTLHDR, 2); 256 266 267 /* Returns true if large packets are written into several RX buffers. */ 268 DECLINLINE(bool) vnetMergeableRxBuffers(PVNETSTATE pState) 269 { 270 return !!(pState->VPCI.uGuestFeatures & VNET_F_MRG_RXBUF); 271 } 272 257 273 DECLINLINE(int) vnetCsEnter(PVNETSTATE pState, int rcBusy) 258 274 { … … 292 308 Log(("%s %s packet #%d (%d bytes):\n", 293 309 INSTANCE(pState), cszText, ++pState->u32PktNo, cb)); 294 //Log3(("%.*Rhxd\n", cb, cpPacket));310 Log3(("%.*Rhxd\n", cb, cpPacket)); 295 311 #endif 296 312 } … … 319 335 | VNET_F_HOST_UFO 320 336 #endif 337 #ifdef VNET_WITH_MERGEABLE_RX_BUFS 338 | VNET_F_MRG_RXBUF 339 #endif 321 340 ; 322 341 } … … 385 404 else 386 405 STATUS = 0; 406 387 407 /* 388 408 * By default we pass all packets up since the older guests cannot control … … 655 675 if ( u16Ptr[6] == RT_H2BE_U16(0x8100) 656 676 && !ASMBitTest(pState->aVlanFilter, RT_BE2H_U16(u16Ptr[7]) & 0xFFF)) 677 { 678 Log4(("%s vnetAddressFilter: not our VLAN, returning false\n", INSTANCE(pState))); 657 679 return false; 680 } 658 681 659 682 if (vnetIsBroadcast(pvBuf)) … … 665 688 if (!memcmp(pState->config.mac.au8, pvBuf, sizeof(RTMAC))) 666 689 return true; 690 Log4(("%s vnetAddressFilter: %RTmac (conf) != %RTmac (dest)\n", 691 INSTANCE(pState), pState->config.mac.au8, pvBuf)); 667 692 668 693 for (unsigned i = 0; i < pState->nMacFilterEntries; i++) 669 694 if (!memcmp(&pState->aMacFilter[i], pvBuf, sizeof(RTMAC))) 670 695 return true; 696 697 Log2(("%s vnetAddressFilter: failed all tests, returning false, packet dump follows:\n", INSTANCE(pState))); 698 vnetPacketDump(pState, (const uint8_t*)pvBuf, cb, "<-- Incoming"); 671 699 672 700 return false; … … 685 713 * @thread RX 686 714 */ 687 static int vnetHandleRxPacket(PVNETSTATE pState, const void *pvBuf, size_t cb) 688 { 689 VNETHDR hdr; 690 691 hdr.u8Flags = 0; 692 hdr.u8GSOType = VNETHDR_GSO_NONE; 693 694 vnetPacketDump(pState, (const uint8_t*)pvBuf, cb, "<-- Incoming"); 715 static int vnetHandleRxPacket(PVNETSTATE pState, const void *pvBuf, size_t cb, 716 PCPDMNETWORKGSO pGso) 717 { 718 VNETHDRMRX Hdr; 719 PVNETHDRMRX pHdr; 720 unsigned uHdrLen; 721 RTGCPHYS addrHdrMrx = 0; 722 723 if (pGso) 724 { 725 Log2(("%s vnetHandleRxPacket: gso type=%x cbHdr=%u mss=%u" 726 " off1=0x%x off2=0x%x\n", INSTANCE(pState), pGso->u8Type, 727 pGso->cbHdrs, pGso->cbMaxSeg, pGso->offHdr1, pGso->offHdr2)); 728 Hdr.Hdr.u8Flags = VNETHDR_F_NEEDS_CSUM; 729 switch (pGso->u8Type) 730 { 731 case PDMNETWORKGSOTYPE_IPV4_TCP: 732 Hdr.Hdr.u8GSOType = VNETHDR_GSO_TCPV4; 733 Hdr.Hdr.u16CSumOffset = RT_OFFSETOF(RTNETTCP, th_sum); 734 break; 735 case PDMNETWORKGSOTYPE_IPV6_TCP: 736 Hdr.Hdr.u8GSOType = VNETHDR_GSO_TCPV6; 737 Hdr.Hdr.u16CSumOffset = RT_OFFSETOF(RTNETTCP, th_sum); 738 break; 739 case PDMNETWORKGSOTYPE_IPV4_UDP: 740 Hdr.Hdr.u8GSOType = VNETHDR_GSO_UDP; 741 Hdr.Hdr.u16CSumOffset = RT_OFFSETOF(RTNETUDP, uh_sum); 742 break; 743 default: 744 return VERR_INVALID_PARAMETER; 745 } 746 Hdr.Hdr.u16HdrLen = pGso->cbHdrs; 747 Hdr.Hdr.u16GSOSize = pGso->cbMaxSeg; 748 Hdr.Hdr.u16CSumStart = pGso->offHdr2; 749 STAM_REL_COUNTER_INC(&pState->StatReceiveGSO); 750 } 751 else 752 { 753 Hdr.Hdr.u8Flags = 0; 754 Hdr.Hdr.u8GSOType = VNETHDR_GSO_NONE; 755 } 756 757 if (vnetMergeableRxBuffers(pState)) 758 uHdrLen = sizeof(VNETHDRMRX); 759 else 760 uHdrLen = sizeof(VNETHDR); 761 762 //vnetPacketDump(pState, (const uint8_t*)pvBuf, cb, "<-- Incoming"); 695 763 696 764 unsigned int uOffset = 0; 697 for (unsigned int nElem = 0; uOffset < cb; nElem++) 765 unsigned int nElem; 766 for (nElem = 0; uOffset < cb; nElem++) 698 767 { 699 768 VQUEUEELEM elem; 700 unsigned int nSeg = 0, uElemSize = 0 ;769 unsigned int nSeg = 0, uElemSize = 0, cbReserved = 0; 701 770 702 771 if (!vqueueGet(&pState->VPCI, pState->pRxQueue, &elem)) 703 772 { 773 /* 774 * @todo: It is possible to run out of RX buffers if only a few 775 * were added and we received a big packet. 776 */ 704 777 Log(("%s vnetHandleRxPacket: Suddenly there is no space in receive queue!\n", INSTANCE(pState))); 705 778 return VERR_INTERNAL_ERROR; … … 714 787 if (nElem == 0) 715 788 { 716 /* The very first segment of the very first element gets the header. */ 717 if (elem.aSegsIn[nSeg].cb != sizeof(VNETHDR)) 789 if (vnetMergeableRxBuffers(pState)) 718 790 { 719 Log(("%s vnetHandleRxPacket: The first descriptor does match the header size!\n", INSTANCE(pState)));720 return VERR_INTERNAL_ERROR;791 addrHdrMrx = elem.aSegsIn[nSeg].addr; 792 cbReserved = uHdrLen; 721 793 } 722 723 elem.aSegsIn[nSeg++].pv = &hdr; 724 uElemSize += sizeof(VNETHDR); 794 else 795 { 796 /* The very first segment of the very first element gets the header. */ 797 if (elem.aSegsIn[nSeg].cb != sizeof(VNETHDR)) 798 { 799 Log(("%s vnetHandleRxPacket: The first descriptor does match the header size!\n", INSTANCE(pState))); 800 return VERR_INTERNAL_ERROR; 801 } 802 elem.aSegsIn[nSeg++].pv = &Hdr; 803 } 804 uElemSize += uHdrLen; 725 805 } 726 727 806 while (nSeg < elem.nIn && uOffset < cb) 728 807 { 729 unsigned int uSize = (unsigned int)RT_MIN(elem.aSegsIn[nSeg].cb, cb - uOffset); 808 unsigned int uSize = (unsigned int)RT_MIN(elem.aSegsIn[nSeg].cb - (nSeg?0:cbReserved), 809 cb - uOffset); 730 810 elem.aSegsIn[nSeg++].pv = (uint8_t*)pvBuf + uOffset; 731 811 uOffset += uSize; … … 733 813 } 734 814 STAM_PROFILE_START(&pState->StatReceiveStore, a); 735 vqueuePut(&pState->VPCI, pState->pRxQueue, &elem, uElemSize );815 vqueuePut(&pState->VPCI, pState->pRxQueue, &elem, uElemSize, cbReserved); 736 816 STAM_PROFILE_STOP(&pState->StatReceiveStore, a); 817 if (!vnetMergeableRxBuffers(pState)) 818 break; 819 cbReserved = 0; 820 } 821 if (vnetMergeableRxBuffers(pState)) 822 { 823 Hdr.u16NumBufs = nElem; 824 int rc = PDMDevHlpPhysWrite(pState->VPCI.CTX_SUFF(pDevIns), addrHdrMrx, 825 &Hdr, sizeof(Hdr)); 826 if (RT_FAILURE(rc)) 827 { 828 Log(("%s vnetHandleRxPacket: Failed to write merged RX buf header: %Rrc\n", 829 INSTANCE(pState), rc)); 830 return rc; 831 } 737 832 } 738 833 vqueueSync(&pState->VPCI, pState->pRxQueue); 834 if (uOffset < cb) 835 { 836 Log(("%s vnetHandleRxPacket: Packet did not fit into RX queue (packet size=%u)!\n", 837 INSTANCE(pState), cb)); 838 return VERR_TOO_MUCH_DATA; 839 } 739 840 740 841 return VINF_SUCCESS; … … 742 843 743 844 /** 744 * @interface_method_impl{PDMINETWORKDOWN,pfnReceive} 745 */ 746 static DECLCALLBACK(int) vnetNetworkDown_Receive(PPDMINETWORKDOWN pInterface, const void *pvBuf, size_t cb) 845 * @interface_method_impl{PDMINETWORKDOWN,pfnReceiveGso} 846 */ 847 static DECLCALLBACK(int) vnetNetworkDown_ReceiveGso(PPDMINETWORKDOWN pInterface, 848 const void *pvBuf, size_t cb, 849 PCPDMNETWORKGSO pGso) 747 850 { 748 851 VNETSTATE *pState = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkDown); 749 852 750 Log2(("%s vnetNetworkDown_Receive: pvBuf=%p cb=%u\n", INSTANCE(pState), pvBuf, cb)); 853 Log2(("%s vnetNetworkDown_ReceiveGso: pvBuf=%p cb=%u pGso=%p\n", 854 INSTANCE(pState), pvBuf, cb, pGso)); 751 855 int rc = vnetCanReceive(pState); 752 856 if (RT_FAILURE(rc)) … … 767 871 if (RT_SUCCESS(rc)) 768 872 { 769 rc = vnetHandleRxPacket(pState, pvBuf, cb );873 rc = vnetHandleRxPacket(pState, pvBuf, cb, pGso); 770 874 STAM_REL_COUNTER_ADD(&pState->StatReceiveBytes, cb); 771 875 vnetCsRxLeave(pState); … … 775 879 STAM_PROFILE_STOP(&pState->StatReceive, a); 776 880 return rc; 881 } 882 883 /** 884 * @interface_method_impl{PDMINETWORKDOWN,pfnReceive} 885 */ 886 static DECLCALLBACK(int) vnetNetworkDown_Receive(PPDMINETWORKDOWN pInterface, const void *pvBuf, size_t cb) 887 { 888 return vnetNetworkDown_ReceiveGso(pInterface, pvBuf, cb, NULL); 777 889 } 778 890 … … 941 1053 } 942 1054 1055 unsigned int uHdrLen; 1056 if (vnetMergeableRxBuffers(pState)) 1057 uHdrLen = sizeof(VNETHDRMRX); 1058 else 1059 uHdrLen = sizeof(VNETHDR); 1060 943 1061 Log3(("%s vnetTransmitPendingPackets: About to trasmit %d pending packets\n", INSTANCE(pState), 944 1062 vringReadAvailIndex(&pState->VPCI, &pState->pTxQueue->VRing) - pState->pTxQueue->uNextAvailIndex)); … … 950 1068 { 951 1069 unsigned int uOffset = 0; 952 if (elem.nOut < 2 || elem.aSegsOut[0].cb != sizeof(VNETHDR))1070 if (elem.nOut < 2 || elem.aSegsOut[0].cb != uHdrLen) 953 1071 { 954 1072 Log(("%s vnetQueueTransmit: The first segment is not the header! (%u < 2 || %u != %u).\n", 955 INSTANCE(pState), elem.nOut, elem.aSegsOut[0].cb, sizeof(VNETHDR)));1073 INSTANCE(pState), elem.nOut, elem.aSegsOut[0].cb, uHdrLen)); 956 1074 break; /* For now we simply ignore the header, but it must be there anyway! */ 957 1075 } … … 992 1110 } 993 1111 pSgBuf->cbUsed = uSize; 994 vnetPacketDump(pState, (uint8_t*)pSgBuf->aSegs[0].pvSeg, uSize, "--> Outgoing");1112 //vnetPacketDump(pState, (uint8_t*)pSgBuf->aSegs[0].pvSeg, uSize, "--> Outgoing"); 995 1113 if (pGso) 996 1114 STAM_REL_COUNTER_INC(&pState->StatTransmitGSO); … … 1475 1593 sizeof(pState->config.mac)); 1476 1594 AssertRCReturn(rc, rc); 1595 1477 1596 if (uVersion > VIRTIO_SAVEDSTATE_VERSION_3_1_BETA1) 1478 1597 { … … 1810 1929 pState->INetworkDown.pfnWaitReceiveAvail = vnetNetworkDown_WaitReceiveAvail; 1811 1930 pState->INetworkDown.pfnReceive = vnetNetworkDown_Receive; 1931 pState->INetworkDown.pfnReceiveGso = vnetNetworkDown_ReceiveGso; 1812 1932 pState->INetworkDown.pfnXmitPending = vnetNetworkDown_XmitPending; 1813 1933 -
trunk/src/VBox/Devices/Network/DrvIntNet.cpp
r32167 r33325 726 726 /* 727 727 * Generic segment offload frame (INTNETHDR_TYPE_GSO). 728 *729 * This is where we do the offloading since we don't730 * emulate any NICs with large receive offload (LRO).731 728 */ 732 729 STAM_COUNTER_INC(&pThis->StatReceivedGso); … … 734 731 if (PDMNetGsoIsValid(pGso, cbFrame, cbFrame - sizeof(PDMNETWORKGSO))) 735 732 { 736 cbFrame -= sizeof(PDMNETWORKGSO); 737 738 uint8_t abHdrScratch[256]; 739 uint32_t const cSegs = PDMNetGsoCalcSegmentCount(pGso, cbFrame); 733 if (!pThis->pIAboveNet->pfnReceiveGso || 734 RT_FAILURE(pThis->pIAboveNet->pfnReceiveGso(pThis->pIAboveNet, 735 (uint8_t *)(pGso + 1), 736 pHdr->cbFrame - sizeof(PDMNETWORKGSO), 737 pGso))) 738 { 739 /* 740 * 741 * This is where we do the offloading since this NIC 742 * does not support large receive offload (LRO). 743 */ 744 cbFrame -= sizeof(PDMNETWORKGSO); 745 746 uint8_t abHdrScratch[256]; 747 uint32_t const cSegs = PDMNetGsoCalcSegmentCount(pGso, cbFrame); 740 748 #ifdef LOG_ENABLED 741 if (LogIsEnabled())742 {743 uint64_t u64Now = RTTimeProgramNanoTS();744 LogFlow(("drvR3IntNetRecvRun: %-4d bytes at %llu ns deltas: r=%llu t=%llu; GSO - %u segs\n",745 cbFrame, u64Now, u64Now - pThis->u64LastReceiveTS, u64Now - pThis->u64LastTransferTS, cSegs));746 pThis->u64LastReceiveTS = u64Now;747 Log2(("drvR3IntNetRecvRun: cbFrame=%#x type=%d cbHdrs=%#x Hdr1=%#x Hdr2=%#x MMS=%#x\n"748 "%.*Rhxd\n",749 cbFrame, pGso->u8Type, pGso->cbHdrs, pGso->offHdr1, pGso->offHdr2, pGso->cbMaxSeg,750 cbFrame - sizeof(*pGso), pGso + 1));751 }749 if (LogIsEnabled()) 750 { 751 uint64_t u64Now = RTTimeProgramNanoTS(); 752 LogFlow(("drvR3IntNetRecvRun: %-4d bytes at %llu ns deltas: r=%llu t=%llu; GSO - %u segs\n", 753 cbFrame, u64Now, u64Now - pThis->u64LastReceiveTS, u64Now - pThis->u64LastTransferTS, cSegs)); 754 pThis->u64LastReceiveTS = u64Now; 755 Log2(("drvR3IntNetRecvRun: cbFrame=%#x type=%d cbHdrs=%#x Hdr1=%#x Hdr2=%#x MMS=%#x\n" 756 "%.*Rhxd\n", 757 cbFrame, pGso->u8Type, pGso->cbHdrs, pGso->offHdr1, pGso->offHdr2, pGso->cbMaxSeg, 758 cbFrame - sizeof(*pGso), pGso + 1)); 759 } 752 760 #endif 753 for (size_t iSeg = 0; iSeg < cSegs; iSeg++) 754 { 755 uint32_t cbSegFrame; 756 void *pvSegFrame = PDMNetGsoCarveSegmentQD(pGso, (uint8_t *)(pGso + 1), cbFrame, abHdrScratch, 757 iSeg, cSegs, &cbSegFrame); 758 rc = drvR3IntNetRecvWaitForSpace(pThis); 759 if (RT_FAILURE(rc)) 761 for (size_t iSeg = 0; iSeg < cSegs; iSeg++) 760 762 { 761 Log(("drvR3IntNetRecvRun: drvR3IntNetRecvWaitForSpace -> %Rrc; iSeg=%u cSegs=%u\n", iSeg, cSegs)); 762 break; /* we drop the rest. */ 763 uint32_t cbSegFrame; 764 void *pvSegFrame = PDMNetGsoCarveSegmentQD(pGso, (uint8_t *)(pGso + 1), cbFrame, abHdrScratch, 765 iSeg, cSegs, &cbSegFrame); 766 rc = drvR3IntNetRecvWaitForSpace(pThis); 767 if (RT_FAILURE(rc)) 768 { 769 Log(("drvR3IntNetRecvRun: drvR3IntNetRecvWaitForSpace -> %Rrc; iSeg=%u cSegs=%u\n", iSeg, cSegs)); 770 break; /* we drop the rest. */ 771 } 772 rc = pThis->pIAboveNet->pfnReceive(pThis->pIAboveNet, pvSegFrame, cbSegFrame); 773 AssertRC(rc); 763 774 } 764 rc = pThis->pIAboveNet->pfnReceive(pThis->pIAboveNet, pvSegFrame, cbSegFrame);765 AssertRC(rc);766 775 } 767 776 } -
trunk/src/VBox/Devices/VirtIO/Virtio.cpp
r33314 r33325 181 181 } 182 182 183 void vqueuePut(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t uLen )184 { 185 unsigned int i, uOffset ;183 void vqueuePut(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t uLen, uint32_t uReserved) 184 { 185 unsigned int i, uOffset, cbReserved = uReserved; 186 186 187 187 Log2(("%s vqueuePut: %s desc_idx=%u acb=%u\n", INSTANCE(pState), 188 188 QUEUENAME(pState, pQueue), pElem->uIndex, uLen)); 189 for (i = uOffset = 0; i < pElem->nIn && uOffset < uLen ; i++)190 { 191 uint32_t cbSegLen = RT_MIN(uLen - uOffset, pElem->aSegsIn[i].cb);189 for (i = uOffset = 0; i < pElem->nIn && uOffset < uLen - uReserved; i++) 190 { 191 uint32_t cbSegLen = RT_MIN(uLen - cbReserved - uOffset, pElem->aSegsIn[i].cb - cbReserved); 192 192 if (pElem->aSegsIn[i].pv) 193 193 { 194 194 Log2(("%s vqueuePut: %s used_idx=%u seg=%u addr=%p pv=%p cb=%u acb=%u\n", INSTANCE(pState), 195 195 QUEUENAME(pState, pQueue), pQueue->uNextUsedIndex, i, pElem->aSegsIn[i].addr, pElem->aSegsIn[i].pv, pElem->aSegsIn[i].cb, cbSegLen)); 196 PDMDevHlpPhysWrite(pState->CTX_SUFF(pDevIns), pElem->aSegsIn[i].addr ,196 PDMDevHlpPhysWrite(pState->CTX_SUFF(pDevIns), pElem->aSegsIn[i].addr + cbReserved, 197 197 pElem->aSegsIn[i].pv, cbSegLen); 198 cbReserved = 0; 198 199 } 199 200 uOffset += cbSegLen; 200 201 } 201 202 203 Assert((uReserved + uOffset) == uLen || pElem->nIn == 0); 202 204 Log2(("%s vqueuePut: %s used_idx=%u guest_used_idx=%u id=%u len=%u\n", INSTANCE(pState), 203 205 QUEUENAME(pState, pQueue), pQueue->uNextUsedIndex, vringReadUsedIndex(pState, &pQueue->VRing), pElem->uIndex, uLen)); -
trunk/src/VBox/Devices/VirtIO/Virtio.h
r28800 r33325 305 305 306 306 bool vqueueGet(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem); 307 void vqueuePut(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t uLen );307 void vqueuePut(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t uLen, uint32_t uReserved = 0); 308 308 void vqueueNotify(PVPCISTATE pState, PVQUEUE pQueue); 309 309 void vqueueSync(PVPCISTATE pState, PVQUEUE pQueue);
Note:
See TracChangeset
for help on using the changeset viewer.