www.pudn.com > PPPOE.rar > packet.cpp


 
//******************************************************************** 
//	ÈÕÆÚ:	2004/08/24 - 24:8:2004   20:37 
//	Ãûǰ:	tiamo 
//	ÃèÊö:	packet 
//********************************************************************* 
 
#include "Stdafx.h" 
 
// for debug memory allocate  
#define __ulFILE__										MAKE_SIG('P','A','K','T') 
 
// pool 
PACKET_POOL g_poolPacket; 
BUFFER_POOL g_poolBuffer; 
 
// ndis buffer pool 
NDIS_HANDLE g_hNdisBufferPool; 
 
// packet lookaside 
NPAGED_LOOKASIDE_LIST g_lookasidePacket; 
 
// init pool 
NDIS_STATUS InitializePoolSystem() 
{ 
	// packet pool 
	g_poolPacket.m_ulSig = PACKET_POOL_SIG; 
	g_poolPacket.m_ulFreePackets = 0; 
	g_poolPacket.m_ulMaxFreeGuard = 100; 
	g_poolPacket.m_ulPacketsPerBlock = 16; 
	g_poolPacket.m_ulProtocolReservedLen = sizeof(PROTOCOL_RESERVED); 
	g_poolPacket.m_ulTotalPackets = 0; 
 
	NdisInitializeListHead(&g_poolPacket.m_ltPacketBlocksHead); 
	NdisInitializeListHead(&g_poolPacket.m_ltFreePacketsHead); 
	NdisAllocateSpinLock(&g_poolPacket.m_lockSelf); 
 
 
	g_poolBuffer.m_ulSig = BUFFER_POOL_SIG; 
	g_poolBuffer.m_ulBufferSize = PPPOE_MAX_ETH_FRAME_SIZE; 
	g_poolBuffer.m_ulBuffersPerBlock = 10; 
	g_poolBuffer.m_ulFreeBuffers = 0; 
	g_poolBuffer.m_ulMaxFreeGuard = 100; 
	g_poolBuffer.m_ulTotalBuffers = 0; 
 
	NdisAllocateSpinLock(&g_poolBuffer.m_lockSelf); 
	NdisInitializeListHead(&g_poolBuffer.m_ltBufferBlocksHead); 
	NdisInitializeListHead(&g_poolBuffer.m_ltFreeBuffersHead); 
 
	NdisInitializeNPagedLookasideList(&g_lookasidePacket,0,0,0,sizeof(PACKET),PACKET_SIG,0); 
 
	NDIS_STATUS status = NDIS_STATUS_SUCCESS; 
 
	// for ndis buffer pool 
	NdisAllocateBufferPool(&status,&g_hNdisBufferPool,30); 
 
	if(status != NDIS_STATUS_SUCCESS) 
	{ 
		DebugError(("can't allocate ndis buffer pool status = 0x%x.\n",status)); 
	} 
 
	return status; 
} 
 
// shut down 
VOID ShutdownPoolSystem() 
{ 
	ASSERT(g_poolBuffer.m_ulSig == BUFFER_POOL_SIG); 
 
	ASSERT(g_poolPacket.m_ulSig == PACKET_POOL_SIG); 
 
	// free buffer pool 
	NdisAcquireSpinLock(&g_poolBuffer.m_lockSelf); 
 
	FreeUnusedBufferBlock(&g_poolBuffer); 
 
	NdisReleaseSpinLock(&g_poolBuffer.m_lockSelf); 
 
	// free packet pool 
	NdisAcquireSpinLock(&g_poolPacket.m_lockSelf); 
 
	FreeUnusedPacketBlock(&g_poolPacket); 
 
	NdisReleaseSpinLock(&g_poolPacket.m_lockSelf); 
 
	// free npaged list 
	NdisDeleteNPagedLookasideList(&g_lookasidePacket); 
 
	// free ndis buffer pool 
	if(g_hNdisBufferPool) 
	{ 
		NdisFreeBufferPool(g_hNdisBufferPool); 
	} 
 
	// dump packet leak 
	DumpPoolLeak(); 
 
	NdisFreeSpinLock(&g_poolPacket.m_lockSelf); 
 
	NdisFreeSpinLock(&g_poolBuffer.m_lockSelf); 
} 
 
// reference packet 
VOID ReferencePacket(PPACKET pPacket) 
{ 
	ASSERT(pPacket && pPacket->m_ulSig == PACKET_SIG); 
 
	InterlockedIncrement(&pPacket->m_lRefCount); 
} 
 
// dereference packet 
VOID DereferencePacket(PPACKET pPacket) 
{ 
	ASSERT(pPacket && pPacket->m_lRefCount > 0 && pPacket->m_ulSig == PACKET_SIG); 
 
	LONG lCount = InterlockedDecrement(&pPacket->m_lRefCount); 
 
	// ref == 0 
	if(!lCount) 
	{ 
		// header buffer chained 
		if(pPacket->m_ulFlags & PPPOE_PACKET_HEADER_BUFFER_CHAINED) 
		{ 
			ASSERT(pPacket->m_pNdisPacket); 
 
			NdisUnchainBufferAtFront(pPacket->m_pNdisPacket,&pPacket->m_pNdisHeaderBuffer); 
		} 
 
		// data chained 
		if(pPacket->m_ulFlags & PPPOE_PACKET_DATA_BUFFER_CHAINED) 
		{ 
			ASSERT(pPacket->m_pNdisPacket); 
 
			NdisUnchainBufferAtFront(pPacket->m_pNdisPacket,&pPacket->m_pNdisDataBuffer); 
		} 
 
		// allocated from our pool 
		if(pPacket->m_ulFlags & PPPOE_PACKET_BUFFER_FROM_POOL) 
		{ 
			ASSERT(pPacket->m_pNdisDataBuffer && pPacket->m_pNdisHeaderBuffer && pPacket->m_pRealBuffer); 
 
			NdisAdjustBufferLength(pPacket->m_pNdisDataBuffer,g_poolBuffer.m_ulBufferSize - PPPOE_HEADER_LEN); 
 
			FreeNdisBufferToPool(&g_poolBuffer,pPacket->m_pRealBuffer); 
		} 
 
		// allocated from ndis pool 
		if(pPacket->m_ulFlags & PPPOE_PACKET_HEADER_BUFFER_FROM_NDIS) 
		{ 
			ASSERT(pPacket->m_pNdisHeaderBuffer); 
 
			NdisFreeBuffer(pPacket->m_pNdisHeaderBuffer); 
		} 
 
		if(pPacket->m_ulFlags & PPPOE_PACKET_DATA_BUFFER_FROM_NDIS) 
		{ 
			ASSERT(pPacket->m_pNdisDataBuffer); 
 
			NdisFreeBuffer(pPacket->m_pNdisDataBuffer); 
		} 
 
		// call send complete 
		if(pPacket->m_ulFlags & PPPOE_PACKET_NEED_CALL_SEND_COMPLETE) 
		{ 
			ASSERT(pPacket->m_pNdisPacket && pPacket->m_pNdisDataBuffer); 
 
			PPROTOCOL_RESERVED pResv = reinterpret_cast(pPacket->m_pNdisPacket->ProtocolReserved); 
 
			ASSERT(pResv && pResv->m_pOrginalPacket && pResv->m_pOrginalPacket); 
 
			NdisChainBufferAtFront(pResv->m_pOrginalPacket,pPacket->m_pNdisDataBuffer); 
 
			ASSERT(pResv->m_pChannel && pResv->m_pChannel->m_hNdisVcHandle); 
 
			NdisMCoSendComplete(pPacket->m_status,pResv->m_pChannel->m_hNdisVcHandle,pResv->m_pOrginalPacket); 
 
			NdisInterlockedDecrement(&pResv->m_pChannel->m_lSendingPackets); 
		} 
 
		// free to pool 
		if(pPacket->m_ulFlags & PPPOE_PACKET_FROM_POOL) 
		{ 
			ASSERT(pPacket->m_pNdisPacket); 
 
			FreeNdisPacketToPool(&g_poolPacket,pPacket->m_pPacketItem); 
		} 
 
		// return the packet 
		if(pPacket->m_ulFlags & PPPOE_PACKET_NEED_RETURN_PACKET) 
		{ 
			ASSERT(pPacket->m_pNdisPacket && pPacket->m_pNdisReturnBuffer); 
 
			NdisChainBufferAtFront(pPacket->m_pNdisPacket,pPacket->m_pNdisReturnBuffer); 
 
			NdisReturnPackets(&pPacket->m_pNdisPacket,1); 
 
			ASSERT(pPacket->m_pBindContext); 
 
			NdisInterlockedDecrement(&pPacket->m_pBindContext->m_lPacketNeedReturn); 
		} 
 
		FreePacket(pPacket); 
	} 
} 
 
// get simple packet 
PPACKET GetSimplePacket() 
{ 
	PPACKET pRetPacket = NULL; 
 
	__try 
	{ 
		// allocate packet storage 
		pRetPacket = AllocPacket(); 
 
		// get ndis packet 
		pRetPacket->m_pNdisPacket = GetNdisPacketFromPool(&g_poolPacket,&pRetPacket->m_pPacketItem); 
 
		// set pointer 
		reinterpret_cast(pRetPacket->m_pNdisPacket->ProtocolReserved)->m_pPacket = pRetPacket; 
 
		// got here packet pointer is not null,set flags 
		pRetPacket->m_ulFlags |= PPPOE_PACKET_FROM_POOL; 
 
		// get frame buffer and ndis buffers 
		pRetPacket->m_pFrame = GetNdisBufferFromPool(&g_poolBuffer,&pRetPacket->m_pNdisHeaderBuffer,&pRetPacket->m_pNdisDataBuffer); 
 
		// chain 
		NdisChainBufferAtFront(pRetPacket->m_pNdisPacket,pRetPacket->m_pNdisDataBuffer); 
 
		// set flags 
		pRetPacket->m_ulFlags |= PPPOE_PACKET_BUFFER_FROM_POOL; 
		pRetPacket->m_ulFlags |= PPPOE_PACKET_DATA_BUFFER_CHAINED; 
 
		NdisChainBufferAtFront(pRetPacket->m_pNdisPacket,pRetPacket->m_pNdisHeaderBuffer); 
		pRetPacket->m_ulFlags |= PPPOE_PACKET_HEADER_BUFFER_CHAINED; 
 
		// set pointer 
		pRetPacket->m_pucDataBuffer = pRetPacket->m_pucFrame + PPPOE_HEADER_LEN; 
	} 
	__except(EXCEPTION_EXECUTE_HANDLER) 
	{ 
		if(pRetPacket) 
		{ 
			DereferencePacket(pRetPacket); 
 
			pRetPacket = NULL; 
		} 
	} 
 
	return pRetPacket; 
} 
 
// clone packet 
PPACKET ClonePacket(PPACKET pPacket) 
{ 
	PPACKET pRet = GetSimplePacket(); 
 
	if(pRet) 
	{ 
		NdisMoveMemory(pRet->m_pFrame,pPacket->m_pFrame,PPPOE_HEADER_LEN); 
 
		NdisMoveMemory(pRet->m_pucDataBuffer,pPacket->m_pucDataBuffer,PPPOE_MAX_DATA_SIZE); 
 
		NdisAdjustBufferLength(pRet->m_pNdisDataBuffer,ntohs(pPacket->m_pFrame->m_pppFrame.m_usLen)); 
	} 
 
	return pRet; 
} 
 
// get packet from pool 
PNDIS_PACKET GetNdisPacketFromPool(PPACKET_POOL pPacketPool,PPACKET_ITEM *ppItem) 
{ 
	PNDIS_PACKET pRet = NULL; 
 
	ASSERT(ppItem && pPacketPool && pPacketPool->m_ulSig == PACKET_POOL_SIG); 
 
	*ppItem = NULL; 
 
	NdisAcquireSpinLock(&pPacketPool->m_lockSelf); 
 
	// no free packets 
	if(IsListEmpty(&pPacketPool->m_ltFreePacketsHead)) 
	{ 
		// allocate a block 
		pRet = AddPacketBlockToPool(pPacketPool,ppItem); 
	} 
	else 
	{ 
		PLIST_ENTRY pEntry = RemoveHeadList(&pPacketPool->m_ltFreePacketsHead); 
 
		PPACKET_ITEM pItem = CONTAINING_RECORD(pEntry,PACKET_ITEM,m_ltPacketItemAnchor); 
 
		pRet = pItem->m_pNdisPacket; 
		*ppItem = pItem; 
 
		pPacketPool->m_ulFreePackets --; 
 
		pItem->m_pPacketBlock->m_ulFreePacketItems --; 
	} 
 
	NdisReleaseSpinLock(&pPacketPool->m_lockSelf); 
 
	return pRet; 
} 
 
// get ndis buffer from pool 
PPPPOE_FRAME GetNdisBufferFromPool(PBUFFER_POOL pBufferPool,PNDIS_BUFFER *ppHeaderBuffer,PNDIS_BUFFER *ppDataBuffer) 
{ 
	PPPPOE_FRAME pRet = NULL; 
 
	ASSERT(ppHeaderBuffer && ppDataBuffer && pBufferPool && pBufferPool->m_ulSig == BUFFER_POOL_SIG); 
 
	*ppHeaderBuffer = NULL; 
	*ppDataBuffer = NULL; 
 
	NdisAcquireSpinLock(&pBufferPool->m_lockSelf); 
 
	// no free packets 
	if(IsListEmpty(&pBufferPool->m_ltFreeBuffersHead)) 
	{ 
		// allocate a block 
		pRet = AddBufferBlockToPool(pBufferPool,ppHeaderBuffer,ppDataBuffer); 
	} 
	else 
	{ 
		// get a free buffer 
		PLIST_ENTRY pEntry = RemoveHeadList(&pBufferPool->m_ltFreeBuffersHead); 
 
		PBUFFER_ITEM pItem = CONTAINING_RECORD(pEntry,BUFFER_ITEM,m_ltBufferItemAnchor); 
 
		pRet = reinterpret_cast(pItem->m_pStorage); 
 
		*ppHeaderBuffer = pItem->m_pNdisHeadBuffer; 
		*ppDataBuffer = pItem->m_pNdisDataBuffer; 
 
		pBufferPool->m_ulFreeBuffers --; 
 
		pItem->m_pBufferBlock->m_ulFreeBufferItems --; 
	} 
 
	NdisReleaseSpinLock(&pBufferPool->m_lockSelf); 
 
	return pRet; 
} 
 
// allocate packet 
PPACKET AllocPacket() 
{ 
	PPACKET pRet = static_cast(NdisAllocateFromNPagedLookasideList(&g_lookasidePacket)); 
 
	NdisZeroMemory(pRet,sizeof(PACKET)); 
 
	pRet->m_lRefCount = 1; 
	pRet->m_ulSig = PACKET_SIG; 
 
	NdisInitializeListHead(&pRet->m_ltPacketAnchor); 
	 
	return pRet; 
} 
 
// free buffers to pool 
VOID FreeNdisBufferToPool(PBUFFER_POOL pPool,PVOID pRealBuffer) 
{ 
	ASSERT(pPool && pRealBuffer && pPool->m_ulSig == BUFFER_POOL_SIG); 
 
	NdisAcquireSpinLock(&pPool->m_lockSelf); 
 
	if(pPool->m_ulFreeBuffers > pPool->m_ulMaxFreeGuard) 
		FreeUnusedBufferBlock(pPool); 
 
	PBUFFER_ITEM pItem = CONTAINING_RECORD(pRealBuffer,BUFFER_ITEM,m_pStorage); 
 
	InsertHeadList(&pPool->m_ltFreeBuffersHead,&pItem->m_ltBufferItemAnchor); 
 
	pPool->m_ulFreeBuffers ++; 
	pItem->m_pBufferBlock->m_ulFreeBufferItems ++; 
 
	NdisReleaseSpinLock(&pPool->m_lockSelf); 
} 
 
// free packet to pool 
VOID FreeNdisPacketToPool(PPACKET_POOL pPool,PPACKET_ITEM pItem) 
{ 
	ASSERT(pPool && pItem && pPool->m_ulSig == PACKET_POOL_SIG); 
 
	NdisAcquireSpinLock(&pPool->m_lockSelf); 
 
	if(pPool->m_ulFreePackets > pPool->m_ulMaxFreeGuard) 
		FreeUnusedPacketBlock(pPool); 
 
	InsertHeadList(&pPool->m_ltFreePacketsHead,&pItem->m_ltPacketItemAnchor); 
 
	pPool->m_ulFreePackets ++; 
	pItem->m_pPacketBlock->m_ulFreePacketItems ++; 
 
	NdisReleaseSpinLock(&pPool->m_lockSelf); 
} 
 
// free packet  
VOID FreePacket(PPACKET pPacket) 
{ 
	ASSERT(pPacket && pPacket->m_lRefCount == 0 && pPacket->m_ulSig == PACKET_SIG); 
 
	NdisFreeToNPagedLookasideList(&g_lookasidePacket,pPacket); 
} 
 
// add packet block to pool 
PNDIS_PACKET AddPacketBlockToPool(PPACKET_POOL pPacketPool,PPACKET_ITEM *ppItem) 
{ 
	ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); 
	ASSERT(pPacketPool && pPacketPool->m_ulSig == PACKET_POOL_SIG && ppItem); 
 
	PNDIS_PACKET pRetPacket = NULL; 
 
	ULONG ulSize = pPacketPool->m_ulPacketsPerBlock * sizeof(PACKET_ITEM) + sizeof(PACKET_BLOCK); 
 
	PPACKET_BLOCK pBlock; 
 
	// allocate block memory 
	NDIS_STATUS status = AllocateMemory((PVOID*)&pBlock,ulSize,PACKET_BLOCK_SIG); 
	if(status != NDIS_STATUS_SUCCESS) 
		return NULL; 
 
	pBlock->m_ulSig = PACKET_BLOCK_SIG; 
 
	// allocate packet pool 
	NdisAllocatePacketPool(&status,&pBlock->m_hPacketPool,pPacketPool->m_ulPacketsPerBlock,pPacketPool->m_ulProtocolReservedLen); 
	if(status != NDIS_STATUS_SUCCESS) 
	{ 
		FreeMemory(pBlock,ulSize); 
		return NULL; 
	} 
 
	// set value 
	pBlock->m_ulTotalPacketItems = pPacketPool->m_ulPacketsPerBlock; 
	pBlock->m_ulFreePacketItems = pPacketPool->m_ulPacketsPerBlock - 1; 
	pBlock->m_pPacketPool = pPacketPool; 
 
	ULONG i; 
	for(i = 0; i < pBlock->m_ulTotalPacketItems; i ++) 
	{ 
		// prepare item 
		PPACKET_ITEM pItem = pBlock->m_arrayItems + i; 
		pItem->m_pPacketBlock = pBlock; 
		pItem->m_ulSig = PACKET_ITEM_SIG; 
 
		NdisAllocatePacket(&status,&pItem->m_pNdisPacket,pBlock->m_hPacketPool); 
		if(status != NDIS_STATUS_SUCCESS) 
		{ 
			break; 
		} 
	} 
 
	// unsuccessful 
	if(status != NDIS_STATUS_SUCCESS) 
	{ 
		for(ULONG j = 0; j < i ; j ++) 
		{ 
			// free it 
			PPACKET_ITEM pItem = pBlock->m_arrayItems + j; 
			NdisFreePacket(pItem->m_pNdisPacket); 
		} 
 
		// free block 
		FreeMemory(pBlock,ulSize); 
	} 
	else 
	{ 
		// update pool value 
		pPacketPool->m_ulFreePackets += pBlock->m_ulFreePacketItems; 
		pPacketPool->m_ulTotalPackets += pPacketPool->m_ulPacketsPerBlock; 
 
		// link block 
		InsertHeadList(&pPacketPool->m_ltPacketBlocksHead,&pBlock->m_ltPacketBlockAnchor); 
 
		// link free packet 
		PPACKET_ITEM pItem; 
		for(i = 1; i < pBlock->m_ulTotalPacketItems; i ++) 
		{ 
			pItem = pBlock->m_arrayItems + i; 
			InsertHeadList(&pPacketPool->m_ltFreePacketsHead,&pItem->m_ltPacketItemAnchor); 
		} 
 
		// return the first one 
		pItem = pBlock->m_arrayItems; 
 
		InitializeListHead(&pItem->m_ltPacketItemAnchor); 
 
		pRetPacket = pItem->m_pNdisPacket; 
 
		*ppItem = pItem; 
	} 
 
	return pRetPacket; 
} 
 
// add buffer block to pool 
PPPPOE_FRAME AddBufferBlockToPool(PBUFFER_POOL pBufferPool,PNDIS_BUFFER *ppHeadBuffer,PNDIS_BUFFER *ppDataBuffer) 
{ 
	ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); 
	ASSERT(pBufferPool && pBufferPool->m_ulSig == BUFFER_POOL_SIG && ppHeadBuffer && ppDataBuffer); 
 
	PPPPOE_FRAME pRetFrame = NULL; 
 
	ULONG ulSize = pBufferPool->m_ulBuffersPerBlock *(pBufferPool->m_ulBufferSize + sizeof(BUFFER_ITEM)) + sizeof(BUFFER_BLOCK); 
 
	// round it 
	ulSize = (ulSize + 7) & 0xfffffff8; 
 
	PBUFFER_BLOCK pBlock; 
 
	// allocate block memory 
	NDIS_STATUS status = AllocateMemory((PVOID*)&pBlock,ulSize,BUFFER_POOL_SIG); 
	if(status != NDIS_STATUS_SUCCESS) 
		return NULL; 
 
	pBlock->m_ulSig = BUFFER_BLOCK_SIG; 
 
	// allocate buffer pool 
	NdisAllocateBufferPool(&status,&pBlock->m_hBufferPool,pBufferPool->m_ulBuffersPerBlock * 2); 
	if(status != NDIS_STATUS_SUCCESS) 
	{ 
		FreeMemory(pBlock,ulSize); 
		return NULL; 
	} 
 
	// set value 
	pBlock->m_ulTotalBufferItems = pBufferPool->m_ulBuffersPerBlock; 
	pBlock->m_ulFreeBufferItems = pBufferPool->m_ulBuffersPerBlock - 1; 
	pBlock->m_pBufferPool = pBufferPool; 
 
	ULONG i; 
	for(i = 0; i < pBlock->m_ulTotalBufferItems; i ++) 
	{ 
		// prepare item 
		PBUFFER_ITEM pItem = GET_ITEM_FROM_BLOCK_BY_INDEX(pBlock,i,pBufferPool->m_ulBufferSize); 
 
		pItem->m_pBufferBlock = pBlock; 
		pItem->m_ulSig = BUFFER_ITEM_SIG; 
 
		NdisAllocateBuffer(&status,&pItem->m_pNdisHeadBuffer,pBlock->m_hBufferPool,pItem->m_pStorage,PPPOE_HEADER_LEN); 
 
		if(status != NDIS_STATUS_SUCCESS) 
		{ 
			break; 
		} 
 
		NdisAllocateBuffer(&status,&pItem->m_pNdisDataBuffer,pBlock->m_hBufferPool,pItem->m_pStorage + PPPOE_HEADER_LEN, 
						   pBufferPool->m_ulBufferSize - PPPOE_HEADER_LEN); 
 
		if(status != NDIS_STATUS_SUCCESS) 
		{ 
			NdisFreeBuffer(pItem->m_pNdisHeadBuffer); 
			break; 
		} 
	} 
 
	// unsuccessful 
	if(status != NDIS_STATUS_SUCCESS) 
	{ 
		for(ULONG j = 0; j < i ; j ++) 
		{ 
			// free it 
			PBUFFER_ITEM pItem = GET_ITEM_FROM_BLOCK_BY_INDEX(pBlock,i,pBufferPool->m_ulBufferSize); 
 
			NdisFreeBuffer(pItem->m_pNdisHeadBuffer); 
			NdisFreeBuffer(pItem->m_pNdisDataBuffer); 
		} 
 
		// free block 
		FreeMemory(pBlock,ulSize); 
	} 
	else 
	{ 
		// update pool value 
		pBufferPool->m_ulFreeBuffers += pBlock->m_ulFreeBufferItems; 
		pBufferPool->m_ulTotalBuffers += pBufferPool->m_ulBuffersPerBlock; 
 
		// link block 
		InsertHeadList(&pBufferPool->m_ltBufferBlocksHead,&pBlock->m_ltBufferBlockAnchor); 
 
		// link free packet 
		PBUFFER_ITEM pItem; 
		for(i = 1; i < pBlock->m_ulTotalBufferItems; i ++) 
		{ 
			PBUFFER_ITEM pItem =  GET_ITEM_FROM_BLOCK_BY_INDEX(pBlock,i,pBufferPool->m_ulBufferSize); 
 
			InsertHeadList(&pBufferPool->m_ltFreeBuffersHead,&pItem->m_ltBufferItemAnchor); 
		} 
 
		// return the first one 
		pItem = pBlock->m_arrayItem; 
 
		InitializeListHead(&pItem->m_ltBufferItemAnchor); 
 
		*ppHeadBuffer = pItem->m_pNdisHeadBuffer; 
		*ppDataBuffer = pItem->m_pNdisDataBuffer; 
 
		pRetFrame = reinterpret_cast(pItem->m_pStorage); 
	} 
 
	return pRetFrame; 
} 
 
// free unused packet block 
VOID FreeUnusedPacketBlock(PPACKET_POOL pPacketPool) 
{ 
	ASSERT(pPacketPool && pPacketPool->m_ulSig == PACKET_POOL_SIG); 
 
	ULONG ulSize = pPacketPool->m_ulPacketsPerBlock * sizeof(PACKET_ITEM) + sizeof(PACKET_BLOCK); 
 
	PLIST_ENTRY pEntry = pPacketPool->m_ltPacketBlocksHead.Flink; 
 
	while(pEntry != &pPacketPool->m_ltPacketBlocksHead) 
	{ 
		PPACKET_BLOCK pBlock = CONTAINING_RECORD(pEntry,PACKET_BLOCK,m_ltPacketBlockAnchor); 
 
		ASSERT(pBlock && pBlock->m_ulSig == PACKET_BLOCK_SIG); 
 
		pEntry = pEntry->Flink; 
 
		if(pBlock->m_ulFreePacketItems == pBlock->m_ulTotalPacketItems) 
		{ 
			for(ULONG j = 0; j < pBlock->m_ulTotalPacketItems ; j ++) 
			{ 
				// free it 
				PPACKET_ITEM pItem = pBlock->m_arrayItems + j; 
 
				ASSERT(pItem && pItem->m_ulSig == PACKET_ITEM_SIG); 
 
				NdisFreePacket(pItem->m_pNdisPacket); 
 
				RemoveEntryList(&pItem->m_ltPacketItemAnchor); 
			} 
 
			pPacketPool->m_ulTotalPackets -= pBlock->m_ulTotalPacketItems; 
			pPacketPool->m_ulFreePackets -= pBlock->m_ulFreePacketItems; 
 
			RemoveEntryList(&pBlock->m_ltPacketBlockAnchor); 
 
			NdisFreePacketPool(pBlock->m_hPacketPool); 
 
			// free block 
			FreeMemory(pBlock,ulSize); 
		} 
	} 
} 
 
// free unused packet block 
VOID FreeUnusedBufferBlock(PBUFFER_POOL pBufferPool) 
{ 
	ASSERT(pBufferPool && pBufferPool->m_ulSig == BUFFER_POOL_SIG); 
 
	ULONG ulSize = pBufferPool->m_ulBuffersPerBlock *(pBufferPool->m_ulBufferSize + sizeof(BUFFER_ITEM)) + sizeof(BUFFER_BLOCK); 
 
	ulSize = (ulSize + 7) & 0xfffffff8; 
 
	PLIST_ENTRY pEntry = pBufferPool->m_ltBufferBlocksHead.Flink; 
 
	while(pEntry != &pBufferPool->m_ltBufferBlocksHead) 
	{ 
		PBUFFER_BLOCK pBlock = CONTAINING_RECORD(pEntry,BUFFER_BLOCK,m_ltBufferBlockAnchor); 
 
		ASSERT(pBlock && pBlock->m_ulSig == BUFFER_BLOCK_SIG); 
 
		pEntry = pEntry->Flink; 
 
		if(pBlock->m_ulFreeBufferItems == pBlock->m_ulTotalBufferItems) 
		{ 
			for(ULONG j = 0; j < pBlock->m_ulTotalBufferItems ; j ++) 
			{ 
				// free it 
				PBUFFER_ITEM pItem =  GET_ITEM_FROM_BLOCK_BY_INDEX(pBlock,j,pBufferPool->m_ulBufferSize); 
 
				ASSERT(pItem && pItem->m_ulSig == BUFFER_ITEM_SIG && pItem->m_pNdisDataBuffer && pItem->m_pNdisHeadBuffer); 
				 
				NdisFreeBuffer(pItem->m_pNdisHeadBuffer); 
 
				NdisFreeBuffer(pItem->m_pNdisDataBuffer);	 
 
				RemoveEntryList(&pItem->m_ltBufferItemAnchor); 
			} 
 
			pBufferPool->m_ulTotalBuffers -= pBlock->m_ulTotalBufferItems; 
			pBufferPool->m_ulFreeBuffers -= pBlock->m_ulFreeBufferItems; 
 
			RemoveEntryList(&pBlock->m_ltBufferBlockAnchor); 
 
			NdisFreeBufferPool(pBlock->m_hBufferPool); 
 
			// free block 
			FreeMemory(pBlock,ulSize); 
		} 
	} 
} 
 
// dump packet leak 
VOID DumpPoolLeak() 
{ 
	NdisAcquireSpinLock(&g_poolBuffer.m_lockSelf); 
 
	PLIST_ENTRY pEntry = g_poolBuffer.m_ltBufferBlocksHead.Flink; 
 
	while(pEntry != &g_poolBuffer.m_ltBufferBlocksHead) 
	{ 
		PBUFFER_BLOCK pBlock = CONTAINING_RECORD(pEntry,BUFFER_BLOCK,m_ltBufferBlockAnchor); 
 
		ASSERT(pBlock && pBlock->m_ulSig == BUFFER_BLOCK_SIG); 
 
		pEntry = pEntry->Flink; 
 
		DebugError(("buffer block = 0x%x,unfree buffer items count = %d\n", 
					pBlock,pBlock->m_ulTotalBufferItems - pBlock->m_ulFreeBufferItems)); 
	} 
 
	NdisReleaseSpinLock(&g_poolBuffer.m_lockSelf); 
 
	NdisAcquireSpinLock(&g_poolPacket.m_lockSelf); 
 
	pEntry = g_poolPacket.m_ltPacketBlocksHead.Flink; 
 
	while(pEntry != &g_poolPacket.m_ltPacketBlocksHead) 
	{ 
		PPACKET_BLOCK pBlock = CONTAINING_RECORD(pEntry,PACKET_BLOCK,m_ltPacketBlockAnchor); 
 
		ASSERT(pBlock && pBlock->m_ulSig == PACKET_BLOCK_SIG); 
 
		pEntry = pEntry->Flink; 
 
		DebugError(("packet block = 0x%x,unfree packet items count = %d\n", 
					pBlock,pBlock->m_ulTotalPacketItems - pBlock->m_ulFreePacketItems)); 
	} 
 
	NdisReleaseSpinLock(&g_poolPacket.m_lockSelf); 
}