diff options
-rw-r--r-- | datapath-windows/ovsext/BufferMgmt.c | 9 | ||||
-rw-r--r-- | datapath-windows/ovsext/BufferMgmt.h | 2 | ||||
-rw-r--r-- | datapath-windows/ovsext/PacketIO.c | 10 |
3 files changed, 20 insertions, 1 deletions
diff --git a/datapath-windows/ovsext/BufferMgmt.c b/datapath-windows/ovsext/BufferMgmt.c index 47d872df2..6627acf25 100644 --- a/datapath-windows/ovsext/BufferMgmt.c +++ b/datapath-windows/ovsext/BufferMgmt.c @@ -81,6 +81,7 @@ #include "Flow.h" #include "Offload.h" #include "NetProto.h" +#include "PacketIO.h" #include "PacketParser.h" #include "Switch.h" #include "Vport.h" @@ -267,6 +268,7 @@ OvsInitNBLContext(POVS_BUFFER_CONTEXT ctx, ctx->srcPortNo = srcPortNo; ctx->origDataLength = origDataLength; ctx->mru = 0; + ctx->pendingSend = 0; } @@ -1746,8 +1748,13 @@ OvsCompleteNBL(PVOID switch_ctx, if (parent != NULL) { ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(parent); ASSERT(ctx && ctx->magic == OVS_CTX_MAGIC); + UINT16 pendingSend = 1, exchange = 0; value = InterlockedDecrement((LONG volatile *)&ctx->refCount); - if (value == 0) { + InterlockedCompareExchange16((SHORT volatile *)&pendingSend, exchange, (SHORT)ctx->pendingSend); + if (value == 1 && pendingSend == exchange) { + InterlockedExchange16((SHORT volatile *)&ctx->pendingSend, 0); + OvsSendNBLIngress(context, parent, ctx->sendFlags); + } else if (value == 0){ return OvsCompleteNBL(context, parent, FALSE); } } diff --git a/datapath-windows/ovsext/BufferMgmt.h b/datapath-windows/ovsext/BufferMgmt.h index 2a74988b8..2ae32723e 100644 --- a/datapath-windows/ovsext/BufferMgmt.h +++ b/datapath-windows/ovsext/BufferMgmt.h @@ -55,7 +55,9 @@ typedef union _OVS_BUFFER_CONTEXT { UINT32 origDataLength; UINT32 dataOffsetDelta; }; + ULONG sendFlags; UINT16 mru; + UINT16 pendingSend; /* Indicates packet can be sent or not. */ }; CHAR value[MEM_ALIGN_SIZE(sizeof(struct dummy))]; diff --git a/datapath-windows/ovsext/PacketIO.c b/datapath-windows/ovsext/PacketIO.c index 57c583ccf..cc0840704 100644 --- a/datapath-windows/ovsext/PacketIO.c +++ b/datapath-windows/ovsext/PacketIO.c @@ -161,6 +161,16 @@ OvsSendNBLIngress(POVS_SWITCH_CONTEXT switchContext, ASSERT(switchContext->dataFlowState == OvsSwitchRunning); + POVS_BUFFER_CONTEXT ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(netBufferLists); + LONG refCount = 1, exchange = 0; + InterlockedCompareExchange((LONG volatile *)&refCount, exchange, (LONG)ctx->refCount); + if (refCount != exchange) { + InterlockedExchange((LONG volatile *)&ctx->sendFlags, sendFlags); + InterlockedExchange16((SHORT volatile *)&ctx->pendingSend, 1); + return; + } + + InterlockedExchange16((SHORT volatile *)&ctx->pendingSend, 0); NdisFSendNetBufferLists(switchContext->NdisFilterHandle, netBufferLists, NDIS_DEFAULT_PORT_NUMBER, sendFlags); } |