From 0bfe5d8c792abcdbcf27bfcc7b7b353fba04aee2 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Thu, 25 Aug 2016 15:29:12 +0100 Subject: A Protocol Independent Hierarchical FIB (VPP-352) Main Enhancements: - Protocol Independent FIB API - Hierarchical FIB entries. Dynamic recursive route resolution. - Extranet Support. - Integration of IP and MPLS forwarding. - Separation of FIB and Adjacency databases. - Data-Plane Object forwarding model. Change-Id: I52dc815c0d0aa8b493e3cf6b978568f3cc82296c Signed-off-by: Neale Ranns --- vpp/app/vpe_cli.c | 66 ++-- vpp/stats/stats.c | 362 +++++++----------- vpp/vpp-api/api.c | 847 +++++++++++++----------------------------- vpp/vpp-api/custom_dump.c | 5 +- vpp/vpp-api/vpe.api | 28 +- vpp/vpp-api/vpp_get_metrics.c | 8 + 6 files changed, 483 insertions(+), 833 deletions(-) (limited to 'vpp') diff --git a/vpp/app/vpe_cli.c b/vpp/app/vpe_cli.c index b9f796881be..3b24c26f3e6 100644 --- a/vpp/app/vpe_cli.c +++ b/vpp/app/vpe_cli.c @@ -14,6 +14,8 @@ */ #include #include +#include +#include typedef struct { @@ -27,20 +29,25 @@ virtual_ip_cmd_fn_command_fn (vlib_main_t * vm, { unformat_input_t _line_input, *line_input = &_line_input; vnet_main_t *vnm = vnet_get_main (); - ip4_main_t *im = &ip4_main; - ip_lookup_main_t *lm = &im->lookup_main; - ip4_address_t ip_addr, next_hop; + ip46_address_t next_hop, *next_hops; + fib_route_path_t *rpaths; + fib_prefix_t prefix; u8 mac_addr[6]; mac_addr_t *mac_addrs = 0; u32 sw_if_index; - u32 i, f; + u32 i; + + next_hops = NULL; + rpaths = NULL; + prefix.fp_len = 32; + prefix.fp_proto = FIB_PROTOCOL_IP4; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) return 0; if (!unformat (line_input, "%U %U", - unformat_ip4_address, &ip_addr, + unformat_ip4_address, &prefix.fp_addr.ip4, unformat_vnet_sw_interface, vnm, &sw_if_index)) goto barf; @@ -53,6 +60,11 @@ virtual_ip_cmd_fn_command_fn (vlib_main_t * vm, vec_add2 (mac_addrs, ma, 1); clib_memcpy (ma, mac_addr, sizeof (mac_addr)); } + else if (unformat (line_input, "next-hop %U", + unformat_ip4_address, &next_hop.ip4)) + { + vec_add1 (next_hops, next_hop); + } else { barf: @@ -60,37 +72,37 @@ virtual_ip_cmd_fn_command_fn (vlib_main_t * vm, format_unformat_error, input); } } - if (vec_len (mac_addrs) == 0) + if (vec_len (mac_addrs) == 0 || + vec_len (next_hops) == 0 || vec_len (mac_addrs) != vec_len (next_hops)) goto barf; /* Create / delete special interface route /32's */ - next_hop.as_u32 = 0; for (i = 0; i < vec_len (mac_addrs); i++) { - ip_adjacency_t adj; - u32 adj_index; - - memset (&adj, 0, sizeof (adj)); - adj.lookup_next_index = IP_LOOKUP_NEXT_REWRITE; - - vnet_rewrite_for_sw_interface (vnm, VNET_L3_PACKET_TYPE_IP4, sw_if_index, ip4_rewrite_node.index, &mac_addrs[i], /* destination address */ - &adj.rewrite_header, - sizeof (adj.rewrite_data)); - - ip_add_adjacency (lm, &adj, 1 /* one adj */ , - &adj_index); - - f = - (i + 1 < vec_len (mac_addrs)) ? IP4_ROUTE_FLAG_NOT_LAST_IN_GROUP : 0; - ip4_add_del_route_next_hop (im, IP4_ROUTE_FLAG_ADD | f, &ip_addr, - 32 /* insert /32's */ , - &next_hop, sw_if_index, 1 /* weight */ , - adj_index, - (u32) ~ 0 /* explicit fib index */ ); + fib_route_path_t *rpath; + + adj_nbr_add_or_lock_w_rewrite (FIB_PROTOCOL_IP4, + FIB_LINK_IP4, + &next_hops[i], + sw_if_index, mac_addrs[i].mac_addr); + + vec_add2 (rpaths, rpath, 1); + + rpath->frp_proto = FIB_PROTOCOL_IP4; + rpath->frp_addr = next_hops[i]; + rpath->frp_sw_if_index = sw_if_index; + rpath->frp_fib_index = ~0; + rpath->frp_weight = 1; + rpath->frp_label = MPLS_LABEL_INVALID; } + fib_table_entry_path_add2 (0, // default FIB table + &prefix, + FIB_SOURCE_CLI, FIB_ENTRY_FLAG_NONE, rpaths); + vec_free (mac_addrs); + vec_free (next_hops); return 0; } diff --git a/vpp/stats/stats.c b/vpp/stats/stats.c index 823e0641c39..ee9a6a6d919 100644 --- a/vpp/stats/stats.c +++ b/vpp/stats/stats.c @@ -15,6 +15,9 @@ #include #include #include +#include +#include +#include #define STATS_DEBUG 0 @@ -250,7 +253,7 @@ do_ip4_fibs (stats_main_t * sm) unix_shared_memory_queue_t *q = shmem_hdr->vl_input_queue; static ip4_route_t *routes; ip4_route_t *r; - ip4_fib_t *fib; + fib_table_t *fib; ip_lookup_main_t *lm = &im4->lookup_main; static uword *results; vl_api_vnet_ip4_fib_counters_t *mp = 0; @@ -260,8 +263,9 @@ do_ip4_fibs (stats_main_t * sm) int i; again: - vec_foreach (fib, im4->fibs) - { + /* *INDENT-OFF* */ + pool_foreach (fib, im4->fibs, + ({ /* We may have bailed out due to control-plane activity */ while ((fib - im4->fibs) < start_at_fib_index) continue; @@ -274,14 +278,14 @@ again: items_this_message * sizeof (vl_api_ip4_fib_counter_t)); mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS); mp->count = 0; - mp->vrf_id = ntohl (fib->table_id); + mp->vrf_id = ntohl (fib->ft_table_id); ctrp = (vl_api_ip4_fib_counter_t *) mp->c; } else { /* happens if the last FIB was empty... */ ASSERT (mp->count == 0); - mp->vrf_id = ntohl (fib->table_id); + mp->vrf_id = ntohl (fib->ft_table_id); } dslock (sm, 0 /* release hint */ , 1 /* tag */ ); @@ -289,15 +293,14 @@ again: vec_reset_length (routes); vec_reset_length (results); - for (i = 0; i < ARRAY_LEN (fib->adj_index_by_dst_address); i++) + for (i = 0; i < ARRAY_LEN (fib->v4.fib_entry_by_dst_address); i++) { - uword *hash = fib->adj_index_by_dst_address[i]; + uword *hash = fib->v4.fib_entry_by_dst_address[i]; hash_pair_t *p; ip4_route_t x; x.address_length = i; - /* *INDENT-OFF* */ hash_foreach_pair (p, hash, ({ x.address.data_u32 = p->key; @@ -321,114 +324,71 @@ again: goto again; } })); - /* *INDENT-ON* */ } vec_foreach (r, routes) - { - vlib_counter_t c, sum; - uword i, j, n_left, n_nhs, adj_index, *result = 0; - ip_adjacency_t *adj; - ip_multipath_next_hop_t *nhs, tmp_nhs[1]; - - adj_index = r->index; - if (lm->fib_result_n_words > 1) - { - result = vec_elt_at_index (results, adj_index); - adj_index = result[0]; - } - - adj = ip_get_adjacency (lm, adj_index); - if (adj->n_adj == 1) - { - nhs = &tmp_nhs[0]; - nhs[0].next_hop_adj_index = ~0; /* not used */ - nhs[0].weight = 1; - n_nhs = 1; - } - else - { - ip_multipath_adjacency_t *madj; - madj = vec_elt_at_index (lm->multipath_adjacencies, - adj->heap_handle); - nhs = heap_elt_at_index - (lm->next_hop_heap, madj->normalized_next_hops.heap_offset); - n_nhs = madj->normalized_next_hops.count; - } + { + vlib_counter_t c; + + vlib_get_combined_counter (&load_balance_main.lbm_to_counters, + r->index, &c); + /* + * If it has actually + * seen at least one packet, send it. + */ + if (c.packets > 0) + { - n_left = nhs[0].weight; - vlib_counter_zero (&sum); - for (i = j = 0; i < adj->n_adj; i++) - { - n_left -= 1; - vlib_get_combined_counter (&lm->adjacency_counters, - adj_index + i, &c); - vlib_counter_add (&sum, &c); - /* - * If we're done with this adj and it has actually - * seen at least one packet, send it. - */ - if (n_left == 0 && sum.packets > 0) - { - - /* already in net byte order */ - ctrp->address = r->address.as_u32; - ctrp->address_length = r->address_length; - ctrp->packets = clib_host_to_net_u64 (sum.packets); - ctrp->bytes = clib_host_to_net_u64 (sum.bytes); - mp->count++; - ctrp++; - - if (mp->count == items_this_message) - { - mp->count = htonl (items_this_message); - /* - * If the main thread's input queue is stuffed, - * drop the data structure lock (which the main thread - * may want), and take a pause. - */ - unix_shared_memory_queue_lock (q); - if (unix_shared_memory_queue_is_full (q)) - { - dsunlock (sm); - vl_msg_api_send_shmem_nolock (q, (u8 *) & mp); - unix_shared_memory_queue_unlock (q); - mp = 0; - ip46_fib_stats_delay (sm, 0 /* sec */ , - STATS_RELEASE_DELAY_NS); - goto again; - } - vl_msg_api_send_shmem_nolock (q, (u8 *) & mp); - unix_shared_memory_queue_unlock (q); - - items_this_message = IP4_FIB_COUNTER_BATCH_SIZE; - mp = vl_msg_api_alloc_as_if_client - (sizeof (*mp) + - items_this_message * sizeof (vl_api_ip4_fib_counter_t)); - mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS); - mp->count = 0; - mp->vrf_id = ntohl (fib->table_id); - ctrp = (vl_api_ip4_fib_counter_t *) mp->c; - } - - j++; - if (j < n_nhs) - { - n_left = nhs[j].weight; - vlib_counter_zero (&sum); - } - } - } /* for each (mp or single) adj */ - if (sm->data_structure_lock->release_hint) - { - start_at_fib_index = fib - im4->fibs; - dsunlock (sm); - ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS); - mp->count = 0; - ctrp = (vl_api_ip4_fib_counter_t *) mp->c; - goto again; - } - } /* vec_foreach (routes) */ + /* already in net byte order */ + ctrp->address = r->address.as_u32; + ctrp->address_length = r->address_length; + ctrp->packets = clib_host_to_net_u64 (c.packets); + ctrp->bytes = clib_host_to_net_u64 (c.bytes); + mp->count++; + ctrp++; + + if (mp->count == items_this_message) + { + mp->count = htonl (items_this_message); + /* + * If the main thread's input queue is stuffed, + * drop the data structure lock (which the main thread + * may want), and take a pause. + */ + unix_shared_memory_queue_lock (q); + if (unix_shared_memory_queue_is_full (q)) + { + dsunlock (sm); + vl_msg_api_send_shmem_nolock (q, (u8 *) & mp); + unix_shared_memory_queue_unlock (q); + mp = 0; + ip46_fib_stats_delay (sm, 0 /* sec */ , + STATS_RELEASE_DELAY_NS); + goto again; + } + vl_msg_api_send_shmem_nolock (q, (u8 *) & mp); + unix_shared_memory_queue_unlock (q); + + items_this_message = IP4_FIB_COUNTER_BATCH_SIZE; + mp = vl_msg_api_alloc_as_if_client + (sizeof (*mp) + + items_this_message * sizeof (vl_api_ip4_fib_counter_t)); + mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS); + mp->count = 0; + mp->vrf_id = ntohl (fib->ft_table_id); + ctrp = (vl_api_ip4_fib_counter_t *) mp->c; + } + } /* for each (mp or single) adj */ + if (sm->data_structure_lock->release_hint) + { + start_at_fib_index = fib - im4->fibs; + dsunlock (sm); + ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS); + mp->count = 0; + ctrp = (vl_api_ip4_fib_counter_t *) mp->c; + goto again; + } + } /* vec_foreach (routes) */ dsunlock (sm); @@ -439,7 +399,9 @@ again: vl_msg_api_send_shmem (q, (u8 *) & mp); mp = 0; } - } /* vec_foreach (fib) */ + })); + /* *INDENT-ON* */ + /* If e.g. the last FIB had no reportable routes, free the buffer */ if (mp) vl_msg_api_free (mp); @@ -489,19 +451,19 @@ do_ip6_fibs (stats_main_t * sm) unix_shared_memory_queue_t *q = shmem_hdr->vl_input_queue; static ip6_route_t *routes; ip6_route_t *r; - ip6_fib_t *fib; - ip_lookup_main_t *lm = &im6->lookup_main; + fib_table_t *fib; static uword *results; vl_api_vnet_ip6_fib_counters_t *mp = 0; u32 items_this_message; vl_api_ip6_fib_counter_t *ctrp = 0; u32 start_at_fib_index = 0; - BVT (clib_bihash) * h = &im6->ip6_lookup_table; + BVT (clib_bihash) * h = &im6->ip6_table[IP6_FIB_TABLE_FWDING].ip6_hash; add_routes_in_fib_arg_t _a, *a = &_a; again: - vec_foreach (fib, im6->fibs) - { + /* *INDENT-OFF* */ + pool_foreach (fib, im6->fibs, + ({ /* We may have bailed out due to control-plane activity */ while ((fib - im6->fibs) < start_at_fib_index) continue; @@ -514,7 +476,7 @@ again: items_this_message * sizeof (vl_api_ip6_fib_counter_t)); mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS); mp->count = 0; - mp->vrf_id = ntohl (fib->table_id); + mp->vrf_id = ntohl (fib->ft_table_id); ctrp = (vl_api_ip6_fib_counter_t *) mp->c; } @@ -544,105 +506,67 @@ again: vec_foreach (r, routes) { - vlib_counter_t c, sum; - uword i, j, n_left, n_nhs, adj_index, *result = 0; - ip_adjacency_t *adj; - ip_multipath_next_hop_t *nhs, tmp_nhs[1]; - - adj_index = r->index; - if (lm->fib_result_n_words > 1) - { - result = vec_elt_at_index (results, adj_index); - adj_index = result[0]; - } - - adj = ip_get_adjacency (lm, adj_index); - if (adj->n_adj == 1) - { - nhs = &tmp_nhs[0]; - nhs[0].next_hop_adj_index = ~0; /* not used */ - nhs[0].weight = 1; - n_nhs = 1; - } - else - { - ip_multipath_adjacency_t *madj; - madj = vec_elt_at_index (lm->multipath_adjacencies, - adj->heap_handle); - nhs = heap_elt_at_index - (lm->next_hop_heap, madj->normalized_next_hops.heap_offset); - n_nhs = madj->normalized_next_hops.count; - } + vlib_counter_t c; + + vlib_get_combined_counter (&load_balance_main.lbm_to_counters, + r->index, &c); + /* + * If it has actually + * seen at least one packet, send it. + */ + if (c.packets > 0) + { + /* already in net byte order */ + ctrp->address[0] = r->address.as_u64[0]; + ctrp->address[1] = r->address.as_u64[1]; + ctrp->address_length = (u8) r->address_length; + ctrp->packets = clib_host_to_net_u64 (c.packets); + ctrp->bytes = clib_host_to_net_u64 (c.bytes); + mp->count++; + ctrp++; + + if (mp->count == items_this_message) + { + mp->count = htonl (items_this_message); + /* + * If the main thread's input queue is stuffed, + * drop the data structure lock (which the main thread + * may want), and take a pause. + */ + unix_shared_memory_queue_lock (q); + if (unix_shared_memory_queue_is_full (q)) + { + dsunlock (sm); + vl_msg_api_send_shmem_nolock (q, (u8 *) & mp); + unix_shared_memory_queue_unlock (q); + mp = 0; + ip46_fib_stats_delay (sm, 0 /* sec */ , + STATS_RELEASE_DELAY_NS); + goto again; + } + vl_msg_api_send_shmem_nolock (q, (u8 *) & mp); + unix_shared_memory_queue_unlock (q); + + items_this_message = IP6_FIB_COUNTER_BATCH_SIZE; + mp = vl_msg_api_alloc_as_if_client + (sizeof (*mp) + + items_this_message * sizeof (vl_api_ip6_fib_counter_t)); + mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS); + mp->count = 0; + mp->vrf_id = ntohl (fib->ft_table_id); + ctrp = (vl_api_ip6_fib_counter_t *) mp->c; + } + } - n_left = nhs[0].weight; - vlib_counter_zero (&sum); - for (i = j = 0; i < adj->n_adj; i++) - { - n_left -= 1; - vlib_get_combined_counter (&lm->adjacency_counters, - adj_index + i, &c); - vlib_counter_add (&sum, &c); - if (n_left == 0 && sum.packets > 0) - { - - /* already in net byte order */ - ctrp->address[0] = r->address.as_u64[0]; - ctrp->address[1] = r->address.as_u64[1]; - ctrp->address_length = (u8) r->address_length; - ctrp->packets = clib_host_to_net_u64 (sum.packets); - ctrp->bytes = clib_host_to_net_u64 (sum.bytes); - mp->count++; - ctrp++; - - if (mp->count == items_this_message) - { - mp->count = htonl (items_this_message); - /* - * If the main thread's input queue is stuffed, - * drop the data structure lock (which the main thread - * may want), and take a pause. - */ - unix_shared_memory_queue_lock (q); - if (unix_shared_memory_queue_is_full (q)) - { - dsunlock (sm); - vl_msg_api_send_shmem_nolock (q, (u8 *) & mp); - unix_shared_memory_queue_unlock (q); - mp = 0; - ip46_fib_stats_delay (sm, 0 /* sec */ , - STATS_RELEASE_DELAY_NS); - goto again; - } - vl_msg_api_send_shmem_nolock (q, (u8 *) & mp); - unix_shared_memory_queue_unlock (q); - - items_this_message = IP6_FIB_COUNTER_BATCH_SIZE; - mp = vl_msg_api_alloc_as_if_client - (sizeof (*mp) + - items_this_message * sizeof (vl_api_ip6_fib_counter_t)); - mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS); - mp->count = 0; - mp->vrf_id = ntohl (fib->table_id); - ctrp = (vl_api_ip6_fib_counter_t *) mp->c; - } - - j++; - if (j < n_nhs) - { - n_left = nhs[j].weight; - vlib_counter_zero (&sum); - } - } - } /* for each (mp or single) adj */ - if (sm->data_structure_lock->release_hint) - { - start_at_fib_index = fib - im6->fibs; - dsunlock (sm); - ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS); - mp->count = 0; - ctrp = (vl_api_ip6_fib_counter_t *) mp->c; - goto again; - } + if (sm->data_structure_lock->release_hint) + { + start_at_fib_index = fib - im6->fibs; + dsunlock (sm); + ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS); + mp->count = 0; + ctrp = (vl_api_ip6_fib_counter_t *) mp->c; + goto again; + } } /* vec_foreach (routes) */ dsunlock (sm); @@ -654,7 +578,9 @@ again: vl_msg_api_send_shmem (q, (u8 *) & mp); mp = 0; } - } /* vec_foreach (fib) */ + })); + /* *INDENT-ON* */ + /* If e.g. the last FIB had no reportable routes, free the buffer */ if (mp) vl_msg_api_free (mp); diff --git a/vpp/vpp-api/api.c b/vpp/vpp-api/api.c index 663096062ef..1a46eb9cf09 100644 --- a/vpp/vpp-api/api.c +++ b/vpp/vpp-api/api.c @@ -54,7 +54,7 @@ #include #include #include -#include +#include #include #include #if IPV6SR > 0 @@ -107,6 +107,13 @@ #include #include +#include +#include +#include +#include +#include +#include + #define f64_endian(a) #define f64_print(a,b) @@ -244,6 +251,7 @@ _(IP_ADD_DEL_ROUTE, ip_add_del_route) \ _(IS_ADDRESS_REACHABLE, is_address_reachable) \ _(SW_INTERFACE_ADD_DEL_ADDRESS, sw_interface_add_del_address) \ _(SW_INTERFACE_SET_TABLE, sw_interface_set_table) \ +_(SW_INTERFACE_SET_MPLS_ENABLE, sw_interface_set_mpls_enable) \ _(SW_INTERFACE_SET_VPATH, sw_interface_set_vpath) \ _(SW_INTERFACE_SET_L2_XCONNECT, sw_interface_set_l2_xconnect) \ _(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge) \ @@ -979,251 +987,165 @@ VLIB_REGISTER_NODE (vpe_resolver_process_node,static) = { /* *INDENT-ON* */ static int -ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) +ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp, + u32 fib_index, + const fib_prefix_t * prefix, + const ip46_address_t * next_hop, + u32 next_hop_sw_if_index, + u32 next_hop_fib_index, u32 next_hop_weight) { - ip4_main_t *im = &ip4_main; - ip_lookup_main_t *lm = &im->lookup_main; vnet_classify_main_t *cm = &vnet_classify_main; + fib_protocol_t proto = prefix->fp_proto; stats_main_t *sm = &stats_main; - ip4_add_del_route_args_t a; - ip4_address_t next_hop_address; - u32 fib_index; - vpe_api_main_t *vam = &vpe_api_main; - vnet_main_t *vnm = vam->vnet_main; - vlib_main_t *vm = vlib_get_main (); - pending_route_t *pr; - vl_api_ip_add_del_route_t *adr; - uword *p; - clib_error_t *e; - u32 ai; - ip_adjacency_t *adj; - - p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id)); - if (!p) - { - if (mp->create_vrf_if_needed) - { - ip4_fib_t *f; - f = find_ip4_fib_by_table_index_or_id (im, ntohl (mp->vrf_id), - 0 /* flags */ ); - fib_index = f->index; - } - else - { - /* No such VRF, and we weren't asked to create one */ - return VNET_API_ERROR_NO_SUCH_FIB; - } - } - else - { - fib_index = p[0]; - } - - if (~0 != mp->next_hop_sw_if_index && - pool_is_free_index (vnm->interface_main.sw_interfaces, - ntohl (mp->next_hop_sw_if_index))) - return VNET_API_ERROR_NO_MATCHING_INTERFACE; - - clib_memcpy (next_hop_address.data, mp->next_hop_address, - sizeof (next_hop_address.data)); - - /* Arp for the next_hop if necessary */ - if (mp->is_add && mp->resolve_if_needed && ~0 != mp->next_hop_sw_if_index) - { - u32 lookup_result; - ip_adjacency_t *adj; - - lookup_result = ip4_fib_lookup_with_table - (im, fib_index, &next_hop_address, 1 /* disable default route */ ); - - adj = ip_get_adjacency (lm, lookup_result); - - if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) - { - pool_get (vam->pending_routes, pr); - pr->resolve_type = RESOLVE_IP4_ADD_DEL_ROUTE; - adr = &pr->r; - clib_memcpy (adr, mp, sizeof (*adr)); - /* recursion block, "just in case" */ - adr->resolve_if_needed = 0; - adr->resolve_attempts = ntohl (mp->resolve_attempts); - vnet_register_ip4_arp_resolution_event - (vnm, &next_hop_address, vpe_resolver_process_node.index, - RESOLUTION_EVENT, pr - vam->pending_routes); - - vlib_process_signal_event - (vm, vpe_resolver_process_node.index, - RESOLUTION_PENDING_EVENT, 0 /* data */ ); - - /* The interface may be down, etc. */ - e = ip4_probe_neighbor - (vm, (ip4_address_t *) & (mp->next_hop_address), - ntohl (mp->next_hop_sw_if_index)); - - if (e) - clib_error_report (e); - - return VNET_API_ERROR_IN_PROGRESS; - } - } if (mp->is_multipath) { - u32 flags; + fib_route_path_flags_t path_flags = FIB_ROUTE_PATH_FLAG_NONE; dslock (sm, 1 /* release hint */ , 10 /* tag */ ); + if (mp->is_resolve_host) + path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST; + if (mp->is_resolve_attached) + path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED; + if (mp->is_add) - flags = IP4_ROUTE_FLAG_ADD; + fib_table_entry_path_add (fib_index, + prefix, + FIB_SOURCE_API, + FIB_ENTRY_FLAG_NONE, + prefix->fp_proto, + next_hop, + next_hop_sw_if_index, + next_hop_fib_index, + next_hop_weight, + MPLS_LABEL_INVALID, path_flags); else - flags = IP4_ROUTE_FLAG_DEL; - - if (mp->not_last) - flags |= IP4_ROUTE_FLAG_NOT_LAST_IN_GROUP; - - ip4_add_del_route_next_hop (im, flags, - (ip4_address_t *) mp->dst_address, - (u32) mp->dst_address_length, - (ip4_address_t *) mp->next_hop_address, - ntohl (mp->next_hop_sw_if_index), - (u32) mp->next_hop_weight, - ~0 /* adj_index */ , - fib_index); + fib_table_entry_path_remove (fib_index, + prefix, + FIB_SOURCE_API, + prefix->fp_proto, + next_hop, + next_hop_sw_if_index, + next_hop_fib_index, + next_hop_weight, path_flags); + dsunlock (sm); return 0; } - memset (&a, 0, sizeof (a)); - clib_memcpy (a.dst_address.data, mp->dst_address, - sizeof (a.dst_address.data)); - - a.dst_address_length = mp->dst_address_length; - - a.flags = (mp->is_add ? IP4_ROUTE_FLAG_ADD : IP4_ROUTE_FLAG_DEL); - a.flags |= IP4_ROUTE_FLAG_FIB_INDEX; - a.table_index_or_table_id = fib_index; - a.add_adj = 0; - a.n_add_adj = 0; - - if (mp->not_last) - a.flags |= IP4_ROUTE_FLAG_NOT_LAST_IN_GROUP; - dslock (sm, 1 /* release hint */ , 2 /* tag */ ); - if (mp->is_add) + if (mp->is_drop || mp->is_local || mp->is_classify || mp->lookup_in_vrf) { - if (mp->is_drop) - ai = lm->drop_adj_index; - else if (mp->is_local) - ai = lm->local_adj_index; - else if (mp->is_classify) + /* + * special route types that link directly to the adj + */ + if (mp->is_add) { - if (pool_is_free_index - (cm->tables, ntohl (mp->classify_table_index))) + dpo_id_t dpo = DPO_NULL; + dpo_proto_t dproto; + + dproto = fib_proto_to_dpo (prefix->fp_proto); + + if (mp->is_drop) + dpo_copy (&dpo, drop_dpo_get (dproto)); + else if (mp->is_local) + receive_dpo_add_or_lock (dproto, ~0, NULL, &dpo); + else if (mp->is_classify) { - dsunlock (sm); - return VNET_API_ERROR_NO_SUCH_TABLE; - } - adj = ip_add_adjacency (lm, - /* template */ 0, - /* block size */ 1, - &ai); + if (pool_is_free_index (cm->tables, + ntohl (mp->classify_table_index))) + { + dsunlock (sm); + return VNET_API_ERROR_NO_SUCH_TABLE; + } - adj->lookup_next_index = IP_LOOKUP_NEXT_CLASSIFY; - adj->classify.table_index = ntohl (mp->classify_table_index); - } - else if (mp->lookup_in_vrf) - { - p = hash_get (im->fib_index_by_table_id, ntohl (mp->lookup_in_vrf)); - if (p) + dpo_set (&dpo, DPO_CLASSIFY, proto, + classify_dpo_create (prefix->fp_proto, + ntohl + (mp->classify_table_index))); + } + else if (mp->lookup_in_vrf) { - adj = ip_add_adjacency (lm, - /* template */ 0, - /* block size */ 1, - &ai); - adj->explicit_fib_index = p[0]; + next_hop_fib_index = + fib_table_id_find_fib_index (dproto, + ntohl (mp->lookup_in_vrf)); + if (~0 == next_hop_fib_index) + { + dsunlock (sm); + return VNET_API_ERROR_NO_SUCH_INNER_FIB; + } + + lookup_dpo_add_or_lock_w_fib_index (next_hop_fib_index, + dproto, + LOOKUP_INPUT_DST_ADDR, + LOOKUP_TABLE_FROM_CONFIG, + &dpo); } else { dsunlock (sm); - return VNET_API_ERROR_NO_SUCH_INNER_FIB; + return VNET_API_ERROR_NO_SUCH_TABLE; } + + fib_table_entry_special_dpo_add (fib_index, + prefix, + FIB_SOURCE_API, + FIB_ENTRY_FLAG_EXCLUSIVE, &dpo); + dpo_reset (&dpo); } else - ai = ip4_route_get_next_hop_adj (im, - fib_index, - &next_hop_address, - ntohl (mp->next_hop_sw_if_index), - fib_index); - - if (ai == lm->miss_adj_index) { - dsunlock (sm); - return VNET_API_ERROR_NO_SUCH_INNER_FIB; + fib_table_entry_special_remove (fib_index, prefix, FIB_SOURCE_API); } } else { - ip_adjacency_t *adj; - int disable_default_route = 1; - - /* Trying to delete the default route? */ - if (a.dst_address.as_u32 == 0 && a.dst_address_length == 0) - disable_default_route = 0; - - ai = ip4_fib_lookup_with_table - (im, fib_index, &a.dst_address, disable_default_route); - if (ai == lm->miss_adj_index) + if (mp->is_add) { - dsunlock (sm); - return VNET_API_ERROR_UNKNOWN_DESTINATION; + fib_route_path_flags_t path_flags = FIB_ROUTE_PATH_FLAG_NONE; + + if (mp->is_resolve_host) + path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST; + if (mp->is_resolve_attached) + path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED; + + fib_table_entry_update_one_path (fib_index, + prefix, + FIB_SOURCE_API, + FIB_ENTRY_FLAG_NONE, + prefix->fp_proto, + next_hop, + next_hop_sw_if_index, + next_hop_fib_index, + next_hop_weight, + MPLS_LABEL_INVALID, path_flags); } - - adj = ip_get_adjacency (lm, ai); - if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) + else { - dsunlock (sm); - return VNET_API_ERROR_ADDRESS_MATCHES_INTERFACE_ADDRESS; + fib_table_entry_delete (fib_index, prefix, FIB_SOURCE_API); } } - a.adj_index = ai; - ip4_add_del_route (im, &a); - dsunlock (sm); - return 0; + return (0); } static int -ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) +ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) { - ip6_main_t *im = &ip6_main; - ip_lookup_main_t *lm = &im->lookup_main; - vnet_main_t *vnm = vnet_get_main (); - vlib_main_t *vm = vlib_get_main (); vpe_api_main_t *vam = &vpe_api_main; - stats_main_t *sm = &stats_main; - ip6_add_del_route_args_t a; - ip6_address_t next_hop_address; - pending_route_t *pr; - vl_api_ip_add_del_route_t *adr; - + vnet_main_t *vnm = vam->vnet_main; u32 fib_index; - uword *p; - clib_error_t *e; - ip_adjacency_t *adj = 0; - u32 ai; - - p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id)); - if (!p) + fib_index = ip4_fib_index_from_table_id (ntohl (mp->vrf_id)); + if (~0 == fib_index) { if (mp->create_vrf_if_needed) { - ip6_fib_t *f; - f = find_ip6_fib_by_table_index_or_id (im, ntohl (mp->vrf_id), - 0 /* flags */ ); - fib_index = f->index; + fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, + ntohl (mp->vrf_id)); } else { @@ -1231,160 +1153,66 @@ ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) return VNET_API_ERROR_NO_SUCH_FIB; } } - else - { - fib_index = p[0]; - } - if (~0 != mp->next_hop_sw_if_index && + if (~0 != ntohl (mp->next_hop_sw_if_index) && pool_is_free_index (vnm->interface_main.sw_interfaces, ntohl (mp->next_hop_sw_if_index))) return VNET_API_ERROR_NO_MATCHING_INTERFACE; - clib_memcpy (next_hop_address.as_u8, mp->next_hop_address, - sizeof (next_hop_address.as_u8)); - - /* Arp for the next_hop if necessary */ - if (mp->is_add && mp->resolve_if_needed && ~0 != mp->next_hop_sw_if_index) - { - u32 lookup_result; - ip_adjacency_t *adj; - - lookup_result = ip6_fib_lookup_with_table - (im, fib_index, &next_hop_address); - - adj = ip_get_adjacency (lm, lookup_result); - - if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) - { - pool_get (vam->pending_routes, pr); - adr = &pr->r; - pr->resolve_type = RESOLVE_IP6_ADD_DEL_ROUTE; - clib_memcpy (adr, mp, sizeof (*adr)); - /* recursion block, "just in case" */ - adr->resolve_if_needed = 0; - adr->resolve_attempts = ntohl (mp->resolve_attempts); - vnet_register_ip6_neighbor_resolution_event - (vnm, &next_hop_address, vpe_resolver_process_node.index, - RESOLUTION_EVENT, pr - vam->pending_routes); - - vlib_process_signal_event - (vm, vpe_resolver_process_node.index, - RESOLUTION_PENDING_EVENT, 0 /* data */ ); - - /* The interface may be down, etc. */ - e = ip6_probe_neighbor - (vm, (ip6_address_t *) & (mp->next_hop_address), - ntohl (mp->next_hop_sw_if_index)); - - if (e) - clib_error_report (e); - - return VNET_API_ERROR_IN_PROGRESS; - } - } - - if (mp->is_multipath) - { - u32 flags; - - dslock (sm, 1 /* release hint */ , 11 /* tag */ ); - - if (mp->is_add) - flags = IP6_ROUTE_FLAG_ADD; - else - flags = IP6_ROUTE_FLAG_DEL; - - if (mp->not_last) - flags |= IP6_ROUTE_FLAG_NOT_LAST_IN_GROUP; - - ip6_add_del_route_next_hop (im, flags, - (ip6_address_t *) mp->dst_address, - (u32) mp->dst_address_length, - (ip6_address_t *) mp->next_hop_address, - ntohl (mp->next_hop_sw_if_index), - (u32) mp->next_hop_weight, - ~0 /* adj_index */ , - fib_index); - dsunlock (sm); - return 0; - } - - memset (&a, 0, sizeof (a)); - clib_memcpy (a.dst_address.as_u8, mp->dst_address, - sizeof (a.dst_address.as_u8)); - - a.dst_address_length = mp->dst_address_length; + fib_prefix_t pfx = { + .fp_len = mp->dst_address_length, + .fp_proto = FIB_PROTOCOL_IP4, + }; + clib_memcpy (&pfx.fp_addr.ip4, mp->dst_address, sizeof (pfx.fp_addr.ip4)); - a.flags = (mp->is_add ? IP6_ROUTE_FLAG_ADD : IP6_ROUTE_FLAG_DEL); - a.flags |= IP6_ROUTE_FLAG_FIB_INDEX; - a.table_index_or_table_id = fib_index; - a.add_adj = 0; - a.n_add_adj = 0; + ip46_address_t nh; + memset (&nh, 0, sizeof (nh)); + memcpy (&nh.ip4, mp->next_hop_address, sizeof (nh.ip4)); - if (mp->not_last) - a.flags |= IP6_ROUTE_FLAG_NOT_LAST_IN_GROUP; + return (ip_add_del_route_t_handler (mp, fib_index, &pfx, &nh, + ntohl (mp->next_hop_sw_if_index), + fib_index, (u32) mp->next_hop_weight)); +} - dslock (sm, 1 /* release hint */ , 3 /* tag */ ); +static int +ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) +{ + vnet_main_t *vnm = vnet_get_main (); + u32 fib_index; - if (mp->is_add) + fib_index = ip6_fib_index_from_table_id (ntohl (mp->vrf_id)); + if (~0 == fib_index) { - if (mp->is_drop) - ai = lm->drop_adj_index; - else if (mp->is_local) - ai = lm->local_adj_index; - else if (mp->lookup_in_vrf) + if (mp->create_vrf_if_needed) { - p = hash_get (im->fib_index_by_table_id, ntohl (mp->lookup_in_vrf)); - if (p) - { - adj = ip_add_adjacency (lm, - /* template */ 0, - /* block size */ 1, - &ai); - adj->explicit_fib_index = p[0]; - } - else - { - dsunlock (sm); - return VNET_API_ERROR_NO_SUCH_INNER_FIB; - } + fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, + ntohl (mp->vrf_id)); } else - ai = ip6_route_get_next_hop_adj (im, - fib_index, - &next_hop_address, - ntohl (mp->next_hop_sw_if_index), - fib_index); - if (ai == lm->miss_adj_index) { - dsunlock (sm); - return VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB; + /* No such VRF, and we weren't asked to create one */ + return VNET_API_ERROR_NO_SUCH_FIB; } } - else - { - ip_adjacency_t *adj; - ai = ip6_fib_lookup_with_table (im, fib_index, &a.dst_address); - if (ai == lm->miss_adj_index) - { - dsunlock (sm); - return VNET_API_ERROR_UNKNOWN_DESTINATION; - } - adj = ip_get_adjacency (lm, ai); - if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) - { - dsunlock (sm); - return VNET_API_ERROR_ADDRESS_MATCHES_INTERFACE_ADDRESS; - } - } + if (~0 != ntohl (mp->next_hop_sw_if_index) && + pool_is_free_index (vnm->interface_main.sw_interfaces, + ntohl (mp->next_hop_sw_if_index))) + return VNET_API_ERROR_NO_MATCHING_INTERFACE; + + fib_prefix_t pfx = { + .fp_len = mp->dst_address_length, + .fp_proto = FIB_PROTOCOL_IP6, + }; + clib_memcpy (&pfx.fp_addr.ip6, mp->dst_address, sizeof (pfx.fp_addr.ip6)); - a.adj_index = ai; - ip6_add_del_route (im, &a); + ip46_address_t nh; + memset (&nh, 0, sizeof (nh)); + memcpy (&nh.ip6, mp->next_hop_address, sizeof (nh.ip6)); - dsunlock (sm); - return 0; + return (ip_add_del_route_t_handler (mp, fib_index, &pfx, + &nh, ntohl (mp->next_hop_sw_if_index), + fib_index, (u32) mp->next_hop_weight)); } void @@ -1406,48 +1234,6 @@ vl_api_ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) REPLY_MACRO (VL_API_IP_ADD_DEL_ROUTE_REPLY); } -void -api_config_default_ip_route (u8 is_ipv6, u8 is_add, u32 vrf_id, - u32 sw_if_index, u8 * next_hop_addr) -{ - vl_api_ip_add_del_route_t mp; - int rv; - - memset (&mp, 0, sizeof (vl_api_ip_add_del_route_t)); - - /* - * Configure default IP route: - * - ip route add 0.0.0.0/1 via - * - ip route add 128.0.0.0/1 via - */ - mp.next_hop_sw_if_index = ntohl (sw_if_index); - mp.vrf_id = vrf_id; - mp.resolve_attempts = ~0; - mp.resolve_if_needed = 1; - mp.is_add = is_add; - mp.is_ipv6 = is_ipv6; - mp.next_hop_weight = 1; - - clib_memcpy (&mp.next_hop_address[0], next_hop_addr, 16); - - if (is_ipv6) - rv = ip6_add_del_route_t_handler (&mp); - else - { - mp.dst_address_length = 1; - - mp.dst_address[0] = 0; - rv = ip4_add_del_route_t_handler (&mp); - - mp.dst_address[0] = 128; - rv |= ip4_add_del_route_t_handler (&mp); - } - - if (rv) - clib_error_return (0, "failed to config default IP route"); - -} - static void vl_api_sw_interface_add_del_address_t_handler (vl_api_sw_interface_add_del_address_t * mp) @@ -1485,6 +1271,7 @@ vl_api_sw_interface_set_table_t_handler (vl_api_sw_interface_set_table_t * mp) u32 sw_if_index = ntohl (mp->sw_if_index); vl_api_sw_interface_set_table_reply_t *rmp; stats_main_t *sm = &stats_main; + u32 fib_index; VALIDATE_SW_IF_INDEX (mp); @@ -1492,35 +1279,20 @@ vl_api_sw_interface_set_table_t_handler (vl_api_sw_interface_set_table_t * mp) if (mp->is_ipv6) { - ip6_main_t *im = &ip6_main; - ip6_fib_t *fib = find_ip6_fib_by_table_index_or_id (im, table_id, - IP6_ROUTE_FLAG_TABLE_ID); - if (fib) - { - vec_validate (im->fib_index_by_sw_if_index, sw_if_index); - im->fib_index_by_sw_if_index[sw_if_index] = fib->index; - } - else - { - rv = VNET_API_ERROR_NO_SUCH_FIB; - } + fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, + table_id); + + vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index); + ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index; } else { - ip4_main_t *im = &ip4_main; - ip4_fib_t *fib = find_ip4_fib_by_table_index_or_id - (im, table_id, IP4_ROUTE_FLAG_TABLE_ID); - /* Truthfully this can't fail */ - if (fib) - { - vec_validate (im->fib_index_by_sw_if_index, sw_if_index); - im->fib_index_by_sw_if_index[sw_if_index] = fib->index; - } - else - { - rv = VNET_API_ERROR_NO_SUCH_FIB; - } + fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, + table_id); + + vec_validate (ip4_main.fib_index_by_sw_if_index, sw_if_index); + ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index; } dsunlock (sm); @@ -2303,10 +2075,11 @@ static int mpls_ethernet_add_del_tunnel_2_t_handler if (inner_fib_index == outer_fib_index) return VNET_API_ERROR_INVALID_VALUE; - lookup_result = ip4_fib_lookup_with_table - (im, outer_fib_index, - (ip4_address_t *) mp->next_hop_ip4_address_in_outer_vrf, - 1 /* disable default route */ ); + // FIXME not an ADJ + lookup_result = ip4_fib_table_lookup_lb (ip4_fib_get (outer_fib_index), + (ip4_address_t *) + mp-> + next_hop_ip4_address_in_outer_vrf); adj = ip_get_adjacency (lm, lookup_result); tx_sw_if_index = adj->rewrite_header.sw_if_index; @@ -2489,14 +2262,18 @@ vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp, { vl_api_ip_neighbor_add_del_reply_t *rmp; vnet_main_t *vnm = vnet_get_main (); - u32 fib_index; - int rv = 0; stats_main_t *sm = &stats_main; + int rv = 0; VALIDATE_SW_IF_INDEX (mp); dslock (sm, 1 /* release hint */ , 7 /* tag */ ); + /* + * there's no validation here of the ND/ARP entry being added. + * The expectation is that the FIB will ensure that nothing bad + * will come of adding bogus entries. + */ if (mp->is_ipv6) { if (mp->is_add) @@ -2512,56 +2289,21 @@ vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp, } else { - ip4_main_t *im = &ip4_main; - ip_lookup_main_t *lm = &im->lookup_main; ethernet_arp_ip4_over_ethernet_address_t a; - u32 ai; - ip_adjacency_t *nh_adj; - - uword *p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id)); - if (!p) - { - rv = VNET_API_ERROR_NO_SUCH_FIB; - goto out; - } - fib_index = p[0]; - - /* - * Unfortunately, folks have a penchant for - * adding interface addresses to the ARP cache, and - * wondering why the forwarder eventually ASSERTs... - */ - ai = ip4_fib_lookup_with_table - (im, fib_index, (ip4_address_t *) (mp->dst_address), - 1 /* disable default route */ ); - - if (ai != 0) - { - nh_adj = ip_get_adjacency (lm, ai); - /* Never allow manipulation of a local adj! */ - if (nh_adj->lookup_next_index == IP_LOOKUP_NEXT_LOCAL) - { - clib_warning ("%U matches local adj", - format_ip4_address, - (ip4_address_t *) (mp->dst_address)); - rv = VNET_API_ERROR_ADDRESS_MATCHES_INTERFACE_ADDRESS; - goto out; - } - } clib_memcpy (&a.ethernet, mp->mac_address, 6); clib_memcpy (&a.ip4, mp->dst_address, 4); if (mp->is_add) rv = vnet_arp_set_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index), - fib_index, &a, mp->is_static); + &a, mp->is_static); else - rv = vnet_arp_unset_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index), - fib_index, &a); + rv = + vnet_arp_unset_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index), &a); } BAD_SW_IF_INDEX_LABEL; -out: + dsunlock (sm); REPLY_MACRO (VL_API_IP_NEIGHBOR_ADD_DEL_REPLY); } @@ -2604,6 +2346,7 @@ vl_api_is_address_reachable_t_handler (vl_api_is_address_reachable_t * mp) else { lm = &im4->lookup_main; + // FIXME NOT an ADJ adj_index = ip4_fib_lookup (im4, sw_if_index, &addr.ip4); } if (adj_index == ~0) @@ -2671,6 +2414,22 @@ vl_api_sw_interface_set_flags_t_handler (vl_api_sw_interface_set_flags_t * mp) REPLY_MACRO (VL_API_SW_INTERFACE_SET_FLAGS_REPLY); } +static void + vl_api_sw_interface_set_mpls_enable_t_handler + (vl_api_sw_interface_set_mpls_enable_t * mp) +{ + vl_api_sw_interface_set_mpls_enable_reply_t *rmp; + int rv = 0; + + VALIDATE_SW_IF_INDEX (mp); + + mpls_sw_interface_enable_disable (&mpls_main, + ntohl (mp->sw_if_index), mp->enable); + + BAD_SW_IF_INDEX_LABEL; + REPLY_MACRO (VL_API_SW_INTERFACE_SET_MPLS_ENABLE_REPLY); +} + static void vl_api_sw_interface_clear_stats_t_handler (vl_api_sw_interface_clear_stats_t * mp) @@ -2999,10 +2758,9 @@ ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp) vnet_main_t *vnm = vnet_get_main (); vnet_interface_main_t *im = &vnm->interface_main; ip4_main_t *im4 = &ip4_main; - static ip4_route_t *routes; static u32 *sw_if_indices_to_shut; stats_main_t *sm = &stats_main; - ip4_route_t *r; + fib_table_t *fib_table; ip4_fib_t *fib; u32 sw_if_index; int i; @@ -3011,9 +2769,11 @@ ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp) dslock (sm, 1 /* release hint */ , 8 /* tag */ ); - vec_foreach (fib, im4->fibs) - { - vnet_sw_interface_t *si; + /* *INDENT-OFF* */ + pool_foreach (fib_table, im4->fibs, + ({ + fib = &fib_table->v4; + vnet_sw_interface_t * si; if (fib->table_id != target_fib_id) continue; @@ -3033,100 +2793,37 @@ ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp) vec_reset_length (sw_if_indices_to_shut); /* Shut down interfaces in this FIB / clean out intfc routes */ - /* *INDENT-OFF* */ pool_foreach (si, im->sw_interfaces, ({ u32 sw_if_index = si->sw_if_index; if (sw_if_index < vec_len (im4->fib_index_by_sw_if_index) && (im4->fib_index_by_sw_if_index[si->sw_if_index] == - fib - im4->fibs)) + fib->index)) vec_add1 (sw_if_indices_to_shut, si->sw_if_index); })); - /* *INDENT-ON* */ - for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) - { - sw_if_index = sw_if_indices_to_shut[i]; - // vec_foreach (sw_if_index, sw_if_indices_to_shut) { - - u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index); - flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP); - vnet_sw_interface_set_flags (vnm, sw_if_index, flags); - } + for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) { + sw_if_index = sw_if_indices_to_shut[i]; + // vec_foreach (sw_if_index, sw_if_indices_to_shut) { - vec_reset_length (routes); - - for (i = 0; i < ARRAY_LEN (fib->adj_index_by_dst_address); i++) - { - uword *hash = fib->adj_index_by_dst_address[i]; - hash_pair_t *p; - ip4_route_t x; - - x.address_length = i; - - /* *INDENT-OFF* */ - hash_foreach_pair (p, hash, - ({ - x.address.data_u32 = p->key; - vec_add1 (routes, x); - })); - /* *INDENT-ON* */ - } - - vec_foreach (r, routes) - { - ip4_add_del_route_args_t a; + u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index); + flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP); + vnet_sw_interface_set_flags (vnm, sw_if_index, flags); + } - memset (&a, 0, sizeof (a)); - a.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_DEL; - a.table_index_or_table_id = fib - im4->fibs; - a.dst_address = r->address; - a.dst_address_length = r->address_length; - a.adj_index = ~0; + fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_API); + fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_INTERFACE); - ip4_add_del_route (im4, &a); - ip4_maybe_remap_adjacencies (im4, fib - im4->fibs, - IP4_ROUTE_FLAG_FIB_INDEX); - } rv = 0; break; - } /* vec_foreach (fib) */ + })); /* pool_foreach (fib) */ + /* *INDENT-ON* */ dsunlock (sm); return rv; } -typedef struct -{ - ip6_address_t address; - u32 address_length; - u32 index; -} ip6_route_t; - -typedef struct -{ - u32 fib_index; - ip6_route_t **routep; -} add_routes_in_fib_arg_t; - -static void -add_routes_in_fib (clib_bihash_kv_24_8_t * kvp, void *arg) -{ - add_routes_in_fib_arg_t *ap = arg; - - if (kvp->key[2] >> 32 == ap->fib_index) - { - ip6_address_t *addr; - ip6_route_t *r; - addr = (ip6_address_t *) kvp; - vec_add2 (*ap->routep, r, 1); - r->address = addr[0]; - r->address_length = kvp->key[2] & 0xFF; - r->index = kvp->value; - } -} - static int ip6_reset_fib_t_handler (vl_api_reset_fib_t * mp) { @@ -3134,22 +2831,21 @@ ip6_reset_fib_t_handler (vl_api_reset_fib_t * mp) vnet_interface_main_t *im = &vnm->interface_main; ip6_main_t *im6 = &ip6_main; stats_main_t *sm = &stats_main; - static ip6_route_t *routes; static u32 *sw_if_indices_to_shut; - ip6_route_t *r; + fib_table_t *fib_table; ip6_fib_t *fib; u32 sw_if_index; int i; int rv = VNET_API_ERROR_NO_SUCH_FIB; u32 target_fib_id = ntohl (mp->vrf_id); - add_routes_in_fib_arg_t _a, *a = &_a; - clib_bihash_24_8_t *h = &im6->ip6_lookup_table; dslock (sm, 1 /* release hint */ , 9 /* tag */ ); - vec_foreach (fib, im6->fibs) - { - vnet_sw_interface_t *si; + /* *INDENT-OFF* */ + pool_foreach (fib_table, im6->fibs, + ({ + vnet_sw_interface_t * si; + fib = &(fib_table->v6); if (fib->table_id != target_fib_id) continue; @@ -3157,52 +2853,29 @@ ip6_reset_fib_t_handler (vl_api_reset_fib_t * mp) vec_reset_length (sw_if_indices_to_shut); /* Shut down interfaces in this FIB / clean out intfc routes */ - /* *INDENT-OFF* */ pool_foreach (si, im->sw_interfaces, - ({ - if (im6->fib_index_by_sw_if_index[si->sw_if_index] == - fib - im6->fibs) - vec_add1 (sw_if_indices_to_shut, si->sw_if_index); - })); - /* *INDENT-ON* */ + ({ + if (im6->fib_index_by_sw_if_index[si->sw_if_index] == + fib->index) + vec_add1 (sw_if_indices_to_shut, si->sw_if_index); + })); - for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) - { - sw_if_index = sw_if_indices_to_shut[i]; - // vec_foreach (sw_if_index, sw_if_indices_to_shut) { - - u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index); - flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP); - vnet_sw_interface_set_flags (vnm, sw_if_index, flags); - } + for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) { + sw_if_index = sw_if_indices_to_shut[i]; + // vec_foreach (sw_if_index, sw_if_indices_to_shut) { - vec_reset_length (routes); - - a->fib_index = fib - im6->fibs; - a->routep = &routes; - - clib_bihash_foreach_key_value_pair_24_8 (h, add_routes_in_fib, a); - - vec_foreach (r, routes) - { - ip6_add_del_route_args_t a; + u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index); + flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP); + vnet_sw_interface_set_flags (vnm, sw_if_index, flags); + } - memset (&a, 0, sizeof (a)); - a.flags = IP6_ROUTE_FLAG_FIB_INDEX | IP6_ROUTE_FLAG_DEL; - a.table_index_or_table_id = fib - im6->fibs; - a.dst_address = r->address; - a.dst_address_length = r->address_length; - a.adj_index = ~0; + fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_API); + fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE); - ip6_add_del_route (im6, &a); - ip6_maybe_remap_adjacencies (im6, fib - im6->fibs, - IP6_ROUTE_FLAG_FIB_INDEX); - } rv = 0; - /* Reinstall the neighbor / router discovery routes */ - vnet_ip6_fib_init (im6, fib - im6->fibs); break; - } /* vec_foreach (fib) */ + })); /* pool_foreach (fib) */ + /* *INDENT-ON* */ dsunlock (sm); return rv; @@ -3519,7 +3192,7 @@ set_ip4_flow_hash (vl_api_set_ip_flow_hash_t * mp) vl_api_set_ip_flow_hash_reply_t *rmp; int rv; u32 table_id; - u32 flow_hash_config = 0; + flow_hash_config_t flow_hash_config = 0; table_id = ntohl (mp->vrf_id); @@ -3580,11 +3253,15 @@ static void vl_api_sw_interface_set_unnumbered_t_handler { si->flags |= VNET_SW_INTERFACE_FLAG_UNNUMBERED; si->unnumbered_sw_if_index = sw_if_index; + ip4_sw_interface_enable_disable (sw_if_index, 1); + ip6_sw_interface_enable_disable (sw_if_index, 1); } else { si->flags &= ~(VNET_SW_INTERFACE_FLAG_UNNUMBERED); si->unnumbered_sw_if_index = (u32) ~ 0; + ip4_sw_interface_enable_disable (sw_if_index, 0); + ip6_sw_interface_enable_disable (sw_if_index, 0); } done: @@ -3769,7 +3446,7 @@ vl_api_set_arp_neighbor_limit_t_handler (vl_api_set_arp_neighbor_limit_t * mp) static void vl_api_sr_tunnel_add_del_t_handler (vl_api_sr_tunnel_add_del_t * mp) { -#if IPV6SR == 0 +#if IP6SR == 0 clib_warning ("unimplemented"); #else ip6_sr_add_del_tunnel_args_t _a, *a = &_a; @@ -3832,7 +3509,7 @@ out: static void vl_api_sr_policy_add_del_t_handler (vl_api_sr_policy_add_del_t * mp) { -#if IPV6SR == 0 +#if IP6SR == 0 clib_warning ("unimplemented"); #else ip6_sr_add_del_policy_args_t _a, *a = &_a; @@ -3886,7 +3563,7 @@ out: static void vl_api_sr_multicast_map_add_del_t_handler (vl_api_sr_multicast_map_add_del_t * mp) { -#if IPV6SR == 0 +#if IP6SR == 0 clib_warning ("unimplemented"); #else ip6_sr_add_del_multicastmap_args_t _a, *a = &_a; @@ -4906,13 +4583,13 @@ static void send_vxlan_tunnel_details { memcpy (rmp->src_address, &(t->src.ip6), 16); memcpy (rmp->dst_address, &(t->dst.ip6), 16); - rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].table_id); + rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id); } else { memcpy (rmp->src_address, &(t->src.ip4), 4); memcpy (rmp->dst_address, &(t->dst.ip4), 4); - rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].table_id); + rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id); } rmp->vni = htonl (t->vni); rmp->decap_next_index = htonl (t->decap_next_index); @@ -5018,7 +4695,7 @@ static void send_gre_tunnel_details rmp->_vl_msg_id = ntohs (VL_API_GRE_TUNNEL_DETAILS); clib_memcpy (rmp->src_address, &(t->tunnel_src), 4); clib_memcpy (rmp->dst_address, &(t->tunnel_dst), 4); - rmp->outer_fib_id = htonl (im->fibs[t->outer_fib_index].table_id); + rmp->outer_fib_id = htonl (im->fibs[t->outer_fib_index].ft_table_id); rmp->teb = t->teb; rmp->sw_if_index = htonl (t->sw_if_index); rmp->context = context; @@ -5178,15 +4855,15 @@ static void send_vxlan_gpe_tunnel_details { memcpy (rmp->local, &(t->local.ip6), 16); memcpy (rmp->remote, &(t->remote.ip6), 16); - rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].table_id); - rmp->decap_vrf_id = htonl (im6->fibs[t->decap_fib_index].table_id); + rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id); + rmp->decap_vrf_id = htonl (im6->fibs[t->decap_fib_index].ft_table_id); } else { memcpy (rmp->local, &(t->local.ip4), 4); memcpy (rmp->remote, &(t->remote.ip4), 4); - rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].table_id); - rmp->decap_vrf_id = htonl (im4->fibs[t->decap_fib_index].table_id); + rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id); + rmp->decap_vrf_id = htonl (im4->fibs[t->decap_fib_index].ft_table_id); } rmp->vni = htonl (t->vni); rmp->protocol = t->protocol; @@ -7630,7 +7307,6 @@ vl_api_mpls_fib_encap_dump_t_handler (vl_api_mpls_fib_encap_dump_t * mp) show_mpls_fib_t *records = 0; show_mpls_fib_t *s; mpls_main_t *mm = &mpls_main; - ip4_main_t *im = &ip4_main; ip4_fib_t *rx_fib; q = vl_api_client_index_to_input_queue (mp->client_index); @@ -7660,7 +7336,7 @@ vl_api_mpls_fib_encap_dump_t_handler (vl_api_mpls_fib_encap_dump_t * mp) vlib_cli_output (vm, "%=6s%=16s%=16s", "Table", "Dest address", "Labels"); vec_foreach (s, records) { - rx_fib = vec_elt_at_index (im->fibs, s->fib_index); + rx_fib = ip4_fib_get (s->fib_index); vlib_cli_output (vm, "%=6d%=16U%=16U", rx_fib->table_id, format_ip4_address, &s->dest, format_mpls_encap_index, mm, s->entry_index); @@ -7715,7 +7391,6 @@ vl_api_mpls_fib_decap_dump_t_handler (vl_api_mpls_fib_decap_dump_t * mp) show_mpls_fib_t *records = 0; show_mpls_fib_t *s; mpls_main_t *mm = &mpls_main; - ip4_main_t *im = &ip4_main; ip4_fib_t *rx_fib; ip4_fib_t *tx_fib; u32 tx_table_id; @@ -7750,9 +7425,9 @@ vl_api_mpls_fib_decap_dump_t_handler (vl_api_mpls_fib_decap_dump_t * mp) { mpls_decap_t *d; d = pool_elt_at_index (mm->decaps, s->entry_index); - if (d->next_index == MPLS_INPUT_NEXT_IP4_INPUT) + if (d->next_index == MPLS_LOOKUP_NEXT_IP4_INPUT) { - tx_fib = vec_elt_at_index (im->fibs, d->tx_fib_index); + tx_fib = ip4_fib_get (d->tx_fib_index); tx_table_id = tx_fib->table_id; swif_tag = " "; } @@ -7761,7 +7436,7 @@ vl_api_mpls_fib_decap_dump_t_handler (vl_api_mpls_fib_decap_dump_t * mp) tx_table_id = d->tx_fib_index; swif_tag = "(i) "; } - rx_fib = vec_elt_at_index (im->fibs, s->fib_index); + rx_fib = ip4_fib_get (s->fib_index); vlib_cli_output (vm, "%=10d%=10d%=5s%=6d%=6d", rx_fib->table_id, tx_table_id, swif_tag, s->label, s->s_bit); @@ -8104,7 +7779,7 @@ vl_api_ipfix_exporter_dump_t_handler (vl_api_ipfix_exporter_dump_t * mp) if (frm->fib_index == ~0) vrf_id = ~0; else - vrf_id = im->fibs[frm->fib_index].table_id; + vrf_id = im->fibs[frm->fib_index].ft_table_id; rmp->vrf_id = htonl (vrf_id); rmp->path_mtu = htonl (frm->path_mtu); rmp->template_interval = htonl (frm->template_interval); diff --git a/vpp/vpp-api/custom_dump.c b/vpp/vpp-api/custom_dump.c index cc37368de10..98598ce3b77 100644 --- a/vpp/vpp-api/custom_dump.c +++ b/vpp/vpp-api/custom_dump.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -1413,6 +1413,9 @@ static void *vl_api_vxlan_add_del_tunnel_t_print s = format (s, "vni %d ", ntohl (mp->vni)); + if (mp->is_add == 0) + s = format (s, "del "); + if (mp->is_add == 0) s = format (s, "del "); diff --git a/vpp/vpp-api/vpe.api b/vpp/vpp-api/vpe.api index 2434517e8cc..5c75986f0c6 100644 --- a/vpp/vpp-api/vpe.api +++ b/vpp/vpp-api/vpe.api @@ -215,6 +215,30 @@ define sw_interface_set_table_reply i32 retval; }; +/** \brief Enable or Disable MPLS on and interface + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param sw_if_index - index of the interface + @param enable - if non-zero enable, else disable +*/ +define sw_interface_set_mpls_enable +{ + u32 client_index; + u32 context; + u32 sw_if_index; + u8 enable; +}; + +/** \brief Reply for MPLS state on an interface + @param context - returned sender context, to match reply w/ request + @param retval - return code +*/ +define sw_interface_set_mpls_enable_reply +{ + u32 context; + i32 retval; +}; + /** \brief Initialize a new tap interface with the given paramters @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @@ -381,8 +405,10 @@ define ip_add_del_route u8 is_ipv6; u8 is_local; u8 is_classify; - /* Is last/not-last message in group of multiple add/del messages. */ u8 is_multipath; + u8 is_resolve_host; + u8 is_resolve_attached; + /* Is last/not-last message in group of multiple add/del messages. */ u8 not_last; u8 next_hop_weight; u8 dst_address_length; diff --git a/vpp/vpp-api/vpp_get_metrics.c b/vpp/vpp-api/vpp_get_metrics.c index 19771e21832..bbfa605a5e4 100644 --- a/vpp/vpp-api/vpp_get_metrics.c +++ b/vpp/vpp-api/vpp_get_metrics.c @@ -243,3 +243,11 @@ main (int argc, char **argv) * eval: (c-set-style "gnu") * End: */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ -- cgit 1.2.3-korg