/* Check if the extension is enabled. */
if (NULL == gOvsSwitchContext) {
- status = STATUS_DEVICE_NOT_READY;
- goto done;
+ status = STATUS_NOT_FOUND;
+ goto exit;
+ }
+
+ if (!OvsAcquireSwitchContext()) {
+ status = STATUS_NOT_FOUND;
+ goto exit;
}
/* Concurrent netlink operations are not supported. */
status = InvokeNetlinkCmdHandler(&usrParamsCtx, nlFamilyOps, &replyLen);
done:
+ OvsReleaseSwitchContext(gOvsSwitchContext);
+
+exit:
KeMemoryBarrier();
instance->inUse = 0;
extern NDIS_HANDLE gOvsExtDriverHandle;
extern NDIS_HANDLE gOvsExtDriverObject;
+/*
+ * Reference count used to prevent premature deallocation of the global switch
+ * context structure, gOvsSwitchContext.
+ */
+volatile LONG gOvsSwitchContextRefCount = 1;
+
static NDIS_STATUS OvsCreateSwitch(NDIS_HANDLE ndisFilterHandle,
POVS_SWITCH_CONTEXT *switchContextOut);
static NDIS_STATUS OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext);
switchContext->isActivateFailed = FALSE;
switchContext->dpNo = OVS_DP_NUMBER;
ovsTimeIncrementPerTick = KeQueryTimeIncrement() / 10000;
+
OVS_LOG_TRACE("Exit: Succesfully initialized switchContext: %p",
switchContext);
return NDIS_STATUS_SUCCESS;
static VOID
OvsUninitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
+{
+ OvsReleaseSwitchContext(switchContext);
+}
+
+VOID
+OvsDeleteSwitchContext(POVS_SWITCH_CONTEXT switchContext)
{
OVS_LOG_TRACE("Enter: Delete switchContext:%p", switchContext);
OVS_LOG_TRACE("Exit: Delete switchContext: %p", switchContext);
}
+VOID
+OvsReleaseSwitchContext(POVS_SWITCH_CONTEXT switchContext)
+{
+ LONG ref = 0;
+ LONG newRef = 0;
+ LONG icxRef = 0;
+
+ do {
+ ref = gOvsSwitchContextRefCount;
+ newRef = (0 == ref) ? 0 : ref - 1;
+ icxRef = InterlockedCompareExchange(&gOvsSwitchContextRefCount,
+ newRef,
+ ref);
+ } while (icxRef != ref);
+
+ if (ref == 1) {
+ OvsDeleteSwitchContext(switchContext);
+ }
+}
+
+BOOLEAN
+OvsAcquireSwitchContext(VOID)
+{
+ LONG ref = 0;
+ LONG newRef = 0;
+ LONG icxRef = 0;
+ BOOLEAN ret = FALSE;
+
+ do {
+ ref = gOvsSwitchContextRefCount;
+ newRef = (0 == ref) ? 0 : ref + 1;
+ icxRef = InterlockedCompareExchange(&gOvsSwitchContextRefCount,
+ newRef,
+ ref);
+ } while (icxRef != ref);
+
+ if (ref != 0) {
+ ret = TRUE;
+ }
+
+ return ret;
+}
+
/*
* --------------------------------------------------------------------------
* This function activates the switch by initializing it with all the runtime
dispatch ? NDIS_RWL_AT_DISPATCH_LEVEL : 0);
}
-
static __inline VOID
OvsReleaseDatapath(OVS_DATAPATH *datapath,
LOCK_STATE_EX *lockState)
NdisReleaseRWLock(datapath->lock, lockState);
}
+BOOLEAN
+OvsAcquireSwitchContext(VOID);
+
+VOID
+OvsReleaseSwitchContext(POVS_SWITCH_CONTEXT switchContext);
PVOID OvsGetExternalVport();