dpif-netlink: add GENEVE creation support
[cascardo/ovs.git] / lib / util.c
index 9473985..6ca04ad 100644 (file)
@@ -413,6 +413,21 @@ ovs_strerror(int error)
     char *buffer;
     char *s;
 
+    if (error == 0) {
+        /*
+         * strerror(0) varies among platforms:
+         *
+         *   Success
+         *   No error
+         *   Undefined error: 0
+         *
+         * We want to provide a consistent result here because
+         * our testsuite has test cases which strictly matches
+         * log messages containing this string.
+         */
+        return "Success";
+    }
+
     save_errno = errno;
     buffer = strerror_buffer_get()->s;
 
@@ -446,14 +461,9 @@ ovs_strerror(int error)
  * vSwitch.  Otherwise, it is assumed to be an external program linking against
  * the Open vSwitch libraries.
  *
- * The 'date' and 'time' arguments should likely be called with
- * "__DATE__" and "__TIME__" to use the time the binary was built.
- * Alternatively, the "ovs_set_program_name" macro may be called to do this
- * automatically.
  */
 void
-ovs_set_program_name__(const char *argv0, const char *version, const char *date,
-                       const char *time)
+ovs_set_program_name(const char *argv0, const char *version)
 {
     char *basename;
 #ifdef _WIN32
@@ -481,14 +491,12 @@ ovs_set_program_name__(const char *argv0, const char *version, const char *date,
 
     free(program_version);
     if (!strcmp(version, VERSION)) {
-        program_version = xasprintf("%s (Open vSwitch) "VERSION"\n"
-                                    "Compiled %s %s\n",
-                                    program_name, date, time);
+        program_version = xasprintf("%s (Open vSwitch) "VERSION"\n",
+                                    program_name);
     } else {
         program_version = xasprintf("%s %s\n"
-                                    "Open vSwitch Library "VERSION"\n"
-                                    "Compiled %s %s\n",
-                                    program_name, version, date, time);
+                                    "Open vSwitch Library "VERSION"\n",
+                                    program_name, version);
     }
 }
 
@@ -500,24 +508,13 @@ get_subprogram_name(void)
     return name ? name : "";
 }
 
-/* Sets the formatted value of 'format' as the name of the currently running
- * thread or process.  (This appears in log messages and may also be visible in
- * system process listings and debuggers.) */
+/* Sets 'subprogram_name' as the name of the currently running thread or
+ * process.  (This appears in log messages and may also be visible in system
+ * process listings and debuggers.) */
 void
-set_subprogram_name(const char *format, ...)
+set_subprogram_name(const char *subprogram_name)
 {
-    char *pname;
-
-    if (format) {
-        va_list args;
-
-        va_start(args, format);
-        pname = xvasprintf(format, args);
-        va_end(args);
-    } else {
-        pname = xstrdup(program_name);
-    }
-
+    char *pname = xstrdup(subprogram_name ? subprogram_name : program_name);
     free(subprogram_name_set(pname));
 
 #if HAVE_GLIBC_PTHREAD_SETNAME_NP
@@ -1365,9 +1362,9 @@ bitwise_is_all_zeros(const void *p_, unsigned int len, unsigned int ofs,
     return true;
 }
 
-/* Scans the bits in 'p' that have bit offsets 'start' through 'end'
- * (inclusive) for the first bit with value 'target'.  If one is found, returns
- * its offset, otherwise 'end'.  'p' is 'len' bytes long.
+/* Scans the bits in 'p' that have bit offsets 'start' (inclusive) through
+ * 'end' (exclusive) for the first bit with value 'target'.  If one is found,
+ * returns its offset, otherwise 'end'.  'p' is 'len' bytes long.
  *
  * If you consider all of 'p' to be a single unsigned integer in network byte
  * order, then bit N is the bit with value 2**N.  That is, bit 0 is the bit
@@ -1378,21 +1375,79 @@ bitwise_is_all_zeros(const void *p_, unsigned int len, unsigned int ofs,
  *   start <= end
  */
 unsigned int
-bitwise_scan(const void *p_, unsigned int len, bool target, unsigned int start,
+bitwise_scan(const void *p, unsigned int len, bool target, unsigned int start,
              unsigned int end)
 {
-    const uint8_t *p = p_;
     unsigned int ofs;
 
     for (ofs = start; ofs < end; ofs++) {
-        bool bit = (p[len - (ofs / 8 + 1)] & (1u << (ofs % 8))) != 0;
-        if (bit == target) {
+        if (bitwise_get_bit(p, len, ofs) == target) {
             break;
         }
     }
     return ofs;
 }
 
+/* Scans the bits in 'p' that have bit offsets 'start' (inclusive) through
+ * 'end' (exclusive) for the first bit with value 'target', in reverse order.
+ * If one is found, returns its offset, otherwise 'end'.  'p' is 'len' bytes
+ * long.
+ *
+ * If you consider all of 'p' to be a single unsigned integer in network byte
+ * order, then bit N is the bit with value 2**N.  That is, bit 0 is the bit
+ * with value 1 in p[len - 1], bit 1 is the bit with value 2, bit 2 is the bit
+ * with value 4, ..., bit 8 is the bit with value 1 in p[len - 2], and so on.
+ *
+ * To scan an entire bit array in reverse order, specify start == len * 8 - 1
+ * and end == -1, in which case the return value is nonnegative if successful
+ * and -1 if no 'target' match is found.
+ *
+ * Required invariant:
+ *   start >= end
+ */
+int
+bitwise_rscan(const void *p, unsigned int len, bool target, int start, int end)
+{
+    const uint8_t *s = p;
+    int start_byte = len - (start / 8 + 1);
+    int end_byte = len - (end / 8 + 1);
+    int ofs_byte;
+    int ofs;
+    uint8_t the_byte;
+
+    /* Find the target in the start_byte from starting offset */
+    ofs_byte = start_byte;
+    the_byte = s[ofs_byte];
+    for (ofs = start % 8; ofs >= 0; ofs--) {
+        if (((the_byte & (1u << ofs)) != 0) == target) {
+            break;
+        }
+    }
+    if (ofs < 0) {
+        /* Target not found in start byte, continue searching byte by byte */
+        for (ofs_byte = start_byte + 1; ofs_byte <= end_byte; ofs_byte++) {
+            if ((target && s[ofs_byte])
+                    || (!target && (s[ofs_byte] != 0xff))) {
+               break;
+            }
+        }
+        if (ofs_byte > end_byte) {
+            return end;
+        }
+        the_byte = s[ofs_byte];
+        /* Target is in the_byte, find it bit by bit */
+        for (ofs = 7; ofs >= 0; ofs--) {
+            if (((the_byte & (1u << ofs)) != 0) == target) {
+                break;
+            }
+        }
+    }
+    int ret = (len - ofs_byte) * 8 - (8 - ofs);
+    if (ret < end) {
+        return end;
+    }
+    return ret;
+}
 
 /* Copies the 'n_bits' low-order bits of 'value' into the 'n_bits' bits
  * starting at bit 'dst_ofs' in 'dst', which is 'dst_len' bytes long.
@@ -1442,6 +1497,104 @@ bitwise_get(const void *src, unsigned int src_len,
                  n_bits);
     return ntohll(value);
 }
+
+/* Returns the value of the bit with offset 'ofs' in 'src', which is 'len'
+ * bytes long.
+ *
+ * If you consider all of 'src' to be a single unsigned integer in network byte
+ * order, then bit N is the bit with value 2**N.  That is, bit 0 is the bit
+ * with value 1 in src[len - 1], bit 1 is the bit with value 2, bit 2 is the
+ * bit with value 4, ..., bit 8 is the bit with value 1 in src[len - 2], and so
+ * on.
+ *
+ * Required invariants:
+ *   ofs < len * 8
+ */
+bool
+bitwise_get_bit(const void *src_, unsigned int len, unsigned int ofs)
+{
+    const uint8_t *src = src_;
+
+    return (src[len - (ofs / 8 + 1)] & (1u << (ofs % 8))) != 0;
+}
+
+/* Sets the bit with offset 'ofs' in 'dst', which is 'len' bytes long, to 0.
+ *
+ * If you consider all of 'dst' to be a single unsigned integer in network byte
+ * order, then bit N is the bit with value 2**N.  That is, bit 0 is the bit
+ * with value 1 in dst[len - 1], bit 1 is the bit with value 2, bit 2 is the
+ * bit with value 4, ..., bit 8 is the bit with value 1 in dst[len - 2], and so
+ * on.
+ *
+ * Required invariants:
+ *   ofs < len * 8
+ */
+void
+bitwise_put0(void *dst_, unsigned int len, unsigned int ofs)
+{
+    uint8_t *dst = dst_;
+
+    dst[len - (ofs / 8 + 1)] &= ~(1u << (ofs % 8));
+}
+
+/* Sets the bit with offset 'ofs' in 'dst', which is 'len' bytes long, to 1.
+ *
+ * If you consider all of 'dst' to be a single unsigned integer in network byte
+ * order, then bit N is the bit with value 2**N.  That is, bit 0 is the bit
+ * with value 1 in dst[len - 1], bit 1 is the bit with value 2, bit 2 is the
+ * bit with value 4, ..., bit 8 is the bit with value 1 in dst[len - 2], and so
+ * on.
+ *
+ * Required invariants:
+ *   ofs < len * 8
+ */
+void
+bitwise_put1(void *dst_, unsigned int len, unsigned int ofs)
+{
+    uint8_t *dst = dst_;
+
+    dst[len - (ofs / 8 + 1)] |= 1u << (ofs % 8);
+}
+
+/* Sets the bit with offset 'ofs' in 'dst', which is 'len' bytes long, to 'b'.
+ *
+ * If you consider all of 'dst' to be a single unsigned integer in network byte
+ * order, then bit N is the bit with value 2**N.  That is, bit 0 is the bit
+ * with value 1 in dst[len - 1], bit 1 is the bit with value 2, bit 2 is the
+ * bit with value 4, ..., bit 8 is the bit with value 1 in dst[len - 2], and so
+ * on.
+ *
+ * Required invariants:
+ *   ofs < len * 8
+ */
+void
+bitwise_put_bit(void *dst, unsigned int len, unsigned int ofs, bool b)
+{
+    if (b) {
+        bitwise_put1(dst, len, ofs);
+    } else {
+        bitwise_put0(dst, len, ofs);
+    }
+}
+
+/* Flips the bit with offset 'ofs' in 'dst', which is 'len' bytes long.
+ *
+ * If you consider all of 'dst' to be a single unsigned integer in network byte
+ * order, then bit N is the bit with value 2**N.  That is, bit 0 is the bit
+ * with value 1 in dst[len - 1], bit 1 is the bit with value 2, bit 2 is the
+ * bit with value 4, ..., bit 8 is the bit with value 1 in dst[len - 2], and so
+ * on.
+ *
+ * Required invariants:
+ *   ofs < len * 8
+ */
+void
+bitwise_toggle_bit(void *dst_, unsigned int len, unsigned int ofs)
+{
+    uint8_t *dst = dst_;
+
+    dst[len - (ofs / 8 + 1)] ^= 1u << (ofs % 8);
+}
 \f
 /* ovs_scan */
 
@@ -1927,6 +2080,17 @@ xsleep(unsigned int seconds)
     ovsrcu_quiesce_end();
 }
 
+/* Determine whether standard output is a tty or not. This is useful to decide
+ * whether to use color output or not when --color option for utilities is set
+ * to `auto`.
+ */
+bool
+is_stdout_a_tty(void)
+{
+    char const *t = getenv("TERM");
+    return (isatty(STDOUT_FILENO) && t && strcmp(t, "dumb") != 0);
+}
+
 #ifdef _WIN32
 \f
 char *
@@ -1935,6 +2099,11 @@ ovs_format_message(int error)
     enum { BUFSIZE = sizeof strerror_buffer_get()->s };
     char *buffer = strerror_buffer_get()->s;
 
+    if (error == 0) {
+        /* See ovs_strerror */
+        return "Success";
+    }
+
     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                   NULL, error, 0, buffer, BUFSIZE, NULL);
     return buffer;