How to drop a Network Buffer from a NBL

In a LWF how do I drop a packet from an NBL received from another layer?

My thought is that I create a clone of the NBL using NdisAllocateCloneNetBufferList with NDIS_CLONE_FLAGS_USE_ORIGINAL_MDLS.

Then I walk the new NBL as follows:

while (pCurrentBufferList)
{
PNET_BUFFER* ppCurrentBuffer = &NET_BUFFER_LIST_FIRST_NB(pCurrentBufferList);
PNET_BUFFER pCurrentBuffer = NET_BUFFER_LIST_FIRST_NB(pCurrentBufferList);

while (pCurrentBuffer)
{
if (DiscardThisBuffer(pCurrentBuffer))
{
// Link around this bbuffer
*ppCurrentBuffer = NET_BUFFER_NEXT_NB(pCurrentBuffer);
// Is the next line legal???
NdisFreeNetBuffer(pCurrentBuffer);
pCurrentBuffer = *ppCurrentBuffer;
}
else
{
pCurrentBuffer = NET_BUFFER_NEXT_NB(pCurrentBuffer);
}
}
}
pCurrentBufferList = NET_BUFFER_LIST_NEXT_NBL(pCurrentBufferList);

When the upper layer returns the NBL I free it with NdisFreeCloneNetBufferList.

My question is: Is it legal to delete the Network Buffer in the above code or do I have to restore the original NBL chain prior to calling NdisFreeCloneNetBufferList?

Your basic approach of creating a clone NBL is right.

In my Impairment Generator Sample:

http://pcausa.com/filters/impairmentgen/default.htm

I don’t free the dropped clone NB explicitly. Instead, when I create the
clone NBL I also create a companion Context area. In the Context area I
build an array of all of the clone NBs. Then I drop desired clone NBs by
unlinking as you are doing. (Remember to handle three cases when unlinking:
NB at head, NB at tail or NB in middle of slist).

When the send completes I use this array to reconstruct the clone NBL
exactly as it was originally allocated from the array stored in the Context
area. This reconstruction will put the dropped NB back in the list before
calling NdisFreeCloneNetBufferList.

FWIW. This worked for me.

Thomas F. Divine
http://www.pcausa.com


From:
Sent: Friday, October 22, 2010 8:54 AM
To: “Windows System Software Devs Interest List”
Subject: [ntdev] How to drop a Network Buffer from a NBL

> In a LWF how do I drop a packet from an NBL received from another layer?
>
> My thought is that I create a clone of the NBL using
> NdisAllocateCloneNetBufferList with NDIS_CLONE_FLAGS_USE_ORIGINAL_MDLS.
>
> Then I walk the new NBL as follows:
>
> while (pCurrentBufferList)
> {
> PNET_BUFFER* ppCurrentBuffer =
> &NET_BUFFER_LIST_FIRST_NB(pCurrentBufferList);
> PNET_BUFFER pCurrentBuffer = NET_BUFFER_LIST_FIRST_NB(pCurrentBufferList);
>
> while (pCurrentBuffer)
> {
> if (DiscardThisBuffer(pCurrentBuffer))
> {
> // Link around this bbuffer
> *ppCurrentBuffer = NET_BUFFER_NEXT_NB(pCurrentBuffer);
> // Is the next line legal???
> NdisFreeNetBuffer(pCurrentBuffer);
> pCurrentBuffer = *ppCurrentBuffer;
> }
> else
> {
> pCurrentBuffer = NET_BUFFER_NEXT_NB(pCurrentBuffer);
> }
> }
> }
> pCurrentBufferList = NET_BUFFER_LIST_NEXT_NBL(pCurrentBufferList);
>
> When the upper layer returns the NBL I free it with
> NdisFreeCloneNetBufferList.
>
> My question is: Is it legal to delete the Network Buffer in the above code
> or do I have to restore the original NBL chain prior to calling
> NdisFreeCloneNetBufferList?
>
>
>
> —
> 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

Thanks Thomas, that sounds like even more overhead.
What if I allocate a new empty NBL and then add the NB’s that are to be passed up. On return I would only have to delete the NBL and signal the original NBL down - sounds too simple - lol.

Might work and be simpler. Let me know!

Thomas


From:
Sent: Friday, October 22, 2010 9:52 AM
To: “Windows System Software Devs Interest List”
Subject: RE:[ntdev] How to drop a Network Buffer from a NBL

> Thanks Thomas, that sounds like even more overhead.
> What if I allocate a new empty NBL and then add the NB’s that are to be
> passed up. On return I would only have to delete the NBL and signal the
> original NBL down - sounds too simple - lol.
>
>
> —
> 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

Thomas’ approach is within the NBL rules.

Yours portentially violates a very important one: You must ‘return’ (or
free) and NBL exactly as you received it.

If you scheme were to include the statement that when the ‘indicated up’ NBL
is returned to your layer, you then remove the NBs from it and put them back
in the original NBL indicated to you to return them, well, that would be
equivalent to Thomas’ approach except you have an extra NBL and he tucked
the restoration context into the clone.

Although I admit your description leaves open to interpretation exactly what
you mean by “… then add the NB’s …”.

If you mean ‘move’ the NBs to the new NBL then you have to put them back as
I noted. If you mean something else, well, what is it?

Good Luck,
Dave Cattley

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@spherecom.com
Sent: Friday, October 22, 2010 9:53 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] How to drop a Network Buffer from a NBL

Thanks Thomas, that sounds like even more overhead.
What if I allocate a new empty NBL and then add the NB’s that are to be
passed up. On return I would only have to delete the NBL and signal the
original NBL down - sounds too simple - lol.


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

Hi Dave,
I was suggesting that I could use NdisAllocateNetBufferAndNetBufferList() to create an empty NBL then iterate over the original NBL copying the pointers to the NB’s that are to be sent up

When the NBL is returned I would reset all the NB pointers back to NULL and call NdisFreeNetBufferList() then send the original NBL back to the driver as usual.

Am I missing something?

Alan

I am not sure I know what you mean by ‘copy the pointer over’ but so long as
you return what you get, you are fine.

If you know which NBs you wish to omit, you can remove them from the
indicated NBL before cloning it, I suppose, then put them back immediately
after the clone operation. The original NBL will be ‘as indicated’ the
clone NBL will have only the NBs (clones of them actually) you wish to
indicate. I think that is legal. But for sure, Thomas’ approach works
because I know he has tested it!

Good Luck,
Dave Cattley

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@spherecom.com
Sent: Friday, October 22, 2010 12:39 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] How to drop a Network Buffer from a NBL

Hi Dave,
I was suggesting that I could use NdisAllocateNetBufferAndNetBufferList() to
create an empty NBL then iterate over the original NBL copying the pointers
to the NB’s that are to be sent up

When the NBL is returned I would reset all the NB pointers back to NULL and
call NdisFreeNetBufferList() then send the original NBL back to the driver
as usual.

Am I missing something?

Alan


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

One note: if you are operating on the receive path (which I inferred from the phrases “a packet from an NBL received …” and “the NB’s that are to be sent up”), and if you are located just underneath TCPIP, then you don’t need to worry about more than one NB per NBL.

The recently-clarified verbiage on http://msdn.microsoft.com/en-us/library/ff554851(VS.85).aspx is illuminating:

“The typical Ethernet miniport must assign exactly one NET_BUFFER structure to a NET_BUFFER_LIST structure when receiving data. This restriction applies only to the Ethernet receive path; it’s not applicable to Native Wifi or NDIS in general.”

If you meet these conditions, then that should rather greatly simplify your algorithm, since 1 NET_BUFFER is always easier to handle than n NET_BUFFERs!

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of David R. Cattley
Sent: Friday, October 22, 2010 10:08 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] How to drop a Network Buffer from a NBL

I am not sure I know what you mean by ‘copy the pointer over’ but so long as you return what you get, you are fine.

If you know which NBs you wish to omit, you can remove them from the indicated NBL before cloning it, I suppose, then put them back immediately
after the clone operation. The original NBL will be ‘as indicated’ the
clone NBL will have only the NBs (clones of them actually) you wish to
indicate. I think that is legal. But for sure, Thomas’ approach works
because I know he has tested it!

Good Luck,
Dave Cattley

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@spherecom.com
Sent: Friday, October 22, 2010 12:39 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] How to drop a Network Buffer from a NBL

Hi Dave,
I was suggesting that I could use NdisAllocateNetBufferAndNetBufferList() to create an empty NBL then iterate over the original NBL copying the pointers to the NB’s that are to be sent up

When the NBL is returned I would reset all the NB pointers back to NULL and call NdisFreeNetBufferList() then send the original NBL back to the driver as usual.

Am I missing something?

Alan


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


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

Hello Jeffrey,
My testing so far has confirmed that I only receive a one NET_BUUFER but I’m concerned about the word typical in the phrase "“The typical Ethernet miniport must assign exactly one NET_BUFFER…”
Can I interpret this to mean that I may come across a vendor in the field that considers itself atypical and ignores this rule?

I am also looking for a packet being sent down from the TCP layer, this packet will be UDP and have a pseudo destination address of 1.0.0.0. From the companion article at http://msdn.microsoft.com/en-us/library/ff570756(v=VS.85).aspx which states:
“All NET_BUFFER structures that are associated with a NET_BUFFER_LIST structure must have the same Ethernet frame type and IP protocol version”, “the same source and destination MAC addresses”, and “same TCP or UDP connection” Can I assume that this NET_BUFFER will also be a singleton even when sandwiched between similar packets with differing port addresses?

Alan

Hope to hear from Jeffrey as well.

However, as I understand it for 802.3 each receive NBL must contain exactly
one NB. The only exception that I am aware of is for native 802.11 packets,
but Microsoft has gone to great pains to restrict bindings at that level
(below the MS Native Wi-Fi LWF); you probably won’t see native 802.11
packets unless you are a monitoring LWF selecting the wlan FilterMediaTypes.

On the send side from my experience when you see a NBL with multiple NBs the
NB is sending a datagram that has been fragmented. The NBs are the fragments
and are being sent to the same remote address and port using the same
protocol. If this is wrong I hope Jeffrey will correct it.

On the send side if you want to drop one NB out of a NBL then you can do so
by “simply” unlinking it from the NBL temporarily. The only caveat is that
you must reconstruct it (re-insert the dropped NB into the original NBL) in
your send completion routine before returning the NBL to it’s owner. To do
this you must allocate some sort of context that keeps track of the dropped
NB and its position so you can replace it in your send completion. You
cannot just free the NB that you are dropping.

Good luck,

Thomas F. Divine
See Also: http://pcausa.com/filters/impairmentgen/default.htm


From:
Sent: Wednesday, November 03, 2010 9:07 AM
To: “Windows System Software Devs Interest List”
Subject: RE:[ntdev] How to drop a Network Buffer from a NBL

> Hello Jeffrey,
> My testing so far has confirmed that I only receive a one NET_BUUFER but
> I’m concerned about the word typical in the phrase "“The typical Ethernet
> miniport must assign exactly one NET_BUFFER…”
> Can I interpret this to mean that I may come across a vendor in the field
> that considers itself atypical and ignores this rule?
>
> I am also looking for a packet being sent down from the TCP layer, this
> packet will be UDP and have a pseudo destination address of 1.0.0.0. From
> the companion article at
> http://msdn.microsoft.com/en-us/library/ff570756(v=VS.85).aspx which
> states:
> “All NET_BUFFER structures that are associated with a NET_BUFFER_LIST
> structure must have the same Ethernet frame type and IP protocol version”,
> “the same source and destination MAC addresses”, and “same TCP or UDP
> connection” Can I assume that this NET_BUFFER will also be a singleton
> even when sandwiched between similar packets with differing port
> addresses?
>
> Alan
>
>
> —
> 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

Hi Thomas,

In my case this driver will only be ever used with a wired NIC so I won’t encounter 802.11 packets.

On the send side the UDP packets of interest will always be a maximum of 696 bytes so will be encapsulated in one ethernet frame and from the MS doc -
“Each NET_BUFFER structure that is linked to a NET_BUFFER_LIST structure describes a single Ethernet frame.”
This would lead me to believe that the NBL can only contain my packet of interest - so I can copy the payload to a new NB/NBL, redirect it and return the original NBL to the TCP stack.

[Alan] > Can I interpret this to mean that I may come across a vendor in the field that considers itself atypical and ignores this rule?

Haha, I like the way you think. I can’t promise that no such miniport exists, but I *can* promise that TCPIP fires an ASSERT on chk builds if anyone ever hands it an NBL with >1 NBs attached to it. So I think it’s safe enough to accept the rule as granted. If you want to code defensively, you can reject such packets (return them to the miniport immediately) and/or code up your own ASSERT.

[Thomas] > If this is wrong I hope Jeffrey will correct it.

No correction is required.

[Alan] > In my case this driver will only be ever used with a wired NIC so I won’t encounter 802.11 packets.

You can actually give a stronger guarantee for free – if you’re above NWIFI.SYS (which you will be unless you specifically try hard to not be), then even 802.11 packets “look like” Ethernet. So your driver will also work on top of an 802.11 miniport.

[Alan] > This would lead me to believe that the NBL can only contain my packet of interest

Yes, the NBL can contain only equivalent UDP packet(s). The NBL only contains packet(s) belonging to the same UDP 4-tuple (src-IP, dest-IP, src-port, dest-port). I can’t promise that there will not be more than one UDP packet in the NBL, however.

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@spherecom.com
Sent: Wednesday, November 03, 2010 8:11 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] How to drop a Network Buffer from a NBL

Hi Thomas,

In my case this driver will only be ever used with a wired NIC so I won’t encounter 802.11 packets.

On the send side the UDP packets of interest will always be a maximum of 696 bytes so will be encapsulated in one ethernet frame and from the MS doc - “Each NET_BUFFER structure that is linked to a NET_BUFFER_LIST structure describes a single Ethernet frame.”
This would lead me to believe that the NBL can only contain my packet of interest - so I can copy the payload to a new NB/NBL, redirect it and return the original NBL to the TCP stack.


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

Thanks Jeffrey,
That have given me good insight into the NBL’s and their use.
In my case if there are more than one NB/NBL then given their 4 tuples are identical then I will be copying each and still dropping the entire NBL so the code is simpler.

Talking of which - until this optimization I was having a hard time understanding why MS claimed that writing a LWF was easier than an IM driver :slight_smile:

Alan