LWF driver - reusing NET_BUFFER_LIST structures for sending

Hello,

I have LWF driver, which is creating and sending down its own packets using preallocated NET_BUFFER_LIST structures. My implementation is working fine on Windows 7,
however on Windows 10 I am observing increase in non-paged pool size. Poolmon points to netio.sys, so probably there must be something wrong in the way I do preallocate and reuse NBLs.

Could you please have a look below and point out what I am doing wrong?

Here is the way I allocate the pool:

NdisZeroMemory(&PoolParameters, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS));

PoolParameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
PoolParameters.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
PoolParameters.Header.Size = sizeof(PoolParameters);
PoolParameters.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT ;
PoolParameters.ContextSize = CONTEXT_BUFFER_SIZE(sizeof(NBL_MYFILTER_CONTEXT));
PoolParameters.fAllocateNetBuffer = TRUE;
PoolParameters.PoolTag = ‘ooPF’;

pFilter->SendNetBufferListPool = NdisAllocateNetBufferListPool(pFilter->FilterHandle, &PoolParameters);

Here is how I allocate single NBL:

NdisAllocateMemoryWithTag(&pDataBuffer, 1530, NBL_DATA_TAG);

pMdl = NdisAllocateMdl(pFilter->FilterHandle, pDataBuffer, DataLength);

pNetBufList = NdisAllocateNetBufferAndNetBufferList(
pFilter->SendNetBufferListPool,
CONTEXT_BUFFER_SIZE(sizeof(NBL_MYFILTER_CONTEXT)), // ContextSize
0, // ContextBackfill
pMdl, // MdlChain
0, // DataOffset
1530); // DataLength

CircularQueuePush (pFilter->sendPrealocatedNBLqueue, pNetBufList)

Here is the way I send the packet:

pNetBufList = (PNET_BUFFER_LIST) CircularQueuePop (pFilter->sendPrealocatedNBLqueue);

NET_BUFFER_DATA_LENGTH(NET_BUFFER_LIST_FIRST_NB(pNetBufList)) = uPacketSize;

pMdl = NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(pNetBufList));

NdisQueryMdl(pMdl, &pCopyBuf, &CurrLength, NormalPagePriority);

pNetBufList->SourceHandle = pFilter->FilterHandle;

NdisMoveMemory(pCopyBuf, pHeaderBuffer, uHeaderBufferSize );
NdisMoveMemory(pCopyBuf+uHeaderBufferSize, pLookaheadBuffer, uLookaheadBufferSize);

NET_BUFFER_LIST_NEXT_NBL (pNetBufList) = NULL; // last element of the list
NET_BUFFER_LIST_INFO(pNetBufList, NetBufferListFrameType) = (PVOID)NDIS_PROTOCOL_ID_TCP_IP;

if ( KeGetCurrentIrql() == DISPATCH_LEVEL )
uSendFlags = NDIS_SEND_FLAGS_DISPATCH_LEVEL;
else uSendFlags = 0;

NdisFSendNetBufferLists(pFilter->FilterHandle, pNetBufList, NDIS_DEFAULT_PORT_NUMBER, uSendFlags);

Finally in send-complete callback I simply return my NBL into the queue:

CurrNbl = NetBufferLists;
while (CurrNbl)
{
tempNbl = CurrNbl;

CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);

// unchain this nbl
NET_BUFFER_LIST_NEXT_NBL(tempNbl) = NULL;

result = CircularQueuePush (pFilter->sendPrealocatedNBLqueue, tempNbl);
}

Many thanks in advance.

Kind regards,
Daniel

Update:

I have checked my NBL received in send-complete callback and it looks that memory, which is leaking comes from NET_BUFFER_LIST_INFO.WfpNetBufferListInfo. Have a look below:

NonPaged Paged
Tag Allocs Frees Diff Used Allocs Frees Diff Used

Wfpn 13169 0 13169 8426432 0 0 0 0 WFP NBL info container , Binary: netio.sys

1: kd> !ndiskd.nbl ffffcf819bd0a910 -info

NET_BUFFER_LIST_INFO

TcpIpChecksumNetBufferListInfo 0
TcpOffloadBytesTransferred 0
IPsecOffloadV1NetBufferListInfo 0
IPsecOffloadV2NetBufferListInfo 0
TcpLargeSendNetBufferListInfo 0
TcpReceiveNoPush 0
ClassificationHandleNetBufferListInfo NULL
Ieee8021QNetBufferListInfo 0
NetBufferListCancelId NULL
MediaSpecificInformation 0
NetBufferListFrameType NDIS_PROTOCOL_ID_TCP_IP
NetBufferListHashValue 0
NetBufferListHashInfo 0
WfpNetBufferListInfo ffffe00019128d90
IPsecOffloadV2TunnelNetBufferListInfo 0
IPsecOffloadV2HeaderNetBufferListInfo 0
NetBufferListCorrelationId NULL
NetBufferListFilteringInfo 0
MediaSpecificInformationEx NULL
NblOriginalInterfaceIfIndex 0
NblReAuthWfpFlowContext NULL
TcpReceiveBytesTransferred 0
TcpRecvSegCoalesceInfo 0
RscTcpTimestampDelta 0
TcpSendOffloadsSupplementalNetBufferListInfo 0
IMReserved NULL
SwitchForwardingReserved NULL
SwitchForwardingDetail NULL
VirtualSubnetInfo 0
NblCurrentOwner 00000018

Is there any way I could release WfpNetBufferListInfo without calling NdisFreeNetBufferList on my NBL?

Many thanks,
Daniel

What version of Win 10? The early versions of Win 10 have NDIS problems.

Larry C

I am running Windows 10 version 1511 (OS Build 10586.164).

Ideas anyone?