#include "Event.h"
#include "Flow.h"
#include "IpHelper.h"
-#include "TunnelIntf.h"
#include "Oid.h"
#ifdef OVS_DBG_MOD
#include "Debug.h"
POVS_SWITCH_CONTEXT gOvsSwitchContext;
-BOOLEAN gOvsInAttach;
+LONG volatile gOvsInAttach;
UINT64 ovsTimeIncrementPerTick;
-extern PNDIS_SPIN_LOCK gOvsCtrlLock;
extern NDIS_HANDLE gOvsExtDriverHandle;
extern NDIS_HANDLE gOvsExtDriverObject;
+extern PDEVICE_OBJECT gOvsDeviceObject;
+
+/*
+ * Reference count used to prevent premature deallocation of the global switch
+ * context structure, gOvsSwitchContext.
+ */
+volatile LONG gOvsSwitchContextRefCount = 0;
static NDIS_STATUS OvsCreateSwitch(NDIS_HANDLE ndisFilterHandle,
POVS_SWITCH_CONTEXT *switchContextOut);
goto cleanup;
}
- NdisAcquireSpinLock(gOvsCtrlLock);
if (gOvsSwitchContext) {
- NdisReleaseSpinLock(gOvsCtrlLock);
OVS_LOG_TRACE("Exit: Failed to create OVS Switch, only one datapath is"
"supported, %p.", gOvsSwitchContext);
goto cleanup;
}
- if (gOvsInAttach) {
- NdisReleaseSpinLock(gOvsCtrlLock);
+
+ if (InterlockedCompareExchange(&gOvsInAttach, 1, 0)) {
/* Just fail the request. */
OVS_LOG_TRACE("Exit: Failed to create OVS Switch, since another attach"
"instance is in attach process.");
goto cleanup;
}
- gOvsInAttach = TRUE;
- NdisReleaseSpinLock(gOvsCtrlLock);
status = OvsInitIpHelper(ndisFilterHandle);
if (status != STATUS_SUCCESS) {
/*
* Register the switch context with NDIS so NDIS can pass it back to the
- * Filterxxx callback functions as the 'FilterModuleContext' parameter.
+ * FilterXXX callback functions as the 'FilterModuleContext' parameter.
*/
RtlZeroMemory(&ovsExtAttributes, sizeof(NDIS_FILTER_ATTRIBUTES));
ovsExtAttributes.Header.Revision = NDIS_FILTER_ATTRIBUTES_REVISION_1;
switchContext->controlFlowState = OvsSwitchAttached;
switchContext->dataFlowState = OvsSwitchPaused;
+ gOvsSwitchContextRefCount = 1;
gOvsSwitchContext = switchContext;
KeMemoryBarrier();
OVS_LOG_TRACE("Enter: Create switch object");
- switchContext =
- (POVS_SWITCH_CONTEXT) OvsAllocateMemory(sizeof(OVS_SWITCH_CONTEXT));
+ switchContext = (POVS_SWITCH_CONTEXT) OvsAllocateMemoryWithTag(
+ sizeof(OVS_SWITCH_CONTEXT), OVS_SWITCH_POOL_TAG);
if (switchContext == NULL) {
status = NDIS_STATUS_RESOURCES;
goto create_switch_done;
if (status != NDIS_STATUS_SUCCESS) {
OVS_LOG_ERROR("OvsExtAttach: Extension is running in "
"non-switch environment.");
- OvsFreeMemory(switchContext);
+ OvsFreeMemoryWithTag(switchContext, OVS_SWITCH_POOL_TAG);
goto create_switch_done;
}
status = OvsInitSwitchContext(switchContext);
if (status != NDIS_STATUS_SUCCESS) {
- OvsFreeMemory(switchContext);
+ OvsFreeMemoryWithTag(switchContext, OVS_SWITCH_POOL_TAG);
+ switchContext = NULL;
goto create_switch_done;
}
- status = OvsTunnelFilterInitialize(gOvsExtDriverObject);
+ status = OvsInitTunnelFilter(gOvsExtDriverObject, gOvsDeviceObject);
if (status != NDIS_STATUS_SUCCESS) {
OvsUninitSwitchContext(switchContext);
- OvsFreeMemory(switchContext);
goto create_switch_done;
}
+
+ status = OvsInitSttDefragmentation();
+ if (status != STATUS_SUCCESS) {
+ OVS_LOG_ERROR("Exit: Failed to initialize Stt Defragmentation");
+ goto create_switch_done;
+ }
+
*switchContextOut = switchContext;
create_switch_done:
}
OvsDeleteSwitch(switchContext);
OvsCleanupIpHelper();
- gOvsSwitchContext = NULL;
+ OvsCleanupSttDefragmentation();
/* This completes the cleanup, and a new attach can be handled now. */
OVS_LOG_TRACE("Exit: OvsDetach Successfully");
if (switchContext)
{
dpNo = switchContext->dpNo;
- OvsTunnelFilterUninitialize(gOvsExtDriverObject);
OvsClearAllSwitchVports(switchContext);
+ OvsUninitTunnelFilter(gOvsExtDriverObject);
OvsUninitSwitchContext(switchContext);
- OvsFreeMemory(switchContext);
}
OVS_LOG_TRACE("Exit: deleted switch %p dpNo: %d", switchContext, dpNo);
}
switchContext->dispatchLock =
NdisAllocateRWLock(switchContext->NdisFilterHandle);
- switchContext->portNoHashArray = (PLIST_ENTRY)
- OvsAllocateMemory(sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE);
- switchContext->ovsPortNameHashArray = (PLIST_ENTRY)
- OvsAllocateMemory(sizeof (LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE);
- switchContext->portIdHashArray= (PLIST_ENTRY)
- OvsAllocateMemory(sizeof (LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE);
- switchContext->pidHashArray = (PLIST_ENTRY)
- OvsAllocateMemory(sizeof(LIST_ENTRY) * OVS_MAX_PID_ARRAY_SIZE);
+ switchContext->portNoHashArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag(
+ sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);
+ switchContext->ovsPortNameHashArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag(
+ sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);
+ switchContext->portIdHashArray= (PLIST_ENTRY)OvsAllocateMemoryWithTag(
+ sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);
+ switchContext->pidHashArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag(
+ sizeof(LIST_ENTRY) * OVS_MAX_PID_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);
+ switchContext->tunnelVportsArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag(
+ sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);
status = OvsAllocateFlowTable(&switchContext->datapath, switchContext);
if (status == NDIS_STATUS_SUCCESS) {
switchContext->portNoHashArray == NULL ||
switchContext->ovsPortNameHashArray == NULL ||
switchContext->portIdHashArray== NULL ||
- switchContext->pidHashArray == NULL) {
+ switchContext->pidHashArray == NULL ||
+ switchContext->tunnelVportsArray == NULL) {
if (switchContext->dispatchLock) {
NdisFreeRWLock(switchContext->dispatchLock);
}
if (switchContext->portNoHashArray) {
- OvsFreeMemory(switchContext->portNoHashArray);
+ OvsFreeMemoryWithTag(switchContext->portNoHashArray,
+ OVS_SWITCH_POOL_TAG);
}
if (switchContext->ovsPortNameHashArray) {
- OvsFreeMemory(switchContext->ovsPortNameHashArray);
+ OvsFreeMemoryWithTag(switchContext->ovsPortNameHashArray,
+ OVS_SWITCH_POOL_TAG);
}
if (switchContext->portIdHashArray) {
- OvsFreeMemory(switchContext->portIdHashArray);
+ OvsFreeMemoryWithTag(switchContext->portIdHashArray,
+ OVS_SWITCH_POOL_TAG);
}
-
if (switchContext->pidHashArray) {
- OvsFreeMemory(switchContext->pidHashArray);
+ OvsFreeMemoryWithTag(switchContext->pidHashArray,
+ OVS_SWITCH_POOL_TAG);
+ }
+
+ if (switchContext->tunnelVportsArray) {
+ OvsFreeMemory(switchContext->tunnelVportsArray);
}
OvsDeleteFlowTable(&switchContext->datapath);
for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
InitializeListHead(&switchContext->ovsPortNameHashArray[i]);
- }
- for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
InitializeListHead(&switchContext->portIdHashArray[i]);
- }
- for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
InitializeListHead(&switchContext->portNoHashArray[i]);
+ InitializeListHead(&switchContext->tunnelVportsArray[i]);
}
for (i = 0; i < OVS_MAX_PID_ARRAY_SIZE; i++) {
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);
+}
+
+/*
+ * --------------------------------------------------------------------------
+ * Frees up the contents of and also the switch context.
+ * --------------------------------------------------------------------------
+ */
+static VOID
+OvsDeleteSwitchContext(POVS_SWITCH_CONTEXT switchContext)
{
OVS_LOG_TRACE("Enter: Delete switchContext:%p", switchContext);
/* We need to do cleanup for tunnel port here. */
ASSERT(switchContext->numHvVports == 0);
+ ASSERT(switchContext->numNonHvVports == 0);
NdisFreeRWLock(switchContext->dispatchLock);
switchContext->dispatchLock = NULL;
NdisFreeSpinLock(&(switchContext->pidHashLock));
- OvsFreeMemory(switchContext->ovsPortNameHashArray);
+ OvsFreeMemoryWithTag(switchContext->ovsPortNameHashArray,
+ OVS_SWITCH_POOL_TAG);
switchContext->ovsPortNameHashArray = NULL;
- OvsFreeMemory(switchContext->portIdHashArray);
+ OvsFreeMemoryWithTag(switchContext->portIdHashArray,
+ OVS_SWITCH_POOL_TAG);
switchContext->portIdHashArray = NULL;
- OvsFreeMemory(switchContext->portNoHashArray);
+ OvsFreeMemoryWithTag(switchContext->portNoHashArray,
+ OVS_SWITCH_POOL_TAG);
switchContext->portNoHashArray = NULL;
- OvsFreeMemory(switchContext->pidHashArray);
+ OvsFreeMemoryWithTag(switchContext->pidHashArray,
+ OVS_SWITCH_POOL_TAG);
switchContext->pidHashArray = NULL;
+ OvsFreeMemory(switchContext->tunnelVportsArray);
+ switchContext->tunnelVportsArray = NULL;
OvsDeleteFlowTable(&switchContext->datapath);
OvsCleanupBufferPool(switchContext);
+
+ OvsFreeMemoryWithTag(switchContext, OVS_SWITCH_POOL_TAG);
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);
+ gOvsSwitchContext = NULL;
+ }
+}
+
+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
OVS_LOG_TRACE("Enter: activate switch %p, dpNo: %ld",
switchContext, switchContext->dpNo);
+ switchContext->isActivated = TRUE;
status = OvsAddConfiguredSwitchPorts(switchContext);
if (status != NDIS_STATUS_SUCCESS) {
OvsClearAllSwitchVports(switchContext);
goto cleanup;
}
- switchContext->isActivated = TRUE;
- OvsPostEvent(OVS_DEFAULT_PORT_NO, OVS_DEFAULT_EVENT_STATUS);
cleanup:
+ if (status != NDIS_STATUS_SUCCESS) {
+ switchContext->isActivated = TRUE;
+ }
+
OVS_LOG_TRACE("Exit: activate switch:%p, isActivated: %s, status = %lx",
switchContext,
(switchContext->isActivated ? "TRUE" : "FALSE"), status);
return status;
}
-PVOID
-OvsGetExternalVport()
-{
- return gOvsSwitchContext->virtualExternalVport;
-}
-
/*
* --------------------------------------------------------------------------
switchContext->isActivateFailed = TRUE;
} else {
ASSERT(switchContext->isActivated == FALSE);
- ASSERT(switchActive == TRUE);
if (switchContext->isActivated == FALSE && switchActive == TRUE) {
status = OvsActivateSwitch(switchContext);
OVS_LOG_TRACE("OvsExtNetPnPEvent: activated switch: %p "