diff options
author | vboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f> | 2013-01-24 13:27:28 +0000 |
---|---|---|
committer | vboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f> | 2013-01-24 13:27:28 +0000 |
commit | 93d057aadb0461de803f4f0d0a6c2f43b4333f33 (patch) | |
tree | fc292d520d2442fa5b04521e1b3a82d01b1fdab1 | |
parent | d1b98bb44c71d609a624ccbc3d113ba5b84b6d48 (diff) | |
download | VirtualBox-svn-93d057aadb0461de803f4f0d0a6c2f43b4333f33.tar.gz |
PDMNetShaper: Cleanups & fixes (untested). PVM -> PUVM. Note: cs is a register within the VMM, not critical section. :)
git-svn-id: https://www.virtualbox.org/svn/vbox/trunk@44355 cfe28804-0f27-0410-a406-dd0f0b0b656f
-rw-r--r-- | include/VBox/vmm/pdmnetshaper.h | 89 | ||||
-rw-r--r-- | src/VBox/Devices/Network/DrvNetShaper.cpp | 14 | ||||
-rw-r--r-- | src/VBox/Main/src-client/ConsoleImpl.cpp | 6 | ||||
-rw-r--r-- | src/VBox/VMM/Makefile.kmk | 5 | ||||
-rw-r--r-- | src/VBox/VMM/VMMR0/PDMNetShaperR0.cpp | 43 | ||||
-rw-r--r-- | src/VBox/VMM/VMMR3/PDMDriver.cpp | 4 | ||||
-rw-r--r-- | src/VBox/VMM/VMMR3/PDMNetShaper.cpp | 313 | ||||
-rw-r--r-- | src/VBox/VMM/include/PDMInternal.h | 5 | ||||
-rw-r--r-- | src/VBox/VMM/include/PDMNetShaperInternal.h (renamed from include/VBox/vmm/pdmnetshaperint.h) | 56 |
9 files changed, 209 insertions, 326 deletions
diff --git a/include/VBox/vmm/pdmnetshaper.h b/include/VBox/vmm/pdmnetshaper.h index b2aa5baba62..979d36ac7df 100644 --- a/include/VBox/vmm/pdmnetshaper.h +++ b/include/VBox/vmm/pdmnetshaper.h @@ -33,84 +33,43 @@ #include <iprt/sg.h> -#define PDM_NETSHAPER_MIN_BUCKET_SIZE 65536 /* bytes */ -#define PDM_NETSHAPER_MAX_LATENCY 100 /* milliseconds */ +/** @defgroup grp_pdm_net_shaper The PDM Network Shaper API + * @ingroup grp_pdm + * @{ + */ + + +#define PDM_NETSHAPER_MIN_BUCKET_SIZE UINT32_C(65536) /**< bytes */ +#define PDM_NETSHAPER_MAX_LATENCY UINT32_C(100) /**< milliseconds */ RT_C_DECLS_BEGIN typedef struct PDMNSFILTER { - /** [R3] Pointer to the next group in the list. */ - struct PDMNSFILTER *pNext; - /** [R3] Pointer to the bandwidth group. */ - struct PDMNSBWGROUP *pBwGroupR3; - /** [R0] Pointer to the bandwidth group. */ - R0PTRTYPE(struct PDMNSBWGROUP *) pBwGroupR0; - /** Becomes true when filter fails to obtain bandwidth. */ - bool fChoked; - /** [R3] The driver this filter is aggregated into. */ - PPDMINETWORKDOWN pIDrvNet; + /** Pointer to the next group in the list (ring-3). */ + R3PTRTYPE(struct PDMNSFILTER *) pNextR3; + /** Pointer to the bandwidth group (ring-3). */ + R3PTRTYPE(struct PDMNSBWGROUP *) pBwGroupR3; + /** Pointer to the bandwidth group (ring-0). */ + R0PTRTYPE(struct PDMNSBWGROUP *) pBwGroupR0; + /** Set when the filter fails to obtain bandwidth. */ + bool fChoked; + /** Aligment padding. */ + bool afPadding[HC_ARCH_BITS == 32 ? 3 : 7]; + /** The driver this filter is aggregated into (ring-3). */ + R3PTRTYPE(PPDMINETWORKDOWN) pIDrvNetR3; } PDMNSFILTER; -/** @defgroup grp_pdm_net_shaper The PDM Network Shaper API - * @ingroup grp_pdm - * @{ - */ - /** Pointer to a PDM filter handle. */ typedef struct PDMNSFILTER *PPDMNSFILTER; /** Pointer to a network shaper. */ typedef struct PDMNETSHAPER *PPDMNETSHAPER; -/** - * Obtain bandwidth in a bandwidth group (R0 version). - * - * @returns VBox status code. - * @param pFilter Pointer to the filter that allocates bandwidth. - * @param cbTransfer Number of bytes to allocate. - */ -VMMR0DECL(bool) PDMR0NsAllocateBandwidth(PPDMNSFILTER pFilter, size_t cbTransfer); - -/** - * Obtain bandwidth in a bandwidth group. - * - * @returns VBox status code. - * @param pFilter Pointer to the filter that allocates bandwidth. - * @param cbTransfer Number of bytes to allocate. - */ -VMMR3DECL(bool) PDMR3NsAllocateBandwidth(PPDMNSFILTER pFilter, size_t cbTransfer); - -/** - * Attach network filter driver from bandwidth group. - * - * @returns VBox status code. - * @param pVM Handle of VM. - * @param pDrvIns The driver instance. - * @param pcszBwGroup Name of the bandwidth group to attach to. - * @param pFilter Pointer to the filter we attach. - */ -VMMR3DECL(int) PDMR3NsAttach(PVM pVM, PPDMDRVINS pDrvIns, const char *pcszBwGroup, PPDMNSFILTER pFilter); - -/** - * Detach network filter driver from bandwidth group. - * - * @returns VBox status code. - * @param pVM Handle of VM. - * @param pDrvIns The driver instance. - * @param pFilter Pointer to the filter we detach. - */ -VMMR3DECL(int) PDMR3NsDetach(PVM pVM, PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter); - -/** - * Adjusts the maximum rate for the bandwidth group. - * - * @returns VBox status code. - * @param pVM Handle of VM. - * @param pcszBwGroup Name of the bandwidth group to attach to. - * @param cbTransferPerSecMax Maximum number of bytes per second to be transmitted. - */ -VMMR3DECL(int) PDMR3NsBwGroupSetLimit(PVM pVM, const char *pcszBwGroup, uint64_t cbTransferPerSecMax); +VMMDECL(bool) PDMNsAllocateBandwidth(PPDMNSFILTER pFilter, size_t cbTransfer); +VMMR3_INT_DECL(int) PDMR3NsAttach(PUVM pUVM, PPDMDRVINS pDrvIns, const char *pcszBwGroup, PPDMNSFILTER pFilter); +VMMR3_INT_DECL(int) PDMR3NsDetach(PUVM pUVM, PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter); +VMMR3DECL(int) PDMR3NsBwGroupSetLimit(PUVM pUVM, const char *pszBwGroup, uint64_t cbPerSecMax); /** @} */ diff --git a/src/VBox/Devices/Network/DrvNetShaper.cpp b/src/VBox/Devices/Network/DrvNetShaper.cpp index 6f3a5930277..86eb1f60358 100644 --- a/src/VBox/Devices/Network/DrvNetShaper.cpp +++ b/src/VBox/Devices/Network/DrvNetShaper.cpp @@ -127,16 +127,8 @@ PDMBOTHCBDECL(int) drvNetShaperUp_AllocBuf(PPDMINETWORKUP pInterface, size_t cbM //LogFlow(("drvNetShaperUp_AllocBuf: cb=%d\n", cbMin)); STAM_REL_COUNTER_ADD(&pThis->StatXmitBytesRequested, cbMin); STAM_REL_COUNTER_INC(&pThis->StatXmitPktsRequested); -#ifdef IN_RING3 - if (!PDMR3NsAllocateBandwidth(&pThis->Filter, cbMin)) - { - STAM_REL_COUNTER_ADD(&pThis->StatXmitBytesDenied, cbMin); - STAM_REL_COUNTER_INC(&pThis->StatXmitPktsDenied); - return VERR_TRY_AGAIN; - } -#endif -#ifdef IN_RING0 - if (!PDMR0NsAllocateBandwidth(&pThis->Filter, cbMin)) +#if defined(IN_RING3) || defined(IN_RING0) + if (!PDMNsAllocateBandwidth(&pThis->Filter, cbMin)) { STAM_REL_COUNTER_ADD(&pThis->StatXmitBytesDenied, cbMin); STAM_REL_COUNTER_INC(&pThis->StatXmitPktsDenied); @@ -476,7 +468,7 @@ static DECLCALLBACK(int) drvR3NetShaperConstruct(PPDMDRVINS pDrvIns, PCFGMNODE p else rc = VINF_SUCCESS; - pThis->Filter.pIDrvNet = &pThis->INetworkDown; + pThis->Filter.pIDrvNetR3 = &pThis->INetworkDown; rc = PDMDrvHlpNetShaperAttach(pDrvIns, pThis->pszBwGroup, &pThis->Filter); if (RT_FAILURE(rc)) { diff --git a/src/VBox/Main/src-client/ConsoleImpl.cpp b/src/VBox/Main/src-client/ConsoleImpl.cpp index ff2b70e534e..792b9d91f60 100644 --- a/src/VBox/Main/src-client/ConsoleImpl.cpp +++ b/src/VBox/Main/src-client/ConsoleImpl.cpp @@ -5343,12 +5343,10 @@ HRESULT Console::onBandwidthGroupChange(IBandwidthGroup *aBandwidthGroup) { int vrc = VINF_SUCCESS; if (enmType == BandwidthGroupType_Disk) - vrc = PDMR3AsyncCompletionBwMgrSetMaxForFile(ptrVM, Utf8Str(strName).c_str(), - cMax); + vrc = PDMR3AsyncCompletionBwMgrSetMaxForFile(ptrVM, Utf8Str(strName).c_str(), cMax); #ifdef VBOX_WITH_NETSHAPER else if (enmType == BandwidthGroupType_Network) - vrc = PDMR3NsBwGroupSetLimit(ptrVM, Utf8Str(strName).c_str(), - cMax); + vrc = PDMR3NsBwGroupSetLimit(ptrVM.rawUVM(), Utf8Str(strName).c_str(), cMax); else rc = E_NOTIMPL; #endif /* VBOX_WITH_NETSHAPER */ diff --git a/src/VBox/VMM/Makefile.kmk b/src/VBox/VMM/Makefile.kmk index 5a9043fad4c..46a3dffa2ba 100644 --- a/src/VBox/VMM/Makefile.kmk +++ b/src/VBox/VMM/Makefile.kmk @@ -213,7 +213,8 @@ ifdef VBOX_WITH_PDM_ASYNC_COMPLETION endif ifdef VBOX_WITH_NETSHAPER VBoxVMM_SOURCES += \ - VMMR3/PDMNetShaper.cpp + VMMR3/PDMNetShaper.cpp \ + VMMAll/PDMAllNetShaper.cpp endif ifdef VBOX_WITH_RAW_MODE @@ -547,7 +548,7 @@ ifndef VBOX_ONLY_EXTPACKS endif ifdef VBOX_WITH_NETSHAPER VMMR0_SOURCES += \ - VMMR0/PDMNetShaperR0.cpp + VMMAll/PDMAllNetShaper.cpp endif VMMR0_SOURCES.amd64 = \ VMMR0/VMMR0JmpA-amd64.asm diff --git a/src/VBox/VMM/VMMR0/PDMNetShaperR0.cpp b/src/VBox/VMM/VMMR0/PDMNetShaperR0.cpp deleted file mode 100644 index 2a075740548..00000000000 --- a/src/VBox/VMM/VMMR0/PDMNetShaperR0.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* $Id$ */ -/** @file - * PDM Network Shaper - Limit network traffic according to bandwidth - * group settings [R0 part]. - */ - -/* - * Copyright (C) 2011-2012 Oracle Corporation - * - * This file is part of VirtualBox Open Source Edition (OSE), as - * available from http://www.virtualbox.org. This file is free software; - * you can redistribute it and/or modify it under the terms of the GNU - * General Public License (GPL) as published by the Free Software - * Foundation, in version 2 as it comes in the "COPYING" file of the - * VirtualBox OSE distribution. VirtualBox OSE is distributed in the - * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - */ - - -/******************************************************************************* -* Header Files * -*******************************************************************************/ -#define LOG_GROUP LOG_GROUP_NET_SHAPER - -#include <VBox/vmm/pdm.h> -#include <VBox/log.h> -#include <iprt/time.h> - -#include <VBox/vmm/pdmnetshaper.h> -#include <VBox/vmm/pdmnetshaperint.h> - - -/** - * Obtain bandwidth in a bandwidth group (R0 version). - * - * @returns VBox status code. - * @param pFilter Pointer to the filter that allocates bandwidth. - * @param cbTransfer Number of bytes to allocate. - */ -VMMR0DECL(bool) PDMR0NsAllocateBandwidth(PPDMNSFILTER pFilter, size_t cbTransfer) -{ - return pdmNsAllocateBandwidth(pFilter, cbTransfer); -} diff --git a/src/VBox/VMM/VMMR3/PDMDriver.cpp b/src/VBox/VMM/VMMR3/PDMDriver.cpp index 19c523423c2..56a3340a551 100644 --- a/src/VBox/VMM/VMMR3/PDMDriver.cpp +++ b/src/VBox/VMM/VMMR3/PDMDriver.cpp @@ -1560,7 +1560,7 @@ static DECLCALLBACK(int) pdmR3DrvHlp_NetShaperAttach(PPDMDRVINS pDrvIns, const c LogFlow(("pdmR3DrvHlp_NetShaperAttach: caller='%s'/%d: pFilter=%p pszBwGroup=%p:{%s}\n", pDrvIns->pReg->szName, pDrvIns->iInstance, pFilter, pszBwGroup, pszBwGroup)); - int rc = PDMR3NsAttach(pDrvIns->Internal.s.pVMR3, pDrvIns, pszBwGroup, pFilter); + int rc = PDMR3NsAttach(pDrvIns->Internal.s.pVMR3->pUVM, pDrvIns, pszBwGroup, pFilter); LogFlow(("pdmR3DrvHlp_NetShaperAttach: caller='%s'/%d: returns %Rrc\n", pDrvIns->pReg->szName, pDrvIns->iInstance, rc)); @@ -1575,7 +1575,7 @@ static DECLCALLBACK(int) pdmR3DrvHlp_NetShaperDetach(PPDMDRVINS pDrvIns, PPDMNSF LogFlow(("pdmR3DrvHlp_NetShaperDetach: caller='%s'/%d: pFilter=%p\n", pDrvIns->pReg->szName, pDrvIns->iInstance, pFilter)); - int rc = PDMR3NsDetach(pDrvIns->Internal.s.pVMR3, pDrvIns, pFilter); + int rc = PDMR3NsDetach(pDrvIns->Internal.s.pVMR3->pUVM, pDrvIns, pFilter); LogFlow(("pdmR3DrvHlp_NetShaperDetach: caller='%s'/%d: returns %Rrc\n", pDrvIns->pReg->szName, pDrvIns->iInstance, rc)); diff --git a/src/VBox/VMM/VMMR3/PDMNetShaper.cpp b/src/VBox/VMM/VMMR3/PDMNetShaper.cpp index a47c31f1d52..af05d40d4f3 100644 --- a/src/VBox/VMM/VMMR3/PDMNetShaper.cpp +++ b/src/VBox/VMM/VMMR3/PDMNetShaper.cpp @@ -41,7 +41,7 @@ #include <iprt/string.h> #include <VBox/vmm/pdmnetshaper.h> -#include <VBox/vmm/pdmnetshaperint.h> +#include "PDMNetShaperInternal.h" /******************************************************************************* @@ -56,32 +56,42 @@ typedef struct PDMNETSHAPER /** Pointer to the VM. */ PVM pVM; /** Critical section protecting all members below. */ - RTCRITSECT cs; + RTCRITSECT Lock; /** Pending TX thread. */ - PPDMTHREAD hTxThread; + PPDMTHREAD pTxThread; /** Pointer to the first bandwidth group. */ PPDMNSBWGROUP pBwGroupsHead; } PDMNETSHAPER; +/** Takes the shaper lock (asserts but doesn't return or anything on + * failure). */ +#define LOCK_NETSHAPER(a_pShaper) do { int rcShaper = RTCritSectEnter(&(a_pShaper)->Lock); AssertRC(rcShaper); } while (0) +/** Takes the shaper lock, returns + asserts on failure. */ +#define LOCK_NETSHAPER_RETURN(a_pShaper) \ + do { int rcShaper = RTCritSectEnter(&(a_pShaper)->Lock); AssertRCReturn(rcShaper, rcShaper); } while (0) +/** Releases the shaper lock (asserts on failure). */ +#define UNLOCK_NETSHAPER(a_pShaper) do { int rcShaper = RTCritSectLeave(&(a_pShaper)->Lock); AssertRC(rcShaper); } while (0) -static PPDMNSBWGROUP pdmNsBwGroupFindById(PPDMNETSHAPER pShaper, const char *pcszId) + + +static PPDMNSBWGROUP pdmNsBwGroupFindById(PPDMNETSHAPER pShaper, const char *pszId) { PPDMNSBWGROUP pBwGroup = NULL; - if (RT_VALID_PTR(pcszId)) + if (RT_VALID_PTR(pszId)) { - int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc); + LOCK_NETSHAPER(pShaper); pBwGroup = pShaper->pBwGroupsHead; while ( pBwGroup - && RTStrCmp(pBwGroup->pszName, pcszId)) - pBwGroup = pBwGroup->pNext; + && RTStrCmp(pBwGroup->pszNameR3, pszId)) + pBwGroup = pBwGroup->pNextR3; - rc = RTCritSectLeave(&pShaper->cs); AssertRC(rc); + UNLOCK_NETSHAPER(pShaper); } return pBwGroup; @@ -90,13 +100,13 @@ static PPDMNSBWGROUP pdmNsBwGroupFindById(PPDMNETSHAPER pShaper, const char *pcs static void pdmNsBwGroupLink(PPDMNSBWGROUP pBwGroup) { - PPDMNETSHAPER pShaper = pBwGroup->pShaper; - int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc); + PPDMNETSHAPER pShaper = pBwGroup->pShaperR3; + LOCK_NETSHAPER(pShaper); - pBwGroup->pNext = pShaper->pBwGroupsHead; + pBwGroup->pNextR3 = pShaper->pBwGroupsHead; pShaper->pBwGroupsHead = pBwGroup; - rc = RTCritSectLeave(&pShaper->cs); AssertRC(rc); + UNLOCK_NETSHAPER(pShaper); } @@ -104,7 +114,7 @@ static void pdmNsBwGroupLink(PPDMNSBWGROUP pBwGroup) static void pdmNsBwGroupUnlink(PPDMNSBWGROUP pBwGroup) { PPDMNETSHAPER pShaper = pBwGroup->pShaper; - int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc); + LOCK_NETSHAPER(pShaper); if (pBwGroup == pShaper->pBwGroupsHead) pShaper->pBwGroupsHead = pBwGroup->pNext; @@ -119,58 +129,56 @@ static void pdmNsBwGroupUnlink(PPDMNSBWGROUP pBwGroup) pPrev->pNext = pBwGroup->pNext; } - rc = RTCritSectLeave(&pShaper->cs); AssertRC(rc); + UNLOCK_NETSHAPER(pShaper); } #endif -static void pdmNsBwGroupSetLimit(PPDMNSBWGROUP pBwGroup, uint64_t cbTransferPerSecMax) +static void pdmNsBwGroupSetLimit(PPDMNSBWGROUP pBwGroup, uint64_t cbPerSecMax) { - pBwGroup->cbTransferPerSecMax = cbTransferPerSecMax; - pBwGroup->cbBucketSize = RT_MAX(PDM_NETSHAPER_MIN_BUCKET_SIZE, - cbTransferPerSecMax * PDM_NETSHAPER_MAX_LATENCY / 1000); - LogFlowFunc(("New rate limit is %llu bytes per second, adjusted bucket size to %d bytes\n", - pBwGroup->cbTransferPerSecMax, pBwGroup->cbBucketSize)); + pBwGroup->cbPerSecMax = cbPerSecMax; + pBwGroup->cbBucket = RT_MAX(PDM_NETSHAPER_MIN_BUCKET_SIZE, cbPerSecMax * PDM_NETSHAPER_MAX_LATENCY / 1000); + LogFlow(("pdmNsBwGroupSetLimit: New rate limit is %llu bytes per second, adjusted bucket size to %u bytes\n", + pBwGroup->cbPerSecMax, pBwGroup->cbBucket)); } -static int pdmNsBwGroupCreate(PPDMNETSHAPER pShaper, const char *pcszBwGroup, uint64_t cbTransferPerSecMax) +static int pdmNsBwGroupCreate(PPDMNETSHAPER pShaper, const char *pszBwGroup, uint64_t cbPerSecMax) { - LogFlowFunc(("pShaper=%#p pcszBwGroup=%#p{%s} cbTransferPerSecMax=%llu\n", - pShaper, pcszBwGroup, pcszBwGroup, cbTransferPerSecMax)); + LogFlow(("pdmNsBwGroupCreate: pShaper=%#p pszBwGroup=%#p{%s} cbPerSecMax=%llu\n", pShaper, pszBwGroup, pszBwGroup, cbPerSecMax)); AssertPtrReturn(pShaper, VERR_INVALID_POINTER); - AssertPtrReturn(pcszBwGroup, VERR_INVALID_POINTER); - AssertReturn(*pcszBwGroup != '\0', VERR_INVALID_PARAMETER); + AssertPtrReturn(pszBwGroup, VERR_INVALID_POINTER); + AssertReturn(*pszBwGroup != '\0', VERR_INVALID_PARAMETER); int rc; - PPDMNSBWGROUP pBwGroup = pdmNsBwGroupFindById(pShaper, pcszBwGroup); + PPDMNSBWGROUP pBwGroup = pdmNsBwGroupFindById(pShaper, pszBwGroup); if (!pBwGroup) { rc = MMHyperAlloc(pShaper->pVM, sizeof(PDMNSBWGROUP), 64, MM_TAG_PDM_NET_SHAPER, (void **)&pBwGroup); if (RT_SUCCESS(rc)) { - rc = PDMR3CritSectInit(pShaper->pVM, &pBwGroup->cs, RT_SRC_POS, "BWGRP"); + rc = PDMR3CritSectInit(pShaper->pVM, &pBwGroup->Lock, RT_SRC_POS, "BWGRP"); if (RT_SUCCESS(rc)) { - pBwGroup->pszName = RTStrDup(pcszBwGroup); - if (pBwGroup->pszName) + pBwGroup->pszNameR3 = MMR3HeapStrDup(pShaper->pVM, MM_TAG_PDM_NET_SHAPER, pszBwGroup); + if (pBwGroup->pszNameR3) { - pBwGroup->pShaper = pShaper; + pBwGroup->pShaperR3 = pShaper; pBwGroup->cRefs = 0; - pdmNsBwGroupSetLimit(pBwGroup, cbTransferPerSecMax); + pdmNsBwGroupSetLimit(pBwGroup, cbPerSecMax); - pBwGroup->cbTokensLast = pBwGroup->cbBucketSize; + pBwGroup->cbTokensLast = pBwGroup->cbBucket; pBwGroup->tsUpdatedLast = RTTimeSystemNanoTS(); - LogFlowFunc(("pcszBwGroup={%s} cbBucketSize=%u\n", - pcszBwGroup, pBwGroup->cbBucketSize)); + LogFlowFunc(("pszBwGroup={%s} cbBucket=%u\n", + pszBwGroup, pBwGroup->cbBucket)); pdmNsBwGroupLink(pBwGroup); return VINF_SUCCESS; } - PDMR3CritSectDelete(&pBwGroup->cs); + PDMR3CritSectDelete(&pBwGroup->Lock); } MMHyperFree(pShaper->pVM, pBwGroup); } @@ -188,8 +196,8 @@ static int pdmNsBwGroupCreate(PPDMNETSHAPER pShaper, const char *pcszBwGroup, ui static void pdmNsBwGroupTerminate(PPDMNSBWGROUP pBwGroup) { Assert(pBwGroup->cRefs == 0); - if (PDMCritSectIsInitialized(&pBwGroup->cs)) - PDMR3CritSectDelete(&pBwGroup->cs); + if (PDMCritSectIsInitialized(&pBwGroup->Lock)) + PDMR3CritSectDelete(&pBwGroup->Lock); } @@ -214,41 +222,41 @@ static void pdmNsBwGroupXmitPending(PPDMNSBWGROUP pBwGroup) * held. */ AssertPtr(pBwGroup); - AssertPtr(pBwGroup->pShaper); - Assert(RTCritSectIsOwner(&pBwGroup->pShaper->cs)); - //int rc = RTCritSectEnter(&pBwGroup->cs); AssertRC(rc); + AssertPtr(pBwGroup->pShaperR3); + Assert(RTCritSectIsOwner(&pBwGroup->pShaperR3->Lock)); + //LOCK_NETSHAPER(pShaper); /* Check if the group is disabled. */ - if (pBwGroup->cbTransferPerSecMax == 0) + if (pBwGroup->cbPerSecMax == 0) return; - PPDMNSFILTER pFilter = pBwGroup->pFiltersHead; + PPDMNSFILTER pFilter = pBwGroup->pFiltersHeadR3; while (pFilter) { bool fChoked = ASMAtomicXchgBool(&pFilter->fChoked, false); Log3((LOG_FN_FMT ": pFilter=%#p fChoked=%RTbool\n", __PRETTY_FUNCTION__, pFilter, fChoked)); - if (fChoked && pFilter->pIDrvNet) + if (fChoked && pFilter->pIDrvNetR3) { LogFlowFunc(("Calling pfnXmitPending for pFilter=%#p\n", pFilter)); - pFilter->pIDrvNet->pfnXmitPending(pFilter->pIDrvNet); + pFilter->pIDrvNetR3->pfnXmitPending(pFilter->pIDrvNetR3); } - pFilter = pFilter->pNext; + pFilter = pFilter->pNextR3; } - //rc = RTCritSectLeave(&pBwGroup->cs); AssertRC(rc); + //UNLOCK_NETSHAPER(pShaper); } static void pdmNsFilterLink(PPDMNSFILTER pFilter) { PPDMNSBWGROUP pBwGroup = pFilter->pBwGroupR3; - int rc = PDMCritSectEnter(&pBwGroup->cs, VERR_SEM_BUSY); AssertRC(rc); + int rc = PDMCritSectEnter(&pBwGroup->Lock, VERR_SEM_BUSY); AssertRC(rc); - pFilter->pNext = pBwGroup->pFiltersHead; - pBwGroup->pFiltersHead = pFilter; + pFilter->pNextR3 = pBwGroup->pFiltersHeadR3; + pBwGroup->pFiltersHeadR3 = pFilter; - rc = PDMCritSectLeave(&pBwGroup->cs); AssertRC(rc); + rc = PDMCritSectLeave(&pBwGroup->Lock); AssertRC(rc); } @@ -261,117 +269,131 @@ static void pdmNsFilterUnlink(PPDMNSFILTER pFilter) * of group's filters. */ AssertPtr(pBwGroup); - AssertPtr(pBwGroup->pShaper); - Assert(RTCritSectIsOwner(&pBwGroup->pShaper->cs)); - int rc = PDMCritSectEnter(&pBwGroup->cs, VERR_SEM_BUSY); AssertRC(rc); + AssertPtr(pBwGroup->pShaperR3); + Assert(RTCritSectIsOwner(&pBwGroup->pShaperR3->Lock)); + int rc = PDMCritSectEnter(&pBwGroup->Lock, VERR_SEM_BUSY); AssertRC(rc); - if (pFilter == pBwGroup->pFiltersHead) - pBwGroup->pFiltersHead = pFilter->pNext; + if (pFilter == pBwGroup->pFiltersHeadR3) + pBwGroup->pFiltersHeadR3 = pFilter->pNextR3; else { - PPDMNSFILTER pPrev = pBwGroup->pFiltersHead; + PPDMNSFILTER pPrev = pBwGroup->pFiltersHeadR3; while ( pPrev - && pPrev->pNext != pFilter) - pPrev = pPrev->pNext; + && pPrev->pNextR3 != pFilter) + pPrev = pPrev->pNextR3; AssertPtr(pPrev); - pPrev->pNext = pFilter->pNext; + pPrev->pNextR3 = pFilter->pNextR3; } - rc = PDMCritSectLeave(&pBwGroup->cs); AssertRC(rc); + rc = PDMCritSectLeave(&pBwGroup->Lock); AssertRC(rc); } -VMMR3DECL(int) PDMR3NsAttach(PVM pVM, PPDMDRVINS pDrvIns, const char *pcszBwGroup, - PPDMNSFILTER pFilter) +/** + * Attach network filter driver from bandwidth group. + * + * @returns VBox status code. + * @param pVM Handle of VM. + * @param pDrvIns The driver instance. + * @param pszBwGroup Name of the bandwidth group to attach to. + * @param pFilter Pointer to the filter we attach. + */ +VMMR3_INT_DECL(int) PDMR3NsAttach(PUVM pUVM, PPDMDRVINS pDrvIns, const char *pszBwGroup, PPDMNSFILTER pFilter) { - VM_ASSERT_EMT(pVM); + VM_ASSERT_EMT(pUVM->pVM); AssertPtrReturn(pFilter, VERR_INVALID_POINTER); AssertReturn(pFilter->pBwGroupR3 == NULL, VERR_ALREADY_EXISTS); - - PUVM pUVM = pVM->pUVM; PPDMNETSHAPER pShaper = pUVM->pdm.s.pNetShaper; + LOCK_NETSHAPER_RETURN(pShaper); - PPDMNSBWGROUP pBwGroupOld = NULL; - PPDMNSBWGROUP pBwGroupNew = NULL; + int rc = VINF_SUCCESS; + PPDMNSBWGROUP pBwGroupNew = NULL; + if (pszBwGroup) + { + pBwGroupNew = pdmNsBwGroupFindById(pShaper, pszBwGroup); + if (pBwGroupNew) + pdmNsBwGroupRef(pBwGroupNew); + else + rc = VERR_NOT_FOUND; + } - int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc); if (RT_SUCCESS(rc)) { - if (pcszBwGroup) - { - pBwGroupNew = pdmNsBwGroupFindById(pShaper, pcszBwGroup); - if (pBwGroupNew) - pdmNsBwGroupRef(pBwGroupNew); - else - rc = VERR_NOT_FOUND; - } - - if (RT_SUCCESS(rc)) - { - pBwGroupOld = ASMAtomicXchgPtrT(&pFilter->pBwGroupR3, pBwGroupNew, PPDMNSBWGROUP); - ASMAtomicWritePtr(&pFilter->pBwGroupR0, MMHyperR3ToR0(pVM, pBwGroupNew)); - if (pBwGroupOld) - pdmNsBwGroupUnref(pBwGroupOld); - pdmNsFilterLink(pFilter); - } - int rc2 = RTCritSectLeave(&pShaper->cs); AssertRC(rc2); + PPDMNSBWGROUP pBwGroupOld = ASMAtomicXchgPtrT(&pFilter->pBwGroupR3, pBwGroupNew, PPDMNSBWGROUP); + ASMAtomicWritePtr(&pFilter->pBwGroupR0, MMHyperR3ToR0(pUVM->pVM, pBwGroupNew)); + if (pBwGroupOld) + pdmNsBwGroupUnref(pBwGroupOld); + pdmNsFilterLink(pFilter); } + UNLOCK_NETSHAPER(pShaper); return rc; } -VMMR3DECL(int) PDMR3NsDetach(PVM pVM, PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter) +/** + * Detach network filter driver from bandwidth group. + * + * @returns VBox status code. + * @param pUVM The user mode VM handle. + * @param pDrvIns The driver instance. + * @param pFilter Pointer to the filter we detach. + */ +VMMR3_INT_DECL(int) PDMR3NsDetach(PUVM pUVM, PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter) { - VM_ASSERT_EMT(pVM); + VM_ASSERT_EMT(pUVM->pVM); AssertPtrReturn(pFilter, VERR_INVALID_POINTER); AssertPtrReturn(pFilter->pBwGroupR3, VERR_INVALID_POINTER); - PUVM pUVM = pVM->pUVM; PPDMNETSHAPER pShaper = pUVM->pdm.s.pNetShaper; + LOCK_NETSHAPER_RETURN(pShaper); - int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc); - if (RT_SUCCESS(rc)) - { - pdmNsFilterUnlink(pFilter); - PPDMNSBWGROUP pBwGroup = NULL; - pBwGroup = ASMAtomicXchgPtrT(&pFilter->pBwGroupR3, NULL, PPDMNSBWGROUP); - if (pBwGroup) - pdmNsBwGroupUnref(pBwGroup); - int rc2 = RTCritSectLeave(&pShaper->cs); AssertRC(rc2); - } - return rc; -} - + pdmNsFilterUnlink(pFilter); + PPDMNSBWGROUP pBwGroup = ASMAtomicXchgPtrT(&pFilter->pBwGroupR3, NULL, PPDMNSBWGROUP); + if (pBwGroup) + pdmNsBwGroupUnref(pBwGroup); -VMMR3DECL(bool) PDMR3NsAllocateBandwidth(PPDMNSFILTER pFilter, size_t cbTransfer) -{ - return pdmNsAllocateBandwidth(pFilter, cbTransfer); + UNLOCK_NETSHAPER(pShaper); + return VINF_SUCCESS; } -VMMR3DECL(int) PDMR3NsBwGroupSetLimit(PVM pVM, const char *pcszBwGroup, uint64_t cbTransferPerSecMax) +/** + * Adjusts the maximum rate for the bandwidth group. + * + * @returns VBox status code. + * @param pUVM The user mode VM handle. + * @param pszBwGroup Name of the bandwidth group to attach to. + * @param cbPerSecMax Maximum number of bytes per second to be transmitted. + */ +VMMR3DECL(int) PDMR3NsBwGroupSetLimit(PUVM pUVM, const char *pszBwGroup, uint64_t cbPerSecMax) { - PUVM pUVM = pVM->pUVM; + UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); PPDMNETSHAPER pShaper = pUVM->pdm.s.pNetShaper; + LOCK_NETSHAPER_RETURN(pShaper); - int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc); - if (RT_SUCCESS(rc)) + int rc; + PPDMNSBWGROUP pBwGroup = pdmNsBwGroupFindById(pShaper, pszBwGroup); + if (pBwGroup) { - PPDMNSBWGROUP pBwGroup = pdmNsBwGroupFindById(pShaper, pcszBwGroup); - if (pBwGroup) + rc = PDMCritSectEnter(&pBwGroup->Lock, VERR_SEM_BUSY); AssertRC(rc); + if (RT_SUCCESS(rc)) { - rc = PDMCritSectEnter(&pBwGroup->cs, VERR_SEM_BUSY); AssertRC(rc); - pdmNsBwGroupSetLimit(pBwGroup, cbTransferPerSecMax); + pdmNsBwGroupSetLimit(pBwGroup, cbPerSecMax); + /* Drop extra tokens */ - if (pBwGroup->cbTokensLast > pBwGroup->cbBucketSize) - pBwGroup->cbTokensLast = pBwGroup->cbBucketSize; - rc = PDMCritSectLeave(&pBwGroup->cs); AssertRC(rc); + if (pBwGroup->cbTokensLast > pBwGroup->cbBucket) + pBwGroup->cbTokensLast = pBwGroup->cbBucket; + + int rc2 = PDMCritSectLeave(&pBwGroup->Lock); AssertRC(rc2); } - rc = RTCritSectLeave(&pShaper->cs); AssertRC(rc); } + else + rc = VERR_NOT_FOUND; + + UNLOCK_NETSHAPER(pShaper); return rc; } @@ -390,15 +412,16 @@ static DECLCALLBACK(int) pdmR3NsTxThread(PVM pVM, PPDMTHREAD pThread) while (pThread->enmState == PDMTHREADSTATE_RUNNING) { RTThreadSleep(PDM_NETSHAPER_MAX_LATENCY); + /* Go over all bandwidth groups/filters calling pfnXmitPending */ - int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc); + LOCK_NETSHAPER(pShaper); PPDMNSBWGROUP pBwGroup = pShaper->pBwGroupsHead; while (pBwGroup) { pdmNsBwGroupXmitPending(pBwGroup); - pBwGroup = pBwGroup->pNext; + pBwGroup = pBwGroup->pNextR3; } - rc = RTCritSectLeave(&pShaper->cs); AssertRC(rc); + UNLOCK_NETSHAPER(pShaper); } return VINF_SUCCESS; } @@ -436,12 +459,13 @@ int pdmR3NetShaperTerm(PVM pVM) while (pBwGroup) { PPDMNSBWGROUP pFree = pBwGroup; - pBwGroup = pBwGroup->pNext; + pBwGroup = pBwGroup->pNextR3; pdmNsBwGroupTerminate(pFree); + MMR3HeapFree(pFree->pszNameR3); MMHyperFree(pVM, pFree); } - RTCritSectDelete(&pShaper->cs); + RTCritSectDelete(&pShaper->Lock); return VINF_SUCCESS; } @@ -454,27 +478,23 @@ int pdmR3NetShaperTerm(PVM pVM) */ int pdmR3NetShaperInit(PVM pVM) { - LogFlowFunc((": pVM=%p\n", pVM)); - + LogFlow(("pdmR3NetShaperInit: pVM=%p\n", pVM)); VM_ASSERT_EMT(pVM); + PUVM pUVM = pVM->pUVM; + AssertMsgReturn(!pUVM->pdm.s.pNetShaper, ("Network shaper was already initialized\n"), VERR_WRONG_ORDER); - PPDMNETSHAPER pNetShaper = NULL; - - int rc = MMR3HeapAllocZEx(pVM, MM_TAG_PDM_NET_SHAPER, - sizeof(PDMNETSHAPER), - (void **)&pNetShaper); + PPDMNETSHAPER pShaper; + int rc = MMR3HeapAllocZEx(pVM, MM_TAG_PDM_NET_SHAPER, sizeof(PDMNETSHAPER), (void **)&pShaper); if (RT_SUCCESS(rc)) { - PCFGMNODE pCfgRoot = CFGMR3GetRoot(pVM); - PCFGMNODE pCfgNetShaper = CFGMR3GetChild(CFGMR3GetChild(pCfgRoot, "PDM"), "NetworkShaper"); + PCFGMNODE pCfgNetShaper = CFGMR3GetChild(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "NetworkShaper"); - pNetShaper->pVM = pVM; - rc = RTCritSectInit(&pNetShaper->cs); + pShaper->pVM = pVM; + rc = RTCritSectInit(&pShaper->Lock); if (RT_SUCCESS(rc)) { /* Create all bandwidth groups. */ PCFGMNODE pCfgBwGrp = CFGMR3GetChild(pCfgNetShaper, "BwGroups"); - if (pCfgBwGrp) { for (PCFGMNODE pCur = CFGMR3GetFirstChild(pCfgBwGrp); pCur; pCur = CFGMR3GetNextChild(pCur)) @@ -495,7 +515,7 @@ int pdmR3NetShaperInit(PVM pVM) if (RT_SUCCESS(rc)) rc = CFGMR3QueryU64(pCur, "Max", &cbMax); if (RT_SUCCESS(rc)) - rc = pdmNsBwGroupCreate(pNetShaper, pszBwGrpId, cbMax); + rc = pdmNsBwGroupCreate(pShaper, pszBwGrpId, cbMax); RTMemFree(pszBwGrpId); @@ -506,29 +526,22 @@ int pdmR3NetShaperInit(PVM pVM) if (RT_SUCCESS(rc)) { - PUVM pUVM = pVM->pUVM; - AssertMsg(!pUVM->pdm.s.pNetShaper, ("Network shaper was already initialized\n")); - - char szDesc[64]; - static unsigned s_iThread; - - RTStrPrintf(szDesc, sizeof(szDesc), "PDMNsTx-%d", ++s_iThread); - rc = PDMR3ThreadCreate(pVM, &pNetShaper->hTxThread, pNetShaper, - pdmR3NsTxThread, pdmR3NsTxWakeUp, 0, - RTTHREADTYPE_IO, szDesc); + rc = PDMR3ThreadCreate(pVM, &pShaper->pTxThread, pShaper, pdmR3NsTxThread, pdmR3NsTxWakeUp, + 0 /*cbStack*/, RTTHREADTYPE_IO, "PDMNsTx"); if (RT_SUCCESS(rc)) { - pUVM->pdm.s.pNetShaper = pNetShaper; + pUVM->pdm.s.pNetShaper = pShaper; return VINF_SUCCESS; } } - RTCritSectDelete(&pNetShaper->cs); + RTCritSectDelete(&pShaper->Lock); } - MMR3HeapFree(pNetShaper); + + MMR3HeapFree(pShaper); } - LogFlowFunc((": pVM=%p rc=%Rrc\n", pVM, rc)); + LogFlow(("pdmR3NetShaperInit: pVM=%p rc=%Rrc\n", pVM, rc)); return rc; } diff --git a/src/VBox/VMM/include/PDMInternal.h b/src/VBox/VMM/include/PDMInternal.h index 1ffb655247f..3a5bea29860 100644 --- a/src/VBox/VMM/include/PDMInternal.h +++ b/src/VBox/VMM/include/PDMInternal.h @@ -1085,13 +1085,14 @@ typedef struct PDMUSERPERVM /** Head of the templates. Singly linked, protected by ListCritSect. */ R3PTRTYPE(PPDMASYNCCOMPLETIONTEMPLATE) pAsyncCompletionTemplates; /** @} */ + + /** Global block cache data. */ + R3PTRTYPE(PPDMBLKCACHEGLOBAL) pBlkCacheGlobal; #ifdef VBOX_WITH_NETSHAPER /** Pointer to network shaper instance. */ R3PTRTYPE(PPDMNETSHAPER) pNetShaper; #endif /* VBOX_WITH_NETSHAPER */ - R3PTRTYPE(PPDMBLKCACHEGLOBAL) pBlkCacheGlobal; - } PDMUSERPERVM; /** Pointer to the PDM data kept in the UVM. */ typedef PDMUSERPERVM *PPDMUSERPERVM; diff --git a/include/VBox/vmm/pdmnetshaperint.h b/src/VBox/VMM/include/PDMNetShaperInternal.h index a4cb1049a17..bcff13091cd 100644 --- a/include/VBox/vmm/pdmnetshaperint.h +++ b/src/VBox/VMM/include/PDMNetShaperInternal.h @@ -1,11 +1,10 @@ /* $Id$ */ /** @file - * PDM Network Shaper - Internal data structures and functions common for both - * R0 and R3 parts. + * PDM Network Shaper - Internal data structures and functions common for both R0 and R3 parts. */ /* - * Copyright (C) 2011-2012 Oracle Corporation + * Copyright (C) 2011-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -31,19 +30,19 @@ typedef struct PDMNSBWGROUP { /** Pointer to the next group in the list. */ - struct PDMNSBWGROUP *pNext; + R3PTRTYPE(struct PDMNSBWGROUP *) pNextR3; /** Pointer to the shared UVM structure. */ - struct PDMNETSHAPER *pShaper; + R3PTRTYPE(struct PDMNETSHAPER *) pShaperR3; /** Critical section protecting all members below. */ - PDMCRITSECT cs; + PDMCRITSECT Lock; /** Pointer to the first filter attached to this group. */ - struct PDMNSFILTER *pFiltersHead; + R3PTRTYPE(struct PDMNSFILTER *) pFiltersHeadR3; /** Bandwidth group name. */ - char *pszName; + R3PTRTYPE(char *) pszNameR3; /** Maximum number of bytes filters are allowed to transfer. */ - volatile uint64_t cbTransferPerSecMax; + volatile uint64_t cbPerSecMax; /** Number of bytes we are allowed to transfer in one burst. */ - volatile uint32_t cbBucketSize; + volatile uint32_t cbBucket; /** Number of bytes we were allowed to transfer at the last update. */ volatile uint32_t cbTokensLast; /** Timestamp of the last update */ @@ -54,41 +53,4 @@ typedef struct PDMNSBWGROUP /** Pointer to a bandwidth group. */ typedef PDMNSBWGROUP *PPDMNSBWGROUP; -DECLINLINE(bool) pdmNsAllocateBandwidth(PPDMNSFILTER pFilter, size_t cbTransfer) -{ - AssertPtrReturn(pFilter, true); - if (!VALID_PTR(pFilter->CTX_SUFF(pBwGroup))) - return true; - - PPDMNSBWGROUP pBwGroup = ASMAtomicReadPtrT(&pFilter->CTX_SUFF(pBwGroup), PPDMNSBWGROUP); - int rc = PDMCritSectEnter(&pBwGroup->cs, VERR_SEM_BUSY); AssertRC(rc); - if (RT_UNLIKELY(rc == VERR_SEM_BUSY)) - return true; - bool fAllowed = true; - if (pBwGroup->cbTransferPerSecMax) - { - /* Re-fill the bucket first */ - uint64_t tsNow = RTTimeSystemNanoTS(); - uint32_t uTokensAdded = (tsNow - pBwGroup->tsUpdatedLast)*pBwGroup->cbTransferPerSecMax/(1000*1000*1000); - uint32_t uTokens = RT_MIN(pBwGroup->cbBucketSize, uTokensAdded + pBwGroup->cbTokensLast); - - if (cbTransfer > uTokens) - { - fAllowed = false; - ASMAtomicWriteBool(&pFilter->fChoked, true); - } - else - { - pBwGroup->tsUpdatedLast = tsNow; - pBwGroup->cbTokensLast = uTokens - (uint32_t)cbTransfer; - } - Log2((LOG_FN_FMT "BwGroup=%#p{%s} cbTransfer=%u uTokens=%u uTokensAdded=%u fAllowed=%RTbool\n", - __PRETTY_FUNCTION__, pBwGroup, pBwGroup->pszName, cbTransfer, uTokens, uTokensAdded, fAllowed)); - } - else - Log2((LOG_FN_FMT "BwGroup=%#p{%s} disabled fAllowed=%RTbool\n", - __PRETTY_FUNCTION__, pBwGroup, pBwGroup->pszName, fAllowed)); - rc = PDMCritSectLeave(&pBwGroup->cs); AssertRC(rc); - return fAllowed; -} |