ok, here’s the code:
FilterSendNetBufferLists code
NET_BUFFER_LIST* CloneNblNormal(In NET_BUFFER_LIST* pNbl, In PSX_SWITCH_OBJECT vSwitch)
{
NET_BUFFER_LIST* pClonedNbl = NULL;
NDIS_STATUS status = 0;
pClonedNbl = NdisAllocateCloneNetBufferList(pNbl, g_hNblPool, g_hNbPool, 0);
if (!pClonedNbl) {
DbgPrint(“CloneNbl: NdisAllocateFragmentNetBufferList failed”);
ASSERT(pClonedNbl);
}
pClonedNbl->SourceHandle = vSwitch->ndisFilterHandle;
status = vSwitch->ndisSwitchHandlers.AllocateNetBufferListForwardingContext(vSwitch->ndisSwitchContext, pClonedNbl);
if (status != NDIS_STATUS_SUCCESS) {
ASSERT(0);
}
status = vSwitch->ndisSwitchHandlers.CopyNetBufferListInfo(vSwitch->ndisSwitchContext, pClonedNbl, pNbl, 0);
if (status != NDIS_STATUS_SUCCESS) {
ASSERT(0);
}
pClonedNbl->ParentNetBufferList = pNbl;
return pClonedNbl;
}
static VOID _ProcessOneNblIngress(PSX_SWITCH_OBJECT vSwitch, ULONG sendFlags, NET_BUFFER_LIST* pNbl)
{
BOOLEAN require_gre = FALSE;
NET_BUFFER_LIST* pClonedNbl = NULL;
VOID* pNetBuffer = NULL;
ULONG ethHeaderSize = sizeof(ABC_ETHERNET_HEADER);
//check if either of the NBs in the NBL requires GRE encapsulation.
require_gre = CheckNbsRequireGre(pNbl, &pNetBuffer);
if (require_gre)
{
NdisAdvanceNetBufferListDataStart(pNbl, ethHeaderSize, FALSE, NULL);
//attempt cloning without fragmenting for the moment
pClonedNbl = CloneNblNormal(pNbl, vSwitch);
ASSERT(pClonedNbl);
//write info from the allocated buffer pNetBuffer which contains all the NB buffer
//retreats bytes: eth + ip + gre, used NdisRetreatNetBufferDataStart to retrieve contiguous memory (the newly allocated mdl created by retreat)
Gre_EncapsulateNbs(pClonedNbl, (ABC_ETHERNET_HEADER*)pNetBuffer);
ExFreePoolWithTag(pNetBuffer, g_frameTag);
//it’s the SxLibSendNetBufferListsIngress function from the sample
_Nbls_SendIngress(vSwitch, pClonedNbl, sendFlags, 0);
} else {
//it’s the SxLibSendNetBufferListsIngress function from the sample
_Nbls_SendIngress(vSwitch, pNbl, sendFlags, 0);
}
}
static VOID _ProcessNblsIngress(PSX_SWITCH_OBJECT vSwitch, PNET_BUFFER_LIST netBufferLists, ULONG sendFlags)
{
NET_BUFFER_LIST* pNbl = netBufferLists;
NET_BUFFER_LIST* pNextNbl = NULL;
DbgPrintNblCount(netBufferLists);
while (pNbl) {
//we are allowed to break the links between NBLs. Each NBL will be sent separately.
pNextNbl = NET_BUFFER_LIST_NEXT_NBL(pNbl);
NET_BUFFER_LIST_NEXT_NBL(pNbl) = NULL;
_ProcessOneNblIngress(vSwitch, sendFlags, pNbl);
pNbl = pNextNbl;
}
}
Use_decl_annotations
VOID Nbls_StartIngress(PSX_SWITCH_OBJECT vSwitch, NDIS_HANDLE extensionContext, PNET_BUFFER_LIST netBufferLists, ULONG sendFlags)
{
UNREFERENCED_PARAMETER(extensionContext);
if (vSwitch->dataFlowState != SxSwitchRunning) {
//this will call complete; it’s the SxLibSendNetBufferListsIngress function from the sample
_Nbls_SendIngress(vSwitch, netBufferLists, sendFlags, 0);
return;
}
_ProcessNblsIngress(vSwitch, netBufferLists, sendFlags);
}
Use_decl_annotations
VOID FilterSendNetBufferLists(NDIS_HANDLE filterModuleContext, PNET_BUFFER_LIST netBufferLists, NDIS_PORT_NUMBER portNumber, ULONG sendFlags)
{
//this struct is from the forwarding sample
PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)filterModuleContext;
UNREFERENCED_PARAMETER(portNumber);
Nbls_StartIngress(switchObject, switchObject->extensionContext, netBufferLists, sendFlags);
}
==============================================================
FilterSendNetBufferListsComplete code
//No ingress complete processing necessary.
Use_decl_annotations
VOID Nbls_CompleteIngress(PSX_SWITCH_OBJECT vSwitch, NDIS_HANDLE extensionContext, PNET_BUFFER_LIST netBufferLists, ULONG sendCompleteFlags)
{
UNREFERENCED_PARAMETER(extensionContext);
NdisFSendNetBufferListsComplete(vSwitch->ndisFilterHandle, netBufferLists, sendCompleteFlags);
}
VOID FreeClonedNblNormal(In NET_BUFFER_LIST* pNbl)
{
NdisFreeCloneNetBufferList(pNbl, 0);
}
VOID FilterSendNetBufferListsComplete(NDIS_HANDLE filterModuleContext, PNET_BUFFER_LIST netBufferLists, ULONG sendCompleteFlags)
{
PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)filterModuleContext;
if (netBufferLists->ParentNetBufferList)
{
Nbls_CompleteIngress(switchObject, switchObject->extensionContext, netBufferLists, sendCompleteFlags);
switchObject->ndisSwitchHandlers.FreeNetBufferListForwardingContext(switchObject->ndisSwitchContext, netBufferLists);
FreeClonedNblNormal(netBufferLists);
NdisRetreatNetBufferListDataStart(netBufferLists->ParentNetBufferList, sizeof(ABC_ETHERNET_HEADER), 0, NULL, NULL);
Nbls_CompleteIngress(switchObject, switchObject->extensionContext, netBufferLists->ParentNetBufferList, sendCompleteFlags);
} else {
Nbls_CompleteIngress(switchObject, switchObject->extensionContext, netBufferLists, sendCompleteFlags);
}
}
=============================================================
I hope it helps.