X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fadj%2Fadj.c;h=5c6ea9b71af6ac2d93322a4b4f90bc31eb0f95ae;hb=e2fe09742;hp=36dfe500eb396cdea591803086f32be38a6e5f15;hpb=0f26c5a0138ac86d7ebd197c31a09d8d624c35fe;p=vpp.git diff --git a/src/vnet/adj/adj.c b/src/vnet/adj/adj.c index 36dfe500eb3..5c6ea9b71af 100644 --- a/src/vnet/adj/adj.c +++ b/src/vnet/adj/adj.c @@ -22,7 +22,10 @@ #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 @@ -35,12 +38,24 @@ ip_adjacency_t *adj_pool; */ 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,31 +63,54 @@ ip_adjacency_t * adj_alloc (fib_protocol_t proto) { ip_adjacency_t *adj; + u8 need_barrier_sync = 0; + vlib_main_t *vm; + vm = vlib_get_main(); + + ASSERT (vm->thread_index == 0); + + pool_get_aligned_will_expand (adj_pool, need_barrier_sync, + CLIB_CACHE_LINE_BYTES); + /* 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)); - ip4_main.lookup_main.adjacency_heap = adj_pool; - ip6_main.lookup_main.adjacency_heap = adj_pool; + if (need_barrier_sync) + vlib_worker_thread_barrier_release (vm); return (adj); } @@ -86,6 +124,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 @@ -103,11 +163,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: @@ -125,32 +190,69 @@ 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) { - adj_delegate_type_t adt; - adj_delegate_t *aed; vlib_counter_t counts; vlib_get_combined_counter(&adjacency_counters, adj_index, &counts); - 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 "); - FOR_EACH_ADJ_DELEGATE(adj, adt, aed, + 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:"); + s = adj_delegate_format(s, adj); + + s = format(s, "\n children:"); + if (fib_node_list_get_size(adj->ia_node.fn_children)) { - s = format(s, " %U\n", format_adj_deletegate, aed); - }); - - s = format(s, "\n children:\n "); - s = fib_node_children_format(adj->ia_node.fn_children, s); + s = format(s, "\n "); + s = fib_node_children_format(adj->ia_node.fn_children, s); + } } 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 * @@ -164,15 +266,18 @@ adj_last_lock_gone (ip_adjacency_t *adj) ASSERT(0 == fib_node_list_get_size(adj->ia_node.fn_children)); ADJ_DBG(adj, "last-lock-gone"); + adj_delegate_adj_deleted(adj); + vlib_worker_thread_barrier_sync (vm); 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 */ @@ -183,11 +288,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; @@ -210,6 +316,16 @@ adj_last_lock_gone (ip_adjacency_t *adj) pool_put(adj_pool, adj); } +u32 +adj_dpo_get_urpf (const dpo_id_t *dpo) +{ + ip_adjacency_t *adj; + + adj = adj_get(dpo->dpoi_index); + + return (adj->rewrite_header.sw_if_index); +} + void adj_lock (adj_index_t adj_index) { @@ -278,7 +394,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_ { @@ -306,18 +422,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 @@ -330,6 +455,30 @@ adj_feature_update (u32 sw_if_index, adj_walk (sw_if_index, adj_feature_update_walk_cb, &ctx); } +static adj_walk_rc_t +adj_mtu_update_walk_cb (adj_index_t ai, + void *arg) +{ + ip_adjacency_t *adj; + + adj = adj_get(ai); + + vnet_rewrite_update_mtu (vnet_get_main(), adj->ia_link, + &adj->rewrite_header); + + return (ADJ_WALK_RC_CONTINUE); +} + +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); + /** * @brief Walk the Adjacencies on a given interface */ @@ -360,7 +509,7 @@ adj_get_link_type (adj_index_t ai) adj = adj_get(ai); - return (adj->ia_link); + return (adj->ia_link); } /** @@ -383,24 +532,7 @@ adj_get_sw_if_index (adj_index_t ai) int adj_is_up (adj_index_t ai) { - const adj_delegate_t *aed; - - aed = adj_delegate_get(adj_get(ai), ADJ_DELEGATE_BFD); - - if (NULL == aed) - { - /* - * no BFD tracking - resolved - */ - return (!0); - } - else - { - /* - * defer to the state of the BFD tracking - */ - return (ADJ_BFD_STATE_UP == aed->ad_bfd_state); - } + return (adj_bfd_is_up(ai)); } /** @@ -443,10 +575,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); } @@ -470,6 +624,8 @@ adj_module_init (vlib_main_t * vm) adj_midchain_module_init(); adj_mcast_module_init(); + vnet_feature_register(adj_feature_update, NULL); + return (NULL); } @@ -488,9 +644,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(), @@ -502,7 +656,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": @@ -599,8 +753,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",