diff options
author | David S. Miller <davem@davemloft.net> | 2008-06-17 05:25:48 +0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-06-17 05:25:48 +0400 |
commit | caea902f72b053fd0c76d0d3b6b2e057beb3fc64 (patch) | |
tree | 74e8d476b2c51480420e2ef7c9bbae249b6edbc9 /net/core | |
parent | 0b4419162aa6c4204843f3a13b48d9ab821d3167 (diff) | |
parent | 65c3e4715b1b934f8dcc002d9f46b4371ca7a9b1 (diff) | |
download | linux-caea902f72b053fd0c76d0d3b6b2e057beb3fc64.tar.xz |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts:
drivers/net/wireless/rt2x00/Kconfig
drivers/net/wireless/rt2x00/rt2x00usb.c
net/sctp/protocol.c
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/dev.c | 34 |
1 files changed, 26 insertions, 8 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 582963077877..68d8df0992ab 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -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: |