return fd;
}
+#define TAP_MAX_INSTANCE 1024
void
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;
vnet_hw_interface_t *hw;
- int i, fd = -1;
+ int i;
int old_netns_fd = -1;
struct ifreq ifr;
size_t hdrsz;
struct vhost_memory *vhost_mem = 0;
virtio_if_t *vif = 0;
clib_error_t *err = 0;
- uword *p;
if (args->id != ~0)
{
- p = hash_get (tm->dev_instance_by_interface_id, args->id);
- if (p)
+ if (clib_bitmap_get (tm->tap_ids, args->id))
{
args->rv = VNET_API_ERROR_INVALID_INTERFACE;
args->error = clib_error_return (0, "interface already exists");
}
else
{
- int tries = 1000;
- while (--tries)
- {
- args->id = tm->last_used_interface_id++;
- p = hash_get (tm->dev_instance_by_interface_id, args->id);
- if (!p)
- break;
- }
+ args->id = clib_bitmap_first_clear (tm->tap_ids);
+ }
- if (!tries)
- {
- args->rv = VNET_API_ERROR_UNSPECIFIED;
- args->error =
- clib_error_return (0, "cannot find free interface id");
- return;
- }
+ if (args->id > TAP_MAX_INSTANCE)
+ {
+ args->rv = VNET_API_ERROR_UNSPECIFIED;
+ args->error = clib_error_return (0, "cannot find free interface id");
+ 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;
vif->id = args->id;
- hash_set (tm->dev_instance_by_interface_id, vif->id, vif->dev_instance);
-
if ((vif->fd = open ("/dev/vhost-net", O_RDWR | O_NONBLOCK)) < 0)
{
args->rv = VNET_API_ERROR_SYSCALL_ERROR_1;
if (args->host_namespace)
{
int fd;
+ int rc;
old_netns_fd = open ("/proc/self/ns/net", O_RDONLY);
if ((fd = open_netns_fd ((char *) args->host_namespace)) == -1)
{
args->rv = VNET_API_ERROR_NETLINK_ERROR;
goto error;
}
- if (setns (fd, CLONE_NEWNET) == -1)
+ rc = setns (fd, CLONE_NEWNET);
+ close (fd);
+ if (rc == -1)
{
args->rv = VNET_API_ERROR_SYSCALL_ERROR_3;
args->error = clib_error_return_unix (0, "setns '%s'",
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;
goto error;
}
+ if (args->host_ip4_gw_set)
+ {
+ args->error = vnet_netlink_add_ip4_route (0, 0, &args->host_ip4_gw);
+ if (args->error)
+ {
+ args->rv = VNET_API_ERROR_NETLINK_ERROR;
+ goto error;
+ }
+ }
+
+ if (args->host_ip6_gw_set)
+ {
+ args->error = vnet_netlink_add_ip6_route (0, 0, &args->host_ip6_gw);
+ if (args->error)
+ {
+ args->rv = VNET_API_ERROR_NETLINK_ERROR;
+ goto error;
+ }
+ }
+
/* switch back to old net namespace */
if (args->host_namespace)
{
/* 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);
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;
vif->host_if_name = args->host_if_name;
args->host_if_name = 0;
vif->net_ns = args->host_namespace;
args->host_namespace = 0;
+ vif->host_bridge = args->host_bridge;
+ args->host_bridge = 0;
+ clib_memcpy (vif->host_mac_addr, args->host_mac_addr, 6);
+ vif->host_ip4_prefix_len = args->host_ip4_prefix_len;
+ vif->host_ip6_prefix_len = args->host_ip6_prefix_len;
+ if (args->host_ip4_prefix_len)
+ clib_memcpy (&vif->host_ip4_addr, &args->host_ip4_addr, 4);
+ if (args->host_ip6_prefix_len)
+ clib_memcpy (&vif->host_ip6_addr, &args->host_ip6_addr, 16);
+
args->error = ethernet_register_interface (vnm, virtio_device_class.index,
vif->dev_instance,
args->mac_addr,
goto error;
}
+ tm->tap_ids = clib_bitmap_set (tm->tap_ids, vif->id, 1);
sw = vnet_get_hw_sw_interface (vnm, vif->hw_if_index);
vif->sw_if_index = sw->sw_if_index;
args->sw_if_index = vif->sw_if_index;
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);
goto done;
error:
close (vif->tap_fd);
if (vif->fd != -1)
close (vif->fd);
- vec_foreach_index (i, vif->vrings) virtio_vring_free (vif, i);
- memset (vif, 0, sizeof (virtio_if_t));
+ vec_foreach_index (i, vif->vrings) virtio_vring_free (vm, vif, i);
+ vec_free (vif->vrings);
+ clib_memset (vif, 0, sizeof (virtio_if_t));
pool_put (vim->interfaces, vif);
done:
if (vhost_mem)
clib_mem_free (vhost_mem);
- if (fd != -1)
- close (fd);
+ if (old_netns_fd != -1)
+ close (old_netns_fd);
}
int
/* 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);
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 (vif, i);
+ vec_foreach_index (i, vif->vrings) virtio_vring_free (vm, vif, i);
vec_free (vif->vrings);
- hash_unset (tm->dev_instance_by_interface_id, vif->id);
- memset (vif, 0, sizeof (*vif));
+ tm->tap_ids = clib_bitmap_set (tm->tap_ids, vif->id, 0);
+ clib_spinlock_free (&vif->lockp);
+ clib_memset (vif, 0, sizeof (*vif));
pool_put (mm->interfaces, vif);
return 0;
/* *INDENT-OFF* */
pool_foreach (vif, mm->interfaces,
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)));
+ 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;
+ clib_memcpy(tapid->host_mac_addr, vif->host_mac_addr, 6);
+ if (vif->host_if_name)
+ {
+ clib_memcpy(tapid->host_if_name, vif->host_if_name,
+ MIN (ARRAY_LEN (tapid->host_if_name) - 1,
+ strlen ((const char *) vif->host_if_name)));
+ }
+ if (vif->net_ns)
+ {
+ clib_memcpy(tapid->host_namespace, vif->net_ns,
+ MIN (ARRAY_LEN (tapid->host_namespace) - 1,
+ strlen ((const char *) vif->net_ns)));
+ }
+ if (vif->host_bridge)
+ {
+ clib_memcpy(tapid->host_bridge, vif->host_bridge,
+ MIN (ARRAY_LEN (tapid->host_bridge) - 1,
+ strlen ((const char *) vif->host_bridge)));
+ }
+ if (vif->host_ip4_prefix_len)
+ clib_memcpy(tapid->host_ip4_addr, &vif->host_ip4_addr, 4);
+ tapid->host_ip4_prefix_len = vif->host_ip4_prefix_len;
+ if (vif->host_ip6_prefix_len)
+ clib_memcpy(tapid->host_ip6_addr, &vif->host_ip6_addr, 16);
+ tapid->host_ip6_prefix_len = vif->host_ip6_prefix_len;
);
/* *INDENT-ON* */
tap_init (vlib_main_t * vm)
{
tap_main_t *tm = &tap_main;
- tm->dev_instance_by_interface_id = hash_create (0, sizeof (uword));
- return 0;
+ clib_error_t *error = 0;
+
+ tm->log_default = vlib_log_register_class ("tap", 0);
+ vlib_log_debug (tm->log_default, "initialized");
+
+ return error;
}
VLIB_INIT_FUNCTION (tap_init);