VirtualBox

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

Last change on this file since 84909 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.8 KB
Line 
1/* $Id: DrvNetShaper.cpp 82968 2020-02-04 10:35:17Z vboxsync $ */
2/** @file
3 * NetShaperFilter - Network shaper filter driver.
4 */
5
6/*
7 * Copyright (C) 2011-2020 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 RT_NOREF(pInterface, pszIID);
316 return NIL_RTRCPTR;
317}
318
319/**
320 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
321 */
322static DECLCALLBACK(void *) drvR3NetShaperIBase_QueryInterface(PPDMIBASE pInterface, const char *pszIID)
323{
324 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
325 PDRVNETSHAPER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSHAPER);
326 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
327 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASER0, &pThis->IBaseR0);
328 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASERC, &pThis->IBaseRC);
329 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKUP, &pThis->INetworkUpR3);
330 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKDOWN, &pThis->INetworkDown);
331 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKCONFIG, &pThis->INetworkConfig);
332 return NULL;
333}
334
335
336/**
337 * @interface_method_impl{PDMDRVREG,pfnDetach}
338 */
339static DECLCALLBACK(void) drvR3NetShaperDetach(PPDMDRVINS pDrvIns, uint32_t fFlags)
340{
341 RT_NOREF(fFlags);
342 PDRVNETSHAPER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSHAPER);
343
344 LogFlow(("drvNetShaperDetach: pDrvIns: %p, fFlags: %u\n", pDrvIns, fFlags));
345 PDMCritSectEnter(&pThis->XmitLock, VERR_IGNORED);
346 pThis->pIBelowNetR3 = NULL;
347 pThis->pIBelowNetR0 = NIL_RTR0PTR;
348 PDMCritSectLeave(&pThis->XmitLock);
349}
350
351
352/**
353 * @interface_method_impl{PDMDRVREG,pfnAttach}
354 */
355static DECLCALLBACK(int) drvR3NetShaperAttach(PPDMDRVINS pDrvIns, uint32_t fFlags)
356{
357 PDRVNETSHAPER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSHAPER);
358 LogFlow(("drvNetShaperAttach/#%#x: fFlags=%#x\n", pDrvIns->iInstance, fFlags));
359 PDMCritSectEnter(&pThis->XmitLock, VERR_IGNORED);
360
361 /*
362 * Query the network connector interface.
363 */
364 PPDMIBASE pBaseDown;
365 int rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBaseDown);
366 if ( rc == VERR_PDM_NO_ATTACHED_DRIVER
367 || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME)
368 {
369 pThis->pIBelowNetR3 = NULL;
370 pThis->pIBelowNetR0 = NIL_RTR0PTR;
371 rc = VINF_SUCCESS;
372 }
373 else if (RT_SUCCESS(rc))
374 {
375 pThis->pIBelowNetR3 = PDMIBASE_QUERY_INTERFACE(pBaseDown, PDMINETWORKUP);
376 if (pThis->pIBelowNetR3)
377 {
378 PPDMIBASER0 pBaseR0 = PDMIBASE_QUERY_INTERFACE(pBaseDown, PDMIBASER0);
379 pThis->pIBelowNetR0 = pBaseR0 ? pBaseR0->pfnQueryInterface(pBaseR0, PDMINETWORKUP_IID) : NIL_RTR0PTR;
380 rc = VINF_SUCCESS;
381 }
382 else
383 {
384 AssertMsgFailed(("Configuration error: the driver below didn't export the network connector interface!\n"));
385 rc = VERR_PDM_MISSING_INTERFACE_BELOW;
386 }
387 }
388 else
389 AssertMsgFailed(("Failed to attach to driver below! rc=%Rrc\n", rc));
390
391 PDMCritSectLeave(&pThis->XmitLock);
392 return VINF_SUCCESS;
393}
394
395
396/**
397 * @interface_method_impl{PDMDRVREG,pfnDestruct}
398 */
399static DECLCALLBACK(void) drvR3NetShaperDestruct(PPDMDRVINS pDrvIns)
400{
401 PDRVNETSHAPER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSHAPER);
402 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
403
404 PDMDrvHlpNetShaperDetach(pDrvIns, &pThis->Filter);
405
406 if (PDMCritSectIsInitialized(&pThis->XmitLock))
407 PDMR3CritSectDelete(&pThis->XmitLock);
408}
409
410
411/**
412 * @interface_method_impl{Construct a NAT network transport driver instance,
413 * PDMDRVREG,pfnDestruct}
414 */
415static DECLCALLBACK(int) drvR3NetShaperConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
416{
417 PDRVNETSHAPER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSHAPER);
418 LogFlow(("drvNetShaperConstruct:\n"));
419 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
420
421 /*
422 * Init the static parts.
423 */
424 pThis->pDrvInsR3 = pDrvIns;
425 pThis->pDrvInsR0 = PDMDRVINS_2_R0PTR(pDrvIns);
426 /* IBase */
427 pDrvIns->IBase.pfnQueryInterface = drvR3NetShaperIBase_QueryInterface;
428 pThis->IBaseR0.pfnQueryInterface = drvR3NetShaperIBaseR0_QueryInterface;
429 pThis->IBaseRC.pfnQueryInterface = drvR3NetShaperIBaseRC_QueryInterface;
430 /* INetworkUp */
431 pThis->INetworkUpR3.pfnBeginXmit = drvNetShaperUp_BeginXmit;
432 pThis->INetworkUpR3.pfnAllocBuf = drvNetShaperUp_AllocBuf;
433 pThis->INetworkUpR3.pfnFreeBuf = drvNetShaperUp_FreeBuf;
434 pThis->INetworkUpR3.pfnSendBuf = drvNetShaperUp_SendBuf;
435 pThis->INetworkUpR3.pfnEndXmit = drvNetShaperUp_EndXmit;
436 pThis->INetworkUpR3.pfnSetPromiscuousMode = drvNetShaperUp_SetPromiscuousMode;
437 pThis->INetworkUpR3.pfnNotifyLinkChanged = drvR3NetShaperUp_NotifyLinkChanged;
438 /* Resolve the ring-0 context interface addresses. */
439 int rc = pDrvIns->pHlpR3->pfnLdrGetR0InterfaceSymbols(pDrvIns, &pThis->INetworkUpR0,
440 sizeof(pThis->INetworkUpR0),
441 "drvNetShaperUp_", PDMINETWORKUP_SYM_LIST);
442 AssertLogRelRCReturn(rc, rc);
443 /* INetworkDown */
444 pThis->INetworkDown.pfnWaitReceiveAvail = drvR3NetShaperDown_WaitReceiveAvail;
445 pThis->INetworkDown.pfnReceive = drvR3NetShaperDown_Receive;
446 pThis->INetworkDown.pfnReceiveGso = drvR3NetShaperDown_ReceiveGso;
447 pThis->INetworkDown.pfnXmitPending = drvR3NetShaperDown_XmitPending;
448 /* INetworkConfig */
449 pThis->INetworkConfig.pfnGetMac = drvR3NetShaperDownCfg_GetMac;
450 pThis->INetworkConfig.pfnGetLinkState = drvR3NetShaperDownCfg_GetLinkState;
451 pThis->INetworkConfig.pfnSetLinkState = drvR3NetShaperDownCfg_SetLinkState;
452
453 /*
454 * Create the locks.
455 */
456 rc = PDMDrvHlpCritSectInit(pDrvIns, &pThis->XmitLock, RT_SRC_POS, "NetShaper");
457 AssertRCReturn(rc, rc);
458
459 /*
460 * Validate the config.
461 */
462 if (!CFGMR3AreValuesValid(pCfg, "BwGroup\0"))
463 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
464
465 /*
466 * Find the bandwidth group we have to attach to.
467 */
468 rc = CFGMR3QueryStringAlloc(pCfg, "BwGroup", &pThis->pszBwGroup);
469 if (RT_FAILURE(rc) && rc != VERR_CFGM_VALUE_NOT_FOUND)
470 {
471 rc = PDMDRV_SET_ERROR(pDrvIns, rc,
472 N_("DrvNetShaper: Configuration error: Querying \"BwGroup\" as string failed"));
473 return rc;
474 }
475 else
476 rc = VINF_SUCCESS;
477
478 pThis->Filter.pIDrvNetR3 = &pThis->INetworkDown;
479 rc = PDMDrvHlpNetShaperAttach(pDrvIns, pThis->pszBwGroup, &pThis->Filter);
480 if (RT_FAILURE(rc))
481 {
482 rc = PDMDRV_SET_ERROR(pDrvIns, rc,
483 N_("DrvNetShaper: Configuration error: Failed to attach to bandwidth group"));
484 return rc;
485 }
486
487 /*
488 * Query the network port interface.
489 */
490 pThis->pIAboveNet = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMINETWORKDOWN);
491 if (!pThis->pIAboveNet)
492 {
493 AssertMsgFailed(("Configuration error: the above device/driver didn't export the network port interface!\n"));
494 return VERR_PDM_MISSING_INTERFACE_ABOVE;
495 }
496
497 /*
498 * Query the network config interface.
499 */
500 pThis->pIAboveConfig = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMINETWORKCONFIG);
501 if (!pThis->pIAboveConfig)
502 {
503 AssertMsgFailed(("Configuration error: the above device/driver didn't export the network config interface!\n"));
504 return VERR_PDM_MISSING_INTERFACE_ABOVE;
505 }
506
507 /*
508 * Query the network connector interface.
509 */
510 PPDMIBASE pBaseDown;
511 rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBaseDown);
512 if ( rc == VERR_PDM_NO_ATTACHED_DRIVER
513 || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME)
514 {
515 pThis->pIBelowNetR3 = NULL;
516 pThis->pIBelowNetR0 = NIL_RTR0PTR;
517 }
518 else if (RT_SUCCESS(rc))
519 {
520 pThis->pIBelowNetR3 = PDMIBASE_QUERY_INTERFACE(pBaseDown, PDMINETWORKUP);
521 if (!pThis->pIBelowNetR3)
522 {
523 AssertMsgFailed(("Configuration error: the driver below didn't export the network connector interface!\n"));
524 return VERR_PDM_MISSING_INTERFACE_BELOW;
525 }
526 PPDMIBASER0 pBaseR0 = PDMIBASE_QUERY_INTERFACE(pBaseDown, PDMIBASER0);
527 pThis->pIBelowNetR0 = pBaseR0 ? pBaseR0->pfnQueryInterface(pBaseR0, PDMINETWORKUP_IID) : NIL_RTR0PTR;
528 }
529 else
530 {
531 AssertMsgFailed(("Failed to attach to driver below! rc=%Rrc\n", rc));
532 return rc;
533 }
534
535 /*
536 * Register statistics.
537 */
538 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pThis->StatXmitBytesRequested, "Bytes/Tx/Requested", STAMUNIT_BYTES, "Number of requested TX bytes.");
539 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pThis->StatXmitBytesDenied, "Bytes/Tx/Denied", STAMUNIT_BYTES, "Number of denied TX bytes.");
540 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pThis->StatXmitBytesGranted, "Bytes/Tx/Granted", STAMUNIT_BYTES, "Number of granted TX bytes.");
541
542 PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPktsRequested, "Packets/Tx/Requested", "Number of requested TX packets.");
543 PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPktsDenied, "Packets/Tx/Denied", "Number of denied TX packets.");
544 PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPktsGranted, "Packets/Tx/Granted", "Number of granted TX packets.");
545 PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPendingCalled, "Tx/WakeUp", "Number of wakeup TX calls.");
546
547 return VINF_SUCCESS;
548}
549
550
551
552/**
553 * Network sniffer filter driver registration record.
554 */
555const PDMDRVREG g_DrvNetShaper =
556{
557 /* u32Version */
558 PDM_DRVREG_VERSION,
559 /* szName */
560 "NetShaper",
561 /* szRCMod */
562 "",
563 /* szR0Mod */
564 "VBoxDDR0.r0",
565 /* pszDescription */
566 "Network Shaper Filter Driver",
567 /* fFlags */
568 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DRVREG_FLAGS_R0,
569 /* fClass. */
570 PDM_DRVREG_CLASS_NETWORK,
571 /* cMaxInstances */
572 UINT32_MAX,
573 /* cbInstance */
574 sizeof(DRVNETSHAPER),
575 /* pfnConstruct */
576 drvR3NetShaperConstruct,
577 /* pfnDestruct */
578 drvR3NetShaperDestruct,
579 /* pfnRelocate */
580 NULL,
581 /* pfnIOCtl */
582 NULL,
583 /* pfnPowerOn */
584 NULL,
585 /* pfnReset */
586 NULL,
587 /* pfnSuspend */
588 NULL,
589 /* pfnResume */
590 NULL,
591 /* pfnAttach */
592 drvR3NetShaperAttach,
593 /* pfnDetach */
594 drvR3NetShaperDetach,
595 /* pfnPowerOff */
596 NULL,
597 /* pfnSoftReset */
598 NULL,
599 /* u32EndVersion */
600 PDM_DRVREG_VERSION
601};
602#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