NDIS essentially keeps a lookaside list of recently-free’d NBLs, for perf reasons. At the moment NDIS hands an NBL to you (NdisAllocateNetBufferList, NdisAllocateNetBufferAndNetBufferList, or NdisAllocateCloneNetBufferList), NDIS adds the internal-only, undocumented flag NBL_FLAGS_ALLOCATED to the NBL. Then, when you return the NBL back to NDIS (NdisFreeNetBufferList or NdisFreeCloneNetBufferList), NDIS will strip the flag. (At that point, NDIS may cache the NBL internally for reuse, or it may free the NBL back to the kernel’s pool.)
As you’ve noticed, there is an ASSERT that checks that the NBL has the ALLOCATED flag set when the NBL is free’d. If the flag is not set, then one of several things has gone wrong:
- You are double-free’ing an NBL, or possibly freeing a garbage pointer that was never an NBL.
- Somebody else was rude enough to free your RX NBL back to NDIS. (This seems unlikely, but you can check by seeing if this repros when there is no 3rd party filter driver or protocol on your miniport’s stack.)
- Somebody has cleared the flag from the NBL’s Flags field. (Not related to the confusingly similarly-named NblFlags field!) Note that the bits in Flags are subdivided by owner – the bits masked by NBL_FLAGS_NDIS_RESERVED shouldn’t be touched by you or any other driver. If you are touching the Flags field (either directly or through NBL_CLEAR_FLAG), ensure you aren’t meddling with any of the flags reserved for NDIS. In particular, it is always a bug to say Nbl->Flags = 0;.
- Somebody is over-zealously zeroing the NBL structure. This also seems unlikely, since NDIS tends to get upset if NdisPoolHandle or SourceHandle is cleared, but stranger things have happened.
If this is a 100% repro problem, then you can solve it quite easily with a break-on-write data breakpoint. Allocate the NBL, then set a “ba w2” on the least-significant word of the Flags field. (This overlaps with the NBL_FLAGS_MINIPORT_RESERVED area, so you will have to ignore some false positives if your miniport uses those bits). Then just let the debugger show you the exact root cause of the bug. (I love data breakpoints).
I allocate an RX NBL pool at init and for perf reasons, I pre-allocate all the required RX NBLs and keep them on a private list. Whenever I need to indicate an RX packet, I get one NBL from this list and put it back on the list after that NBL is returned to me.
During unload, I remove every NBL from this list and explicitly return it to the Pool by calling NdisFreeNetBufferList().
This is normal, and in fact, the most common thing for physical miniports to do. This design is not the problem.
Needless to say, saving the virgin NBL->Flags value and restoring it for every recyled RX NBL avoids the ASSERT.
Needless to say, this is the wrong thing to do. Find the real bug and do not try to hide the problem. Otherwise you will face an even more difficult-to-diagnose problem later.
-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@live.com
Sent: Wednesday, December 01, 2010 4:32 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] NBL_TEST_FLAG ASSERT in checked NDIS.SYS
Hello All
When using the checked version of NDIS.SYS, I am running into the following ASSERT when I try to explicitly free the NBLs from my RX Pool:
*** Assertion failed: NBL_TEST_FLAG(NetBufferList, NBL_FLAGS_ALLOCATED)
*** Source File: d:\w7rtm\minio\ndis\sys\ndisbuf.c, line 895
Background:
I allocate an RX NBL pool at init and for perf reasons, I pre-allocate all the required RX NBLs and keep them on a private list. Whenever I need to indicate an RX packet, I get one NBL from this list and put it back on the list after that NBL is returned to me.
During unload, I remove every NBL from this list and explicitly return it to the Pool by calling NdisFreeNetBufferList(). The strange thing is that this call works fine for an NBL that is *yet* to be used but causes the above ASSERT for any NBL that has been used to indicate an RX packet (due to an apparently invalid value for the NBL->Flags member).
Needless to say, saving the virgin NBL->Flags value and restoring it for every recyled RX NBL avoids the ASSERT.
Maybe I missed it, but the WDK 7.1 samples do not seem to be doing this nor is this requirement documented anywhere.
What am I doing wrong?
NTDEV is sponsored by OSR
For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars
To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer