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 <aserd...@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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev