X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Ffib%2Ffib_test.c;h=61ba9348fd80d66050ee2a55ae8f6d169b6e6d34;hb=7b867a8e491357058d37838091ed67a2e77bce2c;hp=6867cca89597242bac350a40e1907e48d701cee2;hpb=43161a873375ddf156cf6fbe8764bfc206b38fa0;p=vpp.git diff --git a/src/vnet/fib/fib_test.c b/src/vnet/fib/fib_test.c index 6867cca8959..61ba9348fd8 100644 --- a/src/vnet/fib/fib_test.c +++ b/src/vnet/fib/fib_test.c @@ -13,6 +13,7 @@ * limitations under the License. */ +#include #include #include #include @@ -27,15 +28,20 @@ #include #include #include +#include +#include #include +#include #include #include #include #include #include +#include + /* * Add debugs for passing tests */ @@ -266,83 +272,6 @@ fib_test_build_rewrite (u8 *eth_addr) return (rewrite); } -typedef enum fib_test_lb_bucket_type_t_ { - FT_LB_LABEL_O_ADJ, - FT_LB_LABEL_STACK_O_ADJ, - FT_LB_LABEL_O_LB, - FT_LB_O_LB, - FT_LB_SPECIAL, - FT_LB_ADJ, - FT_LB_INTF, -} fib_test_lb_bucket_type_t; - -typedef struct fib_test_lb_bucket_t_ { - fib_test_lb_bucket_type_t type; - - union - { - struct - { - mpls_eos_bit_t eos; - mpls_label_t label; - u8 ttl; - adj_index_t adj; - } label_o_adj; - struct - { - mpls_eos_bit_t eos; - mpls_label_t label_stack[8]; - u8 label_stack_size; - u8 ttl; - adj_index_t adj; - } label_stack_o_adj; - struct - { - mpls_eos_bit_t eos; - mpls_label_t label; - u8 ttl; - index_t lb; - } label_o_lb; - struct - { - index_t adj; - } adj; - struct - { - index_t lb; - } lb; - struct - { - index_t adj; - } special; - }; -} fib_test_lb_bucket_t; - -typedef enum fib_test_rep_bucket_type_t_ { - FT_REP_LABEL_O_ADJ, - FT_REP_DISP_MFIB_LOOKUP, - FT_REP_INTF, -} fib_test_rep_bucket_type_t; - -typedef struct fib_test_rep_bucket_t_ { - fib_test_rep_bucket_type_t type; - - union - { - struct - { - mpls_eos_bit_t eos; - mpls_label_t label; - u8 ttl; - adj_index_t adj; - } label_o_adj; - struct - { - adj_index_t adj; - } adj; - }; -} fib_test_rep_bucket_t; - #define FIB_TEST_LB(_cond, _comment, _args...) \ { \ if (!FIB_TEST_I(_cond, _comment, ##_args)) { \ @@ -353,7 +282,7 @@ typedef struct fib_test_rep_bucket_t_ { int fib_test_validate_rep_v (const replicate_t *rep, u16 n_buckets, - va_list ap) + va_list *ap) { const fib_test_rep_bucket_t *exp; const dpo_id_t *dpo; @@ -364,7 +293,7 @@ fib_test_validate_rep_v (const replicate_t *rep, for (bucket = 0; bucket < n_buckets; bucket++) { - exp = va_arg(ap, fib_test_rep_bucket_t*); + exp = va_arg(*ap, fib_test_rep_bucket_t*); dpo = replicate_get_bucket_i(rep, bucket); @@ -374,7 +303,8 @@ fib_test_validate_rep_v (const replicate_t *rep, { const mpls_label_dpo_t *mld; mpls_label_t hdr; - FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type), + FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE) + == dpo->dpoi_type), "bucket %d stacks on %U", bucket, format_dpo_type, dpo->dpoi_type); @@ -428,8 +358,8 @@ fib_test_validate_rep_v (const replicate_t *rep, int fib_test_validate_lb_v (const load_balance_t *lb, - u16 n_buckets, - va_list ap) + int n_buckets, + va_list *ap) { const dpo_id_t *dpo; int bucket; @@ -440,7 +370,7 @@ fib_test_validate_lb_v (const load_balance_t *lb, { const fib_test_lb_bucket_t *exp; - exp = va_arg(ap, fib_test_lb_bucket_t*); + exp = va_arg(*ap, fib_test_lb_bucket_t*); dpo = load_balance_get_bucket_i(lb, bucket); switch (exp->type) @@ -448,14 +378,19 @@ fib_test_validate_lb_v (const load_balance_t *lb, case FT_LB_LABEL_STACK_O_ADJ: { const mpls_label_dpo_t *mld; + mpls_label_dpo_flags_t mf; mpls_label_t hdr; u32 ii; - FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type), + mf = ((exp->label_stack_o_adj.mode == + FIB_MPLS_LSP_MODE_UNIFORM) ? + MPLS_LABEL_DPO_FLAG_UNIFORM_MODE : + MPLS_LABEL_DPO_FLAG_NONE); + FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type), "bucket %d stacks on %U", bucket, format_dpo_type, dpo->dpoi_type); - + mld = mpls_label_dpo_get(dpo->dpoi_index); FIB_TEST_LB(exp->label_stack_o_adj.label_stack_size == mld->mld_n_labels, @@ -506,7 +441,8 @@ fib_test_validate_lb_v (const load_balance_t *lb, { const mpls_label_dpo_t *mld; mpls_label_t hdr; - FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type), + FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE) + == dpo->dpoi_type), "bucket %d stacks on %U", bucket, format_dpo_type, dpo->dpoi_type); @@ -541,13 +477,18 @@ fib_test_validate_lb_v (const load_balance_t *lb, case FT_LB_LABEL_O_LB: { const mpls_label_dpo_t *mld; + mpls_label_dpo_flags_t mf; mpls_label_t hdr; - FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type), + mf = ((exp->label_o_lb.mode == + FIB_MPLS_LSP_MODE_UNIFORM) ? + MPLS_LABEL_DPO_FLAG_UNIFORM_MODE : + MPLS_LABEL_DPO_FLAG_NONE); + FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type), "bucket %d stacks on %U", bucket, format_dpo_type, dpo->dpoi_type); - + mld = mpls_label_dpo_get(dpo->dpoi_index); hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl); @@ -588,6 +529,30 @@ fib_test_validate_lb_v (const load_balance_t *lb, bucket, exp->adj.adj); break; + case FT_LB_MPLS_DISP_PIPE_O_ADJ: + { + const mpls_disp_dpo_t *mdd; + + FIB_TEST_I((DPO_MPLS_DISPOSITION_PIPE == dpo->dpoi_type), + "bucket %d stacks on %U", + bucket, + format_dpo_type, dpo->dpoi_type); + + mdd = mpls_disp_dpo_get(dpo->dpoi_index); + + dpo = &mdd->mdd_dpo; + + FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) || + (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)), + "bucket %d stacks on %U", + bucket, + format_dpo_type, dpo->dpoi_type); + FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index), + "bucket %d stacks on adj %d", + bucket, + exp->adj.adj); + break; + } case FT_LB_INTF: FIB_TEST_I((DPO_INTERFACE_RX == dpo->dpoi_type), "bucket %d stacks on %U", @@ -598,6 +563,16 @@ fib_test_validate_lb_v (const load_balance_t *lb, bucket, exp->adj.adj); break; + case FT_LB_L2: + FIB_TEST_I((DPO_DVR == dpo->dpoi_type), + "bucket %d stacks on %U", + bucket, + format_dpo_type, dpo->dpoi_type); + FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index), + "bucket %d stacks on adj %d", + bucket, + exp->adj.adj); + break; case FT_LB_O_LB: FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type), "bucket %d stacks on %U", @@ -609,25 +584,70 @@ fib_test_validate_lb_v (const load_balance_t *lb, dpo->dpoi_index, exp->lb.lb); break; - case FT_LB_SPECIAL: - FIB_TEST_I((DPO_DROP == dpo->dpoi_type), - "bucket %d stacks on %U", - bucket, - format_dpo_type, dpo->dpoi_type); - FIB_TEST_LB((exp->special.adj == dpo->dpoi_index), - "bucket %d stacks on drop %d", + case FT_LB_BIER_TABLE: + FIB_TEST_LB((DPO_BIER_TABLE == dpo->dpoi_type), + "bucket %d stacks on %U", + bucket, + format_dpo_type, dpo->dpoi_type); + FIB_TEST_LB((exp->bier.table == dpo->dpoi_index), + "bucket %d stacks on lb %d", + bucket, + exp->bier.table); + break; + case FT_LB_BIER_FMASK: + FIB_TEST_LB((DPO_BIER_FMASK == dpo->dpoi_type), + "bucket %d stacks on %U", + bucket, + format_dpo_type, dpo->dpoi_type); + FIB_TEST_LB((exp->bier.fmask == dpo->dpoi_index), + "bucket %d stacks on lb %d", bucket, - exp->special.adj); + exp->bier.fmask); + break; + case FT_LB_DROP: + FIB_TEST_LB((DPO_DROP == dpo->dpoi_type), + "bucket %d stacks on %U", + bucket, + format_dpo_type, dpo->dpoi_type); break; } } return (!0); } +int +fib_test_validate_lb (const dpo_id_t *dpo, + int n_buckets, + ...) +{ + const load_balance_t *lb; + va_list ap; + int res; + + va_start(ap, n_buckets); + + if (FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type), + "Entry links to %U", + format_dpo_type, dpo->dpoi_type)) + { + lb = load_balance_get(dpo->dpoi_index); + + res = fib_test_validate_lb_v(lb, n_buckets, &ap); + } + else + { + res = !0; + } + + va_end(ap); + + return (res); +} + int fib_test_validate_entry (fib_node_index_t fei, fib_forward_chain_type_t fct, - u16 n_buckets, + int n_buckets, ...) { dpo_id_t dpo = DPO_INVALID; @@ -648,18 +668,19 @@ fib_test_validate_entry (fib_node_index_t fei, const replicate_t *rep; rep = replicate_get(dpo.dpoi_index); - res = fib_test_validate_rep_v(rep, n_buckets, ap); + res = fib_test_validate_rep_v(rep, n_buckets, &ap); } else { const load_balance_t *lb; FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type), - "Entry links to %U", + "%U Entry links to %U", + format_fib_prefix, &pfx, format_dpo_type, dpo.dpoi_type); lb = load_balance_get(dpo.dpoi_index); - res = fib_test_validate_lb_v(lb, n_buckets, ap); + res = fib_test_validate_lb_v(lb, n_buckets, &ap); /* * ensure that the LB contributed by the entry is the @@ -692,7 +713,7 @@ fib_test_validate_entry (fib_node_index_t fei, fw_lbi = 0; } FIB_TEST_LB((fw_lbi == dpo.dpoi_index), - "Contributed LB = FW LB: %U\n %U", + "Contributed LB = FW LB:\n fwd:%U\n cont:%U", format_load_balance, fw_lbi, 0, format_load_balance, dpo.dpoi_index, 0); } @@ -739,7 +760,8 @@ fib_test_v4 (void) lb_count = pool_elts(load_balance_pool); /* Find or create FIB table 11 */ - fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11); + fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11, + FIB_SOURCE_API); for (ii = 0; ii < 4; ii++) { @@ -807,7 +829,15 @@ fib_test_v4 (void) * table, and 4 path-lists in the v6 MFIB table */ #define ENBR (5+5+2) -#define PNBR (5+5+6) + + u32 PNBR = 5+5+2+4; + + /* + * if the IGMP plugin is loaded this adds two more entries to the v4 MFIB + */ + if (vlib_get_plugin_symbol("igmp_plugin.so", "igmp_listen")) + PNBR += 2; + FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty"); FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d", fib_path_list_pool_size()); @@ -3607,6 +3637,49 @@ fib_test_v4 (void) "4.4.4.4/32 is deag in %d %U", lkd->lkd_fib_index, format_dpo_id, dpo, 0); + FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input), + "4.4.4.4/32 is source deag in %d %U", + lkd->lkd_input, + format_dpo_id, dpo, 0); + + fib_table_entry_delete(fib_index, + &pfx_4_4_4_4_s_32, + FIB_SOURCE_API); + FIB_TEST(FIB_NODE_INDEX_INVALID == + fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32), + "4.4.4.4/32 removed"); + vec_free(r_paths); + + /* + * A route deag route in a source lookup table + */ + fib_table_entry_path_add(fib_index, + &pfx_4_4_4_4_s_32, + FIB_SOURCE_API, + FIB_ENTRY_FLAG_NONE, + DPO_PROTO_IP4, + &zero_addr, + ~0, + fib_index, + 1, + NULL, + FIB_ROUTE_PATH_SOURCE_LOOKUP); + + fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32); + FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present"); + + dpo = fib_entry_contribute_ip_forwarding(fei); + dpo = load_balance_get_bucket(dpo->dpoi_index, 0); + lkd = lookup_dpo_get(dpo->dpoi_index); + + FIB_TEST((fib_index == lkd->lkd_fib_index), + "4.4.4.4/32 is deag in %d %U", + lkd->lkd_fib_index, + format_dpo_id, dpo, 0); + FIB_TEST((LOOKUP_INPUT_SRC_ADDR == lkd->lkd_input), + "4.4.4.4/32 is source deag in %d %U", + lkd->lkd_input, + format_dpo_id, dpo, 0); fib_table_entry_delete(fib_index, &pfx_4_4_4_4_s_32, @@ -4065,6 +4138,45 @@ fib_test_v4 (void) "Table and LB newhash config match: %U", format_ip_flow_hash_config, lb->lb_hash_config); + /* + * A route via DVR DPO + */ + fei = fib_table_entry_path_add(fib_index, + &pfx_10_10_10_3_s_32, + FIB_SOURCE_API, + FIB_ENTRY_FLAG_NONE, + DPO_PROTO_IP4, + &zero_addr, + tm->hw[0]->sw_if_index, + ~0, + 1, + NULL, + FIB_ROUTE_PATH_DVR); + dpo_id_t dvr_dpo = DPO_INVALID; + dvr_dpo_add_or_lock(tm->hw[0]->sw_if_index, DPO_PROTO_IP4, &dvr_dpo); + fib_test_lb_bucket_t ip_o_l2 = { + .type = FT_LB_L2, + .adj = { + .adj = dvr_dpo.dpoi_index, + }, + }; + + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &ip_o_l2), + "10.10.10.3 via L2 on Eth0"); + fib_table_entry_path_remove(fib_index, + &pfx_10_10_10_3_s_32, + FIB_SOURCE_API, + DPO_PROTO_IP4, + &zero_addr, + tm->hw[0]->sw_if_index, + fib_index, + 1, + FIB_ROUTE_PATH_DVR); + dpo_reset(&dvr_dpo); + /* * CLEANUP * remove adj-fibs: @@ -4150,7 +4262,7 @@ fib_test_v4 (void) FIB_SOURCE_INTERFACE)), "NO INterface Source'd prefixes"); - fib_table_unlock(fib_index, FIB_PROTOCOL_IP4); + fib_table_unlock(fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_API); FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d", fib_path_list_db_size()); @@ -4164,6 +4276,8 @@ fib_test_v4 (void) pool_elts(load_balance_map_pool)); FIB_TEST((lb_count == pool_elts(load_balance_pool)), "LB pool size is %d", pool_elts(load_balance_pool)); + FIB_TEST((0 == pool_elts(dvr_dpo_pool)), "L2 DPO pool size is %d", + pool_elts(dvr_dpo_pool)); return 0; } @@ -4201,7 +4315,8 @@ fib_test_v6 (void) dpo_drop = drop_dpo_get(DPO_PROTO_IP6); /* Find or create FIB table 11 */ - fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11); + fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11, + FIB_SOURCE_API); for (ii = 0; ii < 4; ii++) { @@ -4238,7 +4353,13 @@ fib_test_v6 (void) * All entries are special so no path-list sharing. */ #define ENPS (5+4) -#define PNPS (5+4+4) + u32 PNPS = (5+4+4); + /* + * if the IGMP plugin is loaded this adds two more entries to the v4 MFIB + */ + if (vlib_get_plugin_symbol("igmp_plugin.so", "igmp_listen")) + PNPS += 2; + FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty"); FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is %d", fib_path_list_pool_size()); @@ -5025,7 +5146,7 @@ fib_test_v6 (void) /* * now remove the VRF */ - fib_table_unlock(fib_index, FIB_PROTOCOL_IP6); + fib_table_unlock(fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_API); FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d", fib_path_list_db_size()); @@ -5157,7 +5278,9 @@ fib_test_ae (void) */ u32 import_fib_index1; - import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11); + import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, + 11, + FIB_SOURCE_CLI); /* * Add an attached route in the import FIB @@ -5233,7 +5356,8 @@ fib_test_ae (void) */ u32 import_fib_index2; - import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12); + import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12, + FIB_SOURCE_CLI); /* * Add an attached route in the import FIB @@ -5595,8 +5719,8 @@ fib_test_ae (void) &local_pfx, FIB_SOURCE_API); - fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4); - fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4); + fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI); + fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI); FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d", adj_nbr_db_size()); @@ -6236,8 +6360,10 @@ fib_test_label (void) .eos = MPLS_NON_EOS, }, }; - mpls_label_t *l99 = NULL; - vec_add1(l99, 99); + fib_mpls_label_t *l99 = NULL, fml99 = { + .fml_value = 99, + }; + vec_add1(l99, fml99); fib_table_entry_update_one_path(fib_index, &pfx_1_1_1_1_s_32, @@ -6275,8 +6401,10 @@ fib_test_label (void) .adj = ai_mpls_10_10_11_1, }, }; - mpls_label_t *l_imp_null = NULL; - vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL); + fib_mpls_label_t *l_imp_null = NULL, fml_imp_null = { + .fml_value = MPLS_IETF_IMPLICIT_NULL_LABEL, + }; + vec_add1(l_imp_null, fml_imp_null); fei = fib_table_entry_path_add(fib_index, &pfx_1_1_1_1_s_32, @@ -6316,6 +6444,12 @@ fib_test_label (void) .fp_label = 24001, .fp_eos = MPLS_NON_EOS, }; + fib_test_lb_bucket_t disp_o_10_10_11_1 = { + .type = FT_LB_MPLS_DISP_PIPE_O_ADJ, + .adj = { + .adj = ai_v4_10_10_11_1, + }, + }; /* * The EOS entry should link to both the paths, @@ -6329,10 +6463,10 @@ fib_test_label (void) FIB_FORW_CHAIN_TYPE_MPLS_EOS, 2, &l99_eos_o_10_10_10_1, - &a_o_10_10_11_1), + &disp_o_10_10_11_1), "24001/eos LB 2 buckets via: " "label 99 over 10.10.10.1, " - "adj over 10.10.11.1"); + "mpls disp adj over 10.10.11.1"); fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID, @@ -6355,6 +6489,13 @@ fib_test_label (void) .adj = ai_v4_10_10_11_2, }, }; + fib_test_lb_bucket_t disp_o_10_10_11_2 = { + .type = FT_LB_MPLS_DISP_PIPE_O_ADJ, + .adj = { + .adj = ai_v4_10_10_11_2, + }, + }; + fei = fib_table_entry_path_add(fib_index, &pfx_1_1_1_1_s_32, @@ -6431,24 +6572,27 @@ fib_test_label (void) .lb = non_eos_1_1_1_1.dpoi_index, .label = 1600, .eos = MPLS_EOS, + .mode = FIB_MPLS_LSP_MODE_UNIFORM, }, }; - mpls_label_t *l1600 = NULL; - vec_add1(l1600, 1600); + fib_mpls_label_t *l1600 = NULL, fml1600 = { + .fml_value = 1600, + .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM, + }; + vec_add1(l1600, fml1600); - fib_table_entry_update_one_path(fib_index, - &pfx_2_2_2_2_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_1_1_1_1_s_32.fp_addr, - ~0, - fib_index, - 1, - l1600, - FIB_ROUTE_PATH_FLAG_NONE); + fei = fib_table_entry_update_one_path(fib_index, + &pfx_2_2_2_2_s_32, + FIB_SOURCE_API, + FIB_ENTRY_FLAG_NONE, + DPO_PROTO_IP4, + &pfx_1_1_1_1_s_32.fp_addr, + ~0, + fib_index, + 1, + l1600, + FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32); FIB_TEST(fib_test_validate_entry(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, @@ -6503,11 +6647,11 @@ fib_test_label (void) FIB_TEST(fib_test_validate_entry(fei, FIB_FORW_CHAIN_TYPE_MPLS_EOS, 2, - &a_o_10_10_11_1, - &adj_o_10_10_11_2), + &disp_o_10_10_11_1, + &disp_o_10_10_11_2), "24001/eos LB 2 buckets via: " - "adj over 10.10.11.1, ", - "adj-v4 over 10.10.11.2"); + "mpls-disp adj over 10.10.11.1, ", + "mpls-disp adj-v4 over 10.10.11.2"); fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID, &pfx_24001_neos); @@ -6580,20 +6724,20 @@ fib_test_label (void) &l99_eos_o_10_10_10_1, &l99_eos_o_10_10_10_1, &l99_eos_o_10_10_10_1, - &a_o_10_10_11_1, - &a_o_10_10_11_1, - &a_o_10_10_11_1, - &a_o_10_10_11_1, - &a_o_10_10_11_1, - &adj_o_10_10_11_2, - &adj_o_10_10_11_2, - &adj_o_10_10_11_2, - &adj_o_10_10_11_2, - &adj_o_10_10_11_2), + &disp_o_10_10_11_1, + &disp_o_10_10_11_1, + &disp_o_10_10_11_1, + &disp_o_10_10_11_1, + &disp_o_10_10_11_1, + &disp_o_10_10_11_2, + &disp_o_10_10_11_2, + &disp_o_10_10_11_2, + &disp_o_10_10_11_2, + &disp_o_10_10_11_2), "24001/eos LB 16 buckets via: " "label 99 over 10.10.10.1, " - "adj over 10.10.11.1", - "adj-v4 over 10.10.11.2"); + "MPLS disp adj over 10.10.11.1", + "MPLS disp adj-v4 over 10.10.11.2"); fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID, &pfx_24001_neos); @@ -6634,11 +6778,11 @@ fib_test_label (void) FIB_TEST(fib_test_validate_entry(fei, FIB_FORW_CHAIN_TYPE_MPLS_EOS, 2, - &a_o_10_10_11_1, - &adj_o_10_10_11_2), + &disp_o_10_10_11_1, + &disp_o_10_10_11_2), "24001/eos LB 2 buckets via: " - "adj over 10.10.11.1, " - "adj-v4 over 10.10.11.2"); + "MPLS disp adj over 10.10.11.1, " + "MPLS disp adj-v4 over 10.10.11.2"); fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID, &pfx_24001_neos); @@ -6654,13 +6798,10 @@ fib_test_label (void) * remove the other path with a valid label */ fib_test_lb_bucket_t bucket_drop = { - .type = FT_LB_SPECIAL, - .special = { - .adj = DPO_PROTO_IP4, - }, + .type = FT_LB_DROP, }; fib_test_lb_bucket_t mpls_bucket_drop = { - .type = FT_LB_SPECIAL, + .type = FT_LB_DROP, .special = { .adj = DPO_PROTO_MPLS, }, @@ -6689,9 +6830,9 @@ fib_test_label (void) FIB_TEST(fib_test_validate_entry(fei, FIB_FORW_CHAIN_TYPE_MPLS_EOS, 1, - &adj_o_10_10_11_2), + &disp_o_10_10_11_2), "24001/eos LB 1 buckets via: " - "adj over 10.10.11.2"); + "MPLS disp adj over 10.10.11.2"); fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID, &pfx_24001_neos); @@ -6705,7 +6846,7 @@ fib_test_label (void) * add back the path with the valid label */ l99 = NULL; - vec_add1(l99, 99); + vec_add1(l99, fml99); fib_table_entry_path_add(fib_index, &pfx_1_1_1_1_s_32, @@ -6735,10 +6876,10 @@ fib_test_label (void) FIB_FORW_CHAIN_TYPE_MPLS_EOS, 2, &l99_eos_o_10_10_10_1, - &adj_o_10_10_11_2), + &disp_o_10_10_11_2), "24001/eos LB 2 buckets via: " "label 99 over 10.10.10.1, " - "adj over 10.10.11.2"); + "MPLS disp adj over 10.10.11.2"); fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID, &pfx_24001_neos); @@ -6780,10 +6921,10 @@ fib_test_label (void) FIB_FORW_CHAIN_TYPE_MPLS_EOS, 2, &l99_eos_o_10_10_10_1, - &adj_o_10_10_11_2), + &disp_o_10_10_11_2), "25005/eos LB 2 buckets via: " "label 99 over 10.10.10.1, " - "adj over 10.10.11.2"); + "MPLS disp adj over 10.10.11.2"); fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID, &pfx_25005_neos); @@ -6835,8 +6976,10 @@ fib_test_label (void) .eos = MPLS_EOS, }, }; - mpls_label_t *l101 = NULL; - vec_add1(l101, 101); + fib_mpls_label_t *l101 = NULL, fml101 = { + .fml_value = 101, + }; + vec_add1(l101, fml101); fei = fib_table_entry_update_one_path(fib_index, &pfx_1_1_1_2_s_32, @@ -6875,8 +7018,10 @@ fib_test_label (void) .eos = MPLS_EOS, }, }; - mpls_label_t *l1601 = NULL; - vec_add1(l1601, 1601); + fib_mpls_label_t *l1601 = NULL, fml1601 = { + .fml_value = 1601, + }; + vec_add1(l1601, fml1601); l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index; @@ -6906,7 +7051,7 @@ fib_test_label (void) * the LB for the recursive can use an imp-null */ l_imp_null = NULL; - vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL); + vec_add1(l_imp_null, fml_imp_null); fei = fib_table_entry_update_one_path(fib_index, &pfx_1_1_1_2_s_32, @@ -7070,11 +7215,11 @@ fib_test_label (void) .eos = MPLS_EOS, }, }; - mpls_label_t *label_stack = NULL; + fib_mpls_label_t *label_stack = NULL; vec_validate(label_stack, 7); for (ii = 0; ii < 8; ii++) { - label_stack[ii] = ii + 200; + label_stack[ii].fml_value = ii + 200; } fei = fib_table_entry_update_one_path(fib_index, @@ -8149,12 +8294,13 @@ static int lfib_test (void) { const mpls_label_t deag_label = 50; + dpo_id_t dpo = DPO_INVALID; + const mpls_disp_dpo_t *mdd; const u32 lfib_index = 0; const u32 fib_index = 0; - dpo_id_t dpo = DPO_INVALID; + const lookup_dpo_t *lkd; const dpo_id_t *dpo1; fib_node_index_t lfe; - lookup_dpo_t *lkd; test_main_t *tm; int lb_count; adj_index_t ai_mpls_10_10_10_1; @@ -8168,9 +8314,10 @@ lfib_test (void) /* * MPLS enable an interface so we get the MPLS table created */ + mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL); mpls_sw_interface_enable_disable(&mpls_main, tm->hw[0]->sw_if_index, - 1); + 1, 1); ip46_address_t nh_10_10_10_1 = { .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01), @@ -8220,7 +8367,6 @@ lfib_test (void) format_mpls_eos_bit, MPLS_EOS, format_dpo_proto, lkd->lkd_proto); - /* * A route deag route for EOS */ @@ -8251,7 +8397,14 @@ lfib_test (void) FIB_FORW_CHAIN_TYPE_MPLS_EOS, &dpo); dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0); - lkd = lookup_dpo_get(dpo1->dpoi_index); + mdd = mpls_disp_dpo_get(dpo1->dpoi_index); + + FIB_TEST((FIB_MPLS_LSP_MODE_PIPE == mdd->mdd_mode), + "%U/%U disp is pipe mode", + format_mpls_unicast_label, deag_label, + format_mpls_eos_bit, MPLS_EOS); + + lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index); FIB_TEST((fib_index == lkd->lkd_fib_index), "%U/%U is deag in %d %U", @@ -8276,63 +8429,127 @@ lfib_test (void) "%U/%U not present", format_mpls_unicast_label, deag_label, format_mpls_eos_bit, MPLS_EOS); + dpo_reset(&dpo); /* - * A route deag route for non-EOS + * A route deag route for EOS with LSP mode uniform */ - pfx.fp_eos = MPLS_NON_EOS; + fib_mpls_label_t *l_pops = NULL, l_pop = { + .fml_value = MPLS_LABEL_POP, + .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM, + }; + vec_add1(l_pops, l_pop); lfe = fib_table_entry_path_add(lfib_index, - &pfx, - FIB_SOURCE_CLI, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &zero_addr, - ~0, - lfib_index, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); + &pfx, + FIB_SOURCE_CLI, + FIB_ENTRY_FLAG_NONE, + DPO_PROTO_IP4, + &zero_addr, + ~0, + fib_index, + 1, + l_pops, + FIB_ROUTE_PATH_FLAG_NONE); FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)), "%U/%U present", format_mpls_unicast_label, deag_label, - format_mpls_eos_bit, MPLS_NON_EOS); + format_mpls_eos_bit, MPLS_EOS); fib_entry_contribute_forwarding(lfe, - FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, - &dpo); + FIB_FORW_CHAIN_TYPE_MPLS_EOS, + &dpo); dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0); - lkd = lookup_dpo_get(dpo1->dpoi_index); + mdd = mpls_disp_dpo_get(dpo1->dpoi_index); + + FIB_TEST((FIB_MPLS_LSP_MODE_UNIFORM == mdd->mdd_mode), + "%U/%U disp is uniform mode", + format_mpls_unicast_label, deag_label, + format_mpls_eos_bit, MPLS_EOS); + + lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index); FIB_TEST((fib_index == lkd->lkd_fib_index), "%U/%U is deag in %d %U", format_mpls_unicast_label, deag_label, - format_mpls_eos_bit, MPLS_NON_EOS, + format_mpls_eos_bit, MPLS_EOS, lkd->lkd_fib_index, format_dpo_id, &dpo, 0); FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input), "%U/%U is dst deag", format_mpls_unicast_label, deag_label, - format_mpls_eos_bit, MPLS_NON_EOS); - - FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto), + format_mpls_eos_bit, MPLS_EOS); + FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto), "%U/%U is %U dst deag", format_mpls_unicast_label, deag_label, - format_mpls_eos_bit, MPLS_NON_EOS, + format_mpls_eos_bit, MPLS_EOS, format_dpo_proto, lkd->lkd_proto); fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI); FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index, - &pfx)), + &pfx)), "%U/%U not present", format_mpls_unicast_label, deag_label, format_mpls_eos_bit, MPLS_EOS); - dpo_reset(&dpo); /* - * An MPLS x-connect + * A route deag route for non-EOS + */ + pfx.fp_eos = MPLS_NON_EOS; + lfe = fib_table_entry_path_add(lfib_index, + &pfx, + FIB_SOURCE_CLI, + FIB_ENTRY_FLAG_NONE, + DPO_PROTO_IP4, + &zero_addr, + ~0, + lfib_index, + 1, + NULL, + FIB_ROUTE_PATH_FLAG_NONE); + + FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)), + "%U/%U present", + format_mpls_unicast_label, deag_label, + format_mpls_eos_bit, MPLS_NON_EOS); + + fib_entry_contribute_forwarding(lfe, + FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, + &dpo); + dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0); + lkd = lookup_dpo_get(dpo1->dpoi_index); + + FIB_TEST((fib_index == lkd->lkd_fib_index), + "%U/%U is deag in %d %U", + format_mpls_unicast_label, deag_label, + format_mpls_eos_bit, MPLS_NON_EOS, + lkd->lkd_fib_index, + format_dpo_id, &dpo, 0); + FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input), + "%U/%U is dst deag", + format_mpls_unicast_label, deag_label, + format_mpls_eos_bit, MPLS_NON_EOS); + + FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto), + "%U/%U is %U dst deag", + format_mpls_unicast_label, deag_label, + format_mpls_eos_bit, MPLS_NON_EOS, + format_dpo_proto, lkd->lkd_proto); + + fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI); + + FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index, + &pfx)), + "%U/%U not present", + format_mpls_unicast_label, deag_label, + format_mpls_eos_bit, MPLS_EOS); + + dpo_reset(&dpo); + + /* + * An MPLS x-connect */ fib_prefix_t pfx_1200 = { .fp_len = 21, @@ -8353,11 +8570,15 @@ lfib_test (void) }; dpo_id_t neos_1200 = DPO_INVALID; dpo_id_t ip_1200 = DPO_INVALID; - mpls_label_t *l200 = NULL; - vec_add1(l200, 200); - vec_add1(l200, 300); - vec_add1(l200, 400); - vec_add1(l200, 500); + fib_mpls_label_t *l200 = NULL; + u32 ii; + for (ii = 0; ii < 4; ii++) + { + fib_mpls_label_t fml = { + .fml_value = 200 + (ii * 100), + }; + vec_add1(l200, fml); + }; lfe = fib_table_entry_update_one_path(fib_index, &pfx_1200, @@ -8416,8 +8637,10 @@ lfib_test (void) .ip4.as_u32 = clib_host_to_net_u32(0x02020204), }, }; - mpls_label_t *l999 = NULL; - vec_add1(l999, 999); + fib_mpls_label_t *l999 = NULL, fml_999 = { + .fml_value = 999, + }; + vec_add1(l999, fml_999); rpaths[0].frp_label_stack = l999, fib_table_entry_path_add2(fib_index, @@ -8472,13 +8695,13 @@ lfib_test (void) * A recursive via a label that does not exist */ fib_test_lb_bucket_t bucket_drop = { - .type = FT_LB_SPECIAL, + .type = FT_LB_DROP, .special = { .adj = DPO_PROTO_IP4, }, }; fib_test_lb_bucket_t mpls_bucket_drop = { - .type = FT_LB_SPECIAL, + .type = FT_LB_DROP, .special = { .adj = DPO_PROTO_MPLS, }, @@ -8583,8 +8806,10 @@ lfib_test (void) .adj = idpo.dpoi_index, }, }; - mpls_label_t *l3300 = NULL; - vec_add1(l3300, 3300); + fib_mpls_label_t *l3300 = NULL, fml_3300 = { + .fml_value = 3300, + }; + vec_add1(l3300, fml_3300); lfe = fib_table_entry_update_one_path(lfib_index, &pfx_3500, @@ -8662,8 +8887,12 @@ lfib_test (void) */ mpls_sw_interface_enable_disable(&mpls_main, tm->hw[0]->sw_if_index, - 0); + 0, 1); + mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API); + FIB_TEST(0 == pool_elts(mpls_disp_dpo_pool), + "mpls_disp_dpo resources freed %d of %d", + 0, pool_elts(mpls_disp_dpo_pool)); FIB_TEST(lb_count == pool_elts(load_balance_pool), "Load-balance resources freed %d of %d", lb_count, pool_elts(load_balance_pool)); @@ -8674,6 +8903,796 @@ lfib_test (void) return (0); } +static int +fib_test_inherit (void) +{ + fib_node_index_t fei; + test_main_t *tm; + int n_feis; + + n_feis = fib_entry_pool_size(); + tm = &test_main; + + const ip46_address_t nh_10_10_10_1 = { + .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01), + }; + const ip46_address_t nh_10_10_10_2 = { + .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02), + }; + const ip46_address_t nh_10_10_10_16 = { + .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a10), + }; + const ip46_address_t nh_10_10_10_20 = { + .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a14), + }; + const ip46_address_t nh_10_10_10_21 = { + .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a15), + }; + const ip46_address_t nh_10_10_10_22 = { + .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a16), + }; + const ip46_address_t nh_10_10_10_255 = { + .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0aff), + }; + const ip46_address_t nh_10_10_10_0 = { + .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a00), + }; + const ip46_address_t nh_10_10_0_0 = { + .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0000), + }; + + /* + * prefixes at the base of a sub-tree + */ + const fib_prefix_t pfx_10_10_10_21_s_32 = { + .fp_len = 32, + .fp_proto = FIB_PROTOCOL_IP4, + .fp_addr = nh_10_10_10_21, + }; + const fib_prefix_t pfx_10_10_10_22_s_32 = { + .fp_len = 32, + .fp_proto = FIB_PROTOCOL_IP4, + .fp_addr = nh_10_10_10_22, + }; + const fib_prefix_t pfx_10_10_10_255_s_32 = { + .fp_len = 32, + .fp_proto = FIB_PROTOCOL_IP4, + .fp_addr = nh_10_10_10_255, + }; + + fib_table_entry_special_add(0, + &pfx_10_10_10_21_s_32, + FIB_SOURCE_CLI, + FIB_ENTRY_FLAG_DROP); + fib_table_entry_special_add(0, + &pfx_10_10_10_22_s_32, + FIB_SOURCE_CLI, + FIB_ENTRY_FLAG_DROP); + fib_table_entry_special_add(0, + &pfx_10_10_10_255_s_32, + FIB_SOURCE_CLI, + FIB_ENTRY_FLAG_DROP); + + /* + * source an entry that pushes its state down the sub-tree + */ + const fib_prefix_t pfx_10_10_10_16_s_28 = { + .fp_len = 28, + .fp_proto = FIB_PROTOCOL_IP4, + .fp_addr = nh_10_10_10_16, + }; + fib_table_entry_update_one_path(0, + &pfx_10_10_10_16_s_28, + FIB_SOURCE_API, + FIB_ENTRY_FLAG_COVERED_INHERIT, + DPO_PROTO_IP4, + &nh_10_10_10_1, + tm->hw[0]->sw_if_index, + ~0, + 1, + NULL, + FIB_ROUTE_PATH_FLAG_NONE); + + /* + * this covering entry and all those below it should have + * the same forwarding information. + */ + adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, + VNET_LINK_IP4, + &nh_10_10_10_1, + tm->hw[0]->sw_if_index); + fib_test_lb_bucket_t adj_o_10_10_10_1 = { + .type = FT_LB_ADJ, + .adj = { + .adj = ai_10_10_10_1, + }, + }; + + fei = fib_table_lookup(0, &pfx_10_10_10_16_s_28); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_16_s_28); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_21_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_22_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32); + FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), + "%U resolves via drop", + format_fib_prefix, &pfx_10_10_10_255_s_32); + + /* + * remove the inherting cover - covereds go back to drop + */ + fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_API); + + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32); + FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), + "%U resolves via drop", + format_fib_prefix, &pfx_10_10_10_21_s_32); + + /* + * source an entry that pushes its state down the sub-tree + */ + const fib_prefix_t pfx_10_10_10_0_s_24 = { + .fp_len = 24, + .fp_proto = FIB_PROTOCOL_IP4, + .fp_addr = nh_10_10_10_0, + }; + fib_table_entry_update_one_path(0, + &pfx_10_10_10_0_s_24, + FIB_SOURCE_API, + FIB_ENTRY_FLAG_COVERED_INHERIT, + DPO_PROTO_IP4, + &nh_10_10_10_1, + tm->hw[0]->sw_if_index, + ~0, + 1, + NULL, + FIB_ROUTE_PATH_FLAG_NONE); + + /* + * whole sub-tree now covered + */ + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_0_s_24); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_21_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_22_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_255_s_32); + + /* + * insert a more specific into the sub-tree - expect inheritance + * this one is directly covered by the root + */ + fib_table_entry_special_add(0, + &pfx_10_10_10_16_s_28, + FIB_SOURCE_CLI, + FIB_ENTRY_FLAG_DROP); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_16_s_28); + + /* + * insert a more specific into the sub-tree - expect inheritance + * this one is indirectly covered by the root + */ + const fib_prefix_t pfx_10_10_10_20_s_30 = { + .fp_len = 30, + .fp_proto = FIB_PROTOCOL_IP4, + .fp_addr = nh_10_10_10_20, + }; + fib_table_entry_special_add(0, + &pfx_10_10_10_20_s_30, + FIB_SOURCE_CLI, + FIB_ENTRY_FLAG_DROP); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_20_s_30); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_20_s_30); + + /* + * remove the prefix from the middle of the sub-tree + * the inherited source will be the only one remaining - expect + * it to be withdrawn and hence the prefix is removed. + */ + fib_table_entry_special_remove(0, + &pfx_10_10_10_20_s_30, + FIB_SOURCE_CLI); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_20_s_30); + FIB_TEST((FIB_NODE_INDEX_INVALID == fei), + "%U gone", + format_fib_prefix, &pfx_10_10_10_20_s_30); + + /* + * inheriting source is modifed - expect the modification to be present + * throughout the sub-tree + */ + adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, + VNET_LINK_IP4, + &nh_10_10_10_2, + tm->hw[0]->sw_if_index); + fib_test_lb_bucket_t adj_o_10_10_10_2 = { + .type = FT_LB_ADJ, + .adj = { + .adj = ai_10_10_10_2, + }, + }; + + fib_table_entry_update_one_path(0, + &pfx_10_10_10_0_s_24, + FIB_SOURCE_API, + FIB_ENTRY_FLAG_COVERED_INHERIT, + DPO_PROTO_IP4, + &nh_10_10_10_2, + tm->hw[0]->sw_if_index, + ~0, + 1, + NULL, + FIB_ROUTE_PATH_FLAG_NONE); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_2), + "%U via 10.10.10.2", + format_fib_prefix, &pfx_10_10_10_21_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_2), + "%U via 10.10.10.2", + format_fib_prefix, &pfx_10_10_10_22_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_2), + "%U via 10.10.10.2", + format_fib_prefix, &pfx_10_10_10_255_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_2), + "%U via 10.10.10.2", + format_fib_prefix, &pfx_10_10_10_0_s_24); + + /* + * add the source that replaces inherited state. + * inheriting source is not the best, so it doesn't push state. + */ + fib_table_entry_update_one_path(0, + &pfx_10_10_10_0_s_24, + FIB_SOURCE_PLUGIN_HI, + FIB_ENTRY_FLAG_NONE, + DPO_PROTO_IP4, + &nh_10_10_10_1, + tm->hw[0]->sw_if_index, + ~0, + 1, + NULL, + FIB_ROUTE_PATH_FLAG_NONE); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_0_s_24); + + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32); + FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), + "%U resolves via drop", + format_fib_prefix, &pfx_10_10_10_21_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32); + FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), + "%U resolves via drop", + format_fib_prefix, &pfx_10_10_10_22_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32); + FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), + "%U resolves via drop", + format_fib_prefix, &pfx_10_10_10_255_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28); + FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), + "%U resolves via drop", + format_fib_prefix, &pfx_10_10_10_16_s_28); + + /* + * withdraw the higher priority source and expect the inherited to return + * throughout the sub-tree + */ + fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, FIB_SOURCE_PLUGIN_HI); + + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_2), + "%U via 10.10.10.2", + format_fib_prefix, &pfx_10_10_10_21_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_2), + "%U via 10.10.10.2", + format_fib_prefix, &pfx_10_10_10_22_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_2), + "%U via 10.10.10.2", + format_fib_prefix, &pfx_10_10_10_255_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_2), + "%U via 10.10.10.2", + format_fib_prefix, &pfx_10_10_10_0_s_24); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_2), + "%U via 10.10.10.2", + format_fib_prefix, &pfx_10_10_10_16_s_28); + + /* + * source a covered entry in the sub-tree with the same inherting source + * - expect that it now owns the sub-tree and thus over-rides its cover + */ + fib_table_entry_update_one_path(0, + &pfx_10_10_10_16_s_28, + FIB_SOURCE_API, + FIB_ENTRY_FLAG_COVERED_INHERIT, + DPO_PROTO_IP4, + &nh_10_10_10_1, + tm->hw[0]->sw_if_index, + ~0, + 1, + NULL, + FIB_ROUTE_PATH_FLAG_NONE); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_16_s_28); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.2", + format_fib_prefix, &pfx_10_10_10_22_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.2", + format_fib_prefix, &pfx_10_10_10_21_s_32); + + /* these two unaffected by the sub-tree change */ + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_2), + "%U via 10.10.10.2", + format_fib_prefix, &pfx_10_10_10_255_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_2), + "%U via 10.10.10.2", + format_fib_prefix, &pfx_10_10_10_0_s_24); + + /* + * removes the more specific, expect the /24 to now re-owns the sub-tree + */ + fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_API); + + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_2), + "%U via 10.10.10.2", + format_fib_prefix, &pfx_10_10_10_16_s_28); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_2), + "%U via 10.10.10.2", + format_fib_prefix, &pfx_10_10_10_21_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_2), + "%U via 10.10.10.2", + format_fib_prefix, &pfx_10_10_10_22_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_2), + "%U via 10.10.10.2", + format_fib_prefix, &pfx_10_10_10_255_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_2), + "%U via 10.10.10.2", + format_fib_prefix, &pfx_10_10_10_0_s_24); + /* + * modify the /24. expect the new forwarding to be pushed down + */ + fib_table_entry_update_one_path(0, + &pfx_10_10_10_0_s_24, + FIB_SOURCE_API, + FIB_ENTRY_FLAG_COVERED_INHERIT, + DPO_PROTO_IP4, + &nh_10_10_10_1, + tm->hw[0]->sw_if_index, + ~0, + 1, + NULL, + FIB_ROUTE_PATH_FLAG_NONE); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_16_s_28); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_21_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_22_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_255_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_0_s_24); + + /* + * add an entry less specific to /24. it should not own the /24's tree + */ + const fib_prefix_t pfx_10_10_0_0_s_16 = { + .fp_len = 16, + .fp_proto = FIB_PROTOCOL_IP4, + .fp_addr = nh_10_10_0_0, + }; + fib_table_entry_update_one_path(0, + &pfx_10_10_0_0_s_16, + FIB_SOURCE_API, + FIB_ENTRY_FLAG_COVERED_INHERIT, + DPO_PROTO_IP4, + &nh_10_10_10_2, + tm->hw[0]->sw_if_index, + ~0, + 1, + NULL, + FIB_ROUTE_PATH_FLAG_NONE); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_16_s_28); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_21_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_22_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_255_s_32); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_1), + "%U via 10.10.10.1", + format_fib_prefix, &pfx_10_10_10_0_s_24); + fei = fib_table_lookup_exact_match(0, &pfx_10_10_0_0_s_16); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP4, + 1, + &adj_o_10_10_10_2), + "%U via 10.10.10.2", + format_fib_prefix, &pfx_10_10_0_0_s_16); + + /* + * cleanup + */ + fib_table_entry_delete(0, &pfx_10_10_10_21_s_32, FIB_SOURCE_CLI); + fib_table_entry_delete(0, &pfx_10_10_10_22_s_32, FIB_SOURCE_CLI); + fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_CLI); + fib_table_entry_delete(0, &pfx_10_10_10_255_s_32, FIB_SOURCE_CLI); + fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, FIB_SOURCE_API); + fib_table_entry_delete(0, &pfx_10_10_0_0_s_16, FIB_SOURCE_API); + adj_unlock(ai_10_10_10_1); + adj_unlock(ai_10_10_10_2); + + /* + * test the v6 tree walk. + * a /64 that covers everytinhg. a /96 that covers one /128 + * a second /128 covered only by the /64. + */ + const fib_prefix_t pfx_2001_s_64 = { + .fp_len = 64, + .fp_proto = FIB_PROTOCOL_IP6, + .fp_addr = { + .ip6 = { + .as_u64 = { + [0] = clib_host_to_net_u64(0x2001000000000000), + [1] = clib_host_to_net_u64(0x0000000000000000), + }, + }, + }, + }; + const fib_prefix_t pfx_2001_1_s_96 = { + .fp_len = 96, + .fp_proto = FIB_PROTOCOL_IP6, + .fp_addr = { + .ip6 = { + .as_u64 = { + [0] = clib_host_to_net_u64(0x2001000000000000), + [1] = clib_host_to_net_u64(0x1000000000000000), + }, + }, + }, + }; + const fib_prefix_t pfx_2001_1_1_s_128 = { + .fp_len = 128, + .fp_proto = FIB_PROTOCOL_IP6, + .fp_addr = { + .ip6 = { + .as_u64 = { + [0] = clib_host_to_net_u64(0x2001000000000000), + [1] = clib_host_to_net_u64(0x1000000000000001), + }, + }, + }, + }; + const fib_prefix_t pfx_2001_0_1_s_128 = { + .fp_len = 128, + .fp_proto = FIB_PROTOCOL_IP6, + .fp_addr = { + .ip6 = { + .as_u64 = { + [0] = clib_host_to_net_u64(0x2001000000000000), + [1] = clib_host_to_net_u64(0x0000000000000001), + }, + }, + }, + }; + const ip46_address_t nh_3000_1 = { + .ip6 = { + .as_u64 = { + [0] = clib_host_to_net_u64(0x3000000000000000), + [1] = clib_host_to_net_u64(0x0000000000000001), + }, + }, + }; + const ip46_address_t nh_3000_2 = { + .ip6 = { + .as_u64 = { + [0] = clib_host_to_net_u64(0x3000000000000000), + [1] = clib_host_to_net_u64(0x0000000000000002), + }, + }, + }; + adj_index_t ai_3000_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6, + VNET_LINK_IP6, + &nh_3000_1, + tm->hw[0]->sw_if_index); + adj_index_t ai_3000_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6, + VNET_LINK_IP6, + &nh_3000_2, + tm->hw[0]->sw_if_index); + fib_test_lb_bucket_t adj_o_3000_1 = { + .type = FT_LB_ADJ, + .adj = { + .adj = ai_3000_1, + }, + }; + fib_test_lb_bucket_t adj_o_3000_2 = { + .type = FT_LB_ADJ, + .adj = { + .adj = ai_3000_2, + }, + }; + + fib_table_entry_special_add(0, + &pfx_2001_0_1_s_128, + FIB_SOURCE_CLI, + FIB_ENTRY_FLAG_DROP); + fib_table_entry_special_add(0, + &pfx_2001_1_1_s_128, + FIB_SOURCE_CLI, + FIB_ENTRY_FLAG_DROP); + + /* + * /96 has inherited forwarding pushed down to its covered /128 + */ + fib_table_entry_update_one_path(0, + &pfx_2001_1_s_96, + FIB_SOURCE_API, + FIB_ENTRY_FLAG_COVERED_INHERIT, + DPO_PROTO_IP6, + &nh_3000_1, + tm->hw[0]->sw_if_index, + ~0, + 1, + NULL, + FIB_ROUTE_PATH_FLAG_NONE); + fei = fib_table_lookup_exact_match(0, &pfx_2001_1_s_96); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP6, + 1, + &adj_o_3000_1), + "%U via 3000::1", + format_fib_prefix, &pfx_2001_1_s_96); + fei = fib_table_lookup_exact_match(0, &pfx_2001_1_1_s_128); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP6, + 1, + &adj_o_3000_1), + "%U via 3000::1", + format_fib_prefix, &pfx_2001_1_1_s_128); + fei = fib_table_lookup_exact_match(0, &pfx_2001_0_1_s_128); + FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), + "%U resolves via drop", + format_fib_prefix, &pfx_2001_0_1_s_128); + + /* + * /64 has inherited forwarding pushed down to all, but the /96 + * and its sub-tree remain unaffected. + */ + fib_table_entry_update_one_path(0, + &pfx_2001_s_64, + FIB_SOURCE_API, + FIB_ENTRY_FLAG_COVERED_INHERIT, + DPO_PROTO_IP6, + &nh_3000_2, + tm->hw[0]->sw_if_index, + ~0, + 1, + NULL, + FIB_ROUTE_PATH_FLAG_NONE); + + fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP6, + 1, + &adj_o_3000_2), + "%U via 3000::2", + format_fib_prefix, &pfx_2001_s_64); + fei = fib_table_lookup_exact_match(0, &pfx_2001_0_1_s_128); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP6, + 1, + &adj_o_3000_2), + "%U via 3000::1", + format_fib_prefix, &pfx_2001_0_1_s_128); + + fei = fib_table_lookup_exact_match(0, &pfx_2001_1_s_96); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP6, + 1, + &adj_o_3000_1), + "%U via 3000::1", + format_fib_prefix, &pfx_2001_1_s_96); + fei = fib_table_lookup_exact_match(0, &pfx_2001_1_1_s_128); + FIB_TEST(fib_test_validate_entry(fei, + FIB_FORW_CHAIN_TYPE_UNICAST_IP6, + 1, + &adj_o_3000_1), + "%U via 3000::1", + format_fib_prefix, &pfx_2001_1_1_s_128); + + /* + * Cleanup + */ + fib_table_entry_delete(0, &pfx_2001_0_1_s_128, FIB_SOURCE_CLI); + fib_table_entry_delete(0, &pfx_2001_1_1_s_128, FIB_SOURCE_CLI); + fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API); + fib_table_entry_delete(0, &pfx_2001_1_s_96, FIB_SOURCE_API); + adj_unlock(ai_3000_1); + adj_unlock(ai_3000_2); + + /* + * test no-one left behind + */ + FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone"); + FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed"); + return (0); +} + static clib_error_t * fib_test (vlib_main_t * vm, unformat_input_t * input, @@ -8718,6 +9737,10 @@ fib_test (vlib_main_t * vm, { res += fib_test_bfd(); } + else if (unformat (input, "inherit")) + { + res += fib_test_inherit(); + } else { res += fib_test_v4(); @@ -8726,6 +9749,7 @@ fib_test (vlib_main_t * vm, res += fib_test_bfd(); res += fib_test_pref(); res += fib_test_label(); + res += fib_test_inherit(); res += lfib_test(); /*