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 /src | |
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
Diffstat (limited to 'src')
-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 | 56 |
8 files changed, 232 insertions, 214 deletions
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/src/VBox/VMM/include/PDMNetShaperInternal.h b/src/VBox/VMM/include/PDMNetShaperInternal.h new file mode 100644 index 00000000000..bcff13091cd --- /dev/null +++ b/src/VBox/VMM/include/PDMNetShaperInternal.h @@ -0,0 +1,56 @@ +/* $Id$ */ +/** @file + * PDM Network Shaper - Internal data structures and functions common for both R0 and R3 parts. + */ + +/* + * 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; + * 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. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + +/** + * Bandwidth group instance data + */ +typedef struct PDMNSBWGROUP +{ + /** Pointer to the next group in the list. */ + R3PTRTYPE(struct PDMNSBWGROUP *) pNextR3; + /** Pointer to the shared UVM structure. */ + R3PTRTYPE(struct PDMNETSHAPER *) pShaperR3; + /** Critical section protecting all members below. */ + PDMCRITSECT Lock; + /** Pointer to the first filter attached to this group. */ + R3PTRTYPE(struct PDMNSFILTER *) pFiltersHeadR3; + /** Bandwidth group name. */ + R3PTRTYPE(char *) pszNameR3; + /** Maximum number of bytes filters are allowed to transfer. */ + volatile uint64_t cbPerSecMax; + /** Number of bytes we are allowed to transfer in one burst. */ + 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 */ + volatile uint64_t tsUpdatedLast; + /** Reference counter - How many filters are associated with this group. */ + volatile uint32_t cRefs; +} PDMNSBWGROUP; +/** Pointer to a bandwidth group. */ +typedef PDMNSBWGROUP *PPDMNSBWGROUP; + + |