X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fdevices%2Fvirtio%2Fpci.c;h=c956e7b75fae9c791d84cd0a39dff754d77f9dad;hb=6d4af8918;hp=b02b79d385b84f06f5366ab97cceca645f15c1dc;hpb=43b512cac2240cd679341a3bc01d548c573b8a85;p=vpp.git diff --git a/src/vnet/devices/virtio/pci.c b/src/vnet/devices/virtio/pci.c index b02b79d385b..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) { @@ -247,7 +257,6 @@ virtio_pci_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hw, static clib_error_t * virtio_pci_get_max_virtqueue_pairs (vlib_main_t * vm, virtio_if_t * vif) { - virtio_main_t *vim = &virtio_main; virtio_net_config_t config; clib_error_t *error = 0; u16 max_queue_pairs = 1; @@ -261,7 +270,7 @@ virtio_pci_get_max_virtqueue_pairs (vlib_main_t * vm, virtio_if_t * vif) max_queue_pairs = config.max_virtqueue_pairs; } - virtio_log_debug (vim, vif, "max queue pair is %x", max_queue_pairs); + virtio_log_debug (vif, "max queue pair is %x", max_queue_pairs); if (max_queue_pairs < 1 || max_queue_pairs > 0x8000) return clib_error_return (error, "max queue pair is %x", max_queue_pairs); @@ -452,31 +461,25 @@ debug_device_config_space (vlib_main_t * vm, virtio_if_t * vif) } } -struct virtio_ctrl_mq_status_hdr +struct virtio_ctrl_msg { struct virtio_net_ctrl_hdr ctrl; - struct virtio_net_ctrl_mq num_mqs; virtio_net_ctrl_ack status; + u8 data[1024]; }; static int -virtio_pci_enable_multiqueue (vlib_main_t * vm, virtio_if_t * vif, - u16 num_queues) +virtio_pci_send_ctrl_msg (vlib_main_t * vm, virtio_if_t * vif, + struct virtio_ctrl_msg *data, u32 len) { - virtio_main_t *vim = &virtio_main; virtio_vring_t *vring = vif->cxq_vring; + virtio_net_ctrl_ack status = VIRTIO_NET_ERR; + struct virtio_ctrl_msg result; u32 buffer_index; vlib_buffer_t *b; u16 used, next, avail; u16 sz = vring->size; u16 mask = sz - 1; - struct virtio_ctrl_mq_status_hdr mq_hdr, result; - virtio_net_ctrl_ack status = VIRTIO_NET_ERR; - - mq_hdr.ctrl.class = VIRTIO_NET_CTRL_MQ; - mq_hdr.ctrl.cmd = VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET; - mq_hdr.status = VIRTIO_NET_ERR; - mq_hdr.num_mqs.virtqueue_pairs = num_queues; used = vring->desc_in_use; next = vring->desc_next; @@ -492,8 +495,8 @@ virtio_pci_enable_multiqueue (vlib_main_t * vm, virtio_if_t * vif, * previous offset. */ b->current_data = 0; - clib_memcpy (vlib_buffer_get_current (b), &mq_hdr, - sizeof (struct virtio_ctrl_mq_status_hdr)); + clib_memcpy (vlib_buffer_get_current (b), data, + sizeof (struct virtio_ctrl_msg)); d->flags = VRING_DESC_F_NEXT; d->addr = vlib_buffer_get_current_pa (vm, b); d->len = sizeof (struct virtio_net_ctrl_hdr); @@ -506,8 +509,8 @@ virtio_pci_enable_multiqueue (vlib_main_t * vm, virtio_if_t * vif, d = &vring->desc[next]; d->flags = VRING_DESC_F_NEXT; d->addr = vlib_buffer_get_current_pa (vm, b) + - STRUCT_OFFSET_OF (struct virtio_ctrl_mq_status_hdr, num_mqs); - d->len = sizeof (struct virtio_net_ctrl_mq); + STRUCT_OFFSET_OF (struct virtio_ctrl_msg, data); + d->len = len; next = (next + 1) & mask; d->next = next; used++; @@ -515,8 +518,8 @@ virtio_pci_enable_multiqueue (vlib_main_t * vm, virtio_if_t * vif, d = &vring->desc[next]; d->flags = VRING_DESC_F_WRITE; d->addr = vlib_buffer_get_current_pa (vm, b) + - STRUCT_OFFSET_OF (struct virtio_ctrl_mq_status_hdr, status); - d->len = sizeof (mq_hdr.status); + STRUCT_OFFSET_OF (struct virtio_ctrl_msg, status); + d->len = sizeof (data->status); next = (next + 1) & mask; used++; @@ -530,7 +533,6 @@ virtio_pci_enable_multiqueue (vlib_main_t * vm, virtio_if_t * vif, virtio_kick (vm, vring, vif); } - clib_memset (&result, 0, sizeof (result)); u16 last = vring->last_used_idx, n_left = 0; n_left = vring->used->idx - last; @@ -555,15 +557,153 @@ virtio_pci_enable_multiqueue (vlib_main_t * vm, virtio_if_t * vif, CLIB_MEMORY_BARRIER (); clib_memcpy (&result, vlib_buffer_get_current (b), - sizeof (struct virtio_ctrl_mq_status_hdr)); - - virtio_log_debug (vim, vif, "multi-queue enable status on Ctrl queue : %u", - result.status); + sizeof (struct virtio_ctrl_msg)); + virtio_log_debug (vif, "ctrl-queue: status %u", result.status); status = result.status; vlib_buffer_free (vm, &buffer_index, 1); 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) +{ + 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); + 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) +{ + struct virtio_ctrl_msg mq_hdr; + virtio_net_ctrl_ack status = VIRTIO_NET_ERR; + + mq_hdr.ctrl.class = VIRTIO_NET_CTRL_MQ; + mq_hdr.ctrl.cmd = VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET; + mq_hdr.status = VIRTIO_NET_ERR; + clib_memcpy (mq_hdr.data, &num_queues, sizeof (num_queues)); + + status = virtio_pci_send_ctrl_msg (vm, vif, &mq_hdr, sizeof (num_queues)); + virtio_log_debug (vif, "multi-queue enable %u queues", num_queues); + return status; +} + static u8 virtio_pci_queue_size_valid (u16 qsz) { @@ -579,7 +719,6 @@ virtio_pci_control_vring_init (vlib_main_t * vm, virtio_if_t * vif, u16 queue_num) { clib_error_t *error = 0; - virtio_main_t *vim = &virtio_main; u16 queue_size = 0; virtio_vring_t *vring; struct vring vr; @@ -619,7 +758,7 @@ virtio_pci_control_vring_init (vlib_main_t * vm, virtio_if_t * vif, ASSERT (vring->buffers == 0); vring->size = queue_size; - virtio_log_debug (vim, vif, "control-queue: number %u, size %u", queue_num, + virtio_log_debug (vif, "control-queue: number %u, size %u", queue_num, queue_size); virtio_pci_legacy_setup_queue (vm, vif, queue_num, ptr); vring->kick_fd = -1; @@ -631,8 +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; - virtio_main_t *vim = &virtio_main; - vlib_thread_main_t *vtm = vlib_get_thread_main (); u16 queue_size = 0; virtio_vring_t *vring; struct vring vr; @@ -654,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)); @@ -684,26 +819,14 @@ virtio_pci_vring_init (vlib_main_t * vm, virtio_if_t * vif, u16 queue_num) ASSERT (vring->buffers == 0); vec_validate_aligned (vring->buffers, queue_size, CLIB_CACHE_LINE_BYTES); - ASSERT (vring->indirect_buffers == 0); - vec_validate_aligned (vring->indirect_buffers, queue_size, - CLIB_CACHE_LINE_BYTES); if (queue_num % 2) { - u32 n_alloc = 0; - do - { - if (n_alloc < queue_size) - n_alloc = - vlib_buffer_alloc (vm, vring->indirect_buffers + n_alloc, - queue_size - n_alloc); - } - while (n_alloc != queue_size); - virtio_log_debug (vim, vif, "tx-queue: number %u, size %u", queue_num, + virtio_log_debug (vif, "tx-queue: number %u, size %u", queue_num, queue_size); } else { - virtio_log_debug (vim, vif, "rx-queue: number %u, size %u", queue_num, + virtio_log_debug (vif, "rx-queue: number %u, size %u", queue_num, queue_size); } vring->size = queue_size; @@ -722,8 +845,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) @@ -750,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 @@ -796,14 +930,13 @@ clib_error_t * virtio_pci_read_caps (vlib_main_t * vm, virtio_if_t * vif) { clib_error_t *error = 0; - virtio_main_t *vim = &virtio_main; struct virtio_pci_cap cap; u8 pos, common_cfg = 0, notify_base = 0, dev_cfg = 0, isr = 0, pci_cfg = 0; vlib_pci_dev_handle_t h = vif->pci_dev_handle; if ((error = vlib_pci_read_config_u8 (vm, h, PCI_CAPABILITY_LIST, &pos))) { - virtio_log_error (vim, vif, "error in reading capabilty list position"); + virtio_log_error (vif, "error in reading capabilty list position"); clib_error_return (error, "error in reading capabilty list position"); } while (pos) @@ -812,7 +945,7 @@ virtio_pci_read_caps (vlib_main_t * vm, virtio_if_t * vif) vlib_pci_read_write_config (vm, h, VLIB_READ, pos, &cap, sizeof (cap)))) { - virtio_log_error (vim, vif, "%s [%2x]", + virtio_log_error (vif, "%s [%2x]", "error in reading the capability at", pos); clib_error_return (error, "error in reading the capability at [%2x]", pos); @@ -830,29 +963,29 @@ virtio_pci_read_caps (vlib_main_t * vm, virtio_if_t * vif) pos + 2); table_size = flags & table_size_mask; - virtio_log_debug (vim, vif, "flags:0x%x %s 0x%x", flags, + virtio_log_debug (vif, "flags:0x%x %s 0x%x", flags, "msix interrupt vector table-size", table_size); if (flags & PCI_MSIX_ENABLE) { - virtio_log_debug (vim, vif, "msix interrupt enabled"); + virtio_log_debug (vif, "msix interrupt enabled"); vif->msix_enabled = VIRTIO_MSIX_ENABLED; } else { - virtio_log_debug (vim, vif, "msix interrupt disabled"); + virtio_log_debug (vif, "msix interrupt disabled"); vif->msix_enabled = VIRTIO_MSIX_DISABLED; } } if (cap.cap_vndr != PCI_CAP_ID_VNDR) { - virtio_log_debug (vim, vif, "[%2x] %s %2x ", pos, + virtio_log_debug (vif, "[%2x] %s %2x ", pos, "skipping non VNDR cap id:", cap.cap_vndr); goto next; } - virtio_log_debug (vim, vif, + virtio_log_debug (vif, "[%4x] cfg type: %u, bar: %u, offset: %04x, len: %u", pos, cap.cfg_type, cap.bar, cap.offset, cap.length); switch (cap.cfg_type) @@ -880,14 +1013,14 @@ virtio_pci_read_caps (vlib_main_t * vm, virtio_if_t * vif) if (common_cfg == 0 || notify_base == 0 || dev_cfg == 0 || isr == 0) { - virtio_log_debug (vim, vif, "legacy virtio pci device found"); + virtio_log_debug (vif, "legacy virtio pci device found"); return error; } if (!pci_cfg) clib_error_return (error, "modern virtio pci device found"); - virtio_log_debug (vim, vif, "transitional virtio pci device found"); + virtio_log_debug (vif, "transitional virtio pci device found"); return error; } @@ -896,7 +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; - virtio_main_t *vim = &virtio_main; + vlib_thread_main_t *vtm = vlib_get_thread_main (); u8 status = 0; if ((error = virtio_pci_read_caps (vm, vif))) @@ -904,7 +1037,7 @@ virtio_pci_device_init (vlib_main_t * vm, virtio_if_t * vif, if (virtio_pci_reset_device (vm, vif) < 0) { - virtio_log_error (vim, vif, "Failed to reset the device"); + virtio_log_error (vif, "Failed to reset the device"); clib_error_return (error, "Failed to reset the device"); } /* @@ -920,7 +1053,7 @@ virtio_pci_device_init (vlib_main_t * vm, virtio_if_t * vif, status = virtio_pci_legacy_get_status (vm, vif); if (!(status & VIRTIO_CONFIG_STATUS_FEATURES_OK)) { - virtio_log_error (vim, vif, + virtio_log_error (vif, "error encountered: Device doesn't support requested features"); clib_error_return (error, "Device doesn't support requested features"); } @@ -954,7 +1087,7 @@ virtio_pci_device_init (vlib_main_t * vm, virtio_if_t * vif, { if ((error = virtio_pci_vring_init (vm, vif, RX_QUEUE (i)))) { - virtio_log_warning (vim, vif, "%s (%u) %s", "error in rxq-queue", + virtio_log_warning (vif, "%s (%u) %s", "error in rxq-queue", RX_QUEUE (i), "initialization"); } else @@ -962,9 +1095,25 @@ 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 (vim, vif, "%s (%u) %s", "error in txq-queue", + virtio_log_warning (vif, "%s (%u) %s", "error in txq-queue", TX_QUEUE (i), "initialization"); } else @@ -978,8 +1127,7 @@ virtio_pci_device_init (vlib_main_t * vm, virtio_if_t * vif, if ((error = virtio_pci_control_vring_init (vm, vif, vif->max_queue_pairs * 2))) { - virtio_log_warning (vim, vif, "%s (%u) %s", - "error in control-queue", + virtio_log_warning (vif, "%s (%u) %s", "error in control-queue", vif->max_queue_pairs * 2, "initialization"); if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MQ)) vif->features &= ~VIRTIO_FEATURE (VIRTIO_NET_F_MQ); @@ -987,7 +1135,7 @@ virtio_pci_device_init (vlib_main_t * vm, virtio_if_t * vif, } else { - virtio_log_debug (vim, vif, "control queue is not available"); + virtio_log_debug (vif, "control queue is not available"); vif->cxq_vring = NULL; } @@ -998,10 +1146,10 @@ virtio_pci_device_init (vlib_main_t * vm, virtio_if_t * vif, { if (virtio_pci_legacy_set_config_irq (vm, vif, 1) == VIRTIO_MSI_NO_VECTOR) - virtio_log_warning (vim, vif, "config vector 1 is not set"); + virtio_log_warning (vif, "config vector 1 is not set"); if (virtio_pci_legacy_set_queue_irq (vm, vif, 0, 0) == VIRTIO_MSI_NO_VECTOR) - virtio_log_warning (vim, vif, "queue vector 0 is not set"); + virtio_log_warning (vif, "queue vector 0 is not set"); } /* @@ -1046,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, @@ -1054,22 +1201,23 @@ 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; vlib_pci_set_private_data (vm, h, vif->dev_instance); vif->numa_node = vlib_pci_get_numa_node (vm, h); + vif->type = VIRTIO_IF_TYPE_PCI; if ((error = vlib_pci_bus_master_enable (vm, h))) { - virtio_log_error (vim, vif, - "error encountered on pci bus master enable"); + virtio_log_error (vif, "error encountered on pci bus master enable"); goto error; } if ((error = vlib_pci_io_region (vm, h, 0))) { - virtio_log_error (vim, vif, "error encountered on pci io region"); + virtio_log_error (vif, "error encountered on pci io region"); goto error; } @@ -1078,26 +1226,25 @@ virtio_pci_create_if (vlib_main_t * vm, virtio_pci_create_if_args_t * args) if ((error = vlib_pci_register_msix_handler (vm, h, 0, 1, &virtio_pci_irq_0_handler))) { - virtio_log_error (vim, vif, + virtio_log_error (vif, "error encountered on pci register msix handler 0"); goto error; } if ((error = vlib_pci_register_msix_handler (vm, h, 1, 1, &virtio_pci_irq_1_handler))) { - virtio_log_error (vim, vif, + virtio_log_error (vif, "error encountered on pci register msix handler 1"); goto error; } if ((error = vlib_pci_enable_msix_irq (vm, h, 0, 2))) { - virtio_log_error (vim, vif, - "error encountered on pci enable msix irq"); + virtio_log_error (vif, "error encountered on pci enable msix irq"); goto error; } vif->support_int_mode = 1; - virtio_log_debug (vim, vif, "device supports msix interrupts"); + virtio_log_debug (vif, "device supports msix interrupts"); } else if (vlib_pci_get_num_msix_interrupts (vm, h) == 1) { @@ -1107,12 +1254,12 @@ virtio_pci_create_if (vlib_main_t * vm, virtio_pci_create_if_args_t * args) if ((error = vlib_pci_register_intx_handler (vm, h, &virtio_pci_irq_handler))) { - virtio_log_error (vim, vif, + virtio_log_error (vif, "error encountered on pci register interrupt handler"); goto error; } vif->support_int_mode = 1; - virtio_log_debug (vim, vif, "pci register interrupt handler"); + virtio_log_debug (vif, "pci register interrupt handler"); } else { @@ -1121,23 +1268,21 @@ virtio_pci_create_if (vlib_main_t * vm, virtio_pci_create_if_args_t * args) * Please don't use interrupt mode with UIO driver. */ vif->support_int_mode = 0; - virtio_log_debug (vim, vif, "driver is configured in poll mode only"); + virtio_log_debug (vif, "driver is configured in poll mode only"); } if ((error = vlib_pci_intr_enable (vm, h))) { - virtio_log_error (vim, vif, - "error encountered on pci interrupt enable"); + virtio_log_error (vif, "error encountered on pci interrupt enable"); goto error; } if ((error = virtio_pci_device_init (vm, vif, args))) { - virtio_log_error (vim, vif, "error encountered on device init"); + virtio_log_error (vif, "error encountered on device init"); goto error; } - vif->type = VIRTIO_IF_TYPE_PCI; /* create interface */ error = ethernet_register_interface (vnm, virtio_device_class.index, vif->dev_instance, vif->mac_addr, @@ -1146,7 +1291,7 @@ virtio_pci_create_if (vlib_main_t * vm, virtio_pci_create_if_args_t * args) if (error) { - virtio_log_error (vim, vif, + virtio_log_error (vif, "error encountered on ethernet register interface"); goto error; } @@ -1177,11 +1322,14 @@ 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); + 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 (virtio_pci_enable_multiqueue (vm, vif, vif->max_queue_pairs)) - virtio_log_warning (vim, vif, "multiqueue is not set"); + virtio_log_warning (vif, "multiqueue is not set"); } return; @@ -1236,7 +1384,6 @@ virtio_pci_delete_if (vlib_main_t * vm, virtio_if_t * vif) virtio_free_rx_buffers (vm, vring); } vec_free (vring->buffers); - vec_free (vring->indirect_buffers); vlib_physmem_free (vm, vring->desc); } @@ -1249,12 +1396,8 @@ virtio_pci_delete_if (vlib_main_t * vm, virtio_if_t * vif) { virtio_free_used_desc (vm, vring); } - if (vring->queue_id % 2) - { - vlib_buffer_free_no_next (vm, vring->indirect_buffers, vring->size); - } vec_free (vring->buffers); - vec_free (vring->indirect_buffers); + clib_spinlock_free (&vring->lockp); vlib_physmem_free (vm, vring->desc); } @@ -1276,10 +1419,6 @@ virtio_pci_delete_if (vlib_main_t * vm, virtio_if_t * vif) vec_free (vif->txq_vrings); vec_free (vif->cxq_vring); - if (vif->fd != -1) - vif->fd = -1; - if (vif->tap_fd != -1) - vif->tap_fd = -1; clib_error_free (vif->error); memset (vif, 0, sizeof (*vif)); pool_put (vim->interfaces, vif); @@ -1287,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 *