提交 6de329e2 编写于 作者: B Ben Hutchings 提交者: David S. Miller

net: Fix test for VLAN TX checksum offload capability

Selected device feature bits can be propagated to VLAN devices, so we
can make use of TX checksum offload and TSO on VLAN-tagged packets.
However, if the physical device does not do VLAN tag insertion or
generic checksum offload then the test for TX checksum offload in
dev_queue_xmit() will see a protocol of htons(ETH_P_8021Q) and yield
false.

This splits the checksum offload test into two functions:

- can_checksum_protocol() tests a given protocol against a feature bitmask

- dev_can_checksum() first tests the skb protocol against the device
  features; if that fails and the protocol is htons(ETH_P_8021Q) then
  it tests the encapsulated protocol against the effective device
  features for VLANs
Signed-off-by: NBen Hutchings <bhutchings@solarflare.com>
Acked-by: NPatrick McHardy <kaber@trash.net>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 319fa2a2
......@@ -119,6 +119,7 @@
#include <linux/err.h>
#include <linux/ctype.h>
#include <linux/if_arp.h>
#include <linux/if_vlan.h>
#include "net-sysfs.h"
......@@ -1362,6 +1363,29 @@ void netif_device_attach(struct net_device *dev)
}
EXPORT_SYMBOL(netif_device_attach);
static bool can_checksum_protocol(unsigned long features, __be16 protocol)
{
return ((features & NETIF_F_GEN_CSUM) ||
((features & NETIF_F_IP_CSUM) &&
protocol == htons(ETH_P_IP)) ||
((features & NETIF_F_IPV6_CSUM) &&
protocol == htons(ETH_P_IPV6)));
}
static bool dev_can_checksum(struct net_device *dev, struct sk_buff *skb)
{
if (can_checksum_protocol(dev->features, skb->protocol))
return true;
if (skb->protocol == htons(ETH_P_8021Q)) {
struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
if (can_checksum_protocol(dev->features & dev->vlan_features,
veh->h_vlan_encapsulated_proto))
return true;
}
return false;
}
/*
* Invalidate hardware checksum when packet is to be mangled, and
......@@ -1640,14 +1664,8 @@ int dev_queue_xmit(struct sk_buff *skb)
if (skb->ip_summed == CHECKSUM_PARTIAL) {
skb_set_transport_header(skb, skb->csum_start -
skb_headroom(skb));
if (!(dev->features & NETIF_F_GEN_CSUM) &&
!((dev->features & NETIF_F_IP_CSUM) &&
skb->protocol == htons(ETH_P_IP)) &&
!((dev->features & NETIF_F_IPV6_CSUM) &&
skb->protocol == htons(ETH_P_IPV6)))
if (skb_checksum_help(skb))
goto out_kfree_skb;
if (!dev_can_checksum(dev, skb) && skb_checksum_help(skb))
goto out_kfree_skb;
}
gso:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册