VirtualBox

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

Last change on this file since 57260 was 56292, checked in by vboxsync, 10 years ago

Devices: Updated (C) year.

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