Might make sure that your logic never can put the same packet into multiple
queues.
Thomas
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Monday, March 30, 2015 7:59 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Getting BSOD from NDIS LWF driver
Hi Tim,
I am using “!analyze -v”, as it came once in my customer laptop. So i am
giving the minidump analysis.
What other information you need from me, can you please mention.
And I am sharing the code,
As per the code FilterHandle is of type PVOID VOID FilterSendNetBufferLists(
IN NDIS_HANDLE FilterModuleContext,
IN PNET_BUFFER_LIST NetBufferLists,
IN NDIS_PORT_NUMBER PortNumber,
IN ULONG SendFlags
)
{
PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PNET_BUFFER_LIST CurrNbl;
BOOLEAN DispatchLevel;
NDF_NBL_QUEUE_HEADER PacketSendQueue; // Packets to passthrough to
lower-level miniport
NDF_NBL_QUEUE_HEADER NblDropQueue; // to return to higher-level
protocol by send completion /*added new */
NDF_NBL_QUEUE_HEADER PacketCompleteQueue; // Packets to return to
higher-level protocol by send completion
NDF_NBL_QUEUE_HEADER NblDelayQueue; // NBLs to passthrough to
lower-level miniport /*added new */
ULONG NumberOfNetBufferLists = 0; // Diagnostic
PCASIM_SEND_FILTER_ACTION SendAction;
Ndf_DbgPrint(DL_TRACE, DBG_SEND, “===>SendNetBufferList: NBL = %p.\n”,
NetBufferLists);
do
{
PNET_BUFFER_LIST pCurrentNetBufferList;
PNET_BUFFER_LIST pNextNetBufList;
DispatchLevel = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags);
//
// Complete Immediately If In Invalid State
// ----------------------------------------
// Should never be given packets to send if not running…
//
NDF_ACQUIRE_SPIN_LOCK(&pFilter->Lock, DispatchLevel);
//
// If the filter is not in running state, fail the send
//
if (pFilter->State != FilterRunning)
{
NDF_RELEASE_SPIN_LOCK(&pFilter->Lock, DispatchLevel);
if( NetBufferLists != NULL )
{
CurrNbl = NetBufferLists;
while (CurrNbl)
{
NET_BUFFER_LIST_STATUS(CurrNbl) = NDIS_STATUS_PAUSED;
CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
}
NdisFSendNetBufferListsComplete(pFilter->FilterHandle,
NetBufferLists,
DispatchLevel ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0);
}
return;
}
NDF_RELEASE_SPIN_LOCK(&pFilter->Lock, DispatchLevel);
NDF_INIT_NBL_QUEUE_HEADER( &PacketSendQueue );
NDF_INIT_NBL_QUEUE_HEADER( &PacketCompleteQueue );
NDF_INIT_NBL_QUEUE_HEADER( &NblDropQueue );
NDF_INIT_NBL_QUEUE_HEADER( &NblDelayQueue );
PacketSendQueue.Head = NetBufferLists; // MAGIC!!! Ignore tail at
this point
// if( IsListEmpty( &pFilter->W32NOpenList ) )
// {
// // Nothing to Do…
////DbgPrint("nothing to do ");
// goto PassthruThePacket;
// }
//count the number of netbufferlist
pCurrentNetBufferList = NetBufferLists;
while(pCurrentNetBufferList != NULL)
{
++NumberOfNetBufferLists;
pCurrentNetBufferList =
NET_BUFFER_LIST_NEXT_NBL(pCurrentNetBufferList);
}
// Walk the List of NetBufferLists
// -------------------------------
// The NET_BUFFER_LIST passed into this routine can be the head
// of a singly-linked list containing multiple NET_BUFFER_LIST
// members.
//
pCurrentNetBufferList = NetBufferLists;
// Reinitialize the Packet Send Queue
NDF_INIT_NBL_QUEUE_HEADER( &PacketSendQueue );
while (pCurrentNetBufferList != NULL)
{
BOOLEAN bAcceptedSend = FALSE;
BOOLEAN Result;
PW32N_OPEN_CONTEXT pW32NOpenContext = NULL;
NDF_PACKET_METADATA MetaData;
ULONG nFilterAction;
PNET_BUFFER pCurrentNetBuffer, pNextNetBuffer; /* added
new */
USHORT NumberOfNetBuffers = 0;
nFilterAction = REDIR_PASS_PACKET;
pW32NOpenContext = NULL;
//
// Locate the Next NetBufferList
//
pNextNetBufList = NET_BUFFER_LIST_NEXT_NBL (pCurrentNetBufferList);
NET_BUFFER_LIST_NEXT_NBL (pCurrentNetBufferList) = NULL;
pCurrentNetBuffer = NET_BUFFER_LIST_FIRST_NB( pCurrentNetBufferList
);
ASSERT( pCurrentNetBuffer );
if( pCurrentNetBuffer == NULL )
break;
// Count the NetBuffers Chained to This NetBufferList
pNextNetBuffer = pCurrentNetBuffer;
while( pNextNetBuffer != NULL )
{
++NumberOfNetBuffers;
pNextNetBuffer = NET_BUFFER_NEXT_NB( pNextNetBuffer );
}
//
// Operate on the First NetBuffer in the Current NetBufferList
// -----------------------------------------------------------
// Get first MDL and data length from the first NB in the current
NBL.
//
// Note that this implementation assumes that all NBs in a NBL are
of
// the same protocol type, same network addresses. If the first NB
// matches the MetaData then the rest will as well.
//
Result = Ndf_GetMetaDataFromNetBuffer(
NET_BUFFER_LIST_FIRST_NB( pCurrentNetBufferList ),
FALSE,
FALSE,
pFilter->MediaType,
&MetaData
);
if( !Result)
{
//PAssthrough Send this netbufferList
NDF_INSERT_TAIL_NBL_QUEUE(&PacketSendQueue,pCurrentNetBufferList);
goto NextNBL;
}
if( Result )
{
//
// Determine Filter Action by Examining MetaData and Filter
Rules
//
// ATTENTION!!! If this function is successful it may return a
non-NULL
// pointer in pW32NOpenContext. In this case the call will have
added
// a reference to the W32N_OPEN_CONTEXT structure that must
eventually
// be dereferenced.
//
nFilterAction = IMFilter_Handler(pFilter, &MetaData,
&pW32NOpenContext, TRUE);
//nFilterAction = IMFilter_GetRedirectionAction(
pFilter, &MetaData, &pW32NOpenContext, TRUE );
/*We are not using pW32NOpenContext */
/*
if( pW32NOpenContext == NULL )
{
//DbgPrint(" nFilterAction =
REDIR_PASS_PACKET;");
nFilterAction = REDIR_PASS_PACKET;
}
*/
}
//
// Handle Based On IP Filter Action
//
if( nFilterAction == REDIR_PASS_PACKET )
{
Ndf_DbgPrint(DL_TRACE, DBG_SEND, “SendNetBufferList: Passing
0x%4.4X Packet\n”, MetaData.Link.Ether.EtherType );
// Passthrough Send This Packet
NDF_INSERT_TAIL_NBL_QUEUE( &PacketSendQueue,
pCurrentNetBufferList );
goto NextNBL;
}
if( ( pW32NOpenContext!= NULL ) && ( nFilterAction &
REDIR_READ_PACKET ) )
{
PPKT_LOG_RECORD pLogRec = NULL;
ASSERT( pW32NOpenContext ); // A “Must Have”!!!
Ndf_DbgPrint(DL_TRACE, DBG_SEND, “SendNetBufferList: Reading
0x%4.4X Packet Src/Dst: 0x%8.8X/0x%8.8X\n”,
MetaData.Link.Ether.EtherType,
(MetaData.Net.pIPv4Header)->ip_src.s_addr,
(MetaData.Net.pIPv4Header)->ip_dst.s_addr
);
// Make Log Records For The NetBufferList
pLogRec = IMFilter_MakeLogRecordFromSendNetBufferList(
pCurrentNetBufferList,
PortNumber,
nFilterAction,
pW32NOpenContext
);
if( pLogRec )
{
// Add The Log Record To The Log Record List
NDF_ACQUIRE_SPIN_LOCK(
&pW32NOpenContext->m_PendingPktLogRecordListLock, FALSE );
InsertTailList(
&pW32NOpenContext->m_PendingPktLogRecordList,
(PLIST_ENTRY )pLogRec
);
NDF_RELEASE_SPIN_LOCK(
&pW32NOpenContext->m_PendingPktLogRecordListLock, FALSE );
}
else
{
// Passthrough Send This Packet
NDF_INSERT_TAIL_NBL_QUEUE( &PacketSendQueue,
pCurrentNetBufferList );
}
}
if( nFilterAction & REDIR_BLOCK_PACKET )
{
Ndf_DbgPrint(DL_TRACE, DBG_SEND, “SendNetBufferList: Blocking
0x%4.4X Packet Src/Dst: 0x%8.8X/0x%8.8X\n”,
MetaData.Link.Ether.EtherType,
(MetaData.Net.pIPv4Header)->ip_src.s_addr,
(MetaData.Net.pIPv4Header)->ip_dst.s_addr
);
// Complete This Send with Success
NET_BUFFER_LIST_STATUS(pCurrentNetBufferList) =
NDIS_STATUS_SUCCESS;
NDF_INSERT_TAIL_NBL_QUEUE( &PacketCompleteQueue,
pCurrentNetBufferList );
}
else
{
Ndf_DbgPrint(DL_TRACE, DBG_SEND, “SendNetBufferList: Passing
0x%4.4X Packet\n”, MetaData.Link.Ether.EtherType );
// Passthrough Send This Packet
NDF_INSERT_TAIL_NBL_QUEUE( &PacketSendQueue,
pCurrentNetBufferList );
}
NextNBL:
if( pW32NOpenContext )
{
//
// Remove Extra Reference If Necessary
// -----------------------------------
// IMFilter_GetRedirectionAction may return a non-NULL pointer
// in pW32NOpenContext. If so, then it has also incremented the
// reference count. This extra reference must be removed here.
//
W32N_DerefOpenContext( pW32NOpenContext );
}
// Move to the Next NetBufferList
pCurrentNetBufferList = pNextNetBufList;
}
//PassthruThePacket:
//
// Send Passthrough Packets
//
if( NDF_GET_NBL_QUEUE_HEAD( &PacketSendQueue ) )
{
NdisFSendNetBufferLists(
pFilter->FilterHandle,
NDF_GET_NBL_QUEUE_HEAD( &PacketSendQueue ),
PortNumber,
SendFlags
);
}
//
// Complete Blocked Packets
//
if( NDF_GET_NBL_QUEUE_HEAD( &PacketCompleteQueue ) )
{
NdisFSendNetBufferListsComplete(
pFilter->FilterHandle,
NDF_GET_NBL_QUEUE_HEAD( &PacketCompleteQueue ),
DispatchLevel ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0
);
}
}
while (FALSE);
// Process Pending Reads If Filter Send/Receive Handlers Installed
if( pFilter->FilterHandlersInstalled )
{
//
// Attempt to Process Any Pending Reads
//
IMFilter_ProcessPendingReadsOnFilter( pFilter );
}
Ndf_DbgPrint(DL_TRACE, DBG_SEND, “<===SendNetBufferList: NBL Count: %d;
Status = %8x.\n”,
NumberOfNetBufferLists, Status
);
}
NTDEV is sponsored by OSR
Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
OSR is HIRING!! See http://www.osr.com/careers
For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars
To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer