2 * Copyright (c) 2014 VMware, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * XXX: OVS_USE_NL_INTERFACE is being used to keep the legacy DPIF interface
19 * alive while we transition over to the netlink based interface.
20 * OVS_USE_NL_INTERFACE = 0 => legacy inteface to use with dpif-windows.c
21 * OVS_USE_NL_INTERFACE = 1 => netlink inteface to use with ported dpif-linux.c
23 #if defined OVS_USE_NL_INTERFACE && OVS_USE_NL_INTERFACE == 0
40 #define OVS_DBG_MOD OVS_DBG_DATAPATH
43 /* Handles to the device object for communication with userspace. */
44 NDIS_HANDLE gOvsDeviceHandle
;
45 PDEVICE_OBJECT gOvsDeviceObject
;
48 * There seems to be a skew between the kernel's version of current time and
49 * the userspace's version of current time. The skew was seen to
50 * monotonically increase as well.
52 * In order to deal with the situation, we pass down the userspace's version
53 * of the timestamp to the kernel, and let the kernel calculate the delta.
55 UINT64 ovsUserTimestampDelta
;
56 UINT64 ovsTimeIncrementPerTick
;
58 _Dispatch_type_(IRP_MJ_CREATE
)
59 _Dispatch_type_(IRP_MJ_CLOSE
)
60 DRIVER_DISPATCH OvsOpenCloseDevice
;
62 _Dispatch_type_(IRP_MJ_CLEANUP
)
63 DRIVER_DISPATCH OvsCleanupDevice
;
65 _Dispatch_type_(IRP_MJ_DEVICE_CONTROL
)
66 DRIVER_DISPATCH OvsDeviceControl
;
69 #pragma alloc_text(INIT, OvsCreateDeviceObject)
70 #pragma alloc_text(PAGE, OvsOpenCloseDevice)
71 #pragma alloc_text(PAGE, OvsCleanupDevice)
72 #pragma alloc_text(PAGE, OvsDeviceControl)
73 #endif // ALLOC_PRAGMA
76 #define OVS_MAX_OPEN_INSTANCES 128
78 POVS_OPEN_INSTANCE ovsOpenInstanceArray
[OVS_MAX_OPEN_INSTANCES
];
79 UINT32 ovsNumberOfOpenInstances
;
80 extern POVS_SWITCH_CONTEXT gOvsSwitchContext
;
82 NDIS_SPIN_LOCK ovsCtrlLockObj
;
83 NDIS_SPIN_LOCK ovsFlowLockObj
;
84 PNDIS_SPIN_LOCK gOvsCtrlLock
;
85 PNDIS_SPIN_LOCK ovsFlowLock
;
90 gOvsCtrlLock
= &ovsCtrlLockObj
;
91 ovsFlowLock
= &ovsFlowLockObj
;
92 NdisAllocateSpinLock(ovsFlowLock
);
93 NdisAllocateSpinLock(gOvsCtrlLock
);
100 NdisFreeSpinLock(ovsFlowLock
);
101 NdisFreeSpinLock(gOvsCtrlLock
);
118 OvsCleanupEventQueue();
126 NdisAcquireSpinLock(gOvsCtrlLock
);
131 NdisReleaseSpinLock(gOvsCtrlLock
);
136 * --------------------------------------------------------------------------
137 * Creates the communication device between user and kernel, and also
138 * initializes the data associated data structures.
139 * --------------------------------------------------------------------------
142 OvsCreateDeviceObject(NDIS_HANDLE ovsExtDriverHandle
)
144 NDIS_STATUS status
= NDIS_STATUS_SUCCESS
;
145 UNICODE_STRING deviceName
;
146 UNICODE_STRING symbolicDeviceName
;
147 PDRIVER_DISPATCH dispatchTable
[IRP_MJ_MAXIMUM_FUNCTION
+1];
148 NDIS_DEVICE_OBJECT_ATTRIBUTES deviceAttributes
;
149 OVS_LOG_TRACE("ovsExtDriverHandle: %p", ovsExtDriverHandle
);
151 RtlZeroMemory(dispatchTable
,
152 (IRP_MJ_MAXIMUM_FUNCTION
+ 1) * sizeof (PDRIVER_DISPATCH
));
153 dispatchTable
[IRP_MJ_CREATE
] = OvsOpenCloseDevice
;
154 dispatchTable
[IRP_MJ_CLOSE
] = OvsOpenCloseDevice
;
155 dispatchTable
[IRP_MJ_CLEANUP
] = OvsCleanupDevice
;
156 dispatchTable
[IRP_MJ_DEVICE_CONTROL
] = OvsDeviceControl
;
158 NdisInitUnicodeString(&deviceName
, OVS_NT_DEVICE_NAME
);
159 NdisInitUnicodeString(&symbolicDeviceName
, OVS_DOS_DEVICE_NAME
);
161 RtlZeroMemory(&deviceAttributes
, sizeof (NDIS_DEVICE_OBJECT_ATTRIBUTES
));
163 OVS_INIT_OBJECT_HEADER(&deviceAttributes
.Header
,
164 NDIS_OBJECT_TYPE_DEVICE_OBJECT_ATTRIBUTES
,
165 NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1
,
166 sizeof (NDIS_DEVICE_OBJECT_ATTRIBUTES
));
168 deviceAttributes
.DeviceName
= &deviceName
;
169 deviceAttributes
.SymbolicName
= &symbolicDeviceName
;
170 deviceAttributes
.MajorFunctions
= dispatchTable
;
171 deviceAttributes
.ExtensionSize
= sizeof (OVS_DEVICE_EXTENSION
);
173 status
= NdisRegisterDeviceEx(ovsExtDriverHandle
,
177 if (status
!= NDIS_STATUS_SUCCESS
) {
178 POVS_DEVICE_EXTENSION ovsExt
=
179 (POVS_DEVICE_EXTENSION
)NdisGetDeviceReservedExtension(gOvsDeviceObject
);
180 ASSERT(gOvsDeviceObject
!= NULL
);
181 ASSERT(gOvsDeviceHandle
!= NULL
);
184 ovsExt
->numberOpenInstance
= 0;
187 /* Initialize the associated data structures. */
190 OVS_LOG_TRACE("DeviceObject: %p", gOvsDeviceObject
);
196 OvsDeleteDeviceObject()
198 if (gOvsDeviceHandle
) {
200 POVS_DEVICE_EXTENSION ovsExt
= (POVS_DEVICE_EXTENSION
)
201 NdisGetDeviceReservedExtension(gOvsDeviceObject
);
203 ASSERT(ovsExt
->numberOpenInstance
== 0);
207 ASSERT(gOvsDeviceObject
);
208 NdisDeregisterDeviceEx(gOvsDeviceHandle
);
209 gOvsDeviceHandle
= NULL
;
210 gOvsDeviceObject
= NULL
;
216 OvsGetOpenInstance(PFILE_OBJECT fileObject
,
219 POVS_OPEN_INSTANCE instance
= (POVS_OPEN_INSTANCE
)fileObject
->FsContext
;
221 ASSERT(instance
->fileObject
== fileObject
);
222 if (gOvsSwitchContext
== NULL
||
223 gOvsSwitchContext
->dpNo
!= dpNo
) {
231 OvsFindOpenInstance(PFILE_OBJECT fileObject
)
234 for (i
= 0, j
= 0; i
< OVS_MAX_OPEN_INSTANCES
&&
235 j
< ovsNumberOfOpenInstances
; i
++) {
236 if (ovsOpenInstanceArray
[i
]) {
237 if (ovsOpenInstanceArray
[i
]->fileObject
== fileObject
) {
238 return ovsOpenInstanceArray
[i
];
247 OvsAddOpenInstance(PFILE_OBJECT fileObject
)
249 POVS_OPEN_INSTANCE instance
=
250 (POVS_OPEN_INSTANCE
) OvsAllocateMemory(sizeof (OVS_OPEN_INSTANCE
));
253 if (instance
== NULL
) {
254 return STATUS_NO_MEMORY
;
256 OvsAcquireCtrlLock();
257 ASSERT(OvsFindOpenInstance(fileObject
) == NULL
);
259 if (ovsNumberOfOpenInstances
>= OVS_MAX_OPEN_INSTANCES
) {
260 OvsReleaseCtrlLock();
261 OvsFreeMemory(instance
);
262 return STATUS_INSUFFICIENT_RESOURCES
;
264 RtlZeroMemory(instance
, sizeof (OVS_OPEN_INSTANCE
));
266 for (i
= 0; i
< OVS_MAX_OPEN_INSTANCES
; i
++) {
267 if (ovsOpenInstanceArray
[i
] == NULL
) {
268 ovsOpenInstanceArray
[i
] = instance
;
269 instance
->cookie
= i
;
273 ASSERT(i
< OVS_MAX_OPEN_INSTANCES
);
274 instance
->fileObject
= fileObject
;
275 ASSERT(fileObject
->FsContext
== NULL
);
276 fileObject
->FsContext
= instance
;
277 OvsReleaseCtrlLock();
278 return STATUS_SUCCESS
;
282 OvsCleanupOpenInstance(PFILE_OBJECT fileObject
)
284 POVS_OPEN_INSTANCE instance
= (POVS_OPEN_INSTANCE
)fileObject
->FsContext
;
286 ASSERT(fileObject
== instance
->fileObject
);
287 OvsCleanupEvent(instance
);
288 OvsCleanupPacketQueue(instance
);
292 OvsRemoveOpenInstance(PFILE_OBJECT fileObject
)
294 POVS_OPEN_INSTANCE instance
;
295 ASSERT(fileObject
->FsContext
);
296 instance
= (POVS_OPEN_INSTANCE
)fileObject
->FsContext
;
297 ASSERT(instance
->cookie
< OVS_MAX_OPEN_INSTANCES
);
299 OvsAcquireCtrlLock();
300 fileObject
->FsContext
= NULL
;
301 ASSERT(ovsOpenInstanceArray
[instance
->cookie
] == instance
);
302 ovsOpenInstanceArray
[instance
->cookie
] = NULL
;
303 OvsReleaseCtrlLock();
304 ASSERT(instance
->eventQueue
== NULL
);
305 ASSERT (instance
->packetQueue
== NULL
);
306 OvsFreeMemory(instance
);
310 OvsCompleteIrpRequest(PIRP irp
,
314 irp
->IoStatus
.Information
= infoPtr
;
315 irp
->IoStatus
.Status
= status
;
316 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
322 OvsOpenCloseDevice(PDEVICE_OBJECT deviceObject
,
325 PIO_STACK_LOCATION irpSp
;
326 NTSTATUS status
= STATUS_SUCCESS
;
327 PFILE_OBJECT fileObject
;
328 POVS_DEVICE_EXTENSION ovsExt
=
329 (POVS_DEVICE_EXTENSION
)NdisGetDeviceReservedExtension(deviceObject
);
331 ASSERT(deviceObject
== gOvsDeviceObject
);
332 ASSERT(ovsExt
!= NULL
);
334 irpSp
= IoGetCurrentIrpStackLocation(irp
);
335 fileObject
= irpSp
->FileObject
;
336 OVS_LOG_TRACE("DeviceObject: %p, fileObject:%p, instance: %u",
337 deviceObject
, fileObject
,
338 ovsExt
->numberOpenInstance
);
340 switch (irpSp
->MajorFunction
) {
342 status
= OvsAddOpenInstance(fileObject
);
343 if (STATUS_SUCCESS
== status
) {
344 InterlockedIncrement((LONG
volatile *)&ovsExt
->numberOpenInstance
);
348 ASSERT(ovsExt
->numberOpenInstance
> 0);
349 OvsRemoveOpenInstance(fileObject
);
350 InterlockedDecrement((LONG
volatile *)&ovsExt
->numberOpenInstance
);
355 return OvsCompleteIrpRequest(irp
, (ULONG_PTR
)0, status
);
358 _Use_decl_annotations_
360 OvsCleanupDevice(PDEVICE_OBJECT deviceObject
,
364 PIO_STACK_LOCATION irpSp
;
365 PFILE_OBJECT fileObject
;
367 NTSTATUS status
= STATUS_SUCCESS
;
369 POVS_DEVICE_EXTENSION ovsExt
=
370 (POVS_DEVICE_EXTENSION
)NdisGetDeviceReservedExtension(deviceObject
);
372 ASSERT(ovsExt
->numberOpenInstance
> 0);
375 UNREFERENCED_PARAMETER(deviceObject
);
377 ASSERT(deviceObject
== gOvsDeviceObject
);
378 irpSp
= IoGetCurrentIrpStackLocation(irp
);
379 fileObject
= irpSp
->FileObject
;
381 ASSERT(irpSp
->MajorFunction
== IRP_MJ_CLEANUP
);
383 OvsCleanupOpenInstance(fileObject
);
385 return OvsCompleteIrpRequest(irp
, (ULONG_PTR
)0, status
);
389 *----------------------------------------------------------------------------
390 * OvsGetVersionIoctl --
393 * On exit Driver version
397 * STATUS_BUFFER_TOO_SMALL
398 *----------------------------------------------------------------------------
401 OvsGetVersionIoctl(PVOID outputBuffer
,
405 POVS_VERSION driverOut
= (POVS_VERSION
)outputBuffer
;
407 if (outputLength
< sizeof (*driverOut
)) {
408 return STATUS_BUFFER_TOO_SMALL
;
410 *replyLen
= sizeof (*driverOut
);
411 driverOut
->mjrDrvVer
= OVS_DRIVER_MAJOR_VER
;
412 driverOut
->mnrDrvVer
= OVS_DRIVER_MINOR_VER
;
414 return STATUS_SUCCESS
;
419 *----------------------------------------------------------------------------
421 * Get All Datapath. For now, we only support one datapath.
425 * STATUS_BUFFER_TOO_SMALL
426 *----------------------------------------------------------------------------
429 OvsDpDumpIoctl(PVOID outputBuffer
,
433 *replyLen
= sizeof (UINT32
);
434 if (outputLength
< sizeof (UINT32
)) {
435 return STATUS_BUFFER_TOO_SMALL
;
437 OvsAcquireCtrlLock();
438 if (gOvsSwitchContext
) {
439 *(UINT32
*)outputBuffer
= gOvsSwitchContext
->dpNo
;
443 OvsReleaseCtrlLock();
445 return STATUS_SUCCESS
;
450 *----------------------------------------------------------------------------
452 * Given dpNo, get all datapath info as defined in OVS_DP_INFO.
456 * STATUS_BUFFER_TOO_SMALL
457 * STATUS_INVALID_PARAMETER
458 *----------------------------------------------------------------------------
461 OvsDpGetIoctl(PVOID inputBuffer
,
469 OVS_DATAPATH
*datapath
;
471 if (inputLength
< sizeof (UINT32
)) {
472 return STATUS_INVALID_PARAMETER
;
475 if (outputLength
< sizeof (OVS_DP_INFO
)) {
476 *replyLen
= sizeof (OVS_DP_INFO
);
477 return STATUS_BUFFER_TOO_SMALL
;
480 dpNo
= *(UINT32
*)inputBuffer
;
481 OvsAcquireCtrlLock();
482 if (gOvsSwitchContext
== NULL
||
483 gOvsSwitchContext
->dpNo
!= dpNo
) {
484 OvsReleaseCtrlLock();
485 return STATUS_INVALID_PARAMETER
;
487 *replyLen
= sizeof (OVS_DP_INFO
);
488 RtlZeroMemory(outputBuffer
, sizeof (OVS_DP_INFO
));
489 info
= (POVS_DP_INFO
)outputBuffer
;
490 RtlCopyMemory(info
->name
, "ovs-system", sizeof ("ovs-system"));
491 datapath
= &gOvsSwitchContext
->datapath
;
492 info
->nMissed
= datapath
->misses
;
493 info
->nHit
= datapath
->hits
;
494 info
->nLost
= datapath
->lost
;
495 info
->nFlows
= datapath
->nFlows
;
496 OvsReleaseCtrlLock();
497 return STATUS_SUCCESS
;
501 OvsDeviceControl(PDEVICE_OBJECT deviceObject
,
505 PIO_STACK_LOCATION irpSp
;
506 NTSTATUS status
= STATUS_SUCCESS
;
507 PFILE_OBJECT fileObject
;
510 UINT32 inputBufferLen
, outputBufferLen
, mdlBufferLen
;
511 UINT32 code
, replyLen
= 0;
513 POVS_DEVICE_EXTENSION ovsExt
=
514 (POVS_DEVICE_EXTENSION
)NdisGetDeviceReservedExtension(deviceObject
);
515 ASSERT(deviceObject
== gOvsDeviceObject
);
517 ASSERT(ovsExt
->numberOpenInstance
> 0);
519 UNREFERENCED_PARAMETER(deviceObject
);
522 irpSp
= IoGetCurrentIrpStackLocation(irp
);
525 ASSERT(irpSp
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
);
526 ASSERT(irpSp
->FileObject
!= NULL
);
528 fileObject
= irpSp
->FileObject
;
529 code
= irpSp
->Parameters
.DeviceIoControl
.IoControlCode
;
530 inputBufferLen
= irpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
531 outputBufferLen
= irpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
533 * In case of an IRP with METHOD_IN_DIRECT or METHOD_OUT_DIRECT, the size
534 * of the MDL is stored in Parameters.DeviceIoControl.OutputBufferLength.
536 mdlBufferLen
= outputBufferLen
;
537 outputBuffer
= inputBuffer
= irp
->AssociatedIrp
.SystemBuffer
;
540 case OVS_IOCTL_VERSION_GET
:
541 status
= OvsGetVersionIoctl(outputBuffer
, outputBufferLen
,
544 case OVS_IOCTL_DP_DUMP
:
545 status
= OvsDpDumpIoctl(outputBuffer
, outputBufferLen
, &replyLen
);
547 case OVS_IOCTL_DP_GET
:
548 if (irp
->MdlAddress
== NULL
) {
549 status
= STATUS_INVALID_PARAMETER
;
552 outputBuffer
= MmGetSystemAddressForMdlSafe(irp
->MdlAddress
,
554 if (outputBuffer
== NULL
) {
555 status
= STATUS_INSUFFICIENT_RESOURCES
;
557 status
= OvsDpGetIoctl(inputBuffer
, inputBufferLen
,
558 outputBuffer
, outputBufferLen
, &replyLen
);
561 case OVS_IOCTL_DP_SET
:
562 status
= STATUS_NOT_IMPLEMENTED
;
564 case OVS_IOCTL_VPORT_DUMP
:
565 if (irp
->MdlAddress
== NULL
) {
566 status
= STATUS_INVALID_PARAMETER
;
569 outputBuffer
= MmGetSystemAddressForMdlSafe(irp
->MdlAddress
,
572 status
= OvsDumpVportIoctl(inputBuffer
, inputBufferLen
,
573 outputBuffer
, outputBufferLen
,
576 status
= STATUS_INSUFFICIENT_RESOURCES
;
579 case OVS_IOCTL_VPORT_GET
:
580 if (irp
->MdlAddress
== NULL
) {
581 status
= STATUS_INVALID_PARAMETER
;
584 outputBuffer
= MmGetSystemAddressForMdlSafe(irp
->MdlAddress
,
587 status
= OvsGetVportIoctl(inputBuffer
, inputBufferLen
,
588 outputBuffer
, outputBufferLen
,
591 status
= STATUS_INSUFFICIENT_RESOURCES
;
594 case OVS_IOCTL_VPORT_SET
:
595 status
= STATUS_NOT_IMPLEMENTED
;
597 case OVS_IOCTL_VPORT_ADD
:
598 if (irp
->MdlAddress
== NULL
) {
599 status
= STATUS_INVALID_PARAMETER
;
602 outputBuffer
= MmGetSystemAddressForMdlSafe(irp
->MdlAddress
,
605 status
= OvsAddVportIoctl(inputBuffer
, inputBufferLen
,
606 outputBuffer
, outputBufferLen
,
609 status
= STATUS_INSUFFICIENT_RESOURCES
;
612 case OVS_IOCTL_VPORT_DEL
:
613 status
= OvsDelVportIoctl(inputBuffer
, inputBufferLen
,
616 case OVS_IOCTL_VPORT_EXT_INFO
:
617 if (irp
->MdlAddress
== NULL
) {
618 status
= STATUS_INVALID_PARAMETER
;
621 outputBuffer
= MmGetSystemAddressForMdlSafe(irp
->MdlAddress
,
624 status
= OvsGetExtInfoIoctl(inputBuffer
, inputBufferLen
,
625 outputBuffer
, outputBufferLen
,
628 OVS_LOG_INFO("ExtInfo: fail to get outputBuffer address");
629 status
= STATUS_INSUFFICIENT_RESOURCES
;
632 case OVS_IOCTL_FLOW_DUMP
:
633 if (irp
->MdlAddress
== NULL
) {
634 status
= STATUS_INVALID_PARAMETER
;
637 outputBuffer
= MmGetSystemAddressForMdlSafe(irp
->MdlAddress
,
640 status
= OvsDumpFlowIoctl(inputBuffer
, inputBufferLen
,
641 outputBuffer
, outputBufferLen
,
644 status
= STATUS_INSUFFICIENT_RESOURCES
;
647 case OVS_IOCTL_FLOW_GET
:
648 if (irp
->MdlAddress
== NULL
) {
649 status
= STATUS_INVALID_PARAMETER
;
652 outputBuffer
= MmGetSystemAddressForMdlSafe(irp
->MdlAddress
,
655 status
= OvsGetFlowIoctl(inputBuffer
, inputBufferLen
,
656 outputBuffer
, outputBufferLen
,
659 status
= STATUS_INSUFFICIENT_RESOURCES
;
662 case OVS_IOCTL_FLOW_PUT
:
663 // XXX: This is not really working - mapping the input buffer
664 // XXX: inputBufferLen = mdlBufferLen;
665 // inputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
666 // NormalPagePriority);
667 status
= OvsPutFlowIoctl(inputBuffer
, inputBufferLen
,
668 outputBuffer
, outputBufferLen
,
671 case OVS_IOCTL_FLOW_FLUSH
:
672 status
= OvsFlushFlowIoctl(inputBuffer
, inputBufferLen
);
674 case OVS_IOCTL_QOS_QUEUE_DUMP
:
675 case OVS_IOCTL_QOS_QUEUE_GET
:
676 case OVS_IOCTL_QOS_QUEUE_SET
:
677 status
= STATUS_NOT_IMPLEMENTED
;
679 case OVS_IOCTL_DATAPATH_SUBSCRIBE
:
680 status
= OvsSubscribeDpIoctl(fileObject
, inputBuffer
,
683 case OVS_IOCTL_DATAPATH_READ
:
684 if (irp
->MdlAddress
== NULL
) {
685 status
= STATUS_INVALID_PARAMETER
;
688 outputBuffer
= MmGetSystemAddressForMdlSafe(irp
->MdlAddress
,
691 status
= OvsReadDpIoctl(fileObject
, outputBuffer
,
692 outputBufferLen
, &replyLen
);
694 status
= STATUS_INSUFFICIENT_RESOURCES
;
697 case OVS_IOCTL_DATAPATH_OPERATE
:
698 status
= STATUS_NOT_IMPLEMENTED
;
700 case OVS_IOCTL_DATAPATH_EXECUTE
:
701 // XXX: need to make the input direct
702 status
= OvsExecuteDpIoctl(inputBuffer
, inputBufferLen
,
705 case OVS_IOCTL_DATAPATH_PURGE
:
706 status
= OvsPurgeDpIoctl(fileObject
);
708 case OVS_IOCTL_DATAPATH_WAIT
:
709 status
= OvsWaitDpIoctl(irp
, fileObject
);
711 case OVS_IOCTL_EVENT_SUBSCRIBE
:
712 status
= OvsSubscribeEventIoctl(fileObject
, inputBuffer
,
715 case OVS_IOCTL_EVENT_POLL
:
716 if (irp
->MdlAddress
== NULL
) {
717 status
= STATUS_INVALID_PARAMETER
;
720 outputBuffer
= MmGetSystemAddressForMdlSafe(irp
->MdlAddress
,
722 if (outputBuffer
== NULL
) {
723 status
= STATUS_INSUFFICIENT_RESOURCES
;
725 status
= OvsPollEventIoctl(fileObject
, inputBuffer
,
726 inputBufferLen
, outputBuffer
,
727 outputBufferLen
, &replyLen
);
730 case OVS_IOCTL_EVENT_WAIT
:
731 status
= OvsWaitEventIoctl(irp
, fileObject
,
732 inputBuffer
, inputBufferLen
);
734 case OVS_IOCTL_DP_TIMESTAMP_SET
:
735 if (inputBufferLen
!= sizeof (ovsUserTimestampDelta
)) {
736 status
= STATUS_INFO_LENGTH_MISMATCH
;
738 int64 currentUserTS
= *(int64
*)inputBuffer
;
739 LARGE_INTEGER tickCount
;
741 /* So many ticks since system booted. */
742 KeQueryTickCount(&tickCount
);
743 ovsUserTimestampDelta
= currentUserTS
-
744 (tickCount
.QuadPart
* ovsTimeIncrementPerTick
);
745 status
= STATUS_SUCCESS
;
749 status
= STATUS_INVALID_DEVICE_REQUEST
;
753 if (status
== STATUS_PENDING
) {
757 * When the system-address-space mapping that is returned by
758 * MmGetSystemAddressForMdlSafe is no longer needed, it must be
760 * http://msdn.microsoft.com/en-us/library/windows/hardware/ff554559(v=vs.85).aspx
762 * We might have to release the MDL here.
764 return OvsCompleteIrpRequest(irp
, (ULONG_PTR
)replyLen
, status
);
768 #endif /* OVS_USE_NL_INTERFACE */