Changeset 44355 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Jan 24, 2013 1:27:28 PM (12 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 1 deleted
- 4 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/Makefile.kmk
r43872 r44355 214 214 ifdef VBOX_WITH_NETSHAPER 215 215 VBoxVMM_SOURCES += \ 216 VMMR3/PDMNetShaper.cpp 216 VMMR3/PDMNetShaper.cpp \ 217 VMMAll/PDMAllNetShaper.cpp 217 218 endif 218 219 … … 548 549 ifdef VBOX_WITH_NETSHAPER 549 550 VMMR0_SOURCES += \ 550 VMM R0/PDMNetShaperR0.cpp551 VMMAll/PDMAllNetShaper.cpp 551 552 endif 552 553 VMMR0_SOURCES.amd64 = \ -
trunk/src/VBox/VMM/VMMR3/PDMDriver.cpp
r43038 r44355 1561 1561 pDrvIns->pReg->szName, pDrvIns->iInstance, pFilter, pszBwGroup, pszBwGroup)); 1562 1562 1563 int rc = PDMR3NsAttach(pDrvIns->Internal.s.pVMR3 , pDrvIns, pszBwGroup, pFilter);1563 int rc = PDMR3NsAttach(pDrvIns->Internal.s.pVMR3->pUVM, pDrvIns, pszBwGroup, pFilter); 1564 1564 1565 1565 LogFlow(("pdmR3DrvHlp_NetShaperAttach: caller='%s'/%d: returns %Rrc\n", pDrvIns->pReg->szName, … … 1576 1576 pDrvIns->pReg->szName, pDrvIns->iInstance, pFilter)); 1577 1577 1578 int rc = PDMR3NsDetach(pDrvIns->Internal.s.pVMR3 , pDrvIns, pFilter);1578 int rc = PDMR3NsDetach(pDrvIns->Internal.s.pVMR3->pUVM, pDrvIns, pFilter); 1579 1579 1580 1580 LogFlow(("pdmR3DrvHlp_NetShaperDetach: caller='%s'/%d: returns %Rrc\n", pDrvIns->pReg->szName, -
trunk/src/VBox/VMM/VMMR3/PDMNetShaper.cpp
r43229 r44355 42 42 43 43 #include <VBox/vmm/pdmnetshaper.h> 44 #include <VBox/vmm/pdmnetshaperint.h>44 #include "PDMNetShaperInternal.h" 45 45 46 46 … … 57 57 PVM pVM; 58 58 /** Critical section protecting all members below. */ 59 RTCRITSECT cs;59 RTCRITSECT Lock; 60 60 /** Pending TX thread. */ 61 PPDMTHREAD hTxThread;61 PPDMTHREAD pTxThread; 62 62 /** Pointer to the first bandwidth group. */ 63 63 PPDMNSBWGROUP pBwGroupsHead; … … 65 65 66 66 67 68 69 70 71 static PPDMNSBWGROUP pdmNsBwGroupFindById(PPDMNETSHAPER pShaper, const char *pcszId) 67 /** Takes the shaper lock (asserts but doesn't return or anything on 68 * failure). */ 69 #define LOCK_NETSHAPER(a_pShaper) do { int rcShaper = RTCritSectEnter(&(a_pShaper)->Lock); AssertRC(rcShaper); } while (0) 70 71 /** Takes the shaper lock, returns + asserts on failure. */ 72 #define LOCK_NETSHAPER_RETURN(a_pShaper) \ 73 do { int rcShaper = RTCritSectEnter(&(a_pShaper)->Lock); AssertRCReturn(rcShaper, rcShaper); } while (0) 74 75 /** Releases the shaper lock (asserts on failure). */ 76 #define UNLOCK_NETSHAPER(a_pShaper) do { int rcShaper = RTCritSectLeave(&(a_pShaper)->Lock); AssertRC(rcShaper); } while (0) 77 78 79 80 81 static PPDMNSBWGROUP pdmNsBwGroupFindById(PPDMNETSHAPER pShaper, const char *pszId) 72 82 { 73 83 PPDMNSBWGROUP pBwGroup = NULL; 74 84 75 if (RT_VALID_PTR(p cszId))76 { 77 int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc);85 if (RT_VALID_PTR(pszId)) 86 { 87 LOCK_NETSHAPER(pShaper); 78 88 79 89 pBwGroup = pShaper->pBwGroupsHead; 80 90 while ( pBwGroup 81 && RTStrCmp(pBwGroup->pszName , pcszId))82 pBwGroup = pBwGroup->pNext ;83 84 rc = RTCritSectLeave(&pShaper->cs); AssertRC(rc);91 && RTStrCmp(pBwGroup->pszNameR3, pszId)) 92 pBwGroup = pBwGroup->pNextR3; 93 94 UNLOCK_NETSHAPER(pShaper); 85 95 } 86 96 … … 91 101 static void pdmNsBwGroupLink(PPDMNSBWGROUP pBwGroup) 92 102 { 93 PPDMNETSHAPER pShaper = pBwGroup->pShaper ;94 int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc);95 96 pBwGroup->pNext = pShaper->pBwGroupsHead;103 PPDMNETSHAPER pShaper = pBwGroup->pShaperR3; 104 LOCK_NETSHAPER(pShaper); 105 106 pBwGroup->pNextR3 = pShaper->pBwGroupsHead; 97 107 pShaper->pBwGroupsHead = pBwGroup; 98 108 99 rc = RTCritSectLeave(&pShaper->cs); AssertRC(rc);109 UNLOCK_NETSHAPER(pShaper); 100 110 } 101 111 … … 105 115 { 106 116 PPDMNETSHAPER pShaper = pBwGroup->pShaper; 107 int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc);117 LOCK_NETSHAPER(pShaper); 108 118 109 119 if (pBwGroup == pShaper->pBwGroupsHead) … … 120 130 } 121 131 122 rc = RTCritSectLeave(&pShaper->cs); AssertRC(rc);132 UNLOCK_NETSHAPER(pShaper); 123 133 } 124 134 #endif 125 135 126 136 127 static void pdmNsBwGroupSetLimit(PPDMNSBWGROUP pBwGroup, uint64_t cbTransferPerSecMax) 128 { 129 pBwGroup->cbTransferPerSecMax = cbTransferPerSecMax; 130 pBwGroup->cbBucketSize = RT_MAX(PDM_NETSHAPER_MIN_BUCKET_SIZE, 131 cbTransferPerSecMax * PDM_NETSHAPER_MAX_LATENCY / 1000); 132 LogFlowFunc(("New rate limit is %llu bytes per second, adjusted bucket size to %d bytes\n", 133 pBwGroup->cbTransferPerSecMax, pBwGroup->cbBucketSize)); 134 } 135 136 137 static int pdmNsBwGroupCreate(PPDMNETSHAPER pShaper, const char *pcszBwGroup, uint64_t cbTransferPerSecMax) 138 { 139 LogFlowFunc(("pShaper=%#p pcszBwGroup=%#p{%s} cbTransferPerSecMax=%llu\n", 140 pShaper, pcszBwGroup, pcszBwGroup, cbTransferPerSecMax)); 137 static void pdmNsBwGroupSetLimit(PPDMNSBWGROUP pBwGroup, uint64_t cbPerSecMax) 138 { 139 pBwGroup->cbPerSecMax = cbPerSecMax; 140 pBwGroup->cbBucket = RT_MAX(PDM_NETSHAPER_MIN_BUCKET_SIZE, cbPerSecMax * PDM_NETSHAPER_MAX_LATENCY / 1000); 141 LogFlow(("pdmNsBwGroupSetLimit: New rate limit is %llu bytes per second, adjusted bucket size to %u bytes\n", 142 pBwGroup->cbPerSecMax, pBwGroup->cbBucket)); 143 } 144 145 146 static int pdmNsBwGroupCreate(PPDMNETSHAPER pShaper, const char *pszBwGroup, uint64_t cbPerSecMax) 147 { 148 LogFlow(("pdmNsBwGroupCreate: pShaper=%#p pszBwGroup=%#p{%s} cbPerSecMax=%llu\n", pShaper, pszBwGroup, pszBwGroup, cbPerSecMax)); 141 149 142 150 AssertPtrReturn(pShaper, VERR_INVALID_POINTER); 143 AssertPtrReturn(p cszBwGroup, VERR_INVALID_POINTER);144 AssertReturn(*p cszBwGroup != '\0', VERR_INVALID_PARAMETER);151 AssertPtrReturn(pszBwGroup, VERR_INVALID_POINTER); 152 AssertReturn(*pszBwGroup != '\0', VERR_INVALID_PARAMETER); 145 153 146 154 int rc; 147 PPDMNSBWGROUP pBwGroup = pdmNsBwGroupFindById(pShaper, p cszBwGroup);155 PPDMNSBWGROUP pBwGroup = pdmNsBwGroupFindById(pShaper, pszBwGroup); 148 156 if (!pBwGroup) 149 157 { … … 152 160 if (RT_SUCCESS(rc)) 153 161 { 154 rc = PDMR3CritSectInit(pShaper->pVM, &pBwGroup-> cs, RT_SRC_POS, "BWGRP");162 rc = PDMR3CritSectInit(pShaper->pVM, &pBwGroup->Lock, RT_SRC_POS, "BWGRP"); 155 163 if (RT_SUCCESS(rc)) 156 164 { 157 pBwGroup->pszName = RTStrDup(pcszBwGroup);158 if (pBwGroup->pszName )165 pBwGroup->pszNameR3 = MMR3HeapStrDup(pShaper->pVM, MM_TAG_PDM_NET_SHAPER, pszBwGroup); 166 if (pBwGroup->pszNameR3) 159 167 { 160 pBwGroup->pShaper 168 pBwGroup->pShaperR3 = pShaper; 161 169 pBwGroup->cRefs = 0; 162 170 163 pdmNsBwGroupSetLimit(pBwGroup, cb TransferPerSecMax);164 165 pBwGroup->cbTokensLast = pBwGroup->cbBucket Size;171 pdmNsBwGroupSetLimit(pBwGroup, cbPerSecMax); 172 173 pBwGroup->cbTokensLast = pBwGroup->cbBucket; 166 174 pBwGroup->tsUpdatedLast = RTTimeSystemNanoTS(); 167 175 168 LogFlowFunc(("p cszBwGroup={%s} cbBucketSize=%u\n",169 p cszBwGroup, pBwGroup->cbBucketSize));176 LogFlowFunc(("pszBwGroup={%s} cbBucket=%u\n", 177 pszBwGroup, pBwGroup->cbBucket)); 170 178 pdmNsBwGroupLink(pBwGroup); 171 179 return VINF_SUCCESS; 172 180 } 173 PDMR3CritSectDelete(&pBwGroup-> cs);181 PDMR3CritSectDelete(&pBwGroup->Lock); 174 182 } 175 183 MMHyperFree(pShaper->pVM, pBwGroup); … … 189 197 { 190 198 Assert(pBwGroup->cRefs == 0); 191 if (PDMCritSectIsInitialized(&pBwGroup-> cs))192 PDMR3CritSectDelete(&pBwGroup-> cs);199 if (PDMCritSectIsInitialized(&pBwGroup->Lock)) 200 PDMR3CritSectDelete(&pBwGroup->Lock); 193 201 } 194 202 … … 215 223 */ 216 224 AssertPtr(pBwGroup); 217 AssertPtr(pBwGroup->pShaper );218 Assert(RTCritSectIsOwner(&pBwGroup->pShaper ->cs));219 // int rc = RTCritSectEnter(&pBwGroup->cs); AssertRC(rc);225 AssertPtr(pBwGroup->pShaperR3); 226 Assert(RTCritSectIsOwner(&pBwGroup->pShaperR3->Lock)); 227 //LOCK_NETSHAPER(pShaper); 220 228 221 229 /* Check if the group is disabled. */ 222 if (pBwGroup->cb TransferPerSecMax == 0)230 if (pBwGroup->cbPerSecMax == 0) 223 231 return; 224 232 225 PPDMNSFILTER pFilter = pBwGroup->pFiltersHead ;233 PPDMNSFILTER pFilter = pBwGroup->pFiltersHeadR3; 226 234 while (pFilter) 227 235 { 228 236 bool fChoked = ASMAtomicXchgBool(&pFilter->fChoked, false); 229 237 Log3((LOG_FN_FMT ": pFilter=%#p fChoked=%RTbool\n", __PRETTY_FUNCTION__, pFilter, fChoked)); 230 if (fChoked && pFilter->pIDrvNet )238 if (fChoked && pFilter->pIDrvNetR3) 231 239 { 232 240 LogFlowFunc(("Calling pfnXmitPending for pFilter=%#p\n", pFilter)); 233 pFilter->pIDrvNet ->pfnXmitPending(pFilter->pIDrvNet);241 pFilter->pIDrvNetR3->pfnXmitPending(pFilter->pIDrvNetR3); 234 242 } 235 243 236 pFilter = pFilter->pNext ;237 } 238 239 // rc = RTCritSectLeave(&pBwGroup->cs); AssertRC(rc);244 pFilter = pFilter->pNextR3; 245 } 246 247 //UNLOCK_NETSHAPER(pShaper); 240 248 } 241 249 … … 244 252 { 245 253 PPDMNSBWGROUP pBwGroup = pFilter->pBwGroupR3; 246 int rc = PDMCritSectEnter(&pBwGroup-> cs, VERR_SEM_BUSY); AssertRC(rc);247 248 pFilter->pNext = pBwGroup->pFiltersHead;249 pBwGroup->pFiltersHead = pFilter;250 251 rc = PDMCritSectLeave(&pBwGroup-> cs); AssertRC(rc);254 int rc = PDMCritSectEnter(&pBwGroup->Lock, VERR_SEM_BUSY); AssertRC(rc); 255 256 pFilter->pNextR3 = pBwGroup->pFiltersHeadR3; 257 pBwGroup->pFiltersHeadR3 = pFilter; 258 259 rc = PDMCritSectLeave(&pBwGroup->Lock); AssertRC(rc); 252 260 } 253 261 … … 262 270 */ 263 271 AssertPtr(pBwGroup); 264 AssertPtr(pBwGroup->pShaper );265 Assert(RTCritSectIsOwner(&pBwGroup->pShaper ->cs));266 int rc = PDMCritSectEnter(&pBwGroup-> cs, VERR_SEM_BUSY); AssertRC(rc);267 268 if (pFilter == pBwGroup->pFiltersHead )269 pBwGroup->pFiltersHead = pFilter->pNext;272 AssertPtr(pBwGroup->pShaperR3); 273 Assert(RTCritSectIsOwner(&pBwGroup->pShaperR3->Lock)); 274 int rc = PDMCritSectEnter(&pBwGroup->Lock, VERR_SEM_BUSY); AssertRC(rc); 275 276 if (pFilter == pBwGroup->pFiltersHeadR3) 277 pBwGroup->pFiltersHeadR3 = pFilter->pNextR3; 270 278 else 271 279 { 272 PPDMNSFILTER pPrev = pBwGroup->pFiltersHead ;280 PPDMNSFILTER pPrev = pBwGroup->pFiltersHeadR3; 273 281 while ( pPrev 274 && pPrev->pNext != pFilter)275 pPrev = pPrev->pNext ;282 && pPrev->pNextR3 != pFilter) 283 pPrev = pPrev->pNextR3; 276 284 277 285 AssertPtr(pPrev); 278 pPrev->pNext = pFilter->pNext; 279 } 280 281 rc = PDMCritSectLeave(&pBwGroup->cs); AssertRC(rc); 282 } 283 284 285 VMMR3DECL(int) PDMR3NsAttach(PVM pVM, PPDMDRVINS pDrvIns, const char *pcszBwGroup, 286 PPDMNSFILTER pFilter) 287 { 288 VM_ASSERT_EMT(pVM); 286 pPrev->pNextR3 = pFilter->pNextR3; 287 } 288 289 rc = PDMCritSectLeave(&pBwGroup->Lock); AssertRC(rc); 290 } 291 292 293 /** 294 * Attach network filter driver from bandwidth group. 295 * 296 * @returns VBox status code. 297 * @param pVM Handle of VM. 298 * @param pDrvIns The driver instance. 299 * @param pszBwGroup Name of the bandwidth group to attach to. 300 * @param pFilter Pointer to the filter we attach. 301 */ 302 VMMR3_INT_DECL(int) PDMR3NsAttach(PUVM pUVM, PPDMDRVINS pDrvIns, const char *pszBwGroup, PPDMNSFILTER pFilter) 303 { 304 VM_ASSERT_EMT(pUVM->pVM); 289 305 AssertPtrReturn(pFilter, VERR_INVALID_POINTER); 290 306 AssertReturn(pFilter->pBwGroupR3 == NULL, VERR_ALREADY_EXISTS); 291 307 292 293 PUVM pUVM = pVM->pUVM;294 308 PPDMNETSHAPER pShaper = pUVM->pdm.s.pNetShaper; 295 296 PPDMNSBWGROUP pBwGroupOld = NULL; 297 PPDMNSBWGROUP pBwGroupNew = NULL; 298 299 int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc); 309 LOCK_NETSHAPER_RETURN(pShaper); 310 311 int rc = VINF_SUCCESS; 312 PPDMNSBWGROUP pBwGroupNew = NULL; 313 if (pszBwGroup) 314 { 315 pBwGroupNew = pdmNsBwGroupFindById(pShaper, pszBwGroup); 316 if (pBwGroupNew) 317 pdmNsBwGroupRef(pBwGroupNew); 318 else 319 rc = VERR_NOT_FOUND; 320 } 321 300 322 if (RT_SUCCESS(rc)) 301 323 { 302 if (pcszBwGroup) 303 { 304 pBwGroupNew = pdmNsBwGroupFindById(pShaper, pcszBwGroup); 305 if (pBwGroupNew) 306 pdmNsBwGroupRef(pBwGroupNew); 307 else 308 rc = VERR_NOT_FOUND; 309 } 310 324 PPDMNSBWGROUP pBwGroupOld = ASMAtomicXchgPtrT(&pFilter->pBwGroupR3, pBwGroupNew, PPDMNSBWGROUP); 325 ASMAtomicWritePtr(&pFilter->pBwGroupR0, MMHyperR3ToR0(pUVM->pVM, pBwGroupNew)); 326 if (pBwGroupOld) 327 pdmNsBwGroupUnref(pBwGroupOld); 328 pdmNsFilterLink(pFilter); 329 } 330 331 UNLOCK_NETSHAPER(pShaper); 332 return rc; 333 } 334 335 336 /** 337 * Detach network filter driver from bandwidth group. 338 * 339 * @returns VBox status code. 340 * @param pUVM The user mode VM handle. 341 * @param pDrvIns The driver instance. 342 * @param pFilter Pointer to the filter we detach. 343 */ 344 VMMR3_INT_DECL(int) PDMR3NsDetach(PUVM pUVM, PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter) 345 { 346 VM_ASSERT_EMT(pUVM->pVM); 347 AssertPtrReturn(pFilter, VERR_INVALID_POINTER); 348 AssertPtrReturn(pFilter->pBwGroupR3, VERR_INVALID_POINTER); 349 350 PPDMNETSHAPER pShaper = pUVM->pdm.s.pNetShaper; 351 LOCK_NETSHAPER_RETURN(pShaper); 352 353 pdmNsFilterUnlink(pFilter); 354 PPDMNSBWGROUP pBwGroup = ASMAtomicXchgPtrT(&pFilter->pBwGroupR3, NULL, PPDMNSBWGROUP); 355 if (pBwGroup) 356 pdmNsBwGroupUnref(pBwGroup); 357 358 UNLOCK_NETSHAPER(pShaper); 359 return VINF_SUCCESS; 360 } 361 362 363 /** 364 * Adjusts the maximum rate for the bandwidth group. 365 * 366 * @returns VBox status code. 367 * @param pUVM The user mode VM handle. 368 * @param pszBwGroup Name of the bandwidth group to attach to. 369 * @param cbPerSecMax Maximum number of bytes per second to be transmitted. 370 */ 371 VMMR3DECL(int) PDMR3NsBwGroupSetLimit(PUVM pUVM, const char *pszBwGroup, uint64_t cbPerSecMax) 372 { 373 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); 374 PPDMNETSHAPER pShaper = pUVM->pdm.s.pNetShaper; 375 LOCK_NETSHAPER_RETURN(pShaper); 376 377 int rc; 378 PPDMNSBWGROUP pBwGroup = pdmNsBwGroupFindById(pShaper, pszBwGroup); 379 if (pBwGroup) 380 { 381 rc = PDMCritSectEnter(&pBwGroup->Lock, VERR_SEM_BUSY); AssertRC(rc); 311 382 if (RT_SUCCESS(rc)) 312 383 { 313 pBwGroupOld = ASMAtomicXchgPtrT(&pFilter->pBwGroupR3, pBwGroupNew, PPDMNSBWGROUP); 314 ASMAtomicWritePtr(&pFilter->pBwGroupR0, MMHyperR3ToR0(pVM, pBwGroupNew)); 315 if (pBwGroupOld) 316 pdmNsBwGroupUnref(pBwGroupOld); 317 pdmNsFilterLink(pFilter); 384 pdmNsBwGroupSetLimit(pBwGroup, cbPerSecMax); 385 386 /* Drop extra tokens */ 387 if (pBwGroup->cbTokensLast > pBwGroup->cbBucket) 388 pBwGroup->cbTokensLast = pBwGroup->cbBucket; 389 390 int rc2 = PDMCritSectLeave(&pBwGroup->Lock); AssertRC(rc2); 318 391 } 319 int rc2 = RTCritSectLeave(&pShaper->cs); AssertRC(rc2); 320 } 321 322 return rc; 323 } 324 325 326 VMMR3DECL(int) PDMR3NsDetach(PVM pVM, PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter) 327 { 328 VM_ASSERT_EMT(pVM); 329 AssertPtrReturn(pFilter, VERR_INVALID_POINTER); 330 AssertPtrReturn(pFilter->pBwGroupR3, VERR_INVALID_POINTER); 331 332 PUVM pUVM = pVM->pUVM; 333 PPDMNETSHAPER pShaper = pUVM->pdm.s.pNetShaper; 334 335 int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc); 336 if (RT_SUCCESS(rc)) 337 { 338 pdmNsFilterUnlink(pFilter); 339 PPDMNSBWGROUP pBwGroup = NULL; 340 pBwGroup = ASMAtomicXchgPtrT(&pFilter->pBwGroupR3, NULL, PPDMNSBWGROUP); 341 if (pBwGroup) 342 pdmNsBwGroupUnref(pBwGroup); 343 int rc2 = RTCritSectLeave(&pShaper->cs); AssertRC(rc2); 344 } 345 return rc; 346 } 347 348 349 VMMR3DECL(bool) PDMR3NsAllocateBandwidth(PPDMNSFILTER pFilter, size_t cbTransfer) 350 { 351 return pdmNsAllocateBandwidth(pFilter, cbTransfer); 352 } 353 354 355 VMMR3DECL(int) PDMR3NsBwGroupSetLimit(PVM pVM, const char *pcszBwGroup, uint64_t cbTransferPerSecMax) 356 { 357 PUVM pUVM = pVM->pUVM; 358 PPDMNETSHAPER pShaper = pUVM->pdm.s.pNetShaper; 359 360 int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc); 361 if (RT_SUCCESS(rc)) 362 { 363 PPDMNSBWGROUP pBwGroup = pdmNsBwGroupFindById(pShaper, pcszBwGroup); 364 if (pBwGroup) 365 { 366 rc = PDMCritSectEnter(&pBwGroup->cs, VERR_SEM_BUSY); AssertRC(rc); 367 pdmNsBwGroupSetLimit(pBwGroup, cbTransferPerSecMax); 368 /* Drop extra tokens */ 369 if (pBwGroup->cbTokensLast > pBwGroup->cbBucketSize) 370 pBwGroup->cbTokensLast = pBwGroup->cbBucketSize; 371 rc = PDMCritSectLeave(&pBwGroup->cs); AssertRC(rc); 372 } 373 rc = RTCritSectLeave(&pShaper->cs); AssertRC(rc); 374 } 392 } 393 else 394 rc = VERR_NOT_FOUND; 395 396 UNLOCK_NETSHAPER(pShaper); 375 397 return rc; 376 398 } … … 391 413 { 392 414 RTThreadSleep(PDM_NETSHAPER_MAX_LATENCY); 415 393 416 /* Go over all bandwidth groups/filters calling pfnXmitPending */ 394 int rc = RTCritSectEnter(&pShaper->cs); AssertRC(rc);417 LOCK_NETSHAPER(pShaper); 395 418 PPDMNSBWGROUP pBwGroup = pShaper->pBwGroupsHead; 396 419 while (pBwGroup) 397 420 { 398 421 pdmNsBwGroupXmitPending(pBwGroup); 399 pBwGroup = pBwGroup->pNext ;422 pBwGroup = pBwGroup->pNextR3; 400 423 } 401 rc = RTCritSectLeave(&pShaper->cs); AssertRC(rc);424 UNLOCK_NETSHAPER(pShaper); 402 425 } 403 426 return VINF_SUCCESS; … … 437 460 { 438 461 PPDMNSBWGROUP pFree = pBwGroup; 439 pBwGroup = pBwGroup->pNext ;462 pBwGroup = pBwGroup->pNextR3; 440 463 pdmNsBwGroupTerminate(pFree); 464 MMR3HeapFree(pFree->pszNameR3); 441 465 MMHyperFree(pVM, pFree); 442 466 } 443 467 444 RTCritSectDelete(&pShaper-> cs);468 RTCritSectDelete(&pShaper->Lock); 445 469 return VINF_SUCCESS; 446 470 } … … 455 479 int pdmR3NetShaperInit(PVM pVM) 456 480 { 457 LogFlowFunc((": pVM=%p\n", pVM)); 458 481 LogFlow(("pdmR3NetShaperInit: pVM=%p\n", pVM)); 459 482 VM_ASSERT_EMT(pVM); 460 461 PPDMNETSHAPER pNetShaper = NULL; 462 463 int rc = MMR3HeapAllocZEx(pVM, MM_TAG_PDM_NET_SHAPER, 464 sizeof(PDMNETSHAPER), 465 (void **)&pNetShaper); 483 PUVM pUVM = pVM->pUVM; 484 AssertMsgReturn(!pUVM->pdm.s.pNetShaper, ("Network shaper was already initialized\n"), VERR_WRONG_ORDER); 485 486 PPDMNETSHAPER pShaper; 487 int rc = MMR3HeapAllocZEx(pVM, MM_TAG_PDM_NET_SHAPER, sizeof(PDMNETSHAPER), (void **)&pShaper); 466 488 if (RT_SUCCESS(rc)) 467 489 { 468 PCFGMNODE pCfgRoot = CFGMR3GetRoot(pVM); 469 PCFGMNODE pCfgNetShaper = CFGMR3GetChild(CFGMR3GetChild(pCfgRoot, "PDM"), "NetworkShaper"); 470 471 pNetShaper->pVM = pVM; 472 rc = RTCritSectInit(&pNetShaper->cs); 490 PCFGMNODE pCfgNetShaper = CFGMR3GetChild(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "NetworkShaper"); 491 492 pShaper->pVM = pVM; 493 rc = RTCritSectInit(&pShaper->Lock); 473 494 if (RT_SUCCESS(rc)) 474 495 { 475 496 /* Create all bandwidth groups. */ 476 497 PCFGMNODE pCfgBwGrp = CFGMR3GetChild(pCfgNetShaper, "BwGroups"); 477 478 498 if (pCfgBwGrp) 479 499 { … … 496 516 rc = CFGMR3QueryU64(pCur, "Max", &cbMax); 497 517 if (RT_SUCCESS(rc)) 498 rc = pdmNsBwGroupCreate(p NetShaper, pszBwGrpId, cbMax);518 rc = pdmNsBwGroupCreate(pShaper, pszBwGrpId, cbMax); 499 519 500 520 RTMemFree(pszBwGrpId); … … 507 527 if (RT_SUCCESS(rc)) 508 528 { 509 PUVM pUVM = pVM->pUVM; 510 AssertMsg(!pUVM->pdm.s.pNetShaper, ("Network shaper was already initialized\n")); 511 512 char szDesc[64]; 513 static unsigned s_iThread; 514 515 RTStrPrintf(szDesc, sizeof(szDesc), "PDMNsTx-%d", ++s_iThread); 516 rc = PDMR3ThreadCreate(pVM, &pNetShaper->hTxThread, pNetShaper, 517 pdmR3NsTxThread, pdmR3NsTxWakeUp, 0, 518 RTTHREADTYPE_IO, szDesc); 529 rc = PDMR3ThreadCreate(pVM, &pShaper->pTxThread, pShaper, pdmR3NsTxThread, pdmR3NsTxWakeUp, 530 0 /*cbStack*/, RTTHREADTYPE_IO, "PDMNsTx"); 519 531 if (RT_SUCCESS(rc)) 520 532 { 521 pUVM->pdm.s.pNetShaper = p NetShaper;533 pUVM->pdm.s.pNetShaper = pShaper; 522 534 return VINF_SUCCESS; 523 535 } 524 536 } 525 537 526 RTCritSectDelete(&p NetShaper->cs);538 RTCritSectDelete(&pShaper->Lock); 527 539 } 528 MMR3HeapFree(pNetShaper); 529 } 530 531 LogFlowFunc((": pVM=%p rc=%Rrc\n", pVM, rc)); 540 541 MMR3HeapFree(pShaper); 542 } 543 544 LogFlow(("pdmR3NetShaperInit: pVM=%p rc=%Rrc\n", pVM, rc)); 532 545 return rc; 533 546 } -
trunk/src/VBox/VMM/include/PDMInternal.h
r43657 r44355 1086 1086 R3PTRTYPE(PPDMASYNCCOMPLETIONTEMPLATE) pAsyncCompletionTemplates; 1087 1087 /** @} */ 1088 1089 /** Global block cache data. */ 1090 R3PTRTYPE(PPDMBLKCACHEGLOBAL) pBlkCacheGlobal; 1088 1091 #ifdef VBOX_WITH_NETSHAPER 1089 1092 /** Pointer to network shaper instance. */ 1090 1093 R3PTRTYPE(PPDMNETSHAPER) pNetShaper; 1091 1094 #endif /* VBOX_WITH_NETSHAPER */ 1092 1093 R3PTRTYPE(PPDMBLKCACHEGLOBAL) pBlkCacheGlobal;1094 1095 1095 1096 } PDMUSERPERVM; -
trunk/src/VBox/VMM/include/PDMNetShaperInternal.h
r44346 r44355 1 1 /* $Id$ */ 2 2 /** @file 3 * PDM Network Shaper - Internal data structures and functions common for both 4 * R0 and R3 parts. 3 * PDM Network Shaper - Internal data structures and functions common for both R0 and R3 parts. 5 4 */ 6 5 7 6 /* 8 * Copyright (C) 2011-201 2Oracle Corporation7 * Copyright (C) 2011-2013 Oracle Corporation 9 8 * 10 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 32 31 { 33 32 /** Pointer to the next group in the list. */ 34 struct PDMNSBWGROUP *pNext;33 R3PTRTYPE(struct PDMNSBWGROUP *) pNextR3; 35 34 /** Pointer to the shared UVM structure. */ 36 struct PDMNETSHAPER *pShaper;35 R3PTRTYPE(struct PDMNETSHAPER *) pShaperR3; 37 36 /** Critical section protecting all members below. */ 38 PDMCRITSECT cs;37 PDMCRITSECT Lock; 39 38 /** Pointer to the first filter attached to this group. */ 40 struct PDMNSFILTER *pFiltersHead;39 R3PTRTYPE(struct PDMNSFILTER *) pFiltersHeadR3; 41 40 /** Bandwidth group name. */ 42 char *pszName;41 R3PTRTYPE(char *) pszNameR3; 43 42 /** Maximum number of bytes filters are allowed to transfer. */ 44 volatile uint64_t cb TransferPerSecMax;43 volatile uint64_t cbPerSecMax; 45 44 /** Number of bytes we are allowed to transfer in one burst. */ 46 volatile uint32_t cbBucket Size;45 volatile uint32_t cbBucket; 47 46 /** Number of bytes we were allowed to transfer at the last update. */ 48 47 volatile uint32_t cbTokensLast; … … 55 54 typedef PDMNSBWGROUP *PPDMNSBWGROUP; 56 55 57 DECLINLINE(bool) pdmNsAllocateBandwidth(PPDMNSFILTER pFilter, size_t cbTransfer)58 {59 AssertPtrReturn(pFilter, true);60 if (!VALID_PTR(pFilter->CTX_SUFF(pBwGroup)))61 return true;62 56 63 PPDMNSBWGROUP pBwGroup = ASMAtomicReadPtrT(&pFilter->CTX_SUFF(pBwGroup), PPDMNSBWGROUP);64 int rc = PDMCritSectEnter(&pBwGroup->cs, VERR_SEM_BUSY); AssertRC(rc);65 if (RT_UNLIKELY(rc == VERR_SEM_BUSY))66 return true;67 bool fAllowed = true;68 if (pBwGroup->cbTransferPerSecMax)69 {70 /* Re-fill the bucket first */71 uint64_t tsNow = RTTimeSystemNanoTS();72 uint32_t uTokensAdded = (tsNow - pBwGroup->tsUpdatedLast)*pBwGroup->cbTransferPerSecMax/(1000*1000*1000);73 uint32_t uTokens = RT_MIN(pBwGroup->cbBucketSize, uTokensAdded + pBwGroup->cbTokensLast);74 75 if (cbTransfer > uTokens)76 {77 fAllowed = false;78 ASMAtomicWriteBool(&pFilter->fChoked, true);79 }80 else81 {82 pBwGroup->tsUpdatedLast = tsNow;83 pBwGroup->cbTokensLast = uTokens - (uint32_t)cbTransfer;84 }85 Log2((LOG_FN_FMT "BwGroup=%#p{%s} cbTransfer=%u uTokens=%u uTokensAdded=%u fAllowed=%RTbool\n",86 __PRETTY_FUNCTION__, pBwGroup, pBwGroup->pszName, cbTransfer, uTokens, uTokensAdded, fAllowed));87 }88 else89 Log2((LOG_FN_FMT "BwGroup=%#p{%s} disabled fAllowed=%RTbool\n",90 __PRETTY_FUNCTION__, pBwGroup, pBwGroup->pszName, fAllowed));91 92 rc = PDMCritSectLeave(&pBwGroup->cs); AssertRC(rc);93 return fAllowed;94 }
Note:
See TracChangeset
for help on using the changeset viewer.