acl-plugin: VPP-1230: fix the "undefined symbol" error for acl_main when using the...
[vpp.git] / src / plugins / acl / acl.c
index 57940fc..7d3a852 100644 (file)
@@ -54,6 +54,7 @@
 #include "public_inlines.h"
 
 acl_main_t acl_main;
+acl_main_t *p_acl_main = &acl_main;
 
 #define REPLY_MSG_ID_BASE am->msg_id_base
 #include <vlibapi/api_helper_macros.h>
@@ -121,7 +122,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;
     }
@@ -278,6 +306,45 @@ warning_acl_print_acl (vlib_main_t * vm, acl_main_t * am, int acl_index)
   acl_print_acl_x (print_clib_warning_and_reset, vm, am, acl_index);
 }
 
+static void
+increment_policy_epoch (acl_main_t * am, u32 sw_if_index, int is_input)
+{
+
+  u32 **ppolicy_epoch_by_swi =
+    is_input ? &am->input_policy_epoch_by_sw_if_index :
+    &am->output_policy_epoch_by_sw_if_index;
+  vec_validate (*ppolicy_epoch_by_swi, sw_if_index);
+
+  u32 *p_epoch = vec_elt_at_index ((*ppolicy_epoch_by_swi), sw_if_index);
+  *p_epoch =
+    ((1 + *p_epoch) & FA_POLICY_EPOCH_MASK) +
+    (is_input * FA_POLICY_EPOCH_IS_INPUT);
+}
+
+static void
+try_increment_acl_policy_epoch (acl_main_t * am, u32 acl_num, int is_input)
+{
+  u32 ***p_swi_vec_by_acl = is_input ? &am->input_sw_if_index_vec_by_acl
+    : &am->output_sw_if_index_vec_by_acl;
+  if (acl_num < vec_len (*p_swi_vec_by_acl))
+    {
+      u32 *p_swi;
+      vec_foreach (p_swi, (*p_swi_vec_by_acl)[acl_num])
+      {
+       increment_policy_epoch (am, *p_swi, is_input);
+      }
+
+    }
+}
+
+static void
+policy_notify_acl_change (acl_main_t * am, u32 acl_num)
+{
+  try_increment_acl_policy_epoch (am, acl_num, 0);
+  try_increment_acl_policy_epoch (am, acl_num, 1);
+}
+
+
 
 static int
 acl_add_list (u32 count, vl_api_acl_rule_t rules[],
@@ -365,6 +432,12 @@ acl_add_list (u32 count, vl_api_acl_rule_t rules[],
   memcpy (a->tag, tag, sizeof (a->tag));
   if (am->trace_acl > 255)
     warning_acl_print_acl (am->vlib_main, am, *acl_list_index);
+  if (am->reclassify_sessions)
+    {
+      /* a change in an ACLs if they are applied may mean a new policy epoch */
+      policy_notify_acl_change (am, *acl_list_index);
+    }
+
   /* notify the lookup contexts about the ACL changes */
   acl_plugin_lookup_context_notify_acl_change (*acl_list_index);
   clib_mem_set_heap (oldheap);
@@ -1241,12 +1314,20 @@ acl_interface_set_inout_acl_list (acl_main_t * am, u32 sw_if_index,
   (*pinout_acl_vec_by_sw_if_index)[sw_if_index] =
     vec_dup (vec_acl_list_index);
 
-  /* if no commonalities between the ACL# - then we should definitely clear the sessions */
-  if (may_clear_sessions && *may_clear_sessions
-      && !clib_bitmap_is_zero (change_acl_bitmap))
+  if (am->reclassify_sessions)
     {
-      acl_clear_sessions (am, sw_if_index);
-      *may_clear_sessions = 0;
+      /* re-applying ACLs means a new policy epoch */
+      increment_policy_epoch (am, sw_if_index, is_input);
+    }
+  else
+    {
+      /* if no commonalities between the ACL# - then we should definitely clear the sessions */
+      if (may_clear_sessions && *may_clear_sessions
+         && !clib_bitmap_is_zero (change_acl_bitmap))
+       {
+         acl_clear_sessions (am, sw_if_index);
+         *may_clear_sessions = 0;
+       }
     }
 
   /*
@@ -1259,6 +1340,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);
@@ -3171,6 +3256,11 @@ acl_set_aclplugin_fn (vlib_main_t * vm,
       am->l4_match_nonfirst_fragment = (val != 0);
       goto done;
     }
+  if (unformat (input, "reclassify-sessions %u", &val))
+    {
+      am->reclassify_sessions = (val != 0);
+      goto done;
+    }
   if (unformat (input, "event-trace"))
     {
       if (!unformat (input, "%u", &val))
@@ -3540,6 +3630,15 @@ acl_plugin_show_interface (acl_main_t * am, u32 sw_if_index, int show_acl,
        continue;
 
       vlib_cli_output (vm, "sw_if_index %d:\n", swi);
+      if (swi < vec_len (am->input_policy_epoch_by_sw_if_index))
+       vlib_cli_output (vm, "   input policy epoch: %x\n",
+                        vec_elt (am->input_policy_epoch_by_sw_if_index,
+                                 swi));
+      if (swi < vec_len (am->output_policy_epoch_by_sw_if_index))
+       vlib_cli_output (vm, "   output policy epoch: %x\n",
+                        vec_elt (am->output_policy_epoch_by_sw_if_index,
+                                 swi));
+
 
       if (intf_has_etype_whitelist (am, swi, 1))
        {
@@ -3730,13 +3829,21 @@ acl_plugin_show_sessions (acl_main_t * am,
                                               ?
                                               pw->fa_session_dels_by_sw_if_index
                                               [sw_if_index] : 0;
+                                              u64 n_epoch_changes =
+                                              sw_if_index <
+                                              vec_len
+                                              (pw->fa_session_epoch_change_by_sw_if_index)
+                                              ?
+                                              pw->fa_session_epoch_change_by_sw_if_index
+                                              [sw_if_index] : 0;
                                               vlib_cli_output (vm,
-                                                               "    sw_if_index %d: add %lu - del %lu = %lu",
+                                                               "    sw_if_index %d: add %lu - del %lu = %lu; epoch chg: %lu",
                                                                sw_if_index,
                                                                n_adds,
                                                                n_dels,
                                                                n_adds -
-                                                               n_dels);
+                                                               n_dels,
+                                                               n_epoch_changes);
                                               }
                    ));
 
@@ -3798,6 +3905,7 @@ acl_plugin_show_sessions (acl_main_t * am,
                   am->fa_cleaner_wait_time_increment * 1000.0,
                   ((f64) am->fa_current_cleaner_timer_wait_interval) *
                   1000.0 / (f64) vm->clib_time.clocks_per_second);
+  vlib_cli_output (vm, "Reclassify sessions: %d", am->reclassify_sessions);
 }
 
 static clib_error_t *
@@ -3972,10 +4080,11 @@ 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;
+  u32 reclassify_sessions;
 
   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     {
@@ -3988,9 +4097,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))
@@ -3998,6 +4113,10 @@ acl_plugin_config (vlib_main_t * vm, unformat_input_t * input)
       else if (unformat (input, "hash lookup hash memory %d",
                         &hash_lookup_hash_memory))
        am->hash_lookup_hash_memory = hash_lookup_hash_memory;
+      else if (unformat (input, "reclassify sessions %d",
+                        &reclassify_sessions))
+       am->reclassify_sessions = reclassify_sessions;
+
       else
        return clib_error_return (0, "unknown input '%U'",
                                  format_unformat_error, input);
@@ -4031,7 +4150,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,6 +4168,7 @@ acl_init (vlib_main_t * vm)
   am->fa_conn_table_hash_memory_size =
     ACL_FA_CONN_TABLE_DEFAULT_HASH_MEMORY_SIZE;
   am->fa_conn_table_max_entries = ACL_FA_CONN_TABLE_DEFAULT_MAX_ENTRIES;
+  am->reclassify_sessions = 0;
   vlib_thread_main_t *tm = vlib_get_thread_main ();
   vec_validate (am->per_worker_data, tm->n_vlib_mains - 1);
   {
@@ -4089,9 +4209,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;
 }