阅读:3801回复:17
斑竹:在passthru里面如何转发包?
我正在用passthru做两个网卡之间住转发数据,主要是在ptreceive
里面收到包后转发到另一个网卡上去,(用NdisSend)但出错,系统 兰屏,错误是DRIVER_IRQL_NOT_LESS_OR_EQUAL 我现在贴出我的代码,恳请帮助: NDIS_STATUS PtReceive( IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE MacReceiveContext, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookAheadBuffer, IN UINT LookAheadBufferSize, IN UINT PacketSize ) /*++ Routine Description: LBFO - need to use primary for all receives Arguments: Return Value: --*/ { PADAPT OutgoingAdapt, pAdapt =(PADAPT)ProtocolBindingContext; PNDIS_PACKET MyPkt,Packet; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; PUCHAR pEnetAddrDest; UINT nDataSize; PNDIS_BUFFER pNdisBuffer; PEnetHeader pEnetHeader; PRSVD Rsvd; PVOID MediaSpecificInfo=NULL; ULONG MediaSpecificInfoSize=0; if(!pAdapt->MiniportHandle) { Status = NDIS_STATUS_FAILURE; } else do { // // If this was indicated by the miniport below as a packet, then get that packet pointer and indicate // it as a packet as well(with appropriate status). This way the OOB stuff is accessible to the // transport above us. // Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext); if(Packet != NULL) { // // Get a packet off the pool and indicate that up // NdisDprAllocatePacket(&Status, &MyPkt, pAdapt->RecvPacketPoolHandle); if(Status == NDIS_STATUS_SUCCESS) { MyPkt->Private.Head = Packet->Private.Head; MyPkt->Private.Tail = Packet->Private.Tail; // // Get the original packet(it could be the same packet as one received or a different one // based on # of layered MPs) and set it on the indicated packet so the OOB stuff is visible // correctly at the top. // NDIS_SET_ORIGINAL_PACKET(MyPkt, NDIS_GET_ORIGINAL_PACKET(Packet)); NDIS_SET_PACKET_HEADER_SIZE(MyPkt, HeaderBufferSize); // // Set Packet Flags // NdisGetPacketFlags(MyPkt) = NdisGetPacketFlags(Packet); // // Make sure the status is set to NDIS_STATUS_RESOURCES. // NDIS_SET_PACKET_STATUS(MyPkt, NDIS_STATUS_RESOURCES); // NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPkt, 1); ASSERT(NDIS_GET_PACKET_STATUS(MyPkt) == NDIS_STATUS_RESOURCES); NdisDprFreePacket(MyPkt); break; } } // Fall through if the miniport below us has either not indicated a packet or we could not // allocate one // pAdapt->IndicateRcvComplete = TRUE; switch(pAdapt->Medium) { case NdisMedium802_3: { nDataSize=HeaderBufferSize+LookAheadBufferSize; pEnetAddrDest=((PUCHAR)HeaderBuffer); if ( pEnetAddrDest) { DBGPRINT("Ethernet packet received.\n"); if ( ETH_IS_BROADCAST(pEnetAddrDest)) { DBGPRINT("Broadcast packet,dropping it.\n"); return ( NDIS_STATUS_SUCCESS); } else { pEnetHeader=(UNALIGNED EnetHeader*)HeaderBuffer; DbgPrint("Enet Dest Addr: 0x%2x-%2x-%2x-%2x-%2x-%2x\n", pEnetHeader->EH_Dest.EA_Addr[0], pEnetHeader->EH_Dest.EA_Addr[1], pEnetHeader->EH_Dest.EA_Addr[2], pEnetHeader->EH_Dest.EA_Addr[3], pEnetHeader->EH_Dest.EA_Addr[4], pEnetHeader->EH_Dest.EA_Addr[5]); } } //Forward the packet. OutgoingAdapt=pAdapt->Next; if (OutgoingAdapt==NULL) { OutgoingAdapt=pAdaptList; DBGPRINT("Forward the packet in the first adapt\n"); } else { DBGPRINT("Forward the packet in the second Adapt!\n") } NdisAllocatePacket( &Status, &Packet, pAdapt->RecvPacketPoolHandle); NdisAllocateBuffer( &Status, &pNdisBuffer, pAdapt->BufferPool, Packet->ProtocolReserved, nDataSize); NdisChainBufferAtFront( Packet, pNdisBuffer); // Header Buffer to the Packet NdisMoveMemory( Packet->ProtocolReserved, HeaderBuffer, HeaderBufferSize ); NdisMoveMemory( &Packet->ProtocolReserved[HeaderBufferSize], LookAheadBuffer, LookAheadBufferSize); Packet->Private.TotalLength=nDataSize; if(IsIMDeviceStateOn(OutgoingAdapt)==FALSE) { return NDIS_STATUS_FAILURE; } NdisAllocatePacket( &Status, &MyPkt, OutgoingAdapt->SendPacketPoolHandle); if(Status==NDIS_STATUS_SUCCESS) { PNDIS_PACKET_EXTENSION Old,New; Rsvd=(PRSVD)(MyPkt->ProtocolReserved); Rsvd->OriginalPkt=Packet; MyPkt->Private.Head=Packet->Private.Head; MyPkt->Private.Tail=Packet->Private.Tail; NdisSetPacketFlags(MyPkt,NDIS_FLAGS_DONT_LOOPBACK); NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPkt), NDIS_OOB_DATA_FROM_PACKET(Packet), sizeof(NDIS_PACKET_OOB_DATA)); NdisIMCopySendPerPacketInfo(MyPkt,Packet); NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet, &MediaSpecificInfo, &MediaSpecificInfoSize); if(MediaSpecificInfo||MediaSpecificInfoSize) { NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPkt, MediaSpecificInfo, MediaSpecificInfoSize); DBGPRINT("MEDIA INFO SET.\n"); } DBGPRINT("sending...\n"); /*NdisSend(&Status, OutgoingAdapt->BindingHandle, MyPkt);*/ if(Status!=NDIS_STATUS_PENDING) { NdisIMCopySendCompletePerPacketInfo(Packet,MyPkt); NdisFreePacket(MyPkt); DBGPRINT("send completed.\n"); } else { return ( Status); } } /*NdisMEthIndicateReceive(pAdapt->MiniportHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize);*/ break; } NdisMTrIndicateReceive(pAdapt->MiniportHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize); break; case NdisMediumFddi: NdisMFddiIndicateReceive(pAdapt->MiniportHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize); break; default: ASSERT(0); break; } } while(FALSE); return Status; } |
|
沙发#
发布于:2001-10-09 19:35
我耐着性子大致看了看你的代码。
你的错误似乎是因为引用了非法内存。 原因在于你把数据包通过NDISIndicatepacket 交给了上层,然后再把这个数据包转发出去, 可是这个内存交给上层之后就被释放了,你 转发的指针是个空指针,当然要出错。 |
|
|
板凳#
发布于:2001-10-10 08:35
不是这样的,PtReceive里面的NdisgetRecievedPacket返回为空,
即NdisMIndicateReceivePacket不会起作用的,我是从lookaheadbuffer和headerbuffer自己组包后再发出去的。再次恳请帮助!! |
|
地板#
发布于:2001-10-10 12:30
你的代码发生错误的地方并不是ndissend这一行吧?
似乎在此之前,你使用packet就不正确了。 packet返回null,不知道为什么你还要使用packet, 而且又继续分配了一个mypacket,而且还拷贝oob数据 等等。其实如果返回null,那么就意味着这些数据根本 就没有oob data。你只要分配一个mypacket,然后 把这些数据拷贝到mypacket里面去就行了。 另外,你还需要判断包是否完整,还要调用transferdata。 |
|
|
地下室#
发布于:2001-10-10 14:01
通过和passthru代码仔细比较,发现你的代码
掉了 case NdisMedium802_5: 这一行代码,你仔细看一下是不是这里出了问题。 saki |
|
|
5楼#
发布于:2001-10-10 14:22
和
case NdisMedium802_5: 毫无关系,我想你的网卡不至于是TOKEN_RING的吧? 这种网卡和网络环境我从来就没有见到过。 |
|
|
6楼#
发布于:2001-10-10 18:15
我的网卡是802。3,packet返回为空,程序流程就转到case语句了,更本不会再使用packet了。 我是在case NdisMedium802_3里面做转发的,
分配了一个packet,并将数据从Headerbuffer和lookAheadBuffer里面 拷到packet里面的,然后转发。 希望不吝赐教!!十分感谢!! |
|
7楼#
发布于:2001-10-10 19:12
// Header Buffer to the Packet
NdisMoveMemory( Packet->ProtocolReserved, HeaderBuffer, HeaderBufferSize ); NdisMoveMemory( &Packet->ProtocolReserved[HeaderBufferSize], LookAheadBuffer, LookAheadBufferSize); Packet->Private.TotalLength=nDataSize; 这段代码是什么意思? |
|
|
8楼#
发布于:2001-10-10 19:30
就是将headerbuffer和lookaheadbuffer里面的数据考到packet里面
packet->protocolreserved是packet的 buffer的vitualaddress. 我很急,希望斑竹不吝赐教!! |
|
9楼#
发布于:2001-10-10 19:54
下面这是你的代码,汉字的注释是我的理解。
NdisAllocatePacket( &Status, &Packet, pAdapt->RecvPacketPoolHandle); //你分配了一个ndis_packet结构 NdisAllocateBuffer( &Status, &pNdisBuffer, pAdapt->BufferPool, Packet->ProtocolReserved, nDataSize); //你分配了一个ndis_buffer结构, //此外,你指定这个buffer结构的内存 //为packet->protocolreserved //但是未初始化的packet的这个值 //到底指向何处?我建议你看看 //protocolreserved的定义。 NdisChainBufferAtFront( Packet, pNdisBuffer); //这行代码是不会出错的。 // Header Buffer to the Packet NdisMoveMemory( Packet->ProtocolReserved, HeaderBuffer, HeaderBufferSize ); 我相信这行代码会导致访问未分配的内存 从而引起错误。 NdisMoveMemory( &Packet->ProtocolReserved[HeaderBufferSize], LookAheadBuffer, LookAheadBufferSize); Packet->Private.TotalLength=nDataSize; 你应该先调用 Status = NdisAllocateMemory( &pPacketContent, 2000, 0, HighestAcceptableAddress); 分配一个2k的缓冲区,然后判断是否应该调用transferdata, 总之得到所有数据之后,然后把这些数据拷贝到pPacketContent, 然后才是allcatebuffer,最后才是NdisChainBufferAtFront。 此外,我真是没有搞懂,你在后面分配一个mypacket到底是 干什么的,而且还把packet的oob拷贝到mypacket,这个packet 是你自己构造的,有没有oob数据你自己难道不知道吗? 总之,我的感觉是你的代码让我深度困惑和不解。 分配的packet和mypacket你可想到应该在那里释放吗? 内核内存泄漏可是很可怕的事情。 |
|
|
10楼#
发布于:2001-10-11 11:58
如果NdisSend返回不为Pending,直接再PtReceive里面释放,否
则在PtSendComplete里面释放。不知是否正确? |
|
11楼#
发布于:2001-10-11 16:52
ptreceive里面得到的数据,你必须先分配一块内存,
拷贝这些数据,然后转发,如果ndissend不是pending, 那么你当然可以释放你自己分配的内存和相关的packet/buffer, 否则在ptsendcomplete释放。 如果你要这个包继续给ip,那么你还要indicatepacket, 如果不要,直接返回nt_success,表示你已经消费了这个包。 |
|
|
12楼#
发布于:2001-10-12 12:17
消费了这个包(consume??)
是不是高消费?? hoho |
|
|
13楼#
发布于:2001-12-28 09:40
我对这个问题也比较感兴趣,如有消息请通知我!谢谢!
|
|
|
14楼#
发布于:2004-04-21 21:52
关注
|
|
|
15楼#
发布于:2004-04-23 10:13
高深 实用 关注 |
|
16楼#
发布于:2004-09-07 20:26
请问这个问题的最终解决方法是怎样的?
论坛里相关的讨论不少,可是一直没有给出最后的解答。 或许有很多种解答吧:) 继续关注,并进行调试。。。。 |
|
17楼#
发布于:2004-09-20 10:02
关注
|
|
|