X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Ffib%2Ffib_entry_src.c;h=ec8c7393030ba74a15169ffd83a9c81c48d20686;hb=refs%2Fchanges%2F81%2F10781%2F7;hp=acb8579e85ebe55395a748490e7a46bfd5205e43;hpb=84517cfd1508f6da24937f310f7fffe752f22584;p=vpp.git diff --git a/src/vnet/fib/fib_entry_src.c b/src/vnet/fib/fib_entry_src.c index acb8579e85e..ec8c7393030 100644 --- a/src/vnet/fib/fib_entry_src.c +++ b/src/vnet/fib/fib_entry_src.c @@ -61,62 +61,13 @@ fib_entry_src_action_init (fib_entry_t *fib_entry, fib_entry_src_vft[source].fesv_init(&esrc); } - if (fib_entry_has_multiple_srcs(fib_entry)) - { - vec_add1(fib_entry->fe_u_src.fe_srcs, esrc); - - vec_sort_with_function(fib_entry->fe_u_src.fe_srcs, - fib_entry_src_cmp_for_sort); - } - else - { - /* - * is this the very first source - */ - if (FIB_SOURCE_INVALID == fib_entry->fe_u_src.fe_src.fes_src) - { - clib_memcpy(&fib_entry->fe_u_src.fe_src, &esrc, sizeof(esrc)); - } - else - { - /* - * transitioning to multiple sources. - * allocate the vecotr of sources. - */ - fib_entry_src_t *srcs = NULL; - - vec_validate(srcs, 1); - - /* - * sorted insert - */ - if (fib_entry->fe_u_src.fe_src.fes_src < esrc.fes_src) - { - srcs[0] = fib_entry->fe_u_src.fe_src; - srcs[1] = esrc; - } - else - { - srcs[0] = esrc; - srcs[1] = fib_entry->fe_u_src.fe_src; - } - memset(&fib_entry->fe_u_src.fe_src, 0, - sizeof(fib_entry->fe_u_src.fe_src)); - fib_entry->fe_u_src.fe_srcs = srcs; - - fib_entry->fe_node.fn_pad |= FIB_ENTRY_NODE_FLAG_MULTIPLE_SRCS; - } - } -} - -u32 -fib_entry_has_multiple_srcs(const fib_entry_t * fib_entry) -{ - return (fib_entry->fe_node.fn_pad & FIB_ENTRY_NODE_FLAG_MULTIPLE_SRCS); + vec_add1(fib_entry->fe_srcs, esrc); + vec_sort_with_function(fib_entry->fe_srcs, + fib_entry_src_cmp_for_sort); } static fib_entry_src_t * -fib_entry_src_find (fib_entry_t *fib_entry, +fib_entry_src_find (const fib_entry_t *fib_entry, fib_source_t source, u32 *index) @@ -125,80 +76,20 @@ fib_entry_src_find (fib_entry_t *fib_entry, int ii; ii = 0; - if (fib_entry_has_multiple_srcs(fib_entry)) + vec_foreach(esrc, fib_entry->fe_srcs) { - vec_foreach(esrc, fib_entry->fe_u_src.fe_srcs) - { - if (esrc->fes_src == source) - { - if (NULL != index) - { - *index = ii; - } - return (esrc); - } - else - { - ii++; - } - } - } - else - { - esrc = &fib_entry->fe_u_src.fe_src; - if (esrc->fes_src == source) - { - if (NULL != index) - { - *index = -1; - } - return (esrc); - } - } - - return (NULL); -} - -static fib_entry_src_t * -fib_entry_src_delete (fib_entry_t *fib_entry, - u32 index) - -{ - if (-1 == index) - { - ASSERT(!fib_entry_has_multiple_srcs(fib_entry)); - memset(&fib_entry->fe_u_src.fe_src, 0, - sizeof(fib_entry->fe_u_src.fe_src)); - } - else - { - vec_del1(fib_entry->fe_u_src.fe_srcs, index); - - ASSERT(vec_len(fib_entry->fe_u_src.fe_srcs)); - if (1 == vec_len(fib_entry->fe_u_src.fe_srcs)) - { - /* - * Is there much point in transitioning back? - * We've paid the cost of the malloc for the vector, - * why not keep it. - * Favour memory use. If the expectation that multiple sources - * is rare is correct, then we should expect this entry is - * unlikely to need the vector again - */ - fib_entry_src_t *srcs; - - srcs = fib_entry->fe_u_src.fe_srcs; - fib_entry->fe_node.fn_pad &= ~FIB_ENTRY_NODE_FLAG_MULTIPLE_SRCS; - clib_memcpy(&fib_entry->fe_u_src.fe_src, - &srcs[0], - sizeof(fib_entry->fe_u_src.fe_src)); - vec_free(srcs); - } - else - { - vec_sort_with_function(fib_entry->fe_u_src.fe_srcs, - fib_entry_src_cmp_for_sort); - } + if (esrc->fes_src == source) + { + if (NULL != index) + { + *index = ii; + } + return (esrc); + } + else + { + ii++; + } } return (NULL); @@ -249,7 +140,7 @@ fib_entry_src_action_deinit (fib_entry_t *fib_entry, } fib_path_ext_list_flush(&esrc->fes_path_exts); - fib_entry_src_delete(fib_entry, index); + vec_del1(fib_entry->fe_srcs, index); } fib_entry_src_cover_res_t @@ -321,6 +212,7 @@ static int fib_entry_src_valid_out_label (mpls_label_t label) { return ((MPLS_LABEL_IS_REAL(label) || + MPLS_LABEL_POP == label || MPLS_IETF_IPV4_EXPLICIT_NULL_LABEL == label || MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL == label || MPLS_IETF_IMPLICIT_NULL_LABEL == label)); @@ -439,6 +331,7 @@ fib_entry_src_get_path_forwarding (fib_node_index_t path_index, &nh->path_dpo); fib_path_stack_mpls_disp(path_index, fib_prefix_get_payload_proto(&ctx->fib_entry->fe_prefix), + FIB_MPLS_LSP_MODE_PIPE, &nh->path_dpo); break; @@ -500,7 +393,7 @@ fib_entry_src_collect_forwarding (fib_node_index_t pl_index, switch (path_ext->fpe_type) { case FIB_PATH_EXT_MPLS: - if (fib_entry_src_valid_out_label(path_ext->fpe_label_stack[0])) + if (fib_entry_src_valid_out_label(path_ext->fpe_label_stack[0].fml_value)) { /* * found a matching extension. stack it to obtain the forwarding @@ -762,6 +655,249 @@ fib_entry_recursive_loop_detect_i (fib_node_index_t path_list_index) vec_free(entries); } +/* + * fib_entry_src_action_copy + * + * copy a source data from another entry to this one + */ +fib_entry_t * +fib_entry_src_action_copy (fib_entry_t *fib_entry, + const fib_entry_src_t *orig_src) +{ + fib_entry_src_t *esrc; + + esrc = fib_entry_src_find_or_create(fib_entry, orig_src->fes_src); + + *esrc = *orig_src; + esrc->fes_ref_count = 1; + esrc->fes_flags |= FIB_ENTRY_SRC_FLAG_INHERITED; + esrc->fes_flags &= ~FIB_ENTRY_SRC_FLAG_ACTIVE; + esrc->fes_entry_flags &= ~FIB_ENTRY_FLAG_COVERED_INHERIT; + + /* + * the source owns a lock on the entry + */ + fib_path_list_lock(esrc->fes_pl); + fib_entry_lock(fib_entry_get_index(fib_entry)); + + return (fib_entry); +} + +/* + * fib_entry_src_action_update + * + * copy a source data from another entry to this one + */ +static fib_entry_src_t * +fib_entry_src_action_update_from_cover (fib_entry_t *fib_entry, + const fib_entry_src_t *orig_src) +{ + fib_entry_src_t *esrc; + + esrc = fib_entry_src_find_or_create(fib_entry, orig_src->fes_src); + + /* + * the source owns a lock on the entry + */ + fib_path_list_unlock(esrc->fes_pl); + esrc->fes_pl = orig_src->fes_pl; + fib_path_list_lock(esrc->fes_pl); + + return (esrc); +} + +static fib_table_walk_rc_t +fib_entry_src_covered_inherit_add_i (fib_entry_t *fib_entry, + const fib_entry_src_t *cover_src) +{ + fib_entry_src_t *esrc; + + esrc = fib_entry_src_find(fib_entry, cover_src->fes_src, NULL); + + if (cover_src == esrc) + { + return (FIB_TABLE_WALK_CONTINUE); + } + + if (NULL != esrc) + { + /* + * the covered entry already has this source. + */ + if (esrc->fes_entry_flags & FIB_ENTRY_FLAG_COVERED_INHERIT) + { + /* + * the covered source is itself a COVERED_INHERIT, i.e. + * it also pushes this source down the sub-tree. + * We consider this more specfic covered to be the owner + * of the sub-tree from this point down. + */ + return (FIB_TABLE_WALK_SUB_TREE_STOP); + } + if (esrc->fes_flags & FIB_ENTRY_SRC_FLAG_INHERITED) + { + /* + * The covered's source data has been inherited, presumably + * from this cover, i.e. this is a modify. + */ + esrc = fib_entry_src_action_update_from_cover(fib_entry, cover_src); + fib_entry_source_change(fib_entry, esrc->fes_src, esrc->fes_src); + } + else + { + /* + * The covered's source was not inherited and it is also + * not inherting. Nevertheless, it still owns the sub-tree from + * this point down. + */ + return (FIB_TABLE_WALK_SUB_TREE_STOP); + } + } + else + { + /* + * The covered does not have this source - add it. + */ + fib_source_t best_source; + + best_source = fib_entry_get_best_source( + fib_entry_get_index(fib_entry)); + + fib_entry_src_action_copy(fib_entry, cover_src); + fib_entry_source_change(fib_entry, best_source, cover_src->fes_src); + + } + return (FIB_TABLE_WALK_CONTINUE); +} + +static fib_table_walk_rc_t +fib_entry_src_covered_inherit_walk_add (fib_node_index_t fei, + void *ctx) +{ + return (fib_entry_src_covered_inherit_add_i(fib_entry_get(fei), ctx)); +} + +static fib_table_walk_rc_t +fib_entry_src_covered_inherit_walk_remove (fib_node_index_t fei, + void *ctx) +{ + fib_entry_src_t *cover_src, *esrc; + fib_entry_t *fib_entry; + + fib_entry = fib_entry_get(fei); + + cover_src = ctx; + esrc = fib_entry_src_find(fib_entry, cover_src->fes_src, NULL); + + if (cover_src == esrc) + { + return (FIB_TABLE_WALK_CONTINUE); + } + + if (NULL != esrc) + { + /* + * the covered entry already has this source. + */ + if (esrc->fes_entry_flags & FIB_ENTRY_FLAG_COVERED_INHERIT) + { + /* + * the covered source is itself a COVERED_INHERIT, i.e. + * it also pushes this source down the sub-tree. + * We consider this more specfic covered to be the owner + * of the sub-tree from this point down. + */ + return (FIB_TABLE_WALK_SUB_TREE_STOP); + } + if (esrc->fes_flags & FIB_ENTRY_SRC_FLAG_INHERITED) + { + /* + * The covered's source data has been inherited, presumably + * from this cover + */ + fib_entry_src_flag_t remaining; + + remaining = fib_entry_special_remove(fei, cover_src->fes_src); + + ASSERT(FIB_ENTRY_SRC_FLAG_ADDED == remaining); + } + else + { + /* + * The covered's source was not inherited and it is also + * not inherting. Nevertheless, it still owns the sub-tree from + * this point down. + */ + return (FIB_TABLE_WALK_SUB_TREE_STOP); + } + } + else + { + /* + * The covered does not have this source - that's an error, + * since it should have inherited, but there is nothing we can do + * about it now. + */ + } + return (FIB_TABLE_WALK_CONTINUE); +} + +void +fib_entry_src_inherit (const fib_entry_t *cover, + fib_entry_t *covered) +{ + CLIB_UNUSED(fib_source_t source); + const fib_entry_src_t *src; + + FOR_EACH_SRC_ADDED(cover, src, source, + ({ + if ((src->fes_entry_flags & FIB_ENTRY_FLAG_COVERED_INHERIT) || + (src->fes_flags & FIB_ENTRY_SRC_FLAG_INHERITED)) + { + fib_entry_src_covered_inherit_add_i(covered, src); + } + })) +} + +static void +fib_entry_src_covered_inherit_add (fib_entry_t *fib_entry, + fib_source_t source) + +{ + fib_entry_src_t *esrc; + + esrc = fib_entry_src_find(fib_entry, source, NULL); + + ASSERT(esrc->fes_flags & FIB_ENTRY_SRC_FLAG_ACTIVE); + + if ((esrc->fes_entry_flags & FIB_ENTRY_FLAG_COVERED_INHERIT) || + (esrc->fes_flags & FIB_ENTRY_SRC_FLAG_INHERITED)) + { + fib_table_sub_tree_walk(fib_entry->fe_fib_index, + fib_entry->fe_prefix.fp_proto, + &fib_entry->fe_prefix, + fib_entry_src_covered_inherit_walk_add, + esrc); + } +} + +static void +fib_entry_src_covered_inherit_remove (fib_entry_t *fib_entry, + fib_entry_src_t *esrc) + +{ + ASSERT(!(esrc->fes_flags & FIB_ENTRY_SRC_FLAG_ACTIVE)); + + if (esrc->fes_entry_flags & FIB_ENTRY_FLAG_COVERED_INHERIT) + { + fib_table_sub_tree_walk(fib_entry->fe_fib_index, + fib_entry->fe_prefix.fp_proto, + &fib_entry->fe_prefix, + fib_entry_src_covered_inherit_walk_remove, + esrc); + } +} + void fib_entry_src_action_activate (fib_entry_t *fib_entry, fib_source_t source) @@ -806,6 +942,11 @@ fib_entry_src_action_activate (fib_entry_t *fib_entry, FIB_ENTRY_DBG(fib_entry, "activate: %d", fib_entry->fe_parent); + /* + * If this source should push its state to covered prefixs, do that now. + */ + fib_entry_src_covered_inherit_add(fib_entry, source); + if (0 != houston_we_are_go_for_install) { fib_entry_src_action_install(fib_entry, source); @@ -837,6 +978,14 @@ fib_entry_src_action_deactivate (fib_entry_t *fib_entry, FIB_ENTRY_DBG(fib_entry, "deactivate: %d", fib_entry->fe_parent); + /* + * If this source should pull its state from covered prefixs, do that now. + * If this source also has the INHERITED flag set then it has a cover + * that wants to push down forwarding. We only want the covereds to see + * one update. + */ + fib_entry_src_covered_inherit_remove(fib_entry, esrc); + /* * un-link from an old path-list. Check for any loops this will clear */ @@ -852,6 +1001,23 @@ fib_entry_src_action_deactivate (fib_entry_t *fib_entry, fib_entry->fe_sibling = FIB_NODE_INDEX_INVALID; } +static void +fib_entry_src_action_fwd_update (const fib_entry_t *fib_entry, + fib_source_t source) +{ + fib_entry_src_t *esrc; + + vec_foreach(esrc, fib_entry->fe_srcs) + { + if (NULL != fib_entry_src_vft[esrc->fes_src].fesv_fwd_update) + { + fib_entry_src_vft[esrc->fes_src].fesv_fwd_update(esrc, + fib_entry, + source); + } + } +} + void fib_entry_src_action_reactivate (fib_entry_t *fib_entry, fib_source_t source) @@ -869,6 +1035,8 @@ fib_entry_src_action_reactivate (fib_entry_t *fib_entry, if (fib_entry->fe_parent != esrc->fes_pl) { + int remain_installed; + /* * un-link from an old path-list. Check for any loops this will clear */ @@ -902,12 +1070,37 @@ fib_entry_src_action_reactivate (fib_entry_t *fib_entry, fib_entry_recursive_loop_detect_i(fib_entry->fe_parent); fib_path_list_unlock(path_list_index); + + /* + * call the source to reactive and get the go/no-go to remain installed + */ + if (NULL != fib_entry_src_vft[source].fesv_reactivate) + { + remain_installed = + fib_entry_src_vft[source].fesv_reactivate(esrc, fib_entry); + } + else + { + remain_installed = 1; + } + + /* + * If this source should push its state to covered prefixs, do that now. + */ + fib_entry_src_covered_inherit_add(fib_entry, source); + + if (!remain_installed) + { + fib_entry_src_action_uninstall(fib_entry); + return; + } } fib_entry_src_action_install(fib_entry, source); + fib_entry_src_action_fwd_update(fib_entry, source); } void -fib_entry_src_action_installed (fib_entry_t *fib_entry, +fib_entry_src_action_installed (const fib_entry_t *fib_entry, fib_source_t source) { fib_entry_src_t *esrc; @@ -919,6 +1112,8 @@ fib_entry_src_action_installed (fib_entry_t *fib_entry, fib_entry_src_vft[source].fesv_installed(esrc, fib_entry); } + + fib_entry_src_action_fwd_update(fib_entry, source); } /* @@ -1000,7 +1195,9 @@ fib_entry_src_action_update (fib_entry_t *fib_entry, esrc = fib_entry_src_find_or_create(fib_entry, source); if (NULL == esrc) + { return (fib_entry_src_action_add(fib_entry, source, flags, dpo)); + } old_path_list_index = esrc->fes_pl; esrc->fes_entry_flags = flags; @@ -1029,6 +1226,60 @@ fib_entry_src_action_update (fib_entry_t *fib_entry, return (fib_entry); } +fib_entry_src_flag_t +fib_entry_src_action_remove_or_update_inherit (fib_entry_t *fib_entry, + fib_source_t source) +{ + fib_entry_src_t *esrc; + + esrc = fib_entry_src_find(fib_entry, source, NULL); + + if (NULL == esrc) + return (FIB_ENTRY_SRC_FLAG_ACTIVE); + + if ((esrc->fes_entry_flags & FIB_ENTRY_FLAG_COVERED_INHERIT) && + (esrc->fes_flags & FIB_ENTRY_SRC_FLAG_INHERITED)) + { + fib_entry_src_t *cover_src; + fib_node_index_t coveri; + fib_entry_t *cover; + + /* + * this source was pushing inherited state, but so is its + * cover. Now that this source is going away, we need to + * pull the covers forwarding and use it to update the covereds. + * Go grab the path-list from the cover, rather than start a walk from + * the cover, so we don't recursively update this entry. + */ + coveri = fib_table_get_less_specific(fib_entry->fe_fib_index, + &fib_entry->fe_prefix); + + /* + * only the default route has itself as its own cover, but the + * default route cannot have inherited from something else. + */ + ASSERT(coveri != fib_entry_get_index(fib_entry)); + + cover = fib_entry_get(coveri); + cover_src = fib_entry_src_find(cover, source, NULL); + + ASSERT(NULL != cover_src); + + esrc = fib_entry_src_action_update_from_cover(fib_entry, cover_src); + esrc->fes_entry_flags &= ~FIB_ENTRY_FLAG_COVERED_INHERIT; + + /* + * Now push the new state from the cover down to the covereds + */ + fib_entry_src_covered_inherit_add(fib_entry, source); + + return (esrc->fes_flags); + } + else + { + return (fib_entry_src_action_remove(fib_entry, source)); + } +} fib_entry_src_flag_t fib_entry_src_action_remove (fib_entry_t *fib_entry, @@ -1057,7 +1308,7 @@ fib_entry_src_action_remove (fib_entry_t *fib_entry, if (esrc->fes_flags & FIB_ENTRY_SRC_FLAG_ACTIVE) { - fib_entry_src_action_deactivate(fib_entry, source); + fib_entry_src_action_deactivate(fib_entry, source); } old_path_list = esrc->fes_pl; @@ -1103,10 +1354,7 @@ fib_route_attached_cross_table (const fib_entry_t *fib_entry, } /* - * fib_route_attached_cross_table - * - * Return true the the route is attached via an interface that - * is not in the same table as the route + * Return true if the path is attached */ static inline int fib_path_is_attached (const fib_route_path_t *rpath) @@ -1165,8 +1413,13 @@ fib_entry_flags_update (const fib_entry_t *fib_entry, { esrc->fes_entry_flags &= ~FIB_ENTRY_FLAG_ATTACHED; } + if (rpath->frp_flags & FIB_ROUTE_PATH_DEAG) + { + esrc->fes_entry_flags |= FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT; + } } - if (fib_route_attached_cross_table(fib_entry, rpath)) + if (fib_route_attached_cross_table(fib_entry, rpath) && + !(esrc->fes_entry_flags & FIB_ENTRY_FLAG_NO_ATTACHED_EXPORT)) { esrc->fes_entry_flags |= FIB_ENTRY_FLAG_IMPORT; } @@ -1269,6 +1522,10 @@ fib_entry_src_action_path_swap (fib_entry_t *fib_entry, fib_entry_get_dpo_proto(fib_entry))); esrc = fib_entry_src_find(fib_entry, source, NULL); } + else + { + esrc->fes_entry_flags = flags; + } /* * swapping paths may create a new path-list (or may use an existing shared) @@ -1342,7 +1599,7 @@ fib_entry_src_action_path_remove (fib_entry_t *fib_entry, /* * no more paths left from this source */ - fib_entry_src_action_remove(fib_entry, source); + fib_entry_src_action_remove_or_update_inherit(fib_entry, source); return (FIB_ENTRY_SRC_FLAG_NONE); } } @@ -1409,6 +1666,7 @@ fib_entry_get_dpo_for_source (fib_node_index_t fib_entry_index, fib_path_list_contribute_forwarding( esrc->fes_pl, fib_entry_get_default_chain_type(fib_entry), + FIB_PATH_LIST_FWD_FLAG_NONE, dpo); return (dpo_id_is_valid(dpo)); @@ -1457,6 +1715,29 @@ fib_entry_get_flags_for_source (fib_node_index_t entry_index, return (FIB_ENTRY_FLAG_NONE); } +fib_entry_flag_t +fib_entry_get_flags_i (const fib_entry_t *fib_entry) +{ + fib_entry_flag_t flags; + + /* + * the vector of sources is deliberately arranged in priority order + */ + if (0 == vec_len(fib_entry->fe_srcs)) + { + flags = FIB_ENTRY_FLAG_NONE; + } + else + { + fib_entry_src_t *esrc; + + esrc = vec_elt_at_index(fib_entry->fe_srcs, 0); + flags = esrc->fes_entry_flags; + } + + return (flags); +} + void fib_entry_set_source_data (fib_node_index_t fib_entry_index, fib_source_t source,