VirtualBox

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

Last change on this file since 93115 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.0 KB
Line 
1/* $Id: DrvNetShaper.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * NetShaperFilter - Network shaper filter driver.
4 */
5
6/*
7 * Copyright (C) 2011-2022 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 = PDMDrvHlpCritSectTryEnter(pThis->CTX_SUFF(pDrvIns), &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 (!PDMDrvHlpNetShaperAllocateBandwidth(pThis->CTX_SUFF(pDrvIns), &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 PDMDrvHlpCritSectLeave(pThis->CTX_SUFF(pDrvIns), &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 PDMDrvHlpCritSectEnter(pDrvIns, &pThis->XmitLock, VERR_IGNORED);
346 pThis->pIBelowNetR3 = NULL;
347 pThis->pIBelowNetR0 = NIL_RTR0PTR;
348 PDMDrvHlpCritSectLeave(pDrvIns, &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 PDMDrvHlpCritSectEnter(pDrvIns, &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 PDMDrvHlpCritSectLeave(pDrvIns, &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 (PDMDrvHlpCritSectIsInitialized(pDrvIns, &pThis->XmitLock))
407 PDMDrvHlpCritSectDelete(pDrvIns, &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 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
418 PDRVNETSHAPER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSHAPER);
419 PCPDMDRVHLPR3 pHlp = pDrvIns->pHlpR3;
420
421 LogFlow(("drvNetShaperConstruct:\n"));
422
423 /*
424 * Init the static parts.
425 */
426 pThis->pDrvInsR3 = pDrvIns;
427 pThis->pDrvInsR0 = PDMDRVINS_2_R0PTR(pDrvIns);
428 /* IBase */
429 pDrvIns->IBase.pfnQueryInterface = drvR3NetShaperIBase_QueryInterface;
430 pThis->IBaseR0.pfnQueryInterface = drvR3NetShaperIBaseR0_QueryInterface;
431 pThis->IBaseRC.pfnQueryInterface = drvR3NetShaperIBaseRC_QueryInterface;
432 /* INetworkUp */
433 pThis->INetworkUpR3.pfnBeginXmit = drvNetShaperUp_BeginXmit;
434 pThis->INetworkUpR3.pfnAllocBuf = drvNetShaperUp_AllocBuf;
435 pThis->INetworkUpR3.pfnFreeBuf = drvNetShaperUp_FreeBuf;
436 pThis->INetworkUpR3.pfnSendBuf = drvNetShaperUp_SendBuf;
437 pThis->INetworkUpR3.pfnEndXmit = drvNetShaperUp_EndXmit;
438 pThis->INetworkUpR3.pfnSetPromiscuousMode = drvNetShaperUp_SetPromiscuousMode;
439 pThis->INetworkUpR3.pfnNotifyLinkChanged = drvR3NetShaperUp_NotifyLinkChanged;
440 /* Resolve the ring-0 context interface addresses. */
441 int rc = pDrvIns->pHlpR3->pfnLdrGetR0InterfaceSymbols(pDrvIns, &pThis->INetworkUpR0,
442 sizeof(pThis->INetworkUpR0),
443 "drvNetShaperUp_", PDMINETWORKUP_SYM_LIST);
444 AssertLogRelRCReturn(rc, rc);
445 /* INetworkDown */
446 pThis->INetworkDown.pfnWaitReceiveAvail = drvR3NetShaperDown_WaitReceiveAvail;
447 pThis->INetworkDown.pfnReceive = drvR3NetShaperDown_Receive;
448 pThis->INetworkDown.pfnReceiveGso = drvR3NetShaperDown_ReceiveGso;
449 pThis->INetworkDown.pfnXmitPending = drvR3NetShaperDown_XmitPending;
450 /* INetworkConfig */
451 pThis->INetworkConfig.pfnGetMac = drvR3NetShaperDownCfg_GetMac;
452 pThis->INetworkConfig.pfnGetLinkState = drvR3NetShaperDownCfg_GetLinkState;
453 pThis->INetworkConfig.pfnSetLinkState = drvR3NetShaperDownCfg_SetLinkState;
454
455 /*
456 * Create the locks.
457 */
458 rc = PDMDrvHlpCritSectInit(pDrvIns, &pThis->XmitLock, RT_SRC_POS, "NetShaper");
459 AssertRCReturn(rc, rc);
460
461 /*
462 * Validate the config.
463 */
464 PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, "BwGroup", "");
465
466 /*
467 * Find the bandwidth group we have to attach to.
468 */
469 rc = pHlp->pfnCFGMQueryStringAlloc(pCfg, "BwGroup", &pThis->pszBwGroup);
470 if (RT_FAILURE(rc) && rc != VERR_CFGM_VALUE_NOT_FOUND)
471 {
472 rc = PDMDRV_SET_ERROR(pDrvIns, rc,
473 N_("DrvNetShaper: Configuration error: Querying \"BwGroup\" as string failed"));
474 return rc;
475 }
476 else
477 rc = VINF_SUCCESS;
478
479 pThis->Filter.pIDrvNetR3 = &pThis->INetworkDown;
480 rc = PDMDrvHlpNetShaperAttach(pDrvIns, pThis->pszBwGroup, &pThis->Filter);
481 if (RT_FAILURE(rc))
482 {
483 rc = PDMDRV_SET_ERROR(pDrvIns, rc,
484 N_("DrvNetShaper: Configuration error: Failed to attach to bandwidth group"));
485 return rc;
486 }
487
488 /*
489 * Query the network port interface.
490 */
491 pThis->pIAboveNet = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMINETWORKDOWN);
492 if (!pThis->pIAboveNet)
493 {
494 AssertMsgFailed(("Configuration error: the above device/driver didn't export the network port interface!\n"));
495 return VERR_PDM_MISSING_INTERFACE_ABOVE;
496 }
497
498 /*
499 * Query the network config interface.
500 */
501 pThis->pIAboveConfig = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMINETWORKCONFIG);
502 if (!pThis->pIAboveConfig)
503 {
504 AssertMsgFailed(("Configuration error: the above device/driver didn't export the network config interface!\n"));
505 return VERR_PDM_MISSING_INTERFACE_ABOVE;
506 }
507
508 /*
509 * Query the network connector interface.
510 */
511 PPDMIBASE pBaseDown;
512 rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBaseDown);
513 if ( rc == VERR_PDM_NO_ATTACHED_DRIVER
514 || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME)
515 {
516 pThis->pIBelowNetR3 = NULL;
517 pThis->pIBelowNetR0 = NIL_RTR0PTR;
518 }
519 else if (RT_SUCCESS(rc))
520 {
521 pThis->pIBelowNetR3 = PDMIBASE_QUERY_INTERFACE(pBaseDown, PDMINETWORKUP);
522 if (!pThis->pIBelowNetR3)
523 {
524 AssertMsgFailed(("Configuration error: the driver below didn't export the network connector interface!\n"));
525 return VERR_PDM_MISSING_INTERFACE_BELOW;
526 }
527 PPDMIBASER0 pBaseR0 = PDMIBASE_QUERY_INTERFACE(pBaseDown, PDMIBASER0);
528 pThis->pIBelowNetR0 = pBaseR0 ? pBaseR0->pfnQueryInterface(pBaseR0, PDMINETWORKUP_IID) : NIL_RTR0PTR;
529 }
530 else
531 {
532 AssertMsgFailed(("Failed to attach to driver below! rc=%Rrc\n", rc));
533 return rc;
534 }
535
536 /*
537 * Register statistics.
538 */
539 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pThis->StatXmitBytesRequested, "Bytes/Tx/Requested", STAMUNIT_BYTES, "Number of requested TX bytes.");
540 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pThis->StatXmitBytesDenied, "Bytes/Tx/Denied", STAMUNIT_BYTES, "Number of denied TX bytes.");
541 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pThis->StatXmitBytesGranted, "Bytes/Tx/Granted", STAMUNIT_BYTES, "Number of granted TX bytes.");
542
543 PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPktsRequested, "Packets/Tx/Requested", "Number of requested TX packets.");
544 PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPktsDenied, "Packets/Tx/Denied", "Number of denied TX packets.");
545 PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPktsGranted, "Packets/Tx/Granted", "Number of granted TX packets.");
546 PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPendingCalled, "Tx/WakeUp", "Number of wakeup TX calls.");
547
548 return VINF_SUCCESS;
549}
550
551
552
553/**
554 * Network sniffer filter driver registration record.
555 */
556const PDMDRVREG g_DrvNetShaper =
557{
558 /* u32Version */
559 PDM_DRVREG_VERSION,
560 /* szName */
561 "NetShaper",
562 /* szRCMod */
563 "",
564 /* szR0Mod */
565 "VBoxDDR0.r0",
566 /* pszDescription */
567 "Network Shaper Filter Driver",
568 /* fFlags */
569 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DRVREG_FLAGS_R0,
570 /* fClass. */
571 PDM_DRVREG_CLASS_NETWORK,
572 /* cMaxInstances */
573 UINT32_MAX,
574 /* cbInstance */
575 sizeof(DRVNETSHAPER),
576 /* pfnConstruct */
577 drvR3NetShaperConstruct,
578 /* pfnDestruct */
579 drvR3NetShaperDestruct,
580 /* pfnRelocate */
581 NULL,
582 /* pfnIOCtl */
583 NULL,
584 /* pfnPowerOn */
585 NULL,
586 /* pfnReset */
587 NULL,
588 /* pfnSuspend */
589 NULL,
590 /* pfnResume */
591 NULL,
592 /* pfnAttach */
593 drvR3NetShaperAttach,
594 /* pfnDetach */
595 drvR3NetShaperDetach,
596 /* pfnPowerOff */
597 NULL,
598 /* pfnSoftReset */
599 NULL,
600 /* u32EndVersion */
601 PDM_DRVREG_VERSION
602};
603#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