cc82902fa476b1808b3af80f52cdabb70b450944vboxsync/* $Id$ */
1c511098095d1a92509192393fe382493c016127vboxsync/** @file
1c511098095d1a92509192393fe382493c016127vboxsync * PDM Network Shaper - Limit network traffic according to bandwidth group settings.
1c511098095d1a92509192393fe382493c016127vboxsync */
1c511098095d1a92509192393fe382493c016127vboxsync
1c511098095d1a92509192393fe382493c016127vboxsync/*
1c511098095d1a92509192393fe382493c016127vboxsync * Copyright (C) 2011-2013 Oracle Corporation
1c511098095d1a92509192393fe382493c016127vboxsync *
1c511098095d1a92509192393fe382493c016127vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
1c511098095d1a92509192393fe382493c016127vboxsync * available from http://www.virtualbox.org. This file is free software;
1c511098095d1a92509192393fe382493c016127vboxsync * you can redistribute it and/or modify it under the terms of the GNU
1c511098095d1a92509192393fe382493c016127vboxsync * General Public License (GPL) as published by the Free Software
1c511098095d1a92509192393fe382493c016127vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
1c511098095d1a92509192393fe382493c016127vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1c511098095d1a92509192393fe382493c016127vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c511098095d1a92509192393fe382493c016127vboxsync */
1c511098095d1a92509192393fe382493c016127vboxsync
1c511098095d1a92509192393fe382493c016127vboxsync
1c511098095d1a92509192393fe382493c016127vboxsync/*******************************************************************************
1c511098095d1a92509192393fe382493c016127vboxsync* Header Files *
1c511098095d1a92509192393fe382493c016127vboxsync*******************************************************************************/
1c511098095d1a92509192393fe382493c016127vboxsync#define LOG_GROUP LOG_GROUP_NET_SHAPER
1c511098095d1a92509192393fe382493c016127vboxsync#include <VBox/vmm/pdm.h>
1c511098095d1a92509192393fe382493c016127vboxsync#include <VBox/log.h>
1c511098095d1a92509192393fe382493c016127vboxsync#include <iprt/time.h>
1c511098095d1a92509192393fe382493c016127vboxsync
1c511098095d1a92509192393fe382493c016127vboxsync#include <VBox/vmm/pdmnetshaper.h>
1c511098095d1a92509192393fe382493c016127vboxsync#include "PDMNetShaperInternal.h"
1c511098095d1a92509192393fe382493c016127vboxsync
1c511098095d1a92509192393fe382493c016127vboxsync
1c511098095d1a92509192393fe382493c016127vboxsync/**
1c511098095d1a92509192393fe382493c016127vboxsync * Obtain bandwidth in a bandwidth group.
1c511098095d1a92509192393fe382493c016127vboxsync *
1c511098095d1a92509192393fe382493c016127vboxsync * @returns True if bandwidth was allocated, false if not.
1c511098095d1a92509192393fe382493c016127vboxsync * @param pFilter Pointer to the filter that allocates bandwidth.
1c511098095d1a92509192393fe382493c016127vboxsync * @param cbTransfer Number of bytes to allocate.
1c511098095d1a92509192393fe382493c016127vboxsync */
1c511098095d1a92509192393fe382493c016127vboxsyncVMMDECL(bool) PDMNsAllocateBandwidth(PPDMNSFILTER pFilter, size_t cbTransfer)
1c511098095d1a92509192393fe382493c016127vboxsync{
1c511098095d1a92509192393fe382493c016127vboxsync AssertPtrReturn(pFilter, true);
1c511098095d1a92509192393fe382493c016127vboxsync if (!VALID_PTR(pFilter->CTX_SUFF(pBwGroup)))
1c511098095d1a92509192393fe382493c016127vboxsync return true;
1c511098095d1a92509192393fe382493c016127vboxsync
1c511098095d1a92509192393fe382493c016127vboxsync PPDMNSBWGROUP pBwGroup = ASMAtomicReadPtrT(&pFilter->CTX_SUFF(pBwGroup), PPDMNSBWGROUP);
1c511098095d1a92509192393fe382493c016127vboxsync int rc = PDMCritSectEnter(&pBwGroup->Lock, VERR_SEM_BUSY); AssertRC(rc);
1c511098095d1a92509192393fe382493c016127vboxsync if (RT_UNLIKELY(rc == VERR_SEM_BUSY))
1c511098095d1a92509192393fe382493c016127vboxsync return true;
1c511098095d1a92509192393fe382493c016127vboxsync
1c511098095d1a92509192393fe382493c016127vboxsync bool fAllowed = true;
1c511098095d1a92509192393fe382493c016127vboxsync if (pBwGroup->cbPerSecMax)
1c511098095d1a92509192393fe382493c016127vboxsync {
1c511098095d1a92509192393fe382493c016127vboxsync /* Re-fill the bucket first */
1c511098095d1a92509192393fe382493c016127vboxsync uint64_t tsNow = RTTimeSystemNanoTS();
1c511098095d1a92509192393fe382493c016127vboxsync uint32_t uTokensAdded = (tsNow - pBwGroup->tsUpdatedLast) * pBwGroup->cbPerSecMax / (1000 * 1000 * 1000);
1c511098095d1a92509192393fe382493c016127vboxsync uint32_t uTokens = RT_MIN(pBwGroup->cbBucket, uTokensAdded + pBwGroup->cbTokensLast);
1c511098095d1a92509192393fe382493c016127vboxsync
1c511098095d1a92509192393fe382493c016127vboxsync if (cbTransfer > uTokens)
1c511098095d1a92509192393fe382493c016127vboxsync {
1c511098095d1a92509192393fe382493c016127vboxsync fAllowed = false;
1c511098095d1a92509192393fe382493c016127vboxsync ASMAtomicWriteBool(&pFilter->fChoked, true);
1c511098095d1a92509192393fe382493c016127vboxsync }
1c511098095d1a92509192393fe382493c016127vboxsync else
1c511098095d1a92509192393fe382493c016127vboxsync {
1c511098095d1a92509192393fe382493c016127vboxsync pBwGroup->tsUpdatedLast = tsNow;
1c511098095d1a92509192393fe382493c016127vboxsync pBwGroup->cbTokensLast = uTokens - (uint32_t)cbTransfer;
1c511098095d1a92509192393fe382493c016127vboxsync }
1c511098095d1a92509192393fe382493c016127vboxsync Log2(("pdmNsAllocateBandwidth: BwGroup=%#p{%s} cbTransfer=%u uTokens=%u uTokensAdded=%u fAllowed=%RTbool\n",
1c511098095d1a92509192393fe382493c016127vboxsync pBwGroup, R3STRING(pBwGroup->pszNameR3), cbTransfer, uTokens, uTokensAdded, fAllowed));
1c511098095d1a92509192393fe382493c016127vboxsync }
1c511098095d1a92509192393fe382493c016127vboxsync else
1c511098095d1a92509192393fe382493c016127vboxsync Log2(("pdmNsAllocateBandwidth: BwGroup=%#p{%s} disabled fAllowed=%RTbool\n",
1c511098095d1a92509192393fe382493c016127vboxsync pBwGroup, R3STRING(pBwGroup->pszNameR3), fAllowed));
1c511098095d1a92509192393fe382493c016127vboxsync
1c511098095d1a92509192393fe382493c016127vboxsync rc = PDMCritSectLeave(&pBwGroup->Lock); AssertRC(rc);
1c511098095d1a92509192393fe382493c016127vboxsync return fAllowed;
1c511098095d1a92509192393fe382493c016127vboxsync}
1c511098095d1a92509192393fe382493c016127vboxsync