/* * -------------------------------------------------------------------------- * 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; }
/* * -------------------------------------------------------------------------- * OvsInitBufferPool -- * * Allocate NBL and NB pool * * XXX: more optimization may be done for buffer management include local cache * of NBL, NB, data, context, MDL. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsInitBufferPool(PVOID ovsContext) { POVS_NBL_POOL ovsPool; POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext; NET_BUFFER_LIST_POOL_PARAMETERS nblParam; NET_BUFFER_POOL_PARAMETERS nbParam; C_ASSERT(MEMORY_ALLOCATION_ALIGNMENT >= 8); OVS_LOG_TRACE("Enter: context: %p", context); ovsPool = &context->ovsPool; RtlZeroMemory(ovsPool, sizeof (OVS_NBL_POOL)); ovsPool->ndisHandle = context->NdisFilterHandle; ovsPool->ndisContext = context->NdisSwitchContext; /* * fix size NBL pool includes * NBL + NB + MDL + DATA + Context * This is mainly used for Packet execute or slow path when copy is * required and size is less than OVS_DEFAULT_DATA_SIZE. We expect * Most of packet from user space will use this Pool. (This is * true for all bfd and cfm packet. */ RtlZeroMemory(&nblParam, sizeof (nblParam)); OVS_INIT_OBJECT_HEADER(&nblParam.Header, NDIS_OBJECT_TYPE_DEFAULT, NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1, NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1); nblParam.ContextSize = OVS_DEFAULT_NBL_CONTEXT_SIZE; nblParam.PoolTag = OVS_FIX_SIZE_NBL_POOL_TAG; nblParam.fAllocateNetBuffer = TRUE; nblParam.DataSize = OVS_DEFAULT_DATA_SIZE + OVS_DEFAULT_HEADROOM_SIZE; ovsPool->fixSizePool = NdisAllocateNetBufferListPool(context->NdisSwitchContext, &nblParam); if (ovsPool->fixSizePool == NULL) { goto pool_cleanup; } /* * Zero Size NBL Pool includes * NBL + NB + Context * This is mainly for packet with large data Size, in this case MDL and * Data will be allocate separately. */ RtlZeroMemory(&nblParam, sizeof (nblParam)); OVS_INIT_OBJECT_HEADER(&nblParam.Header, NDIS_OBJECT_TYPE_DEFAULT, NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1, NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1); nblParam.ContextSize = OVS_DEFAULT_NBL_CONTEXT_SIZE; nblParam.PoolTag = OVS_VARIABLE_SIZE_NBL_POOL_TAG; nblParam.fAllocateNetBuffer = TRUE; nblParam.DataSize = 0; ovsPool->zeroSizePool = NdisAllocateNetBufferListPool(context->NdisSwitchContext, &nblParam); if (ovsPool->zeroSizePool == NULL) { goto pool_cleanup; } /* * NBL only pool just includes * NBL (+ context) * This is mainly used for clone and partial copy */ RtlZeroMemory(&nblParam, sizeof (nblParam)); OVS_INIT_OBJECT_HEADER(&nblParam.Header, NDIS_OBJECT_TYPE_DEFAULT, NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1, NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1); nblParam.ContextSize = OVS_DEFAULT_NBL_CONTEXT_SIZE; nblParam.PoolTag = OVS_NBL_ONLY_POOL_TAG; nblParam.fAllocateNetBuffer = FALSE; nblParam.DataSize = 0; ovsPool->nblOnlyPool = NdisAllocateNetBufferListPool(context->NdisSwitchContext, &nblParam); if (ovsPool->nblOnlyPool == NULL) { goto pool_cleanup; } /* nb Pool * NB only pool, used for copy */ OVS_INIT_OBJECT_HEADER(&nbParam.Header, NDIS_OBJECT_TYPE_DEFAULT, NET_BUFFER_POOL_PARAMETERS_REVISION_1, NDIS_SIZEOF_NET_BUFFER_POOL_PARAMETERS_REVISION_1); nbParam.PoolTag = OVS_NET_BUFFER_POOL_TAG; nbParam.DataSize = 0; ovsPool->nbPool = NdisAllocateNetBufferPool(context->NdisSwitchContext, &nbParam); if (ovsPool->nbPool == NULL) { goto pool_cleanup; } OVS_LOG_TRACE("Exit: fixSizePool: %p zeroSizePool: %p nblOnlyPool: %p" "nbPool: %p", ovsPool->fixSizePool, ovsPool->zeroSizePool, ovsPool->nblOnlyPool, ovsPool->nbPool); return NDIS_STATUS_SUCCESS; pool_cleanup: OvsCleanupBufferPool(context); OVS_LOG_TRACE("Exit: Fail to initialize ovs buffer pool"); return NDIS_STATUS_RESOURCES; }