Setting the OpenParameters.FrameTypeArray to NULL is not ideal, since that can put the miniport stack into a low performance mode. Setting the array to NULL means that you want all EtherTypes to be delivered to your protocol.
If there is any other protocol driver on the NIC, then that puts NDIS into an awkward position: the other protocol wants some packets, and you want all packets. When NDIS sees two protocols that overlap on their EtherTypes, NDIS doesn’t try to efficiently sort the NBLs by EtherType anymore; it just gives all NBLs to all protocols with the NDIS_RECEIVE_FLAGS_RESOURCES
flag. That’s not great for perf.
(Yes, with some significant effort, NDIS could probably be a little bit smarter here. But really it’s a rare case that 2 protocols want the same EtherTypes – usually they all want disjoint sets, so that’s what NDIS has optimized for.)
NDIS generally requires miniports to strip the 802.1Q tag and put the tag’s value into the NBL’s Ieee8021QNetBufferListInfo. NDIS also requires miniports to drop traffic that’s not destined to the currently-configured VLAN (Set-NetAdapter -VlanID
). As a special exception, setting the packet filter to NDIS_PACKET_TYPE_PROMISCUOUS
instructs the NIC to not do any VLAN filtering.
After the Q header is removed by the miniport, NDIS parses out the EtherType. The packet is given to the protocol(s) that asked for that EtherType. As discussed above, if a protocol provides a NULL FrameTypeArray, that’s equivalent to a wildcard for EtherType matching.
There are a few cases where NDIS gives up on FrameType matching, and just dumps all NBLs onto all protocols. It sort of sounds like you were accidentally relying on this behavior? Make sure you specify exactly the EtherType(s) you care about. If you need to see all VLANs, then you do have to enable promiscuous mode.
It’s by design that the vSwitch consumes the Q tags and, well, switches traffic based on the Q tag. So you probably can’t get full fidelity Q tags from above the vswitch. Think about the vswitch as a real hardware switch. If your protocol attaches to a host vNIC, then you’re on another switch port from the physical NIC. The vswitch can be configured to put a port into Trunk mode, which might help (Set-VMNetworkAdapterVlan
).
Otherwise, if your protocol is really tied to the external physical NIC, it should just bind to that directly, rather than trying to reach through the vswitch. Creating an external vswitch automatically unbinds all other protocols from the external NIC, but you can just bind it back again (Enable-NetAdapterBinding
).
Footnote on Q-in-Q: if there is more than one Q tag, then the NIC strips only the outermost one. We are currently considering an extension to NDIS to instruct the NIC strip out the 2nd outermost one too. After the NIC has stripped one (or someday, two) tags, that leaves the remaining Q header(s) intact in the packet payload. NDIS currently knows how to read the EtherType if there’s exactly zero or one Q tag remaining. So in summary, you can currently rely on EtherTypes if you have no Q tags, 1 Q tag, or 2 Q tags. If there’s 2 Q tags, then you’ll have the outermost tag in the NBL’s OOB data, and the inner tag will still be intact. If there’s more than 2 Q tags, it all sort of falls apart.