Added support for creating and handling multiple NBLs with only one NB for ingress data path.
Signed-off-by: Sorin Vinturis <svintu...@cloudbasesolutions.com> Reported-by: Alessandro Pilotti <apilo...@cloudbasesolutions.com> Reported-at: https://github.com/openvswitch/ovs-issues/issues/2 --- datapath-windows/ovsext/PacketIO.c | 91 ++++++++++++++++++++++++++++++-------- 1 file changed, 72 insertions(+), 19 deletions(-) diff --git a/datapath-windows/ovsext/PacketIO.c b/datapath-windows/ovsext/PacketIO.c index 69d7110..7d20ef2 100644 --- a/datapath-windows/ovsext/PacketIO.c +++ b/datapath-windows/ovsext/PacketIO.c @@ -44,6 +44,10 @@ extern NDIS_STRING ovsExtFriendlyNameUC; static VOID OvsFinalizeCompletionList(OvsCompletionList *completionList); static VOID OvsCompleteNBLIngress(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST netBufferLists, ULONG sendCompleteFlags); +static NTSTATUS OvsCreateNewNBLsFromMultipleNBs( + POVS_SWITCH_CONTEXT switchContext, + PNET_BUFFER_LIST *curNbl, + PNET_BUFFER_LIST *nextNbl); __inline VOID OvsInitCompletionList(OvsCompletionList *completionList, @@ -235,6 +239,7 @@ OvsStartNBLIngress(POVS_SWITCH_CONTEXT switchContext, OvsFlowKey key; UINT64 hash; PNET_BUFFER curNb; + POVS_BUFFER_CONTEXT ctx; BOOLEAN isRecv = FALSE; nextNbl = curNbl->Next; @@ -259,18 +264,35 @@ OvsStartNBLIngress(POVS_SWITCH_CONTEXT switchContext, } #endif - /* Ethernet Header is a guaranteed safe access. */ - curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); - if (curNb->Next != NULL) { - /* XXX: This case is not handled yet. */ + ctx = OvsInitExternalNBLContext(switchContext, curNbl, isRecv); + if (ctx == NULL) { RtlInitUnicodeString(&filterReason, - L"Dropping NBLs with multiple NBs"); + L"Cannot allocate external NBL context."); + OvsStartNBLIngressError(switchContext, curNbl, sendCompleteFlags, &filterReason, NDIS_STATUS_RESOURCES); continue; - } else { - POVS_BUFFER_CONTEXT ctx; + } + + /* Ethernet Header is a guaranteed safe access. */ + curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); + if (curNb->Next != NULL) { + /* Create a NET_BUFFER_LIST for each NET_BUFFER. */ + status = OvsCreateNewNBLsFromMultipleNBs(switchContext, + &curNbl, + &nextNbl); + if (!NT_SUCCESS(status)) { + RtlInitUnicodeString(&filterReason, + L"Cannot allocate NBLs with single NB."); + + OvsStartNBLIngressError(switchContext, curNbl, + sendCompleteFlags, &filterReason, + NDIS_STATUS_RESOURCES); + continue; + } + } + { OvsFlow *flow; /* Take the DispatchLock so none of the VPORTs disconnect while @@ -281,18 +303,6 @@ OvsStartNBLIngress(POVS_SWITCH_CONTEXT switchContext, NdisAcquireRWLockRead(switchContext->dispatchLock, &lockState, dispatch); - ctx = OvsInitExternalNBLContext(switchContext, curNbl, isRecv); - if (ctx == NULL) { - RtlInitUnicodeString(&filterReason, - L"Cannot allocate external NBL context."); - - OvsStartNBLIngressError(switchContext, curNbl, - sendCompleteFlags, &filterReason, - NDIS_STATUS_RESOURCES); - NdisReleaseRWLock(switchContext->dispatchLock, &lockState); - continue; - } - vport = OvsFindVportByPortIdAndNicIndex(switchContext, sourcePort, sourceIndex); if (vport == NULL || vport->ovsState != OVS_STATE_CONNECTED) { @@ -483,3 +493,46 @@ OvsExtCancelSendNBL(NDIS_HANDLE filterModuleContext, /* All send requests get completed synchronously, so there is no need to * implement this callback. */ } + +static NTSTATUS +OvsCreateNewNBLsFromMultipleNBs(POVS_SWITCH_CONTEXT switchContext, + PNET_BUFFER_LIST *curNbl, + PNET_BUFFER_LIST *nextNbl) +{ + NTSTATUS status = STATUS_SUCCESS; + PNET_BUFFER_LIST newNbls = NULL; + PNET_BUFFER_LIST lastNbl = NULL; + PNET_BUFFER_LIST nbl = NULL; + POVS_BUFFER_CONTEXT bufContext = NULL; + BOOLEAN error = TRUE; + + do { + /* Decrement buffer context reference count. */ + bufContext = (POVS_BUFFER_CONTEXT) + NET_BUFFER_LIST_CONTEXT_DATA_START(*curNbl); + InterlockedDecrement((volatile LONG*)&bufContext->refCount); + + /* Create new NBLs from curNbl with multiple net buffers. */ + newNbls = OvsPartialCopyToMultipleNBLs(switchContext, + *curNbl, 0, 0, TRUE); + if (NULL == newNbls) { + OVS_LOG_ERROR("Failed to allocate NBLs with single NB."); + status = NDIS_STATUS_RESOURCES; + break; + } + + nbl = newNbls; + while (nbl) { + lastNbl = nbl; + nbl = NET_BUFFER_LIST_NEXT_NBL(nbl); + } + lastNbl->Next = *nextNbl; + *nextNbl = newNbls->Next; + *curNbl = newNbls; + (*curNbl)->Next = NULL; + + error = FALSE; + } while (error); + + return status; +} -- 1.9.0.msysgit.0 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev