/* Used in foo-over-udp, set in udp[46]_gro_receive */
        u8      is_ipv6:1;
 
-       /* 7 bit hole */
+       /* Used in GRE, set in fou/gue_gro_receive */
+       u8      is_fou:1;
+
+       /* 6 bit hole */
 
        /* used to support CHECKSUM_COMPLETE for tunneling protocols */
        __wsum  csum;
 
                NAPI_GRO_CB(skb)->flush = 0;
                NAPI_GRO_CB(skb)->free = 0;
                NAPI_GRO_CB(skb)->encap_mark = 0;
+               NAPI_GRO_CB(skb)->is_fou = 0;
                NAPI_GRO_CB(skb)->gro_remcsum_start = 0;
 
                /* Setup for GRO checksum validation */
 
         */
        NAPI_GRO_CB(skb)->encap_mark = 0;
 
+       /* Flag this frame as already having an outer encap header */
+       NAPI_GRO_CB(skb)->is_fou = 1;
+
        rcu_read_lock();
        offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads;
        ops = rcu_dereference(offloads[proto]);
         */
        NAPI_GRO_CB(skb)->encap_mark = 0;
 
+       /* Flag this frame as already having an outer encap header */
+       NAPI_GRO_CB(skb)->is_fou = 1;
+
        rcu_read_lock();
        offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads;
        ops = rcu_dereference(offloads[guehdr->proto_ctype]);
 
        if ((greh->flags & ~(GRE_KEY|GRE_CSUM)) != 0)
                goto out;
 
+       /* We can only support GRE_CSUM if we can track the location of
+        * the GRE header.  In the case of FOU/GUE we cannot because the
+        * outer UDP header displaces the GRE header leaving us in a state
+        * of limbo.
+        */
+       if ((greh->flags & GRE_CSUM) && NAPI_GRO_CB(skb)->is_fou)
+               goto out;
+
        type = greh->protocol;
 
        rcu_read_lock();
 
        dev->hw_features        |= GRE_FEATURES;
 
        if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
-               /* TCP offload with GRE SEQ is not supported. */
-               dev->features    |= NETIF_F_GSO_SOFTWARE;
-               dev->hw_features |= NETIF_F_GSO_SOFTWARE;
+               /* TCP offload with GRE SEQ is not supported, nor
+                * can we support 2 levels of outer headers requiring
+                * an update.
+                */
+               if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
+                   (tunnel->encap.type == TUNNEL_ENCAP_NONE)) {
+                       dev->features    |= NETIF_F_GSO_SOFTWARE;
+                       dev->hw_features |= NETIF_F_GSO_SOFTWARE;
+               }
+
                /* Can use a lockless transmit, unless we generate
                 * output sequences
                 */