The GRE implementation used bitwise shifts to convert an ovs_be32 to an
ovs_be64 (with zero extension), but on big-endian systems these conversions
are no-ops.  This fixes the problem.

Signed-off-by: Ben Pfaff <b...@ovn.org>
---
 lib/byte-order.h        | 31 ++++++++++++++++++++++++++++++-
 lib/netdev-native-tnl.c |  5 ++---
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/lib/byte-order.h b/lib/byte-order.h
index 0437d4e..e864658 100644
--- a/lib/byte-order.h
+++ b/lib/byte-order.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2010, 2011, 2013 Nicira, Inc.
+ * Copyright (c) 2008, 2010, 2011, 2013, 2016 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -110,4 +110,33 @@ uint32_byteswap(uint32_t crc) {
     (OVS_FORCE ovs_be32)((uint32_t)(B1) | (B2) << 16)
 #endif
 
+/* These functions zero-extend big-endian values to longer ones,
+ * or truncate long big-endian value to shorter ones. */
+#ifndef __CHECKER__
+#if WORDS_BIGENDIAN
+static inline ovs_be32 be16_to_be32(ovs_be16 x) { return x; }
+static inline ovs_be64 be16_to_be64(ovs_be16 x) { return x; }
+static inline ovs_be64 be32_to_be64(ovs_be32 x) { return x; }
+static inline ovs_be32 be64_to_be32(ovs_be64 x) { return x; }
+static inline ovs_be16 be64_to_be16(ovs_be64 x) { return x; }
+static inline ovs_be16 be32_to_be16(ovs_be32 x) { return x; }
+#else /* !WORDS_BIGENDIAN */
+static inline ovs_be32 be16_to_be32(ovs_be16 x) { return (ovs_be32) x << 16; }
+static inline ovs_be64 be16_to_be64(ovs_be16 x) { return (ovs_be64) x << 48; }
+static inline ovs_be64 be32_to_be64(ovs_be32 x) { return (ovs_be64) x << 32; }
+static inline ovs_be32 be64_to_be32(ovs_be64 x) { return x >> 32; }
+static inline ovs_be16 be64_to_be16(ovs_be64 x) { return x >> 48; }
+static inline ovs_be16 be32_to_be16(ovs_be32 x) { return x >> 16; }
+#endif /* !WORDS_BIGENDIAN */
+#else /* __CHECKER__ */
+/* Making sparse happy with these functions also makes them unreadable, so
+ * don't bother to show it their implementations. */
+ovs_be32 be16_to_be32(ovs_be16);
+ovs_be64 be16_to_be64(ovs_be16);
+ovs_be64 be32_to_be64(ovs_be32);
+ovs_be32 be64_to_be32(ovs_be64);
+ovs_be16 be64_to_be16(ovs_be64);
+ovs_be16 be32_to_be16(ovs_be32);
+#endif
+
 #endif /* byte-order.h */
diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c
index e144679..dd7e85f 100644
--- a/lib/netdev-native-tnl.c
+++ b/lib/netdev-native-tnl.c
@@ -387,7 +387,7 @@ parse_gre_header(struct dp_packet *packet,
     }
 
     if (greh->flags & htons(GRE_KEY)) {
-        tnl->tun_id = (OVS_FORCE ovs_be64) ((OVS_FORCE 
uint64_t)(get_16aligned_be32(options)) << 32);
+        tnl->tun_id = be32_to_be64(get_16aligned_be32(options));
         tnl->flags |= FLOW_TNL_F_KEY;
         options++;
     }
@@ -471,8 +471,7 @@ netdev_gre_build_header(const struct netdev *netdev,
 
     if (tnl_cfg->out_key_present) {
         greh->flags |= htons(GRE_KEY);
-        put_16aligned_be32(options, (OVS_FORCE ovs_be32)
-                                    ((OVS_FORCE uint64_t) 
params->flow->tunnel.tun_id >> 32));
+        put_16aligned_be32(options, be64_to_be32(params->flow->tunnel.tun_id));
         options++;
     }
 
-- 
2.1.3

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to