GRE-GSO generates ip fragments with id 0,2,3,4... for every
GSO packet, which is not correct. Following patch fixes it
by setting ip-header id unique id of fragments are allowed.
As Eric Dumazet suggested it is optimized by using inner ip-header
whenever inner packet is ipv4.
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
        }
 }
 
+static inline void tunnel_ip_select_ident(struct sk_buff *skb,
+                                         const struct iphdr  *old_iph,
+                                         struct dst_entry *dst)
+{
+       struct iphdr *iph = ip_hdr(skb);
+
+       if (iph->frag_off & htons(IP_DF))
+               iph->id = 0;
+       else {
+               /* Use inner packet iph-id if possible. */
+               if (skb->protocol == htons(ETH_P_IP) && old_iph->id)
+                       iph->id = old_iph->id;
+               else
+                       __ip_select_ident(iph, dst,
+                                         (skb_shinfo(skb)->gso_segs ?: 1) - 1);
+       }
+}
 #endif
 
                        if (skb->next != NULL)
                                iph->frag_off |= htons(IP_MF);
                        offset += (skb->len - skb->mac_len - iph->ihl * 4);
-               } else
-                       iph->id = htons(id++);
+               } else  {
+                       if (!(iph->frag_off & htons(IP_DF)))
+                               iph->id = htons(id++);
+               }
                iph->tot_len = htons(skb->len - skb->mac_len);
                iph->check = 0;
                iph->check = ip_fast_csum(skb_network_header(skb), iph->ihl);
 
        iph->daddr              =       fl4.daddr;
        iph->saddr              =       fl4.saddr;
        iph->ttl                =       ttl;
-       iph->id                 =       0;
+
+       tunnel_ip_select_ident(skb, old_iph, &rt->dst);
 
        if (ttl == 0) {
                if (skb->protocol == htons(ETH_P_IP))