static void ip_del_adjacency2 (ip_lookup_main_t * lm, u32 adj_index, u32 delete_multipath_adjacency) { ip_adjacency_t * adj; uword handle; ip_call_add_del_adjacency_callbacks (lm, adj_index, /* is_del */ 1); adj = ip_get_adjacency (lm, adj_index); handle = adj->heap_handle; if (delete_multipath_adjacency) ip_multipath_del_adjacency (lm, adj_index); ip_poison_adjacencies (adj, adj->n_adj); heap_dealloc (lm->adjacency_heap, handle); }
static u32 ip_multipath_adjacency_get (ip_lookup_main_t * lm, ip_multipath_next_hop_t * raw_next_hops, uword create_if_non_existent) { uword * p; u32 i, j, n_adj, adj_index, adj_heap_handle; ip_adjacency_t * adj, * copy_adj; ip_multipath_next_hop_t * nh, * nhs; ip_multipath_adjacency_t * madj; n_adj = ip_multipath_normalize_next_hops (lm, raw_next_hops, &lm->next_hop_hash_lookup_key_normalized); nhs = lm->next_hop_hash_lookup_key_normalized; /* Basic sanity. */ ASSERT (n_adj >= vec_len (raw_next_hops)); /* Use normalized next hops to see if we've seen a block equivalent to this one before. */ p = hash_get_mem (lm->multipath_adjacency_by_next_hops, nhs); if (p) return p[0]; if (! create_if_non_existent) return 0; adj = ip_add_adjacency (lm, /* copy_adj */ 0, n_adj, &adj_index); adj_heap_handle = adj[0].heap_handle; /* Fill in adjacencies in block based on corresponding next hop adjacencies. */ i = 0; vec_foreach (nh, nhs) { copy_adj = ip_get_adjacency (lm, nh->next_hop_adj_index); for (j = 0; j < nh->weight; j++) { adj[i] = copy_adj[0]; adj[i].heap_handle = adj_heap_handle; adj[i].n_adj = n_adj; i++; } }
int vnet_lisp_gpe_add_del_fwd_entry (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, u32 * hw_if_indexp) { lisp_gpe_main_t * lgm = &lisp_gpe_main; ip_adjacency_t adj, * adjp; u32 adj_index, rv, tun_index = ~0; ip_prefix_t * dpref, * spref; uword * lookup_next_index, * lgpe_sw_if_index, * lnip; u8 ip_ver; if (vnet_lisp_gpe_enable_disable_status() == 0) { clib_warning ("LISP is disabled!"); return VNET_API_ERROR_LISP_DISABLED; } /* treat negative fwd entries separately */ if (a->is_negative) return add_del_negative_fwd_entry (lgm, a); dpref = &gid_address_ippref(&a->deid); spref = &gid_address_ippref(&a->seid); ip_ver = ip_prefix_version(dpref); /* add/del tunnel to tunnels pool and prepares rewrite */ rv = add_del_ip_tunnel (a, &tun_index); if (rv) return rv; /* setup adjacency for eid */ memset (&adj, 0, sizeof(adj)); adj.n_adj = 1; /* fill in lookup_next_index with a 'legal' value to avoid problems */ adj.lookup_next_index = (ip_ver == IP4) ? lgm->ip4_lookup_next_lgpe_ip4_lookup : lgm->ip6_lookup_next_lgpe_ip6_lookup; if (a->is_add) { /* send packets that hit this adj to lisp-gpe interface output node in * requested vrf. */ lnip = (ip_ver == IP4) ? lgm->lgpe_ip4_lookup_next_index_by_table_id : lgm->lgpe_ip6_lookup_next_index_by_table_id; lookup_next_index = hash_get(lnip, a->table_id); lgpe_sw_if_index = hash_get(lgm->tunnel_term_sw_if_index_by_vni, a->vni); /* the assumption is that the interface must've been created before * programming the dp */ ASSERT(lookup_next_index != 0); ASSERT(lgpe_sw_if_index != 0); /* hijack explicit fib index to store lisp interface node index and * if_address_index for the tunnel index */ adj.explicit_fib_index = lookup_next_index[0]; adj.if_address_index = tun_index; adj.rewrite_header.sw_if_index = lgpe_sw_if_index[0]; } /* add/delete route for prefix */ rv = ip_sd_fib_add_del_route (lgm, dpref, spref, a->table_id, &adj, a->is_add); /* check that everything worked */ if (CLIB_DEBUG && a->is_add) { adj_index = ip_sd_fib_get_route (lgm, dpref, spref, a->table_id); ASSERT(adj_index != 0); adjp = ip_get_adjacency ((ip_ver == IP4) ? lgm->lm4 : lgm->lm6, adj_index); ASSERT(adjp != 0); ASSERT(adjp->if_address_index == tun_index); } return rv; }