devices: vhost handling VHOST_USER_SET_FEATURES
[vpp.git] / src / vnet / devices / virtio / pci.c
index 3736225..1acbb32 100644 (file)
@@ -556,6 +556,27 @@ virtio_pci_send_ctrl_msg (vlib_main_t * vm, virtio_if_t * vif,
   return status;
 }
 
+static int
+virtio_pci_enable_gso (vlib_main_t * vm, virtio_if_t * vif)
+{
+  virtio_main_t *vim = &virtio_main;
+  struct virtio_ctrl_msg gso_hdr;
+  virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
+
+  gso_hdr.ctrl.class = VIRTIO_NET_CTRL_GUEST_OFFLOADS;
+  gso_hdr.ctrl.cmd = VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET;
+  gso_hdr.status = VIRTIO_NET_ERR;
+  u64 offloads = VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_CSUM)
+    | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_TSO4)
+    | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_TSO6)
+    | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_UFO);
+  clib_memcpy (gso_hdr.data, &offloads, sizeof (offloads));
+
+  status = virtio_pci_send_ctrl_msg (vm, vif, &gso_hdr, sizeof (offloads));
+  virtio_log_debug (vim, vif, "enable gso");
+  return status;
+}
+
 static int
 virtio_pci_enable_multiqueue (vlib_main_t * vm, virtio_if_t * vif,
                              u16 num_queues)
@@ -720,8 +741,18 @@ virtio_negotiate_features (vlib_main_t * vm, virtio_if_t * vif,
    * if features are not requested
    * default: all supported features
    */
-  u64 supported_features = VIRTIO_FEATURE (VIRTIO_NET_F_MTU)
+  u64 supported_features = VIRTIO_FEATURE (VIRTIO_NET_F_CSUM)
+    | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_CSUM)
+    | VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)
+    | VIRTIO_FEATURE (VIRTIO_NET_F_MTU)
     | VIRTIO_FEATURE (VIRTIO_NET_F_MAC)
+    | VIRTIO_FEATURE (VIRTIO_NET_F_GSO)
+    | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_TSO4)
+    | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_TSO6)
+    | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_UFO)
+    | VIRTIO_FEATURE (VIRTIO_NET_F_HOST_TSO4)
+    | VIRTIO_FEATURE (VIRTIO_NET_F_HOST_TSO6)
+    | VIRTIO_FEATURE (VIRTIO_NET_F_HOST_UFO)
     | VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF)
     | VIRTIO_FEATURE (VIRTIO_NET_F_STATUS)
     | VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ)
@@ -1175,14 +1206,31 @@ virtio_pci_create_if (vlib_main_t * vm, virtio_pci_create_if_args_t * args)
   else
     vnet_hw_interface_set_flags (vnm, vif->hw_if_index, 0);
 
-  if ((vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ)) &&
-      (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MQ)))
+  if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
     {
-      if (virtio_pci_enable_multiqueue (vm, vif, vif->max_queue_pairs))
-       virtio_log_warning (vim, vif, "multiqueue is not set");
+      if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) &&
+         args->gso_enabled)
+       {
+         if (virtio_pci_enable_gso (vm, vif))
+           {
+             virtio_log_warning (vim, vif, "gso is not enabled");
+           }
+         else
+           {
+             vif->gso_enabled = 1;
+             hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO;
+             vnm->interface_main.gso_interface_count++;
+           }
+       }
+      if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MQ))
+       {
+         if (virtio_pci_enable_multiqueue (vm, vif, vif->max_queue_pairs))
+           virtio_log_warning (vim, vif, "multiqueue is not set");
+       }
     }
   return;
 
+
 error:
   virtio_pci_delete_if (vm, vif);
   args->rv = VNET_API_ERROR_INVALID_INTERFACE;
@@ -1212,6 +1260,9 @@ virtio_pci_delete_if (vlib_main_t * vm, virtio_if_t * vif)
 
   virtio_pci_legacy_reset (vm, vif);
 
+  if (vif->gso_enabled)
+    vnm->interface_main.gso_interface_count--;
+
   if (vif->hw_if_index)
     {
       vnet_hw_interface_set_flags (vnm, vif->hw_if_index, 0);
@@ -1247,6 +1298,7 @@ virtio_pci_delete_if (vlib_main_t * vm, virtio_if_t * vif)
        virtio_free_used_desc (vm, vring);
       }
     vec_free (vring->buffers);
+    clib_spinlock_free (&vring->lockp);
     vlib_physmem_free (vm, vring->desc);
   }