diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2010-10-22 04:12:19 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-10-27 11:37:29 -0700 |
commit | af1905dbec44445d75851996819ac2203670bd0f (patch) | |
tree | 0b34c62feeda057f5cb7233875b2b14b4228b2f1 | |
parent | cd0ea2419544cfc4ccbf8ee0087d0d9f109852d2 (diff) | |
download | linux-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.c | 16 |
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); } /** |