aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/hyperv/netvsc_drv.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-04-11 15:15:22 -0400
committerDavid S. Miller <davem@davemloft.net>2014-04-11 15:15:22 -0400
commitad20d5f673898578f9d8a156d7a4c921f5ca4584 (patch)
tree7a95879de0f7b22181a67c2e7e23e7407d97b529 /drivers/net/hyperv/netvsc_drv.c
parenteb7076182d1ae4bc4641534134ed707100d76acc (diff)
parentaf9893a3dc790ae0c4d3e68adde12bc3cb9c63fa (diff)
Merge branch 'hyperv'
K. Y. Srinivasan says: ==================== Fix issues with Heper-V network offload code WS2008 R2 does not support udp checksum offload. Furthermore, ws2012 and ws2012 r2 have issues offloading udp checksum from Linux guests. This patch-set addresses these issues as well as other bug fixes. Please apply. In this version, I have addressed the comment from David Miller with reagards to COWing the skb prior to modifying the header (patch 3/3). ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/hyperv/netvsc_drv.c')
-rw-r--r--drivers/net/hyperv/netvsc_drv.c30
1 files changed, 28 insertions, 2 deletions
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 4e4cf9e0c8d7..31e55fba7cad 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -319,7 +319,9 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
319 packet = kzalloc(sizeof(struct hv_netvsc_packet) + 319 packet = kzalloc(sizeof(struct hv_netvsc_packet) +
320 (num_data_pgs * sizeof(struct hv_page_buffer)) + 320 (num_data_pgs * sizeof(struct hv_page_buffer)) +
321 sizeof(struct rndis_message) + 321 sizeof(struct rndis_message) +
322 NDIS_VLAN_PPI_SIZE, GFP_ATOMIC); 322 NDIS_VLAN_PPI_SIZE +
323 NDIS_CSUM_PPI_SIZE +
324 NDIS_LSO_PPI_SIZE, GFP_ATOMIC);
323 if (!packet) { 325 if (!packet) {
324 /* out of memory, drop packet */ 326 /* out of memory, drop packet */
325 netdev_err(net, "unable to allocate hv_netvsc_packet\n"); 327 netdev_err(net, "unable to allocate hv_netvsc_packet\n");
@@ -396,7 +398,30 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
396 csum_info->transmit.tcp_checksum = 1; 398 csum_info->transmit.tcp_checksum = 1;
397 csum_info->transmit.tcp_header_offset = hdr_offset; 399 csum_info->transmit.tcp_header_offset = hdr_offset;
398 } else if (net_trans_info & INFO_UDP) { 400 } else if (net_trans_info & INFO_UDP) {
399 csum_info->transmit.udp_checksum = 1; 401 /* UDP checksum offload is not supported on ws2008r2.
402 * Furthermore, on ws2012 and ws2012r2, there are some
403 * issues with udp checksum offload from Linux guests.
404 * (these are host issues).
405 * For now compute the checksum here.
406 */
407 struct udphdr *uh;
408 u16 udp_len;
409
410 ret = skb_cow_head(skb, 0);
411 if (ret)
412 goto drop;
413
414 uh = udp_hdr(skb);
415 udp_len = ntohs(uh->len);
416 uh->check = 0;
417 uh->check = csum_tcpudp_magic(ip_hdr(skb)->saddr,
418 ip_hdr(skb)->daddr,
419 udp_len, IPPROTO_UDP,
420 csum_partial(uh, udp_len, 0));
421 if (uh->check == 0)
422 uh->check = CSUM_MANGLED_0;
423
424 csum_info->transmit.udp_checksum = 0;
400 } 425 }
401 goto do_send; 426 goto do_send;
402 427
@@ -436,6 +461,7 @@ do_send:
436 461
437 ret = netvsc_send(net_device_ctx->device_ctx, packet); 462 ret = netvsc_send(net_device_ctx->device_ctx, packet);
438 463
464drop:
439 if (ret == 0) { 465 if (ret == 0) {
440 net->stats.tx_bytes += skb->len; 466 net->stats.tx_bytes += skb->len;
441 net->stats.tx_packets++; 467 net->stats.tx_packets++;