diff options
author | Neale Ranns <nranns@cisco.com> | 2018-12-03 10:48:27 +0000 |
---|---|---|
committer | Ole Trøan <otroan@employees.org> | 2018-12-03 13:21:12 +0000 |
commit | 494a09a3959f3782a7c7f1fa42b7d16a99c98630 (patch) | |
tree | ebee049201a5778a769faa0d0f9ce5e68a5b74ff /src/vnet/fib | |
parent | 64fb99568fd4a38d0696cd1d6a0cafb3d5203c3e (diff) |
move [m]fib and BIER tests to unittest plugin
Change-Id: I9d2f52e756363df011026773bfffa838a557313f
Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'src/vnet/fib')
-rw-r--r-- | src/vnet/fib/fib_test.c | 10551 |
1 files changed, 0 insertions, 10551 deletions
diff --git a/src/vnet/fib/fib_test.c b/src/vnet/fib/fib_test.c deleted file mode 100644 index e26cc674a88..00000000000 --- a/src/vnet/fib/fib_test.c +++ /dev/null @@ -1,10551 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <vnet/fib/fib_test.h> -#include <vnet/fib/ip6_fib.h> -#include <vnet/fib/ip4_fib.h> -#include <vnet/fib/mpls_fib.h> -#include <vnet/adj/adj.h> -#include <vnet/dpo/load_balance.h> -#include <vnet/dpo/load_balance_map.h> -#include <vnet/dpo/mpls_label_dpo.h> -#include <vnet/dpo/lookup_dpo.h> -#include <vnet/dpo/drop_dpo.h> -#include <vnet/dpo/receive_dpo.h> -#include <vnet/dpo/ip_null_dpo.h> -#include <vnet/bfd/bfd_main.h> -#include <vnet/dpo/interface_rx_dpo.h> -#include <vnet/dpo/replicate_dpo.h> -#include <vnet/dpo/dvr_dpo.h> -#include <vnet/dpo/mpls_disposition.h> -#include <vnet/dpo/punt_dpo.h> - -#include <vnet/mpls/mpls.h> - -#include <vnet/fib/fib_test.h> -#include <vnet/fib/fib_path_list.h> -#include <vnet/fib/fib_entry_src.h> -#include <vnet/fib/fib_walk.h> -#include <vnet/fib/fib_node_list.h> -#include <vnet/fib/fib_urpf_list.h> - -#include <vlib/unix/plugin.h> - -/* - * Add debugs for passing tests - */ -static int fib_test_do_debug; - -#define FIB_TEST_I(_cond, _comment, _args...) \ -({ \ - int _evald = (_cond); \ - if (!(_evald)) { \ - fformat(stderr, "FAIL:%d: " _comment "\n", \ - __LINE__, ##_args); \ - res = 1; \ - } else { \ - if (fib_test_do_debug) \ - fformat(stderr, "PASS:%d: " _comment "\n", \ - __LINE__, ##_args); \ - } \ - res; \ -}) -#define FIB_TEST(_cond, _comment, _args...) \ -{ \ - if (FIB_TEST_I(_cond, _comment, ##_args)) { \ - return 1; \ - ASSERT(!("FAIL: " _comment)); \ - } \ -} - -/** - * A 'i'm not fussed is this is not efficient' store of test data - */ -typedef struct test_main_t_ { - /** - * HW if indicies - */ - u32 hw_if_indicies[4]; - /** - * HW interfaces - */ - vnet_hw_interface_t * hw[4]; - -} test_main_t; -static test_main_t test_main; - -/* fake ethernet device class, distinct from "fake-ethX" */ -static u8 * format_test_interface_name (u8 * s, va_list * args) -{ - u32 dev_instance = va_arg (*args, u32); - return format (s, "test-eth%d", dev_instance); -} - -static uword dummy_interface_tx (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - clib_warning ("you shouldn't be here, leaking buffers..."); - return frame->n_vectors; -} - -static clib_error_t * -test_interface_admin_up_down (vnet_main_t * vnm, - u32 hw_if_index, - u32 flags) -{ - u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? - VNET_HW_INTERFACE_FLAG_LINK_UP : 0; - vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags); - return 0; -} - -VNET_DEVICE_CLASS (test_interface_device_class,static) = { - .name = "Test interface", - .format_device_name = format_test_interface_name, - .tx_function = dummy_interface_tx, - .admin_up_down_function = test_interface_admin_up_down, -}; - -static u8 *hw_address; - -static int -fib_test_mk_intf (u32 ninterfaces) -{ - clib_error_t * error = NULL; - test_main_t *tm = &test_main; - u32 i, res; - u8 byte; - - res = 0; - ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies)); - - for (i=0; i<6; i++) - { - byte = 0xd0+i; - vec_add1(hw_address, byte); - } - - for (i = 0; i < ninterfaces; i++) - { - hw_address[5] = i; - - error = ethernet_register_interface(vnet_get_main(), - test_interface_device_class.index, - i /* instance */, - hw_address, - &tm->hw_if_indicies[i], - /* flag change */ 0); - - FIB_TEST((NULL == error), "ADD interface %d", i); - - error = vnet_hw_interface_set_flags(vnet_get_main(), - tm->hw_if_indicies[i], - VNET_HW_INTERFACE_FLAG_LINK_UP); - tm->hw[i] = vnet_get_hw_interface(vnet_get_main(), - tm->hw_if_indicies[i]); - vec_validate (ip4_main.fib_index_by_sw_if_index, - tm->hw[i]->sw_if_index); - vec_validate (ip6_main.fib_index_by_sw_if_index, - tm->hw[i]->sw_if_index); - ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0; - ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0; - - error = vnet_sw_interface_set_flags(vnet_get_main(), - tm->hw[i]->sw_if_index, - VNET_SW_INTERFACE_FLAG_ADMIN_UP); - FIB_TEST((NULL == error), "UP interface %d", i); - } - /* - * re-eval after the inevitable realloc - */ - for (i = 0; i < ninterfaces; i++) - { - tm->hw[i] = vnet_get_hw_interface(vnet_get_main(), - tm->hw_if_indicies[i]); - } - - return (res); -} - -#define FIB_TEST_REC_FORW(_rec_prefix, _via_prefix, _bucket) \ - { \ - const dpo_id_t *_rec_dpo = fib_entry_contribute_ip_forwarding( \ - fib_table_lookup_exact_match(fib_index, (_rec_prefix))); \ - const dpo_id_t *_via_dpo = fib_entry_contribute_ip_forwarding( \ - fib_table_lookup(fib_index, (_via_prefix))); \ - FIB_TEST(!dpo_cmp(_via_dpo, \ - load_balance_get_bucket(_rec_dpo->dpoi_index, \ - _bucket)), \ - "%U is recursive via %U", \ - format_fib_prefix, (_rec_prefix), \ - format_fib_prefix, _via_prefix); \ - } - -#define FIB_TEST_LB_BUCKET_VIA_ADJ(_prefix, _bucket, _ai) \ - { \ - const dpo_id_t *_dpo = fib_entry_contribute_ip_forwarding( \ - fib_table_lookup_exact_match(fib_index, (_prefix))); \ - const dpo_id_t *_dpo1 = \ - load_balance_get_bucket(_dpo->dpoi_index, _bucket); \ - FIB_TEST(DPO_ADJACENCY == _dpo1->dpoi_type, "type is %U", \ - format_dpo_type, _dpo1->dpoi_type); \ - FIB_TEST((_ai == _dpo1->dpoi_index), \ - "%U bucket %d resolves via %U", \ - format_fib_prefix, (_prefix), \ - _bucket, \ - format_dpo_id, _dpo1, 0); \ - } - -#define FIB_TEST_RPF(_cond, _comment, _args...) \ - { \ - if (FIB_TEST_I(_cond, _comment, ##_args)) { \ - res = 1; \ - goto cleanup; \ - } \ - } - -static int -fib_test_urpf_is_equal (fib_node_index_t fei, - fib_forward_chain_type_t fct, - u32 num, ...) -{ - dpo_id_t dpo = DPO_INVALID; - fib_urpf_list_t *urpf; - int ii, res; - index_t ui; - va_list ap; - - va_start(ap, num); - - res = 0; - fib_entry_contribute_forwarding(fei, fct, &dpo); - ui = load_balance_get_urpf(dpo.dpoi_index); - - urpf = fib_urpf_list_get(ui); - - FIB_TEST_RPF(num == vec_len(urpf->furpf_itfs), - "RPF:%U len %d == %d", - format_fib_urpf_list, ui, - num, vec_len(urpf->furpf_itfs)); - FIB_TEST_RPF(num == fib_urpf_check_size(ui), - "RPF:%U check-size %d == %d", - format_fib_urpf_list, ui, - num, vec_len(urpf->furpf_itfs)); - - for (ii = 0; ii < num; ii++) - { - adj_index_t ai = va_arg(ap, adj_index_t); - - FIB_TEST_RPF(ai == urpf->furpf_itfs[ii], - "RPF:%d item:%d - %d == %d", - ui, ii, ai, urpf->furpf_itfs[ii]); - FIB_TEST_RPF(fib_urpf_check(ui, ai), - "RPF:%d %d found", - ui, ai); - } - - dpo_reset(&dpo); - -cleanup: - va_end(ap); - - return (res); -} - -static u8* -fib_test_build_rewrite (u8 *eth_addr) -{ - u8* rewrite = NULL; - - vec_validate(rewrite, 13); - - memcpy(rewrite, eth_addr, 6); - memcpy(rewrite+6, eth_addr, 6); - - return (rewrite); -} - -#define FIB_TEST_LB(_cond, _comment, _args...) \ - { \ - if (FIB_TEST_I(_cond, _comment, ##_args)) { \ - return (1); \ - } \ - } - -int -fib_test_validate_rep_v (const replicate_t *rep, - u16 n_buckets, - va_list *ap) -{ - const fib_test_rep_bucket_t *exp; - const dpo_id_t *dpo; - int bucket, res; - - res = 0; - FIB_TEST_LB((n_buckets == rep->rep_n_buckets), - "n_buckets = %d", rep->rep_n_buckets); - - for (bucket = 0; bucket < n_buckets; bucket++) - { - exp = va_arg(*ap, fib_test_rep_bucket_t*); - - dpo = replicate_get_bucket_i(rep, bucket); - - switch (exp->type) - { - case FT_REP_LABEL_O_ADJ: - { - const mpls_label_dpo_t *mld; - mpls_label_t hdr; - - 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); - - mld = mpls_label_dpo_get(dpo->dpoi_index); - hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl); - - FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) == - exp->label_o_adj.label), - "bucket %d stacks on label %d", - bucket, - exp->label_o_adj.label); - - FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) == - exp->label_o_adj.eos), - "bucket %d stacks on label %d %U", - bucket, - exp->label_o_adj.label, - format_mpls_eos_bit, exp->label_o_adj.eos); - - FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type), - "bucket %d label stacks on %U", - bucket, - format_dpo_type, mld->mld_dpo.dpoi_type); - - FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index), - "bucket %d label stacks on adj %d", - bucket, - exp->label_o_adj.adj); - } - break; - case FT_REP_INTF: - FIB_TEST_LB((DPO_INTERFACE_RX == 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_REP_DISP_MFIB_LOOKUP: -// ASSERT(0); - break; - } - } - - return (res); -} - -int -fib_test_validate_lb_v (const load_balance_t *lb, - int n_buckets, - va_list *ap) -{ - const dpo_id_t *dpo; - int bucket, res; - - res = 0; - FIB_TEST_LB((n_buckets == lb->lb_n_buckets), "n_buckets = %d", lb->lb_n_buckets); - - for (bucket = 0; bucket < n_buckets; bucket++) - { - const fib_test_lb_bucket_t *exp; - - exp = va_arg(*ap, fib_test_lb_bucket_t*); - dpo = load_balance_get_bucket_i(lb, bucket); - - switch (exp->type) - { - 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; - - 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, - "label stack size", - mld->mld_n_labels); - - for (ii = 0; ii < mld->mld_n_labels; ii++) - { - hdr = clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl); - FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) == - exp->label_stack_o_adj.label_stack[ii]), - "bucket %d stacks on label %d", - bucket, - exp->label_stack_o_adj.label_stack[ii]); - - if (ii == mld->mld_n_labels-1) - { - FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) == - exp->label_o_adj.eos), - "bucket %d stacks on label %d %U!=%U", - bucket, - exp->label_stack_o_adj.label_stack[ii], - format_mpls_eos_bit, exp->label_o_adj.eos, - format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr)); - } - else - { - FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) == MPLS_NON_EOS), - "bucket %d stacks on label %d %U", - bucket, - exp->label_stack_o_adj.label_stack[ii], - format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr)); - } - } - - FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type), - "bucket %d label stacks on %U", - bucket, - format_dpo_type, mld->mld_dpo.dpoi_type); - - FIB_TEST_LB((exp->label_stack_o_adj.adj == mld->mld_dpo.dpoi_index), - "bucket %d label stacks on adj %d", - bucket, - exp->label_stack_o_adj.adj); - } - break; - case FT_LB_LABEL_O_ADJ: - { - const mpls_label_dpo_t *mld; - mpls_label_t hdr; - 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); - - mld = mpls_label_dpo_get(dpo->dpoi_index); - hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl); - - FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) == - exp->label_o_adj.label), - "bucket %d stacks on label %d", - bucket, - exp->label_o_adj.label); - - FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) == - exp->label_o_adj.eos), - "bucket %d stacks on label %d %U", - bucket, - exp->label_o_adj.label, - format_mpls_eos_bit, exp->label_o_adj.eos); - - FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type), - "bucket %d label stacks on %U", - bucket, - format_dpo_type, mld->mld_dpo.dpoi_type); - - FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index), - "bucket %d label stacks on adj %d", - bucket, - exp->label_o_adj.adj); - } - break; - case FT_LB_LABEL_O_LB: - { - const mpls_label_dpo_t *mld; - mpls_label_dpo_flags_t mf; - mpls_label_t hdr; - - 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); - - FIB_TEST_LB(1 == mld->mld_n_labels, "label stack size", - mld->mld_n_labels); - FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) == - exp->label_o_lb.label), - "bucket %d stacks on label %d", - bucket, - exp->label_o_lb.label); - - FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) == - exp->label_o_lb.eos), - "bucket %d stacks on label %d %U", - bucket, - exp->label_o_lb.label, - format_mpls_eos_bit, exp->label_o_lb.eos); - - FIB_TEST_LB((DPO_LOAD_BALANCE == mld->mld_dpo.dpoi_type), - "bucket %d label stacks on %U", - bucket, - format_dpo_type, mld->mld_dpo.dpoi_type); - - FIB_TEST_LB((exp->label_o_lb.lb == mld->mld_dpo.dpoi_index), - "bucket %d label stacks on LB %d", - bucket, - exp->label_o_lb.lb); - } - break; - case FT_LB_ADJ: - res = 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_MPLS_DISP_PIPE_O_ADJ: - { - const mpls_disp_dpo_t *mdd; - - res = 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; - - res = 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: - res = FIB_TEST_I((DPO_INTERFACE_RX == 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_L2: - res = 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: - res = FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type), - "bucket %d stacks on %U", - bucket, - format_dpo_type, dpo->dpoi_type); - FIB_TEST_LB((exp->lb.lb == dpo->dpoi_index), - "bucket %d stacks on lb %d not %d", - bucket, - dpo->dpoi_index, - exp->lb.lb); - break; - 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->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; - case FT_LB_PUNT: - FIB_TEST_LB((DPO_PUNT == dpo->dpoi_type), - "bucket %d stacks on %U", - bucket, - format_dpo_type, dpo->dpoi_type); - break; - } - } - return (res); -} - -int -fib_test_validate_lb (const dpo_id_t *dpo, - int n_buckets, - ...) -{ - const load_balance_t *lb; - va_list ap; - int res; - - res = 0; - 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 = 1; - } - - va_end(ap); - - return (res); -} - -int -fib_test_validate_entry (fib_node_index_t fei, - fib_forward_chain_type_t fct, - int n_buckets, - ...) -{ - dpo_id_t dpo = DPO_INVALID; - const fib_prefix_t *pfx; - index_t fw_lbi; - u32 fib_index; - va_list ap; - int res; - - - res = 0; - pfx = fib_entry_get_prefix(fei); - fib_index = fib_entry_get_fib_index(fei); - fib_entry_contribute_forwarding(fei, fct, &dpo); - - if (DPO_REPLICATE == dpo.dpoi_type) - { - const replicate_t *rep; - - va_start(ap, n_buckets); - rep = replicate_get(dpo.dpoi_index); - res = fib_test_validate_rep_v(rep, n_buckets, &ap); - va_end (ap); - } - else - { - const load_balance_t *lb; - - FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type), - "%U Entry links to %U", - format_fib_prefix, pfx, - format_dpo_type, dpo.dpoi_type); - - va_start(ap, n_buckets); - lb = load_balance_get(dpo.dpoi_index); - res = fib_test_validate_lb_v(lb, n_buckets, &ap); - va_end(ap); - - /* - * ensure that the LB contributed by the entry is the - * same as the LB in the forwarding tables - */ - if (fct == fib_entry_get_default_chain_type(fib_entry_get(fei))) - { - switch (pfx->fp_proto) - { - case FIB_PROTOCOL_IP4: - fw_lbi = ip4_fib_forwarding_lookup(fib_index, &pfx->fp_addr.ip4); - break; - case FIB_PROTOCOL_IP6: - fw_lbi = ip6_fib_table_fwding_lookup(&ip6_main, fib_index, &pfx->fp_addr.ip6); - break; - case FIB_PROTOCOL_MPLS: - { - mpls_unicast_header_t hdr = { - .label_exp_s_ttl = 0, - }; - - vnet_mpls_uc_set_label(&hdr.label_exp_s_ttl, pfx->fp_label); - vnet_mpls_uc_set_s(&hdr.label_exp_s_ttl, pfx->fp_eos); - hdr.label_exp_s_ttl = clib_host_to_net_u32(hdr.label_exp_s_ttl); - - fw_lbi = mpls_fib_table_forwarding_lookup(fib_index, &hdr); - break; - } - default: - fw_lbi = 0; - } - FIB_TEST_LB((fw_lbi == dpo.dpoi_index), - "Contributed LB = FW LB:\n fwd:%U\n cont:%U", - format_load_balance, fw_lbi, 0, - format_load_balance, dpo.dpoi_index, 0); - } - } - - dpo_reset(&dpo); - - return (res); -} - -static int -fib_test_v4 (void) -{ - /* - * In the default table check for the presence and correct forwarding - * of the special entries - */ - fib_node_index_t dfrt, fei, ai, ai2, locked_ai, ai_01, ai_02, ai_03; - const dpo_id_t *dpo, *dpo1, *dpo2, *dpo_drop; - const ip_adjacency_t *adj; - const load_balance_t *lb; - test_main_t *tm; - u32 fib_index; - int lb_count; - int ii, res; - - res = 0; - /* via 10.10.10.1 */ - ip46_address_t nh_10_10_10_1 = { - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01), - }; - /* via 10.10.10.2 */ - ip46_address_t nh_10_10_10_2 = { - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02), - }; - - FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d", - pool_elts(load_balance_map_pool)); - - tm = &test_main; - - /* record the nubmer of load-balances in use before we start */ - 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_SOURCE_API); - - for (ii = 0; ii < 4; ii++) - { - ip4_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index; - } - - fib_prefix_t pfx_0_0_0_0_s_0 = { - .fp_len = 0, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4 = { - {0} - }, - }, - }; - - fib_prefix_t pfx = { - .fp_len = 0, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4 = { - {0} - }, - }, - }; - - dpo_drop = drop_dpo_get(DPO_PROTO_IP4); - - dfrt = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0); - FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present"); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)), - "Default route is DROP"); - - pfx.fp_len = 32; - fei = fib_table_lookup(fib_index, &pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all zeros route present"); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "all 0s route is DROP"); - - pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xffffffff); - pfx.fp_len = 32; - fei = fib_table_lookup(fib_index, &pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all ones route present"); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "all 1s route is DROP"); - - pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xe0000000); - pfx.fp_len = 8; - fei = fib_table_lookup(fib_index, &pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all-mcast route present"); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "all-mcast route is DROP"); - - pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xf0000000); - pfx.fp_len = 8; - fei = fib_table_lookup(fib_index, &pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "class-e route present"); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "class-e route is DROP"); - - /* - * at this stage there are 5 entries in the test FIB (plus 5 in the default), - * all of which are special sourced and so none of which share path-lists. - * There are also 2 entries, and 2 non-shared path-lists, in the v6 default - * table, and 4 path-lists in the v6 MFIB table - */ -#define ENBR (5+5+2) - - u32 PNBR = 5+5+2+4; - - /* - * if the IGMP plugin is loaded this adds two more entries to the v4 MFIB - */ - 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()); - FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * add interface routes. - * validate presence of /24 attached and /32 recieve. - * test for the presence of the receive address in the glean and local adj - */ - fib_prefix_t local_pfx = { - .fp_len = 24, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4 = { - .as_u32 = clib_host_to_net_u32(0x0a0a0a0a), - }, - }, - }; - - fib_table_entry_update_one_path(fib_index, &local_pfx, - FIB_SOURCE_INTERFACE, - (FIB_ENTRY_FLAG_CONNECTED | - FIB_ENTRY_FLAG_ATTACHED), - DPO_PROTO_IP4, - NULL, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, // weight - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup(fib_index, &local_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present"); - FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) == - fib_entry_get_flags(fei)), - "Flags set on attached interface"); - - ai = fib_entry_get_adj(fei); - FIB_TEST((FIB_NODE_INDEX_INVALID != ai), - "attached interface route adj present %d", ai); - adj = adj_get(ai); - FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index), - "attached interface adj is glean"); - FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr, - &adj->sub_type.glean.receive_addr)), - "attached interface adj is receive ok"); - - local_pfx.fp_len = 32; - fib_table_entry_update_one_path(fib_index, &local_pfx, - FIB_SOURCE_INTERFACE, - (FIB_ENTRY_FLAG_CONNECTED | - FIB_ENTRY_FLAG_LOCAL), - DPO_PROTO_IP4, - NULL, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, // weight - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup(fib_index, &local_pfx); - FIB_TEST(((FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_CONNECTED) == - fib_entry_get_flags(fei)), - "Flags set on local interface"); - - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present"); - - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0), - "RPF list for local length 0"); - dpo = load_balance_get_bucket(dpo->dpoi_index, 0); - FIB_TEST((DPO_RECEIVE == dpo->dpoi_type), - "local interface adj is local"); - receive_dpo_t *rd = receive_dpo_get(dpo->dpoi_index); - - FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr, - &rd->rd_addr)), - "local interface adj is receive ok"); - - FIB_TEST((2 == fib_table_get_num_entries(fib_index, - FIB_PROTOCOL_IP4, - FIB_SOURCE_INTERFACE)), - "2 Interface Source'd prefixes"); - - /* - * +2 interface routes +2 non-shared path-lists - */ - FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty"); - FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * Modify the default route to be via an adj not yet known. - * this sources the defalut route with the API source, which is - * a higher preference to the DEFAULT_ROUTE source - */ - pfx.fp_addr.ip4.as_u32 = 0; - pfx.fp_len = 0; - fib_table_entry_path_add(fib_index, &pfx, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup(fib_index, &pfx); - FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)), - "Flags set on API route"); - - FIB_TEST((fei == dfrt), "default route same index"); - ai = fib_entry_get_adj(fei); - FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present"); - adj = adj_get(ai); - FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index), - "adj is incomplete"); - FIB_TEST((0 == ip46_address_cmp(&nh_10_10_10_1, &adj->sub_type.nbr.next_hop)), - "adj nbr next-hop ok"); - FIB_TEST((1 == fib_table_get_num_entries(fib_index, - FIB_PROTOCOL_IP4, - FIB_SOURCE_API)), - "1 API Source'd prefixes"); - - /* - * find the adj in the shared db - */ - locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index); - FIB_TEST((locked_ai == ai), "ADJ NBR DB find"); - adj_unlock(locked_ai); - - /* - * +1 shared path-list - */ - FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+3 == fib_path_list_pool_size()), "path list pool size is%d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * remove the API source from the default route. We expected - * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP - */ - pfx.fp_addr.ip4.as_u32 = 0; - pfx.fp_len = 0; - fib_table_entry_path_remove(fib_index, &pfx, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // non-recursive path, so no FIB index - 1, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup(fib_index, &pfx); - - FIB_TEST((fei == dfrt), "default route same index"); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "Default route is DROP"); - - /* - * -1 shared-path-list - */ - FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty"); - FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * Add an 2 ARP entry => a complete ADJ plus adj-fib. - */ - fib_prefix_t pfx_10_10_10_1_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 10.10.10.1 */ - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01), - }, - }; - fib_prefix_t pfx_10_10_10_2_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 10.10.10.2 */ - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02), - }, - }; - fib_prefix_t pfx_11_11_11_11_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 11.11.11.11 */ - .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b), - }, - }; - u8 eth_addr[] = { - 0xde, 0xde, 0xde, 0xba, 0xba, 0xba, - }; - - ip46_address_t nh_12_12_12_12 = { - .ip4.as_u32 = clib_host_to_net_u32(0x0c0c0c0c), - }; - adj_index_t ai_12_12_12_12; - - /* - * Add a route via an incomplete ADJ. then complete the ADJ - * Expect the route LB is updated to use complete adj type. - */ - fei = fib_table_entry_update_one_path(fib_index, - &pfx_11_11_11_11_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_ATTACHED, - DPO_PROTO_IP4, - &pfx_10_10_10_1_s_32.fp_addr, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - dpo = fib_entry_contribute_ip_forwarding(fei); - dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0); - FIB_TEST(DPO_ADJACENCY_INCOMPLETE == dpo1->dpoi_type, - "11.11.11.11/32 via incomplete adj"); - - ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_IP4, - &pfx_10_10_10_1_s_32.fp_addr, - tm->hw[0]->sw_if_index); - FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created"); - adj = adj_get(ai_01); - FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index), - "adj is incomplete"); - FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr, - &adj->sub_type.nbr.next_hop)), - "adj nbr next-hop ok"); - - adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE, - fib_test_build_rewrite(eth_addr)); - FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index), - "adj is complete"); - FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr, - &adj->sub_type.nbr.next_hop)), - "adj nbr next-hop ok"); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj"); - - dpo = fib_entry_contribute_ip_forwarding(fei); - dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0); - FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, - "11.11.11.11/32 via complete adj"); - FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, - tm->hw[0]->sw_if_index), - "RPF list for adj-fib contains adj"); - - ai_12_12_12_12 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_IP4, - &nh_12_12_12_12, - tm->hw[1]->sw_if_index); - FIB_TEST((FIB_NODE_INDEX_INVALID != ai_12_12_12_12), "adj created"); - adj = adj_get(ai_12_12_12_12); - FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index), - "adj is incomplete"); - FIB_TEST((0 == ip46_address_cmp(&nh_12_12_12_12, - &adj->sub_type.nbr.next_hop)), - "adj nbr next-hop ok"); - adj_nbr_update_rewrite(ai_12_12_12_12, ADJ_NBR_REWRITE_FLAG_COMPLETE, - fib_test_build_rewrite(eth_addr)); - FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index), - "adj is complete"); - - /* - * add the adj fib - */ - fei = fib_table_entry_path_add(fib_index, - &pfx_10_10_10_1_s_32, - FIB_SOURCE_ADJ, - FIB_ENTRY_FLAG_ATTACHED, - DPO_PROTO_IP4, - &pfx_10_10_10_1_s_32.fp_addr, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)), - "Flags set on adj-fib"); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj, %d", ai); - - fib_table_entry_path_remove(fib_index, - &pfx_11_11_11_11_s_32, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &pfx_10_10_10_1_s_32.fp_addr, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - FIB_ROUTE_PATH_FLAG_NONE); - - eth_addr[5] = 0xb2; - - ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_IP4, - &pfx_10_10_10_2_s_32.fp_addr, - tm->hw[0]->sw_if_index); - FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created"); - adj = adj_get(ai_02); - FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index), - "adj is incomplete"); - FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr, - &adj->sub_type.nbr.next_hop)), - "adj nbr next-hop ok"); - - adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE, - fib_test_build_rewrite(eth_addr)); - FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index), - "adj is complete"); - FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr, - &adj->sub_type.nbr.next_hop)), - "adj nbr next-hop ok"); - FIB_TEST((ai_01 != ai_02), "ADJs are different"); - - fib_table_entry_path_add(fib_index, - &pfx_10_10_10_2_s_32, - FIB_SOURCE_ADJ, - FIB_ENTRY_FLAG_ATTACHED, - DPO_PROTO_IP4, - &pfx_10_10_10_2_s_32.fp_addr, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj"); - - /* - * +2 adj-fibs, and their non-shared path-lists - */ - FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty"); - FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * Add 2 routes via the first ADJ. ensure path-list sharing - */ - fib_prefix_t pfx_1_1_1_1_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 1.1.1.1/32 */ - .ip4.as_u32 = clib_host_to_net_u32(0x01010101), - }, - }; - - fib_table_entry_path_add(fib_index, - &pfx_1_1_1_1_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_01 == ai), "1.1.1.1 resolves via 10.10.10.1"); - - /* - * +1 entry and a shared path-list - */ - FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty"); - FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* 1.1.2.0/24 */ - fib_prefix_t pfx_1_1_2_0_s_24 = { - .fp_len = 24, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x01010200), - } - }; - - fib_table_entry_path_add(fib_index, - &pfx_1_1_2_0_s_24, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1"); - - /* - * +1 entry only - */ - FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty"); - FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * modify 1.1.2.0/24 to use multipath. - */ - fib_table_entry_path_add(fib_index, - &pfx_1_1_2_0_s_24, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_2, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, tm->hw[0]->sw_if_index), - "RPF list for 1.1.2.0/24 contains both adjs"); - - dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0); - FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type); - FIB_TEST((ai_01 == dpo1->dpoi_index), - "1.1.2.0/24 bucket 0 resolves via 10.10.10.1 (%d=%d)", - ai_01, dpo1->dpoi_index); - - dpo1 = load_balance_get_bucket(dpo->dpoi_index, 1); - FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type); - FIB_TEST((ai_02 == dpo1->dpoi_index), - "1.1.2.0/24 bucket 1 resolves via 10.10.10.2"); - - /* - * +1 shared-pathlist - */ - FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty"); - FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * revert the modify - */ - fib_table_entry_path_remove(fib_index, - &pfx_1_1_2_0_s_24, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &nh_10_10_10_2, - tm->hw[0]->sw_if_index, - ~0, - 1, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, tm->hw[0]->sw_if_index), - "RPF list for 1.1.2.0/24 contains one adj"); - - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1"); - - /* - * +1 shared-pathlist - */ - FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d", - fib_path_list_db_size()); - FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * Add 2 recursive routes: - * 100.100.100.100/32 via 1.1.1.1/32 => the via entry is installed. - * 100.100.100.101/32 via 1.1.1.1/32 => the via entry is installed. - */ - fib_prefix_t bgp_100_pfx = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 100.100.100.100/32 */ - .ip4.as_u32 = clib_host_to_net_u32(0x64646464), - }, - }; - /* via 1.1.1.1 */ - ip46_address_t nh_1_1_1_1 = { - .ip4.as_u32 = clib_host_to_net_u32(0x01010101), - }; - - fei = fib_table_entry_path_add(fib_index, - &bgp_100_pfx, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_1_1_1_1, - ~0, // no index provided. - fib_index, // nexthop in same fib as route - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST_REC_FORW(&bgp_100_pfx, &pfx_1_1_1_1_s_32, 0); - FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, - tm->hw[0]->sw_if_index), - "RPF list for adj-fib contains adj"); - - /* - * +1 entry and +1 shared-path-list - */ - FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - fib_prefix_t bgp_101_pfx = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 100.100.100.101/32 */ - .ip4.as_u32 = clib_host_to_net_u32(0x64646465), - }, - }; - - fib_table_entry_path_add(fib_index, - &bgp_101_pfx, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_1_1_1_1, - ~0, // no index provided. - fib_index, // nexthop in same fib as route - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST_REC_FORW(&bgp_101_pfx, &pfx_1_1_1_1_s_32, 0); - FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, - tm->hw[0]->sw_if_index), - "RPF list for adj-fib contains adj"); - - /* - * +1 entry, but the recursive path-list is shared. - */ - FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * An special route; one where the user (me) provides the - * adjacency through which the route will resovle by setting the flags - */ - fib_prefix_t ex_pfx = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 4.4.4.4/32 */ - .ip4.as_u32 = clib_host_to_net_u32(0x04040404), - }, - }; - - fib_table_entry_special_add(fib_index, - &ex_pfx, - FIB_SOURCE_SPECIAL, - FIB_ENTRY_FLAG_LOCAL); - fei = fib_table_lookup_exact_match(fib_index, &ex_pfx); - dpo = fib_entry_contribute_ip_forwarding(fei); - dpo = load_balance_get_bucket(dpo->dpoi_index, 0); - FIB_TEST((DPO_RECEIVE == dpo->dpoi_type), - "local interface adj is local"); - - fib_table_entry_special_remove(fib_index, - &ex_pfx, - FIB_SOURCE_SPECIAL); - FIB_TEST(FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &ex_pfx), - "Exclusive reoute removed"); - - /* - * An EXCLUSIVE route; one where the user (me) provides the exclusive - * adjacency through which the route will resovle - */ - dpo_id_t ex_dpo = DPO_INVALID; - - lookup_dpo_add_or_lock_w_fib_index(fib_index, - DPO_PROTO_IP4, - LOOKUP_UNICAST, - LOOKUP_INPUT_DST_ADDR, - LOOKUP_TABLE_FROM_CONFIG, - &ex_dpo); - - fib_table_entry_special_dpo_add(fib_index, - &ex_pfx, - FIB_SOURCE_SPECIAL, - FIB_ENTRY_FLAG_EXCLUSIVE, - &ex_dpo); - fei = fib_table_lookup_exact_match(fib_index, &ex_pfx); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)), - "exclusive remote uses lookup DPO"); - - /* - * update the exclusive to use a different DPO - */ - ip_null_dpo_add_and_lock(DPO_PROTO_IP4, - IP_NULL_ACTION_SEND_ICMP_UNREACH, - &ex_dpo); - fib_table_entry_special_dpo_update(fib_index, - &ex_pfx, - FIB_SOURCE_SPECIAL, - FIB_ENTRY_FLAG_EXCLUSIVE, - &ex_dpo); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)), - "exclusive remote uses now uses NULL DPO"); - - fib_table_entry_special_remove(fib_index, - &ex_pfx, - FIB_SOURCE_SPECIAL); - FIB_TEST(FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &ex_pfx), - "Exclusive reoute removed"); - dpo_reset(&ex_dpo); - - /* - * Add a recursive route: - * 200.200.200.200/32 via 1.1.1.2/32 => the via entry is NOT installed. - */ - fib_prefix_t bgp_200_pfx = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 200.200.200.200/32 */ - .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c8), - }, - }; - /* via 1.1.1.2 */ - fib_prefix_t pfx_1_1_1_2_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x01010102), - }, - }; - - fei = fib_table_entry_path_add(fib_index, - &bgp_200_pfx, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_1_1_1_2_s_32.fp_addr, - ~0, // no index provided. - fib_index, // nexthop in same fib as route - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "Recursive via unresolved is drop"); - - /* - * the adj should be recursive via drop, since the route resolves via - * the default route, which is itself a DROP - */ - fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32); - dpo1 = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(load_balance_is_drop(dpo1), "1.1.1.2/32 is drop"); - FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0), - "RPF list for 1.1.1.2/32 contains 0 adjs"); - - /* - * +2 entry and +1 shared-path-list - */ - FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * Unequal Cost load-balance. 3:1 ratio. fits in a 4 bucket LB - * The paths are sort by NH first. in this case the the path with greater - * weight is first in the set. This ordering is to test the RPF sort|uniq logic - */ - fib_prefix_t pfx_1_2_3_4_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x01020304), - }, - }; - fib_table_entry_path_add(fib_index, - &pfx_1_2_3_4_s_32, - FIB_SOURCE_API, - 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_entry_path_add(fib_index, - &pfx_1_2_3_4_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_12_12_12_12, - tm->hw[1]->sw_if_index, - ~0, - 3, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.4/32 presnet"); - dpo = fib_entry_contribute_ip_forwarding(fei); - lb = load_balance_get(dpo->dpoi_index); - FIB_TEST((lb->lb_n_buckets == 4), - "1.2.3.4/32 LB has %d bucket", - lb->lb_n_buckets); - - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 0, ai_12_12_12_12); - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 1, ai_12_12_12_12); - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 2, ai_12_12_12_12); - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 3, ai_01); - - FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2, - tm->hw[0]->sw_if_index, - tm->hw[1]->sw_if_index), - "RPF list for 1.2.3.4/32 contains both adjs"); - - - /* - * Unequal Cost load-balance. 4:1 ratio. - * fits in a 16 bucket LB with ratio 13:3 - */ - fib_prefix_t pfx_1_2_3_5_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x01020305), - }, - }; - fib_table_entry_path_add(fib_index, - &pfx_1_2_3_5_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_12_12_12_12, - tm->hw[1]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_entry_path_add(fib_index, - &pfx_1_2_3_5_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, - 4, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.5/32 presnet"); - dpo = fib_entry_contribute_ip_forwarding(fei); - lb = load_balance_get(dpo->dpoi_index); - FIB_TEST((lb->lb_n_buckets == 16), - "1.2.3.5/32 LB has %d bucket", - lb->lb_n_buckets); - - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 0, ai_01); - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 1, ai_01); - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 2, ai_01); - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 3, ai_01); - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 4, ai_01); - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 5, ai_01); - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 6, ai_01); - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 7, ai_01); - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 8, ai_01); - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 9, ai_01); - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 10, ai_01); - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 11, ai_01); - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 12, ai_01); - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 13, ai_12_12_12_12); - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 14, ai_12_12_12_12); - FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 15, ai_12_12_12_12); - - FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2, - tm->hw[0]->sw_if_index, - tm->hw[1]->sw_if_index), - "RPF list for 1.2.3.4/32 contains both adjs"); - - /* - * Test UCMP with a large weight skew - this produces load-balance objects with large - * numbers of buckets to accommodate the skew. By updating said load-balances we are - * laso testing the LB in placce modify code when number of buckets is large. - */ - fib_prefix_t pfx_6_6_6_6_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 1.1.1.1/32 */ - .ip4.as_u32 = clib_host_to_net_u32(0x06060606), - }, - }; - fib_test_lb_bucket_t ip_o_10_10_10_1 = { - .type = FT_LB_ADJ, - .adj = { - .adj = ai_01, - }, - }; - fib_test_lb_bucket_t ip_o_10_10_10_2 = { - .type = FT_LB_ADJ, - .adj = { - .adj = ai_02, - }, - }; - fib_test_lb_bucket_t ip_6_6_6_6_o_12_12_12_12 = { - .type = FT_LB_ADJ, - .adj = { - .adj = ai_12_12_12_12, - }, - }; - fib_table_entry_update_one_path(fib_index, - &pfx_6_6_6_6_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 0, // zero weigth - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &ip_o_10_10_10_1), - "6.6.6.6/32 via 10.10.10.1"); - - fib_table_entry_path_add(fib_index, - &pfx_6_6_6_6_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_2, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 100, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 64, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_1), - "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio"); - - fib_table_entry_path_add(fib_index, - &pfx_6_6_6_6_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_12_12_12_12, - tm->hw[1]->sw_if_index, - ~0, // invalid fib index - 100, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 128, - &ip_o_10_10_10_1, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12, - &ip_6_6_6_6_o_12_12_12_12), - "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio"); - - fib_table_entry_path_remove(fib_index, - &pfx_6_6_6_6_s_32, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &nh_12_12_12_12, - tm->hw[1]->sw_if_index, - ~0, // invalid fib index - 100, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 64, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_2, - &ip_o_10_10_10_1), - "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio"); - - fib_table_entry_path_remove(fib_index, - &pfx_6_6_6_6_s_32, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &nh_10_10_10_2, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 100, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &ip_o_10_10_10_1), - "6.6.6.6/32 via 10.10.10.1"); - - fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API); - - /* - * A recursive via the two unequal cost entries - */ - fib_prefix_t bgp_44_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 200.200.200.201/32 */ - .ip4.as_u32 = clib_host_to_net_u32(0x44444444), - }, - }; - fei = fib_table_entry_path_add(fib_index, - &bgp_44_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_1_2_3_4_s_32.fp_addr, - ~0, - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_entry_path_add(fib_index, - &bgp_44_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_1_2_3_5_s_32.fp_addr, - ~0, - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_4_s_32, 0); - FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_5_s_32, 1); - FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2, - tm->hw[0]->sw_if_index, - tm->hw[1]->sw_if_index), - "RPF list for 1.2.3.4/32 contains both adjs"); - - /* - * test the uRPF check functions - */ - dpo_id_t dpo_44 = DPO_INVALID; - index_t urpfi; - - fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44); - urpfi = load_balance_get_urpf(dpo_44.dpoi_index); - - FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index), - "uRPF check for 68.68.68.68/32 on %d OK", - tm->hw[0]->sw_if_index); - FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index), - "uRPF check for 68.68.68.68/32 on %d OK", - tm->hw[1]->sw_if_index); - FIB_TEST(!fib_urpf_check(urpfi, 99), - "uRPF check for 68.68.68.68/32 on 99 not-OK", - 99); - dpo_reset(&dpo_44); - - fib_table_entry_delete(fib_index, - &bgp_44_s_32, - FIB_SOURCE_API); - fib_table_entry_delete(fib_index, - &pfx_1_2_3_5_s_32, - FIB_SOURCE_API); - fib_table_entry_delete(fib_index, - &pfx_1_2_3_4_s_32, - FIB_SOURCE_API); - - /* - * Add a recursive route: - * 200.200.200.201/32 via 1.1.1.200/32 => the via entry is NOT installed. - */ - fib_prefix_t bgp_201_pfx = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 200.200.200.201/32 */ - .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c9), - }, - }; - /* via 1.1.1.200 */ - fib_prefix_t pfx_1_1_1_200_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x010101c8), - }, - }; - - fei = fib_table_entry_path_add(fib_index, - &bgp_201_pfx, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_1_1_1_200_s_32.fp_addr, - ~0, // no index provided. - fib_index, // nexthop in same fib as route - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "Recursive via unresolved is drop"); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32); - FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)), - "Flags set on RR via non-attached"); - FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0), - "RPF list for BGP route empty"); - - /* - * +2 entry (BGP & RR) and +1 shared-path-list - */ - FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * insert a route that covers the missing 1.1.1.2/32. we epxect - * 200.200.200.200/32 and 200.200.200.201/32 to resolve through it. - */ - fib_prefix_t pfx_1_1_1_0_s_24 = { - .fp_len = 24, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 1.1.1.0/24 */ - .ip4.as_u32 = clib_host_to_net_u32(0x01010100), - }, - }; - - fib_table_entry_path_add(fib_index, - &pfx_1_1_1_0_s_24, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24); - dpo1 = fib_entry_contribute_ip_forwarding(fei); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_01 == ai), "1.1.1.0/24 resolves via 10.10.10.1"); - fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32); - dpo1 = fib_entry_contribute_ip_forwarding(fei); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_01 == ai), "1.1.1.2/32 resolves via 10.10.10.1"); - fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32); - dpo1 = fib_entry_contribute_ip_forwarding(fei); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_01 == ai), "1.1.1.200/24 resolves via 10.10.10.1"); - - /* - * +1 entry. 1.1.1.1/32 already uses 10.10.10.1 so no new pah-list - */ - FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * the recursive adj for 200.200.200.200 should be updated. - */ - FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0); - FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0); - fei = fib_table_lookup(fib_index, &bgp_200_pfx); - FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, - tm->hw[0]->sw_if_index), - "RPF list for BGP route has itf index 0"); - - /* - * insert a more specific route than 1.1.1.0/24 that also covers the - * missing 1.1.1.2/32, but not 1.1.1.200/32. we expect - * 200.200.200.200 to resolve through it. - */ - fib_prefix_t pfx_1_1_1_0_s_28 = { - .fp_len = 28, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 1.1.1.0/24 */ - .ip4.as_u32 = clib_host_to_net_u32(0x01010100), - }, - }; - - fib_table_entry_path_add(fib_index, - &pfx_1_1_1_0_s_28, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_2, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28); - dpo2 = fib_entry_contribute_ip_forwarding(fei); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_02 == ai), "1.1.1.0/24 resolves via 10.10.10.2"); - - /* - * +1 entry. +1 shared path-list - */ - FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+9 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+14 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * the recursive adj for 200.200.200.200 should be updated. - * 200.200.200.201 remains unchanged. - */ - FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0); - FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0); - - /* - * remove this /28. 200.200.200.200/32 should revert back to via 1.1.1.0/24 - */ - fib_table_entry_path_remove(fib_index, - &pfx_1_1_1_0_s_28, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &nh_10_10_10_2, - tm->hw[0]->sw_if_index, - ~0, - 1, - FIB_ROUTE_PATH_FLAG_NONE); - FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28) == - FIB_NODE_INDEX_INVALID), - "1.1.1.0/28 removed"); - FIB_TEST((fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28) == - fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24)), - "1.1.1.0/28 lookup via /24"); - FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0); - FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0); - - /* - * -1 entry. -1 shared path-list - */ - FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * remove 1.1.1.0/24. 200.200.200.200/32 should revert back to via 0.0.0.0/0 - */ - fib_table_entry_path_remove(fib_index, - &pfx_1_1_1_0_s_24, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, - 1, - FIB_ROUTE_PATH_FLAG_NONE); - FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_24) == - FIB_NODE_INDEX_INVALID), - "1.1.1.0/24 removed"); - - fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "1.1.1.2/32 route is DROP"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "1.1.1.200/32 route is DROP"); - - fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "201 is drop"); - fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "200 is drop"); - - /* - * -1 entry - */ - FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * insert the missing 1.1.1.2/32 - */ - fei = fib_table_entry_path_add(fib_index, - &pfx_1_1_1_2_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - dpo1 = fib_entry_contribute_ip_forwarding(fei); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai = ai_01), "1.1.1.2/32 resolves via 10.10.10.1"); - - fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "201 is drop"); - FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0); - - /* - * no change. 1.1.1.2/32 was already there RR sourced. - */ - FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * give 201 a resolved path. - * it now has the unresolved 1.1.1.200 and the resolved 1.1.1.2, - * only the latter contributes forwarding. - */ - fei = fib_table_entry_path_add(fib_index, - &bgp_201_pfx, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_1_1_1_2_s_32.fp_addr, - ~0, - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_2_s_32, 0); - fib_table_entry_path_remove(fib_index, - &bgp_201_pfx, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &pfx_1_1_1_2_s_32.fp_addr, - ~0, - fib_index, - 1, - FIB_ROUTE_PATH_FLAG_NONE); - - /* - * remove 200.200.200.201/32 which does not have a valid via FIB - */ - fib_table_entry_path_remove(fib_index, - &bgp_201_pfx, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &pfx_1_1_1_200_s_32.fp_addr, - ~0, // no index provided. - fib_index, - 1, - FIB_ROUTE_PATH_FLAG_NONE); - - /* - * -2 entries (BGP and RR). -1 shared path-list; - */ - FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) == - FIB_NODE_INDEX_INVALID), - "200.200.200.201/32 removed"); - FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32) == - FIB_NODE_INDEX_INVALID), - "1.1.1.200/32 removed"); - - FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * remove 200.200.200.200/32 which does have a valid via FIB - */ - fib_table_entry_path_remove(fib_index, - &bgp_200_pfx, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &pfx_1_1_1_2_s_32.fp_addr, - ~0, // no index provided. - fib_index, - 1, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) == - FIB_NODE_INDEX_INVALID), - "200.200.200.200/32 removed"); - FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32) != - FIB_NODE_INDEX_INVALID), - "1.1.1.2/32 still present"); - - /* - * -1 entry (BGP, the RR source is also API sourced). -1 shared path-list; - */ - FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+9 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * A recursive prefix that has a 2 path load-balance. - * It also shares a next-hop with other BGP prefixes and hence - * test the ref counting of RR sourced prefixes and 2 level LB. - */ - const fib_prefix_t bgp_102 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 100.100.100.101/32 */ - .ip4.as_u32 = clib_host_to_net_u32(0x64646466), - }, - }; - fib_table_entry_path_add(fib_index, - &bgp_102, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_1_1_1_1_s_32.fp_addr, - ~0, // no index provided. - fib_index, // same as route - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fib_table_entry_path_add(fib_index, - &bgp_102, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_1_1_1_2_s_32.fp_addr, - ~0, // no index provided. - fib_index, // same as route's FIB - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(fib_index, &bgp_102); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "100.100.100.102/32 presnet"); - dpo = fib_entry_contribute_ip_forwarding(fei); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32); - dpo1 = fib_entry_contribute_ip_forwarding(fei); - fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32); - dpo2 = fib_entry_contribute_ip_forwarding(fei); - - lb = load_balance_get(dpo->dpoi_index); - FIB_TEST((lb->lb_n_buckets == 2), "Recursive LB has %d bucket", lb->lb_n_buckets); - FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)), - "First via 10.10.10.1"); - FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 1)), - "Second via 10.10.10.1"); - - fib_table_entry_path_remove(fib_index, - &bgp_102, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &pfx_1_1_1_1_s_32.fp_addr, - ~0, // no index provided. - fib_index, // same as route's FIB - 1, - FIB_ROUTE_PATH_FLAG_NONE); - fib_table_entry_path_remove(fib_index, - &bgp_102, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &pfx_1_1_1_2_s_32.fp_addr, - ~0, // no index provided. - fib_index, // same as route's FIB - 1, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(fib_index, &bgp_102); - FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "100.100.100.102/32 removed"); - - /* - * remove the remaining recursives - */ - fib_table_entry_path_remove(fib_index, - &bgp_100_pfx, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &pfx_1_1_1_1_s_32.fp_addr, - ~0, // no index provided. - fib_index, // same as route's FIB - 1, - FIB_ROUTE_PATH_FLAG_NONE); - fib_table_entry_path_remove(fib_index, - &bgp_101_pfx, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &pfx_1_1_1_1_s_32.fp_addr, - ~0, // no index provided. - fib_index, // same as route's FIB - 1, - FIB_ROUTE_PATH_FLAG_NONE); - FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_100_pfx) == - FIB_NODE_INDEX_INVALID), - "100.100.100.100/32 removed"); - FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_101_pfx) == - FIB_NODE_INDEX_INVALID), - "100.100.100.101/32 removed"); - - /* - * -2 entry (2*BGP, the RR source is also API sourced). -1 shared path-list; - */ - FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * Add a recursive route via a connected cover, using an adj-fib that does exist - */ - fib_table_entry_path_add(fib_index, - &bgp_200_pfx, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_1, - ~0, // no index provided. - fib_index, // Same as route's FIB - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - /* - * +1 entry. +1 shared path-list (recursive via 10.10.10.1) - */ - FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx); - dpo = fib_entry_contribute_ip_forwarding(fei); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32); - dpo1 = fib_entry_contribute_ip_forwarding(fei); - - FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)), - "200.200.200.200/32 is recursive via adj for 10.10.10.1"); - - FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)), - "Flags set on RR via existing attached"); - - /* - * Add a recursive route via a connected cover, using and adj-fib that does - * not exist - */ - ip46_address_t nh_10_10_10_3 = { - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03), - }; - fib_prefix_t pfx_10_10_10_3 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = nh_10_10_10_3, - }; - - fib_table_entry_path_add(fib_index, - &bgp_201_pfx, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_3, - ~0, // no index provided. - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - /* - * +2 entries (BGP and RR). +1 shared path-list (recursive via 10.10.10.3) and - * one unshared non-recursive via 10.10.10.3 - */ - FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_IP4, - &nh_10_10_10_3, - tm->hw[0]->sw_if_index); - - fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx); - dpo = fib_entry_contribute_ip_forwarding(fei); - fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3); - dpo1 = fib_entry_contribute_ip_forwarding(fei); - - ai = fib_entry_get_adj(fei); - FIB_TEST((ai == ai_03), "adj for 10.10.10.3/32 is via adj for 10.10.10.3"); - FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) == - fib_entry_get_flags(fei)), - "Flags set on RR via non-existing attached"); - - FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)), - "adj for 200.200.200.200/32 is recursive via adj for 10.10.10.3"); - - adj_unlock(ai_03); - - /* - * remove the recursives - */ - fib_table_entry_path_remove(fib_index, - &bgp_200_pfx, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &nh_10_10_10_1, - ~0, // no index provided. - fib_index, // same as route's FIB - 1, - FIB_ROUTE_PATH_FLAG_NONE); - fib_table_entry_path_remove(fib_index, - &bgp_201_pfx, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &nh_10_10_10_3, - ~0, // no index provided. - fib_index, // same as route's FIB - 1, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) == - FIB_NODE_INDEX_INVALID), - "200.200.200.201/32 removed"); - FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) == - FIB_NODE_INDEX_INVALID), - "200.200.200.200/32 removed"); - FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3) == - FIB_NODE_INDEX_INVALID), - "10.10.10.3/32 removed"); - - /* - * -3 entries (2*BGP and RR). -2 shared path-list (recursive via 10.10.10.3 & - * 10.10.10.1) and one unshared non-recursive via 10.10.10.3 - */ - FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - - /* - * RECURSION LOOPS - * Add 5.5.5.5/32 -> 5.5.5.6/32 -> 5.5.5.7/32 -> 5.5.5.5/32 - */ - fib_prefix_t pfx_5_5_5_5_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x05050505), - }, - }; - fib_prefix_t pfx_5_5_5_6_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x05050506), - }, - }; - fib_prefix_t pfx_5_5_5_7_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x05050507), - }, - }; - - fib_table_entry_path_add(fib_index, - &pfx_5_5_5_5_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_5_5_5_6_s_32.fp_addr, - ~0, // no index provided. - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fib_table_entry_path_add(fib_index, - &pfx_5_5_5_6_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_5_5_5_7_s_32.fp_addr, - ~0, // no index provided. - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fib_table_entry_path_add(fib_index, - &pfx_5_5_5_7_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_5_5_5_5_s_32.fp_addr, - ~0, // no index provided. - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - /* - * +3 entries, +3 shared path-list - */ - FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * All the entries have only looped paths, so they are all drop - */ - fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "LB for 5.5.5.7/32 is via adj for DROP"); - fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "LB for 5.5.5.5/32 is via adj for DROP"); - fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "LB for 5.5.5.6/32 is via adj for DROP"); - - /* - * provide 5.5.5.6/32 with alternate path. - * this will allow only 5.5.5.6/32 to forward with this path, the others - * are still drop since the loop is still present. - */ - fib_table_entry_path_add(fib_index, - &pfx_5_5_5_6_s_32, - FIB_SOURCE_API, - 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(fib_index, &pfx_5_5_5_6_s_32); - dpo1 = fib_entry_contribute_ip_forwarding(fei); - - lb = load_balance_get(dpo1->dpoi_index); - FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.6 LB has %d bucket", lb->lb_n_buckets); - - dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0); - FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type); - FIB_TEST((ai_01 == dpo2->dpoi_index), - "5.5.5.6 bucket 0 resolves via 10.10.10.2"); - - fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "LB for 5.5.5.7/32 is via adj for DROP"); - fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "LB for 5.5.5.5/32 is via adj for DROP"); - - /* - * remove the alternate path for 5.5.5.6/32 - * back to all drop - */ - fib_table_entry_path_remove(fib_index, - &pfx_5_5_5_6_s_32, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, - 1, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "LB for 5.5.5.7/32 is via adj for DROP"); - fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "LB for 5.5.5.5/32 is via adj for DROP"); - fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "LB for 5.5.5.6/32 is via adj for DROP"); - - /* - * break the loop by giving 5.5.5.5/32 a new set of paths - * expect all to forward via this new path. - */ - fib_table_entry_update_one_path(fib_index, - &pfx_5_5_5_5_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32); - dpo1 = fib_entry_contribute_ip_forwarding(fei); - lb = load_balance_get(dpo1->dpoi_index); - FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.5 LB has %d bucket", lb->lb_n_buckets); - - dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0); - FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type); - FIB_TEST((ai_01 == dpo2->dpoi_index), - "5.5.5.5 bucket 0 resolves via 10.10.10.2"); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_7_s_32); - dpo2 = fib_entry_contribute_ip_forwarding(fei); - - lb = load_balance_get(dpo2->dpoi_index); - FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets); - FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo2->dpoi_index, 0)), - "5.5.5.5.7 via 5.5.5.5"); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32); - dpo1 = fib_entry_contribute_ip_forwarding(fei); - - lb = load_balance_get(dpo1->dpoi_index); - FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets); - FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)), - "5.5.5.5.6 via 5.5.5.7"); - - /* - * revert back to the loop. so we can remove the prefixes with - * the loop intact - */ - fib_table_entry_update_one_path(fib_index, - &pfx_5_5_5_5_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_5_5_5_6_s_32.fp_addr, - ~0, // no index provided. - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "LB for 5.5.5.7/32 is via adj for DROP"); - fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "LB for 5.5.5.5/32 is via adj for DROP"); - fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "LB for 5.5.5.6/32 is via adj for DROP"); - - /* - * remove all the 5.5.5.x/32 prefixes - */ - fib_table_entry_path_remove(fib_index, - &pfx_5_5_5_5_s_32, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &pfx_5_5_5_6_s_32.fp_addr, - ~0, // no index provided. - fib_index, // same as route's FIB - 1, - FIB_ROUTE_PATH_FLAG_NONE); - fib_table_entry_path_remove(fib_index, - &pfx_5_5_5_6_s_32, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &pfx_5_5_5_7_s_32.fp_addr, - ~0, // no index provided. - fib_index, // same as route's FIB - 1, - FIB_ROUTE_PATH_FLAG_NONE); - fib_table_entry_path_remove(fib_index, - &pfx_5_5_5_7_s_32, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &pfx_5_5_5_5_s_32.fp_addr, - ~0, // no index provided. - fib_index, // same as route's FIB - 1, - FIB_ROUTE_PATH_FLAG_NONE); - fib_table_entry_path_remove(fib_index, - &pfx_5_5_5_6_s_32, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &nh_10_10_10_2, - ~0, // no index provided. - fib_index, // same as route's FIB - 1, - FIB_ROUTE_PATH_FLAG_NONE); - - /* - * -3 entries, -3 shared path-list - */ - FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * Single level loop 5.5.5.5/32 via 5.5.5.5/32 - */ - fib_table_entry_path_add(fib_index, - &pfx_5_5_5_6_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_5_5_5_6_s_32.fp_addr, - ~0, // no index provided. - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "1-level 5.5.5.6/32 loop is via adj for DROP"); - - fib_table_entry_path_remove(fib_index, - &pfx_5_5_5_6_s_32, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &pfx_5_5_5_6_s_32.fp_addr, - ~0, // no index provided. - fib_index, // same as route's FIB - 1, - FIB_ROUTE_PATH_FLAG_NONE); - FIB_TEST(FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32), - "1-level 5.5.5.6/32 loop is removed"); - - /* - * A recursive route whose next-hop is covered by the prefix. - * This would mean the via-fib, which inherits forwarding from its - * cover, thus picks up forwarding from the prfix, which is via the - * via-fib, and we have a loop. - */ - fib_prefix_t pfx_23_23_23_0_s_24 = { - .fp_len = 24, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x17171700), - }, - }; - fib_prefix_t pfx_23_23_23_23_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x17171717), - }, - }; - fei = fib_table_entry_path_add(fib_index, - &pfx_23_23_23_0_s_24, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_23_23_23_23_s_32.fp_addr, - ~0, // recursive - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(load_balance_is_drop(dpo), - "23.23.23.0/24 via covered is DROP"); - fib_table_entry_delete_index(fei, FIB_SOURCE_API); - - /* - * add-remove test. no change. - */ - FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * Make the default route recursive via a unknown next-hop. Thus the - * next hop's cover would be the default route - */ - fei = fib_table_entry_path_add(fib_index, - &pfx_0_0_0_0_s_0, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_23_23_23_23_s_32.fp_addr, - ~0, // recursive - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(load_balance_is_drop(dpo), - "0.0.0.0.0/0 via is DROP"); - FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0), - "no resolving interface for looped 0.0.0.0/0"); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_23_23_23_23_s_32); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(load_balance_is_drop(dpo), - "23.23.23.23/32 via is DROP"); - FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0), - "no resolving interface for looped 23.23.23.23/32"); - - fib_table_entry_delete(fib_index, &pfx_0_0_0_0_s_0, FIB_SOURCE_API); - - /* - * A recursive route with recursion constraints. - * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained - */ - fib_table_entry_path_add(fib_index, - &bgp_200_pfx, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_1_1_1_1, - ~0, - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_RESOLVE_VIA_HOST); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32); - dpo2 = fib_entry_contribute_ip_forwarding(fei); - - fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx); - dpo1 = fib_entry_contribute_ip_forwarding(fei); - - FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)), - "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1"); - - /* - * save the load-balance. we expect it to be inplace modified - */ - lb = load_balance_get(dpo1->dpoi_index); - - /* - * add a covering prefix for the via fib that would otherwise serve - * as the resolving route when the host is removed - */ - fib_table_entry_path_add(fib_index, - &pfx_1_1_1_0_s_28, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai == ai_01), - "adj for 1.1.1.0/28 is via adj for 1.1.1.1"); - - /* - * remove the host via FIB - expect the BGP prefix to be drop - */ - fib_table_entry_path_remove(fib_index, - &pfx_1_1_1_1_s_32, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)), - "adj for 200.200.200.200/32 is recursive via adj for DROP"); - - /* - * add the via-entry host reoute back. expect to resolve again - */ - fib_table_entry_path_add(fib_index, - &pfx_1_1_1_1_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)), - "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1"); - - /* - * add another path for the recursive. it will then have 2. - */ - fib_prefix_t pfx_1_1_1_3_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x01010103), - }, - }; - fib_table_entry_path_add(fib_index, - &pfx_1_1_1_3_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_2, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - fib_table_entry_path_add(fib_index, - &bgp_200_pfx, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_1_1_1_3_s_32.fp_addr, - ~0, - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_RESOLVE_VIA_HOST); - - /* - * add a bunch load more entries using this path combo so that we get - * an LB-map created. - */ -#define N_P 128 - fib_prefix_t bgp_78s[N_P]; - for (ii = 0; ii < N_P; ii++) - { - bgp_78s[ii].fp_len = 32; - bgp_78s[ii].fp_proto = FIB_PROTOCOL_IP4; - bgp_78s[ii].fp_addr.ip4.as_u32 = clib_host_to_net_u32(0x4e000000+ii); - - - fib_table_entry_path_add(fib_index, - &bgp_78s[ii], - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_1_1_1_3_s_32.fp_addr, - ~0, - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_RESOLVE_VIA_HOST); - fib_table_entry_path_add(fib_index, - &bgp_78s[ii], - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_1_1_1_1, - ~0, - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_RESOLVE_VIA_HOST); - } - - fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx); - dpo = fib_entry_contribute_ip_forwarding(fei); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32); - dpo2 = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)), - "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32); - dpo1 = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)), - "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3"); - - /* - * expect the lb-map used by the recursive's load-balance is using both buckets - */ - load_balance_map_t *lbm; - index_t lbmi; - - lb = load_balance_get(dpo->dpoi_index); - lbmi = lb->lb_map; - load_balance_map_lock(lbmi); - lbm = load_balance_map_get(lbmi); - - FIB_TEST(lbm->lbm_buckets[0] == 0, - "LB maps's bucket 0 is %d", - lbm->lbm_buckets[0]); - FIB_TEST(lbm->lbm_buckets[1] == 1, - "LB maps's bucket 1 is %d", - lbm->lbm_buckets[1]); - - /* - * withdraw one of the /32 via-entrys. - * that ECMP path will be unresolved and forwarding should continue on the - * other available path. this is an iBGP PIC edge failover. - * Test the forwarding changes without re-fetching the adj from the - * recursive entry. this ensures its the same one that is updated; i.e. an - * inplace-modify. - */ - fib_table_entry_path_remove(fib_index, - &pfx_1_1_1_1_s_32, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - FIB_ROUTE_PATH_FLAG_NONE); - - /* suspend so the update walk kicks int */ - vlib_process_suspend(vlib_get_main(), 1e-5); - - fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx); - FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)), - "post PIC 200.200.200.200/32 was inplace modified"); - - FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)), - "post PIC adj for 200.200.200.200/32 is recursive" - " via adj for 1.1.1.3"); - - /* - * the LB maps that was locked above should have been modified to remove - * the path that was down, and thus its bucket points to a path that is - * still up. - */ - FIB_TEST(lbm->lbm_buckets[0] == 1, - "LB maps's bucket 0 is %d", - lbm->lbm_buckets[0]); - FIB_TEST(lbm->lbm_buckets[1] == 1, - "LB maps's bucket 1 is %d", - lbm->lbm_buckets[1]); - - load_balance_map_unlock(lbmi); - - /* - * add it back. again - */ - fib_table_entry_path_add(fib_index, - &pfx_1_1_1_1_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - /* suspend so the update walk kicks in */ - vlib_process_suspend(vlib_get_main(), 1e-5); - - FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)), - "post PIC recovery adj for 200.200.200.200/32 is recursive " - "via adj for 1.1.1.1"); - FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)), - "post PIC recovery adj for 200.200.200.200/32 is recursive " - "via adj for 1.1.1.3"); - - fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(lb == load_balance_get(dpo->dpoi_index), - "post PIC 200.200.200.200/32 was inplace modified"); - - /* - * add a 3rd path. this makes the LB 16 buckets. - */ - fib_table_entry_path_add(fib_index, - &bgp_200_pfx, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_1_1_1_2_s_32.fp_addr, - ~0, - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_RESOLVE_VIA_HOST); - for (ii = 0; ii < N_P; ii++) - { - fib_table_entry_path_add(fib_index, - &bgp_78s[ii], - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_1_1_1_2_s_32.fp_addr, - ~0, - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_RESOLVE_VIA_HOST); - } - - fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(lb == load_balance_get(dpo->dpoi_index), - "200.200.200.200/32 was inplace modified for 3rd path"); - FIB_TEST(16 == lb->lb_n_buckets, - "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets"); - - lbmi = lb->lb_map; - load_balance_map_lock(lbmi); - lbm = load_balance_map_get(lbmi); - - for (ii = 0; ii < 16; ii++) - { - FIB_TEST(lbm->lbm_buckets[ii] == ii, - "LB Map for 200.200.200.200/32 at %d is %d", - ii, lbm->lbm_buckets[ii]); - } - - /* - * trigger PIC by removing the first via-entry - * the first 6 buckets of the map should map to the next 6 - */ - fib_table_entry_path_remove(fib_index, - &pfx_1_1_1_1_s_32, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, - 1, - FIB_ROUTE_PATH_FLAG_NONE); - /* suspend so the update walk kicks int */ - vlib_process_suspend(vlib_get_main(), 1e-5); - - fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(lb == load_balance_get(dpo->dpoi_index), - "200.200.200.200/32 was inplace modified for 3rd path"); - FIB_TEST(2 == lb->lb_n_buckets, - "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets"); - - for (ii = 0; ii < 6; ii++) - { - FIB_TEST(lbm->lbm_buckets[ii] == ii+6, - "LB Map for 200.200.200.200/32 at %d is %d", - ii, lbm->lbm_buckets[ii]); - } - for (ii = 6; ii < 16; ii++) - { - FIB_TEST(lbm->lbm_buckets[ii] == ii, - "LB Map for 200.200.200.200/32 at %d is %d", - ii, lbm->lbm_buckets[ii]); - } - load_balance_map_unlock(lbmi); - - /* - * tidy up - */ - fib_table_entry_path_add(fib_index, - &pfx_1_1_1_1_s_32, - FIB_SOURCE_API, - 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); - - for (ii = 0; ii < N_P; ii++) - { - fib_table_entry_delete(fib_index, - &bgp_78s[ii], - FIB_SOURCE_API); - FIB_TEST((FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &bgp_78s[ii])), - "%U removed", - format_fib_prefix, &bgp_78s[ii]); - } - fib_table_entry_path_remove(fib_index, - &bgp_200_pfx, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &pfx_1_1_1_2_s_32.fp_addr, - ~0, - fib_index, - 1, - MPLS_LABEL_INVALID); - fib_table_entry_path_remove(fib_index, - &bgp_200_pfx, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &nh_1_1_1_1, - ~0, - fib_index, - 1, - FIB_ROUTE_PATH_RESOLVE_VIA_HOST); - fib_table_entry_path_remove(fib_index, - &bgp_200_pfx, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &pfx_1_1_1_3_s_32.fp_addr, - ~0, - fib_index, - 1, - FIB_ROUTE_PATH_RESOLVE_VIA_HOST); - fib_table_entry_delete(fib_index, - &pfx_1_1_1_3_s_32, - FIB_SOURCE_API); - fib_table_entry_delete(fib_index, - &pfx_1_1_1_0_s_28, - FIB_SOURCE_API); - /* suspend so the update walk kicks int */ - vlib_process_suspend(vlib_get_main(), 1e-5); - FIB_TEST((FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)), - "1.1.1.1/28 removed"); - FIB_TEST((FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)), - "1.1.1.3/32 removed"); - FIB_TEST((FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)), - "200.200.200.200/32 removed"); - - /* - * add-remove test. no change. - */ - FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * A route whose paths are built up iteratively and then removed - * all at once - */ - fib_prefix_t pfx_4_4_4_4_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 4.4.4.4/32 */ - .ip4.as_u32 = clib_host_to_net_u32(0x04040404), - }, - }; - - fib_table_entry_path_add(fib_index, - &pfx_4_4_4_4_s_32, - FIB_SOURCE_API, - 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); - fib_table_entry_path_add(fib_index, - &pfx_4_4_4_4_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_2, - tm->hw[0]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fib_table_entry_path_add(fib_index, - &pfx_4_4_4_4_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_3, - tm->hw[0]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - 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 present"); - - 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"); - - /* - * add-remove test. no change. - */ - FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * A route with multiple paths at once - */ - fib_route_path_t *r_paths = NULL; - - for (ii = 0; ii < 4; ii++) - { - fib_route_path_t r_path = { - .frp_proto = DPO_PROTO_IP4, - .frp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii), - }, - .frp_sw_if_index = tm->hw[0]->sw_if_index, - .frp_weight = 1, - .frp_fib_index = ~0, - }; - vec_add1(r_paths, r_path); - } - - fib_table_entry_update(fib_index, - &pfx_4_4_4_4_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - r_paths); - - 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); - - lb = load_balance_get(dpo->dpoi_index); - FIB_TEST((lb->lb_n_buckets == 4), "4.4.4.4/32 lb over %d paths", lb->lb_n_buckets); - - 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); - - /* - * add-remove test. no change. - */ - FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * A route deag route - */ - 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_FLAG_NONE); - - 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); - lookup_dpo_t *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_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, - 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); - - /* - * add-remove test. no change. - */ - FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * Duplicate paths: - * add a recursive with duplicate paths. Expect the duplicate to be ignored. - */ - fib_prefix_t pfx_34_1_1_1_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x22010101), - }, - }; - fib_prefix_t pfx_34_34_1_1_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x22220101), - }, - }; - fei = fib_table_entry_path_add(fib_index, - &pfx_34_34_1_1_s_32, - FIB_SOURCE_API, - 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_entry_path_add(fib_index, - &pfx_34_1_1_1_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_34_34_1_1_s_32.fp_addr, - ~0, - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_entry_path_add(fib_index, - &pfx_34_1_1_1_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_34_34_1_1_s_32.fp_addr, - ~0, - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0); - fib_table_entry_delete_index(fei, FIB_SOURCE_API); - fib_table_entry_delete(fib_index, - &pfx_34_34_1_1_s_32, - FIB_SOURCE_API); - - /* - * CLEANUP - * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32 - * all of which are via 10.10.10.1, Itf1 - */ - fib_table_entry_path_remove(fib_index, - &pfx_1_1_1_2_s_32, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, - 1, - FIB_ROUTE_PATH_FLAG_NONE); - fib_table_entry_path_remove(fib_index, - &pfx_1_1_1_1_s_32, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, - 1, - FIB_ROUTE_PATH_FLAG_NONE); - fib_table_entry_path_remove(fib_index, - &pfx_1_1_2_0_s_24, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, - 1, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST(FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32), - "1.1.1.1/32 removed"); - FIB_TEST(FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32), - "1.1.1.2/32 removed"); - FIB_TEST(FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24), - "1.1.2.0/24 removed"); - - /* - * -3 entries and -1 shared path-list - */ - FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * An attached-host route. Expect to link to the incomplete adj - */ - fib_prefix_t pfx_4_1_1_1_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 4.1.1.1/32 */ - .ip4.as_u32 = clib_host_to_net_u32(0x04010101), - }, - }; - fib_table_entry_path_add(fib_index, - &pfx_4_1_1_1_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &zero_addr, - tm->hw[0]->sw_if_index, - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present"); - ai = fib_entry_get_adj(fei); - - ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_IP4, - &pfx_4_1_1_1_s_32.fp_addr, - tm->hw[0]->sw_if_index); - FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ"); - adj_unlock(ai2); - - /* - * +1 entry and +1 shared path-list - */ - FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - fib_table_entry_delete(fib_index, - &pfx_4_1_1_1_s_32, - FIB_SOURCE_API); - - FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * add a v6 prefix via v4 next-hops - */ - 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), - }, - }; - fei = fib_table_entry_path_add(0, //default v6 table - &pfx_2001_s_64, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present"); - ai = fib_entry_get_adj(fei); - adj = adj_get(ai); - FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP), - "2001::/64 via ARP-adj"); - FIB_TEST((adj->ia_link == VNET_LINK_IP6), - "2001::/64 is link type v6"); - FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4), - "2001::/64 ADJ-adj is NH proto v4"); - fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API); - - /* - * add a uRPF exempt prefix: - * test: - * - it's forwarding is drop - * - it's uRPF list is not empty - * - the uRPF list for the default route (it's cover) is empty - */ - fei = fib_table_entry_special_add(fib_index, - &pfx_4_1_1_1_s_32, - FIB_SOURCE_URPF_EXEMPT, - FIB_ENTRY_FLAG_DROP); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(load_balance_is_drop(dpo), - "uRPF exempt 4.1.1.1/32 DROP"); - FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0), - "uRPF list for exempt prefix has itf index 0"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0); - FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0), - "uRPF list for 0.0.0.0/0 empty"); - - fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT); - - /* - * An adj-fib that fails the refinement criteria - no connected cover - */ - fib_prefix_t pfx_12_10_10_2_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 12.10.10.2 */ - .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02), - }, - }; - - fib_table_entry_path_add(fib_index, - &pfx_12_10_10_2_s_32, - FIB_SOURCE_ADJ, - FIB_ENTRY_FLAG_ATTACHED, - DPO_PROTO_IP4, - &pfx_12_10_10_2_s_32.fp_addr, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(dpo_is_drop(dpo), - "no connected cover adj-fib fails refinement: %U", - format_dpo_id, dpo, 0); - - fib_table_entry_delete(fib_index, - &pfx_12_10_10_2_s_32, - FIB_SOURCE_ADJ); - - /* - * An adj-fib that fails the refinement criteria - cover is connected - * but on a different interface - */ - fib_prefix_t pfx_10_10_10_127_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 10.10.10.127 */ - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f), - }, - }; - - fib_table_entry_path_add(fib_index, - &pfx_10_10_10_127_s_32, - FIB_SOURCE_ADJ, - FIB_ENTRY_FLAG_ATTACHED, - DPO_PROTO_IP4, - &pfx_10_10_10_127_s_32.fp_addr, - tm->hw[1]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(dpo_is_drop(dpo), - "wrong interface adj-fib fails refinement"); - - fib_table_entry_delete(fib_index, - &pfx_10_10_10_127_s_32, - FIB_SOURCE_ADJ); - - /* - * add a second path to an adj-fib - * this is a sumiluation of another ARP entry created - * on an interface on which the connected prefix does not exist. - * The second path fails refinement. Expect to forward through the - * first. - */ - fib_prefix_t pfx_10_10_10_3_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 10.10.10.3 */ - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03), - }, - }; - - ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_IP4, - &nh_10_10_10_3, - tm->hw[0]->sw_if_index); - - fib_test_lb_bucket_t ip_o_10_10_10_3 = { - .type = FT_LB_ADJ, - .adj = { - .adj = ai_03, - }, - }; - fei = fib_table_entry_path_add(fib_index, - &pfx_10_10_10_3_s_32, - FIB_SOURCE_ADJ, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_3, - tm->hw[0]->sw_if_index, - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_entry_path_add(fib_index, - &pfx_10_10_10_3_s_32, - FIB_SOURCE_ADJ, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_12_12_12_12, - tm->hw[1]->sw_if_index, - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &ip_o_10_10_10_3), - "10.10.10.3 via 10.10.10.3/Eth0 only"); - - /* - * remove the path that refines the cover, should go unresolved - */ - fib_table_entry_path_remove(fib_index, - &pfx_10_10_10_3_s_32, - FIB_SOURCE_ADJ, - DPO_PROTO_IP4, - &nh_10_10_10_3, - tm->hw[0]->sw_if_index, - fib_index, - 1, - FIB_ROUTE_PATH_FLAG_NONE); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(dpo_is_drop(dpo), - "wrong interface adj-fib fails refinement"); - - /* - * add back the path that refines the cover - */ - fei = fib_table_entry_path_add(fib_index, - &pfx_10_10_10_3_s_32, - FIB_SOURCE_ADJ, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_3, - tm->hw[0]->sw_if_index, - fib_index, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &ip_o_10_10_10_3), - "10.10.10.3 via 10.10.10.3/Eth0 only"); - - /* - * remove the path that does not refine the cover - */ - fib_table_entry_path_remove(fib_index, - &pfx_10_10_10_3_s_32, - FIB_SOURCE_ADJ, - DPO_PROTO_IP4, - &nh_12_12_12_12, - tm->hw[1]->sw_if_index, - fib_index, - 1, - FIB_ROUTE_PATH_FLAG_NONE); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &ip_o_10_10_10_3), - "10.10.10.3 via 10.10.10.3/Eth0 only"); - - /* - * remove the path that does refine, it's the last path, so - * the entry should be gone - */ - fib_table_entry_path_remove(fib_index, - &pfx_10_10_10_3_s_32, - FIB_SOURCE_ADJ, - DPO_PROTO_IP4, - &nh_10_10_10_3, - tm->hw[0]->sw_if_index, - fib_index, - 1, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32); - FIB_TEST((fei == FIB_NODE_INDEX_INVALID), "10.10.10.3 gone"); - - adj_unlock(ai_03); - - /* - * change the table's flow-hash config - expect the update to propagete to - * the entries' load-balance objects - */ - flow_hash_config_t old_hash_config, new_hash_config; - - old_hash_config = fib_table_get_flow_hash_config(fib_index, - FIB_PROTOCOL_IP4); - new_hash_config = (IP_FLOW_HASH_SRC_ADDR | - IP_FLOW_HASH_DST_ADDR); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32); - dpo = fib_entry_contribute_ip_forwarding(fei); - lb = load_balance_get(dpo->dpoi_index); - FIB_TEST((lb->lb_hash_config == old_hash_config), - "Table and LB hash config match: %U", - format_ip_flow_hash_config, lb->lb_hash_config); - - fib_table_set_flow_hash_config(fib_index, FIB_PROTOCOL_IP4, new_hash_config); - - FIB_TEST((lb->lb_hash_config == new_hash_config), - "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: - */ - fib_table_entry_delete(fib_index, - &pfx_10_10_10_1_s_32, - FIB_SOURCE_ADJ); - fib_table_entry_delete(fib_index, - &pfx_10_10_10_2_s_32, - FIB_SOURCE_ADJ); - FIB_TEST(FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32), - "10.10.10.1/32 adj-fib removed"); - FIB_TEST(FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32), - "10.10.10.2/32 adj-fib removed"); - - /* - * -2 entries and -2 non-shared path-list - */ - FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * unlock the adjacencies for which this test provided a rewrite. - * These are the last locks on these adjs. they should thus go away. - */ - adj_unlock(ai_02); - adj_unlock(ai_01); - adj_unlock(ai_12_12_12_12); - - FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d", - adj_nbr_db_size()); - - /* - * CLEANUP - * remove the interface prefixes - */ - local_pfx.fp_len = 32; - fib_table_entry_special_remove(fib_index, &local_pfx, - FIB_SOURCE_INTERFACE); - fei = fib_table_lookup(fib_index, &local_pfx); - - FIB_TEST(FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &local_pfx), - "10.10.10.10/32 adj-fib removed"); - - local_pfx.fp_len = 24; - fib_table_entry_delete(fib_index, &local_pfx, - FIB_SOURCE_INTERFACE); - - FIB_TEST(FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &local_pfx), - "10.10.10.10/24 adj-fib removed"); - - /* - * -2 entries and -2 non-shared path-list - */ - FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * Last but not least, remove the VRF - */ - FIB_TEST((0 == fib_table_get_num_entries(fib_index, - FIB_PROTOCOL_IP4, - FIB_SOURCE_API)), - "NO API Source'd prefixes"); - FIB_TEST((0 == fib_table_get_num_entries(fib_index, - FIB_PROTOCOL_IP4, - FIB_SOURCE_RR)), - "NO RR Source'd prefixes"); - FIB_TEST((0 == fib_table_get_num_entries(fib_index, - FIB_PROTOCOL_IP4, - FIB_SOURCE_INTERFACE)), - "NO INterface Source'd prefixes"); - - 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()); - FIB_TEST((PNBR-5 == fib_path_list_pool_size()), "path list pool size is %d", - fib_path_list_pool_size()); - FIB_TEST((ENBR-5 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - FIB_TEST((ENBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d", - pool_elts(fib_urpf_list_pool)); - FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d", - 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 (res); -} - -static int -fib_test_v6 (void) -{ - /* - * In the default table check for the presence and correct forwarding - * of the special entries - */ - fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02; - const dpo_id_t *dpo, *dpo_drop; - const ip_adjacency_t *adj; - const receive_dpo_t *rd; - test_main_t *tm; - u32 fib_index; - int ii, res; - - res = 0; - FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d", - adj_nbr_db_size()); - - /* via 2001:0:0:1::2 */ - ip46_address_t nh_2001_2 = { - .ip6 = { - .as_u64 = { - [0] = clib_host_to_net_u64(0x2001000000000001), - [1] = clib_host_to_net_u64(0x0000000000000002), - }, - }, - }; - - tm = &test_main; - - 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_SOURCE_API); - - for (ii = 0; ii < 4; ii++) - { - ip6_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index; - } - - fib_prefix_t pfx_0_0 = { - .fp_len = 0, - .fp_proto = FIB_PROTOCOL_IP6, - .fp_addr = { - .ip6 = { - {0, 0}, - }, - }, - }; - - dfrt = fib_table_lookup(fib_index, &pfx_0_0); - FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present"); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)), - "Default route is DROP"); - - dpo = fib_entry_contribute_ip_forwarding(dfrt); - FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup( - &ip6_main, - 1, - &pfx_0_0.fp_addr.ip6)), - "default-route; fwd and non-fwd tables match"); - - // FIXME - check specials. - - /* - * At this stage there is one v4 FIB with 5 routes and two v6 FIBs - * each with 2 entries and a v6 mfib with 4 path-lists. - * All entries are special so no path-list sharing. - */ -#define ENPS (5+4) - u32 PNPS = (5+4+4); - /* - * if the IGMP plugin is loaded this adds two more entries to the v4 MFIB - */ - 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()); - FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * add interface routes. - * validate presence of /64 attached and /128 recieve. - * test for the presence of the receive address in the glean and local adj - * - * receive on 2001:0:0:1::1/128 - */ - fib_prefix_t local_pfx = { - .fp_len = 64, - .fp_proto = FIB_PROTOCOL_IP6, - .fp_addr = { - .ip6 = { - .as_u64 = { - [0] = clib_host_to_net_u64(0x2001000000000001), - [1] = clib_host_to_net_u64(0x0000000000000001), - }, - }, - } - }; - - fib_table_entry_update_one_path(fib_index, &local_pfx, - FIB_SOURCE_INTERFACE, - (FIB_ENTRY_FLAG_CONNECTED | - FIB_ENTRY_FLAG_ATTACHED), - DPO_PROTO_IP6, - NULL, - tm->hw[0]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(fib_index, &local_pfx); - - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present"); - - ai = fib_entry_get_adj(fei); - FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present"); - adj = adj_get(ai); - FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index), - "attached interface adj is glean"); - FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr, - &adj->sub_type.glean.receive_addr)), - "attached interface adj is receive ok"); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup( - &ip6_main, - 1, - &local_pfx.fp_addr.ip6)), - "attached-route; fwd and non-fwd tables match"); - - local_pfx.fp_len = 128; - fib_table_entry_update_one_path(fib_index, &local_pfx, - FIB_SOURCE_INTERFACE, - (FIB_ENTRY_FLAG_CONNECTED | - FIB_ENTRY_FLAG_LOCAL), - DPO_PROTO_IP6, - NULL, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup(fib_index, &local_pfx); - - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present"); - - dpo = fib_entry_contribute_ip_forwarding(fei); - dpo = load_balance_get_bucket(dpo->dpoi_index, 0); - FIB_TEST((DPO_RECEIVE == dpo->dpoi_type), - "local interface adj is local"); - rd = receive_dpo_get(dpo->dpoi_index); - - FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr, - &rd->rd_addr)), - "local interface adj is receive ok"); - - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup( - &ip6_main, - 1, - &local_pfx.fp_addr.ip6)), - "local-route; fwd and non-fwd tables match"); - - /* - * +2 entries. +2 unshared path-lists - */ - FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty"); - FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d", - fib_path_list_pool_size()); - FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * Modify the default route to be via an adj not yet known. - * this sources the defalut route with the API source, which is - * a higher preference to the DEFAULT_ROUTE source - */ - fib_table_entry_path_add(fib_index, &pfx_0_0, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP6, - &nh_2001_2, - tm->hw[0]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup(fib_index, &pfx_0_0); - - FIB_TEST((fei == dfrt), "default route same index"); - ai = fib_entry_get_adj(fei); - FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present"); - adj = adj_get(ai); - FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index), - "adj is incomplete"); - FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)), - "adj nbr next-hop ok"); - - /* - * find the adj in the shared db - */ - locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6, - VNET_LINK_IP6, - &nh_2001_2, - tm->hw[0]->sw_if_index); - FIB_TEST((locked_ai == ai), "ADJ NBR DB find"); - adj_unlock(locked_ai); - - /* - * no more entires. +1 shared path-list - */ - FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNPS+3 == fib_path_list_pool_size()), "path list pool size is%d", - fib_path_list_pool_size()); - FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * remove the API source from the default route. We expected - * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP - */ - fib_table_entry_path_remove(fib_index, &pfx_0_0, - FIB_SOURCE_API, - DPO_PROTO_IP6, - &nh_2001_2, - tm->hw[0]->sw_if_index, - ~0, - 1, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup(fib_index, &pfx_0_0); - - FIB_TEST((fei == dfrt), "default route same index"); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)), - "Default route is DROP"); - - /* - * no more entires. -1 shared path-list - */ - FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d", - fib_path_list_pool_size()); - FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * Add an 2 ARP entry => a complete ADJ plus adj-fib. - */ - fib_prefix_t pfx_2001_1_2_s_128 = { - .fp_len = 128, - .fp_proto = FIB_PROTOCOL_IP6, - .fp_addr = { - .ip6 = { - .as_u64 = { - [0] = clib_host_to_net_u64(0x2001000000000001), - [1] = clib_host_to_net_u64(0x0000000000000002), - }, - }, - } - }; - fib_prefix_t pfx_2001_1_3_s_128 = { - .fp_len = 128, - .fp_proto = FIB_PROTOCOL_IP6, - .fp_addr = { - .ip6 = { - .as_u64 = { - [0] = clib_host_to_net_u64(0x2001000000000001), - [1] = clib_host_to_net_u64(0x0000000000000003), - }, - }, - } - }; - u8 eth_addr[] = { - 0xde, 0xde, 0xde, 0xba, 0xba, 0xba, - }; - - ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6, - VNET_LINK_IP6, - &pfx_2001_1_2_s_128.fp_addr, - tm->hw[0]->sw_if_index); - FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created"); - adj = adj_get(ai_01); - FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index), - "adj is incomplete"); - FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr, - &adj->sub_type.nbr.next_hop)), - "adj nbr next-hop ok"); - - adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE, - fib_test_build_rewrite(eth_addr)); - FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index), - "adj is complete"); - FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr, - &adj->sub_type.nbr.next_hop)), - "adj nbr next-hop ok"); - - fib_table_entry_path_add(fib_index, - &pfx_2001_1_2_s_128, - FIB_SOURCE_ADJ, - FIB_ENTRY_FLAG_ATTACHED, - DPO_PROTO_IP6, - &pfx_2001_1_2_s_128.fp_addr, - tm->hw[0]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj"); - - eth_addr[5] = 0xb2; - - ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6, - VNET_LINK_IP6, - &pfx_2001_1_3_s_128.fp_addr, - tm->hw[0]->sw_if_index); - FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created"); - adj = adj_get(ai_02); - FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index), - "adj is incomplete"); - FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr, - &adj->sub_type.nbr.next_hop)), - "adj nbr next-hop ok"); - - adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE, - fib_test_build_rewrite(eth_addr)); - FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index), - "adj is complete"); - FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr, - &adj->sub_type.nbr.next_hop)), - "adj nbr next-hop ok"); - FIB_TEST((ai_01 != ai_02), "ADJs are different"); - - fib_table_entry_path_add(fib_index, - &pfx_2001_1_3_s_128, - FIB_SOURCE_ADJ, - FIB_ENTRY_FLAG_ATTACHED, - DPO_PROTO_IP6, - &pfx_2001_1_3_s_128.fp_addr, - tm->hw[0]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj"); - - /* - * +2 entries, +2 unshread path-lists. - */ - FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNPS+4 == fib_path_list_pool_size()), "path list pool size is%d", - fib_path_list_pool_size()); - FIB_TEST((ENPS+4 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * Add a 2 routes via the first ADJ. ensure path-list sharing - */ - fib_prefix_t pfx_2001_a_s_64 = { - .fp_len = 64, - .fp_proto = FIB_PROTOCOL_IP6, - .fp_addr = { - .ip6 = { - .as_u64 = { - [0] = clib_host_to_net_u64(0x200100000000000a), - [1] = clib_host_to_net_u64(0x0000000000000000), - }, - }, - } - }; - fib_prefix_t pfx_2001_b_s_64 = { - .fp_len = 64, - .fp_proto = FIB_PROTOCOL_IP6, - .fp_addr = { - .ip6 = { - .as_u64 = { - [0] = clib_host_to_net_u64(0x200100000000000b), - [1] = clib_host_to_net_u64(0x0000000000000000), - }, - }, - } - }; - - fib_table_entry_path_add(fib_index, - &pfx_2001_a_s_64, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP6, - &nh_2001_2, - tm->hw[0]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1"); - fib_table_entry_path_add(fib_index, - &pfx_2001_b_s_64, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP6, - &nh_2001_2, - tm->hw[0]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1"); - - /* - * +2 entries, +1 shared path-list. - */ - FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d", - fib_path_list_pool_size()); - FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * add a v4 prefix via a v6 next-hop - */ - fib_prefix_t pfx_1_1_1_1_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = 0x01010101, - }, - }; - fei = fib_table_entry_path_add(0, // default table - &pfx_1_1_1_1_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP6, - &nh_2001_2, - tm->hw[0]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32), - "1.1.1.1/32 o v6 route present"); - ai = fib_entry_get_adj(fei); - adj = adj_get(ai); - FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP), - "1.1.1.1/32 via ARP-adj"); - FIB_TEST((adj->ia_link == VNET_LINK_IP4), - "1.1.1.1/32 ADJ-adj is link type v4"); - FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6), - "1.1.1.1/32 ADJ-adj is NH proto v6"); - fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API); - - /* - * An attached route - */ - fib_prefix_t pfx_2001_c_s_64 = { - .fp_len = 64, - .fp_proto = FIB_PROTOCOL_IP6, - .fp_addr = { - .ip6 = { - .as_u64 = { - [0] = clib_host_to_net_u64(0x200100000000000c), - [1] = clib_host_to_net_u64(0x0000000000000000), - }, - }, - } - }; - fib_table_entry_path_add(fib_index, - &pfx_2001_c_s_64, - FIB_SOURCE_CLI, - FIB_ENTRY_FLAG_ATTACHED, - DPO_PROTO_IP6, - NULL, - tm->hw[0]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present"); - ai = fib_entry_get_adj(fei); - adj = adj_get(ai); - FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN), - "2001:0:0:c/64 attached resolves via glean"); - - fib_table_entry_path_remove(fib_index, - &pfx_2001_c_s_64, - FIB_SOURCE_CLI, - DPO_PROTO_IP6, - NULL, - tm->hw[0]->sw_if_index, - ~0, - 1, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64); - FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached route removed"); - - /* - * Shutdown the interface on which we have a connected and through - * which the routes are reachable. - * This will result in the connected, adj-fibs, and routes linking to drop - * The local/for-us prefix continues to receive. - */ - clib_error_t * error; - - error = vnet_sw_interface_set_flags(vnet_get_main(), - tm->hw[0]->sw_if_index, - ~VNET_SW_INTERFACE_FLAG_ADMIN_UP); - FIB_TEST((NULL == error), "Interface shutdown OK"); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)), - "2001::b/64 resolves via drop"); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)), - "2001::a/64 resolves via drop"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)), - "2001:0:0:1::3/64 resolves via drop"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)), - "2001:0:0:1::2/64 resolves via drop"); - fei = fib_table_lookup_exact_match(fib_index, &local_pfx); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)), - "2001:0:0:1::1/128 not drop"); - local_pfx.fp_len = 64; - fei = fib_table_lookup_exact_match(fib_index, &local_pfx); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)), - "2001:0:0:1/64 resolves via drop"); - - /* - * no change - */ - FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d", - fib_path_list_pool_size()); - FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * shutdown one of the other interfaces, then add a connected. - * and swap one of the routes to it. - */ - error = vnet_sw_interface_set_flags(vnet_get_main(), - tm->hw[1]->sw_if_index, - ~VNET_SW_INTERFACE_FLAG_ADMIN_UP); - FIB_TEST((NULL == error), "Interface 1 shutdown OK"); - - fib_prefix_t connected_pfx = { - .fp_len = 64, - .fp_proto = FIB_PROTOCOL_IP6, - .fp_addr = { - .ip6 = { - /* 2001:0:0:2::1/64 */ - .as_u64 = { - [0] = clib_host_to_net_u64(0x2001000000000002), - [1] = clib_host_to_net_u64(0x0000000000000001), - }, - }, - } - }; - fib_table_entry_update_one_path(fib_index, &connected_pfx, - FIB_SOURCE_INTERFACE, - (FIB_ENTRY_FLAG_CONNECTED | - FIB_ENTRY_FLAG_ATTACHED), - DPO_PROTO_IP6, - NULL, - tm->hw[1]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(fib_index, &connected_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present"); - dpo = fib_entry_contribute_ip_forwarding(fei); - dpo = load_balance_get_bucket(dpo->dpoi_index, 0); - FIB_TEST(!dpo_cmp(dpo, dpo_drop), - "2001:0:0:2/64 not resolves via drop"); - - connected_pfx.fp_len = 128; - fib_table_entry_update_one_path(fib_index, &connected_pfx, - FIB_SOURCE_INTERFACE, - (FIB_ENTRY_FLAG_CONNECTED | - FIB_ENTRY_FLAG_LOCAL), - DPO_PROTO_IP6, - NULL, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup(fib_index, &connected_pfx); - - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present"); - dpo = fib_entry_contribute_ip_forwarding(fei); - dpo = load_balance_get_bucket(dpo->dpoi_index, 0); - FIB_TEST((DPO_RECEIVE == dpo->dpoi_type), - "local interface adj is local"); - rd = receive_dpo_get(dpo->dpoi_index); - FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr, - &rd->rd_addr)), - "local interface adj is receive ok"); - - /* - * +2 entries, +2 unshared path-lists - */ - FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d", - fib_path_list_pool_size()); - FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - - /* - * bring the interface back up. we expected the routes to return - * to normal forwarding. - */ - error = vnet_sw_interface_set_flags(vnet_get_main(), - tm->hw[0]->sw_if_index, - VNET_SW_INTERFACE_FLAG_ADMIN_UP); - FIB_TEST((NULL == error), "Interface bring-up OK"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj"); - local_pfx.fp_len = 64; - fei = fib_table_lookup_exact_match(fib_index, &local_pfx); - ai = fib_entry_get_adj(fei); - adj = adj_get(ai); - FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index), - "attached interface adj is glean"); - - /* - * Same test as above, but this time the HW interface goes down - */ - error = vnet_hw_interface_set_flags(vnet_get_main(), - tm->hw_if_indicies[0], - ~VNET_HW_INTERFACE_FLAG_LINK_UP); - FIB_TEST((NULL == error), "Interface shutdown OK"); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)), - "2001::b/64 resolves via drop"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)), - "2001::a/64 resolves via drop"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)), - "2001:0:0:1::3/128 resolves via drop"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)), - "2001:0:0:1::2/128 resolves via drop"); - local_pfx.fp_len = 128; - fei = fib_table_lookup_exact_match(fib_index, &local_pfx); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)), - "2001:0:0:1::1/128 not drop"); - local_pfx.fp_len = 64; - fei = fib_table_lookup_exact_match(fib_index, &local_pfx); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)), - "2001:0:0:1/64 resolves via drop"); - - error = vnet_hw_interface_set_flags(vnet_get_main(), - tm->hw_if_indicies[0], - VNET_HW_INTERFACE_FLAG_LINK_UP); - FIB_TEST((NULL == error), "Interface bring-up OK"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128); - ai = fib_entry_get_adj(fei); - FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj"); - local_pfx.fp_len = 64; - fei = fib_table_lookup_exact_match(fib_index, &local_pfx); - ai = fib_entry_get_adj(fei); - adj = adj_get(ai); - FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index), - "attached interface adj is glean"); - - /* - * Delete the interface that the routes reolve through. - * Again no routes are removed. They all point to drop. - * - * This is considered an error case. The control plane should - * not remove interfaces through which routes resolve, but - * such things can happen. ALL affected routes will drop. - */ - vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "2001::b/64 resolves via drop"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "2001::b/64 resolves via drop"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "2001:0:0:1::3/64 resolves via drop"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "2001:0:0:1::2/64 resolves via drop"); - fei = fib_table_lookup_exact_match(fib_index, &local_pfx); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "2001:0:0:1::1/128 is drop"); - local_pfx.fp_len = 64; - fei = fib_table_lookup_exact_match(fib_index, &local_pfx); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "2001:0:0:1/64 resolves via drop"); - - /* - * no change - */ - FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d", - fib_path_list_pool_size()); - FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * Add the interface back. routes stay unresolved. - */ - error = ethernet_register_interface(vnet_get_main(), - test_interface_device_class.index, - 0 /* instance */, - hw_address, - &tm->hw_if_indicies[0], - /* flag change */ 0); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "2001::b/64 resolves via drop"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "2001::b/64 resolves via drop"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "2001:0:0:1::3/64 resolves via drop"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "2001:0:0:1::2/64 resolves via drop"); - fei = fib_table_lookup_exact_match(fib_index, &local_pfx); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "2001:0:0:1::1/128 is drop"); - local_pfx.fp_len = 64; - fei = fib_table_lookup_exact_match(fib_index, &local_pfx); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "2001:0:0:1/64 resolves via drop"); - - /* - * CLEANUP ALL the routes - */ - fib_table_entry_delete(fib_index, - &pfx_2001_c_s_64, - FIB_SOURCE_API); - fib_table_entry_delete(fib_index, - &pfx_2001_a_s_64, - FIB_SOURCE_API); - fib_table_entry_delete(fib_index, - &pfx_2001_b_s_64, - FIB_SOURCE_API); - fib_table_entry_delete(fib_index, - &pfx_2001_1_3_s_128, - FIB_SOURCE_ADJ); - fib_table_entry_delete(fib_index, - &pfx_2001_1_2_s_128, - FIB_SOURCE_ADJ); - local_pfx.fp_len = 64; - fib_table_entry_delete(fib_index, &local_pfx, - FIB_SOURCE_INTERFACE); - local_pfx.fp_len = 128; - fib_table_entry_special_remove(fib_index, &local_pfx, - FIB_SOURCE_INTERFACE); - connected_pfx.fp_len = 64; - fib_table_entry_delete(fib_index, &connected_pfx, - FIB_SOURCE_INTERFACE); - connected_pfx.fp_len = 128; - fib_table_entry_special_remove(fib_index, &connected_pfx, - FIB_SOURCE_INTERFACE); - - FIB_TEST((FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)), - "2001::a/64 removed"); - FIB_TEST((FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)), - "2001::b/64 removed"); - FIB_TEST((FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)), - "2001:0:0:1::3/128 removed"); - FIB_TEST((FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)), - "2001:0:0:1::3/128 removed"); - local_pfx.fp_len = 64; - FIB_TEST((FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &local_pfx)), - "2001:0:0:1/64 removed"); - local_pfx.fp_len = 128; - FIB_TEST((FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &local_pfx)), - "2001:0:0:1::1/128 removed"); - connected_pfx.fp_len = 64; - FIB_TEST((FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &connected_pfx)), - "2001:0:0:2/64 removed"); - connected_pfx.fp_len = 128; - FIB_TEST((FIB_NODE_INDEX_INVALID == - fib_table_lookup_exact_match(fib_index, &connected_pfx)), - "2001:0:0:2::1/128 removed"); - - /* - * -8 entries. -7 path-lists (1 was shared). - */ - FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d", - fib_path_list_db_size()); - FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is%d", - fib_path_list_pool_size()); - FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - /* - * now remove the VRF - */ - 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()); - FIB_TEST((PNPS-2 == fib_path_list_pool_size()), "path list pool size is%d", - fib_path_list_pool_size()); - FIB_TEST((ENPS-2 == fib_entry_pool_size()), "entry pool size is %d", - fib_entry_pool_size()); - - adj_unlock(ai_02); - adj_unlock(ai_01); - - /* - * return the interfaces to up state - */ - error = vnet_sw_interface_set_flags(vnet_get_main(), - tm->hw[0]->sw_if_index, - VNET_SW_INTERFACE_FLAG_ADMIN_UP); - error = vnet_sw_interface_set_flags(vnet_get_main(), - tm->hw[1]->sw_if_index, - VNET_SW_INTERFACE_FLAG_ADMIN_UP); - - FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d", - adj_nbr_db_size()); - - return (res); -} - -/* - * Test Attached Exports - */ -static int -fib_test_ae (void) -{ - const dpo_id_t *dpo, *dpo_drop; - const u32 fib_index = 0; - fib_node_index_t fei; - test_main_t *tm; - ip4_main_t *im; - int res; - - res = 0; - tm = &test_main; - im = &ip4_main; - - FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d", - adj_nbr_db_size()); - - /* - * add interface routes. We'll assume this works. It's more rigorously - * tested elsewhere. - */ - fib_prefix_t local_pfx = { - .fp_len = 24, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4 = { - /* 10.10.10.10 */ - .as_u32 = clib_host_to_net_u32(0x0a0a0a0a), - }, - }, - }; - - vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index); - im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index; - - dpo_drop = drop_dpo_get(DPO_PROTO_IP4); - - fib_table_entry_update_one_path(fib_index, &local_pfx, - FIB_SOURCE_INTERFACE, - (FIB_ENTRY_FLAG_CONNECTED | - FIB_ENTRY_FLAG_ATTACHED), - DPO_PROTO_IP4, - NULL, - tm->hw[0]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(fib_index, &local_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), - "attached interface route present"); - - local_pfx.fp_len = 32; - fib_table_entry_update_one_path(fib_index, &local_pfx, - FIB_SOURCE_INTERFACE, - (FIB_ENTRY_FLAG_CONNECTED | - FIB_ENTRY_FLAG_LOCAL), - DPO_PROTO_IP4, - NULL, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(fib_index, &local_pfx); - - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), - "local interface route present"); - - /* - * Add an 2 ARP entry => a complete ADJ plus adj-fib. - */ - fib_prefix_t pfx_10_10_10_1_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 10.10.10.1 */ - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01), - }, - }; - fib_node_index_t ai; - - fib_table_entry_path_add(fib_index, - &pfx_10_10_10_1_s_32, - FIB_SOURCE_ADJ, - FIB_ENTRY_FLAG_ATTACHED, - DPO_PROTO_IP4, - &pfx_10_10_10_1_s_32.fp_addr, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created"); - ai = fib_entry_get_adj(fei); - - /* - * create another FIB table into which routes will be imported - */ - u32 import_fib_index1; - - 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 - */ - local_pfx.fp_len = 24; - fib_table_entry_update_one_path(import_fib_index1, - &local_pfx, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - NULL, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created"); - - /* - * check for the presence of the adj-fibs in the import table - */ - fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported"); - FIB_TEST((ai == fib_entry_get_adj(fei)), - "adj-fib1 Import uses same adj as export"); - - /* - * check for the presence of the local in the import table - */ - local_pfx.fp_len = 32; - fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported"); - - /* - * Add another adj-fin in the export table. Expect this - * to get magically exported; - */ - fib_prefix_t pfx_10_10_10_2_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 10.10.10.2 */ - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02), - }, - }; - - fib_table_entry_path_add(fib_index, - &pfx_10_10_10_2_s_32, - FIB_SOURCE_ADJ, - FIB_ENTRY_FLAG_ATTACHED, - DPO_PROTO_IP4, - &pfx_10_10_10_2_s_32.fp_addr, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present"); - ai = fib_entry_get_adj(fei); - - fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported"); - FIB_TEST((ai == fib_entry_get_adj(fei)), - "Import uses same adj as export"); - FIB_TEST((FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(fei)), - "ADJ-fib2 imported flags %d", - fib_entry_get_flags(fei)); - - /* - * create a 2nd FIB table into which routes will be imported - */ - u32 import_fib_index2; - - 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 - */ - local_pfx.fp_len = 24; - fib_table_entry_update_one_path(import_fib_index2, - &local_pfx, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - NULL, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created"); - - /* - * check for the presence of all the adj-fibs and local in the import table - */ - fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported"); - fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported"); - local_pfx.fp_len = 32; - fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported"); - - /* - * add a 3rd adj-fib. expect it to be exported to both tables. - */ - fib_prefix_t pfx_10_10_10_3_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 10.10.10.3 */ - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03), - }, - }; - - fib_table_entry_path_add(fib_index, - &pfx_10_10_10_3_s_32, - FIB_SOURCE_ADJ, - FIB_ENTRY_FLAG_ATTACHED, - DPO_PROTO_IP4, - &pfx_10_10_10_3_s_32.fp_addr, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present"); - ai = fib_entry_get_adj(fei); - - fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1"); - FIB_TEST((ai == fib_entry_get_adj(fei)), - "Import uses same adj as export"); - fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2"); - FIB_TEST((ai == fib_entry_get_adj(fei)), - "Import uses same adj as export"); - - /* - * remove the 3rd adj fib. we expect it to be removed from both FIBs - */ - fib_table_entry_delete(fib_index, - &pfx_10_10_10_3_s_32, - FIB_SOURCE_ADJ); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved"); - - fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1"); - - fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2"); - - /* - * remove the attached route from the 2nd FIB. expect the imported - * entires to be removed - */ - local_pfx.fp_len = 24; - fib_table_entry_delete(import_fib_index2, - &local_pfx, - FIB_SOURCE_API); - fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed"); - - fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2"); - fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2"); - local_pfx.fp_len = 32; - fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2"); - - fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1"); - fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1"); - local_pfx.fp_len = 32; - fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1"); - - /* - * modify the route in FIB1 so it is no longer attached. expect the imported - * entires to be removed - */ - local_pfx.fp_len = 24; - fib_table_entry_update_one_path(import_fib_index1, - &local_pfx, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_10_10_10_2_s_32.fp_addr, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1"); - fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1"); - local_pfx.fp_len = 32; - fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1"); - - /* - * modify it back to attached. expect the adj-fibs back - */ - local_pfx.fp_len = 24; - fib_table_entry_update_one_path(import_fib_index1, - &local_pfx, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - NULL, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1"); - fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1"); - local_pfx.fp_len = 32; - fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1"); - - /* - * add a covering attached next-hop for the interface address, so we have - * a valid adj to find when we check the forwarding tables - */ - fib_prefix_t pfx_10_0_0_0_s_8 = { - .fp_len = 8, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - /* 10.0.0.0 */ - .ip4.as_u32 = clib_host_to_net_u32(0x0a000000), - }, - }; - - fei = fib_table_entry_update_one_path(fib_index, - &pfx_10_0_0_0_s_8, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_10_10_10_3_s_32.fp_addr, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - dpo = fib_entry_contribute_ip_forwarding(fei); - - /* - * remove the route in the export fib. expect the adj-fibs to be removed - */ - local_pfx.fp_len = 24; - fib_table_entry_delete(fib_index, - &local_pfx, - FIB_SOURCE_INTERFACE); - - fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1"); - fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1"); - local_pfx.fp_len = 32; - fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1"); - - /* - * the adj-fibs in the export VRF are present in the FIB table, - * but not installed in forwarding, since they have no attached cover. - * Consequently a lookup in the MTRIE gives the adj for the covering - * route 10.0.0.0/8. - */ - fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export"); - - index_t lbi; - lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4); - FIB_TEST(lbi == dpo->dpoi_index, - "10.10.10.1 forwards on \n%U not \n%U", - format_load_balance, lbi, 0, - format_dpo_id, dpo, 0); - lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4); - FIB_TEST(lbi == dpo->dpoi_index, - "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0); - lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4); - FIB_TEST(lbi == dpo->dpoi_index, - "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0); - - /* - * add the export prefix back, but not as attached. - * No adj-fibs in export nor import tables - */ - local_pfx.fp_len = 24; - fei = fib_table_entry_update_one_path(fib_index, - &local_pfx, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_10_10_10_1_s_32.fp_addr, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - dpo = fib_entry_contribute_ip_forwarding(fei); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export"); - lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4); - FIB_TEST(lbi == dpo->dpoi_index, - "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0); - fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export"); - lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4); - FIB_TEST(lbi == dpo->dpoi_index, - "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0); - - fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1"); - fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1"); - local_pfx.fp_len = 32; - fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1"); - - /* - * modify the export prefix so it is attached. expect all covereds to return - */ - local_pfx.fp_len = 24; - fib_table_entry_update_one_path(fib_index, - &local_pfx, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - NULL, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export"); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)), - "Adj-fib1 is not drop in export"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export"); - local_pfx.fp_len = 32; - fei = fib_table_lookup_exact_match(fib_index, &local_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export"); - fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported"); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)), - "Adj-fib1 is not drop in export: %U %U", - format_dpo_id, dpo, 0, - format_dpo_id, load_balance_get_bucket(dpo->dpoi_index, 0), 0); - fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported"); - fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported"); - local_pfx.fp_len = 32; - fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported"); - - /* - * modify the export prefix so connected. no change. - */ - local_pfx.fp_len = 24; - fib_table_entry_update_one_path(fib_index, &local_pfx, - FIB_SOURCE_INTERFACE, - (FIB_ENTRY_FLAG_CONNECTED | - FIB_ENTRY_FLAG_ATTACHED), - DPO_PROTO_IP4, - NULL, - tm->hw[0]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export"); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)), - "Adj-fib1 is not drop in export"); - fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export"); - local_pfx.fp_len = 32; - fei = fib_table_lookup_exact_match(fib_index, &local_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export"); - fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported"); - dpo = fib_entry_contribute_ip_forwarding(fei); - FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)), - "Adj-fib1 is not drop in export"); - fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported"); - local_pfx.fp_len = 32; - fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported"); - - /* - * CLEANUP - */ - fib_table_entry_delete(fib_index, - &pfx_10_0_0_0_s_8, - FIB_SOURCE_API); - fib_table_entry_delete(fib_index, - &pfx_10_10_10_1_s_32, - FIB_SOURCE_ADJ); - fib_table_entry_delete(fib_index, - &pfx_10_10_10_2_s_32, - FIB_SOURCE_ADJ); - local_pfx.fp_len = 32; - fib_table_entry_delete(fib_index, - &local_pfx, - FIB_SOURCE_INTERFACE); - local_pfx.fp_len = 24; - fib_table_entry_delete(fib_index, - &local_pfx, - FIB_SOURCE_API); - fib_table_entry_delete(fib_index, - &local_pfx, - FIB_SOURCE_INTERFACE); - local_pfx.fp_len = 24; - fib_table_entry_delete(import_fib_index1, - &local_pfx, - FIB_SOURCE_API); - - 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()); - - return (res); -} - -/* - * Test Path Preference - */ -static int -fib_test_pref (void) -{ - test_main_t *tm = &test_main; - int res; - - res = 0; - const fib_prefix_t pfx_1_1_1_1_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4 = { - .as_u32 = clib_host_to_net_u32(0x01010101), - }, - }, - }; - - /* - * 2 high, 2 medium and 2 low preference non-recursive paths - */ - fib_route_path_t nr_path_hi_1 = { - .frp_proto = DPO_PROTO_IP4, - .frp_sw_if_index = tm->hw[0]->sw_if_index, - .frp_fib_index = ~0, - .frp_weight = 1, - .frp_preference = 0, - .frp_flags = FIB_ROUTE_PATH_FLAG_NONE, - .frp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01), - }, - }; - fib_route_path_t nr_path_hi_2 = { - .frp_proto = DPO_PROTO_IP4, - .frp_sw_if_index = tm->hw[0]->sw_if_index, - .frp_fib_index = ~0, - .frp_weight = 1, - .frp_preference = 0, - .frp_flags = FIB_ROUTE_PATH_FLAG_NONE, - .frp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02), - }, - }; - fib_route_path_t nr_path_med_1 = { - .frp_proto = DPO_PROTO_IP4, - .frp_sw_if_index = tm->hw[1]->sw_if_index, - .frp_fib_index = ~0, - .frp_weight = 1, - .frp_preference = 1, - .frp_flags = FIB_ROUTE_PATH_FLAG_NONE, - .frp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01), - }, - }; - fib_route_path_t nr_path_med_2 = { - .frp_proto = DPO_PROTO_IP4, - .frp_sw_if_index = tm->hw[1]->sw_if_index, - .frp_fib_index = ~0, - .frp_weight = 1, - .frp_preference = 1, - .frp_flags = FIB_ROUTE_PATH_FLAG_NONE, - .frp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01), - }, - }; - fib_route_path_t nr_path_low_1 = { - .frp_proto = DPO_PROTO_IP4, - .frp_sw_if_index = tm->hw[2]->sw_if_index, - .frp_fib_index = ~0, - .frp_weight = 1, - .frp_preference = 2, - .frp_flags = FIB_ROUTE_PATH_FLAG_NONE, - .frp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b01), - }, - }; - fib_route_path_t nr_path_low_2 = { - .frp_proto = DPO_PROTO_IP4, - .frp_sw_if_index = tm->hw[2]->sw_if_index, - .frp_fib_index = ~0, - .frp_weight = 1, - .frp_preference = 2, - .frp_flags = FIB_ROUTE_PATH_FLAG_NONE, - .frp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b02), - }, - }; - fib_route_path_t *nr_paths = NULL; - - vec_add1(nr_paths, nr_path_hi_1); - vec_add1(nr_paths, nr_path_hi_2); - vec_add1(nr_paths, nr_path_med_1); - vec_add1(nr_paths, nr_path_med_2); - vec_add1(nr_paths, nr_path_low_1); - vec_add1(nr_paths, nr_path_low_2); - - adj_index_t ai_hi_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_IP4, - &nr_path_hi_1.frp_addr, - nr_path_hi_1.frp_sw_if_index); - adj_index_t ai_hi_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_IP4, - &nr_path_hi_2.frp_addr, - nr_path_hi_2.frp_sw_if_index); - adj_index_t ai_med_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_IP4, - &nr_path_med_1.frp_addr, - nr_path_med_1.frp_sw_if_index); - adj_index_t ai_med_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_IP4, - &nr_path_med_2.frp_addr, - nr_path_med_2.frp_sw_if_index); - adj_index_t ai_low_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_IP4, - &nr_path_low_1.frp_addr, - nr_path_low_1.frp_sw_if_index); - adj_index_t ai_low_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_IP4, - &nr_path_low_2.frp_addr, - nr_path_low_2.frp_sw_if_index); - - fib_test_lb_bucket_t ip_hi_1 = { - .type = FT_LB_ADJ, - .adj = { - .adj = ai_hi_1, - }, - }; - fib_test_lb_bucket_t ip_hi_2 = { - .type = FT_LB_ADJ, - .adj = { - .adj = ai_hi_2, - }, - }; - fib_test_lb_bucket_t ip_med_1 = { - .type = FT_LB_ADJ, - .adj = { - .adj = ai_med_1, - }, - }; - fib_test_lb_bucket_t ip_med_2 = { - .type = FT_LB_ADJ, - .adj = { - .adj = ai_med_2, - }, - }; - fib_test_lb_bucket_t ip_low_1 = { - .type = FT_LB_ADJ, - .adj = { - .adj = ai_low_1, - }, - }; - fib_test_lb_bucket_t ip_low_2 = { - .type = FT_LB_ADJ, - .adj = { - .adj = ai_low_2, - }, - }; - - fib_node_index_t fei; - - fei = fib_table_entry_path_add2(0, - &pfx_1_1_1_1_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - nr_paths); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 2, - &ip_hi_1, - &ip_hi_2), - "1.1.1.1/32 via high preference paths"); - - /* - * bring down the interface on which the high preference path lie - */ - vnet_sw_interface_set_flags(vnet_get_main(), - tm->hw[0]->sw_if_index, - 0); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 2, - &ip_med_1, - &ip_med_2), - "1.1.1.1/32 via medium preference paths"); - - /* - * bring down the interface on which the medium preference path lie - */ - vnet_sw_interface_set_flags(vnet_get_main(), - tm->hw[1]->sw_if_index, - 0); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 2, - &ip_low_1, - &ip_low_2), - "1.1.1.1/32 via low preference paths"); - - /* - * bring up the interface on which the high preference path lie - */ - vnet_sw_interface_set_flags(vnet_get_main(), - tm->hw[0]->sw_if_index, - VNET_SW_INTERFACE_FLAG_ADMIN_UP); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 2, - &ip_hi_1, - &ip_hi_2), - "1.1.1.1/32 via high preference paths"); - - /* - * bring up the interface on which the medium preference path lie - */ - vnet_sw_interface_set_flags(vnet_get_main(), - tm->hw[1]->sw_if_index, - VNET_SW_INTERFACE_FLAG_ADMIN_UP); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 2, - &ip_hi_1, - &ip_hi_2), - "1.1.1.1/32 via high preference paths"); - - dpo_id_t ip_1_1_1_1 = DPO_INVALID; - fib_entry_contribute_forwarding(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - &ip_1_1_1_1); - - /* - * 3 recursive paths of different preference - */ - const fib_prefix_t pfx_1_1_1_2_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4 = { - .as_u32 = clib_host_to_net_u32(0x01010102), - }, - }, - }; - const fib_prefix_t pfx_1_1_1_3_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4 = { - .as_u32 = clib_host_to_net_u32(0x01010103), - }, - }, - }; - fei = fib_table_entry_path_add2(0, - &pfx_1_1_1_2_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - nr_paths); - dpo_id_t ip_1_1_1_2 = DPO_INVALID; - fib_entry_contribute_forwarding(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - &ip_1_1_1_2); - fei = fib_table_entry_path_add2(0, - &pfx_1_1_1_3_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - nr_paths); - dpo_id_t ip_1_1_1_3 = DPO_INVALID; - fib_entry_contribute_forwarding(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - &ip_1_1_1_3); - - fib_test_lb_bucket_t ip_o_1_1_1_1 = { - .type = FT_LB_O_LB, - .lb = { - .lb = ip_1_1_1_1.dpoi_index, - }, - }; - fib_test_lb_bucket_t ip_o_1_1_1_2 = { - .type = FT_LB_O_LB, - .lb = { - .lb = ip_1_1_1_2.dpoi_index, - }, - }; - fib_test_lb_bucket_t ip_o_1_1_1_3 = { - .type = FT_LB_O_LB, - .lb = { - .lb = ip_1_1_1_3.dpoi_index, - }, - }; - fib_route_path_t r_path_hi = { - .frp_proto = DPO_PROTO_IP4, - .frp_sw_if_index = ~0, - .frp_fib_index = 0, - .frp_weight = 1, - .frp_preference = 0, - .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST, - .frp_addr = pfx_1_1_1_1_s_32.fp_addr, - }; - fib_route_path_t r_path_med = { - .frp_proto = DPO_PROTO_IP4, - .frp_sw_if_index = ~0, - .frp_fib_index = 0, - .frp_weight = 1, - .frp_preference = 10, - .frp_flags = FIB_ROUTE_PATH_FLAG_NONE, - .frp_addr = pfx_1_1_1_2_s_32.fp_addr, - }; - fib_route_path_t r_path_low = { - .frp_proto = DPO_PROTO_IP4, - .frp_sw_if_index = ~0, - .frp_fib_index = 0, - .frp_weight = 1, - .frp_preference = 255, - .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST, - .frp_addr = pfx_1_1_1_3_s_32.fp_addr, - }; - fib_route_path_t *r_paths = NULL; - - vec_add1(r_paths, r_path_hi); - vec_add1(r_paths, r_path_low); - vec_add1(r_paths, r_path_med); - - /* - * add many recursive so we get the LB MAp created - */ -#define N_PFXS 64 - fib_prefix_t pfx_r[N_PFXS]; - unsigned int n_pfxs; - for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++) - { - pfx_r[n_pfxs].fp_len = 32; - pfx_r[n_pfxs].fp_proto = FIB_PROTOCOL_IP4; - pfx_r[n_pfxs].fp_addr.ip4.as_u32 = - clib_host_to_net_u32(0x02000000 + n_pfxs); - - fei = fib_table_entry_path_add2(0, - &pfx_r[n_pfxs], - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - r_paths); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &ip_o_1_1_1_1), - "recursive via high preference paths"); - - /* - * withdraw hig pref resolving entry - */ - fib_table_entry_delete(0, - &pfx_1_1_1_1_s_32, - FIB_SOURCE_API); - - /* suspend so the update walk kicks int */ - vlib_process_suspend(vlib_get_main(), 1e-5); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &ip_o_1_1_1_2), - "recursive via medium preference paths"); - - /* - * withdraw medium pref resolving entry - */ - fib_table_entry_delete(0, - &pfx_1_1_1_2_s_32, - FIB_SOURCE_API); - - /* suspend so the update walk kicks int */ - vlib_process_suspend(vlib_get_main(), 1e-5); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &ip_o_1_1_1_3), - "recursive via low preference paths"); - - /* - * add back paths for next iteration - */ - fei = fib_table_entry_update(0, - &pfx_1_1_1_2_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - nr_paths); - fei = fib_table_entry_update(0, - &pfx_1_1_1_1_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - nr_paths); - - /* suspend so the update walk kicks int */ - vlib_process_suspend(vlib_get_main(), 1e-5); - - fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &ip_o_1_1_1_1), - "recursive via high preference paths"); - } - - - fib_table_entry_delete(0, - &pfx_1_1_1_1_s_32, - FIB_SOURCE_API); - - /* suspend so the update walk kicks int */ - vlib_process_suspend(vlib_get_main(), 1e-5); - - for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++) - { - fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &ip_o_1_1_1_2), - "recursive via medium preference paths"); - } - for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++) - { - fib_table_entry_delete(0, - &pfx_r[n_pfxs], - FIB_SOURCE_API); - } - - /* - * Cleanup - */ - fib_table_entry_delete(0, - &pfx_1_1_1_2_s_32, - FIB_SOURCE_API); - fib_table_entry_delete(0, - &pfx_1_1_1_3_s_32, - FIB_SOURCE_API); - - dpo_reset(&ip_1_1_1_1); - dpo_reset(&ip_1_1_1_2); - dpo_reset(&ip_1_1_1_3); - adj_unlock(ai_low_2); - adj_unlock(ai_low_1); - adj_unlock(ai_med_2); - adj_unlock(ai_med_1); - adj_unlock(ai_hi_2); - adj_unlock(ai_hi_1); - - return (res); -} - -/* - * Test the recursive route route handling for GRE tunnels - */ -static int -fib_test_label (void) -{ - fib_node_index_t fei, ai_mpls_10_10_10_1, ai_v4_10_10_11_1, ai_v4_10_10_11_2, ai_mpls_10_10_11_2, ai_mpls_10_10_11_1; - const u32 fib_index = 0; - int lb_count, ii, res; - test_main_t *tm; - ip4_main_t *im; - - res = 0; - lb_count = pool_elts(load_balance_pool); - tm = &test_main; - im = &ip4_main; - - /* - * add interface routes. We'll assume this works. It's more rigorously - * tested elsewhere. - */ - fib_prefix_t local0_pfx = { - .fp_len = 24, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4 = { - /* 10.10.10.10 */ - .as_u32 = clib_host_to_net_u32(0x0a0a0a0a), - }, - }, - }; - - FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d", - adj_nbr_db_size()); - - vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index); - im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index; - - fib_table_entry_update_one_path(fib_index, &local0_pfx, - FIB_SOURCE_INTERFACE, - (FIB_ENTRY_FLAG_CONNECTED | - FIB_ENTRY_FLAG_ATTACHED), - DPO_PROTO_IP4, - NULL, - tm->hw[0]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(fib_index, &local0_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), - "attached interface route present"); - - local0_pfx.fp_len = 32; - fib_table_entry_update_one_path(fib_index, &local0_pfx, - FIB_SOURCE_INTERFACE, - (FIB_ENTRY_FLAG_CONNECTED | - FIB_ENTRY_FLAG_LOCAL), - DPO_PROTO_IP4, - NULL, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(fib_index, &local0_pfx); - - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), - "local interface route present"); - - fib_prefix_t local1_pfx = { - .fp_len = 24, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4 = { - /* 10.10.11.10 */ - .as_u32 = clib_host_to_net_u32(0x0a0a0b0a), - }, - }, - }; - - vec_validate(im->fib_index_by_sw_if_index, tm->hw[1]->sw_if_index); - im->fib_index_by_sw_if_index[tm->hw[1]->sw_if_index] = fib_index; - - fib_table_entry_update_one_path(fib_index, &local1_pfx, - FIB_SOURCE_INTERFACE, - (FIB_ENTRY_FLAG_CONNECTED | - FIB_ENTRY_FLAG_ATTACHED), - DPO_PROTO_IP4, - NULL, - tm->hw[1]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(fib_index, &local1_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), - "attached interface route present"); - - local1_pfx.fp_len = 32; - fib_table_entry_update_one_path(fib_index, &local1_pfx, - FIB_SOURCE_INTERFACE, - (FIB_ENTRY_FLAG_CONNECTED | - FIB_ENTRY_FLAG_LOCAL), - DPO_PROTO_IP4, - NULL, - tm->hw[1]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup_exact_match(fib_index, &local1_pfx); - - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), - "local interface route present"); - - ip46_address_t nh_10_10_10_1 = { - .ip4 = { - .as_u32 = clib_host_to_net_u32(0x0a0a0a01), - }, - }; - ip46_address_t nh_10_10_11_1 = { - .ip4 = { - .as_u32 = clib_host_to_net_u32(0x0a0a0b01), - }, - }; - ip46_address_t nh_10_10_11_2 = { - .ip4 = { - .as_u32 = clib_host_to_net_u32(0x0a0a0b02), - }, - }; - - ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_IP4, - &nh_10_10_11_1, - tm->hw[1]->sw_if_index); - ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_IP4, - &nh_10_10_11_2, - tm->hw[1]->sw_if_index); - ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_MPLS, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index); - ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_MPLS, - &nh_10_10_11_2, - tm->hw[1]->sw_if_index); - ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_MPLS, - &nh_10_10_11_1, - tm->hw[1]->sw_if_index); - - /* - * Add an etry with one path with a real out-going label - */ - fib_prefix_t pfx_1_1_1_1_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x01010101), - }, - }; - fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = { - .type = FT_LB_LABEL_O_ADJ, - .label_o_adj = { - .adj = ai_mpls_10_10_10_1, - .label = 99, - .eos = MPLS_EOS, - }, - }; - fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = { - .type = FT_LB_LABEL_O_ADJ, - .label_o_adj = { - .adj = ai_mpls_10_10_10_1, - .label = 99, - .eos = MPLS_NON_EOS, - }, - }; - 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, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - l99, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32); - FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created"); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &l99_eos_o_10_10_10_1), - "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1"); - - /* - * add a path with an implicit NULL label - */ - fib_test_lb_bucket_t a_o_10_10_11_1 = { - .type = FT_LB_ADJ, - .adj = { - .adj = ai_v4_10_10_11_1, - }, - }; - fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = { - .type = FT_LB_ADJ, - .adj = { - .adj = ai_mpls_10_10_11_1, - }, - }; - 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, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_11_1, - tm->hw[1]->sw_if_index, - ~0, // invalid fib index - 1, - l_imp_null, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 2, - &l99_eos_o_10_10_10_1, - &a_o_10_10_11_1), - "1.1.1.1/32 LB 2 buckets via: " - "label 99 over 10.10.10.1, " - "adj over 10.10.11.1"); - - /* - * assign the route a local label - */ - fib_table_entry_local_label_add(fib_index, - &pfx_1_1_1_1_s_32, - 24001); - - fib_prefix_t pfx_24001_eos = { - .fp_proto = FIB_PROTOCOL_MPLS, - .fp_label = 24001, - .fp_eos = MPLS_EOS, - }; - fib_prefix_t pfx_24001_neos = { - .fp_proto = FIB_PROTOCOL_MPLS, - .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, - * and use an ip adj for the imp-null - * The NON-EOS entry should link to both the paths, - * and use an mpls adj for the imp-null - */ - fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID, - &pfx_24001_eos); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_MPLS_EOS, - 2, - &l99_eos_o_10_10_10_1, - &disp_o_10_10_11_1), - "24001/eos LB 2 buckets via: " - "label 99 over 10.10.10.1, " - "mpls disp adj over 10.10.11.1"); - - - fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID, - &pfx_24001_neos); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, - 2, - &l99_neos_o_10_10_10_1, - &a_mpls_o_10_10_11_1), - "24001/neos LB 1 bucket via: " - "label 99 over 10.10.10.1 ", - "mpls-adj via 10.10.11.1"); - - /* - * add an unlabelled path, this is excluded from the neos chains, - */ - fib_test_lb_bucket_t adj_o_10_10_11_2 = { - .type = FT_LB_ADJ, - .adj = { - .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, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_11_2, - tm->hw[1]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 16, // 3 choices spread over 16 buckets - &l99_eos_o_10_10_10_1, - &l99_eos_o_10_10_10_1, - &l99_eos_o_10_10_10_1, - &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), - "1.1.1.1/32 LB 16 buckets via: " - "label 99 over 10.10.10.1, " - "adj over 10.10.11.1", - "adj over 10.10.11.2"); - - /* - * get and lock a reference to the non-eos of the via entry 1.1.1.1/32 - */ - dpo_id_t non_eos_1_1_1_1 = DPO_INVALID; - fib_entry_contribute_forwarding(fei, - FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, - &non_eos_1_1_1_1); - - /* - * n-eos has only the 2 labelled paths - */ - fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID, - &pfx_24001_neos); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, - 2, - &l99_neos_o_10_10_10_1, - &a_mpls_o_10_10_11_1), - "24001/neos LB 2 buckets via: " - "label 99 over 10.10.10.1, " - "adj-mpls over 10.10.11.2"); - - /* - * A labelled recursive - */ - fib_prefix_t pfx_2_2_2_2_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x02020202), - }, - }; - fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = { - .type = FT_LB_LABEL_O_LB, - .label_o_lb = { - .lb = non_eos_1_1_1_1.dpoi_index, - .label = 1600, - .eos = MPLS_EOS, - .mode = FIB_MPLS_LSP_MODE_UNIFORM, - }, - }; - fib_mpls_label_t *l1600 = NULL, fml1600 = { - .fml_value = 1600, - .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM, - }; - vec_add1(l1600, fml1600); - - 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); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &l1600_eos_o_1_1_1_1), - "2.2.2.2.2/32 LB 1 buckets via: " - "label 1600 over 1.1.1.1"); - - dpo_id_t dpo_44 = DPO_INVALID; - index_t urpfi; - - fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44); - urpfi = load_balance_get_urpf(dpo_44.dpoi_index); - - FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index), - "uRPF check for 2.2.2.2/32 on %d OK", - tm->hw[0]->sw_if_index); - FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index), - "uRPF check for 2.2.2.2/32 on %d OK", - tm->hw[1]->sw_if_index); - FIB_TEST(!fib_urpf_check(urpfi, 99), - "uRPF check for 2.2.2.2/32 on 99 not-OK", - 99); - - fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44); - FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index), - "Shared uRPF on IP and non-EOS chain"); - - dpo_reset(&dpo_44); - - /* - * we are holding a lock on the non-eos LB of the via-entry. - * do a PIC-core failover by shutting the link of the via-entry. - * - * shut down the link with the valid label - */ - vnet_sw_interface_set_flags(vnet_get_main(), - tm->hw[0]->sw_if_index, - 0); - - fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 2, - &a_o_10_10_11_1, - &adj_o_10_10_11_2), - "1.1.1.1/32 LB 2 buckets via: " - "adj over 10.10.11.1, ", - "adj-v4 over 10.10.11.2"); - - fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID, - &pfx_24001_eos); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_MPLS_EOS, - 2, - &disp_o_10_10_11_1, - &disp_o_10_10_11_2), - "24001/eos LB 2 buckets via: " - "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); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, - 1, - &a_mpls_o_10_10_11_1), - "24001/neos LB 1 buckets via: " - "adj-mpls over 10.10.11.2"); - - /* - * test that the pre-failover load-balance has been in-place - * modified - */ - dpo_id_t current = DPO_INVALID; - fib_entry_contribute_forwarding(fei, - FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, - ¤t); - - FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1, - ¤t), - "PIC-core LB inplace modified %U %U", - format_dpo_id, &non_eos_1_1_1_1, 0, - format_dpo_id, ¤t, 0); - - dpo_reset(&non_eos_1_1_1_1); - dpo_reset(¤t); - - /* - * no-shut the link with the valid label - */ - vnet_sw_interface_set_flags(vnet_get_main(), - tm->hw[0]->sw_if_index, - VNET_SW_INTERFACE_FLAG_ADMIN_UP); - - fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 16, // 3 choices spread over 16 buckets - &l99_eos_o_10_10_10_1, - &l99_eos_o_10_10_10_1, - &l99_eos_o_10_10_10_1, - &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), - "1.1.1.1/32 LB 16 buckets via: " - "label 99 over 10.10.10.1, " - "adj over 10.10.11.1", - "adj-v4 over 10.10.11.2"); - - - fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID, - &pfx_24001_eos); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_MPLS_EOS, - 16, // 3 choices spread over 16 buckets - &l99_eos_o_10_10_10_1, - &l99_eos_o_10_10_10_1, - &l99_eos_o_10_10_10_1, - &l99_eos_o_10_10_10_1, - &l99_eos_o_10_10_10_1, - &l99_eos_o_10_10_10_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_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, " - "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); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, - 2, - &l99_neos_o_10_10_10_1, - &a_mpls_o_10_10_11_1), - "24001/neos LB 2 buckets via: " - "label 99 over 10.10.10.1, " - "adj-mpls over 10.10.11.2"); - - /* - * remove the first path with the valid label - */ - fib_table_entry_path_remove(fib_index, - &pfx_1_1_1_1_s_32, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 2, - &a_o_10_10_11_1, - &adj_o_10_10_11_2), - "1.1.1.1/32 LB 2 buckets via: " - "adj over 10.10.11.1, " - "adj-v4 over 10.10.11.2"); - - fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID, - &pfx_24001_eos); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_MPLS_EOS, - 2, - &disp_o_10_10_11_1, - &disp_o_10_10_11_2), - "24001/eos LB 2 buckets via: " - "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); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, - 1, - &a_mpls_o_10_10_11_1), - "24001/neos LB 1 buckets via: " - "adj-mpls over 10.10.11.2"); - - /* - * remove the other path with a valid label - */ - fib_test_lb_bucket_t bucket_drop = { - .type = FT_LB_DROP, - }; - fib_test_lb_bucket_t mpls_bucket_drop = { - .type = FT_LB_DROP, - .special = { - .adj = DPO_PROTO_MPLS, - }, - }; - - fib_table_entry_path_remove(fib_index, - &pfx_1_1_1_1_s_32, - FIB_SOURCE_API, - DPO_PROTO_IP4, - &nh_10_10_11_1, - tm->hw[1]->sw_if_index, - ~0, // invalid fib index - 1, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &adj_o_10_10_11_2), - "1.1.1.1/32 LB 1 buckets via: " - "adj over 10.10.11.2"); - - fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID, - &pfx_24001_eos); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_MPLS_EOS, - 1, - &disp_o_10_10_11_2), - "24001/eos LB 1 buckets via: " - "MPLS disp adj over 10.10.11.2"); - - fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID, - &pfx_24001_neos); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, - 1, - &mpls_bucket_drop), - "24001/neos LB 1 buckets via: DROP"); - - /* - * add back the path with the valid label - */ - l99 = NULL; - vec_add1(l99, fml99); - - fib_table_entry_path_add(fib_index, - &pfx_1_1_1_1_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - l99, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 2, - &l99_eos_o_10_10_10_1, - &adj_o_10_10_11_2), - "1.1.1.1/32 LB 2 buckets via: " - "label 99 over 10.10.10.1, " - "adj over 10.10.11.2"); - - fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID, - &pfx_24001_eos); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_MPLS_EOS, - 2, - &l99_eos_o_10_10_10_1, - &disp_o_10_10_11_2), - "24001/eos LB 2 buckets via: " - "label 99 over 10.10.10.1, " - "MPLS disp adj over 10.10.11.2"); - - fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID, - &pfx_24001_neos); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, - 1, - &l99_neos_o_10_10_10_1), - "24001/neos LB 1 buckets via: " - "label 99 over 10.10.10.1"); - - /* - * change the local label - */ - fib_table_entry_local_label_add(fib_index, - &pfx_1_1_1_1_s_32, - 25005); - - fib_prefix_t pfx_25005_eos = { - .fp_proto = FIB_PROTOCOL_MPLS, - .fp_label = 25005, - .fp_eos = MPLS_EOS, - }; - fib_prefix_t pfx_25005_neos = { - .fp_proto = FIB_PROTOCOL_MPLS, - .fp_label = 25005, - .fp_eos = MPLS_NON_EOS, - }; - - FIB_TEST((FIB_NODE_INDEX_INVALID == - fib_table_lookup(fib_index, &pfx_24001_eos)), - "24001/eos removed after label change"); - FIB_TEST((FIB_NODE_INDEX_INVALID == - fib_table_lookup(fib_index, &pfx_24001_neos)), - "24001/eos removed after label change"); - - fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID, - &pfx_25005_eos); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_MPLS_EOS, - 2, - &l99_eos_o_10_10_10_1, - &disp_o_10_10_11_2), - "25005/eos LB 2 buckets via: " - "label 99 over 10.10.10.1, " - "MPLS disp adj over 10.10.11.2"); - - fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID, - &pfx_25005_neos); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, - 1, - &l99_neos_o_10_10_10_1), - "25005/neos LB 1 buckets via: " - "label 99 over 10.10.10.1"); - - /* - * remove the local label. - * the check that the MPLS entries are gone is done by the fact the - * MPLS table is no longer present. - */ - fib_table_entry_local_label_remove(fib_index, - &pfx_1_1_1_1_s_32, - 25005); - - fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 2, - &l99_eos_o_10_10_10_1, - &adj_o_10_10_11_2), - "24001/eos LB 2 buckets via: " - "label 99 over 10.10.10.1, " - "adj over 10.10.11.2"); - - FIB_TEST((FIB_NODE_INDEX_INVALID == - mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)), - "No more MPLS FIB entries => table removed"); - - /* - * add another via-entry for the recursive - */ - fib_prefix_t pfx_1_1_1_2_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x01010102), - }, - }; - fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = { - .type = FT_LB_LABEL_O_ADJ, - .label_o_adj = { - .adj = ai_mpls_10_10_10_1, - .label = 101, - .eos = MPLS_EOS, - }, - }; - 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, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - l101, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &l101_eos_o_10_10_10_1), - "1.1.1.2/32 LB 1 buckets via: " - "label 101 over 10.10.10.1"); - - dpo_id_t non_eos_1_1_1_2 = DPO_INVALID; - fib_entry_contribute_forwarding(fib_table_lookup(fib_index, - &pfx_1_1_1_1_s_32), - FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, - &non_eos_1_1_1_1); - fib_entry_contribute_forwarding(fib_table_lookup(fib_index, - &pfx_1_1_1_2_s_32), - FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, - &non_eos_1_1_1_2); - - fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = { - .type = FT_LB_LABEL_O_LB, - .label_o_lb = { - .lb = non_eos_1_1_1_2.dpoi_index, - .label = 1601, - .eos = MPLS_EOS, - }, - }; - 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; - - fei = fib_table_entry_path_add(fib_index, - &pfx_2_2_2_2_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_1_1_1_2_s_32.fp_addr, - ~0, - fib_index, - 1, - l1601, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 2, - &l1600_eos_o_1_1_1_1, - &l1601_eos_o_1_1_1_2), - "2.2.2.2/32 LB 2 buckets via: " - "label 1600 via 1.1,1.1, " - "label 16001 via 1.1.1.2"); - - /* - * update the via-entry so it no longer has an imp-null path. - * the LB for the recursive can use an imp-null - */ - l_imp_null = NULL; - vec_add1(l_imp_null, fml_imp_null); - - fei = fib_table_entry_update_one_path(fib_index, - &pfx_1_1_1_2_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_11_1, - tm->hw[1]->sw_if_index, - ~0, // invalid fib index - 1, - l_imp_null, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &a_o_10_10_11_1), - "1.1.1.2/32 LB 1 buckets via: " - "adj 10.10.11.1"); - - 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, - 2, - &l1600_eos_o_1_1_1_1, - &l1601_eos_o_1_1_1_2), - "2.2.2.2/32 LB 2 buckets via: " - "label 1600 via 1.1,1.1, " - "label 16001 via 1.1.1.2"); - - /* - * update the via-entry so it no longer has labelled paths. - * the LB for the recursive should exclue this via form its LB - */ - fei = fib_table_entry_update_one_path(fib_index, - &pfx_1_1_1_2_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_11_1, - tm->hw[1]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &a_o_10_10_11_1), - "1.1.1.2/32 LB 1 buckets via: " - "adj 10.10.11.1"); - - 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, - &l1600_eos_o_1_1_1_1), - "2.2.2.2/32 LB 1 buckets via: " - "label 1600 via 1.1,1.1"); - - dpo_reset(&non_eos_1_1_1_1); - dpo_reset(&non_eos_1_1_1_2); - - /* - * Add a recursive with no out-labels. We expect to use the IP of the via - */ - fib_prefix_t pfx_2_2_2_3_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x02020203), - }, - }; - dpo_id_t ip_1_1_1_1 = DPO_INVALID; - - fib_table_entry_update_one_path(fib_index, - &pfx_2_2_2_3_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, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - fib_entry_contribute_forwarding(fib_table_lookup(fib_index, - &pfx_1_1_1_1_s_32), - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - &ip_1_1_1_1); - - fib_test_lb_bucket_t ip_o_1_1_1_1 = { - .type = FT_LB_O_LB, - .lb = { - .lb = ip_1_1_1_1.dpoi_index, - }, - }; - - fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &ip_o_1_1_1_1), - "2.2.2.2.3/32 LB 1 buckets via: " - "ip 1.1.1.1"); - - /* - * Add a recursive with an imp-null out-label. - * We expect to use the IP of the via - */ - fib_prefix_t pfx_2_2_2_4_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x02020204), - }, - }; - - fib_table_entry_update_one_path(fib_index, - &pfx_2_2_2_4_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, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &ip_o_1_1_1_1), - "2.2.2.2.4/32 LB 1 buckets via: " - "ip 1.1.1.1"); - - dpo_reset(&ip_1_1_1_1); - - /* - * Create an entry with a deep label stack - */ - fib_prefix_t pfx_2_2_5_5_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x02020505), - }, - }; - fib_test_lb_bucket_t ls_eos_o_10_10_10_1 = { - .type = FT_LB_LABEL_STACK_O_ADJ, - .label_stack_o_adj = { - .adj = ai_mpls_10_10_11_1, - .label_stack_size = 8, - .label_stack = { - 200, 201, 202, 203, 204, 205, 206, 207 - }, - .eos = MPLS_EOS, - }, - }; - fib_mpls_label_t *label_stack = NULL; - vec_validate(label_stack, 7); - for (ii = 0; ii < 8; ii++) - { - label_stack[ii].fml_value = ii + 200; - } - - fei = fib_table_entry_update_one_path(fib_index, - &pfx_2_2_5_5_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_11_1, - tm->hw[1]->sw_if_index, - ~0, // invalid fib index - 1, - label_stack, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &ls_eos_o_10_10_10_1), - "2.2.5.5/32 LB 1 buckets via: " - "adj 10.10.11.1"); - fib_table_entry_delete_index(fei, FIB_SOURCE_API); - - /* - * cleanup - */ - fib_table_entry_delete(fib_index, - &pfx_1_1_1_2_s_32, - FIB_SOURCE_API); - - 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, - &l1600_eos_o_1_1_1_1), - "2.2.2.2/32 LB 1 buckets via: " - "label 1600 via 1.1,1.1"); - - fib_table_entry_delete(fib_index, - &pfx_1_1_1_1_s_32, - FIB_SOURCE_API); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &bucket_drop), - "2.2.2.2/32 LB 1 buckets via: DROP"); - - fib_table_entry_delete(fib_index, - &pfx_2_2_2_2_s_32, - FIB_SOURCE_API); - fib_table_entry_delete(fib_index, - &pfx_2_2_2_3_s_32, - FIB_SOURCE_API); - fib_table_entry_delete(fib_index, - &pfx_2_2_2_4_s_32, - FIB_SOURCE_API); - - adj_unlock(ai_mpls_10_10_10_1); - adj_unlock(ai_mpls_10_10_11_2); - adj_unlock(ai_v4_10_10_11_1); - adj_unlock(ai_v4_10_10_11_2); - adj_unlock(ai_mpls_10_10_11_1); - - FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d", - adj_nbr_db_size()); - - local0_pfx.fp_len = 32; - fib_table_entry_delete(fib_index, - &local0_pfx, - FIB_SOURCE_INTERFACE); - local0_pfx.fp_len = 24; - fib_table_entry_delete(fib_index, - &local0_pfx, - FIB_SOURCE_INTERFACE); - local1_pfx.fp_len = 32; - fib_table_entry_delete(fib_index, - &local1_pfx, - FIB_SOURCE_INTERFACE); - local1_pfx.fp_len = 24; - fib_table_entry_delete(fib_index, - &local1_pfx, - FIB_SOURCE_INTERFACE); - - /* - * +1 for the drop LB in the MPLS tables. - */ - FIB_TEST(lb_count+1 == pool_elts(load_balance_pool), - "Load-balance resources freed %d of %d", - lb_count+1, pool_elts(load_balance_pool)); - - return (res); -} - -#define N_TEST_CHILDREN 4 -#define PARENT_INDEX 0 - -typedef struct fib_node_test_t_ -{ - fib_node_t node; - u32 sibling; - u32 index; - fib_node_back_walk_ctx_t *ctxs; - u32 destroyed; -} fib_node_test_t; - -static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1]; - -#define PARENT() (&fib_test_nodes[PARENT_INDEX].node) - -#define FOR_EACH_TEST_CHILD(_tc) \ - for (ii = 1, (_tc) = &fib_test_nodes[1]; \ - ii < N_TEST_CHILDREN+1; \ - ii++, (_tc) = &fib_test_nodes[ii]) - -static fib_node_t * -fib_test_child_get_node (fib_node_index_t index) -{ - return (&fib_test_nodes[index].node); -} - -static int fib_test_walk_spawns_walks; - -static fib_node_back_walk_rc_t -fib_test_child_back_walk_notify (fib_node_t *node, - fib_node_back_walk_ctx_t *ctx) -{ - fib_node_test_t *tc = (fib_node_test_t*) node; - - vec_add1(tc->ctxs, *ctx); - - if (1 == fib_test_walk_spawns_walks) - fib_walk_sync(FIB_NODE_TYPE_TEST, tc->index, ctx); - if (2 == fib_test_walk_spawns_walks) - fib_walk_async(FIB_NODE_TYPE_TEST, tc->index, - FIB_WALK_PRIORITY_HIGH, ctx); - - return (FIB_NODE_BACK_WALK_CONTINUE); -} - -static void -fib_test_child_last_lock_gone (fib_node_t *node) -{ - fib_node_test_t *tc = (fib_node_test_t *)node; - - tc->destroyed = 1; -} - -/** - * The FIB walk's graph node virtual function table - */ -static const fib_node_vft_t fib_test_child_vft = { - .fnv_get = fib_test_child_get_node, - .fnv_last_lock = fib_test_child_last_lock_gone, - .fnv_back_walk = fib_test_child_back_walk_notify, -}; - -/* - * the function (that should have been static but isn't so I can do this) - * that processes the walk from the async queue, - */ -f64 fib_walk_process_queues(vlib_main_t * vm, - const f64 quota); -u32 fib_walk_queue_get_size(fib_walk_priority_t prio); - -static int -fib_test_walk (void) -{ - fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {}; - fib_node_test_t *tc; - vlib_main_t *vm; - u32 ii, res; - - res = 0; - vm = vlib_get_main(); - fib_node_register_type(FIB_NODE_TYPE_TEST, &fib_test_child_vft); - - /* - * init a fake node on which we will add children - */ - fib_node_init(&fib_test_nodes[PARENT_INDEX].node, - FIB_NODE_TYPE_TEST); - - FOR_EACH_TEST_CHILD(tc) - { - fib_node_init(&tc->node, FIB_NODE_TYPE_TEST); - fib_node_lock(&tc->node); - tc->ctxs = NULL; - tc->index = ii; - tc->sibling = fib_node_child_add(FIB_NODE_TYPE_TEST, - PARENT_INDEX, - FIB_NODE_TYPE_TEST, ii); - } - - /* - * enqueue a walk across the parents children. - */ - high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE; - - fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX, - FIB_WALK_PRIORITY_HIGH, &high_ctx); - FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children), - "Parent has %d children pre-walk", - fib_node_list_get_size(PARENT()->fn_children)); - - /* - * give the walk a large amount of time so it gets to the end - */ - fib_walk_process_queues(vm, 1); - - FOR_EACH_TEST_CHILD(tc) - { - FIB_TEST(1 == vec_len(tc->ctxs), - "%d child visitsed %d times", - ii, vec_len(tc->ctxs)); - vec_free(tc->ctxs); - } - FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH), - "Queue is empty post walk"); - FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children), - "Parent has %d children post walk", - fib_node_list_get_size(PARENT()->fn_children)); - - /* - * walk again. should be no increase in the number of visits, since - * the walk will have terminated. - */ - fib_walk_process_queues(vm, 1); - - FOR_EACH_TEST_CHILD(tc) - { - FIB_TEST(0 == vec_len(tc->ctxs), - "%d child visitsed %d times", - ii, vec_len(tc->ctxs)); - } - - /* - * schedule a low and hig priority walk. expect the high to be performed - * before the low. - * schedule the high prio walk first so that it is further from the head - * of the dependency list. that way it won't merge with the low one. - */ - high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE; - low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE; - - fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX, - FIB_WALK_PRIORITY_HIGH, &high_ctx); - fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX, - FIB_WALK_PRIORITY_LOW, &low_ctx); - - fib_walk_process_queues(vm, 1); - - FOR_EACH_TEST_CHILD(tc) - { - FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason, - "%d child visitsed by high prio walk", ii); - FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason, - "%d child visitsed by low prio walk", ii); - vec_free(tc->ctxs); - } - FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH), - "Queue is empty post prio walk"); - FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children), - "Parent has %d children post prio walk", - fib_node_list_get_size(PARENT()->fn_children)); - - /* - * schedule 2 walks of the same priority that can be megred. - * expect that each child is thus visited only once. - */ - high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE; - low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE; - - fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX, - FIB_WALK_PRIORITY_HIGH, &high_ctx); - fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX, - FIB_WALK_PRIORITY_HIGH, &low_ctx); - - fib_walk_process_queues(vm, 1); - - FOR_EACH_TEST_CHILD(tc) - { - FIB_TEST(1 == vec_len(tc->ctxs), - "%d child visitsed %d times during merge walk", - ii, vec_len(tc->ctxs)); - vec_free(tc->ctxs); - } - FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH), - "Queue is empty post merge walk"); - FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children), - "Parent has %d children post merge walk", - fib_node_list_get_size(PARENT()->fn_children)); - - /* - * schedule 2 walks of the same priority that cannot be megred. - * expect that each child is thus visited twice and in the order - * in which the walks were scheduled. - */ - high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE; - low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE; - - fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX, - FIB_WALK_PRIORITY_HIGH, &high_ctx); - fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX, - FIB_WALK_PRIORITY_HIGH, &low_ctx); - - fib_walk_process_queues(vm, 1); - - FOR_EACH_TEST_CHILD(tc) - { - FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason, - "%d child visitsed by high prio walk", ii); - FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason, - "%d child visitsed by low prio walk", ii); - vec_free(tc->ctxs); - } - FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH), - "Queue is empty post no-merge walk"); - FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children), - "Parent has %d children post no-merge walk", - fib_node_list_get_size(PARENT()->fn_children)); - - /* - * schedule a walk that makes one one child progress. - * we do this by giving the queue draining process zero - * time quanta. it's a do..while loop, so it does something. - */ - high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE; - - fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX, - FIB_WALK_PRIORITY_HIGH, &high_ctx); - fib_walk_process_queues(vm, 0); - - FOR_EACH_TEST_CHILD(tc) - { - if (ii == N_TEST_CHILDREN) - { - FIB_TEST(1 == vec_len(tc->ctxs), - "%d child visitsed %d times in zero quanta walk", - ii, vec_len(tc->ctxs)); - } - else - { - FIB_TEST(0 == vec_len(tc->ctxs), - "%d child visitsed %d times in 0 quanta walk", - ii, vec_len(tc->ctxs)); - } - } - FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH), - "Queue is not empty post zero quanta walk"); - FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children), - "Parent has %d children post zero qunta walk", - fib_node_list_get_size(PARENT()->fn_children)); - - /* - * another one step - */ - fib_walk_process_queues(vm, 0); - - FOR_EACH_TEST_CHILD(tc) - { - if (ii >= N_TEST_CHILDREN-1) - { - FIB_TEST(1 == vec_len(tc->ctxs), - "%d child visitsed %d times in 2nd zero quanta walk", - ii, vec_len(tc->ctxs)); - } - else - { - FIB_TEST(0 == vec_len(tc->ctxs), - "%d child visitsed %d times in 2nd 0 quanta walk", - ii, vec_len(tc->ctxs)); - } - } - FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH), - "Queue is not empty post zero quanta walk"); - FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children), - "Parent has %d children post zero qunta walk", - fib_node_list_get_size(PARENT()->fn_children)); - - /* - * schedule another walk that will catch-up and merge. - */ - fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX, - FIB_WALK_PRIORITY_HIGH, &high_ctx); - fib_walk_process_queues(vm, 1); - - FOR_EACH_TEST_CHILD(tc) - { - if (ii >= N_TEST_CHILDREN-1) - { - FIB_TEST(2 == vec_len(tc->ctxs), - "%d child visitsed %d times in 2nd zero quanta merge walk", - ii, vec_len(tc->ctxs)); - vec_free(tc->ctxs); - } - else - { - FIB_TEST(1 == vec_len(tc->ctxs), - "%d child visitsed %d times in 2nd 0 quanta merge walk", - ii, vec_len(tc->ctxs)); - vec_free(tc->ctxs); - } - } - FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH), - "Queue is not empty post 2nd zero quanta merge walk"); - FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children), - "Parent has %d children post 2nd zero qunta merge walk", - fib_node_list_get_size(PARENT()->fn_children)); - - /* - * park a async walk in the middle of the list, then have an sync walk catch - * it. same expectations as async catches async. - */ - high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE; - - fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX, - FIB_WALK_PRIORITY_HIGH, &high_ctx); - - fib_walk_process_queues(vm, 0); - fib_walk_process_queues(vm, 0); - - fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx); - - FOR_EACH_TEST_CHILD(tc) - { - if (ii >= N_TEST_CHILDREN-1) - { - FIB_TEST(2 == vec_len(tc->ctxs), - "%d child visitsed %d times in sync catches async walk", - ii, vec_len(tc->ctxs)); - vec_free(tc->ctxs); - } - else - { - FIB_TEST(1 == vec_len(tc->ctxs), - "%d child visitsed %d times in sync catches async walk", - ii, vec_len(tc->ctxs)); - vec_free(tc->ctxs); - } - } - FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH), - "Queue is not empty post 2nd zero quanta merge walk"); - FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children), - "Parent has %d children post 2nd zero qunta merge walk", - fib_node_list_get_size(PARENT()->fn_children)); - - /* - * make the parent a child of one of its children, thus inducing a routing loop. - */ - fib_test_nodes[PARENT_INDEX].sibling = - fib_node_child_add(FIB_NODE_TYPE_TEST, - 1, // the first child - FIB_NODE_TYPE_TEST, - PARENT_INDEX); - - /* - * execute a sync walk from the parent. each child visited spawns more sync - * walks. we expect the walk to terminate. - */ - fib_test_walk_spawns_walks = 1; - - fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx); - - FOR_EACH_TEST_CHILD(tc) - { - /* - * child 1 - which is last in the list - has the loop. - * the other children a re thus visitsed first. the we meet - * child 1. we go round the loop again, visting the other children. - * then we meet the walk in the dep list and bail. child 1 is not visitsed - * again. - */ - if (1 == ii) - { - FIB_TEST(1 == vec_len(tc->ctxs), - "child %d visitsed %d times during looped sync walk", - ii, vec_len(tc->ctxs)); - } - else - { - FIB_TEST(2 == vec_len(tc->ctxs), - "child %d visitsed %d times during looped sync walk", - ii, vec_len(tc->ctxs)); - } - vec_free(tc->ctxs); - } - FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children), - "Parent has %d children post sync loop walk", - fib_node_list_get_size(PARENT()->fn_children)); - - /* - * the walk doesn't reach the max depth because the infra knows that sync - * meets sync implies a loop and bails early. - */ - FIB_TEST(high_ctx.fnbw_depth == 9, - "Walk context depth %d post sync loop walk", - high_ctx.fnbw_depth); - - /* - * execute an async walk of the graph loop, with each child spawns sync walks - */ - high_ctx.fnbw_depth = 0; - fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX, - FIB_WALK_PRIORITY_HIGH, &high_ctx); - - fib_walk_process_queues(vm, 1); - - FOR_EACH_TEST_CHILD(tc) - { - /* - * we don't really care how many times the children are visisted, as long as - * it is more than once. - */ - FIB_TEST(1 <= vec_len(tc->ctxs), - "child %d visitsed %d times during looped aync spawns sync walk", - ii, vec_len(tc->ctxs)); - vec_free(tc->ctxs); - } - - /* - * execute an async walk of the graph loop, with each child spawns async walks - */ - fib_test_walk_spawns_walks = 2; - high_ctx.fnbw_depth = 0; - fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX, - FIB_WALK_PRIORITY_HIGH, &high_ctx); - - fib_walk_process_queues(vm, 1); - - FOR_EACH_TEST_CHILD(tc) - { - /* - * we don't really care how many times the children are visisted, as long as - * it is more than once. - */ - FIB_TEST(1 <= vec_len(tc->ctxs), - "child %d visitsed %d times during looped async spawns async walk", - ii, vec_len(tc->ctxs)); - vec_free(tc->ctxs); - } - - - fib_node_child_remove(FIB_NODE_TYPE_TEST, - 1, // the first child - fib_test_nodes[PARENT_INDEX].sibling); - - /* - * cleanup - */ - FOR_EACH_TEST_CHILD(tc) - { - fib_node_child_remove(FIB_NODE_TYPE_TEST, PARENT_INDEX, - tc->sibling); - fib_node_deinit(&tc->node); - fib_node_unlock(&tc->node); - } - fib_node_deinit(PARENT()); - - /* - * The parent will be destroyed when the last lock on it goes. - * this test ensures all the walk objects are unlocking it. - */ - FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed), - "Parent was destroyed"); - - return (res); -} - -/* - * declaration of the otherwise static callback functions - */ -void fib_bfd_notify (bfd_listen_event_e event, - const bfd_session_t *session); -void adj_bfd_notify (bfd_listen_event_e event, - const bfd_session_t *session); - -/** - * Test BFD session interaction with FIB - */ -static int -fib_test_bfd (void) -{ - fib_node_index_t fei; - test_main_t *tm; - int n_feis, res; - - res = 0; - /* via 10.10.10.1 */ - ip46_address_t nh_10_10_10_1 = { - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01), - }; - /* via 10.10.10.2 */ - ip46_address_t nh_10_10_10_2 = { - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02), - }; - /* via 10.10.10.10 */ - ip46_address_t nh_10_10_10_10 = { - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a), - }; - n_feis = fib_entry_pool_size(); - - tm = &test_main; - - /* - * add interface routes. we'll assume this works. it's tested elsewhere - */ - fib_prefix_t pfx_10_10_10_10_s_24 = { - .fp_len = 24, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = nh_10_10_10_10, - }; - - fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_24, - FIB_SOURCE_INTERFACE, - (FIB_ENTRY_FLAG_CONNECTED | - FIB_ENTRY_FLAG_ATTACHED), - DPO_PROTO_IP4, - NULL, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, // weight - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - fib_prefix_t pfx_10_10_10_10_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = nh_10_10_10_10, - }; - fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_32, - FIB_SOURCE_INTERFACE, - (FIB_ENTRY_FLAG_CONNECTED | - FIB_ENTRY_FLAG_LOCAL), - DPO_PROTO_IP4, - NULL, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, // weight - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - /* - * A BFD session via a neighbour we do not yet know - */ - bfd_session_t bfd_10_10_10_1 = { - .udp = { - .key = { - .fib_index = 0, - .peer_addr = nh_10_10_10_1, - }, - }, - .hop_type = BFD_HOP_TYPE_MULTI, - .local_state = BFD_STATE_init, - }; - - fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1); - - /* - * A new entry will be created that forwards via the adj - */ - 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_prefix_t pfx_10_10_10_1_s_32 = { - .fp_addr = nh_10_10_10_1, - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - }; - 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_exact_match(0, &pfx_10_10_10_1_s_32); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &adj_o_10_10_10_1), - "BFD sourced %U via %U", - format_fib_prefix, &pfx_10_10_10_1_s_32, - format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE); - - /* - * Delete the BFD session. Expect the fib_entry to be removed - */ - fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1); - - fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32); - FIB_TEST(FIB_NODE_INDEX_INVALID == fei, - "BFD sourced %U removed", - format_fib_prefix, &pfx_10_10_10_1_s_32); - - /* - * Add the BFD source back - */ - fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1); - - /* - * source the entry via the ADJ fib - */ - fei = fib_table_entry_path_add(0, - &pfx_10_10_10_1_s_32, - FIB_SOURCE_ADJ, - FIB_ENTRY_FLAG_ATTACHED, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - /* - * Delete the BFD session. Expect the fib_entry to remain - */ - fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1); - - fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &adj_o_10_10_10_1), - "BFD sourced %U remains via %U", - format_fib_prefix, &pfx_10_10_10_1_s_32, - format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE); - - /* - * Add the BFD source back - */ - fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1); - - /* - * Create another ADJ FIB - */ - fib_prefix_t pfx_10_10_10_2_s_32 = { - .fp_addr = nh_10_10_10_2, - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - }; - fib_table_entry_path_add(0, - &pfx_10_10_10_2_s_32, - FIB_SOURCE_ADJ, - FIB_ENTRY_FLAG_ATTACHED, - DPO_PROTO_IP4, - &nh_10_10_10_2, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - /* - * A BFD session for the new ADJ FIB - */ - bfd_session_t bfd_10_10_10_2 = { - .udp = { - .key = { - .fib_index = 0, - .peer_addr = nh_10_10_10_2, - }, - }, - .hop_type = BFD_HOP_TYPE_MULTI, - .local_state = BFD_STATE_init, - }; - - fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_2); - - /* - * remove the adj-fib source whilst the session is present - * then add it back - */ - fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ); - fib_table_entry_path_add(0, - &pfx_10_10_10_2_s_32, - FIB_SOURCE_ADJ, - FIB_ENTRY_FLAG_ATTACHED, - DPO_PROTO_IP4, - &nh_10_10_10_2, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - /* - * Before adding a recursive via the BFD tracked ADJ-FIBs, - * bring one of the sessions UP, leave the other down - */ - bfd_10_10_10_1.local_state = BFD_STATE_up; - fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1); - bfd_10_10_10_2.local_state = BFD_STATE_down; - fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2); - - /* - * A recursive prefix via both of the ADJ FIBs - */ - fib_prefix_t pfx_200_0_0_0_s_24 = { - .fp_proto = FIB_PROTOCOL_IP4, - .fp_len = 32, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0xc8000000), - }, - }; - const dpo_id_t *dpo_10_10_10_1, *dpo_10_10_10_2; - - dpo_10_10_10_1 = - fib_entry_contribute_ip_forwarding( - fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32)); - dpo_10_10_10_2 = - fib_entry_contribute_ip_forwarding( - fib_table_lookup_exact_match(0, &pfx_10_10_10_2_s_32)); - - fib_test_lb_bucket_t lb_o_10_10_10_1 = { - .type = FT_LB_O_LB, - .lb = { - .lb = dpo_10_10_10_1->dpoi_index, - }, - }; - fib_test_lb_bucket_t lb_o_10_10_10_2 = { - .type = FT_LB_O_LB, - .lb = { - .lb = dpo_10_10_10_2->dpoi_index, - }, - }; - - /* - * A prefix via the adj-fib that is BFD down => DROP - */ - fei = fib_table_entry_path_add(0, - &pfx_200_0_0_0_s_24, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_2, - ~0, // recursive - 0, // default fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "%U resolves via drop", - format_fib_prefix, &pfx_200_0_0_0_s_24); - - /* - * add a path via the UP BFD adj-fib. - * we expect that the DOWN BFD ADJ FIB is not used. - */ - fei = fib_table_entry_path_add(0, - &pfx_200_0_0_0_s_24, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_1, - ~0, // recursive - 0, // default fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &lb_o_10_10_10_1), - "Recursive %U only UP BFD adj-fibs", - format_fib_prefix, &pfx_200_0_0_0_s_24); - - /* - * Send a BFD state change to UP - both sessions are now up - * the recursive prefix should LB over both - */ - bfd_10_10_10_2.local_state = BFD_STATE_up; - fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2); - - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 2, - &lb_o_10_10_10_1, - &lb_o_10_10_10_2), - "Recursive %U via both UP BFD adj-fibs", - format_fib_prefix, &pfx_200_0_0_0_s_24); - - /* - * Send a BFD state change to DOWN - * the recursive prefix should exclude the down - */ - bfd_10_10_10_2.local_state = BFD_STATE_down; - fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2); - - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &lb_o_10_10_10_1), - "Recursive %U via only UP", - format_fib_prefix, &pfx_200_0_0_0_s_24); - - /* - * Delete the BFD session while it is in the DOWN state. - * FIB should consider the entry's state as back up - */ - fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_2); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 2, - &lb_o_10_10_10_1, - &lb_o_10_10_10_2), - "Recursive %U via both UP BFD adj-fibs post down session delete", - format_fib_prefix, &pfx_200_0_0_0_s_24); - - /* - * Delete the BFD other session while it is in the UP state. - */ - fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 2, - &lb_o_10_10_10_1, - &lb_o_10_10_10_2), - "Recursive %U via both UP BFD adj-fibs post up session delete", - format_fib_prefix, &pfx_200_0_0_0_s_24); - - /* - * cleaup - */ - fib_table_entry_delete(0, &pfx_200_0_0_0_s_24, FIB_SOURCE_API); - fib_table_entry_delete(0, &pfx_10_10_10_1_s_32, FIB_SOURCE_ADJ); - fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ); - - fib_table_entry_delete(0, &pfx_10_10_10_10_s_32, FIB_SOURCE_INTERFACE); - fib_table_entry_delete(0, &pfx_10_10_10_10_s_24, FIB_SOURCE_INTERFACE); - - adj_unlock(ai_10_10_10_1); - /* - * 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"); - - /* - * Single-hop BFD tests - */ - bfd_10_10_10_1.hop_type = BFD_HOP_TYPE_SINGLE; - bfd_10_10_10_1.udp.key.sw_if_index = tm->hw[0]->sw_if_index; - - adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1); - - 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); - /* - * whilst the BFD session is not signalled, the adj is up - */ - FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on uninit session"); - - /* - * bring the BFD session up - */ - bfd_10_10_10_1.local_state = BFD_STATE_up; - adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1); - FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on UP session"); - - /* - * bring the BFD session down - */ - bfd_10_10_10_1.local_state = BFD_STATE_down; - adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1); - FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on DOWN session"); - - /* - * add an attached next hop FIB entry via the down adj - */ - fib_prefix_t pfx_5_5_5_5_s_32 = { - .fp_addr = { - .ip4 = { - .as_u32 = clib_host_to_net_u32(0x05050505), - }, - }, - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - }; - - fei = fib_table_entry_path_add(0, - &pfx_5_5_5_5_s_32, - FIB_SOURCE_CLI, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)), - "%U resolves via drop", - format_fib_prefix, &pfx_5_5_5_5_s_32); - - /* - * Add a path via an ADJ that is up - */ - 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, - }, - }; - adj_o_10_10_10_1.adj.adj = ai_10_10_10_1; - - fei = fib_table_entry_path_add(0, - &pfx_5_5_5_5_s_32, - FIB_SOURCE_CLI, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_2, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &adj_o_10_10_10_2), - "BFD sourced %U via %U", - format_fib_prefix, &pfx_5_5_5_5_s_32, - format_ip_adjacency, ai_10_10_10_2, FORMAT_IP_ADJACENCY_NONE); - - /* - * Bring up the down session - should now LB - */ - bfd_10_10_10_1.local_state = BFD_STATE_up; - adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 2, - &adj_o_10_10_10_1, - &adj_o_10_10_10_2), - "BFD sourced %U via noth adjs", - format_fib_prefix, &pfx_5_5_5_5_s_32); - - /* - * remove the BFD session state from the adj - */ - adj_bfd_notify(BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1); - - /* - * clean-up - */ - fib_table_entry_delete(0, &pfx_5_5_5_5_s_32, FIB_SOURCE_CLI); - adj_unlock(ai_10_10_10_1); - adj_unlock(ai_10_10_10_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 (res); -} - -static int -lfib_test (void) -{ - const mpls_label_t deag_label = 50; - adj_index_t ai_mpls_10_10_10_1; - dpo_id_t dpo = DPO_INVALID; - const u32 lfib_index = 0; - const u32 fib_index = 0; - const dpo_id_t *dpo1; - fib_node_index_t lfe; - lookup_dpo_t *lkd; - int lb_count, res; - test_main_t *tm; - - res = 0; - tm = &test_main; - lb_count = pool_elts(load_balance_pool); - - FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d", - adj_nbr_db_size()); - - /* - * 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); - - ip46_address_t nh_10_10_10_1 = { - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01), - }; - ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_MPLS, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index); - - /* - * Test the specials stack properly. - */ - fib_prefix_t exp_null_v6_pfx = { - .fp_proto = FIB_PROTOCOL_MPLS, - .fp_eos = MPLS_EOS, - .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL, - .fp_payload_proto = DPO_PROTO_IP6, - }; - lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx); - FIB_TEST((FIB_NODE_INDEX_INVALID != lfe), - "%U/%U present", - format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL, - format_mpls_eos_bit, MPLS_EOS); - fib_entry_contribute_forwarding(lfe, - FIB_FORW_CHAIN_TYPE_MPLS_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_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_EOS); - FIB_TEST((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table), - "%U/%U is lookup in interface's table", - format_mpls_unicast_label, deag_label, - format_mpls_eos_bit, MPLS_EOS); - FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto), - "%U/%U is %U dst deag", - format_mpls_unicast_label, deag_label, - format_mpls_eos_bit, MPLS_EOS, - format_dpo_proto, lkd->lkd_proto); - - /* - * A route deag route for EOS - */ - fib_prefix_t pfx = { - .fp_proto = FIB_PROTOCOL_MPLS, - .fp_eos = MPLS_EOS, - .fp_label = deag_label, - .fp_payload_proto = DPO_PROTO_IP4, - }; - mpls_disp_dpo_t *mdd; - lfe = fib_table_entry_path_add(lfib_index, - &pfx, - FIB_SOURCE_CLI, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &zero_addr, - ~0, - fib_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_EOS); - - fib_entry_contribute_forwarding(lfe, - FIB_FORW_CHAIN_TYPE_MPLS_EOS, - &dpo); - dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0); - 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", - format_mpls_unicast_label, deag_label, - 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_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_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); - - /* - * A route deag route for EOS with LSP mode uniform - */ - 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, - 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_EOS); - - fib_entry_contribute_forwarding(lfe, - FIB_FORW_CHAIN_TYPE_MPLS_EOS, - &dpo); - dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0); - 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_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_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_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); - - /* - * 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, - .fp_proto = FIB_PROTOCOL_MPLS, - .fp_label = 1200, - .fp_eos = MPLS_NON_EOS, - }; - fib_test_lb_bucket_t neos_o_10_10_10_1 = { - .type = FT_LB_LABEL_STACK_O_ADJ, - .label_stack_o_adj = { - .adj = ai_mpls_10_10_10_1, - .label_stack_size = 4, - .label_stack = { - 200, 300, 400, 500, - }, - .eos = MPLS_NON_EOS, - }, - }; - dpo_id_t neos_1200 = DPO_INVALID; - dpo_id_t ip_1200 = DPO_INVALID; - 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, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - l200, - FIB_ROUTE_PATH_FLAG_NONE); - - FIB_TEST(!fib_test_validate_entry(lfe, - FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, - 1, - &neos_o_10_10_10_1), - "1200/0 LB 1 buckets via: " - "adj 10.10.11.1"); - - /* - * A recursive route via the MPLS x-connect - */ - fib_prefix_t pfx_2_2_2_3_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x02020203), - }, - }; - fib_route_path_t *rpaths = NULL, rpath = { - .frp_proto = DPO_PROTO_MPLS, - .frp_local_label = 1200, - .frp_eos = MPLS_NON_EOS, - .frp_sw_if_index = ~0, // recurive - .frp_fib_index = 0, // Default MPLS fib - .frp_weight = 1, - .frp_flags = FIB_ROUTE_PATH_FLAG_NONE, - .frp_label_stack = NULL, - }; - vec_add1(rpaths, rpath); - - fib_table_entry_path_add2(fib_index, - &pfx_2_2_2_3_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - rpaths); - - /* - * A labelled recursive route via the MPLS x-connect - */ - fib_prefix_t pfx_2_2_2_4_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x02020204), - }, - }; - 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, - &pfx_2_2_2_4_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - rpaths); - - fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200), - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - &ip_1200); - fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200), - FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, - &neos_1200); - - fib_test_lb_bucket_t ip_o_1200 = { - .type = FT_LB_O_LB, - .lb = { - .lb = ip_1200.dpoi_index, - }, - }; - fib_test_lb_bucket_t mpls_o_1200 = { - .type = FT_LB_LABEL_O_LB, - .label_o_lb = { - .lb = neos_1200.dpoi_index, - .label = 999, - .eos = MPLS_EOS, - }, - }; - - lfe = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32); - FIB_TEST(!fib_test_validate_entry(lfe, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &ip_o_1200), - "2.2.2.2.3/32 LB 1 buckets via: label 1200 EOS"); - lfe = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32); - FIB_TEST(!fib_test_validate_entry(lfe, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &mpls_o_1200), - "2.2.2.2.4/32 LB 1 buckets via: label 1200 non-EOS"); - - fib_table_entry_delete(fib_index, &pfx_1200, FIB_SOURCE_API); - fib_table_entry_delete(fib_index, &pfx_2_2_2_3_s_32, FIB_SOURCE_API); - fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API); - - dpo_reset(&neos_1200); - dpo_reset(&ip_1200); - - /* - * A recursive via a label that does not exist - */ - fib_test_lb_bucket_t bucket_drop = { - .type = FT_LB_DROP, - .special = { - .adj = DPO_PROTO_IP4, - }, - }; - fib_test_lb_bucket_t mpls_bucket_drop = { - .type = FT_LB_DROP, - .special = { - .adj = DPO_PROTO_MPLS, - }, - }; - - rpaths[0].frp_label_stack = NULL; - lfe = fib_table_entry_path_add2(fib_index, - &pfx_2_2_2_4_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - rpaths); - - fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200), - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - &ip_1200); - ip_o_1200.lb.lb = ip_1200.dpoi_index; - - FIB_TEST(!fib_test_validate_entry(lfe, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &bucket_drop), - "2.2.2.2.4/32 LB 1 buckets via: drop"); - lfe = fib_table_lookup(fib_index, &pfx_1200); - FIB_TEST(!fib_test_validate_entry(lfe, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &bucket_drop), - "1200/neos LB 1 buckets via: ip4-DROP"); - FIB_TEST(!fib_test_validate_entry(lfe, - FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, - 1, - &mpls_bucket_drop), - "1200/neos LB 1 buckets via: mpls-DROP"); - - fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API); - - dpo_reset(&ip_1200); - - /* - * An rx-interface route. - * like the tail of an mcast LSP - */ - dpo_id_t idpo = DPO_INVALID; - - interface_rx_dpo_add_or_lock(DPO_PROTO_IP4, - tm->hw[0]->sw_if_index, - &idpo); - - fib_prefix_t pfx_2500 = { - .fp_len = 21, - .fp_proto = FIB_PROTOCOL_MPLS, - .fp_label = 2500, - .fp_eos = MPLS_EOS, - .fp_payload_proto = DPO_PROTO_IP4, - }; - fib_test_lb_bucket_t rx_intf_0 = { - .type = FT_LB_INTF, - .adj = { - .adj = idpo.dpoi_index, - }, - }; - - lfe = fib_table_entry_update_one_path(fib_index, - &pfx_2500, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - NULL, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 0, - NULL, - FIB_ROUTE_PATH_INTF_RX); - FIB_TEST(!fib_test_validate_entry(lfe, - FIB_FORW_CHAIN_TYPE_MPLS_EOS, - 1, - &rx_intf_0), - "2500 rx-interface 0"); - fib_table_entry_delete(fib_index, &pfx_2500, FIB_SOURCE_API); - - /* - * An MPLS mulicast entry - */ - fib_prefix_t pfx_3500 = { - .fp_len = 21, - .fp_proto = FIB_PROTOCOL_MPLS, - .fp_label = 3500, - .fp_eos = MPLS_EOS, - .fp_payload_proto = DPO_PROTO_IP4, - }; - fib_test_rep_bucket_t mc_0 = { - .type = FT_REP_LABEL_O_ADJ, - .label_o_adj = { - .adj = ai_mpls_10_10_10_1, - .label = 3300, - .eos = MPLS_EOS, - }, - }; - fib_test_rep_bucket_t mc_intf_0 = { - .type = FT_REP_INTF, - .adj = { - .adj = idpo.dpoi_index, - }, - }; - 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, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_MULTICAST, - DPO_PROTO_IP4, - &nh_10_10_10_1, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 1, - l3300, - FIB_ROUTE_PATH_FLAG_NONE); - FIB_TEST(!fib_test_validate_entry(lfe, - FIB_FORW_CHAIN_TYPE_MPLS_EOS, - 1, - &mc_0), - "3500 via replicate over 10.10.10.1"); - - /* - * MPLS Bud-node. Add a replication via an interface-receieve path - */ - lfe = fib_table_entry_path_add(lfib_index, - &pfx_3500, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_MULTICAST, - DPO_PROTO_IP4, - NULL, - tm->hw[0]->sw_if_index, - ~0, // invalid fib index - 0, - NULL, - FIB_ROUTE_PATH_INTF_RX); - FIB_TEST(!fib_test_validate_entry(lfe, - FIB_FORW_CHAIN_TYPE_MPLS_EOS, - 2, - &mc_0, - &mc_intf_0), - "3500 via replicate over 10.10.10.1 and interface-rx"); - - /* - * Add a replication via an interface-free for-us path - */ - fib_test_rep_bucket_t mc_disp = { - .type = FT_REP_DISP_MFIB_LOOKUP, - .adj = { - .adj = idpo.dpoi_index, - }, - }; - lfe = fib_table_entry_path_add(lfib_index, - &pfx_3500, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_MULTICAST, - DPO_PROTO_IP4, - NULL, - 5, // rpf-id - 0, // default table - 0, - NULL, - FIB_ROUTE_PATH_RPF_ID); - FIB_TEST(!fib_test_validate_entry(lfe, - FIB_FORW_CHAIN_TYPE_MPLS_EOS, - 3, - &mc_0, - &mc_disp, - &mc_intf_0), - "3500 via replicate over 10.10.10.1 and interface-rx"); - - - - fib_table_entry_delete(fib_index, &pfx_3500, FIB_SOURCE_API); - dpo_reset(&idpo); - - /* - * cleanup - */ - mpls_sw_interface_enable_disable(&mpls_main, - tm->hw[0]->sw_if_index, - 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)); - FIB_TEST(0 == pool_elts(interface_rx_dpo_pool), - "interface_rx_dpo resources freed %d of %d", - 0, pool_elts(interface_rx_dpo_pool)); - - return (res); -} - -static int -fib_test_inherit (void) -{ - fib_node_index_t fei; - test_main_t *tm; - int n_feis, res; - - res = 0; - 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_3 = { - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03), - }; - 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), - }; - const ip46_address_t nh_11_11_11_11 = { - .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b), - }; - const ip46_address_t nh_11_11_11_0 = { - .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b00), - }; - - /* - * 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, - }; - const u32 N_PLS = fib_path_list_pool_size(); - - 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); - 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); - - /* - * Add/remove an interposer source to a new /32 - */ - const fib_prefix_t pfx_11_11_11_11_s_32 = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = nh_11_11_11_11, - }; - - fib_table_entry_update_one_path(0, - &pfx_11_11_11_11_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_3, - tm->hw[0]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - dpo_id_t interposer = DPO_INVALID; - fib_mpls_label_t *l99 = NULL, fml_99 = { - .fml_value = 99, - }; - vec_add1(l99, fml_99); - - mpls_label_dpo_create(l99, - MPLS_EOS, - DPO_PROTO_IP4, - MPLS_LABEL_DPO_FLAG_NONE, - punt_dpo_get(DPO_PROTO_MPLS), - &interposer); - - adj_index_t ai_10_10_10_3 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_IP4, - &nh_10_10_10_3, - tm->hw[0]->sw_if_index); - fib_test_lb_bucket_t adj_o_10_10_10_3 = { - .type = FT_LB_ADJ, - .adj = { - .adj = ai_10_10_10_3, - }, - }; - fib_test_lb_bucket_t l99_o_10_10_10_3 = { - .type = FT_LB_LABEL_O_ADJ, - .label_o_adj = { - .adj = ai_10_10_10_3, - .label = 99, - .eos = MPLS_EOS, - }, - }; - - fei = fib_table_entry_special_dpo_add(0, - &pfx_11_11_11_11_s_32, - FIB_SOURCE_SPECIAL, - FIB_ENTRY_FLAG_INTERPOSE, - &interposer); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &l99_o_10_10_10_3), - "%U via interposer adj", - format_fib_prefix,&pfx_11_11_11_11_s_32); - - fib_table_entry_special_remove(0, - &pfx_11_11_11_11_s_32, - FIB_SOURCE_SPECIAL); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &adj_o_10_10_10_3), - "%U via 10.10.10.1", - format_fib_prefix, &pfx_11_11_11_11_s_32); - - /* - * remove and re-add the second best API source while the interpose - * is present - */ - fei = fib_table_entry_special_dpo_add(0, - &pfx_11_11_11_11_s_32, - FIB_SOURCE_SPECIAL, - FIB_ENTRY_FLAG_INTERPOSE, - &interposer); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &l99_o_10_10_10_3), - "%U via interposer adj", - format_fib_prefix,&pfx_11_11_11_11_s_32); - - FIB_TEST(2 == pool_elts(mpls_label_dpo_pool), - "MPLS label pool: %d", - pool_elts(mpls_label_dpo_pool)); - - fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API); - - /* - * the interpose does not get stacked when there are not valid paths - */ - fib_test_lb_bucket_t bucket_drop = { - .type = FT_LB_DROP, - .special = { - .adj = DPO_PROTO_IP4, - }, - }; - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &bucket_drop), - "%U via drop", - format_fib_prefix,&pfx_11_11_11_11_s_32); - - fib_table_entry_update_one_path(0, - &pfx_11_11_11_11_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_3, - tm->hw[0]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &l99_o_10_10_10_3), - "%U via interposer adj", - format_fib_prefix,&pfx_11_11_11_11_s_32); - fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API); - - /* - * add a cover for the interposed entry, so that we test it selects - * the covers forwarding. - */ - const fib_prefix_t pfx_11_11_11_0_s_24 = { - .fp_len = 24, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = nh_11_11_11_0, - }; - fib_table_entry_update_one_path(0, - &pfx_11_11_11_0_s_24, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_3, - tm->hw[0]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &l99_o_10_10_10_3), - "%U via interposer adj", - format_fib_prefix,&pfx_11_11_11_11_s_32); - - /* - * multiple interpose sources on the same entry. Only the high - * priority source gets to add the interpose. - */ - dpo_id_t interposer2 = DPO_INVALID; - fib_mpls_label_t *l100 = NULL, fml_100 = { - .fml_value = 100, - }; - vec_add1(l100, fml_100); - - mpls_label_dpo_create(l100, - MPLS_EOS, - DPO_PROTO_IP4, - MPLS_LABEL_DPO_FLAG_NONE, - punt_dpo_get(DPO_PROTO_MPLS), - &interposer2); - - fei = fib_table_entry_special_dpo_add(0, - &pfx_11_11_11_11_s_32, - FIB_SOURCE_CLASSIFY, - FIB_ENTRY_FLAG_INTERPOSE, - &interposer2); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &l99_o_10_10_10_3), - "%U via interposer label 99", - format_fib_prefix,&pfx_11_11_11_11_s_32); - - fib_test_lb_bucket_t l100_o_10_10_10_3 = { - .type = FT_LB_LABEL_O_ADJ, - .label_o_adj = { - .adj = ai_10_10_10_3, - .label = 100, - .eos = MPLS_EOS, - }, - }; - - fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_SPECIAL); - - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &l100_o_10_10_10_3), - "%U via interposer label 99", - format_fib_prefix,&pfx_11_11_11_11_s_32); - - fib_table_entry_delete(0, &pfx_11_11_11_0_s_24, FIB_SOURCE_API); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &bucket_drop), - "%U via drop", - format_fib_prefix,&pfx_11_11_11_11_s_32); - fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_CLASSIFY); - - /* - * update a source to/from interpose. - */ - /* fib_table_entry_update_one_path(0, */ - /* &pfx_11_11_11_0_s_24, */ - /* FIB_SOURCE_API, */ - /* FIB_ENTRY_FLAG_NONE, */ - /* DPO_PROTO_IP4, */ - /* &nh_10_10_10_3, */ - /* tm->hw[0]->sw_if_index, */ - /* ~0, */ - /* 1, */ - /* NULL, */ - /* FIB_ROUTE_PATH_FLAG_NONE); */ - /* fei = fib_table_entry_special_dpo_add(0, */ - /* &pfx_11_11_11_11_s_32, */ - /* FIB_SOURCE_API, */ - /* FIB_ENTRY_FLAG_INTERPOSE, */ - /* &interposer); */ - /* FIB_TEST(!fib_test_validate_entry(fei, */ - /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */ - /* 1, */ - /* &l99_o_10_10_10_3), */ - /* "%U via interposer label 99", */ - /* format_fib_prefix,&pfx_11_11_11_11_s_32); */ - - /* FIB_TEST(3 == pool_elts(mpls_label_dpo_pool), */ - /* "MPLS label pool: %d", */ - /* pool_elts(mpls_label_dpo_pool)); */ - /* FIB_TEST((2 == mpls_label_dpo_get(interposer.dpoi_index)->mld_locks), */ - /* "Interposer %d locks", */ - /* mpls_label_dpo_get(interposer.dpoi_index)->mld_locks); */ - - /* fib_table_entry_update_one_path(0, */ - /* &pfx_11_11_11_11_s_32, */ - /* FIB_SOURCE_API, */ - /* FIB_ENTRY_FLAG_NONE, */ - /* DPO_PROTO_IP4, */ - /* &nh_10_10_10_2, */ - /* tm->hw[0]->sw_if_index, */ - /* ~0, */ - /* 1, */ - /* NULL, */ - /* FIB_ROUTE_PATH_FLAG_NONE); */ - /* 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_11_11_11_11_s_32); */ - - /* FIB_TEST((1 == mpls_label_dpo_get(interposer.dpoi_index)->mld_locks), */ - /* "Interposer %d locks", */ - /* mpls_label_dpo_get(interposer.dpoi_index)->mld_locks); */ - /* FIB_TEST(2 == pool_elts(mpls_label_dpo_pool), */ - /* "MPLS label pool: %d", */ - /* pool_elts(mpls_label_dpo_pool)); */ - - /* fei = fib_table_entry_special_dpo_add(0, */ - /* &pfx_11_11_11_11_s_32, */ - /* FIB_SOURCE_API, */ - /* FIB_ENTRY_FLAG_INTERPOSE, */ - /* &interposer); */ - /* FIB_TEST(!fib_test_validate_entry(fei, */ - /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */ - /* 1, */ - /* &l99_o_10_10_10_3), */ - /* "%U via interposer label 99", */ - /* format_fib_prefix,&pfx_11_11_11_11_s_32); */ - - /* fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API); */ - - /* - * Add/remove an interposer source from the top of the subtrie. The - * interposer source is not inherited. - */ - 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_3, - tm->hw[0]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_entry_special_dpo_add(0, - &pfx_10_10_10_0_s_24, - FIB_SOURCE_SPECIAL, - FIB_ENTRY_FLAG_INTERPOSE, - &interposer); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &l99_o_10_10_10_3), - "%U via interposer label", - 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, - &bucket_drop), - "%U via drop", - format_fib_prefix, &pfx_10_10_10_21_s_32); - - fib_table_entry_special_remove(0, - &pfx_10_10_10_0_s_24, - FIB_SOURCE_SPECIAL); - 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_3), - "%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_3), - "%U via via 10.10.10.1", - format_fib_prefix, &pfx_10_10_10_21_s_32); - - /* - * Add/remove an interposer source from the top of the subtrie. The - * interposer source is inherited. - */ - fei = fib_table_entry_special_dpo_add(0, - &pfx_10_10_10_0_s_24, - FIB_SOURCE_SPECIAL, - (FIB_ENTRY_FLAG_COVERED_INHERIT | - FIB_ENTRY_FLAG_INTERPOSE), - &interposer); - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &l99_o_10_10_10_3), - "%U via interposer label", - format_fib_prefix,&pfx_10_10_10_0_s_24); - - /* interposer gets forwarding from the drop cli source */ - 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, - &bucket_drop), - "%U via drop", - format_fib_prefix,&pfx_10_10_10_21_s_32); - - fib_table_entry_update_one_path(0, - &pfx_10_10_10_21_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh_10_10_10_3, - tm->hw[0]->sw_if_index, - ~0, - 1, - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - fib_table_entry_delete(0, &pfx_10_10_10_21_s_32, FIB_SOURCE_CLI); - /* interposer gets forwarding from the API source */ - FIB_TEST(!fib_test_validate_entry(fei, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - 1, - &l99_o_10_10_10_3), - "%U via interposer label", - format_fib_prefix,&pfx_10_10_10_21_s_32); - - /* - * cleanup - */ - fib_table_entry_delete(0, &pfx_10_10_10_22_s_32, FIB_SOURCE_CLI); - fib_table_entry_delete(0, &pfx_10_10_10_21_s_32, FIB_SOURCE_API); - 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); - fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, FIB_SOURCE_SPECIAL); - adj_unlock(ai_10_10_10_1); - adj_unlock(ai_10_10_10_2); - adj_unlock(ai_10_10_10_3); - dpo_reset(&interposer); - dpo_reset(&interposer2); - FIB_TEST(0 == pool_elts(mpls_label_dpo_pool), - "MPLS label pool empty: %d", - pool_elts(mpls_label_dpo_pool)); - FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed"); - FIB_TEST(N_PLS == fib_path_list_pool_size(), - "number of path-lists: %d = %d", - N_PLS, fib_path_list_pool_size()); - - /* - * test the v6 tree walk. - * a /64 that covers everything. 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 (res); -} - -static int -fib_test_sticky (void) -{ - fib_route_path_t *r_paths = NULL; - test_main_t *tm = &test_main; - u32 ii, lb_count, pl_count; - dpo_id_t dpo = DPO_INVALID; - fib_node_index_t pl_index; - int res = 0; -#define N_PATHS 16 - - fib_test_lb_bucket_t buckets[N_PATHS]; - bfd_session_t bfds[N_PATHS] = {{0}}; - - lb_count = pool_elts(load_balance_pool); - pl_count = fib_path_list_pool_size(); - - for (ii = 0; ii < N_PATHS; ii++) - { - ip46_address_t nh = { - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii), - }; - adj_index_t ai; - - ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - VNET_LINK_IP4, - &nh, tm->hw[0]->sw_if_index); - - buckets[ii].type = FT_LB_ADJ; - buckets[ii].adj.adj = ai; - - bfds[ii].udp.key.peer_addr = nh; - bfds[ii].udp.key.sw_if_index = tm->hw[0]->sw_if_index; - bfds[ii].hop_type = BFD_HOP_TYPE_SINGLE; - bfds[ii].local_state = BFD_STATE_init; - adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfds[ii]); - bfds[ii].local_state = BFD_STATE_up; - adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[ii]); - } - - for (ii = 0; ii < N_PATHS; ii++) - { - fib_route_path_t r_path = { - .frp_proto = DPO_PROTO_IP4, - .frp_addr = { - .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii), - }, - .frp_sw_if_index = tm->hw[0]->sw_if_index, - .frp_weight = 1, - .frp_fib_index = ~0, - }; - vec_add1(r_paths, r_path); - }; - - pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths); - fib_path_list_lock(pl_index); - - fib_path_list_contribute_forwarding(pl_index, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - FIB_PATH_LIST_FWD_FLAG_STICKY, - &dpo); - - FIB_TEST(!fib_test_validate_lb(&dpo, - 16, - &buckets[0], - &buckets[1], - &buckets[2], - &buckets[3], - &buckets[4], - &buckets[5], - &buckets[6], - &buckets[7], - &buckets[8], - &buckets[9], - &buckets[10], - &buckets[11], - &buckets[12], - &buckets[13], - &buckets[14], - &buckets[15]), - "Setup OK"); - - /* take down paths */ - bfds[0].local_state = BFD_STATE_down; - adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[0]); - - fib_path_list_contribute_forwarding(pl_index, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - FIB_PATH_LIST_FWD_FLAG_STICKY, - &dpo); - - FIB_TEST(!fib_test_validate_lb(&dpo, - 16, - &buckets[1], - &buckets[1], - &buckets[2], - &buckets[3], - &buckets[4], - &buckets[5], - &buckets[6], - &buckets[7], - &buckets[8], - &buckets[9], - &buckets[10], - &buckets[11], - &buckets[12], - &buckets[13], - &buckets[14], - &buckets[15]), - "Failed at shut-down path 0"); - - bfds[7].local_state = BFD_STATE_down; - adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[7]); - - fib_path_list_contribute_forwarding(pl_index, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - FIB_PATH_LIST_FWD_FLAG_STICKY, - &dpo); - - FIB_TEST(!fib_test_validate_lb(&dpo, - 16, - &buckets[1], - &buckets[1], - &buckets[2], - &buckets[3], - &buckets[4], - &buckets[5], - &buckets[6], - &buckets[2], - &buckets[8], - &buckets[9], - &buckets[10], - &buckets[11], - &buckets[12], - &buckets[13], - &buckets[14], - &buckets[15]), - "Failed at shut-down path 7"); - - /* paths back up */ - bfds[0].local_state = BFD_STATE_up; - adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[0]); - bfds[7].local_state = BFD_STATE_up; - adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[7]); - - fib_path_list_contribute_forwarding(pl_index, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - FIB_PATH_LIST_FWD_FLAG_STICKY, - &dpo); - - FIB_TEST(!fib_test_validate_lb(&dpo, - 16, - &buckets[0], - &buckets[1], - &buckets[2], - &buckets[3], - &buckets[4], - &buckets[5], - &buckets[6], - &buckets[7], - &buckets[8], - &buckets[9], - &buckets[10], - &buckets[11], - &buckets[12], - &buckets[13], - &buckets[14], - &buckets[15]), - "recovery OK"); - - fib_path_list_unlock(pl_index); - - /* - * non-power of 2 number of buckets - */ - fib_route_path_t *r_paths2 = NULL; - - r_paths2 = vec_dup(r_paths); - _vec_len(r_paths2) = 3; - - pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths2); - fib_path_list_lock(pl_index); - - fib_path_list_contribute_forwarding(pl_index, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - FIB_PATH_LIST_FWD_FLAG_STICKY, - &dpo); - - FIB_TEST(!fib_test_validate_lb(&dpo, - 16, - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[1], - &buckets[1], - &buckets[1], - &buckets[1], - &buckets[1], - &buckets[2], - &buckets[2], - &buckets[2], - &buckets[2], - &buckets[2]), - "non-power of 2"); - - bfds[1].local_state = BFD_STATE_down; - adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]); - - fib_path_list_contribute_forwarding(pl_index, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - FIB_PATH_LIST_FWD_FLAG_STICKY, - &dpo); - - /* - * path 1's buckets alternate between path 0 and 2 - */ - FIB_TEST(!fib_test_validate_lb(&dpo, - 16, - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[2], - &buckets[0], - &buckets[2], - &buckets[0], - &buckets[2], - &buckets[2], - &buckets[2], - &buckets[2], - &buckets[2]), - "non-power of 2"); - bfds[1].local_state = BFD_STATE_up; - adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]); - - fib_path_list_unlock(pl_index); - - /* - * unequal cost - */ - fib_route_path_t *r_paths3 = NULL; - - r_paths3 = vec_dup(r_paths); - _vec_len(r_paths3) = 3; - - r_paths3[0].frp_weight = 3; - - pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths3); - fib_path_list_lock(pl_index); - - fib_path_list_contribute_forwarding(pl_index, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - FIB_PATH_LIST_FWD_FLAG_STICKY, - &dpo); - - FIB_TEST(!fib_test_validate_lb(&dpo, - 16, - &buckets[1], - &buckets[1], - &buckets[1], - &buckets[2], - &buckets[2], - &buckets[2], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0]), - "UCMP"); - - bfds[1].local_state = BFD_STATE_down; - adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]); - - fib_path_list_contribute_forwarding(pl_index, - FIB_FORW_CHAIN_TYPE_UNICAST_IP4, - FIB_PATH_LIST_FWD_FLAG_STICKY, - &dpo); - /* No attempt to Un-equal distribute the down path's buckets */ - FIB_TEST(!fib_test_validate_lb(&dpo, - 16, - &buckets[2], - &buckets[0], - &buckets[2], - &buckets[2], - &buckets[2], - &buckets[2], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0], - &buckets[0]), - "UCMP"); - bfds[1].local_state = BFD_STATE_up; - adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]); - - dpo_reset(&dpo); - fib_path_list_unlock(pl_index); - - vec_free(r_paths); - vec_free(r_paths2); - vec_free(r_paths3); - - FIB_TEST(lb_count == pool_elts(load_balance_pool), "no leaked LBs"); - FIB_TEST(pl_count == fib_path_list_pool_size(), "no leaked PLs"); - - return 0; -} - -static clib_error_t * -fib_test (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd_arg) -{ - int res; - - res = 0; - - fib_test_mk_intf(4); - - if (unformat (input, "debug")) - { - fib_test_do_debug = 1; - } - - if (unformat (input, "ip4")) - { - res += fib_test_v4(); - } - else if (unformat (input, "ip6")) - { - res += fib_test_v6(); - } - else if (unformat (input, "ip")) - { - res += fib_test_v4(); - res += fib_test_v6(); - } - else if (unformat (input, "label")) - { - res += fib_test_label(); - } - else if (unformat (input, "ae")) - { - res += fib_test_ae(); - } - else if (unformat (input, "pref")) - { - res += fib_test_pref(); - } - else if (unformat (input, "lfib")) - { - res += lfib_test(); - } - else if (unformat (input, "walk")) - { - res += fib_test_walk(); - } - else if (unformat (input, "bfd")) - { - res += fib_test_bfd(); - } - else if (unformat (input, "inherit")) - { - res += fib_test_inherit(); - } - else if (unformat (input, "sticky")) - { - res += fib_test_sticky(); - } - else - { - res += fib_test_v4(); - res += fib_test_v6(); - res += fib_test_ae(); - res += fib_test_bfd(); - res += fib_test_pref(); - res += fib_test_label(); - res += fib_test_inherit(); - res += lfib_test(); - - /* - * fib-walk process must be disabled in order for the walk tests to work - */ - fib_walk_process_disable(); - res += fib_test_walk(); - fib_walk_process_enable(); - } - - fflush(NULL); - if (res) - { - return clib_error_return(0, "FIB Unit Test Failed"); - } - else - { - return (NULL); - } -} - -VLIB_CLI_COMMAND (test_fib_command, static) = { - .path = "test fib", - .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM", - .function = fib_test, -}; - -clib_error_t * -fib_test_init (vlib_main_t *vm) -{ - return 0; -} - -VLIB_INIT_FUNCTION (fib_test_init); |