ProtocolReceivePacket这个函数花了不少时间研究,部分资料中提到这个函数可实现多包接收,但我认为它仅仅是可以接收完整数据包而已。理由有:
1.它的参数是PNDIS_PACKET,即单个数据包,而这个结构并没有链表的特征。发送多个数据包的函数MiniportSendPackets,不仅函数名带复数,参数也是PPNDIS_PACKET,明显是一个数据包数组。从开发风格的同一性来看,ProtocolReceivePacket不太可能处理多包。
2.另一个函数ProtocolReceive并非接收单个数据包,参数是缓冲区地址,接收的是否单个数据包还需要在函数中进行判断。相对来说,ProtocolReceivePacket处理完整的数据包,已经是提升了效率。
3.DDK帮助中有这么2段话:
ProtocolReceivePacket processes receive indications made by underlying connectionless NIC driver(s) that call NdisMIndicateReceivePacket either with packet arrays because the underlying driver supports multipacket receive indications or with individual packets that have associated out-of-band information.
这段话咋一看好像是可以多包接收,但实际上所谓的“with packet arrays”是指NIC driver(s)调用NdisMIndicateReceivePacket时的参数,而NdisMIndicateReceivePacket的参数则是PPNDIS_PACKET,如同第1点所讲的,带有明显的数组特征,有别于PNDIS_PACKET。
Packet
Specifies a pointer to a packet descriptor for the received net packet. NDIS extracted this pointer from an array of packet descriptor pointers that an underlying driver passed to NdisMIndicateReceivePacket.
结合之前那句话,这句话的意思应该是,Packet是NDIS从NdisMIndicateReceivePacket参数的packet数组中取出的某一个指针,而不是整个数组。
4.Passthru源代码中的返回值是0或1,而关于返回值的解释是,非0表示将调用NdisReturnPackets()的次数。
5.为此我还专门做过一个测试:在ProtocolReceivePacket中检查Packet参数,过滤某个地址对本机的ICMP数据包,通过EtherPeek构造并以每次20个数据包的速度发送,发现所有数据包都通过ProtocolReceivePacket进行处理,并且所有该过滤的都过滤了。