diff options
Diffstat (limited to 'src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c')
-rw-r--r-- | src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c | 1595 |
1 files changed, 0 insertions, 1595 deletions
diff --git a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c deleted file mode 100644 index 487ba246b4d..00000000000 --- a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c +++ /dev/null @@ -1,1595 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <vnet/lisp-gpe/lisp_gpe_fwd_entry.h> -#include <vnet/lisp-gpe/lisp_gpe_adjacency.h> -#include <vnet/lisp-gpe/lisp_gpe_tenant.h> -#include <vnet/lisp-cp/lisp_cp_dpo.h> -#include <vnet/fib/fib_table.h> -#include <vnet/fib/fib_entry.h> -#include <vnet/fib/fib_path_list.h> -#include <vnet/fib/ip6_fib.h> -#include <vnet/fib/ip4_fib.h> -#include <vnet/dpo/drop_dpo.h> -#include <vnet/dpo/lookup_dpo.h> -#include <vnet/dpo/load_balance.h> -#include <vnet/adj/adj_midchain.h> - -/** - * @brief Add route to IP4 or IP6 Destination FIB. - * - * Add a route to the destination FIB that results in the lookup - * in the SRC FIB. The SRC FIB is created is it does not yet exist. - * - * @param[in] dst_table_id Destination FIB Table-ID - * @param[in] dst_prefix Destination IP prefix. - * - * @return src_fib_index The index/ID of the SRC FIB created. - */ -static u32 -ip_dst_fib_add_route (u32 dst_fib_index, const ip_prefix_t * dst_prefix) -{ - fib_node_index_t src_fib_index; - fib_prefix_t dst_fib_prefix; - fib_node_index_t dst_fei; - - ASSERT (NULL != dst_prefix); - - ip_prefix_to_fib_prefix (dst_prefix, &dst_fib_prefix); - - /* - * lookup the destination prefix in the VRF table and retrieve the - * LISP associated data - */ - dst_fei = fib_table_lookup_exact_match (dst_fib_index, &dst_fib_prefix); - - /* - * If the FIB entry is not present, or not LISP sourced, add it - */ - if (dst_fei == FIB_NODE_INDEX_INVALID || - NULL == fib_entry_get_source_data (dst_fei, FIB_SOURCE_LISP)) - { - dpo_id_t src_lkup_dpo = DPO_INVALID; - - /* create a new src FIB. */ - src_fib_index = - fib_table_create_and_lock (dst_fib_prefix.fp_proto, - FIB_SOURCE_LISP, - "LISP-src for [%d,%U]", - dst_fib_index, - format_fib_prefix, &dst_fib_prefix); - /* - * add src fib default route - */ - fib_prefix_t prefix = { - .fp_proto = dst_fib_prefix.fp_proto, - }; - fib_table_entry_special_dpo_add (src_fib_index, &prefix, - FIB_SOURCE_LISP, - FIB_ENTRY_FLAG_EXCLUSIVE, - lisp_cp_dpo_get (fib_proto_to_dpo - (dst_fib_prefix.fp_proto))); - /* - * create a data-path object to perform the source address lookup - * in the SRC FIB - */ - lookup_dpo_add_or_lock_w_fib_index (src_fib_index, - (ip_prefix_version (dst_prefix) == - AF_IP6 ? DPO_PROTO_IP6 : - DPO_PROTO_IP4), - LOOKUP_UNICAST, - LOOKUP_INPUT_SRC_ADDR, - LOOKUP_TABLE_FROM_CONFIG, - &src_lkup_dpo); - - /* - * add the entry to the destination FIB that uses the lookup DPO - */ - dst_fei = fib_table_entry_special_dpo_add (dst_fib_index, - &dst_fib_prefix, - FIB_SOURCE_LISP, - FIB_ENTRY_FLAG_EXCLUSIVE, - &src_lkup_dpo); - - /* - * the DPO is locked by the FIB entry, and we have no further - * need for it. - */ - dpo_unlock (&src_lkup_dpo); - - /* - * save the SRC FIB index on the entry so we can retrieve it for - * subsequent routes. - */ - fib_entry_set_source_data (dst_fei, FIB_SOURCE_LISP, &src_fib_index); - } - else - { - /* - * destination FIB entry already present - */ - src_fib_index = *(u32 *) fib_entry_get_source_data (dst_fei, - FIB_SOURCE_LISP); - } - - return (src_fib_index); -} - -/** - * @brief Del route to IP4 or IP6 SD FIB. - * - * Remove routes from both destination and source FIBs. - * - * @param[in] src_fib_index The index/ID of the SRC FIB - * @param[in] src_prefix Source IP prefix. - * @param[in] dst_fib_index The index/ID of the DST FIB - * @param[in] dst_prefix Destination IP prefix. - */ -static void -ip_src_dst_fib_del_route (u32 src_fib_index, - const ip_prefix_t * src_prefix, - u32 dst_fib_index, const ip_prefix_t * dst_prefix) -{ - fib_prefix_t dst_fib_prefix, src_fib_prefix; - u8 have_default = 0; - u32 n_entries; - - ASSERT (NULL != dst_prefix); - ASSERT (NULL != src_prefix); - - ip_prefix_to_fib_prefix (dst_prefix, &dst_fib_prefix); - ip_prefix_to_fib_prefix (src_prefix, &src_fib_prefix); - - fib_table_entry_delete (src_fib_index, &src_fib_prefix, FIB_SOURCE_LISP); - - /* check if only default left or empty */ - fib_prefix_t default_pref = { - .fp_proto = dst_fib_prefix.fp_proto - }; - - if (fib_table_lookup_exact_match (src_fib_index, - &default_pref) != FIB_NODE_INDEX_INVALID) - have_default = 1; - - n_entries = fib_table_get_num_entries (src_fib_index, - src_fib_prefix.fp_proto, - FIB_SOURCE_LISP); - if (n_entries == 0 || (have_default && n_entries == 1)) - { - /* - * remove src FIB default route - */ - if (have_default) - fib_table_entry_special_remove (src_fib_index, &default_pref, - FIB_SOURCE_LISP); - - /* - * there's nothing left now, unlock the source FIB and the - * destination route - */ - fib_table_entry_special_remove (dst_fib_index, - &dst_fib_prefix, FIB_SOURCE_LISP); - fib_table_unlock (src_fib_index, src_fib_prefix.fp_proto, - FIB_SOURCE_LISP); - } -} - -/** - * @brief Add route to IP4 or IP6 SRC FIB. - * - * Adds a route to in the LISP SRC FIB with the result of the route - * being the DPO passed. - * - * @param[in] src_fib_index The index/ID of the SRC FIB - * @param[in] src_prefix Source IP prefix. - * @param[in] src_dpo The DPO the route will link to. - * - * @return fib index of the inserted prefix - */ -static fib_node_index_t -ip_src_fib_add_route_w_dpo (u32 src_fib_index, - const ip_prefix_t * src_prefix, - const dpo_id_t * src_dpo) -{ - fib_node_index_t fei = ~0; - fib_prefix_t src_fib_prefix; - - ip_prefix_to_fib_prefix (src_prefix, &src_fib_prefix); - - /* - * add the entry into the source fib. - */ - fib_node_index_t src_fei; - - src_fei = fib_table_lookup_exact_match (src_fib_index, &src_fib_prefix); - - if (FIB_NODE_INDEX_INVALID == src_fei || - !fib_entry_is_sourced (src_fei, FIB_SOURCE_LISP)) - { - fei = fib_table_entry_special_dpo_add (src_fib_index, - &src_fib_prefix, - FIB_SOURCE_LISP, - FIB_ENTRY_FLAG_EXCLUSIVE, - src_dpo); - } - return fei; -} - -static fib_route_path_t * -lisp_gpe_mk_fib_paths (const lisp_fwd_path_t * paths) -{ - const lisp_gpe_adjacency_t *ladj; - fib_route_path_t *rpaths = NULL; - fib_protocol_t fp; - u8 best_priority; - u32 ii; - - vec_validate (rpaths, vec_len (paths) - 1); - - best_priority = paths[0].priority; - - vec_foreach_index (ii, paths) - { - if (paths[0].priority != best_priority) - break; - - ladj = lisp_gpe_adjacency_get (paths[ii].lisp_adj); - - fp = ip_address_to_46 (&ladj->remote_rloc, &rpaths[ii].frp_addr); - - rpaths[ii].frp_proto = fib_proto_to_dpo (fp); - rpaths[ii].frp_sw_if_index = ladj->sw_if_index; - rpaths[ii].frp_weight = (paths[ii].weight ? paths[ii].weight : 1); - } - - ASSERT (0 != vec_len (rpaths)); - - return (rpaths); -} - -/** - * @brief Add route to IP4 or IP6 SRC FIB. - * - * Adds a route to in the LISP SRC FIB for the tunnel. - * - * @param[in] src_fib_index The index/ID of the SRC FIB - * @param[in] src_prefix Source IP prefix. - * @param[in] paths The paths from which to construct the - * load balance - */ -static fib_node_index_t -ip_src_fib_add_route (u32 src_fib_index, - const ip_prefix_t * src_prefix, - const lisp_fwd_path_t * paths) -{ - fib_prefix_t src_fib_prefix; - fib_route_path_t *rpaths; - - ip_prefix_to_fib_prefix (src_prefix, &src_fib_prefix); - - rpaths = lisp_gpe_mk_fib_paths (paths); - - fib_node_index_t fib_entry_index = - fib_table_entry_update (src_fib_index, &src_fib_prefix, FIB_SOURCE_LISP, - FIB_ENTRY_FLAG_NONE, rpaths); - vec_free (rpaths); - return fib_entry_index; -} - -static void -gpe_native_fwd_add_del_lfe (lisp_gpe_fwd_entry_t * lfe, u8 is_add) -{ - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - u8 found = 0, ip_version; - u32 *lfei, new_lfei; - ip_version = ip_prefix_version (&lfe->key->rmt.ippref); - - new_lfei = lfe - lgm->lisp_fwd_entry_pool; - vec_foreach (lfei, lgm->native_fwd_lfes[ip_version]) - { - lfe = pool_elt_at_index (lgm->lisp_fwd_entry_pool, lfei[0]); - if (lfei[0] == new_lfei) - { - found = 1; - break; - } - } - - if (is_add) - { - if (!found) - vec_add1 (lgm->native_fwd_lfes[ip_version], new_lfei); - } - else - { - if (found) - vec_del1 (lgm->native_fwd_lfes[ip_version], lfei[0]); - } -} - -static index_t -create_fib_entries (lisp_gpe_fwd_entry_t * lfe) -{ - fib_node_index_t fi; - fib_entry_t *fe; - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - dpo_proto_t dproto; - ip_prefix_t ippref; - fib_prefix_t fib_prefix; - u8 ip_version = ip_prefix_version (&lfe->key->rmt.ippref); - dproto = (ip_version == AF_IP4 ? DPO_PROTO_IP4 : DPO_PROTO_IP6); - - if (lfe->is_src_dst) - { - lfe->src_fib_index = ip_dst_fib_add_route (lfe->eid_fib_index, - &lfe->key->rmt.ippref); - memcpy (&ippref, &lfe->key->lcl.ippref, sizeof (ippref)); - } - else - { - lfe->src_fib_index = lfe->eid_fib_index; - memcpy (&ippref, &lfe->key->rmt.ippref, sizeof (ippref)); - } - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE == lfe->type) - { - dpo_id_t dpo = DPO_INVALID; - - switch (lfe->action) - { - case LISP_FORWARD_NATIVE: - /* TODO handle route overlaps with fib and default route */ - if (vec_len (lgm->native_fwd_rpath[ip_version])) - { - ip_prefix_to_fib_prefix (&lfe->key->rmt.ippref, &fib_prefix); - fi = fib_table_entry_update (lfe->eid_fib_index, &fib_prefix, - FIB_SOURCE_LISP, - FIB_ENTRY_FLAG_NONE, - lgm->native_fwd_rpath[ip_version]); - gpe_native_fwd_add_del_lfe (lfe, 1); - goto done; - } - case LISP_NO_ACTION: - /* TODO update timers? */ - case LISP_SEND_MAP_REQUEST: - /* insert tunnel that always sends map-request */ - dpo_copy (&dpo, lisp_cp_dpo_get (dproto)); - break; - case LISP_DROP: - /* for drop fwd entries, just add route, no need to add encap tunnel */ - dpo_copy (&dpo, drop_dpo_get (dproto)); - break; - } - fi = ip_src_fib_add_route_w_dpo (lfe->src_fib_index, &ippref, &dpo); - dpo_reset (&dpo); - } - else - { - fi = ip_src_fib_add_route (lfe->src_fib_index, &ippref, lfe->paths); - } -done: - fe = fib_entry_get (fi); - return fe->fe_lb.dpoi_index; -} - -static void -delete_fib_entries (lisp_gpe_fwd_entry_t * lfe) -{ - fib_prefix_t dst_fib_prefix; - - if (lfe->is_src_dst) - ip_src_dst_fib_del_route (lfe->src_fib_index, - &lfe->key->lcl.ippref, - lfe->eid_fib_index, &lfe->key->rmt.ippref); - else - { - ip_prefix_to_fib_prefix (&lfe->key->rmt.ippref, &dst_fib_prefix); - fib_table_entry_delete (lfe->src_fib_index, &dst_fib_prefix, - FIB_SOURCE_LISP); - gpe_native_fwd_add_del_lfe (lfe, 0); - } -} - -static lisp_gpe_fwd_entry_t * -find_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a, - lisp_gpe_fwd_entry_key_t * key) -{ - uword *p; - - clib_memset (key, 0, sizeof (*key)); - - if (GID_ADDR_IP_PREFIX == gid_address_type (&a->rmt_eid)) - { - /* - * the ip version of the source is not set to ip6 when the - * source is all zeros. force it. - */ - ip_prefix_version (&gid_address_ippref (&a->lcl_eid)) = - ip_prefix_version (&gid_address_ippref (&a->rmt_eid)); - } - - gid_to_dp_address (&a->rmt_eid, &key->rmt); - gid_to_dp_address (&a->lcl_eid, &key->lcl); - key->vni = a->vni; - - p = hash_get_mem (lgm->lisp_gpe_fwd_entries, key); - - if (NULL != p) - { - return (pool_elt_at_index (lgm->lisp_fwd_entry_pool, p[0])); - } - return (NULL); -} - -static int -lisp_gpe_fwd_entry_path_sort (void *a1, void *a2) -{ - lisp_fwd_path_t *p1 = a1, *p2 = a2; - - return (p1->priority - p2->priority); -} - -static void -lisp_gpe_fwd_entry_mk_paths (lisp_gpe_fwd_entry_t * lfe, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a) -{ - lisp_fwd_path_t *path; - u32 index; - - vec_validate (lfe->paths, vec_len (a->locator_pairs) - 1); - - vec_foreach_index (index, a->locator_pairs) - { - path = &lfe->paths[index]; - - path->priority = a->locator_pairs[index].priority; - path->weight = a->locator_pairs[index].weight; - - path->lisp_adj = - lisp_gpe_adjacency_find_or_create_and_lock (&a->locator_pairs - [index], - a->dp_table, lfe->key->vni); - } - vec_sort_with_function (lfe->paths, lisp_gpe_fwd_entry_path_sort); -} - -void -vnet_lisp_gpe_add_fwd_counters (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, - u32 fwd_entry_index) -{ - const lisp_gpe_adjacency_t *ladj; - lisp_fwd_path_t *path; - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - u8 *placeholder_elt; - lisp_gpe_fwd_entry_t *lfe; - lisp_gpe_fwd_entry_key_t fe_key; - lisp_stats_key_t key; - - lfe = find_fwd_entry (lgm, a, &fe_key); - - if (!lfe) - return; - - if (LISP_GPE_FWD_ENTRY_TYPE_NORMAL != lfe->type) - return; - - clib_memset (&key, 0, sizeof (key)); - key.fwd_entry_index = fwd_entry_index; - - vec_foreach (path, lfe->paths) - { - ladj = lisp_gpe_adjacency_get (path->lisp_adj); - key.tunnel_index = ladj->tunnel_index; - lisp_stats_key_t *key_copy = clib_mem_alloc (sizeof (*key_copy)); - memcpy (key_copy, &key, sizeof (*key_copy)); - pool_get (lgm->placeholder_stats_pool, placeholder_elt); - hash_set_mem (lgm->lisp_stats_index_by_key, key_copy, - placeholder_elt - lgm->placeholder_stats_pool); - - vlib_validate_combined_counter (&lgm->counters, - placeholder_elt - - lgm->placeholder_stats_pool); - vlib_zero_combined_counter (&lgm->counters, - placeholder_elt - - lgm->placeholder_stats_pool); - } -} - -/** - * @brief Add/Delete LISP IP forwarding entry. - * - * creation of forwarding entries for IP LISP overlay: - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] a Parameters for building the forwarding entry. - * - * @return 0 on success. - */ -static int -add_ip_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a) -{ - lisp_gpe_fwd_entry_key_t key; - lisp_gpe_fwd_entry_t *lfe; - fib_protocol_t fproto; - - lfe = find_fwd_entry (lgm, a, &key); - - if (NULL != lfe) - /* don't support updates */ - return VNET_API_ERROR_INVALID_VALUE; - - pool_get (lgm->lisp_fwd_entry_pool, lfe); - clib_memset (lfe, 0, sizeof (*lfe)); - lfe->key = clib_mem_alloc (sizeof (key)); - memcpy (lfe->key, &key, sizeof (key)); - - hash_set_mem (lgm->lisp_gpe_fwd_entries, lfe->key, - lfe - lgm->lisp_fwd_entry_pool); - a->fwd_entry_index = lfe - lgm->lisp_fwd_entry_pool; - - fproto = (AF_IP4 == ip_prefix_version (&fid_addr_ippref (&lfe->key->rmt)) ? - FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6); - - lfe->type = (a->is_negative ? - LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE : - LISP_GPE_FWD_ENTRY_TYPE_NORMAL); - lfe->tenant = lisp_gpe_tenant_find_or_create (lfe->key->vni); - lfe->eid_table_id = a->table_id; - lfe->eid_fib_index = fib_table_find_or_create_and_lock (fproto, - lfe->eid_table_id, - FIB_SOURCE_LISP); - lfe->is_src_dst = a->is_src_dst; - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) - { - lisp_gpe_fwd_entry_mk_paths (lfe, a); - } - else - { - lfe->action = a->action; - } - - lfe->dpoi_index = create_fib_entries (lfe); - return (0); -} - -static void -del_ip_fwd_entry_i (lisp_gpe_main_t * lgm, lisp_gpe_fwd_entry_t * lfe) -{ - lisp_fwd_path_t *path; - fib_protocol_t fproto; - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) - { - vec_foreach (path, lfe->paths) - { - lisp_gpe_adjacency_unlock (path->lisp_adj); - } - } - - delete_fib_entries (lfe); - - fproto = (AF_IP4 == ip_prefix_version (&fid_addr_ippref (&lfe->key->rmt)) ? - FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6); - fib_table_unlock (lfe->eid_fib_index, fproto, FIB_SOURCE_LISP); - - hash_unset_mem (lgm->lisp_gpe_fwd_entries, lfe->key); - clib_mem_free (lfe->key); - pool_put (lgm->lisp_fwd_entry_pool, lfe); -} - -/** - * @brief Add/Delete LISP IP forwarding entry. - * - * removal of forwarding entries for IP LISP overlay: - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] a Parameters for building the forwarding entry. - * - * @return 0 on success. - */ -static int -del_ip_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a) -{ - lisp_gpe_fwd_entry_key_t key; - lisp_gpe_fwd_entry_t *lfe; - - lfe = find_fwd_entry (lgm, a, &key); - - if (NULL == lfe) - /* no such entry */ - return VNET_API_ERROR_INVALID_VALUE; - - del_ip_fwd_entry_i (lgm, lfe); - - return (0); -} - -static void -make_mac_fib_key (BVT (clib_bihash_kv) * kv, u16 bd_index, u8 src_mac[6], - u8 dst_mac[6]) -{ - kv->key[0] = (((u64) bd_index) << 48) | mac_to_u64 (dst_mac); - kv->key[1] = mac_to_u64 (src_mac); - kv->key[2] = 0; -} - -/** - * @brief Lookup L2 SD FIB entry - * - * Does a vni + dest + source lookup in the L2 LISP FIB. If the lookup fails - * it tries a second time with source set to 0 (i.e., a simple dest lookup). - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] bd_index Bridge domain index. - * @param[in] src_mac Source mac address. - * @param[in] dst_mac Destination mac address. - * - * @return index of mapping matching the lookup key. - */ -index_t -lisp_l2_fib_lookup (lisp_gpe_main_t * lgm, u16 bd_index, u8 src_mac[6], - u8 dst_mac[6]) -{ - int rv; - BVT (clib_bihash_kv) kv, value; - - make_mac_fib_key (&kv, bd_index, src_mac, dst_mac); - rv = BV (clib_bihash_search_inline_2) (&lgm->l2_fib, &kv, &value); - - /* no match, try with src 0, catch all for dst */ - if (rv != 0) - { - kv.key[1] = 0; - rv = BV (clib_bihash_search_inline_2) (&lgm->l2_fib, &kv, &value); - if (rv == 0) - return value.value; - } - else - return value.value; - - return lisp_gpe_main.l2_lb_cp_lkup.dpoi_index; -} - -/** - * @brief Add/del L2 SD FIB entry - * - * Inserts value in L2 FIB keyed by vni + dest + source. If entry is - * overwritten the associated value is returned. - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] bd_index Bridge domain index. - * @param[in] src_mac Source mac address. - * @param[in] dst_mac Destination mac address. - * @param[in] val Value to add. - * @param[in] is_add Add/del flag. - * - * @return ~0 or value of overwritten entry. - */ -static u32 -lisp_l2_fib_add_del_entry (u16 bd_index, u8 src_mac[6], - u8 dst_mac[6], const dpo_id_t * dpo, u8 is_add) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - BVT (clib_bihash_kv) kv, value; - u32 old_val = ~0; - - make_mac_fib_key (&kv, bd_index, src_mac, dst_mac); - - if (BV (clib_bihash_search) (&lgm->l2_fib, &kv, &value) == 0) - old_val = value.value; - - if (!is_add) - BV (clib_bihash_add_del) (&lgm->l2_fib, &kv, 0 /* is_add */ ); - else - { - kv.value = dpo->dpoi_index; - BV (clib_bihash_add_del) (&lgm->l2_fib, &kv, 1 /* is_add */ ); - } - return old_val; -} - -#define L2_FIB_DEFAULT_HASH_NUM_BUCKETS (64 * 1024) -#define L2_FIB_DEFAULT_HASH_MEMORY_SIZE (32<<20) - -static void -l2_fib_init (lisp_gpe_main_t * lgm) -{ - index_t lbi; - - BV (clib_bihash_init) (&lgm->l2_fib, "l2 fib", - 1 << max_log2 (L2_FIB_DEFAULT_HASH_NUM_BUCKETS), - L2_FIB_DEFAULT_HASH_MEMORY_SIZE); - - /* - * the result from a 'miss' in a L2 Table - */ - lbi = load_balance_create (1, DPO_PROTO_ETHERNET, 0); - load_balance_set_bucket (lbi, 0, lisp_cp_dpo_get (DPO_PROTO_ETHERNET)); - - dpo_set (&lgm->l2_lb_cp_lkup, DPO_LOAD_BALANCE, DPO_PROTO_ETHERNET, lbi); -} - -static void -del_l2_fwd_entry_i (lisp_gpe_main_t * lgm, lisp_gpe_fwd_entry_t * lfe) -{ - lisp_fwd_path_t *path; - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) - { - vec_foreach (path, lfe->paths) - { - lisp_gpe_adjacency_unlock (path->lisp_adj); - } - fib_path_list_child_remove (lfe->l2.path_list_index, - lfe->l2.child_index); - } - - lisp_l2_fib_add_del_entry (lfe->l2.eid_bd_index, - fid_addr_mac (&lfe->key->lcl), - fid_addr_mac (&lfe->key->rmt), NULL, 0); - - hash_unset_mem (lgm->lisp_gpe_fwd_entries, lfe->key); - clib_mem_free (lfe->key); - pool_put (lgm->lisp_fwd_entry_pool, lfe); -} - -/** - * @brief Delete LISP L2 forwarding entry. - * - * Coordinates the removal of forwarding entries for L2 LISP overlay: - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] a Parameters for building the forwarding entry. - * - * @return 0 on success. - */ -static int -del_l2_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a) -{ - lisp_gpe_fwd_entry_key_t key; - lisp_gpe_fwd_entry_t *lfe; - - lfe = find_fwd_entry (lgm, a, &key); - - if (NULL == lfe) - return VNET_API_ERROR_INVALID_VALUE; - - del_l2_fwd_entry_i (lgm, lfe); - - return (0); -} - -/** - * @brief Construct and insert the forwarding information used by an L2 entry - */ -static void -lisp_gpe_l2_update_fwding (lisp_gpe_fwd_entry_t * lfe) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - dpo_id_t dpo = DPO_INVALID; - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) - { - fib_path_list_contribute_forwarding (lfe->l2.path_list_index, - FIB_FORW_CHAIN_TYPE_ETHERNET, - FIB_PATH_LIST_FWD_FLAG_NONE, - &lfe->l2.dpo); - dpo_copy (&dpo, &lfe->l2.dpo); - } - else - { - switch (lfe->action) - { - case SEND_MAP_REQUEST: - dpo_copy (&dpo, &lgm->l2_lb_cp_lkup); - break; - case NO_ACTION: - case FORWARD_NATIVE: - case DROP: - dpo_copy (&dpo, drop_dpo_get (DPO_PROTO_ETHERNET)); - } - } - - /* add entry to l2 lisp fib */ - lisp_l2_fib_add_del_entry (lfe->l2.eid_bd_index, - fid_addr_mac (&lfe->key->lcl), - fid_addr_mac (&lfe->key->rmt), &dpo, 1); - lfe->dpoi_index = dpo.dpoi_index; - - dpo_reset (&dpo); -} - -/** - * @brief Add LISP L2 forwarding entry. - * - * Coordinates the creation of forwarding entries for L2 LISP overlay: - * creates lisp-gpe tunnel and injects new entry in Source/Dest L2 FIB. - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] a Parameters for building the forwarding entry. - * - * @return 0 on success. - */ -static int -add_l2_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a) -{ - lisp_gpe_fwd_entry_key_t key; - bd_main_t *bdm = &bd_main; - lisp_gpe_fwd_entry_t *lfe; - uword *bd_indexp; - - bd_indexp = hash_get (bdm->bd_index_by_bd_id, a->bd_id); - if (!bd_indexp) - { - clib_warning ("bridge domain %d doesn't exist", a->bd_id); - return -1; - } - - lfe = find_fwd_entry (lgm, a, &key); - - if (NULL != lfe) - /* don't support updates */ - return VNET_API_ERROR_INVALID_VALUE; - - pool_get (lgm->lisp_fwd_entry_pool, lfe); - clib_memset (lfe, 0, sizeof (*lfe)); - lfe->key = clib_mem_alloc (sizeof (key)); - memcpy (lfe->key, &key, sizeof (key)); - - hash_set_mem (lgm->lisp_gpe_fwd_entries, lfe->key, - lfe - lgm->lisp_fwd_entry_pool); - a->fwd_entry_index = lfe - lgm->lisp_fwd_entry_pool; - - lfe->type = (a->is_negative ? - LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE : - LISP_GPE_FWD_ENTRY_TYPE_NORMAL); - lfe->l2.eid_bd_id = a->bd_id; - lfe->l2.eid_bd_index = bd_indexp[0]; - lfe->tenant = lisp_gpe_tenant_find_or_create (lfe->key->vni); - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) - { - fib_route_path_t *rpaths; - - /* - * Make the sorted array of LISP paths with their resp. adjacency - */ - lisp_gpe_fwd_entry_mk_paths (lfe, a); - - /* - * From the LISP paths, construct a FIB path list that will - * contribute a load-balance. - */ - rpaths = lisp_gpe_mk_fib_paths (lfe->paths); - - lfe->l2.path_list_index = - fib_path_list_create (FIB_PATH_LIST_FLAG_NONE, rpaths); - - /* - * become a child of the path-list so we receive updates when - * its forwarding state changes. this includes an implicit lock. - */ - lfe->l2.child_index = - fib_path_list_child_add (lfe->l2.path_list_index, - FIB_NODE_TYPE_LISP_GPE_FWD_ENTRY, - lfe - lgm->lisp_fwd_entry_pool); - } - else - { - lfe->action = a->action; - } - - lisp_gpe_l2_update_fwding (lfe); - - return 0; -} - -/** - * @brief Lookup NSH SD FIB entry - * - * Does an SPI+SI lookup in the NSH LISP FIB. - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] spi_si SPI + SI. - * - * @return next node index. - */ -const dpo_id_t * -lisp_nsh_fib_lookup (lisp_gpe_main_t * lgm, u32 spi_si_net_order) -{ - int rv; - BVT (clib_bihash_kv) kv, value; - - clib_memset (&kv, 0, sizeof (kv)); - kv.key[0] = spi_si_net_order; - rv = BV (clib_bihash_search_inline_2) (&lgm->nsh_fib, &kv, &value); - - if (rv != 0) - { - return lgm->nsh_cp_lkup; - } - else - { - lisp_gpe_fwd_entry_t *lfe; - lfe = pool_elt_at_index (lgm->lisp_fwd_entry_pool, value.value); - return &lfe->nsh.choice; - } -} - -/** - * @brief Add/del NSH FIB entry - * - * Inserts value in NSH FIB keyed by SPI+SI. If entry is - * overwritten the associated value is returned. - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] spi_si SPI + SI. - * @param[in] dpo Load balanced mapped to SPI + SI - * - * @return ~0 or value of overwritten entry. - */ -static u32 -lisp_nsh_fib_add_del_entry (u32 spi_si_host_order, u32 lfei, u8 is_add) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - BVT (clib_bihash_kv) kv, value; - u32 old_val = ~0; - - clib_memset (&kv, 0, sizeof (kv)); - kv.key[0] = clib_host_to_net_u32 (spi_si_host_order); - kv.value = 0ULL; - - if (BV (clib_bihash_search) (&lgm->nsh_fib, &kv, &value) == 0) - old_val = value.value; - - if (!is_add) - BV (clib_bihash_add_del) (&lgm->nsh_fib, &kv, 0 /* is_add */ ); - else - { - kv.value = lfei; - BV (clib_bihash_add_del) (&lgm->nsh_fib, &kv, 1 /* is_add */ ); - } - return old_val; -} - -#define NSH_FIB_DEFAULT_HASH_NUM_BUCKETS (64 * 1024) -#define NSH_FIB_DEFAULT_HASH_MEMORY_SIZE (32<<20) - -static void -nsh_fib_init (lisp_gpe_main_t * lgm) -{ - BV (clib_bihash_init) (&lgm->nsh_fib, "nsh fib", - 1 << max_log2 (NSH_FIB_DEFAULT_HASH_NUM_BUCKETS), - NSH_FIB_DEFAULT_HASH_MEMORY_SIZE); - - /* - * the result from a 'miss' in a NSH Table - */ - lgm->nsh_cp_lkup = lisp_cp_dpo_get (DPO_PROTO_NSH); -} - -static void -del_nsh_fwd_entry_i (lisp_gpe_main_t * lgm, lisp_gpe_fwd_entry_t * lfe) -{ - lisp_fwd_path_t *path; - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) - { - vec_foreach (path, lfe->paths) - { - lisp_gpe_adjacency_unlock (path->lisp_adj); - } - fib_path_list_child_remove (lfe->nsh.path_list_index, - lfe->nsh.child_index); - dpo_reset (&lfe->nsh.choice); - } - - lisp_nsh_fib_add_del_entry (fid_addr_nsh (&lfe->key->rmt), (u32) ~ 0, 0); - - hash_unset_mem (lgm->lisp_gpe_fwd_entries, lfe->key); - clib_mem_free (lfe->key); - pool_put (lgm->lisp_fwd_entry_pool, lfe); -} - -/** - * @brief Delete LISP NSH forwarding entry. - * - * Coordinates the removal of forwarding entries for NSH LISP overlay: - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] a Parameters for building the forwarding entry. - * - * @return 0 on success. - */ -static int -del_nsh_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a) -{ - lisp_gpe_fwd_entry_key_t key; - lisp_gpe_fwd_entry_t *lfe; - - lfe = find_fwd_entry (lgm, a, &key); - - if (NULL == lfe) - return VNET_API_ERROR_INVALID_VALUE; - - del_nsh_fwd_entry_i (lgm, lfe); - - return (0); -} - -/** - * @brief Construct and insert the forwarding information used by an NSH entry - */ -static void -lisp_gpe_nsh_update_fwding (lisp_gpe_fwd_entry_t * lfe) -{ - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - dpo_id_t dpo = DPO_INVALID; - vnet_hw_interface_t *hi; - uword *hip; - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) - { - fib_path_list_contribute_forwarding (lfe->nsh.path_list_index, - FIB_FORW_CHAIN_TYPE_NSH, - FIB_PATH_LIST_FWD_FLAG_NONE, - &lfe->nsh.dpo); - - /* - * LISP encap is always the same for this SPI+SI so we do that hash now - * and stack on the choice. - */ - if (DPO_LOAD_BALANCE == lfe->nsh.dpo.dpoi_type) - { - const dpo_id_t *tmp; - const load_balance_t *lb; - int hash; - - lb = load_balance_get (lfe->nsh.dpo.dpoi_index); - hash = fid_addr_nsh (&lfe->key->rmt) % lb->lb_n_buckets; - tmp = - load_balance_get_bucket_i (lb, hash & lb->lb_n_buckets_minus_1); - - dpo_copy (&dpo, tmp); - } - } - else - { - switch (lfe->action) - { - case SEND_MAP_REQUEST: - dpo_copy (&dpo, lgm->nsh_cp_lkup); - break; - case NO_ACTION: - case FORWARD_NATIVE: - case DROP: - dpo_copy (&dpo, drop_dpo_get (DPO_PROTO_NSH)); - } - } - - /* We have only one nsh-lisp interface (no NSH virtualization) */ - hip = hash_get (lgm->nsh_ifaces.hw_if_index_by_dp_table, 0); - if (hip) - { - hi = vnet_get_hw_interface (lgm->vnet_main, hip[0]); - dpo_stack_from_node (hi->tx_node_index, &lfe->nsh.choice, &dpo); - } - /* add entry to nsh lisp fib */ - lisp_nsh_fib_add_del_entry (fid_addr_nsh (&lfe->key->rmt), - lfe - lgm->lisp_fwd_entry_pool, 1); - dpo_reset (&dpo); - -} - -/** - * @brief Add LISP NSH forwarding entry. - * - * Coordinates the creation of forwarding entries for L2 LISP overlay: - * creates lisp-gpe tunnel and injects new entry in Source/Dest L2 FIB. - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] a Parameters for building the forwarding entry. - * - * @return 0 on success. - */ -static int -add_nsh_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a) -{ - lisp_gpe_fwd_entry_key_t key; - lisp_gpe_fwd_entry_t *lfe; - - lfe = find_fwd_entry (lgm, a, &key); - - if (NULL != lfe) - /* don't support updates */ - return VNET_API_ERROR_INVALID_VALUE; - - pool_get (lgm->lisp_fwd_entry_pool, lfe); - clib_memset (lfe, 0, sizeof (*lfe)); - lfe->key = clib_mem_alloc (sizeof (key)); - memcpy (lfe->key, &key, sizeof (key)); - - hash_set_mem (lgm->lisp_gpe_fwd_entries, lfe->key, - lfe - lgm->lisp_fwd_entry_pool); - a->fwd_entry_index = lfe - lgm->lisp_fwd_entry_pool; - - lfe->type = (a->is_negative ? - LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE : - LISP_GPE_FWD_ENTRY_TYPE_NORMAL); - lfe->tenant = 0; - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) - { - fib_route_path_t *rpaths; - - /* - * Make the sorted array of LISP paths with their resp. adjacency - */ - lisp_gpe_fwd_entry_mk_paths (lfe, a); - - /* - * From the LISP paths, construct a FIB path list that will - * contribute a load-balance. - */ - rpaths = lisp_gpe_mk_fib_paths (lfe->paths); - - lfe->nsh.path_list_index = - fib_path_list_create (FIB_PATH_LIST_FLAG_NONE, rpaths); - - /* - * become a child of the path-list so we receive updates when - * its forwarding state changes. this includes an implicit lock. - */ - lfe->nsh.child_index = - fib_path_list_child_add (lfe->nsh.path_list_index, - FIB_NODE_TYPE_LISP_GPE_FWD_ENTRY, - lfe - lgm->lisp_fwd_entry_pool); - } - else - { - lfe->action = a->action; - } - - lisp_gpe_nsh_update_fwding (lfe); - - return 0; -} - -/** - * @brief conver from the embedded fib_node_t struct to the LSIP entry - */ -static lisp_gpe_fwd_entry_t * -lisp_gpe_fwd_entry_from_fib_node (fib_node_t * node) -{ - return ((lisp_gpe_fwd_entry_t *) (((char *) node) - - STRUCT_OFFSET_OF (lisp_gpe_fwd_entry_t, - node))); -} - -/** - * @brief Function invoked during a backwalk of the FIB graph - */ -static fib_node_back_walk_rc_t -lisp_gpe_fib_node_back_walk (fib_node_t * node, - fib_node_back_walk_ctx_t * ctx) -{ - lisp_gpe_fwd_entry_t *lfe = lisp_gpe_fwd_entry_from_fib_node (node); - - if (fid_addr_type (&lfe->key->rmt) == FID_ADDR_MAC) - lisp_gpe_l2_update_fwding (lfe); - else if (fid_addr_type (&lfe->key->rmt) == FID_ADDR_NSH) - lisp_gpe_nsh_update_fwding (lfe); - - return (FIB_NODE_BACK_WALK_CONTINUE); -} - -/** - * @brief Get a fib_node_t struct from the index of a LISP fwd entry - */ -static fib_node_t * -lisp_gpe_fwd_entry_get_fib_node (fib_node_index_t index) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - lisp_gpe_fwd_entry_t *lfe; - - lfe = pool_elt_at_index (lgm->lisp_fwd_entry_pool, index); - - return (&(lfe->node)); -} - -/** - * @brief An indication from the graph that the last lock has gone - */ -static void -lisp_gpe_fwd_entry_fib_node_last_lock_gone (fib_node_t * node) -{ - /* We don't manage the locks of the LISP objects via the graph, since - * this object has no children. so this is a no-op. */ -} - -/** - * @brief Virtual function table to register with FIB for the LISP type - */ -const static fib_node_vft_t lisp_fwd_vft = { - .fnv_get = lisp_gpe_fwd_entry_get_fib_node, - .fnv_last_lock = lisp_gpe_fwd_entry_fib_node_last_lock_gone, - .fnv_back_walk = lisp_gpe_fib_node_back_walk, -}; - -/** - * @brief Forwarding entry create/remove dispatcher. - * - * Calls l2 or l3 forwarding entry add/del function based on input data. - * - * @param[in] a Forwarding entry parameters. - * @param[out] hw_if_indexp NOT USED - * - * @return 0 on success. - */ -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; - u8 type; - - if (vnet_lisp_gpe_enable_disable_status () == 0) - { - clib_warning ("LISP is disabled!"); - return VNET_API_ERROR_LISP_DISABLED; - } - - type = gid_address_type (&a->rmt_eid); - switch (type) - { - case GID_ADDR_IP_PREFIX: - if (a->is_add) - return add_ip_fwd_entry (lgm, a); - else - return del_ip_fwd_entry (lgm, a); - break; - case GID_ADDR_MAC: - if (a->is_add) - return add_l2_fwd_entry (lgm, a); - else - return del_l2_fwd_entry (lgm, a); - case GID_ADDR_NSH: - if (a->is_add) - return add_nsh_fwd_entry (lgm, a); - else - return del_nsh_fwd_entry (lgm, a); - default: - clib_warning ("Forwarding entries for type %d not supported!", type); - return -1; - } -} - -int -vnet_lisp_flush_stats (void) -{ - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - vlib_combined_counter_main_t *cm = &lgm->counters; - u32 i; - - if (cm->counters == NULL) - return 0; - - for (i = 0; i < vlib_combined_counter_n_counters (cm); i++) - vlib_zero_combined_counter (cm, i); - - return 0; -} - -static void -lisp_del_adj_stats (lisp_gpe_main_t * lgm, u32 fwd_entry_index, u32 ti) -{ - hash_pair_t *hp; - lisp_stats_key_t key; - void *key_copy; - uword *p; - u8 *s; - - clib_memset (&key, 0, sizeof (key)); - key.fwd_entry_index = fwd_entry_index; - key.tunnel_index = ti; - - p = hash_get_mem (lgm->lisp_stats_index_by_key, &key); - if (p) - { - s = pool_elt_at_index (lgm->placeholder_stats_pool, p[0]); - hp = hash_get_pair (lgm->lisp_stats_index_by_key, &key); - key_copy = (void *) (hp->key); - hash_unset_mem (lgm->lisp_stats_index_by_key, &key); - clib_mem_free (key_copy); - pool_put (lgm->placeholder_stats_pool, s); - } -} - -void -vnet_lisp_gpe_del_fwd_counters (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, - u32 fwd_entry_index) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - lisp_gpe_fwd_entry_key_t fe_key; - lisp_gpe_fwd_entry_t *lfe; - lisp_fwd_path_t *path; - const lisp_gpe_adjacency_t *ladj; - - lfe = find_fwd_entry (lgm, a, &fe_key); - if (!lfe) - return; - - if (LISP_GPE_FWD_ENTRY_TYPE_NORMAL != lfe->type) - return; - - vec_foreach (path, lfe->paths) - { - ladj = lisp_gpe_adjacency_get (path->lisp_adj); - lisp_del_adj_stats (lgm, fwd_entry_index, ladj->tunnel_index); - } -} - -/** - * @brief Flush all the forwrding entries - */ -void -vnet_lisp_gpe_fwd_entry_flush (void) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - lisp_gpe_fwd_entry_t *lfe; - - /* *INDENT-OFF* */ - pool_foreach (lfe, lgm->lisp_fwd_entry_pool, - ({ - switch (fid_addr_type(&lfe->key->rmt)) - { - case FID_ADDR_MAC: - del_l2_fwd_entry_i (lgm, lfe); - break; - case FID_ADDR_IP_PREF: - del_ip_fwd_entry_i (lgm, lfe); - break; - case FID_ADDR_NSH: - del_nsh_fwd_entry_i (lgm, lfe); - break; - } - })); - /* *INDENT-ON* */ -} - -static u8 * -format_lisp_fwd_path (u8 * s, va_list * ap) -{ - lisp_fwd_path_t *lfp = va_arg (*ap, lisp_fwd_path_t *); - - s = format (s, "weight:%d ", lfp->weight); - s = format (s, "adj:[%U]\n", - format_lisp_gpe_adjacency, - lisp_gpe_adjacency_get (lfp->lisp_adj), - LISP_GPE_ADJ_FORMAT_FLAG_NONE); - - return (s); -} - -typedef enum lisp_gpe_fwd_entry_format_flag_t_ -{ - LISP_GPE_FWD_ENTRY_FORMAT_NONE = (0 << 0), - LISP_GPE_FWD_ENTRY_FORMAT_DETAIL = (1 << 1), -} lisp_gpe_fwd_entry_format_flag_t; - - -static u8 * -format_lisp_gpe_fwd_entry (u8 * s, va_list * ap) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - lisp_gpe_fwd_entry_t *lfe = va_arg (*ap, lisp_gpe_fwd_entry_t *); - lisp_gpe_fwd_entry_format_flag_t flags = - va_arg (*ap, lisp_gpe_fwd_entry_format_flag_t); - - s = format (s, "VNI:%d VRF:%d EID: %U -> %U [index:%d]", - lfe->key->vni, lfe->eid_table_id, - format_fid_address, &lfe->key->lcl, - format_fid_address, &lfe->key->rmt, - lfe - lgm->lisp_fwd_entry_pool); - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE == lfe->type) - { - s = format (s, "\n Negative - action:%U", - format_negative_mapping_action, lfe->action); - } - else - { - lisp_fwd_path_t *path; - - s = format (s, "\n via:"); - vec_foreach (path, lfe->paths) - { - s = format (s, "\n %U", format_lisp_fwd_path, path); - } - } - - if (flags & LISP_GPE_FWD_ENTRY_FORMAT_DETAIL) - { - switch (fid_addr_type (&lfe->key->rmt)) - { - case FID_ADDR_MAC: - s = format (s, " fib-path-list:%d\n", lfe->l2.path_list_index); - s = format (s, " dpo:%U\n", format_dpo_id, &lfe->l2.dpo, 0); - break; - case FID_ADDR_NSH: - s = format (s, " fib-path-list:%d\n", lfe->nsh.path_list_index); - s = format (s, " dpo:%U\n", format_dpo_id, &lfe->nsh.dpo, 0); - break; - case FID_ADDR_IP_PREF: - break; - } - } - - return (s); -} - -static clib_error_t * -lisp_gpe_fwd_entry_show (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - lisp_gpe_fwd_entry_t *lfe; - index_t index; - u32 vni = ~0; - - if (unformat (input, "vni %d", &vni)) - ; - else if (unformat (input, "%d", &index)) - { - if (!pool_is_free_index (lgm->lisp_fwd_entry_pool, index)) - { - lfe = pool_elt_at_index (lgm->lisp_fwd_entry_pool, index); - - vlib_cli_output (vm, "[%d@] %U", - index, - format_lisp_gpe_fwd_entry, lfe, - LISP_GPE_FWD_ENTRY_FORMAT_DETAIL); - } - else - { - vlib_cli_output (vm, "entry %d invalid", index); - } - - return (NULL); - } - - /* *INDENT-OFF* */ - pool_foreach (lfe, lgm->lisp_fwd_entry_pool, - ({ - if ((vni == ~0) || - (lfe->key->vni == vni)) - vlib_cli_output (vm, "%U", format_lisp_gpe_fwd_entry, lfe, - LISP_GPE_FWD_ENTRY_FORMAT_NONE); - })); - /* *INDENT-ON* */ - - return (NULL); -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_gpe_fwd_entry_show_command, static) = { - .path = "show gpe entry", - .short_help = "show gpe entry vni <vni> vrf <vrf> [leid <leid>] reid <reid>", - .function = lisp_gpe_fwd_entry_show, -}; -/* *INDENT-ON* */ - -clib_error_t * -lisp_gpe_fwd_entry_init (vlib_main_t * vm) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - clib_error_t *error = NULL; - - if ((error = vlib_call_init_function (vm, lisp_cp_dpo_module_init))) - return (error); - - l2_fib_init (lgm); - nsh_fib_init (lgm); - - fib_node_register_type (FIB_NODE_TYPE_LISP_GPE_FWD_ENTRY, &lisp_fwd_vft); - - return (error); -} - -u32 * -vnet_lisp_gpe_get_fwd_entry_vnis (void) -{ - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - lisp_gpe_fwd_entry_t *lfe; - u32 *vnis = 0; - - /* *INDENT-OFF* */ - pool_foreach (lfe, lgm->lisp_fwd_entry_pool, - ({ - hash_set (vnis, lfe->key->vni, 0); - })); - /* *INDENT-ON* */ - - return vnis; -} - -lisp_api_gpe_fwd_entry_t * -vnet_lisp_gpe_fwd_entries_get_by_vni (u32 vni) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - lisp_gpe_fwd_entry_t *lfe; - lisp_api_gpe_fwd_entry_t *entries = 0, e; - - /* *INDENT-OFF* */ - pool_foreach (lfe, lgm->lisp_fwd_entry_pool, - ({ - if (lfe->key->vni == vni) - { - clib_memset (&e, 0, sizeof (e)); - e.dp_table = lfe->eid_table_id; - e.vni = lfe->key->vni; - if (lfe->type == LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE) - e.action = lfe->action; - e.fwd_entry_index = lfe - lgm->lisp_fwd_entry_pool; - memcpy (&e.reid, &lfe->key->rmt, sizeof (e.reid)); - memcpy (&e.leid, &lfe->key->lcl, sizeof (e.leid)); - vec_add1 (entries, e); - } - })); - /* *INDENT-ON* */ - - return entries; -} - -int -vnet_lisp_gpe_get_fwd_stats (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, - vlib_counter_t * c) -{ - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - lisp_gpe_fwd_entry_t *lfe; - lisp_gpe_fwd_entry_key_t unused; - - lfe = find_fwd_entry (lgm, a, &unused); - if (NULL == lfe) - return -1; - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE == lfe->type) - return -1; - - if (~0 == lfe->dpoi_index) - return -1; - - vlib_get_combined_counter (&load_balance_main.lbm_to_counters, - lfe->dpoi_index, c); - return 0; -} - -VLIB_INIT_FUNCTION (lisp_gpe_fwd_entry_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ |