static VOID OvsUninitSwitchContext(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; OvsDeleteFlowTable(&switchContext->datapath); OvsCleanupBufferPool(switchContext); OVS_LOG_TRACE("Exit: Delete switchContext: %p", switchContext); }
/* * -------------------------------------------------------------------------- * 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) OvsAllocateMemoryWithTag( sizeof(OVS_SWITCH_CONTEXT), OVS_SWITCH_POOL_TAG); 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."); OvsFreeMemoryWithTag(switchContext, OVS_SWITCH_POOL_TAG); 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) { OvsFreeMemoryWithTag(switchContext, OVS_SWITCH_POOL_TAG); switchContext = NULL; goto create_switch_done; } status = OvsInitTunnelFilter(gOvsExtDriverObject, gOvsDeviceObject); if (status != NDIS_STATUS_SUCCESS) { OvsUninitSwitchContext(switchContext); goto create_switch_done; } *switchContextOut = switchContext; create_switch_done: OVS_LOG_TRACE("Exit: switchContext: %p status: %#lx", switchContext, status); return status; }
/* * -------------------------------------------------------------------------- * OvsDeferredActionsCleanup -- * The function frees all deferred actions resources. * -------------------------------------------------------------------------- */ VOID OvsDeferredActionsCleanup() { if (deferredData) { OvsFreeMemoryWithTag(deferredData, OVS_RECIRC_POOL_TAG); deferredData = NULL; } }
static VOID OvsFreeMDLAndData(PMDL mdl) { PVOID data; data = MmGetMdlVirtualAddress(mdl); NdisFreeMdl(mdl); OvsFreeMemoryWithTag(data, OVS_MDL_POOL_TAG); }
/* * -------------------------------------------------------------------------- * Utility function to get the array of nics on the extensible switch. Upon * success, the caller needs to free the returned array. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsGetNicsOnSwitch(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_NIC_ARRAY *nicArrayOut) { PNDIS_SWITCH_NIC_ARRAY nicArray; UINT32 arraySize = sizeof *nicArray; NDIS_STATUS status = NDIS_STATUS_FAILURE; OVS_LOG_TRACE("Enter: switchContext: %p, nicArray: %p", switchContext, nicArrayOut); do { UINT32 reqdArraySize; nicArray = OvsAllocateMemoryWithTag(arraySize, OVS_OID_POOL_TAG); if (!nicArray) { status = NDIS_STATUS_RESOURCES; goto done; } /* * Even though 'nicArray' is supposed to be populated by the OID, it * needs to be initialized nevertheless. Otherwise, OID returns * NDIS_STATUS_INVALID_PARAMETER. This is not clear in the documentation. */ RtlZeroMemory(nicArray, sizeof *nicArray); nicArray->Header.Revision = NDIS_SWITCH_NIC_ARRAY_REVISION_1; nicArray->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; nicArray->Header.Size = NDIS_SIZEOF_NDIS_SWITCH_NIC_ARRAY_REVISION_1; status = OvsIssueOidRequest(switchContext, NdisRequestQueryInformation, OID_SWITCH_NIC_ARRAY, NULL, 0, (PVOID)nicArray, arraySize, &reqdArraySize); if (status == NDIS_STATUS_SUCCESS) { *nicArrayOut = nicArray; break; } OvsFreeMemoryWithTag(nicArray, OVS_OID_POOL_TAG); arraySize = reqdArraySize; if (status != NDIS_STATUS_INVALID_LENGTH) { break; } } while(status == NDIS_STATUS_INVALID_LENGTH); done: OVS_LOG_TRACE("Exit: status %8x.", status); return status; }
/* * -------------------------------------------------------------------------- * Utility function to query if the extensible switch has completed activation * successfully. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsQuerySwitchActivationComplete(POVS_SWITCH_CONTEXT switchContext, BOOLEAN *switchActive) { NDIS_STATUS status; PNDIS_SWITCH_PARAMETERS switchParams; UINT32 outputSizeNeeded; OVS_LOG_TRACE("Enter: switchContext: %p, switchActive: %p", switchContext, switchActive); switchParams = OvsAllocateMemoryWithTag(sizeof *switchParams, OVS_OID_POOL_TAG); if (!switchParams) { status = NDIS_STATUS_RESOURCES; goto done; } /* * Even though 'switchParms' is supposed to be populated by the OID, it * needs to be initialized nevertheless. Otherwise, OID returns * NDIS_STATUS_INVALID_PARAMETER. This is not clear in the documentation. */ RtlZeroMemory(switchParams, sizeof *switchParams); switchParams->Header.Revision = NDIS_SWITCH_PARAMETERS_REVISION_1; switchParams->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; switchParams->Header.Size = NDIS_SIZEOF_NDIS_SWITCH_PARAMETERS_REVISION_1; status = OvsIssueOidRequest(switchContext, NdisRequestQueryInformation, OID_SWITCH_PARAMETERS, NULL, 0, (PVOID)switchParams, sizeof *switchParams, &outputSizeNeeded); ASSERT(status != NDIS_STATUS_INVALID_LENGTH); ASSERT(status != NDIS_STATUS_PENDING); if (status == NDIS_STATUS_SUCCESS) { ASSERT(switchParams->Header.Type == NDIS_OBJECT_TYPE_DEFAULT); ASSERT(switchParams->Header.Revision == NDIS_SWITCH_PARAMETERS_REVISION_1); ASSERT(switchParams->Header.Size == NDIS_SIZEOF_NDIS_SWITCH_PARAMETERS_REVISION_1); *switchActive = switchParams->IsActive; } OvsFreeMemoryWithTag(switchParams, OVS_OID_POOL_TAG); done: OVS_LOG_TRACE("Exit: status %8x, switchActive: %d.", status, *switchActive); return status; }
/* * -------------------------------------------------------------------------- * 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 = (UINT32) -1; OVS_LOG_TRACE("Enter: switchContext:%p", switchContext); if (switchContext) { dpNo = switchContext->dpNo; OvsTunnelFilterUninitialize(gOvsExtDriverObject); OvsClearAllSwitchVports(switchContext); OvsUninitSwitchContext(switchContext); OvsFreeMemoryWithTag(switchContext, OVS_SWITCH_POOL_TAG); } OVS_LOG_TRACE("Exit: deleted switch %p dpNo: %d", switchContext, dpNo); }
static PMDL OvsAllocateMDLAndData(NDIS_HANDLE ndisHandle, UINT32 dataSize) { PMDL mdl; PVOID data; data = OvsAllocateMemoryWithTag(dataSize, OVS_MDL_POOL_TAG); if (data == NULL) { return NULL; } mdl = NdisAllocateMdl(ndisHandle, data, dataSize); if (mdl == NULL) { OvsFreeMemoryWithTag(data, OVS_MDL_POOL_TAG); } return mdl; }
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); 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) { 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); } 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]); } 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]); } 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; }
VOID OvsFreeSwitchNicsArray(PNDIS_SWITCH_NIC_ARRAY nicsArray) { if (nicsArray) { OvsFreeMemoryWithTag(nicsArray, OVS_OID_POOL_TAG); } }
VOID OvsFreeSwitchPortsArray(PNDIS_SWITCH_PORT_ARRAY portsArray) { if (portsArray) { OvsFreeMemoryWithTag(portsArray, OVS_OID_POOL_TAG); } }
/* * -------------------------------------------------------------------------- * Utility function to issue the specified OID to the NDIS stack. The OID is * directed towards the miniport edge of the extensible switch. * An OID that gets issued may not complete immediately, and in such cases, the * function waits for the OID to complete. Thus, this function must not be * called at the PASSIVE_LEVEL. * -------------------------------------------------------------------------- */ static NDIS_STATUS OvsIssueOidRequest(POVS_SWITCH_CONTEXT switchContext, NDIS_REQUEST_TYPE oidType, UINT32 oidRequestEnum, PVOID oidInputBuffer, UINT32 inputSize, PVOID oidOutputBuffer, UINT32 outputSize, UINT32 *outputSizeNeeded) { NDIS_STATUS status; PNDIS_OID_REQUEST oidRequest; POVS_OID_CONTEXT oidContext; ULONG OvsExtOidRequestId = 'ISVO'; DBG_UNREFERENCED_PARAMETER(inputSize); DBG_UNREFERENCED_PARAMETER(oidInputBuffer); OVS_LOG_TRACE("Enter: switchContext: %p, oidType: %d", switchContext, oidType); ASSERT(oidInputBuffer == NULL || inputSize != 0); ASSERT(oidOutputBuffer == NULL || outputSize != 0); ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); oidRequest = OvsAllocateMemoryWithTag(sizeof *oidRequest, OVS_OID_POOL_TAG); if (!oidRequest) { status = NDIS_STATUS_RESOURCES; goto done; } oidContext = OvsAllocateMemoryWithTag(sizeof *oidContext, OVS_OID_POOL_TAG); if (!oidContext) { OvsFreeMemoryWithTag(oidRequest, OVS_OID_POOL_TAG); status = NDIS_STATUS_RESOURCES; goto done; } RtlZeroMemory(oidRequest, sizeof *oidRequest); RtlZeroMemory(oidContext, sizeof *oidContext); oidRequest->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST; oidRequest->Header.Revision = NDIS_OID_REQUEST_REVISION_1; oidRequest->Header.Size = NDIS_SIZEOF_OID_REQUEST_REVISION_1; oidRequest->RequestType = oidType; oidRequest->PortNumber = 0; oidRequest->Timeout = 0; oidRequest->RequestId = (PVOID)OvsExtOidRequestId; switch(oidType) { case NdisRequestQueryInformation: oidRequest->DATA.QUERY_INFORMATION.Oid = oidRequestEnum; oidRequest->DATA.QUERY_INFORMATION.InformationBuffer = oidOutputBuffer; oidRequest->DATA.QUERY_INFORMATION.InformationBufferLength = outputSize; break; default: ASSERT(FALSE); status = NDIS_STATUS_INVALID_PARAMETER; break; } /* * We make use of the SourceReserved field in the OID request to store * pointers to the original OID (if any), and also context for completion * (if any). */ oidContext->status = NDIS_STATUS_SUCCESS; NdisInitializeEvent(&oidContext->oidComplete); OvsOidSetOrigRequest(oidRequest, NULL); OvsOidSetContext(oidRequest, oidContext); NdisInterlockedIncrement(&(switchContext->pendingOidCount)); status = NdisFOidRequest(switchContext->NdisFilterHandle, oidRequest); if (status == NDIS_STATUS_PENDING) { NdisWaitEvent(&oidContext->oidComplete, 0); } else { NdisInterlockedDecrement(&(switchContext->pendingOidCount)); } if (status == NDIS_STATUS_INVALID_LENGTH || oidContext->status == NDIS_STATUS_INVALID_LENGTH) { switch(oidType) { case NdisRequestQueryInformation: *outputSizeNeeded = oidRequest->DATA.QUERY_INFORMATION.BytesNeeded; } } status = oidContext->status; ASSERT(status != NDIS_STATUS_PENDING); OvsFreeMemoryWithTag(oidRequest, OVS_OID_POOL_TAG); OvsFreeMemoryWithTag(oidContext, OVS_OID_POOL_TAG); done: OVS_LOG_TRACE("Exit: status %8x.", status); return status; }