NDIS IM调试遇到的问题:OID_TCP_TASK_OFFLOAD

来源:互联网 发布:java最新商城源码 编辑:程序博客网 时间:2024/06/04 20:14

这几天调试NDIS xLan的时候,发现在 win2003上运行不正常,以前在 XP,WIN7,WIN8上测试都能正常,于是查找原因。
先说说这驱动是干什么的,这是个NDIS中间驱动,采用应用层拦截的方式处理数据包,
就是在中间驱动里获得的数据包,发送到应用层程序,应用层程序分析处理之后再返回给中间驱动。
很类似应用层防火墙的功能,数据包的拦截处理全在应用层完成。
类似的实现,可参看 linux 里的 netfilter内核模块,
他拦截IP数据包之后返回 NF_QUEUE,表示把数据包排队,然应让应用层程序接收处理。

NDIS xLan驱动实现里,如果没应用程序绑定到网卡,就让数据包直接通过,如果有应有程序绑定到这块网卡,就把数据包发到应用层里。
在win2003里测试,如果不打开应用程序,一切正常,如果发到应用,网络就非常卡,基本无法上网。
于是猜测可能在 发包到应有层有问题,于是一步步调试,最终确定问题所在:
当从应用层把数据包传递到驱动里,驱动自己构造 Packet(NdisAllocketPacket),
做各种初始化操作,调用 NdisSendPackets ,表面上发送虽然成功,但是对方机器就是接收不到数据包。
抓包分析发现发送的数据包里,全是 TCP头里校验码错误的数据包,真是奇怪,因为各种校验码都计算正确的。
(这里抓包使用 WinPCAP为基础的Ethereal软件,因为 WinPCAP是基于协议驱动的,是无法抓包到 NDIS 中间驱动里的,
幸好我这是在 vmwrea虚拟机里测试,网络桥接方式,在宿主机里抓包,就能抓取到虚拟机里的数据包了。)
再仔细查看驱动代码,直接PASS的数据包复制了原始 OOB信息,而发给应用层的数据,因为丢弃了原始包信息,所以也无从复制OOB了。
当初开发这驱动时候,其实也不大关心这个OOB。
OOB一般翻译为带外数据,这个跟TCP协议里说的 OOB不一样的概念,这是微软NDIS驱动里 NDIS_PACKET结构相关的一种数据结构,
大概意思是协议驱动可以填写这些信息,然后指示NIC网卡使用硬件加速功能处理什么的,或者反过来。
应该是网卡和上层驱动交互的一种额外信息,用于提高效率的,具体其实也不很理解。

于是带着 NdisSendPacnekts和 OOB的问题,去搜索google, 终于找到一点信息,在老外的一个技术论坛里,
恰好有人遇到了跟我一样的问题。
下面是英文原话:
If you have disable NDIS task offload, then all of that OOB stuff doesn't matter.
If you have not disabled NDIS task offload,then you should   examine the OOB data and see if it applies to your modified packet.
大概意思当你禁止了 NDIS task offload, 就能忽略 OOB的处理了,反之则必须正确处理OOB。
http://msdn.microsoft.com/en-us/library/windows/hardware/gg463469.aspx
上面的MSDN文档里 有对 NDIS task offload的解释。
对TCP/IP协议栈,task offload可以让网卡硬件做如下事情(如果网卡支持)
1)计算校验码
2)计算分段
3)  IPSec加密
因为都是在网卡硬件里计算,所以速度很快。
可能有些网卡支持,有些网卡不支持,硬件支持的话,的要正确处理 OOB信息,否则就会出错。
NDIS xLan处理自己的数据包时候,没能处理OOB信息,在遇到网卡不支持的机器上,刚好能正常运作,遇到支持的网卡,那就乱套了。

所以很显然,要解决NDIS xLan问题,得屏蔽掉 task offload,让上层驱动都认为网卡不支持task offload。
这个应该跟上层调用 NdisRequest查询驱动OID有关,于是终于找到 OID_TCP_TASK_OFFLOAD,
再回到自己的驱动代码,找到这个OID,却发现原来在开发驱动时候,只是简单 交给底层处理,于是改成直接 返回
NDIS_STATUS_NOT_SUPPORTED
问题得到解决。

 

下面一段信息,也可帮助理解(从网上复制):

"Dmitriy Gubarkov" <begger@ukr.net>

I have to redirect packets from specified port to another one.
So I'm using passthru as a base and I implemented Send and Receive handlers
to change ports.
Everything seems to be ok with incoming packets, but outgoing packets has
invalid checksum. But I've made a correct calculation and replace old one
with new checksum and client got packet with old checksum. It strange I
can't even imagine what could be a reason. Besides new port value is exists
while checksum is old, and this happens only in Send handler.

Can anybody point me where to look for possible reason or maybe I missed
something?

"Thomas F. Divine" <pcausa@hotmail.com>

Perhaps this is related to NDIS task offload - checksum offload.

In your IM driver you need to monitor the queries and sets related to NDIS
task offload. If the adapter offers hardware checksum offload and the TCP/IP
driver has elected to use it, then send packets will not have the correct
checksum because it is understood that the hardware will compute them. Going
further, if you compute a correct checksum in your IM filter, the outgoing
checksum will be incorrect because the hardware will make an additional
computation.

Read the info on the checksum task offload. There you will find how to
detect when offload is enabled and the expected values to be put into the
packet checksum field, etc . for this scheme to work.

 

原创粉丝点击