tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
{
vnet_main_t *vnm = vnet_get_main ();
- vlib_thread_main_t *thm = vlib_get_thread_main ();
virtio_main_t *vim = &virtio_main;
tap_main_t *tm = &tap_main;
vnet_sw_interface_t *sw;
struct vhost_memory *vhost_mem = 0;
virtio_if_t *vif = 0;
clib_error_t *err = 0;
+ int fd = -1;
if (args->id != ~0)
{
return;
}
- memset (&ifr, 0, sizeof (ifr));
+ clib_memset (&ifr, 0, sizeof (ifr));
pool_get (vim->interfaces, vif);
vif->dev_instance = vif - vim->interfaces;
vif->tap_fd = -1;
_IOCTL (vif->fd, VHOST_GET_FEATURES, &vif->remote_features);
- if ((vif->remote_features & (1ULL << VIRTIO_NET_F_MRG_RXBUF)) == 0)
+ if ((vif->remote_features & VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF)) == 0)
{
args->rv = VNET_API_ERROR_UNSUPPORTED;
args->error = clib_error_return (0, "vhost-net backend doesn't support "
goto error;
}
- if ((vif->remote_features & (1ULL << VIRTIO_RING_F_INDIRECT_DESC)) == 0)
+ if ((vif->remote_features & VIRTIO_FEATURE (VIRTIO_RING_F_INDIRECT_DESC)) ==
+ 0)
{
args->rv = VNET_API_ERROR_UNSUPPORTED;
args->error = clib_error_return (0, "vhost-net backend doesn't support "
goto error;
}
- if ((vif->remote_features & (1ULL << VIRTIO_F_VERSION_1)) == 0)
+ if ((vif->remote_features & VIRTIO_FEATURE (VIRTIO_F_VERSION_1)) == 0)
{
args->rv = VNET_API_ERROR_UNSUPPORTED;
args->error = clib_error_return (0, "vhost-net backend doesn't support "
goto error;
}
- vif->features |= 1ULL << VIRTIO_NET_F_MRG_RXBUF;
- vif->features |= 1ULL << VIRTIO_F_VERSION_1;
- vif->features |= 1ULL << VIRTIO_RING_F_INDIRECT_DESC;
+ vif->features |= VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF);
+ vif->features |= VIRTIO_FEATURE (VIRTIO_F_VERSION_1);
+ vif->features |= VIRTIO_FEATURE (VIRTIO_RING_F_INDIRECT_DESC);
+
+ virtio_set_net_hdr_size (vif);
_IOCTL (vif->fd, VHOST_SET_FEATURES, &vif->features);
_IOCTL (vif->tap_fd, TUNSETIFF, (void *) &ifr);
vif->ifindex = if_nametoindex (ifr.ifr_ifrn.ifrn_name);
+ if (!args->host_if_name)
+ args->host_if_name = (u8 *) ifr.ifr_ifrn.ifrn_name;
+
unsigned int offload = 0;
hdrsz = sizeof (struct virtio_net_hdr_v1);
+ if (args->tap_flags & TAP_FLAG_GSO)
+ {
+ offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6;
+ vif->gso_enabled = 1;
+ }
+ else
+ {
+ vif->gso_enabled = 0;
+ }
+
_IOCTL (vif->tap_fd, TUNSETOFFLOAD, offload);
_IOCTL (vif->tap_fd, TUNSETVNETHDRSZ, &hdrsz);
_IOCTL (vif->fd, VHOST_SET_OWNER, 0);
after we change our net namespace */
if (args->host_namespace)
{
- int fd;
old_netns_fd = open ("/proc/self/ns/net", O_RDONLY);
if ((fd = open_netns_fd ((char *) args->host_namespace)) == -1)
{
args->host_namespace);
goto error;
}
- close (fd);
if ((vif->ifindex = if_nametoindex ((char *) args->host_if_name)) == 0)
{
args->rv = VNET_API_ERROR_SYSCALL_ERROR_3;
/* Set vhost memory table */
i = sizeof (struct vhost_memory) + sizeof (struct vhost_memory_region);
vhost_mem = clib_mem_alloc (i);
- memset (vhost_mem, 0, i);
+ clib_memset (vhost_mem, 0, i);
vhost_mem->nregions = 1;
vhost_mem->regions[0].memory_size = (1ULL << 47) - 4096;
_IOCTL (vif->fd, VHOST_SET_MEM_TABLE, vhost_mem);
- if ((args->error = virtio_vring_init (vm, vif, 0, args->rx_ring_sz)))
+ if ((args->error =
+ virtio_vring_init (vm, vif, RX_QUEUE (0), args->rx_ring_sz)))
{
args->rv = VNET_API_ERROR_INIT_FAILED;
goto error;
}
+ vif->num_rxqs = 1;
- if ((args->error = virtio_vring_init (vm, vif, 1, args->tx_ring_sz)))
+ if ((args->error =
+ virtio_vring_init (vm, vif, TX_QUEUE (0), args->tx_ring_sz)))
{
args->rv = VNET_API_ERROR_INIT_FAILED;
goto error;
}
+ vif->num_txqs = 1;
if (!args->mac_addr_set)
- {
- f64 now = vlib_time_now (vm);
- u32 rnd;
- rnd = (u32) (now * 1e6);
- rnd = random_u32 (&rnd);
-
- memcpy (args->mac_addr + 2, &rnd, sizeof (rnd));
- args->mac_addr[0] = 2;
- args->mac_addr[1] = 0xfe;
- }
- vif->rx_ring_sz = args->rx_ring_sz != 0 ? args->rx_ring_sz : 256;
- vif->tx_ring_sz = args->tx_ring_sz != 0 ? args->tx_ring_sz : 256;
+ ethernet_mac_address_generate (args->mac_addr);
+
+ clib_memcpy (vif->mac_addr, args->mac_addr, 6);
+
vif->host_if_name = args->host_if_name;
args->host_if_name = 0;
vif->net_ns = args->host_namespace;
if (args->host_ip6_prefix_len)
clib_memcpy (&vif->host_ip6_addr, &args->host_ip6_addr, 16);
+ vif->type = VIRTIO_IF_TYPE_TAP;
args->error = ethernet_register_interface (vnm, virtio_device_class.index,
vif->dev_instance,
- args->mac_addr,
+ vif->mac_addr,
&vif->hw_if_index,
virtio_eth_flag_change);
if (args->error)
args->sw_if_index = vif->sw_if_index;
hw = vnet_get_hw_interface (vnm, vif->hw_if_index);
hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_INT_MODE;
+ if (args->tap_flags & TAP_FLAG_GSO)
+ {
+ hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO;
+ vnm->interface_main.gso_interface_count++;
+ }
vnet_hw_interface_set_input_node (vnm, vif->hw_if_index,
virtio_input_node.index);
vnet_hw_interface_assign_rx_thread (vnm, vif->hw_if_index, 0, ~0);
vnet_hw_interface_set_rx_mode (vnm, vif->hw_if_index, 0,
VNET_HW_INTERFACE_RX_MODE_DEFAULT);
vif->per_interface_next_index = ~0;
- vif->type = VIRTIO_IF_TYPE_TAP;
+ virtio_vring_set_numa_node (vm, vif, RX_QUEUE (0));
vif->flags |= VIRTIO_IF_FLAG_ADMIN_UP;
vnet_hw_interface_set_flags (vnm, vif->hw_if_index,
VNET_HW_INTERFACE_FLAG_LINK_UP);
- if (thm->n_vlib_mains > 1)
- clib_spinlock_init (&vif->lockp);
+ vif->cxq_vring = NULL;
+
goto done;
error:
close (vif->tap_fd);
if (vif->fd != -1)
close (vif->fd);
- vec_foreach_index (i, vif->vrings) virtio_vring_free (vm, vif, i);
- vec_free (vif->vrings);
- memset (vif, 0, sizeof (virtio_if_t));
+ vec_foreach_index (i, vif->rxq_vrings) virtio_vring_free_rx (vm, vif,
+ RX_QUEUE (i));
+ vec_foreach_index (i, vif->txq_vrings) virtio_vring_free_tx (vm, vif,
+ TX_QUEUE (i));
+ vec_free (vif->rxq_vrings);
+ vec_free (vif->txq_vrings);
+ clib_memset (vif, 0, sizeof (virtio_if_t));
pool_put (vim->interfaces, vif);
done:
clib_mem_free (vhost_mem);
if (old_netns_fd != -1)
close (old_netns_fd);
+ if (fd != -1)
+ close (fd);
}
int
vif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
+ if (vif->type != VIRTIO_IF_TYPE_TAP)
+ return VNET_API_ERROR_INVALID_INTERFACE;
+
+ /* decrement if this was a GSO interface */
+ if (hw->flags & VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO)
+ vnm->interface_main.gso_interface_count--;
+
/* bring down the interface */
vnet_hw_interface_set_flags (vnm, vif->hw_if_index, 0);
vnet_sw_interface_set_flags (vnm, vif->sw_if_index, 0);
- vnet_hw_interface_unassign_rx_thread (vnm, vif->hw_if_index, 0);
+ vnet_hw_interface_unassign_rx_thread (vnm, vif->hw_if_index, RX_QUEUE (0));
ethernet_delete_interface (vnm, vif->hw_if_index);
vif->hw_if_index = ~0;
if (vif->fd != -1)
close (vif->fd);
- vec_foreach_index (i, vif->vrings) virtio_vring_free (vm, vif, i);
- vec_free (vif->vrings);
+ vec_foreach_index (i, vif->rxq_vrings) virtio_vring_free_rx (vm, vif,
+ RX_QUEUE (i));
+ vec_foreach_index (i, vif->txq_vrings) virtio_vring_free_tx (vm, vif,
+ TX_QUEUE (i));
+ vec_free (vif->rxq_vrings);
+ vec_free (vif->txq_vrings);
tm->tap_ids = clib_bitmap_set (tm->tap_ids, vif->id, 0);
- clib_spinlock_free (&vif->lockp);
- memset (vif, 0, sizeof (*vif));
+ clib_memset (vif, 0, sizeof (*vif));
pool_put (mm->interfaces, vif);
return 0;
}
+int
+tap_gso_enable_disable (vlib_main_t * vm, u32 sw_if_index, int enable_disable)
+{
+ vnet_main_t *vnm = vnet_get_main ();
+ virtio_main_t *mm = &virtio_main;
+ virtio_if_t *vif;
+ vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
+ clib_error_t *err = 0;
+
+ if (hw == NULL || virtio_device_class.index != hw->dev_class_index)
+ return VNET_API_ERROR_INVALID_SW_IF_INDEX;
+
+ vif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
+
+ const unsigned int gso_on = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6;
+ const unsigned int gso_off = 0;
+ unsigned int offload = enable_disable ? gso_on : gso_off;
+ _IOCTL (vif->tap_fd, TUNSETOFFLOAD, offload);
+ vif->gso_enabled = enable_disable ? 1 : 0;
+ if (enable_disable)
+ {
+ if ((hw->flags & VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO) == 0)
+ {
+ vnm->interface_main.gso_interface_count++;
+ hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO;
+ }
+ }
+ else
+ {
+ if ((hw->flags & VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO) != 0)
+ {
+ vnm->interface_main.gso_interface_count--;
+ hw->flags &= ~VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO;
+ }
+ }
+
+error:
+ if (err)
+ {
+ clib_warning ("Error %s gso on sw_if_index %d",
+ enable_disable ? "enabling" : "disabling", sw_if_index);
+ return VNET_API_ERROR_SYSCALL_ERROR_3;
+ }
+ return 0;
+}
+
int
tap_dump_ifs (tap_interface_details_t ** out_tapids)
{
vnet_main_t *vnm = vnet_get_main ();
virtio_main_t *mm = &virtio_main;
virtio_if_t *vif;
+ virtio_vring_t *vring;
vnet_hw_interface_t *hi;
tap_interface_details_t *r_tapids = NULL;
tap_interface_details_t *tapid = NULL;
/* *INDENT-OFF* */
pool_foreach (vif, mm->interfaces,
+ if (vif->type != VIRTIO_IF_TYPE_TAP)
+ continue;
vec_add2(r_tapids, tapid, 1);
- memset (tapid, 0, sizeof (*tapid));
+ clib_memset (tapid, 0, sizeof (*tapid));
tapid->id = vif->id;
tapid->sw_if_index = vif->sw_if_index;
hi = vnet_get_hw_interface (vnm, vif->hw_if_index);
clib_memcpy(tapid->dev_name, hi->name,
MIN (ARRAY_LEN (tapid->dev_name) - 1,
strlen ((const char *) hi->name)));
- tapid->rx_ring_sz = vif->rx_ring_sz;
- tapid->tx_ring_sz = vif->tx_ring_sz;
+ vring = vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS(0));
+ tapid->rx_ring_sz = vring->size;
+ vring = vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS(0));
+ tapid->tx_ring_sz = vring->size;
clib_memcpy(tapid->host_mac_addr, vif->host_mac_addr, 6);
if (vif->host_if_name)
{