diff options
Diffstat (limited to 'net/core/dev.c')
-rw-r--r-- | net/core/dev.c | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index fec8cf27f75d..d23972f56fc7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -1155,7 +1155,7 @@ EXPORT_SYMBOL(netif_device_attach); | |||
1155 | int skb_checksum_help(struct sk_buff *skb) | 1155 | int skb_checksum_help(struct sk_buff *skb) |
1156 | { | 1156 | { |
1157 | __wsum csum; | 1157 | __wsum csum; |
1158 | int ret = 0, offset = skb_transport_offset(skb); | 1158 | int ret = 0, offset; |
1159 | 1159 | ||
1160 | if (skb->ip_summed == CHECKSUM_COMPLETE) | 1160 | if (skb->ip_summed == CHECKSUM_COMPLETE) |
1161 | goto out_set_summed; | 1161 | goto out_set_summed; |
@@ -1171,15 +1171,16 @@ int skb_checksum_help(struct sk_buff *skb) | |||
1171 | goto out; | 1171 | goto out; |
1172 | } | 1172 | } |
1173 | 1173 | ||
1174 | offset = skb->csum_start - skb_headroom(skb); | ||
1174 | BUG_ON(offset > (int)skb->len); | 1175 | BUG_ON(offset > (int)skb->len); |
1175 | csum = skb_checksum(skb, offset, skb->len-offset, 0); | 1176 | csum = skb_checksum(skb, offset, skb->len-offset, 0); |
1176 | 1177 | ||
1177 | offset = skb->tail - skb->transport_header; | 1178 | offset = skb_headlen(skb) - offset; |
1178 | BUG_ON(offset <= 0); | 1179 | BUG_ON(offset <= 0); |
1179 | BUG_ON(skb->csum_offset + 2 > offset); | 1180 | BUG_ON(skb->csum_offset + 2 > offset); |
1180 | 1181 | ||
1181 | *(__sum16 *)(skb_transport_header(skb) + | 1182 | *(__sum16 *)(skb->head + skb->csum_start + skb->csum_offset) = |
1182 | skb->csum_offset) = csum_fold(csum); | 1183 | csum_fold(csum); |
1183 | out_set_summed: | 1184 | out_set_summed: |
1184 | skb->ip_summed = CHECKSUM_NONE; | 1185 | skb->ip_summed = CHECKSUM_NONE; |
1185 | out: | 1186 | out: |
@@ -1431,12 +1432,16 @@ int dev_queue_xmit(struct sk_buff *skb) | |||
1431 | /* If packet is not checksummed and device does not support | 1432 | /* If packet is not checksummed and device does not support |
1432 | * checksumming for this protocol, complete checksumming here. | 1433 | * checksumming for this protocol, complete checksumming here. |
1433 | */ | 1434 | */ |
1434 | if (skb->ip_summed == CHECKSUM_PARTIAL && | 1435 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
1435 | (!(dev->features & NETIF_F_GEN_CSUM) && | 1436 | skb_set_transport_header(skb, skb->csum_start - |
1436 | (!(dev->features & NETIF_F_IP_CSUM) || | 1437 | skb_headroom(skb)); |
1437 | skb->protocol != htons(ETH_P_IP)))) | 1438 | |
1438 | if (skb_checksum_help(skb)) | 1439 | if (!(dev->features & NETIF_F_GEN_CSUM) && |
1439 | goto out_kfree_skb; | 1440 | (!(dev->features & NETIF_F_IP_CSUM) || |
1441 | skb->protocol != htons(ETH_P_IP))) | ||
1442 | if (skb_checksum_help(skb)) | ||
1443 | goto out_kfree_skb; | ||
1444 | } | ||
1440 | 1445 | ||
1441 | gso: | 1446 | gso: |
1442 | spin_lock_prefetch(&dev->queue_lock); | 1447 | spin_lock_prefetch(&dev->queue_lock); |