/* * -------------------------------------------------------------------------- * This function allocated the switch context, and initializes its necessary * members. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsCreateSwitch(NDIS_HANDLE ndisFilterHandle, POVS_SWITCH_CONTEXT *switchContextOut) { NDIS_STATUS status; POVS_SWITCH_CONTEXT switchContext; NDIS_SWITCH_CONTEXT hostSwitchContext; NDIS_SWITCH_OPTIONAL_HANDLERS hostSwitchHandler; OVS_LOG_TRACE("Enter: Create switch object"); switchContext = (POVS_SWITCH_CONTEXT) OvsAllocateMemory(sizeof(OVS_SWITCH_CONTEXT)); if (switchContext == NULL) { status = NDIS_STATUS_RESOURCES; goto create_switch_done; } RtlZeroMemory(switchContext, sizeof(OVS_SWITCH_CONTEXT)); /* Initialize the switch. */ hostSwitchHandler.Header.Type = NDIS_OBJECT_TYPE_SWITCH_OPTIONAL_HANDLERS; hostSwitchHandler.Header.Size = NDIS_SIZEOF_SWITCH_OPTIONAL_HANDLERS_REVISION_1; hostSwitchHandler.Header.Revision = NDIS_SWITCH_OPTIONAL_HANDLERS_REVISION_1; status = NdisFGetOptionalSwitchHandlers(ndisFilterHandle, &hostSwitchContext, &hostSwitchHandler); if (status != NDIS_STATUS_SUCCESS) { OVS_LOG_ERROR("OvsExtAttach: Extension is running in " "non-switch environment."); OvsFreeMemory(switchContext); goto create_switch_done; } switchContext->NdisFilterHandle = ndisFilterHandle; switchContext->NdisSwitchContext = hostSwitchContext; RtlCopyMemory(&switchContext->NdisSwitchHandlers, &hostSwitchHandler, sizeof(NDIS_SWITCH_OPTIONAL_HANDLERS)); status = OvsInitSwitchContext(switchContext); if (status != NDIS_STATUS_SUCCESS) { OvsFreeMemory(switchContext); goto create_switch_done; } status = OvsTunnelFilterInitialize(gOvsExtDriverObject); if (status != NDIS_STATUS_SUCCESS) { OvsFreeMemory(switchContext); goto create_switch_done; } *switchContextOut = switchContext; create_switch_done: OVS_LOG_TRACE("Exit: switchContext: %p status: %#lx", switchContext, status); return status; }
/* * -------------------------------------------------------------------------- * 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)); OvsFreeMemoryWithTag(switchContext->ovsPortNameHashArray, OVS_SWITCH_POOL_TAG); switchContext->ovsPortNameHashArray = NULL; OvsFreeMemoryWithTag(switchContext->portIdHashArray, OVS_SWITCH_POOL_TAG); switchContext->portIdHashArray = NULL; OvsFreeMemoryWithTag(switchContext->portNoHashArray, OVS_SWITCH_POOL_TAG); switchContext->portNoHashArray = NULL; 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); }
NTSTATUS OvsAddOpenInstance(PFILE_OBJECT fileObject) { POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE) OvsAllocateMemory(sizeof (OVS_OPEN_INSTANCE)); UINT32 i; if (instance == NULL) { return STATUS_NO_MEMORY; } OvsAcquireCtrlLock(); ASSERT(OvsFindOpenInstance(fileObject) == NULL); if (ovsNumberOfOpenInstances >= OVS_MAX_OPEN_INSTANCES) { OvsReleaseCtrlLock(); OvsFreeMemory(instance); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(instance, sizeof (OVS_OPEN_INSTANCE)); for (i = 0; i < OVS_MAX_OPEN_INSTANCES; i++) { if (ovsOpenInstanceArray[i] == NULL) { ovsOpenInstanceArray[i] = instance; instance->cookie = i; break; } } ASSERT(i < OVS_MAX_OPEN_INSTANCES); instance->fileObject = fileObject; ASSERT(fileObject->FsContext == NULL); fileObject->FsContext = instance; OvsReleaseCtrlLock(); return STATUS_SUCCESS; }
static VOID OvsCleanupSwitchContext(POVS_SWITCH_CONTEXT switchContext) { OVS_LOG_TRACE("Enter: Delete switchContext:%p", switchContext); /* We need to do cleanup for tunnel port here. */ ASSERT(switchContext->numVports == 0); NdisFreeRWLock(switchContext->dispatchLock); OvsFreeMemory(switchContext->nameHashArray); OvsFreeMemory(switchContext->portHashArray); OvsFreeMemory(switchContext->vportArray); OvsDeleteFlowTable(&switchContext->datapath); OvsCleanupBufferPool(switchContext); OVS_LOG_TRACE("Exit: Delete switchContext: %p", switchContext); }
VOID OvsCleanupVxlanTunnel(POVS_VPORT_ENTRY vport) { if (vport->ovsType != OVS_VPORT_TYPE_VXLAN || vport->priv == NULL) { return; } OvsFreeMemory(vport->priv); vport->priv = NULL; }
/* * -------------------------------------------------------------------------- * This function deletes the switch by freeing all memory previously allocated. * XXX need synchronization with other path. * -------------------------------------------------------------------------- */ VOID OvsDeleteSwitch(POVS_SWITCH_CONTEXT switchContext) { UINT32 dpNo = switchContext->dpNo; OVS_LOG_TRACE("Enter: switchContext:%p", switchContext); OvsTunnelFilterUninitialize(gOvsExtDriverObject); OvsClearAllSwitchVports(switchContext); OvsCleanupSwitchContext(switchContext); OvsFreeMemory(switchContext); OVS_LOG_TRACE("Exit: deleted switch %p dpNo: %d", switchContext, dpNo); }
VOID OvsRemoveOpenInstance(PFILE_OBJECT fileObject) { POVS_OPEN_INSTANCE instance; ASSERT(fileObject->FsContext); instance = (POVS_OPEN_INSTANCE)fileObject->FsContext; ASSERT(instance->cookie < OVS_MAX_OPEN_INSTANCES); OvsAcquireCtrlLock(); fileObject->FsContext = NULL; ASSERT(ovsOpenInstanceArray[instance->cookie] == instance); ovsOpenInstanceArray[instance->cookie] = NULL; OvsReleaseCtrlLock(); ASSERT(instance->eventQueue == NULL); ASSERT (instance->packetQueue == NULL); OvsFreeMemory(instance); }
NTSTATUS OvsAddOpenInstance(POVS_DEVICE_EXTENSION ovsExt, PFILE_OBJECT fileObject) { POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE) OvsAllocateMemory(sizeof (OVS_OPEN_INSTANCE)); UINT32 i; if (instance == NULL) { return STATUS_NO_MEMORY; } OvsAcquireCtrlLock(); ASSERT(OvsFindOpenInstance(fileObject) == NULL); if (ovsNumberOfOpenInstances >= OVS_MAX_OPEN_INSTANCES) { OvsReleaseCtrlLock(); OvsFreeMemory(instance); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(instance, sizeof (OVS_OPEN_INSTANCE)); for (i = 0; i < OVS_MAX_OPEN_INSTANCES; i++) { if (ovsOpenInstanceArray[i] == NULL) { ovsOpenInstanceArray[i] = instance; instance->cookie = i; break; } } ASSERT(i < OVS_MAX_OPEN_INSTANCES); instance->fileObject = fileObject; ASSERT(fileObject->FsContext == NULL); instance->pid = (UINT32)InterlockedIncrement((LONG volatile *)&ovsExt->pidCount); if (instance->pid == 0) { /* XXX: check for rollover. */ } fileObject->FsContext = instance; OvsReleaseCtrlLock(); return STATUS_SUCCESS; }
static NDIS_STATUS OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext) { int i; NTSTATUS status; OVS_LOG_TRACE("Enter: switchContext: %p", switchContext); switchContext->dispatchLock = NdisAllocateRWLock(switchContext->NdisFilterHandle); 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) { status = OvsInitBufferPool(switchContext); } if (status != NDIS_STATUS_SUCCESS || switchContext->dispatchLock == NULL || switchContext->portNoHashArray == NULL || switchContext->ovsPortNameHashArray == NULL || switchContext->portIdHashArray== NULL || switchContext->pidHashArray == NULL || switchContext->tunnelVportsArray == NULL) { if (switchContext->dispatchLock) { NdisFreeRWLock(switchContext->dispatchLock); } if (switchContext->portNoHashArray) { OvsFreeMemoryWithTag(switchContext->portNoHashArray, OVS_SWITCH_POOL_TAG); } if (switchContext->ovsPortNameHashArray) { OvsFreeMemoryWithTag(switchContext->ovsPortNameHashArray, OVS_SWITCH_POOL_TAG); } if (switchContext->portIdHashArray) { OvsFreeMemoryWithTag(switchContext->portIdHashArray, OVS_SWITCH_POOL_TAG); } if (switchContext->pidHashArray) { OvsFreeMemoryWithTag(switchContext->pidHashArray, OVS_SWITCH_POOL_TAG); } if (switchContext->tunnelVportsArray) { OvsFreeMemory(switchContext->tunnelVportsArray); } OvsDeleteFlowTable(&switchContext->datapath); OvsCleanupBufferPool(switchContext); OVS_LOG_TRACE("Exit: Failed to init switchContext"); return NDIS_STATUS_RESOURCES; } for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) { InitializeListHead(&switchContext->ovsPortNameHashArray[i]); InitializeListHead(&switchContext->portIdHashArray[i]); InitializeListHead(&switchContext->portNoHashArray[i]); InitializeListHead(&switchContext->tunnelVportsArray[i]); } for (i = 0; i < OVS_MAX_PID_ARRAY_SIZE; i++) { InitializeListHead(&switchContext->pidHashArray[i]); } NdisAllocateSpinLock(&(switchContext->pidHashLock)); switchContext->isActivated = FALSE; switchContext->isActivateFailed = FALSE; switchContext->dpNo = OVS_DP_NUMBER; ovsTimeIncrementPerTick = KeQueryTimeIncrement() / 10000; OVS_LOG_TRACE("Exit: Succesfully initialized switchContext: %p", switchContext); return NDIS_STATUS_SUCCESS; }