PDMNetShaper.cpp revision b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/* $Id$ */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/** @file
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * PDM Network Shaper - Limit network traffic according to bandwidth
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * group settings.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/*
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Copyright (C) 2006-2012 Oracle Corporation
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync *
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * available from http://www.virtualbox.org. This file is free software;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * General Public License (GPL) as published by the Free Software
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/*******************************************************************************
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync* Header Files *
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync*******************************************************************************/
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#define LOG_GROUP LOG_GROUP_NET_SHAPER
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#include "PDMInternal.h"
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#include <VBox/vmm/pdm.h>
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#include <VBox/vmm/mm.h>
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#ifdef VBOX_WITH_REM
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync# include <VBox/vmm/rem.h>
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#endif
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#include <VBox/vmm/vm.h>
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#include <VBox/vmm/uvm.h>
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#include <VBox/err.h>
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#include <VBox/log.h>
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#include <iprt/asm.h>
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#include <iprt/assert.h>
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#include <iprt/thread.h>
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#include <iprt/mem.h>
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#include <iprt/critsect.h>
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#include <iprt/tcp.h>
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#include <iprt/path.h>
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#include <iprt/string.h>
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#include <VBox/vmm/pdmnetshaper.h>
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/*******************************************************************************
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync* Structures and Typedefs *
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync*******************************************************************************/
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/**
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Bandwidth group instance data
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsynctypedef struct PDMNSBWGROUP
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** Pointer to the next group in the list. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync struct PDMNSBWGROUP *pNext;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** Pointer to the shared UVM structure. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync struct PDMNETSHAPER *pShaper;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** Critical section protecting all members below. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync RTCRITSECT cs;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** Pointer to the first filter attached to this group. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync struct PDMNSFILTER *pFiltersHead;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** Bandwidth group name. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync char *pszName;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** Maximum number of bytes filters are allowed to transfer. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync volatile uint32_t cbTransferPerSecMax;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** Number of bytes we are allowed to transfer in one burst. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync volatile uint32_t cbBucketSize;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** Number of bytes we were allowed to transfer at the last update. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync volatile uint32_t cbTokensLast;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** Timestamp of the last update */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync volatile uint64_t tsUpdatedLast;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** Reference counter - How many filters are associated with this group. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync volatile uint32_t cRefs;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync} PDMNSBWGROUP;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/** Pointer to a bandwidth group. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsynctypedef PDMNSBWGROUP *PPDMNSBWGROUP;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/**
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Network shaper data. One instance per VM.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsynctypedef struct PDMNETSHAPER
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** Pointer to the shared VM structure. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PVM pVM;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** Critical section protecting all members below. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync RTCRITSECT cs;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** Pointer to the first bandwidth group. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSBWGROUP pBwGroupsHead;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync} PDMNETSHAPER;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/*******************************************************************************
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync* Internal Functions *
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync*******************************************************************************/
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncstatic PPDMNSBWGROUP pdmNsBwGroupFindById(PPDMNETSHAPER pShaper, const char *pcszId)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSBWGROUP pBwGroup = NULL;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_VALID_PTR(pcszId))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup = pShaper->pBwGroupsHead;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync while ( pBwGroup
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync && RTStrCmp(pBwGroup->pszName, pcszId))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup = pBwGroup->pNext;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync rc = RTCritSectLeave(&pShaper->cs); AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync return pBwGroup;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncstatic void pdmNsBwGroupLink(PPDMNSBWGROUP pBwGroup)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNETSHAPER pShaper = pBwGroup->pShaper;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup->pNext = pShaper->pBwGroupsHead;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pShaper->pBwGroupsHead = pBwGroup;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync rc = RTCritSectLeave(&pShaper->cs); AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#if 0
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncstatic void pdmNsBwGroupUnlink(PPDMNSBWGROUP pBwGroup)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNETSHAPER pShaper = pBwGroup->pShaper;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (pBwGroup == pShaper->pBwGroupsHead)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pShaper->pBwGroupsHead = pBwGroup->pNext;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync else
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSBWGROUP pPrev = pShaper->pBwGroupsHead;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync while ( pPrev
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync && pPrev->pNext != pBwGroup)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pPrev = pPrev->pNext;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync AssertPtr(pPrev);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pPrev->pNext = pBwGroup->pNext;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync rc = RTCritSectLeave(&pShaper->cs); AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#endif
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncstatic int pdmNsBwGroupCreate(PPDMNETSHAPER pShaper, const char *pcszBwGroup, uint32_t cbTransferPerSecMax)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync LogFlowFunc(("pShaper=%#p pcszBwGroup=%#p{%s} cbTransferPerSecMax=%u\n",
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pShaper, pcszBwGroup, pcszBwGroup, cbTransferPerSecMax));
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync AssertPtrReturn(pShaper, VERR_INVALID_POINTER);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync AssertPtrReturn(pcszBwGroup, VERR_INVALID_POINTER);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync AssertReturn(*pcszBwGroup != '\0', VERR_INVALID_PARAMETER);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync int rc;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSBWGROUP pBwGroup = pdmNsBwGroupFindById(pShaper, pcszBwGroup);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (!pBwGroup)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync rc = MMR3HeapAllocZEx(pShaper->pVM, MM_TAG_PDM_NET_SHAPER,
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync sizeof(PDMNSBWGROUP),
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync (void **)&pBwGroup);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_SUCCESS(rc))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync rc = RTCritSectInit(&pBwGroup->cs);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_SUCCESS(rc))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup->pszName = RTStrDup(pcszBwGroup);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (pBwGroup->pszName)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup->pShaper = pShaper;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup->cRefs = 0;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup->cbTransferPerSecMax = cbTransferPerSecMax;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup->cbBucketSize = RT_MAX(PDM_NETSHAPER_MIN_BUCKET_SIZE,
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync cbTransferPerSecMax * PDM_NETSHAPER_MAX_LATENCY / 1000);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup->cbTokensLast = pBwGroup->cbBucketSize;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup->tsUpdatedLast = RTTimeSystemNanoTS();
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync LogFlowFunc(("pcszBwGroup={%s} cbBucketSize=%u\n",
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pcszBwGroup, pBwGroup->cbBucketSize));
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pdmNsBwGroupLink(pBwGroup);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync return VINF_SUCCESS;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync RTCritSectDelete(&pBwGroup->cs);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync MMR3HeapFree(pBwGroup);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync else
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync rc = VERR_NO_MEMORY;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync else
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync rc = VERR_ALREADY_EXISTS;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync LogFlowFunc(("returns rc=%Rrc\n", rc));
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync return rc;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncstatic void pdmNsBwGroupTerminate(PPDMNSBWGROUP pBwGroup)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync Assert(pBwGroup->cRefs == 0);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RTCritSectIsInitialized(&pBwGroup->cs))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync RTCritSectDelete(&pBwGroup->cs);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncDECLINLINE(void) pdmNsBwGroupRef(PPDMNSBWGROUP pBwGroup)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync ASMAtomicIncU32(&pBwGroup->cRefs);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncDECLINLINE(void) pdmNsBwGroupUnref(PPDMNSBWGROUP pBwGroup)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync Assert(pBwGroup->cRefs > 0);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync ASMAtomicDecU32(&pBwGroup->cRefs);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncstatic void pdmNsFilterLink(PPDMNSFILTER pFilter)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSBWGROUP pBwGroup = pFilter->pBwGroupR3;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync int rc = RTCritSectEnter(&pBwGroup->cs); AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pFilter->pNext = pBwGroup->pFiltersHead;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup->pFiltersHead = pFilter;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync rc = RTCritSectLeave(&pBwGroup->cs); AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncstatic void pdmNsFilterUnlink(PPDMNSFILTER pFilter)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSBWGROUP pBwGroup = pFilter->pBwGroupR3;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync int rc = RTCritSectEnter(&pBwGroup->cs); AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (pFilter == pBwGroup->pFiltersHead)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup->pFiltersHead = pFilter->pNext;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync else
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSFILTER pPrev = pBwGroup->pFiltersHead;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync while ( pPrev
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync && pPrev->pNext != pFilter)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pPrev = pPrev->pNext;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync AssertPtr(pPrev);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pPrev->pNext = pFilter->pNext;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync rc = RTCritSectLeave(&pBwGroup->cs); AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncVMMR3DECL(int) PDMR3NsAttach(PVM pVM, PPDMDRVINS pDrvIns, const char *pcszBwGroup,
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSFILTER pFilter)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync VM_ASSERT_EMT(pVM);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync AssertPtrReturn(pFilter, VERR_INVALID_POINTER);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync AssertReturn(pFilter->pBwGroupR3 == NULL, VERR_ALREADY_EXISTS);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PUVM pUVM = pVM->pUVM;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNETSHAPER pShaper = pUVM->pdm.s.pNetShaper;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSBWGROUP pBwGroupOld = NULL;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSBWGROUP pBwGroupNew = NULL;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_SUCCESS(rc))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (pcszBwGroup)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroupNew = pdmNsBwGroupFindById(pShaper, pcszBwGroup);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (pBwGroupNew)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pdmNsBwGroupRef(pBwGroupNew);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync else
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync rc = VERR_NOT_FOUND;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_SUCCESS(rc))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroupOld = ASMAtomicXchgPtrT(&pFilter->pBwGroupR3, pBwGroupNew, PPDMNSBWGROUP);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (pBwGroupOld)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pdmNsBwGroupUnref(pBwGroupOld);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pdmNsFilterLink(pFilter);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync int rc2 = RTCritSectLeave(&pShaper->cs); AssertRC(rc2);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync return rc;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncVMMR3DECL(int) PDMR3NsDetach(PVM pVM, PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync VM_ASSERT_EMT(pVM);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync AssertPtrReturn(pFilter, VERR_INVALID_POINTER);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync AssertPtrReturn(pFilter->pBwGroupR3, VERR_INVALID_POINTER);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PUVM pUVM = pVM->pUVM;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNETSHAPER pShaper = pUVM->pdm.s.pNetShaper;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_SUCCESS(rc))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pdmNsFilterUnlink(pFilter);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSBWGROUP pBwGroup = NULL;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup = ASMAtomicXchgPtrT(&pFilter->pBwGroupR3, NULL, PPDMNSBWGROUP);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (pBwGroup)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pdmNsBwGroupUnref(pBwGroup);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync int rc2 = RTCritSectLeave(&pShaper->cs); AssertRC(rc2);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync return rc;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncbool PDMR3NsAllocateBandwidth(PPDMNSFILTER pFilter, uint32_t cbTransfer)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (!VALID_PTR(pFilter->pBwGroupR3))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync return true;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSBWGROUP pBwGroup = ASMAtomicReadPtrT(&pFilter->pBwGroupR3, PPDMNSBWGROUP);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync int rc = RTCritSectEnter(&pBwGroup->cs); AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync bool fAllowed = true;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /* Re-fill the bucket first */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync uint64_t tsNow = RTTimeSystemNanoTS();
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync uint32_t uTokensAdded = (tsNow - pBwGroup->tsUpdatedLast)*pBwGroup->cbTransferPerSecMax/(1000*1000*1000);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync uint32_t uTokens = RT_MIN(pBwGroup->cbBucketSize, uTokensAdded + pBwGroup->cbTokensLast);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (cbTransfer > uTokens)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync fAllowed = false;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync else
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup->tsUpdatedLast = tsNow;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup->cbTokensLast = uTokens - cbTransfer;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync rc = RTCritSectLeave(&pBwGroup->cs); AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync LogFlowFunc(("BwGroup=%#p{%s} cbTransfer=%u uTokens=%u uTokensAdded=%u fAllowed=%RTbool\n",
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup, pBwGroup->pszName, cbTransfer, uTokens, uTokensAdded, fAllowed));
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync return true; // @todo: i need to implement TX thread first! return fAllowed;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/**
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Terminate the network shaper.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync *
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * @returns VBox error code.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * @param pVM Pointer to VM.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync *
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * @remarks This method destroys all bandwidth group objects.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncint pdmR3NetShaperTerm(PVM pVM)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PUVM pUVM = pVM->pUVM;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNETSHAPER pShaper = pUVM->pdm.s.pNetShaper;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /* Destroy the bandwidth managers. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSBWGROUP pBwGroup = pShaper->pBwGroupsHead;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync while (pBwGroup)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSBWGROUP pFree = pBwGroup;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup = pBwGroup->pNext;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pdmNsBwGroupTerminate(pFree);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync MMR3HeapFree(pFree);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync RTCritSectDelete(&pShaper->cs);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync return VINF_SUCCESS;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/**
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Initialize the network shaper.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync *
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * @returns VBox status code
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * @param pVM Pointer to the shared VM structure.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncint pdmR3NetShaperInit(PVM pVM)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync LogFlowFunc((": pVM=%p\n", pVM));
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync VM_ASSERT_EMT(pVM);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNETSHAPER pNetShaper = NULL;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync int rc = MMR3HeapAllocZEx(pVM, MM_TAG_PDM_NET_SHAPER,
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync sizeof(PDMNETSHAPER),
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync (void **)&pNetShaper);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_SUCCESS(rc))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PCFGMNODE pCfgRoot = CFGMR3GetRoot(pVM);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PCFGMNODE pCfgNetShaper = CFGMR3GetChild(CFGMR3GetChild(pCfgRoot, "PDM"), "NetworkShaper");
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pNetShaper->pVM = pVM;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync rc = RTCritSectInit(&pNetShaper->cs);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_SUCCESS(rc))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /* Create all bandwidth groups. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PCFGMNODE pCfgBwGrp = CFGMR3GetChild(pCfgNetShaper, "BwGroups");
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (pCfgBwGrp)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync for (PCFGMNODE pCur = CFGMR3GetFirstChild(pCfgBwGrp); pCur; pCur = CFGMR3GetNextChild(pCur))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync uint32_t cbMax;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync size_t cchName = CFGMR3GetNameLen(pCur) + 1;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync char *pszBwGrpId = (char *)RTMemAllocZ(cchName);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (!pszBwGrpId)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync rc = VERR_NO_MEMORY;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync break;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync rc = CFGMR3GetName(pCur, pszBwGrpId, cchName);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_SUCCESS(rc))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync rc = CFGMR3QueryU32(pCur, "Max", &cbMax);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_SUCCESS(rc))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync rc = pdmNsBwGroupCreate(pNetShaper, pszBwGrpId, cbMax);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync RTMemFree(pszBwGrpId);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_FAILURE(rc))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync break;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_SUCCESS(rc))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PUVM pUVM = pVM->pUVM;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync AssertMsg(!pUVM->pdm.s.pNetShaper,
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync ("Network shaper was already initialized\n"));
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pUVM->pdm.s.pNetShaper = pNetShaper;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync return VINF_SUCCESS;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync RTCritSectDelete(&pNetShaper->cs);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync MMR3HeapFree(pNetShaper);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync LogFlowFunc((": pVM=%p rc=%Rrc\n", pVM, rc));
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync return rc;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync