X-Git-Url: https://gerrit.fd.io/r/gitweb?p=vpp.git;a=blobdiff_plain;f=src%2Fvnet%2Flisp-gpe%2Flisp_gpe_fwd_entry.c;h=d31fdd7e799a76cca9e45af2ddd6a163e9f55ffa;hp=efa724e0d5b00e48cab22f90a6d740fdd6b41913;hb=282872127;hpb=25ad0ea266f03af1f4ec563a3de498bd49de6d61 diff --git a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c index efa724e0d5b..d31fdd7e799 100644 --- a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c +++ b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c @@ -66,6 +66,7 @@ ip_dst_fib_add_route (u32 dst_fib_index, const ip_prefix_t * dst_prefix) /* 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); @@ -86,8 +87,9 @@ ip_dst_fib_add_route (u32 dst_fib_index, const ip_prefix_t * dst_prefix) */ lookup_dpo_add_or_lock_w_fib_index (src_fib_index, (ip_prefix_version (dst_prefix) == - IP6 ? DPO_PROTO_IP6 : + AF_IP6 ? DPO_PROTO_IP6 : DPO_PROTO_IP4), + LOOKUP_UNICAST, LOOKUP_INPUT_SRC_ADDR, LOOKUP_TABLE_FROM_CONFIG, &src_lkup_dpo); @@ -179,7 +181,8 @@ ip_src_dst_fib_del_route (u32 src_fib_index, */ 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_table_unlock (src_fib_index, src_fib_prefix.fp_proto, + FIB_SOURCE_LISP); } } @@ -192,12 +195,15 @@ ip_src_dst_fib_del_route (u32 src_fib_index, * @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 void +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); @@ -212,11 +218,13 @@ ip_src_fib_add_route_w_dpo (u32 src_fib_index, if (FIB_NODE_INDEX_INVALID == src_fei || !fib_entry_is_sourced (src_fei, FIB_SOURCE_LISP)) { - fib_table_entry_special_dpo_add (src_fib_index, - &src_fib_prefix, - FIB_SOURCE_LISP, - FIB_ENTRY_FLAG_EXCLUSIVE, src_dpo); + 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 * @@ -224,6 +232,7 @@ 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; @@ -238,9 +247,9 @@ lisp_gpe_mk_fib_paths (const lisp_fwd_path_t * paths) ladj = lisp_gpe_adjacency_get (paths[ii].lisp_adj); - ip_address_to_46 (&ladj->remote_rloc, - &rpaths[ii].frp_addr, &rpaths[ii].frp_proto); + 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); } @@ -260,7 +269,7 @@ lisp_gpe_mk_fib_paths (const lisp_fwd_path_t * paths) * @param[in] paths The paths from which to construct the * load balance */ -static void +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) @@ -272,20 +281,55 @@ ip_src_fib_add_route (u32 src_fib_index, rpaths = lisp_gpe_mk_fib_paths (paths); - fib_table_entry_update (src_fib_index, - &src_fib_prefix, - FIB_SOURCE_LISP, FIB_ENTRY_FLAG_NONE, rpaths); + 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; - dproto = (ip_prefix_version (&lfe->key->rmt.ippref) == IP4 ? - DPO_PROTO_IP4 : DPO_PROTO_IP6); + 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) { @@ -305,11 +349,20 @@ create_fib_entries (lisp_gpe_fwd_entry_t * lfe) 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_FORWARD_NATIVE: - /* TODO check if route/next-hop for eid exists in fib and add - * more specific for the eid with the next-hop found */ case LISP_SEND_MAP_REQUEST: /* insert tunnel that always sends map-request */ dpo_copy (&dpo, lisp_cp_dpo_get (dproto)); @@ -319,13 +372,16 @@ create_fib_entries (lisp_gpe_fwd_entry_t * lfe) dpo_copy (&dpo, drop_dpo_get (dproto)); break; } - ip_src_fib_add_route_w_dpo (lfe->src_fib_index, &ippref, &dpo); + fi = ip_src_fib_add_route_w_dpo (lfe->src_fib_index, &ippref, &dpo); dpo_reset (&dpo); } else { - ip_src_fib_add_route (lfe->src_fib_index, &ippref, lfe->paths); + 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 @@ -342,6 +398,7 @@ delete_fib_entries (lisp_gpe_fwd_entry_t * lfe) 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); } } @@ -352,7 +409,7 @@ find_fwd_entry (lisp_gpe_main_t * lgm, { uword *p; - memset (key, 0, sizeof (*key)); + clib_memset (key, 0, sizeof (*key)); if (GID_ADDR_IP_PREFIX == gid_address_type (&a->rmt_eid)) { @@ -409,6 +466,46 @@ lisp_gpe_fwd_entry_mk_paths (lisp_gpe_fwd_entry_t * lfe, 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 *dummy_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->dummy_stats_pool, dummy_elt); + hash_set_mem (lgm->lisp_stats_index_by_key, key_copy, + dummy_elt - lgm->dummy_stats_pool); + + vlib_validate_combined_counter (&lgm->counters, + dummy_elt - lgm->dummy_stats_pool); + vlib_zero_combined_counter (&lgm->counters, + dummy_elt - lgm->dummy_stats_pool); + } +} + /** * @brief Add/Delete LISP IP forwarding entry. * @@ -434,14 +531,15 @@ add_ip_fwd_entry (lisp_gpe_main_t * lgm, return VNET_API_ERROR_INVALID_VALUE; pool_get (lgm->lisp_fwd_entry_pool, lfe); - memset (lfe, 0, sizeof (*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 = (IP4 == ip_prefix_version (&fid_addr_ippref (&lfe->key->rmt)) ? + fproto = (AF_IP4 == ip_prefix_version (&fid_addr_ippref (&lfe->key->rmt)) ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6); lfe->type = (a->is_negative ? @@ -450,15 +548,20 @@ add_ip_fwd_entry (lisp_gpe_main_t * lgm, 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); + 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; + } - create_fib_entries (lfe); + lfe->dpoi_index = create_fib_entries (lfe); return (0); } @@ -468,16 +571,19 @@ 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; - vec_foreach (path, lfe->paths) - { - lisp_gpe_adjacency_unlock (path->lisp_adj); - } + 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 = (IP4 == ip_prefix_version (&fid_addr_ippref (&lfe->key->rmt)) ? + 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_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); @@ -681,6 +787,7 @@ lisp_gpe_l2_update_fwding (lisp_gpe_fwd_entry_t * lfe) { 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); } @@ -702,6 +809,7 @@ lisp_gpe_l2_update_fwding (lisp_gpe_fwd_entry_t * lfe) 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); } @@ -740,12 +848,13 @@ add_l2_fwd_entry (lisp_gpe_main_t * lgm, return VNET_API_ERROR_INVALID_VALUE; pool_get (lgm->lisp_fwd_entry_pool, lfe); - memset (lfe, 0, sizeof (*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 : @@ -807,7 +916,7 @@ lisp_nsh_fib_lookup (lisp_gpe_main_t * lgm, u32 spi_si_net_order) int rv; BVT (clib_bihash_kv) kv, value; - memset (&kv, 0, sizeof (kv)); + 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); @@ -842,7 +951,7 @@ lisp_nsh_fib_add_del_entry (u32 spi_si_host_order, u32 lfei, u8 is_add) BVT (clib_bihash_kv) kv, value; u32 old_val = ~0; - memset (&kv, 0, sizeof (kv)); + clib_memset (&kv, 0, sizeof (kv)); kv.key[0] = clib_host_to_net_u32 (spi_si_host_order); kv.value = 0ULL; @@ -940,6 +1049,7 @@ lisp_gpe_nsh_update_fwding (lisp_gpe_fwd_entry_t * lfe) { fib_path_list_contribute_forwarding (lfe->nsh.path_list_index, FIB_FORW_CHAIN_TYPE_NSH, + FIB_PATH_LIST_FWD_FLAG_NONE, &lfe->nsh.dpo); /* @@ -1013,12 +1123,13 @@ add_nsh_fwd_entry (lisp_gpe_main_t * lgm, return VNET_API_ERROR_INVALID_VALUE; pool_get (lgm->lisp_fwd_entry_pool, lfe); - memset (lfe, 0, sizeof (*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 : @@ -1171,19 +1282,20 @@ vnet_lisp_gpe_add_del_fwd_entry (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, } } -void +int vnet_lisp_flush_stats (void) { lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - lisp_stats_t *stat; + vlib_combined_counter_main_t *cm = &lgm->counters; + u32 i; - /* *INDENT-OFF* */ - pool_foreach (stat, lgm->lisp_stats_pool, - { - stat->pkt_count = 0; - stat->bytes = 0; - }); - /* *INDENT-ON* */ + 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 @@ -1193,27 +1305,27 @@ lisp_del_adj_stats (lisp_gpe_main_t * lgm, u32 fwd_entry_index, u32 ti) lisp_stats_key_t key; void *key_copy; uword *p; - lisp_stats_t *s; + u8 *s; - memset (&key, 0, sizeof (key)); + 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->lisp_stats_pool, p[0]); + s = pool_elt_at_index (lgm->dummy_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->lisp_stats_pool, s); + pool_put (lgm->dummy_stats_pool, s); } } void -vnet_lisp_del_fwd_stats (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, - u32 fwd_entry_index) +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; @@ -1264,9 +1376,9 @@ vnet_lisp_gpe_fwd_entry_flush (void) } static u8 * -format_lisp_fwd_path (u8 * s, va_list ap) +format_lisp_fwd_path (u8 * s, va_list * ap) { - lisp_fwd_path_t *lfp = va_arg (ap, lisp_fwd_path_t *); + 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", @@ -1285,12 +1397,12 @@ typedef enum lisp_gpe_fwd_entry_format_flag_t_ static u8 * -format_lisp_gpe_fwd_entry (u8 * s, va_list ap) +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_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); + 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, @@ -1402,6 +1514,23 @@ lisp_gpe_fwd_entry_init (vlib_main_t * vm) 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) { @@ -1414,9 +1543,11 @@ vnet_lisp_gpe_fwd_entries_get_by_vni (u32 vni) ({ if (lfe->key->vni == vni) { - memset (&e, 0, sizeof (e)); + 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)); @@ -1428,6 +1559,29 @@ vnet_lisp_gpe_fwd_entries_get_by_vni (u32 vni) 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); /*