X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fadj%2Fadj.c;h=8808294f7a67ea449aa6f070b604c4aeae805e8f;hb=8f5fef2c7;hp=90182006f60be75c048a6aae3b657c89d6fb01ca;hpb=88fc83eb716bf07f4634de6de5b569f795a56418;p=vpp.git diff --git a/src/vnet/adj/adj.c b/src/vnet/adj/adj.c index 90182006f60..8808294f7a6 100644 --- a/src/vnet/adj/adj.c +++ b/src/vnet/adj/adj.c @@ -20,9 +20,13 @@ #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 @@ -35,12 +39,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,27 +64,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; - ip4_main.lookup_main.adjacency_heap = adj_pool; - ip6_main.lookup_main.adjacency_heap = adj_pool; + /* lest it become a midchain in the future */ + 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); } @@ -82,6 +125,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 @@ -99,11 +164,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: @@ -118,32 +188,72 @@ format_ip_adjacency (u8 * s, va_list * args) case IP_LOOKUP_NEXT_MCAST: s = format (s, "%U", format_adj_mcast, adj_index, 0); break; - default: + case IP_LOOKUP_NEXT_MCAST_MIDCHAIN: + s = format (s, "%U", format_adj_mcast_midchain, adj_index, 0); 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 * @@ -157,15 +267,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 */ @@ -176,9 +289,11 @@ 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_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); @@ -202,6 +317,26 @@ 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); +} + +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) { @@ -270,7 +405,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_ { @@ -298,18 +433,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 @@ -322,6 +466,43 @@ 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); + 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 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 */ @@ -338,6 +519,7 @@ adj_walk (u32 sw_if_index, FOR_EACH_FIB_IP_PROTOCOL(proto) { adj_nbr_walk(sw_if_index, proto, cb, ctx); + adj_mcast_walk(sw_if_index, proto, cb, ctx); } } @@ -351,7 +533,7 @@ adj_get_link_type (adj_index_t ai) adj = adj_get(ai); - return (adj->ia_link); + return (adj->ia_link); } /** @@ -374,24 +556,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)); } /** @@ -434,10 +599,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); } @@ -461,6 +648,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); } @@ -479,9 +668,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(), @@ -493,7 +680,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": @@ -517,8 +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)) { @@ -530,7 +717,7 @@ adj_show (vlib_main_t * vm, format_ip_adjacency, ai, FORMAT_IP_ADJACENCY_NONE); } - })); + } /* *INDENT-ON* */ } } @@ -544,9 +731,9 @@ adj_show (vlib_main_t * vm, * [@0] * [@1] glean: loop0 * [@2] ipv4 via 1.0.0.2 loop0: IP4: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc - * [@3] mpls via 1.0.0.2 loop0: MPLS_UNICAST: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc + * [@3] mpls via 1.0.0.2 loop0: MPLS: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc * [@4] ipv4 via 1.0.0.3 loop0: IP4: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc - * [@5] mpls via 1.0.0.3 loop0: MPLS_UNICAST: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc + * [@5] mpls via 1.0.0.3 loop0: MPLS: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc * @cliexend ?*/ VLIB_CLI_COMMAND (adj_show_command, static) = { @@ -590,8 +777,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",