Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTDEV

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


Before Posting...

Please check out the Community Guidelines in the Announcements and Administration Category.

NDIS6 bug or IEEE 802.1Q specification?

Rob_WallaceRob_Wallace Member Posts: 10

Hi,

A while ago I ported our old NDIS5 protocol driver to NDIS6. Our driver was based on a Microsoft example. I can no longer find the NDIS5 example but the updated NDIS6 example is here:
https://github.com/microsoft/Windows-driver-samples/tree/master/network/ndis/ndisprot/6x

I followed the NDIS6 example to port our driver and it’s working fine. The problem I’m having is when a Hyper-V virtual adapter is created. At this point the driver can no longer read QoS packets on the physical adapter (only the virtual adapter). You might be tempted to say this is normal, the QoS packets should go to the VLAN however the old NDIS5 driver can read the QoS packets from both the physical adapter and the virtual adapter. Wireshark can also see the QoS packets on the physical adapter. The only way I can make NDIS6 see the packets on the physical adapter is by enabling promiscuous mode.

NDIS5 and NDIS6 are still very similar in the way they open and bind to an adapter - the biggest difference being NdisOpenAdapter() vs NdisOpenAdapterEx(). I suspect NdisOpenAdapterEx() is causing the reception issue (unintentionally or by design). I can’t prove this because NdisOpenAdapter() is no longer available for NDIS6.

Does anyone have any clue how to solve this issue without enabling promiscuous mode? Is this a bug or is NDIS6 simply complying with the 802.1Q specification?

Comments

  • Pavel_APavel_A Member Posts: 2,764

    At this point the driver can no longer read QoS packets on the physical adapter (only the virtual adapter

    What are "QoS packets" - 802.1Q or IP with diffserv info?
    So it does not get any packet with 802.1Q tag at all, or it gets packets with the tags stripped off/moved to OOB info?

    -- pa

  • Rob_WallaceRob_Wallace Member Posts: 10

    Sorry, when I say QoS I mean Quality of Service which is the priority setting of the 802.1Q tag. To answer your question, the driver does not receive any packets with the 802.1Q tag at all on the physical adapter. They appear to be forwarded to the virtual adapter even when the VLAN id is not set.

    Powershell commands:
    New-VMSwitch -Name ETH1 -NetAdapterName ETH1 -AllowManagementOS $False
    Add-VMNetworkAdapter -Name 'ETH1' -ManagementOS -SwitchName ETH1

    Anyway, it looks like I found the answer to my problem here:
    https://marc.info/?l=wireshark-dev&m=143444451202831&w=2

    In the thread he says, "WinPcap cannot capture 802.1Q tagged VLAN headers received by NDIS 6.x" and later he says, "I also add the code to capture 802.1Q VLAN tags correctly"

    So I downloaded his code to see how he was calling NdisOpenAdapterEx(). Sure enough I found a difference. He sets the OpenParameters.FrameTypeArray = NULL. I was setting this like the Microsoft example. When I set this option to NULL it works. The driver can now see 802.1Q tags on the physical adapter when a VLAN is defined. Problem solved.

    Maybe it would be nice to understand exactly what the option does.

  • Rob_WallaceRob_Wallace Member Posts: 10

    I should rephrase my statement "the driver can now see 802.1Q tags". The tag is actually stripped off when the packet is received but at least I'm getting packets. Previously any packets with the 802.1Q tags were not received.

  • Pavel_APavel_A Member Posts: 2,764

    The tag is actually stripped off when the packet is received but at least I'm getting packets.

    Do you see the missing bits in OOB info?
    -- pa

  • Jeffrey_Tippet_[MSFT]Jeffrey_Tippet_[MSFT] Member - All Emails Posts: 577

    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.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Developing Minifilters 24 May 2021 Live, Online
Writing WDF Drivers 14 June 2021 Live, Online
Internals & Software Drivers 2 August 2021 Live, Online
Kernel Debugging 27 Sept 2021 Live, Online