datapath-windows: Suppress flow attribute probe.
[cascardo/ovs.git] / datapath-windows / ovsext / Flow.c
index 14c3072..8117cf7 100644 (file)
@@ -31,7 +31,6 @@
 #pragma warning( push )
 #pragma warning( disable:4127 )
 
-extern PNDIS_SPIN_LOCK gOvsCtrlLock;
 extern POVS_SWITCH_CONTEXT gOvsSwitchContext;
 extern UINT64 ovsTimeIncrementPerTick;
 
@@ -103,7 +102,8 @@ const NL_POLICY nlFlowPolicy[] = {
                              .maxLen = sizeof(struct ovs_flow_stats),
                              .optional = TRUE},
     [OVS_FLOW_ATTR_TCP_FLAGS] = {NL_A_U8, .optional = TRUE},
-    [OVS_FLOW_ATTR_USED] = {NL_A_U64, .optional = TRUE}
+    [OVS_FLOW_ATTR_USED] = {NL_A_U64, .optional = TRUE},
+    [OVS_FLOW_ATTR_PROBE] = {.type = NL_A_FLAG, .optional = TRUE}
 };
 
 /* For Parsing nested OVS_FLOW_ATTR_KEY attributes.
@@ -172,6 +172,7 @@ const NL_POLICY nlFlowKeyPolicy[] = {
                                 .maxLen = 4, .optional = TRUE},
     [OVS_KEY_ATTR_MPLS] = {.type = NL_A_VAR_LEN, .optional = TRUE}
 };
+const UINT32 nlFlowKeyPolicyLen = ARRAY_SIZE(nlFlowKeyPolicy);
 
 /* For Parsing nested OVS_KEY_ATTR_TUNNEL attributes */
 const NL_POLICY nlFlowTunnelKeyPolicy[] = {
@@ -247,6 +248,7 @@ OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
                     UINT32 *replyLen)
 {
     NTSTATUS rc = STATUS_SUCCESS;
+    BOOLEAN ok;
     POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
     POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;
     PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
@@ -258,7 +260,6 @@ OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
     OvsFlowStats stats;
     struct ovs_flow_stats replyStats;
     NL_ERROR nlError = NL_ERROR_SUCCESS;
-
     NL_BUFFER nlBuf;
 
     RtlZeroMemory(&mappedFlow, sizeof(OvsFlowPut));
@@ -273,7 +274,8 @@ OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
 
     /* Get all the top level Flow attributes */
     if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
-                     nlFlowPolicy, nlAttrs, ARRAY_SIZE(nlAttrs)))
+                     nlFlowPolicy, ARRAY_SIZE(nlFlowPolicy),
+                     nlAttrs, ARRAY_SIZE(nlAttrs)))
                      != TRUE) {
         OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
                        nlMsgHdr);
@@ -294,19 +296,26 @@ OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
                       usrParamsCtx->outputLength);
 
             /* Prepare nl Msg headers */
-            rc = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
+            ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
                               nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
                               genlMsgHdr->cmd, OVS_FLOW_VERSION,
                               ovsHdr->dp_ifindex);
-
-            if (rc == STATUS_SUCCESS) {
+            if (ok) {
                 *replyLen = msgOut->nlMsg.nlmsgLen;
+            } else {
+                rc = STATUS_INVALID_BUFFER_SIZE;
             }
        }
 
        goto done;
     }
 
+    if (flowAttrs[OVS_FLOW_ATTR_PROBE]) {
+        OVS_LOG_ERROR("Attribute OVS_FLOW_ATTR_PROBE not supported");
+        nlError = NL_ERROR_NOENT;
+        goto done;
+    }
+
     if ((rc = _MapNlToFlowPut(msgIn, nlAttrs[OVS_FLOW_ATTR_KEY],
          nlAttrs[OVS_FLOW_ATTR_ACTIONS], nlAttrs[OVS_FLOW_ATTR_CLEAR],
          &mappedFlow))
@@ -318,7 +327,7 @@ OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
     rc = OvsPutFlowIoctl(&mappedFlow, sizeof (struct OvsFlowPut),
                          &stats);
     if (rc != STATUS_SUCCESS) {
-        OVS_LOG_ERROR("OvsFlowPut failed.");
+        OVS_LOG_ERROR("OvsPutFlowIoctl failed.");
         goto done;
     }
 
@@ -330,13 +339,15 @@ OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
               usrParamsCtx->outputLength);
 
     /* Prepare nl Msg headers */
-    rc = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
+    ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
                       nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
                       genlMsgHdr->cmd, OVS_FLOW_VERSION,
                       ovsHdr->dp_ifindex);
-
-    if (rc != STATUS_SUCCESS) {
+    if (!ok) {
+        rc = STATUS_INVALID_BUFFER_SIZE;
         goto done;
+    } else {
+        rc = STATUS_SUCCESS;
     }
 
     /* Append OVS_FLOW_ATTR_STATS attribute */
@@ -355,7 +366,7 @@ done:
     if (nlError != NL_ERROR_SUCCESS) {
         POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
                                        usrParamsCtx->outputBuffer;
-        BuildErrorMsg(msgIn, msgError, nlError);
+        NlBuildErrorMsg(msgIn, msgError, nlError);
         *replyLen = msgError->nlMsg.nlmsgLen;
         rc = STATUS_SUCCESS;
     }
@@ -387,7 +398,7 @@ OvsFlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
             (usrParamsCtx->outputBuffer)) {
             POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
                                            usrParamsCtx->outputBuffer;
-            BuildErrorMsg(msgIn, msgError, nlError);
+            NlBuildErrorMsg(msgIn, msgError, nlError);
             *replyLen = msgError->nlMsg.nlmsgLen;
             status = STATUS_SUCCESS;
             goto done;
@@ -411,9 +422,7 @@ _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
                      UINT32 *replyLen)
 {
     NTSTATUS rc = STATUS_SUCCESS;
-    POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)
-                                  (usrParamsCtx->ovsInstance);
-    POVS_MESSAGE msgIn = instance->dumpState.ovsMsg;
+    POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
     PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
     POVS_HDR ovsHdr = &(msgIn->ovsHdr);
     PNL_MSG_HDR nlMsgOutHdr = NULL;
@@ -432,6 +441,7 @@ _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
     RtlZeroMemory(&getOutput, sizeof(OvsFlowGetOutput));
     UINT32 keyAttrOffset = 0;
     UINT32 tunnelKeyAttrOffset = 0;
+    BOOLEAN ok;
 
     if (usrParamsCtx->inputLength > usrParamsCtx->outputLength) {
         /* Should not be the case.
@@ -445,7 +455,8 @@ _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
 
     /* Get all the top level Flow attributes */
     if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
-                     nlFlowPolicy, nlAttrs, ARRAY_SIZE(nlAttrs)))
+                     nlFlowPolicy, ARRAY_SIZE(nlFlowPolicy),
+                     nlAttrs, ARRAY_SIZE(nlAttrs)))
                      != TRUE) {
         OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
                        nlMsgHdr);
@@ -459,7 +470,8 @@ _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
     /* Get flow keys attributes */
     if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset,
                            NlAttrLen(nlAttrs[OVS_FLOW_ATTR_KEY]),
-                           nlFlowKeyPolicy, keyAttrs, ARRAY_SIZE(keyAttrs)))
+                           nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy),
+                           keyAttrs, ARRAY_SIZE(keyAttrs)))
                            != TRUE) {
         OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
                        nlMsgHdr);
@@ -475,7 +487,8 @@ _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
         /* Get tunnel keys attributes */
         if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
                                NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
-                               nlFlowTunnelKeyPolicy,
+                               nlFlowTunnelKeyPolicy, 
+                               ARRAY_SIZE(nlFlowTunnelKeyPolicy),
                                tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
                                != TRUE) {
             OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
@@ -505,8 +518,12 @@ _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
 
     /* Input already has all the attributes for the flow key.
      * Lets copy the values back. */
-    RtlCopyMemory(usrParamsCtx->outputBuffer, usrParamsCtx->inputBuffer,
-                  usrParamsCtx->inputLength);
+    ok = NlMsgPutTail(&nlBuf, (PCHAR)(usrParamsCtx->inputBuffer),
+                      usrParamsCtx->inputLength);
+    if (!ok) {
+        OVS_LOG_ERROR("Could not copy the data to the buffer tail");
+        goto done;
+    }
 
     rc = _MapFlowStatsToNlStats(&nlBuf, &((getOutput.info).stats));
     if (rc != STATUS_SUCCESS) {
@@ -532,7 +549,7 @@ done:
 /*
  *----------------------------------------------------------------------------
  *  _FlowNlDumpCmdHandler --
- *    Handler for OVS_FLOW_CMD_GET command.
+ *    Handler for OVS_FLOW_CMD_DUMP command.
  *----------------------------------------------------------------------------
  */
 NTSTATUS
@@ -588,15 +605,20 @@ _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
 
         /* Done with Dump, send NLMSG_DONE */
         if (!(dumpOutput.n)) {
+            BOOLEAN ok;
+
             OVS_LOG_INFO("Dump Done");
 
             nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, NlBufSize(&nlBuf), 0));
-            rc = NlFillNlHdr(&nlBuf, NLMSG_DONE, NLM_F_MULTI,
+            ok = NlFillNlHdr(&nlBuf, NLMSG_DONE, NLM_F_MULTI,
                              nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid);
 
-            if (rc != STATUS_SUCCESS) {
+            if (!ok) {
+                rc = STATUS_INVALID_BUFFER_SIZE;
                 OVS_LOG_ERROR("Unable to prepare DUMP_DONE reply.");
                 break;
+            } else {
+                rc = STATUS_SUCCESS;
             }
 
             NlMsgAlignSize(nlMsgOutHdr);
@@ -605,17 +627,18 @@ _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
             FreeUserDumpState(instance);
             break;
         } else {
+            BOOLEAN ok;
 
             hdrOffset = NlBufSize(&nlBuf);
             nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, hdrOffset, 0));
 
             /* Netlink header */
-            rc = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, NLM_F_MULTI,
+            ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, NLM_F_MULTI,
                               nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
                               genlMsgHdr->cmd, genlMsgHdr->version,
                               ovsHdr->dp_ifindex);
 
-            if (rc != STATUS_SUCCESS) {
+            if (!ok) {
                 /* Reset rc to success so that we can
                  * send already added messages to user space. */
                 rc = STATUS_SUCCESS;
@@ -1171,7 +1194,8 @@ _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
 
     /* Get flow keys attributes */
     if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),
-                           nlFlowKeyPolicy, keyAttrs, ARRAY_SIZE(keyAttrs)))
+                           nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy),
+                           keyAttrs, ARRAY_SIZE(keyAttrs)))
                            != TRUE) {
         OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
                        nlMsgHdr);
@@ -1184,12 +1208,11 @@ _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
                               (keyAttrs[OVS_KEY_ATTR_TUNNEL])
                               - (PCHAR)nlMsgHdr);
 
-        OVS_LOG_ERROR("Parse Flow Tunnel Key Policy");
-
         /* Get tunnel keys attributes */
         if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
                                NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
                                nlFlowTunnelKeyPolicy,
+                               ARRAY_SIZE(nlFlowTunnelKeyPolicy),
                                tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
                                != TRUE) {
             OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
@@ -1502,8 +1525,13 @@ OvsDeleteFlowTable(OVS_DATAPATH *datapath)
     }
 
     DeleteAllFlows(datapath);
-    OvsFreeMemory(datapath->flowTable);
+    OvsFreeMemoryWithTag(datapath->flowTable, OVS_FLOW_POOL_TAG);
     datapath->flowTable = NULL;
+
+    if (datapath->lock == NULL) {
+        return NDIS_STATUS_SUCCESS;
+    }
+
     NdisFreeRWLock(datapath->lock);
 
     return NDIS_STATUS_SUCCESS;
@@ -1524,8 +1552,8 @@ OvsAllocateFlowTable(OVS_DATAPATH *datapath,
     PLIST_ENTRY bucket;
     int i;
 
-    datapath->flowTable = OvsAllocateMemory(OVS_FLOW_TABLE_SIZE *
-                                            sizeof (LIST_ENTRY));
+    datapath->flowTable = OvsAllocateMemoryWithTag(
+        OVS_FLOW_TABLE_SIZE * sizeof(LIST_ENTRY), OVS_FLOW_POOL_TAG);
     if (!datapath->flowTable) {
         return NDIS_STATUS_RESOURCES;
     }
@@ -1535,6 +1563,10 @@ OvsAllocateFlowTable(OVS_DATAPATH *datapath,
     }
     datapath->lock = NdisAllocateRWLock(switchContext->NdisFilterHandle);
 
+    if (!datapath->lock) {
+        return NDIS_STATUS_RESOURCES;
+    }
+
     return NDIS_STATUS_SUCCESS;
 }
 
@@ -1877,7 +1909,6 @@ RemoveFlow(OVS_DATAPATH *datapath,
 {
     OvsFlow *f = *flow;
     *flow = NULL;
-    UNREFERENCED_PARAMETER(datapath);
 
     ASSERT(datapath->nFlows);
     datapath->nFlows--;
@@ -1967,7 +1998,7 @@ VOID
 FreeFlow(OvsFlow *flow)
 {
     ASSERT(flow);
-    OvsFreeMemory(flow);
+    OvsFreeMemoryWithTag(flow, OVS_FLOW_POOL_TAG);
 }
 
 NTSTATUS
@@ -1986,26 +2017,23 @@ OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
     BOOLEAN findNextNonEmpty = FALSE;
 
     dpNo = dumpInput->dpNo;
-    NdisAcquireSpinLock(gOvsCtrlLock);
-    if (gOvsSwitchContext == NULL ||
-        gOvsSwitchContext->dpNo != dpNo) {
+    if (gOvsSwitchContext->dpNo != dpNo) {
         status = STATUS_INVALID_PARAMETER;
-        goto unlock;
+        goto exit;
     }
 
     rowIndex = dumpInput->position[0];
     if (rowIndex >= OVS_FLOW_TABLE_SIZE) {
         dumpOutput->n = 0;
         *replyLen = sizeof(*dumpOutput);
-        goto unlock;
+        goto exit;
     }
 
     columnIndex = dumpInput->position[1];
 
     datapath = &gOvsSwitchContext->datapath;
     ASSERT(datapath);
-    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
-    OvsAcquireDatapathRead(datapath, &dpLockState, TRUE);
+    OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
 
     head = &datapath->flowTable[rowIndex];
     node = head->Flink;
@@ -2054,33 +2082,10 @@ OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
 dp_unlock:
     OvsReleaseDatapath(datapath, &dpLockState);
 
-unlock:
-    NdisReleaseSpinLock(gOvsCtrlLock);
+exit:
     return status;
 }
 
-NTSTATUS
-OvsDumpFlowIoctl(PVOID inputBuffer,
-                 UINT32 inputLength,
-                 PVOID outputBuffer,
-                 UINT32 outputLength,
-                 UINT32 *replyLen)
-{
-    OvsFlowDumpOutput *dumpOutput = (OvsFlowDumpOutput *)outputBuffer;
-    OvsFlowDumpInput *dumpInput = (OvsFlowDumpInput *)inputBuffer;
-
-    if (inputBuffer == NULL || outputBuffer == NULL) {
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    if ((inputLength != sizeof(OvsFlowDumpInput))
-        || (outputLength != sizeof *dumpOutput + dumpInput->actionsLen)) {
-        return STATUS_INFO_LENGTH_MISMATCH;
-    }
-
-    return OvsDoDumpFlows(dumpInput, dumpOutput, replyLen);
-}
-
 static NTSTATUS
 ReportFlowInfo(OvsFlow *flow,
                UINT32 getFlags,
@@ -2138,22 +2143,18 @@ OvsPutFlowIoctl(PVOID inputBuffer,
     }
 
     dpNo = put->dpNo;
-    NdisAcquireSpinLock(gOvsCtrlLock);
-    if (gOvsSwitchContext == NULL ||
-        gOvsSwitchContext->dpNo != dpNo) {
+    if (gOvsSwitchContext->dpNo != dpNo) {
         status = STATUS_INVALID_PARAMETER;
-        goto unlock;
+        goto exit;
     }
 
     datapath = &gOvsSwitchContext->datapath;
     ASSERT(datapath);
-    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
-    OvsAcquireDatapathWrite(datapath, &dpLockState, TRUE);
+    OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
     status = HandleFlowPut(put, datapath, stats);
     OvsReleaseDatapath(datapath, &dpLockState);
 
-unlock:
-    NdisReleaseSpinLock(gOvsCtrlLock);
+exit:
     return status;
 }
 
@@ -2185,7 +2186,6 @@ HandleFlowPut(OvsFlowPut *put,
 
         status = OvsPrepareFlow(&KernelFlow, put, hash);
         if (status != STATUS_SUCCESS) {
-            FreeFlow(KernelFlow);
             return STATUS_UNSUCCESSFUL;
         }
 
@@ -2274,7 +2274,8 @@ OvsPrepareFlow(OvsFlow **flow,
 
     do {
         *flow = localFlow =
-            OvsAllocateMemory(sizeof(OvsFlow) + put->actionsLen);
+            OvsAllocateMemoryWithTag(sizeof(OvsFlow) + put->actionsLen,
+                                     OVS_FLOW_POOL_TAG);
         if (localFlow == NULL) {
             status = STATUS_NO_MEMORY;
             break;
@@ -2320,17 +2321,14 @@ OvsGetFlowIoctl(PVOID inputBuffer,
     }
 
     dpNo = getInput->dpNo;
-    NdisAcquireSpinLock(gOvsCtrlLock);
-    if (gOvsSwitchContext == NULL ||
-        gOvsSwitchContext->dpNo != dpNo) {
+    if (gOvsSwitchContext->dpNo != dpNo) {
         status = STATUS_INVALID_PARAMETER;
-        goto unlock;
+        goto exit;
     }
 
     datapath = &gOvsSwitchContext->datapath;
     ASSERT(datapath);
-    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
-    OvsAcquireDatapathRead(datapath, &dpLockState, TRUE);
+    OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
     flow = OvsLookupFlow(datapath, &getInput->key, &hash, FALSE);
     if (!flow) {
         status = STATUS_INVALID_PARAMETER;
@@ -2342,8 +2340,7 @@ OvsGetFlowIoctl(PVOID inputBuffer,
 
 dp_unlock:
     OvsReleaseDatapath(datapath, &dpLockState);
-unlock:
-    NdisReleaseSpinLock(gOvsCtrlLock);
+exit:
     return status;
 }
 
@@ -2354,22 +2351,18 @@ OvsFlushFlowIoctl(UINT32 dpNo)
     OVS_DATAPATH *datapath = NULL;
     LOCK_STATE_EX dpLockState;
 
-    NdisAcquireSpinLock(gOvsCtrlLock);
-    if (gOvsSwitchContext == NULL ||
-        gOvsSwitchContext->dpNo != dpNo) {
+    if (gOvsSwitchContext->dpNo != dpNo) {
         status = STATUS_INVALID_PARAMETER;
-        goto unlock;
+        goto exit;
     }
 
     datapath = &gOvsSwitchContext->datapath;
     ASSERT(datapath);
-    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
-    OvsAcquireDatapathWrite(datapath, &dpLockState, TRUE);
+    OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
     DeleteAllFlows(datapath);
     OvsReleaseDatapath(datapath, &dpLockState);
 
-unlock:
-    NdisReleaseSpinLock(gOvsCtrlLock);
+exit:
     return status;
 }