]> www.infradead.org Git - users/jedix/linux-maple.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)
committerChuck Anderson <chuck.anderson@oracle.com>
Thu, 10 Mar 2016 16:37:40 +0000 (08:37 -0800)
Orabug: 22342532

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 commit 5453205cd0975b845f6f8837f0c2b7c8cb80fcf8)
Signed-off-by: Brian Maly <brian.maly@oracle.com>
drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/i40evf/i40e_txrx.c

index 5ad8a88b1bcca1ad73f0fb65241f525e09f35b20..1324530dbf9bac472be27baf09ab594a70965215 100644 (file)
@@ -2271,6 +2271,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;
@@ -2297,7 +2298,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);
@@ -2459,6 +2471,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 26525ca094f09a5d258cd26cca1e08d84eac4f75..ac329e8c1640746ea0f6acaa59eaba6684fbc17f 100644 (file)
@@ -1531,6 +1531,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;
@@ -1557,7 +1558,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);
@@ -1677,6 +1689,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;