Exemplo n.º 1
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;
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
Arquivo: Util.c Projeto: alshabib/ovs
VOID *
OvsAllocateMemoryPerCpu(size_t size, ULONG tag)
{
    VOID *ptr = NULL;
    ULONG count = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);

    ASSERT(KeQueryActiveGroupCount() == 1);

    ptr = OvsAllocateMemoryWithTag(count * size, tag);
    if (ptr) {
        RtlZeroMemory(ptr, count * size);
    }

    return ptr;
}
Exemplo n.º 5
0
OVS_CT_ENTRY *
OvsConntrackCreateTcpEntry(const TCPHdr *tcp,
                           PNET_BUFFER_LIST nbl,
                           UINT64 now)
{
    struct conn_tcp* newconn;
    struct tcp_peer *src, *dst;

    newconn = OvsAllocateMemoryWithTag(sizeof(struct conn_tcp),
                                       OVS_CT_POOL_TAG);
    if (!newconn) {
        return NULL;
    }

    newconn->up = (OVS_CT_ENTRY) {0};
    src = &newconn->peer[0];
    dst = &newconn->peer[1];

    src->seqlo = ntohl(tcp->seq);
    src->seqhi = src->seqlo + OvsGetTcpPayloadLength(nbl) + 1;

    if (tcp->flags & TCP_SYN) {
        src->seqhi++;
        src->wscale = OvsTcpGetWscale(tcp);
    } else {
        src->wscale = CT_WSCALE_UNKNOWN;
        dst->wscale = CT_WSCALE_UNKNOWN;
    }
    src->max_win = MAX(ntohs(tcp->window), 1);
    if (src->wscale & CT_WSCALE_MASK) {
        /* Remove scale factor from initial window */
        uint8_t sws = src->wscale & CT_WSCALE_MASK;
        src->max_win = DIV_ROUND_UP((uint32_t) src->max_win, 1 << sws);
    }
    if (tcp->flags & TCP_FIN) {
        src->seqhi++;
    }
    dst->seqhi = 1;
    dst->max_win = 1;
    src->state = CT_DPIF_TCPS_SYN_SENT;
    dst->state = CT_DPIF_TCPS_CLOSED;

    OvsConntrackUpdateExpiration(newconn, now, CT_ENTRY_TIMEOUT);

    return &newconn->up;
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
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;
}