阅读:4679回复:20
我的ptreceive的思路,请指教
我参考了passthru和imdrv后对passthru的ptreceive修改如下:
ptreceive() { if(LookAheadBufferSize>=PacketSize) { // allocate my packet descriptor NdisDprAllocatePacket(); // copy headerbuffer and lookaheadbuffer into my packet NdisMoveMemory(); // indicate packet NdisMIndicateReceivePacket(); // free my packet descriptor NdisDprFreePacket(); } else { // LookAheadBufferSize < PacketSize // remaining data for us to receive // allocate my packet descriptor NdisDprAllocatePacket(); // copy headerbuffer and lookaheadbuffer into my packet NdisMoveMemory(); // copy data remained NdisTransferData(); if(Status != NDIS_STATUS_PENDING) { PtTransferDataComplete(); } // free my packet descriptor // in pttransferdatacomplete // NdisDprFreePacket(); } return NDIS_STATUS_SUCCESS; } 1)思路有什么不对的地方,或是大虾们有更好的,请不吝赐教; 2)这里不单要申请包描述符,还要自己建立MDL,请问大虾这里都要注意什么关键的细节问题? |
|
沙发#
发布于:2001-08-26 16:21
我没有仔细看,不过你这样处理会损失oob数据。
对于某些情况来说也许是对的,但是某些应用来 说,可能会非常惨。 |
|
|
板凳#
发布于:2001-08-26 16:56
在PtReceive中,如果LookAheadBufferSize>=PacketSize,按照pcausa的说法,需要调整LookAheadBufferSize = PacketSize.
所以不存在这种情况.根据ddk document,PacketSize >= LookAheadBufferSize, 如果是大于,需要调用ndistransferdata得到后面的数据.而且,PtTransferDataComplete()应该不是这里调用的,而是被ndis在ndistransferdata完成时调用. 至于oob数据,想和hu大侠请教一下:我感觉oob数据是mac用的,存放在ndis_packet里.在ptreceive里,如果NdisGetReceivedPacket 返回0(绝大部分情况如此),也就是下面只提供buffer,没有完整的packet,那么oob数据是不是就已经丢失了? |
|
地板#
发布于:2001-08-26 20:46
transferdatacomplete可以在这里调用,此外你说的也对,
让我们来把这个过程理理顺。 ptreceive 接收数据,发现只有头,那么,调用transferdata, 然后,判断pending,然后调用ndistransferdatacomplete。 这是一种做法。我个人推荐这种做法,因为这样节省了一个 pttransferdata,pttransferdatacomplete。 还有一种做法是象passthru一样,调用介质相关函数去 indicatepacket,这样会导致ip.sys调用pttransferdata, 然后是pttransferdatacomplete。这种做法也有好处, 虚拟网卡完全仿真了miniport。 下面关于oob: oob并不完全是mac用的,协议也用。例如ip/tcpchksum。 ndisgetreceivepacket返回null并不是大多数情况,只有 非常老的网卡是这样。这种情况下没有oob数据,也就是 说不存在丢失的问题。对于不返回null的情况有这么几种: 1、系统内存不够,因此miniport设置packet的status 为resource,然后miniport用介质无关函数indicatepacket, 这种情况会使ndis调用protocol的recevie函数而不是 receivepacket函数。因为receive这个函数所提供的包 是由miniport保留的,protocol只读,而receivepacket 这个函数提供的包对protocol来说是可写的。这里面有些 细节。 2、这个情况是ddk document没有说过的。当网卡被设置 为混杂模式,ndis也调用ptreceive,而不是ptreceivepacket。 这也可以理解,因为混杂模式会收到很多不要的包,如果 用receivpacket,为每个协议driver复制一份,浪费内存。 只要miniport调用介质无关indicatepacket,就会包含 oob data。以上就是ndisgetreceivepacet不返回null 的情况。 |
|
|
地下室#
发布于:2001-08-28 16:04
Huyg大侠:
当LookAheadBufferSize < PacketSize 时,如果用你所说的第二种方式,是不是只将HeadERBuffer和LookAheadBuffer都COPY出来以一个自定议的BUFFER,然后系统就会自动调用MPTransferData(对了你上面怎么写的是pttransferdata),然后再在这个函数里加一些操作将其余的数据COPY到自定议BUFFER就能处到整个包啦? 另外,你有QQ或者其它联系方式吗?》 |
|
|
5楼#
发布于:2001-08-28 18:21
哦,你说的那个地方是我的笔误。
NDIS当然不会自动调用miniporttransferdata,你 看看passthru怎么做的?它调用了一个介质相关 函数ndiseth/fddi/xxx/indicatepacket。这种情况 你不需要构造packet结构。 我曾经有过一个qq号,但是很久不用,而且我也不 记得号码了。 我一般不用在线聊天工具聊天,多年的战友兄弟们除外。 |
|
|
6楼#
发布于:2001-08-28 19:35
老版:
要不要我给你一个QQ号啊(NND,现在的QQ不能在线申了)。我还有一点问提,我用的是第一种方法,我是想在PTRECEIVE的后的包处理之前,将整个以太包(包括MAC层的)拷贝到一个缓冲,分析整个包并进行过滤(随便改掉IP层的协议),在通常的PC台式机上可能正常运行,可是在笔记本或是HP等专用机上就有问提,不知道哪一步不对,请指教,我的思路是: ptreceive() { ////////////////////////////////////add UCHAR pBuffer[2000]; ... if(LookAheadBufferSize==PacketSize) { 将HeaderBuffer和LookAheadBuffer copy到pBuffer } else if (LookAheadBufferSize<PacketSize) { 将HeaderBuffer和LookAheadBuffer的前20byte copy到pBuffer 我以为,在这种情况下,系统会自动调用miniport.c的MPTransferData(),所以我就在这种函数可添加了一段代码,完成将其余的数据COPY到pBuffer的相应位置来完成对数据的获取,不知道对不对? } //分析判断是否要过滤,如果过滤就将第三层协议随便改一个值! ///////////////////////////////////////// .. //其后不变 if(!pAdapt->MiniportHandle) { Status = NDIS_STATUS_FAILURE; } ....... pAdapt->IndicateRcvComplete = TRUE; switch(pAdapt->Medium) { case NdisMedium802_3: 。。。。 } |
|
|
7楼#
发布于:2001-08-28 21:28
关于为什么代码在有些机器上能跑,在另外一些机器上不能跑,
我曾经在whnet bbs上发过多篇贴子讨论这个问题。因为我自己 也曾经为此和17熬了几乎有一个星期的通宵。 所有的问题都来自网卡,和网卡状态,以及网卡驱动程序。 但是好的代码应该能够适应所有的环境。 你必须自己调用ndistransferdata,不要用mptransferdata, 你用第一种做法,可以不要mptransferdata这个函数(注释掉 它吧)。而且也注释掉后面的 switch case xxx {} 都用不着 我不要QQ号,因为我上qq几乎都是用来和小妹妹聊天。 |
|
|
8楼#
发布于:2001-08-29 09:31
Huyg大侠,能 不能给个筐架啊?
我试了一下,如果不调用 pAdapt->IndicateRcvComplete = TRUE; switch(pAdapt->Medium) { case NdisMedium802_3: 。。的话,什么包都不能上传了。。》? |
|
|
9楼#
发布于:2001-08-29 09:35
另外较正一下,我用的是第二种方式(我纺造PASSTHRU改的),在数据上传之前,怎么获取整个包的数据,进行处理。
|
|
|
10楼#
发布于:2001-08-29 10:17
这是我的监视记录,我是用的PASSTHRU的方式处理LookAheadBufferSize < PacketSize 的,可是为何多次出现这种情况后Ndis才调用MPTransferData(内含NdisTransferData)?
请指教! 101.399837 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 1496 101.520389 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=52 PacketSize = 52 101.557171 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 1496 101.900381 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 1496 102.057922 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 1496 102.142583 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 296 102.142662 Default *** E:\FW\2000\port\miniport.c (1152) *** NdisTransferData have been called (LookAheadBufferSize < PacketSize) 102.144032 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 852 102.144095 Default *** E:\FW\2000\port\miniport.c (1152) *** NdisTransferData have been called (LookAheadBufferSize < PacketSize) 102.144134 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=140 PacketSize = 140 102.400964 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 1496 102.558654 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 1496 102.901504 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 1496 103.059389 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 1496 103.402575 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 1496 103.560120 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 1496 103.902609 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 1496 103.935210 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=194 PacketSize = 194 104.060866 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 1496 104.403163 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 1496 104.561605 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 1496 104.585576 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 296 104.585646 Default *** E:\FW\2000\port\miniport.c (1152) *** NdisTransferData have been called (LookAheadBufferSize < PacketSize) 104.586266 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=140 PacketSize = 140 104.903724 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 1496 105.062374 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 1496 105.198491 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 852 105.198572 Default *** E:\FW\2000\port\miniport.c (1152) *** NdisTransferData have been called (LookAheadBufferSize < PacketSize) 105.404288 Default Recv Packet HeadBufferSize = 14 LookAheeadBufferSize=200 PacketSize = 1496 |
|
|
11楼#
发布于:2001-08-29 10:46
不只是Digital,这种情况我也遇到过,就是因为
搞不懂,所以决定采用第一种方法的(仿照imdrv, 也是版主推荐的) 斑竹,继续出手吧! :) |
|
12楼#
发布于:2001-08-29 10:51
哦,关于这两种方法,不同时期我曾经推荐过不同的方法。
原因是第一种省事,也许效率高些,第二种更兼容。 不同时期我看重不同的东西。 第2种方法并不适合你的项目,我想你是要修改包内容的吧? ndisethindicatepacket已经把包交给了ip,你还怎么改? |
|
|
13楼#
发布于:2001-08-29 11:12
我也是想在passthru的基础上,加入对指定的包类型
进行过滤,这样的话就必须首先得到整个包,看来 我还是用地一种方法吧 :( 这样的话,就得全面改写 ptreceive,还要注意版主提到的oob数据 |
|
14楼#
发布于:2001-08-29 11:26
实验室的东西往往很简单,但是实用化就比较困难。
97年的时候我就开始学习ndis,但是直到现在还是 一知半解。新东西和老东西简直无法兼容,ipsec 和nat,ipip的兼容都很难解决。 学习ndis,对注册表的了解是非常重要的,我推荐一个 东西,2k/nt 的resource kit。这个东西没有盗版, 但是总是会有人买msdn,然后放到网上。resource kit 里面详细的描述了所有注册表信息的含义。开发 driver资料很重要,没有chk build有的时候也 很难受。 |
|
|
15楼#
发布于:2001-08-29 11:30
我对第一种的流程还是不大清楚,我享细说一下,不对了请指教:
ptreceive() { if(LookAheadBufferSize>=PacketSize) { //这种情直接将将HEADERBUFFER和LookAheadBUffer组合就是了 //致于以下几步是不是指示上层,已接收到数据包,如果是,哪么、上层(如IP层)又以何种方式取得数据包呢? // allocate my packet descriptor NdisDprAllocatePacket(); // copy headerbuffer and lookaheadbuffer into my packet NdisMoveMemory(); // indicate packet NdisMIndicateReceivePacket(); // free my packet descriptor NdisDprFreePacket(); } else { //这种情况下,调用了NDISTRANSFERDATA是不是将数据传到了上层,为何又没有调用 NdisMIndicateReceivePacket(),还有就是在这种情况下,是不是我还要写一个函数将数据从PACKET描述符中取出,并与前面的组合, // LookAheadBufferSize < PacketSize // remaining data for us to receive // allocate my packet descriptor NdisDprAllocatePacket(); // copy headerbuffer and lookaheadbuffer into my packet NdisMoveMemory(); // copy data remained NdisTransferData(); if(Status != NDIS_STATUS_PENDING) { PtTransferDataComplete(); } // free my packet descriptor // in pttransferdatacomplete // NdisDprFreePacket(); } return NDIS_STATUS_SUCCESS; } 谢谢指捣, 请教两位的联系方式, 我的QQ:15614487 email:digitalbrain@163.com 个人主页:www.ishacker.com |
|
|
16楼#
发布于:2001-08-29 14:29
if(LookAheadBufferSize>=PacketSize) 的时候你需要将HEADERBUFFER和LookAheadBUffer的数据考到自己的缓冲区中,然后检查,再自己分配PNDIS_BUFFER和PNDIS_PACKET,然后将你自己的Packet指示给Ip。
else的时候,你也要将HEADERBUFFER和LookAheadBUffer的数据考到自己的缓冲区中,然后调用NdisTransferData,在ProtocolTransferDataComplete里面你就能得到后续的数据,然后再自己构造一个Packet,指示给IP。 |
|
|
17楼#
发布于:2001-10-23 10:22
版主:
请问为什么在PASSTHRUY基础上网卡工作在混杂模式的时候,本机收到的LOOKAHEADBUFFERSIZE<PACKETSIZE是都会调用MPTRANSFERDATA 但是如果是其他及其的包,就不一定了,有时候会调用,有时候不会调用。我个人认为是因为PROTOCOL接到NdisMEthIndicateReceive 通知,发现接收的包衣本机无关,那么就放弃,自然就不会调用 MPTRANSFERDATA了,如果是这样,请问怎么让PROTOCOL一定调用 MPTRANSFERDATA呢????清多指点,谢谢! 至于直接调用NDISTRANSFERDATA,我是过了,实在PTRECEIVE中 直接调用的,我只是NdisDprAllocatePacket,没有定义什么MDL 各种包的标志设置什么的(因为不知道这个包是什么样的)。后 果是一进入NDISTRANSFERDATA系统就崩溃了。我应该怎么做呢! ???? |
|
|
18楼#
发布于:2002-06-02 23:51
需要好好学习,看了很多遍,还是有不理解的。
|
|
|
19楼#
发布于:2002-06-03 09:29
请问版主有没有网址给一个,下载2k/nt 的resource kit! 多谢!!! |
|
上一页
下一页