tunneling: Fix location of GRE checksums.
authorJesse Gross <jesse@nicira.com>
Fri, 27 Mar 2015 00:09:38 +0000 (17:09 -0700)
committerJesse Gross <jesse@nicira.com>
Tue, 7 Apr 2015 23:26:44 +0000 (16:26 -0700)
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 <jesse@nicira.com>
Acked-by: Pritesh Kothari <pritesh.kothari@cisco.com>
Acked-by: Pravin B Shelar <pshelar@nicira.com>
lib/netdev-vport.c
lib/odp-util.c

index 1ee68bc..a9639d3 100644 (file)
@@ -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));
     }
 }
 
index 827b91c..b2e5319 100644 (file)
@@ -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)) {