X-Git-Url: https://gerrit.fd.io/r/gitweb?p=vpp.git;a=blobdiff_plain;f=src%2Fplugins%2Facl%2Facl.c;h=1e040b6a0363b532cec10a04db7494a3e45fcd9e;hp=57940fcccd784cb161021a3ca935f06b083fa3d1;hb=bb5d22d;hpb=563a8531cbc3e7c222e3e4841637b94b65637caa diff --git a/src/plugins/acl/acl.c b/src/plugins/acl/acl.c index 57940fcccd7..1e040b6a036 100644 --- a/src/plugins/acl/acl.c +++ b/src/plugins/acl/acl.c @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -58,6 +59,13 @@ acl_main_t acl_main; #define REPLY_MSG_ID_BASE am->msg_id_base #include +/* + * The code for the bihash, used by the session management. + */ +#include +#include +#include + /* List of message types that this plugin understands */ #define foreach_acl_plugin_api_msg \ @@ -77,7 +85,8 @@ _(MACIP_ACL_DUMP, macip_acl_dump) \ _(MACIP_ACL_INTERFACE_GET, macip_acl_interface_get) \ _(MACIP_ACL_INTERFACE_LIST_DUMP, macip_acl_interface_list_dump) \ _(ACL_INTERFACE_SET_ETYPE_WHITELIST, acl_interface_set_etype_whitelist) \ -_(ACL_INTERFACE_ETYPE_WHITELIST_DUMP, acl_interface_etype_whitelist_dump) +_(ACL_INTERFACE_ETYPE_WHITELIST_DUMP, acl_interface_etype_whitelist_dump) \ +_(ACL_PLUGIN_GET_CONN_TABLE_MAX_ENTRIES,acl_plugin_get_conn_table_max_entries) /* *INDENT-OFF* */ @@ -87,6 +96,9 @@ VLIB_PLUGIN_REGISTER () = { }; /* *INDENT-ON* */ +/* methods exported from ACL-as-a-service */ +static acl_plugin_methods_t acl_plugin; + /* Format vec16. */ u8 * format_vec16 (u8 * s, va_list * va) @@ -103,27 +115,42 @@ format_vec16 (u8 * s, va_list * va) return s; } - - -u8 -acl_plugin_acl_exists (u32 acl_index) -{ - acl_main_t *am = &acl_main; - - if (pool_is_free_index (am->acls, acl_index)) - return 0; - - return 1; -} - static void * acl_set_heap (acl_main_t * am) { if (0 == am->acl_mheap) { - am->acl_mheap = mheap_alloc (0 /* use VM */ , am->acl_mheap_size); - mheap_t *h = mheap_header (am->acl_mheap); - h->flags |= MHEAP_FLAG_THREAD_SAFE; + 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_with_lock (0 /* use VM */ , + am->acl_mheap_size, + 1 /* locked */ ); + 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); + } } void *oldheap = clib_mem_set_heap (am->acl_mheap); return oldheap; @@ -140,6 +167,7 @@ void acl_plugin_acl_set_validate_heap (acl_main_t * am, int on) { clib_mem_set_heap (acl_set_heap (am)); +#if USE_DLMALLOC == 0 mheap_t *h = mheap_header (am->acl_mheap); if (on) { @@ -152,12 +180,14 @@ acl_plugin_acl_set_validate_heap (acl_main_t * am, int on) h->flags &= ~MHEAP_FLAG_VALIDATE; h->flags |= MHEAP_FLAG_SMALL_OBJECT_CACHE; } +#endif } void acl_plugin_acl_set_trace_heap (acl_main_t * am, int on) { clib_mem_set_heap (acl_set_heap (am)); +#if USE_DLMALLOC == 0 mheap_t *h = mheap_header (am->acl_mheap); if (on) { @@ -167,6 +197,7 @@ acl_plugin_acl_set_trace_heap (acl_main_t * am, int on) { h->flags &= ~MHEAP_FLAG_TRACE; } +#endif } static void @@ -182,7 +213,7 @@ vl_api_acl_plugin_get_version_t_handler (vl_api_acl_plugin_get_version_t * mp) return; rmp = vl_msg_api_alloc (msg_size); - memset (rmp, 0, msg_size); + clib_memset (rmp, 0, msg_size); rmp->_vl_msg_id = ntohs (VL_API_ACL_PLUGIN_GET_VERSION_REPLY + am->msg_id_base); rmp->context = mp->context; @@ -236,7 +267,7 @@ acl_print_acl_x (acl_vector_print_func_t vpr, vlib_main_t * vm, for (j = 0; j < am->acls[acl_index].count; j++) { r = &am->acls[acl_index].rules[j]; - out0 = format (out0, " %4d: %s ", j, r->is_ipv6 ? "ipv6" : "ipv4"); + out0 = format (out0, " %9d: %s ", j, r->is_ipv6 ? "ipv6" : "ipv4"); out0 = format_acl_action (out0, r->is_permit); out0 = format (out0, " src %U/%d", format_ip46_address, &r->src, r->is_ipv6 ? IP46_TYPE_IP6 : IP46_TYPE_IP4, @@ -266,6 +297,32 @@ acl_print_acl_x (acl_vector_print_func_t vpr, vlib_main_t * vm, } } +static void + vl_api_acl_plugin_get_conn_table_max_entries_t_handler + (vl_api_acl_plugin_get_conn_table_max_entries_t * mp) +{ + acl_main_t *am = &acl_main; + vl_api_acl_plugin_get_conn_table_max_entries_reply_t *rmp; + int msg_size = sizeof (*rmp); + unix_shared_memory_queue_t *q; + + q = vl_api_client_index_to_input_queue (mp->client_index); + if (q == 0) + { + return; + } + + rmp = vl_msg_api_alloc (msg_size); + memset (rmp, 0, msg_size); + rmp->_vl_msg_id = + ntohs (VL_API_ACL_PLUGIN_GET_CONN_TABLE_MAX_ENTRIES_REPLY + + am->msg_id_base); + rmp->context = mp->context; + rmp->conn_table_max_entries = __bswap_64 (am->fa_conn_table_max_entries); + + vl_msg_api_send_shmem (q, (u8 *) & rmp); +} + static void acl_print_acl (vlib_main_t * vm, acl_main_t * am, int acl_index) { @@ -278,6 +335,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[], @@ -321,7 +417,7 @@ acl_add_list (u32 count, vl_api_acl_rule_t rules[], for (i = 0; i < count; i++) { r = vec_elt_at_index (acl_new_rules, i); - memset (r, 0, sizeof (*r)); + clib_memset (r, 0, sizeof (*r)); r->is_permit = rules[i].is_permit; r->is_ipv6 = rules[i].is_ipv6; if (r->is_ipv6) @@ -349,7 +445,7 @@ acl_add_list (u32 count, vl_api_acl_rule_t rules[], { /* Get ACL index */ pool_get_aligned (am->acls, a, CLIB_CACHE_LINE_BYTES); - memset (a, 0, sizeof (*a)); + clib_memset (a, 0, sizeof (*a)); /* Will return the newly allocated ACL index */ *acl_list_index = a - am->acls; } @@ -365,6 +461,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); @@ -398,7 +500,7 @@ acl_del_list (u32 acl_list_index) return VNET_API_ERROR_ACL_IN_USE_INBOUND; if (acl_is_used_by (acl_list_index, am->output_sw_if_index_vec_by_acl)) return VNET_API_ERROR_ACL_IN_USE_OUTBOUND; - /* lookup contexts cover other cases, not just inbound/oubound, so check that */ + /* lookup contexts cover other cases, not just inbound/outbound, so check that */ if (acl_is_used_by (acl_list_index, am->lc_index_vec_by_acl)) return VNET_API_ERROR_ACL_IN_USE_BY_LOOKUP_CONTEXT; @@ -415,86 +517,6 @@ acl_del_list (u32 acl_list_index) return 0; } -/* Some aids in ASCII graphing the content */ -#define XX "\377" -#define __ "\000" -#define _(x) -#define v -/* *INDENT-OFF* */ - -u8 ip4_5tuple_mask[] = - _(" dmac smac etype ") - _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v __ __ v - _(" v ihl totlen ") - _(0x0000) - __ __ __ __ - _(" ident fl+fo ") - _(0x0004) - __ __ __ __ - _(" ttl pr checksum ") - _(0x0008) - __ XX __ __ - _(" src address ") - _(0x000C) - XX XX XX XX - _(" dst address ") - _(0x0010) - XX XX XX XX - _("L4 T/U sport dport ") - _(tcpudp) - XX XX XX XX - _(padpad) - __ __ __ __ - _(padpad) - __ __ __ __ - _(padeth) - __ __; - - u8 ip6_5tuple_mask[] = - _(" dmac smac etype ") - _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v __ __ v - _(" v tc + flow ") - _(0x0000) __ __ __ __ - _(" plen nh hl ") - _(0x0004) __ __ XX __ - _(" src address ") - _(0x0008) XX XX XX XX - _(0x000C) XX XX XX XX - _(0x0010) XX XX XX XX - _(0x0014) XX XX XX XX - _(" dst address ") - _(0x0018) XX XX XX XX - _(0x001C) XX XX XX XX - _(0x0020) XX XX XX XX - _(0x0024) XX XX XX XX - _("L4T/U sport dport ") - _(tcpudp) XX XX XX XX _(padpad) __ __ __ __ _(padeth) __ __; - - u8 dot1q_5tuple_mask[] = - _(" dmac smac dot1q etype ") - _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v XX XX __ __ v XX XX v - _(padpad) __ __ __ __ - _(padpad) __ __ __ __ - _(padpad) __ __ __ __ - _(padeth) __ __; - - u8 dot1ad_5tuple_mask[] = - _(" dmac smac dot1ad dot1q etype ") - _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v XX XX __ __ XX XX __ __ v XX XX v - _(padpad) __ __ __ __ - _(padpad) __ __ __ __ - _(padeth) __ __; - - u8 ethertype_mask[] = - _(" dmac smac etype ") - _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v XX XX __ __; - -/* *INDENT-ON* */ -#undef XX -#undef __ -#undef _ -#undef v - static int count_skip (u8 * p, u32 size) { @@ -510,33 +532,6 @@ count_skip (u8 * p, u32 size) return (p64 - (u64 *) p) / 2; } -static int -acl_classify_add_del_table_tiny (vnet_classify_main_t * cm, u8 * mask, - u32 mask_len, u32 next_table_index, - u32 miss_next_index, u32 * table_index, - int is_add) -{ - u32 nbuckets = 1; - u32 memory_size = 2 << 13; - u32 skip = count_skip (mask, mask_len); - u32 match = (mask_len / 16) - skip; - u8 *skip_mask_ptr = mask + 16 * skip; - u32 current_data_flag = 0; - int current_data_offset = 0; - - if (0 == match) - match = 1; - void *oldheap = clib_mem_set_heap (cm->vlib_main->heap_base); - int ret = vnet_classify_add_del_table (cm, skip_mask_ptr, nbuckets, - memory_size, skip, match, - next_table_index, miss_next_index, - table_index, current_data_flag, - current_data_offset, is_add, - 1 /* delete_chain */ ); - clib_mem_set_heap (oldheap); - return ret; -} - static int acl_classify_add_del_table_small (vnet_classify_main_t * cm, u8 * mask, u32 mask_len, u32 next_table_index, @@ -565,503 +560,14 @@ acl_classify_add_del_table_small (vnet_classify_main_t * cm, u8 * mask, return ret; } -static int -acl_unhook_l2_input_classify (acl_main_t * am, u32 sw_if_index) -{ - vnet_classify_main_t *cm = &vnet_classify_main; - u32 ip4_table_index = ~0; - u32 ip6_table_index = ~0; - u32 dot1q_table_index = ~0; - u32 dot1ad_table_index = ~0; - u32 etype_table_index = ~0; - void *oldheap = acl_set_heap (am); - - vec_validate_init_empty (am->acl_ip4_input_classify_table_by_sw_if_index, - sw_if_index, ~0); - vec_validate_init_empty (am->acl_ip6_input_classify_table_by_sw_if_index, - sw_if_index, ~0); - vec_validate_init_empty (am->acl_dot1q_input_classify_table_by_sw_if_index, - sw_if_index, ~0); - vec_validate_init_empty (am->acl_dot1ad_input_classify_table_by_sw_if_index, - sw_if_index, ~0); - vec_validate_init_empty (am->acl_etype_input_classify_table_by_sw_if_index, - sw_if_index, ~0); - - /* switch to global heap while calling vnet_* functions */ - clib_mem_set_heap (cm->vlib_main->heap_base); - vnet_l2_input_classify_enable_disable (sw_if_index, 0); - - if (am->acl_ip4_input_classify_table_by_sw_if_index[sw_if_index] != ~0) - { - ip4_table_index = - am->acl_ip4_input_classify_table_by_sw_if_index[sw_if_index]; - am->acl_ip4_input_classify_table_by_sw_if_index[sw_if_index] = ~0; - acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask, - sizeof (ip4_5tuple_mask) - 1, ~0, - am->l2_input_classify_next_acl_ip4, - &ip4_table_index, 0); - } - if (am->acl_ip6_input_classify_table_by_sw_if_index[sw_if_index] != ~0) - { - ip6_table_index = - am->acl_ip6_input_classify_table_by_sw_if_index[sw_if_index]; - am->acl_ip6_input_classify_table_by_sw_if_index[sw_if_index] = ~0; - acl_classify_add_del_table_tiny (cm, ip6_5tuple_mask, - sizeof (ip6_5tuple_mask) - 1, ~0, - am->l2_input_classify_next_acl_ip6, - &ip6_table_index, 0); - } - if (am->acl_dot1q_input_classify_table_by_sw_if_index[sw_if_index] != ~0) - { - dot1q_table_index = - am->acl_dot1q_input_classify_table_by_sw_if_index[sw_if_index]; - am->acl_dot1q_input_classify_table_by_sw_if_index[sw_if_index] = ~0; - acl_classify_add_del_table_tiny (cm, ip6_5tuple_mask, - sizeof (ip6_5tuple_mask) - 1, ~0, - ~0, &dot1q_table_index, 0); - } - if (am->acl_dot1ad_input_classify_table_by_sw_if_index[sw_if_index] != ~0) - { - dot1ad_table_index = - am->acl_dot1ad_input_classify_table_by_sw_if_index[sw_if_index]; - am->acl_dot1ad_input_classify_table_by_sw_if_index[sw_if_index] = ~0; - acl_classify_add_del_table_tiny (cm, dot1ad_5tuple_mask, - sizeof (dot1ad_5tuple_mask) - 1, ~0, - ~0, &dot1ad_table_index, 0); - } - if (am->acl_etype_input_classify_table_by_sw_if_index[sw_if_index] != ~0) - { - etype_table_index = - am->acl_etype_input_classify_table_by_sw_if_index[sw_if_index]; - am->acl_etype_input_classify_table_by_sw_if_index[sw_if_index] = ~0; - acl_classify_add_del_table_tiny (cm, ethertype_mask, - sizeof (ethertype_mask) - 1, ~0, - ~0, &etype_table_index, 0); - } - clib_mem_set_heap (oldheap); - return 0; -} - -static int -acl_unhook_l2_output_classify (acl_main_t * am, u32 sw_if_index) -{ - vnet_classify_main_t *cm = &vnet_classify_main; - u32 ip4_table_index = ~0; - u32 ip6_table_index = ~0; - u32 dot1q_table_index = ~0; - u32 dot1ad_table_index = ~0; - u32 etype_table_index = ~0; - void *oldheap = acl_set_heap (am); - - vec_validate_init_empty (am->acl_ip4_output_classify_table_by_sw_if_index, - sw_if_index, ~0); - vec_validate_init_empty (am->acl_ip6_output_classify_table_by_sw_if_index, - sw_if_index, ~0); - vec_validate_init_empty (am->acl_dot1q_output_classify_table_by_sw_if_index, - sw_if_index, ~0); - vec_validate_init_empty - (am->acl_dot1ad_output_classify_table_by_sw_if_index, sw_if_index, ~0); - vec_validate_init_empty (am->acl_etype_output_classify_table_by_sw_if_index, - sw_if_index, ~0); - - /* switch to global heap while calling vnet_* functions */ - clib_mem_set_heap (cm->vlib_main->heap_base); - - vnet_l2_output_classify_enable_disable (sw_if_index, 0); - - if (am->acl_ip4_output_classify_table_by_sw_if_index[sw_if_index] != ~0) - { - ip4_table_index = - am->acl_ip4_output_classify_table_by_sw_if_index[sw_if_index]; - am->acl_ip4_output_classify_table_by_sw_if_index[sw_if_index] = ~0; - acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask, - sizeof (ip4_5tuple_mask) - 1, ~0, - am->l2_output_classify_next_acl_ip4, - &ip4_table_index, 0); - } - if (am->acl_ip6_output_classify_table_by_sw_if_index[sw_if_index] != ~0) - { - ip6_table_index = - am->acl_ip6_output_classify_table_by_sw_if_index[sw_if_index]; - am->acl_ip6_output_classify_table_by_sw_if_index[sw_if_index] = ~0; - acl_classify_add_del_table_tiny (cm, ip6_5tuple_mask, - sizeof (ip6_5tuple_mask) - 1, ~0, - am->l2_output_classify_next_acl_ip6, - &ip6_table_index, 0); - } - if (am->acl_dot1q_output_classify_table_by_sw_if_index[sw_if_index] != ~0) - { - dot1q_table_index = - am->acl_dot1q_output_classify_table_by_sw_if_index[sw_if_index]; - am->acl_dot1q_output_classify_table_by_sw_if_index[sw_if_index] = ~0; - acl_classify_add_del_table_tiny (cm, ip6_5tuple_mask, - sizeof (ip6_5tuple_mask) - 1, ~0, - ~0, &dot1q_table_index, 0); - } - if (am->acl_dot1ad_output_classify_table_by_sw_if_index[sw_if_index] != ~0) - { - dot1ad_table_index = - am->acl_dot1ad_output_classify_table_by_sw_if_index[sw_if_index]; - am->acl_dot1ad_output_classify_table_by_sw_if_index[sw_if_index] = ~0; - acl_classify_add_del_table_tiny (cm, dot1ad_5tuple_mask, - sizeof (dot1ad_5tuple_mask) - 1, ~0, - ~0, &dot1ad_table_index, 0); - } - if (am->acl_etype_output_classify_table_by_sw_if_index[sw_if_index] != ~0) - { - etype_table_index = - am->acl_etype_output_classify_table_by_sw_if_index[sw_if_index]; - am->acl_etype_output_classify_table_by_sw_if_index[sw_if_index] = ~0; - acl_classify_add_del_table_tiny (cm, ethertype_mask, - sizeof (ethertype_mask) - 1, ~0, - ~0, &etype_table_index, 0); - } - clib_mem_set_heap (oldheap); - return 0; -} - -static void -acl_add_vlan_session (acl_main_t * am, u32 table_index, u8 is_output, - u8 is_dot1ad, u8 is_ip6) -{ - vnet_classify_main_t *cm = &vnet_classify_main; - u8 *match; - u32 next_acl; - u8 idx; - u8 session_idx; - - if (is_ip6) - { - next_acl = - (is_output) ? am-> - l2_output_classify_next_acl_ip6 : am->l2_input_classify_next_acl_ip6; - } - else - { - next_acl = - (is_output) ? am-> - l2_output_classify_next_acl_ip4 : am->l2_input_classify_next_acl_ip4; - } - match = (is_dot1ad) ? dot1ad_5tuple_mask : dot1q_5tuple_mask; - idx = (is_dot1ad) ? 20 : 16; - if (is_dot1ad) - { - /* 802.1ad ethertype */ - match[12] = 0x88; - match[13] = 0xa8; - /* 802.1q ethertype */ - match[16] = 0x81; - match[17] = 0x00; - } - else - { - /* 802.1q ethertype */ - match[12] = 0x81; - match[13] = 0x00; - } - - /* add sessions to vlan tables per ethernet_type */ - if (is_ip6) - { - match[idx] = 0x86; - match[idx + 1] = 0xdd; - session_idx = 1; - } - else - { - match[idx] = 0x08; - match[idx + 1] = 0x00; - session_idx = 0; - } - vnet_classify_add_del_session (cm, table_index, match, next_acl, - session_idx, 0, 0, 0, 1); - /* reset the mask back to being a mask */ - match[idx] = 0xff; - match[idx + 1] = 0xff; - match[12] = 0xff; - match[13] = 0xff; - if (is_dot1ad) - { - match[16] = 0xff; - match[17] = 0xff; - } -} - static int intf_has_etype_whitelist (acl_main_t * am, u32 sw_if_index, int is_input) { u16 **v = is_input ? am->input_etype_whitelist_by_sw_if_index : am->output_etype_whitelist_by_sw_if_index; - return ((vec_len (v) > sw_if_index) && vec_elt (v, sw_if_index)); -} - -static int -etype_whitelist_add_sessions (acl_main_t * am, u32 sw_if_index, int is_input, - u32 etype_table_index) -{ - vnet_classify_main_t *cm = &vnet_classify_main; - u16 **v = is_input - ? am->input_etype_whitelist_by_sw_if_index - : am->output_etype_whitelist_by_sw_if_index; - u8 *match = ethertype_mask; - - int i; - int rv = 0; - u16 *whitelist = vec_elt (v, sw_if_index); - u32 next = ~0; /* permit */ - for (i = 0; i < vec_len (whitelist); i++) - { - /* big-endian */ - match[12] = (whitelist[i] >> 8) & 0xff; - match[13] = whitelist[i] & 0xff; - rv = rv - || vnet_classify_add_del_session (cm, etype_table_index, match, next, - whitelist[i], 0, 0, 0, 1); - } - - /* restore the mask */ - match[12] = 0xff; - match[13] = 0xff; - return rv; -} - -static int -acl_hook_l2_input_classify (acl_main_t * am, u32 sw_if_index) -{ - vnet_classify_main_t *cm = &vnet_classify_main; - u32 ip4_table_index = ~0; - u32 ip6_table_index = ~0; - u32 dot1q_table_index = ~0; - u32 dot1ad_table_index = ~0; - u32 etype_table_index = ~0; - int rv; - - void *prevheap = clib_mem_set_heap (cm->vlib_main->heap_base); - - /* in case there were previous tables attached */ - acl_unhook_l2_input_classify (am, sw_if_index); - rv = - acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask, - sizeof (ip4_5tuple_mask) - 1, ~0, - am->l2_input_classify_next_acl_ip4, - &ip4_table_index, 1); - if (rv) - goto done; - - rv = - acl_classify_add_del_table_tiny (cm, ip6_5tuple_mask, - sizeof (ip6_5tuple_mask) - 1, ~0, - am->l2_input_classify_next_acl_ip6, - &ip6_table_index, 1); - if (rv) - { - acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask, - sizeof (ip4_5tuple_mask) - 1, ~0, - am->l2_input_classify_next_acl_ip4, - &ip4_table_index, 0); - goto done; - } - - if (intf_has_etype_whitelist (am, sw_if_index, 1)) - { - acl_classify_add_del_table_tiny (cm, ethertype_mask, sizeof (ethertype_mask) - 1, ~0, 0, /* drop if no match */ - &etype_table_index, 1); - etype_whitelist_add_sessions (am, sw_if_index, 1, etype_table_index); - } - - rv = - acl_classify_add_del_table_tiny (cm, dot1ad_5tuple_mask, - sizeof (dot1ad_5tuple_mask) - 1, - etype_table_index, ~0, - &dot1ad_table_index, 1); - rv = - acl_classify_add_del_table_tiny (cm, dot1q_5tuple_mask, - sizeof (dot1q_5tuple_mask) - 1, - dot1ad_table_index, ~0, - &dot1q_table_index, 1); - if (rv) - { - acl_classify_add_del_table_tiny (cm, dot1ad_5tuple_mask, - sizeof (dot1ad_5tuple_mask) - 1, ~0, - ~0, &dot1ad_table_index, 0); - acl_classify_add_del_table_tiny (cm, ip6_5tuple_mask, - sizeof (ip6_5tuple_mask) - 1, ~0, - am->l2_input_classify_next_acl_ip6, - &ip6_table_index, 0); - acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask, - sizeof (ip4_5tuple_mask) - 1, ~0, - am->l2_input_classify_next_acl_ip4, - &ip4_table_index, 0); - goto done; - } - - rv = - vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index, - ip6_table_index, dot1q_table_index); - - if (rv) - { - acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask, - sizeof (ip4_5tuple_mask) - 1, ~0, - am->l2_input_classify_next_acl_ip4, - &ip4_table_index, 0); - acl_classify_add_del_table_tiny (cm, ip6_5tuple_mask, - sizeof (ip6_5tuple_mask) - 1, ~0, - am->l2_input_classify_next_acl_ip6, - &ip6_table_index, 0); - acl_classify_add_del_table_tiny (cm, dot1q_5tuple_mask, - sizeof (dot1q_5tuple_mask) - 1, ~0, - ~0, &dot1q_table_index, 0); - acl_classify_add_del_table_tiny (cm, dot1ad_5tuple_mask, - sizeof (dot1ad_5tuple_mask) - 1, ~0, - ~0, &dot1ad_table_index, 0); - goto done; - } - - /* add sessions to vlan tables per ethernet_type */ - acl_add_vlan_session (am, dot1q_table_index, 0, 0, 0); - acl_add_vlan_session (am, dot1q_table_index, 0, 0, 1); - acl_add_vlan_session (am, dot1ad_table_index, 0, 1, 0); - acl_add_vlan_session (am, dot1ad_table_index, 0, 1, 1); - - am->acl_ip4_input_classify_table_by_sw_if_index[sw_if_index] = - ip4_table_index; - am->acl_ip6_input_classify_table_by_sw_if_index[sw_if_index] = - ip6_table_index; - am->acl_dot1q_input_classify_table_by_sw_if_index[sw_if_index] = - dot1q_table_index; - am->acl_dot1ad_input_classify_table_by_sw_if_index[sw_if_index] = - dot1ad_table_index; - am->acl_dot1ad_input_classify_table_by_sw_if_index[sw_if_index] = - dot1ad_table_index; - am->acl_etype_input_classify_table_by_sw_if_index[sw_if_index] = - etype_table_index; - - vnet_l2_input_classify_enable_disable (sw_if_index, 1); -done: - clib_mem_set_heap (prevheap); - return rv; -} - -static int -acl_hook_l2_output_classify (acl_main_t * am, u32 sw_if_index) -{ - vnet_classify_main_t *cm = &vnet_classify_main; - u32 ip4_table_index = ~0; - u32 ip6_table_index = ~0; - u32 dot1q_table_index = ~0; - u32 dot1ad_table_index = ~0; - u32 etype_table_index = ~0; - int rv; - - void *prevheap = clib_mem_set_heap (cm->vlib_main->heap_base); - - /* in case there were previous tables attached */ - acl_unhook_l2_output_classify (am, sw_if_index); - rv = - acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask, - sizeof (ip4_5tuple_mask) - 1, ~0, - am->l2_output_classify_next_acl_ip4, - &ip4_table_index, 1); - if (rv) - goto done; - rv = - acl_classify_add_del_table_tiny (cm, ip6_5tuple_mask, - sizeof (ip6_5tuple_mask) - 1, ~0, - am->l2_output_classify_next_acl_ip6, - &ip6_table_index, 1); - if (rv) - { - acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask, - sizeof (ip4_5tuple_mask) - 1, ~0, - am->l2_output_classify_next_acl_ip4, - &ip4_table_index, 0); - goto done; - } - - if (intf_has_etype_whitelist (am, sw_if_index, 0)) - { - acl_classify_add_del_table_tiny (cm, ethertype_mask, sizeof (ethertype_mask) - 1, ~0, 0, /* drop if no match */ - &etype_table_index, 1); - etype_whitelist_add_sessions (am, sw_if_index, 0, etype_table_index); - } - - - rv = - acl_classify_add_del_table_tiny (cm, dot1ad_5tuple_mask, - sizeof (dot1ad_5tuple_mask) - 1, - etype_table_index, ~0, - &dot1ad_table_index, 1); - rv = - acl_classify_add_del_table_tiny (cm, dot1q_5tuple_mask, - sizeof (dot1q_5tuple_mask) - 1, - dot1ad_table_index, ~0, - &dot1q_table_index, 1); - if (rv) - { - acl_classify_add_del_table_tiny (cm, dot1ad_5tuple_mask, - sizeof (dot1ad_5tuple_mask) - 1, ~0, - ~0, &dot1ad_table_index, 0); - acl_classify_add_del_table_tiny (cm, ip6_5tuple_mask, - sizeof (ip6_5tuple_mask) - 1, ~0, - am->l2_output_classify_next_acl_ip6, - &ip6_table_index, 0); - acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask, - sizeof (ip4_5tuple_mask) - 1, ~0, - am->l2_output_classify_next_acl_ip4, - &ip4_table_index, 0); - goto done; - } - - rv = - vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index, - ip6_table_index, dot1q_table_index); -/* - clib_warning - ("ACL enabling on interface sw_if_index %d, setting tables to the following: ip4: %d ip6: %d\n", - sw_if_index, ip4_table_index, ip6_table_index); -*/ - if (rv) - { - acl_classify_add_del_table_tiny (cm, ip6_5tuple_mask, - sizeof (ip6_5tuple_mask) - 1, ~0, - am->l2_output_classify_next_acl_ip6, - &ip6_table_index, 0); - acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask, - sizeof (ip4_5tuple_mask) - 1, ~0, - am->l2_output_classify_next_acl_ip4, - &ip4_table_index, 0); - acl_classify_add_del_table_tiny (cm, dot1q_5tuple_mask, - sizeof (dot1q_5tuple_mask) - 1, ~0, - ~0, &dot1q_table_index, 0); - acl_classify_add_del_table_tiny (cm, dot1ad_5tuple_mask, - sizeof (dot1ad_5tuple_mask) - 1, ~0, - ~0, &dot1ad_table_index, 0); - goto done; - } - - /* add sessions to vlan tables per ethernet_type */ - acl_add_vlan_session (am, dot1q_table_index, 1, 0, 0); - acl_add_vlan_session (am, dot1q_table_index, 1, 0, 1); - acl_add_vlan_session (am, dot1ad_table_index, 1, 1, 0); - acl_add_vlan_session (am, dot1ad_table_index, 1, 1, 1); - - am->acl_ip4_output_classify_table_by_sw_if_index[sw_if_index] = - ip4_table_index; - am->acl_ip6_output_classify_table_by_sw_if_index[sw_if_index] = - ip6_table_index; - am->acl_dot1q_output_classify_table_by_sw_if_index[sw_if_index] = - dot1q_table_index; - am->acl_dot1ad_output_classify_table_by_sw_if_index[sw_if_index] = - dot1ad_table_index; - am->acl_etype_output_classify_table_by_sw_if_index[sw_if_index] = - etype_table_index; - - vnet_l2_output_classify_enable_disable (sw_if_index, 1); -done: - clib_mem_set_heap (prevheap); - return rv; + u16 *whitelist = (vec_len (v) > sw_if_index) ? vec_elt (v, sw_if_index) : 0; + return vec_len (whitelist) > 0; } static void @@ -1092,14 +598,22 @@ acl_interface_in_enable_disable (acl_main_t * am, u32 sw_if_index, acl_fa_enable_disable (sw_if_index, 1, enable_disable); - if (enable_disable) - { - rv = acl_hook_l2_input_classify (am, sw_if_index); - } - else - { - rv = acl_unhook_l2_input_classify (am, sw_if_index); - } + void *oldheap = clib_mem_set_heap (am->vlib_main->heap_base); + rv = vnet_l2_feature_enable_disable ("l2-input-ip4", "acl-plugin-in-ip4-l2", + sw_if_index, enable_disable, 0, 0); + if (rv) + clib_error ("Could not enable on input"); + rv = vnet_l2_feature_enable_disable ("l2-input-ip6", "acl-plugin-in-ip6-l2", + sw_if_index, enable_disable, 0, 0); + if (rv) + clib_error ("Could not enable on input"); + + if (intf_has_etype_whitelist (am, sw_if_index, 1)) + vnet_l2_feature_enable_disable ("l2-input-nonip", + "acl-plugin-in-nonip-l2", sw_if_index, + enable_disable, 0, 0); + + clib_mem_set_heap (oldheap); am->in_acl_on_sw_if_index = clib_bitmap_set (am->in_acl_on_sw_if_index, sw_if_index, enable_disable); @@ -1111,7 +625,7 @@ static int acl_interface_out_enable_disable (acl_main_t * am, u32 sw_if_index, int enable_disable) { - int rv; + int rv = 0; /* Utterly wrong? */ if (pool_is_free_index (am->vnet_main->interface_main.sw_interfaces, @@ -1124,14 +638,24 @@ acl_interface_out_enable_disable (acl_main_t * am, u32 sw_if_index, acl_fa_enable_disable (sw_if_index, 0, enable_disable); - if (enable_disable) - { - rv = acl_hook_l2_output_classify (am, sw_if_index); - } - else - { - rv = acl_unhook_l2_output_classify (am, sw_if_index); - } + void *oldheap = clib_mem_set_heap (am->vlib_main->heap_base); + rv = + vnet_l2_feature_enable_disable ("l2-output-ip4", "acl-plugin-out-ip4-l2", + sw_if_index, enable_disable, 0, 0); + if (rv) + clib_error ("Could not enable on output"); + rv = + vnet_l2_feature_enable_disable ("l2-output-ip6", "acl-plugin-out-ip6-l2", + sw_if_index, enable_disable, 0, 0); + if (rv) + clib_error ("Could not enable on output"); + if (intf_has_etype_whitelist (am, sw_if_index, 0)) + vnet_l2_feature_enable_disable ("l2-output-nonip", + "acl-plugin-out-nonip-l2", sw_if_index, + enable_disable, 0, 0); + + + clib_mem_set_heap (oldheap); am->out_acl_on_sw_if_index = clib_bitmap_set (am->out_acl_on_sw_if_index, sw_if_index, enable_disable); @@ -1241,12 +765,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) + { + /* re-applying ACLs means a new policy epoch */ + increment_policy_epoch (am, sw_if_index, is_input); + } + else { - acl_clear_sessions (am, sw_if_index); - *may_clear_sessions = 0; + /* 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,19 +791,22 @@ 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, + acl_plugin.get_lookup_context_index (am->interface_acl_user_id, sw_if_index, is_input); - ASSERT (lc_index >= 0); (*pinout_lc_index_by_sw_if_index)[sw_if_index] = lc_index; } - acl_plugin_set_acl_vec_for_context (lc_index, vec_acl_list_index); + acl_plugin.set_acl_vec_for_context (lc_index, vec_acl_list_index); } else { if (~0 != (*pinout_lc_index_by_sw_if_index)[sw_if_index]) { - acl_plugin_put_lookup_context_index ((*pinout_lc_index_by_sw_if_index)[sw_if_index]); + acl_plugin.put_lookup_context_index ((*pinout_lc_index_by_sw_if_index)[sw_if_index]); (*pinout_lc_index_by_sw_if_index)[sw_if_index] = ~0; } } @@ -1333,7 +868,7 @@ acl_interface_add_del_inout_acl (u32 sw_if_index, u8 is_add, u8 is_input, } else { - if (sw_if_index > vec_len (*pinout_acl_vec_by_sw_if_index)) + if (sw_if_index >= vec_len (*pinout_acl_vec_by_sw_if_index)) { rv = VNET_API_ERROR_NO_SUCH_ENTRY; goto done; @@ -1597,7 +1132,7 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index) */ for (tags = 2; tags >= 0; tags--) { - memset (mask, 0, sizeof (mask)); + clib_memset (mask, 0, sizeof (mask)); /* source MAC address */ memcpy (&mask[6], mt->mac_mask, 6); @@ -1605,20 +1140,20 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index) { case 0: default: - memset (&mask[12], 0xff, 2); /* ethernet protocol */ + clib_memset (&mask[12], 0xff, 2); /* ethernet protocol */ l3_offset = 14; last_tag_table = &mt->arp_table_index; break; case 1: - memset (&mask[12], 0xff, 2); /* VLAN tag1 */ - memset (&mask[16], 0xff, 2); /* ethernet protocol */ + clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */ + clib_memset (&mask[16], 0xff, 2); /* ethernet protocol */ l3_offset = 18; last_tag_table = &mt->arp_dot1q_table_index; break; case 2: - memset (&mask[12], 0xff, 2); /* VLAN tag1 */ - memset (&mask[16], 0xff, 2); /* VLAN tag2 */ - memset (&mask[20], 0xff, 2); /* ethernet protocol */ + clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */ + clib_memset (&mask[16], 0xff, 2); /* VLAN tag2 */ + clib_memset (&mask[20], 0xff, 2); /* ethernet protocol */ l3_offset = 22; last_tag_table = &mt->arp_dot1ad_table_index; break; @@ -1643,26 +1178,26 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index) if (mt->has_egress) { /* egress ARP table */ - memset (mask, 0, sizeof (mask)); + clib_memset (mask, 0, sizeof (mask)); switch (tags) { case 0: default: - memset (&mask[12], 0xff, 2); /* ethernet protocol */ + clib_memset (&mask[12], 0xff, 2); /* ethernet protocol */ l3_offset = 14; out_last_tag_table = &mt->out_arp_table_index; break; case 1: - memset (&mask[12], 0xff, 2); /* VLAN tag1 */ - memset (&mask[16], 0xff, 2); /* ethernet protocol */ + clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */ + clib_memset (&mask[16], 0xff, 2); /* ethernet protocol */ l3_offset = 18; out_last_tag_table = &mt->out_arp_dot1q_table_index; break; case 2: - memset (&mask[12], 0xff, 2); /* VLAN tag1 */ - memset (&mask[16], 0xff, 2); /* VLAN tag2 */ - memset (&mask[20], 0xff, 2); /* ethernet protocol */ + clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */ + clib_memset (&mask[16], 0xff, 2); /* VLAN tag2 */ + clib_memset (&mask[20], 0xff, 2); /* ethernet protocol */ l3_offset = 22; out_last_tag_table = &mt->out_arp_dot1ad_table_index; break; @@ -1699,25 +1234,25 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index) */ for (tags = 2; tags >= 0; tags--) { - memset (mask, 0, sizeof (mask)); + clib_memset (mask, 0, sizeof (mask)); memcpy (&mask[6], mt->mac_mask, 6); l3_src_offs = tags * 4 + get_l3_src_offset (is6); switch (tags) { case 0: default: - memset (&mask[12], 0xff, 2); /* ethernet protocol */ + clib_memset (&mask[12], 0xff, 2); /* ethernet protocol */ last_tag_table = &mt->table_index; break; case 1: - memset (&mask[12], 0xff, 2); /* VLAN tag1 */ - memset (&mask[16], 0xff, 2); /* ethernet protocol */ + clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */ + clib_memset (&mask[16], 0xff, 2); /* ethernet protocol */ last_tag_table = &mt->dot1q_table_index; break; case 2: - memset (&mask[12], 0xff, 2); /* VLAN tag1 */ - memset (&mask[16], 0xff, 2); /* VLAN tag2 */ - memset (&mask[20], 0xff, 2); /* ethernet protocol */ + clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */ + clib_memset (&mask[16], 0xff, 2); /* VLAN tag2 */ + clib_memset (&mask[20], 0xff, 2); /* ethernet protocol */ last_tag_table = &mt->dot1ad_table_index; break; } @@ -1745,7 +1280,7 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index) { for (tags = 2; tags >= 0; tags--) { - memset (mask, 0, sizeof (mask)); + clib_memset (mask, 0, sizeof (mask)); /* MAC destination */ memcpy (&mask[0], mt->mac_mask, 6); l3_dst_offs = tags * 4 + get_l3_dst_offset (is6); @@ -1753,18 +1288,18 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index) { case 0: default: - memset (&mask[12], 0xff, 2); /* ethernet protocol */ + clib_memset (&mask[12], 0xff, 2); /* ethernet protocol */ out_last_tag_table = &mt->out_table_index; break; case 1: - memset (&mask[12], 0xff, 2); /* VLAN tag1 */ - memset (&mask[16], 0xff, 2); /* ethernet protocol */ + clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */ + clib_memset (&mask[16], 0xff, 2); /* ethernet protocol */ out_last_tag_table = &mt->out_dot1q_table_index; break; case 2: - memset (&mask[12], 0xff, 2); /* VLAN tag1 */ - memset (&mask[16], 0xff, 2); /* VLAN tag2 */ - memset (&mask[20], 0xff, 2); /* ethernet protocol */ + clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */ + clib_memset (&mask[16], 0xff, 2); /* VLAN tag2 */ + clib_memset (&mask[20], 0xff, 2); /* ethernet protocol */ out_last_tag_table = &mt->out_dot1ad_table_index; break; } @@ -1819,7 +1354,7 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index) for (tags = 2; tags >= 0; tags--) { - memset (mask, 0, sizeof (mask)); + clib_memset (mask, 0, sizeof (mask)); l3_src_offs = tags * 4 + get_l3_src_offset (is6); memcpy (&mask[6], a->rules[i].src_mac, 6); switch (tags) @@ -1861,13 +1396,13 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index) vnet_classify_add_del_session (cm, tag_table, mask, a->rules[i].is_permit ? ~0 : 0, i, 0, action, metadata, 1); - memset (&mask[12], 0, sizeof (mask) - 12); + clib_memset (&mask[12], 0, sizeof (mask) - 12); } /* add ARP table entry too */ if (!is6 && (mvec[match_type_index].arp_table_index != ~0)) { - memset (mask, 0, sizeof (mask)); + clib_memset (mask, 0, sizeof (mask)); memcpy (&mask[6], a->rules[i].src_mac, 6); for (tags = 2; tags >= 0; tags--) @@ -1914,7 +1449,7 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index) /* Add the egress entry with destination set */ for (tags = 2; tags >= 0; tags--) { - memset (mask, 0, sizeof (mask)); + clib_memset (mask, 0, sizeof (mask)); l3_dst_offs = tags * 4 + get_l3_dst_offset (is6); /* src mac in the other direction becomes dst */ memcpy (&mask[0], a->rules[i].src_mac, 6); @@ -1960,7 +1495,7 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index) mask, a->rules[i].is_permit ? ~0 : 0, i, 0, action, metadata, 1); - // memset (&mask[12], 0, sizeof (mask) - 12); + // clib_memset (&mask[12], 0, sizeof (mask) - 12); } /* add ARP table entry too */ @@ -1968,7 +1503,7 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index) { for (tags = 2; tags >= 0; tags--) { - memset (mask, 0, sizeof (mask)); + clib_memset (mask, 0, sizeof (mask)); switch (tags) { case 0: @@ -2136,7 +1671,7 @@ macip_acl_add_list (u32 count, vl_api_macip_acl_rule_t rules[], { /* Get ACL index */ pool_get_aligned (am->macip_acls, a, CLIB_CACHE_LINE_BYTES); - memset (a, 0, sizeof (*a)); + clib_memset (a, 0, sizeof (*a)); /* Will return the newly allocated ACL index */ *acl_list_index = a - am->macip_acls; } @@ -2154,7 +1689,7 @@ macip_acl_add_list (u32 count, vl_api_macip_acl_rule_t rules[], a->count = count; memcpy (a->tag, tag, sizeof (a->tag)); - /* Create and populate the classifer tables */ + /* Create and populate the classifier tables */ macip_create_classify_tables (am, *acl_list_index); clib_mem_set_heap (oldheap); /* If the ACL was already applied somewhere, reapply the newly created tables */ @@ -2472,7 +2007,7 @@ send_acl_details (acl_main_t * am, vl_api_registration_t * reg, void *oldheap = acl_set_heap (am); mp = vl_msg_api_alloc (msg_size); - memset (mp, 0, msg_size); + clib_memset (mp, 0, msg_size); mp->_vl_msg_id = ntohs (VL_API_ACL_DETAILS + am->msg_id_base); /* fill in the message */ @@ -2558,7 +2093,7 @@ send_acl_interface_list_details (acl_main_t * am, msg_size += sizeof (mp->acls[0]) * count; mp = vl_msg_api_alloc (msg_size); - memset (mp, 0, msg_size); + clib_memset (mp, 0, msg_size); mp->_vl_msg_id = ntohs (VL_API_ACL_INTERFACE_LIST_DETAILS + am->msg_id_base); @@ -2710,7 +2245,7 @@ send_macip_acl_details (acl_main_t * am, vl_api_registration_t * reg, int msg_size = sizeof (*mp) + (acl ? sizeof (mp->r[0]) * acl->count : 0); mp = vl_msg_api_alloc (msg_size); - memset (mp, 0, msg_size); + clib_memset (mp, 0, msg_size); mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_DETAILS + am->msg_id_base); /* fill in the message */ @@ -2800,7 +2335,7 @@ vl_api_macip_acl_interface_get_t_handler (vl_api_macip_acl_interface_get_t * return; rmp = vl_msg_api_alloc (msg_size); - memset (rmp, 0, msg_size); + clib_memset (rmp, 0, msg_size); rmp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_INTERFACE_GET_REPLY + am->msg_id_base); rmp->context = mp->context; @@ -2824,7 +2359,7 @@ send_macip_acl_interface_list_details (acl_main_t * am, int msg_size = sizeof (*rmp) + sizeof (rmp->acls[0]); rmp = vl_msg_api_alloc (msg_size); - memset (rmp, 0, msg_size); + clib_memset (rmp, 0, msg_size); rmp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_INTERFACE_LIST_DETAILS + am->msg_id_base); @@ -2940,7 +2475,7 @@ send_acl_interface_etype_whitelist_details (acl_main_t * am, msg_size += sizeof (mp->whitelist[0]) * count; mp = vl_msg_api_alloc (msg_size); - memset (mp, 0, msg_size); + clib_memset (mp, 0, msg_size); mp->_vl_msg_id = ntohs (VL_API_ACL_INTERFACE_ETYPE_WHITELIST_DETAILS + am->msg_id_base); @@ -3029,50 +2564,6 @@ setup_message_id_table (acl_main_t * am, api_main_t * apim) #undef _ } -static void -acl_setup_fa_nodes (void) -{ - vlib_main_t *vm = vlib_get_main (); - acl_main_t *am = &acl_main; - vlib_node_t *n, *n4, *n6; - - n = vlib_get_node_by_name (vm, (u8 *) "l2-input-classify"); - n4 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-in-ip4-l2"); - n6 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-in-ip6-l2"); - - - am->l2_input_classify_next_acl_ip4 = - vlib_node_add_next_with_slot (vm, n->index, n4->index, ~0); - am->l2_input_classify_next_acl_ip6 = - vlib_node_add_next_with_slot (vm, n->index, n6->index, ~0); - - feat_bitmap_init_next_nodes (vm, n4->index, L2INPUT_N_FEAT, - l2input_get_feat_names (), - am->fa_acl_in_ip4_l2_node_feat_next_node_index); - - feat_bitmap_init_next_nodes (vm, n6->index, L2INPUT_N_FEAT, - l2input_get_feat_names (), - am->fa_acl_in_ip6_l2_node_feat_next_node_index); - - - n = vlib_get_node_by_name (vm, (u8 *) "l2-output-classify"); - n4 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-out-ip4-l2"); - n6 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-out-ip6-l2"); - - am->l2_output_classify_next_acl_ip4 = - vlib_node_add_next_with_slot (vm, n->index, n4->index, ~0); - am->l2_output_classify_next_acl_ip6 = - vlib_node_add_next_with_slot (vm, n->index, n6->index, ~0); - - feat_bitmap_init_next_nodes (vm, n4->index, L2OUTPUT_N_FEAT, - l2output_get_feat_names (), - am->fa_acl_out_ip4_l2_node_feat_next_node_index); - - feat_bitmap_init_next_nodes (vm, n6->index, L2OUTPUT_N_FEAT, - l2output_get_feat_names (), - am->fa_acl_out_ip6_l2_node_feat_next_node_index); -} - static void acl_set_timeout_sec (int timeout_type, u32 value) { @@ -3171,6 +2662,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)) @@ -3367,7 +2863,7 @@ macip_acl_print (acl_main_t * am, u32 macip_acl_index) int i; /* Don't try to print someone else's memory */ - if (macip_acl_index > vec_len (am->macip_acls)) + if (macip_acl_index >= vec_len (am->macip_acls)) return; macip_acl_list_t *a = vec_elt_at_index (am->macip_acls, macip_acl_index); @@ -3540,6 +3036,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)) { @@ -3674,13 +3179,22 @@ acl_plugin_show_sessions (acl_main_t * am, u16 wk; vnet_interface_main_t *im = &am->vnet_main->interface_main; vnet_sw_interface_t *swif; + u64 now = clib_cpu_time_now (); + u64 clocks_per_second = am->vlib_main->clib_time.clocks_per_second; { u64 n_adds = am->fa_session_total_adds; u64 n_dels = am->fa_session_total_dels; + u64 n_deact = am->fa_session_total_deactivations; vlib_cli_output (vm, "Sessions total: add %lu - del %lu = %lu", n_adds, n_dels, n_adds - n_dels); + vlib_cli_output (vm, "Sessions active: add %lu - deact %lu = %lu", n_adds, + n_deact, n_adds - n_deact); + vlib_cli_output (vm, "Sessions being purged: deact %lu - del %lu = %lu", + n_deact, n_dels, n_deact - n_dels); } + vlib_cli_output (vm, "now: %lu clocks per second: %lu", now, + clocks_per_second); vlib_cli_output (vm, "\n\nPer-thread data:"); for (wk = 0; wk < vec_len (am->per_worker_data); wk++) { @@ -3730,13 +3244,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); } )); @@ -3784,6 +3306,10 @@ acl_plugin_show_sessions (acl_main_t * am, pw->interrupt_is_unwanted); vlib_cli_output (vm, " interrupt generation: %d", pw->interrupt_generation); + vlib_cli_output (vm, " received session change requests: %d", + pw->rcvd_session_change_requests); + vlib_cli_output (vm, " sent session change requests: %d", + pw->sent_session_change_requests); } vlib_cli_output (vm, "\n\nConn cleaner thread counters:"); #define _(cnt, desc) vlib_cli_output(vm, " %20lu: %s", am->cnt, desc); @@ -3798,6 +3324,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 * @@ -3829,7 +3356,7 @@ acl_show_aclplugin_tables_fn (vlib_main_t * vm, clib_error_t *error = 0; u32 acl_index = ~0; - u32 sw_if_index = ~0; + u32 lc_index = ~0; int show_acl_hash_info = 0; int show_applied_info = 0; int show_mask_type = 0; @@ -3846,7 +3373,7 @@ acl_show_aclplugin_tables_fn (vlib_main_t * vm, else if (unformat (input, "applied")) { show_applied_info = 1; - unformat (input, "sw_if_index %u", &sw_if_index); + unformat (input, "lc_index %u", &lc_index); } else if (unformat (input, "mask")) { @@ -3873,7 +3400,7 @@ acl_show_aclplugin_tables_fn (vlib_main_t * vm, if (show_acl_hash_info) acl_plugin_show_tables_acl_hash_info (acl_index); if (show_applied_info) - acl_plugin_show_tables_applied_info (sw_if_index); + acl_plugin_show_tables_applied_info (lc_index); if (show_bihash) acl_plugin_show_tables_bihash (show_bihash_verbose); @@ -3942,7 +3469,7 @@ VLIB_CLI_COMMAND (aclplugin_show_sessions_command, static) = { 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] ]", + .short_help = "show acl-plugin tables [ acl [index N] | applied [ lc_index N ] | mask | hash [verbose N] ]", .function = acl_show_aclplugin_tables_fn, }; @@ -3970,34 +3497,59 @@ 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; + uword 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; + uword hash_lookup_hash_memory; + u32 reclassify_sessions; + u32 use_tuple_merge; + u32 tuple_merge_split_threshold; 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)) + else + if (unformat + (input, "connection hash memory %U", unformat_memory_size, + &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)) + 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)) am->hash_lookup_hash_buckets = hash_lookup_hash_buckets; - else if (unformat (input, "hash lookup hash memory %d", - &hash_lookup_hash_memory)) + else + if (unformat + (input, "hash lookup hash memory %U", unformat_memory_size, + &hash_lookup_hash_memory)) am->hash_lookup_hash_memory = hash_lookup_hash_memory; + else if (unformat (input, "use tuple merge %d", &use_tuple_merge)) + am->use_tuple_merge = use_tuple_merge; + else + if (unformat + (input, "tuple merge split threshold %d", + &tuple_merge_split_threshold)) + am->tuple_merge_split_threshold = tuple_merge_split_threshold; + + 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); @@ -4012,9 +3564,10 @@ acl_init (vlib_main_t * vm) { acl_main_t *am = &acl_main; clib_error_t *error = 0; - memset (am, 0, sizeof (*am)); + clib_memset (am, 0, sizeof (*am)); am->vlib_main = vm; am->vnet_main = vnet_get_main (); + am->log_default = vlib_log_register_class ("acl_plugin", 0); u8 *name = format (0, "acl_%08x%c", api_version, 0); @@ -4029,9 +3582,15 @@ acl_init (vlib_main_t * vm) vec_free (name); - acl_setup_fa_nodes (); + if (error) + return error; + + error = acl_plugin_exports_init (&acl_plugin); + + if (error) + return error; - 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,31 +3608,39 @@ 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 (); + + am->fa_min_deleted_sessions_per_interval = + ACL_FA_DEFAULT_MIN_DELETED_SESSIONS_PER_INTERVAL; + am->fa_max_deleted_sessions_per_interval = + ACL_FA_DEFAULT_MAX_DELETED_SESSIONS_PER_INTERVAL; + am->fa_cleaner_wait_time_increment = + ACL_FA_DEFAULT_CLEANER_WAIT_TIME_INCREMENT; + vec_validate (am->per_worker_data, tm->n_vlib_mains - 1); { u16 wk; - u8 tt; for (wk = 0; wk < vec_len (am->per_worker_data); wk++) { acl_fa_per_worker_data_t *pw = &am->per_worker_data[wk]; - vec_validate (pw->fa_conn_list_head, ACL_N_TIMEOUTS - 1); - vec_validate (pw->fa_conn_list_tail, ACL_N_TIMEOUTS - 1); - for (tt = 0; tt < ACL_N_TIMEOUTS; tt++) + if (tm->n_vlib_mains > 1) { - pw->fa_conn_list_head[tt] = ~0; - pw->fa_conn_list_tail[tt] = ~0; + clib_spinlock_init (&pw->pending_session_change_request_lock); } + vec_validate (pw->expired, + ACL_N_TIMEOUTS * + am->fa_max_deleted_sessions_per_interval); + _vec_len (pw->expired) = 0; + vec_validate_init_empty (pw->fa_conn_list_head, ACL_N_TIMEOUTS - 1, + FA_SESSION_BOGUS_INDEX); + vec_validate_init_empty (pw->fa_conn_list_tail, ACL_N_TIMEOUTS - 1, + FA_SESSION_BOGUS_INDEX); + vec_validate_init_empty (pw->fa_conn_list_head_expiry_time, + ACL_N_TIMEOUTS - 1, ~0ULL); } } - am->fa_min_deleted_sessions_per_interval = - ACL_FA_DEFAULT_MIN_DELETED_SESSIONS_PER_INTERVAL; - am->fa_max_deleted_sessions_per_interval = - ACL_FA_DEFAULT_MAX_DELETED_SESSIONS_PER_INTERVAL; - am->fa_cleaner_wait_time_increment = - ACL_FA_DEFAULT_CLEANER_WAIT_TIME_INCREMENT; - am->fa_cleaner_cnt_delete_by_sw_index = 0; am->fa_cleaner_cnt_delete_by_sw_index_ok = 0; am->fa_cleaner_cnt_unknown_event = 0; @@ -4088,10 +3655,12 @@ acl_init (vlib_main_t * vm) /* use the new fancy hash-based matching */ am->use_hash_acl_matching = 1; + /* use tuplemerge by default */ + am->use_tuple_merge = 1; + /* Set the default threshold */ + am->tuple_merge_split_threshold = TM_SPLIT_THRESHOLD; - 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; }