]> git.proxmox.com Git - mirror_ovs.git/blobdiff - lib/netlink-socket.c
dpif-netlink-rtnl: Support GENEVE creation
[mirror_ovs.git] / lib / netlink-socket.c
index 7502764de006a824ac8b700554d00c54945d3cf5..ccfd55e9220663f55fa5fd1828f73de8850289d0 100644 (file)
@@ -60,6 +60,22 @@ static void log_nlmsg(const char *function, int error,
 #ifdef _WIN32
 static int get_sock_pid_from_kernel(struct nl_sock *sock);
 static int set_sock_property(struct nl_sock *sock);
+static int nl_sock_transact(struct nl_sock *sock, const struct ofpbuf *request,
+                            struct ofpbuf **replyp);
+
+/* In the case DeviceIoControl failed and GetLastError returns with
+ * ERROR_NOT_FOUND means we lost communication with the kernel device.
+ * CloseHandle will fail because the handle in 'theory' does not exist.
+ * The only remaining option is to crash and allow the service to be restarted
+ * via service manager.  This is the only way to close the handle from both
+ * userspace and kernel. */
+void
+lost_communication(DWORD last_err)
+{
+    if (last_err == ERROR_NOT_FOUND) {
+        ovs_abort(0, "lost communication with the kernel device");
+    }
+}
 #endif
 \f
 /* Netlink sockets. */
@@ -278,6 +294,7 @@ get_sock_pid_from_kernel(struct nl_sock *sock)
     if (!DeviceIoControl(sock->handle, OVS_IOCTL_GET_PID,
                          NULL, 0, &pid, sizeof(pid),
                          &bytes, NULL)) {
+        lost_communication(GetLastError());
         retval = EINVAL;
     } else {
         if (bytes < sizeof(pid)) {
@@ -424,6 +441,30 @@ nl_sock_join_mcgroup(struct nl_sock *sock, unsigned int multicast_group)
 }
 
 #ifdef _WIN32
+int
+nl_sock_subscribe_packet__(struct nl_sock *sock, bool subscribe)
+{
+    struct ofpbuf request;
+    uint64_t request_stub[128];
+    struct ovs_header *ovs_header;
+    struct nlmsghdr *nlmsg;
+    int error;
+
+    ofpbuf_use_stub(&request, request_stub, sizeof request_stub);
+    nl_msg_put_genlmsghdr(&request, 0, OVS_WIN_NL_CTRL_FAMILY_ID, 0,
+                          OVS_CTRL_CMD_PACKET_SUBSCRIBE_REQ,
+                          OVS_WIN_CONTROL_VERSION);
+
+    ovs_header = ofpbuf_put_uninit(&request, sizeof *ovs_header);
+    ovs_header->dp_ifindex = 0;
+    nl_msg_put_u8(&request, OVS_NL_ATTR_PACKET_SUBSCRIBE, subscribe ? 1 : 0);
+    nl_msg_put_u32(&request, OVS_NL_ATTR_PACKET_PID, sock->pid);
+
+    error = nl_sock_send(sock, &request, true);
+    ofpbuf_uninit(&request);
+    return error;
+}
+
 int
 nl_sock_subscribe_packets(struct nl_sock *sock)
 {
@@ -459,30 +500,6 @@ nl_sock_unsubscribe_packets(struct nl_sock *sock)
     sock->read_ioctl = OVS_IOCTL_READ;
     return 0;
 }
-
-int
-nl_sock_subscribe_packet__(struct nl_sock *sock, bool subscribe)
-{
-    struct ofpbuf request;
-    uint64_t request_stub[128];
-    struct ovs_header *ovs_header;
-    struct nlmsghdr *nlmsg;
-    int error;
-
-    ofpbuf_use_stub(&request, request_stub, sizeof request_stub);
-    nl_msg_put_genlmsghdr(&request, 0, OVS_WIN_NL_CTRL_FAMILY_ID, 0,
-                          OVS_CTRL_CMD_PACKET_SUBSCRIBE_REQ,
-                          OVS_WIN_CONTROL_VERSION);
-
-    ovs_header = ofpbuf_put_uninit(&request, sizeof *ovs_header);
-    ovs_header->dp_ifindex = 0;
-    nl_msg_put_u8(&request, OVS_NL_ATTR_PACKET_SUBSCRIBE, subscribe ? 1 : 0);
-    nl_msg_put_u32(&request, OVS_NL_ATTR_PACKET_PID, sock->pid);
-
-    error = nl_sock_send(sock, &request, true);
-    ofpbuf_uninit(&request);
-    return error;
-}
 #endif
 
 /* Tries to make 'sock' stop listening to 'multicast_group'.  Returns 0 if
@@ -535,11 +552,12 @@ nl_sock_send__(struct nl_sock *sock, const struct ofpbuf *msg,
         if (!DeviceIoControl(sock->handle, OVS_IOCTL_WRITE,
                              msg->data, msg->size, NULL, 0,
                              &bytes, NULL)) {
+            lost_communication(GetLastError());
             retval = -1;
             /* XXX: Map to a more appropriate error based on GetLastError(). */
             errno = EINVAL;
             VLOG_DBG_RL(&rl, "fatal driver failure in write: %s",
-                ovs_lasterror_to_string());
+                        ovs_lasterror_to_string());
         } else {
             retval = msg->size;
         }
@@ -629,6 +647,7 @@ nl_sock_recv__(struct nl_sock *sock, struct ofpbuf *buf, bool wait)
         DWORD bytes;
         if (!DeviceIoControl(sock->handle, sock->read_ioctl,
                              NULL, 0, tail, sizeof tail, &bytes, NULL)) {
+            lost_communication(GetLastError());
             VLOG_DBG_RL(&rl, "fatal driver failure in transact: %s",
                         ovs_lasterror_to_string());
             retval = -1;
@@ -879,6 +898,7 @@ nl_sock_transact_multiple__(struct nl_sock *sock,
             }
         } else if (!ret) {
             /* XXX: Map to a more appropriate error. */
+            lost_communication(GetLastError());
             error = EINVAL;
             VLOG_DBG_RL(&rl, "fatal driver failure: %s",
                 ovs_lasterror_to_string());
@@ -886,6 +906,8 @@ nl_sock_transact_multiple__(struct nl_sock *sock,
         }
 
         if (reply_len != 0) {
+            request_nlmsg = nl_msg_nlmsghdr(txn->request);
+
             if (reply_len < sizeof *reply_nlmsg) {
                 nl_sock_record_errors__(transactions, n, 0);
                 VLOG_DBG_RL(&rl, "insufficient length of reply %#"PRIu32
@@ -894,7 +916,6 @@ nl_sock_transact_multiple__(struct nl_sock *sock,
             }
 
             /* Validate the sequence number in the reply. */
-            request_nlmsg = nl_msg_nlmsghdr(txn->request);
             reply_nlmsg = (struct nlmsghdr *)reply_buf;
 
             if (request_nlmsg->nlmsg_seq != reply_nlmsg->nlmsg_seq) {
@@ -1275,6 +1296,7 @@ pend_io_request(struct nl_sock *sock)
         error = GetLastError();
         /* Check if the I/O got pended */
         if (error != ERROR_IO_INCOMPLETE && error != ERROR_IO_PENDING) {
+            lost_communication(error);
             VLOG_ERR("nl_sock_wait failed - %s\n", ovs_format_message(error));
             retval = EINVAL;
         }
@@ -1698,7 +1720,9 @@ nl_transact(int protocol, const struct ofpbuf *request,
 
     error = nl_pool_alloc(protocol, &sock);
     if (error) {
-        *replyp = NULL;
+        if (replyp) {
+            *replyp = NULL;
+        }
         return error;
     }