diff options
Diffstat (limited to 'src/vnet/devices/virtio/pci.c')
-rw-r--r-- | src/vnet/devices/virtio/pci.c | 61 |
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); |