X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fip%2Fip6_neighbor.c;h=58b997aa0db04d03f4211cb0e4cde595b3fe1703;hb=0f26c5a0138ac86d7ebd197c31a09d8d624c35fe;hp=715891b81005af58f5036eabd33553f00ed21da3;hpb=3f844d0bc900e5db40ba74724e2b61e7943682d3;p=vpp.git diff --git a/src/vnet/ip/ip6_neighbor.c b/src/vnet/ip/ip6_neighbor.c index 715891b8100..58b997aa0db 100644 --- a/src/vnet/ip/ip6_neighbor.c +++ b/src/vnet/ip/ip6_neighbor.c @@ -235,6 +235,9 @@ format_ip6_neighbor_ip6_entry (u8 * s, va_list * va) if (n->flags & IP6_NEIGHBOR_FLAG_STATIC) flags = format (flags, "S"); + if (n->flags & IP6_NEIGHBOR_FLAG_NO_FIB_ENTRY) + flags = format (flags, "N"); + si = vnet_get_sw_interface (vnm, n->key.sw_if_index); s = format (s, "%=12U%=20U%=6s%=20U%=40U", format_vlib_cpu_time, vm, n->cpu_time_last_updated, @@ -317,6 +320,7 @@ typedef struct { u8 is_add; u8 is_static; + u8 is_no_fib_entry; u8 link_layer_address[6]; u32 sw_if_index; ip6_address_t addr; @@ -328,7 +332,8 @@ static void ip6_neighbor_set_unset_rpc_callback static void set_unset_ip6_neighbor_rpc (vlib_main_t * vm, u32 sw_if_index, - ip6_address_t * a, u8 * link_layer_address, int is_add, int is_static) + ip6_address_t * a, u8 * link_layer_address, int is_add, int is_static, + int is_no_fib_entry) { ip6_neighbor_set_unset_rpc_args_t args; void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length); @@ -336,6 +341,7 @@ static void set_unset_ip6_neighbor_rpc args.sw_if_index = sw_if_index; args.is_add = is_add; args.is_static = is_static; + args.is_no_fib_entry = is_no_fib_entry; clib_memcpy (&args.addr, a, sizeof (*a)); if (NULL != link_layer_address) clib_memcpy (args.link_layer_address, link_layer_address, 6); @@ -524,33 +530,34 @@ ip6_ethernet_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai) } break; case IP_LOOKUP_NEXT_MCAST: - /* - * Construct a partial rewrite from the known ethernet mcast dest MAC - */ - adj_mcast_update_rewrite - (ai, - ethernet_build_rewrite (vnm, - sw_if_index, - adj->ia_link, - ethernet_ip6_mcast_dst_addr ())); - - /* - * Complete the remaining fields of the adj's rewrite to direct the - * complete of the rewrite at switch time by copying in the IP - * dst address's bytes. - * Ofset is 12 bytes from the end of the MAC header - which is 2 - * bytes into the desintation address. And we write 4 bytes. - */ - adj->rewrite_header.dst_mcast_offset = 12; - adj->rewrite_header.dst_mcast_n_bytes = 4; - - break; + { + /* + * Construct a partial rewrite from the known ethernet mcast dest MAC + */ + u8 *rewrite; + u8 offset; + + rewrite = ethernet_build_rewrite (vnm, + sw_if_index, + adj->ia_link, + ethernet_ip6_mcast_dst_addr ()); + + /* + * Complete the remaining fields of the adj's rewrite to direct the + * complete of the rewrite at switch time by copying in the IP + * dst address's bytes. + * Ofset is 2 bytes into the desintation address. And we write 4 bytes. + */ + offset = vec_len (rewrite) - 2; + adj_mcast_update_rewrite (ai, rewrite, offset, 0xffffffff); + break; + } case IP_LOOKUP_NEXT_DROP: case IP_LOOKUP_NEXT_PUNT: case IP_LOOKUP_NEXT_LOCAL: case IP_LOOKUP_NEXT_REWRITE: - case IP_LOOKUP_NEXT_LOAD_BALANCE: + case IP_LOOKUP_NEXT_MCAST_MIDCHAIN: case IP_LOOKUP_NEXT_MIDCHAIN: case IP_LOOKUP_NEXT_ICMP_ERROR: case IP_LOOKUP_N_NEXT: @@ -565,7 +572,7 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm, ip6_address_t * a, u8 * link_layer_address, uword n_bytes_link_layer_address, - int is_static) + int is_static, int is_no_fib_entry) { ip6_neighbor_main_t *nm = &ip6_neighbor_main; ip6_neighbor_key_t k; @@ -575,10 +582,11 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm, u32 next_index; pending_resolution_t *pr, *mc; - if (os_get_cpu_number ()) + if (vlib_get_thread_index ()) { set_unset_ip6_neighbor_rpc (vm, sw_if_index, a, link_layer_address, - 1 /* set new neighbor */ , is_static); + 1 /* set new neighbor */ , is_static, + is_no_fib_entry); return 0; } @@ -598,16 +606,6 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm, if (make_new_nd_cache_entry) { - fib_prefix_t pfx = { - .fp_len = 128, - .fp_proto = FIB_PROTOCOL_IP6, - .fp_addr = { - .ip6 = k.ip6_address, - } - , - }; - u32 fib_index; - pool_get (nm->neighbor_pool, n); mhash_set (&nm->neighbor_index_by_key, &k, n - nm->neighbor_pool, /* old value */ 0); @@ -619,9 +617,25 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm, /* * create the adj-fib. the entry in the FIB table for and to the peer. */ - fib_index = ip6_main.fib_index_by_sw_if_index[n->key.sw_if_index]; - n->fib_entry_index = fib_table_entry_update_one_path (fib_index, &pfx, FIB_SOURCE_ADJ, FIB_ENTRY_FLAG_NONE, FIB_PROTOCOL_IP6, &pfx.fp_addr, n->key.sw_if_index, ~0, 1, NULL, // no label stack - FIB_ROUTE_PATH_FLAG_NONE); + if (!is_no_fib_entry) + { + fib_prefix_t pfx = { + .fp_len = 128, + .fp_proto = FIB_PROTOCOL_IP6, + .fp_addr.ip6 = k.ip6_address, + }; + u32 fib_index; + + fib_index = ip6_main.fib_index_by_sw_if_index[n->key.sw_if_index]; + n->fib_entry_index = + fib_table_entry_update_one_path (fib_index, &pfx, + FIB_SOURCE_ADJ, + FIB_ENTRY_FLAG_NONE, + FIB_PROTOCOL_IP6, &pfx.fp_addr, + n->key.sw_if_index, ~0, 1, NULL, + FIB_ROUTE_PATH_FLAG_NONE); + n->flags |= IP6_NEIGHBOR_FLAG_NO_FIB_ENTRY; + } } else { @@ -709,10 +723,10 @@ vnet_unset_ip6_ethernet_neighbor (vlib_main_t * vm, uword *p; int rv = 0; - if (os_get_cpu_number ()) + if (vlib_get_thread_index ()) { set_unset_ip6_neighbor_rpc (vm, sw_if_index, a, link_layer_address, - 0 /* unset */ , 0); + 0 /* unset */ , 0, 0); return 0; } @@ -746,7 +760,8 @@ static void ip6_neighbor_set_unset_rpc_callback vlib_main_t *vm = vlib_get_main (); if (a->is_add) vnet_set_ip6_ethernet_neighbor (vm, a->sw_if_index, &a->addr, - a->link_layer_address, 6, a->is_static); + a->link_layer_address, 6, a->is_static, + a->is_no_fib_entry); else vnet_unset_ip6_ethernet_neighbor (vm, a->sw_if_index, &a->addr, a->link_layer_address, 6); @@ -850,6 +865,7 @@ set_ip6_neighbor (vlib_main_t * vm, int addr_valid = 0; int is_del = 0; int is_static = 0; + int is_no_fib_entry = 0; u32 sw_if_index; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) @@ -865,6 +881,8 @@ set_ip6_neighbor (vlib_main_t * vm, is_del = 1; else if (unformat (input, "static")) is_static = 1; + else if (unformat (input, "no-fib-entry")) + is_no_fib_entry = 1; else break; } @@ -875,7 +893,7 @@ set_ip6_neighbor (vlib_main_t * vm, if (!is_del) vnet_set_ip6_ethernet_neighbor (vm, sw_if_index, &addr, mac_address, sizeof (mac_address), - is_static); + is_static, is_no_fib_entry); else vnet_unset_ip6_ethernet_neighbor (vm, sw_if_index, &addr, mac_address, sizeof (mac_address)); @@ -1023,7 +1041,7 @@ icmp6_neighbor_solicitation_or_advertisement (vlib_main_t * vm, &h0->target_address, o0->ethernet_address, sizeof (o0->ethernet_address), - 0); + 0, 0); } if (is_solicitation && error0 == ICMP6_ERROR_NONE) @@ -1338,7 +1356,7 @@ icmp6_router_solicitation (vlib_main_t * vm, &ip0->src_address, o0->ethernet_address, sizeof (o0->ethernet_address), - 0); + 0, 0); } /* default is to drop */ @@ -3892,76 +3910,59 @@ vnet_add_del_ip6_nd_change_event (vnet_main_t * vnm, { ip6_neighbor_main_t *nm = &ip6_neighbor_main; ip6_address_t *address = address_arg; - uword *p; + + /* Try to find an existing entry */ + u32 *first = (u32 *) mhash_get (&nm->mac_changes_by_address, address); + u32 *p = first; pending_resolution_t *mc; - void (*fp) (u32, u8 *) = data_callback; + while (p && *p != ~0) + { + mc = pool_elt_at_index (nm->mac_changes, *p); + if (mc->node_index == node_index && mc->type_opaque == type_opaque + && mc->pid == pid) + break; + p = &mc->next_index; + } + int found = p && *p != ~0; if (is_add) { - pool_get (nm->mac_changes, mc); + if (found) + return VNET_API_ERROR_ENTRY_ALREADY_EXISTS; - mc->next_index = ~0; - mc->node_index = node_index; - mc->type_opaque = type_opaque; - mc->data = data; - mc->data_callback = data_callback; - mc->pid = pid; + pool_get (nm->mac_changes, mc); + *mc = (pending_resolution_t) + { + .next_index = ~0,.node_index = node_index,.type_opaque = + type_opaque,.data = data,.data_callback = data_callback,.pid = + pid,}; - p = mhash_get (&nm->mac_changes_by_address, address); + /* Insert new resolution at the end of the list */ + u32 new_idx = mc - nm->mac_changes; if (p) - { - /* Insert new resolution at the head of the list */ - mc->next_index = p[0]; - mhash_unset (&nm->mac_changes_by_address, address, 0); - } - - mhash_set (&nm->mac_changes_by_address, address, - mc - nm->mac_changes, 0); - return 0; + p[0] = new_idx; + else + mhash_set (&nm->mac_changes_by_address, address, new_idx, 0); } else { - u32 index; - pending_resolution_t *mc_last = 0; - - p = mhash_get (&nm->mac_changes_by_address, address); - if (p == 0) + if (!found) return VNET_API_ERROR_NO_SUCH_ENTRY; - index = p[0]; + /* Clients may need to clean up pool entries, too */ + void (*fp) (u32, u8 *) = data_callback; + if (fp) + (*fp) (mc->data, 0 /* no new mac addrs */ ); - while (index != (u32) ~ 0) - { - mc = pool_elt_at_index (nm->mac_changes, index); - if (mc->node_index == node_index && - mc->type_opaque == type_opaque && mc->pid == pid) - { - /* Clients may need to clean up pool entries, too */ - if (fp) - (*fp) (mc->data, 0 /* no new mac addrs */ ); - if (index == p[0]) - { - mhash_unset (&nm->mac_changes_by_address, address, 0); - if (mc->next_index != ~0) - mhash_set (&nm->mac_changes_by_address, address, - mc->next_index, 0); - pool_put (nm->mac_changes, mc); - return 0; - } - else - { - ASSERT (mc_last); - mc_last->next_index = mc->next_index; - pool_put (nm->mac_changes, mc); - return 0; - } - } - mc_last = mc; - index = mc->next_index; - } + /* Remove the entry from the list and delete the entry */ + *p = mc->next_index; + pool_put (nm->mac_changes, mc); - return VNET_API_ERROR_NO_SUCH_ENTRY; + /* Remove from hash if we deleted the last entry */ + if (*p == ~0 && p == first) + mhash_unset (&nm->mac_changes_by_address, address, 0); } + return 0; } int @@ -3969,12 +3970,11 @@ vnet_ip6_nd_term (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_buffer_t * p0, ethernet_header_t * eth, - ip6_header_t * ip, u32 sw_if_index, u16 bd_index, u8 shg) + ip6_header_t * ip, u32 sw_if_index, u16 bd_index) { ip6_neighbor_main_t *nm = &ip6_neighbor_main; icmp6_neighbor_solicitation_or_advertisement_header_t *ndh; pending_resolution_t *mc; - uword *p; ndh = ip6_next_header (ip); if (ndh->icmp.type != ICMP6_neighbor_solicitation && @@ -3990,9 +3990,8 @@ vnet_ip6_nd_term (vlib_main_t * vm, } /* Check if anyone want ND events for L2 BDs */ - p = mhash_get (&nm->mac_changes_by_address, &ip6a_zero); - if (p && shg == 0 && /* Only SHG 0 interface which is more likely local */ - !ip6_address_is_link_local_unicast (&ip->src_address)) + uword *p = mhash_get (&nm->mac_changes_by_address, &ip6a_zero); + if (p && !ip6_address_is_link_local_unicast (&ip->src_address)) { u32 next_index = p[0]; while (next_index != (u32) ~ 0)