|
@@ -1509,9 +1509,11 @@ int dev_queue_xmit(struct sk_buff *skb)
|
|
|
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)))
|
|
|
+ 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;
|
|
|
}
|
|
@@ -3107,6 +3109,22 @@ int register_netdevice(struct net_device *dev)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /* Fix illegal checksum combinations */
|
|
|
+ if ((dev->features & NETIF_F_HW_CSUM) &&
|
|
|
+ (dev->features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
|
|
|
+ printk(KERN_NOTICE "%s: mixed HW and IP checksum settings.\n",
|
|
|
+ dev->name);
|
|
|
+ dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((dev->features & NETIF_F_NO_CSUM) &&
|
|
|
+ (dev->features & (NETIF_F_HW_CSUM|NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
|
|
|
+ printk(KERN_NOTICE "%s: mixed no checksumming and other settings.\n",
|
|
|
+ dev->name);
|
|
|
+ dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
/* Fix illegal SG+CSUM combinations. */
|
|
|
if ((dev->features & NETIF_F_SG) &&
|
|
|
!(dev->features & NETIF_F_ALL_CSUM)) {
|