summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBen Pfaff <blp@ovn.org>2016-05-26 16:53:52 -0700
committerBen Pfaff <blp@ovn.org>2016-06-03 13:18:19 -0700
commit3d75c66007c88f886864df02b86afaa3a440088a (patch)
treecd2f61f31dcb08d9363338e413cccc2f145b0bc3 /lib
parent117d72495467efaa3eb7e7e4f7d110cd1223b967 (diff)
downloadopenvswitch-3d75c66007c88f886864df02b86afaa3a440088a.tar.gz
netdev-native-tnl: Fix treatment of GRE key on big-endian systems.
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>
Diffstat (limited to 'lib')
-rw-r--r--lib/byte-order.h31
-rw-r--r--lib/netdev-native-tnl.c5
2 files changed, 32 insertions, 4 deletions
diff --git a/lib/byte-order.h b/lib/byte-order.h
index 0437d4e45..e864658f9 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 086496f7f..15975ade9 100644
--- a/lib/netdev-native-tnl.c
+++ b/lib/netdev-native-tnl.c
@@ -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++;
}