NDIS Protocol driver not getting ProtocolReceiveNetBufferLists function called

The underlying driver calls NdisMIndicateReceiveNetBufferLists to indicate receive data to NDIS. I’m expecting NDIS to call my protocol driver’s ProtocolReceiveNetBufferLists function when data is received. This does happen if I open the interface in Wireshark and start a capture. As soon as I stop the capture my ProtocolReceiveNetBufferLists is no longer called.

Any ideas?

It’s likely that the protocol hasn’t sent down OID_GEN_CURRENT_PACKET_FILTER with the flags for the packet types that you want.

Protocols express their interest in a particular type of packet by sending the OID. By default, protocols get nothing.

Note that this is a performance optimization only, not a correctness thing. So NDIS does not guarantee minimal packet filtering: NDIS permits itself to give you more packets than you asked for.

Corollary: if your protocol driver has opinions about the EtherType or destination MAC address, you need to double-check them yourself. Don’t rely on NDIS to do it.

One curious consequence of the way that NDIS implements its performance optimizations combined with the way that Wireshark’s NPF driver infests itself into the stack is that all other protocols start getting all other traffic as soon as Wireshark starts. (This should make you nervous: a diagnostic tool shouldn’t visibly change the behavior of the system, lest you risk Heisenbugs.)

Anyway, send the OID and the receive path should start flowing. And consider routinely testing both with and without wireshark installed, since it obviously has some interactions with other drivers.

Very good info to know. I went back and tried the sample protocol driver from GitHub and am observing the same behavior.

I think it’s doing what you’re recommending as part of the IOCTL_NDISPROT_OPEN_DEVICE call chain:

NdisOidRequest
ndisprotDoRequest
ndisprotValidateOpenAndDoRequest <-- sets the packet filter to NDIS_PACKET_TYPE_DIRECTED|MULTICAST|BROADCAST
ndisprotOpenDevice
NdisProtEvtIoDeviceControl

Any other thoughts?

Another thing that could go wrong: If you’re on Ethernet media type, your protocol will provide a list of the EtherTypes that it wants. If you provide an empty list, then NDIS assumes you want all EtherTypes. Otherwise, if you put some value in there, NDIS will generally try to limit traffic to just the EtherType you asked for.

Double-check that the packet filter got set with !ndiskd.mopen. After the OID succeeds, you should see the Receive path has a Packet filter that allows whatever flags you asked for (presumably at least DIRECTED packets).

Example:

kd> !ndiskd.mopen ffff8a0288a50bf0

RECEIVE PATH

    Packet filter      DIRECTED, MULTICAST, BROADCAST
    Frame Type(s)      0x0800, 0x0806
    Multicast address list 01-00-5e-00-00-01
                       01-00-5e-7f-ff-fa
                       01-00-5e-00-00-fb
                       01-00-5e-00-00-fc

In that example, a protocol has asked for EtherTypes 0x0800 and 0806. It has asked to receive packets to the unicast address (aka DIRECTED), to the broadcast address, and to 4 different multicast addresses. NDIS will deliver inbound packets that match both the destination address and the ethertype. Any other packets might get delivered accidentally, but no effort is made.

Here’s what I got after the OID succeeds. Prior to sending the OID the packet filter is [No flags set], so that makes me think at least packet filter request is working.

kd> !ndiskd.mopen ffff8d05666e8c00

RECEIVE PATH
    Packet filter      DIRECTED, MULTICAST, BROADCAST
    Frame Type(s)      0x888e, 0x8100
    Multicast address list [This protocol has not added any multicast addresses]

You mentioned the protocol asking for specific EtherTypes. How is that done? I’m trying to match 0xF788 ethType.
Still not sure why NDIS is only delivering NBLs when Wireshark is open.

The parameter to NdisOpenAdapterEx takes NDIS_OPEN_PARAMETERS::FrameTypeArray. Evidently you have EtherTypes 0x888e and 0x8100 in it now. If you want 0xf788, make sure that’s in the list.

Still not sure why NDIS is only delivering NBLs when Wireshark is open.

All this is a performance optimization. Wireshark defeats the performance optimization, so NDIS floods packets to all protocols, regardless of what filters they had set up.