util: Add be32_prefix_mask().
authorJarno Rajahalme <jrajahalme@nicira.com>
Tue, 11 Nov 2014 23:50:51 +0000 (15:50 -0800)
committerJarno Rajahalme <jrajahalme@nicira.com>
Tue, 11 Nov 2014 23:56:08 +0000 (15:56 -0800)
Shifting a 32-bit entity by 32 bits is undefined behavior.  As we have 2
cases where we may hit this, it is a time to introduce a helper for
this.

Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com>
Acked-by: Pravin B Shelar <pshelar@nicira.com>
lib/classifier.c
lib/meta-flow.c
lib/util.h

index d8aa88e..83a53d8 100644 (file)
@@ -1829,7 +1829,7 @@ find_match_wc(const struct cls_subtable *subtable, const struct flow *flow,
         trie_lookup_value(subtable->ports_trie, &value, 32, &mbits);
 
         ((OVS_FORCE ovs_be32 *)&wc->masks)[TP_PORTS_OFS32] |=
-            mask & htonl(~0 << (32 - mbits));
+            mask & be32_prefix_mask(mbits);
 
         ofs.start = TP_PORTS_OFS32;
         goto range_out;
index e28a00b..c94e0c5 100644 (file)
@@ -33,6 +33,7 @@
 #include "shash.h"
 #include "socket-util.h"
 #include "unaligned.h"
+#include "util.h"
 #include "vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(meta_flow);
@@ -2405,13 +2406,10 @@ mf_from_ipv4_string(const struct mf_field *mf, const char *s,
         /* OK. */
     } else if (ovs_scan(s, IP_SCAN_FMT"/%d", IP_SCAN_ARGS(ip), &prefix)) {
         if (prefix <= 0 || prefix > 32) {
-            return xasprintf("%s: network prefix bits not between 1 and "
+            return xasprintf("%s: network prefix bits not between 0 and "
                              "32", s);
-        } else if (prefix == 32) {
-            *mask = OVS_BE32_MAX;
-        } else {
-            *mask = htonl(((1u << prefix) - 1) << (32 - prefix));
         }
+        *mask = be32_prefix_mask(prefix);
     } else if (ovs_scan(s, IP_SCAN_FMT, IP_SCAN_ARGS(ip))) {
         *mask = OVS_BE32_MAX;
     } else {
index 4282007..d2adfd4 100644 (file)
@@ -26,6 +26,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include "byte-order.h"
 #include "compiler.h"
 #include "openvswitch/types.h"
 
@@ -478,6 +479,14 @@ leftmost_1bit_idx(uint32_t x)
 {
     return x ? log_2_floor(x) : 32;
 }
+
+/* Return a ovs_be32 prefix in network byte order with 'plen' highest bits set.
+ * Shift with 32 is undefined behavior, but we rather use 64-bit shift than
+ * compare. */
+static inline ovs_be32 be32_prefix_mask(int plen)
+{
+    return htonl((uint64_t)UINT32_MAX << (32 - plen));
+}
 \f
 bool is_all_zeros(const uint8_t *, size_t);
 bool is_all_ones(const uint8_t *, size_t);