From d804d31e24a47d51bf066052c87524ed865f3f4a Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Thu, 26 Mar 2015 17:09:38 -0700 Subject: [PATCH] tunneling: Fix location of GRE checksums. The GRE checksum is a 16 bit field stored in a 32 bit option (the rest is reserved). The current code treats the checksum as a 32-bit field and places it in the right place for little endian systems but not big endian. This fixes the problem by storing the 16 bit field directly. Signed-off-by: Jesse Gross Acked-by: Pritesh Kothari Acked-by: Pravin B Shelar --- lib/netdev-vport.c | 6 ++---- lib/odp-util.c | 10 ++++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index 1ee68bcc1..a9639d3c3 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -996,10 +996,8 @@ netdev_gre_push_header__(struct dp_packet *packet, greh = push_ip_header(packet, header, size, &ip_tot_size); if (greh->flags & htons(GRE_CSUM)) { - ovs_16aligned_be32 *options = (ovs_16aligned_be32 *) (greh + 1); - - put_16aligned_be32(options, - (OVS_FORCE ovs_be32) csum(greh, ip_tot_size - sizeof (struct ip_header))); + ovs_be16 *csum_opt = (ovs_be16 *) (greh + 1); + *csum_opt = csum(greh, ip_tot_size - sizeof (struct ip_header)); } } diff --git a/lib/odp-util.c b/lib/odp-util.c index 827b91c6e..b2e5319c5 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -565,7 +565,7 @@ format_odp_tnl_push_header(struct ds *ds, struct ovs_action_push_tnl *data) greh->flags, ntohs(greh->protocol)); options = (ovs_16aligned_be32 *)(greh + 1); if (greh->flags & htons(GRE_CSUM)) { - ds_put_format(ds, ",csum=0x%"PRIx32, ntohl(get_16aligned_be32(options))); + ds_put_format(ds, ",csum=0x%"PRIx16, ntohs(*((ovs_be16 *)options))); options++; } if (greh->flags & htons(GRE_KEY)) { @@ -913,12 +913,14 @@ ovs_parse_tnl_push(const char *s, struct ovs_action_push_tnl *data) ovs_16aligned_be32 *options = (ovs_16aligned_be32 *) (greh + 1); if (greh->flags & htons(GRE_CSUM)) { - uint32_t csum; + uint16_t csum; - if (!ovs_scan_len(s, &n, ",csum=0x%"SCNx32, &csum)) { + if (!ovs_scan_len(s, &n, ",csum=0x%"SCNx16, &csum)) { return -EINVAL; } - put_16aligned_be32(options, htonl(csum)); + + memset(options, 0, sizeof *options); + *((ovs_be16 *)options) = htons(csum); options++; } if (greh->flags & htons(GRE_KEY)) { -- 2.20.1