summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2010-10-22 04:12:19 +0000
committerDavid S. Miller <davem@davemloft.net>2010-10-27 11:37:29 -0700
commitaf1905dbec44445d75851996819ac2203670bd0f (patch)
tree0b34c62feeda057f5cb7233875b2b14b4228b2f1
parentcd0ea2419544cfc4ccbf8ee0087d0d9f109852d2 (diff)
downloadlinux-af1905dbec44445d75851996819ac2203670bd0f.tar.gz
linux-af1905dbec44445d75851996819ac2203670bd0f.tar.bz2
linux-af1905dbec44445d75851996819ac2203670bd0f.zip
net: Fix some corner cases in dev_can_checksum()
dev_can_checksum() incorrectly returns true in these cases: 1. The skb has both out-of-band and in-band VLAN tags and the device supports checksum offload for the encapsulated protocol but only with one layer of encapsulation. 2. The skb has a VLAN tag and the device supports generic checksumming but not in conjunction with VLAN encapsulation. Rearrange the VLAN tag checks to avoid these. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/core/dev.c16
1 files changed, 6 insertions, 10 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index e8a8dc19365b..3c5fbfbb3181 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1696,22 +1696,18 @@ static bool can_checksum_protocol(unsigned long features, __be16 protocol)
static bool dev_can_checksum(struct net_device *dev, struct sk_buff *skb)
{
+ __be16 protocol = skb->protocol;
int features = dev->features;
- if (vlan_tx_tag_present(skb))
+ if (vlan_tx_tag_present(skb)) {
features &= dev->vlan_features;
-
- if (can_checksum_protocol(features, skb->protocol))
- return true;
-
- if (skb->protocol == htons(ETH_P_8021Q)) {
+ } else if (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;
+ protocol = veh->h_vlan_encapsulated_proto;
+ features &= dev->vlan_features;
}
- return false;
+ return can_checksum_protocol(features, protocol);
}
/**