阅读:2675回复:18
Passthru:胡大侠的代码为撒当PacketSize>LookAheadBufferSize,在PtTransferDataComplete中重新组装Indicate网络不通(附代码)?
参考胡大侠的代码,我已经搞定了mpSend(屏蔽掉sendPacket),接收时候的ptRecv(屏蔽掉ptRecvPacket)在Packet = NdisGetReceivedPacket时候,Packet!=空也可以,
当Packet==NULL,当PacketSize <= LookAheadBufferSize也通了, 就是当PacketSize > LookAheadBufferSize时候(如果ping包大于128,就会走这条路),因为只是返回了一部分Packet数据,需要在PtTransferDataComplete中重新组装新的数据报,我跟踪了所有函数,返回都是成功,但是网络就是不通,因为indicate上去的数据报是两个Packet组装起来的,我开始用的PTRecv中返回的OOB数据,后来换成PtTransferDataComplete中返回的Packet的OOB数据,依然不通,哪位前辈帮我看看下面的代码,谢谢了,或者哪位有已经通过的PtTransferDataComplete给我参考参考。stand_fucai@163.com。 VOID PtTransferDataComplete( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet, IN NDIS_STATUS Status, IN UINT BytesTransferred ) /*++ Routine Description: Entry point called by NDIS to indicate completion of a call by us to NdisTransferData. See notes under SendComplete. Arguments: Return Value: --*/ { PADAPT pAdapt =(PADAPT)ProtocolBindingContext; PUCHAR pPacketContent; PRECV_RSVD Resvd; UINT OffsetSize; UINT result; UINT PacketLen; PVOID MediaSpecificInfo = NULL; ULONG MediaSpecificInfoSize = 0; PNDIS_BUFFER PacketBuffer; PNDIS_PACKET OffsetPacket; PNDIS_BUFFER OffsetBuffer; PUCHAR pBakContent; UINT bufLength; NDIS_STATUS status; NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress; HighestAcceptableAddress.LowPart = -1; HighestAcceptableAddress.HighPart = -1; Resvd = (PRECV_RSVD)(Packet->MiniportReserved); OffsetPacket = (PNDIS_PACKET)Resvd->OriginalPkt; if(pAdapt->MiniportHandle) { //NdisMTransferDataComplete(pAdapt->MiniportHandle,Packet,Status,BytesTransferred); DbgPrint(\"PtTransferDataComplete(BytesTransferred:%d)! OffsetPacket:%x Packet:%x\\n\",BytesTransferred,OffsetPacket,Packet); if (OffsetPacket==NULL){//如果为空,则说明不是自己请求的传输动作,直接调用结束即可 NdisMTransferDataComplete(pAdapt->MiniportHandle,Packet,Status,BytesTransferred); }else{ status = NdisAllocateMemory(&pPacketContent,2000,0,HighestAcceptableAddress); CopyPacket2Buffer(OffsetPacket,pPacketContent,&OffsetSize); CopyPacket2Buffer(Packet,pPacketContent+OffsetSize,&PacketLen);//packetlen == bytestransferred PacketLen+=OffsetSize; //result = RecvProcess(pAdapt,pPacketContent,&PacketLen); //if( result == PACKET_REFUSE ){ // MPReturnPacket((NDIS_HANDLE)pAdapt,Packet); // DbgPrint(\"recvprocess return packet_refuse\\n\"); // return; //} NdisUnchainBufferAtFront( Packet,&PacketBuffer ); NdisQueryBufferSafe(PacketBuffer,&pBakContent,&bufLength,32); NdisFreeBuffer(PacketBuffer); NdisFreeMemory(pBakContent,2000,0); //重新构造完整数据报对应的Packet! //add@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@没有下面代码,还是不通 NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(Packet), NDIS_OOB_DATA_FROM_PACKET(OffsetPacket), sizeof(NDIS_PACKET_OOB_DATA)); NdisIMCopySendPerPacketInfo(Packet, OffsetPacket); NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(OffsetPacket, &MediaSpecificInfo, &MediaSpecificInfoSize); if (MediaSpecificInfo || MediaSpecificInfoSize){ NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(Packet, MediaSpecificInfo, MediaSpecificInfoSize); } //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ // 手动释放原来的offsetpacket NdisUnchainBufferAtFront( OffsetPacket,&OffsetBuffer ); NdisQueryBufferSafe(OffsetBuffer,&pBakContent,&bufLength, 32 ); NdisFreeBuffer(OffsetBuffer); NdisFreeMemory(pBakContent,2000,0); NdisFreePacket(OffsetPacket); memset(Packet->MiniportReserved,0,sizeof(Packet->MiniportReserved)); NdisAllocateBuffer(&status,&PacketBuffer,pAdapt->RecvPacketPoolHandle,pPacketContent,PacketLen); NdisChainBufferAtFront(Packet,PacketBuffer); Packet->Private.Head->Next =NULL; Packet->Private.Tail=NULL; NDIS_SET_PACKET_HEADER_SIZE(Packet,14); DbgPrint(\"PtTransferDataComplete:Will NdisMIndicateReceivePacket: Packet:%x\\n\",Packet); NdisMIndicateReceivePacket(pAdapt->MiniportHandle ,&Packet,1); status=NDIS_GET_PACKET_STATUS(Packet); DbgPrint(\"PtTransferDataComplete:NdisMIndicateReceivePacket return Code:%d\\n\",status); if(status!= NDIS_STATUS_PENDING) { DbgPrint(\"PtTransferDataComplete:NdisMIndicateReceivePacket Not Pending Will MPReturnPacket:Packet:%x\\n\",Packet); MPReturnPacket((NDIS_HANDLE)pAdapt,Packet); }else{ DbgPrint(\"PtTransferDataComplete:NdisMIndicateReceivePacket Pending Packet:%x\\n\",Packet); } }//offsetPacket!=NULL } } |
|
最新喜欢:![]() |
沙发#
发布于:2003-01-13 10:48
重新组包算校验和了么?
还有,packet是你导致分片的么?如果不是你为什么要组包? |
|
|
板凳#
发布于:2003-01-13 10:55
ndistransferdata并不需要组包,本来就是一个packet里面的东西,你为什么说是两个packet?难道你是用两个pacekt接收的?如果你是用了两个packet估计肯定用问题了。
|
|
|
地板#
发布于:2003-01-13 11:21
是要组包压,因为在ptReve中只是接收到一个完整数据报的一部分,
另外部分在TransdataComplete中得到,那么不是在TransdataComplete中将原来的数据与现在的数据一起合成一个数据报,应该不需要算CheckSum,因为是一个原始数据报在不通地方得到不通部分而已,我看了几个贴出来的代码,都没有算CheckSum,不知道为什么我的不通,他们贴出来的就通了。还恳请大侠指教! 注意:在PtRecv中先申请了一个Packet,将已经得到的数据放在此Packet中,也就是TransdataComplete中的OffsetPacket, Resvd = (PRECV_RSVD)(Packet->MiniportReserved); OffsetPacket = (PNDIS_PACKET)Resvd->OriginalPkt; 再又生成一个Packet,用此Packet来调用NdisTransData, NdisTransferData(&Status,pAdapt->BindingHandle ,MacReceiveContext,LookAheadBufferSize, PacketSize-LookAheadBufferSize ,MyPacket,&BytesTransferred); 以得到剩余的数据, 在TransdataComlete中也就是将这两个Packet数据组合到一个Packet中,可参见代码,为什么不通呢? 普通的ping包因为PacketSize <= LookAheadBufferSize所以不需要调用NDISTRansdata,可以Ping通,当ping X.X.X.X -l 129(大于128), 走的是TransData,就是不通。 |
|
地下室#
发布于:2003-01-13 11:47
再又生成一个Packet,用此Packet来调用NdisTransData 不用在生成一个packet,如果你方才申请的buffer不够用,那就在申请一个buffer,然后把这个buffer链到原先的packet上去就可以了。 不过ndistransferdata只会向第一个buffer里面copy数据,所以这时候你有两个选择,或者直接从lookaheardbuffer里面copy出来packetsize大小的内容来,如果你不放心,那就让ndistransferdata从0开始传递数据,这样就可以了,不要再分配一个packet, 然后要别忘了OOB数据。 |
|
|
5楼#
发布于:2003-01-13 15:08
我现在就是对自己生成Packet的OOB数据不知道怎么处理。
对于自己生成的Packet,OOB数据怎么设置呢? 另外,如果不用再申请Packet,那么,是不是就在PTRecv中直接生成Packet,Indicate上去?但是如果Ndistransdata pending怎么办? 恳请大侠指教! |
|
6楼#
发布于:2003-01-13 15:40
首先你分配的buffer 的size应该是packetsize大小,然后如果lookaheadbuffersize<packetsize,你传给ndistransferdata这个packet,如果是pending,那就在transfercomeplete里面处理好了,这时候你还是能得到这个packet吖。
至于oob数据,可以用ddk里面的宏来得到,然后在对你分配的packet进行设置。如果调用了ndistransferdata,应该就不用在特意设置这些数据了。 |
|
|
7楼#
发布于:2003-01-13 15:47
实际的packet的大小应该是packetsize+headbuffersize。
不过如果你调用ndistransferdata从offet 0开始传递数据,这时候是没有headbuffer的,在向上交包时要特别处理一下 |
|
|
8楼#
发布于:2003-01-13 15:51
在很多lookaheadbuffersize<packetsize的情况下,你直接从lookaheadbuffer里面copy出来packetsize大小的内容来就可以了。因为都在那里放着呢
|
|
|
9楼#
发布于:2003-01-13 16:17
谢谢楼上大侠指教,我直接从lookaheadbuffer里面copy出来packetsize大小的内容,重新生成新的数据报,没有调用Tranferdata,居然通了。不过我大为不解压,如果是这样,
NDIS把lookaheadbuffer设置为PacketSize不就可以了吗?为什么还要别人去NdisTransferData,还有,是不是所有的网卡都是这样直接copy PacketSize也可以呢?比如在拨号网卡情况下,行的通吗? 谢谢! |
|
10楼#
发布于:2003-01-13 16:24
设计这样的方式是在以前使用的,现在的网卡一般都是把所有数据一次交上来的。拨号我没有试过,你可以试一下,看看是什么结果。我是用ndistransferdata从0开始取数据的:)
|
|
|
11楼#
发布于:2003-01-13 16:38
听说现在的网卡大部分都是直接调用PtRecvPacket,而不是PtRecv,
为了处理简单一点,我将PtRecvPacketHandle=NULL,让NDIS只是调用PtRecv,不知道行缶?由于我试验了几台机器,在我屏蔽RecvPacket之前,都只是调用了RecvPacket,因此,只好询问大侠了。 |
|
12楼#
发布于:2003-01-13 16:40
注册的时候PtRecvPacketHandle=NULL就可以了,就只会调用receive 了。
其实你在receivepacket里面处理不是更好么?收到的都是完整的packet了。 |
|
|
13楼#
发布于:2003-01-13 22:27
按照您的方法,直接从LookaheaderBuffer中拷贝PacketSize字节,在实验室的机器上可以通,但是寝室的机器就不行了,估计还是不是标准做法,导致兼容性不够,我寝室是老式Realtek RTL8029网卡,我想还是按照老胡的代码,在NdisTRansData中处理完整数据报,也就是我提问题贴出来的代码,
烦大侠再帮我看看,好吗?谢谢,我可以再开贴子给分。 |
|
14楼#
发布于:2003-01-17 16:07
到底有没有在TransDataComplete中重新组装数据报Indicate上去成功的?我试验了XPPassthru与2KPassthru,照胡大侠代码改的,
就是当数据报大于一定数值网络就不通。 恳请已经调通了这条路的大侠们指教! |
|
15楼#
发布于:2003-01-17 20:59
FT,还是自己发现了其中的Bug.
胡大侠的代码没错。是我自己用错了一个变量。 今天用SoftICE总算发现了。 不靠天,不靠地,还是只能靠自己亚! |
|
16楼#
发布于:2003-01-17 21:51
你会帮别人去改这种程序错误么?
|
|
|
17楼#
发布于:2003-01-17 23:34
确实。这种错误很花时间与精力。
关键还是靠自己的细心调试与检查。 我总是抱着一丝幻想,也许别人会指出来。结果,耽误了时间。 不过,通过这次错误的查找,也学会了核心太调试的一些技巧。 呵呵,今后我会尽量帮别人的啦。 也谢谢楼上的大侠给我的帮助。 |
|
18楼#
发布于:2004-05-31 10:50
我现在遇到和你一样的问题,我是把包收下后保存在自己的队列中(队列映射了包的信息),然后经过处理后再发送,也是当包大于某一值的时候有你说的那个问题。可以告诉我怎么解决的吗?谢谢了!
|
|