TAP memory leaks:
[vpp.git] / src / vnet / devices / tap / tap.c
index a7d10fe..2341bbb 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/rtnetlink.h>
 
 #include <vlib/vlib.h>
+#include <vlib/log.h>
 #include <vlib/unix/unix.h>
 #include <vnet/ethernet/ethernet.h>
 #include <vnet/ip/ip4_packet.h>
@@ -75,11 +76,13 @@ open_netns_fd (char *netns)
   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;
@@ -91,12 +94,10 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
   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");
@@ -105,22 +106,14 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
     }
   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));
@@ -129,8 +122,6 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
   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;
@@ -292,6 +283,26 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
       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)
     {
@@ -362,6 +373,7 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
       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;
@@ -377,6 +389,8 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
   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:
@@ -391,6 +405,7 @@ error:
   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));
   pool_put (vim->interfaces, vif);
 
@@ -420,6 +435,7 @@ tap_delete_if (vlib_main_t * vm, u32 sw_if_index)
   /* 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;
@@ -432,7 +448,8 @@ tap_delete_if (vlib_main_t * vm, u32 sw_if_index)
   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);
+  tm->tap_ids = clib_bitmap_set (tm->tap_ids, vif->id, 0);
+  clib_spinlock_free (&vif->lockp);
   memset (vif, 0, sizeof (*vif));
   pool_put (mm->interfaces, vif);
 
@@ -494,12 +511,21 @@ tap_dump_ifs (tap_interface_details_t ** out_tapids)
   return 0;
 }
 
+#define vlib_log_info(...) vlib_log(VLIB_LOG_LEVEL_INFO, __VA_ARGS__)
+
 static clib_error_t *
 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;
+  error = vlib_call_init_function (vm, vlib_log_init);
+  if (error)
+    return error;
+
+  tm->log_default = vlib_log_register_class ("tap", 0);
+  vlib_log_info (tm->log_default, "initialized");
+
+  return NULL;
 }
 
 VLIB_INIT_FUNCTION (tap_init);