X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fadj%2Fadj.c;h=201561fe485eb9335f9f75ab71a3545023a2b7ec;hb=2f4586d9b3507243918c11ce99b9d151d5bde7a0;hp=0de3fc8b7751872ef4e72ba359dbce6562933fe4;hpb=d723161e038d00e59766aa67a6a0dcc350227e4b;p=vpp.git diff --git a/src/vnet/adj/adj.c b/src/vnet/adj/adj.c index 0de3fc8b775..201561fe485 100644 --- a/src/vnet/adj/adj.c +++ b/src/vnet/adj/adj.c @@ -20,27 +20,48 @@ #include #include #include +#include /* Adjacency packet/byte counters indexed by adjacency index. */ -vlib_combined_counter_main_t adjacency_counters; +vlib_combined_counter_main_t adjacency_counters = { + .name = "adjacency", + .stat_segment_name = "/net/adjacency", +}; /* * the single adj pool */ ip_adjacency_t *adj_pool; +/** + * The adjacency logger + */ +vlib_log_class_t adj_logger; + /** * @brief Global Config for enabling per-adjacency counters. * By default these are disabled. */ int adj_per_adj_counters; +const ip46_address_t ADJ_BCAST_ADDR = { + .ip6 = { + .as_u64[0] = 0xffffffffffffffff, + .as_u64[1] = 0xffffffffffffffff, + }, +}; + +/** + * Adj flag names + */ +static const char *adj_attr_names[] = ADJ_ATTR_NAMES; + always_inline void adj_poison (ip_adjacency_t * adj) { if (CLIB_DEBUG > 0) { - memset (adj, 0xfe, sizeof (adj[0])); + clib_memset (adj, 0xfe, sizeof (adj[0])); } } @@ -48,30 +69,53 @@ ip_adjacency_t * adj_alloc (fib_protocol_t proto) { ip_adjacency_t *adj; + u8 need_barrier_sync = pool_get_will_expand (adj_pool); + vlib_main_t *vm; + vm = vlib_get_main(); + + ASSERT (vm->thread_index == 0); + + /* If the adj_pool will expand, stop the parade. */ + if (need_barrier_sync) + vlib_worker_thread_barrier_sync (vm); pool_get_aligned(adj_pool, adj, CLIB_CACHE_LINE_BYTES); adj_poison(adj); - /* Make sure certain fields are always initialized. */ /* Validate adjacency counters. */ + if (need_barrier_sync == 0) + { + /* If the adj counter pool will expand, stop the parade */ + need_barrier_sync = vlib_validate_combined_counter_will_expand + (&adjacency_counters, adj_get_index (adj)); + if (need_barrier_sync) + vlib_worker_thread_barrier_sync (vm); + } vlib_validate_combined_counter(&adjacency_counters, adj_get_index(adj)); + /* Make sure certain fields are always initialized. */ + vlib_zero_combined_counter(&adjacency_counters, + adj_get_index(adj)); fib_node_init(&adj->ia_node, FIB_NODE_TYPE_ADJ); adj->ia_nh_proto = proto; adj->ia_flags = 0; + adj->ia_cfg_index = 0; adj->rewrite_header.sw_if_index = ~0; adj->rewrite_header.flags = 0; adj->lookup_next_index = 0; adj->ia_delegates = NULL; /* lest it become a midchain in the future */ - memset(&adj->sub_type.midchain.next_dpo, 0, + clib_memset(&adj->sub_type.midchain.next_dpo, 0, sizeof(adj->sub_type.midchain.next_dpo)); + if (need_barrier_sync) + vlib_worker_thread_barrier_release (vm); + return (adj); } @@ -84,6 +128,28 @@ adj_index_is_special (adj_index_t adj_index) return (0); } +u8* +format_adj_flags (u8 * s, va_list * args) +{ + adj_flags_t af; + adj_attr_t at; + + af = va_arg (*args, int); + + if (ADJ_FLAG_NONE == af) + { + return (format(s, "None")); + } + FOR_EACH_ADJ_ATTR(at) + { + if (af & (1 << at)) + { + s = format(s, "%s ", adj_attr_names[at]); + } + } + return (s); +} + /** * @brief Pretty print helper function for formatting specific adjacencies. * @param s - input string to format @@ -101,11 +167,16 @@ format_ip_adjacency (u8 * s, va_list * args) adj_index = va_arg (*args, u32); fiaf = va_arg (*args, format_ip_adjacency_flags_t); + + if (!adj_is_valid(adj_index)) + return format(s, ""); + adj = adj_get(adj_index); - + switch (adj->lookup_next_index) { case IP_LOOKUP_NEXT_REWRITE: + case IP_LOOKUP_NEXT_BCAST: s = format (s, "%U", format_adj_nbr, adj_index, 0); break; case IP_LOOKUP_NEXT_ARP: @@ -123,8 +194,12 @@ format_ip_adjacency (u8 * s, va_list * args) case IP_LOOKUP_NEXT_MCAST_MIDCHAIN: s = format (s, "%U", format_adj_mcast_midchain, adj_index, 0); break; - default: - break; + case IP_LOOKUP_NEXT_DROP: + case IP_LOOKUP_NEXT_PUNT: + case IP_LOOKUP_NEXT_LOCAL: + case IP_LOOKUP_NEXT_ICMP_ERROR: + case IP_LOOKUP_N_NEXT: + break; } if (fiaf & FORMAT_IP_ADJACENCY_DETAIL) @@ -132,10 +207,11 @@ format_ip_adjacency (u8 * s, va_list * args) vlib_counter_t counts; vlib_get_combined_counter(&adjacency_counters, adj_index, &counts); + s = format (s, "\n flags:%U", format_adj_flags, adj->ia_flags); s = format (s, "\n counts:[%Ld:%Ld]", counts.packets, counts.bytes); s = format (s, "\n locks:%d", adj->ia_node.fn_locks); - s = format(s, "\n delegates:\n "); - adj_delegate_format(s, adj); + s = format(s, "\n delegates:"); + s = adj_delegate_format(s, adj); s = format(s, "\n children:"); if (fib_node_list_get_size(adj->ia_node.fn_children)) @@ -148,6 +224,39 @@ format_ip_adjacency (u8 * s, va_list * args) return s; } +int +adj_recursive_loop_detect (adj_index_t ai, + fib_node_index_t **entry_indicies) +{ + ip_adjacency_t * adj; + + adj = adj_get(ai); + + switch (adj->lookup_next_index) + { + case IP_LOOKUP_NEXT_REWRITE: + case IP_LOOKUP_NEXT_ARP: + case IP_LOOKUP_NEXT_GLEAN: + case IP_LOOKUP_NEXT_MCAST: + case IP_LOOKUP_NEXT_BCAST: + case IP_LOOKUP_NEXT_DROP: + case IP_LOOKUP_NEXT_PUNT: + case IP_LOOKUP_NEXT_LOCAL: + case IP_LOOKUP_NEXT_ICMP_ERROR: + case IP_LOOKUP_N_NEXT: + /* + * these adjacency types are terminal graph nodes, so there's no + * possibility of a loop down here. + */ + break; + case IP_LOOKUP_NEXT_MIDCHAIN: + case IP_LOOKUP_NEXT_MCAST_MIDCHAIN: + return (adj_ndr_midchain_recursive_loop_detect(ai, entry_indicies)); + } + + return (0); +} + /* * adj_last_lock_gone * @@ -168,10 +277,11 @@ adj_last_lock_gone (ip_adjacency_t *adj) switch (adj->lookup_next_index) { case IP_LOOKUP_NEXT_MIDCHAIN: - dpo_reset(&adj->sub_type.midchain.next_dpo); + adj_midchain_teardown(adj); /* FALL THROUGH */ case IP_LOOKUP_NEXT_ARP: case IP_LOOKUP_NEXT_REWRITE: + case IP_LOOKUP_NEXT_BCAST: /* * complete and incomplete nbr adjs */ @@ -182,11 +292,12 @@ adj_last_lock_gone (ip_adjacency_t *adj) adj->rewrite_header.sw_if_index); break; case IP_LOOKUP_NEXT_GLEAN: - adj_glean_remove(adj->ia_nh_proto, - adj->rewrite_header.sw_if_index); + adj_glean_remove(adj); break; - case IP_LOOKUP_NEXT_MCAST: case IP_LOOKUP_NEXT_MCAST_MIDCHAIN: + adj_midchain_teardown(adj); + /* FALL THROUGH */ + case IP_LOOKUP_NEXT_MCAST: adj_mcast_remove(adj->ia_nh_proto, adj->rewrite_header.sw_if_index); break; @@ -201,12 +312,12 @@ adj_last_lock_gone (ip_adjacency_t *adj) break; } - vlib_worker_thread_barrier_release(vm); fib_node_deinit(&adj->ia_node); ASSERT(0 == vec_len(adj->ia_delegates)); vec_free(adj->ia_delegates); pool_put(adj_pool, adj); + vlib_worker_thread_barrier_release(vm); } u32 @@ -219,6 +330,16 @@ adj_dpo_get_urpf (const dpo_id_t *dpo) return (adj->rewrite_header.sw_if_index); } +u16 +adj_dpo_get_mtu (const dpo_id_t *dpo) +{ + ip_adjacency_t *adj; + + adj = adj_get(dpo->dpoi_index); + + return (adj->rewrite_header.max_l3_packet_bytes); +} + void adj_lock (adj_index_t adj_index) { @@ -232,7 +353,6 @@ adj_lock (adj_index_t adj_index) adj = adj_get(adj_index); ASSERT(adj); - ADJ_DBG(adj, "lock"); fib_node_lock(&adj->ia_node); } @@ -249,9 +369,6 @@ adj_unlock (adj_index_t adj_index) adj = adj_get(adj_index); ASSERT(adj); - ADJ_DBG(adj, "unlock"); - ASSERT(adj); - fib_node_unlock(&adj->ia_node); } @@ -287,7 +404,7 @@ adj_child_remove (adj_index_t adj_index, } /* - * Context for the walk to update the cached feture flags. + * Context for the walk to update the cached feature flags. */ typedef struct adj_feature_update_t_ { @@ -315,18 +432,27 @@ adj_feature_update_walk_cb (adj_index_t ai, ((ctx->arc == mpls_main.output_feature_arc_index) && (VNET_LINK_MPLS == adj->ia_link))) { + vnet_feature_main_t *fm = &feature_main; + vnet_feature_config_main_t *cm; + + cm = &fm->feature_config_mains[ctx->arc]; + if (ctx->enable) adj->rewrite_header.flags |= VNET_REWRITE_HAS_FEATURES; else adj->rewrite_header.flags &= ~VNET_REWRITE_HAS_FEATURES; + + adj->ia_cfg_index = vec_elt (cm->config_index_by_sw_if_index, + adj->rewrite_header.sw_if_index); } return (ADJ_WALK_RC_CONTINUE); } -void +static void adj_feature_update (u32 sw_if_index, u8 arc_index, - u8 is_enable) + u8 is_enable, + void *data) { /* * Walk all the adjacencies on the interface to update the cached @@ -349,14 +475,29 @@ adj_mtu_update_walk_cb (adj_index_t ai, vnet_rewrite_update_mtu (vnet_get_main(), adj->ia_link, &adj->rewrite_header); + adj_delegate_adj_modified(adj); + + /** + * Backwalk to all Path MTU trackers, casual like .. + */ + { + fib_node_back_walk_ctx_t bw_ctx = { + .fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_MTU, + }; + + fib_walk_async(FIB_NODE_TYPE_ADJ, ai, + FIB_WALK_PRIORITY_LOW, &bw_ctx); + } return (ADJ_WALK_RC_CONTINUE); } -static void +static clib_error_t * adj_mtu_update (vnet_main_t * vnm, u32 sw_if_index, u32 flags) { adj_walk (sw_if_index, adj_mtu_update_walk_cb, NULL); + + return (NULL); } VNET_SW_INTERFACE_MTU_CHANGE_FUNCTION(adj_mtu_update); @@ -391,7 +532,7 @@ adj_get_link_type (adj_index_t ai) adj = adj_get(ai); - return (adj->ia_link); + return (adj->ia_link); } /** @@ -457,10 +598,32 @@ static fib_node_back_walk_rc_t adj_back_walk_notify (fib_node_t *node, fib_node_back_walk_ctx_t *ctx) { - /* - * Que pasa. yo soj en el final! - */ - ASSERT(0); + ip_adjacency_t *adj; + + adj = ADJ_FROM_NODE(node); + + switch (adj->lookup_next_index) + { + case IP_LOOKUP_NEXT_MIDCHAIN: + adj_midchain_delegate_restack(adj_get_index(adj)); + break; + case IP_LOOKUP_NEXT_ARP: + case IP_LOOKUP_NEXT_REWRITE: + case IP_LOOKUP_NEXT_BCAST: + case IP_LOOKUP_NEXT_GLEAN: + case IP_LOOKUP_NEXT_MCAST: + case IP_LOOKUP_NEXT_MCAST_MIDCHAIN: + case IP_LOOKUP_NEXT_DROP: + case IP_LOOKUP_NEXT_PUNT: + case IP_LOOKUP_NEXT_LOCAL: + case IP_LOOKUP_NEXT_ICMP_ERROR: + case IP_LOOKUP_N_NEXT: + /* + * Que pasa. yo soj en el final! + */ + ASSERT(0); + break; + } return (FIB_NODE_BACK_WALK_CONTINUE); } @@ -484,6 +647,10 @@ adj_module_init (vlib_main_t * vm) adj_midchain_module_init(); adj_mcast_module_init(); + vnet_feature_register(adj_feature_update, NULL); + + adj_logger = vlib_log_register_class("adj", "adj"); + return (NULL); } @@ -502,9 +669,7 @@ adj_show (vlib_main_t * vm, { if (unformat (input, "%d", &ai)) ; - else if (unformat (input, "sum")) - summary = 1; - else if (unformat (input, "summary")) + else if (unformat (input, "summary") || unformat (input, "sum")) summary = 1; else if (unformat (input, "%U", unformat_vnet_sw_interface, vnet_get_main(), @@ -516,7 +681,7 @@ adj_show (vlib_main_t * vm, if (summary) { - vlib_cli_output (vm, "Number of adjacenies: %d", pool_elts(adj_pool)); + vlib_cli_output (vm, "Number of adjacencies: %d", pool_elts(adj_pool)); vlib_cli_output (vm, "Per-adjacency counters: %s", (adj_are_counters_enabled() ? "enabled": @@ -539,9 +704,8 @@ adj_show (vlib_main_t * vm, } else { - /* *INDENT-OFF* */ - pool_foreach_index(ai, adj_pool, - ({ + pool_foreach_index (ai, adj_pool) + { if (~0 != sw_if_index && sw_if_index != adj_get_sw_if_index(ai)) { @@ -553,8 +717,7 @@ adj_show (vlib_main_t * vm, format_ip_adjacency, ai, FORMAT_IP_ADJACENCY_NONE); } - })); - /* *INDENT-ON* */ + } } } return 0; @@ -613,8 +776,8 @@ adj_cli_counters_set (vlib_main_t * vm, } /*? - * Enabe/disble per-adjacency counters. This is optional because it comes with - * a non-negligible performance cost. + * Enable/disable per-adjacency counters. This is optional because it comes + * with a non-negligible performance cost. ?*/ VLIB_CLI_COMMAND (adj_cli_counters_set_command, static) = { .path = "adjacency counters",