I'd like to add a follow-up from our internal investigation.
The OS implements different semantics from what MSDN and I have been telling you. We're going to fix the documentation to align with the actual OS behavior. Until the updated MSDN topic goes live, here's the rules.
NDIS_PM_CAPABILITIES.NumNSOffloadIPv6Addresses tells the OS how many OID_PM_ADD_PROTOCOL_OFFLOAD requests you support. Since each PM offload request can have 1 or 2 target addresses, you actually need to support up to 2x the number of addresses that you claim in NumNSOffloadIPv6Addresses. (Yes, the field is now misnamed; we'll union-rename it in a future version of the header.)
Note that the logo requirements (Device.Network.LAN.PM.PowMgmtNDIS, Device.Network.WLAN.WoWLAN.ImplementWakeOnWLAN, etc.) continue to be interpreted to require that NumNSOffloadIPv6Addresses be at least 2. Therefore, the careful reader will note that the logo requires 2x2 = 4 addresses. Not all requirements' wording is as clear as Device.Network.LAN.PM.PowMgmtNDIS, which says "Devices must support at least 2 NS offloads, each with up to 2 target IPv6 addresses.", but others should be interpreted in a similar vein.
While scrutinizing the matter, we've noticed that not all vendors are correctly handling the NS protocol. As a public service announcement... there are actually *two kinds* of NS requests, and your miniport must be prepared to respond to *both* kinds. (This may mean that you need to plumb down two separate patterns to your firmware.) While I recommend reading RFC 4861 -- especially sections [4.3], [4.4] and [7.1] -- here's a summary.
Your miniport must be prepared to match two kinds of NS/NA messages. The unicast variety looks like this:
Ethernet.EtherType = 0x86dd (IPv6)
IPv6.Version = 6
IPv6.NextHeader = 58 (ICMPv6)
IPv6.HopLimit = 255
IPv6.Destination = OID.TargetIPv6Addresses[x] or OID.SolicitedNodeIPv6Address
IPv6.ICMPv6.Type = 135 (NS)
IPv6.ICMPv6.Code = 0
IPv6.ICMPv6.TargetAddress = OID.TargetIPv6Addresses[x]
Additionally, if OID.RemoteIPv6Address is not 0::0, then the miniport should add another field to the pattern:
IPv6.Source = OID.RemoteIPv6Address
The other variety of NS is the same as the above pattern, except this field:
IPv6.Destination = OID.SolicitedNodeIPv6Address
(all other fields the same as NS/unicast above)
In both cases, you're expected to reply with this message:
Ethernet.Destination = Ethernet.Source of the NS
Ethernet.Source = Miniport's current MAC address
IPv6.HopLimit = 255
IPv6.Source = IPv6.ICMPv6.TargetAddress of the NS
IPv6.Destination = IPv6.Source of the NS (unless it was 0::0, then use FF02::1)
IPv6.ICMPv6.Type = 136 (NA)
IPv6.ICMPv6.Code = 0
IPv6.ICMPv6.RouterFlag = 0
IPv6.ICMPv6.SolicitedFlag = 0 if IPv6.Source of the NS was 0::0, 1 otherwise
IPv6.ICMPv6.OverrideFlag = 1
IPv6.ICMPv6.TargetAddress = IPv6.ICMPv6.TargetAddress of the NS
IPv6.ICMPv6.TLLAOption.Type = 2 (Target Link-layer Address)
IPv6.ICMPv6.TLLAOption.Length = 1
IPv6.ICMPv6.TLLAOption.LinkLayerAddress = OID.MacAddress
The NS must be matched for *both* TargetIPv6Addresses supplied in the OID, if two are supplied. If the 2nd TargetIPv6Address is 0::0, then you can ignore it and only create patterns for the first TargetIPv6Address. Since there are two possible types of NS message per TargetIPv6Address, your hardware may require you to plumb as many as 4 patterns per OID request. Given that the logo requirement for Windows 8 and Windows RT requires a minimum of 2 OID requests, you may need as many as 8 match patterns:
[2 OID requests] x [2 TargetIPv6Addresses] x [2 types of NS message] = [8 match patterns]
Of course, the exact number of patterns required depends on the details of how your hardware is programmed. If your hardware is more flexible on matching the IPv6.Destination, then you might only need a single pattern for the entire OID request.
Expect a future version of the kit to have a more comprehensive logo test for NS protocol offloads.