Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fc693a59 authored by Haiyang Zhang's avatar Haiyang Zhang Committed by Greg Kroah-Hartman
Browse files

hv_netvsc: Fix IP header checksum for coalesced packets



[ Upstream commit bf48648d650db1146b75b9bd358502431e86cf4f ]

Incoming packets may have IP header checksum verified by the host.
They may not have IP header checksum computed after coalescing.
This patch re-compute the checksum when necessary, otherwise the
packets may be dropped, because Linux network stack always checks it.

Signed-off-by: default avatarHaiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 64a458de
Loading
Loading
Loading
Loading
+19 −3
Original line number Diff line number Diff line
@@ -593,6 +593,14 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
	schedule_delayed_work(&ndev_ctx->dwork, 0);
}

static void netvsc_comp_ipcsum(struct sk_buff *skb)
{
	struct iphdr *iph = (struct iphdr *)skb->data;

	iph->check = 0;
	iph->check = ip_fast_csum(iph, iph->ihl);
}

static struct sk_buff *netvsc_alloc_recv_skb(struct net_device *net,
				struct hv_netvsc_packet *packet,
				struct ndis_tcp_ip_checksum_info *csum_info,
@@ -616,9 +624,17 @@ static struct sk_buff *netvsc_alloc_recv_skb(struct net_device *net,
	/* 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.
	/* Incoming packets may have IP header checksum verified by the host.
	 * They may not have IP header checksum computed after coalescing.
	 * We compute it here if the flags are set, because on Linux, the IP
	 * checksum is always checked.
	 */
	if (csum_info && csum_info->receive.ip_checksum_value_invalid &&
	    csum_info->receive.ip_checksum_succeeded &&
	    skb->protocol == htons(ETH_P_IP))
		netvsc_comp_ipcsum(skb);

	/* Do L4 checksum offload if enabled and present.
	 */
	if (csum_info && (net->features & NETIF_F_RXCSUM)) {
		if (csum_info->receive.tcp_checksum_succeeded ||