Consider a case where a network application calls Windows QoS APIs to add a layer-2 IEEE 802.1Q UserPriority tag (almost always referred to as 802.1p) to outgoing traffic. Ascertaining whether the tag actually got added to an outgoing packet is not as simple as it seems due to the nature of how the Windows network stack is designed, and how framing actually occurs. From an internal implementation perspective, The QoS Packet Scheduler (Pacer.sys in Vista/2008 Server, and Psched.sys in XP/2003 Server) in the network stack merely updates an out-of-band structure (not the actual formed packet) that an 802.1Q UserPriority tag should be added. The specific NDIS structure is NDIS_NET_BUFFER_LIST_8021Q_INFO, which contains member variables for both VlanID and UserPriority, and is passed to the NDIS miniport driver for implementing both priority tagging (UserPriority) and VLAN (VlanId). It is up to the NDIS miniport driver to actually insert the 802.1Q tag into the frame based on these values before transmitting on the wire. A miniport driver will only insert this tag if the feature is supported and enabled in the advanced properties of the NIC driver; typically layer-2 priority tagging is disabled by default.

From a network stack layering perspective, it’s important to understand that Pacer.sys is an NDIS Lightweight Filter (LWF) driver, and will always be inserted above a miniport driver, which will always be the lowest network software in the stack because it communicates directly with the NIC hardware. Also note that network sniffing applications like NetMon and WireShark are also network stack filters, and will always be inserted above the miniport driver. This is important knowledge because it should be clear that taking a network sniff of traffic on the sending PC will never show the tag in a packet (because the tag gets added below the sniffing software). Also, the QoS Packet Scheduler can't know for absolute certainty whether the miniport driver added the tag to the outgoing packet. 

What about trying to do a network sniff on the receiving PC? Good question, but also will show the layer-2 tag not present in packets. The reason for this is NDIS developer documentation clearly states that miniport drivers must strip the tag when received, and populate the NDIS_NET_BUFFER_LIST_8021Q_INFO UserPriority and VlanId fields with the values in the tag. This out-of-band structure can then be used by NDIS filter drivers higher up in the stack for implementing these features. The functional reason for stripping the layer-2 tag is because Tcpip.sys will drop any received packet that contains this tag. Therefore, if a misbehaving miniport driver does not strip the tag, the packet will never be received by the user-mode application because it will be dropped internally.

In conclusion:

  • A network sniffing app on the sending PC will never see a tag
  • A network sniffing app on the receiving PC will never see a tag
    • Unless the miniport driver is misbehaving, which will result in dropped packets
  • Monitoring tagged packets from intermediate network elements (such as a switch) is hard if at all possible
    • Perhaps a clever SNMP counter could be used, but would depend on the device manufacturer

If you have not came to this conclusion already, the only way to determine whether a layer-2 tag got added on the sending PC and/or received by the receiving PC is to monitor the NDIS_NET_BUFFER_LIST_8021Q_INFO.UserPriority field. Stay tuned for a follow-up post which describes how to do this.

-- Gabe Frost