ip6gre: Add support for basic offloads offloads excluding GSO
authorAlexander Duyck <aduyck@mirantis.com>
Thu, 14 Apr 2016 19:33:51 +0000 (15:33 -0400)
committerDavid S. Miller <davem@davemloft.net>
Sat, 16 Apr 2016 23:09:13 +0000 (19:09 -0400)
This patch adds support for the basic offloads we support on most devices.
Specifically with this patch set we can support checksum offload, basic
scatter-gather, and highdma.

Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv6/ip6_gre.c

index 2be66e7b4a78ab05a51c836b09c6085e1c484c39..1a5ad143be40df6affdc8c95893f05c2937df5de 100644 (file)
@@ -598,6 +598,18 @@ static void init_tel_txopt(struct ipv6_tel_txoption *opt, __u8 encap_limit)
        opt->ops.opt_nflen = 8;
 }
 
+static __sum16 gre6_checksum(struct sk_buff *skb)
+{
+       __wsum csum;
+
+       if (skb->ip_summed == CHECKSUM_PARTIAL)
+               csum = lco_csum(skb);
+       else
+               csum = skb_checksum(skb, sizeof(struct ipv6hdr),
+                                   skb->len - sizeof(struct ipv6hdr), 0);
+       return csum_fold(csum);
+}
+
 static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb,
                         struct net_device *dev,
                         __u8 dsfield,
@@ -750,8 +762,7 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb,
                }
                if (tunnel->parms.o_flags&GRE_CSUM) {
                        *ptr = 0;
-                       *(__sum16 *)ptr = ip_compute_csum((void *)(ipv6h+1),
-                               skb->len - sizeof(struct ipv6hdr));
+                       *(__sum16 *)ptr = gre6_checksum(skb);
                }
        }
 
@@ -1507,6 +1518,11 @@ static const struct net_device_ops ip6gre_tap_netdev_ops = {
        .ndo_get_iflink = ip6_tnl_get_iflink,
 };
 
+#define GRE6_FEATURES (NETIF_F_SG |            \
+                      NETIF_F_FRAGLIST |       \
+                      NETIF_F_HIGHDMA |                \
+                      NETIF_F_HW_CSUM)
+
 static void ip6gre_tap_setup(struct net_device *dev)
 {
 
@@ -1540,6 +1556,9 @@ static int ip6gre_newlink(struct net *src_net, struct net_device *dev,
        nt->net = dev_net(dev);
        ip6gre_tnl_link_config(nt, !tb[IFLA_MTU]);
 
+       dev->features           |= GRE6_FEATURES;
+       dev->hw_features        |= GRE6_FEATURES;
+
        /* Can use a lockless transmit, unless we generate output sequences */
        if (!(nt->parms.o_flags & GRE_SEQ))
                dev->features |= NETIF_F_LLTX;