X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fdevices%2Fvirtio%2Fpci.c;h=c956e7b75fae9c791d84cd0a39dff754d77f9dad;hb=6d4af8918;hp=1f569acb00852f9be9f4f1be1302d40f1552859d;hpb=f41244f423a44c6d295895b011eec4bbeef08a8d;p=vpp.git diff --git a/src/vnet/devices/virtio/pci.c b/src/vnet/devices/virtio/pci.c index 1f569acb008..c956e7b75fa 100644 --- a/src/vnet/devices/virtio/pci.c +++ b/src/vnet/devices/virtio/pci.c @@ -110,7 +110,7 @@ virtio_pci_legacy_write_config (vlib_main_t * vm, virtio_if_t * vif, } static u64 -virtio_pci_legacy_get_features (vlib_main_t * vm, virtio_if_t * vif) +virtio_pci_legacy_get_host_features (vlib_main_t * vm, virtio_if_t * vif) { u32 features; vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_HOST_FEATURES, @@ -119,8 +119,18 @@ virtio_pci_legacy_get_features (vlib_main_t * vm, virtio_if_t * vif) } static u32 -virtio_pci_legacy_set_features (vlib_main_t * vm, virtio_if_t * vif, - u64 features) +virtio_pci_legacy_get_guest_features (vlib_main_t * vm, virtio_if_t * vif) +{ + u32 feature = 0; + vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_GUEST_FEATURES, + &feature); + vif->features = feature; + return feature; +} + +static u32 +virtio_pci_legacy_set_guest_features (vlib_main_t * vm, virtio_if_t * vif, + u64 features) { if ((features >> 32) != 0) { @@ -554,6 +564,47 @@ virtio_pci_send_ctrl_msg (vlib_main_t * vm, virtio_if_t * vif, return status; } +static int +virtio_pci_disable_offload (vlib_main_t * vm, virtio_if_t * vif) +{ + struct virtio_ctrl_msg offload_hdr; + virtio_net_ctrl_ack status = VIRTIO_NET_ERR; + + offload_hdr.ctrl.class = VIRTIO_NET_CTRL_GUEST_OFFLOADS; + offload_hdr.ctrl.cmd = VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET; + offload_hdr.status = VIRTIO_NET_ERR; + u64 offloads = 0ULL; + clib_memcpy (offload_hdr.data, &offloads, sizeof (offloads)); + + status = + virtio_pci_send_ctrl_msg (vm, vif, &offload_hdr, sizeof (offloads)); + virtio_log_debug (vif, "disable offloads"); + vif->remote_features = virtio_pci_legacy_get_host_features (vm, vif); + virtio_pci_legacy_get_guest_features (vm, vif); + return status; +} + +static int +virtio_pci_enable_checksum_offload (vlib_main_t * vm, virtio_if_t * vif) +{ + struct virtio_ctrl_msg csum_offload_hdr; + virtio_net_ctrl_ack status = VIRTIO_NET_ERR; + + csum_offload_hdr.ctrl.class = VIRTIO_NET_CTRL_GUEST_OFFLOADS; + csum_offload_hdr.ctrl.cmd = VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET; + csum_offload_hdr.status = VIRTIO_NET_ERR; + u64 offloads = 0ULL; + offloads |= VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_CSUM); + clib_memcpy (csum_offload_hdr.data, &offloads, sizeof (offloads)); + + status = + virtio_pci_send_ctrl_msg (vm, vif, &csum_offload_hdr, sizeof (offloads)); + virtio_log_debug (vif, "enable checksum offload"); + vif->remote_features = virtio_pci_legacy_get_host_features (vm, vif); + virtio_pci_legacy_get_guest_features (vm, vif); + return status; +} + static int virtio_pci_enable_gso (vlib_main_t * vm, virtio_if_t * vif) { @@ -565,15 +616,77 @@ virtio_pci_enable_gso (vlib_main_t * vm, virtio_if_t * vif) 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); + | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_TSO6); clib_memcpy (gso_hdr.data, &offloads, sizeof (offloads)); status = virtio_pci_send_ctrl_msg (vm, vif, &gso_hdr, sizeof (offloads)); virtio_log_debug (vif, "enable gso"); + vif->remote_features = virtio_pci_legacy_get_host_features (vm, vif); + virtio_pci_legacy_get_guest_features (vm, vif); return status; } +static int +virtio_pci_offloads (vlib_main_t * vm, virtio_if_t * vif, int gso_enabled, + int csum_offload_enabled) +{ + vnet_main_t *vnm = vnet_get_main (); + vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, vif->hw_if_index); + + if ((vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ)) && + (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_GUEST_OFFLOADS))) + { + if (gso_enabled + && (vif->features & (VIRTIO_FEATURE (VIRTIO_NET_F_HOST_TSO4) | + VIRTIO_FEATURE (VIRTIO_NET_F_HOST_TSO6)))) + { + if (virtio_pci_enable_gso (vm, vif)) + { + virtio_log_warning (vif, "gso is not enabled"); + } + else + { + vif->gso_enabled = 1; + vif->csum_offload_enabled = 0; + hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO | + VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD; + } + } + else if (csum_offload_enabled + && (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CSUM))) + { + if (virtio_pci_enable_checksum_offload (vm, vif)) + { + virtio_log_warning (vif, "checksum offload is not enabled"); + } + else + { + vif->csum_offload_enabled = 1; + vif->gso_enabled = 0; + hw->flags &= ~VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO; + hw->flags |= + VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD; + } + } + else + { + if (virtio_pci_disable_offload (vm, vif)) + { + virtio_log_warning (vif, "offloads are not disabled"); + } + else + { + vif->csum_offload_enabled = 0; + vif->gso_enabled = 0; + hw->flags &= ~(VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO | + VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD); + } + } + } + + return 0; +} + static int virtio_pci_enable_multiqueue (vlib_main_t * vm, virtio_if_t * vif, u16 num_queues) @@ -657,7 +770,6 @@ clib_error_t * virtio_pci_vring_init (vlib_main_t * vm, virtio_if_t * vif, u16 queue_num) { clib_error_t *error = 0; - vlib_thread_main_t *vtm = vlib_get_thread_main (); u16 queue_size = 0; virtio_vring_t *vring; struct vring vr; @@ -679,8 +791,6 @@ virtio_pci_vring_init (vlib_main_t * vm, virtio_if_t * vif, u16 queue_num) if (queue_num % 2) { - if (TX_QUEUE_ACCESS (queue_num) > vtm->n_vlib_mains) - return error; vec_validate_aligned (vif->txq_vrings, TX_QUEUE_ACCESS (queue_num), CLIB_CACHE_LINE_BYTES); vring = vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS (queue_num)); @@ -773,13 +883,14 @@ virtio_negotiate_features (vlib_main_t * vm, virtio_if_t * vif, vif->features &= ~VIRTIO_FEATURE (VIRTIO_NET_F_MTU); } - vif->features = virtio_pci_legacy_set_features (vm, vif, vif->features); + vif->features = + virtio_pci_legacy_set_guest_features (vm, vif, vif->features); } void virtio_pci_read_device_feature (vlib_main_t * vm, virtio_if_t * vif) { - vif->remote_features = virtio_pci_legacy_get_features (vm, vif); + vif->remote_features = virtio_pci_legacy_get_host_features (vm, vif); } int @@ -918,6 +1029,7 @@ virtio_pci_device_init (vlib_main_t * vm, virtio_if_t * vif, virtio_pci_create_if_args_t * args) { clib_error_t *error = 0; + vlib_thread_main_t *vtm = vlib_get_thread_main (); u8 status = 0; if ((error = virtio_pci_read_caps (vm, vif))) @@ -983,6 +1095,22 @@ virtio_pci_device_init (vlib_main_t * vm, virtio_if_t * vif, vif->num_rxqs++; } + if (i >= vtm->n_vlib_mains) + { + /* + * There is 1:1 mapping between tx queue and vpp worker thread. + * tx queue 0 is bind with thread index 0, tx queue 1 on thread + * index 1 and so on. + * Multiple worker threads can poll same tx queue when number of + * workers are more than tx queues. In this case, 1:N mapping + * between tx queue and vpp worker thread. + */ + virtio_log_debug (vif, "%s %u, %s", "tx-queue: number", + TX_QUEUE (i), + "no VPP worker thread is available"); + continue; + } + if ((error = virtio_pci_vring_init (vm, vif, TX_QUEUE (i)))) { virtio_log_warning (vif, "%s (%u) %s", "error in txq-queue", @@ -1066,7 +1194,6 @@ virtio_pci_create_if (vlib_main_t * vm, virtio_pci_create_if_args_t * args) vlib_pci_device_open (vm, (vlib_pci_addr_t *) & vif->pci_addr, virtio_pci_device_ids, &h))) { - pool_put (vim->interfaces, vif); args->rv = VNET_API_ERROR_INVALID_INTERFACE; args->error = clib_error_return (error, "pci-addr %U", format_vlib_pci_addr, @@ -1074,6 +1201,7 @@ virtio_pci_create_if (vlib_main_t * vm, virtio_pci_create_if_args_t * args) vlib_log (VLIB_LOG_LEVEL_ERR, vim->log_default, "%U: %s", format_vlib_pci_addr, &vif->pci_addr, "error encountered on pci device open"); + pool_put (vim->interfaces, vif); return; } vif->pci_dev_handle = h; @@ -1194,31 +1322,17 @@ 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)) + virtio_pci_offloads (vm, vif, args->gso_enabled, + args->checksum_offload_enabled); + + 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_GUEST_OFFLOADS) && - args->gso_enabled) - { - if (virtio_pci_enable_gso (vm, vif)) - { - virtio_log_warning (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 (vif, "multiqueue is not set"); - } + if (virtio_pci_enable_multiqueue (vm, vif, vif->max_queue_pairs)) + virtio_log_warning (vif, "multiqueue is not set"); } return; - error: virtio_pci_delete_if (vm, vif); args->rv = VNET_API_ERROR_INVALID_INTERFACE; @@ -1248,9 +1362,6 @@ 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); @@ -1315,6 +1426,25 @@ virtio_pci_delete_if (vlib_main_t * vm, virtio_if_t * vif) return 0; } +int +virtio_pci_enable_disable_offloads (vlib_main_t * vm, virtio_if_t * vif, + int gso_enabled, + int checksum_offload_enabled, + int offloads_disabled) +{ + if (vif->type != VIRTIO_IF_TYPE_PCI) + return VNET_API_ERROR_INVALID_INTERFACE; + + if (gso_enabled) + virtio_pci_offloads (vm, vif, 1, 0); + else if (checksum_offload_enabled) + virtio_pci_offloads (vm, vif, 0, 1); + else if (offloads_disabled) + virtio_pci_offloads (vm, vif, 0, 0); + + return 0; +} + /* * fd.io coding-style-patch-verification: ON *