Commit 09067122 authored by Alexander Duyck's avatar Alexander Duyck Committed by David S. Miller

net/mlx4_en: Add support for inner IPv6 checksum offloads and TSO

>From what I can tell the ConnectX-3 will support an inner IPv6 checksum and
segmentation offload, however it cannot support outer IPv6 headers.  This
assumption is based on the fact that I could see the checksum being
offloaded for inner header on IPv4 tunnels, but not on IPv6 tunnels.

For this reason I am adding the feature to the hw_enc_features and adding
an extra check to the features_check call that will disable GSO and
checksum offload in the case that the encapsulated frame has an outer IP
version of that is not 4.  The check in mlx4_en_features_check could be
removed if at some point in the future a fix is found that allows the
hardware to offload segmentation/checksum on tunnels with an outer IPv6
header.
Signed-off-by: default avatarAlexander Duyck <aduyck@mirantis.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3c9346b2
...@@ -2357,8 +2357,10 @@ static void mlx4_en_add_vxlan_offloads(struct work_struct *work) ...@@ -2357,8 +2357,10 @@ static void mlx4_en_add_vxlan_offloads(struct work_struct *work)
} }
/* set offloads */ /* set offloads */
priv->dev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM | priv->dev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_TSO | NETIF_F_GSO_UDP_TUNNEL | NETIF_F_RXCSUM |
NETIF_F_TSO | NETIF_F_TSO6 |
NETIF_F_GSO_UDP_TUNNEL |
NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_UDP_TUNNEL_CSUM |
NETIF_F_GSO_PARTIAL; NETIF_F_GSO_PARTIAL;
} }
...@@ -2369,8 +2371,10 @@ static void mlx4_en_del_vxlan_offloads(struct work_struct *work) ...@@ -2369,8 +2371,10 @@ static void mlx4_en_del_vxlan_offloads(struct work_struct *work)
struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv, struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
vxlan_del_task); vxlan_del_task);
/* unset offloads */ /* unset offloads */
priv->dev->hw_enc_features &= ~(NETIF_F_IP_CSUM | NETIF_F_RXCSUM | priv->dev->hw_enc_features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_TSO | NETIF_F_GSO_UDP_TUNNEL | NETIF_F_RXCSUM |
NETIF_F_TSO | NETIF_F_TSO6 |
NETIF_F_GSO_UDP_TUNNEL |
NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_UDP_TUNNEL_CSUM |
NETIF_F_GSO_PARTIAL); NETIF_F_GSO_PARTIAL);
...@@ -2431,7 +2435,18 @@ static netdev_features_t mlx4_en_features_check(struct sk_buff *skb, ...@@ -2431,7 +2435,18 @@ static netdev_features_t mlx4_en_features_check(struct sk_buff *skb,
netdev_features_t features) netdev_features_t features)
{ {
features = vlan_features_check(skb, features); features = vlan_features_check(skb, features);
return vxlan_features_check(skb, features); features = vxlan_features_check(skb, features);
/* The ConnectX-3 doesn't support outer IPv6 checksums but it does
* support inner IPv6 checksums and segmentation so we need to
* strip that feature if this is an IPv6 encapsulated frame.
*/
if (skb->encapsulation &&
(skb->ip_summed == CHECKSUM_PARTIAL) &&
(ip_hdr(skb)->version != 4))
features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
return features;
} }
#endif #endif
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/tcp.h> #include <linux/tcp.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include "mlx4_en.h" #include "mlx4_en.h"
...@@ -920,8 +921,18 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -920,8 +921,18 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
tx_ind, fragptr); tx_ind, fragptr);
if (skb->encapsulation) { if (skb->encapsulation) {
struct iphdr *ipv4 = (struct iphdr *)skb_inner_network_header(skb); union {
if (ipv4->protocol == IPPROTO_TCP || ipv4->protocol == IPPROTO_UDP) struct iphdr *v4;
struct ipv6hdr *v6;
unsigned char *hdr;
} ip;
u8 proto;
ip.hdr = skb_inner_network_header(skb);
proto = (ip.v4->version == 4) ? ip.v4->protocol :
ip.v6->nexthdr;
if (proto == IPPROTO_TCP || proto == IPPROTO_UDP)
op_own |= cpu_to_be32(MLX4_WQE_CTRL_IIP | MLX4_WQE_CTRL_ILP); op_own |= cpu_to_be32(MLX4_WQE_CTRL_IIP | MLX4_WQE_CTRL_ILP);
else else
op_own |= cpu_to_be32(MLX4_WQE_CTRL_IIP); op_own |= cpu_to_be32(MLX4_WQE_CTRL_IIP);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment