Example #1
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;
}
Example #2
0
static VOID
OvsDumpNBLContext(PNET_BUFFER_LIST nbl)
{
    PNET_BUFFER_LIST_CONTEXT ctx = nbl->Context;
    if (ctx == NULL) {
        OVS_LOG_INFO("No Net Buffer List context");
        return;
    }
    while (ctx) {
        OVS_LOG_INFO("nbl: %p, ctx: %p, TotalSize: %d, Offset: %d",
                     nbl, ctx, ctx->Size, ctx->Offset);
        ctx = ctx->Next;
    }
}
Example #3
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");
}
Example #4
0
static VOID
OvsDumpMDLChain(PMDL mdl)
{
    PMDL tmp;
    tmp = mdl;
    while (tmp) {
        OVS_LOG_INFO("MDL: %p, Size: %d, MappedSystemVa: %p, StartVa: %p"
                     " ByteCount: %d, ByteOffset: %d",
                     tmp, tmp->Size, tmp->MappedSystemVa,
                     tmp->StartVa, tmp->ByteCount, tmp->ByteOffset);
        tmp = tmp->Next;
    }
}
Example #5
0
/*
 * --------------------------------------------------------------------------
 * OvsFullCopyToMultipleNBLs --
 *
 *    Copy NBL to multiple NBLs, each NB will have its own NBL
 * --------------------------------------------------------------------------
 */
PNET_BUFFER_LIST
OvsFullCopyToMultipleNBLs(PVOID ovsContext,
                          PNET_BUFFER_LIST nbl,
                          UINT32 headRoom,
                          BOOLEAN copyNblInfo)
{

    POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext;
    PNET_BUFFER_LIST firstNbl, currNbl, newNbl;
    PNET_BUFFER nb;
    POVS_BUFFER_CONTEXT srcCtx;

    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);
    newNbl = OvsCopySinglePacketNBL(context, nbl, nb, headRoom, copyNblInfo);

    if (newNbl == NULL || NET_BUFFER_NEXT_NB(nb) == NULL) {
        return newNbl;
    } else {
        firstNbl = newNbl;
        currNbl = newNbl;
    }

    while (nb) {
        newNbl = OvsCopySinglePacketNBL(context, nbl, nb, headRoom,
                                        copyNblInfo);
        if (newNbl == NULL) {
            goto copymultiple_error;
        }
        NET_BUFFER_LIST_NEXT_NBL(currNbl) = newNbl;
        currNbl = newNbl;
        nb = NET_BUFFER_NEXT_NB(nb);
    }
    return firstNbl;

copymultiple_error:
    while (firstNbl) {
        currNbl = firstNbl;
        firstNbl = NET_BUFFER_LIST_NEXT_NBL(firstNbl);
        NET_BUFFER_LIST_NEXT_NBL(currNbl) = NULL;
        OvsCompleteNBL(context, currNbl, TRUE);
    }
    return NULL;

}
Example #6
0
static VOID
OvsDumpNetBuffer(PNET_BUFFER nb)
{
    OVS_LOG_INFO("NET_BUFFER: %p, ChecksumBias: %d Handle: %p, MDLChain: %p "
                 "CurrMDL: %p, CurrOffset: %d, DataLen: %d, Offset: %d",
                 nb,
                 NET_BUFFER_CHECKSUM_BIAS(nb), nb->NdisPoolHandle,
                 NET_BUFFER_FIRST_MDL(nb),
                 NET_BUFFER_CURRENT_MDL(nb),
                 NET_BUFFER_CURRENT_MDL_OFFSET(nb),
                 NET_BUFFER_DATA_LENGTH(nb),
                 NET_BUFFER_DATA_OFFSET(nb));
    OvsDumpMDLChain(NET_BUFFER_FIRST_MDL(nb));
}
Example #7
0
static VOID
OvsDumpNetBufferList(PNET_BUFFER_LIST nbl)
{
    PNET_BUFFER nb;
    OVS_LOG_INFO("NBL: %p, parent: %p, SrcHandle: %p, ChildCount:%d "
                 "poolHandle: %p",
                 nbl, nbl->ParentNetBufferList,
                 nbl->SourceHandle, nbl->ChildRefCount,
                 nbl->NdisPoolHandle);
    OvsDumpNBLContext(nbl);
    nb = NET_BUFFER_LIST_FIRST_NB(nbl);
    while (nb) {
        OvsDumpNetBuffer(nb);
        nb = NET_BUFFER_NEXT_NB(nb);
    }
}
Example #8
0
static VOID
OvsDumpForwardingDetails(PNET_BUFFER_LIST nbl)
{
    PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO info;
    info = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(nbl);
    if (info == NULL) {
        return;
    }
    OVS_LOG_INFO("nbl: %p, numAvailableDest: %d, srcId:%d, srcIndex: %d "
                 "isDataSafe: %s, safeDataSize: %d",
                 nbl, info->NumAvailableDestinations, info->SourcePortId,
                 info->SourceNicIndex,
                 info->IsPacketDataSafe ? "TRUE" : "FALSE",
                 info->IsPacketDataSafe ? 0 : info->SafePacketDataSize);

}
Example #9
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;
}
Example #10
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;
}
Example #11
0
NTSTATUS
OvsDeviceControl(PDEVICE_OBJECT deviceObject,
                 PIRP irp)
{

    PIO_STACK_LOCATION irpSp;
    NTSTATUS status = STATUS_SUCCESS;
    PFILE_OBJECT fileObject;
    PVOID inputBuffer;
    PVOID outputBuffer;
    UINT32 inputBufferLen, outputBufferLen, mdlBufferLen;
    UINT32 code, replyLen = 0;
#ifdef DBG
    POVS_DEVICE_EXTENSION ovsExt =
        (POVS_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(deviceObject);
    ASSERT(deviceObject == gOvsDeviceObject);
    ASSERT(ovsExt);
    ASSERT(ovsExt->numberOpenInstance > 0);
#else
    UNREFERENCED_PARAMETER(deviceObject);
#endif

    irpSp = IoGetCurrentIrpStackLocation(irp);


    ASSERT(irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL);
    ASSERT(irpSp->FileObject != NULL);

    fileObject = irpSp->FileObject;
    code = irpSp->Parameters.DeviceIoControl.IoControlCode;
    inputBufferLen = irpSp->Parameters.DeviceIoControl.InputBufferLength;
    outputBufferLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
    /*
     * In case of an IRP with METHOD_IN_DIRECT or METHOD_OUT_DIRECT, the size
     * of the MDL is stored in Parameters.DeviceIoControl.OutputBufferLength.
     */
    mdlBufferLen = outputBufferLen;
    outputBuffer = inputBuffer = irp->AssociatedIrp.SystemBuffer;

    switch(code) {
    case OVS_IOCTL_VERSION_GET:
        status = OvsGetVersionIoctl(outputBuffer, outputBufferLen,
                                    &replyLen);
        break;
    case OVS_IOCTL_DP_DUMP:
        status = OvsDpDumpIoctl(outputBuffer, outputBufferLen, &replyLen);
        break;
    case OVS_IOCTL_DP_GET:
        if (irp->MdlAddress == NULL) {
            status = STATUS_INVALID_PARAMETER;
            break;
        }
        outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
                                                    NormalPagePriority);
        if (outputBuffer == NULL) {
            status = STATUS_INSUFFICIENT_RESOURCES;
        } else {
            status = OvsDpGetIoctl(inputBuffer, inputBufferLen,
                                   outputBuffer, outputBufferLen, &replyLen);
        }
        break;
    case OVS_IOCTL_DP_SET:
        status = STATUS_NOT_IMPLEMENTED;
        break;
    case OVS_IOCTL_VPORT_DUMP:
        if (irp->MdlAddress == NULL) {
            status = STATUS_INVALID_PARAMETER;
            break;
        }
        outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
                                                    NormalPagePriority);
        if (outputBuffer) {
            status = OvsDumpVportIoctl(inputBuffer, inputBufferLen,
                                       outputBuffer, outputBufferLen,
                                       &replyLen);
        } else {
            status = STATUS_INSUFFICIENT_RESOURCES;
        }
        break;
    case OVS_IOCTL_VPORT_GET:
        if (irp->MdlAddress == NULL) {
            status = STATUS_INVALID_PARAMETER;
            break;
        }
        outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
                                                    NormalPagePriority);
        if (outputBuffer) {
            status = OvsGetVportIoctl(inputBuffer, inputBufferLen,
                                      outputBuffer, outputBufferLen,
                                      &replyLen);
        } else {
            status =  STATUS_INSUFFICIENT_RESOURCES;
        }
        break;
    case OVS_IOCTL_VPORT_SET:
        status = STATUS_NOT_IMPLEMENTED;
        break;
    case OVS_IOCTL_VPORT_ADD:
        if (irp->MdlAddress == NULL) {
            status = STATUS_INVALID_PARAMETER;
            break;
        }
        outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
                                                    NormalPagePriority);
        if (outputBuffer) {
            status = OvsAddVportIoctl(inputBuffer, inputBufferLen,
                                      outputBuffer, outputBufferLen,
                                      &replyLen);
        }  else {
            status = STATUS_INSUFFICIENT_RESOURCES;
        }
        break;
    case OVS_IOCTL_VPORT_DEL:
        status = OvsDelVportIoctl(inputBuffer, inputBufferLen,
                                  &replyLen);
        break;
    case OVS_IOCTL_VPORT_EXT_INFO:
        if (irp->MdlAddress == NULL) {
            status = STATUS_INVALID_PARAMETER;
            break;
        }
        outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
                                                    NormalPagePriority);
        if (outputBuffer) {
            status = OvsGetExtInfoIoctl(inputBuffer, inputBufferLen,
                                          outputBuffer, outputBufferLen,
                                          &replyLen);
        } else {
            OVS_LOG_INFO("ExtInfo: fail to get outputBuffer address");
            status = STATUS_INSUFFICIENT_RESOURCES;
        }
        break;
    case OVS_IOCTL_FLOW_DUMP:
        if (irp->MdlAddress == NULL) {
            status = STATUS_INVALID_PARAMETER;
            break;
        }
        outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
                                                    NormalPagePriority);
        if (outputBuffer) {
            status = OvsDumpFlowIoctl(inputBuffer, inputBufferLen,
                                      outputBuffer, outputBufferLen,
                                      &replyLen);
        } else {
            status = STATUS_INSUFFICIENT_RESOURCES;
        }
        break;
    case OVS_IOCTL_FLOW_GET:
        if (irp->MdlAddress == NULL) {
            status = STATUS_INVALID_PARAMETER;
            break;
        }
        outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
                                                    NormalPagePriority);
        if (outputBuffer) {
            status = OvsGetFlowIoctl(inputBuffer, inputBufferLen,
                                     outputBuffer, outputBufferLen,
                                     &replyLen);
        } else {
            status = STATUS_INSUFFICIENT_RESOURCES;
        }
        break;
    case OVS_IOCTL_FLOW_PUT:
        // XXX: This is not really working - mapping the input buffer
        // XXX: inputBufferLen = mdlBufferLen;
        // inputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
                                                   // NormalPagePriority);
        status = OvsPutFlowIoctl(inputBuffer, inputBufferLen,
                                 outputBuffer, outputBufferLen,
                                 &replyLen);
        break;
    case OVS_IOCTL_FLOW_FLUSH:
        status = OvsFlushFlowIoctl(inputBuffer, inputBufferLen);
        break;
    case OVS_IOCTL_QOS_QUEUE_DUMP:
    case OVS_IOCTL_QOS_QUEUE_GET:
    case OVS_IOCTL_QOS_QUEUE_SET:
        status = STATUS_NOT_IMPLEMENTED;
        break;
    case OVS_IOCTL_DATAPATH_SUBSCRIBE:
        status = OvsSubscribeDpIoctl(fileObject, inputBuffer,
                                           inputBufferLen);
        break;
    case OVS_IOCTL_DATAPATH_READ:
        if (irp->MdlAddress == NULL) {
            status = STATUS_INVALID_PARAMETER;
            break;
        }
        outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
                                                    NormalPagePriority);
        if (outputBuffer) {
            status = OvsReadDpIoctl(fileObject, outputBuffer,
                                          outputBufferLen, &replyLen);
        } else {
            status = STATUS_INSUFFICIENT_RESOURCES;
        }
        break;
    case OVS_IOCTL_DATAPATH_OPERATE:
        status = STATUS_NOT_IMPLEMENTED;
        break;
    case OVS_IOCTL_DATAPATH_EXECUTE:
        // XXX: need to make the input direct
        status = OvsExecuteDpIoctl(inputBuffer, inputBufferLen,
                                         outputBufferLen);
        break;
    case OVS_IOCTL_DATAPATH_PURGE:
        status = OvsPurgeDpIoctl(fileObject);
        break;
    case OVS_IOCTL_DATAPATH_WAIT:
        status = OvsWaitDpIoctl(irp, fileObject);
        break;
    case OVS_IOCTL_EVENT_SUBSCRIBE:
        status = OvsSubscribeEventIoctl(fileObject, inputBuffer,
                                        inputBufferLen);
        break;
    case OVS_IOCTL_EVENT_POLL:
        if (irp->MdlAddress == NULL) {
            status = STATUS_INVALID_PARAMETER;
            break;
        }
        outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
                                                    NormalPagePriority);
        if (outputBuffer == NULL) {
            status = STATUS_INSUFFICIENT_RESOURCES;
        } else {
            status = OvsPollEventIoctl(fileObject, inputBuffer,
                                       inputBufferLen, outputBuffer,
                                       outputBufferLen, &replyLen);
        }
        break;
    case OVS_IOCTL_EVENT_WAIT:
        status = OvsWaitEventIoctl(irp, fileObject,
                                   inputBuffer, inputBufferLen);
        break;
    case OVS_IOCTL_DP_TIMESTAMP_SET:
        if (inputBufferLen != sizeof (ovsUserTimestampDelta)) {
            status = STATUS_INFO_LENGTH_MISMATCH;
        } else {
            int64 currentUserTS = *(int64 *)inputBuffer;
            LARGE_INTEGER tickCount;

            /* So many ticks since system booted. */
            KeQueryTickCount(&tickCount);
            ovsUserTimestampDelta = currentUserTS -
                                    (tickCount.QuadPart * ovsTimeIncrementPerTick);
            status = STATUS_SUCCESS;
        }
        break;
    default:
        status = STATUS_INVALID_DEVICE_REQUEST;
        break;
    }

    if (status == STATUS_PENDING) {
        return status;
    } else {
        /*
         * When the system-address-space mapping that is returned by
         * MmGetSystemAddressForMdlSafe is no longer needed, it must be
         * released.
         * http://msdn.microsoft.com/en-us/library/windows/hardware/ff554559(v=vs.85).aspx
         *
         * We might have to release the MDL here.
         */
        return OvsCompleteIrpRequest(irp, (ULONG_PTR)replyLen, status);
    }
}
Example #12
0
/*
 * --------------------------------------------------------------------------
 * OvsFullCopyNBL --
 *
 *    Copy the NBL to a new NBL including data.
 *
 * Notes:
 *     The NBL can have multiple NBs, but the final result is one NBL.
 * --------------------------------------------------------------------------
 */
PNET_BUFFER_LIST
OvsFullCopyNBL(PVOID ovsContext,
               PNET_BUFFER_LIST nbl,
               UINT32 headRoom,
               BOOLEAN copyNblInfo)
{
    POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext;
    POVS_NBL_POOL ovsPool = &context->ovsPool;
    PNET_BUFFER_LIST newNbl;
    PNET_BUFFER nb, newNb, firstNb = NULL, prevNb = NULL;
    POVS_BUFFER_CONTEXT dstCtx, srcCtx;
    PMDL mdl;
    NDIS_STATUS status;
    UINT32 size, totalSize;
    ULONG copiedSize;
    UINT16 flags;
    PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO dstInfo;

    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);

    if (NET_BUFFER_NEXT_NB(nb) == NULL) {
        return OvsCopySinglePacketNBL(context, nbl, nb, headRoom, copyNblInfo);
    }

    newNbl = NdisAllocateNetBufferList(ovsPool->nblOnlyPool,
                                       (UINT16)sizeof (OVS_BUFFER_CONTEXT),
                                       (UINT16)OVS_DEFAULT_NBL_CONTEXT_FILL);
    if (newNbl == NULL) {
        return NULL;
    }

    while (nb) {
        size = NET_BUFFER_DATA_LENGTH(nb);
        totalSize = MEM_ALIGN_SIZE(size + headRoom);
        mdl = OvsAllocateMDLAndData(ovsPool->ndisHandle, totalSize);

        if (mdl == NULL) {
            goto nblcopy_error;
        }
        newNb = NdisAllocateNetBuffer(ovsPool->nbPool, mdl, totalSize, 0);
        if (newNb == NULL) {
            OvsFreeMDLAndData(mdl);
            goto nblcopy_error;
        }
        if (firstNb == NULL) {
            firstNb = newNb;
        } else {
            NET_BUFFER_NEXT_NB(prevNb) = newNb;
        }
        prevNb = newNb;
#ifdef DBG
        InterlockedIncrement((LONG volatile *)&ovsPool->nbCount);
#endif
        status = NdisRetreatNetBufferDataStart(newNb, size, 0, NULL);
        ASSERT(status == NDIS_STATUS_SUCCESS);

        status = NdisCopyFromNetBufferToNetBuffer(newNb, 0, size, nb, 0,
                                                  &copiedSize);
        if (status != NDIS_STATUS_SUCCESS || size != copiedSize) {
            goto nblcopy_error;
        }

        nb = NET_BUFFER_NEXT_NB(nb);
    }

    NET_BUFFER_LIST_FIRST_NB(newNbl) = firstNb;

    newNbl->SourceHandle = ovsPool->ndisHandle;
    status = context->NdisSwitchHandlers.
         AllocateNetBufferListForwardingContext(ovsPool->ndisContext, newNbl);

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

    status = OvsCopyNBLInfo(nbl, newNbl, srcCtx, 0, copyNblInfo);
    if (status != NDIS_STATUS_SUCCESS) {
        goto nblcopy_error;
    }

    dstInfo = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl);
    dstInfo->IsPacketDataSafe = TRUE;

    dstCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(newNbl);

    flags = srcCtx->flags & (OVS_BUFFER_RECV_BUFFER | OVS_BUFFER_SEND_BUFFER);

    flags |= OVS_BUFFER_PRIVATE_MDL | OVS_BUFFER_PRIVATE_DATA |
             OVS_BUFFER_PRIVATE_NET_BUFFER | OVS_BUFFER_FROM_NBL_ONLY_POOL |
             OVS_BUFFER_PRIVATE_FORWARD_CONTEXT;

    OvsInitNBLContext(dstCtx, flags, NET_BUFFER_DATA_LENGTH(firstNb),
                      OVS_DEFAULT_PORT_NO);

#ifdef DBG
    OvsDumpNetBufferList(nbl);
    OvsDumpForwardingDetails(nbl);
    InterlockedIncrement((LONG volatile *)&ovsPool->nblOnlyCount);
#endif
    OVS_LOG_LOUD("newNbl: %p", newNbl);
    return newNbl;

nblcopy_error:
    while (firstNb) {
#ifdef DBG
        InterlockedDecrement((LONG volatile *)&ovsPool->nbCount);
#endif
        prevNb = firstNb;
        firstNb = NET_BUFFER_NEXT_NB(prevNb);
        mdl = NET_BUFFER_FIRST_MDL(prevNb);
        NET_BUFFER_FIRST_MDL(prevNb) = NULL;
        NdisFreeNetBuffer(prevNb);
        OvsFreeMDLAndData(mdl);
    }
    NdisFreeNetBufferList(newNbl);
    OVS_LOG_ERROR("OvsFullCopyNBL failed");
    return NULL;
}
Example #13
0
/*
 * --------------------------------------------------------------------------
 * OvsPartialCopyNBL --
 *
 *    Partial copy NBL, if there is multiple NB in NBL, each one will be
 *    copied. We also reserve headroom for the new NBL.
 *
 *    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.
 * --------------------------------------------------------------------------
 */
PNET_BUFFER_LIST
OvsPartialCopyNBL(PVOID ovsContext,
                  PNET_BUFFER_LIST nbl,
                  UINT32 copySize,
                  UINT32 headRoom,
                  BOOLEAN copyNblInfo)
{
    PNET_BUFFER_LIST newNbl;
    POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext;
    NDIS_STATUS status;
    PNET_BUFFER srcNb, dstNb;
    ULONG byteCopied;
    POVS_NBL_POOL ovsPool = &context->ovsPool;
    POVS_BUFFER_CONTEXT srcCtx, dstCtx;
    UINT16 flags;

    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;
    }

    if (copySize) {
        NdisAdvanceNetBufferListDataStart(nbl, copySize, FALSE, NULL);
    }
    newNbl = NdisAllocateCloneNetBufferList(nbl, ovsPool->nblOnlyPool,
                                            NULL, 0);
    if (copySize) {
        status = NdisRetreatNetBufferListDataStart(nbl, copySize, 0,
                                                   NULL, NULL);
        ASSERT(status == NDIS_STATUS_SUCCESS);
    }

    if (newNbl == NULL) {
        return NULL;
    }

    /*
     * Allocate private memory for copy
     */
    if (copySize + headRoom) {
        status = NdisRetreatNetBufferListDataStart(newNbl, copySize + headRoom,
                                                   0, NULL, NULL);
        if (status != NDIS_STATUS_SUCCESS) {
            goto retreat_error;
        }

        if (headRoom) {
            NdisAdvanceNetBufferListDataStart(newNbl, headRoom, FALSE, NULL);
        }
        if (copySize) {
            srcNb = NET_BUFFER_LIST_FIRST_NB(nbl);
            dstNb = NET_BUFFER_LIST_FIRST_NB(newNbl);

            while (srcNb) {
                status = NdisCopyFromNetBufferToNetBuffer(dstNb, 0, copySize,
                                                          srcNb, 0,
                                                          &byteCopied);
                if (status != NDIS_STATUS_SUCCESS || copySize != byteCopied) {
                    goto nbl_context_error;
                }
                srcNb = NET_BUFFER_NEXT_NB(srcNb);
                dstNb = NET_BUFFER_NEXT_NB(dstNb);
            }
        }
    }

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

    status = OvsCopyNBLInfo(nbl, newNbl, srcCtx, copySize, copyNblInfo);
    if (status != NDIS_STATUS_SUCCESS) {
        goto copy_list_info_error;
    }

#ifdef DBG
    InterlockedIncrement((LONG volatile *)&ovsPool->nblOnlyCount);
#endif

    newNbl->ParentNetBufferList = nbl;

    dstCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(newNbl);
    ASSERT(dstCtx != NULL);

    flags = srcCtx->flags & (OVS_BUFFER_RECV_BUFFER | OVS_BUFFER_SEND_BUFFER);

    flags |= OVS_BUFFER_FROM_NBL_ONLY_POOL | OVS_BUFFER_PRIVATE_CONTEXT |
             OVS_BUFFER_PRIVATE_FORWARD_CONTEXT;

    srcNb = NET_BUFFER_LIST_FIRST_NB(nbl);
    OvsInitNBLContext(dstCtx, flags, NET_BUFFER_DATA_LENGTH(srcNb) - copySize,
                      OVS_DEFAULT_PORT_NO);

    InterlockedIncrement((LONG volatile *)&srcCtx->refCount);
#ifdef DBG
    OvsDumpNetBufferList(nbl);
    OvsDumpForwardingDetails(nbl);

    OvsDumpNetBufferList(newNbl);
    OvsDumpForwardingDetails(newNbl);
#endif
    OVS_LOG_LOUD("Partial Copy new NBL: %p", newNbl);
    return newNbl;

copy_list_info_error:
    OvsFreeNBLContext(context, newNbl);
nbl_context_error:
    if (copySize) {
        NdisAdvanceNetBufferListDataStart(newNbl, copySize, TRUE, NULL);
    }
retreat_error:
    NdisFreeCloneNetBufferList(newNbl, 0);
    return NULL;
}
Example #14
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;
}