X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Facl%2Ffa_node.c;h=0bbc7423a392a016c943d7594d43e93a98472d72;hb=e48457a99d3e9294f2eced29d3840023cc4de4b9;hp=78b10dc95043574d3e0fc921553d002fdc744a1e;hpb=7d5fae861ed243983155ade90c81fc27a47bf376;p=vpp.git diff --git a/src/plugins/acl/fa_node.c b/src/plugins/acl/fa_node.c index 78b10dc9504..0bbc7423a39 100644 --- a/src/plugins/acl/fa_node.c +++ b/src/plugins/acl/fa_node.c @@ -26,6 +26,7 @@ #include #include "fa_node.h" +#include "hash_lookup.h" typedef struct { @@ -136,7 +137,7 @@ fa_acl_match_port (u16 port, u16 port_first, u16 port_last, int is_ip6) } int -acl_match_5tuple (acl_main_t * am, u32 acl_index, fa_5tuple_t * pkt_5tuple, +single_acl_match_5tuple (acl_main_t * am, u32 acl_index, fa_5tuple_t * pkt_5tuple, int is_ip6, u8 * r_action, u32 * r_acl_match_p, u32 * r_rule_match_p, u32 * trace_bitmap) { @@ -259,7 +260,7 @@ acl_match_5tuple (acl_main_t * am, u32 acl_index, fa_5tuple_t * pkt_5tuple, } static u8 -full_acl_match_5tuple (u32 sw_if_index, fa_5tuple_t * pkt_5tuple, int is_l2, +linear_multi_acl_match_5tuple (u32 sw_if_index, fa_5tuple_t * pkt_5tuple, int is_l2, int is_ip6, int is_input, u32 * acl_match_p, u32 * rule_match_p, u32 * trace_bitmap) { @@ -284,7 +285,7 @@ full_acl_match_5tuple (u32 sw_if_index, fa_5tuple_t * pkt_5tuple, int is_l2, clib_warning ("ACL_FA_NODE_DBG: Trying to match ACL: %d", acl_vector[i]); #endif - if (acl_match_5tuple + if (single_acl_match_5tuple (am, acl_vector[i], pkt_5tuple, is_ip6, &action, acl_match_p, rule_match_p, trace_bitmap)) { @@ -303,6 +304,21 @@ full_acl_match_5tuple (u32 sw_if_index, fa_5tuple_t * pkt_5tuple, int is_l2, return 0; } +static u8 +multi_acl_match_5tuple (u32 sw_if_index, fa_5tuple_t * pkt_5tuple, int is_l2, + int is_ip6, int is_input, u32 * acl_match_p, + u32 * rule_match_p, u32 * trace_bitmap) +{ + acl_main_t *am = &acl_main; + if (am->use_hash_acl_matching) { + return hash_multi_acl_match_5tuple(sw_if_index, pkt_5tuple, is_l2, is_ip6, + is_input, acl_match_p, rule_match_p, trace_bitmap); + } else { + return linear_multi_acl_match_5tuple(sw_if_index, pkt_5tuple, is_l2, is_ip6, + is_input, acl_match_p, rule_match_p, trace_bitmap); + } +} + static int offset_within_packet (vlib_buffer_t * b0, int offset) { @@ -314,7 +330,7 @@ static void acl_fill_5tuple (acl_main_t * am, vlib_buffer_t * b0, int is_ip6, int is_input, int is_l2_path, fa_5tuple_t * p5tuple_pkt) { - int l3_offset = 14; + int l3_offset = ethernet_buffer_header_size(b0); int l4_offset; u16 ports[2]; u16 proto; @@ -494,9 +510,7 @@ acl_make_5tuple_session_key (int is_input, fa_5tuple_t * p5tuple_pkt, static int acl_fa_ifc_has_sessions (acl_main_t * am, int sw_if_index0) { - int has_sessions = - clib_bitmap_get (am->fa_sessions_on_sw_if_index, sw_if_index0); - return has_sessions; + return am->fa_sessions_hash_is_initialized; } static int @@ -594,13 +608,11 @@ acl_fa_ifc_init_sessions (acl_main_t * am, int sw_if_index0) sw_if_index0, am->fa_conn_table_hash_num_buckets, am->fa_conn_table_hash_memory_size); #endif - vec_validate (am->fa_sessions_by_sw_if_index, sw_if_index0); - BV (clib_bihash_init) (&am->fa_sessions_by_sw_if_index - [sw_if_index0], "ACL plugin FA session bihash", + BV (clib_bihash_init) (&am->fa_sessions_hash, + "ACL plugin FA session bihash", am->fa_conn_table_hash_num_buckets, am->fa_conn_table_hash_memory_size); - am->fa_sessions_on_sw_if_index = - clib_bitmap_set (am->fa_sessions_on_sw_if_index, sw_if_index0, 1); + am->fa_sessions_hash_is_initialized = 1; } static inline fa_session_t *get_session_ptr(acl_main_t *am, u16 thread_index, u32 session_index) @@ -715,7 +727,7 @@ acl_fa_delete_session (acl_main_t * am, u32 sw_if_index, fa_full_session_id_t se { fa_session_t *sess = get_session_ptr(am, sess_id.thread_index, sess_id.session_index); ASSERT(sess->thread_index == os_get_thread_index ()); - BV (clib_bihash_add_del) (&am->fa_sessions_by_sw_if_index[sw_if_index], + BV (clib_bihash_add_del) (&am->fa_sessions_hash, &sess->info.kv, 0); acl_fa_per_worker_data_t *pw = &am->per_worker_data[sess_id.thread_index]; pool_put_index (pw->fa_sessions_pool, sess_id.session_index); @@ -723,18 +735,15 @@ acl_fa_delete_session (acl_main_t * am, u32 sw_if_index, fa_full_session_id_t se as the caller must have dealt with the timers. */ vec_validate (am->fa_session_dels_by_sw_if_index, sw_if_index); am->fa_session_dels_by_sw_if_index[sw_if_index]++; + clib_smp_atomic_add(&am->fa_session_total_dels, 1); } static int acl_fa_can_add_session (acl_main_t * am, int is_input, u32 sw_if_index) { - u64 curr_sess; - vec_validate (am->fa_session_adds_by_sw_if_index, sw_if_index); - vec_validate (am->fa_session_dels_by_sw_if_index, sw_if_index); - curr_sess = - am->fa_session_adds_by_sw_if_index[sw_if_index] - - am->fa_session_dels_by_sw_if_index[sw_if_index]; - return (curr_sess < am->fa_conn_table_max_entries); + u64 curr_sess_count; + curr_sess_count = am->fa_session_total_adds - am->fa_session_total_dels; + return (curr_sess_count < am->fa_conn_table_max_entries); } static u64 @@ -889,12 +898,13 @@ acl_fa_add_session (acl_main_t * am, int is_input, u32 sw_if_index, u64 now, acl_fa_ifc_init_sessions (am, sw_if_index); } - BV (clib_bihash_add_del) (&am->fa_sessions_by_sw_if_index[sw_if_index], + BV (clib_bihash_add_del) (&am->fa_sessions_hash, &kv, 1); acl_fa_conn_list_add_session(am, f_sess_id, now); vec_validate (am->fa_session_adds_by_sw_if_index, sw_if_index); am->fa_session_adds_by_sw_if_index[sw_if_index]++; + clib_smp_atomic_add(&am->fa_session_total_adds, 1); } static int @@ -902,7 +912,7 @@ acl_fa_find_session (acl_main_t * am, u32 sw_if_index0, fa_5tuple_t * p5tuple, clib_bihash_kv_40_8_t * pvalue_sess) { return (BV (clib_bihash_search) - (&am->fa_sessions_by_sw_if_index[sw_if_index0], &p5tuple->kv, + (&am->fa_sessions_hash, &p5tuple->kv, pvalue_sess) == 0); } @@ -977,7 +987,12 @@ acl_fa_node_fn (vlib_main_t * vm, */ acl_fill_5tuple (am, b0, is_ip6, is_input, is_l2_path, &fa_5tuple); + fa_5tuple.l4.lsb_of_sw_if_index = sw_if_index0 & 0xffff; acl_make_5tuple_session_key (is_input, &fa_5tuple, &kv_sess); + fa_5tuple.pkt.sw_if_index = sw_if_index0; + fa_5tuple.pkt.is_ip6 = is_ip6; + fa_5tuple.pkt.is_input = is_input; + fa_5tuple.pkt.mask_type_index_lsb = ~0; #ifdef FA_NODE_VERBOSE_DEBUG clib_warning ("ACL_FA_NODE_DBG: session 5-tuple %016llx %016llx %016llx %016llx %016llx : %016llx", @@ -1024,13 +1039,27 @@ acl_fa_node_fn (vlib_main_t * vm, 0x00010000 + ((0xff & old_timeout_type) << 8) + (0xff & new_timeout_type); } + /* + * I estimate the likelihood to be very low - the VPP needs + * to have >64K interfaces to start with and then on + * exactly 64K indices apart needs to be exactly the same + * 5-tuple... Anyway, since this probability is nonzero - + * print an error and drop the unlucky packet. + * If this shows up in real world, we would need to bump + * the hash key length. + */ + if (PREDICT_FALSE(sess->sw_if_index != sw_if_index0)) { + clib_warning("BUG: session LSB16(sw_if_index) and 5-tuple collision!"); + acl_check_needed = 0; + action = 0; + } } } if (acl_check_needed) { action = - full_acl_match_5tuple (sw_if_index0, &fa_5tuple, is_l2_path, + multi_acl_match_5tuple (sw_if_index0, &fa_5tuple, is_l2_path, is_ip6, is_input, &match_acl_in_index, &match_rule_index, &trace_bitmap); error0 = action; @@ -1355,7 +1384,7 @@ acl_fa_session_cleaner_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) { acl_main_t *am = &acl_main; - u64 now = clib_cpu_time_now (); + u64 now; f64 cpu_cps = vm->clib_time.clocks_per_second; u64 next_expire; /* We should check if there are connections to clean up - at least twice a second */ @@ -1424,7 +1453,6 @@ acl_fa_session_cleaner_process (vlib_main_t * vm, vlib_node_runtime_t * rt, } } - now = clib_cpu_time_now (); switch (event_type) { case ~0: @@ -1437,6 +1465,7 @@ acl_fa_session_cleaner_process (vlib_main_t * vm, vlib_node_runtime_t * rt, { uword *clear_sw_if_index_bitmap = 0; uword *sw_if_index0; + int clear_all = 0; #ifdef FA_NODE_VERBOSE_DEBUG clib_warning("ACL_FA_CLEANER_DELETE_BY_SW_IF_INDEX received"); #endif @@ -1448,7 +1477,17 @@ acl_fa_session_cleaner_process (vlib_main_t * vm, vlib_node_runtime_t * rt, ("ACL_FA_NODE_CLEAN: ACL_FA_CLEANER_DELETE_BY_SW_IF_INDEX: %d", *sw_if_index0); #endif - clear_sw_if_index_bitmap = clib_bitmap_set(clear_sw_if_index_bitmap, *sw_if_index0, 1); + if (*sw_if_index0 == ~0) + { + clear_all = 1; + } + else + { + if (!pool_is_free_index (am->vnet_main->interface_main.sw_interfaces, *sw_if_index0)) + { + clear_sw_if_index_bitmap = clib_bitmap_set(clear_sw_if_index_bitmap, *sw_if_index0, 1); + } + } } #ifdef FA_NODE_VERBOSE_DEBUG clib_warning("ACL_FA_CLEANER_DELETE_BY_SW_IF_INDEX bitmap: %U", format_bitmap_hex, clear_sw_if_index_bitmap); @@ -1468,7 +1507,15 @@ acl_fa_session_cleaner_process (vlib_main_t * vm, vlib_node_runtime_t * rt, if (pw0->clear_in_process) { clib_warning("ERROR-BUG! Could not initiate cleaning on worker because another cleanup in progress"); } else { - pw0->pending_clear_sw_if_index_bitmap = clib_bitmap_dup(clear_sw_if_index_bitmap); + if (clear_all) + { + /* if we need to clear all, then just clear the interfaces that we are servicing */ + pw0->pending_clear_sw_if_index_bitmap = clib_bitmap_dup(pw0->serviced_sw_if_index_bitmap); + } + else + { + pw0->pending_clear_sw_if_index_bitmap = clib_bitmap_dup(clear_sw_if_index_bitmap); + } pw0->clear_in_process = 1; } } @@ -1551,6 +1598,7 @@ acl_fa_enable_disable (u32 sw_if_index, int is_input, int enable_disable) acl_main_t *am = &acl_main; if (is_input) { + ASSERT(clib_bitmap_get(am->fa_in_acl_on_sw_if_index, sw_if_index) != enable_disable); vnet_feature_enable_disable ("ip4-unicast", "acl-plugin-in-ip4-fa", sw_if_index, enable_disable, 0, 0); vnet_feature_enable_disable ("ip6-unicast", "acl-plugin-in-ip6-fa", @@ -1561,6 +1609,7 @@ acl_fa_enable_disable (u32 sw_if_index, int is_input, int enable_disable) } else { + ASSERT(clib_bitmap_get(am->fa_out_acl_on_sw_if_index, sw_if_index) != enable_disable); vnet_feature_enable_disable ("ip4-output", "acl-plugin-out-ip4-fa", sw_if_index, enable_disable, 0, 0); vnet_feature_enable_disable ("ip6-output", "acl-plugin-out-ip6-fa", @@ -1581,6 +1630,17 @@ acl_fa_enable_disable (u32 sw_if_index, int is_input, int enable_disable) } } +void +show_fa_sessions_hash(vlib_main_t * vm, u32 verbose) +{ + acl_main_t *am = &acl_main; + if (am->fa_sessions_hash_is_initialized) { + vlib_cli_output(vm, "\nSession lookup hash table:\n%U\n\n", + BV (format_bihash), &am->fa_sessions_hash, verbose); + } else { + vlib_cli_output(vm, "\nSession lookup hash table is not allocated.\n\n"); + } +} /* *INDENT-OFF* */