ip: add ip_table_allocate to api
[vpp.git] / src / vnet / ip / ip_api.c
index f9f9ac7..f5ebd02 100644 (file)
@@ -601,6 +601,32 @@ ip_table_delete (fib_protocol_t fproto, u32 table_id, u8 is_api)
     }
 }
 
+/*
+ * Returns an unused table id, and ~0 if it can't find one.
+ */
+u32
+ip_table_get_unused_id (fib_protocol_t fproto)
+{
+  int i, j;
+  u32 seed = random_default_seed ();
+  /* limit to 1M tries */
+  for (j = 0; j < 1 << 10; j++)
+    {
+      seed = random_u32 (&seed);
+      for (i = 0; i < 1 << 10; i++)
+       {
+         /* look around randomly generated id */
+         seed += (2 * (i % 2) - 1) * i;
+         if (seed == ~0)
+           continue;
+         if (fib_table_find (fproto, seed) == ~0)
+           return seed;
+       }
+    }
+
+  return ~0;
+}
+
 void
 vl_api_ip_table_add_del_t_handler (vl_api_ip_table_add_del_t * mp)
 {
@@ -622,6 +648,29 @@ vl_api_ip_table_add_del_t_handler (vl_api_ip_table_add_del_t * mp)
   REPLY_MACRO (VL_API_IP_TABLE_ADD_DEL_REPLY);
 }
 
+void
+vl_api_ip_table_allocate_t_handler (vl_api_ip_table_allocate_t *mp)
+{
+  vl_api_ip_table_allocate_reply_t *rmp;
+  fib_protocol_t fproto =
+    (mp->table.is_ip6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
+  u32 table_id = ntohl (mp->table.table_id);
+  int rv = 0;
+
+  if (~0 == table_id)
+    table_id = ip_table_get_unused_id (fproto);
+
+  if (~0 == table_id)
+    rv = VNET_API_ERROR_EAGAIN;
+  else
+    ip_table_create (fproto, table_id, 1, mp->table.name);
+
+  REPLY_MACRO2 (VL_API_IP_TABLE_ALLOCATE_REPLY, {
+    clib_memcpy_fast (&rmp->table, &mp->table, sizeof (mp->table));
+    rmp->table.table_id = htonl (table_id);
+  })
+}
+
 static int
 ip_route_add_del_t_handler (vl_api_ip_route_add_del_t * mp, u32 * stats_index)
 {