virtio: vhost gso checksum error when both indirect and mrg_rxbuf are off 59/25959/2
authorSteven Luong <sluong@cisco.com>
Tue, 17 Mar 2020 16:01:30 +0000 (09:01 -0700)
committerDamjan Marion <dmarion@me.com>
Mon, 23 Mar 2020 13:01:54 +0000 (13:01 +0000)
Turn on gso, turn off both indirect and mrg_rxbuf caused traffic received
and sent with checksum error. The problem is we are not mapping the hdr
correctly in the shared memory address.

Type: fix

Signed-off-by: Steven Luong <sluong@cisco.com>
Change-Id: I7ef3bc2755544167b0e624365988111b17399e89

src/vnet/devices/virtio/vhost_user_input.c

index 1c3e180..a371e57 100644 (file)
@@ -544,13 +544,11 @@ vhost_user_if_input (vlib_main_t * vm,
       /* This depends on the setup but is very consistent
        * So I think the CPU branch predictor will make a pretty good job
        * at optimizing the decision. */
-      u8 indirect = 0;
       if (txvq->desc[desc_current].flags & VIRTQ_DESC_F_INDIRECT)
        {
          desc_table = map_guest_mem (vui, txvq->desc[desc_current].addr,
                                      &map_hint);
          desc_current = 0;
-         indirect = 1;
          if (PREDICT_FALSE (desc_table == 0))
            {
              vlib_error_count (vm, node->node_index,
@@ -565,35 +563,36 @@ vhost_user_if_input (vlib_main_t * vm,
        {
          virtio_net_hdr_mrg_rxbuf_t *hdr;
          u8 *b_data;
-         u16 current = desc_current;
-         u32 data_offset = desc_data_offset;
+         u16 current;
 
-         if ((data_offset == desc_table[current].len) &&
-             (desc_table[current].flags & VIRTQ_DESC_F_NEXT))
-           {
-             current = desc_table[current].next;
-             data_offset = 0;
-           }
-         hdr = map_guest_mem (vui, desc_table[current].addr, &map_hint);
+         hdr = map_guest_mem (vui, desc_table[desc_current].addr, &map_hint);
          if (PREDICT_FALSE (hdr == 0))
            {
              vlib_error_count (vm, node->node_index,
                                VHOST_USER_INPUT_FUNC_ERROR_MMAP_FAIL, 1);
              goto out;
            }
-         b_data = (u8 *) hdr + data_offset;
-         if (indirect)
+         if (hdr->hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM)
            {
-             hdr = map_guest_mem (vui, desc_table[desc_current].addr,
-                                  &map_hint);
-             if (PREDICT_FALSE (hdr == 0))
+             if ((desc_data_offset == desc_table[desc_current].len) &&
+                 (desc_table[desc_current].flags & VIRTQ_DESC_F_NEXT))
                {
-                 vlib_error_count (vm, node->node_index,
-                                   VHOST_USER_INPUT_FUNC_ERROR_MMAP_FAIL, 1);
-                 goto out;
+                 current = desc_table[desc_current].next;
+                 b_data = map_guest_mem (vui, desc_table[current].addr,
+                                         &map_hint);
+                 if (PREDICT_FALSE (b_data == 0))
+                   {
+                     vlib_error_count (vm, node->node_index,
+                                       VHOST_USER_INPUT_FUNC_ERROR_MMAP_FAIL,
+                                       1);
+                     goto out;
+                   }
                }
+             else
+               b_data = (u8 *) hdr + desc_data_offset;
+
+             vhost_user_handle_rx_offload (b_head, b_data, &hdr->hdr);
            }
-         vhost_user_handle_rx_offload (b_head, b_data, &hdr->hdr);
        }
 
       while (1)