hv_netvsc: Fix IP header checksum for coalesced packets [Linux 5.0]

hv_netvsc: Fix IP header checksum for coalesced packets [Linux 5.0]

This Linux kernel change "hv_netvsc: Fix IP header checksum for coalesced packets" is included in the Linux 5.0 release. This change is authored by Haiyang Zhang <haiyangz [at] microsoft.com> on Fri Feb 22 18:25:03 2019 +0000. The commit for this change in Linux stable tree is bf48648 (patch).

hv_netvsc: Fix IP header checksum for coalesced packets

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 <[email protected]>
Signed-off-by: David S. Miller <[email protected]>

There are 22 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/net/hyperv/netvsc_drv.c | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 256adbd..cf48970 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -744,6 +744,14 @@ void netvsc_linkstatus_callback(struct net_device *net,
    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 netvsc_channel *nvchan)
 {
@@ -770,9 +778,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 ||

Leave a Reply

Your email address will not be published. Required fields are marked *