[ovs-dev] [PATCH 11/14] Changes needed for netlink-socket.c

Alin Serdean aserdean at cloudbasesolutions.com
Fri Jul 11 01:06:50 UTC 2014


Adding CreateFile, WriteFile, ReadFile and CloseHandle instead of linux
counterparts when compiling netlink-socket.c with MSVC. Also add socket pid
generation function that will later on will be needed in the kernel
extension.

Signed-off-by: Alin Gabriel Serdean <aserdean at cloudbasesolutions.com>
---
 lib/netlink-socket.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 149 insertions(+)

diff --git a/lib/netlink-socket.c b/lib/netlink-socket.c
index 8fd3933..a320895 100644
--- a/lib/netlink-socket.c
+++ b/lib/netlink-socket.c
@@ -71,6 +71,36 @@ struct nl_sock {
  * of iovecs on the stack. */
 #define MAX_IOVS 128
 
+#if _WIN32
+static uint32_t g_last_portid = 0;
+
+//port ids must be unique!
+static uint32_t portid_next()
+{
+    g_last_portid++;
+    return g_last_portid;
+}
+
+static void set_sock_pid_in_kernel(HANDLE hFile, UINT32 pid)
+{
+    typedef struct _ovs_message_set_pid {
+        struct nlmsghdr;
+    }ovs_message_set_pid;
+
+    ovs_message_set_pid msg = { 0 };
+
+    msg.nlmsg_len = sizeof(ovs_message_set_pid);
+    msg.nlmsg_type = 80; //target = set file pid
+    msg.nlmsg_flags = 0;
+    msg.nlmsg_seq = 0;
+    msg.nlmsg_pid = pid;
+
+    WriteFile(hFile, &msg, sizeof(ovs_message_set_pid), NULL, NULL);
+    Sleep(50);
+}
+
+#endif
+
 /* Maximum number of iovecs that may be passed to sendmsg, capped at a
  * minimum of _XOPEN_IOV_MAX (16) and a maximum of MAX_IOVS.
  *
@@ -114,15 +144,25 @@ nl_sock_create(int protocol, struct nl_sock **sockp)
     *sockp = NULL;
     sock = xmalloc(sizeof *sock);
 
+#ifdef _WIN32
+    HANDLE hConn = CreateFileA("\\\\.\\OpenVSwitchDevice",
+                               GENERIC_READ | GENERIC_WRITE,
+                               FILE_SHARE_READ | FILE_SHARE_WRITE,
+                               NULL, OPEN_EXISTING,
+                               FILE_ATTRIBUTE_NORMAL, NULL);
+    sock->fd = hConn;
+#else
     sock->fd = socket(AF_NETLINK, SOCK_RAW, protocol);
     if (sock->fd < 0) {
         VLOG_ERR("fcntl: %s", ovs_strerror(errno));
         goto error;
     }
+#endif
     sock->protocol = protocol;
     sock->next_seq = 1;
 
     rcvbuf = 1024 * 1024;
+#ifndef _WIN32
     if (setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUFFORCE,
                    &rcvbuf, sizeof rcvbuf)) {
         /* Only root can use SO_RCVBUFFORCE.  Everyone else gets EPERM.
@@ -139,16 +179,24 @@ nl_sock_create(int protocol, struct nl_sock **sockp)
         goto error;
     }
     sock->rcvbuf = retval;
+#else
+    sock->rcvbuf = rcvbuf;
+#endif
 
+#ifndef _WIN32
     /* Connect to kernel (pid 0) as remote address. */
     memset(&remote, 0, sizeof remote);
     remote.nl_family = AF_NETLINK;
     remote.nl_pid = 0;
     if (connect(sock->fd, (struct sockaddr *) &remote, sizeof remote) < 0) {
+#else
+    if (sock->fd == INVALID_HANDLE_VALUE) {
+#endif
         VLOG_ERR("connect(0): %s", ovs_strerror(errno));
         goto error;
     }
 
+#ifndef _WIN32
     /* Obtain pid assigned by kernel. */
     local_size = sizeof local;
     if (getsockname(sock->fd, (struct sockaddr *) &local, &local_size) < 0) {
@@ -161,6 +209,10 @@ nl_sock_create(int protocol, struct nl_sock **sockp)
         goto error;
     }
     sock->pid = local.nl_pid;
+#else
+    sock->pid = portid_next();
+    set_sock_pid_in_kernel((HANDLE)sock->fd, sock->pid);
+#endif
 
     *sockp = sock;
     return 0;
@@ -173,7 +225,11 @@ error:
         }
     }
     if (sock->fd >= 0) {
+#ifndef _WIN32
         close(sock->fd);
+#else
+        CloseHandle((HANDLE)sock->fd);
+#endif
     }
     free(sock);
     return retval;
@@ -193,7 +249,11 @@ void
 nl_sock_destroy(struct nl_sock *sock)
 {
     if (sock) {
+#ifndef _WIN32
         close(sock->fd);
+#else
+        CloseHandle((HANDLE)sock->fd);
+#endif
         free(sock);
     }
 }
@@ -212,12 +272,37 @@ nl_sock_destroy(struct nl_sock *sock)
 int
 nl_sock_join_mcgroup(struct nl_sock *sock, unsigned int multicast_group)
 {
+#ifndef _WIN32
     if (setsockopt(sock->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
                    &multicast_group, sizeof multicast_group) < 0) {
         VLOG_WARN("could not join multicast group %u (%s)",
                   multicast_group, ovs_strerror(errno));
         return errno;
     }
+#else
+    typedef struct _ovs_message_multicast {
+        struct nlmsghdr;
+
+        //if true, join; if else, leave
+        unsigned char join;
+        unsigned int groupId;
+    }ovs_message_multicast;
+
+    ovs_message_multicast msg = { 0 };
+
+    msg.nlmsg_len = sizeof(ovs_message_multicast);
+    msg.nlmsg_type = 33;
+    msg.nlmsg_flags = 0;
+    msg.nlmsg_seq = 0;
+    msg.nlmsg_pid = sock->pid;
+
+    msg.join = 1;
+    msg.groupId = multicast_group;
+
+
+    WriteFile((HANDLE)sock->fd, &msg, sizeof(ovs_message_multicast),
+              NULL, NULL);
+#endif
     return 0;
 }
 
@@ -234,12 +319,28 @@ nl_sock_join_mcgroup(struct nl_sock *sock, unsigned int multicast_group)
 int
 nl_sock_leave_mcgroup(struct nl_sock *sock, unsigned int multicast_group)
 {
+#ifndef _WIN32
     if (setsockopt(sock->fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
                    &multicast_group, sizeof multicast_group) < 0) {
         VLOG_WARN("could not leave multicast group %u (%s)",
                   multicast_group, ovs_strerror(errno));
         return errno;
     }
+#else
+    typedef struct _ovs_message_multicast {
+        struct nlmsghdr;
+
+        //if true, join; if else, leave
+        unsigned char join;
+    }ovs_message_multicast;
+
+    ovs_message_multicast msg = { 0 };
+    nl_msg_put_nlmsghdr(&msg, sizeof(ovs_message_multicast), multicast_group, 
+                        0);
+    msg.join = 0;
+
+    nl_sock_transact(sock, &msg, NULL);
+#endif
     return 0;
 }
 
@@ -255,7 +356,19 @@ nl_sock_send__(struct nl_sock *sock, const struct ofpbuf *msg,
     nlmsg->nlmsg_pid = sock->pid;
     do {
         int retval;
+#ifndef _WIN32
         retval = send(sock->fd, ofpbuf_data(msg), ofpbuf_size(msg), wait ? 0 : MSG_DONTWAIT);
+#else
+        WSAOVERLAPPED RecvOverlapped;
+        SecureZeroMemory((PVOID)& RecvOverlapped, sizeof (WSAOVERLAPPED));
+        RecvOverlapped.hEvent = WSACreateEvent();
+        if (RecvOverlapped.hEvent == NULL) {
+            LPOVERLAPPED
+                retval = -1;
+        }
+        retval = WriteFile((HANDLE)sock->fd, ofpbuf_data(msg), ofpbuf_size(msg),
+                           NULL, NULL);
+#endif
         error = retval < 0 ? errno : 0;
     } while (error == EINTR);
     log_nlmsg(__func__, error, ofpbuf_data(msg), ofpbuf_size(msg), sock->protocol);
@@ -680,7 +793,35 @@ nl_sock_transact(struct nl_sock *sock, const struct ofpbuf *request,
 int
 nl_sock_drain(struct nl_sock *sock)
 {
+#ifndef _WIN32
     return drain_rcvbuf(sock->fd);
+#else
+ int rcvbuf;
+
+    rcvbuf = get_socket_rcvbuf(sock->fd);
+    if (rcvbuf < 0) {
+        return -rcvbuf;
+    }
+
+    while (rcvbuf > 0) {
+        /* In Linux, specifying MSG_TRUNC in the flags argument causes the
+         * datagram length to be returned, even if that is longer than the
+         * buffer provided.  Thus, we can use a 1-byte buffer to discard the
+         * incoming datagram and still be able to account how many bytes were
+         * removed from the receive buffer.
+         *
+         * On other Unix-like OSes, MSG_TRUNC has no effect in the flags
+         * argument. */
+        char buffer[2048];
+        ssize_t n_bytes = recv(sock->fd, buffer, sizeof buffer,
+                               MSG_TRUNC | MSG_DONTROUTE);
+        if (n_bytes <= 0 || n_bytes >= rcvbuf) {
+            break;
+        }
+        rcvbuf -= n_bytes;
+    }
+    return 0;
+#endif
 }
 
 /* Starts a Netlink "dump" operation, by sending 'request' to the kernel on a
@@ -993,7 +1134,15 @@ nl_lookup_genl_mcgroup(const char *family_name, const char *group_name,
     }
 
     if (!family_attrs[CTRL_ATTR_MCAST_GROUPS]) {
+#ifndef _WIN32
         error = EPROTO;
+#else
+#define OVS_VPORT_MCGROUP_FALLBACK_ID 33
+        *multicast_group = 33;
+        VLOG_WARN("%s-%s: has no multicast group, using fallback %d",
+                  family_name, group_name, *multicast_group);
+        error = 0;
+#endif
         goto exit;
     }
 
-- 
1.9.0.msysgit.0




More information about the dev mailing list