acl-plugin: autosize the ACL plugin heap and fix the heap size types and parsing
[vpp.git] / src / plugins / acl / acl.c
index 365d852..7c2572d 100644 (file)
@@ -121,7 +121,34 @@ acl_set_heap (acl_main_t * am)
 {
   if (0 == am->acl_mheap)
     {
+      if (0 == am->acl_mheap_size)
+       {
+         vlib_thread_main_t *tm = vlib_get_thread_main ();
+         u64 per_worker_slack = 1000000LL;
+         u64 per_worker_size =
+           per_worker_slack +
+           ((u64) am->fa_conn_table_max_entries) * sizeof (fa_session_t);
+         u64 per_worker_size_with_slack = per_worker_slack + per_worker_size;
+         u64 main_slack = 2000000LL;
+         u64 bihash_size = (u64) am->fa_conn_table_hash_memory_size;
+
+         am->acl_mheap_size =
+           per_worker_size_with_slack * tm->n_vlib_mains + bihash_size +
+           main_slack;
+       }
+      u64 max_possible = ((uword) ~ 0);
+      if (am->acl_mheap_size > max_possible)
+       {
+         clib_warning ("ACL heap size requested: %lld, max possible %lld",
+                       am->acl_mheap_size, max_possible);
+       }
       am->acl_mheap = mheap_alloc (0 /* use VM */ , am->acl_mheap_size);
+      if (0 == am->acl_mheap)
+       {
+         clib_error
+           ("ACL plugin failed to allocate main heap of %U bytes, abort",
+            format_memory_size, am->acl_mheap_size);
+       }
       mheap_t *h = mheap_header (am->acl_mheap);
       h->flags |= MHEAP_FLAG_THREAD_SAFE;
     }
@@ -129,6 +156,13 @@ acl_set_heap (acl_main_t * am)
   return oldheap;
 }
 
+void *
+acl_plugin_set_heap ()
+{
+  acl_main_t *am = &acl_main;
+  return acl_set_heap (am);
+}
+
 void
 acl_plugin_acl_set_validate_heap (acl_main_t * am, int on)
 {
@@ -1252,6 +1286,10 @@ acl_interface_set_inout_acl_list (acl_main_t * am, u32 sw_if_index,
       u32 lc_index = (*pinout_lc_index_by_sw_if_index)[sw_if_index];
       if (~0 == lc_index)
        {
+         if (~0 == am->interface_acl_user_id)
+           am->interface_acl_user_id =
+             acl_plugin_register_user_module ("interface ACL", "sw_if_index",
+                                              "is_input");
          lc_index =
            acl_plugin_get_lookup_context_index (am->interface_acl_user_id,
                                                 sw_if_index, is_input);
@@ -2156,8 +2194,12 @@ macip_acl_add_list (u32 count, vl_api_macip_acl_rule_t rules[],
   return rv;
 }
 
-
-/* No check for validity of sw_if_index - the callers were supposed to validate */
+/* No check that sw_if_index denotes a valid interface - the callers
+ * were supposed to validate.
+ *
+ * That said, if sw_if_index corresponds to an interface that exists at all,
+ * this function must return errors accordingly if the ACL is not applied.
+ */
 
 static int
 macip_acl_interface_del_acl (acl_main_t * am, u32 sw_if_index)
@@ -2165,13 +2207,16 @@ macip_acl_interface_del_acl (acl_main_t * am, u32 sw_if_index)
   int rv;
   u32 macip_acl_index;
   macip_acl_list_t *a;
-  void *oldheap = acl_set_heap (am);
-  vec_validate_init_empty (am->macip_acl_by_sw_if_index, sw_if_index, ~0);
-  clib_mem_set_heap (oldheap);
+
+  /* The vector is too short - MACIP ACL is not applied */
+  if (sw_if_index >= vec_len (am->macip_acl_by_sw_if_index))
+    return VNET_API_ERROR_NO_SUCH_ENTRY;
+
   macip_acl_index = am->macip_acl_by_sw_if_index[sw_if_index];
   /* No point in deleting MACIP ACL which is not applied */
   if (~0 == macip_acl_index)
     return VNET_API_ERROR_NO_SUCH_ENTRY;
+
   a = pool_elt_at_index (am->macip_acls, macip_acl_index);
   /* remove the classifier tables off the interface L2 ACL */
   rv =
@@ -2183,6 +2228,11 @@ macip_acl_interface_del_acl (acl_main_t * am, u32 sw_if_index)
                               a->out_l2_table_index, 0);
   /* Unset the MACIP ACL index */
   am->macip_acl_by_sw_if_index[sw_if_index] = ~0;
+  /* macip_acl_interface_add_acl did a vec_add1() to this previously, so [sw_if_index] should be valid */
+  u32 index = vec_search (am->sw_if_index_vec_by_macip_acl[macip_acl_index],
+                         sw_if_index);
+  if (index != ~0)
+    vec_del1 (am->sw_if_index_vec_by_macip_acl[macip_acl_index], index);
   return rv;
 }
 
@@ -2201,6 +2251,8 @@ macip_acl_interface_add_acl (acl_main_t * am, u32 sw_if_index,
   void *oldheap = acl_set_heap (am);
   a = pool_elt_at_index (am->macip_acls, macip_acl_index);
   vec_validate_init_empty (am->macip_acl_by_sw_if_index, sw_if_index, ~0);
+  vec_validate (am->sw_if_index_vec_by_macip_acl, macip_acl_index);
+  vec_add1 (am->sw_if_index_vec_by_macip_acl[macip_acl_index], sw_if_index);
   clib_mem_set_heap (oldheap);
   /* If there already a MACIP ACL applied, unapply it */
   if (~0 != am->macip_acl_by_sw_if_index[sw_if_index])
@@ -3345,10 +3397,6 @@ macip_acl_print (acl_main_t * am, u32 macip_acl_index)
   vlib_main_t *vm = am->vlib_main;
   int i;
 
-  /* Don't attempt to show the ACLs that do not exist */
-  if (pool_is_free_index (am->macip_acls, macip_acl_index))
-    return;
-
   /* Don't try to print someone else's memory */
   if (macip_acl_index > vec_len (am->macip_acls))
     return;
@@ -3382,8 +3430,31 @@ acl_show_aclplugin_macip_acl_fn (vlib_main_t * vm,
   clib_error_t *error = 0;
   acl_main_t *am = &acl_main;
   int i;
+  u32 acl_index = ~0;
+
+  (void) unformat (input, "index %u", &acl_index);
+
   for (i = 0; i < vec_len (am->macip_acls); i++)
-    macip_acl_print (am, i);
+    {
+      /* Don't attempt to show the ACLs that do not exist */
+      if (pool_is_free_index (am->macip_acls, i))
+       continue;
+
+      if ((acl_index != ~0) && (acl_index != i))
+       {
+         continue;
+       }
+
+      macip_acl_print (am, i);
+      if (i < vec_len (am->sw_if_index_vec_by_macip_acl))
+       {
+         vlib_cli_output (vm, "  applied on sw_if_index(s): %U\n",
+                          format_vec32,
+                          vec_elt (am->sw_if_index_vec_by_macip_acl, i),
+                          "%d");
+       }
+    }
+
   return error;
 }
 
@@ -3908,7 +3979,7 @@ VLIB_CLI_COMMAND (aclplugin_show_tables_command, static) = {
 
 VLIB_CLI_COMMAND (aclplugin_show_macip_acl_command, static) = {
     .path = "show acl-plugin macip acl",
-    .short_help = "show acl-plugin macip acl",
+    .short_help = "show acl-plugin macip acl [index N]",
     .function = acl_show_aclplugin_macip_acl_fn,
 };
 
@@ -3932,8 +4003,8 @@ acl_plugin_config (vlib_main_t * vm, unformat_input_t * input)
   u32 conn_table_hash_buckets;
   u32 conn_table_hash_memory_size;
   u32 conn_table_max_entries;
-  u32 main_heap_size;
-  u32 hash_heap_size;
+  uword main_heap_size;
+  uword hash_heap_size;
   u32 hash_lookup_hash_buckets;
   u32 hash_lookup_hash_memory;
 
@@ -3948,9 +4019,15 @@ acl_plugin_config (vlib_main_t * vm, unformat_input_t * input)
       else if (unformat (input, "connection count max %d",
                         &conn_table_max_entries))
        am->fa_conn_table_max_entries = conn_table_max_entries;
-      else if (unformat (input, "main heap size %d", &main_heap_size))
+      else
+       if (unformat
+           (input, "main heap size %U", unformat_memory_size,
+            &main_heap_size))
        am->acl_mheap_size = main_heap_size;
-      else if (unformat (input, "hash lookup heap size %d", &hash_heap_size))
+      else
+       if (unformat
+           (input, "hash lookup heap size %U", unformat_memory_size,
+            &hash_heap_size))
        am->hash_lookup_mheap_size = hash_heap_size;
       else if (unformat (input, "hash lookup hash buckets %d",
                         &hash_lookup_hash_buckets))
@@ -3991,7 +4068,7 @@ acl_init (vlib_main_t * vm)
 
   acl_setup_fa_nodes ();
 
-  am->acl_mheap_size = ACL_FA_DEFAULT_HEAP_SIZE;
+  am->acl_mheap_size = 0;      /* auto size when initializing */
   am->hash_lookup_mheap_size = ACL_PLUGIN_HASH_LOOKUP_HEAP_SIZE;
 
   am->hash_lookup_hash_buckets = ACL_PLUGIN_HASH_LOOKUP_HASH_BUCKETS;
@@ -4049,9 +4126,7 @@ acl_init (vlib_main_t * vm)
   /* use the new fancy hash-based matching */
   am->use_hash_acl_matching = 1;
 
-  am->interface_acl_user_id =
-    acl_plugin_register_user_module ("interface ACL", "sw_if_index",
-                                    "is_input");
+  am->interface_acl_user_id = ~0;      /* defer till the first use */
 
   return error;
 }