VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use