Commit ad19bc8a authored by stephen hemminger's avatar stephen hemminger Committed by David S. Miller

netvsc: fix checksum on UDP IPV6

The software calculation of UDP checksum in Netvsc driver was
only handling IPv4 case. By using skb_checksum_help() instead
all protocols can be handled. Rearrange code to eliminate goto
and look like other drivers.

This is a temporary solution; recent versions of Window Server etc
do support UDP checksum offload, just need to do the appropriate negotiation
with host to validate before using. This will be done in later patch.

Please queue this for -stable as well.
Signed-off-by: default avatarStephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ab102b80
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <net/arp.h> #include <net/arp.h>
#include <net/route.h> #include <net/route.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/udp.h>
#include <net/pkt_sched.h> #include <net/pkt_sched.h>
#include "hyperv_net.h" #include "hyperv_net.h"
...@@ -442,8 +443,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) ...@@ -442,8 +443,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
} }
net_trans_info = get_net_transport_info(skb, &hdr_offset); net_trans_info = get_net_transport_info(skb, &hdr_offset);
if (net_trans_info == TRANSPORT_INFO_NOT_IP)
goto do_send;
/* /*
* Setup the sendside checksum offload only if this is not a * Setup the sendside checksum offload only if this is not a
...@@ -478,56 +477,29 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) ...@@ -478,56 +477,29 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
} }
lso_info->lso_v2_transmit.tcp_header_offset = hdr_offset; lso_info->lso_v2_transmit.tcp_header_offset = hdr_offset;
lso_info->lso_v2_transmit.mss = skb_shinfo(skb)->gso_size; lso_info->lso_v2_transmit.mss = skb_shinfo(skb)->gso_size;
goto do_send; } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
} if (net_trans_info & INFO_TCP) {
rndis_msg_size += NDIS_CSUM_PPI_SIZE;
if ((skb->ip_summed == CHECKSUM_NONE) || ppi = init_ppi_data(rndis_msg, NDIS_CSUM_PPI_SIZE,
(skb->ip_summed == CHECKSUM_UNNECESSARY)) TCPIP_CHKSUM_PKTINFO);
goto do_send;
csum_info = (struct ndis_tcp_ip_checksum_info *)((void *)ppi +
rndis_msg_size += NDIS_CSUM_PPI_SIZE; ppi->ppi_offset);
ppi = init_ppi_data(rndis_msg, NDIS_CSUM_PPI_SIZE,
TCPIP_CHKSUM_PKTINFO); if (net_trans_info & (INFO_IPV4 << 16))
csum_info->transmit.is_ipv4 = 1;
csum_info = (struct ndis_tcp_ip_checksum_info *)((void *)ppi + else
ppi->ppi_offset); csum_info->transmit.is_ipv6 = 1;
if (net_trans_info & (INFO_IPV4 << 16)) csum_info->transmit.tcp_checksum = 1;
csum_info->transmit.is_ipv4 = 1; csum_info->transmit.tcp_header_offset = hdr_offset;
else } else {
csum_info->transmit.is_ipv6 = 1; /* UDP checksum (and other) offload is not supported. */
if (skb_checksum_help(skb))
if (net_trans_info & INFO_TCP) { goto drop;
csum_info->transmit.tcp_checksum = 1; }
csum_info->transmit.tcp_header_offset = hdr_offset;
} else if (net_trans_info & INFO_UDP) {
/* UDP checksum offload is not supported on ws2008r2.
* Furthermore, on ws2012 and ws2012r2, there are some
* issues with udp checksum offload from Linux guests.
* (these are host issues).
* For now compute the checksum here.
*/
struct udphdr *uh;
u16 udp_len;
ret = skb_cow_head(skb, 0);
if (ret)
goto no_memory;
uh = udp_hdr(skb);
udp_len = ntohs(uh->len);
uh->check = 0;
uh->check = csum_tcpudp_magic(ip_hdr(skb)->saddr,
ip_hdr(skb)->daddr,
udp_len, IPPROTO_UDP,
csum_partial(uh, udp_len, 0));
if (uh->check == 0)
uh->check = CSUM_MANGLED_0;
csum_info->transmit.udp_checksum = 0;
} }
do_send:
/* Start filling in the page buffers with the rndis hdr */ /* Start filling in the page buffers with the rndis hdr */
rndis_msg->msg_len += rndis_msg_size; rndis_msg->msg_len += rndis_msg_size;
packet->total_data_buflen = rndis_msg->msg_len; packet->total_data_buflen = rndis_msg->msg_len;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment