Move Autoconf's macro definitions into config.h.
[openvswitch] / lib / socket-util.c
index 6061d266f1c7a35e42a1e4904a9b27f70d4649ab..91cdc1d6829c1b663e52ead3b71b9d86f1038475 100644 (file)
@@ -31,6 +31,7 @@
  * derivatives without specific, written prior permission.
  */
 
+#include <config.h>
 #include "socket-util.h"
 #include <arpa/inet.h>
 #include <errno.h>
@@ -118,3 +119,44 @@ check_connection_completion(int fd)
         return EAGAIN;
     }
 }
+
+/* Drain all the data currently in the receive queue of a datagram socket (and
+ * possibly additional data).  There is no way to know how many packets are in
+ * the receive queue, but we do know that the total number of bytes queued does
+ * not exceed the receive buffer size, so we pull packets until none are left
+ * or we've read that many bytes. */
+int
+drain_rcvbuf(int fd)
+{
+    socklen_t rcvbuf_len;
+    size_t rcvbuf;
+
+    rcvbuf_len = sizeof rcvbuf;
+    if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &rcvbuf_len) < 0) {
+        VLOG_ERR("getsockopt(SO_RCVBUF) failed: %s", strerror(errno));
+        return errno;
+    }
+    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. */
+#ifdef __linux__
+#define BUFFER_SIZE 1
+#else
+#define BUFFER_SIZE 2048
+#endif
+        char buffer[BUFFER_SIZE];
+        ssize_t n_bytes = recv(fd, buffer, sizeof buffer,
+                               MSG_TRUNC | MSG_DONTWAIT);
+        if (n_bytes <= 0 || n_bytes >= rcvbuf) {
+            break;
+        }
+        rcvbuf -= n_bytes;
+    }
+    return 0;
+}