[SRU][Trusty][PATCH 2/2] netvsc: fix incorrect receive checksum offloading

Joseph Salisbury joseph.salisbury at canonical.com
Thu Dec 8 20:13:07 UTC 2016

From: Stephen Hemminger <sthemmin at microsoft.com>

BugLink: http://bugs.launchpad.net/bugs/1636656

The Hyper-V netvsc driver was looking at the incorrect status bits
in the checksum info. It was setting the receive checksum unnecessary
flag based on the IP header checksum being correct. The checksum
flag is skb is about TCP and UDP checksum status. Because of this
bug, any packet received with bad TCP checksum would be passed
up the stack and to the application causing data corruption.
The problem is reproducible via netcat and netem.

This had a side effect of not doing receive checksum offload
on IPv6. The driver was also also always doing checksum offload
independent of the checksum setting done via ethtool.

Signed-off-by: Stephen Hemminger <sthemmin at microsoft.com>
Signed-off-by: David S. Miller <davem at davemloft.net>
(cherry picked from commit e52fed7177f74382f742c27de2cc5314790aebb6)
Signed-off-by: Joseph Salisbury <joseph.salisbury at canonical.com>
 drivers/net/hyperv/netvsc_drv.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 81d2933..d3132f0 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -294,15 +294,18 @@ int netvsc_recv_callback(struct hv_device *device_obj,
 	skb->protocol = eth_type_trans(skb, net);
-	if (csum_info) {
-		/* We only look at the IP checksum here.
-		 * Should we be dropping the packet if checksum
-		 * failed? How do we deal with other checksums - TCP/UDP?
-		 */
-		if (csum_info->receive.ip_checksum_succeeded)
+	/* skb is already created with CHECKSUM_NONE */
+	skb_checksum_none_assert(skb);
+	/*
+	 * In Linux, the IP checksum is always checked.
+	 * Do L4 checksum offload if enabled and present.
+	 */
+	if (csum_info && (net->features & NETIF_F_RXCSUM)) {
+		if (csum_info->receive.tcp_checksum_succeeded ||
+		    csum_info->receive.udp_checksum_succeeded)
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
-		else
-			skb->ip_summed = CHECKSUM_NONE;
 	if (packet->vlan_tci & VLAN_TAG_PRESENT)

More information about the kernel-team mailing list