qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Stefan Hajnoczi <stefanha@redhat.com>
To: qemu-devel@nongnu.org
Cc: Peter Maydell <peter.maydell@linaro.org>,
	Dana Rubin <dana.rubin@ravellosystems.com>,
	Stefan Hajnoczi <stefanha@redhat.com>,
	Shmulik Ladkani <shmulik.ladkani@ravellosystems.com>
Subject: [Qemu-devel] [PULL for-2.4 3/7] net/vmxnet3: Fix RX TCP/UDP checksum on partially summed packets
Date: Mon, 20 Jul 2015 18:25:21 +0100	[thread overview]
Message-ID: <1437413125-24888-4-git-send-email-stefanha@redhat.com> (raw)
In-Reply-To: <1437413125-24888-1-git-send-email-stefanha@redhat.com>

From: Dana Rubin <dana.rubin@ravellosystems.com>

Convert partially summed packets to be fully checksummed.

In case csum offloaded packet, vmxnet3 implementation always passes an
RxCompDesc with the "Checksum calculated and found correct" notification
to the OS. This emulates the observed ESXi behavior.

Therefore, if packet has the NEEDS_CSUM bit set, we must calculate and
place a fully computed checksum into the tcp/udp header. Otherwise, the
OS driver will receive a checksum-correct indication but with the actual
tcp/udp checksum field having just the pseudo header csum value.

If host OS performs forwarding, it will forward an incorrectly
checksummed packet.

Signed-off-by: Dana Rubin <dana.rubin@ravellosystems.com>
Signed-off-by: Shmulik Ladkani <shmulik.ladkani@ravellosystems.com>
Message-id: 1436864116-19154-3-git-send-email-shmulik.ladkani@ravellosystems.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 hw/net/vmxnet3.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index dd22a0a..59b06b8 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -885,6 +885,63 @@ vmxnet3_get_next_rx_descr(VMXNET3State *s, bool is_head,
     }
 }
 
+/* In case packet was csum offloaded (either NEEDS_CSUM or DATA_VALID),
+ * the implementation always passes an RxCompDesc with a "Checksum
+ * calculated and found correct" to the OS (cnc=0 and tuc=1, see
+ * vmxnet3_rx_update_descr). This emulates the observed ESXi behavior.
+ *
+ * Therefore, if packet has the NEEDS_CSUM set, we must calculate
+ * and place a fully computed checksum into the tcp/udp header.
+ * Otherwise, the OS driver will receive a checksum-correct indication
+ * (CHECKSUM_UNNECESSARY), but with the actual tcp/udp checksum field
+ * having just the pseudo header csum value.
+ *
+ * While this is not a problem if packet is destined for local delivery,
+ * in the case the host OS performs forwarding, it will forward an
+ * incorrectly checksummed packet.
+ */
+static void vmxnet3_rx_need_csum_calculate(struct VmxnetRxPkt *pkt,
+                                           const void *pkt_data,
+                                           size_t pkt_len)
+{
+    struct virtio_net_hdr *vhdr;
+    bool isip4, isip6, istcp, isudp;
+    uint8_t *data;
+    int len;
+
+    if (!vmxnet_rx_pkt_has_virt_hdr(pkt)) {
+        return;
+    }
+
+    vhdr = vmxnet_rx_pkt_get_vhdr(pkt);
+    if (!VMXNET_FLAG_IS_SET(vhdr->flags, VIRTIO_NET_HDR_F_NEEDS_CSUM)) {
+        return;
+    }
+
+    vmxnet_rx_pkt_get_protocols(pkt, &isip4, &isip6, &isudp, &istcp);
+    if (!(isip4 || isip6) || !(istcp || isudp)) {
+        return;
+    }
+
+    vmxnet3_dump_virt_hdr(vhdr);
+
+    /* Validate packet len: csum_start + scum_offset + length of csum field */
+    if (pkt_len < (vhdr->csum_start + vhdr->csum_offset + 2)) {
+        VMW_PKPRN("packet len:%d < csum_start(%d) + csum_offset(%d) + 2, "
+                  "cannot calculate checksum",
+                  len, vhdr->csum_start, vhdr->csum_offset);
+        return;
+    }
+
+    data = (uint8_t *)pkt_data + vhdr->csum_start;
+    len = pkt_len - vhdr->csum_start;
+    /* Put the checksum obtained into the packet */
+    stw_be_p(data + vhdr->csum_offset, net_raw_checksum(data, len));
+
+    vhdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM;
+    vhdr->flags |= VIRTIO_NET_HDR_F_DATA_VALID;
+}
+
 static void vmxnet3_rx_update_descr(struct VmxnetRxPkt *pkt,
     struct Vmxnet3_RxCompDesc *rxcd)
 {
@@ -1898,6 +1955,7 @@ vmxnet3_receive(NetClientState *nc, const uint8_t *buf, size_t size)
 
     if (vmxnet3_rx_filter_may_indicate(s, buf, size)) {
         vmxnet_rx_pkt_set_protocols(s->rx_pkt, buf, size);
+        vmxnet3_rx_need_csum_calculate(s->rx_pkt, buf, size);
         vmxnet_rx_pkt_attach_data(s->rx_pkt, buf, size, s->rx_vlan_stripping);
         bytes_indicated = vmxnet3_indicate_packet(s) ? size : -1;
         if (bytes_indicated < size) {
-- 
2.4.3

  parent reply	other threads:[~2015-07-20 17:25 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-20 17:25 [Qemu-devel] [PULL for-2.4 0/7] Net patches Stefan Hajnoczi
2015-07-20 17:25 ` [Qemu-devel] [PULL for-2.4 1/7] socket: pass correct size in net_socket_send() Stefan Hajnoczi
2015-07-20 17:25 ` [Qemu-devel] [PULL for-2.4 2/7] net/vmxnet3: Refactor 'vmxnet_rx_pkt_attach_data' Stefan Hajnoczi
2015-07-20 17:25 ` Stefan Hajnoczi [this message]
2015-07-20 17:25 ` [Qemu-devel] [PULL for-2.4 4/7] musicpal: Drop eth_can_receive Stefan Hajnoczi
2015-07-20 17:25 ` [Qemu-devel] [PULL for-2.4 5/7] etraxfs_eth: " Stefan Hajnoczi
2015-07-20 17:25 ` [Qemu-devel] [PULL for-2.4 6/7] lan9118: Drop lan9118_can_receive Stefan Hajnoczi
2015-07-20 17:25 ` [Qemu-devel] [PULL for-2.4 7/7] net: Flush queued packets when guest resumes Stefan Hajnoczi
2015-07-21  8:20 ` [Qemu-devel] [PULL for-2.4 0/7] Net patches Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1437413125-24888-4-git-send-email-stefanha@redhat.com \
    --to=stefanha@redhat.com \
    --cc=dana.rubin@ravellosystems.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=shmulik.ladkani@ravellosystems.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).