From 526a7c85d11dc049ec8f255b948328bf9ba58529 Mon Sep 17 00:00:00 2001 From: Jarno Rajahalme Date: Tue, 11 Nov 2014 15:50:51 -0800 Subject: [PATCH] util: Add be32_prefix_mask(). 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 Acked-by: Pravin B Shelar --- lib/classifier.c | 2 +- lib/meta-flow.c | 8 +++----- lib/util.h | 9 +++++++++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/classifier.c b/lib/classifier.c index d8aa88e4e..83a53d856 100644 --- a/lib/classifier.c +++ b/lib/classifier.c @@ -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; diff --git a/lib/meta-flow.c b/lib/meta-flow.c index e28a00b8e..c94e0c591 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -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 { diff --git a/lib/util.h b/lib/util.h index 4282007c8..d2adfd449 100644 --- a/lib/util.h +++ b/lib/util.h @@ -26,6 +26,7 @@ #include #include #include +#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)); +} bool is_all_zeros(const uint8_t *, size_t); bool is_all_ones(const uint8_t *, size_t); -- 2.20.1