Beispiel #1
0
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);
}
Beispiel #2
0
/*
 * --------------------------------------------------------------------------
 * OvsCleanupBufferPool --
 *  Free Buffer pool for NBL and NB.
 * --------------------------------------------------------------------------
 */
VOID
OvsCleanupBufferPool(PVOID ovsContext)
{
    POVS_NBL_POOL ovsPool;
    POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext;
    ovsPool = &context->ovsPool;
    OVS_LOG_TRACE("Enter: context: %p", context);
#ifdef DBG
    ASSERT(ovsPool->fixNBLCount == 0);
    ASSERT(ovsPool->zeroNBLCount == 0);
    ASSERT(ovsPool->nblOnlyCount == 0);
    ASSERT(ovsPool->nbCount == 0);
    ASSERT(ovsPool->sysNBLCount == 0);
    ASSERT(ovsPool->fragNBLCount == 0);
#endif

    if (ovsPool->fixSizePool) {
        NdisFreeNetBufferListPool(ovsPool->fixSizePool);
        ovsPool->fixSizePool = NULL;
    }
    if (ovsPool->zeroSizePool) {
        NdisFreeNetBufferListPool(ovsPool->zeroSizePool);
        ovsPool->zeroSizePool = NULL;
    }
    if (ovsPool->nblOnlyPool) {
        NdisFreeNetBufferListPool(ovsPool->nblOnlyPool);
        ovsPool->nblOnlyPool = NULL;
    }
    if (ovsPool->nbPool) {
        NdisFreeNetBufferPool(ovsPool->nbPool);
        ovsPool->nbPool = NULL;
    }
    OVS_LOG_TRACE("Exit: cleanup OVS Buffer pool");
}
Beispiel #3
0
/*
 * --------------------------------------------------------------------------
 * Implements filter driver's FilterNetPnPEvent function.
 * --------------------------------------------------------------------------
 */
NDIS_STATUS
OvsExtNetPnPEvent(NDIS_HANDLE filterModuleContext,
                  PNET_PNP_EVENT_NOTIFICATION netPnPEvent)
{
    NDIS_STATUS status = NDIS_STATUS_SUCCESS;
    POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)filterModuleContext;

    OVS_LOG_TRACE("Enter: filterModuleContext: %p, NetEvent: %d",
                  filterModuleContext, (netPnPEvent->NetPnPEvent).NetEvent);
    /*
     * The only interesting event is the NetEventSwitchActivate. It provides
     * an asynchronous notification of the switch completing activation.
     */
    if (netPnPEvent->NetPnPEvent.NetEvent == NetEventSwitchActivate) {
        ASSERT(switchContext->isActivated == FALSE);
        if (switchContext->isActivated == FALSE) {
            status = OvsActivateSwitch(switchContext);
            OVS_LOG_TRACE("OvsExtNetPnPEvent: activated switch: %p "
                          "status: %s", switchContext,
                          status ? "TRUE" : "FALSE");
        }
    }

    if (netPnPEvent->NetPnPEvent.NetEvent == NetEventFilterPreDetach) {
        switchContext->dataFlowState = OvsSwitchPaused;
        KeMemoryBarrier();
    }

    status = NdisFNetPnPEvent(switchContext->NdisFilterHandle,
                              netPnPEvent);
    OVS_LOG_TRACE("Exit: OvsExtNetPnPEvent");

    return status;
}
Beispiel #4
0
/*
 * --------------------------------------------------------------------------
 *  This function activates the switch by initializing it with all the runtime
 *  state. First it queries all of the MAC addresses set as custom switch policy
 *  to allow sends from, and adds tme to the property list. Then it queries the
 *  NIC list and verifies it can support all of the NICs currently connected to
 *  the switch, and adds the NICs to the NIC list.
 * --------------------------------------------------------------------------
 */
static NDIS_STATUS
OvsActivateSwitch(POVS_SWITCH_CONTEXT switchContext)
{
    NDIS_STATUS status;

    ASSERT(!switchContext->isActivated);

    OVS_LOG_TRACE("Enter: activate switch %p, dpNo: %ld",
                  switchContext, switchContext->dpNo);

    status = OvsAddConfiguredSwitchPorts(switchContext);

    if (status != NDIS_STATUS_SUCCESS) {
        OVS_LOG_WARN("Failed to add configured switch ports");
        goto cleanup;

    }
    status = OvsInitConfiguredSwitchNics(switchContext);

    if (status != NDIS_STATUS_SUCCESS) {
        OVS_LOG_WARN("Failed to add configured vports");
        OvsClearAllSwitchVports(switchContext);
        goto cleanup;
    }
    switchContext->isActivated = TRUE;
    OvsPostEvent(OVS_DEFAULT_PORT_NO, OVS_DEFAULT_EVENT_STATUS);

cleanup:
    OVS_LOG_TRACE("Exit: activate switch:%p, isActivated: %s, status = %lx",
                  switchContext,
                  (switchContext->isActivated ? "TRUE" : "FALSE"), status);
    return status;
}
Beispiel #5
0
/*
 * --------------------------------------------------------------------------
 *  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;
}
Beispiel #6
0
static NDIS_STATUS
OvsProcessMethodOid(POVS_SWITCH_CONTEXT switchObject,
                    PNDIS_OID_REQUEST oidRequest,
                    PBOOLEAN complete,
                    PULONG bytesNeededParam)
{
    NDIS_STATUS status = NDIS_STATUS_SUCCESS;
    struct _METHOD *methodInfo = &(oidRequest->DATA.METHOD_INFORMATION);
    struct _SET *nicReqSetInfo = NULL;
    PNDIS_OBJECT_HEADER header = NULL;
    PNDIS_OID_REQUEST nicOidRequest = NULL;

    UNREFERENCED_PARAMETER(switchObject);

    OVS_LOG_TRACE("Enter: oidRequest %p, Oid: %lu",
                  oidRequest, methodInfo->Oid);

    *complete = FALSE;
    *bytesNeededParam = 0;
    header = methodInfo->InformationBuffer;

    switch(methodInfo->Oid) {
    /* We deal with only OID_SWITCH_NIC_REQUEST as of now */
    case  OID_SWITCH_NIC_REQUEST:
        if (OvsCheckOidHeader(header,
            NDIS_SWITCH_NIC_OID_REQUEST_REVISION_1)) {
            OVS_LOG_INFO("Check Header failed");
            status = NDIS_STATUS_NOT_SUPPORTED;
            *complete = TRUE;
            goto done;
        }

        nicOidRequest = (((PNDIS_SWITCH_NIC_OID_REQUEST)header)->OidRequest);
        nicReqSetInfo = &(nicOidRequest->DATA.SET_INFORMATION);

        /* Fail the SR-IOV VF case */
        if ((nicOidRequest->RequestType == NdisRequestSetInformation) &&
                   (nicReqSetInfo->Oid == OID_NIC_SWITCH_ALLOCATE_VF)) {
            OVS_LOG_INFO("We do not support Oid: "
                         "OID_NIC_SWITCH_ALLOCATE_VF");
            status = NDIS_STATUS_FAILURE;
            *complete = TRUE;
        }
        break;
    default:
        /* No op */
        break;
    }

done:
    OVS_LOG_TRACE("Exit: status %8x.", status);
    return status;
}
Beispiel #7
0
/*
 * --------------------------------------------------------------------------
 * Creates the communication device between user and kernel, and also
 * initializes the data associated data structures.
 * --------------------------------------------------------------------------
 */
NDIS_STATUS
OvsCreateDeviceObject(NDIS_HANDLE ovsExtDriverHandle)
{
    NDIS_STATUS status = NDIS_STATUS_SUCCESS;
    UNICODE_STRING deviceName;
    UNICODE_STRING symbolicDeviceName;
    PDRIVER_DISPATCH dispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1];
    NDIS_DEVICE_OBJECT_ATTRIBUTES deviceAttributes;
    OVS_LOG_TRACE("ovsExtDriverHandle: %p", ovsExtDriverHandle);

    RtlZeroMemory(dispatchTable,
                  (IRP_MJ_MAXIMUM_FUNCTION + 1) * sizeof (PDRIVER_DISPATCH));
    dispatchTable[IRP_MJ_CREATE] = OvsOpenCloseDevice;
    dispatchTable[IRP_MJ_CLOSE] = OvsOpenCloseDevice;
    dispatchTable[IRP_MJ_CLEANUP] = OvsCleanupDevice;
    dispatchTable[IRP_MJ_DEVICE_CONTROL] = OvsDeviceControl;

    NdisInitUnicodeString(&deviceName, OVS_DEVICE_NAME_NT);
    NdisInitUnicodeString(&symbolicDeviceName, OVS_DEVICE_NAME_DOS);

    RtlZeroMemory(&deviceAttributes, sizeof (NDIS_DEVICE_OBJECT_ATTRIBUTES));

    OVS_INIT_OBJECT_HEADER(&deviceAttributes.Header,
                           NDIS_OBJECT_TYPE_DEVICE_OBJECT_ATTRIBUTES,
                           NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1,
                           sizeof (NDIS_DEVICE_OBJECT_ATTRIBUTES));

    deviceAttributes.DeviceName = &deviceName;
    deviceAttributes.SymbolicName = &symbolicDeviceName;
    deviceAttributes.MajorFunctions = dispatchTable;
    deviceAttributes.ExtensionSize = sizeof (OVS_DEVICE_EXTENSION);

    status = NdisRegisterDeviceEx(ovsExtDriverHandle,
                                  &deviceAttributes,
                                  &gOvsDeviceObject,
                                  &gOvsDeviceHandle);
    if (status != NDIS_STATUS_SUCCESS) {
        POVS_DEVICE_EXTENSION ovsExt =
            (POVS_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(gOvsDeviceObject);
        ASSERT(gOvsDeviceObject != NULL);
        ASSERT(gOvsDeviceHandle != NULL);

        if (ovsExt) {
            ovsExt->numberOpenInstance = 0;
        }
    } else {
        /* Initialize the associated data structures. */
        OvsInit();
    }
    OVS_LOG_TRACE("DeviceObject: %p", gOvsDeviceObject);
    return status;
}
Beispiel #8
0
/*
 * --------------------------------------------------------------------------
 * Implements filter driver's FilterOidRequestComplete function.
 * --------------------------------------------------------------------------
 */
VOID
OvsExtOidRequestComplete(NDIS_HANDLE filterModuleContext,
                         PNDIS_OID_REQUEST oidRequest,
                         NDIS_STATUS status)
{
    POVS_SWITCH_CONTEXT switchObject = (POVS_SWITCH_CONTEXT)filterModuleContext;
    PNDIS_OID_REQUEST origReq = OvsOidGetOrigRequest(oidRequest);
    POVS_OID_CONTEXT oidContext = OvsOidGetContext(oidRequest);

    /* Only one of the two should be set */
    ASSERT(origReq != NULL || oidContext != NULL);
    ASSERT(oidContext != NULL || origReq != NULL);

    OVS_LOG_TRACE("Enter: oidRequest %p, reqType: %d",
                  oidRequest, oidRequest->RequestType);

    if (origReq == NULL) {
        NdisInterlockedDecrement(&(switchObject->pendingOidCount));
        oidContext->status = status;
        NdisSetEvent(&oidContext->oidComplete);
        OVS_LOG_INFO("Internally generated request");
        goto done;
    }

    switch(oidRequest->RequestType) {
    case NdisRequestMethod:
        OvsOidRequestCompleteMethod(switchObject, oidRequest,
                                    origReq, status);
        break;

    case NdisRequestSetInformation:
        OvsOidRequestCompleteSetInfo(switchObject, oidRequest,
                                     origReq, status);
        break;

    case NdisRequestQueryInformation:
    case NdisRequestQueryStatistics:
    default:
        OvsOidRequestCompleteQuery(switchObject, oidRequest,
                                   origReq, status);
        break;
    }

    OvsOidSetOrigRequest(oidRequest, NULL);

    NdisFreeCloneOidRequest(switchObject->NdisFilterHandle, oidRequest);
    NdisFOidRequestComplete(switchObject->NdisFilterHandle, origReq, status);
    NdisInterlockedDecrement(&(switchObject->pendingOidCount));

done:
    OVS_LOG_TRACE("Exit");
}
Beispiel #9
0
/*
 * --------------------------------------------------------------------------
 *  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);
}
Beispiel #10
0
/*
 * --------------------------------------------------------------------------
 * 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;
}
Beispiel #11
0
/*
 * --------------------------------------------------------------------------
 * 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;
}
Beispiel #12
0
/*
 * --------------------------------------------------------------------------
 *  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;
        OvsClearAllSwitchVports(switchContext);
        OvsUninitTunnelFilter(gOvsExtDriverObject);
        OvsUninitSwitchContext(switchContext);
    }
    OVS_LOG_TRACE("Exit: deleted switch %p  dpNo: %d", switchContext, dpNo);
}
Beispiel #13
0
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);
}
Beispiel #14
0
/*
 * --------------------------------------------------------------------------
 * Implements filter driver's FilterCancelOidRequest function.
 * --------------------------------------------------------------------------
 */
VOID
OvsExtCancelOidRequest(NDIS_HANDLE filterModuleContext,
                       PVOID requestId)
{
    OVS_LOG_TRACE("Enter: requestId: %p", requestId);

    UNREFERENCED_PARAMETER(filterModuleContext);
    UNREFERENCED_PARAMETER(requestId);
}
Beispiel #15
0
/*
 * --------------------------------------------------------------------------
 *  Implements filter driver's FilterRestart function.
 * --------------------------------------------------------------------------
 */
_Use_decl_annotations_
NDIS_STATUS
OvsExtRestart(NDIS_HANDLE filterModuleContext,
              PNDIS_FILTER_RESTART_PARAMETERS filterRestartParameters)
{
    POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)filterModuleContext;
    NDIS_STATUS status = NDIS_STATUS_SUCCESS;
    BOOLEAN switchActive;

    UNREFERENCED_PARAMETER(filterRestartParameters);

    OVS_LOG_TRACE("Enter: filterModuleContext %p",
                  filterModuleContext);

    /* Activate the switch if this is the first restart. */
    if (!switchContext->isActivated && !switchContext->isActivateFailed) {
        status = OvsQuerySwitchActivationComplete(switchContext,
                                                  &switchActive);
        if (status != NDIS_STATUS_SUCCESS) {
            switchContext->isActivateFailed = TRUE;
            status = NDIS_STATUS_RESOURCES;
            goto cleanup;
        }

        if (switchActive) {
            status = OvsActivateSwitch(switchContext);

            if (status != NDIS_STATUS_SUCCESS) {
                OVS_LOG_WARN("Failed to activate switch, dpNo:%d",
                             switchContext->dpNo);
                status = NDIS_STATUS_RESOURCES;
                goto cleanup;
            }
        }
    }

    ASSERT(switchContext->dataFlowState == OvsSwitchPaused);
    switchContext->dataFlowState = OvsSwitchRunning;

cleanup:
    OVS_LOG_TRACE("Exit: Restart switch:%p, dpNo: %d, status: %#x",
                  switchContext, switchContext->dpNo, status);
    return status;
}
Beispiel #16
0
/*
 * --------------------------------------------------------------------------
 *  Implements filter driver's FilterPause function
 * --------------------------------------------------------------------------
 */
NDIS_STATUS
OvsExtPause(NDIS_HANDLE filterModuleContext,
            PNDIS_FILTER_PAUSE_PARAMETERS pauseParameters)
{
    POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)filterModuleContext;

    UNREFERENCED_PARAMETER(pauseParameters);
    OVS_LOG_TRACE("Enter: filterModuleContext %p",
                  filterModuleContext);

    switchContext->dataFlowState = OvsSwitchPaused;
    KeMemoryBarrier();
    while(switchContext->pendingOidCount > 0) {
        NdisMSleep(1000);
    }

    OVS_LOG_TRACE("Exit: OvsExtPause Successfully");
    return NDIS_STATUS_SUCCESS;
}
Beispiel #17
0
static VOID
OvsOidRequestCompleteQuery(POVS_SWITCH_CONTEXT switchObject,
                           PNDIS_OID_REQUEST oidRequest,
                           PNDIS_OID_REQUEST origOidRequest,
                           NDIS_STATUS status)
{
    UNREFERENCED_PARAMETER(switchObject);
    UNREFERENCED_PARAMETER(status);

    struct _QUERY *queryInfo = &((oidRequest->DATA).QUERY_INFORMATION);
    struct _QUERY *origQueryInfo = &((origOidRequest->DATA).QUERY_INFORMATION);

    OVS_LOG_TRACE("Enter: oidRequest %p, Oid: %lu",
                  oidRequest, queryInfo->Oid);

    origQueryInfo->BytesWritten = queryInfo->BytesWritten;
    origQueryInfo->BytesNeeded = queryInfo->BytesNeeded;

    OVS_LOG_TRACE("Exit");
}
Beispiel #18
0
/*
 * --------------------------------------------------------------------------
 *  Implements filter driver's FilterDetach function.
 * --------------------------------------------------------------------------
 */
_Use_decl_annotations_
VOID
OvsExtDetach(NDIS_HANDLE filterModuleContext)
{
    POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)filterModuleContext;

    OVS_LOG_TRACE("Enter: filterModuleContext %p", filterModuleContext);

    ASSERT(switchContext->dataFlowState == OvsSwitchPaused);
    switchContext->controlFlowState = OvsSwitchDetached;
    KeMemoryBarrier();
    while(switchContext->pendingOidCount > 0) {
        NdisMSleep(1000);
    }
    OvsDeleteSwitch(switchContext);
    OvsCleanupIpHelper();
    /* This completes the cleanup, and a new attach can be handled now. */

    OVS_LOG_TRACE("Exit: OvsDetach Successfully");
}
Beispiel #19
0
/*
 * --------------------------------------------------------------------------
 * Implements filter driver's FilterNetPnPEvent function.
 * --------------------------------------------------------------------------
 */
NDIS_STATUS
OvsExtNetPnPEvent(NDIS_HANDLE filterModuleContext,
                  PNET_PNP_EVENT_NOTIFICATION netPnPEvent)
{
    NDIS_STATUS status = NDIS_STATUS_SUCCESS;
    POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)filterModuleContext;
    BOOLEAN switchActive;

    OVS_LOG_TRACE("Enter: filterModuleContext: %p, NetEvent: %d",
                  filterModuleContext, (netPnPEvent->NetPnPEvent).NetEvent);
    /*
     * The only interesting event is the NetEventSwitchActivate. It provides
     * an asynchronous notification of the switch completing activation.
     */
    if (netPnPEvent->NetPnPEvent.NetEvent == NetEventSwitchActivate) {
        status = OvsQuerySwitchActivationComplete(switchContext, &switchActive);
        if (status != NDIS_STATUS_SUCCESS) {
            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 "
                              "status: %s", switchContext,
                              status ? "TRUE" : "FALSE");
            }
        }
    }

    if (status == NDIS_STATUS_SUCCESS) {
        status = NdisFNetPnPEvent(switchContext->NdisFilterHandle,
                                  netPnPEvent);
    }
    OVS_LOG_TRACE("Exit: OvsExtNetPnPEvent");

    return status;
}
Beispiel #20
0
static VOID
OvsOidRequestCompleteMethod(POVS_SWITCH_CONTEXT switchObject,
                            PNDIS_OID_REQUEST oidRequest,
                            PNDIS_OID_REQUEST origOidRequest,
                            NDIS_STATUS status)
{
    UNREFERENCED_PARAMETER(status);
    UNREFERENCED_PARAMETER(switchObject);

    struct _METHOD *methodInfo = &(oidRequest->DATA.METHOD_INFORMATION);
    struct _METHOD *origMethodInfo = &(origOidRequest->DATA.
                                       METHOD_INFORMATION);

    OVS_LOG_TRACE("Enter: oidRequest %p, Oid: %lu",
                  oidRequest, methodInfo->Oid);

    origMethodInfo->OutputBufferLength = methodInfo->OutputBufferLength;
    origMethodInfo->BytesRead = methodInfo->BytesRead;
    origMethodInfo->BytesNeeded = methodInfo->BytesNeeded;
    origMethodInfo->BytesWritten = methodInfo->BytesWritten;

    OVS_LOG_TRACE("Exit");
}
Beispiel #21
0
static VOID
OvsOidRequestCompleteSetInfo(POVS_SWITCH_CONTEXT switchObject,
                             PNDIS_OID_REQUEST oidRequest,
                             PNDIS_OID_REQUEST origOidRequest,
                             NDIS_STATUS status)
{
    struct _SET *setInfo = &(oidRequest->DATA.SET_INFORMATION);
    struct _SET *origSetInfo = &(origOidRequest->DATA.SET_INFORMATION);
    PNDIS_OBJECT_HEADER origHeader = origSetInfo->InformationBuffer;

    OVS_LOG_TRACE("Enter: oidRequest %p, Oid: %lu",
                  oidRequest, setInfo->Oid);

    origSetInfo->BytesRead = setInfo->BytesRead;
    origSetInfo->BytesNeeded = setInfo->BytesNeeded;

    if (status != NDIS_STATUS_SUCCESS) {

        switch(setInfo->Oid) {
        case OID_SWITCH_PORT_CREATE:
            HvDeletePort(switchObject,
                         (PNDIS_SWITCH_PORT_PARAMETERS)origHeader);
            break;

        case OID_SWITCH_NIC_CREATE:
            HvDeleteNic(switchObject,
                        (PNDIS_SWITCH_NIC_PARAMETERS)origHeader);
            break;

        default:
            break;
        }
    }

    OVS_LOG_TRACE("Exit");
}
Beispiel #22
0
NTSTATUS
OvsOpenCloseDevice(PDEVICE_OBJECT deviceObject,
                   PIRP irp)
{
    PIO_STACK_LOCATION irpSp;
    NTSTATUS status = STATUS_SUCCESS;
    PFILE_OBJECT fileObject;
    POVS_DEVICE_EXTENSION ovsExt =
        (POVS_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(deviceObject);

    ASSERT(deviceObject == gOvsDeviceObject);
    ASSERT(ovsExt != NULL);

    irpSp = IoGetCurrentIrpStackLocation(irp);
    fileObject = irpSp->FileObject;
    OVS_LOG_TRACE("DeviceObject: %p, fileObject:%p, instance: %u",
                  deviceObject, fileObject,
                  ovsExt->numberOpenInstance);

    switch (irpSp->MajorFunction) {
    case IRP_MJ_CREATE:
        status = OvsAddOpenInstance(ovsExt, fileObject);
        if (STATUS_SUCCESS == status) {
            InterlockedIncrement((LONG volatile *)&ovsExt->numberOpenInstance);
        }
        break;
    case IRP_MJ_CLOSE:
        ASSERT(ovsExt->numberOpenInstance > 0);
        OvsRemoveOpenInstance(fileObject);
        InterlockedDecrement((LONG volatile *)&ovsExt->numberOpenInstance);
        break;
    default:
        ASSERT(0);
    }
    return OvsCompleteIrpRequest(irp, (ULONG_PTR)0, status);
}
Beispiel #23
0
/*
 *----------------------------------------------------------------------------
 * OvsCalculateUDPChecksum
 *     Calculate UDP checksum
 *----------------------------------------------------------------------------
 */
static __inline NDIS_STATUS
OvsCalculateUDPChecksum(PNET_BUFFER_LIST curNbl,
                        PNET_BUFFER curNb,
                        IPHdr *ipHdr,
                        UDPHdr *udpHdr,
                        UINT32 packetLength)
{
    NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo;
    UINT16 checkSum;

    csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo);

    /* Next check if UDP checksum has been calculated. */
    if (!csumInfo.Receive.UdpChecksumSucceeded) {
        UINT32 l4Payload;

        checkSum = udpHdr->check;

        l4Payload = packetLength - sizeof(EthHdr) - ipHdr->ihl * 4;
        udpHdr->check = 0;
        udpHdr->check =
            IPPseudoChecksum((UINT32 *)&ipHdr->saddr,
                             (UINT32 *)&ipHdr->daddr,
                             IPPROTO_UDP, (UINT16)l4Payload);
        udpHdr->check = CalculateChecksumNB(curNb, (UINT16)l4Payload,
            sizeof(EthHdr) + ipHdr->ihl * 4);
        if (checkSum != udpHdr->check) {
            OVS_LOG_TRACE("UDP checksum incorrect.");
            return NDIS_STATUS_INVALID_PACKET;
        }
    }

    csumInfo.Receive.UdpChecksumSucceeded = 1;
    NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo) = csumInfo.Value;
    return NDIS_STATUS_SUCCESS;
}
Beispiel #24
0
/*
 * --------------------------------------------------------------------------
 *  Implements filter driver's FilterAttach function.
 *
 *  This function allocates the switch context, and initializes its necessary
 *  members.
 * --------------------------------------------------------------------------
 */
NDIS_STATUS
OvsExtAttach(NDIS_HANDLE ndisFilterHandle,
             NDIS_HANDLE filterDriverContext,
             PNDIS_FILTER_ATTACH_PARAMETERS attachParameters)
{
    NDIS_STATUS status = NDIS_STATUS_FAILURE;
    NDIS_FILTER_ATTRIBUTES ovsExtAttributes;
    POVS_SWITCH_CONTEXT switchContext = NULL;

    UNREFERENCED_PARAMETER(filterDriverContext);

    OVS_LOG_TRACE("Enter: ndisFilterHandle %p", ndisFilterHandle);

    ASSERT(filterDriverContext == (NDIS_HANDLE)gOvsExtDriverObject);
    if (attachParameters->MiniportMediaType != NdisMedium802_3) {
        status = NDIS_STATUS_INVALID_PARAMETER;
        goto cleanup;
    }

    if (gOvsExtDriverHandle == NULL) {
        OVS_LOG_TRACE("Exit: OVSEXT driver is not loaded.");
        ASSERT(FALSE);
        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);
        /* 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) {
        OVS_LOG_ERROR("Exit: Failed to initialize IP helper.");
        goto cleanup;
    }

    status = OvsCreateSwitch(ndisFilterHandle, &switchContext);
    if (status != NDIS_STATUS_SUCCESS) {
        OvsCleanupIpHelper();
        goto cleanup;
    }
    ASSERT(switchContext);

    /*
     * Register the switch context with NDIS so NDIS can pass it back to the
     * Filterxxx callback functions as the 'FilterModuleContext' parameter.
     */
    RtlZeroMemory(&ovsExtAttributes, sizeof(NDIS_FILTER_ATTRIBUTES));
    ovsExtAttributes.Header.Revision = NDIS_FILTER_ATTRIBUTES_REVISION_1;
    ovsExtAttributes.Header.Size = sizeof(NDIS_FILTER_ATTRIBUTES);
    ovsExtAttributes.Header.Type = NDIS_OBJECT_TYPE_FILTER_ATTRIBUTES;
    ovsExtAttributes.Flags = 0;

    NDIS_DECLARE_FILTER_MODULE_CONTEXT(OVS_SWITCH_CONTEXT);
    status = NdisFSetAttributes(ndisFilterHandle, switchContext, &ovsExtAttributes);
    if (status != NDIS_STATUS_SUCCESS) {
        OVS_LOG_ERROR("Failed to set attributes.");
        OvsCleanupIpHelper();
        goto cleanup;
    }

    /* Setup the state machine. */
    switchContext->controlFlowState = OvsSwitchAttached;
    switchContext->dataFlowState = OvsSwitchPaused;

    gOvsSwitchContext = switchContext;
    KeMemoryBarrier();

cleanup:
    gOvsInAttach = FALSE;
    if (status != NDIS_STATUS_SUCCESS) {
        if (switchContext != NULL) {
            OvsDeleteSwitch(switchContext);
        }
    }
    OVS_LOG_TRACE("Exit: status %x", status);

    return status;
}
Beispiel #25
0
/*
 * --------------------------------------------------------------------------
 * OvsTcpSegmentyNBL --
 *
 *    Segment TCP payload, and prepend each segment with ether/IP/TCP header.
 *    Leave headRoom for additional encap.
 *
 *    Please note,
 *       NBL should have OVS_BUFFER_CONTEXT setup before calling
 *       this function.
 *       The NBL should already have ref to itself so that during copy
 *       it will not be freed.
 *       Currently this API assert there is only one NB in an NBL, it needs
 *       to be fixed if we receive multiple NBs in an NBL.
 * --------------------------------------------------------------------------
 */
PNET_BUFFER_LIST
OvsTcpSegmentNBL(PVOID ovsContext,
                 PNET_BUFFER_LIST nbl,
                 POVS_PACKET_HDR_INFO hdrInfo,
                 UINT32 mss,
                 UINT32 headRoom)
{
    POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext;
#ifdef DBG
    POVS_NBL_POOL ovsPool = &context->ovsPool;
#endif
    POVS_BUFFER_CONTEXT dstCtx, srcCtx;
    UINT32 size, hdrSize, seqNumber;
    PNET_BUFFER_LIST newNbl;
    PNET_BUFFER nb, newNb;
    NDIS_STATUS status;
    UINT16 segmentSize;
    ULONG copiedSize;

    srcCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);
    if (srcCtx == NULL || srcCtx->magic != OVS_CTX_MAGIC) {
        OVS_LOG_INFO("src nbl must have ctx initialized");
        ASSERT(srcCtx && srcCtx->magic == OVS_CTX_MAGIC);
        return NULL;
    }

    nb = NET_BUFFER_LIST_FIRST_NB(nbl);
    ASSERT(NET_BUFFER_NEXT_NB(nb) == NULL);

    /* Figure out the segment header size */
    status = GetSegmentHeaderInfo(nbl, hdrInfo, &hdrSize, &seqNumber);
    if (status != NDIS_STATUS_SUCCESS) {
        OVS_LOG_INFO("Cannot parse NBL header");
        return NULL;
    }

    size = NET_BUFFER_DATA_LENGTH(nb) - hdrSize;

    /* XXX add to ovsPool counters? */
    newNbl = NdisAllocateFragmentNetBufferList(nbl, NULL,
            NULL, hdrSize, mss, hdrSize + headRoom , 0, 0);
    if (newNbl == NULL) {
        return NULL;
    }

    /* Now deal with TCP payload */
    for (newNb = NET_BUFFER_LIST_FIRST_NB(newNbl); newNb != NULL;
            newNb = NET_BUFFER_NEXT_NB(newNb)) {
        segmentSize = (size > mss ? mss : size) & 0xffff;
        if (headRoom) {
            NdisAdvanceNetBufferDataStart(newNb, headRoom, FALSE, NULL);
        }

        /* Now copy the eth/IP/TCP header and fix up */
        status = NdisCopyFromNetBufferToNetBuffer(newNb, 0, hdrSize, nb, 0,
                                                  &copiedSize);
        if (status != NDIS_STATUS_SUCCESS || hdrSize != copiedSize) {
            goto nblcopy_error;
        }

        status = FixSegmentHeader(newNb, segmentSize, seqNumber);
        if (status != NDIS_STATUS_SUCCESS) {
            goto nblcopy_error;
        }


        /* Move on to the next segment */
        size -= segmentSize;
        seqNumber += segmentSize;
    }

    status = OvsAllocateNBLContext(context, newNbl);
    if (status != NDIS_STATUS_SUCCESS) {
        goto nblcopy_error;
    }

    status = OvsCopyNBLInfo(nbl, newNbl, srcCtx, hdrSize + headRoom, FALSE);
    if (status != NDIS_STATUS_SUCCESS) {
        goto nbl_context_error;
    }

    newNbl->ParentNetBufferList = nbl;

    /* Remember it's a fragment NBL so we can free it properly */
    dstCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(newNbl);
    ASSERT(dstCtx != NULL);
    dstCtx->flags = OVS_BUFFER_FRAGMENT | OVS_BUFFER_PRIVATE_CONTEXT |
        OVS_BUFFER_PRIVATE_FORWARD_CONTEXT | OVS_BUFFER_SEND_BUFFER;
    dstCtx->refCount = 1;
    dstCtx->magic = OVS_CTX_MAGIC;
    dstCtx->dataOffsetDelta = hdrSize + headRoom;

    InterlockedIncrement((LONG volatile *)&srcCtx->refCount);
#ifdef DBG
    InterlockedIncrement((LONG volatile *)&ovsPool->fragNBLCount);

    OvsDumpNetBufferList(nbl);
    OvsDumpForwardingDetails(nbl);

    OvsDumpNetBufferList(newNbl);
    OvsDumpForwardingDetails(newNbl);
#endif
    OVS_LOG_TRACE("Segment nbl %p to newNbl: %p", nbl, newNbl);
    return newNbl;

nbl_context_error:
    OvsFreeNBLContext(context, newNbl);
nblcopy_error:
#ifdef DBG
    InterlockedDecrement((LONG volatile *)&ovsPool->fragNBLCount);
#endif
    NdisFreeFragmentNetBufferList(newNbl, hdrSize + headRoom, 0);
    return NULL;
}
Beispiel #26
0
/*
 * --------------------------------------------------------------------------
 * OvsCompleteNBL --
 *
 *     This function tries to free the NBL allocated by OVS buffer
 *     management module. If it trigger the completion of the parent
 *     NBL, it will recursively call itself. If it trigger the completion
 *     of external NBL, it will be returned to the caller. The caller
 *     is responsible to call API to return to upper layer.
 * --------------------------------------------------------------------------
 */
PNET_BUFFER_LIST
OvsCompleteNBL(POVS_SWITCH_CONTEXT context,
               PNET_BUFFER_LIST nbl,
               BOOLEAN updateRef)
{
    POVS_BUFFER_CONTEXT ctx;
    UINT16 flags;
    PNET_BUFFER_LIST parent;
    NDIS_STATUS status;
    NDIS_HANDLE poolHandle;
    LONG value;
    POVS_NBL_POOL ovsPool = &context->ovsPool;
    PNET_BUFFER nb;


    ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);

    ASSERT(ctx && ctx->magic == OVS_CTX_MAGIC);

    OVS_LOG_TRACE("Enter: nbl: %p, ctx: %p, refCount: %d, updateRef:%d",
                 nbl, ctx, ctx->refCount, updateRef);

    if (updateRef) {
        value = InterlockedDecrement((LONG volatile *)&ctx->refCount);
        if (value != 0) {
            return NULL;
        }
    } else {
        /*
         * This is a special case, the refCount must be zero
         */
        ASSERT(ctx->refCount == 0);
    }

    nb = NET_BUFFER_LIST_FIRST_NB(nbl);

    flags = ctx->flags;
    if (!(flags & OVS_BUFFER_FRAGMENT) &&
        NET_BUFFER_DATA_LENGTH(nb) != ctx->origDataLength) {
        UINT32 diff;
        if (NET_BUFFER_DATA_LENGTH(nb) < ctx->origDataLength) {
            diff = ctx->origDataLength -NET_BUFFER_DATA_LENGTH(nb);
            status = NdisRetreatNetBufferListDataStart(nbl, diff, 0,
                                                       NULL, NULL);
            ASSERT(status == NDIS_STATUS_SUCCESS);
        } else {
            diff = NET_BUFFER_DATA_LENGTH(nb) - ctx->origDataLength;
            NdisAdvanceNetBufferListDataStart(nbl, diff, TRUE, NULL);
        }
    }

    if (ctx->flags & OVS_BUFFER_PRIVATE_CONTEXT) {
        NdisFreeNetBufferListContext(nbl, sizeof (OVS_BUFFER_CONTEXT));
    }

    if (flags & OVS_BUFFER_NEED_COMPLETE) {
        /*
         * return to caller for completion
         */
#ifdef DBG
        InterlockedDecrement((LONG volatile *)&ovsPool->sysNBLCount);
#endif
        return nbl;
    }

    if (flags & OVS_BUFFER_PRIVATE_FORWARD_CONTEXT) {
        context->NdisSwitchHandlers.
              FreeNetBufferListForwardingContext(ovsPool->ndisContext, nbl);
    }

    if (flags & (OVS_BUFFER_PRIVATE_MDL | OVS_BUFFER_PRIVATE_DATA)) {
        PNET_BUFFER nb = NET_BUFFER_LIST_FIRST_NB(nbl);
        while (nb) {
            PMDL mdl = NET_BUFFER_FIRST_MDL(nb);
            NET_BUFFER_FIRST_MDL(nb) = NULL;
            ASSERT(mdl->Next == NULL);
            OvsFreeMDLAndData(mdl);
            nb = NET_BUFFER_NEXT_NB(nb);
        }
    }

    if (flags & OVS_BUFFER_PRIVATE_NET_BUFFER) {
        PNET_BUFFER nb, nextNb;

        nb = NET_BUFFER_LIST_FIRST_NB(nbl);
        while (nb) {
            nextNb = NET_BUFFER_NEXT_NB(nb);
            NdisFreeNetBuffer(nb);
#ifdef DBG
            InterlockedDecrement((LONG volatile *)&ovsPool->nbCount);
#endif
            nb = nextNb;
        }
        NET_BUFFER_LIST_FIRST_NB(nbl) = NULL;
    }

    parent = nbl->ParentNetBufferList;

    poolHandle = NdisGetPoolFromNetBufferList(nbl);
    if (flags & OVS_BUFFER_FROM_FIX_SIZE_POOL) {
        ASSERT(poolHandle == ovsPool->fixSizePool);
#ifdef DBG
        InterlockedDecrement((LONG volatile *)&ovsPool->fixNBLCount);
#endif
        NdisFreeNetBufferList(nbl);
    } else if (flags & OVS_BUFFER_FROM_ZERO_SIZE_POOL) {
        ASSERT(poolHandle == ovsPool->zeroSizePool);
#ifdef DBG
        InterlockedDecrement((LONG volatile *)&ovsPool->zeroNBLCount);
#endif
        NdisFreeNetBufferList(nbl);
    } else if (flags & OVS_BUFFER_FROM_NBL_ONLY_POOL) {
        ASSERT(poolHandle == ovsPool->nblOnlyPool);
#ifdef DBG
        InterlockedDecrement((LONG volatile *)&ovsPool->nblOnlyCount);
#endif
        NdisFreeCloneNetBufferList(nbl, 0);
    } else if (flags & OVS_BUFFER_FRAGMENT) {
        OVS_LOG_TRACE("Free fragment %p parent %p", nbl, parent);
#ifdef DBG
        InterlockedDecrement((LONG volatile *)&ovsPool->fragNBLCount);
#endif
        NdisFreeFragmentNetBufferList(nbl, ctx->dataOffsetDelta, 0);
    }

    if (parent != NULL) {
        ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(parent);
        ASSERT(ctx && ctx->magic == OVS_CTX_MAGIC);
        value = InterlockedDecrement((LONG volatile *)&ctx->refCount);
        if (value == 0) {
            return OvsCompleteNBL(context, parent, FALSE);
        }
    }
    return NULL;
}
Beispiel #27
0
static NDIS_STATUS
OvsProcessSetOid(POVS_SWITCH_CONTEXT switchObject,
                 PNDIS_OID_REQUEST oidRequest,
                 PBOOLEAN complete)
{
    NDIS_STATUS status = NDIS_STATUS_SUCCESS;
    struct _SET *setInfo = &(oidRequest->DATA.SET_INFORMATION);

    *complete = FALSE;

    OVS_LOG_TRACE("Enter: oidRequest %p, Oid: %lu",
                  oidRequest, setInfo->Oid);

    /* Verify the basic Oid paramters first */
    if (setInfo->InformationBufferLength &&
       (setInfo->InformationBufferLength < sizeof(NDIS_OBJECT_HEADER))) {
        status = NDIS_STATUS_INVALID_OID;
        OVS_LOG_INFO("Invalid input %d", setInfo->InformationBufferLength);
        goto error;
    }

    /* Documentation does not specify what should be done
     * if informationBuffer is not present. Although it mentions the
     * structure type informationBUffer points to for each oid request,
     * but it does not explicitly mention that it is a MUST.
     * hence we are following this scenario same way as what sample code
     * mentions. */
    if (!(setInfo->InformationBufferLength)) {
        /* We cannot do anything about this oid request,
         * lets just pass it down. */
        OVS_LOG_INFO("Buffer Length Zero");
        goto done;
    }

    switch(setInfo->Oid) {
    case OID_SWITCH_PORT_PROPERTY_ADD:
    case OID_SWITCH_PORT_PROPERTY_UPDATE:
    case OID_SWITCH_PORT_PROPERTY_DELETE:
        status = OvsProcessSetOidPortProp(switchObject, oidRequest);
    break;

    case OID_SWITCH_PORT_CREATE:
    case OID_SWITCH_PORT_UPDATED:
    case OID_SWITCH_PORT_TEARDOWN:
    case OID_SWITCH_PORT_DELETE:
        status = OvsProcessSetOidPort(switchObject, oidRequest);
    break;

    case OID_SWITCH_NIC_CREATE:
    case OID_SWITCH_NIC_CONNECT:
    case OID_SWITCH_NIC_UPDATED:
    case OID_SWITCH_NIC_DISCONNECT:
    case OID_SWITCH_NIC_DELETE:
        status = OvsProcessSetOidNic(switchObject, oidRequest);
    break;

    default:
        /* Non handled OID request */
        break;
    }

    if (status != NDIS_STATUS_SUCCESS) {
        goto error;
    }

    goto done;

error:
    *complete = TRUE;
done:
    OVS_LOG_TRACE("Exit: status %8x.", status);
    return status;
}
Beispiel #28
0
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;
}
Beispiel #29
0
NDIS_STATUS
OvsExtOidRequest(NDIS_HANDLE filterModuleContext,
                 PNDIS_OID_REQUEST oidRequest)
{
    POVS_SWITCH_CONTEXT switchObject = (POVS_SWITCH_CONTEXT)filterModuleContext;
    NDIS_STATUS status = NDIS_STATUS_SUCCESS;
    PNDIS_OID_REQUEST clonedOidRequest = NULL;
    struct _METHOD *methodInfo = &(oidRequest->DATA.METHOD_INFORMATION);
    BOOLEAN completeOid = FALSE;
    ULONG bytesNeeded = 0;

    OVS_LOG_TRACE("Enter: oidRequest %p, reqType: %d",
                  oidRequest, oidRequest->RequestType);
    status = NdisAllocateCloneOidRequest(switchObject->NdisFilterHandle,
                                         oidRequest, OVS_MEMORY_TAG,
                                         &clonedOidRequest);
    if (status != NDIS_STATUS_SUCCESS) {
        goto done;
    }

    NdisInterlockedIncrement(&(switchObject->pendingOidCount));

    /* set the original oid request in cloned one. */
    OvsOidSetOrigRequest(clonedOidRequest, oidRequest);
    OvsOidSetContext(clonedOidRequest, NULL);

    switch(clonedOidRequest->RequestType) {
    case NdisRequestSetInformation:
        status = OvsProcessSetOid(switchObject, clonedOidRequest,
                                                   &completeOid);
        break;
    case NdisRequestMethod:
        status = OvsProcessMethodOid(switchObject, clonedOidRequest,
                                     &completeOid, &bytesNeeded);
        break;
    default:
        /* We do not handle other request types as of now.
         * We are just a passthrough for those. */
        break;
    }

    if (completeOid == TRUE) {
        /* dont leave any reference back to original request,
         * even if we are freeing it up. */
        OVS_LOG_INFO("Complete True oidRequest %p.", oidRequest);
        OvsOidSetOrigRequest(clonedOidRequest, NULL);
        NdisFreeCloneOidRequest(switchObject->NdisFilterHandle,
                                             clonedOidRequest);
        methodInfo->BytesNeeded = bytesNeeded;
        NdisInterlockedDecrement(&switchObject->pendingOidCount);
        goto done;
    }

    /* pass the request down */
    status = NdisFOidRequest(switchObject->NdisFilterHandle, clonedOidRequest);
    if (status != NDIS_STATUS_PENDING) {
        OvsExtOidRequestComplete(switchObject, clonedOidRequest, status);
        /* sample code says so */
        status = NDIS_STATUS_PENDING;
    }

done:
    OVS_LOG_TRACE("Exit: status %8x.", status);
    return status;
}
Beispiel #30
0
/*
 * --------------------------------------------------------------------------
 * 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;
}