b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/* $Id$ */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/** @file
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync * PDM Network Shaper - Limit network traffic according to bandwidth group settings.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/*
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2011-2013 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>
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync#include "PDMNetShaperInternal.h"
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/*******************************************************************************
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync* Structures and Typedefs *
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync*******************************************************************************/
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/**
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Network shaper data. One instance per VM.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsynctypedef struct PDMNETSHAPER
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
c458503b85d643d51c5287959b8d96a3e32d9499vboxsync /** Pointer to the VM. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PVM pVM;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** Critical section protecting all members below. */
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync RTCRITSECT Lock;
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync /** Pending TX thread. */
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync PPDMTHREAD pTxThread;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** Pointer to the first bandwidth group. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSBWGROUP pBwGroupsHead;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync} PDMNETSHAPER;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync/** Takes the shaper lock (asserts but doesn't return or anything on
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync * failure). */
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync#define LOCK_NETSHAPER(a_pShaper) do { int rcShaper = RTCritSectEnter(&(a_pShaper)->Lock); AssertRC(rcShaper); } while (0)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync/** Takes the shaper lock, returns + asserts on failure. */
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync#define LOCK_NETSHAPER_RETURN(a_pShaper) \
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync do { int rcShaper = RTCritSectEnter(&(a_pShaper)->Lock); AssertRCReturn(rcShaper, rcShaper); } while (0)
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync/** Releases the shaper lock (asserts on failure). */
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync#define UNLOCK_NETSHAPER(a_pShaper) do { int rcShaper = RTCritSectLeave(&(a_pShaper)->Lock); AssertRC(rcShaper); } while (0)
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsyncstatic PPDMNSBWGROUP pdmNsBwGroupFindById(PPDMNETSHAPER pShaper, const char *pszId)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSBWGROUP pBwGroup = NULL;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync if (RT_VALID_PTR(pszId))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync LOCK_NETSHAPER(pShaper);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup = pShaper->pBwGroupsHead;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync while ( pBwGroup
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync && RTStrCmp(pBwGroup->pszNameR3, pszId))
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pBwGroup = pBwGroup->pNextR3;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync UNLOCK_NETSHAPER(pShaper);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync return pBwGroup;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncstatic void pdmNsBwGroupLink(PPDMNSBWGROUP pBwGroup)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync PPDMNETSHAPER pShaper = pBwGroup->pShaperR3;
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync LOCK_NETSHAPER(pShaper);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pBwGroup->pNextR3 = pShaper->pBwGroupsHead;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pShaper->pBwGroupsHead = pBwGroup;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync UNLOCK_NETSHAPER(pShaper);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#if 0
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncstatic void pdmNsBwGroupUnlink(PPDMNSBWGROUP pBwGroup)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNETSHAPER pShaper = pBwGroup->pShaper;
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync LOCK_NETSHAPER(pShaper);
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
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync UNLOCK_NETSHAPER(pShaper);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#endif
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsyncstatic void pdmNsBwGroupSetLimit(PPDMNSBWGROUP pBwGroup, uint64_t cbPerSecMax)
0247b3970a16ddb81e15bfd8ff8a4eb9747595ccvboxsync{
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pBwGroup->cbPerSecMax = cbPerSecMax;
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pBwGroup->cbBucket = RT_MAX(PDM_NETSHAPER_MIN_BUCKET_SIZE, cbPerSecMax * PDM_NETSHAPER_MAX_LATENCY / 1000);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync LogFlow(("pdmNsBwGroupSetLimit: New rate limit is %llu bytes per second, adjusted bucket size to %u bytes\n",
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pBwGroup->cbPerSecMax, pBwGroup->cbBucket));
0247b3970a16ddb81e15bfd8ff8a4eb9747595ccvboxsync}
0247b3970a16ddb81e15bfd8ff8a4eb9747595ccvboxsync
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsyncstatic int pdmNsBwGroupCreate(PPDMNETSHAPER pShaper, const char *pszBwGroup, uint64_t cbPerSecMax)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync LogFlow(("pdmNsBwGroupCreate: pShaper=%#p pszBwGroup=%#p{%s} cbPerSecMax=%llu\n", pShaper, pszBwGroup, pszBwGroup, cbPerSecMax));
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync AssertPtrReturn(pShaper, VERR_INVALID_POINTER);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync AssertPtrReturn(pszBwGroup, VERR_INVALID_POINTER);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync AssertReturn(*pszBwGroup != '\0', VERR_INVALID_PARAMETER);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync int rc;
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync PPDMNSBWGROUP pBwGroup = pdmNsBwGroupFindById(pShaper, pszBwGroup);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (!pBwGroup)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
1e80130a8de15c1a537ab0ffcf8999e986217a1avboxsync rc = MMHyperAlloc(pShaper->pVM, sizeof(PDMNSBWGROUP), 64,
1e80130a8de15c1a537ab0ffcf8999e986217a1avboxsync MM_TAG_PDM_NET_SHAPER, (void **)&pBwGroup);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_SUCCESS(rc))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync rc = PDMR3CritSectInit(pShaper->pVM, &pBwGroup->Lock, RT_SRC_POS, "BWGRP");
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_SUCCESS(rc))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pBwGroup->pszNameR3 = MMR3HeapStrDup(pShaper->pVM, MM_TAG_PDM_NET_SHAPER, pszBwGroup);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync if (pBwGroup->pszNameR3)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pBwGroup->pShaperR3 = pShaper;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup->cRefs = 0;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pdmNsBwGroupSetLimit(pBwGroup, cbPerSecMax);
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pBwGroup->cbTokensLast = pBwGroup->cbBucket;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pBwGroup->tsUpdatedLast = RTTimeSystemNanoTS();
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync LogFlowFunc(("pszBwGroup={%s} cbBucket=%u\n",
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pszBwGroup, pBwGroup->cbBucket));
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pdmNsBwGroupLink(pBwGroup);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync return VINF_SUCCESS;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync PDMR3CritSectDelete(&pBwGroup->Lock);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
1e80130a8de15c1a537ab0ffcf8999e986217a1avboxsync MMHyperFree(pShaper->pVM, 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
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncstatic void pdmNsBwGroupTerminate(PPDMNSBWGROUP pBwGroup)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync Assert(pBwGroup->cRefs == 0);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync if (PDMCritSectIsInitialized(&pBwGroup->Lock))
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync PDMR3CritSectDelete(&pBwGroup->Lock);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncDECLINLINE(void) pdmNsBwGroupRef(PPDMNSBWGROUP pBwGroup)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync ASMAtomicIncU32(&pBwGroup->cRefs);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncDECLINLINE(void) pdmNsBwGroupUnref(PPDMNSBWGROUP pBwGroup)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync Assert(pBwGroup->cRefs > 0);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync ASMAtomicDecU32(&pBwGroup->cRefs);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsyncstatic void pdmNsBwGroupXmitPending(PPDMNSBWGROUP pBwGroup)
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync{
404dd7b4bf7209363c3ab5b98944ff8405e0130bvboxsync /*
404dd7b4bf7209363c3ab5b98944ff8405e0130bvboxsync * We don't need to hold the bandwidth group lock to iterate over the list
404dd7b4bf7209363c3ab5b98944ff8405e0130bvboxsync * of filters since the filters are removed while the shaper lock is being
404dd7b4bf7209363c3ab5b98944ff8405e0130bvboxsync * held.
404dd7b4bf7209363c3ab5b98944ff8405e0130bvboxsync */
404dd7b4bf7209363c3ab5b98944ff8405e0130bvboxsync AssertPtr(pBwGroup);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync AssertPtr(pBwGroup->pShaperR3);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync Assert(RTCritSectIsOwner(&pBwGroup->pShaperR3->Lock));
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync //LOCK_NETSHAPER(pShaper);
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync
10b09c6100b7c788267d108dbb1c68dde55b053avboxsync /* Check if the group is disabled. */
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync if (pBwGroup->cbPerSecMax == 0)
10b09c6100b7c788267d108dbb1c68dde55b053avboxsync return;
10b09c6100b7c788267d108dbb1c68dde55b053avboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync PPDMNSFILTER pFilter = pBwGroup->pFiltersHeadR3;
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync while (pFilter)
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync {
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync bool fChoked = ASMAtomicXchgBool(&pFilter->fChoked, false);
0247b3970a16ddb81e15bfd8ff8a4eb9747595ccvboxsync Log3((LOG_FN_FMT ": pFilter=%#p fChoked=%RTbool\n", __PRETTY_FUNCTION__, pFilter, fChoked));
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync if (fChoked && pFilter->pIDrvNetR3)
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync {
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync LogFlowFunc(("Calling pfnXmitPending for pFilter=%#p\n", pFilter));
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pFilter->pIDrvNetR3->pfnXmitPending(pFilter->pIDrvNetR3);
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync }
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pFilter = pFilter->pNextR3;
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync }
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync //UNLOCK_NETSHAPER(pShaper);
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync}
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncstatic void pdmNsFilterLink(PPDMNSFILTER pFilter)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSBWGROUP pBwGroup = pFilter->pBwGroupR3;
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync int rc = PDMCritSectEnter(&pBwGroup->Lock, VERR_SEM_BUSY); AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pFilter->pNextR3 = pBwGroup->pFiltersHeadR3;
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pBwGroup->pFiltersHeadR3 = pFilter;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync rc = PDMCritSectLeave(&pBwGroup->Lock); AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncstatic void pdmNsFilterUnlink(PPDMNSFILTER pFilter)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSBWGROUP pBwGroup = pFilter->pBwGroupR3;
404dd7b4bf7209363c3ab5b98944ff8405e0130bvboxsync /*
404dd7b4bf7209363c3ab5b98944ff8405e0130bvboxsync * We need to make sure we hold the shaper lock since pdmNsBwGroupXmitPending()
404dd7b4bf7209363c3ab5b98944ff8405e0130bvboxsync * does not hold the bandwidth group lock while iterating over the list
404dd7b4bf7209363c3ab5b98944ff8405e0130bvboxsync * of group's filters.
404dd7b4bf7209363c3ab5b98944ff8405e0130bvboxsync */
404dd7b4bf7209363c3ab5b98944ff8405e0130bvboxsync AssertPtr(pBwGroup);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync AssertPtr(pBwGroup->pShaperR3);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync Assert(RTCritSectIsOwner(&pBwGroup->pShaperR3->Lock));
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync int rc = PDMCritSectEnter(&pBwGroup->Lock, VERR_SEM_BUSY); AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync if (pFilter == pBwGroup->pFiltersHeadR3)
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pBwGroup->pFiltersHeadR3 = pFilter->pNextR3;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync else
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync PPDMNSFILTER pPrev = pBwGroup->pFiltersHeadR3;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync while ( pPrev
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync && pPrev->pNextR3 != pFilter)
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pPrev = pPrev->pNextR3;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync AssertPtr(pPrev);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pPrev->pNextR3 = pFilter->pNextR3;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync rc = PDMCritSectLeave(&pBwGroup->Lock); AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync/**
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync * Attach network filter driver from bandwidth group.
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync *
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync * @returns VBox status code.
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync * @param pVM Handle of VM.
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync * @param pDrvIns The driver instance.
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync * @param pszBwGroup Name of the bandwidth group to attach to.
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync * @param pFilter Pointer to the filter we attach.
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync */
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsyncVMMR3_INT_DECL(int) PDMR3NsAttach(PUVM pUVM, PPDMDRVINS pDrvIns, const char *pszBwGroup, PPDMNSFILTER pFilter)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync VM_ASSERT_EMT(pUVM->pVM);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync AssertPtrReturn(pFilter, VERR_INVALID_POINTER);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync AssertReturn(pFilter->pBwGroupR3 == NULL, VERR_ALREADY_EXISTS);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNETSHAPER pShaper = pUVM->pdm.s.pNetShaper;
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync LOCK_NETSHAPER_RETURN(pShaper);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync int rc = VINF_SUCCESS;
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync PPDMNSBWGROUP pBwGroupNew = NULL;
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync if (pszBwGroup)
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync {
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pBwGroupNew = pdmNsBwGroupFindById(pShaper, pszBwGroup);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync if (pBwGroupNew)
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pdmNsBwGroupRef(pBwGroupNew);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync else
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync rc = VERR_NOT_FOUND;
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_SUCCESS(rc))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync PPDMNSBWGROUP pBwGroupOld = ASMAtomicXchgPtrT(&pFilter->pBwGroupR3, pBwGroupNew, PPDMNSBWGROUP);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync ASMAtomicWritePtr(&pFilter->pBwGroupR0, MMHyperR3ToR0(pUVM->pVM, pBwGroupNew));
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync if (pBwGroupOld)
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pdmNsBwGroupUnref(pBwGroupOld);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pdmNsFilterLink(pFilter);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync UNLOCK_NETSHAPER(pShaper);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync return rc;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync/**
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync * Detach network filter driver from bandwidth group.
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync *
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync * @returns VBox status code.
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync * @param pUVM The user mode VM handle.
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync * @param pDrvIns The driver instance.
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync * @param pFilter Pointer to the filter we detach.
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync */
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsyncVMMR3_INT_DECL(int) PDMR3NsDetach(PUVM pUVM, PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync VM_ASSERT_EMT(pUVM->pVM);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync AssertPtrReturn(pFilter, VERR_INVALID_POINTER);
1e1273b11e17928ec3c3a8fff45121aa7a169413vboxsync /* Now, return quietly if the filter isn't attached since driver/device
1e1273b11e17928ec3c3a8fff45121aa7a169413vboxsync destructors are called on constructor failure. */
1e1273b11e17928ec3c3a8fff45121aa7a169413vboxsync if (!pFilter->pBwGroupR3)
1e1273b11e17928ec3c3a8fff45121aa7a169413vboxsync return VINF_SUCCESS;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync AssertPtrReturn(pFilter->pBwGroupR3, VERR_INVALID_POINTER);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNETSHAPER pShaper = pUVM->pdm.s.pNetShaper;
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync LOCK_NETSHAPER_RETURN(pShaper);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pdmNsFilterUnlink(pFilter);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync PPDMNSBWGROUP pBwGroup = ASMAtomicXchgPtrT(&pFilter->pBwGroupR3, NULL, PPDMNSBWGROUP);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync if (pBwGroup)
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pdmNsBwGroupUnref(pBwGroup);
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync UNLOCK_NETSHAPER(pShaper);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync return VINF_SUCCESS;
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync}
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync/**
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync * Adjusts the maximum rate for the bandwidth group.
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync *
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync * @returns VBox status code.
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync * @param pUVM The user mode VM handle.
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync * @param pszBwGroup Name of the bandwidth group to attach to.
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync * @param cbPerSecMax Maximum number of bytes per second to be transmitted.
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync */
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsyncVMMR3DECL(int) PDMR3NsBwGroupSetLimit(PUVM pUVM, const char *pszBwGroup, uint64_t cbPerSecMax)
0247b3970a16ddb81e15bfd8ff8a4eb9747595ccvboxsync{
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
0247b3970a16ddb81e15bfd8ff8a4eb9747595ccvboxsync PPDMNETSHAPER pShaper = pUVM->pdm.s.pNetShaper;
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync LOCK_NETSHAPER_RETURN(pShaper);
0247b3970a16ddb81e15bfd8ff8a4eb9747595ccvboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync int rc;
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync PPDMNSBWGROUP pBwGroup = pdmNsBwGroupFindById(pShaper, pszBwGroup);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync if (pBwGroup)
0247b3970a16ddb81e15bfd8ff8a4eb9747595ccvboxsync {
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync rc = PDMCritSectEnter(&pBwGroup->Lock, VERR_SEM_BUSY); AssertRC(rc);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync if (RT_SUCCESS(rc))
0247b3970a16ddb81e15bfd8ff8a4eb9747595ccvboxsync {
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pdmNsBwGroupSetLimit(pBwGroup, cbPerSecMax);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync
0247b3970a16ddb81e15bfd8ff8a4eb9747595ccvboxsync /* Drop extra tokens */
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync if (pBwGroup->cbTokensLast > pBwGroup->cbBucket)
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pBwGroup->cbTokensLast = pBwGroup->cbBucket;
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync int rc2 = PDMCritSectLeave(&pBwGroup->Lock); AssertRC(rc2);
0247b3970a16ddb81e15bfd8ff8a4eb9747595ccvboxsync }
0247b3970a16ddb81e15bfd8ff8a4eb9747595ccvboxsync }
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync else
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync rc = VERR_NOT_FOUND;
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync UNLOCK_NETSHAPER(pShaper);
0247b3970a16ddb81e15bfd8ff8a4eb9747595ccvboxsync return rc;
0247b3970a16ddb81e15bfd8ff8a4eb9747595ccvboxsync}
0247b3970a16ddb81e15bfd8ff8a4eb9747595ccvboxsync
0247b3970a16ddb81e15bfd8ff8a4eb9747595ccvboxsync
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync/**
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync * I/O thread for pending TX.
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync *
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync * @returns VINF_SUCCESS (ignored).
4bfa7b58e362a1bca0628643c352c137900bf01avboxsync * @param pVM Pointer to the VM.
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync * @param pThread The PDM thread data.
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync */
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsyncstatic DECLCALLBACK(int) pdmR3NsTxThread(PVM pVM, PPDMTHREAD pThread)
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync{
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync PPDMNETSHAPER pShaper = (PPDMNETSHAPER)pThread->pvUser;
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync LogFlow(("pdmR3NsTxThread: pShaper=%p\n", pShaper));
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync while (pThread->enmState == PDMTHREADSTATE_RUNNING)
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync {
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync RTThreadSleep(PDM_NETSHAPER_MAX_LATENCY);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync /* Go over all bandwidth groups/filters calling pfnXmitPending */
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync LOCK_NETSHAPER(pShaper);
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync PPDMNSBWGROUP pBwGroup = pShaper->pBwGroupsHead;
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync while (pBwGroup)
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync {
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync pdmNsBwGroupXmitPending(pBwGroup);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pBwGroup = pBwGroup->pNextR3;
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync }
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync UNLOCK_NETSHAPER(pShaper);
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync }
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync return VINF_SUCCESS;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync/**
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync * @copydoc FNPDMTHREADWAKEUPINT
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync */
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsyncstatic DECLCALLBACK(int) pdmR3NsTxWakeUp(PVM pVM, PPDMTHREAD pThread)
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync{
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync PPDMNETSHAPER pShaper = (PPDMNETSHAPER)pThread->pvUser;
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync LogFlow(("pdmR3NsTxWakeUp: pShaper=%p\n", pShaper));
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync /* Nothing to do */
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync return VINF_SUCCESS;
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync
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;
80bc18dbd439331cef10440eeca1cb36457b1d89vboxsync AssertPtrReturn(pUVM, VERR_INVALID_POINTER);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNETSHAPER pShaper = pUVM->pdm.s.pNetShaper;
80bc18dbd439331cef10440eeca1cb36457b1d89vboxsync AssertPtrReturn(pShaper, VERR_INVALID_POINTER);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /* Destroy the bandwidth managers. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSBWGROUP pBwGroup = pShaper->pBwGroupsHead;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync while (pBwGroup)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PPDMNSBWGROUP pFree = pBwGroup;
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pBwGroup = pBwGroup->pNextR3;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync pdmNsBwGroupTerminate(pFree);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync MMR3HeapFree(pFree->pszNameR3);
1e80130a8de15c1a537ab0ffcf8999e986217a1avboxsync MMHyperFree(pVM, pFree);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync RTCritSectDelete(&pShaper->Lock);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync return VINF_SUCCESS;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
13ce95e4c4dc7fb501c89c137a4ab8caecee6cbavboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/**
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Initialize the network shaper.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync *
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * @returns VBox status code
c458503b85d643d51c5287959b8d96a3e32d9499vboxsync * @param pVM Pointer to the VM.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncint pdmR3NetShaperInit(PVM pVM)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync{
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync LogFlow(("pdmR3NetShaperInit: pVM=%p\n", pVM));
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync VM_ASSERT_EMT(pVM);
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync PUVM pUVM = pVM->pUVM;
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync AssertMsgReturn(!pUVM->pdm.s.pNetShaper, ("Network shaper was already initialized\n"), VERR_WRONG_ORDER);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync PPDMNETSHAPER pShaper;
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync int rc = MMR3HeapAllocZEx(pVM, MM_TAG_PDM_NET_SHAPER, sizeof(PDMNETSHAPER), (void **)&pShaper);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_SUCCESS(rc))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync PCFGMNODE pCfgNetShaper = CFGMR3GetChild(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "NetworkShaper");
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pShaper->pVM = pVM;
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync rc = RTCritSectInit(&pShaper->Lock);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_SUCCESS(rc))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /* Create all bandwidth groups. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync PCFGMNODE pCfgBwGrp = CFGMR3GetChild(pCfgNetShaper, "BwGroups");
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (pCfgBwGrp)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync for (PCFGMNODE pCur = CFGMR3GetFirstChild(pCfgBwGrp); pCur; pCur = CFGMR3GetNextChild(pCur))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
80bc18dbd439331cef10440eeca1cb36457b1d89vboxsync uint64_t cbMax;
4a268cd37879e04ad6ef4b8412bc2d293a44bc7avboxsync size_t cbName = CFGMR3GetNameLen(pCur) + 1;
4a268cd37879e04ad6ef4b8412bc2d293a44bc7avboxsync char *pszBwGrpId = (char *)RTMemAllocZ(cbName);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (!pszBwGrpId)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync rc = VERR_NO_MEMORY;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync break;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
4a268cd37879e04ad6ef4b8412bc2d293a44bc7avboxsync rc = CFGMR3GetName(pCur, pszBwGrpId, cbName);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync AssertRC(rc);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_SUCCESS(rc))
80bc18dbd439331cef10440eeca1cb36457b1d89vboxsync rc = CFGMR3QueryU64(pCur, "Max", &cbMax);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_SUCCESS(rc))
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync rc = pdmNsBwGroupCreate(pShaper, pszBwGrpId, cbMax);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync RTMemFree(pszBwGrpId);
c458503b85d643d51c5287959b8d96a3e32d9499vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_FAILURE(rc))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync break;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync if (RT_SUCCESS(rc))
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync {
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync rc = PDMR3ThreadCreate(pVM, &pShaper->pTxThread, pShaper, pdmR3NsTxThread, pdmR3NsTxWakeUp,
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync 0 /*cbStack*/, RTTHREADTYPE_IO, "PDMNsTx");
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync if (RT_SUCCESS(rc))
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync {
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync pUVM->pdm.s.pNetShaper = pShaper;
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync return VINF_SUCCESS;
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync RTCritSectDelete(&pShaper->Lock);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync MMR3HeapFree(pShaper);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync
cdc4c218c2bf31f90badfd20b1c185946a7e412evboxsync LogFlow(("pdmR3NetShaperInit: pVM=%p rc=%Rrc\n", pVM, rc));
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync return rc;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync