[ovs-dev] [PATCH] Windows NetLink Socket - Support for asynchronous event notification

Eitan Eliahu eliahue at vmware.com
Mon Sep 8 13:58:23 UTC 2014


Thanks Sam!
Eitan

-----Original Message-----
From: Samuel Ghinet [mailto:sghinet at cloudbasesolutions.com] 
Sent: Saturday, September 06, 2014 6:03 PM
To: dev at openvswitch.org; Eitan Eliahu
Cc: Alin Serdean
Subject: [ovs-dev] [PATCH] Windows NetLink Socket - Support for asynchronous event notification

Looks good, as far as I can tell.

One minor style thing though:
> +            goto done;
> +        }
> +    }
> +    else {
> +        /* The I/O was completed synchronously */
> +        poll_immediate_wake();
> +    }
I think it should have been:
> } else {

Regards,
Sam
________________________________________

Date: Thu,  4 Sep 2014 03:18:13 -0700
From: Eitan Eliahu <eliahue at vmware.com>
To: dev at openvswitch.org
Subject: [ovs-dev] [PATCH] Windows NetLink Socket - Support for
        asynchronous    event notification
Message-ID: <1409825893-3280-1-git-send-email-eliahue at vmware.com>

We keep an outstanding, out of band, I/O request in the driver at all time.
Once an event generated the driver queues the event message, completes the pending I/O and unblocks the calling thread through setting the event in the overlapped structure n the  NL socket. The thread will read all all event messages synchronous through the call of nl_sock_recv()
---
 datapath-windows/include/OvsDpInterfaceExt.h |  1 +
 lib/netlink-socket.c                         | 82 ++++++++++++++++++++++++++--
 2 files changed, 79 insertions(+), 4 deletions(-)

diff --git a/datapath-windows/include/OvsDpInterfaceExt.h b/datapath-windows/include/OvsDpInterfaceExt.h
index 73dfcbe..ab2088a 100644
--- a/datapath-windows/include/OvsDpInterfaceExt.h
+++ b/datapath-windows/include/OvsDpInterfaceExt.h
@@ -70,6 +70,7 @@
 /* Commands available under the OVS_WIN_CONTROL_FAMILY. */  enum ovs_win_control_cmd {
     OVS_CTRL_CMD_WIN_GET_PID,
+    OVS_CTRL_CMD_WIN_PEND_REQ
 };

 #endif /* __OVS_DP_INTERFACE_EXT_H_ */
diff --git a/lib/netlink-socket.c b/lib/netlink-socket.c index a6be186..4b535f0 100644
--- a/lib/netlink-socket.c
+++ b/lib/netlink-socket.c
@@ -80,6 +80,7 @@ static int get_sock_pid_from_kernel(struct nl_sock *sock);  struct nl_sock {  #ifdef _WIN32
     HANDLE handle;
+    OVERLAPPED overlapped;
 #else
     int fd;
 #endif
@@ -139,21 +140,30 @@ nl_sock_create(int protocol, struct nl_sock **sockp)
     sock = xmalloc(sizeof *sock);

 #ifdef _WIN32
-    sock->handle = CreateFileA("\\\\.\\OpenVSwitchDevice",
+    sock->handle = CreateFile(TEXT("\\\\.\\OpenVSwitchDevice"),
                                GENERIC_READ | GENERIC_WRITE,
                                FILE_SHARE_READ | FILE_SHARE_WRITE,
                                NULL, OPEN_EXISTING,
-                               FILE_ATTRIBUTE_NORMAL, NULL);
-
-    int last_error = GetLastError();
+                               FILE_FLAG_OVERLAPPED, NULL);

     if (sock->handle == INVALID_HANDLE_VALUE) {
+        int last_error = GetLastError();
+        VLOG_ERR("fcntl: %s", ovs_strerror(last_error));
+        goto error;
+    }
+
+    memset(&sock->overlapped, 0, sizeof sock->overlapped);
+    sock->overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (sock->overlapped.hEvent == NULL) {
+        int last_error = GetLastError();
         VLOG_ERR("fcntl: %s", ovs_strerror(last_error));
         goto error;
     }
+
 #else
     sock->fd = socket(AF_NETLINK, SOCK_RAW, protocol);
     if (sock->fd < 0) {
+        int last_error = GetLastError();
         VLOG_ERR("fcntl: %s", ovs_strerror(errno));
         goto error;
     }
@@ -221,6 +231,9 @@ error:
         }
     }
 #ifdef _WIN32
+    if (sock->overlapped.hEvent) {
+        CloseHandle(sock->overlapped.hEvent);
+    }
     if (sock->handle != INVALID_HANDLE_VALUE) {
         CloseHandle(sock->handle);
     }
@@ -248,6 +261,9 @@ nl_sock_destroy(struct nl_sock *sock)  {
     if (sock) {
 #ifdef _WIN32
+        if (sock->overlapped.hEvent) {
+            CloseHandle(sock->overlapped.hEvent);
+        }
         CloseHandle(sock->handle);
 #else
         close(sock->fd);
@@ -1040,12 +1056,70 @@ nl_dump_done(struct nl_dump *dump)
     return status == EOF ? 0 : status;
 }

+#ifdef _WIN32
+/* Pend an I/O request in the driver. The driver completes the I/O 
+whenever
+* an event or a packet is ready to be read. Once the I/O is completed
+* the overlapped structure event assocaited with the pending I/O will 
+be set */ static int pend_io_request(const struct nl_sock *sock) {
+    struct ofpbuf request;
+    uint64_t request_stub[128];
+    struct ovs_header *ovs_header;
+    struct nlmsghdr *nlmsg;
+    uint32_t seq;
+    int retval;
+    int error;
+    DWORD bytes;
+    OVERLAPPED *overlapped = &sock->overlapped;
+
+    int ovs_msg_size = sizeof (struct nlmsghdr) + sizeof (struct genlmsghdr) +
+                               sizeof (struct ovs_header);
+
+    ofpbuf_use_stub(&request, request_stub, sizeof request_stub);
+
+    seq = nl_sock_allocate_seq(sock, 1);
+    nl_msg_put_genlmsghdr(&request, 0, OVS_WIN_NL_CTRL_FAMILY_ID, 0,
+                          OVS_CTRL_CMD_WIN_PEND_REQ, OVS_WIN_CONTROL_VERSION);
+    nlmsg = nl_msg_nlmsghdr(&request);
+    nlmsg->nlmsg_seq = seq;
+
+    ovs_header = ofpbuf_put_uninit(&request, sizeof *ovs_header);
+    ovs_header->dp_ifindex = 0;
+
+    if (!DeviceIoControl(sock->handle, OVS_IOCTL_WRITE,
+        ofpbuf_data(&request), ofpbuf_size(&request),
+        NULL, 0, &bytes, overlapped)) {
+        error = GetLastError();
+        /* Check if the I/O got pended */
+        if (error != ERROR_IO_INCOMPLETE && error != ERROR_IO_PENDING) {
+            VLOG_ERR("nl_sock_wait failed - %s\n", ovs_format_message(error));
+            retval = EINVAL;
+            goto done;
+        }
+    }
+    else {
+        /* The I/O was completed synchronously */
+        poll_immediate_wake();
+    }
+    retval = 0;
+
+done:
+    ofpbuf_uninit(&request);
+    return retval;
+}
+#endif  /* _WIN32 */
+
 /* Causes poll_block() to wake up when any of the specified 'events' (which is
  * a OR'd combination of POLLIN, POLLOUT, etc.) occur on 'sock'. */  void  nl_sock_wait(const struct nl_sock *sock, short int events)  {  #ifdef _WIN32
+    if (sock->overlapped.Internal != STATUS_PENDING) {
+        pend_io_request(sock);
+    }
     poll_fd_wait(sock->handle, events);  #else
     poll_fd_wait(sock->fd, events);
--
1.9.4.msysgit.0



------------------------------

Subject: Digest Footer

_______________________________________________
dev mailing list
dev at openvswitch.org
https://urldefense.proofpoint.com/v1/url?u=http://openvswitch.org/mailman/listinfo/dev&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=yTvML8OxA42Jb6ViHe7fUXbvPVOYDPVq87w43doxtlY%3D%0A&m=AgyAoJdlQ3RjvFB0AGfc96MMElM1dsMmFu3wHE1sRVk%3D%0A&s=11705c06638d89d6ade8dcfd306fc28bcaaf05631f779584e56ae5edff801302


------------------------------

End of dev Digest, Vol 62, Issue 47
***********************************



More information about the dev mailing list