[ovs-dev] [PATCH v4] datapath-windows Event read handler

Alin Serdean aserdean at cloudbasesolutions.com
Sat Sep 27 11:57:51 UTC 2014


Acked-by: Alin Gabriel Serdean <aserdean at cloudbasesolutions.com>



-----Mesaj original-----
De la: dev [mailto:dev-bounces at openvswitch.org] În numele Eitan Eliahu
Trimis: Saturday, September 27, 2014 11:39 AM
Către: dev at openvswitch.org
Subiect: [ovs-dev] [PATCH v4] datapath-windows Event read handler

The Read event handler is executed when user mode issues a socket receive on an MC socket associated with the event queue. A new IOCTL READ command is used to differentiate between transaction based and packet miss sockets.
An entry for the handler will be added once the Control family (logically should have been added to the Vport family) implementation checked in.
User mode code for setting the socket type will follow

Signed-off-by: Eitan Eliahu <eliahue at vmware.com>
Acked-by: Ankur Sharma <ankursharma at vmware.com>
Acked-by: Nithin Raju <nithin at vmware.com>
---
 datapath-windows/include/OvsDpInterfaceExt.h |  13 ++-
 datapath-windows/ovsext/Datapath.c           | 158 +++++++++++++++++++++++++++
 datapath-windows/ovsext/Event.c              |  42 +++++++
 datapath-windows/ovsext/Event.h              |   2 +
 4 files changed, 213 insertions(+), 2 deletions(-)

diff --git a/datapath-windows/include/OvsDpInterfaceExt.h b/datapath-windows/include/OvsDpInterfaceExt.h
index 72b2e8e..e1c186f 100644
--- a/datapath-windows/include/OvsDpInterfaceExt.h
+++ b/datapath-windows/include/OvsDpInterfaceExt.h
@@ -34,11 +34,17 @@
 #define OVS_IOCTL_READ \
     CTL_CODE (OVS_IOCTL_DEVICE_TYPE, OVS_IOCTL_START + 0x0, METHOD_OUT_DIRECT,\
               FILE_READ_ACCESS)
+#define OVS_IOCTL_READ_EVENT \
+    CTL_CODE (OVS_IOCTL_DEVICE_TYPE, OVS_IOCTL_START + 0x1, METHOD_OUT_DIRECT, \
+              FILE_READ_ACCESS)
+#define OVS_IOCTL_READ_PACKET \
+    CTL_CODE (OVS_IOCTL_DEVICE_TYPE, OVS_IOCTL_START + 0x2, METHOD_OUT_DIRECT, \
+              FILE_READ_ACCESS)
 #define OVS_IOCTL_WRITE \
-    CTL_CODE (OVS_IOCTL_DEVICE_TYPE, OVS_IOCTL_START + 0x1, METHOD_IN_DIRECT,\
+    CTL_CODE (OVS_IOCTL_DEVICE_TYPE, OVS_IOCTL_START + 0x3, 
+ METHOD_IN_DIRECT,\
               FILE_READ_ACCESS)
 #define OVS_IOCTL_TRANSACT \
-    CTL_CODE (OVS_IOCTL_DEVICE_TYPE, OVS_IOCTL_START + 0x2, METHOD_OUT_DIRECT,\
+    CTL_CODE (OVS_IOCTL_DEVICE_TYPE, OVS_IOCTL_START + 0x4, 
+ METHOD_OUT_DIRECT,\
               FILE_WRITE_ACCESS)
 
 /*
@@ -72,6 +78,9 @@ enum ovs_win_control_cmd {
     OVS_CTRL_CMD_WIN_GET_PID,
     OVS_CTRL_CMD_WIN_PEND_REQ,
     OVS_CTRL_CMD_MC_SUBSCRIBE_REQ,
+
+    /* This command is logically belong to the Vport family */
+    OVS_CTRL_CMD_EVENT_NOTIFY
 };
 
 /* NL Attributes for joining/unjoining an MC group */ diff --git a/datapath-windows/ovsext/Datapath.c b/datapath-windows/ovsext/Datapath.c
index 2091777..5c9eb62 100644
--- a/datapath-windows/ovsext/Datapath.c
+++ b/datapath-windows/ovsext/Datapath.c
@@ -93,6 +93,7 @@ typedef struct _NETLINK_FAMILY {
 #define OVS_READ_DEV_OP          (1 << 0)
 #define OVS_WRITE_DEV_OP         (1 << 1)
 #define OVS_TRANSACTION_DEV_OP   (1 << 2)
+#define OVS_READ_EVENT_DEV_OP    (1 << 3)
 
 /* Handlers for the various netlink commands. */  static NetlinkCmdHandler OvsGetPidCmdHandler, @@ -100,6 +101,7 @@ static NetlinkCmdHandler OvsGetPidCmdHandler,
                          OvsPendEventCmdHandler,
                          OvsSubscribeEventCmdHandler,
                          OvsSetDpCmdHandler,
+                         OvsReadEventCmdHandler,
                          OvsGetVportCmdHandler;
 
 static NTSTATUS HandleGetDpTransaction(POVS_USER_PARAMS_CONTEXT usrParamsCtx, @@ -132,6 +134,11 @@ NETLINK_CMD nlControlFamilyCmdOps[] = {
       .handler = OvsSubscribeEventCmdHandler,
       .supportedDevOp = OVS_WRITE_DEV_OP,
       .validateDpIndex = TRUE,
+    },
+    { .cmd = OVS_CTRL_CMD_EVENT_NOTIFY,
+      .handler = OvsReadEventCmdHandler,
+      .supportedDevOp = OVS_READ_EVENT_DEV_OP,
+      .validateDpIndex = FALSE,
     }
 };
 
@@ -629,6 +636,29 @@ OvsDeviceControl(PDEVICE_OBJECT deviceObject,
         devOp = OVS_TRANSACTION_DEV_OP;
         break;
 
+    case OVS_IOCTL_READ_EVENT:
+        /* This IOCTL is used to read events */
+        if (outputBufferLen != 0) {
+            status = MapIrpOutputBuffer(irp, outputBufferLen,
+                                        sizeof *ovsMsg, &outputBuffer);
+            if (status != STATUS_SUCCESS) {
+                goto done;
+            }
+            ASSERT(outputBuffer);
+        } else {
+            status = STATUS_NDIS_INVALID_LENGTH;
+            goto done;
+        }
+        inputBuffer = NULL;
+        inputBufferLen = 0;
+
+        ovsMsg = &ovsMsgReadOp;
+        ovsMsg->nlMsg.nlmsgType = OVS_WIN_NL_CTRL_FAMILY_ID;
+        /* An "artificial" command so we can use NL family function table*/
+        ovsMsg->genlMsg.cmd = OVS_CTRL_CMD_EVENT_NOTIFY;
+        devOp = OVS_READ_DEV_OP;
+        break;
+
     case OVS_IOCTL_READ:
         /* Output buffer is mandatory. */
         if (outputBufferLen != 0) {
@@ -934,6 +964,7 @@ OvsPendEventCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
     return status;
 }
 
+
 /*
  * --------------------------------------------------------------------------
  *  Handler for the subscription for the event queue @@ -1566,4 +1597,131 @@ MapIrpOutputBuffer(PIRP irp,
     return STATUS_SUCCESS;
 }
 
+/*
+ * 
+-----------------------------------------------------------------------
+---
+ * Utility function to fill up information about the state of a port in 
+a reply
+ * to* userspace.
+ * Assumes that 'gOvsCtrlLock' lock is acquired.
+ * 
+-----------------------------------------------------------------------
+---
+ */
+static NTSTATUS
+OvsPortFillInfo(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
+                POVS_EVENT_ENTRY eventEntry,
+                PNL_BUFFER nlBuf)
+{
+    NTSTATUS status;
+    BOOLEAN rc;
+    OVS_MESSAGE msgOutTmp;
+    PNL_MSG_HDR nlMsg;
+    POVS_VPORT_ENTRY vport;
+
+    ASSERT(NlBufAt(nlBuf, 0, 0) != 0 && nlBuf->bufRemLen >= sizeof 
+ msgOutTmp);
+
+    msgOutTmp.nlMsg.nlmsgType = OVS_WIN_NL_VPORT_FAMILY_ID;
+    msgOutTmp.nlMsg.nlmsgFlags = 0;  /* XXX: ? */
+
+    /* driver intiated messages should have zerp seq number*/
+    msgOutTmp.nlMsg.nlmsgSeq = 0;
+    msgOutTmp.nlMsg.nlmsgPid = usrParamsCtx->ovsInstance->pid;
+
+    msgOutTmp.genlMsg.version = nlVportFamilyOps.version;
+    msgOutTmp.genlMsg.reserved = 0;
+
+    /* we don't have netdev yet, treat link up/down a adding/removing a port*/
+    if (eventEntry->status & (OVS_EVENT_LINK_UP | OVS_EVENT_CONNECT)) {
+        msgOutTmp.genlMsg.cmd = OVS_VPORT_CMD_NEW;
+    } else if (eventEntry->status &
+             (OVS_EVENT_LINK_DOWN | OVS_EVENT_DISCONNECT)) {
+        msgOutTmp.genlMsg.cmd = OVS_VPORT_CMD_DEL;
+    } else {
+        ASSERT(FALSE);
+        return STATUS_UNSUCCESSFUL;
+    }
+    msgOutTmp.ovsHdr.dp_ifindex = gOvsSwitchContext->dpNo;
+
+    rc = NlMsgPutHead(nlBuf, (PCHAR)&msgOutTmp, sizeof msgOutTmp);
+    if (!rc) {
+        status = STATUS_INVALID_BUFFER_SIZE;
+        goto cleanup;
+    }
+
+    vport = OvsFindVportByPortNo(gOvsSwitchContext, eventEntry->portNo);
+    if (!vport) {
+        status = STATUS_DEVICE_DOES_NOT_EXIST;
+        goto cleanup;
+    }
+
+    rc = NlMsgPutTailU32(nlBuf, OVS_VPORT_ATTR_PORT_NO, eventEntry->portNo) ||
+         NlMsgPutTailU32(nlBuf, OVS_VPORT_ATTR_TYPE, vport->ovsType) ||
+         NlMsgPutTailString(nlBuf, OVS_VPORT_ATTR_NAME, vport->ovsName);
+    if (!rc) {
+        status = STATUS_INVALID_BUFFER_SIZE;
+        goto cleanup;
+    }
+
+    /* XXXX Should we add the port stats attributes?*/
+    nlMsg = (PNL_MSG_HDR)NlBufAt(nlBuf, 0, 0);
+    nlMsg->nlmsgLen = NlBufSize(nlBuf);
+    status = STATUS_SUCCESS;
+
+cleanup:
+    return status;
+}
+
+
+/*
+ * 
+-----------------------------------------------------------------------
+---
+ * Handler for reading events from the driver event queue. This handler 
+is
+ * executed when user modes issues a socket receive on a socket 
+assocaited
+ * with the MC group for events.
+ * XXX user mode should read multiple events in one system call
+ * 
+-----------------------------------------------------------------------
+---
+ */
+static NTSTATUS
+OvsReadEventCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
+                       UINT32 *replyLen) { #ifdef DBG
+    POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;
+    POVS_OPEN_INSTANCE instance =
+        (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance;
+#endif
+    NL_BUFFER nlBuf;
+    NTSTATUS status;
+    OVS_EVENT_ENTRY eventEntry;
+
+    ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP);
+
+    /* Should never read events with a dump socket */
+    ASSERT(instance->dumpState.ovsMsg == NULL);
+
+    /* Must have an event queue */
+    ASSERT(instance->eventQueue != NULL);
+
+    /* Output buffer has been validated while validating read dev op. */
+    ASSERT(msgOut != NULL && usrParamsCtx->outputLength >= sizeof 
+ *msgOut);
+
+    NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, 
+ usrParamsCtx->outputLength);
+
+    OvsAcquireCtrlLock();
+    if (!gOvsSwitchContext) {
+        status = STATUS_SUCCESS;
+        goto cleanup;
+    }
+
+    /* remove an event entry from the event queue */
+    status = OvsRemoveEventEntry(usrParamsCtx->ovsInstance, &eventEntry);
+    if (status != STATUS_SUCCESS) {
+        goto cleanup;
+    }
+
+    status = OvsPortFillInfo(usrParamsCtx, &eventEntry, &nlBuf);
+    if (status == NDIS_STATUS_SUCCESS) {
+        *replyLen = NlBufSize(&nlBuf);
+    }
+
+cleanup:
+    OvsReleaseCtrlLock();
+    return status;
+}
 #endif /* OVS_USE_NL_INTERFACE */
diff --git a/datapath-windows/ovsext/Event.c b/datapath-windows/ovsext/Event.c index fec3485..467771d 100644
--- a/datapath-windows/ovsext/Event.c
+++ b/datapath-windows/ovsext/Event.c
@@ -292,6 +292,7 @@ done_event_subscribe:
     return status;
 }
 
+#if defined OVS_USE_NL_INTERFACE && OVS_USE_NL_INTERFACE == 0
 /*
  * --------------------------------------------------------------------------
  * Poll event queued in the event queue. always synchronous.
@@ -376,6 +377,7 @@ event_poll_done:
     OVS_LOG_TRACE("Exit: numEventPolled: %d", numEntry);
     return STATUS_SUCCESS;
 }
+#endif /* OVS_USE_NL_INTERFACE */
 
 
 /*
@@ -494,3 +496,43 @@ OvsWaitEventIoctl(PIRP irp,
     OVS_LOG_TRACE("Exit: return status: %#x", status);
     return status;
 }
+
+/*
+ 
+*----------------------------------------------------------------------
+----
+ * Poll event queued in the event queue.always synchronous.
+ *
+ * Results:
+ *     STATUS_SUCCESS event was dequeued
+ *     STATUS_UNSUCCESSFUL the queue is empty.
+ * 
+-----------------------------------------------------------------------
+---
+ */
+NTSTATUS
+OvsRemoveEventEntry(POVS_OPEN_INSTANCE instance,
+                    POVS_EVENT_ENTRY entry) {
+    NTSTATUS status = STATUS_UNSUCCESSFUL;
+    POVS_EVENT_QUEUE queue;
+    POVS_EVENT_QUEUE_ELEM elem;
+
+    OvsAcquireEventQueueLock();
+
+    queue = (POVS_EVENT_QUEUE)instance->eventQueue;
+
+    if (queue == NULL) {
+        ASSERT(queue);
+        goto remove_event_done;
+    }
+
+    if (queue->numElems) {
+        elem = (POVS_EVENT_QUEUE_ELEM)RemoveHeadList(&queue->elemList);
+        entry->portNo = elem->portNo;
+        entry->status = elem->status;
+        OvsFreeMemory(elem);
+        queue->numElems--;
+        status = STATUS_SUCCESS;
+    }
+
+remove_event_done:
+    OvsReleaseEventQueueLock();
+    return status;
+}
diff --git a/datapath-windows/ovsext/Event.h b/datapath-windows/ovsext/Event.h index f4801b9..a43a0bb 100644
--- a/datapath-windows/ovsext/Event.h
+++ b/datapath-windows/ovsext/Event.h
@@ -47,4 +47,6 @@ NTSTATUS OvsPollEventIoctl(PFILE_OBJECT fileObject, PVOID inputBuffer,
                            UINT32 outputLength, UINT32 *replyLen);  NTSTATUS OvsWaitEventIoctl(PIRP irp, PFILE_OBJECT fileObject,
                            PVOID inputBuffer, UINT32 inputLength);
+NTSTATUS OvsRemoveEventEntry(PVOID instance, POVS_EVENT_ENTRY entry);
+
 #endif /* __EVENT_H_ */
--
1.9.4.msysgit.0

_______________________________________________
dev mailing list
dev at openvswitch.org
http://openvswitch.org/mailman/listinfo/dev



More information about the dev mailing list