+ {
+ u64 n_adds = am->fa_session_total_adds;
+ u64 n_dels = am->fa_session_total_dels;
+ vlib_cli_output (vm, "Sessions total: add %lu - del %lu = %lu", n_adds,
+ n_dels, n_adds - n_dels);
+ }
+ vlib_cli_output (vm, "\n\nPer-thread data:");
+ for (wk = 0; wk < vec_len (am->per_worker_data); wk++)
+ {
+ acl_fa_per_worker_data_t *pw = &am->per_worker_data[wk];
+ vlib_cli_output (vm, "Thread #%d:", wk);
+ if (show_session_thread_id == wk
+ && show_session_session_index < pool_len (pw->fa_sessions_pool))
+ {
+ vlib_cli_output (vm, " session index %u:",
+ show_session_session_index);
+ fa_session_t *sess =
+ pw->fa_sessions_pool + show_session_session_index;
+ u64 *m = (u64 *) & sess->info;
+ vlib_cli_output (vm,
+ " info: %016llx %016llx %016llx %016llx %016llx %016llx",
+ m[0], m[1], m[2], m[3], m[4], m[5]);
+ vlib_cli_output (vm, " sw_if_index: %u", sess->sw_if_index);
+ vlib_cli_output (vm, " tcp_flags_seen: %x",
+ sess->tcp_flags_seen.as_u16);
+ vlib_cli_output (vm, " last active time: %lu",
+ sess->last_active_time);
+ vlib_cli_output (vm, " thread index: %u", sess->thread_index);
+ vlib_cli_output (vm, " link enqueue time: %lu",
+ sess->link_enqueue_time);
+ vlib_cli_output (vm, " link next index: %u",
+ sess->link_next_idx);
+ vlib_cli_output (vm, " link prev index: %u",
+ sess->link_prev_idx);
+ vlib_cli_output (vm, " link list id: %u", sess->link_list_id);
+ }
+ vlib_cli_output (vm, " connection add/del stats:", wk);
+ pool_foreach (swif, im->sw_interfaces, (
+ {
+ u32 sw_if_index =
+ swif->sw_if_index;
+ u64 n_adds =
+ sw_if_index <
+ vec_len
+ (pw->fa_session_adds_by_sw_if_index)
+ ?
+ pw->fa_session_adds_by_sw_if_index
+ [sw_if_index] : 0;
+ u64 n_dels =
+ sw_if_index <
+ vec_len
+ (pw->fa_session_dels_by_sw_if_index)
+ ?
+ pw->fa_session_dels_by_sw_if_index
+ [sw_if_index] : 0;
+ vlib_cli_output (vm,
+ " sw_if_index %d: add %lu - del %lu = %lu",
+ sw_if_index,
+ n_adds,
+ n_dels,
+ n_adds -
+ n_dels);
+ }
+ ));
+
+ vlib_cli_output (vm, " connection timeout type lists:", wk);
+ u8 tt = 0;
+ for (tt = 0; tt < ACL_N_TIMEOUTS; tt++)
+ {
+ u32 head_session_index = pw->fa_conn_list_head[tt];
+ vlib_cli_output (vm, " fa_conn_list_head[%d]: %d", tt,
+ head_session_index);
+ if (~0 != head_session_index)
+ {
+ fa_session_t *sess = pw->fa_sessions_pool + head_session_index;
+ vlib_cli_output (vm, " last active time: %lu",
+ sess->last_active_time);
+ vlib_cli_output (vm, " link enqueue time: %lu",
+ sess->link_enqueue_time);
+ }
+ }
+
+ vlib_cli_output (vm, " Next expiry time: %lu", pw->next_expiry_time);
+ vlib_cli_output (vm, " Requeue until time: %lu",
+ pw->requeue_until_time);
+ vlib_cli_output (vm, " Current time wait interval: %lu",
+ pw->current_time_wait_interval);
+ vlib_cli_output (vm, " Count of deleted sessions: %lu",
+ pw->cnt_deleted_sessions);
+ vlib_cli_output (vm, " Delete already deleted: %lu",
+ pw->cnt_already_deleted_sessions);
+ vlib_cli_output (vm, " Session timers restarted: %lu",
+ pw->cnt_session_timer_restarted);
+ vlib_cli_output (vm, " Swipe until this time: %lu",
+ pw->swipe_end_time);
+ vlib_cli_output (vm, " sw_if_index serviced bitmap: %U",
+ format_bitmap_hex, pw->serviced_sw_if_index_bitmap);
+ vlib_cli_output (vm, " pending clear intfc bitmap : %U",
+ format_bitmap_hex,
+ pw->pending_clear_sw_if_index_bitmap);
+ vlib_cli_output (vm, " clear in progress: %u", pw->clear_in_process);
+ vlib_cli_output (vm, " interrupt is pending: %d",
+ pw->interrupt_is_pending);
+ vlib_cli_output (vm, " interrupt is needed: %d",
+ pw->interrupt_is_needed);
+ vlib_cli_output (vm, " interrupt is unwanted: %d",
+ pw->interrupt_is_unwanted);
+ vlib_cli_output (vm, " interrupt generation: %d",
+ pw->interrupt_generation);
+ }
+ vlib_cli_output (vm, "\n\nConn cleaner thread counters:");
+#define _(cnt, desc) vlib_cli_output(vm, " %20lu: %s", am->cnt, desc);
+ foreach_fa_cleaner_counter;
+#undef _
+ vlib_cli_output (vm, "Interrupt generation: %d",
+ am->fa_interrupt_generation);
+ vlib_cli_output (vm,
+ "Sessions per interval: min %lu max %lu increment: %f ms current: %f ms",
+ am->fa_min_deleted_sessions_per_interval,
+ am->fa_max_deleted_sessions_per_interval,
+ 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);
+}
+
+static clib_error_t *
+acl_show_aclplugin_sessions_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ clib_error_t *error = 0;
+ acl_main_t *am = &acl_main;
+
+ u32 show_bihash_verbose = 0;
+ u32 show_session_thread_id = ~0;
+ u32 show_session_session_index = ~0;
+ (void) unformat (input, "thread %u index %u", &show_session_thread_id,
+ &show_session_session_index);
+ (void) unformat (input, "verbose %u", &show_bihash_verbose);
+
+ acl_plugin_show_sessions (am, show_session_thread_id,
+ show_session_session_index);
+ show_fa_sessions_hash (vm, show_bihash_verbose);
+ return error;
+}
+
+static void
+acl_plugin_show_tables_mask_type (acl_main_t * am)
+{
+ vlib_main_t *vm = am->vlib_main;
+ ace_mask_type_entry_t *mte;
+
+ vlib_cli_output (vm, "Mask-type entries:");
+ /* *INDENT-OFF* */
+ pool_foreach(mte, am->ace_mask_type_pool,
+ ({
+ vlib_cli_output(vm, " %3d: %016llx %016llx %016llx %016llx %016llx %016llx refcount %d",
+ mte - am->ace_mask_type_pool,
+ mte->mask.kv.key[0], mte->mask.kv.key[1], mte->mask.kv.key[2],
+ mte->mask.kv.key[3], mte->mask.kv.key[4], mte->mask.kv.value, mte->refcount);
+ }));
+ /* *INDENT-ON* */
+}
+
+static void
+acl_plugin_show_tables_acl_hash_info (acl_main_t * am, u32 acl_index)
+{
+ vlib_main_t *vm = am->vlib_main;
+ u32 i, j;
+ u64 *m;
+ vlib_cli_output (vm, "Mask-ready ACL representations\n");
+ for (i = 0; i < vec_len (am->hash_acl_infos); i++)
+ {
+ if ((acl_index != ~0) && (acl_index != i))
+ {
+ continue;
+ }
+ hash_acl_info_t *ha = &am->hash_acl_infos[i];
+ vlib_cli_output (vm, "acl-index %u bitmask-ready layout\n", i);
+ vlib_cli_output (vm, " applied inbound on sw_if_index list: %U\n",
+ format_vec32, ha->inbound_sw_if_index_list, "%d");
+ vlib_cli_output (vm, " applied outbound on sw_if_index list: %U\n",
+ format_vec32, ha->outbound_sw_if_index_list, "%d");
+ vlib_cli_output (vm, " mask type index bitmap: %U\n",
+ format_bitmap_hex, ha->mask_type_index_bitmap);
+ for (j = 0; j < vec_len (ha->rules); j++)
+ {
+ hash_ace_info_t *pa = &ha->rules[j];
+ m = (u64 *) & pa->match;
+ vlib_cli_output (vm,
+ " %4d: %016llx %016llx %016llx %016llx %016llx %016llx mask index %d acl %d rule %d action %d src/dst portrange not ^2: %d,%d\n",
+ j, m[0], m[1], m[2], m[3], m[4], m[5],
+ pa->mask_type_index, pa->acl_index, pa->ace_index,
+ pa->action, pa->src_portrange_not_powerof2,
+ pa->dst_portrange_not_powerof2);
+ }
+ }
+}
+
+static void
+acl_plugin_print_pae (vlib_main_t * vm, int j, applied_hash_ace_entry_t * pae)
+{
+ vlib_cli_output (vm,
+ " %4d: acl %d rule %d action %d bitmask-ready rule %d next %d prev %d tail %d hitcount %lld",
+ j, pae->acl_index, pae->ace_index, pae->action,
+ pae->hash_ace_info_index, pae->next_applied_entry_index,
+ pae->prev_applied_entry_index,
+ pae->tail_applied_entry_index, pae->hitcount);
+}
+
+static void
+acl_plugin_show_tables_applied_info (acl_main_t * am, u32 sw_if_index)
+{
+ vlib_main_t *vm = am->vlib_main;
+ u32 swi, j;
+ vlib_cli_output (vm, "Applied lookup entries for interfaces");
+
+ for (swi = 0;
+ (swi < vec_len (am->input_applied_hash_acl_info_by_sw_if_index))
+ || (swi < vec_len (am->output_applied_hash_acl_info_by_sw_if_index))
+ || (swi < vec_len (am->input_hash_entry_vec_by_sw_if_index))
+ || (swi < vec_len (am->output_hash_entry_vec_by_sw_if_index)); swi++)
+ {
+ if ((sw_if_index != ~0) && (sw_if_index != swi))
+ {
+ continue;
+ }
+ vlib_cli_output (vm, "sw_if_index %d:", swi);
+ if (swi < vec_len (am->input_applied_hash_acl_info_by_sw_if_index))
+ {
+ applied_hash_acl_info_t *pal =
+ &am->input_applied_hash_acl_info_by_sw_if_index[swi];
+ vlib_cli_output (vm, " input lookup mask_type_index_bitmap: %U",
+ format_bitmap_hex, pal->mask_type_index_bitmap);
+ vlib_cli_output (vm, " input applied acls: %U", format_vec32,
+ pal->applied_acls, "%d");
+ }
+ if (swi < vec_len (am->input_hash_entry_vec_by_sw_if_index))
+ {
+ vlib_cli_output (vm, " input lookup applied entries:");
+ for (j = 0;
+ j < vec_len (am->input_hash_entry_vec_by_sw_if_index[swi]);
+ j++)
+ {
+ acl_plugin_print_pae (vm, j,
+ &am->input_hash_entry_vec_by_sw_if_index
+ [swi][j]);
+ }
+ }
+
+ if (swi < vec_len (am->output_applied_hash_acl_info_by_sw_if_index))
+ {
+ applied_hash_acl_info_t *pal =
+ &am->output_applied_hash_acl_info_by_sw_if_index[swi];
+ vlib_cli_output (vm, " output lookup mask_type_index_bitmap: %U",
+ format_bitmap_hex, pal->mask_type_index_bitmap);
+ vlib_cli_output (vm, " output applied acls: %U", format_vec32,
+ pal->applied_acls, "%d");
+ }
+ if (swi < vec_len (am->output_hash_entry_vec_by_sw_if_index))
+ {
+ vlib_cli_output (vm, " output lookup applied entries:");
+ for (j = 0;
+ j < vec_len (am->output_hash_entry_vec_by_sw_if_index[swi]);
+ j++)
+ {
+ acl_plugin_print_pae (vm, j,
+ &am->output_hash_entry_vec_by_sw_if_index
+ [swi][j]);
+ }
+ }
+ }
+}
+
+static void
+acl_plugin_show_tables_bihash (acl_main_t * am, u32 show_bihash_verbose)
+{
+ vlib_main_t *vm = am->vlib_main;
+ show_hash_acl_hash (vm, am, show_bihash_verbose);
+}
+
+static clib_error_t *
+acl_show_aclplugin_tables_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ clib_error_t *error = 0;
+ acl_main_t *am = &acl_main;
+
+ u32 acl_index = ~0;
+ u32 sw_if_index = ~0;
+ int show_acl_hash_info = 0;
+ int show_applied_info = 0;
+ int show_mask_type = 0;
+ int show_bihash = 0;
+ u32 show_bihash_verbose = 0;
+
+ if (unformat (input, "acl"))
+ {
+ show_acl_hash_info = 1;
+ /* mask-type is handy to see as well right there */
+ show_mask_type = 1;
+ unformat (input, "index %u", &acl_index);
+ }
+ else if (unformat (input, "applied"))
+ {
+ show_applied_info = 1;
+ unformat (input, "sw_if_index %u", &sw_if_index);
+ }
+ else if (unformat (input, "mask"))
+ {
+ show_mask_type = 1;
+ }
+ else if (unformat (input, "hash"))
+ {
+ show_bihash = 1;
+ unformat (input, "verbose %u", &show_bihash_verbose);
+ }
+
+ if (!
+ (show_mask_type || show_acl_hash_info || show_applied_info
+ || show_bihash))
+ {
+ /* if no qualifiers specified, show all */
+ show_mask_type = 1;
+ show_acl_hash_info = 1;
+ show_applied_info = 1;
+ show_bihash = 1;
+ }
+ if (show_mask_type)
+ acl_plugin_show_tables_mask_type (am);
+ if (show_acl_hash_info)
+ acl_plugin_show_tables_acl_hash_info (am, acl_index);
+ if (show_applied_info)
+ acl_plugin_show_tables_applied_info (am, sw_if_index);
+ if (show_bihash)
+ acl_plugin_show_tables_bihash (am, show_bihash_verbose);
+
+ return error;
+}
+
+static clib_error_t *
+acl_clear_aclplugin_fn (vlib_main_t * vm,
+ unformat_input_t * input, vlib_cli_command_t * cmd)
+{
+ clib_error_t *error = 0;
+ acl_main_t *am = &acl_main;
+ vlib_process_signal_event (am->vlib_main, am->fa_cleaner_node_index,
+ ACL_FA_CLEANER_DELETE_BY_SW_IF_INDEX, ~0);
+ return error;
+}
+
+ /* *INDENT-OFF* */
+VLIB_CLI_COMMAND (aclplugin_set_command, static) = {
+ .path = "set acl-plugin",
+ .short_help = "set acl-plugin session timeout {{udp idle}|tcp {idle|transient}} <seconds>",
+ .function = acl_set_aclplugin_fn,
+};
+
+VLIB_CLI_COMMAND (aclplugin_show_acl_command, static) = {
+ .path = "show acl-plugin acl",
+ .short_help = "show acl-plugin acl [index N]",
+ .function = acl_show_aclplugin_acl_fn,
+};
+
+VLIB_CLI_COMMAND (aclplugin_show_decode_5tuple_command, static) = {
+ .path = "show acl-plugin decode 5tuple",
+ .short_help = "show acl-plugin decode 5tuple XXXX XXXX XXXX XXXX XXXX XXXX",
+ .function = acl_show_aclplugin_decode_5tuple_fn,
+};
+
+VLIB_CLI_COMMAND (aclplugin_show_interface_command, static) = {
+ .path = "show acl-plugin interface",
+ .short_help = "show acl-plugin interface [sw_if_index N] [acl]",
+ .function = acl_show_aclplugin_interface_fn,
+};
+
+VLIB_CLI_COMMAND (aclplugin_show_memory_command, static) = {
+ .path = "show acl-plugin memory",
+ .short_help = "show acl-plugin memory",
+ .function = acl_show_aclplugin_memory_fn,
+};
+
+VLIB_CLI_COMMAND (aclplugin_show_sessions_command, static) = {
+ .path = "show acl-plugin sessions",
+ .short_help = "show acl-plugin sessions",
+ .function = acl_show_aclplugin_sessions_fn,
+};
+
+VLIB_CLI_COMMAND (aclplugin_show_tables_command, static) = {
+ .path = "show acl-plugin tables",
+ .short_help = "show acl-plugin tables [ acl [index N] | applied [ sw_if_index N ] | mask | hash [verbose N] ]",
+ .function = acl_show_aclplugin_tables_fn,
+};
+
+VLIB_CLI_COMMAND (aclplugin_show_macip_acl_command, static) = {
+ .path = "show acl-plugin macip acl",
+ .short_help = "show acl-plugin macip acl",
+ .function = acl_show_aclplugin_macip_acl_fn,
+};
+
+VLIB_CLI_COMMAND (aclplugin_show_macip_interface_command, static) = {
+ .path = "show acl-plugin macip interface",
+ .short_help = "show acl-plugin macip interface",
+ .function = acl_show_aclplugin_macip_interface_fn,
+};
+
+VLIB_CLI_COMMAND (aclplugin_clear_command, static) = {
+ .path = "clear acl-plugin sessions",
+ .short_help = "clear acl-plugin sessions",
+ .function = acl_clear_aclplugin_fn,
+};
+/* *INDENT-ON* */
+
+static clib_error_t *
+acl_plugin_config (vlib_main_t * vm, unformat_input_t * input)
+{
+ acl_main_t *am = &acl_main;
+ u32 conn_table_hash_buckets;
+ u32 conn_table_hash_memory_size;
+ u32 conn_table_max_entries;
+ u32 main_heap_size;
+ u32 hash_heap_size;
+ u32 hash_lookup_hash_buckets;
+ u32 hash_lookup_hash_memory;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat
+ (input, "connection hash buckets %d", &conn_table_hash_buckets))
+ am->fa_conn_table_hash_num_buckets = conn_table_hash_buckets;
+ else if (unformat (input, "connection hash memory %d",
+ &conn_table_hash_memory_size))
+ am->fa_conn_table_hash_memory_size = conn_table_hash_memory_size;
+ 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))
+ am->acl_mheap_size = main_heap_size;
+ else if (unformat (input, "hash lookup heap size %d", &hash_heap_size))
+ am->hash_lookup_mheap_size = hash_heap_size;
+ else if (unformat (input, "hash lookup hash buckets %d",
+ &hash_lookup_hash_buckets))
+ am->hash_lookup_hash_buckets = hash_lookup_hash_buckets;
+ else if (unformat (input, "hash lookup hash memory %d",
+ &hash_lookup_hash_memory))
+ am->hash_lookup_hash_memory = hash_lookup_hash_memory;
+ else
+ return clib_error_return (0, "unknown input '%U'",
+ format_unformat_error, input);
+ }
+ return 0;
+}
+
+VLIB_CONFIG_FUNCTION (acl_plugin_config, "acl-plugin");