Add the structure sockaddr_nl to netlink-socket.c when compiling under MSVC.
Add two functions set_sock_pid_in_kernel and portid_next. This will allow the channel identification for the kernel extension to send back messages. Replace send with WriteFile equivalent and ignore nl_sock_drain for the moment under MSVC. On MSVC the rcvbuf does not have a reasonable limit, the current value can suffice for our needs. Signed-off-by: Alin Gabriel Serdean <aserd...@cloudbasesolutions.com> --- lib/netlink-socket.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/lib/netlink-socket.c b/lib/netlink-socket.c index b1e6804..1318c94 100644 --- a/lib/netlink-socket.c +++ b/lib/netlink-socket.c @@ -48,6 +48,38 @@ COVERAGE_DEFINE(netlink_sent); #define SOL_NETLINK 270 #endif +#ifdef _WIN32 +struct sockaddr_nl { + sa_family_t nl_family; + unsigned short int nl_pad; + uint32_t nl_pid; + uint32_t nl_groups; +}; + +static struct ovs_mutex portid_mutex = OVS_MUTEX_INITIALIZER; +static uint32_t g_last_portid = 0; + +//port ids must be unique! +uint32_t portid_next() OVS_GUARDED_BY(portid_mutex) +{ + g_last_portid++; + return g_last_portid; +} + +void set_sock_pid_in_kernel(HANDLE hFile, UINT32 pid) OVS_GUARDED_BY(portid_mutex) +{ + struct nlmsghdr msg = { 0 }; + + msg.nlmsg_len = sizeof(struct nlmsghdr); + msg.nlmsg_type = 80; //target = set file pid + msg.nlmsg_flags = 0; + msg.nlmsg_seq = 0; + msg.nlmsg_pid = pid; + + WriteFile(hFile, &msg, sizeof(struct nlmsghdr), NULL, NULL); +} +#endif + /* A single (bad) Netlink message can in theory dump out many, many log * messages, so the burst size is set quite high here to avoid missing useful * information. Also, at high logging levels we log *all* Netlink messages. */ @@ -60,7 +92,11 @@ static void log_nlmsg(const char *function, int error, /* Netlink sockets. */ struct nl_sock { +#ifdef _WIN32 + HANDLE handle; +#else int fd; +#endif uint32_t next_seq; uint32_t pid; int protocol; @@ -114,15 +150,39 @@ nl_sock_create(int protocol, struct nl_sock **sockp) *sockp = NULL; sock = xmalloc(sizeof *sock); +#ifdef _WIN32 + sock->handle = CreateFileA("\\\\.\\OpenVSwitchDevice", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + + int last_error = GetLastError(); + + if(sock->handle == INVALID_HANDLE_VALUE) { + VLOG_ERR("fcntl: %s", ovs_strerror(last_error)); + goto error; + } +#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; +#ifdef _WIN32 + sock->rcvbuf = rcvbuf; + ovs_mutex_init(&portid_mutex); + ovs_mutex_lock(&portid_mutex); + sock->pid = portid_next(); + set_sock_pid_in_kernel(sock->handle, sock->pid); + ovs_mutex_unlock(&portid_mutex); +#else if (setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUFFORCE, &rcvbuf, sizeof rcvbuf)) { /* Only root can use SO_RCVBUFFORCE. Everyone else gets EPERM. @@ -161,6 +221,7 @@ nl_sock_create(int protocol, struct nl_sock **sockp) goto error; } sock->pid = local.nl_pid; +#endif *sockp = sock; return 0; @@ -172,9 +233,15 @@ error: retval = EINVAL; } } +#ifdef _WIN32 + if (sock->handle != INVALID_HANDLE_VALUE) { + CloseHandle(sock->handle); + } +#else if (sock->fd >= 0) { close(sock->fd); } +#endif free(sock); return retval; } @@ -193,7 +260,11 @@ void nl_sock_destroy(struct nl_sock *sock) { if (sock) { +#ifdef _WIN32 + CloseHandle(sock->handle); +#else close(sock->fd); +#endif free(sock); } } @@ -212,12 +283,36 @@ nl_sock_destroy(struct nl_sock *sock) int nl_sock_join_mcgroup(struct nl_sock *sock, unsigned int multicast_group) { +#ifdef _WIN32 +#define OVS_VPORT_MCGROUP_FALLBACK_ID 33 + struct message_multicast + { + struct nlmsghdr; + //if true, join; if else, leave + unsigned char join; + unsigned int groupId; + }; + + struct message_multicast msg = { 0 }; + + msg.nlmsg_len = sizeof(struct message_multicast); + msg.nlmsg_type = OVS_VPORT_MCGROUP_FALLBACK_ID; + msg.nlmsg_flags = 0; + msg.nlmsg_seq = 0; + msg.nlmsg_pid = sock->pid; + + msg.join = 1; + msg.groupId = multicast_group; + + nl_sock_transact(sock, &msg, NULL); +#else 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; } +#endif return 0; } @@ -234,12 +329,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) { +#ifdef _WIN32 + struct message_multicast + { + struct nlmsghdr; + //if true, join; if else, leave + unsigned char join; + }; + + struct message_multicast msg = { 0 }; + nl_msg_put_nlmsghdr(&msg, sizeof(struct message_multicast), + multicast_group, 0); + msg.join = 0; + + nl_sock_transact(sock, &msg, NULL); +#else 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; } +#endif return 0; } @@ -255,7 +366,16 @@ nl_sock_send__(struct nl_sock *sock, const struct ofpbuf *msg, nlmsg->nlmsg_pid = sock->pid; do { int retval; +#ifdef _WIN32 + retval = WriteFile(sock->handle, ofpbuf_data(msg), ofpbuf_size(msg), + NULL, NULL); + if(!retval) { + retval = -1; + _set_errno(EAGAIN); + } +#else retval = send(sock->fd, ofpbuf_data(msg), ofpbuf_size(msg), wait ? 0 : MSG_DONTWAIT); +#endif error = retval < 0 ? errno : 0; } while (error == EINTR); log_nlmsg(__func__, error, ofpbuf_data(msg), ofpbuf_size(msg), sock->protocol); @@ -334,7 +454,11 @@ nl_sock_recv__(struct nl_sock *sock, struct ofpbuf *buf, bool wait) nlmsghdr = ofpbuf_base(buf); do { nlmsghdr->nlmsg_len = UINT32_MAX; +#ifdef _WIN32 + retval = recvmsg(sock->handle, &msg, wait ? 0 : MSG_DONTWAIT); +#else retval = recvmsg(sock->fd, &msg, wait ? 0 : MSG_DONTWAIT); +#endif error = (retval < 0 ? errno : retval == 0 ? ECONNRESET /* not possible? */ : nlmsghdr->nlmsg_len != UINT32_MAX ? 0 @@ -447,7 +571,11 @@ nl_sock_transact_multiple__(struct nl_sock *sock, msg.msg_iov = iovs; msg.msg_iovlen = n; do { +#ifdef _WIN32 + error = sendmsg(sock->handle, &msg, 0) < 0 ? errno : 0; +#else error = sendmsg(sock->fd, &msg, 0) < 0 ? errno : 0; +#endif } while (error == EINTR); for (i = 0; i < n; i++) { @@ -680,7 +808,11 @@ 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 + return 0; +#endif } /* Starts a Netlink "dump" operation, by sending 'request' to the kernel on a @@ -871,7 +1003,11 @@ nl_dump_done(struct nl_dump *dump) void nl_sock_wait(const struct nl_sock *sock, short int events) { +#ifdef _WIN32 + poll_fd_wait(sock->handle, events); +#else poll_fd_wait(sock->fd, events); +#endif } /* Returns the underlying fd for 'sock', for use in "poll()"-like operations @@ -884,7 +1020,11 @@ nl_sock_wait(const struct nl_sock *sock, short int events) int nl_sock_fd(const struct nl_sock *sock) { +#ifdef _WIN32 + return sock->handle; +#else return sock->fd; +#endif } /* Returns the PID associated with this socket. */ -- 1.9.0.msysgit.0 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev