netdev-native-tnl: Fix treatment of GRE key on big-endian systems.
authorBen Pfaff <blp@ovn.org>
Thu, 26 May 2016 23:53:52 +0000 (16:53 -0700)
committerBen Pfaff <blp@ovn.org>
Fri, 3 Jun 2016 20:18:19 +0000 (13:18 -0700)
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 <blp@ovn.org>
Acked-by: Aaron Conole <aconole@redhat.com>
Acked-by: Gerhard Stenzel <gstenzel@linux.vnet.ibm.com>
lib/byte-order.h
lib/netdev-native-tnl.c

index 0437d4e..e864658 100644 (file)
@@ -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 */
index 086496f..15975ad 100644 (file)
@@ -373,7 +373,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++;
     }
@@ -457,8 +457,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++;
     }