VirtualBox

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

Last change on this file since 42813 was 42102, checked in by vboxsync, 12 years ago

NetShaper: GSO on RX path (#5582)

  • 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 42102 2012-07-11 10:52:50Z vboxsync $ */
2/** @file
3 * NetShaperFilter - Network shaper filter driver.
4 */
5
6/*
7 * Copyright (C) 2011-2012 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#ifdef IN_RING3
131 if (!PDMR3NsAllocateBandwidth(&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#ifdef IN_RING0
139 if (!PDMR0NsAllocateBandwidth(&pThis->Filter, cbMin))
140 {
141 STAM_REL_COUNTER_ADD(&pThis->StatXmitBytesDenied, cbMin);
142 STAM_REL_COUNTER_INC(&pThis->StatXmitPktsDenied);
143 return VERR_TRY_AGAIN;
144 }
145#endif
146 STAM_REL_COUNTER_ADD(&pThis->StatXmitBytesGranted, cbMin);
147 STAM_REL_COUNTER_INC(&pThis->StatXmitPktsGranted);
148 //LogFlow(("drvNetShaperUp_AllocBuf: got cb=%d\n", cbMin));
149 return pThis->CTX_SUFF(pIBelowNet)->pfnAllocBuf(pThis->CTX_SUFF(pIBelowNet), cbMin, pGso, ppSgBuf);
150}
151
152
153/**
154 * @interface_method_impl{PDMINETWORKUP,pfnFreeBuf}
155 */
156PDMBOTHCBDECL(int) drvNetShaperUp_FreeBuf(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf)
157{
158 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, CTX_SUFF(INetworkUp));
159 if (RT_UNLIKELY(!pThis->CTX_SUFF(pIBelowNet)))
160 return VERR_NET_DOWN;
161 return pThis->CTX_SUFF(pIBelowNet)->pfnFreeBuf(pThis->CTX_SUFF(pIBelowNet), pSgBuf);
162}
163
164
165/**
166 * @interface_method_impl{PDMINETWORKUP,pfnSendBuf}
167 */
168PDMBOTHCBDECL(int) drvNetShaperUp_SendBuf(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread)
169{
170 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, CTX_SUFF(INetworkUp));
171 if (RT_UNLIKELY(!pThis->CTX_SUFF(pIBelowNet)))
172 return VERR_NET_DOWN;
173
174 return pThis->CTX_SUFF(pIBelowNet)->pfnSendBuf(pThis->CTX_SUFF(pIBelowNet), pSgBuf, fOnWorkerThread);
175}
176
177
178/**
179 * @interface_method_impl{PDMINETWORKUP,pfnEndXmit}
180 */
181PDMBOTHCBDECL(void) drvNetShaperUp_EndXmit(PPDMINETWORKUP pInterface)
182{
183 //LogFlow(("drvNetShaperUp_EndXmit:\n"));
184 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, CTX_SUFF(INetworkUp));
185 if (RT_LIKELY(pThis->CTX_SUFF(pIBelowNet)))
186 pThis->CTX_SUFF(pIBelowNet)->pfnEndXmit(pThis->CTX_SUFF(pIBelowNet));
187 else
188 PDMCritSectLeave(&pThis->XmitLock);
189}
190
191
192/**
193 * @interface_method_impl{PDMINETWORKUP,pfnSetPromiscuousMode}
194 */
195PDMBOTHCBDECL(void) drvNetShaperUp_SetPromiscuousMode(PPDMINETWORKUP pInterface, bool fPromiscuous)
196{
197 LogFlow(("drvNetShaperUp_SetPromiscuousMode: fPromiscuous=%d\n", fPromiscuous));
198 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, CTX_SUFF(INetworkUp));
199 if (pThis->CTX_SUFF(pIBelowNet))
200 pThis->CTX_SUFF(pIBelowNet)->pfnSetPromiscuousMode(pThis->CTX_SUFF(pIBelowNet), fPromiscuous);
201}
202
203
204#ifdef IN_RING3
205/**
206 * @interface_method_impl{PDMINETWORKUP,pfnNotifyLinkChanged}
207 */
208static DECLCALLBACK(void) drvR3NetShaperUp_NotifyLinkChanged(PPDMINETWORKUP pInterface, PDMNETWORKLINKSTATE enmLinkState)
209{
210 LogFlow(("drvNetShaperUp_NotifyLinkChanged: enmLinkState=%d\n", enmLinkState));
211 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, CTX_SUFF(INetworkUp));
212 if (pThis->pIBelowNetR3)
213 pThis->pIBelowNetR3->pfnNotifyLinkChanged(pThis->pIBelowNetR3, enmLinkState);
214}
215
216/**
217 * @interface_method_impl{PDMINETWORKDOWN,pfnWaitReceiveAvail}
218 */
219static DECLCALLBACK(int) drvR3NetShaperDown_WaitReceiveAvail(PPDMINETWORKDOWN pInterface, RTMSINTERVAL cMillies)
220{
221 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, INetworkDown);
222 return pThis->pIAboveNet->pfnWaitReceiveAvail(pThis->pIAboveNet, cMillies);
223}
224
225
226/**
227 * @interface_method_impl{PDMINETWORKDOWN,pfnReceive}
228 */
229static DECLCALLBACK(int) drvR3NetShaperDown_Receive(PPDMINETWORKDOWN pInterface, const void *pvBuf, size_t cb)
230{
231 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, INetworkDown);
232 return pThis->pIAboveNet->pfnReceive(pThis->pIAboveNet, pvBuf, cb);
233}
234
235
236/**
237 * @interface_method_impl{PDMINETWORKDOWN,pfnReceiveGso}
238 */
239static DECLCALLBACK(int) drvR3NetShaperDown_ReceiveGso(PPDMINETWORKDOWN pInterface, const void *pvBuf, size_t cb, PCPDMNETWORKGSO pGso)
240{
241 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, INetworkDown);
242 if (pThis->pIAboveNet->pfnReceiveGso)
243 return pThis->pIAboveNet->pfnReceiveGso(pThis->pIAboveNet, pvBuf, cb, pGso);
244 return VERR_NOT_SUPPORTED;
245}
246
247
248/**
249 * @interface_method_impl{PDMINETWORKDOWN,pfnXmitPending}
250 */
251static DECLCALLBACK(void) drvR3NetShaperDown_XmitPending(PPDMINETWORKDOWN pInterface)
252{
253 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, INetworkDown);
254 STAM_REL_COUNTER_INC(&pThis->StatXmitPendingCalled);
255 pThis->pIAboveNet->pfnXmitPending(pThis->pIAboveNet);
256}
257
258
259/**
260 * Gets the current Media Access Control (MAC) address.
261 *
262 * @returns VBox status code.
263 * @param pInterface Pointer to the interface structure containing the called function pointer.
264 * @param pMac Where to store the MAC address.
265 * @thread EMT
266 */
267static DECLCALLBACK(int) drvR3NetShaperDownCfg_GetMac(PPDMINETWORKCONFIG pInterface, PRTMAC pMac)
268{
269 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, INetworkConfig);
270 return pThis->pIAboveConfig->pfnGetMac(pThis->pIAboveConfig, pMac);
271}
272
273/**
274 * Gets the new link state.
275 *
276 * @returns The current link state.
277 * @param pInterface Pointer to the interface structure containing the called function pointer.
278 * @thread EMT
279 */
280static DECLCALLBACK(PDMNETWORKLINKSTATE) drvR3NetShaperDownCfg_GetLinkState(PPDMINETWORKCONFIG pInterface)
281{
282 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, INetworkConfig);
283 return pThis->pIAboveConfig->pfnGetLinkState(pThis->pIAboveConfig);
284}
285
286/**
287 * Sets the new link state.
288 *
289 * @returns VBox status code.
290 * @param pInterface Pointer to the interface structure containing the called function pointer.
291 * @param enmState The new link state
292 * @thread EMT
293 */
294static DECLCALLBACK(int) drvR3NetShaperDownCfg_SetLinkState(PPDMINETWORKCONFIG pInterface, PDMNETWORKLINKSTATE enmState)
295{
296 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, INetworkConfig);
297 return pThis->pIAboveConfig->pfnSetLinkState(pThis->pIAboveConfig, enmState);
298}
299
300
301/**
302 * @interface_method_impl{PDMIBASER0,pfnQueryInterface}
303 */
304static DECLCALLBACK(RTR0PTR) drvR3NetShaperIBaseR0_QueryInterface(PPDMIBASER0 pInterface, const char *pszIID)
305{
306 PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, IBaseR0);
307 PDMIBASER0_RETURN_INTERFACE(pThis->pDrvInsR3, pszIID, PDMINETWORKUP, &pThis->INetworkUpR0);
308 return NIL_RTR0PTR;
309}
310
311/**
312 * @interface_method_impl{PDMIBASERC,pfnQueryInterface}
313 */
314static DECLCALLBACK(RTRCPTR) drvR3NetShaperIBaseRC_QueryInterface(PPDMIBASERC pInterface, const char *pszIID)
315{
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 PDRVNETSHAPER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSHAPER);
342
343 LogFlow(("drvNetShaperDetach: pDrvIns: %p, fFlags: %u\n", pDrvIns, fFlags));
344 PDMCritSectEnter(&pThis->XmitLock, VERR_IGNORED);
345 pThis->pIBelowNetR3 = NULL;
346 pThis->pIBelowNetR0 = NIL_RTR0PTR;
347 PDMCritSectLeave(&pThis->XmitLock);
348}
349
350
351/**
352 * @interface_method_impl{PDMDRVREG,pfnAttach}
353 */
354static DECLCALLBACK(int) drvR3NetShaperAttach(PPDMDRVINS pDrvIns, uint32_t fFlags)
355{
356 PDRVNETSHAPER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSHAPER);
357 LogFlow(("drvNetShaperAttach/#%#x: fFlags=%#x\n", pDrvIns->iInstance, fFlags));
358 PDMCritSectEnter(&pThis->XmitLock, VERR_IGNORED);
359
360 /*
361 * Query the network connector interface.
362 */
363 PPDMIBASE pBaseDown;
364 int rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBaseDown);
365 if ( rc == VERR_PDM_NO_ATTACHED_DRIVER
366 || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME)
367 {
368 pThis->pIBelowNetR3 = NULL;
369 pThis->pIBelowNetR0 = NIL_RTR0PTR;
370 rc = VINF_SUCCESS;
371 }
372 else if (RT_SUCCESS(rc))
373 {
374 pThis->pIBelowNetR3 = PDMIBASE_QUERY_INTERFACE(pBaseDown, PDMINETWORKUP);
375 if (pThis->pIBelowNetR3)
376 {
377 PPDMIBASER0 pBaseR0 = PDMIBASE_QUERY_INTERFACE(pBaseDown, PDMIBASER0);
378 pThis->pIBelowNetR0 = pBaseR0 ? pBaseR0->pfnQueryInterface(pBaseR0, PDMINETWORKUP_IID) : NIL_RTR0PTR;
379 rc = VINF_SUCCESS;
380 }
381 else
382 {
383 AssertMsgFailed(("Configuration error: the driver below didn't export the network connector interface!\n"));
384 rc = VERR_PDM_MISSING_INTERFACE_BELOW;
385 }
386 }
387 else
388 AssertMsgFailed(("Failed to attach to driver below! rc=%Rrc\n", rc));
389
390 PDMCritSectLeave(&pThis->XmitLock);
391 return VINF_SUCCESS;
392}
393
394
395/**
396 * @interface_method_impl{PDMDRVREG,pfnDestruct}
397 */
398static DECLCALLBACK(void) drvR3NetShaperDestruct(PPDMDRVINS pDrvIns)
399{
400 PDRVNETSHAPER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSHAPER);
401 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
402
403 PDMDrvHlpNetShaperDetach(pDrvIns, &pThis->Filter);
404
405 if (PDMCritSectIsInitialized(&pThis->XmitLock))
406 PDMR3CritSectDelete(&pThis->XmitLock);
407}
408
409
410/**
411 * @interface_method_impl{Construct a NAT network transport driver instance,
412 * PDMDRVREG,pfnDestruct}
413 */
414static DECLCALLBACK(int) drvR3NetShaperConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
415{
416 PDRVNETSHAPER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSHAPER);
417 LogFlow(("drvNetShaperConstruct:\n"));
418 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
419
420 /*
421 * Init the static parts.
422 */
423 pThis->pDrvInsR3 = pDrvIns;
424 pThis->pDrvInsR0 = PDMDRVINS_2_R0PTR(pDrvIns);
425 /* IBase */
426 pDrvIns->IBase.pfnQueryInterface = drvR3NetShaperIBase_QueryInterface;
427 pThis->IBaseR0.pfnQueryInterface = drvR3NetShaperIBaseR0_QueryInterface;
428 pThis->IBaseRC.pfnQueryInterface = drvR3NetShaperIBaseRC_QueryInterface;
429 /* INetworkUp */
430 pThis->INetworkUpR3.pfnBeginXmit = drvNetShaperUp_BeginXmit;
431 pThis->INetworkUpR3.pfnAllocBuf = drvNetShaperUp_AllocBuf;
432 pThis->INetworkUpR3.pfnFreeBuf = drvNetShaperUp_FreeBuf;
433 pThis->INetworkUpR3.pfnSendBuf = drvNetShaperUp_SendBuf;
434 pThis->INetworkUpR3.pfnEndXmit = drvNetShaperUp_EndXmit;
435 pThis->INetworkUpR3.pfnSetPromiscuousMode = drvNetShaperUp_SetPromiscuousMode;
436 pThis->INetworkUpR3.pfnNotifyLinkChanged = drvR3NetShaperUp_NotifyLinkChanged;
437 /*
438 * Resolve the ring-0 context interface addresses.
439 */
440 int rc = pDrvIns->pHlpR3->pfnLdrGetR0InterfaceSymbols(pDrvIns, &pThis->INetworkUpR0,
441 sizeof(pThis->INetworkUpR0),
442 "drvNetShaperUp_", PDMINETWORKUP_SYM_LIST);
443 AssertLogRelRCReturn(rc, rc);
444 /* INetworkDown */
445 pThis->INetworkDown.pfnWaitReceiveAvail = drvR3NetShaperDown_WaitReceiveAvail;
446 pThis->INetworkDown.pfnReceive = drvR3NetShaperDown_Receive;
447 pThis->INetworkDown.pfnReceiveGso = drvR3NetShaperDown_ReceiveGso;
448 pThis->INetworkDown.pfnXmitPending = drvR3NetShaperDown_XmitPending;
449 /* INetworkConfig */
450 pThis->INetworkConfig.pfnGetMac = drvR3NetShaperDownCfg_GetMac;
451 pThis->INetworkConfig.pfnGetLinkState = drvR3NetShaperDownCfg_GetLinkState;
452 pThis->INetworkConfig.pfnSetLinkState = drvR3NetShaperDownCfg_SetLinkState;
453
454 /*
455 * Create the locks.
456 */
457 rc = PDMDrvHlpCritSectInit(pDrvIns, &pThis->XmitLock, RT_SRC_POS, "NetShaper");
458 AssertRCReturn(rc, rc);
459
460 /*
461 * Validate the config.
462 */
463 if (!CFGMR3AreValuesValid(pCfg, "BwGroup\0"))
464 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
465
466 /*
467 * Find the bandwidth group we have to attach to.
468 */
469 rc = CFGMR3QueryStringAlloc(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.pIDrvNet = &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