PDMNetShaper.cpp revision 404dd7b4bf7209363c3ab5b98944ff8405e0130b
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/* $Id$ */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** @file
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * PDM Network Shaper - Limit network traffic according to bandwidth
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * group settings.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync/*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Copyright (C) 2006-2012 Oracle Corporation
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * available from http://www.virtualbox.org. This file is free software;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * you can redistribute it and/or modify it under the terms of the GNU
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * General Public License (GPL) as published by the Free Software
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/*******************************************************************************
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync* Header Files *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync*******************************************************************************/
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#define LOG_GROUP LOG_GROUP_NET_SHAPER
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include "PDMInternal.h"
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <VBox/vmm/pdm.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <VBox/vmm/mm.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#ifdef VBOX_WITH_REM
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync# include <VBox/vmm/rem.h>
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync#endif
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync#include <VBox/vmm/vm.h>
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync#include <VBox/vmm/uvm.h>
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync#include <VBox/err.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <VBox/log.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/asm.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/assert.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/thread.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/mem.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/critsect.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/tcp.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/path.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/string.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync#include <VBox/vmm/pdmnetshaper.h>
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/*******************************************************************************
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync* Structures and Typedefs *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync*******************************************************************************/
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Bandwidth group instance data
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsynctypedef struct PDMNSBWGROUP
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Pointer to the next group in the list. */
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync struct PDMNSBWGROUP *pNext;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Pointer to the shared UVM structure. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync struct PDMNETSHAPER *pShaper;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Critical section protecting all members below. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTCRITSECT cs;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Pointer to the first filter attached to this group. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync struct PDMNSFILTER *pFiltersHead;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Bandwidth group name. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync char *pszName;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Maximum number of bytes filters are allowed to transfer. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync volatile uint32_t cbTransferPerSecMax;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Number of bytes we are allowed to transfer in one burst. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync volatile uint32_t cbBucketSize;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Number of bytes we were allowed to transfer at the last update. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync volatile uint32_t cbTokensLast;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Timestamp of the last update */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync volatile uint64_t tsUpdatedLast;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Reference counter - How many filters are associated with this group. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync volatile uint32_t cRefs;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync} PDMNSBWGROUP;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** Pointer to a bandwidth group. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsynctypedef PDMNSBWGROUP *PPDMNSBWGROUP;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Network shaper data. One instance per VM.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsynctypedef struct PDMNETSHAPER
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Pointer to the VM. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PVM pVM;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Critical section protecting all members below. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTCRITSECT cs;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Pending TX thread. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMTHREAD hTxThread;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Pointer to the first bandwidth group. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNSBWGROUP pBwGroupsHead;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync} PDMNETSHAPER;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/*******************************************************************************
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync* Internal Functions *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync*******************************************************************************/
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic PPDMNSBWGROUP pdmNsBwGroupFindById(PPDMNETSHAPER pShaper, const char *pcszId)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNSBWGROUP pBwGroup = NULL;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_VALID_PTR(pcszId))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync pBwGroup = pShaper->pBwGroupsHead;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync while ( pBwGroup
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync && RTStrCmp(pBwGroup->pszName, pcszId))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroup = pBwGroup->pNext;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTCritSectLeave(&pShaper->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return pBwGroup;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic void pdmNsBwGroupLink(PPDMNSBWGROUP pBwGroup)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNETSHAPER pShaper = pBwGroup->pShaper;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroup->pNext = pShaper->pBwGroupsHead;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pShaper->pBwGroupsHead = pBwGroup;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTCritSectLeave(&pShaper->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#if 0
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic void pdmNsBwGroupUnlink(PPDMNSBWGROUP pBwGroup)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNETSHAPER pShaper = pBwGroup->pShaper;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pBwGroup == pShaper->pBwGroupsHead)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pShaper->pBwGroupsHead = pBwGroup->pNext;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNSBWGROUP pPrev = pShaper->pBwGroupsHead;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync while ( pPrev
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync && pPrev->pNext != pBwGroup)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pPrev = pPrev->pNext;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtr(pPrev);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pPrev->pNext = pBwGroup->pNext;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTCritSectLeave(&pShaper->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#endif
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic void pdmNsBwGroupSetLimit(PPDMNSBWGROUP pBwGroup, uint32_t cbTransferPerSecMax)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroup->cbTransferPerSecMax = cbTransferPerSecMax;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroup->cbBucketSize = RT_MAX(PDM_NETSHAPER_MIN_BUCKET_SIZE,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync cbTransferPerSecMax * PDM_NETSHAPER_MAX_LATENCY / 1000);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogFlowFunc(("New rate limit is %d bytes per second, adjusted bucket size to %d bytes\n",
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroup->cbTransferPerSecMax, pBwGroup->cbBucketSize));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic int pdmNsBwGroupCreate(PPDMNETSHAPER pShaper, const char *pcszBwGroup, uint32_t cbTransferPerSecMax)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogFlowFunc(("pShaper=%#p pcszBwGroup=%#p{%s} cbTransferPerSecMax=%u\n",
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pShaper, pcszBwGroup, pcszBwGroup, cbTransferPerSecMax));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtrReturn(pShaper, VERR_INVALID_POINTER);
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync AssertPtrReturn(pcszBwGroup, VERR_INVALID_POINTER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertReturn(*pcszBwGroup != '\0', VERR_INVALID_PARAMETER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNSBWGROUP pBwGroup = pdmNsBwGroupFindById(pShaper, pcszBwGroup);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!pBwGroup)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = MMR3HeapAllocZEx(pShaper->pVM, MM_TAG_PDM_NET_SHAPER,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync sizeof(PDMNSBWGROUP),
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync (void **)&pBwGroup);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTCritSectInit(&pBwGroup->cs);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroup->pszName = RTStrDup(pcszBwGroup);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pBwGroup->pszName)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroup->pShaper = pShaper;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroup->cRefs = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pdmNsBwGroupSetLimit(pBwGroup, cbTransferPerSecMax);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroup->cbTokensLast = pBwGroup->cbBucketSize;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroup->tsUpdatedLast = RTTimeSystemNanoTS();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogFlowFunc(("pcszBwGroup={%s} cbBucketSize=%u\n",
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pcszBwGroup, pBwGroup->cbBucketSize));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pdmNsBwGroupLink(pBwGroup);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return VINF_SUCCESS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTCritSectDelete(&pBwGroup->cs);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync MMR3HeapFree(pBwGroup);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = VERR_NO_MEMORY;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = VERR_ALREADY_EXISTS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogFlowFunc(("returns rc=%Rrc\n", rc));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic void pdmNsBwGroupTerminate(PPDMNSBWGROUP pBwGroup)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync Assert(pBwGroup->cRefs == 0);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RTCritSectIsInitialized(&pBwGroup->cs))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTCritSectDelete(&pBwGroup->cs);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncDECLINLINE(void) pdmNsBwGroupRef(PPDMNSBWGROUP pBwGroup)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync ASMAtomicIncU32(&pBwGroup->cRefs);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncDECLINLINE(void) pdmNsBwGroupUnref(PPDMNSBWGROUP pBwGroup)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync Assert(pBwGroup->cRefs > 0);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync ASMAtomicDecU32(&pBwGroup->cRefs);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic void pdmNsBwGroupXmitPending(PPDMNSBWGROUP pBwGroup)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * We don't need to hold the bandwidth group lock to iterate over the list
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * of filters since the filters are removed while the shaper lock is being
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * held.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtr(pBwGroup);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtr(pBwGroup->pShaper);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync Assert(RTCritSectIsOwner(&pBwGroup->pShaper->cs));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync //int rc = RTCritSectEnter(&pBwGroup->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNSFILTER pFilter = pBwGroup->pFiltersHead;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync while (pFilter)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync bool fChoked = ASMAtomicXchgBool(&pFilter->fChoked, false);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync Log3((LOG_FN_FMT ": pFilter=%#p fChoked=%RTbool\n", __PRETTY_FUNCTION__, pFilter, fChoked));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (fChoked && pFilter->pIDrvNet)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogFlowFunc(("Calling pfnXmitPending for pFilter=%#p\n", pFilter));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pFilter->pIDrvNet->pfnXmitPending(pFilter->pIDrvNet);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pFilter = pFilter->pNext;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync //rc = RTCritSectLeave(&pBwGroup->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic void pdmNsFilterLink(PPDMNSFILTER pFilter)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNSBWGROUP pBwGroup = pFilter->pBwGroupR3;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = RTCritSectEnter(&pBwGroup->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pFilter->pNext = pBwGroup->pFiltersHead;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroup->pFiltersHead = pFilter;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTCritSectLeave(&pBwGroup->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic void pdmNsFilterUnlink(PPDMNSFILTER pFilter)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNSBWGROUP pBwGroup = pFilter->pBwGroupR3;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * We need to make sure we hold the shaper lock since pdmNsBwGroupXmitPending()
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * does not hold the bandwidth group lock while iterating over the list
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * of group's filters.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtr(pBwGroup);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtr(pBwGroup->pShaper);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync Assert(RTCritSectIsOwner(&pBwGroup->pShaper->cs));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = RTCritSectEnter(&pBwGroup->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pFilter == pBwGroup->pFiltersHead)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroup->pFiltersHead = pFilter->pNext;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNSFILTER pPrev = pBwGroup->pFiltersHead;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync while ( pPrev
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync && pPrev->pNext != pFilter)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pPrev = pPrev->pNext;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtr(pPrev);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pPrev->pNext = pFilter->pNext;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTCritSectLeave(&pBwGroup->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncVMMR3DECL(int) PDMR3NsAttach(PVM pVM, PPDMDRVINS pDrvIns, const char *pcszBwGroup,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNSFILTER pFilter)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync VM_ASSERT_EMT(pVM);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtrReturn(pFilter, VERR_INVALID_POINTER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertReturn(pFilter->pBwGroupR3 == NULL, VERR_ALREADY_EXISTS);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PUVM pUVM = pVM->pUVM;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNETSHAPER pShaper = pUVM->pdm.s.pNetShaper;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNSBWGROUP pBwGroupOld = NULL;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNSBWGROUP pBwGroupNew = NULL;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pcszBwGroup)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroupNew = pdmNsBwGroupFindById(pShaper, pcszBwGroup);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pBwGroupNew)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pdmNsBwGroupRef(pBwGroupNew);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = VERR_NOT_FOUND;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroupOld = ASMAtomicXchgPtrT(&pFilter->pBwGroupR3, pBwGroupNew, PPDMNSBWGROUP);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pBwGroupOld)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pdmNsBwGroupUnref(pBwGroupOld);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pdmNsFilterLink(pFilter);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc2 = RTCritSectLeave(&pShaper->cs); AssertRC(rc2);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncVMMR3DECL(int) PDMR3NsDetach(PVM pVM, PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync VM_ASSERT_EMT(pVM);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtrReturn(pFilter, VERR_INVALID_POINTER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtrReturn(pFilter->pBwGroupR3, VERR_INVALID_POINTER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PUVM pUVM = pVM->pUVM;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNETSHAPER pShaper = pUVM->pdm.s.pNetShaper;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pdmNsFilterUnlink(pFilter);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNSBWGROUP pBwGroup = NULL;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroup = ASMAtomicXchgPtrT(&pFilter->pBwGroupR3, NULL, PPDMNSBWGROUP);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pBwGroup)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pdmNsBwGroupUnref(pBwGroup);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc2 = RTCritSectLeave(&pShaper->cs); AssertRC(rc2);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncVMMR3DECL(bool) PDMR3NsAllocateBandwidth(PPDMNSFILTER pFilter, uint32_t cbTransfer)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtrReturn(pFilter, VERR_INVALID_POINTER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!VALID_PTR(pFilter->pBwGroupR3))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return true;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNSBWGROUP pBwGroup = ASMAtomicReadPtrT(&pFilter->pBwGroupR3, PPDMNSBWGROUP);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = RTCritSectEnter(&pBwGroup->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync bool fAllowed = true;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Re-fill the bucket first */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync uint64_t tsNow = RTTimeSystemNanoTS();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync uint32_t uTokensAdded = (tsNow - pBwGroup->tsUpdatedLast)*pBwGroup->cbTransferPerSecMax/(1000*1000*1000);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync uint32_t uTokens = RT_MIN(pBwGroup->cbBucketSize, uTokensAdded + pBwGroup->cbTokensLast);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (cbTransfer > uTokens)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync fAllowed = false;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync ASMAtomicWriteBool(&pFilter->fChoked, true);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroup->tsUpdatedLast = tsNow;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroup->cbTokensLast = uTokens - cbTransfer;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTCritSectLeave(&pBwGroup->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync Log2((LOG_FN_FMT "BwGroup=%#p{%s} cbTransfer=%u uTokens=%u uTokensAdded=%u fAllowed=%RTbool\n",
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync __PRETTY_FUNCTION__, pBwGroup, pBwGroup->pszName, cbTransfer, uTokens, uTokensAdded, fAllowed));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return fAllowed;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsyncVMMR3DECL(int) PDMR3NsBwGroupSetLimit(PVM pVM, const char *pcszBwGroup, uint32_t cbTransferPerSecMax)
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync{
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync PUVM pUVM = pVM->pUVM;
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync PPDMNETSHAPER pShaper = pUVM->pdm.s.pNetShaper;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc);
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync if (RT_SUCCESS(rc))
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync {
a39ea3668b7019c23a68936259545f9b71bce1aavboxsync PPDMNSBWGROUP pBwGroup = pdmNsBwGroupFindById(pShaper, pcszBwGroup);
0db6a029780d9f9b347500e117320a8d5661efe5vboxsync if (pBwGroup)
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTCritSectEnter(&pBwGroup->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pdmNsBwGroupSetLimit(pBwGroup, cbTransferPerSecMax);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync /* Drop extra tokens */
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync if (pBwGroup->cbTokensLast > pBwGroup->cbBucketSize)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroup->cbTokensLast = pBwGroup->cbBucketSize;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTCritSectLeave(&pBwGroup->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTCritSectLeave(&pShaper->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * I/O thread for pending TX.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns VINF_SUCCESS (ignored).
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pVM Pointer to the VM.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pThread The PDM thread data.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic DECLCALLBACK(int) pdmR3NsTxThread(PVM pVM, PPDMTHREAD pThread)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNETSHAPER pShaper = (PPDMNETSHAPER)pThread->pvUser;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogFlow(("pdmR3NsTxThread: pShaper=%p\n", pShaper));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync while (pThread->enmState == PDMTHREADSTATE_RUNNING)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTThreadSleep(PDM_NETSHAPER_MAX_LATENCY);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Go over all bandwidth groups/filters calling pfnXmitPending */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNSBWGROUP pBwGroup = pShaper->pBwGroupsHead;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync while (pBwGroup)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pdmNsBwGroupXmitPending(pBwGroup);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroup = pBwGroup->pNext;
cba6719bd64ec749967bbe931230452664109857vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTCritSectLeave(&pShaper->cs); AssertRC(rc);
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return VINF_SUCCESS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @copydoc FNPDMTHREADWAKEUPINT
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic DECLCALLBACK(int) pdmR3NsTxWakeUp(PVM pVM, PPDMTHREAD pThread)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync PPDMNETSHAPER pShaper = (PPDMNETSHAPER)pThread->pvUser;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogFlow(("pdmR3NsTxWakeUp: pShaper=%p\n", pShaper));
5530d99d77afedf5676a976e5135c89478b4e8d0vboxsync /* Nothing to do */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return VINF_SUCCESS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Terminate the network shaper.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns VBox error code.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pVM Pointer to VM.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @remarks This method destroys all bandwidth group objects.
0db6a029780d9f9b347500e117320a8d5661efe5vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncint pdmR3NetShaperTerm(PVM pVM)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PUVM pUVM = pVM->pUVM;
cba6719bd64ec749967bbe931230452664109857vboxsync PPDMNETSHAPER pShaper = pUVM->pdm.s.pNetShaper;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Destroy the bandwidth managers. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNSBWGROUP pBwGroup = pShaper->pBwGroupsHead;
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync while (pBwGroup)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNSBWGROUP pFree = pBwGroup;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBwGroup = pBwGroup->pNext;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pdmNsBwGroupTerminate(pFree);
8bed792bc65abd39393889351f22263ce6c289bfvboxsync MMR3HeapFree(pFree);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTCritSectDelete(&pShaper->cs);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return VINF_SUCCESS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
fbf08fabb4c4b383d6aa2830c2bd5b943a26f10cvboxsync
fbf08fabb4c4b383d6aa2830c2bd5b943a26f10cvboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Initialize the network shaper.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns VBox status code
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pVM Pointer to the VM.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncint pdmR3NetShaperInit(PVM pVM)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogFlowFunc((": pVM=%p\n", pVM));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync VM_ASSERT_EMT(pVM);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMNETSHAPER pNetShaper = NULL;
5b465a7c1237993faf8bb50120d247f3f0319adavboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = MMR3HeapAllocZEx(pVM, MM_TAG_PDM_NET_SHAPER,
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync sizeof(PDMNETSHAPER),
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync (void **)&pNetShaper);
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync if (RT_SUCCESS(rc))
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PCFGMNODE pCfgRoot = CFGMR3GetRoot(pVM);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PCFGMNODE pCfgNetShaper = CFGMR3GetChild(CFGMR3GetChild(pCfgRoot, "PDM"), "NetworkShaper");
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pNetShaper->pVM = pVM;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTCritSectInit(&pNetShaper->cs);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Create all bandwidth groups. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PCFGMNODE pCfgBwGrp = CFGMR3GetChild(pCfgNetShaper, "BwGroups");
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pCfgBwGrp)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync for (PCFGMNODE pCur = CFGMR3GetFirstChild(pCfgBwGrp); pCur; pCur = CFGMR3GetNextChild(pCur))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync uint32_t cbMax;
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync size_t cchName = CFGMR3GetNameLen(pCur) + 1;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync char *pszBwGrpId = (char *)RTMemAllocZ(cchName);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!pszBwGrpId)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = VERR_NO_MEMORY;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
be284093a5d9a46ac136e8d272fda9201eb8d048vboxsync rc = CFGMR3GetName(pCur, pszBwGrpId, cchName);
be284093a5d9a46ac136e8d272fda9201eb8d048vboxsync AssertRC(rc);
cba6719bd64ec749967bbe931230452664109857vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = CFGMR3QueryU32(pCur, "Max", &cbMax);
5530d99d77afedf5676a976e5135c89478b4e8d0vboxsync if (RT_SUCCESS(rc))
cba6719bd64ec749967bbe931230452664109857vboxsync rc = pdmNsBwGroupCreate(pNetShaper, pszBwGrpId, cbMax);
5530d99d77afedf5676a976e5135c89478b4e8d0vboxsync
cba6719bd64ec749967bbe931230452664109857vboxsync RTMemFree(pszBwGrpId);
cba6719bd64ec749967bbe931230452664109857vboxsync
cba6719bd64ec749967bbe931230452664109857vboxsync if (RT_FAILURE(rc))
cba6719bd64ec749967bbe931230452664109857vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
be284093a5d9a46ac136e8d272fda9201eb8d048vboxsync }
if (RT_SUCCESS(rc))
{
PUVM pUVM = pVM->pUVM;
AssertMsg(!pUVM->pdm.s.pNetShaper,
("Network shaper was already initialized\n"));
char szDesc[256];
static unsigned iThread;
RTStrPrintf(szDesc, sizeof(szDesc), "PDMNSTXThread-%d", ++iThread);
rc = PDMR3ThreadCreate(pVM, &pNetShaper->hTxThread, pNetShaper,
pdmR3NsTxThread, pdmR3NsTxWakeUp, 0,
RTTHREADTYPE_IO, szDesc);
if (RT_SUCCESS(rc))
{
pUVM->pdm.s.pNetShaper = pNetShaper;
return VINF_SUCCESS;
}
}
RTCritSectDelete(&pNetShaper->cs);
}
MMR3HeapFree(pNetShaper);
}
LogFlowFunc((": pVM=%p rc=%Rrc\n", pVM, rc));
return rc;
}