]> Pileus Git - ~andy/linux/blobdiff - net/ipv4/ip_gre.c
IP_GRE: Fix GRE_CSUM case.
[~andy/linux] / net / ipv4 / ip_gre.c
index a56f1182c176dd87cff194914bd379f9674f6b00..4065129345077b15a30cdf6d989343f550ad30fa 100644 (file)
@@ -735,7 +735,7 @@ drop:
        return 0;
 }
 
-static struct sk_buff *handle_offloads(struct sk_buff *skb)
+static struct sk_buff *handle_offloads(struct ip_tunnel *tunnel, struct sk_buff *skb)
 {
        int err;
 
@@ -745,12 +745,13 @@ static struct sk_buff *handle_offloads(struct sk_buff *skb)
                        goto error;
                skb_shinfo(skb)->gso_type |= SKB_GSO_GRE;
                return skb;
-       } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+       } else if (skb->ip_summed == CHECKSUM_PARTIAL &&
+                  tunnel->parms.o_flags&GRE_CSUM) {
                err = skb_checksum_help(skb);
                if (unlikely(err))
                        goto error;
-       }
-       skb->ip_summed = CHECKSUM_NONE;
+       } else if (skb->ip_summed != CHECKSUM_PARTIAL)
+               skb->ip_summed = CHECKSUM_NONE;
 
        return skb;
 
@@ -779,7 +780,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
        int    err;
        int    pkt_len;
 
-       skb = handle_offloads(skb);
+       skb = handle_offloads(tunnel, skb);
        if (IS_ERR(skb)) {
                dev->stats.tx_dropped++;
                return NETDEV_TX_OK;
@@ -973,7 +974,8 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
        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))
@@ -1009,10 +1011,8 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
 
                        if (skb_has_shared_frag(skb)) {
                                err = __skb_linearize(skb);
-                               if (err) {
-                                       ip_rt_put(rt);
+                               if (err)
                                        goto tx_error;
-                               }
                        }
 
                        *ptr = 0;
@@ -1106,8 +1106,14 @@ static int ipgre_tunnel_bind_dev(struct net_device *dev)
        tunnel->hlen = addend;
        /* TCP offload with GRE SEQ is not supported. */
        if (!(tunnel->parms.o_flags & GRE_SEQ)) {
-               dev->features           |= NETIF_F_GSO_SOFTWARE;
-               dev->hw_features        |= NETIF_F_GSO_SOFTWARE;
+               /* device supports enc gso offload*/
+               if (tdev->hw_enc_features & NETIF_F_GRE_GSO) {
+                       dev->features           |= NETIF_F_TSO;
+                       dev->hw_features        |= NETIF_F_TSO;
+               } else {
+                       dev->features           |= NETIF_F_GSO_SOFTWARE;
+                       dev->hw_features        |= NETIF_F_GSO_SOFTWARE;
+               }
        }
 
        return mtu;