VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/DrvNetShaper.cpp@ 59775

Last change on this file since 59775 was 57358, checked in by vboxsync, 9 years ago

*: scm cleanup run.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.7 KB
Line 
1/* $Id: DrvNetShaper.cpp 57358 2015-08-14 15:16:38Z vboxsync $ */
2/** @file
3 * NetShaperFilter - Network shaper filter driver.
4 */
5
6/*
7 * Copyright (C) 2011-2015 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_NET_SHAPER
23
24#include <VBox/vmm/pdmdrv.h>
25#include <VBox/vmm/pdmnetifs.h>
26#include <VBox/vmm/pdmnetshaper.h>
27
28#include <VBox/log.h>
29#include <iprt/assert.h>
30#include <iprt/critsect.h>
31#include <iprt/string.h>
32#include <iprt/uuid.h>
33
34#include "VBoxDD.h"
35
36
37/*********************************************************************************************************************************
38* Structures and Typedefs *
39*********************************************************************************************************************************/
40/**
41 * Block driver instance data.
42 *
43 * @implements PDMINETWORKUP
44 * @implements PDMINETWORKDOWN
45 * @implements PDMINETWORKCONFIG
46 */
47typedef struct DRVNETSHAPER
48{
49 /** Pointer to the driver instance. */
50 PPDMDRVINS pDrvInsR3;
51 /** The network interface. */
52 PDMINETWORKUP INetworkUpR3;
53 /** The connector that's attached to us. */
54 PPDMINETWORKUP pIBelowNetR3;
55
56 /** Pointer to the driver instance. */
57 PPDMDRVINSR0 pDrvInsR0;
58 /** The network interface. */
59 PDMINETWORKUPR0 INetworkUpR0;
60 /** The connector that's attached to us. */
61 PPDMINETWORKUPR0 pIBelowNetR0;
62
63 /** Ring-3 base interface for the ring-0 context. */
64 PDMIBASER0 IBaseR0;
65 /** Ring-3 base interface for the raw-mode context. */
66 PDMIBASERC IBaseRC;
67
68 /** For when we're the leaf driver. */
69 PDMCRITSECT XmitLock;
70
71 /** The network interface. */
72 PDMINETWORKDOWN INetworkDown;
73 /** The network config interface.
74 * @todo this is a main interface and shouldn't be here... */
75 PDMINETWORKCONFIG INetworkConfig;
76 /** The port we're attached to. */
77 PPDMINETWORKDOWN pIAboveNet;
78 /** The config port interface we're attached to. */
79 PPDMINETWORKCONFIG pIAboveConfig;
80 /** The filter that represents us at bandwidth group. */
81 PDMNSFILTER Filter;
82 /** The name of bandwidth group we are attached to. */
83 char * pszBwGroup;
84
85 /** TX: Total number of bytes to allocate. */
86 STAMCOUNTER StatXmitBytesRequested;
87 /** TX: Number of bytes delayed. */
88 STAMCOUNTER StatXmitBytesDenied;
89 /** TX: Number of bytes allowed to pass. */
90 STAMCOUNTER StatXmitBytesGranted;
91 /** TX: Total number of packets being sent. */
92 STAMCOUNTER StatXmitPktsRequested;
93 /** TX: Number of packets delayed. */
94 STAMCOUNTER StatXmitPktsDenied;
95 /** TX: Number of packets allowed to pass. */
96 STAMCOUNTER StatXmitPktsGranted;
97 /** TX: Number of calls to pfnXmitPending. */
98 STAMCOUNTER StatXmitPendingCalled;
99} DRVNETSHAPER, *PDRVNETSHAPER;
100
101
102/**
103 * @interface_method_impl{PDMINETWORKUP,pfnBeginXmit}
104 */
105PDMBOTHCBDECL(int) drvNetShaperUp_BeginXmit(PPDMINETWORKUP pInterface, bool fOnWorkerThread)
106{
107 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, CTX_SUFF(INetworkUp));
108 if (RT_UNLIKELY(!pThis->CTX_SUFF(pIBelowNet)))
109 {
110 int rc = PDMCritSectTryEnter(&pThis->XmitLock);
111 if (RT_UNLIKELY(rc == VERR_SEM_BUSY))
112 rc = VERR_TRY_AGAIN;
113 return rc;
114 }
115 return pThis->CTX_SUFF(pIBelowNet)->pfnBeginXmit(pThis->CTX_SUFF(pIBelowNet), fOnWorkerThread);
116}
117
118
119/**
120 * @interface_method_impl{PDMINETWORKUP,pfnAllocBuf}
121 */
122PDMBOTHCBDECL(int) drvNetShaperUp_AllocBuf(PPDMINETWORKUP pInterface, size_t cbMin,
123 PCPDMNETWORKGSO pGso, PPPDMSCATTERGATHER ppSgBuf)
124{
125 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, CTX_SUFF(INetworkUp));
126 if (RT_UNLIKELY(!pThis->CTX_SUFF(pIBelowNet)))
127 return VERR_NET_DOWN;
128 //LogFlow(("drvNetShaperUp_AllocBuf: cb=%d\n", cbMin));
129 STAM_REL_COUNTER_ADD(&pThis->StatXmitBytesRequested, cbMin);
130 STAM_REL_COUNTER_INC(&pThis->StatXmitPktsRequested);
131#if defined(IN_RING3) || defined(IN_RING0)
132 if (!PDMNsAllocateBandwidth(&pThis->Filter, cbMin))
133 {
134 STAM_REL_COUNTER_ADD(&pThis->StatXmitBytesDenied, cbMin);
135 STAM_REL_COUNTER_INC(&pThis->StatXmitPktsDenied);
136 return VERR_TRY_AGAIN;
137 }
138#endif
139 STAM_REL_COUNTER_ADD(&pThis->StatXmitBytesGranted, cbMin);
140 STAM_REL_COUNTER_INC(&pThis->StatXmitPktsGranted);
141 //LogFlow(("drvNetShaperUp_AllocBuf: got cb=%d\n", cbMin));
142 return pThis->CTX_SUFF(pIBelowNet)->pfnAllocBuf(pThis->CTX_SUFF(pIBelowNet), cbMin, pGso, ppSgBuf);
143}
144
145
146/**
147 * @interface_method_impl{PDMINETWORKUP,pfnFreeBuf}
148 */
149PDMBOTHCBDECL(int) drvNetShaperUp_FreeBuf(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf)
150{
151 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, CTX_SUFF(INetworkUp));
152 if (RT_UNLIKELY(!pThis->CTX_SUFF(pIBelowNet)))
153 return VERR_NET_DOWN;
154 return pThis->CTX_SUFF(pIBelowNet)->pfnFreeBuf(pThis->CTX_SUFF(pIBelowNet), pSgBuf);
155}
156
157
158/**
159 * @interface_method_impl{PDMINETWORKUP,pfnSendBuf}
160 */
161PDMBOTHCBDECL(int) drvNetShaperUp_SendBuf(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread)
162{
163 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, CTX_SUFF(INetworkUp));
164 if (RT_UNLIKELY(!pThis->CTX_SUFF(pIBelowNet)))
165 return VERR_NET_DOWN;
166
167 return pThis->CTX_SUFF(pIBelowNet)->pfnSendBuf(pThis->CTX_SUFF(pIBelowNet), pSgBuf, fOnWorkerThread);
168}
169
170
171/**
172 * @interface_method_impl{PDMINETWORKUP,pfnEndXmit}
173 */
174PDMBOTHCBDECL(void) drvNetShaperUp_EndXmit(PPDMINETWORKUP pInterface)
175{
176 //LogFlow(("drvNetShaperUp_EndXmit:\n"));
177 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, CTX_SUFF(INetworkUp));
178 if (RT_LIKELY(pThis->CTX_SUFF(pIBelowNet)))
179 pThis->CTX_SUFF(pIBelowNet)->pfnEndXmit(pThis->CTX_SUFF(pIBelowNet));
180 else
181 PDMCritSectLeave(&pThis->XmitLock);
182}
183
184
185/**
186 * @interface_method_impl{PDMINETWORKUP,pfnSetPromiscuousMode}
187 */
188PDMBOTHCBDECL(void) drvNetShaperUp_SetPromiscuousMode(PPDMINETWORKUP pInterface, bool fPromiscuous)
189{
190 LogFlow(("drvNetShaperUp_SetPromiscuousMode: fPromiscuous=%d\n", fPromiscuous));
191 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, CTX_SUFF(INetworkUp));
192 if (pThis->CTX_SUFF(pIBelowNet))
193 pThis->CTX_SUFF(pIBelowNet)->pfnSetPromiscuousMode(pThis->CTX_SUFF(pIBelowNet), fPromiscuous);
194}
195
196
197#ifdef IN_RING3
198/**
199 * @interface_method_impl{PDMINETWORKUP,pfnNotifyLinkChanged}
200 */
201static DECLCALLBACK(void) drvR3NetShaperUp_NotifyLinkChanged(PPDMINETWORKUP pInterface, PDMNETWORKLINKSTATE enmLinkState)
202{
203 LogFlow(("drvNetShaperUp_NotifyLinkChanged: enmLinkState=%d\n", enmLinkState));
204 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, CTX_SUFF(INetworkUp));
205 if (pThis->pIBelowNetR3)
206 pThis->pIBelowNetR3->pfnNotifyLinkChanged(pThis->pIBelowNetR3, enmLinkState);
207}
208
209/**
210 * @interface_method_impl{PDMINETWORKDOWN,pfnWaitReceiveAvail}
211 */
212static DECLCALLBACK(int) drvR3NetShaperDown_WaitReceiveAvail(PPDMINETWORKDOWN pInterface, RTMSINTERVAL cMillies)
213{
214 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, INetworkDown);
215 return pThis->pIAboveNet->pfnWaitReceiveAvail(pThis->pIAboveNet, cMillies);
216}
217
218
219/**
220 * @interface_method_impl{PDMINETWORKDOWN,pfnReceive}
221 */
222static DECLCALLBACK(int) drvR3NetShaperDown_Receive(PPDMINETWORKDOWN pInterface, const void *pvBuf, size_t cb)
223{
224 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, INetworkDown);
225 return pThis->pIAboveNet->pfnReceive(pThis->pIAboveNet, pvBuf, cb);
226}
227
228
229/**
230 * @interface_method_impl{PDMINETWORKDOWN,pfnReceiveGso}
231 */
232static DECLCALLBACK(int) drvR3NetShaperDown_ReceiveGso(PPDMINETWORKDOWN pInterface, const void *pvBuf, size_t cb, PCPDMNETWORKGSO pGso)
233{
234 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, INetworkDown);
235 if (pThis->pIAboveNet->pfnReceiveGso)
236 return pThis->pIAboveNet->pfnReceiveGso(pThis->pIAboveNet, pvBuf, cb, pGso);
237 return VERR_NOT_SUPPORTED;
238}
239
240
241/**
242 * @interface_method_impl{PDMINETWORKDOWN,pfnXmitPending}
243 */
244static DECLCALLBACK(void) drvR3NetShaperDown_XmitPending(PPDMINETWORKDOWN pInterface)
245{
246 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, INetworkDown);
247 STAM_REL_COUNTER_INC(&pThis->StatXmitPendingCalled);
248 pThis->pIAboveNet->pfnXmitPending(pThis->pIAboveNet);
249}
250
251
252/**
253 * Gets the current Media Access Control (MAC) address.
254 *
255 * @returns VBox status code.
256 * @param pInterface Pointer to the interface structure containing the called function pointer.
257 * @param pMac Where to store the MAC address.
258 * @thread EMT
259 */
260static DECLCALLBACK(int) drvR3NetShaperDownCfg_GetMac(PPDMINETWORKCONFIG pInterface, PRTMAC pMac)
261{
262 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, INetworkConfig);
263 return pThis->pIAboveConfig->pfnGetMac(pThis->pIAboveConfig, pMac);
264}
265
266/**
267 * Gets the new link state.
268 *
269 * @returns The current link state.
270 * @param pInterface Pointer to the interface structure containing the called function pointer.
271 * @thread EMT
272 */
273static DECLCALLBACK(PDMNETWORKLINKSTATE) drvR3NetShaperDownCfg_GetLinkState(PPDMINETWORKCONFIG pInterface)
274{
275 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, INetworkConfig);
276 return pThis->pIAboveConfig->pfnGetLinkState(pThis->pIAboveConfig);
277}
278
279/**
280 * Sets the new link state.
281 *
282 * @returns VBox status code.
283 * @param pInterface Pointer to the interface structure containing the called function pointer.
284 * @param enmState The new link state
285 * @thread EMT
286 */
287static DECLCALLBACK(int) drvR3NetShaperDownCfg_SetLinkState(PPDMINETWORKCONFIG pInterface, PDMNETWORKLINKSTATE enmState)
288{
289 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, INetworkConfig);
290 return pThis->pIAboveConfig->pfnSetLinkState(pThis->pIAboveConfig, enmState);
291}
292
293
294/**
295 * @interface_method_impl{PDMIBASER0,pfnQueryInterface}
296 */
297static DECLCALLBACK(RTR0PTR) drvR3NetShaperIBaseR0_QueryInterface(PPDMIBASER0 pInterface, const char *pszIID)
298{
299 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, IBaseR0);
300 /*
301 * We need to check if the underlying driver supports R0. If it does not,
302 * then it is useless and even harmful to support R0 here, as we will end up
303 * returning errors when a network adapter tries to allocate a buffer in R0.
304 */
305 if (pThis->pIBelowNetR0)
306 PDMIBASER0_RETURN_INTERFACE(pThis->pDrvInsR3, pszIID, PDMINETWORKUP, &pThis->INetworkUpR0);
307 return NIL_RTR0PTR;
308}
309
310/**
311 * @interface_method_impl{PDMIBASERC,pfnQueryInterface}
312 */
313static DECLCALLBACK(RTRCPTR) drvR3NetShaperIBaseRC_QueryInterface(PPDMIBASERC pInterface, const char *pszIID)
314{
315 return NIL_RTRCPTR;
316}
317
318/**
319 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
320 */
321static DECLCALLBACK(void *) drvR3NetShaperIBase_QueryInterface(PPDMIBASE pInterface, const char *pszIID)
322{
323 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
324 PDRVNETSHAPER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSHAPER);
325 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
326 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASER0, &pThis->IBaseR0);
327 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASERC, &pThis->IBaseRC);
328 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKUP, &pThis->INetworkUpR3);
329 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKDOWN, &pThis->INetworkDown);
330 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKCONFIG, &pThis->INetworkConfig);
331 return NULL;
332}
333
334
335/**
336 * @interface_method_impl{PDMDRVREG,pfnDetach}
337 */
338static DECLCALLBACK(void) drvR3NetShaperDetach(PPDMDRVINS pDrvIns, uint32_t fFlags)
339{
340 PDRVNETSHAPER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSHAPER);
341
342 LogFlow(("drvNetShaperDetach: pDrvIns: %p, fFlags: %u\n", pDrvIns, fFlags));
343 PDMCritSectEnter(&pThis->XmitLock, VERR_IGNORED);
344 pThis->pIBelowNetR3 = NULL;
345 pThis->pIBelowNetR0 = NIL_RTR0PTR;
346 PDMCritSectLeave(&pThis->XmitLock);
347}
348
349
350/**
351 * @interface_method_impl{PDMDRVREG,pfnAttach}
352 */
353static DECLCALLBACK(int) drvR3NetShaperAttach(PPDMDRVINS pDrvIns, uint32_t fFlags)
354{
355 PDRVNETSHAPER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSHAPER);
356 LogFlow(("drvNetShaperAttach/#%#x: fFlags=%#x\n", pDrvIns->iInstance, fFlags));
357 PDMCritSectEnter(&pThis->XmitLock, VERR_IGNORED);
358
359 /*
360 * Query the network connector interface.
361 */
362 PPDMIBASE pBaseDown;
363 int rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBaseDown);
364 if ( rc == VERR_PDM_NO_ATTACHED_DRIVER
365 || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME)
366 {
367 pThis->pIBelowNetR3 = NULL;
368 pThis->pIBelowNetR0 = NIL_RTR0PTR;
369 rc = VINF_SUCCESS;
370 }
371 else if (RT_SUCCESS(rc))
372 {
373 pThis->pIBelowNetR3 = PDMIBASE_QUERY_INTERFACE(pBaseDown, PDMINETWORKUP);
374 if (pThis->pIBelowNetR3)
375 {
376 PPDMIBASER0 pBaseR0 = PDMIBASE_QUERY_INTERFACE(pBaseDown, PDMIBASER0);
377 pThis->pIBelowNetR0 = pBaseR0 ? pBaseR0->pfnQueryInterface(pBaseR0, PDMINETWORKUP_IID) : NIL_RTR0PTR;
378 rc = VINF_SUCCESS;
379 }
380 else
381 {
382 AssertMsgFailed(("Configuration error: the driver below didn't export the network connector interface!\n"));
383 rc = VERR_PDM_MISSING_INTERFACE_BELOW;
384 }
385 }
386 else
387 AssertMsgFailed(("Failed to attach to driver below! rc=%Rrc\n", rc));
388
389 PDMCritSectLeave(&pThis->XmitLock);
390 return VINF_SUCCESS;
391}
392
393
394/**
395 * @interface_method_impl{PDMDRVREG,pfnDestruct}
396 */
397static DECLCALLBACK(void) drvR3NetShaperDestruct(PPDMDRVINS pDrvIns)
398{
399 PDRVNETSHAPER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSHAPER);
400 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
401
402 PDMDrvHlpNetShaperDetach(pDrvIns, &pThis->Filter);
403
404 if (PDMCritSectIsInitialized(&pThis->XmitLock))
405 PDMR3CritSectDelete(&pThis->XmitLock);
406}
407
408
409/**
410 * @interface_method_impl{Construct a NAT network transport driver instance,
411 * PDMDRVREG,pfnDestruct}
412 */
413static DECLCALLBACK(int) drvR3NetShaperConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
414{
415 PDRVNETSHAPER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSHAPER);
416 LogFlow(("drvNetShaperConstruct:\n"));
417 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
418
419 /*
420 * Init the static parts.
421 */
422 pThis->pDrvInsR3 = pDrvIns;
423 pThis->pDrvInsR0 = PDMDRVINS_2_R0PTR(pDrvIns);
424 /* IBase */
425 pDrvIns->IBase.pfnQueryInterface = drvR3NetShaperIBase_QueryInterface;
426 pThis->IBaseR0.pfnQueryInterface = drvR3NetShaperIBaseR0_QueryInterface;
427 pThis->IBaseRC.pfnQueryInterface = drvR3NetShaperIBaseRC_QueryInterface;
428 /* INetworkUp */
429 pThis->INetworkUpR3.pfnBeginXmit = drvNetShaperUp_BeginXmit;
430 pThis->INetworkUpR3.pfnAllocBuf = drvNetShaperUp_AllocBuf;
431 pThis->INetworkUpR3.pfnFreeBuf = drvNetShaperUp_FreeBuf;
432 pThis->INetworkUpR3.pfnSendBuf = drvNetShaperUp_SendBuf;
433 pThis->INetworkUpR3.pfnEndXmit = drvNetShaperUp_EndXmit;
434 pThis->INetworkUpR3.pfnSetPromiscuousMode = drvNetShaperUp_SetPromiscuousMode;
435 pThis->INetworkUpR3.pfnNotifyLinkChanged = drvR3NetShaperUp_NotifyLinkChanged;
436 /* Resolve the ring-0 context interface addresses. */
437 int rc = pDrvIns->pHlpR3->pfnLdrGetR0InterfaceSymbols(pDrvIns, &pThis->INetworkUpR0,
438 sizeof(pThis->INetworkUpR0),
439 "drvNetShaperUp_", PDMINETWORKUP_SYM_LIST);
440 AssertLogRelRCReturn(rc, rc);
441 /* INetworkDown */
442 pThis->INetworkDown.pfnWaitReceiveAvail = drvR3NetShaperDown_WaitReceiveAvail;
443 pThis->INetworkDown.pfnReceive = drvR3NetShaperDown_Receive;
444 pThis->INetworkDown.pfnReceiveGso = drvR3NetShaperDown_ReceiveGso;
445 pThis->INetworkDown.pfnXmitPending = drvR3NetShaperDown_XmitPending;
446 /* INetworkConfig */
447 pThis->INetworkConfig.pfnGetMac = drvR3NetShaperDownCfg_GetMac;
448 pThis->INetworkConfig.pfnGetLinkState = drvR3NetShaperDownCfg_GetLinkState;
449 pThis->INetworkConfig.pfnSetLinkState = drvR3NetShaperDownCfg_SetLinkState;
450
451 /*
452 * Create the locks.
453 */
454 rc = PDMDrvHlpCritSectInit(pDrvIns, &pThis->XmitLock, RT_SRC_POS, "NetShaper");
455 AssertRCReturn(rc, rc);
456
457 /*
458 * Validate the config.
459 */
460 if (!CFGMR3AreValuesValid(pCfg, "BwGroup\0"))
461 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
462
463 /*
464 * Find the bandwidth group we have to attach to.
465 */
466 rc = CFGMR3QueryStringAlloc(pCfg, "BwGroup", &pThis->pszBwGroup);
467 if (RT_FAILURE(rc) && rc != VERR_CFGM_VALUE_NOT_FOUND)
468 {
469 rc = PDMDRV_SET_ERROR(pDrvIns, rc,
470 N_("DrvNetShaper: Configuration error: Querying \"BwGroup\" as string failed"));
471 return rc;
472 }
473 else
474 rc = VINF_SUCCESS;
475
476 pThis->Filter.pIDrvNetR3 = &pThis->INetworkDown;
477 rc = PDMDrvHlpNetShaperAttach(pDrvIns, pThis->pszBwGroup, &pThis->Filter);
478 if (RT_FAILURE(rc))
479 {
480 rc = PDMDRV_SET_ERROR(pDrvIns, rc,
481 N_("DrvNetShaper: Configuration error: Failed to attach to bandwidth group"));
482 return rc;
483 }
484
485 /*
486 * Query the network port interface.
487 */
488 pThis->pIAboveNet = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMINETWORKDOWN);
489 if (!pThis->pIAboveNet)
490 {
491 AssertMsgFailed(("Configuration error: the above device/driver didn't export the network port interface!\n"));
492 return VERR_PDM_MISSING_INTERFACE_ABOVE;
493 }
494
495 /*
496 * Query the network config interface.
497 */
498 pThis->pIAboveConfig = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMINETWORKCONFIG);
499 if (!pThis->pIAboveConfig)
500 {
501 AssertMsgFailed(("Configuration error: the above device/driver didn't export the network config interface!\n"));
502 return VERR_PDM_MISSING_INTERFACE_ABOVE;
503 }
504
505 /*
506 * Query the network connector interface.
507 */
508 PPDMIBASE pBaseDown;
509 rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBaseDown);
510 if ( rc == VERR_PDM_NO_ATTACHED_DRIVER
511 || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME)
512 {
513 pThis->pIBelowNetR3 = NULL;
514 pThis->pIBelowNetR0 = NIL_RTR0PTR;
515 }
516 else if (RT_SUCCESS(rc))
517 {
518 pThis->pIBelowNetR3 = PDMIBASE_QUERY_INTERFACE(pBaseDown, PDMINETWORKUP);
519 if (!pThis->pIBelowNetR3)
520 {
521 AssertMsgFailed(("Configuration error: the driver below didn't export the network connector interface!\n"));
522 return VERR_PDM_MISSING_INTERFACE_BELOW;
523 }
524 PPDMIBASER0 pBaseR0 = PDMIBASE_QUERY_INTERFACE(pBaseDown, PDMIBASER0);
525 pThis->pIBelowNetR0 = pBaseR0 ? pBaseR0->pfnQueryInterface(pBaseR0, PDMINETWORKUP_IID) : NIL_RTR0PTR;
526 }
527 else
528 {
529 AssertMsgFailed(("Failed to attach to driver below! rc=%Rrc\n", rc));
530 return rc;
531 }
532
533 /*
534 * Register statistics.
535 */
536 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pThis->StatXmitBytesRequested, "Bytes/Tx/Requested", STAMUNIT_BYTES, "Number of requested TX bytes.");
537 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pThis->StatXmitBytesDenied, "Bytes/Tx/Denied", STAMUNIT_BYTES, "Number of denied TX bytes.");
538 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pThis->StatXmitBytesGranted, "Bytes/Tx/Granted", STAMUNIT_BYTES, "Number of granted TX bytes.");
539
540 PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPktsRequested, "Packets/Tx/Requested", "Number of requested TX packets.");
541 PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPktsDenied, "Packets/Tx/Denied", "Number of denied TX packets.");
542 PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPktsGranted, "Packets/Tx/Granted", "Number of granted TX packets.");
543 PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPendingCalled, "Tx/WakeUp", "Number of wakeup TX calls.");
544
545 return VINF_SUCCESS;
546}
547
548
549
550/**
551 * Network sniffer filter driver registration record.
552 */
553const PDMDRVREG g_DrvNetShaper =
554{
555 /* u32Version */
556 PDM_DRVREG_VERSION,
557 /* szName */
558 "NetShaper",
559 /* szRCMod */
560 "",
561 /* szR0Mod */
562 "VBoxDDR0.r0",
563 /* pszDescription */
564 "Network Shaper Filter Driver",
565 /* fFlags */
566 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DRVREG_FLAGS_R0,
567 /* fClass. */
568 PDM_DRVREG_CLASS_NETWORK,
569 /* cMaxInstances */
570 UINT32_MAX,
571 /* cbInstance */
572 sizeof(DRVNETSHAPER),
573 /* pfnConstruct */
574 drvR3NetShaperConstruct,
575 /* pfnDestruct */
576 drvR3NetShaperDestruct,
577 /* pfnRelocate */
578 NULL,
579 /* pfnIOCtl */
580 NULL,
581 /* pfnPowerOn */
582 NULL,
583 /* pfnReset */
584 NULL,
585 /* pfnSuspend */
586 NULL,
587 /* pfnResume */
588 NULL,
589 /* pfnAttach */
590 drvR3NetShaperAttach,
591 /* pfnDetach */
592 drvR3NetShaperDetach,
593 /* pfnPowerOff */
594 NULL,
595 /* pfnSoftReset */
596 NULL,
597 /* u32EndVersion */
598 PDM_DRVREG_VERSION
599};
600#endif /* IN_RING3 */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette