summaryrefslogtreecommitdiffstats
path: root/src/vnet/devices/virtio/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/devices/virtio/pci.c')
-rw-r--r--src/vnet/devices/virtio/pci.c61
1 files changed, 56 insertions, 5 deletions
diff --git a/src/vnet/devices/virtio/pci.c b/src/vnet/devices/virtio/pci.c
index 3736225b25c..f53552a8436 100644
--- a/src/vnet/devices/virtio/pci.c
+++ b/src/vnet/devices/virtio/pci.c
@@ -557,6 +557,27 @@ virtio_pci_send_ctrl_msg (vlib_main_t * vm, virtio_if_t * vif,
}
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);