]> git.proxmox.com Git - mirror_ovs.git/blob - datapath-windows/ovsext/Ioctl.c
datapath-windows: Rename files.
[mirror_ovs.git] / datapath-windows / ovsext / Ioctl.c
1 /*
2 * Copyright (c) 2014 VMware, Inc.
3 *
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:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17 /*
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
22 */
23 #if defined OVS_USE_NL_INTERFACE && OVS_USE_NL_INTERFACE == 0
24
25 #include "precomp.h"
26 #include "Ioctl.h"
27 #include "Jhash.h"
28 #include "Switch.h"
29 #include "Vport.h"
30 #include "Event.h"
31 #include "User.h"
32 #include "PacketIO.h"
33 #include "NetProto.h"
34 #include "Flow.h"
35 #include "User.h"
36
37 #ifdef OVS_DBG_MOD
38 #undef OVS_DBG_MOD
39 #endif
40 #define OVS_DBG_MOD OVS_DBG_DATAPATH
41 #include "Debug.h"
42
43 /* Handles to the device object for communication with userspace. */
44 NDIS_HANDLE gOvsDeviceHandle;
45 PDEVICE_OBJECT gOvsDeviceObject;
46
47 /*
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.
51 *
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.
54 */
55 UINT64 ovsUserTimestampDelta;
56 UINT64 ovsTimeIncrementPerTick;
57
58 _Dispatch_type_(IRP_MJ_CREATE)
59 _Dispatch_type_(IRP_MJ_CLOSE)
60 DRIVER_DISPATCH OvsOpenCloseDevice;
61
62 _Dispatch_type_(IRP_MJ_CLEANUP)
63 DRIVER_DISPATCH OvsCleanupDevice;
64
65 _Dispatch_type_(IRP_MJ_DEVICE_CONTROL)
66 DRIVER_DISPATCH OvsDeviceControl;
67
68 #ifdef ALLOC_PRAGMA
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
74
75
76 #define OVS_MAX_OPEN_INSTANCES 128
77
78 POVS_OPEN_INSTANCE ovsOpenInstanceArray[OVS_MAX_OPEN_INSTANCES];
79 UINT32 ovsNumberOfOpenInstances;
80 extern POVS_SWITCH_CONTEXT gOvsSwitchContext;
81
82 NDIS_SPIN_LOCK ovsCtrlLockObj;
83 NDIS_SPIN_LOCK ovsFlowLockObj;
84 PNDIS_SPIN_LOCK gOvsCtrlLock;
85 PNDIS_SPIN_LOCK ovsFlowLock;
86
87 VOID
88 OvsInitIoctl()
89 {
90 gOvsCtrlLock = &ovsCtrlLockObj;
91 ovsFlowLock = &ovsFlowLockObj;
92 NdisAllocateSpinLock(ovsFlowLock);
93 NdisAllocateSpinLock(gOvsCtrlLock);
94 }
95
96 VOID
97 OvsCleanupIoctl()
98 {
99 if (ovsFlowLock) {
100 NdisFreeSpinLock(ovsFlowLock);
101 NdisFreeSpinLock(gOvsCtrlLock);
102 gOvsCtrlLock = NULL;
103 gOvsCtrlLock = NULL;
104 }
105 }
106
107 VOID
108 OvsInit()
109 {
110 OvsInitIoctl();
111 OvsInitEventQueue();
112 OvsUserInit();
113 }
114
115 VOID
116 OvsCleanup()
117 {
118 OvsCleanupEventQueue();
119 OvsCleanupIoctl();
120 OvsUserCleanup();
121 }
122
123 VOID
124 OvsAcquireCtrlLock()
125 {
126 NdisAcquireSpinLock(gOvsCtrlLock);
127 }
128 VOID
129 OvsReleaseCtrlLock()
130 {
131 NdisReleaseSpinLock(gOvsCtrlLock);
132 }
133
134
135 /*
136 * --------------------------------------------------------------------------
137 * Creates the communication device between user and kernel, and also
138 * initializes the data associated data structures.
139 * --------------------------------------------------------------------------
140 */
141 NDIS_STATUS
142 OvsCreateDeviceObject(NDIS_HANDLE ovsExtDriverHandle)
143 {
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);
150
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;
157
158 NdisInitUnicodeString(&deviceName, OVS_NT_DEVICE_NAME);
159 NdisInitUnicodeString(&symbolicDeviceName, OVS_DOS_DEVICE_NAME);
160
161 RtlZeroMemory(&deviceAttributes, sizeof (NDIS_DEVICE_OBJECT_ATTRIBUTES));
162
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));
167
168 deviceAttributes.DeviceName = &deviceName;
169 deviceAttributes.SymbolicName = &symbolicDeviceName;
170 deviceAttributes.MajorFunctions = dispatchTable;
171 deviceAttributes.ExtensionSize = sizeof (OVS_DEVICE_EXTENSION);
172
173 status = NdisRegisterDeviceEx(ovsExtDriverHandle,
174 &deviceAttributes,
175 &gOvsDeviceObject,
176 &gOvsDeviceHandle);
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);
182
183 if (ovsExt) {
184 ovsExt->numberOpenInstance = 0;
185 }
186 } else {
187 /* Initialize the associated data structures. */
188 OvsInit();
189 }
190 OVS_LOG_TRACE("DeviceObject: %p", gOvsDeviceObject);
191 return status;
192 }
193
194
195 VOID
196 OvsDeleteDeviceObject()
197 {
198 if (gOvsDeviceHandle) {
199 #ifdef DBG
200 POVS_DEVICE_EXTENSION ovsExt = (POVS_DEVICE_EXTENSION)
201 NdisGetDeviceReservedExtension(gOvsDeviceObject);
202 if (ovsExt) {
203 ASSERT(ovsExt->numberOpenInstance == 0);
204 }
205 #endif
206
207 ASSERT(gOvsDeviceObject);
208 NdisDeregisterDeviceEx(gOvsDeviceHandle);
209 gOvsDeviceHandle = NULL;
210 gOvsDeviceObject = NULL;
211 }
212 OvsCleanup();
213 }
214
215 POVS_OPEN_INSTANCE
216 OvsGetOpenInstance(PFILE_OBJECT fileObject,
217 UINT32 dpNo)
218 {
219 POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)fileObject->FsContext;
220 ASSERT(instance);
221 ASSERT(instance->fileObject == fileObject);
222 if (gOvsSwitchContext == NULL ||
223 gOvsSwitchContext->dpNo != dpNo) {
224 return NULL;
225 }
226 return instance;
227 }
228
229
230 POVS_OPEN_INSTANCE
231 OvsFindOpenInstance(PFILE_OBJECT fileObject)
232 {
233 UINT32 i, j;
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];
239 }
240 j++;
241 }
242 }
243 return NULL;
244 }
245
246 NTSTATUS
247 OvsAddOpenInstance(PFILE_OBJECT fileObject)
248 {
249 POVS_OPEN_INSTANCE instance =
250 (POVS_OPEN_INSTANCE) OvsAllocateMemory(sizeof (OVS_OPEN_INSTANCE));
251 UINT32 i;
252
253 if (instance == NULL) {
254 return STATUS_NO_MEMORY;
255 }
256 OvsAcquireCtrlLock();
257 ASSERT(OvsFindOpenInstance(fileObject) == NULL);
258
259 if (ovsNumberOfOpenInstances >= OVS_MAX_OPEN_INSTANCES) {
260 OvsReleaseCtrlLock();
261 OvsFreeMemory(instance);
262 return STATUS_INSUFFICIENT_RESOURCES;
263 }
264 RtlZeroMemory(instance, sizeof (OVS_OPEN_INSTANCE));
265
266 for (i = 0; i < OVS_MAX_OPEN_INSTANCES; i++) {
267 if (ovsOpenInstanceArray[i] == NULL) {
268 ovsOpenInstanceArray[i] = instance;
269 instance->cookie = i;
270 break;
271 }
272 }
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;
279 }
280
281 static VOID
282 OvsCleanupOpenInstance(PFILE_OBJECT fileObject)
283 {
284 POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)fileObject->FsContext;
285 ASSERT(instance);
286 ASSERT(fileObject == instance->fileObject);
287 OvsCleanupEvent(instance);
288 OvsCleanupPacketQueue(instance);
289 }
290
291 VOID
292 OvsRemoveOpenInstance(PFILE_OBJECT fileObject)
293 {
294 POVS_OPEN_INSTANCE instance;
295 ASSERT(fileObject->FsContext);
296 instance = (POVS_OPEN_INSTANCE)fileObject->FsContext;
297 ASSERT(instance->cookie < OVS_MAX_OPEN_INSTANCES);
298
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);
307 }
308
309 NTSTATUS
310 OvsCompleteIrpRequest(PIRP irp,
311 ULONG_PTR infoPtr,
312 NTSTATUS status)
313 {
314 irp->IoStatus.Information = infoPtr;
315 irp->IoStatus.Status = status;
316 IoCompleteRequest(irp, IO_NO_INCREMENT);
317 return status;
318 }
319
320
321 NTSTATUS
322 OvsOpenCloseDevice(PDEVICE_OBJECT deviceObject,
323 PIRP irp)
324 {
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);
330
331 ASSERT(deviceObject == gOvsDeviceObject);
332 ASSERT(ovsExt != NULL);
333
334 irpSp = IoGetCurrentIrpStackLocation(irp);
335 fileObject = irpSp->FileObject;
336 OVS_LOG_TRACE("DeviceObject: %p, fileObject:%p, instance: %u",
337 deviceObject, fileObject,
338 ovsExt->numberOpenInstance);
339
340 switch (irpSp->MajorFunction) {
341 case IRP_MJ_CREATE:
342 status = OvsAddOpenInstance(fileObject);
343 if (STATUS_SUCCESS == status) {
344 InterlockedIncrement((LONG volatile *)&ovsExt->numberOpenInstance);
345 }
346 break;
347 case IRP_MJ_CLOSE:
348 ASSERT(ovsExt->numberOpenInstance > 0);
349 OvsRemoveOpenInstance(fileObject);
350 InterlockedDecrement((LONG volatile *)&ovsExt->numberOpenInstance);
351 break;
352 default:
353 ASSERT(0);
354 }
355 return OvsCompleteIrpRequest(irp, (ULONG_PTR)0, status);
356 }
357
358 _Use_decl_annotations_
359 NTSTATUS
360 OvsCleanupDevice(PDEVICE_OBJECT deviceObject,
361 PIRP irp)
362 {
363
364 PIO_STACK_LOCATION irpSp;
365 PFILE_OBJECT fileObject;
366
367 NTSTATUS status = STATUS_SUCCESS;
368 #ifdef DBG
369 POVS_DEVICE_EXTENSION ovsExt =
370 (POVS_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(deviceObject);
371 if (ovsExt) {
372 ASSERT(ovsExt->numberOpenInstance > 0);
373 }
374 #else
375 UNREFERENCED_PARAMETER(deviceObject);
376 #endif
377 ASSERT(deviceObject == gOvsDeviceObject);
378 irpSp = IoGetCurrentIrpStackLocation(irp);
379 fileObject = irpSp->FileObject;
380
381 ASSERT(irpSp->MajorFunction == IRP_MJ_CLEANUP);
382
383 OvsCleanupOpenInstance(fileObject);
384
385 return OvsCompleteIrpRequest(irp, (ULONG_PTR)0, status);
386 }
387
388 /*
389 *----------------------------------------------------------------------------
390 * OvsGetVersionIoctl --
391 *
392 * On entry None
393 * On exit Driver version
394 *
395 * Result:
396 * STATUS_SUCCESS
397 * STATUS_BUFFER_TOO_SMALL
398 *----------------------------------------------------------------------------
399 */
400 NTSTATUS
401 OvsGetVersionIoctl(PVOID outputBuffer,
402 uint32 outputLength,
403 uint32 *replyLen)
404 {
405 POVS_VERSION driverOut = (POVS_VERSION)outputBuffer;
406
407 if (outputLength < sizeof (*driverOut)) {
408 return STATUS_BUFFER_TOO_SMALL;
409 }
410 *replyLen = sizeof (*driverOut);
411 driverOut->mjrDrvVer = OVS_DRIVER_MAJOR_VER;
412 driverOut->mnrDrvVer = OVS_DRIVER_MINOR_VER;
413
414 return STATUS_SUCCESS;
415 }
416
417
418 /*
419 *----------------------------------------------------------------------------
420 * OvsDpDumpIoctl --
421 * Get All Datapath. For now, we only support one datapath.
422 *
423 * Result:
424 * STATUS_SUCCESS
425 * STATUS_BUFFER_TOO_SMALL
426 *----------------------------------------------------------------------------
427 */
428 NTSTATUS
429 OvsDpDumpIoctl(PVOID outputBuffer,
430 UINT32 outputLength,
431 UINT32 *replyLen)
432 {
433 *replyLen = sizeof (UINT32);
434 if (outputLength < sizeof (UINT32)) {
435 return STATUS_BUFFER_TOO_SMALL;
436 }
437 OvsAcquireCtrlLock();
438 if (gOvsSwitchContext) {
439 *(UINT32 *)outputBuffer = gOvsSwitchContext->dpNo;
440 } else {
441 *replyLen = 0;
442 }
443 OvsReleaseCtrlLock();
444
445 return STATUS_SUCCESS;
446 }
447
448
449 /*
450 *----------------------------------------------------------------------------
451 * OvsDpGetIoctl --
452 * Given dpNo, get all datapath info as defined in OVS_DP_INFO.
453 *
454 * Result:
455 * STATUS_SUCCESS
456 * STATUS_BUFFER_TOO_SMALL
457 * STATUS_INVALID_PARAMETER
458 *----------------------------------------------------------------------------
459 */
460 NTSTATUS
461 OvsDpGetIoctl(PVOID inputBuffer,
462 UINT32 inputLength,
463 PVOID outputBuffer,
464 UINT32 outputLength,
465 UINT32 *replyLen)
466 {
467 UINT32 dpNo;
468 POVS_DP_INFO info;
469 OVS_DATAPATH *datapath;
470
471 if (inputLength < sizeof (UINT32)) {
472 return STATUS_INVALID_PARAMETER;
473 }
474
475 if (outputLength < sizeof (OVS_DP_INFO)) {
476 *replyLen = sizeof (OVS_DP_INFO);
477 return STATUS_BUFFER_TOO_SMALL;
478 }
479
480 dpNo = *(UINT32 *)inputBuffer;
481 OvsAcquireCtrlLock();
482 if (gOvsSwitchContext == NULL ||
483 gOvsSwitchContext->dpNo != dpNo) {
484 OvsReleaseCtrlLock();
485 return STATUS_INVALID_PARAMETER;
486 }
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;
498 }
499
500 NTSTATUS
501 OvsDeviceControl(PDEVICE_OBJECT deviceObject,
502 PIRP irp)
503 {
504
505 PIO_STACK_LOCATION irpSp;
506 NTSTATUS status = STATUS_SUCCESS;
507 PFILE_OBJECT fileObject;
508 PVOID inputBuffer;
509 PVOID outputBuffer;
510 UINT32 inputBufferLen, outputBufferLen, mdlBufferLen;
511 UINT32 code, replyLen = 0;
512 #ifdef DBG
513 POVS_DEVICE_EXTENSION ovsExt =
514 (POVS_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(deviceObject);
515 ASSERT(deviceObject == gOvsDeviceObject);
516 ASSERT(ovsExt);
517 ASSERT(ovsExt->numberOpenInstance > 0);
518 #else
519 UNREFERENCED_PARAMETER(deviceObject);
520 #endif
521
522 irpSp = IoGetCurrentIrpStackLocation(irp);
523
524
525 ASSERT(irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL);
526 ASSERT(irpSp->FileObject != NULL);
527
528 fileObject = irpSp->FileObject;
529 code = irpSp->Parameters.DeviceIoControl.IoControlCode;
530 inputBufferLen = irpSp->Parameters.DeviceIoControl.InputBufferLength;
531 outputBufferLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
532 /*
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.
535 */
536 mdlBufferLen = outputBufferLen;
537 outputBuffer = inputBuffer = irp->AssociatedIrp.SystemBuffer;
538
539 switch(code) {
540 case OVS_IOCTL_VERSION_GET:
541 status = OvsGetVersionIoctl(outputBuffer, outputBufferLen,
542 &replyLen);
543 break;
544 case OVS_IOCTL_DP_DUMP:
545 status = OvsDpDumpIoctl(outputBuffer, outputBufferLen, &replyLen);
546 break;
547 case OVS_IOCTL_DP_GET:
548 if (irp->MdlAddress == NULL) {
549 status = STATUS_INVALID_PARAMETER;
550 break;
551 }
552 outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
553 NormalPagePriority);
554 if (outputBuffer == NULL) {
555 status = STATUS_INSUFFICIENT_RESOURCES;
556 } else {
557 status = OvsDpGetIoctl(inputBuffer, inputBufferLen,
558 outputBuffer, outputBufferLen, &replyLen);
559 }
560 break;
561 case OVS_IOCTL_DP_SET:
562 status = STATUS_NOT_IMPLEMENTED;
563 break;
564 case OVS_IOCTL_VPORT_DUMP:
565 if (irp->MdlAddress == NULL) {
566 status = STATUS_INVALID_PARAMETER;
567 break;
568 }
569 outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
570 NormalPagePriority);
571 if (outputBuffer) {
572 status = OvsDumpVportIoctl(inputBuffer, inputBufferLen,
573 outputBuffer, outputBufferLen,
574 &replyLen);
575 } else {
576 status = STATUS_INSUFFICIENT_RESOURCES;
577 }
578 break;
579 case OVS_IOCTL_VPORT_GET:
580 if (irp->MdlAddress == NULL) {
581 status = STATUS_INVALID_PARAMETER;
582 break;
583 }
584 outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
585 NormalPagePriority);
586 if (outputBuffer) {
587 status = OvsGetVportIoctl(inputBuffer, inputBufferLen,
588 outputBuffer, outputBufferLen,
589 &replyLen);
590 } else {
591 status = STATUS_INSUFFICIENT_RESOURCES;
592 }
593 break;
594 case OVS_IOCTL_VPORT_SET:
595 status = STATUS_NOT_IMPLEMENTED;
596 break;
597 case OVS_IOCTL_VPORT_ADD:
598 if (irp->MdlAddress == NULL) {
599 status = STATUS_INVALID_PARAMETER;
600 break;
601 }
602 outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
603 NormalPagePriority);
604 if (outputBuffer) {
605 status = OvsAddVportIoctl(inputBuffer, inputBufferLen,
606 outputBuffer, outputBufferLen,
607 &replyLen);
608 } else {
609 status = STATUS_INSUFFICIENT_RESOURCES;
610 }
611 break;
612 case OVS_IOCTL_VPORT_DEL:
613 status = OvsDelVportIoctl(inputBuffer, inputBufferLen,
614 &replyLen);
615 break;
616 case OVS_IOCTL_VPORT_EXT_INFO:
617 if (irp->MdlAddress == NULL) {
618 status = STATUS_INVALID_PARAMETER;
619 break;
620 }
621 outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
622 NormalPagePriority);
623 if (outputBuffer) {
624 status = OvsGetExtInfoIoctl(inputBuffer, inputBufferLen,
625 outputBuffer, outputBufferLen,
626 &replyLen);
627 } else {
628 OVS_LOG_INFO("ExtInfo: fail to get outputBuffer address");
629 status = STATUS_INSUFFICIENT_RESOURCES;
630 }
631 break;
632 case OVS_IOCTL_FLOW_DUMP:
633 if (irp->MdlAddress == NULL) {
634 status = STATUS_INVALID_PARAMETER;
635 break;
636 }
637 outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
638 NormalPagePriority);
639 if (outputBuffer) {
640 status = OvsDumpFlowIoctl(inputBuffer, inputBufferLen,
641 outputBuffer, outputBufferLen,
642 &replyLen);
643 } else {
644 status = STATUS_INSUFFICIENT_RESOURCES;
645 }
646 break;
647 case OVS_IOCTL_FLOW_GET:
648 if (irp->MdlAddress == NULL) {
649 status = STATUS_INVALID_PARAMETER;
650 break;
651 }
652 outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
653 NormalPagePriority);
654 if (outputBuffer) {
655 status = OvsGetFlowIoctl(inputBuffer, inputBufferLen,
656 outputBuffer, outputBufferLen,
657 &replyLen);
658 } else {
659 status = STATUS_INSUFFICIENT_RESOURCES;
660 }
661 break;
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,
669 &replyLen);
670 break;
671 case OVS_IOCTL_FLOW_FLUSH:
672 status = OvsFlushFlowIoctl(inputBuffer, inputBufferLen);
673 break;
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;
678 break;
679 case OVS_IOCTL_DATAPATH_SUBSCRIBE:
680 status = OvsSubscribeDpIoctl(fileObject, inputBuffer,
681 inputBufferLen);
682 break;
683 case OVS_IOCTL_DATAPATH_READ:
684 if (irp->MdlAddress == NULL) {
685 status = STATUS_INVALID_PARAMETER;
686 break;
687 }
688 outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
689 NormalPagePriority);
690 if (outputBuffer) {
691 status = OvsReadDpIoctl(fileObject, outputBuffer,
692 outputBufferLen, &replyLen);
693 } else {
694 status = STATUS_INSUFFICIENT_RESOURCES;
695 }
696 break;
697 case OVS_IOCTL_DATAPATH_OPERATE:
698 status = STATUS_NOT_IMPLEMENTED;
699 break;
700 case OVS_IOCTL_DATAPATH_EXECUTE:
701 // XXX: need to make the input direct
702 status = OvsExecuteDpIoctl(inputBuffer, inputBufferLen,
703 outputBufferLen);
704 break;
705 case OVS_IOCTL_DATAPATH_PURGE:
706 status = OvsPurgeDpIoctl(fileObject);
707 break;
708 case OVS_IOCTL_DATAPATH_WAIT:
709 status = OvsWaitDpIoctl(irp, fileObject);
710 break;
711 case OVS_IOCTL_EVENT_SUBSCRIBE:
712 status = OvsSubscribeEventIoctl(fileObject, inputBuffer,
713 inputBufferLen);
714 break;
715 case OVS_IOCTL_EVENT_POLL:
716 if (irp->MdlAddress == NULL) {
717 status = STATUS_INVALID_PARAMETER;
718 break;
719 }
720 outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
721 NormalPagePriority);
722 if (outputBuffer == NULL) {
723 status = STATUS_INSUFFICIENT_RESOURCES;
724 } else {
725 status = OvsPollEventIoctl(fileObject, inputBuffer,
726 inputBufferLen, outputBuffer,
727 outputBufferLen, &replyLen);
728 }
729 break;
730 case OVS_IOCTL_EVENT_WAIT:
731 status = OvsWaitEventIoctl(irp, fileObject,
732 inputBuffer, inputBufferLen);
733 break;
734 case OVS_IOCTL_DP_TIMESTAMP_SET:
735 if (inputBufferLen != sizeof (ovsUserTimestampDelta)) {
736 status = STATUS_INFO_LENGTH_MISMATCH;
737 } else {
738 int64 currentUserTS = *(int64 *)inputBuffer;
739 LARGE_INTEGER tickCount;
740
741 /* So many ticks since system booted. */
742 KeQueryTickCount(&tickCount);
743 ovsUserTimestampDelta = currentUserTS -
744 (tickCount.QuadPart * ovsTimeIncrementPerTick);
745 status = STATUS_SUCCESS;
746 }
747 break;
748 default:
749 status = STATUS_INVALID_DEVICE_REQUEST;
750 break;
751 }
752
753 if (status == STATUS_PENDING) {
754 return status;
755 } else {
756 /*
757 * When the system-address-space mapping that is returned by
758 * MmGetSystemAddressForMdlSafe is no longer needed, it must be
759 * released.
760 * http://msdn.microsoft.com/en-us/library/windows/hardware/ff554559(v=vs.85).aspx
761 *
762 * We might have to release the MDL here.
763 */
764 return OvsCompleteIrpRequest(irp, (ULONG_PTR)replyLen, status);
765 }
766 }
767
768 #endif /* OVS_USE_NL_INTERFACE */