I will respin it later on tomorrow.

Alin.

> -----Mesaj original-----
> De la: dev [mailto:dev-boun...@openvswitch.org] În numele Sairam
> Venugopal
> Trimis: Monday, February 29, 2016 9:35 PM
> Către: Sorin Vinturis <svintu...@cloudbasesolutions.com>;
> dev@openvswitch.org
> Subiect: Re: [ovs-dev] [PATCH v3 1/6] datapath-windows: Added
> recirculation support.
> 
> Hi Sorin,
> 
> I look forward to the new patch. I had confused the usage of
> OvsDeferredActionsQueueIsEmpty with the previous patch.
> 
> Thanks,
> Sairam
> 
> On 2/27/16, 4:39 AM, "Sorin Vinturis" <svintu...@cloudbasesolutions.com>
> wrote:
> 
> >Hi Sairam,
> >
> >Thank you for reviewing recirculation patches. Please see my answers
> >inline.
> >
> >-Sorin
> >
> >-----Original Message-----
> >From: Sairam Venugopal [mailto:vsai...@vmware.com]
> >Sent: Friday, 26 February, 2016 21:51
> >To: Sorin Vinturis; dev@openvswitch.org
> >Subject: Re: [ovs-dev] [PATCH v3 1/6] datapath-windows: Added
> >recirculation support.
> >
> >Hi Sorin,
> >
> >Thanks for the patch. Please check the comments inline.
> >
> >Thanks,
> >Sairam
> >
> >On 2/22/16, 6:07 AM, "Sorin Vinturis"
> ><svintu...@cloudbasesolutions.com>
> >wrote:
> >
> >>Recirculation support for the OVS extension.
> >>
> >>Tested using PING and iperf with Driver Verifier enabled.
> >>
> >>Signed-off-by: Sorin Vinturis <svintu...@cloudbasesolutions.com>
> >>Co-authored-by: Alin Gabriel Serdean
> <aserd...@cloudbasesolutions.com>
> >>Reported-by: Sorin Vinturis <svintu...@cloudbasesolutions.com>
> >>Reported-at:
> >>https://urldefense.proofpoint.com/v2/url?u=https-
> 3A__github.com_openvs
> >>wit
> >>ch_ovs-
> 2Dissues_issues_104&d=BQIFAw&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-Yi
> >>hVM
> >>NtXt-
> uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=xvtKJvzpDJ
> sqi
> >>sOG
> >>VQT_4cZ5UaZJntaL6eM3Jisxkwo&s=ERhkBKIgo2mvl24FaQeUrlJVOOd8QOj
> oFc1a5VBE
> >>Prg
> >>&e=
> >>---
> >>v2: Initialize flow key before using it.
> >>v3: Synchronized access to deferred actions queue.
> >>---
> >> datapath-windows/automake.mk              |   3 +
> >> datapath-windows/ovsext/Actions.c         | 215
> >>++++++++++++++++++++++++++----
> >> datapath-windows/ovsext/Actions.h         |  54 ++++++++
> >> datapath-windows/ovsext/Datapath.c        |   4 +
> >> datapath-windows/ovsext/DpInternal.h      |   2 +-
> >> datapath-windows/ovsext/Flow.c            |  76 +++++++++--
> >> datapath-windows/ovsext/Flow.h            |   5 +-
> >> datapath-windows/ovsext/Netlink/Netlink.h |  11 ++
> >> datapath-windows/ovsext/PacketIO.c        |  16 ++-
> >> datapath-windows/ovsext/PacketIO.h        |  10 --
> >> datapath-windows/ovsext/Recirc.c          | 171
> ++++++++++++++++++++++++
> >> datapath-windows/ovsext/Recirc.h          |  82 ++++++++++++
> >> datapath-windows/ovsext/Tunnel.c          |  15 ++-
> >> datapath-windows/ovsext/User.c            |  13 +-
> >> datapath-windows/ovsext/ovsext.vcxproj    |   3 +
> >> 15 files changed, 612 insertions(+), 68 deletions(-) create mode
> >> 100644 datapath-windows/ovsext/Actions.h create mode 100644
> >> datapath-windows/ovsext/Recirc.c create mode 100644
> >> datapath-windows/ovsext/Recirc.h
> >>
> >>diff --git a/datapath-windows/automake.mk
> >>b/datapath-windows/automake.mk index f29f548..04fc97f 100644
> >>--- a/datapath-windows/automake.mk
> >>+++ b/datapath-windows/automake.mk
> >>@@ -9,6 +9,7 @@ EXTRA_DIST += \
> >>    datapath-windows/misc/uninstall.cmd \
> >>    datapath-windows/ovsext.sln \
> >>    datapath-windows/ovsext/Actions.c \
> >>+   datapath-windows/ovsext/Actions.h \
> >>    datapath-windows/ovsext/Atomic.h \
> >>    datapath-windows/ovsext/BufferMgmt.c \
> >>    datapath-windows/ovsext/BufferMgmt.h \ @@ -45,6 +46,8 @@
> EXTRA_DIST
> >>+= \
> >>    datapath-windows/ovsext/PacketIO.h \
> >>    datapath-windows/ovsext/PacketParser.c \
> >>    datapath-windows/ovsext/PacketParser.h \
> >>+   datapath-windows/ovsext/Recirc.c \
> >>+   datapath-windows/ovsext/Recirc.h \
> >>    datapath-windows/ovsext/Stt.c \
> >>    datapath-windows/ovsext/Stt.h \
> >>    datapath-windows/ovsext/Switch.c \
> >>diff --git a/datapath-windows/ovsext/Actions.c
> >>b/datapath-windows/ovsext/Actions.c
> >>index 5a04541..d3f18f2 100644
> >>--- a/datapath-windows/ovsext/Actions.c
> >>+++ b/datapath-windows/ovsext/Actions.c
> >>@@ -14,8 +14,7 @@
> >>  * limitations under the License.
> >>  */
> >>
> >>-#include "precomp.h"
> >>-
> >>+#include "Actions.h"
> >> #include "Debug.h"
> >> #include "Event.h"
> >> #include "Flow.h"
> >>@@ -24,6 +23,7 @@
> >> #include "NetProto.h"
> >> #include "Offload.h"
> >> #include "PacketIO.h"
> >>+#include "Recirc.h"
> >> #include "Stt.h"
> >> #include "Switch.h"
> >> #include "User.h"
> >>@@ -35,6 +35,8 @@
> >> #endif
> >> #define OVS_DBG_MOD OVS_DBG_ACTION
> >>
> >>+#define OVS_DEST_PORTS_ARRAY_MIN_SIZE 2
> >>+
> >> typedef struct _OVS_ACTION_STATS {
> >>     UINT64 rxGre;
> >>     UINT64 txGre;
> >>@@ -66,7 +68,6 @@ OVS_ACTION_STATS ovsActionStats;
> >>  * exercised while adding new members to the structure - only add
> >>ones that get
> >>  * used across multiple stages in the pipeline/get used in multiple
> >>functions.
> >>  */
> >>-#define OVS_DEST_PORTS_ARRAY_MIN_SIZE 2  typedef struct
> >>OvsForwardingContext {
> >>     POVS_SWITCH_CONTEXT switchContext;
> >>     /* The NBL currently used in the pipeline. */ @@ -99,7 +100,7 @@
> >>typedef struct OvsForwardingContext {
> >>      */
> >>     OvsIPv4TunnelKey tunKey;
> >>
> >>-     /*
> >>+    /*
> >>      * Tunneling - Tx:
> >>      * To store the output port, when it is a tunneled port. We don't
> >>foresee
> >>      * multiple tunneled ports as outport for any given NBL.
> >>@@ -117,7 +118,6 @@ typedef struct OvsForwardingContext {
> >>     OVS_PACKET_HDR_INFO layers;
> >> } OvsForwardingContext;
> >>
> >>-
> >> /*
> >>  *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>  * OvsInitForwardingCtx --
> >>@@ -564,10 +564,10 @@
> OvsCompleteNBLForwardingCtx(OvsForwardingContext
> >>*ovsFwdCtx,
> >> static __inline NDIS_STATUS
> >> OvsDoFlowLookupOutput(OvsForwardingContext *ovsFwdCtx)  {
> >>-    OvsFlowKey key;
> >>-    OvsFlow *flow;
> >>-    UINT64 hash;
> >>-    NDIS_STATUS status;
> >>+    OvsFlowKey key = { 0 };
> >>+    OvsFlow *flow = NULL;
> >>+    UINT64 hash = 0;
> >>+    NDIS_STATUS status = NDIS_STATUS_SUCCESS;
> >>     POVS_VPORT_ENTRY vport =
> >>         OvsFindVportByPortNo(ovsFwdCtx->switchContext,
> >>ovsFwdCtx->srcVportNo);
> >>     if (vport == NULL || vport->ovsState != OVS_STATE_CONNECTED) { @@
> >>-595,11 +595,13 @@ OvsDoFlowLookupOutput(OvsForwardingContext
> >>*ovsFwdCtx)
> >>     if (flow) {
> >>         OvsFlowUsed(flow, ovsFwdCtx->curNbl, &ovsFwdCtx->layers);
> >>         ovsFwdCtx->switchContext->datapath.hits++;
> >>-        status = OvsActionsExecute(ovsFwdCtx->switchContext,
> >>-                                   ovsFwdCtx->completionList,
> >>ovsFwdCtx->curNbl,
> >>-                                   ovsFwdCtx->srcVportNo,
> >>ovsFwdCtx->sendFlags,
> >>-                                   &key, &hash, &ovsFwdCtx->layers,
> >>-                                   flow->actions, flow->actionsLen);
> >>+        status = OvsDoExecuteActions(ovsFwdCtx->switchContext,
> >>+                                     ovsFwdCtx->completionList,
> >>+                                     ovsFwdCtx->curNbl,
> >>+                                     ovsFwdCtx->srcVportNo,
> >>+                                     ovsFwdCtx->sendFlags,
> >>+                                     &key, &hash, &ovsFwdCtx->layers,
> >>+                                     flow->actions,
> >>+ flow->actionsLen);
> >>         ovsFwdCtx->curNbl = NULL;
> >>     } else {
> >>         LIST_ENTRY missedPackets;
> >>@@ -1520,7 +1522,58 @@ OvsExecuteSetAction(OvsForwardingContext
> >>*ovsFwdCtx,
> >>
> >> /*
> >>  *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>- * OvsActionsExecute --
> >>+ * OvsActionExecuteRecirc --
> >>+ *     The function adds a deferred action to allow the current packet,
> >>nbl,
> >>+ *     to re-enter datapath packet processing.
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ */
> >>+NTSTATUS
> >>+OvsActionExecuteRecirc(POVS_SWITCH_CONTEXT switchContext,
> >>+                       PNET_BUFFER_LIST nbl,
> >>+                       OvsFlowKey *key,
> >>+                       UINT64 *hashAction,
> >>+                       const PNL_ATTR actions,
> >>+                       int rem)
> >>+{
> >>+    POVS_DEFERRED_ACTION deferredAction = NULL;
> >>+    PNET_BUFFER_LIST newNbl = NULL;
> >>+    UINT64 hash = 0;
> >>+
> >>+    if (!NlAttrIsLast(actions, rem)) {
> >>+        /*
> >>+         * Recirc action is the not the last action of the action
> >>+ list,
> >>so we
> >>+         * need to clone the packet.
> >>+         */
> >>+        newNbl = OvsPartialCopyNBL(switchContext, nbl,
> >>+                                   0, 0, TRUE /*copy NBL info*/);
> >>+        /*
> >>+         * Skip the recirc action when out of memory, but continue on
> >>with the
> >>+         * rest of the action list.
> >>+         */
> >>+        if (newNbl == NULL) {
> >>+            ovsActionStats.noCopiedNbl++;
> >>+            return STATUS_SUCCESS;
> >>+        }
> >>+        nbl = newNbl;
> >>+    }
> >>+
> >>+    hash = hashAction ? *hashAction : OvsHashFlow(key);
> >>+
> >>+    deferredAction = OvsAddDeferredActions(nbl, key, hash, NULL);
> >>+    if (deferredAction) {
> >>+        deferredAction->key.recircId = NlAttrGetU32(actions);
> >>+    } else {
> >>+        if (newNbl) {
> >>+            OvsCompleteNBL(switchContext, newNbl, TRUE);
> >>+        }
> >>+    }
> >>+
> >>+    return STATUS_SUCCESS;
> >>+}
> >>+
> >>+/*
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ * OvsDoExecuteActions --
> >>  *     Interpret and execute the specified 'actions' on the specifed
> >>packet
> >>  *     'curNbl'. The expectation is that if the packet needs to be
> >>dropped
> >>  *     (completed) for some reason, it is added to 'completionList' so
> >>that the
> >>@@ -1537,16 +1590,16 @@ OvsExecuteSetAction(OvsForwardingContext
> >>*ovsFwdCtx,
> >>  *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>  */
> >> NDIS_STATUS
> >>-OvsActionsExecute(POVS_SWITCH_CONTEXT switchContext,
> >>-                  OvsCompletionList *completionList,
> >>-                  PNET_BUFFER_LIST curNbl,
> >>-                  UINT32 portNo,
> >>-                  ULONG sendFlags,
> >>-                  OvsFlowKey *key,
> >>-                  UINT64 *hash,
> >>-                  OVS_PACKET_HDR_INFO *layers,
> >>-                  const PNL_ATTR actions,
> >>-                  INT actionsLen)
> >>+OvsDoExecuteActions(POVS_SWITCH_CONTEXT switchContext,
> >>+                    OvsCompletionList *completionList,
> >>+                    PNET_BUFFER_LIST curNbl,
> >>+                    UINT32 portNo,
> >>+                    ULONG sendFlags,
> >>+                    OvsFlowKey *key,
> >>+                    UINT64 *hash,
> >>+                    OVS_PACKET_HDR_INFO *layers,
> >>+                    const PNL_ATTR actions,
> >>+                    INT actionsLen)
> >> {
> >>     PNL_ATTR a;
> >>     INT rem;
> >>@@ -1695,6 +1748,31 @@ OvsActionsExecute(POVS_SWITCH_CONTEXT
> >>switchContext,
> >>             break;
> >>         }
> >>
> >>+        case OVS_ACTION_ATTR_RECIRC:
> >>+        {
> >>+            if (ovsFwdCtx.destPortsSizeOut > 0 ||
> >>+ ovsFwdCtx.tunnelTxNic
> >>!= NULL
> >>+                || ovsFwdCtx.tunnelRxNic != NULL) {
> >>+                status = OvsOutputBeforeSetAction(&ovsFwdCtx);
> >>+                if (status != NDIS_STATUS_SUCCESS) {
> >>+                    dropReason = L"OVS-adding destination failed";
> >>+                    goto dropit;
> >>+                }
> >>+            }
> >>+
> >>+            status = OvsActionExecuteRecirc(ovsFwdCtx.switchContext,
> >>+                                            ovsFwdCtx.curNbl, key, hash,
> >>+                                            (const PNL_ATTR)a, rem);
> >>+            if (status != NDIS_STATUS_SUCCESS) {
> >>+                dropReason = L"OVS-recirculation action failed";
> >>+                goto dropit;
> >>+            }
> >>+
> >>+            if (NlAttrIsLast(a, rem)) {
> >>+                goto exit;
> >>+            }
> >>+            break;
> >>+        }
> >>+
> >>         case OVS_ACTION_ATTR_USERSPACE:
> >>         {
> >>             PNL_ATTR userdataAttr;
> >>@@ -1781,5 +1859,92 @@ dropit:
> >>         OvsCompleteNBLForwardingCtx(&ovsFwdCtx, dropReason);
> >>     }
> >>
> >>+exit:
> >>+    return status;
> >>+}
> >>+
> >>+NDIS_STATUS
> >>+OvsActionsExecute(POVS_SWITCH_CONTEXT switchContext,
> >>+                  OvsCompletionList *completionList,
> >>+                  PNET_BUFFER_LIST curNbl,
> >>+                  UINT32 portNo,
> >>+                  ULONG sendFlags,
> >>+                  OvsFlowKey *key,
> >>+                  UINT64 *hash,
> >>+                  OVS_PACKET_HDR_INFO *layers,
> >>+                  const PNL_ATTR actions,
> >>+                  INT actionsLen)
> >>+{
> >>+    NDIS_STATUS status = STATUS_SUCCESS;
> >>+
> >>+    status = OvsDoExecuteActions(switchContext, completionList, curNbl,
> >>+                                 portNo, sendFlags, key, hash, layers,
> >>+                                 actions, actionsLen);
> >>+
> >>+    if (status == STATUS_SUCCESS) {
> >>+        status = OvsProcessDeferredActions(switchContext,
> >>completionList,
> >>+                                           portNo, sendFlags, layers);
> >>+    }
> >>+
> >>+    return status;
> >>+}
> >>+
> >>+NDIS_STATUS
> >>+OvsDoRecircFlowLookupOutput(POVS_SWITCH_CONTEXT
> switchContext,
> >>+                            OvsCompletionList *completionList,
> >>+                            PNET_BUFFER_LIST curNbl,
> >>+                            OvsFlowKey *key,
> >>+                            UINT64 *hash) {
> >>+    NDIS_STATUS status = NDIS_STATUS_SUCCESS;
> >>+    OvsFlow *flow = NULL;
> >>+    OvsForwardingContext ovsFwdCtx = { 0 };
> >>+    POVS_VPORT_ENTRY internalVport = switchContext->internalVport;
> >>+
> >>+    ASSERT(switchContext->internalVport);
> >>+    ASSERT(internalVport->nicState == NdisSwitchNicStateConnected);
> >>+
> >>+    OvsInitForwardingCtx(&ovsFwdCtx, switchContext, curNbl,
> >>+                         internalVport->portNo, 0,
> >>+
> >>NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl),
> >>+                         completionList, NULL, TRUE);
> >>+
> >>+    flow = OvsLookupFlowRecirc(&ovsFwdCtx.switchContext->datapath,
> >>+                               key, hash);
> >>+    if (flow) {
> >>+        OvsFlowUsed(flow, ovsFwdCtx.curNbl, &ovsFwdCtx.layers);
> >>+        ovsFwdCtx.switchContext->datapath.hits++;
> >>+        status = OvsActionsExecute(ovsFwdCtx.switchContext,
> >>+                                   ovsFwdCtx.completionList,
> >>ovsFwdCtx.curNbl,
> >>+                                   ovsFwdCtx.srcVportNo,
> >>ovsFwdCtx.sendFlags,
> >>+                                   key, hash, &ovsFwdCtx.layers,
> >>+                                   flow->actions, flow->actionsLen);
> >>+        ovsFwdCtx.curNbl = NULL;
> >>+    } else {
> >>+        LIST_ENTRY missedPackets;
> >>+        UINT32 num = 0;
> >>+        ovsFwdCtx.switchContext->datapath.misses++;
> >>+        InitializeListHead(&missedPackets);
> >
> >Sai -  &ovsFwdCtx.layers is not initialized. Call
> >OvsExtractFlow(curNbl,
> >internalVport->portNo, key, &ovsFwdCtx.layers, NULL);
> >SV: OK.
> >
> >>+        status = OvsCreateAndAddPackets(NULL, 0,
> OVS_PACKET_CMD_MISS,
> >>+                          internalVport, key,ovsFwdCtx.curNbl,
> >>+                          FALSE, &ovsFwdCtx.layers,
> >>+                          ovsFwdCtx.switchContext, &missedPackets,
> >>+ &num);
> >
> >Sai - Can you fix the alignment of the arguments to keep it consistent?
> >SV: Sure.
> >
> >
> >>+        if (num) {
> >>+            OvsQueuePackets(&missedPackets, num);
> >>+        }
> >>+        if (status == NDIS_STATUS_SUCCESS) {
> >>+            /* Complete the packet since it was copied to user buffer.
> >>*/
> >>+            OvsCompleteNBLForwardingCtx(&ovsFwdCtx,
> >>+                L"OVS-Dropped since packet was copied to userspace");
> >>+            ovsActionStats.flowMiss++;
> >>+            status = NDIS_STATUS_SUCCESS;
> >>+        } else {
> >>+            OvsCompleteNBLForwardingCtx(&ovsFwdCtx,
> >>+                L"OVS-Dropped due to failure to queue to userspace");
> >>+            status = NDIS_STATUS_FAILURE;
> >>+            ovsActionStats.failedFlowMiss++;
> >>+        }
> >>+    }
> >>+
> >>     return status;
> >> }
> >>diff --git a/datapath-windows/ovsext/Actions.h
> >>b/datapath-windows/ovsext/Actions.h
> >>new file mode 100644
> >>index 0000000..01ad8d2
> >>--- /dev/null
> >>+++ b/datapath-windows/ovsext/Actions.h
> >>@@ -0,0 +1,54 @@
> >>+/*
> >>+ * Copyright (c) 2015 Cloudbase Solutions Srl
> >>+ *
> >>+ * Licensed under the Apache License, Version 2.0 (the "License");
> >>+ * you may not use this file except in compliance with the License.
> >>+ * You may obtain a copy of the License at:
> >>+ *
> >>+ *
> >>https://urldefense.proofpoint.com/v2/url?u=http-
> 3A__www.apache.org_lic
> >>ens
> >>es_LICENSE-2D2.0&d=BQIFAw&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-
> YihVMNtXt-uE
> >>s&r
> >>=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=xvtKJvzpDJsqis
> OGVQT_4cZ
> >>5Ua
> ZJntaL6eM3Jisxkwo&s=kHCjput72ZhJsAXzrf15z3mr80BW2XuxvE1QIGkayyQ&
> e=
> >>+ *
> >>+ * Unless required by applicable law or agreed to in writing,
> >>+ software
> >>+ * distributed under the License is distributed on an "AS IS" BASIS,
> >>+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
> or
> >>implied.
> >>+ * See the License for the specific language governing permissions
> >>+ and
> >>+ * limitations under the License.
> >>+ */
> >>+
> >>+#ifndef __ACTIONS_H_
> >>+#define __ACTIONS_H_ 1
> >>+
> >>+#include "Switch.h"
> >>+#include "PacketIO.h"
> >>+
> >>+NDIS_STATUS
> >>+OvsActionsExecute(POVS_SWITCH_CONTEXT switchContext,
> >>+                  OvsCompletionList *completionList,
> >>+                  PNET_BUFFER_LIST curNbl,
> >>+                  UINT32 srcVportNo,
> >>+                  ULONG sendFlags,
> >>+                  OvsFlowKey *key,
> >>+                  UINT64 *hash,
> >>+                  OVS_PACKET_HDR_INFO *layers,
> >>+                  const PNL_ATTR actions,
> >>+                  int actionsLen);
> >>+
> >>+NDIS_STATUS
> >>+OvsDoExecuteActions(POVS_SWITCH_CONTEXT switchContext,
> >>+                  OvsCompletionList *completionList,
> >>+                  PNET_BUFFER_LIST curNbl,
> >>+                  UINT32 srcVportNo,
> >>+                  ULONG sendFlags,
> >>+                  OvsFlowKey *key,
> >>+                  UINT64 *hash,
> >>+                  OVS_PACKET_HDR_INFO *layers,
> >>+                  const PNL_ATTR actions,
> >>+                  int actionsLen);
> >>+
> >>+NDIS_STATUS
> >>+OvsDoRecircFlowLookupOutput(POVS_SWITCH_CONTEXT
> switchContext,
> >>+                            OvsCompletionList *completionList,
> >>+                            PNET_BUFFER_LIST curNbl,
> >>+                            OvsFlowKey *key,
> >>+                            UINT64 *hash);
> >>+
> >>+#endif /* __ACTIONS_H_ */
> >>diff --git a/datapath-windows/ovsext/Datapath.c
> >>b/datapath-windows/ovsext/Datapath.c
> >>index a9a218d..9e7d6a4 100644
> >>--- a/datapath-windows/ovsext/Datapath.c
> >>+++ b/datapath-windows/ovsext/Datapath.c
> >>@@ -346,6 +346,8 @@ extern POVS_SWITCH_CONTEXT
> gOvsSwitchContext;
> >>NDIS_SPIN_LOCK ovsCtrlLockObj;  PNDIS_SPIN_LOCK gOvsCtrlLock;
> >>
> >>+NDIS_SPIN_LOCK ovsRecircLockObj;
> >>+
> >> NTSTATUS
> >> InitUserDumpState(POVS_OPEN_INSTANCE instance,
> >>                   POVS_MESSAGE ovsMsg) @@ -383,6 +385,7 @@ OvsInit()
> >>{
> >>     gOvsCtrlLock = &ovsCtrlLockObj;
> >>     NdisAllocateSpinLock(gOvsCtrlLock);
> >>+    NdisAllocateSpinLock(&ovsRecircLockObj);
> >>     OvsInitEventQueue();
> >> }
> >>
> >>@@ -394,6 +397,7 @@ OvsCleanup()
> >>         NdisFreeSpinLock(gOvsCtrlLock);
> >>         gOvsCtrlLock = NULL;
> >>     }
> >>+    NdisFreeSpinLock(&ovsRecircLockObj);
> >> }
> >>
> >> VOID
> >>diff --git a/datapath-windows/ovsext/DpInternal.h
> >>b/datapath-windows/ovsext/DpInternal.h
> >>index c094f32..845c132 100644
> >>--- a/datapath-windows/ovsext/DpInternal.h
> >>+++ b/datapath-windows/ovsext/DpInternal.h
> >>@@ -20,7 +20,6 @@
> >> #include <netioapi.h>
> >> #define IFNAMSIZ IF_NAMESIZE
> >> #include "../ovsext/Netlink/Netlink.h"
> >>-#include "Mpls.h"
> >>
> >> #define OVS_DP_NUMBER   ((uint32_t) 0)
> >>
> >>@@ -166,6 +165,7 @@ typedef __declspec(align(8)) struct OvsFlowKey {
> >>         Icmp6Key icmp6Key;       /* size 72 */
> >>         MplsKey mplsKey;         /* size 8 */
> >>     };
> >>+    UINT32 recircId;             /* Recirculation ID.  */
> >> } OvsFlowKey;
> >>
> >> #define OVS_WIN_TUNNEL_KEY_SIZE (sizeof (OvsIPv4TunnelKey)) diff
> >>--git a/datapath-windows/ovsext/Flow.c
> >>b/datapath-windows/ovsext/Flow.c index
> >>5eec513..baf8422 100644
> >>--- a/datapath-windows/ovsext/Flow.c
> >>+++ b/datapath-windows/ovsext/Flow.c
> >>@@ -110,9 +110,7 @@ const NL_POLICY nlFlowPolicy[] = {
> >>     [OVS_FLOW_ATTR_PROBE] = {.type = NL_A_FLAG, .optional = TRUE}  };
> >>
> >>-/* For Parsing nested OVS_FLOW_ATTR_KEY attributes.
> >>- * Some of the attributes like OVS_KEY_ATTR_RECIRC_ID
> >>- * are not supported yet. */
> >>+/* For Parsing nested OVS_FLOW_ATTR_KEY attributes. */
> >>
> >> const NL_POLICY nlFlowKeyPolicy[] = {
> >>     [OVS_KEY_ATTR_ENCAP] = {.type = NL_A_VAR_LEN, .optional = TRUE},
> >>@@ -252,7 +250,7 @@
> OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT
> >>usrParamsCtx,
> >>                     UINT32 *replyLen)  {
> >>     NTSTATUS rc = STATUS_SUCCESS;
> >>-    BOOLEAN ok;
> >>+    BOOLEAN ok = FALSE;
> >>     POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx-
> >inputBuffer;
> >>     POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx-
> >outputBuffer;
> >>     PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg); @@ -260,11 +258,11 @@
> >>OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT
> >>usrParamsCtx,
> >>     POVS_HDR ovsHdr = &(msgIn->ovsHdr);
> >>     PNL_ATTR flowAttrs[__OVS_FLOW_ATTR_MAX];
> >>     UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
> >>-    OvsFlowPut mappedFlow;
> >>-    OvsFlowStats stats;
> >>-    struct ovs_flow_stats replyStats;
> >>+    OvsFlowPut mappedFlow = { 0 };
> >>+    OvsFlowStats stats = { 0 };
> >>+    struct ovs_flow_stats replyStats = { 0 };
> >>     NL_ERROR nlError = NL_ERROR_SUCCESS;
> >>-    NL_BUFFER nlBuf;
> >>+    NL_BUFFER nlBuf = { 0 };
> >>
> >>     RtlZeroMemory(&mappedFlow, sizeof(OvsFlowPut));
> >>     RtlZeroMemory(&stats, sizeof(stats)); @@ -594,9 +592,9 @@
> >>_FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT
> >>usrParamsCtx,
> >>     UINT32 hdrOffset = 0;
> >>
> >>     /* Get Next */
> >>-    OvsFlowDumpOutput dumpOutput;
> >>-    OvsFlowDumpInput dumpInput;
> >>-    NL_BUFFER nlBuf;
> >>+    OvsFlowDumpOutput dumpOutput = { 0 };
> >>+    OvsFlowDumpInput dumpInput = { 0 };
> >>+    NL_BUFFER nlBuf = { 0 };
> >>
> >>     NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
> >>               usrParamsCtx->outputLength); @@ -826,6 +824,12 @@
> >>MapFlowKeyToNlKey(PNL_BUFFER nlBuf,
> >>         goto error_nested_start;
> >>     }
> >>
> >>+    if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_RECIRC_ID,
> >>+                         flowKey->recircId)) {
> >>+        rc = STATUS_UNSUCCESSFUL;
> >>+        goto done;
> >>+    }
> >>+
> >>     /* Ethernet header */
> >>     RtlCopyMemory(&(ethKey.eth_src), flowKey->l2.dlSrc,
> ETH_ADDR_LEN);
> >>     RtlCopyMemory(&(ethKey.eth_dst), flowKey->l2.dlDst,
> >>ETH_ADDR_LEN); @@ -1348,6 +1352,10 @@
> _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,  {
> >>     _MapTunAttrToFlowPut(keyAttrs, tunnelAttrs, destKey);
> >>
> >>+    if (keyAttrs[OVS_KEY_ATTR_RECIRC_ID]) {
> >>+        destKey->recircId =
> >>NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_RECIRC_ID]);
> >>+    }
> >>+
> >>     /* ===== L2 headers ===== */
> >>     destKey->l2.inPort =
> >> NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);
> >>
> >>@@ -2072,6 +2080,9 @@ OvsLookupFlow(OVS_DATAPATH *datapath,
> >>
> >>     if (!hashValid) {
> >>         *hash = OvsJhashBytes(start, size, 0);
> >>+        if (key->recircId) {
> >>+            *hash = OvsJhashWords((UINT32*)hash, 1, key->recircId);
> >>+        }
> >>     }
> >>
> >>     head = &datapath->flowTable[HASH_BUCKET(*hash)];
> >>@@ -2090,6 +2101,47 @@ OvsLookupFlow(OVS_DATAPATH *datapath,
> >>     return NULL;
> >> }
> >>
> >>+/*
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>--
> >>+ * OvsLookupFlowRecirc --
> >>+ *
> >>+ *    Find flow from flow table based on flow key and recircId, if
> >>available.
> >>+ *    Caller should either hold portset handle or should
> >>+ *    have a flowRef in datapath or Acquired datapath.
> >>+ *
> >>+ * Results:
> >>+ *    Flow pointer if lookup successful.
> >>+ *    NULL if not exists.
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>--
> >>+ */
> >>+OvsFlow *
> >>+OvsLookupFlowRecirc(OVS_DATAPATH *datapath,
> >>+                    const OvsFlowKey *key,
> >>+                    UINT64 *hash)
> >>+{
> >>+    OvsFlow* flow = NULL;
> >>+
> >>+    if (!hash || !(*hash)) {
> >>+        flow = OvsLookupFlow(datapath, key, hash, FALSE);
> >>+    } else {
> >>+        /*
> >>+         * Pre and post recirculation flows usually have the same hash
> >>+         * value. To avoid hash collisions, rehash the 'hash' with
> >>+         * 'recircId'.
> >>+         */
> >>+        if (key->recircId) {
> >>+            *hash = OvsJhashWords((UINT32*)hash, 1, key->recircId);
> >>+        }
> >>+
> >>+        flow = OvsLookupFlow(datapath, key, hash, FALSE);
> >>+        if (flow) {
> >>+            flow->hash = *hash;
> >>+        }
> >>+    }
> >>+
> >>+    return flow;
> >>+}
> >>+
> >>
> >> /*
> >>  *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>--
> >>@@ -2239,6 +2291,8 @@ ReportFlowInfo(OvsFlow *flow,
> >>         }
> >>     }
> >>
> >>+    info->key.recircId = flow->key.recircId;
> >>+
> >>     return status;
> >> }
> >>
> >>diff --git a/datapath-windows/ovsext/Flow.h
> >>b/datapath-windows/ovsext/Flow.h index 74b9dfb..78bf7cc 100644
> >>--- a/datapath-windows/ovsext/Flow.h
> >>+++ b/datapath-windows/ovsext/Flow.h
> >>@@ -54,8 +54,11 @@ NDIS_STATUS
> OvsAllocateFlowTable(OVS_DATAPATH
> >>*datapath,  NDIS_STATUS OvsExtractFlow(const NET_BUFFER_LIST *pkt,
> >>UINT32 inPort,
> >>                            OvsFlowKey *flow, POVS_PACKET_HDR_INFO
> >>layers,
> >>                            OvsIPv4TunnelKey *tunKey); -OvsFlow
> >>*OvsLookupFlow(OVS_DATAPATH *datapath, const OvsFlowKey *key,
> >>+OvsFlow* OvsLookupFlow(OVS_DATAPATH *datapath, const
> OvsFlowKey *key,
> >>                        UINT64 *hash, BOOLEAN hashValid);
> >>+OvsFlow* OvsLookupFlowRecirc(OVS_DATAPATH *datapath,
> >>+                             const OvsFlowKey *key,
> >>+                             UINT64 *hash);
> >> UINT64 OvsHashFlow(const OvsFlowKey *key);  VOID
> OvsFlowUsed(OvsFlow
> >>*flow, const NET_BUFFER_LIST *pkt,
> >>                  const POVS_PACKET_HDR_INFO layers); diff --git
> >>a/datapath-windows/ovsext/Netlink/Netlink.h
> >>b/datapath-windows/ovsext/Netlink/Netlink.h
> >>index 99665fb..8f6a5be 100644
> >>--- a/datapath-windows/ovsext/Netlink/Netlink.h
> >>+++ b/datapath-windows/ovsext/Netlink/Netlink.h
> >>@@ -173,6 +173,17 @@ static __inline NlAttrTotalSize(UINT32
> payloadSize)
> >>     return NLA_ALIGN(NlAttrSize(payloadSize));
> >> }
> >>
> >>+/*
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>-
> >>+ * Returns true if the last attribute is reached.
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>-
> >>+ */
> >>+BOOLEAN
> >>+static __inline NlAttrIsLast(const PNL_ATTR nla, int rem) {
> >>+    return nla->nlaLen == rem;
> >>+}
> >>+
> >> /* Netlink attribute validation */
> >> BOOLEAN NlAttrValidate(const PNL_ATTR, const PNL_POLICY);
> >>
> >>diff --git a/datapath-windows/ovsext/PacketIO.c
> >>b/datapath-windows/ovsext/PacketIO.c
> >>index cfbae34..a0ddc3d 100644
> >>--- a/datapath-windows/ovsext/PacketIO.c
> >>+++ b/datapath-windows/ovsext/PacketIO.c
> >>@@ -20,6 +20,8 @@
> >>  */
> >>
> >> #include "precomp.h"
> >>+
> >>+#include "Actions.h"
> >> #include "Switch.h"
> >> #include "Vport.h"
> >> #include "NetProto.h"
> >>@@ -234,14 +236,14 @@ OvsStartNBLIngress(POVS_SWITCH_CONTEXT
> >>switchContext,
> >>     OvsInitCompletionList(&completionList, switchContext,
> >>sendCompleteFlags);
> >>
> >>     for (curNbl = netBufferLists; curNbl != NULL; curNbl = nextNbl) {
> >>-        POVS_VPORT_ENTRY vport;
> >>-        UINT32 portNo;
> >>+        POVS_VPORT_ENTRY vport = NULL;
> >>+        UINT32 portNo = 0;
> >>         OVS_DATAPATH *datapath = &switchContext->datapath;
> >>-        OVS_PACKET_HDR_INFO layers;
> >>-        OvsFlowKey key;
> >>-        UINT64 hash;
> >>-        PNET_BUFFER curNb;
> >>-        POVS_BUFFER_CONTEXT ctx;
> >>+        OVS_PACKET_HDR_INFO layers = { 0 };
> >>+        OvsFlowKey key = { 0 };
> >>+        UINT64 hash = 0;
> >>+        PNET_BUFFER curNb = NULL;
> >>+        POVS_BUFFER_CONTEXT ctx = NULL;
> >>
> >>         nextNbl = curNbl->Next;
> >>         curNbl->Next = NULL;
> >>diff --git a/datapath-windows/ovsext/PacketIO.h
> >>b/datapath-windows/ovsext/PacketIO.h
> >>index 7247869..a7c1f76 100644
> >>--- a/datapath-windows/ovsext/PacketIO.h
> >>+++ b/datapath-windows/ovsext/PacketIO.h
> >>@@ -48,14 +48,4 @@ VOID OvsSendNBLIngress(POVS_SWITCH_CONTEXT
> >>switchContext,
> >>                        PNET_BUFFER_LIST netBufferLists,
> >>                        ULONG sendFlags);
> >>
> >>-NDIS_STATUS OvsActionsExecute(POVS_SWITCH_CONTEXT
> switchContext,
> >>-                              OvsCompletionList *completionList,
> >>-                              PNET_BUFFER_LIST curNbl, UINT32
> >>srcVportNo,
> >>-                              ULONG sendFlags, OvsFlowKey *key, UINT64
> >>*hash,
> >>-                              OVS_PACKET_HDR_INFO *layers,
> >>-                              const PNL_ATTR actions, int actionsLen);
> >>-
> >>-VOID OvsLookupFlowOutput(POVS_SWITCH_CONTEXT switchContext,
> >>-                         VOID *compList, PNET_BUFFER_LIST curNbl);
> >>-
> >> #endif /* __PACKETIO_H_ */
> >>diff --git a/datapath-windows/ovsext/Recirc.c
> >>b/datapath-windows/ovsext/Recirc.c
> >>new file mode 100644
> >>index 0000000..fa8db80
> >>--- /dev/null
> >>+++ b/datapath-windows/ovsext/Recirc.c
> >>@@ -0,0 +1,171 @@
> >>+/*
> >>+ * Copyright (c) 2015 Cloudbase Solutions Srl
> >>+ *
> >>+ * Licensed under the Apache License, Version 2.0 (the "License");
> >>+ * you may not use this file except in compliance with the License.
> >>+ * You may obtain a copy of the License at:
> >>+ *
> >>+ *
> >>https://urldefense.proofpoint.com/v2/url?u=http-
> 3A__www.apache.org_lic
> >>ens
> >>es_LICENSE-2D2.0&d=BQIFAw&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-
> YihVMNtXt-uE
> >>s&r
> >>=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=xvtKJvzpDJsqis
> OGVQT_4cZ
> >>5Ua
> ZJntaL6eM3Jisxkwo&s=kHCjput72ZhJsAXzrf15z3mr80BW2XuxvE1QIGkayyQ&
> e=
> >>+ *
> >>+ * Unless required by applicable law or agreed to in writing,
> >>+ software
> >>+ * distributed under the License is distributed on an "AS IS" BASIS,
> >>+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
> or
> >>implied.
> >>+ * See the License for the specific language governing permissions
> >>+ and
> >>+ * limitations under the License.
> >>+ */
> >>+
> >>+#include "Recirc.h"
> >>+#include "Flow.h"
> >>+#include "Jhash.h"
> >>+
> >>+static OVS_DEFERRED_ACTION_QUEUE ovsDeferredActionsQueue = { 0
> };
> >>+extern NDIS_SPIN_LOCK ovsRecircLockObj;
> >>+
> >>+/*
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ * OvsDeferredActionsQueueInit --
> >>+ *     The function resets the queue to be ready for the next packet.
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ */
> >>+static
> >>+VOID
> >>+OvsDeferredActionsQueueInit(POVS_DEFERRED_ACTION_QUEUE
> queue) {
> >>+    queue->head = 0;
> >>+    queue->tail = 0;
> >>+}
> >>+
> >>+/*
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ * OvsDeferredActionsQueueIsEmpty --
> >>+ *     The function verifies if the queue is empty.
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ */
> >>+static
> >>+BOOLEAN
> >>+OvsDeferredActionsQueueIsEmpty(const
> POVS_DEFERRED_ACTION_QUEUE
> >>+queue) {
> >
> >Sai - This doesn¹t seem thread safe since
> >OvsDeferredActionsQueueIsEmpty is called outside the lock
> >SV: OvsDeferredActionsQueueIsEmpty is an internal function and is used
> >only inside of a lock.
> >
> >>+    return (queue->head == queue->tail); }
> >>+
> >>+/*
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ * OvsDeferredActionsQueuePop --
> >>+ *     The function pops the next queue element.
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ */
> >>+static
> >>+POVS_DEFERRED_ACTION
> >>+OvsDeferredActionsQueuePop(POVS_DEFERRED_ACTION_QUEUE
> queue) {
> >>+    POVS_DEFERRED_ACTION deferredAction = NULL;
> >>+
> >>+    NdisAcquireSpinLock(&ovsRecircLockObj);
> >>+
> >>+    if (OvsDeferredActionsQueueIsEmpty(queue)) {
> >>+        /* Reset the queue for the next packet. */
> >>+        OvsDeferredActionsQueueInit(queue);
> >>+    } else {
> >>+        deferredAction = &queue->queue[queue->tail++];
> >>+    }
> >>+
> >>+    NdisReleaseSpinLock(&ovsRecircLockObj);
> >>+
> >>+    return deferredAction;
> >>+}
> >>+
> >>+/*
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ * OvsDeferredActionsQueuePush --
> >>+ *     The function pushes the current element in the deferred actions
> >>queue.
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ */
> >>+static
> >>+POVS_DEFERRED_ACTION
> >>+OvsDeferredActionsQueuePush(POVS_DEFERRED_ACTION_QUEUE
> queue) {
> >>+    POVS_DEFERRED_ACTION deferredAction = NULL;
> >>+
> >>+    NdisAcquireSpinLock(&ovsRecircLockObj);
> >>+
> >>+    if (queue->head < DEFERRED_ACTION_QUEUE_SIZE) {
> >>+        deferredAction = &queue->queue[queue->head++];
> >>+    }
> >>+
> >>+    NdisReleaseSpinLock(&ovsRecircLockObj);
> >>+
> >>+    return deferredAction;
> >>+}
> >>+
> >>+/*
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ * OvsAddDeferredActions --
> >>+ *     This function returns the new queue entry if the queue is not
> >>already
> >>+ *     full.
> >>+ *
> >>+ * Note:
> >>+ *     The function is thread-safe.
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ */
> >>+POVS_DEFERRED_ACTION
> >>+OvsAddDeferredActions(PNET_BUFFER_LIST packet,
> >>+                      OvsFlowKey *key,
> >>+                      UINT64 hash,
> >>+                      const PNL_ATTR actions) {
> >>+    POVS_DEFERRED_ACTION deferredAction = NULL;
> >>+
> >>+    deferredAction =
> >>OvsDeferredActionsQueuePush(&ovsDeferredActionsQueue);
> >>+    if (deferredAction) {
> >>+        deferredAction->packet = packet;
> >>+        deferredAction->actions = actions;
> >>+        deferredAction->key = *key;
> >>+        deferredAction->hash = hash;
> >>+    }
> >>+
> >>+    return deferredAction;
> >>+}
> >>+
> >>+/*
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ * OvsProcessDeferredActions --
> >>+ *     This function processes all deferred actions contained in the
> >>queue.
> >>+ *
> >>+ * Note:
> >>+ *     The function is thread-safe.
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ */
> >>+NTSTATUS
> >>+OvsProcessDeferredActions(POVS_SWITCH_CONTEXT switchContext,
> >>+                          OvsCompletionList *completionList,
> >>+                          UINT32 portNo,
> >>+                          ULONG sendFlags,
> >>+                          OVS_PACKET_HDR_INFO *layers) {
> >>+    NTSTATUS status = STATUS_SUCCESS;
> >>+    POVS_DEFERRED_ACTION_QUEUE queue =
> &ovsDeferredActionsQueue;
> >>+    POVS_DEFERRED_ACTION deferredAction = NULL;
> >>+
> >>+    /* Process all deferred actions. */
> >>+    while ((deferredAction = OvsDeferredActionsQueuePop(queue)) !=
> >>+ NULL)
> >>{
> >>+        if (deferredAction->actions) {
> >>+            status = OvsDoExecuteActions(switchContext,
> >>+                                         completionList,
> >>+                                         deferredAction->packet,
> >>+                                         portNo,
> >>+                                         sendFlags,
> >>+                                         &deferredAction->key,
> >>+                                         &deferredAction->hash,
> >>+                                         layers,
> >>+ deferredAction->actions,
> >>+
> >>NlAttrGetSize(deferredAction->actions));
> >>+        } else {
> >>+            status = OvsDoRecircFlowLookupOutput(switchContext,
> >>+                                                 completionList,
> >>+                                                 deferredAction->packet,
> >>+                                                 &deferredAction->key,
> >>+                                                 &deferredAction->hash);
> >>+        }
> >>+    }
> >>+
> >>+    return status;
> >>+}
> >>diff --git a/datapath-windows/ovsext/Recirc.h
> >>b/datapath-windows/ovsext/Recirc.h
> >>new file mode 100644
> >>index 0000000..6b5653c
> >>--- /dev/null
> >>+++ b/datapath-windows/ovsext/Recirc.h
> >>@@ -0,0 +1,82 @@
> >>+/*
> >>+ * Copyright (c) 2015 Cloudbase Solutions Srl
> >>+ *
> >>+ * Licensed under the Apache License, Version 2.0 (the "License");
> >>+ * you may not use this file except in compliance with the License.
> >>+ * You may obtain a copy of the License at:
> >>+ *
> >>+ *
> >>https://urldefense.proofpoint.com/v2/url?u=http-
> 3A__www.apache.org_lic
> >>ens
> >>es_LICENSE-2D2.0&d=BQIFAw&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-
> YihVMNtXt-uE
> >>s&r
> >>=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=xvtKJvzpDJsqis
> OGVQT_4cZ
> >>5Ua
> ZJntaL6eM3Jisxkwo&s=kHCjput72ZhJsAXzrf15z3mr80BW2XuxvE1QIGkayyQ&
> e=
> >>+ *
> >>+ * Unless required by applicable law or agreed to in writing,
> >>+ software
> >>+ * distributed under the License is distributed on an "AS IS" BASIS,
> >>+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
> or
> >>implied.
> >>+ * See the License for the specific language governing permissions
> >>+ and
> >>+ * limitations under the License.
> >>+ */
> >>+
> >>+#ifndef __RECIRC_H_
> >>+#define __RECIRC_H_ 1
> >>+
> >>+#include "Actions.h"
> >>+
> >>+#define DEFERRED_ACTION_QUEUE_SIZE          10
> >>+
> >>+typedef struct _OVS_DEFERRED_ACTION {
> >>+    PNET_BUFFER_LIST    packet;
> >>+    PNL_ATTR            actions;
> >>+    OvsFlowKey          key;
> >>+    UINT64              hash;
> >>+} OVS_DEFERRED_ACTION, *POVS_DEFERRED_ACTION;
> >>+
> >>+/*
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ * '_OVS_DEFERRED_ACTION_QUEUE' is responsible for keeping track of
> >>+ all
> >>+ * deferred actions. The maximum number of deferred actions should
> >>+ not
> >>exceed
> >>+ * 'DEFERRED_ACTION_QUEUE_SIZE'.
> >>+ *
> >>+ * Note:
> >>+ *   Adding/removing a deferred action to/from the queue is only safe
> >>while
> >>+ *   holding a proper lock.
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ */
> >>+typedef struct _OVS_DEFERRED_ACTION_QUEUE {
> >>+    UINT32  head;
> >>+    UINT32  tail;
> >>+    OVS_DEFERRED_ACTION queue[DEFERRED_ACTION_QUEUE_SIZE];
> >>+} OVS_DEFERRED_ACTION_QUEUE, *POVS_DEFERRED_ACTION_QUEUE;
> >>+
> >>+/*
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ * OvsProcessDeferredActions --
> >>+ *     This function processes all deferred actions contained in the
> >>queue.
> >>+ *
> >>+ * Note:
> >>+ *     The function is not thread-safe. It is the resposibility of the
> >>caller
> >>+ *     to hold a proper lock.
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ */
> >>+NTSTATUS
> >>+OvsProcessDeferredActions(POVS_SWITCH_CONTEXT switchContext,
> >>+                          OvsCompletionList *completionList,
> >>+                          UINT32 portNo,
> >>+                          ULONG sendFlags,
> >>+                          OVS_PACKET_HDR_INFO *layers);
> >>+
> >>+/*
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ * OvsAddDeferredActions --
> >>+ *     This function returns the new queue entry if the queue is not
> >>already
> >>+ *     full.
> >>+ *
> >>+ * Note:
> >>+ *     The function is not thread-safe. It is the resposibility of the
> >>caller
> >>+ *     to hold a proper lock.
> >>+ *
> >>----------------------------------------------------------------------
> >>-
> >>---
> >>+ */
> >>+POVS_DEFERRED_ACTION
> >>+OvsAddDeferredActions(PNET_BUFFER_LIST packet,
> >>+                      OvsFlowKey *key,
> >>+                      UINT64 hash,
> >>+                      const PNL_ATTR actions);
> >>+
> >>+#endif /* __RECIRC_H_ */
> >>diff --git a/datapath-windows/ovsext/Tunnel.c
> >>b/datapath-windows/ovsext/Tunnel.c
> >>index eea4a84..e957aaf 100644
> >>--- a/datapath-windows/ovsext/Tunnel.c
> >>+++ b/datapath-windows/ovsext/Tunnel.c
> >>@@ -39,6 +39,7 @@
> >> #include "PacketIO.h"
> >> #include "NetProto.h"
> >> #include "Flow.h"
> >>+#include "Actions.h"
> >>
> >> extern POVS_SWITCH_CONTEXT gOvsSwitchContext;
> >>
> >>@@ -258,13 +259,13 @@
> OvsInjectPacketThroughActions(PNET_BUFFER_LIST
> >>pNbl,
> >>                           sendCompleteFlags);
> >>
> >>     {
> >>-        POVS_VPORT_ENTRY vport;
> >>-        UINT32 portNo;
> >>-        OVS_PACKET_HDR_INFO layers;
> >>-        OvsFlowKey key;
> >>-        UINT64 hash;
> >>-        PNET_BUFFER curNb;
> >>-        OvsFlow *flow;
> >>+        POVS_VPORT_ENTRY vport = NULL;
> >>+        UINT32 portNo = 0;
> >>+        OVS_PACKET_HDR_INFO layers = { 0 };
> >>+        OvsFlowKey key = { 0 };
> >>+        UINT64 hash = 0;
> >>+        PNET_BUFFER curNb = NULL;
> >>+        OvsFlow *flow = NULL;
> >>
> >>         fwdDetail =
> NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(pNbl);
> >>
> >>diff --git a/datapath-windows/ovsext/User.c
> >>b/datapath-windows/ovsext/User.c index e97f2b2..cadffda 100644
> >>--- a/datapath-windows/ovsext/User.c
> >>+++ b/datapath-windows/ovsext/User.c
> >>@@ -22,6 +22,7 @@
> >>
> >> #include "precomp.h"
> >>
> >>+#include "Actions.h"
> >> #include "Datapath.h"
> >> #include "Debug.h"
> >> #include "Event.h"
> >>@@ -388,14 +389,14 @@ NTSTATUS
> >> OvsExecuteDpIoctl(OvsPacketExecute *execute)  {
> >>     NTSTATUS                    status = STATUS_SUCCESS;
> >>-    NTSTATUS                    ndisStatus;
> >>+    NTSTATUS                    ndisStatus = STATUS_SUCCESS;
> >>     LOCK_STATE_EX               lockState;
> >>-    PNET_BUFFER_LIST pNbl;
> >>-    PNL_ATTR actions;
> >>+    PNET_BUFFER_LIST            pNbl = NULL;
> >>+    PNL_ATTR                    actions = NULL;
> >>     PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO
> fwdDetail;
> >>-    OvsFlowKey key;
> >>-    OVS_PACKET_HDR_INFO layers;
> >>-    POVS_VPORT_ENTRY vport;
> >>+    OvsFlowKey                  key = { 0 };
> >>+    OVS_PACKET_HDR_INFO         layers = { 0 };
> >>+    POVS_VPORT_ENTRY            vport = NULL;
> >>
> >>     if (execute->packetLen == 0) {
> >>         status = STATUS_INVALID_PARAMETER; diff --git
> >>a/datapath-windows/ovsext/ovsext.vcxproj
> >>b/datapath-windows/ovsext/ovsext.vcxproj
> >>index 7b0ebcf..36187a6 100644
> >>--- a/datapath-windows/ovsext/ovsext.vcxproj
> >>+++ b/datapath-windows/ovsext/ovsext.vcxproj
> >>@@ -71,6 +71,7 @@
> >>   </ImportGroup>
> >>   <ItemGroup Label="WrappedTaskItems">
> >>     <ClInclude Include="..\include\OvsDpInterfaceExt.h" />
> >>+    <ClInclude Include="Actions.h" />
> >>     <ClInclude Include="Atomic.h" />
> >>     <ClInclude Include="BufferMgmt.h" />
> >>     <ClInclude Include="Datapath.h" /> @@ -93,6 +94,7 @@
> >>     <ClInclude Include="PacketIO.h" />
> >>     <ClInclude Include="PacketParser.h" />
> >>     <ClInclude Include="precomp.h" />
> >>+    <ClInclude Include="Recirc.h" />
> >>     <ClInclude Include="resource.h" />
> >>     <ClInclude Include="Stt.h" />
> >>     <ClInclude Include="Switch.h" />
> >>@@ -189,6 +191,7 @@
> >>       <PreCompiledHeader>Create</PreCompiledHeader>
> >>
> >><PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiled
> Heade
> >>r
> >>Out
> >>putFile>
> >>     </ClCompile>
> >>+    <ClCompile Include="Recirc.c" />
> >>     <ClCompile Include="Stt.c" />
> >>     <ClCompile Include="Switch.c" />
> >>     <ClCompile Include="Tunnel.c" />
> >>--
> >>1.9.0.msysgit.0
> >>
> >>_______________________________________________
> >>dev mailing list
> >>dev@openvswitch.org
> >>https://urldefense.proofpoint.com/v2/url?u=http-
> 3A__openvswitch.org_ma
> >>ilm
> >>an_listinfo_dev&d=BQIFAw&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-
> YihVMNtXt-uEs
> >>&r=
> >>Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=xvtKJvzpDJsqis
> OGVQT_4cZ5
> >>UaZ JntaL6eM3Jisxkwo&s=Rl4mC2vA2nuegMiJ6sYRoEbzBtAFm-
> 9T2Y4aYaoPy7E&e=
> >
> >
> >
> 
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to