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_openvswit >>ch_ovs-2Dissues_issues_104&d=BQIFAw&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVM >>NtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=xvtKJvzpDJsqisOG >>VQT_4cZ5UaZJntaL6eM3Jisxkwo&s=ERhkBKIgo2mvl24FaQeUrlJVOOd8QOjoFc1a5VBEPrg >>&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_licens >>es_LICENSE-2D2.0&d=BQIFAw&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r >>=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=xvtKJvzpDJsqisOGVQT_4cZ5Ua >>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_licens >>es_LICENSE-2D2.0&d=BQIFAw&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r >>=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=xvtKJvzpDJsqisOGVQT_4cZ5Ua >>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_licens >>es_LICENSE-2D2.0&d=BQIFAw&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r >>=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=xvtKJvzpDJsqisOGVQT_4cZ5Ua >>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</PreCompiledHeader >>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_mailm >>an_listinfo_dev&d=BQIFAw&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r= >>Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=xvtKJvzpDJsqisOGVQT_4cZ5UaZ >>JntaL6eM3Jisxkwo&s=Rl4mC2vA2nuegMiJ6sYRoEbzBtAFm-9T2Y4aYaoPy7E&e= > > > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev