X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Ffib%2Ffib_entry_src.c;h=c79b745b5b5d1b3ac3c7a3f21da9f0c2c068039d;hb=58f37b21eace1c93ed5b20047cae4d0056cba376;hp=ad8b23e4af189b53db66c8bac3fabc0b579d89b2;hpb=6ede570259a91cd0c34b9faf9fec7e4ec8275200;p=vpp.git diff --git a/src/vnet/fib/fib_entry_src.c b/src/vnet/fib/fib_entry_src.c index ad8b23e4af1..c79b745b5b5 100644 --- a/src/vnet/fib/fib_entry_src.c +++ b/src/vnet/fib/fib_entry_src.c @@ -46,6 +46,7 @@ fib_entry_src_get_vft (const fib_entry_src_t *esrc) return (&fib_entry_src_bh_vft[FIB_SOURCE_BH_INTERPOSE]); } + ASSERT(bh < FIB_SOURCE_BH_MAX); return (&fib_entry_src_bh_vft[bh]); } @@ -127,7 +128,7 @@ fib_entry_src_find_i (const fib_entry_t *fib_entry, return (NULL); } -static fib_entry_src_t * +fib_entry_src_t * fib_entry_src_find (const fib_entry_t *fib_entry, fib_source_t source) @@ -253,25 +254,27 @@ typedef struct fib_entry_src_collect_forwarding_ctx_t_ { load_balance_path_t *next_hops; const fib_entry_t *fib_entry; - const fib_entry_src_t *esrc; + i32 start_source_index, end_source_index; fib_forward_chain_type_t fct; int n_recursive_constrained; u16 preference; + dpo_proto_t payload_proto; } fib_entry_src_collect_forwarding_ctx_t; /** * @brief Determine whether this FIB entry should use a load-balance MAP * to support PIC edge fast convergence */ -load_balance_flags_t -fib_entry_calc_lb_flags (fib_entry_src_collect_forwarding_ctx_t *ctx) +static load_balance_flags_t +fib_entry_calc_lb_flags (fib_entry_src_collect_forwarding_ctx_t *ctx, + const fib_entry_src_t *esrc) { /** * We'll use a LB map if the path-list has multiple recursive paths. * recursive paths implies BGP, and hence scale. */ if (ctx->n_recursive_constrained > 1 && - fib_path_list_is_popular(ctx->esrc->fes_pl)) + fib_path_list_is_popular(esrc->fes_pl)) { return (LOAD_BALANCE_FLAG_USES_MAP); } @@ -288,47 +291,6 @@ fib_entry_src_valid_out_label (mpls_label_t label) MPLS_IETF_IMPLICIT_NULL_LABEL == label)); } -/** - * @brief Turn the chain type requested by the client into the one they - * really wanted - */ -fib_forward_chain_type_t -fib_entry_chain_type_fixup (const fib_entry_t *entry, - fib_forward_chain_type_t fct) -{ - /* - * The EOS chain is a tricky since one cannot know the adjacency - * to link to without knowing what the packets payload protocol - * will be once the label is popped. - */ - fib_forward_chain_type_t dfct; - - if (FIB_FORW_CHAIN_TYPE_MPLS_EOS != fct) - { - return (fct); - } - - dfct = fib_entry_get_default_chain_type(entry); - - if (FIB_FORW_CHAIN_TYPE_MPLS_EOS == dfct) - { - /* - * If the entry being asked is a eos-MPLS label entry, - * then use the payload-protocol field, that we stashed there - * for just this purpose - */ - return (fib_forw_chain_type_from_dpo_proto( - entry->fe_prefix.fp_payload_proto)); - } - /* - * else give them what this entry would be by default. i.e. if it's a v6 - * entry, then the label its local labelled should be carrying v6 traffic. - * If it's a non-EOS label entry, then there are more labels and we want - * a non-eos chain. - */ - return (dfct); -} - static dpo_proto_t fib_prefix_get_payload_proto (const fib_prefix_t *pfx) { @@ -370,7 +332,8 @@ fib_entry_src_get_path_forwarding (fib_node_index_t path_index, nh->path_index = path_index; nh->path_weight = fib_path_get_weight(path_index); - fib_path_contribute_forwarding(path_index, ctx->fct, &nh->path_dpo); + fib_path_contribute_forwarding(path_index, ctx->fct, + ctx->payload_proto, &nh->path_dpo); break; case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS: @@ -383,6 +346,7 @@ fib_entry_src_get_path_forwarding (fib_node_index_t path_index, nh->path_weight = fib_path_get_weight(path_index); fib_path_contribute_forwarding(path_index, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, + ctx->payload_proto, &nh->path_dpo); } break; @@ -396,11 +360,11 @@ fib_entry_src_get_path_forwarding (fib_node_index_t path_index, nh->path_index = path_index; nh->path_weight = fib_path_get_weight(path_index); fib_path_contribute_forwarding(path_index, - fib_entry_chain_type_fixup(ctx->fib_entry, - ctx->fct), + ctx->fct, + ctx->payload_proto, &nh->path_dpo); fib_path_stack_mpls_disp(path_index, - fib_prefix_get_payload_proto(&ctx->fib_entry->fe_prefix), + ctx->payload_proto, FIB_MPLS_LSP_MODE_PIPE, &nh->path_dpo); @@ -419,12 +383,18 @@ fib_entry_src_collect_forwarding (fib_node_index_t pl_index, void *arg) { fib_entry_src_collect_forwarding_ctx_t *ctx; + const fib_entry_src_t *esrc; fib_path_ext_t *path_ext; u32 n_nhs; ctx = arg; n_nhs = vec_len(ctx->next_hops); + /* + * walk the paths and extension of the best non-interpose source + */ + esrc = &ctx->fib_entry->fe_srcs[ctx->end_source_index]; + /* * if the path is not resolved, don't include it. */ @@ -457,7 +427,7 @@ fib_entry_src_collect_forwarding (fib_node_index_t pl_index, /* * get the matching path-extension for the path being visited. */ - path_ext = fib_path_ext_list_find_by_path_index(&ctx->esrc->fes_path_exts, + path_ext = fib_path_ext_list_find_by_path_index(&esrc->fes_path_exts, path_index); if (NULL != path_ext) @@ -473,9 +443,8 @@ fib_entry_src_collect_forwarding (fib_node_index_t pl_index, */ ctx->next_hops = fib_path_ext_stack(path_ext, + ctx->payload_proto, ctx->fct, - fib_entry_chain_type_fixup(ctx->fib_entry, - ctx->fct), ctx->next_hops); } else @@ -514,14 +483,26 @@ fib_entry_src_collect_forwarding (fib_node_index_t pl_index, */ const fib_entry_src_vft_t *vft; - vft = fib_entry_src_get_vft(ctx->esrc); + /* + * roll up the sources that are interposes + */ + i32 index; - if (NULL != vft->fesv_contribute_interpose) + for (index = ctx->end_source_index; + index >= ctx->start_source_index; + index--) { const dpo_id_t *interposer; - interposer = vft->fesv_contribute_interpose(ctx->esrc, - ctx->fib_entry); + esrc = &ctx->fib_entry->fe_srcs[index]; + vft = fib_entry_src_get_vft(esrc); + + if (!(esrc->fes_flags & FIB_ENTRY_SRC_FLAG_CONTRIBUTING) || + !(esrc->fes_entry_flags & FIB_ENTRY_FLAG_INTERPOSE)) + continue; + + ASSERT(vft->fesv_contribute_interpose); + interposer = vft->fesv_contribute_interpose(esrc, ctx->fib_entry); if (NULL != interposer) { @@ -542,11 +523,40 @@ fib_entry_src_collect_forwarding (fib_node_index_t pl_index, void fib_entry_src_mk_lb (fib_entry_t *fib_entry, - const fib_entry_src_t *esrc, + fib_source_t source, fib_forward_chain_type_t fct, dpo_id_t *dpo_lb) { + const fib_entry_src_t *esrc; dpo_proto_t lb_proto; + u32 start, end; + + /* + * The source passed here is the 'best', i.e. the one the client + * wants. however, if it's an interpose then it does not contribute + * the forwarding, the next best source that is not an interpose does. + * So roll down the sources, to find the best non-interpose + */ + vec_foreach_index (start, fib_entry->fe_srcs) + { + if (source == fib_entry->fe_srcs[start].fes_src) + break; + } + for (end = start; end < vec_len (fib_entry->fe_srcs); end++) + { + if (!(fib_entry->fe_srcs[end].fes_entry_flags & + FIB_ENTRY_FLAG_INTERPOSE) && + (fib_entry->fe_srcs[end].fes_flags & + FIB_ENTRY_SRC_FLAG_CONTRIBUTING)) + break; + } + if (end == vec_len(fib_entry->fe_srcs)) + { + /* didn't find any contributing non-interpose sources */ + end = start; + } + + esrc = &fib_entry->fe_srcs[end]; /* * If the entry has path extensions then we construct a load-balance @@ -554,12 +564,14 @@ fib_entry_src_mk_lb (fib_entry_t *fib_entry, * Otherwise we use the load-balance of the path-list */ fib_entry_src_collect_forwarding_ctx_t ctx = { - .esrc = esrc, .fib_entry = fib_entry, .next_hops = NULL, .n_recursive_constrained = 0, .fct = fct, .preference = 0xffff, + .start_source_index = start, + .end_source_index = end, + .payload_proto = fib_prefix_get_payload_proto(&fib_entry->fe_prefix), }; /* @@ -644,7 +656,7 @@ fib_entry_src_mk_lb (fib_entry_t *fib_entry, { load_balance_multipath_update(dpo_lb, ctx.next_hops, - fib_entry_calc_lb_flags(&ctx)); + fib_entry_calc_lb_flags(&ctx, esrc)); vec_free(ctx.next_hops); /* @@ -688,11 +700,9 @@ fib_entry_src_action_install (fib_entry_t *fib_entry, * tables */ fib_forward_chain_type_t fct; - fib_entry_src_t *esrc; int insert; fct = fib_entry_get_default_chain_type(fib_entry); - esrc = fib_entry_src_find(fib_entry, source); /* * Every entry has its own load-balance object. All changes to the entry's @@ -702,7 +712,7 @@ fib_entry_src_action_install (fib_entry_t *fib_entry, */ insert = !dpo_id_is_valid(&fib_entry->fe_lb); - fib_entry_src_mk_lb(fib_entry, esrc, fct, &fib_entry->fe_lb); + fib_entry_src_mk_lb(fib_entry, source, fct, &fib_entry->fe_lb); ASSERT(dpo_id_is_valid(&fib_entry->fe_lb)); FIB_ENTRY_DBG(fib_entry, "install: %d", fib_entry->fe_lb); @@ -726,7 +736,7 @@ fib_entry_src_action_install (fib_entry_t *fib_entry, FOR_EACH_DELEGATE_CHAIN(fib_entry, fdt, fed, { - fib_entry_src_mk_lb(fib_entry, esrc, + fib_entry_src_mk_lb(fib_entry, source, fib_entry_delegate_type_to_chain_type(fdt), &fed->fd_dpo); }); @@ -747,6 +757,7 @@ fib_entry_src_action_uninstall (fib_entry_t *fib_entry) &fib_entry->fe_prefix, &fib_entry->fe_lb); + vlib_worker_wait_one_loop(); dpo_reset(&fib_entry->fe_lb); } } @@ -1446,55 +1457,38 @@ fib_entry_src_action_remove (fib_entry_t *fib_entry, * Return true the the route is attached via an interface that * is not in the same table as the route */ -static inline int +static int fib_route_attached_cross_table (const fib_entry_t *fib_entry, const fib_route_path_t *rpath) { - /* - * - All zeros next-hop - * - a valid interface - * - entry's fib index not equeal to interface's index - */ - if (ip46_address_is_zero(&rpath->frp_addr) && - (~0 != rpath->frp_sw_if_index) && - !(rpath->frp_flags & FIB_ROUTE_PATH_DVR) && - (fib_entry->fe_fib_index != - fib_table_get_index_for_sw_if_index(fib_entry_get_proto(fib_entry), - rpath->frp_sw_if_index))) - { - return (!0); - } - return (0); -} + const fib_prefix_t *pfx = &fib_entry->fe_prefix; -/* - * Return true if the path is attached - */ -static inline int -fib_path_is_attached (const fib_route_path_t *rpath) -{ - /* - * DVR paths are not attached, since we are not playing the - * L3 game with these - */ - if (rpath->frp_flags & FIB_ROUTE_PATH_DVR) + switch (pfx->fp_proto) { - return (0); + case FIB_PROTOCOL_MPLS: + /* MPLS routes are never imported/exported */ + return (0); + case FIB_PROTOCOL_IP6: + /* Ignore link local addresses these also can't be imported/exported */ + if (ip6_address_is_link_local_unicast (&pfx->fp_addr.ip6)) + { + return (0); + } + break; + case FIB_PROTOCOL_IP4: + break; } /* - * - All zeros next-hop - * - a valid interface + * an attached path and entry's fib index not equal to interface's index */ - if (ip46_address_is_zero(&rpath->frp_addr) && - (~0 != rpath->frp_sw_if_index)) + if (fib_route_path_is_attached(rpath) && + fib_entry->fe_fib_index != + fib_table_get_index_for_sw_if_index(fib_entry_get_proto(fib_entry), + rpath->frp_sw_if_index)) { return (!0); } - else if (rpath->frp_flags & FIB_ROUTE_PATH_ATTACHED) - { - return (!0); - } return (0); } @@ -1532,7 +1526,7 @@ fib_entry_flags_update (const fib_entry_t *fib_entry, if ((esrc->fes_src == FIB_SOURCE_API) || (esrc->fes_src == FIB_SOURCE_CLI)) { - if (fib_path_is_attached(rpath)) + if (fib_route_path_is_attached(rpath)) { esrc->fes_entry_flags |= FIB_ENTRY_FLAG_ATTACHED; } @@ -1804,6 +1798,25 @@ fib_entry_get_dpo_for_source (fib_node_index_t fib_entry_index, return (0); } +fib_node_index_t +fib_entry_get_path_list_for_source (fib_node_index_t fib_entry_index, + fib_source_t source) +{ + fib_entry_t *fib_entry; + fib_entry_src_t *esrc; + + if (FIB_NODE_INDEX_INVALID == fib_entry_index) + return FIB_NODE_INDEX_INVALID; + + fib_entry = fib_entry_get(fib_entry_index); + esrc = fib_entry_src_find(fib_entry, source); + + if (esrc) + return esrc->fes_pl; + + return FIB_NODE_INDEX_INVALID; +} + u32 fib_entry_get_resolving_interface_for_source (fib_node_index_t entry_index, fib_source_t source)