NDIS Filter Driver

Hello All,
I am trying to do a “customized mac bridge” between two lans.I
started with LWF of DDK. My project is like this. I have virtual lan
device (used from DDK).and two NIC’s on the same machine. Every
packet you receive on these two nics should be sent to Virtual NIC as
a copy.
So in the FilterReceivenetBufferlists I am cloning the each packet and
sending it to the Virtual Miniport. I have attached my function here.
But the problem I am facing is the whenever i try to file transfer or
big network load receive ,network connection is just disconnected.but
with smaller ping traffics it just works fine.After the drop of
connection I need to restart the machine(it doesn’t hang) to start the
network.

Can anybody suggest me what must be happening? I think there is some
problem with freeing the clone buffer list.What will be best place to
free this buffer?

///

//////////
do
{

DispatchLevel = NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags);

ASSERT(NumberOfNetBufferLists >= 1);

{
CurrNbl = NetBufferLists;
while (CurrNbl)
{

DbgPrint(" RecvNetBufferList: CurrNbl = %p\n",
CurrNbl);
if(g_bIsVirtual==FALSE)
{
ClonedList=NdisAllocateCloneNetBufferList(CurrNbl,0,0,0);
Status =
NdisAllocateNetBufferListContext(ClonedList,sizeof(IM_NBL_ENTRY), 0,
FILTER_TAG);

if (Status != NDIS_STATUS_SUCCESS)
{
NdisFreeCloneNetBufferList(ClonedList,0);
}
else
{
CloneRecvContext = (PIM_NBL_ENTRY)
NET_BUFFER_LIST_CONTEXT_DATA_START(ClonedList);
NdisZeroMemory(CloneRecvContext, sizeof(IM_NBL_ENTRY));
// SendContext->PreviousSourceHandle =
CurrNbl->SourceHandle;
CloneRecvContext->pFilter = gpVirtual;
ClonetFilter = gpVirtual;
NdisFIndicateReceiveNetBufferLists(
ClonetFilter->FilterHandle,
ClonedList,
PortNumber,
1,
ReceiveFlags);
//NdisFreeCloneNetBufferList(ClonedList,0);
}
}//End of checking whether it is virtual or not.
/*CHEATING END*/

NetBufferLists = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
NET_BUFFER_LIST_NEXT_NBL(CurrNbl) = NULL;

{
NET_BUFFER *pNB = NET_BUFFER_LIST_FIRST_NB(CurrNbl);
DbgPrint(" Data Length:%d\n",
NET_BUFFER_DATA_LENGTH(pNB));
pEthFrame = NdisGetDataBuffer(pNB, 14, NULL, 1, 0);
}

Status = NdisAllocateNetBufferListContext(CurrNbl,
sizeof(IM_NBL_ENTRY), 0, FILTER_TAG);

if (Status != NDIS_STATUS_SUCCESS)
{
NdisFReturnNetBufferLists(
pFilter->FilterHandle, CurrNbl,
DispatchLevel ?
NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0);
}
else
{
RecvContext = (PIM_NBL_ENTRY)
NET_BUFFER_LIST_CONTEXT_DATA_START(CurrNbl);
NdisZeroMemory(RecvContext, sizeof(IM_NBL_ENTRY));
// SendContext->PreviousSourceHandle =
CurrNbl->SourceHandle;
RecvContext->pFilter = pFilter;
tFilter = pFilter;

DbgPrint(" toVNIC:%d\n", toVNIC);

}

DbgPrint(" LWF==>%c%c TCPIP==>%c%c\n",
pFilter->MiniportFriendlyName.Buffer[13],
pFilter->MiniportFriendlyName.Buffer[14],
tFilter->MiniportFriendlyName.Buffer[13],
tFilter->MiniportFriendlyName.Buffer[14]);

NdisFIndicateReceiveNetBufferLists(
tFilter->FilterHandle,
CurrNbl,
PortNumber,
1,
ReceiveFlags);

}
CurrNbl = NetBufferLists;
}
}
} while (FALSE);


Thanks
Abhijeet Kolekar

> I have virtual lan

device (used from DDK).and two NIC’s on the same machine. Every
packet you receive on these two nics should be sent to Virtual NIC as
a copy.
So in the FilterReceivenetBufferlists I am cloning the each packet and
sending it to the Virtual Miniport

Is this virtual miniport’s protocol side bound to physical NICs??? If it is, then it receives packets from them anyway. If it is not bound to physical NICs, then it is not related to LWF that is bound to them either, so that your indications are not going to reach it. In other words, no matter how you look at it, your project just does not seem to make sense, at least in its current implementation. It would make sense if virtual miniport was bound only to NIC X, and you wanted to forward a copy of data that arrives on NIC Y ( i.e the one it is not bound to) to it, using NDIS_HANDLE that corresponds to binding between NIC X and your LWF.

I think there is some problem with freeing the clone buffer list.

Indeed, I see a *HUGE* problem here, although it is not related to the memory leak…

What will be best place to free this buffer?

It does not matter *WHERE* you free it - it depends on *HOW* you do things…

If you don’t specify NDIS_RECEIVE_FLAG_RESOURCES, then your buffer will be returned to FilterReturnNetBufferLists() so that you can free it. Alternatively, you can
set NDIS_RECEIVE_FLAG_RESOURCES in ‘ReceiveFlags’ parameter of NdisFIndicateReceiveNetBufferLists(), which forces overlying drivers to copy packet data. If you do it this way, then you have to free it in the function that calls NdisFIndicateReceiveNetBufferLists(), which is FilterReceiveNetBufferList() in your case.

Now look at what you do:

NdisFIndicateReceiveNetBufferLists( ClonetFilter->FilterHandle,
ClonedList, PortNumber, 1, ReceiveFlags);
NdisFreeCloneNetBufferList(ClonedList,0);

Once you have not specified NDIS_RECEIVE_FLAG_RESOURCES flag, overlying drivers are free to access it until calling NdisReturnNetBufferLists(), i.e. something that can be done at some later stage. However, you free the list right after
NdisFIndicateReceiveNetBufferLists() returns control. In other words, overlying drivers may eventually access a list that you have already freed. BANG!!!

Concerning the memory leak, I can see 2 calls to NdisAllocateNetBufferListContext(), but not a single one to NdisFreeNetBufferListContext()…

Anton Bassov

Hello Anton,
Thank you for help.I am new to windows networking driver development.
Regarding the virtual miniport. I am using netvmini that comes with DDK. It
is not bound to any physical NIC. My project is somewhat like this. Other
machines on the network would see this Virtual miniport adapter only not the
other physical NICs. So every packet that comes in should be copied and sent
to virtual NIC.I am taking care of ARP in filter driver’s send function.
Also I am freeing the buffers in FilterReturnNetBufferLists which has
NdisReturnNetBufferLists.

Do you think this is the right way to go.Any help will be appreciated.
Thanks

On 3/28/07, xxxxx@hotmail.com wrote:
>
> > I have virtual lan
> > device (used from DDK).and two NIC’s on the same machine. Every
> > packet you receive on these two nics should be sent to Virtual NIC as
> > a copy.
> > So in the FilterReceivenetBufferlists I am cloning the each packet and
> > sending it to the Virtual Miniport
>
> Is this virtual miniport’s protocol side bound to physical NICs??? If it
> is, then it receives packets from them anyway. If it is not bound to
> physical NICs, then it is not related to LWF that is bound to them either,
> so that your indications are not going to reach it. In other words, no
> matter how you look at it, your project just does not seem to make sense, at
> least in its current implementation. It would make sense if virtual miniport
> was bound only to NIC X, and you wanted to forward a copy of data that
> arrives on NIC Y ( i.e the one it is not bound to) to it, using
> NDIS_HANDLE that corresponds to binding between NIC X and your LWF.
>
>
> > I think there is some problem with freeing the clone buffer list.
>
> Indeed, I see a HUGE problem here, although it is not related to the
> memory leak…
>
> > What will be best place to free this buffer?
>
> It does not matter WHERE you free it - it depends on HOW you do
> things…
>
> If you don’t specify NDIS_RECEIVE_FLAG_RESOURCES, then your buffer will be
> returned to FilterReturnNetBufferLists() so that you can free it.
> Alternatively, you can
> set NDIS_RECEIVE_FLAG_RESOURCES in ‘ReceiveFlags’ parameter of
> NdisFIndicateReceiveNetBufferLists(), which forces overlying drivers to copy
> packet data. If you do it this way, then you have to free it in the function
> that calls NdisFIndicateReceiveNetBufferLists(), which is
> FilterReceiveNetBufferList() in your case.
>
> Now look at what you do:
>
>
> > NdisFIndicateReceiveNetBufferLists( ClonetFilter->FilterHandle,
> > ClonedList, PortNumber, 1, ReceiveFlags);
> > NdisFreeCloneNetBufferList(ClonedList,0);
>
> Once you have not specified NDIS_RECEIVE_FLAG_RESOURCES flag, overlying
> drivers are free to access it until calling NdisReturnNetBufferLists(),
> i.e. something that can be done at some later stage. However, you free the
> list right after
> NdisFIndicateReceiveNetBufferLists() returns control. In other words,
> overlying drivers may eventually access a list that you have already freed.
> BANG!!!
>
> Concerning the memory leak, I can see 2 calls to
> NdisAllocateNetBufferListContext(), but not a single one to
> NdisFreeNetBufferListContext()…
>
>
> Anton Bassov
>
>
> —
> Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>


Thanks
Abhijeet Kolekar