]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
i40e/i40evf: Enable support for SKB_GSO_UDP_TUNNEL_CSUM
authorAlexander Duyck <aduyck@mirantis.com>
Mon, 25 Jan 2016 05:17:29 +0000 (21:17 -0800)
committerTim Gardner <tim.gardner@canonical.com>
Wed, 6 Apr 2016 09:20:49 +0000 (10:20 +0100)
BugLink: http://bugs.launchpad.net/bugs/1547674
The XL722 has support for providing the outer UDP tunnel checksum on
transmits.  Make use of this feature to support segmenting UDP tunnels with
outer checksums enabled.

Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
(cherry picked from net-next commit 5453205cd0975b845f6f8837f0c2b7c8cb80fcf8)
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/i40evf/i40e_txrx.c

index 2aced1d5ad90db5ff88b9696330517d60360d1de..26b7b8d6ae6c74a0c495be05aa818894ff5607b4 100644 (file)
@@ -2273,6 +2273,7 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
        } ip;
        union {
                struct tcphdr *tcp;
+               struct udphdr *udp;
                unsigned char *hdr;
        } l4;
        u32 paylen, l4_offset;
@@ -2299,7 +2300,18 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
                ip.v6->payload_len = 0;
        }
 
-       if (skb_shinfo(skb)->gso_type & (SKB_GSO_UDP_TUNNEL | SKB_GSO_GRE)) {
+       if (skb_shinfo(skb)->gso_type & (SKB_GSO_UDP_TUNNEL | SKB_GSO_GRE |
+                                        SKB_GSO_UDP_TUNNEL_CSUM)) {
+               if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM) {
+                       /* determine offset of outer transport header */
+                       l4_offset = l4.hdr - skb->data;
+
+                       /* remove payload length from outer checksum */
+                       paylen = (__force u16)l4.udp->check;
+                       paylen += ntohs(1) * (u16)~(skb->len - l4_offset);
+                       l4.udp->check = ~csum_fold((__force __wsum)paylen);
+               }
+
                /* reset pointers to inner headers */
                ip.hdr = skb_inner_network_header(skb);
                l4.hdr = skb_inner_transport_header(skb);
@@ -2461,6 +2473,11 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
                tunnel |= ((ip.hdr - l4.hdr) / 2) <<
                          I40E_TXD_CTX_QW0_NATLEN_SHIFT;
 
+               /* indicate if we need to offload outer UDP header */
+               if ((*tx_flags & I40E_TX_FLAGS_TSO) &&
+                   (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM))
+                       tunnel |= I40E_TXD_CTX_QW0_L4T_CS_MASK;
+
                /* record tunnel offload values */
                *cd_tunneling |= tunnel;
 
index 2521a466d4918e705736ac8fb49e5e01b2a3a124..969abe72277b6e9b41b468b69943be69b0418c24 100644 (file)
@@ -1533,6 +1533,7 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
        } ip;
        union {
                struct tcphdr *tcp;
+               struct udphdr *udp;
                unsigned char *hdr;
        } l4;
        u32 paylen, l4_offset;
@@ -1559,7 +1560,18 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
                ip.v6->payload_len = 0;
        }
 
-       if (skb_shinfo(skb)->gso_type & (SKB_GSO_UDP_TUNNEL | SKB_GSO_GRE)) {
+       if (skb_shinfo(skb)->gso_type & (SKB_GSO_UDP_TUNNEL | SKB_GSO_GRE |
+                                        SKB_GSO_UDP_TUNNEL_CSUM)) {
+               if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM) {
+                       /* determine offset of outer transport header */
+                       l4_offset = l4.hdr - skb->data;
+
+                       /* remove payload length from outer checksum */
+                       paylen = (__force u16)l4.udp->check;
+                       paylen += ntohs(1) * (u16)~(skb->len - l4_offset);
+                       l4.udp->check = ~csum_fold((__force __wsum)paylen);
+               }
+
                /* reset pointers to inner headers */
                ip.hdr = skb_inner_network_header(skb);
                l4.hdr = skb_inner_transport_header(skb);
@@ -1679,6 +1691,11 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
                tunnel |= ((ip.hdr - l4.hdr) / 2) <<
                          I40E_TXD_CTX_QW0_NATLEN_SHIFT;
 
+               /* indicate if we need to offload outer UDP header */
+               if ((*tx_flags & I40E_TX_FLAGS_TSO) &&
+                   (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM))
+                       tunnel |= I40E_TXD_CTX_QW0_L4T_CS_MASK;
+
                /* record tunnel offload values */
                *cd_tunneling |= tunnel;