Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
vrouter: implement communication channels with vRouter Agent
Changes required to support Contrail on Windows: - windows/vr_devices.c - common code used to set up named pipes used to exchange data between vRouter and Agent on Windows - windows/vr_ksync.c - Windows-specific implementation of KSync messages handling, based on named pipes - windows/vr_pkt0.c - Windows-specific implementation of Pkt0 packet handling, based on named pipes - windows/vr_mem.c - code responsible for allocation of memory used for flow table - windows/vr_flow_device.c - implementation of named pipe used as file to map memory from, for flows table Other changes: - extract computing oflow table size into function Initial work: https://github.com/codilime/contrail-vrouter/commits/windows Change-Id: I366eda3d497059aa2963384598ad7ef64dc1661f Partial-Bug: #1734699
- Loading branch information
Dariusz Sosnowski
committed
Dec 1, 2017
1 parent
7e1320e
commit 5a0c693
Showing
7 changed files
with
1,155 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* | ||
* Copyright (c) 2017 Juniper Networks, Inc. All rights reserved. | ||
*/ | ||
#include "precomp.h" | ||
#include "windows_devices.h" | ||
|
||
NTSTATUS | ||
VRouterSetUpNamedDevice(NDIS_HANDLE DriverHandle, | ||
PCWSTR DeviceName, | ||
PCWSTR DeviceSymlink, | ||
PVR_DEVICE_DISPATCH_CALLBACKS Callbacks, | ||
PDEVICE_OBJECT *DeviceObject, | ||
NDIS_HANDLE *DeviceHandle) | ||
{ | ||
NTSTATUS status; | ||
UNICODE_STRING device_name; | ||
UNICODE_STRING device_symlink; | ||
|
||
status = RtlUnicodeStringInit(&device_name, DeviceName); | ||
if (!NT_SUCCESS(status)) { | ||
return status; | ||
} | ||
|
||
status = RtlUnicodeStringInit(&device_symlink, DeviceSymlink); | ||
if (!NT_SUCCESS(status)) { | ||
return status; | ||
} | ||
|
||
PDRIVER_DISPATCH dispatch_table[IRP_MJ_MAXIMUM_FUNCTION + 1]; | ||
NdisZeroMemory(dispatch_table, (IRP_MJ_MAXIMUM_FUNCTION + 1) * sizeof(PDRIVER_DISPATCH)); | ||
|
||
dispatch_table[IRP_MJ_CREATE] = Callbacks->create; | ||
dispatch_table[IRP_MJ_CLEANUP] = Callbacks->cleanup; | ||
dispatch_table[IRP_MJ_CLOSE] = Callbacks->close; | ||
dispatch_table[IRP_MJ_WRITE] = Callbacks->write; | ||
dispatch_table[IRP_MJ_READ] = Callbacks->read; | ||
dispatch_table[IRP_MJ_DEVICE_CONTROL] = Callbacks->device_control; | ||
|
||
NDIS_DEVICE_OBJECT_ATTRIBUTES attributes; | ||
NdisZeroMemory(&attributes, sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES)); | ||
|
||
attributes.Header.Type = NDIS_OBJECT_TYPE_DEVICE_OBJECT_ATTRIBUTES; | ||
attributes.Header.Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1; | ||
attributes.Header.Size = NDIS_SIZEOF_DEVICE_OBJECT_ATTRIBUTES_REVISION_1; | ||
|
||
attributes.DeviceName = &device_name; | ||
attributes.SymbolicName = &device_symlink; | ||
attributes.MajorFunctions = &dispatch_table[0]; | ||
attributes.ExtensionSize = 0; | ||
attributes.DefaultSDDLString = &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX; | ||
attributes.DeviceClassGuid = NULL; | ||
|
||
status = NdisRegisterDeviceEx(DriverHandle, &attributes, DeviceObject, DeviceHandle); | ||
if (NT_SUCCESS(status)) { | ||
(*DeviceObject)->Flags |= DO_DIRECT_IO; | ||
} | ||
|
||
return status; | ||
} | ||
|
||
VOID | ||
VRouterTearDownNamedDevice(NDIS_HANDLE *DeviceHandle) | ||
{ | ||
if (*DeviceHandle == NULL) { | ||
return; | ||
} | ||
|
||
NdisDeregisterDeviceEx(*DeviceHandle); | ||
*DeviceHandle = NULL; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
/* | ||
* Copyright (c) 2017 Juniper Networks, Inc. All rights reserved. | ||
*/ | ||
#include "precomp.h" | ||
|
||
#include "windows_devices.h" | ||
#include "windows_flow_ioctl.h" | ||
#include "windows_ksync.h" | ||
#include "windows_mem.h" | ||
|
||
static const WCHAR FlowDeviceName[] = L"\\Device\\vrouterFlow"; | ||
static const WCHAR FlowDeviceSymLink[] = L"\\DosDevices\\vrouterFlow"; | ||
|
||
static PDEVICE_OBJECT FlowDeviceObject = NULL; | ||
static NDIS_HANDLE FlowDeviceHandle = NULL; | ||
|
||
static ULONG FlowAllocationTag = 'LFRV'; | ||
|
||
static PFLOW_DEVICE_CONTEXT | ||
FlowAllocateContext() | ||
{ | ||
PFLOW_DEVICE_CONTEXT ctx; | ||
|
||
ctx = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(*ctx), FlowAllocationTag); | ||
if (ctx == NULL) | ||
return NULL; | ||
|
||
ctx->UserVirtualAddress = NULL; | ||
|
||
return ctx; | ||
} | ||
|
||
static VOID | ||
FlowFreeContext(PFLOW_DEVICE_CONTEXT ctx) | ||
{ | ||
if (ctx != NULL) { | ||
ExFreePool(ctx); | ||
} | ||
} | ||
|
||
static VOID | ||
FlowAttachContextToFileContext(PFLOW_DEVICE_CONTEXT ctx, PIRP irp) | ||
{ | ||
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(irp); | ||
PFILE_OBJECT fileObj = ioStack->FileObject; | ||
fileObj->FsContext = ctx; | ||
} | ||
|
||
static PFLOW_DEVICE_CONTEXT | ||
FlowGetContextFromFileContext(PIRP irp) | ||
{ | ||
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(irp); | ||
PFILE_OBJECT fileObj = ioStack->FileObject; | ||
return fileObj->FsContext; | ||
} | ||
|
||
static NTSTATUS | ||
FlowCompleteIrp(PIRP Irp, NTSTATUS Status, ULONG_PTR Information) | ||
{ | ||
Irp->IoStatus.Status = Status; | ||
Irp->IoStatus.Information = Information; | ||
IoCompleteRequest(Irp, IO_NO_INCREMENT); | ||
return Status; | ||
} | ||
|
||
static NTSTATUS | ||
FlowDispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp) | ||
{ | ||
PFLOW_DEVICE_CONTEXT ctx = FlowAllocateContext(); | ||
if (ctx == NULL) | ||
goto Failure; | ||
FlowAttachContextToFileContext(ctx, Irp); | ||
|
||
PMDL flowMemoryMdl = GetFlowMemoryMdl(); | ||
if (flowMemoryMdl == NULL) | ||
goto Failure; | ||
|
||
MM_PAGE_PRIORITY pagePriority = NormalPagePriority | MdlMappingNoExecute; | ||
PVOID userVirtualAddress = MmMapLockedPagesSpecifyCache(flowMemoryMdl, | ||
UserMode, | ||
MmNonCached, | ||
NULL, | ||
FALSE, | ||
pagePriority); | ||
if (userVirtualAddress == NULL) | ||
goto Failure; | ||
|
||
ctx->UserVirtualAddress = userVirtualAddress; | ||
ctx->FlowMemoryMdl = flowMemoryMdl; | ||
|
||
return FlowCompleteIrp(Irp, STATUS_SUCCESS, (ULONG_PTR)(FILE_OPENED)); | ||
|
||
Failure: | ||
if (ctx != NULL) { | ||
FlowAttachContextToFileContext(NULL, Irp); | ||
FlowFreeContext(ctx); | ||
} | ||
|
||
return FlowCompleteIrp(Irp, STATUS_INSUFFICIENT_RESOURCES, (ULONG_PTR)(0)); | ||
} | ||
|
||
static NTSTATUS | ||
FlowDispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp) | ||
{ | ||
PFLOW_DEVICE_CONTEXT ctx = FlowGetContextFromFileContext(Irp); | ||
|
||
ASSERT(ctx != NULL); | ||
ASSERT(ctx->UserVirtualAddress != NULL); | ||
ASSERT(ctx->FlowMemoryMdl != NULL); | ||
|
||
MmUnmapLockedPages(ctx->UserVirtualAddress, ctx->FlowMemoryMdl); | ||
FlowAttachContextToFileContext(NULL, Irp); | ||
FlowFreeContext(ctx); | ||
|
||
return FlowCompleteIrp(Irp, STATUS_SUCCESS, (ULONG_PTR)(0)); | ||
} | ||
|
||
static NTSTATUS | ||
FlowDispatchCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp) | ||
{ | ||
return FlowCompleteIrp(Irp, STATUS_SUCCESS, (ULONG_PTR)(0)); | ||
} | ||
|
||
static NTSTATUS | ||
FlowHandleGetAddress(PDEVICE_OBJECT DeviceObject, | ||
PIRP Irp, | ||
PFLOW_DEVICE_CONTEXT ctx) | ||
{ | ||
NTSTATUS status; | ||
|
||
PMDL bufferMdl = Irp->MdlAddress; | ||
ULONG expectedLength = sizeof(ctx->UserVirtualAddress); | ||
ULONG bufferLength = MmGetMdlByteCount(bufferMdl); | ||
if (bufferLength != expectedLength) { | ||
status = STATUS_INVALID_PARAMETER; | ||
goto Failure; | ||
} | ||
|
||
PVOID buffer = MmGetSystemAddressForMdlSafe(bufferMdl, | ||
NormalPagePriority | MdlMappingNoExecute); | ||
if (buffer == NULL) { | ||
status = STATUS_INSUFFICIENT_RESOURCES; | ||
goto Failure; | ||
} | ||
RtlCopyMemory(buffer, &ctx->UserVirtualAddress, expectedLength); | ||
|
||
return FlowCompleteIrp(Irp, STATUS_SUCCESS, expectedLength); | ||
|
||
Failure: | ||
return FlowCompleteIrp(Irp, status, (ULONG_PTR)(0)); | ||
} | ||
|
||
static NTSTATUS | ||
FlowDispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) | ||
{ | ||
PIO_STACK_LOCATION ioStack; | ||
PFLOW_DEVICE_CONTEXT ctx; | ||
PVOID buffer; | ||
|
||
ctx = FlowGetContextFromFileContext(Irp); | ||
ASSERT(ctx != NULL); | ||
|
||
ioStack = IoGetCurrentIrpStackLocation(Irp); | ||
switch (ioStack->Parameters.DeviceIoControl.IoControlCode) { | ||
case IOCTL_FLOW_GET_ADDRESS: | ||
return FlowHandleGetAddress(DeviceObject, Irp, ctx); | ||
default: | ||
return FlowCompleteIrp(Irp, STATUS_INVALID_DEVICE_REQUEST, (ULONG_PTR)(0)); | ||
} | ||
} | ||
|
||
static NTSTATUS | ||
FlowDispatchRead(PDEVICE_OBJECT DeviceObject, PIRP Irp) | ||
{ | ||
return FlowCompleteIrp(Irp, STATUS_INVALID_DEVICE_REQUEST, (ULONG_PTR)(0)); | ||
} | ||
|
||
static NTSTATUS | ||
FlowDispatchWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp) | ||
{ | ||
return FlowCompleteIrp(Irp, STATUS_INVALID_DEVICE_REQUEST, (ULONG_PTR)(0)); | ||
} | ||
|
||
NTSTATUS | ||
FlowCreateDevice(NDIS_HANDLE DriverHandle) | ||
{ | ||
VR_DEVICE_DISPATCH_CALLBACKS callbacks = { | ||
.create = FlowDispatchCreate, | ||
.cleanup = FlowDispatchCleanup, | ||
.close = FlowDispatchClose, | ||
.write = FlowDispatchWrite, | ||
.read = FlowDispatchRead, | ||
.device_control = FlowDispatchDeviceControl, | ||
}; | ||
|
||
return VRouterSetUpNamedDevice(DriverHandle, FlowDeviceName, FlowDeviceSymLink, | ||
&callbacks, &FlowDeviceObject, &FlowDeviceHandle); | ||
} | ||
|
||
VOID | ||
FlowDestroyDevice(VOID) | ||
{ | ||
VRouterTearDownNamedDevice(&FlowDeviceHandle); | ||
} |
Oops, something went wrong.