]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
hv_netvsc: Fix IP header checksum for coalesced packets
authorHaiyang Zhang <haiyangz@microsoft.com>
Fri, 22 Feb 2019 18:25:03 +0000 (18:25 +0000)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Wed, 14 Aug 2019 09:18:49 +0000 (11:18 +0200)
BugLink: https://bugs.launchpad.net/bugs/1837813
[ 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: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
drivers/net/hyperv/netvsc_drv.c

index 5331f496d43d662c74ab413402f53b0490d2717b..6e5c666dd14b1e30c30d3656c3f6bf22378a6333 100644 (file)
@@ -755,6 +755,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 napi_struct *napi,
                                             const struct ndis_tcp_ip_checksum_info *csum_info,
@@ -778,9 +786,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 ||