X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Ffib%2Ffib_entry_src.c;h=1d73af3bf0d5b1c2e1fc6cc8cd433f804ed02c33;hb=9128637ee8f7b0d903551f165a1447d427e8dd19;hp=a700282ee9b88b26e3c0385ed135a21bb9f84d57;hpb=0f26c5a0138ac86d7ebd197c31a09d8d624c35fe;p=vpp.git diff --git a/src/vnet/fib/fib_entry_src.c b/src/vnet/fib/fib_entry_src.c index a700282ee9b..1d73af3bf0d 100644 --- a/src/vnet/fib/fib_entry_src.c +++ b/src/vnet/fib/fib_entry_src.c @@ -29,12 +29,6 @@ */ static fib_entry_src_vft_t fib_entry_src_vft[FIB_SOURCE_MAX]; -static fib_protocol_t -fib_entry_get_proto (const fib_entry_t * fib_entry) -{ - return (fib_entry->fe_prefix.fp_proto); -} - void fib_entry_src_register (fib_source_t source, const fib_entry_src_vft_t *vft) @@ -146,7 +140,7 @@ fib_entry_src_action_deinit (fib_entry_t *fib_entry, fib_entry_src_vft[source].fesv_deinit(esrc); } - vec_free(esrc->fes_path_exts); + fib_path_ext_list_flush(&esrc->fes_path_exts); vec_del1(fib_entry->fe_srcs, index); } @@ -188,11 +182,12 @@ fib_entry_src_action_cover_update (fib_entry_t *fib_entry, typedef struct fib_entry_src_collect_forwarding_ctx_t_ { - load_balance_path_t * next_hops; + load_balance_path_t *next_hops; const fib_entry_t *fib_entry; const fib_entry_src_t *esrc; fib_forward_chain_type_t fct; - int is_recursive; + int n_recursive_constrained; + u16 preference; } fib_entry_src_collect_forwarding_ctx_t; /** @@ -203,10 +198,11 @@ load_balance_flags_t fib_entry_calc_lb_flags (fib_entry_src_collect_forwarding_ctx_t *ctx) { /** - * We'll use a LB map is the path-list has recursive paths. + * We'll use a LB map if the path-list has multiple recursive paths. * recursive paths implies BGP, and hence scale. */ - if (ctx->is_recursive) + if (ctx->n_recursive_constrained > 1 && + fib_path_list_is_popular(ctx->esrc->fes_pl)) { return (LOAD_BALANCE_FLAG_USES_MAP); } @@ -263,95 +259,64 @@ fib_entry_chain_type_fixup (const fib_entry_t *entry, return (dfct); } -static int -fib_entry_src_collect_forwarding (fib_node_index_t pl_index, - fib_node_index_t path_index, - void *arg) +static dpo_proto_t +fib_prefix_get_payload_proto (const fib_prefix_t *pfx) { - fib_entry_src_collect_forwarding_ctx_t *ctx; - fib_path_ext_t *path_ext; - int have_path_ext; - - ctx = arg; - - /* - * if the path is not resolved, don't include it. - */ - if (!fib_path_is_resolved(path_index)) + switch (pfx->fp_proto) { - return (!0); + case FIB_PROTOCOL_IP4: + return (DPO_PROTO_IP4); + case FIB_PROTOCOL_IP6: + return (DPO_PROTO_IP6); + case FIB_PROTOCOL_MPLS: + return (pfx->fp_payload_proto); } - if (fib_path_is_recursive(path_index)) - { - ctx->is_recursive = 1; - } + ASSERT(0); + return (DPO_PROTO_IP4); +} + +static void +fib_entry_src_get_path_forwarding (fib_node_index_t path_index, + fib_entry_src_collect_forwarding_ctx_t *ctx) +{ + load_balance_path_t *nh; /* - * get the matching path-extension for the path being visited. + * no extension => no out-going label for this path. that's OK + * in the case of an IP or EOS chain, but not for non-EOS */ - have_path_ext = 0; - vec_foreach(path_ext, ctx->esrc->fes_path_exts) - { - if (path_ext->fpe_path_index == path_index) - { - have_path_ext = 1; - break; - } - } - - if (have_path_ext && - fib_entry_src_valid_out_label(path_ext->fpe_label_stack[0])) + switch (ctx->fct) { + case FIB_FORW_CHAIN_TYPE_UNICAST_IP4: + case FIB_FORW_CHAIN_TYPE_UNICAST_IP6: + case FIB_FORW_CHAIN_TYPE_MCAST_IP4: + case FIB_FORW_CHAIN_TYPE_MCAST_IP6: + case FIB_FORW_CHAIN_TYPE_BIER: /* - * found a matching extension. stack it to obtain the forwarding - * info for this path. + * EOS traffic with no label to stack, we need the IP Adj */ - ctx->next_hops = - fib_path_ext_stack(path_ext, - ctx->fct, - fib_entry_chain_type_fixup(ctx->fib_entry, - ctx->fct), - ctx->next_hops); - } - else - { - load_balance_path_t *nh; + vec_add2(ctx->next_hops, nh, 1); - /* - * no extension => no out-going label for this path. that's OK - * in the case of an IP or EOS chain, but not for non-EOS - */ - switch (ctx->fct) + 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); + + break; + case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS: + if (fib_path_is_exclusive(path_index) || + fib_path_is_deag(path_index)) { - case FIB_FORW_CHAIN_TYPE_UNICAST_IP4: - case FIB_FORW_CHAIN_TYPE_UNICAST_IP6: - case FIB_FORW_CHAIN_TYPE_MCAST_IP4: - case FIB_FORW_CHAIN_TYPE_MCAST_IP6: - /* - * EOS traffic with no label to stack, we need the IP Adj - */ vec_add2(ctx->next_hops, nh, 1); 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); - - break; - case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS: - if (fib_path_is_exclusive(path_index) || - fib_path_is_deag(path_index)) - { - vec_add2(ctx->next_hops, nh, 1); - - nh->path_index = path_index; - nh->path_weight = fib_path_get_weight(path_index); - fib_path_contribute_forwarding(path_index, - FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, - &nh->path_dpo); - } - break; - case FIB_FORW_CHAIN_TYPE_MPLS_EOS: + fib_path_contribute_forwarding(path_index, + FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, + &nh->path_dpo); + } + break; + case FIB_FORW_CHAIN_TYPE_MPLS_EOS: { /* * no label. we need a chain based on the payload. fixup. @@ -365,19 +330,106 @@ fib_entry_src_collect_forwarding (fib_node_index_t pl_index, ctx->fct), &nh->path_dpo); fib_path_stack_mpls_disp(path_index, - ctx->fib_entry->fe_prefix.fp_payload_proto, + fib_prefix_get_payload_proto(&ctx->fib_entry->fe_prefix), &nh->path_dpo); break; } - case FIB_FORW_CHAIN_TYPE_ETHERNET: - case FIB_FORW_CHAIN_TYPE_NSH: - ASSERT(0); - break; + case FIB_FORW_CHAIN_TYPE_ETHERNET: + case FIB_FORW_CHAIN_TYPE_NSH: + ASSERT(0); + break; + } +} + +static fib_path_list_walk_rc_t +fib_entry_src_collect_forwarding (fib_node_index_t pl_index, + fib_node_index_t path_index, + void *arg) +{ + fib_entry_src_collect_forwarding_ctx_t *ctx; + fib_path_ext_t *path_ext; + + ctx = arg; + + /* + * if the path is not resolved, don't include it. + */ + if (!fib_path_is_resolved(path_index)) + { + return (FIB_PATH_LIST_WALK_CONTINUE); + } + + if (fib_path_is_recursive_constrained(path_index)) + { + ctx->n_recursive_constrained += 1; + } + if (0xffff == ctx->preference) + { + /* + * not set a preference yet, so the first path we encounter + * sets the preference we are collecting. + */ + ctx->preference = fib_path_get_preference(path_index); + } + else if (ctx->preference != fib_path_get_preference(path_index)) + { + /* + * this path does not belong to the same preference as the + * previous paths encountered. we are done now. + */ + return (FIB_PATH_LIST_WALK_STOP); + } + + /* + * 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_index); + + if (NULL != path_ext) + { + switch (path_ext->fpe_type) + { + case FIB_PATH_EXT_MPLS: + if (fib_entry_src_valid_out_label(path_ext->fpe_label_stack[0])) + { + /* + * found a matching extension. stack it to obtain the forwarding + * info for this path. + */ + ctx->next_hops = + fib_path_ext_stack(path_ext, + ctx->fct, + fib_entry_chain_type_fixup(ctx->fib_entry, + ctx->fct), + ctx->next_hops); + } + else + { + fib_entry_src_get_path_forwarding(path_index, ctx); + } + break; + case FIB_PATH_EXT_ADJ: + if (FIB_PATH_EXT_ADJ_FLAG_REFINES_COVER & path_ext->fpe_adj_flags) + { + fib_entry_src_get_path_forwarding(path_index, ctx); + } + /* + * else + * the path does not refine the cover, meaning that + * the adjacency doesdoes not match the sub-net on the link. + * So this path does not contribute forwarding. + */ + break; } } + else + { + fib_entry_src_get_path_forwarding(path_index, ctx); + } - return (!0); + return (FIB_PATH_LIST_WALK_CONTINUE); } void @@ -397,8 +449,9 @@ fib_entry_src_mk_lb (fib_entry_t *fib_entry, .esrc = esrc, .fib_entry = fib_entry, .next_hops = NULL, - .is_recursive = 0, + .n_recursive_constrained = 0, .fct = fct, + .preference = 0xffff, }; /* @@ -409,7 +462,7 @@ fib_entry_src_mk_lb (fib_entry_t *fib_entry, vec_validate(ctx.next_hops, fib_path_list_get_n_paths(esrc->fes_pl)); vec_reset_length(ctx.next_hops); - lb_proto = fib_proto_to_dpo(fib_entry->fe_prefix.fp_proto); + lb_proto = fib_forw_chain_type_to_dpo_proto(fct); fib_path_list_walk(esrc->fes_pl, fib_entry_src_collect_forwarding, @@ -445,10 +498,26 @@ fib_entry_src_mk_lb (fib_entry_t *fib_entry, } else { + fib_protocol_t flow_hash_proto; flow_hash_config_t fhc; - fhc = fib_table_get_flow_hash_config(fib_entry->fe_fib_index, - dpo_proto_to_fib(lb_proto)); + /* + * if the protocol for the LB we are building does not match that + * of the fib_entry (i.e. we are build the [n]EOS LB for an IPv[46] + * then the fib_index is not an index that relates to the table + * type we need. So get the default flow-hash config instead. + */ + flow_hash_proto = dpo_proto_to_fib(lb_proto); + if (fib_entry->fe_prefix.fp_proto != flow_hash_proto) + { + fhc = fib_table_get_default_flow_hash_config(flow_hash_proto); + } + else + { + fhc = fib_table_get_flow_hash_config(fib_entry->fe_fib_index, + flow_hash_proto); + } + dpo_set(dpo_lb, DPO_LOAD_BALANCE, lb_proto, @@ -805,7 +874,7 @@ fib_entry_src_action_add (fib_entry_t *fib_entry, fib_entry_src_vft[source].fesv_add(esrc, fib_entry, flags, - fib_entry_get_proto(fib_entry), + fib_entry_get_dpo_proto(fib_entry), dpo); } @@ -858,7 +927,7 @@ fib_entry_src_action_update (fib_entry_t *fib_entry, fib_entry_src_vft[source].fesv_add(esrc, fib_entry, flags, - fib_entry_get_proto(fib_entry), + fib_entry_get_dpo_proto(fib_entry), dpo); } @@ -1019,58 +1088,6 @@ fib_entry_flags_update (const fib_entry_t *fib_entry, } } -/* - * fib_entry_src_path_ext_add - * - * append a path extension to the entry's list - */ -static void -fib_entry_src_path_ext_append (fib_entry_src_t *esrc, - const fib_route_path_t *rpath) -{ - if (NULL != rpath->frp_label_stack) - { - fib_path_ext_t *path_ext; - - vec_add2(esrc->fes_path_exts, path_ext, 1); - - fib_path_ext_init(path_ext, esrc->fes_pl, rpath); - } -} - -/* - * fib_entry_src_path_ext_insert - * - * insert, sorted, a path extension to the entry's list. - * It's not strictly necessary in sort the path extensions, since each - * extension has the path index to which it resolves. However, by being - * sorted the load-balance produced has a deterministic order, not an order - * based on the sequence of extension additions. this is a considerable benefit. - */ -static void -fib_entry_src_path_ext_insert (fib_entry_src_t *esrc, - const fib_route_path_t *rpath) -{ - if (0 == vec_len(esrc->fes_path_exts)) - return (fib_entry_src_path_ext_append(esrc, rpath)); - - if (NULL != rpath->frp_label_stack) - { - fib_path_ext_t path_ext; - int i = 0; - - fib_path_ext_init(&path_ext, esrc->fes_pl, rpath); - - while (i < vec_len(esrc->fes_path_exts) && - (fib_path_ext_cmp(&esrc->fes_path_exts[i], rpath) < 0)) - { - i++; - } - - vec_insert_elts(esrc->fes_path_exts, &path_ext, 1, i); - } -} - /* * fib_entry_src_action_add * @@ -1087,7 +1104,6 @@ fib_entry_src_action_path_add (fib_entry_t *fib_entry, { fib_node_index_t old_path_list, fib_entry_index; fib_path_list_flags_t pl_flags; - fib_path_ext_t *path_ext; fib_entry_src_t *esrc; /* @@ -1103,8 +1119,7 @@ fib_entry_src_action_path_add (fib_entry_t *fib_entry, source, flags, drop_dpo_get( - fib_proto_to_dpo( - fib_entry_get_proto(fib_entry)))); + fib_entry_get_dpo_proto(fib_entry))); esrc = fib_entry_src_find(fib_entry, source, NULL); } @@ -1124,18 +1139,6 @@ fib_entry_src_action_path_add (fib_entry_t *fib_entry, fib_entry_src_vft[source].fesv_path_add(esrc, fib_entry, pl_flags, rpath); fib_entry = fib_entry_get(fib_entry_index); - /* - * re-resolve all the path-extensions with the new path-list - */ - vec_foreach(path_ext, esrc->fes_path_exts) - { - fib_path_ext_resolve(path_ext, esrc->fes_pl); - } - /* - * if the path has a label we need to add a path extension - */ - fib_entry_src_path_ext_insert(esrc, rpath); - fib_path_list_lock(esrc->fes_pl); fib_path_list_unlock(old_path_list); @@ -1160,7 +1163,6 @@ fib_entry_src_action_path_swap (fib_entry_t *fib_entry, fib_node_index_t old_path_list, fib_entry_index; fib_path_list_flags_t pl_flags; const fib_route_path_t *rpath; - fib_path_ext_t *path_ext; fib_entry_src_t *esrc; esrc = fib_entry_src_find(fib_entry, source, NULL); @@ -1176,8 +1178,7 @@ fib_entry_src_action_path_swap (fib_entry_t *fib_entry, source, flags, drop_dpo_get( - fib_proto_to_dpo( - fib_entry_get_proto(fib_entry)))); + fib_entry_get_dpo_proto(fib_entry))); esrc = fib_entry_src_find(fib_entry, source, NULL); } @@ -1202,17 +1203,6 @@ fib_entry_src_action_path_swap (fib_entry_t *fib_entry, pl_flags, rpaths); - vec_foreach(path_ext, esrc->fes_path_exts) - { - vec_free(path_ext->fpe_label_stack); - } - vec_free(esrc->fes_path_exts); - - vec_foreach(rpath, rpaths) - { - fib_entry_src_path_ext_append(esrc, rpath); - } - fib_entry = fib_entry_get(fib_entry_index); fib_path_list_lock(esrc->fes_pl); @@ -1228,7 +1218,6 @@ fib_entry_src_action_path_remove (fib_entry_t *fib_entry, { fib_path_list_flags_t pl_flags; fib_node_index_t old_path_list; - fib_path_ext_t *path_ext; fib_entry_src_t *esrc; esrc = fib_entry_src_find(fib_entry, source, NULL); @@ -1250,29 +1239,6 @@ fib_entry_src_action_path_remove (fib_entry_t *fib_entry, fib_entry_flags_update(fib_entry, rpath, &pl_flags, esrc); fib_entry_src_vft[source].fesv_path_remove(esrc, pl_flags, rpath); - /* - * find the matching path extension and remove it - */ - vec_foreach(path_ext, esrc->fes_path_exts) - { - if (!fib_path_ext_cmp(path_ext, rpath)) - { - /* - * delete the element moving the remaining elements down 1 position. - * this preserves the sorted order. - */ - vec_free(path_ext->fpe_label_stack); - vec_delete(esrc->fes_path_exts, 1, (path_ext - esrc->fes_path_exts)); - break; - } - } - /* - * re-resolve all the path-extensions with the new path-list - */ - vec_foreach(path_ext, esrc->fes_path_exts) - { - fib_path_ext_resolve(path_ext, esrc->fes_pl); - } /* * lock the new path-list, unlock the old if it had one @@ -1355,6 +1321,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));