2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 #include <vnet/fib/fib_test.h>
17 #include <vnet/fib/ip6_fib.h>
18 #include <vnet/fib/ip4_fib.h>
19 #include <vnet/fib/mpls_fib.h>
20 #include <vnet/adj/adj.h>
21 #include <vnet/dpo/load_balance.h>
22 #include <vnet/dpo/load_balance_map.h>
23 #include <vnet/dpo/mpls_label_dpo.h>
24 #include <vnet/dpo/lookup_dpo.h>
25 #include <vnet/dpo/drop_dpo.h>
26 #include <vnet/dpo/receive_dpo.h>
27 #include <vnet/dpo/ip_null_dpo.h>
28 #include <vnet/bfd/bfd_main.h>
29 #include <vnet/dpo/interface_rx_dpo.h>
30 #include <vnet/dpo/replicate_dpo.h>
31 #include <vnet/dpo/dvr_dpo.h>
32 #include <vnet/dpo/mpls_disposition.h>
34 #include <vnet/mpls/mpls.h>
36 #include <vnet/fib/fib_test.h>
37 #include <vnet/fib/fib_path_list.h>
38 #include <vnet/fib/fib_entry_src.h>
39 #include <vnet/fib/fib_walk.h>
40 #include <vnet/fib/fib_node_list.h>
41 #include <vnet/fib/fib_urpf_list.h>
43 #include <vlib/unix/plugin.h>
46 * Add debugs for passing tests
48 static int fib_test_do_debug;
50 #define FIB_TEST_I(_cond, _comment, _args...) \
52 int _evald = (_cond); \
54 fformat(stderr, "FAIL:%d: " _comment "\n", \
57 if (fib_test_do_debug) \
58 fformat(stderr, "PASS:%d: " _comment "\n", \
63 #define FIB_TEST(_cond, _comment, _args...) \
65 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
67 ASSERT(!("FAIL: " _comment)); \
72 * A 'i'm not fussed is this is not efficient' store of test data
74 typedef struct test_main_t_ {
78 u32 hw_if_indicies[4];
82 vnet_hw_interface_t * hw[4];
85 static test_main_t test_main;
87 /* fake ethernet device class, distinct from "fake-ethX" */
88 static u8 * format_test_interface_name (u8 * s, va_list * args)
90 u32 dev_instance = va_arg (*args, u32);
91 return format (s, "test-eth%d", dev_instance);
94 static uword dummy_interface_tx (vlib_main_t * vm,
95 vlib_node_runtime_t * node,
98 clib_warning ("you shouldn't be here, leaking buffers...");
99 return frame->n_vectors;
102 static clib_error_t *
103 test_interface_admin_up_down (vnet_main_t * vnm,
107 u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
108 VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
109 vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
113 VNET_DEVICE_CLASS (test_interface_device_class,static) = {
114 .name = "Test interface",
115 .format_device_name = format_test_interface_name,
116 .tx_function = dummy_interface_tx,
117 .admin_up_down_function = test_interface_admin_up_down,
120 static u8 *hw_address;
123 fib_test_mk_intf (u32 ninterfaces)
125 clib_error_t * error = NULL;
126 test_main_t *tm = &test_main;
130 ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
135 vec_add1(hw_address, byte);
138 for (i = 0; i < ninterfaces; i++)
142 error = ethernet_register_interface(vnet_get_main(),
143 test_interface_device_class.index,
146 &tm->hw_if_indicies[i],
147 /* flag change */ 0);
149 FIB_TEST((NULL == error), "ADD interface %d", i);
151 error = vnet_hw_interface_set_flags(vnet_get_main(),
152 tm->hw_if_indicies[i],
153 VNET_HW_INTERFACE_FLAG_LINK_UP);
154 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
155 tm->hw_if_indicies[i]);
156 vec_validate (ip4_main.fib_index_by_sw_if_index,
157 tm->hw[i]->sw_if_index);
158 vec_validate (ip6_main.fib_index_by_sw_if_index,
159 tm->hw[i]->sw_if_index);
160 ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
161 ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
163 error = vnet_sw_interface_set_flags(vnet_get_main(),
164 tm->hw[i]->sw_if_index,
165 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
166 FIB_TEST((NULL == error), "UP interface %d", i);
169 * re-eval after the inevitable realloc
171 for (i = 0; i < ninterfaces; i++)
173 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
174 tm->hw_if_indicies[i]);
180 #define FIB_TEST_REC_FORW(_rec_prefix, _via_prefix, _bucket) \
182 const dpo_id_t *_rec_dpo = fib_entry_contribute_ip_forwarding( \
183 fib_table_lookup_exact_match(fib_index, (_rec_prefix))); \
184 const dpo_id_t *_via_dpo = fib_entry_contribute_ip_forwarding( \
185 fib_table_lookup(fib_index, (_via_prefix))); \
186 FIB_TEST(!dpo_cmp(_via_dpo, \
187 load_balance_get_bucket(_rec_dpo->dpoi_index, \
189 "%U is recursive via %U", \
190 format_fib_prefix, (_rec_prefix), \
191 format_fib_prefix, _via_prefix); \
194 #define FIB_TEST_LB_BUCKET_VIA_ADJ(_prefix, _bucket, _ai) \
196 const dpo_id_t *_dpo = fib_entry_contribute_ip_forwarding( \
197 fib_table_lookup_exact_match(fib_index, (_prefix))); \
198 const dpo_id_t *_dpo1 = \
199 load_balance_get_bucket(_dpo->dpoi_index, _bucket); \
200 FIB_TEST(DPO_ADJACENCY == _dpo1->dpoi_type, "type is %U", \
201 format_dpo_type, _dpo1->dpoi_type); \
202 FIB_TEST((_ai == _dpo1->dpoi_index), \
203 "%U bucket %d resolves via %U", \
204 format_fib_prefix, (_prefix), \
206 format_dpo_id, _dpo1, 0); \
209 #define FIB_TEST_RPF(_cond, _comment, _args...) \
211 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
217 fib_test_urpf_is_equal (fib_node_index_t fei,
218 fib_forward_chain_type_t fct,
221 dpo_id_t dpo = DPO_INVALID;
222 fib_urpf_list_t *urpf;
229 fib_entry_contribute_forwarding(fei, fct, &dpo);
230 ui = load_balance_get_urpf(dpo.dpoi_index);
232 urpf = fib_urpf_list_get(ui);
234 FIB_TEST_RPF(num == vec_len(urpf->furpf_itfs),
235 "RPF:%U len %d == %d",
236 format_fib_urpf_list, ui,
237 num, vec_len(urpf->furpf_itfs));
238 FIB_TEST_RPF(num == fib_urpf_check_size(ui),
239 "RPF:%U check-size %d == %d",
240 format_fib_urpf_list, ui,
241 num, vec_len(urpf->furpf_itfs));
243 for (ii = 0; ii < num; ii++)
245 adj_index_t ai = va_arg(ap, adj_index_t);
247 FIB_TEST_RPF(ai == urpf->furpf_itfs[ii],
248 "RPF:%d item:%d - %d == %d",
249 ui, ii, ai, urpf->furpf_itfs[ii]);
250 FIB_TEST_RPF(fib_urpf_check(ui, ai),
263 fib_test_build_rewrite (u8 *eth_addr)
267 vec_validate(rewrite, 13);
269 memcpy(rewrite, eth_addr, 6);
270 memcpy(rewrite+6, eth_addr, 6);
275 #define FIB_TEST_LB(_cond, _comment, _args...) \
277 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
283 fib_test_validate_rep_v (const replicate_t *rep,
287 const fib_test_rep_bucket_t *exp;
291 FIB_TEST_LB((n_buckets == rep->rep_n_buckets),
292 "n_buckets = %d", rep->rep_n_buckets);
294 for (bucket = 0; bucket < n_buckets; bucket++)
296 exp = va_arg(*ap, fib_test_rep_bucket_t*);
298 dpo = replicate_get_bucket_i(rep, bucket);
302 case FT_REP_LABEL_O_ADJ:
304 const mpls_label_dpo_t *mld;
306 FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE)
308 "bucket %d stacks on %U",
310 format_dpo_type, dpo->dpoi_type);
312 mld = mpls_label_dpo_get(dpo->dpoi_index);
313 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
315 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
316 exp->label_o_adj.label),
317 "bucket %d stacks on label %d",
319 exp->label_o_adj.label);
321 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
322 exp->label_o_adj.eos),
323 "bucket %d stacks on label %d %U",
325 exp->label_o_adj.label,
326 format_mpls_eos_bit, exp->label_o_adj.eos);
328 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
329 "bucket %d label stacks on %U",
331 format_dpo_type, mld->mld_dpo.dpoi_type);
333 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
334 "bucket %d label stacks on adj %d",
336 exp->label_o_adj.adj);
340 FIB_TEST_LB((DPO_INTERFACE_RX == dpo->dpoi_type),
341 "bucket %d stacks on %U",
343 format_dpo_type, dpo->dpoi_type);
345 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
346 "bucket %d stacks on adj %d",
350 case FT_REP_DISP_MFIB_LOOKUP:
360 fib_test_validate_lb_v (const load_balance_t *lb,
367 FIB_TEST_LB((n_buckets == lb->lb_n_buckets), "n_buckets = %d", lb->lb_n_buckets);
369 for (bucket = 0; bucket < n_buckets; bucket++)
371 const fib_test_lb_bucket_t *exp;
373 exp = va_arg(*ap, fib_test_lb_bucket_t*);
374 dpo = load_balance_get_bucket_i(lb, bucket);
378 case FT_LB_LABEL_STACK_O_ADJ:
380 const mpls_label_dpo_t *mld;
381 mpls_label_dpo_flags_t mf;
385 mf = ((exp->label_stack_o_adj.mode ==
386 FIB_MPLS_LSP_MODE_UNIFORM) ?
387 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
388 MPLS_LABEL_DPO_FLAG_NONE);
389 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
390 "bucket %d stacks on %U",
392 format_dpo_type, dpo->dpoi_type);
394 mld = mpls_label_dpo_get(dpo->dpoi_index);
396 FIB_TEST_LB(exp->label_stack_o_adj.label_stack_size == mld->mld_n_labels,
400 for (ii = 0; ii < mld->mld_n_labels; ii++)
402 hdr = clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
403 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
404 exp->label_stack_o_adj.label_stack[ii]),
405 "bucket %d stacks on label %d",
407 exp->label_stack_o_adj.label_stack[ii]);
409 if (ii == mld->mld_n_labels-1)
411 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
412 exp->label_o_adj.eos),
413 "bucket %d stacks on label %d %U!=%U",
415 exp->label_stack_o_adj.label_stack[ii],
416 format_mpls_eos_bit, exp->label_o_adj.eos,
417 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
421 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) == MPLS_NON_EOS),
422 "bucket %d stacks on label %d %U",
424 exp->label_stack_o_adj.label_stack[ii],
425 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
429 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
430 "bucket %d label stacks on %U",
432 format_dpo_type, mld->mld_dpo.dpoi_type);
434 FIB_TEST_LB((exp->label_stack_o_adj.adj == mld->mld_dpo.dpoi_index),
435 "bucket %d label stacks on adj %d",
437 exp->label_stack_o_adj.adj);
440 case FT_LB_LABEL_O_ADJ:
442 const mpls_label_dpo_t *mld;
444 FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE)
446 "bucket %d stacks on %U",
448 format_dpo_type, dpo->dpoi_type);
450 mld = mpls_label_dpo_get(dpo->dpoi_index);
451 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
453 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
454 exp->label_o_adj.label),
455 "bucket %d stacks on label %d",
457 exp->label_o_adj.label);
459 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
460 exp->label_o_adj.eos),
461 "bucket %d stacks on label %d %U",
463 exp->label_o_adj.label,
464 format_mpls_eos_bit, exp->label_o_adj.eos);
466 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
467 "bucket %d label stacks on %U",
469 format_dpo_type, mld->mld_dpo.dpoi_type);
471 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
472 "bucket %d label stacks on adj %d",
474 exp->label_o_adj.adj);
477 case FT_LB_LABEL_O_LB:
479 const mpls_label_dpo_t *mld;
480 mpls_label_dpo_flags_t mf;
483 mf = ((exp->label_o_lb.mode ==
484 FIB_MPLS_LSP_MODE_UNIFORM) ?
485 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
486 MPLS_LABEL_DPO_FLAG_NONE);
487 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
488 "bucket %d stacks on %U",
490 format_dpo_type, dpo->dpoi_type);
492 mld = mpls_label_dpo_get(dpo->dpoi_index);
493 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
495 FIB_TEST_LB(1 == mld->mld_n_labels, "label stack size",
497 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
498 exp->label_o_lb.label),
499 "bucket %d stacks on label %d",
501 exp->label_o_lb.label);
503 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
504 exp->label_o_lb.eos),
505 "bucket %d stacks on label %d %U",
507 exp->label_o_lb.label,
508 format_mpls_eos_bit, exp->label_o_lb.eos);
510 FIB_TEST_LB((DPO_LOAD_BALANCE == mld->mld_dpo.dpoi_type),
511 "bucket %d label stacks on %U",
513 format_dpo_type, mld->mld_dpo.dpoi_type);
515 FIB_TEST_LB((exp->label_o_lb.lb == mld->mld_dpo.dpoi_index),
516 "bucket %d label stacks on LB %d",
522 FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
523 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
524 "bucket %d stacks on %U",
526 format_dpo_type, dpo->dpoi_type);
527 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
528 "bucket %d stacks on adj %d",
532 case FT_LB_MPLS_DISP_PIPE_O_ADJ:
534 const mpls_disp_dpo_t *mdd;
536 FIB_TEST_I((DPO_MPLS_DISPOSITION_PIPE == dpo->dpoi_type),
537 "bucket %d stacks on %U",
539 format_dpo_type, dpo->dpoi_type);
541 mdd = mpls_disp_dpo_get(dpo->dpoi_index);
545 FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
546 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
547 "bucket %d stacks on %U",
549 format_dpo_type, dpo->dpoi_type);
550 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
551 "bucket %d stacks on adj %d",
557 FIB_TEST_I((DPO_INTERFACE_RX == dpo->dpoi_type),
558 "bucket %d stacks on %U",
560 format_dpo_type, dpo->dpoi_type);
561 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
562 "bucket %d stacks on adj %d",
567 FIB_TEST_I((DPO_DVR == dpo->dpoi_type),
568 "bucket %d stacks on %U",
570 format_dpo_type, dpo->dpoi_type);
571 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
572 "bucket %d stacks on adj %d",
577 FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
578 "bucket %d stacks on %U",
580 format_dpo_type, dpo->dpoi_type);
581 FIB_TEST_LB((exp->lb.lb == dpo->dpoi_index),
582 "bucket %d stacks on lb %d not %d",
587 case FT_LB_BIER_TABLE:
588 FIB_TEST_LB((DPO_BIER_TABLE == dpo->dpoi_type),
589 "bucket %d stacks on %U",
591 format_dpo_type, dpo->dpoi_type);
592 FIB_TEST_LB((exp->bier.table == dpo->dpoi_index),
593 "bucket %d stacks on lb %d",
597 case FT_LB_BIER_FMASK:
598 FIB_TEST_LB((DPO_BIER_FMASK == dpo->dpoi_type),
599 "bucket %d stacks on %U",
601 format_dpo_type, dpo->dpoi_type);
602 FIB_TEST_LB((exp->bier.fmask == dpo->dpoi_index),
603 "bucket %d stacks on lb %d",
608 FIB_TEST_LB((DPO_DROP == dpo->dpoi_type),
609 "bucket %d stacks on %U",
611 format_dpo_type, dpo->dpoi_type);
619 fib_test_validate_lb (const dpo_id_t *dpo,
623 const load_balance_t *lb;
627 va_start(ap, n_buckets);
629 if (FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
631 format_dpo_type, dpo->dpoi_type))
633 lb = load_balance_get(dpo->dpoi_index);
635 res = fib_test_validate_lb_v(lb, n_buckets, &ap);
648 fib_test_validate_entry (fib_node_index_t fei,
649 fib_forward_chain_type_t fct,
653 dpo_id_t dpo = DPO_INVALID;
660 va_start(ap, n_buckets);
662 fib_entry_get_prefix(fei, &pfx);
663 fib_index = fib_entry_get_fib_index(fei);
664 fib_entry_contribute_forwarding(fei, fct, &dpo);
666 if (DPO_REPLICATE == dpo.dpoi_type)
668 const replicate_t *rep;
670 rep = replicate_get(dpo.dpoi_index);
671 res = fib_test_validate_rep_v(rep, n_buckets, &ap);
675 const load_balance_t *lb;
677 FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type),
678 "%U Entry links to %U",
679 format_fib_prefix, &pfx,
680 format_dpo_type, dpo.dpoi_type);
682 lb = load_balance_get(dpo.dpoi_index);
683 res = fib_test_validate_lb_v(lb, n_buckets, &ap);
686 * ensure that the LB contributed by the entry is the
687 * same as the LB in the forwarding tables
689 if (fct == fib_entry_get_default_chain_type(fib_entry_get(fei)))
691 switch (pfx.fp_proto)
693 case FIB_PROTOCOL_IP4:
694 fw_lbi = ip4_fib_forwarding_lookup(fib_index, &pfx.fp_addr.ip4);
696 case FIB_PROTOCOL_IP6:
697 fw_lbi = ip6_fib_table_fwding_lookup(&ip6_main, fib_index, &pfx.fp_addr.ip6);
699 case FIB_PROTOCOL_MPLS:
701 mpls_unicast_header_t hdr = {
702 .label_exp_s_ttl = 0,
705 vnet_mpls_uc_set_label(&hdr.label_exp_s_ttl, pfx.fp_label);
706 vnet_mpls_uc_set_s(&hdr.label_exp_s_ttl, pfx.fp_eos);
707 hdr.label_exp_s_ttl = clib_host_to_net_u32(hdr.label_exp_s_ttl);
709 fw_lbi = mpls_fib_table_forwarding_lookup(fib_index, &hdr);
715 FIB_TEST_LB((fw_lbi == dpo.dpoi_index),
716 "Contributed LB = FW LB:\n fwd:%U\n cont:%U",
717 format_load_balance, fw_lbi, 0,
718 format_load_balance, dpo.dpoi_index, 0);
733 * In the default table check for the presence and correct forwarding
734 * of the special entries
736 fib_node_index_t dfrt, fei, ai, ai2, locked_ai, ai_01, ai_02, ai_03;
737 const dpo_id_t *dpo, *dpo1, *dpo2, *dpo_drop;
738 const ip_adjacency_t *adj;
739 const load_balance_t *lb;
746 ip46_address_t nh_10_10_10_1 = {
747 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
750 ip46_address_t nh_10_10_10_2 = {
751 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
754 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
755 pool_elts(load_balance_map_pool));
759 /* record the nubmer of load-balances in use before we start */
760 lb_count = pool_elts(load_balance_pool);
762 /* Find or create FIB table 11 */
763 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11,
766 for (ii = 0; ii < 4; ii++)
768 ip4_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
771 fib_prefix_t pfx_0_0_0_0_s_0 = {
773 .fp_proto = FIB_PROTOCOL_IP4,
783 .fp_proto = FIB_PROTOCOL_IP4,
791 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
793 dfrt = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
794 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
795 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
796 "Default route is DROP");
799 fei = fib_table_lookup(fib_index, &pfx);
800 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all zeros route present");
801 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
802 "all 0s route is DROP");
804 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xffffffff);
806 fei = fib_table_lookup(fib_index, &pfx);
807 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all ones route present");
808 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
809 "all 1s route is DROP");
811 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xe0000000);
813 fei = fib_table_lookup(fib_index, &pfx);
814 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all-mcast route present");
815 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
816 "all-mcast route is DROP");
818 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xf0000000);
820 fei = fib_table_lookup(fib_index, &pfx);
821 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "class-e route present");
822 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
823 "class-e route is DROP");
826 * at this stage there are 5 entries in the test FIB (plus 5 in the default),
827 * all of which are special sourced and so none of which share path-lists.
828 * There are also 2 entries, and 2 non-shared path-lists, in the v6 default
829 * table, and 4 path-lists in the v6 MFIB table
836 * if the IGMP plugin is loaded this adds two more entries to the v4 MFIB
838 if (vlib_get_plugin_symbol("igmp_plugin.so", "igmp_listen"))
841 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
842 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
843 fib_path_list_pool_size());
844 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
845 fib_entry_pool_size());
848 * add interface routes.
849 * validate presence of /24 attached and /32 recieve.
850 * test for the presence of the receive address in the glean and local adj
852 fib_prefix_t local_pfx = {
854 .fp_proto = FIB_PROTOCOL_IP4,
857 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
862 fib_table_entry_update_one_path(fib_index, &local_pfx,
863 FIB_SOURCE_INTERFACE,
864 (FIB_ENTRY_FLAG_CONNECTED |
865 FIB_ENTRY_FLAG_ATTACHED),
868 tm->hw[0]->sw_if_index,
869 ~0, // invalid fib index
872 FIB_ROUTE_PATH_FLAG_NONE);
873 fei = fib_table_lookup(fib_index, &local_pfx);
874 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
875 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
876 fib_entry_get_flags(fei)),
877 "Flags set on attached interface");
879 ai = fib_entry_get_adj(fei);
880 FIB_TEST((FIB_NODE_INDEX_INVALID != ai),
881 "attached interface route adj present %d", ai);
883 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
884 "attached interface adj is glean");
885 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
886 &adj->sub_type.glean.receive_addr)),
887 "attached interface adj is receive ok");
889 local_pfx.fp_len = 32;
890 fib_table_entry_update_one_path(fib_index, &local_pfx,
891 FIB_SOURCE_INTERFACE,
892 (FIB_ENTRY_FLAG_CONNECTED |
893 FIB_ENTRY_FLAG_LOCAL),
896 tm->hw[0]->sw_if_index,
897 ~0, // invalid fib index
900 FIB_ROUTE_PATH_FLAG_NONE);
901 fei = fib_table_lookup(fib_index, &local_pfx);
902 FIB_TEST(((FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_CONNECTED) ==
903 fib_entry_get_flags(fei)),
904 "Flags set on local interface");
906 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
908 dpo = fib_entry_contribute_ip_forwarding(fei);
909 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
910 "RPF list for local length 0");
911 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
912 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
913 "local interface adj is local");
914 receive_dpo_t *rd = receive_dpo_get(dpo->dpoi_index);
916 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
918 "local interface adj is receive ok");
920 FIB_TEST((2 == fib_table_get_num_entries(fib_index,
922 FIB_SOURCE_INTERFACE)),
923 "2 Interface Source'd prefixes");
926 * +2 interface routes +2 non-shared path-lists
928 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
929 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
930 fib_path_list_pool_size());
931 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
932 fib_entry_pool_size());
935 * Modify the default route to be via an adj not yet known.
936 * this sources the defalut route with the API source, which is
937 * a higher preference to the DEFAULT_ROUTE source
939 pfx.fp_addr.ip4.as_u32 = 0;
941 fib_table_entry_path_add(fib_index, &pfx,
946 tm->hw[0]->sw_if_index,
947 ~0, // invalid fib index
950 FIB_ROUTE_PATH_FLAG_NONE);
951 fei = fib_table_lookup(fib_index, &pfx);
952 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
953 "Flags set on API route");
955 FIB_TEST((fei == dfrt), "default route same index");
956 ai = fib_entry_get_adj(fei);
957 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
959 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
960 "adj is incomplete");
961 FIB_TEST((0 == ip46_address_cmp(&nh_10_10_10_1, &adj->sub_type.nbr.next_hop)),
962 "adj nbr next-hop ok");
963 FIB_TEST((1 == fib_table_get_num_entries(fib_index,
966 "1 API Source'd prefixes");
969 * find the adj in the shared db
971 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
974 tm->hw[0]->sw_if_index);
975 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
976 adj_unlock(locked_ai);
979 * +1 shared path-list
981 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
982 fib_path_list_db_size());
983 FIB_TEST((PNBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
984 fib_path_list_pool_size());
985 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
986 fib_entry_pool_size());
989 * remove the API source from the default route. We expected
990 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
992 pfx.fp_addr.ip4.as_u32 = 0;
994 fib_table_entry_path_remove(fib_index, &pfx,
998 tm->hw[0]->sw_if_index,
999 ~0, // non-recursive path, so no FIB index
1001 FIB_ROUTE_PATH_FLAG_NONE);
1003 fei = fib_table_lookup(fib_index, &pfx);
1005 FIB_TEST((fei == dfrt), "default route same index");
1006 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
1007 "Default route is DROP");
1010 * -1 shared-path-list
1012 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
1013 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
1014 fib_path_list_pool_size());
1015 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
1016 fib_entry_pool_size());
1019 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
1021 fib_prefix_t pfx_10_10_10_1_s_32 = {
1023 .fp_proto = FIB_PROTOCOL_IP4,
1026 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
1029 fib_prefix_t pfx_10_10_10_2_s_32 = {
1031 .fp_proto = FIB_PROTOCOL_IP4,
1034 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
1037 fib_prefix_t pfx_11_11_11_11_s_32 = {
1039 .fp_proto = FIB_PROTOCOL_IP4,
1042 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
1046 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
1049 ip46_address_t nh_12_12_12_12 = {
1050 .ip4.as_u32 = clib_host_to_net_u32(0x0c0c0c0c),
1052 adj_index_t ai_12_12_12_12;
1055 * Add a route via an incomplete ADJ. then complete the ADJ
1056 * Expect the route LB is updated to use complete adj type.
1058 fei = fib_table_entry_update_one_path(fib_index,
1059 &pfx_11_11_11_11_s_32,
1061 FIB_ENTRY_FLAG_ATTACHED,
1063 &pfx_10_10_10_1_s_32.fp_addr,
1064 tm->hw[0]->sw_if_index,
1065 ~0, // invalid fib index
1068 FIB_ROUTE_PATH_FLAG_NONE);
1070 dpo = fib_entry_contribute_ip_forwarding(fei);
1071 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1072 FIB_TEST(DPO_ADJACENCY_INCOMPLETE == dpo1->dpoi_type,
1073 "11.11.11.11/32 via incomplete adj");
1075 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1077 &pfx_10_10_10_1_s_32.fp_addr,
1078 tm->hw[0]->sw_if_index);
1079 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
1080 adj = adj_get(ai_01);
1081 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1082 "adj is incomplete");
1083 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1084 &adj->sub_type.nbr.next_hop)),
1085 "adj nbr next-hop ok");
1087 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1088 fib_test_build_rewrite(eth_addr));
1089 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1091 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1092 &adj->sub_type.nbr.next_hop)),
1093 "adj nbr next-hop ok");
1094 ai = fib_entry_get_adj(fei);
1095 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
1097 dpo = fib_entry_contribute_ip_forwarding(fei);
1098 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1099 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type,
1100 "11.11.11.11/32 via complete adj");
1101 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1102 tm->hw[0]->sw_if_index),
1103 "RPF list for adj-fib contains adj");
1105 ai_12_12_12_12 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1108 tm->hw[1]->sw_if_index);
1109 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_12_12_12_12), "adj created");
1110 adj = adj_get(ai_12_12_12_12);
1111 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1112 "adj is incomplete");
1113 FIB_TEST((0 == ip46_address_cmp(&nh_12_12_12_12,
1114 &adj->sub_type.nbr.next_hop)),
1115 "adj nbr next-hop ok");
1116 adj_nbr_update_rewrite(ai_12_12_12_12, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1117 fib_test_build_rewrite(eth_addr));
1118 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1124 fei = fib_table_entry_path_add(fib_index,
1125 &pfx_10_10_10_1_s_32,
1127 FIB_ENTRY_FLAG_ATTACHED,
1129 &pfx_10_10_10_1_s_32.fp_addr,
1130 tm->hw[0]->sw_if_index,
1131 ~0, // invalid fib index
1134 FIB_ROUTE_PATH_FLAG_NONE);
1135 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
1136 "Flags set on adj-fib");
1137 ai = fib_entry_get_adj(fei);
1138 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj, %d", ai);
1140 fib_table_entry_path_remove(fib_index,
1141 &pfx_11_11_11_11_s_32,
1144 &pfx_10_10_10_1_s_32.fp_addr,
1145 tm->hw[0]->sw_if_index,
1146 ~0, // invalid fib index
1148 FIB_ROUTE_PATH_FLAG_NONE);
1152 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1154 &pfx_10_10_10_2_s_32.fp_addr,
1155 tm->hw[0]->sw_if_index);
1156 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
1157 adj = adj_get(ai_02);
1158 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1159 "adj is incomplete");
1160 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1161 &adj->sub_type.nbr.next_hop)),
1162 "adj nbr next-hop ok");
1164 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1165 fib_test_build_rewrite(eth_addr));
1166 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1168 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1169 &adj->sub_type.nbr.next_hop)),
1170 "adj nbr next-hop ok");
1171 FIB_TEST((ai_01 != ai_02), "ADJs are different");
1173 fib_table_entry_path_add(fib_index,
1174 &pfx_10_10_10_2_s_32,
1176 FIB_ENTRY_FLAG_ATTACHED,
1178 &pfx_10_10_10_2_s_32.fp_addr,
1179 tm->hw[0]->sw_if_index,
1180 ~0, // invalid fib index
1183 FIB_ROUTE_PATH_FLAG_NONE);
1185 fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32);
1186 ai = fib_entry_get_adj(fei);
1187 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
1190 * +2 adj-fibs, and their non-shared path-lists
1192 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
1193 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
1194 fib_path_list_pool_size());
1195 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
1196 fib_entry_pool_size());
1199 * Add 2 routes via the first ADJ. ensure path-list sharing
1201 fib_prefix_t pfx_1_1_1_1_s_32 = {
1203 .fp_proto = FIB_PROTOCOL_IP4,
1206 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1210 fib_table_entry_path_add(fib_index,
1213 FIB_ENTRY_FLAG_NONE,
1216 tm->hw[0]->sw_if_index,
1217 ~0, // invalid fib index
1220 FIB_ROUTE_PATH_FLAG_NONE);
1221 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
1222 ai = fib_entry_get_adj(fei);
1223 FIB_TEST((ai_01 == ai), "1.1.1.1 resolves via 10.10.10.1");
1226 * +1 entry and a shared path-list
1228 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
1229 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1230 fib_path_list_pool_size());
1231 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
1232 fib_entry_pool_size());
1235 fib_prefix_t pfx_1_1_2_0_s_24 = {
1237 .fp_proto = FIB_PROTOCOL_IP4,
1239 .ip4.as_u32 = clib_host_to_net_u32(0x01010200),
1243 fib_table_entry_path_add(fib_index,
1246 FIB_ENTRY_FLAG_NONE,
1249 tm->hw[0]->sw_if_index,
1250 ~0, // invalid fib index
1253 FIB_ROUTE_PATH_FLAG_NONE);
1254 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1255 ai = fib_entry_get_adj(fei);
1256 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1261 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
1262 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1263 fib_path_list_pool_size());
1264 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1265 fib_entry_pool_size());
1268 * modify 1.1.2.0/24 to use multipath.
1270 fib_table_entry_path_add(fib_index,
1273 FIB_ENTRY_FLAG_NONE,
1276 tm->hw[0]->sw_if_index,
1277 ~0, // invalid fib index
1280 FIB_ROUTE_PATH_FLAG_NONE);
1281 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1282 dpo = fib_entry_contribute_ip_forwarding(fei);
1283 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1284 1, tm->hw[0]->sw_if_index),
1285 "RPF list for 1.1.2.0/24 contains both adjs");
1287 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1288 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1289 FIB_TEST((ai_01 == dpo1->dpoi_index),
1290 "1.1.2.0/24 bucket 0 resolves via 10.10.10.1 (%d=%d)",
1291 ai_01, dpo1->dpoi_index);
1293 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 1);
1294 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1295 FIB_TEST((ai_02 == dpo1->dpoi_index),
1296 "1.1.2.0/24 bucket 1 resolves via 10.10.10.2");
1299 * +1 shared-pathlist
1301 FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty");
1302 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1303 fib_path_list_pool_size());
1304 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1305 fib_entry_pool_size());
1310 fib_table_entry_path_remove(fib_index,
1315 tm->hw[0]->sw_if_index,
1318 FIB_ROUTE_PATH_FLAG_NONE);
1319 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1320 dpo = fib_entry_contribute_ip_forwarding(fei);
1321 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1322 1, tm->hw[0]->sw_if_index),
1323 "RPF list for 1.1.2.0/24 contains one adj");
1325 ai = fib_entry_get_adj(fei);
1326 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1329 * +1 shared-pathlist
1331 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d",
1332 fib_path_list_db_size());
1333 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1334 fib_path_list_pool_size());
1335 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1336 fib_entry_pool_size());
1339 * Add 2 recursive routes:
1340 * 100.100.100.100/32 via 1.1.1.1/32 => the via entry is installed.
1341 * 100.100.100.101/32 via 1.1.1.1/32 => the via entry is installed.
1343 fib_prefix_t bgp_100_pfx = {
1345 .fp_proto = FIB_PROTOCOL_IP4,
1347 /* 100.100.100.100/32 */
1348 .ip4.as_u32 = clib_host_to_net_u32(0x64646464),
1352 ip46_address_t nh_1_1_1_1 = {
1353 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1356 fei = fib_table_entry_path_add(fib_index,
1359 FIB_ENTRY_FLAG_NONE,
1362 ~0, // no index provided.
1363 fib_index, // nexthop in same fib as route
1366 FIB_ROUTE_PATH_FLAG_NONE);
1368 FIB_TEST_REC_FORW(&bgp_100_pfx, &pfx_1_1_1_1_s_32, 0);
1369 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1370 tm->hw[0]->sw_if_index),
1371 "RPF list for adj-fib contains adj");
1374 * +1 entry and +1 shared-path-list
1376 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1377 fib_path_list_db_size());
1378 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1379 fib_path_list_pool_size());
1380 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
1381 fib_entry_pool_size());
1383 fib_prefix_t bgp_101_pfx = {
1385 .fp_proto = FIB_PROTOCOL_IP4,
1387 /* 100.100.100.101/32 */
1388 .ip4.as_u32 = clib_host_to_net_u32(0x64646465),
1392 fib_table_entry_path_add(fib_index,
1395 FIB_ENTRY_FLAG_NONE,
1398 ~0, // no index provided.
1399 fib_index, // nexthop in same fib as route
1402 FIB_ROUTE_PATH_FLAG_NONE);
1404 FIB_TEST_REC_FORW(&bgp_101_pfx, &pfx_1_1_1_1_s_32, 0);
1405 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1406 tm->hw[0]->sw_if_index),
1407 "RPF list for adj-fib contains adj");
1410 * +1 entry, but the recursive path-list is shared.
1412 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1413 fib_path_list_db_size());
1414 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1415 fib_path_list_pool_size());
1416 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
1417 fib_entry_pool_size());
1420 * An special route; one where the user (me) provides the
1421 * adjacency through which the route will resovle by setting the flags
1423 fib_prefix_t ex_pfx = {
1425 .fp_proto = FIB_PROTOCOL_IP4,
1428 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
1432 fib_table_entry_special_add(fib_index,
1435 FIB_ENTRY_FLAG_LOCAL);
1436 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1437 dpo = fib_entry_contribute_ip_forwarding(fei);
1438 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
1439 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
1440 "local interface adj is local");
1442 fib_table_entry_special_remove(fib_index,
1444 FIB_SOURCE_SPECIAL);
1445 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1446 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1447 "Exclusive reoute removed");
1450 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1451 * adjacency through which the route will resovle
1453 dpo_id_t ex_dpo = DPO_INVALID;
1455 lookup_dpo_add_or_lock_w_fib_index(fib_index,
1458 LOOKUP_INPUT_DST_ADDR,
1459 LOOKUP_TABLE_FROM_CONFIG,
1462 fib_table_entry_special_dpo_add(fib_index,
1465 FIB_ENTRY_FLAG_EXCLUSIVE,
1467 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1468 dpo = fib_entry_contribute_ip_forwarding(fei);
1469 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1470 "exclusive remote uses lookup DPO");
1473 * update the exclusive to use a different DPO
1475 ip_null_dpo_add_and_lock(DPO_PROTO_IP4,
1476 IP_NULL_ACTION_SEND_ICMP_UNREACH,
1478 fib_table_entry_special_dpo_update(fib_index,
1481 FIB_ENTRY_FLAG_EXCLUSIVE,
1483 dpo = fib_entry_contribute_ip_forwarding(fei);
1484 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1485 "exclusive remote uses now uses NULL DPO");
1487 fib_table_entry_special_remove(fib_index,
1489 FIB_SOURCE_SPECIAL);
1490 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1491 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1492 "Exclusive reoute removed");
1496 * Add a recursive route:
1497 * 200.200.200.200/32 via 1.1.1.2/32 => the via entry is NOT installed.
1499 fib_prefix_t bgp_200_pfx = {
1501 .fp_proto = FIB_PROTOCOL_IP4,
1503 /* 200.200.200.200/32 */
1504 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c8),
1508 fib_prefix_t pfx_1_1_1_2_s_32 = {
1510 .fp_proto = FIB_PROTOCOL_IP4,
1512 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
1516 fei = fib_table_entry_path_add(fib_index,
1519 FIB_ENTRY_FLAG_NONE,
1521 &pfx_1_1_1_2_s_32.fp_addr,
1522 ~0, // no index provided.
1523 fib_index, // nexthop in same fib as route
1526 FIB_ROUTE_PATH_FLAG_NONE);
1528 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
1529 "Recursive via unresolved is drop");
1532 * the adj should be recursive via drop, since the route resolves via
1533 * the default route, which is itself a DROP
1535 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
1536 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1537 FIB_TEST(load_balance_is_drop(dpo1), "1.1.1.2/32 is drop");
1538 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1539 "RPF list for 1.1.1.2/32 contains 0 adjs");
1542 * +2 entry and +1 shared-path-list
1544 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
1545 fib_path_list_db_size());
1546 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
1547 fib_path_list_pool_size());
1548 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
1549 fib_entry_pool_size());
1552 * Unequal Cost load-balance. 3:1 ratio. fits in a 4 bucket LB
1553 * The paths are sort by NH first. in this case the the path with greater
1554 * weight is first in the set. This ordering is to test the RPF sort|uniq logic
1556 fib_prefix_t pfx_1_2_3_4_s_32 = {
1558 .fp_proto = FIB_PROTOCOL_IP4,
1560 .ip4.as_u32 = clib_host_to_net_u32(0x01020304),
1563 fib_table_entry_path_add(fib_index,
1566 FIB_ENTRY_FLAG_NONE,
1569 tm->hw[0]->sw_if_index,
1573 FIB_ROUTE_PATH_FLAG_NONE);
1574 fei = fib_table_entry_path_add(fib_index,
1577 FIB_ENTRY_FLAG_NONE,
1580 tm->hw[1]->sw_if_index,
1584 FIB_ROUTE_PATH_FLAG_NONE);
1586 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.4/32 presnet");
1587 dpo = fib_entry_contribute_ip_forwarding(fei);
1588 lb = load_balance_get(dpo->dpoi_index);
1589 FIB_TEST((lb->lb_n_buckets == 4),
1590 "1.2.3.4/32 LB has %d bucket",
1593 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 0, ai_12_12_12_12);
1594 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 1, ai_12_12_12_12);
1595 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 2, ai_12_12_12_12);
1596 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 3, ai_01);
1598 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1599 tm->hw[0]->sw_if_index,
1600 tm->hw[1]->sw_if_index),
1601 "RPF list for 1.2.3.4/32 contains both adjs");
1605 * Unequal Cost load-balance. 4:1 ratio.
1606 * fits in a 16 bucket LB with ratio 13:3
1608 fib_prefix_t pfx_1_2_3_5_s_32 = {
1610 .fp_proto = FIB_PROTOCOL_IP4,
1612 .ip4.as_u32 = clib_host_to_net_u32(0x01020305),
1615 fib_table_entry_path_add(fib_index,
1618 FIB_ENTRY_FLAG_NONE,
1621 tm->hw[1]->sw_if_index,
1625 FIB_ROUTE_PATH_FLAG_NONE);
1626 fei = fib_table_entry_path_add(fib_index,
1629 FIB_ENTRY_FLAG_NONE,
1632 tm->hw[0]->sw_if_index,
1636 FIB_ROUTE_PATH_FLAG_NONE);
1638 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.5/32 presnet");
1639 dpo = fib_entry_contribute_ip_forwarding(fei);
1640 lb = load_balance_get(dpo->dpoi_index);
1641 FIB_TEST((lb->lb_n_buckets == 16),
1642 "1.2.3.5/32 LB has %d bucket",
1645 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 0, ai_01);
1646 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 1, ai_01);
1647 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 2, ai_01);
1648 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 3, ai_01);
1649 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 4, ai_01);
1650 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 5, ai_01);
1651 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 6, ai_01);
1652 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 7, ai_01);
1653 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 8, ai_01);
1654 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 9, ai_01);
1655 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 10, ai_01);
1656 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 11, ai_01);
1657 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 12, ai_01);
1658 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 13, ai_12_12_12_12);
1659 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 14, ai_12_12_12_12);
1660 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 15, ai_12_12_12_12);
1662 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1663 tm->hw[0]->sw_if_index,
1664 tm->hw[1]->sw_if_index),
1665 "RPF list for 1.2.3.4/32 contains both adjs");
1668 * Test UCMP with a large weight skew - this produces load-balance objects with large
1669 * numbers of buckets to accommodate the skew. By updating said load-balances we are
1670 * laso testing the LB in placce modify code when number of buckets is large.
1672 fib_prefix_t pfx_6_6_6_6_s_32 = {
1674 .fp_proto = FIB_PROTOCOL_IP4,
1677 .ip4.as_u32 = clib_host_to_net_u32(0x06060606),
1680 fib_test_lb_bucket_t ip_o_10_10_10_1 = {
1686 fib_test_lb_bucket_t ip_o_10_10_10_2 = {
1692 fib_test_lb_bucket_t ip_6_6_6_6_o_12_12_12_12 = {
1695 .adj = ai_12_12_12_12,
1698 fib_table_entry_update_one_path(fib_index,
1701 FIB_ENTRY_FLAG_NONE,
1704 tm->hw[0]->sw_if_index,
1705 ~0, // invalid fib index
1708 FIB_ROUTE_PATH_FLAG_NONE);
1710 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1711 FIB_TEST(fib_test_validate_entry(fei,
1712 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1715 "6.6.6.6/32 via 10.10.10.1");
1717 fib_table_entry_path_add(fib_index,
1720 FIB_ENTRY_FLAG_NONE,
1723 tm->hw[0]->sw_if_index,
1724 ~0, // invalid fib index
1727 FIB_ROUTE_PATH_FLAG_NONE);
1729 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1730 FIB_TEST(fib_test_validate_entry(fei,
1731 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1797 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1799 fib_table_entry_path_add(fib_index,
1802 FIB_ENTRY_FLAG_NONE,
1805 tm->hw[1]->sw_if_index,
1806 ~0, // invalid fib index
1809 FIB_ROUTE_PATH_FLAG_NONE);
1811 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1812 FIB_TEST(fib_test_validate_entry(fei,
1813 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1880 &ip_6_6_6_6_o_12_12_12_12,
1881 &ip_6_6_6_6_o_12_12_12_12,
1882 &ip_6_6_6_6_o_12_12_12_12,
1883 &ip_6_6_6_6_o_12_12_12_12,
1884 &ip_6_6_6_6_o_12_12_12_12,
1885 &ip_6_6_6_6_o_12_12_12_12,
1886 &ip_6_6_6_6_o_12_12_12_12,
1887 &ip_6_6_6_6_o_12_12_12_12,
1888 &ip_6_6_6_6_o_12_12_12_12,
1889 &ip_6_6_6_6_o_12_12_12_12,
1890 &ip_6_6_6_6_o_12_12_12_12,
1891 &ip_6_6_6_6_o_12_12_12_12,
1892 &ip_6_6_6_6_o_12_12_12_12,
1893 &ip_6_6_6_6_o_12_12_12_12,
1894 &ip_6_6_6_6_o_12_12_12_12,
1895 &ip_6_6_6_6_o_12_12_12_12,
1896 &ip_6_6_6_6_o_12_12_12_12,
1897 &ip_6_6_6_6_o_12_12_12_12,
1898 &ip_6_6_6_6_o_12_12_12_12,
1899 &ip_6_6_6_6_o_12_12_12_12,
1900 &ip_6_6_6_6_o_12_12_12_12,
1901 &ip_6_6_6_6_o_12_12_12_12,
1902 &ip_6_6_6_6_o_12_12_12_12,
1903 &ip_6_6_6_6_o_12_12_12_12,
1904 &ip_6_6_6_6_o_12_12_12_12,
1905 &ip_6_6_6_6_o_12_12_12_12,
1906 &ip_6_6_6_6_o_12_12_12_12,
1907 &ip_6_6_6_6_o_12_12_12_12,
1908 &ip_6_6_6_6_o_12_12_12_12,
1909 &ip_6_6_6_6_o_12_12_12_12,
1910 &ip_6_6_6_6_o_12_12_12_12,
1911 &ip_6_6_6_6_o_12_12_12_12,
1912 &ip_6_6_6_6_o_12_12_12_12,
1913 &ip_6_6_6_6_o_12_12_12_12,
1914 &ip_6_6_6_6_o_12_12_12_12,
1915 &ip_6_6_6_6_o_12_12_12_12,
1916 &ip_6_6_6_6_o_12_12_12_12,
1917 &ip_6_6_6_6_o_12_12_12_12,
1918 &ip_6_6_6_6_o_12_12_12_12,
1919 &ip_6_6_6_6_o_12_12_12_12,
1920 &ip_6_6_6_6_o_12_12_12_12,
1921 &ip_6_6_6_6_o_12_12_12_12,
1922 &ip_6_6_6_6_o_12_12_12_12,
1923 &ip_6_6_6_6_o_12_12_12_12,
1924 &ip_6_6_6_6_o_12_12_12_12,
1925 &ip_6_6_6_6_o_12_12_12_12,
1926 &ip_6_6_6_6_o_12_12_12_12,
1927 &ip_6_6_6_6_o_12_12_12_12,
1928 &ip_6_6_6_6_o_12_12_12_12,
1929 &ip_6_6_6_6_o_12_12_12_12,
1930 &ip_6_6_6_6_o_12_12_12_12,
1931 &ip_6_6_6_6_o_12_12_12_12,
1932 &ip_6_6_6_6_o_12_12_12_12,
1933 &ip_6_6_6_6_o_12_12_12_12,
1934 &ip_6_6_6_6_o_12_12_12_12,
1935 &ip_6_6_6_6_o_12_12_12_12,
1936 &ip_6_6_6_6_o_12_12_12_12,
1937 &ip_6_6_6_6_o_12_12_12_12,
1938 &ip_6_6_6_6_o_12_12_12_12,
1939 &ip_6_6_6_6_o_12_12_12_12,
1940 &ip_6_6_6_6_o_12_12_12_12,
1941 &ip_6_6_6_6_o_12_12_12_12,
1942 &ip_6_6_6_6_o_12_12_12_12),
1943 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1945 fib_table_entry_path_remove(fib_index,
1950 tm->hw[1]->sw_if_index,
1951 ~0, // invalid fib index
1953 FIB_ROUTE_PATH_FLAG_NONE);
1955 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1956 FIB_TEST(fib_test_validate_entry(fei,
1957 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2023 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
2025 fib_table_entry_path_remove(fib_index,
2030 tm->hw[0]->sw_if_index,
2031 ~0, // invalid fib index
2033 FIB_ROUTE_PATH_FLAG_NONE);
2035 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
2036 FIB_TEST(fib_test_validate_entry(fei,
2037 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2040 "6.6.6.6/32 via 10.10.10.1");
2042 fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API);
2045 * A recursive via the two unequal cost entries
2047 fib_prefix_t bgp_44_s_32 = {
2049 .fp_proto = FIB_PROTOCOL_IP4,
2051 /* 200.200.200.201/32 */
2052 .ip4.as_u32 = clib_host_to_net_u32(0x44444444),
2055 fei = fib_table_entry_path_add(fib_index,
2058 FIB_ENTRY_FLAG_NONE,
2060 &pfx_1_2_3_4_s_32.fp_addr,
2065 FIB_ROUTE_PATH_FLAG_NONE);
2066 fei = fib_table_entry_path_add(fib_index,
2069 FIB_ENTRY_FLAG_NONE,
2071 &pfx_1_2_3_5_s_32.fp_addr,
2076 FIB_ROUTE_PATH_FLAG_NONE);
2078 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_4_s_32, 0);
2079 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_5_s_32, 1);
2080 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
2081 tm->hw[0]->sw_if_index,
2082 tm->hw[1]->sw_if_index),
2083 "RPF list for 1.2.3.4/32 contains both adjs");
2086 * test the uRPF check functions
2088 dpo_id_t dpo_44 = DPO_INVALID;
2091 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
2092 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
2094 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
2095 "uRPF check for 68.68.68.68/32 on %d OK",
2096 tm->hw[0]->sw_if_index);
2097 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
2098 "uRPF check for 68.68.68.68/32 on %d OK",
2099 tm->hw[1]->sw_if_index);
2100 FIB_TEST(!fib_urpf_check(urpfi, 99),
2101 "uRPF check for 68.68.68.68/32 on 99 not-OK",
2105 fib_table_entry_delete(fib_index,
2108 fib_table_entry_delete(fib_index,
2111 fib_table_entry_delete(fib_index,
2116 * Add a recursive route:
2117 * 200.200.200.201/32 via 1.1.1.200/32 => the via entry is NOT installed.
2119 fib_prefix_t bgp_201_pfx = {
2121 .fp_proto = FIB_PROTOCOL_IP4,
2123 /* 200.200.200.201/32 */
2124 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c9),
2128 fib_prefix_t pfx_1_1_1_200_s_32 = {
2130 .fp_proto = FIB_PROTOCOL_IP4,
2132 .ip4.as_u32 = clib_host_to_net_u32(0x010101c8),
2136 fei = fib_table_entry_path_add(fib_index,
2139 FIB_ENTRY_FLAG_NONE,
2141 &pfx_1_1_1_200_s_32.fp_addr,
2142 ~0, // no index provided.
2143 fib_index, // nexthop in same fib as route
2146 FIB_ROUTE_PATH_FLAG_NONE);
2148 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2149 "Recursive via unresolved is drop");
2151 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2152 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
2153 "Flags set on RR via non-attached");
2154 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
2155 "RPF list for BGP route empty");
2158 * +2 entry (BGP & RR) and +1 shared-path-list
2160 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2161 fib_path_list_db_size());
2162 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2163 fib_path_list_pool_size());
2164 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2165 fib_entry_pool_size());
2168 * insert a route that covers the missing 1.1.1.2/32. we epxect
2169 * 200.200.200.200/32 and 200.200.200.201/32 to resolve through it.
2171 fib_prefix_t pfx_1_1_1_0_s_24 = {
2173 .fp_proto = FIB_PROTOCOL_IP4,
2176 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2180 fib_table_entry_path_add(fib_index,
2183 FIB_ENTRY_FLAG_NONE,
2186 tm->hw[0]->sw_if_index,
2187 ~0, // invalid fib index
2190 FIB_ROUTE_PATH_FLAG_NONE);
2191 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24);
2192 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2193 ai = fib_entry_get_adj(fei);
2194 FIB_TEST((ai_01 == ai), "1.1.1.0/24 resolves via 10.10.10.1");
2195 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2196 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2197 ai = fib_entry_get_adj(fei);
2198 FIB_TEST((ai_01 == ai), "1.1.1.2/32 resolves via 10.10.10.1");
2199 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2200 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2201 ai = fib_entry_get_adj(fei);
2202 FIB_TEST((ai_01 == ai), "1.1.1.200/24 resolves via 10.10.10.1");
2205 * +1 entry. 1.1.1.1/32 already uses 10.10.10.1 so no new pah-list
2207 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2208 fib_path_list_db_size());
2209 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2210 fib_path_list_pool_size());
2211 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
2212 fib_entry_pool_size());
2215 * the recursive adj for 200.200.200.200 should be updated.
2217 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2218 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2219 fei = fib_table_lookup(fib_index, &bgp_200_pfx);
2220 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
2221 tm->hw[0]->sw_if_index),
2222 "RPF list for BGP route has itf index 0");
2225 * insert a more specific route than 1.1.1.0/24 that also covers the
2226 * missing 1.1.1.2/32, but not 1.1.1.200/32. we epxect
2227 * 200.200.200.200 to resolve through it.
2229 fib_prefix_t pfx_1_1_1_0_s_28 = {
2231 .fp_proto = FIB_PROTOCOL_IP4,
2234 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2238 fib_table_entry_path_add(fib_index,
2241 FIB_ENTRY_FLAG_NONE,
2244 tm->hw[0]->sw_if_index,
2245 ~0, // invalid fib index
2248 FIB_ROUTE_PATH_FLAG_NONE);
2249 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28);
2250 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2251 ai = fib_entry_get_adj(fei);
2252 FIB_TEST((ai_02 == ai), "1.1.1.0/24 resolves via 10.10.10.2");
2255 * +1 entry. +1 shared path-list
2257 FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d",
2258 fib_path_list_db_size());
2259 FIB_TEST((PNBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
2260 fib_path_list_pool_size());
2261 FIB_TEST((ENBR+14 == fib_entry_pool_size()), "entry pool size is %d",
2262 fib_entry_pool_size());
2265 * the recursive adj for 200.200.200.200 should be updated.
2266 * 200.200.200.201 remains unchanged.
2268 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2269 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2272 * remove this /28. 200.200.200.200/32 should revert back to via 1.1.1.0/24
2274 fib_table_entry_path_remove(fib_index,
2279 tm->hw[0]->sw_if_index,
2282 FIB_ROUTE_PATH_FLAG_NONE);
2283 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28) ==
2284 FIB_NODE_INDEX_INVALID),
2285 "1.1.1.0/28 removed");
2286 FIB_TEST((fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28) ==
2287 fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24)),
2288 "1.1.1.0/28 lookup via /24");
2289 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2290 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2293 * -1 entry. -1 shared path-list
2295 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2296 fib_path_list_db_size());
2297 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2298 fib_path_list_pool_size());
2299 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
2300 fib_entry_pool_size());
2303 * remove 1.1.1.0/24. 200.200.200.200/32 should revert back to via 0.0.0.0/0
2305 fib_table_entry_path_remove(fib_index,
2310 tm->hw[0]->sw_if_index,
2313 FIB_ROUTE_PATH_FLAG_NONE);
2314 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_24) ==
2315 FIB_NODE_INDEX_INVALID),
2316 "1.1.1.0/24 removed");
2318 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2319 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2320 "1.1.1.2/32 route is DROP");
2321 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2322 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2323 "1.1.1.200/32 route is DROP");
2325 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2326 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2328 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2329 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2335 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2336 fib_path_list_db_size());
2337 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2338 fib_path_list_pool_size());
2339 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2340 fib_entry_pool_size());
2343 * insert the missing 1.1.1.2/32
2345 fei = fib_table_entry_path_add(fib_index,
2348 FIB_ENTRY_FLAG_NONE,
2351 tm->hw[0]->sw_if_index,
2352 ~0, // invalid fib index
2355 FIB_ROUTE_PATH_FLAG_NONE);
2356 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2357 ai = fib_entry_get_adj(fei);
2358 FIB_TEST((ai = ai_01), "1.1.1.2/32 resolves via 10.10.10.1");
2360 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2361 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2363 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2366 * no change. 1.1.1.2/32 was already there RR sourced.
2368 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2369 fib_path_list_db_size());
2370 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2371 fib_path_list_pool_size());
2372 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2373 fib_entry_pool_size());
2376 * give 201 a resolved path.
2377 * it now has the unresolved 1.1.1.200 and the resolved 1.1.1.2,
2378 * only the latter contributes forwarding.
2380 fei = fib_table_entry_path_add(fib_index,
2383 FIB_ENTRY_FLAG_NONE,
2385 &pfx_1_1_1_2_s_32.fp_addr,
2390 FIB_ROUTE_PATH_FLAG_NONE);
2391 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_2_s_32, 0);
2392 fib_table_entry_path_remove(fib_index,
2396 &pfx_1_1_1_2_s_32.fp_addr,
2400 FIB_ROUTE_PATH_FLAG_NONE);
2403 * remove 200.200.200.201/32 which does not have a valid via FIB
2405 fib_table_entry_path_remove(fib_index,
2409 &pfx_1_1_1_200_s_32.fp_addr,
2410 ~0, // no index provided.
2413 FIB_ROUTE_PATH_FLAG_NONE);
2416 * -2 entries (BGP and RR). -1 shared path-list;
2418 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2419 FIB_NODE_INDEX_INVALID),
2420 "200.200.200.201/32 removed");
2421 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32) ==
2422 FIB_NODE_INDEX_INVALID),
2423 "1.1.1.200/32 removed");
2425 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2426 fib_path_list_db_size());
2427 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
2428 fib_path_list_pool_size());
2429 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2430 fib_entry_pool_size());
2433 * remove 200.200.200.200/32 which does have a valid via FIB
2435 fib_table_entry_path_remove(fib_index,
2439 &pfx_1_1_1_2_s_32.fp_addr,
2440 ~0, // no index provided.
2443 FIB_ROUTE_PATH_FLAG_NONE);
2445 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2446 FIB_NODE_INDEX_INVALID),
2447 "200.200.200.200/32 removed");
2448 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32) !=
2449 FIB_NODE_INDEX_INVALID),
2450 "1.1.1.2/32 still present");
2453 * -1 entry (BGP, the RR source is also API sourced). -1 shared path-list;
2455 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2456 fib_path_list_db_size());
2457 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2458 fib_path_list_pool_size());
2459 FIB_TEST((ENBR+9 == fib_entry_pool_size()), "entry pool size is %d",
2460 fib_entry_pool_size());
2463 * A recursive prefix that has a 2 path load-balance.
2464 * It also shares a next-hop with other BGP prefixes and hence
2465 * test the ref counting of RR sourced prefixes and 2 level LB.
2467 const fib_prefix_t bgp_102 = {
2469 .fp_proto = FIB_PROTOCOL_IP4,
2471 /* 100.100.100.101/32 */
2472 .ip4.as_u32 = clib_host_to_net_u32(0x64646466),
2475 fib_table_entry_path_add(fib_index,
2478 FIB_ENTRY_FLAG_NONE,
2480 &pfx_1_1_1_1_s_32.fp_addr,
2481 ~0, // no index provided.
2482 fib_index, // same as route
2485 FIB_ROUTE_PATH_FLAG_NONE);
2486 fib_table_entry_path_add(fib_index,
2489 FIB_ENTRY_FLAG_NONE,
2491 &pfx_1_1_1_2_s_32.fp_addr,
2492 ~0, // no index provided.
2493 fib_index, // same as route's FIB
2496 FIB_ROUTE_PATH_FLAG_NONE);
2497 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2498 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "100.100.100.102/32 presnet");
2499 dpo = fib_entry_contribute_ip_forwarding(fei);
2501 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2502 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2503 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32);
2504 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2506 lb = load_balance_get(dpo->dpoi_index);
2507 FIB_TEST((lb->lb_n_buckets == 2), "Recursive LB has %d bucket", lb->lb_n_buckets);
2508 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2509 "First via 10.10.10.1");
2510 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 1)),
2511 "Second via 10.10.10.1");
2513 fib_table_entry_path_remove(fib_index,
2517 &pfx_1_1_1_1_s_32.fp_addr,
2518 ~0, // no index provided.
2519 fib_index, // same as route's FIB
2521 FIB_ROUTE_PATH_FLAG_NONE);
2522 fib_table_entry_path_remove(fib_index,
2526 &pfx_1_1_1_2_s_32.fp_addr,
2527 ~0, // no index provided.
2528 fib_index, // same as route's FIB
2530 FIB_ROUTE_PATH_FLAG_NONE);
2531 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2532 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "100.100.100.102/32 removed");
2535 * remove the remaining recursives
2537 fib_table_entry_path_remove(fib_index,
2541 &pfx_1_1_1_1_s_32.fp_addr,
2542 ~0, // no index provided.
2543 fib_index, // same as route's FIB
2545 FIB_ROUTE_PATH_FLAG_NONE);
2546 fib_table_entry_path_remove(fib_index,
2550 &pfx_1_1_1_1_s_32.fp_addr,
2551 ~0, // no index provided.
2552 fib_index, // same as route's FIB
2554 FIB_ROUTE_PATH_FLAG_NONE);
2555 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_100_pfx) ==
2556 FIB_NODE_INDEX_INVALID),
2557 "100.100.100.100/32 removed");
2558 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_101_pfx) ==
2559 FIB_NODE_INDEX_INVALID),
2560 "100.100.100.101/32 removed");
2563 * -2 entry (2*BGP, the RR source is also API sourced). -1 shared path-list;
2565 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2566 fib_path_list_db_size());
2567 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2568 fib_path_list_pool_size());
2569 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2570 fib_entry_pool_size());
2573 * Add a recursive route via a connected cover, using an adj-fib that does exist
2575 fib_table_entry_path_add(fib_index,
2578 FIB_ENTRY_FLAG_NONE,
2581 ~0, // no index provided.
2582 fib_index, // Same as route's FIB
2585 FIB_ROUTE_PATH_FLAG_NONE);
2588 * +1 entry. +1 shared path-list (recursive via 10.10.10.1)
2590 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2591 fib_path_list_db_size());
2592 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2593 fib_path_list_pool_size());
2594 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
2595 fib_entry_pool_size());
2597 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2598 dpo = fib_entry_contribute_ip_forwarding(fei);
2600 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
2601 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2603 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2604 "200.200.200.200/32 is recursive via adj for 10.10.10.1");
2606 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
2607 "Flags set on RR via existing attached");
2610 * Add a recursive route via a connected cover, using and adj-fib that does
2613 ip46_address_t nh_10_10_10_3 = {
2614 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
2616 fib_prefix_t pfx_10_10_10_3 = {
2618 .fp_proto = FIB_PROTOCOL_IP4,
2619 .fp_addr = nh_10_10_10_3,
2622 fib_table_entry_path_add(fib_index,
2625 FIB_ENTRY_FLAG_NONE,
2628 ~0, // no index provided.
2632 FIB_ROUTE_PATH_FLAG_NONE);
2635 * +2 entries (BGP and RR). +1 shared path-list (recursive via 10.10.10.3) and
2636 * one unshared non-recursive via 10.10.10.3
2638 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2639 fib_path_list_db_size());
2640 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2641 fib_path_list_pool_size());
2642 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2643 fib_entry_pool_size());
2645 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
2648 tm->hw[0]->sw_if_index);
2650 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2651 dpo = fib_entry_contribute_ip_forwarding(fei);
2652 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3);
2653 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2655 ai = fib_entry_get_adj(fei);
2656 FIB_TEST((ai == ai_03), "adj for 10.10.10.3/32 is via adj for 10.10.10.3");
2657 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
2658 fib_entry_get_flags(fei)),
2659 "Flags set on RR via non-existing attached");
2661 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2662 "adj for 200.200.200.200/32 is recursive via adj for 10.10.10.3");
2667 * remove the recursives
2669 fib_table_entry_path_remove(fib_index,
2674 ~0, // no index provided.
2675 fib_index, // same as route's FIB
2677 FIB_ROUTE_PATH_FLAG_NONE);
2678 fib_table_entry_path_remove(fib_index,
2683 ~0, // no index provided.
2684 fib_index, // same as route's FIB
2686 FIB_ROUTE_PATH_FLAG_NONE);
2688 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2689 FIB_NODE_INDEX_INVALID),
2690 "200.200.200.201/32 removed");
2691 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2692 FIB_NODE_INDEX_INVALID),
2693 "200.200.200.200/32 removed");
2694 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3) ==
2695 FIB_NODE_INDEX_INVALID),
2696 "10.10.10.3/32 removed");
2699 * -3 entries (2*BGP and RR). -2 shared path-list (recursive via 10.10.10.3 &
2700 * 10.10.10.1) and one unshared non-recursive via 10.10.10.3
2702 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2703 fib_path_list_db_size());
2704 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2705 fib_path_list_pool_size());
2706 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2707 fib_entry_pool_size());
2712 * Add 5.5.5.5/32 -> 5.5.5.6/32 -> 5.5.5.7/32 -> 5.5.5.5/32
2714 fib_prefix_t pfx_5_5_5_5_s_32 = {
2716 .fp_proto = FIB_PROTOCOL_IP4,
2718 .ip4.as_u32 = clib_host_to_net_u32(0x05050505),
2721 fib_prefix_t pfx_5_5_5_6_s_32 = {
2723 .fp_proto = FIB_PROTOCOL_IP4,
2725 .ip4.as_u32 = clib_host_to_net_u32(0x05050506),
2728 fib_prefix_t pfx_5_5_5_7_s_32 = {
2730 .fp_proto = FIB_PROTOCOL_IP4,
2732 .ip4.as_u32 = clib_host_to_net_u32(0x05050507),
2736 fib_table_entry_path_add(fib_index,
2739 FIB_ENTRY_FLAG_NONE,
2741 &pfx_5_5_5_6_s_32.fp_addr,
2742 ~0, // no index provided.
2746 FIB_ROUTE_PATH_FLAG_NONE);
2747 fib_table_entry_path_add(fib_index,
2750 FIB_ENTRY_FLAG_NONE,
2752 &pfx_5_5_5_7_s_32.fp_addr,
2753 ~0, // no index provided.
2757 FIB_ROUTE_PATH_FLAG_NONE);
2758 fib_table_entry_path_add(fib_index,
2761 FIB_ENTRY_FLAG_NONE,
2763 &pfx_5_5_5_5_s_32.fp_addr,
2764 ~0, // no index provided.
2768 FIB_ROUTE_PATH_FLAG_NONE);
2770 * +3 entries, +3 shared path-list
2772 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2773 fib_path_list_db_size());
2774 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2775 fib_path_list_pool_size());
2776 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2777 fib_entry_pool_size());
2780 * All the entries have only looped paths, so they are all drop
2782 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2783 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2784 "LB for 5.5.5.7/32 is via adj for DROP");
2785 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2786 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2787 "LB for 5.5.5.5/32 is via adj for DROP");
2788 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2789 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2790 "LB for 5.5.5.6/32 is via adj for DROP");
2793 * provide 5.5.5.6/32 with alternate path.
2794 * this will allow only 5.5.5.6/32 to forward with this path, the others
2795 * are still drop since the loop is still present.
2797 fib_table_entry_path_add(fib_index,
2800 FIB_ENTRY_FLAG_NONE,
2803 tm->hw[0]->sw_if_index,
2807 FIB_ROUTE_PATH_FLAG_NONE);
2809 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2810 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2812 lb = load_balance_get(dpo1->dpoi_index);
2813 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.6 LB has %d bucket", lb->lb_n_buckets);
2815 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2816 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2817 FIB_TEST((ai_01 == dpo2->dpoi_index),
2818 "5.5.5.6 bucket 0 resolves via 10.10.10.2");
2820 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2821 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2822 "LB for 5.5.5.7/32 is via adj for DROP");
2823 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2824 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2825 "LB for 5.5.5.5/32 is via adj for DROP");
2828 * remove the alternate path for 5.5.5.6/32
2831 fib_table_entry_path_remove(fib_index,
2836 tm->hw[0]->sw_if_index,
2839 FIB_ROUTE_PATH_FLAG_NONE);
2841 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2842 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2843 "LB for 5.5.5.7/32 is via adj for DROP");
2844 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2845 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2846 "LB for 5.5.5.5/32 is via adj for DROP");
2847 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2848 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2849 "LB for 5.5.5.6/32 is via adj for DROP");
2852 * break the loop by giving 5.5.5.5/32 a new set of paths
2853 * expect all to forward via this new path.
2855 fib_table_entry_update_one_path(fib_index,
2858 FIB_ENTRY_FLAG_NONE,
2861 tm->hw[0]->sw_if_index,
2862 ~0, // invalid fib index
2865 FIB_ROUTE_PATH_FLAG_NONE);
2867 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2868 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2869 lb = load_balance_get(dpo1->dpoi_index);
2870 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.5 LB has %d bucket", lb->lb_n_buckets);
2872 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2873 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2874 FIB_TEST((ai_01 == dpo2->dpoi_index),
2875 "5.5.5.5 bucket 0 resolves via 10.10.10.2");
2877 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_7_s_32);
2878 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2880 lb = load_balance_get(dpo2->dpoi_index);
2881 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2882 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo2->dpoi_index, 0)),
2883 "5.5.5.5.7 via 5.5.5.5");
2885 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32);
2886 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2888 lb = load_balance_get(dpo1->dpoi_index);
2889 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2890 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2891 "5.5.5.5.6 via 5.5.5.7");
2894 * revert back to the loop. so we can remove the prefixes with
2897 fib_table_entry_update_one_path(fib_index,
2900 FIB_ENTRY_FLAG_NONE,
2902 &pfx_5_5_5_6_s_32.fp_addr,
2903 ~0, // no index provided.
2907 FIB_ROUTE_PATH_FLAG_NONE);
2909 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2910 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2911 "LB for 5.5.5.7/32 is via adj for DROP");
2912 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2913 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2914 "LB for 5.5.5.5/32 is via adj for DROP");
2915 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2916 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2917 "LB for 5.5.5.6/32 is via adj for DROP");
2920 * remove all the 5.5.5.x/32 prefixes
2922 fib_table_entry_path_remove(fib_index,
2926 &pfx_5_5_5_6_s_32.fp_addr,
2927 ~0, // no index provided.
2928 fib_index, // same as route's FIB
2930 FIB_ROUTE_PATH_FLAG_NONE);
2931 fib_table_entry_path_remove(fib_index,
2935 &pfx_5_5_5_7_s_32.fp_addr,
2936 ~0, // no index provided.
2937 fib_index, // same as route's FIB
2939 FIB_ROUTE_PATH_FLAG_NONE);
2940 fib_table_entry_path_remove(fib_index,
2944 &pfx_5_5_5_5_s_32.fp_addr,
2945 ~0, // no index provided.
2946 fib_index, // same as route's FIB
2948 FIB_ROUTE_PATH_FLAG_NONE);
2949 fib_table_entry_path_remove(fib_index,
2954 ~0, // no index provided.
2955 fib_index, // same as route's FIB
2957 FIB_ROUTE_PATH_FLAG_NONE);
2960 * -3 entries, -3 shared path-list
2962 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2963 fib_path_list_db_size());
2964 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2965 fib_path_list_pool_size());
2966 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2967 fib_entry_pool_size());
2970 * Single level loop 5.5.5.5/32 via 5.5.5.5/32
2972 fib_table_entry_path_add(fib_index,
2975 FIB_ENTRY_FLAG_NONE,
2977 &pfx_5_5_5_6_s_32.fp_addr,
2978 ~0, // no index provided.
2982 FIB_ROUTE_PATH_FLAG_NONE);
2983 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2984 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2985 "1-level 5.5.5.6/32 loop is via adj for DROP");
2987 fib_table_entry_path_remove(fib_index,
2991 &pfx_5_5_5_6_s_32.fp_addr,
2992 ~0, // no index provided.
2993 fib_index, // same as route's FIB
2995 FIB_ROUTE_PATH_FLAG_NONE);
2996 FIB_TEST(FIB_NODE_INDEX_INVALID ==
2997 fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32),
2998 "1-level 5.5.5.6/32 loop is removed");
3001 * A recursive route whose next-hop is covered by the prefix.
3002 * This would mean the via-fib, which inherits forwarding from its
3003 * cover, thus picks up forwarding from the prfix, which is via the
3004 * via-fib, and we have a loop.
3006 fib_prefix_t pfx_23_23_23_0_s_24 = {
3008 .fp_proto = FIB_PROTOCOL_IP4,
3010 .ip4.as_u32 = clib_host_to_net_u32(0x17171700),
3013 fib_prefix_t pfx_23_23_23_23_s_32 = {
3015 .fp_proto = FIB_PROTOCOL_IP4,
3017 .ip4.as_u32 = clib_host_to_net_u32(0x17171717),
3020 fei = fib_table_entry_path_add(fib_index,
3021 &pfx_23_23_23_0_s_24,
3023 FIB_ENTRY_FLAG_NONE,
3025 &pfx_23_23_23_23_s_32.fp_addr,
3030 FIB_ROUTE_PATH_FLAG_NONE);
3031 dpo = fib_entry_contribute_ip_forwarding(fei);
3032 FIB_TEST(load_balance_is_drop(dpo),
3033 "23.23.23.0/24 via covered is DROP");
3034 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3037 * add-remove test. no change.
3039 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3040 fib_path_list_db_size());
3041 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3042 fib_path_list_pool_size());
3043 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3044 fib_entry_pool_size());
3047 * Make the default route recursive via a unknown next-hop. Thus the
3048 * next hop's cover would be the default route
3050 fei = fib_table_entry_path_add(fib_index,
3053 FIB_ENTRY_FLAG_NONE,
3055 &pfx_23_23_23_23_s_32.fp_addr,
3060 FIB_ROUTE_PATH_FLAG_NONE);
3061 dpo = fib_entry_contribute_ip_forwarding(fei);
3062 FIB_TEST(load_balance_is_drop(dpo),
3063 "0.0.0.0.0/0 via is DROP");
3064 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3065 "no resolving interface for looped 0.0.0.0/0");
3067 fei = fib_table_lookup_exact_match(fib_index, &pfx_23_23_23_23_s_32);
3068 dpo = fib_entry_contribute_ip_forwarding(fei);
3069 FIB_TEST(load_balance_is_drop(dpo),
3070 "23.23.23.23/32 via is DROP");
3071 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3072 "no resolving interface for looped 23.23.23.23/32");
3074 fib_table_entry_delete(fib_index, &pfx_0_0_0_0_s_0, FIB_SOURCE_API);
3077 * A recursive route with recursion constraints.
3078 * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained
3080 fib_table_entry_path_add(fib_index,
3083 FIB_ENTRY_FLAG_NONE,
3090 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3092 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3093 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3095 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3096 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3098 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3099 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3102 * save the load-balance. we expect it to be inplace modified
3104 lb = load_balance_get(dpo1->dpoi_index);
3107 * add a covering prefix for the via fib that would otherwise serve
3108 * as the resolving route when the host is removed
3110 fib_table_entry_path_add(fib_index,
3113 FIB_ENTRY_FLAG_NONE,
3116 tm->hw[0]->sw_if_index,
3117 ~0, // invalid fib index
3120 FIB_ROUTE_PATH_FLAG_NONE);
3121 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28);
3122 ai = fib_entry_get_adj(fei);
3123 FIB_TEST((ai == ai_01),
3124 "adj for 1.1.1.0/28 is via adj for 1.1.1.1");
3127 * remove the host via FIB - expect the BGP prefix to be drop
3129 fib_table_entry_path_remove(fib_index,
3134 tm->hw[0]->sw_if_index,
3135 ~0, // invalid fib index
3137 FIB_ROUTE_PATH_FLAG_NONE);
3139 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3140 "adj for 200.200.200.200/32 is recursive via adj for DROP");
3143 * add the via-entry host reoute back. expect to resolve again
3145 fib_table_entry_path_add(fib_index,
3148 FIB_ENTRY_FLAG_NONE,
3151 tm->hw[0]->sw_if_index,
3152 ~0, // invalid fib index
3155 FIB_ROUTE_PATH_FLAG_NONE);
3156 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3157 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3160 * add another path for the recursive. it will then have 2.
3162 fib_prefix_t pfx_1_1_1_3_s_32 = {
3164 .fp_proto = FIB_PROTOCOL_IP4,
3166 .ip4.as_u32 = clib_host_to_net_u32(0x01010103),
3169 fib_table_entry_path_add(fib_index,
3172 FIB_ENTRY_FLAG_NONE,
3175 tm->hw[0]->sw_if_index,
3176 ~0, // invalid fib index
3179 FIB_ROUTE_PATH_FLAG_NONE);
3181 fib_table_entry_path_add(fib_index,
3184 FIB_ENTRY_FLAG_NONE,
3186 &pfx_1_1_1_3_s_32.fp_addr,
3191 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3194 * add a bunch load more entries using this path combo so that we get
3195 * an LB-map created.
3198 fib_prefix_t bgp_78s[N_P];
3199 for (ii = 0; ii < N_P; ii++)
3201 bgp_78s[ii].fp_len = 32;
3202 bgp_78s[ii].fp_proto = FIB_PROTOCOL_IP4;
3203 bgp_78s[ii].fp_addr.ip4.as_u32 = clib_host_to_net_u32(0x4e000000+ii);
3206 fib_table_entry_path_add(fib_index,
3209 FIB_ENTRY_FLAG_NONE,
3211 &pfx_1_1_1_3_s_32.fp_addr,
3216 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3217 fib_table_entry_path_add(fib_index,
3220 FIB_ENTRY_FLAG_NONE,
3227 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3230 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3231 dpo = fib_entry_contribute_ip_forwarding(fei);
3233 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3234 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3235 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)),
3236 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3237 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32);
3238 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3239 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)),
3240 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3");
3243 * expect the lb-map used by the recursive's load-balance is using both buckets
3245 load_balance_map_t *lbm;
3248 lb = load_balance_get(dpo->dpoi_index);
3250 load_balance_map_lock(lbmi);
3251 lbm = load_balance_map_get(lbmi);
3253 FIB_TEST(lbm->lbm_buckets[0] == 0,
3254 "LB maps's bucket 0 is %d",
3255 lbm->lbm_buckets[0]);
3256 FIB_TEST(lbm->lbm_buckets[1] == 1,
3257 "LB maps's bucket 1 is %d",
3258 lbm->lbm_buckets[1]);
3261 * withdraw one of the /32 via-entrys.
3262 * that ECMP path will be unresolved and forwarding should continue on the
3263 * other available path. this is an iBGP PIC edge failover.
3264 * Test the forwarding changes without re-fetching the adj from the
3265 * recursive entry. this ensures its the same one that is updated; i.e. an
3268 fib_table_entry_path_remove(fib_index,
3273 tm->hw[0]->sw_if_index,
3274 ~0, // invalid fib index
3276 FIB_ROUTE_PATH_FLAG_NONE);
3278 /* suspend so the update walk kicks int */
3279 vlib_process_suspend(vlib_get_main(), 1e-5);
3281 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3282 FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)),
3283 "post PIC 200.200.200.200/32 was inplace modified");
3285 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)),
3286 "post PIC adj for 200.200.200.200/32 is recursive"
3287 " via adj for 1.1.1.3");
3290 * the LB maps that was locked above should have been modified to remove
3291 * the path that was down, and thus its bucket points to a path that is
3294 FIB_TEST(lbm->lbm_buckets[0] == 1,
3295 "LB maps's bucket 0 is %d",
3296 lbm->lbm_buckets[0]);
3297 FIB_TEST(lbm->lbm_buckets[1] == 1,
3298 "LB maps's bucket 1 is %d",
3299 lbm->lbm_buckets[1]);
3301 load_balance_map_unlock(lbmi);
3304 * add it back. again
3306 fib_table_entry_path_add(fib_index,
3309 FIB_ENTRY_FLAG_NONE,
3312 tm->hw[0]->sw_if_index,
3313 ~0, // invalid fib index
3316 FIB_ROUTE_PATH_FLAG_NONE);
3318 /* suspend so the update walk kicks in */
3319 vlib_process_suspend(vlib_get_main(), 1e-5);
3321 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)),
3322 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3323 "via adj for 1.1.1.1");
3324 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)),
3325 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3326 "via adj for 1.1.1.3");
3328 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3329 dpo = fib_entry_contribute_ip_forwarding(fei);
3330 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3331 "post PIC 200.200.200.200/32 was inplace modified");
3334 * add a 3rd path. this makes the LB 16 buckets.
3336 fib_table_entry_path_add(fib_index,
3339 FIB_ENTRY_FLAG_NONE,
3341 &pfx_1_1_1_2_s_32.fp_addr,
3346 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3347 for (ii = 0; ii < N_P; ii++)
3349 fib_table_entry_path_add(fib_index,
3352 FIB_ENTRY_FLAG_NONE,
3354 &pfx_1_1_1_2_s_32.fp_addr,
3359 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3362 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3363 dpo = fib_entry_contribute_ip_forwarding(fei);
3364 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3365 "200.200.200.200/32 was inplace modified for 3rd path");
3366 FIB_TEST(16 == lb->lb_n_buckets,
3367 "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets");
3370 load_balance_map_lock(lbmi);
3371 lbm = load_balance_map_get(lbmi);
3373 for (ii = 0; ii < 16; ii++)
3375 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3376 "LB Map for 200.200.200.200/32 at %d is %d",
3377 ii, lbm->lbm_buckets[ii]);
3381 * trigger PIC by removing the first via-entry
3382 * the first 6 buckets of the map should map to the next 6
3384 fib_table_entry_path_remove(fib_index,
3389 tm->hw[0]->sw_if_index,
3392 FIB_ROUTE_PATH_FLAG_NONE);
3393 /* suspend so the update walk kicks int */
3394 vlib_process_suspend(vlib_get_main(), 1e-5);
3396 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3397 dpo = fib_entry_contribute_ip_forwarding(fei);
3398 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3399 "200.200.200.200/32 was inplace modified for 3rd path");
3400 FIB_TEST(2 == lb->lb_n_buckets,
3401 "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets");
3403 for (ii = 0; ii < 6; ii++)
3405 FIB_TEST(lbm->lbm_buckets[ii] == ii+6,
3406 "LB Map for 200.200.200.200/32 at %d is %d",
3407 ii, lbm->lbm_buckets[ii]);
3409 for (ii = 6; ii < 16; ii++)
3411 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3412 "LB Map for 200.200.200.200/32 at %d is %d",
3413 ii, lbm->lbm_buckets[ii]);
3415 load_balance_map_unlock(lbmi);
3420 fib_table_entry_path_add(fib_index,
3423 FIB_ENTRY_FLAG_NONE,
3426 tm->hw[0]->sw_if_index,
3430 FIB_ROUTE_PATH_FLAG_NONE);
3432 for (ii = 0; ii < N_P; ii++)
3434 fib_table_entry_delete(fib_index,
3437 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3438 fib_table_lookup_exact_match(fib_index, &bgp_78s[ii])),
3440 format_fib_prefix, &bgp_78s[ii]);
3442 fib_table_entry_path_remove(fib_index,
3446 &pfx_1_1_1_2_s_32.fp_addr,
3450 MPLS_LABEL_INVALID);
3451 fib_table_entry_path_remove(fib_index,
3459 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3460 fib_table_entry_path_remove(fib_index,
3464 &pfx_1_1_1_3_s_32.fp_addr,
3468 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3469 fib_table_entry_delete(fib_index,
3472 fib_table_entry_delete(fib_index,
3475 /* suspend so the update walk kicks int */
3476 vlib_process_suspend(vlib_get_main(), 1e-5);
3477 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3478 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)),
3479 "1.1.1.1/28 removed");
3480 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3481 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)),
3482 "1.1.1.3/32 removed");
3483 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3484 fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)),
3485 "200.200.200.200/32 removed");
3488 * add-remove test. no change.
3490 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3491 fib_path_list_db_size());
3492 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3493 fib_path_list_pool_size());
3494 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3495 fib_entry_pool_size());
3498 * A route whose paths are built up iteratively and then removed
3501 fib_prefix_t pfx_4_4_4_4_s_32 = {
3503 .fp_proto = FIB_PROTOCOL_IP4,
3506 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
3510 fib_table_entry_path_add(fib_index,
3513 FIB_ENTRY_FLAG_NONE,
3516 tm->hw[0]->sw_if_index,
3520 FIB_ROUTE_PATH_FLAG_NONE);
3521 fib_table_entry_path_add(fib_index,
3524 FIB_ENTRY_FLAG_NONE,
3527 tm->hw[0]->sw_if_index,
3531 FIB_ROUTE_PATH_FLAG_NONE);
3532 fib_table_entry_path_add(fib_index,
3535 FIB_ENTRY_FLAG_NONE,
3538 tm->hw[0]->sw_if_index,
3542 FIB_ROUTE_PATH_FLAG_NONE);
3543 FIB_TEST(FIB_NODE_INDEX_INVALID !=
3544 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3545 "4.4.4.4/32 present");
3547 fib_table_entry_delete(fib_index,
3550 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3551 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3552 "4.4.4.4/32 removed");
3555 * add-remove test. no change.
3557 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3558 fib_path_list_db_size());
3559 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3560 fib_path_list_pool_size());
3561 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3562 fib_entry_pool_size());
3565 * A route with multiple paths at once
3567 fib_route_path_t *r_paths = NULL;
3569 for (ii = 0; ii < 4; ii++)
3571 fib_route_path_t r_path = {
3572 .frp_proto = DPO_PROTO_IP4,
3574 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
3576 .frp_sw_if_index = tm->hw[0]->sw_if_index,
3578 .frp_fib_index = ~0,
3580 vec_add1(r_paths, r_path);
3583 fib_table_entry_update(fib_index,
3586 FIB_ENTRY_FLAG_NONE,
3589 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3590 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3591 dpo = fib_entry_contribute_ip_forwarding(fei);
3593 lb = load_balance_get(dpo->dpoi_index);
3594 FIB_TEST((lb->lb_n_buckets == 4), "4.4.4.4/32 lb over %d paths", lb->lb_n_buckets);
3596 fib_table_entry_delete(fib_index,
3599 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3600 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3601 "4.4.4.4/32 removed");
3605 * add-remove test. no change.
3607 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3608 fib_path_list_db_size());
3609 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3610 fib_path_list_pool_size());
3611 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3612 fib_entry_pool_size());
3615 * A route deag route
3617 fib_table_entry_path_add(fib_index,
3620 FIB_ENTRY_FLAG_NONE,
3627 FIB_ROUTE_PATH_FLAG_NONE);
3629 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3630 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3632 dpo = fib_entry_contribute_ip_forwarding(fei);
3633 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3634 lookup_dpo_t *lkd = lookup_dpo_get(dpo->dpoi_index);
3636 FIB_TEST((fib_index == lkd->lkd_fib_index),
3637 "4.4.4.4/32 is deag in %d %U",
3639 format_dpo_id, dpo, 0);
3640 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
3641 "4.4.4.4/32 is source deag in %d %U",
3643 format_dpo_id, dpo, 0);
3645 fib_table_entry_delete(fib_index,
3648 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3649 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3650 "4.4.4.4/32 removed");
3654 * A route deag route in a source lookup table
3656 fib_table_entry_path_add(fib_index,
3659 FIB_ENTRY_FLAG_NONE,
3666 FIB_ROUTE_PATH_SOURCE_LOOKUP);
3668 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3669 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3671 dpo = fib_entry_contribute_ip_forwarding(fei);
3672 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3673 lkd = lookup_dpo_get(dpo->dpoi_index);
3675 FIB_TEST((fib_index == lkd->lkd_fib_index),
3676 "4.4.4.4/32 is deag in %d %U",
3678 format_dpo_id, dpo, 0);
3679 FIB_TEST((LOOKUP_INPUT_SRC_ADDR == lkd->lkd_input),
3680 "4.4.4.4/32 is source deag in %d %U",
3682 format_dpo_id, dpo, 0);
3684 fib_table_entry_delete(fib_index,
3687 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3688 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3689 "4.4.4.4/32 removed");
3693 * add-remove test. no change.
3695 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3696 fib_path_list_db_size());
3697 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3698 fib_path_list_pool_size());
3699 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3700 fib_entry_pool_size());
3704 * add a recursive with duplicate paths. Expect the duplicate to be ignored.
3706 fib_prefix_t pfx_34_1_1_1_s_32 = {
3708 .fp_proto = FIB_PROTOCOL_IP4,
3710 .ip4.as_u32 = clib_host_to_net_u32(0x22010101),
3713 fib_prefix_t pfx_34_34_1_1_s_32 = {
3715 .fp_proto = FIB_PROTOCOL_IP4,
3717 .ip4.as_u32 = clib_host_to_net_u32(0x22220101),
3720 fei = fib_table_entry_path_add(fib_index,
3721 &pfx_34_34_1_1_s_32,
3723 FIB_ENTRY_FLAG_NONE,
3726 tm->hw[0]->sw_if_index,
3730 FIB_ROUTE_PATH_FLAG_NONE);
3731 fei = fib_table_entry_path_add(fib_index,
3734 FIB_ENTRY_FLAG_NONE,
3736 &pfx_34_34_1_1_s_32.fp_addr,
3741 FIB_ROUTE_PATH_FLAG_NONE);
3742 fei = fib_table_entry_path_add(fib_index,
3745 FIB_ENTRY_FLAG_NONE,
3747 &pfx_34_34_1_1_s_32.fp_addr,
3752 FIB_ROUTE_PATH_FLAG_NONE);
3753 FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0);
3754 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3755 fib_table_entry_delete(fib_index,
3756 &pfx_34_34_1_1_s_32,
3761 * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32
3762 * all of which are via 10.10.10.1, Itf1
3764 fib_table_entry_path_remove(fib_index,
3769 tm->hw[0]->sw_if_index,
3772 FIB_ROUTE_PATH_FLAG_NONE);
3773 fib_table_entry_path_remove(fib_index,
3778 tm->hw[0]->sw_if_index,
3781 FIB_ROUTE_PATH_FLAG_NONE);
3782 fib_table_entry_path_remove(fib_index,
3787 tm->hw[0]->sw_if_index,
3790 FIB_ROUTE_PATH_FLAG_NONE);
3792 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3793 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32),
3794 "1.1.1.1/32 removed");
3795 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3796 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32),
3797 "1.1.1.2/32 removed");
3798 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3799 fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24),
3800 "1.1.2.0/24 removed");
3803 * -3 entries and -1 shared path-list
3805 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3806 fib_path_list_db_size());
3807 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3808 fib_path_list_pool_size());
3809 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3810 fib_entry_pool_size());
3813 * An attached-host route. Expect to link to the incomplete adj
3815 fib_prefix_t pfx_4_1_1_1_s_32 = {
3817 .fp_proto = FIB_PROTOCOL_IP4,
3820 .ip4.as_u32 = clib_host_to_net_u32(0x04010101),
3823 fib_table_entry_path_add(fib_index,
3826 FIB_ENTRY_FLAG_NONE,
3829 tm->hw[0]->sw_if_index,
3833 FIB_ROUTE_PATH_FLAG_NONE);
3835 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32);
3836 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present");
3837 ai = fib_entry_get_adj(fei);
3839 ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
3841 &pfx_4_1_1_1_s_32.fp_addr,
3842 tm->hw[0]->sw_if_index);
3843 FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ");
3847 * +1 entry and +1 shared path-list
3849 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3850 fib_path_list_db_size());
3851 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3852 fib_path_list_pool_size());
3853 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
3854 fib_entry_pool_size());
3856 fib_table_entry_delete(fib_index,
3860 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3861 fib_path_list_db_size());
3862 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3863 fib_path_list_pool_size());
3864 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3865 fib_entry_pool_size());
3868 * add a v6 prefix via v4 next-hops
3870 fib_prefix_t pfx_2001_s_64 = {
3872 .fp_proto = FIB_PROTOCOL_IP6,
3874 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
3877 fei = fib_table_entry_path_add(0, //default v6 table
3880 FIB_ENTRY_FLAG_NONE,
3883 tm->hw[0]->sw_if_index,
3887 FIB_ROUTE_PATH_FLAG_NONE);
3889 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
3890 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present");
3891 ai = fib_entry_get_adj(fei);
3893 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
3894 "2001::/64 via ARP-adj");
3895 FIB_TEST((adj->ia_link == VNET_LINK_IP6),
3896 "2001::/64 is link type v6");
3897 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4),
3898 "2001::/64 ADJ-adj is NH proto v4");
3899 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
3902 * add a uRPF exempt prefix:
3904 * - it's forwarding is drop
3905 * - it's uRPF list is not empty
3906 * - the uRPF list for the default route (it's cover) is empty
3908 fei = fib_table_entry_special_add(fib_index,
3910 FIB_SOURCE_URPF_EXEMPT,
3911 FIB_ENTRY_FLAG_DROP);
3912 dpo = fib_entry_contribute_ip_forwarding(fei);
3913 FIB_TEST(load_balance_is_drop(dpo),
3914 "uRPF exempt 4.1.1.1/32 DROP");
3915 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0),
3916 "uRPF list for exempt prefix has itf index 0");
3917 fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0);
3918 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
3919 "uRPF list for 0.0.0.0/0 empty");
3921 fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
3924 * An adj-fib that fails the refinement criteria - no connected cover
3926 fib_prefix_t pfx_12_10_10_2_s_32 = {
3928 .fp_proto = FIB_PROTOCOL_IP4,
3931 .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02),
3935 fib_table_entry_path_add(fib_index,
3936 &pfx_12_10_10_2_s_32,
3938 FIB_ENTRY_FLAG_ATTACHED,
3940 &pfx_12_10_10_2_s_32.fp_addr,
3941 tm->hw[0]->sw_if_index,
3942 ~0, // invalid fib index
3945 FIB_ROUTE_PATH_FLAG_NONE);
3947 fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32);
3948 dpo = fib_entry_contribute_ip_forwarding(fei);
3949 FIB_TEST(!dpo_id_is_valid(dpo),
3950 "no connected cover adj-fib fails refinement");
3952 fib_table_entry_delete(fib_index,
3953 &pfx_12_10_10_2_s_32,
3957 * An adj-fib that fails the refinement criteria - cover is connected
3958 * but on a different interface
3960 fib_prefix_t pfx_10_10_10_127_s_32 = {
3962 .fp_proto = FIB_PROTOCOL_IP4,
3965 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f),
3969 fib_table_entry_path_add(fib_index,
3970 &pfx_10_10_10_127_s_32,
3972 FIB_ENTRY_FLAG_ATTACHED,
3974 &pfx_10_10_10_127_s_32.fp_addr,
3975 tm->hw[1]->sw_if_index,
3976 ~0, // invalid fib index
3979 FIB_ROUTE_PATH_FLAG_NONE);
3981 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32);
3982 dpo = fib_entry_contribute_ip_forwarding(fei);
3983 FIB_TEST(!dpo_id_is_valid(dpo),
3984 "wrong interface adj-fib fails refinement");
3986 fib_table_entry_delete(fib_index,
3987 &pfx_10_10_10_127_s_32,
3991 * add a second path to an adj-fib
3992 * this is a sumiluation of another ARP entry created
3993 * on an interface on which the connected prefi does not exist.
3994 * The second path fails refinement. Expect to forward through the
3997 fib_prefix_t pfx_10_10_10_3_s_32 = {
3999 .fp_proto = FIB_PROTOCOL_IP4,
4002 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
4006 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
4009 tm->hw[0]->sw_if_index);
4011 fib_test_lb_bucket_t ip_o_10_10_10_3 = {
4017 fei = fib_table_entry_path_add(fib_index,
4018 &pfx_10_10_10_3_s_32,
4020 FIB_ENTRY_FLAG_NONE,
4023 tm->hw[0]->sw_if_index,
4027 FIB_ROUTE_PATH_FLAG_NONE);
4028 fei = fib_table_entry_path_add(fib_index,
4029 &pfx_10_10_10_3_s_32,
4031 FIB_ENTRY_FLAG_NONE,
4034 tm->hw[1]->sw_if_index,
4038 FIB_ROUTE_PATH_FLAG_NONE);
4039 FIB_TEST(fib_test_validate_entry(fei,
4040 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4043 "10.10.10.3 via 10.10.10.3/Eth0 only");
4046 * remove the path that refines the cover, should go unresolved
4048 fib_table_entry_path_remove(fib_index,
4049 &pfx_10_10_10_3_s_32,
4053 tm->hw[0]->sw_if_index,
4056 FIB_ROUTE_PATH_FLAG_NONE);
4057 dpo = fib_entry_contribute_ip_forwarding(fei);
4058 FIB_TEST(!dpo_id_is_valid(dpo),
4059 "wrong interface adj-fib fails refinement");
4062 * add back the path that refines the cover
4064 fei = fib_table_entry_path_add(fib_index,
4065 &pfx_10_10_10_3_s_32,
4067 FIB_ENTRY_FLAG_NONE,
4070 tm->hw[0]->sw_if_index,
4074 FIB_ROUTE_PATH_FLAG_NONE);
4075 FIB_TEST(fib_test_validate_entry(fei,
4076 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4079 "10.10.10.3 via 10.10.10.3/Eth0 only");
4082 * remove the path that does not refine the cover
4084 fib_table_entry_path_remove(fib_index,
4085 &pfx_10_10_10_3_s_32,
4089 tm->hw[1]->sw_if_index,
4092 FIB_ROUTE_PATH_FLAG_NONE);
4093 FIB_TEST(fib_test_validate_entry(fei,
4094 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4097 "10.10.10.3 via 10.10.10.3/Eth0 only");
4100 * remove the path that does refine, it's the last path, so
4101 * the entry should be gone
4103 fib_table_entry_path_remove(fib_index,
4104 &pfx_10_10_10_3_s_32,
4108 tm->hw[0]->sw_if_index,
4111 FIB_ROUTE_PATH_FLAG_NONE);
4112 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
4113 FIB_TEST((fei == FIB_NODE_INDEX_INVALID), "10.10.10.3 gone");
4118 * change the table's flow-hash config - expect the update to propagete to
4119 * the entries' load-balance objects
4121 flow_hash_config_t old_hash_config, new_hash_config;
4123 old_hash_config = fib_table_get_flow_hash_config(fib_index,
4125 new_hash_config = (IP_FLOW_HASH_SRC_ADDR |
4126 IP_FLOW_HASH_DST_ADDR);
4128 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
4129 dpo = fib_entry_contribute_ip_forwarding(fei);
4130 lb = load_balance_get(dpo->dpoi_index);
4131 FIB_TEST((lb->lb_hash_config == old_hash_config),
4132 "Table and LB hash config match: %U",
4133 format_ip_flow_hash_config, lb->lb_hash_config);
4135 fib_table_set_flow_hash_config(fib_index, FIB_PROTOCOL_IP4, new_hash_config);
4137 FIB_TEST((lb->lb_hash_config == new_hash_config),
4138 "Table and LB newhash config match: %U",
4139 format_ip_flow_hash_config, lb->lb_hash_config);
4142 * A route via DVR DPO
4144 fei = fib_table_entry_path_add(fib_index,
4145 &pfx_10_10_10_3_s_32,
4147 FIB_ENTRY_FLAG_NONE,
4150 tm->hw[0]->sw_if_index,
4154 FIB_ROUTE_PATH_DVR);
4155 dpo_id_t dvr_dpo = DPO_INVALID;
4156 dvr_dpo_add_or_lock(tm->hw[0]->sw_if_index, DPO_PROTO_IP4, &dvr_dpo);
4157 fib_test_lb_bucket_t ip_o_l2 = {
4160 .adj = dvr_dpo.dpoi_index,
4164 FIB_TEST(fib_test_validate_entry(fei,
4165 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4168 "10.10.10.3 via L2 on Eth0");
4169 fib_table_entry_path_remove(fib_index,
4170 &pfx_10_10_10_3_s_32,
4174 tm->hw[0]->sw_if_index,
4177 FIB_ROUTE_PATH_DVR);
4178 dpo_reset(&dvr_dpo);
4184 fib_table_entry_delete(fib_index,
4185 &pfx_10_10_10_1_s_32,
4187 fib_table_entry_delete(fib_index,
4188 &pfx_10_10_10_2_s_32,
4190 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4191 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32),
4192 "10.10.10.1/32 adj-fib removed");
4193 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4194 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32),
4195 "10.10.10.2/32 adj-fib removed");
4198 * -2 entries and -2 non-shared path-list
4200 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4201 fib_path_list_db_size());
4202 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
4203 fib_path_list_pool_size());
4204 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
4205 fib_entry_pool_size());
4208 * unlock the adjacencies for which this test provided a rewrite.
4209 * These are the last locks on these adjs. they should thus go away.
4213 adj_unlock(ai_12_12_12_12);
4215 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4220 * remove the interface prefixes
4222 local_pfx.fp_len = 32;
4223 fib_table_entry_special_remove(fib_index, &local_pfx,
4224 FIB_SOURCE_INTERFACE);
4225 fei = fib_table_lookup(fib_index, &local_pfx);
4227 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4228 fib_table_lookup_exact_match(fib_index, &local_pfx),
4229 "10.10.10.10/32 adj-fib removed");
4231 local_pfx.fp_len = 24;
4232 fib_table_entry_delete(fib_index, &local_pfx,
4233 FIB_SOURCE_INTERFACE);
4235 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4236 fib_table_lookup_exact_match(fib_index, &local_pfx),
4237 "10.10.10.10/24 adj-fib removed");
4240 * -2 entries and -2 non-shared path-list
4242 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4243 fib_path_list_db_size());
4244 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
4245 fib_path_list_pool_size());
4246 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
4247 fib_entry_pool_size());
4250 * Last but not least, remove the VRF
4252 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4255 "NO API Source'd prefixes");
4256 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4259 "NO RR Source'd prefixes");
4260 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4262 FIB_SOURCE_INTERFACE)),
4263 "NO INterface Source'd prefixes");
4265 fib_table_unlock(fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
4267 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4268 fib_path_list_db_size());
4269 FIB_TEST((PNBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
4270 fib_path_list_pool_size());
4271 FIB_TEST((ENBR-5 == fib_entry_pool_size()), "entry pool size is %d",
4272 fib_entry_pool_size());
4273 FIB_TEST((ENBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
4274 pool_elts(fib_urpf_list_pool));
4275 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
4276 pool_elts(load_balance_map_pool));
4277 FIB_TEST((lb_count == pool_elts(load_balance_pool)), "LB pool size is %d",
4278 pool_elts(load_balance_pool));
4279 FIB_TEST((0 == pool_elts(dvr_dpo_pool)), "L2 DPO pool size is %d",
4280 pool_elts(dvr_dpo_pool));
4289 * In the default table check for the presence and correct forwarding
4290 * of the special entries
4292 fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02;
4293 const dpo_id_t *dpo, *dpo_drop;
4294 const ip_adjacency_t *adj;
4295 const receive_dpo_t *rd;
4300 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4303 /* via 2001:0:0:1::2 */
4304 ip46_address_t nh_2001_2 = {
4307 [0] = clib_host_to_net_u64(0x2001000000000001),
4308 [1] = clib_host_to_net_u64(0x0000000000000002),
4315 dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
4317 /* Find or create FIB table 11 */
4318 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11,
4321 for (ii = 0; ii < 4; ii++)
4323 ip6_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
4326 fib_prefix_t pfx_0_0 = {
4328 .fp_proto = FIB_PROTOCOL_IP6,
4336 dfrt = fib_table_lookup(fib_index, &pfx_0_0);
4337 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
4338 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4339 "Default route is DROP");
4341 dpo = fib_entry_contribute_ip_forwarding(dfrt);
4342 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4345 &pfx_0_0.fp_addr.ip6)),
4346 "default-route; fwd and non-fwd tables match");
4348 // FIXME - check specials.
4351 * At this stage there is one v4 FIB with 5 routes and two v6 FIBs
4352 * each with 2 entries and a v6 mfib with 4 path-lists.
4353 * All entries are special so no path-list sharing.
4358 * if the IGMP plugin is loaded this adds two more entries to the v4 MFIB
4360 if (vlib_get_plugin_symbol("igmp_plugin.so", "igmp_listen"))
4363 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
4364 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is %d",
4365 fib_path_list_pool_size());
4366 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
4367 fib_entry_pool_size());
4370 * add interface routes.
4371 * validate presence of /64 attached and /128 recieve.
4372 * test for the presence of the receive address in the glean and local adj
4374 * receive on 2001:0:0:1::1/128
4376 fib_prefix_t local_pfx = {
4378 .fp_proto = FIB_PROTOCOL_IP6,
4382 [0] = clib_host_to_net_u64(0x2001000000000001),
4383 [1] = clib_host_to_net_u64(0x0000000000000001),
4389 fib_table_entry_update_one_path(fib_index, &local_pfx,
4390 FIB_SOURCE_INTERFACE,
4391 (FIB_ENTRY_FLAG_CONNECTED |
4392 FIB_ENTRY_FLAG_ATTACHED),
4395 tm->hw[0]->sw_if_index,
4399 FIB_ROUTE_PATH_FLAG_NONE);
4400 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4402 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4404 ai = fib_entry_get_adj(fei);
4405 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
4407 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4408 "attached interface adj is glean");
4409 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4410 &adj->sub_type.glean.receive_addr)),
4411 "attached interface adj is receive ok");
4412 dpo = fib_entry_contribute_ip_forwarding(fei);
4413 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4416 &local_pfx.fp_addr.ip6)),
4417 "attached-route; fwd and non-fwd tables match");
4419 local_pfx.fp_len = 128;
4420 fib_table_entry_update_one_path(fib_index, &local_pfx,
4421 FIB_SOURCE_INTERFACE,
4422 (FIB_ENTRY_FLAG_CONNECTED |
4423 FIB_ENTRY_FLAG_LOCAL),
4426 tm->hw[0]->sw_if_index,
4427 ~0, // invalid fib index
4430 FIB_ROUTE_PATH_FLAG_NONE);
4431 fei = fib_table_lookup(fib_index, &local_pfx);
4433 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4435 dpo = fib_entry_contribute_ip_forwarding(fei);
4436 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4437 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4438 "local interface adj is local");
4439 rd = receive_dpo_get(dpo->dpoi_index);
4441 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4443 "local interface adj is receive ok");
4445 dpo = fib_entry_contribute_ip_forwarding(fei);
4446 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4449 &local_pfx.fp_addr.ip6)),
4450 "local-route; fwd and non-fwd tables match");
4453 * +2 entries. +2 unshared path-lists
4455 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
4456 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
4457 fib_path_list_pool_size());
4458 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4459 fib_entry_pool_size());
4462 * Modify the default route to be via an adj not yet known.
4463 * this sources the defalut route with the API source, which is
4464 * a higher preference to the DEFAULT_ROUTE source
4466 fib_table_entry_path_add(fib_index, &pfx_0_0,
4468 FIB_ENTRY_FLAG_NONE,
4471 tm->hw[0]->sw_if_index,
4475 FIB_ROUTE_PATH_FLAG_NONE);
4476 fei = fib_table_lookup(fib_index, &pfx_0_0);
4478 FIB_TEST((fei == dfrt), "default route same index");
4479 ai = fib_entry_get_adj(fei);
4480 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
4482 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4483 "adj is incomplete");
4484 FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)),
4485 "adj nbr next-hop ok");
4488 * find the adj in the shared db
4490 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4493 tm->hw[0]->sw_if_index);
4494 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
4495 adj_unlock(locked_ai);
4498 * no more entires. +1 shared path-list
4500 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4501 fib_path_list_db_size());
4502 FIB_TEST((PNPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
4503 fib_path_list_pool_size());
4504 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4505 fib_entry_pool_size());
4508 * remove the API source from the default route. We expected
4509 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
4511 fib_table_entry_path_remove(fib_index, &pfx_0_0,
4515 tm->hw[0]->sw_if_index,
4518 FIB_ROUTE_PATH_FLAG_NONE);
4519 fei = fib_table_lookup(fib_index, &pfx_0_0);
4521 FIB_TEST((fei == dfrt), "default route same index");
4522 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4523 "Default route is DROP");
4526 * no more entires. -1 shared path-list
4528 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4529 fib_path_list_db_size());
4530 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
4531 fib_path_list_pool_size());
4532 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4533 fib_entry_pool_size());
4536 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4538 fib_prefix_t pfx_2001_1_2_s_128 = {
4540 .fp_proto = FIB_PROTOCOL_IP6,
4544 [0] = clib_host_to_net_u64(0x2001000000000001),
4545 [1] = clib_host_to_net_u64(0x0000000000000002),
4550 fib_prefix_t pfx_2001_1_3_s_128 = {
4552 .fp_proto = FIB_PROTOCOL_IP6,
4556 [0] = clib_host_to_net_u64(0x2001000000000001),
4557 [1] = clib_host_to_net_u64(0x0000000000000003),
4563 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
4566 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4568 &pfx_2001_1_2_s_128.fp_addr,
4569 tm->hw[0]->sw_if_index);
4570 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
4571 adj = adj_get(ai_01);
4572 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4573 "adj is incomplete");
4574 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4575 &adj->sub_type.nbr.next_hop)),
4576 "adj nbr next-hop ok");
4578 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4579 fib_test_build_rewrite(eth_addr));
4580 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4582 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4583 &adj->sub_type.nbr.next_hop)),
4584 "adj nbr next-hop ok");
4586 fib_table_entry_path_add(fib_index,
4587 &pfx_2001_1_2_s_128,
4589 FIB_ENTRY_FLAG_ATTACHED,
4591 &pfx_2001_1_2_s_128.fp_addr,
4592 tm->hw[0]->sw_if_index,
4596 FIB_ROUTE_PATH_FLAG_NONE);
4598 fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
4599 ai = fib_entry_get_adj(fei);
4600 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4604 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4606 &pfx_2001_1_3_s_128.fp_addr,
4607 tm->hw[0]->sw_if_index);
4608 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
4609 adj = adj_get(ai_02);
4610 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4611 "adj is incomplete");
4612 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4613 &adj->sub_type.nbr.next_hop)),
4614 "adj nbr next-hop ok");
4616 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4617 fib_test_build_rewrite(eth_addr));
4618 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4620 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4621 &adj->sub_type.nbr.next_hop)),
4622 "adj nbr next-hop ok");
4623 FIB_TEST((ai_01 != ai_02), "ADJs are different");
4625 fib_table_entry_path_add(fib_index,
4626 &pfx_2001_1_3_s_128,
4628 FIB_ENTRY_FLAG_ATTACHED,
4630 &pfx_2001_1_3_s_128.fp_addr,
4631 tm->hw[0]->sw_if_index,
4635 FIB_ROUTE_PATH_FLAG_NONE);
4637 fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
4638 ai = fib_entry_get_adj(fei);
4639 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4642 * +2 entries, +2 unshread path-lists.
4644 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4645 fib_path_list_db_size());
4646 FIB_TEST((PNPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
4647 fib_path_list_pool_size());
4648 FIB_TEST((ENPS+4 == fib_entry_pool_size()), "entry pool size is %d",
4649 fib_entry_pool_size());
4652 * Add a 2 routes via the first ADJ. ensure path-list sharing
4654 fib_prefix_t pfx_2001_a_s_64 = {
4656 .fp_proto = FIB_PROTOCOL_IP6,
4660 [0] = clib_host_to_net_u64(0x200100000000000a),
4661 [1] = clib_host_to_net_u64(0x0000000000000000),
4666 fib_prefix_t pfx_2001_b_s_64 = {
4668 .fp_proto = FIB_PROTOCOL_IP6,
4672 [0] = clib_host_to_net_u64(0x200100000000000b),
4673 [1] = clib_host_to_net_u64(0x0000000000000000),
4679 fib_table_entry_path_add(fib_index,
4682 FIB_ENTRY_FLAG_NONE,
4685 tm->hw[0]->sw_if_index,
4689 FIB_ROUTE_PATH_FLAG_NONE);
4690 fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64);
4691 ai = fib_entry_get_adj(fei);
4692 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4693 fib_table_entry_path_add(fib_index,
4696 FIB_ENTRY_FLAG_NONE,
4699 tm->hw[0]->sw_if_index,
4703 FIB_ROUTE_PATH_FLAG_NONE);
4704 fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64);
4705 ai = fib_entry_get_adj(fei);
4706 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4709 * +2 entries, +1 shared path-list.
4711 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4712 fib_path_list_db_size());
4713 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4714 fib_path_list_pool_size());
4715 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
4716 fib_entry_pool_size());
4719 * add a v4 prefix via a v6 next-hop
4721 fib_prefix_t pfx_1_1_1_1_s_32 = {
4723 .fp_proto = FIB_PROTOCOL_IP4,
4725 .ip4.as_u32 = 0x01010101,
4728 fei = fib_table_entry_path_add(0, // default table
4731 FIB_ENTRY_FLAG_NONE,
4734 tm->hw[0]->sw_if_index,
4738 FIB_ROUTE_PATH_FLAG_NONE);
4739 FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32),
4740 "1.1.1.1/32 o v6 route present");
4741 ai = fib_entry_get_adj(fei);
4743 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
4744 "1.1.1.1/32 via ARP-adj");
4745 FIB_TEST((adj->ia_link == VNET_LINK_IP4),
4746 "1.1.1.1/32 ADJ-adj is link type v4");
4747 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6),
4748 "1.1.1.1/32 ADJ-adj is NH proto v6");
4749 fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API);
4754 fib_prefix_t pfx_2001_c_s_64 = {
4756 .fp_proto = FIB_PROTOCOL_IP6,
4760 [0] = clib_host_to_net_u64(0x200100000000000c),
4761 [1] = clib_host_to_net_u64(0x0000000000000000),
4766 fib_table_entry_path_add(fib_index,
4769 FIB_ENTRY_FLAG_ATTACHED,
4772 tm->hw[0]->sw_if_index,
4776 FIB_ROUTE_PATH_FLAG_NONE);
4777 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4778 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present");
4779 ai = fib_entry_get_adj(fei);
4781 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN),
4782 "2001:0:0:c/64 attached resolves via glean");
4784 fib_table_entry_path_remove(fib_index,
4789 tm->hw[0]->sw_if_index,
4792 FIB_ROUTE_PATH_FLAG_NONE);
4793 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4794 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached route removed");
4797 * Shutdown the interface on which we have a connected and through
4798 * which the routes are reachable.
4799 * This will result in the connected, adj-fibs, and routes linking to drop
4800 * The local/for-us prefix continues to receive.
4802 clib_error_t * error;
4804 error = vnet_sw_interface_set_flags(vnet_get_main(),
4805 tm->hw[0]->sw_if_index,
4806 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4807 FIB_TEST((NULL == error), "Interface shutdown OK");
4809 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4810 dpo = fib_entry_contribute_ip_forwarding(fei);
4811 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4812 "2001::b/64 resolves via drop");
4814 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4815 dpo = fib_entry_contribute_ip_forwarding(fei);
4816 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4817 "2001::a/64 resolves via drop");
4818 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4819 dpo = fib_entry_contribute_ip_forwarding(fei);
4820 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4821 "2001:0:0:1::3/64 resolves via drop");
4822 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4823 dpo = fib_entry_contribute_ip_forwarding(fei);
4824 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4825 "2001:0:0:1::2/64 resolves via drop");
4826 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4827 dpo = fib_entry_contribute_ip_forwarding(fei);
4828 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4829 "2001:0:0:1::1/128 not drop");
4830 local_pfx.fp_len = 64;
4831 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4832 dpo = fib_entry_contribute_ip_forwarding(fei);
4833 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4834 "2001:0:0:1/64 resolves via drop");
4839 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4840 fib_path_list_db_size());
4841 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4842 fib_path_list_pool_size());
4843 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
4844 fib_entry_pool_size());
4847 * shutdown one of the other interfaces, then add a connected.
4848 * and swap one of the routes to it.
4850 error = vnet_sw_interface_set_flags(vnet_get_main(),
4851 tm->hw[1]->sw_if_index,
4852 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4853 FIB_TEST((NULL == error), "Interface 1 shutdown OK");
4855 fib_prefix_t connected_pfx = {
4857 .fp_proto = FIB_PROTOCOL_IP6,
4860 /* 2001:0:0:2::1/64 */
4862 [0] = clib_host_to_net_u64(0x2001000000000002),
4863 [1] = clib_host_to_net_u64(0x0000000000000001),
4868 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4869 FIB_SOURCE_INTERFACE,
4870 (FIB_ENTRY_FLAG_CONNECTED |
4871 FIB_ENTRY_FLAG_ATTACHED),
4874 tm->hw[1]->sw_if_index,
4878 FIB_ROUTE_PATH_FLAG_NONE);
4879 fei = fib_table_lookup_exact_match(fib_index, &connected_pfx);
4880 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4881 dpo = fib_entry_contribute_ip_forwarding(fei);
4882 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4883 FIB_TEST(!dpo_cmp(dpo, dpo_drop),
4884 "2001:0:0:2/64 not resolves via drop");
4886 connected_pfx.fp_len = 128;
4887 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4888 FIB_SOURCE_INTERFACE,
4889 (FIB_ENTRY_FLAG_CONNECTED |
4890 FIB_ENTRY_FLAG_LOCAL),
4893 tm->hw[0]->sw_if_index,
4894 ~0, // invalid fib index
4897 FIB_ROUTE_PATH_FLAG_NONE);
4898 fei = fib_table_lookup(fib_index, &connected_pfx);
4900 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4901 dpo = fib_entry_contribute_ip_forwarding(fei);
4902 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4903 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4904 "local interface adj is local");
4905 rd = receive_dpo_get(dpo->dpoi_index);
4906 FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr,
4908 "local interface adj is receive ok");
4911 * +2 entries, +2 unshared path-lists
4913 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4914 fib_path_list_db_size());
4915 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
4916 fib_path_list_pool_size());
4917 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
4918 fib_entry_pool_size());
4922 * bring the interface back up. we expected the routes to return
4923 * to normal forwarding.
4925 error = vnet_sw_interface_set_flags(vnet_get_main(),
4926 tm->hw[0]->sw_if_index,
4927 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4928 FIB_TEST((NULL == error), "Interface bring-up OK");
4929 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4930 ai = fib_entry_get_adj(fei);
4931 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4932 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4933 ai = fib_entry_get_adj(fei);
4934 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4935 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4936 ai = fib_entry_get_adj(fei);
4937 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4938 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4939 ai = fib_entry_get_adj(fei);
4940 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4941 local_pfx.fp_len = 64;
4942 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4943 ai = fib_entry_get_adj(fei);
4945 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4946 "attached interface adj is glean");
4949 * Same test as above, but this time the HW interface goes down
4951 error = vnet_hw_interface_set_flags(vnet_get_main(),
4952 tm->hw_if_indicies[0],
4953 ~VNET_HW_INTERFACE_FLAG_LINK_UP);
4954 FIB_TEST((NULL == error), "Interface shutdown OK");
4956 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4957 dpo = fib_entry_contribute_ip_forwarding(fei);
4958 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4959 "2001::b/64 resolves via drop");
4960 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4961 dpo = fib_entry_contribute_ip_forwarding(fei);
4962 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4963 "2001::a/64 resolves via drop");
4964 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4965 dpo = fib_entry_contribute_ip_forwarding(fei);
4966 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4967 "2001:0:0:1::3/128 resolves via drop");
4968 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4969 dpo = fib_entry_contribute_ip_forwarding(fei);
4970 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4971 "2001:0:0:1::2/128 resolves via drop");
4972 local_pfx.fp_len = 128;
4973 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4974 dpo = fib_entry_contribute_ip_forwarding(fei);
4975 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4976 "2001:0:0:1::1/128 not drop");
4977 local_pfx.fp_len = 64;
4978 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4979 dpo = fib_entry_contribute_ip_forwarding(fei);
4980 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4981 "2001:0:0:1/64 resolves via drop");
4983 error = vnet_hw_interface_set_flags(vnet_get_main(),
4984 tm->hw_if_indicies[0],
4985 VNET_HW_INTERFACE_FLAG_LINK_UP);
4986 FIB_TEST((NULL == error), "Interface bring-up OK");
4987 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4988 ai = fib_entry_get_adj(fei);
4989 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4990 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4991 ai = fib_entry_get_adj(fei);
4992 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4993 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4994 ai = fib_entry_get_adj(fei);
4995 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4996 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4997 ai = fib_entry_get_adj(fei);
4998 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4999 local_pfx.fp_len = 64;
5000 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5001 ai = fib_entry_get_adj(fei);
5003 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
5004 "attached interface adj is glean");
5007 * Delete the interface that the routes reolve through.
5008 * Again no routes are removed. They all point to drop.
5010 * This is considered an error case. The control plane should
5011 * not remove interfaces through which routes resolve, but
5012 * such things can happen. ALL affected routes will drop.
5014 vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]);
5016 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5017 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5018 "2001::b/64 resolves via drop");
5019 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5020 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5021 "2001::b/64 resolves via drop");
5022 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5023 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5024 "2001:0:0:1::3/64 resolves via drop");
5025 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5026 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5027 "2001:0:0:1::2/64 resolves via drop");
5028 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5029 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5030 "2001:0:0:1::1/128 is drop");
5031 local_pfx.fp_len = 64;
5032 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5033 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5034 "2001:0:0:1/64 resolves via drop");
5039 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
5040 fib_path_list_db_size());
5041 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
5042 fib_path_list_pool_size());
5043 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
5044 fib_entry_pool_size());
5047 * Add the interface back. routes stay unresolved.
5049 error = ethernet_register_interface(vnet_get_main(),
5050 test_interface_device_class.index,
5053 &tm->hw_if_indicies[0],
5054 /* flag change */ 0);
5056 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5057 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5058 "2001::b/64 resolves via drop");
5059 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5060 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5061 "2001::b/64 resolves via drop");
5062 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5063 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5064 "2001:0:0:1::3/64 resolves via drop");
5065 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5066 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5067 "2001:0:0:1::2/64 resolves via drop");
5068 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5069 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5070 "2001:0:0:1::1/128 is drop");
5071 local_pfx.fp_len = 64;
5072 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5073 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5074 "2001:0:0:1/64 resolves via drop");
5077 * CLEANUP ALL the routes
5079 fib_table_entry_delete(fib_index,
5082 fib_table_entry_delete(fib_index,
5085 fib_table_entry_delete(fib_index,
5088 fib_table_entry_delete(fib_index,
5089 &pfx_2001_1_3_s_128,
5091 fib_table_entry_delete(fib_index,
5092 &pfx_2001_1_2_s_128,
5094 local_pfx.fp_len = 64;
5095 fib_table_entry_delete(fib_index, &local_pfx,
5096 FIB_SOURCE_INTERFACE);
5097 local_pfx.fp_len = 128;
5098 fib_table_entry_special_remove(fib_index, &local_pfx,
5099 FIB_SOURCE_INTERFACE);
5100 connected_pfx.fp_len = 64;
5101 fib_table_entry_delete(fib_index, &connected_pfx,
5102 FIB_SOURCE_INTERFACE);
5103 connected_pfx.fp_len = 128;
5104 fib_table_entry_special_remove(fib_index, &connected_pfx,
5105 FIB_SOURCE_INTERFACE);
5107 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5108 fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)),
5109 "2001::a/64 removed");
5110 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5111 fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)),
5112 "2001::b/64 removed");
5113 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5114 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)),
5115 "2001:0:0:1::3/128 removed");
5116 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5117 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)),
5118 "2001:0:0:1::3/128 removed");
5119 local_pfx.fp_len = 64;
5120 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5121 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5122 "2001:0:0:1/64 removed");
5123 local_pfx.fp_len = 128;
5124 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5125 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5126 "2001:0:0:1::1/128 removed");
5127 connected_pfx.fp_len = 64;
5128 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5129 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5130 "2001:0:0:2/64 removed");
5131 connected_pfx.fp_len = 128;
5132 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5133 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5134 "2001:0:0:2::1/128 removed");
5137 * -8 entries. -7 path-lists (1 was shared).
5139 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5140 fib_path_list_db_size());
5141 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is%d",
5142 fib_path_list_pool_size());
5143 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
5144 fib_entry_pool_size());
5147 * now remove the VRF
5149 fib_table_unlock(fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
5151 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5152 fib_path_list_db_size());
5153 FIB_TEST((PNPS-2 == fib_path_list_pool_size()), "path list pool size is%d",
5154 fib_path_list_pool_size());
5155 FIB_TEST((ENPS-2 == fib_entry_pool_size()), "entry pool size is %d",
5156 fib_entry_pool_size());
5162 * return the interfaces to up state
5164 error = vnet_sw_interface_set_flags(vnet_get_main(),
5165 tm->hw[0]->sw_if_index,
5166 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5167 error = vnet_sw_interface_set_flags(vnet_get_main(),
5168 tm->hw[1]->sw_if_index,
5169 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5171 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5178 * Test Attached Exports
5183 const dpo_id_t *dpo, *dpo_drop;
5184 const u32 fib_index = 0;
5185 fib_node_index_t fei;
5192 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5196 * add interface routes. We'll assume this works. It's more rigorously
5199 fib_prefix_t local_pfx = {
5201 .fp_proto = FIB_PROTOCOL_IP4,
5205 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5210 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
5211 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
5213 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
5215 fib_table_entry_update_one_path(fib_index, &local_pfx,
5216 FIB_SOURCE_INTERFACE,
5217 (FIB_ENTRY_FLAG_CONNECTED |
5218 FIB_ENTRY_FLAG_ATTACHED),
5221 tm->hw[0]->sw_if_index,
5225 FIB_ROUTE_PATH_FLAG_NONE);
5226 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5227 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5228 "attached interface route present");
5230 local_pfx.fp_len = 32;
5231 fib_table_entry_update_one_path(fib_index, &local_pfx,
5232 FIB_SOURCE_INTERFACE,
5233 (FIB_ENTRY_FLAG_CONNECTED |
5234 FIB_ENTRY_FLAG_LOCAL),
5237 tm->hw[0]->sw_if_index,
5238 ~0, // invalid fib index
5241 FIB_ROUTE_PATH_FLAG_NONE);
5242 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5244 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5245 "local interface route present");
5248 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
5250 fib_prefix_t pfx_10_10_10_1_s_32 = {
5252 .fp_proto = FIB_PROTOCOL_IP4,
5255 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5258 fib_node_index_t ai;
5260 fib_table_entry_path_add(fib_index,
5261 &pfx_10_10_10_1_s_32,
5263 FIB_ENTRY_FLAG_ATTACHED,
5265 &pfx_10_10_10_1_s_32.fp_addr,
5266 tm->hw[0]->sw_if_index,
5267 ~0, // invalid fib index
5270 FIB_ROUTE_PATH_FLAG_NONE);
5272 fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
5273 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
5274 ai = fib_entry_get_adj(fei);
5277 * create another FIB table into which routes will be imported
5279 u32 import_fib_index1;
5281 import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4,
5286 * Add an attached route in the import FIB
5288 local_pfx.fp_len = 24;
5289 fib_table_entry_update_one_path(import_fib_index1,
5292 FIB_ENTRY_FLAG_NONE,
5295 tm->hw[0]->sw_if_index,
5296 ~0, // invalid fib index
5299 FIB_ROUTE_PATH_FLAG_NONE);
5300 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5301 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5304 * check for the presence of the adj-fibs in the import table
5306 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5307 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5308 FIB_TEST((ai == fib_entry_get_adj(fei)),
5309 "adj-fib1 Import uses same adj as export");
5312 * check for the presence of the local in the import table
5314 local_pfx.fp_len = 32;
5315 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5316 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5319 * Add another adj-fin in the export table. Expect this
5320 * to get magically exported;
5322 fib_prefix_t pfx_10_10_10_2_s_32 = {
5324 .fp_proto = FIB_PROTOCOL_IP4,
5327 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5331 fib_table_entry_path_add(fib_index,
5332 &pfx_10_10_10_2_s_32,
5334 FIB_ENTRY_FLAG_ATTACHED,
5336 &pfx_10_10_10_2_s_32.fp_addr,
5337 tm->hw[0]->sw_if_index,
5338 ~0, // invalid fib index
5341 FIB_ROUTE_PATH_FLAG_NONE);
5342 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5343 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
5344 ai = fib_entry_get_adj(fei);
5346 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5347 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5348 FIB_TEST((ai == fib_entry_get_adj(fei)),
5349 "Import uses same adj as export");
5350 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(fei)),
5351 "ADJ-fib2 imported flags %d",
5352 fib_entry_get_flags(fei));
5355 * create a 2nd FIB table into which routes will be imported
5357 u32 import_fib_index2;
5359 import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12,
5363 * Add an attached route in the import FIB
5365 local_pfx.fp_len = 24;
5366 fib_table_entry_update_one_path(import_fib_index2,
5369 FIB_ENTRY_FLAG_NONE,
5372 tm->hw[0]->sw_if_index,
5373 ~0, // invalid fib index
5376 FIB_ROUTE_PATH_FLAG_NONE);
5377 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5378 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5381 * check for the presence of all the adj-fibs and local in the import table
5383 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5384 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5385 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5386 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5387 local_pfx.fp_len = 32;
5388 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5389 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5392 * add a 3rd adj-fib. expect it to be exported to both tables.
5394 fib_prefix_t pfx_10_10_10_3_s_32 = {
5396 .fp_proto = FIB_PROTOCOL_IP4,
5399 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
5403 fib_table_entry_path_add(fib_index,
5404 &pfx_10_10_10_3_s_32,
5406 FIB_ENTRY_FLAG_ATTACHED,
5408 &pfx_10_10_10_3_s_32.fp_addr,
5409 tm->hw[0]->sw_if_index,
5410 ~0, // invalid fib index
5413 FIB_ROUTE_PATH_FLAG_NONE);
5414 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5415 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
5416 ai = fib_entry_get_adj(fei);
5418 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5419 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1");
5420 FIB_TEST((ai == fib_entry_get_adj(fei)),
5421 "Import uses same adj as export");
5422 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5423 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2");
5424 FIB_TEST((ai == fib_entry_get_adj(fei)),
5425 "Import uses same adj as export");
5428 * remove the 3rd adj fib. we expect it to be removed from both FIBs
5430 fib_table_entry_delete(fib_index,
5431 &pfx_10_10_10_3_s_32,
5434 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5435 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved");
5437 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5438 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1");
5440 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5441 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2");
5444 * remove the attached route from the 2nd FIB. expect the imported
5445 * entires to be removed
5447 local_pfx.fp_len = 24;
5448 fib_table_entry_delete(import_fib_index2,
5451 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5452 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed");
5454 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5455 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2");
5456 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5457 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2");
5458 local_pfx.fp_len = 32;
5459 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5460 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2");
5462 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5463 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1");
5464 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5465 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1");
5466 local_pfx.fp_len = 32;
5467 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5468 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1");
5471 * modify the route in FIB1 so it is no longer attached. expect the imported
5472 * entires to be removed
5474 local_pfx.fp_len = 24;
5475 fib_table_entry_update_one_path(import_fib_index1,
5478 FIB_ENTRY_FLAG_NONE,
5480 &pfx_10_10_10_2_s_32.fp_addr,
5481 tm->hw[0]->sw_if_index,
5482 ~0, // invalid fib index
5485 FIB_ROUTE_PATH_FLAG_NONE);
5486 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5487 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5488 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5489 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5490 local_pfx.fp_len = 32;
5491 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5492 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5495 * modify it back to attached. expect the adj-fibs back
5497 local_pfx.fp_len = 24;
5498 fib_table_entry_update_one_path(import_fib_index1,
5501 FIB_ENTRY_FLAG_NONE,
5504 tm->hw[0]->sw_if_index,
5505 ~0, // invalid fib index
5508 FIB_ROUTE_PATH_FLAG_NONE);
5509 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5510 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1");
5511 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5512 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1");
5513 local_pfx.fp_len = 32;
5514 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5515 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1");
5518 * add a covering attached next-hop for the interface address, so we have
5519 * a valid adj to find when we check the forwarding tables
5521 fib_prefix_t pfx_10_0_0_0_s_8 = {
5523 .fp_proto = FIB_PROTOCOL_IP4,
5526 .ip4.as_u32 = clib_host_to_net_u32(0x0a000000),
5530 fei = fib_table_entry_update_one_path(fib_index,
5533 FIB_ENTRY_FLAG_NONE,
5535 &pfx_10_10_10_3_s_32.fp_addr,
5536 tm->hw[0]->sw_if_index,
5537 ~0, // invalid fib index
5540 FIB_ROUTE_PATH_FLAG_NONE);
5541 dpo = fib_entry_contribute_ip_forwarding(fei);
5544 * remove the route in the export fib. expect the adj-fibs to be removed
5546 local_pfx.fp_len = 24;
5547 fib_table_entry_delete(fib_index,
5549 FIB_SOURCE_INTERFACE);
5551 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5552 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1");
5553 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5554 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5555 local_pfx.fp_len = 32;
5556 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5557 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5560 * the adj-fibs in the export VRF are present in the FIB table,
5561 * but not installed in forwarding, since they have no attached cover.
5562 * Consequently a lookup in the MTRIE gives the adj for the covering
5565 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5566 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5569 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5570 FIB_TEST(lbi == dpo->dpoi_index,
5571 "10.10.10.1 forwards on \n%U not \n%U",
5572 format_load_balance, lbi, 0,
5573 format_dpo_id, dpo, 0);
5574 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5575 FIB_TEST(lbi == dpo->dpoi_index,
5576 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5577 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4);
5578 FIB_TEST(lbi == dpo->dpoi_index,
5579 "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0);
5582 * add the export prefix back, but not as attached.
5583 * No adj-fibs in export nor import tables
5585 local_pfx.fp_len = 24;
5586 fei = fib_table_entry_update_one_path(fib_index,
5589 FIB_ENTRY_FLAG_NONE,
5591 &pfx_10_10_10_1_s_32.fp_addr,
5592 tm->hw[0]->sw_if_index,
5593 ~0, // invalid fib index
5596 FIB_ROUTE_PATH_FLAG_NONE);
5597 dpo = fib_entry_contribute_ip_forwarding(fei);
5599 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5600 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export");
5601 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5602 FIB_TEST(lbi == dpo->dpoi_index,
5603 "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0);
5604 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5605 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5606 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5607 FIB_TEST(lbi == dpo->dpoi_index,
5608 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5610 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5611 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5612 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5613 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5614 local_pfx.fp_len = 32;
5615 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5616 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5619 * modify the export prefix so it is attached. expect all covereds to return
5621 local_pfx.fp_len = 24;
5622 fib_table_entry_update_one_path(fib_index,
5625 FIB_ENTRY_FLAG_NONE,
5628 tm->hw[0]->sw_if_index,
5629 ~0, // invalid fib index
5632 FIB_ROUTE_PATH_FLAG_NONE);
5634 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5635 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5636 dpo = fib_entry_contribute_ip_forwarding(fei);
5637 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5638 "Adj-fib1 is not drop in export");
5639 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5640 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5641 local_pfx.fp_len = 32;
5642 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5643 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5644 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5645 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5646 dpo = fib_entry_contribute_ip_forwarding(fei);
5647 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5648 "Adj-fib1 is not drop in export");
5649 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5650 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5651 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5652 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5653 local_pfx.fp_len = 32;
5654 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5655 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5658 * modify the export prefix so connected. no change.
5660 local_pfx.fp_len = 24;
5661 fib_table_entry_update_one_path(fib_index, &local_pfx,
5662 FIB_SOURCE_INTERFACE,
5663 (FIB_ENTRY_FLAG_CONNECTED |
5664 FIB_ENTRY_FLAG_ATTACHED),
5667 tm->hw[0]->sw_if_index,
5671 FIB_ROUTE_PATH_FLAG_NONE);
5673 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5674 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5675 dpo = fib_entry_contribute_ip_forwarding(fei);
5676 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5677 "Adj-fib1 is not drop in export");
5678 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5679 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5680 local_pfx.fp_len = 32;
5681 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5682 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5683 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5684 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5685 dpo = fib_entry_contribute_ip_forwarding(fei);
5686 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5687 "Adj-fib1 is not drop in export");
5688 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5689 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5690 local_pfx.fp_len = 32;
5691 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5692 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5697 fib_table_entry_delete(fib_index,
5700 fib_table_entry_delete(fib_index,
5701 &pfx_10_10_10_1_s_32,
5703 fib_table_entry_delete(fib_index,
5704 &pfx_10_10_10_2_s_32,
5706 local_pfx.fp_len = 32;
5707 fib_table_entry_delete(fib_index,
5709 FIB_SOURCE_INTERFACE);
5710 local_pfx.fp_len = 24;
5711 fib_table_entry_delete(fib_index,
5714 fib_table_entry_delete(fib_index,
5716 FIB_SOURCE_INTERFACE);
5717 local_pfx.fp_len = 24;
5718 fib_table_entry_delete(import_fib_index1,
5722 fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
5723 fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
5725 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5732 * Test Path Preference
5735 fib_test_pref (void)
5737 test_main_t *tm = &test_main;
5739 const fib_prefix_t pfx_1_1_1_1_s_32 = {
5741 .fp_proto = FIB_PROTOCOL_IP4,
5744 .as_u32 = clib_host_to_net_u32(0x01010101),
5750 * 2 high, 2 medium and 2 low preference non-recursive paths
5752 fib_route_path_t nr_path_hi_1 = {
5753 .frp_proto = DPO_PROTO_IP4,
5754 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5755 .frp_fib_index = ~0,
5757 .frp_preference = 0,
5758 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5760 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5763 fib_route_path_t nr_path_hi_2 = {
5764 .frp_proto = DPO_PROTO_IP4,
5765 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5766 .frp_fib_index = ~0,
5768 .frp_preference = 0,
5769 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5771 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5774 fib_route_path_t nr_path_med_1 = {
5775 .frp_proto = DPO_PROTO_IP4,
5776 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5777 .frp_fib_index = ~0,
5779 .frp_preference = 1,
5780 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5782 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5785 fib_route_path_t nr_path_med_2 = {
5786 .frp_proto = DPO_PROTO_IP4,
5787 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5788 .frp_fib_index = ~0,
5790 .frp_preference = 1,
5791 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5793 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5796 fib_route_path_t nr_path_low_1 = {
5797 .frp_proto = DPO_PROTO_IP4,
5798 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5799 .frp_fib_index = ~0,
5801 .frp_preference = 2,
5802 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5804 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b01),
5807 fib_route_path_t nr_path_low_2 = {
5808 .frp_proto = DPO_PROTO_IP4,
5809 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5810 .frp_fib_index = ~0,
5812 .frp_preference = 2,
5813 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5815 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b02),
5818 fib_route_path_t *nr_paths = NULL;
5820 vec_add1(nr_paths, nr_path_hi_1);
5821 vec_add1(nr_paths, nr_path_hi_2);
5822 vec_add1(nr_paths, nr_path_med_1);
5823 vec_add1(nr_paths, nr_path_med_2);
5824 vec_add1(nr_paths, nr_path_low_1);
5825 vec_add1(nr_paths, nr_path_low_2);
5827 adj_index_t ai_hi_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5829 &nr_path_hi_1.frp_addr,
5830 nr_path_hi_1.frp_sw_if_index);
5831 adj_index_t ai_hi_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5833 &nr_path_hi_2.frp_addr,
5834 nr_path_hi_2.frp_sw_if_index);
5835 adj_index_t ai_med_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5837 &nr_path_med_1.frp_addr,
5838 nr_path_med_1.frp_sw_if_index);
5839 adj_index_t ai_med_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5841 &nr_path_med_2.frp_addr,
5842 nr_path_med_2.frp_sw_if_index);
5843 adj_index_t ai_low_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5845 &nr_path_low_1.frp_addr,
5846 nr_path_low_1.frp_sw_if_index);
5847 adj_index_t ai_low_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5849 &nr_path_low_2.frp_addr,
5850 nr_path_low_2.frp_sw_if_index);
5852 fib_test_lb_bucket_t ip_hi_1 = {
5858 fib_test_lb_bucket_t ip_hi_2 = {
5864 fib_test_lb_bucket_t ip_med_1 = {
5870 fib_test_lb_bucket_t ip_med_2 = {
5876 fib_test_lb_bucket_t ip_low_1 = {
5882 fib_test_lb_bucket_t ip_low_2 = {
5889 fib_node_index_t fei;
5891 fei = fib_table_entry_path_add2(0,
5894 FIB_ENTRY_FLAG_NONE,
5897 FIB_TEST(fib_test_validate_entry(fei,
5898 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5902 "1.1.1.1/32 via high preference paths");
5905 * bring down the interface on which the high preference path lie
5907 vnet_sw_interface_set_flags(vnet_get_main(),
5908 tm->hw[0]->sw_if_index,
5911 FIB_TEST(fib_test_validate_entry(fei,
5912 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5916 "1.1.1.1/32 via medium preference paths");
5919 * bring down the interface on which the medium preference path lie
5921 vnet_sw_interface_set_flags(vnet_get_main(),
5922 tm->hw[1]->sw_if_index,
5925 FIB_TEST(fib_test_validate_entry(fei,
5926 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5930 "1.1.1.1/32 via low preference paths");
5933 * bring up the interface on which the high preference path lie
5935 vnet_sw_interface_set_flags(vnet_get_main(),
5936 tm->hw[0]->sw_if_index,
5937 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5939 FIB_TEST(fib_test_validate_entry(fei,
5940 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5944 "1.1.1.1/32 via high preference paths");
5947 * bring up the interface on which the medium preference path lie
5949 vnet_sw_interface_set_flags(vnet_get_main(),
5950 tm->hw[1]->sw_if_index,
5951 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5953 FIB_TEST(fib_test_validate_entry(fei,
5954 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5958 "1.1.1.1/32 via high preference paths");
5960 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
5961 fib_entry_contribute_forwarding(fei,
5962 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5966 * 3 recursive paths of different preference
5968 const fib_prefix_t pfx_1_1_1_2_s_32 = {
5970 .fp_proto = FIB_PROTOCOL_IP4,
5973 .as_u32 = clib_host_to_net_u32(0x01010102),
5977 const fib_prefix_t pfx_1_1_1_3_s_32 = {
5979 .fp_proto = FIB_PROTOCOL_IP4,
5982 .as_u32 = clib_host_to_net_u32(0x01010103),
5986 fei = fib_table_entry_path_add2(0,
5989 FIB_ENTRY_FLAG_NONE,
5991 dpo_id_t ip_1_1_1_2 = DPO_INVALID;
5992 fib_entry_contribute_forwarding(fei,
5993 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5995 fei = fib_table_entry_path_add2(0,
5998 FIB_ENTRY_FLAG_NONE,
6000 dpo_id_t ip_1_1_1_3 = DPO_INVALID;
6001 fib_entry_contribute_forwarding(fei,
6002 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6005 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
6008 .lb = ip_1_1_1_1.dpoi_index,
6011 fib_test_lb_bucket_t ip_o_1_1_1_2 = {
6014 .lb = ip_1_1_1_2.dpoi_index,
6017 fib_test_lb_bucket_t ip_o_1_1_1_3 = {
6020 .lb = ip_1_1_1_3.dpoi_index,
6023 fib_route_path_t r_path_hi = {
6024 .frp_proto = DPO_PROTO_IP4,
6025 .frp_sw_if_index = ~0,
6028 .frp_preference = 0,
6029 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
6030 .frp_addr = pfx_1_1_1_1_s_32.fp_addr,
6032 fib_route_path_t r_path_med = {
6033 .frp_proto = DPO_PROTO_IP4,
6034 .frp_sw_if_index = ~0,
6037 .frp_preference = 10,
6038 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
6039 .frp_addr = pfx_1_1_1_2_s_32.fp_addr,
6041 fib_route_path_t r_path_low = {
6042 .frp_proto = DPO_PROTO_IP4,
6043 .frp_sw_if_index = ~0,
6046 .frp_preference = 255,
6047 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
6048 .frp_addr = pfx_1_1_1_3_s_32.fp_addr,
6050 fib_route_path_t *r_paths = NULL;
6052 vec_add1(r_paths, r_path_hi);
6053 vec_add1(r_paths, r_path_low);
6054 vec_add1(r_paths, r_path_med);
6057 * add many recursive so we get the LB MAp created
6060 fib_prefix_t pfx_r[N_PFXS];
6061 unsigned int n_pfxs;
6062 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6064 pfx_r[n_pfxs].fp_len = 32;
6065 pfx_r[n_pfxs].fp_proto = FIB_PROTOCOL_IP4;
6066 pfx_r[n_pfxs].fp_addr.ip4.as_u32 =
6067 clib_host_to_net_u32(0x02000000 + n_pfxs);
6069 fei = fib_table_entry_path_add2(0,
6072 FIB_ENTRY_FLAG_NONE,
6075 FIB_TEST(fib_test_validate_entry(fei,
6076 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6079 "recursive via high preference paths");
6082 * withdraw hig pref resolving entry
6084 fib_table_entry_delete(0,
6088 /* suspend so the update walk kicks int */
6089 vlib_process_suspend(vlib_get_main(), 1e-5);
6091 FIB_TEST(fib_test_validate_entry(fei,
6092 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6095 "recursive via medium preference paths");
6098 * withdraw medium pref resolving entry
6100 fib_table_entry_delete(0,
6104 /* suspend so the update walk kicks int */
6105 vlib_process_suspend(vlib_get_main(), 1e-5);
6107 FIB_TEST(fib_test_validate_entry(fei,
6108 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6111 "recursive via low preference paths");
6114 * add back paths for next iteration
6116 fei = fib_table_entry_update(0,
6119 FIB_ENTRY_FLAG_NONE,
6121 fei = fib_table_entry_update(0,
6124 FIB_ENTRY_FLAG_NONE,
6127 /* suspend so the update walk kicks int */
6128 vlib_process_suspend(vlib_get_main(), 1e-5);
6130 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6131 FIB_TEST(fib_test_validate_entry(fei,
6132 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6135 "recursive via high preference paths");
6139 fib_table_entry_delete(0,
6143 /* suspend so the update walk kicks int */
6144 vlib_process_suspend(vlib_get_main(), 1e-5);
6146 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6148 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6150 FIB_TEST(fib_test_validate_entry(fei,
6151 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6154 "recursive via medium preference paths");
6156 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6158 fib_table_entry_delete(0,
6166 fib_table_entry_delete(0,
6169 fib_table_entry_delete(0,
6173 dpo_reset(&ip_1_1_1_1);
6174 dpo_reset(&ip_1_1_1_2);
6175 dpo_reset(&ip_1_1_1_3);
6176 adj_unlock(ai_low_2);
6177 adj_unlock(ai_low_1);
6178 adj_unlock(ai_med_2);
6179 adj_unlock(ai_med_1);
6180 adj_unlock(ai_hi_2);
6181 adj_unlock(ai_hi_1);
6186 * Test the recursive route route handling for GRE tunnels
6189 fib_test_label (void)
6191 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;
6192 const u32 fib_index = 0;
6197 lb_count = pool_elts(load_balance_pool);
6202 * add interface routes. We'll assume this works. It's more rigorously
6205 fib_prefix_t local0_pfx = {
6207 .fp_proto = FIB_PROTOCOL_IP4,
6211 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
6216 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6219 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
6220 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
6222 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6223 FIB_SOURCE_INTERFACE,
6224 (FIB_ENTRY_FLAG_CONNECTED |
6225 FIB_ENTRY_FLAG_ATTACHED),
6228 tm->hw[0]->sw_if_index,
6232 FIB_ROUTE_PATH_FLAG_NONE);
6233 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6234 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6235 "attached interface route present");
6237 local0_pfx.fp_len = 32;
6238 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6239 FIB_SOURCE_INTERFACE,
6240 (FIB_ENTRY_FLAG_CONNECTED |
6241 FIB_ENTRY_FLAG_LOCAL),
6244 tm->hw[0]->sw_if_index,
6245 ~0, // invalid fib index
6248 FIB_ROUTE_PATH_FLAG_NONE);
6249 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6251 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6252 "local interface route present");
6254 fib_prefix_t local1_pfx = {
6256 .fp_proto = FIB_PROTOCOL_IP4,
6260 .as_u32 = clib_host_to_net_u32(0x0a0a0b0a),
6265 vec_validate(im->fib_index_by_sw_if_index, tm->hw[1]->sw_if_index);
6266 im->fib_index_by_sw_if_index[tm->hw[1]->sw_if_index] = fib_index;
6268 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6269 FIB_SOURCE_INTERFACE,
6270 (FIB_ENTRY_FLAG_CONNECTED |
6271 FIB_ENTRY_FLAG_ATTACHED),
6274 tm->hw[1]->sw_if_index,
6278 FIB_ROUTE_PATH_FLAG_NONE);
6279 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6280 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6281 "attached interface route present");
6283 local1_pfx.fp_len = 32;
6284 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6285 FIB_SOURCE_INTERFACE,
6286 (FIB_ENTRY_FLAG_CONNECTED |
6287 FIB_ENTRY_FLAG_LOCAL),
6290 tm->hw[1]->sw_if_index,
6291 ~0, // invalid fib index
6294 FIB_ROUTE_PATH_FLAG_NONE);
6295 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6297 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6298 "local interface route present");
6300 ip46_address_t nh_10_10_10_1 = {
6302 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
6305 ip46_address_t nh_10_10_11_1 = {
6307 .as_u32 = clib_host_to_net_u32(0x0a0a0b01),
6310 ip46_address_t nh_10_10_11_2 = {
6312 .as_u32 = clib_host_to_net_u32(0x0a0a0b02),
6316 ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6319 tm->hw[1]->sw_if_index);
6320 ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6323 tm->hw[1]->sw_if_index);
6324 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6327 tm->hw[0]->sw_if_index);
6328 ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6331 tm->hw[1]->sw_if_index);
6332 ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6335 tm->hw[1]->sw_if_index);
6338 * Add an etry with one path with a real out-going label
6340 fib_prefix_t pfx_1_1_1_1_s_32 = {
6342 .fp_proto = FIB_PROTOCOL_IP4,
6344 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
6347 fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = {
6348 .type = FT_LB_LABEL_O_ADJ,
6350 .adj = ai_mpls_10_10_10_1,
6355 fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = {
6356 .type = FT_LB_LABEL_O_ADJ,
6358 .adj = ai_mpls_10_10_10_1,
6360 .eos = MPLS_NON_EOS,
6363 fib_mpls_label_t *l99 = NULL, fml99 = {
6366 vec_add1(l99, fml99);
6368 fib_table_entry_update_one_path(fib_index,
6371 FIB_ENTRY_FLAG_NONE,
6374 tm->hw[0]->sw_if_index,
6375 ~0, // invalid fib index
6378 FIB_ROUTE_PATH_FLAG_NONE);
6380 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6381 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created");
6383 FIB_TEST(fib_test_validate_entry(fei,
6384 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6386 &l99_eos_o_10_10_10_1),
6387 "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1");
6390 * add a path with an implicit NULL label
6392 fib_test_lb_bucket_t a_o_10_10_11_1 = {
6395 .adj = ai_v4_10_10_11_1,
6398 fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = {
6401 .adj = ai_mpls_10_10_11_1,
6404 fib_mpls_label_t *l_imp_null = NULL, fml_imp_null = {
6405 .fml_value = MPLS_IETF_IMPLICIT_NULL_LABEL,
6407 vec_add1(l_imp_null, fml_imp_null);
6409 fei = fib_table_entry_path_add(fib_index,
6412 FIB_ENTRY_FLAG_NONE,
6415 tm->hw[1]->sw_if_index,
6416 ~0, // invalid fib index
6419 FIB_ROUTE_PATH_FLAG_NONE);
6421 FIB_TEST(fib_test_validate_entry(fei,
6422 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6424 &l99_eos_o_10_10_10_1,
6426 "1.1.1.1/32 LB 2 buckets via: "
6427 "label 99 over 10.10.10.1, "
6428 "adj over 10.10.11.1");
6431 * assign the route a local label
6433 fib_table_entry_local_label_add(fib_index,
6437 fib_prefix_t pfx_24001_eos = {
6438 .fp_proto = FIB_PROTOCOL_MPLS,
6442 fib_prefix_t pfx_24001_neos = {
6443 .fp_proto = FIB_PROTOCOL_MPLS,
6445 .fp_eos = MPLS_NON_EOS,
6447 fib_test_lb_bucket_t disp_o_10_10_11_1 = {
6448 .type = FT_LB_MPLS_DISP_PIPE_O_ADJ,
6450 .adj = ai_v4_10_10_11_1,
6455 * The EOS entry should link to both the paths,
6456 * and use an ip adj for the imp-null
6457 * The NON-EOS entry should link to both the paths,
6458 * and use an mpls adj for the imp-null
6460 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6462 FIB_TEST(fib_test_validate_entry(fei,
6463 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6465 &l99_eos_o_10_10_10_1,
6466 &disp_o_10_10_11_1),
6467 "24001/eos LB 2 buckets via: "
6468 "label 99 over 10.10.10.1, "
6469 "mpls disp adj over 10.10.11.1");
6472 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6474 FIB_TEST(fib_test_validate_entry(fei,
6475 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6477 &l99_neos_o_10_10_10_1,
6478 &a_mpls_o_10_10_11_1),
6479 "24001/neos LB 1 bucket via: "
6480 "label 99 over 10.10.10.1 ",
6481 "mpls-adj via 10.10.11.1");
6484 * add an unlabelled path, this is excluded from the neos chains,
6486 fib_test_lb_bucket_t adj_o_10_10_11_2 = {
6489 .adj = ai_v4_10_10_11_2,
6492 fib_test_lb_bucket_t disp_o_10_10_11_2 = {
6493 .type = FT_LB_MPLS_DISP_PIPE_O_ADJ,
6495 .adj = ai_v4_10_10_11_2,
6500 fei = fib_table_entry_path_add(fib_index,
6503 FIB_ENTRY_FLAG_NONE,
6506 tm->hw[1]->sw_if_index,
6507 ~0, // invalid fib index
6510 FIB_ROUTE_PATH_FLAG_NONE);
6512 FIB_TEST(fib_test_validate_entry(fei,
6513 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6514 16, // 3 choices spread over 16 buckets
6515 &l99_eos_o_10_10_10_1,
6516 &l99_eos_o_10_10_10_1,
6517 &l99_eos_o_10_10_10_1,
6518 &l99_eos_o_10_10_10_1,
6519 &l99_eos_o_10_10_10_1,
6520 &l99_eos_o_10_10_10_1,
6531 "1.1.1.1/32 LB 16 buckets via: "
6532 "label 99 over 10.10.10.1, "
6533 "adj over 10.10.11.1",
6534 "adj over 10.10.11.2");
6537 * get and lock a reference to the non-eos of the via entry 1.1.1.1/32
6539 dpo_id_t non_eos_1_1_1_1 = DPO_INVALID;
6540 fib_entry_contribute_forwarding(fei,
6541 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6545 * n-eos has only the 2 labelled paths
6547 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6550 FIB_TEST(fib_test_validate_entry(fei,
6551 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6553 &l99_neos_o_10_10_10_1,
6554 &a_mpls_o_10_10_11_1),
6555 "24001/neos LB 2 buckets via: "
6556 "label 99 over 10.10.10.1, "
6557 "adj-mpls over 10.10.11.2");
6560 * A labelled recursive
6562 fib_prefix_t pfx_2_2_2_2_s_32 = {
6564 .fp_proto = FIB_PROTOCOL_IP4,
6566 .ip4.as_u32 = clib_host_to_net_u32(0x02020202),
6569 fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = {
6570 .type = FT_LB_LABEL_O_LB,
6572 .lb = non_eos_1_1_1_1.dpoi_index,
6575 .mode = FIB_MPLS_LSP_MODE_UNIFORM,
6578 fib_mpls_label_t *l1600 = NULL, fml1600 = {
6580 .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM,
6582 vec_add1(l1600, fml1600);
6584 fei = fib_table_entry_update_one_path(fib_index,
6587 FIB_ENTRY_FLAG_NONE,
6589 &pfx_1_1_1_1_s_32.fp_addr,
6594 FIB_ROUTE_PATH_FLAG_NONE);
6596 FIB_TEST(fib_test_validate_entry(fei,
6597 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6599 &l1600_eos_o_1_1_1_1),
6600 "2.2.2.2.2/32 LB 1 buckets via: "
6601 "label 1600 over 1.1.1.1");
6603 dpo_id_t dpo_44 = DPO_INVALID;
6606 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
6607 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
6609 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
6610 "uRPF check for 2.2.2.2/32 on %d OK",
6611 tm->hw[0]->sw_if_index);
6612 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
6613 "uRPF check for 2.2.2.2/32 on %d OK",
6614 tm->hw[1]->sw_if_index);
6615 FIB_TEST(!fib_urpf_check(urpfi, 99),
6616 "uRPF check for 2.2.2.2/32 on 99 not-OK",
6619 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44);
6620 FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index),
6621 "Shared uRPF on IP and non-EOS chain");
6626 * we are holding a lock on the non-eos LB of the via-entry.
6627 * do a PIC-core failover by shutting the link of the via-entry.
6629 * shut down the link with the valid label
6631 vnet_sw_interface_set_flags(vnet_get_main(),
6632 tm->hw[0]->sw_if_index,
6635 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6636 FIB_TEST(fib_test_validate_entry(fei,
6637 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6641 "1.1.1.1/32 LB 2 buckets via: "
6642 "adj over 10.10.11.1, ",
6643 "adj-v4 over 10.10.11.2");
6645 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6647 FIB_TEST(fib_test_validate_entry(fei,
6648 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6651 &disp_o_10_10_11_2),
6652 "24001/eos LB 2 buckets via: "
6653 "mpls-disp adj over 10.10.11.1, ",
6654 "mpls-disp adj-v4 over 10.10.11.2");
6656 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6658 FIB_TEST(fib_test_validate_entry(fei,
6659 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6661 &a_mpls_o_10_10_11_1),
6662 "24001/neos LB 1 buckets via: "
6663 "adj-mpls over 10.10.11.2");
6666 * test that the pre-failover load-balance has been in-place
6669 dpo_id_t current = DPO_INVALID;
6670 fib_entry_contribute_forwarding(fei,
6671 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6674 FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1,
6676 "PIC-core LB inplace modified %U %U",
6677 format_dpo_id, &non_eos_1_1_1_1, 0,
6678 format_dpo_id, ¤t, 0);
6680 dpo_reset(&non_eos_1_1_1_1);
6681 dpo_reset(¤t);
6684 * no-shut the link with the valid label
6686 vnet_sw_interface_set_flags(vnet_get_main(),
6687 tm->hw[0]->sw_if_index,
6688 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6690 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6691 FIB_TEST(fib_test_validate_entry(fei,
6692 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6693 16, // 3 choices spread over 16 buckets
6694 &l99_eos_o_10_10_10_1,
6695 &l99_eos_o_10_10_10_1,
6696 &l99_eos_o_10_10_10_1,
6697 &l99_eos_o_10_10_10_1,
6698 &l99_eos_o_10_10_10_1,
6699 &l99_eos_o_10_10_10_1,
6710 "1.1.1.1/32 LB 16 buckets via: "
6711 "label 99 over 10.10.10.1, "
6712 "adj over 10.10.11.1",
6713 "adj-v4 over 10.10.11.2");
6716 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6718 FIB_TEST(fib_test_validate_entry(fei,
6719 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6720 16, // 3 choices spread over 16 buckets
6721 &l99_eos_o_10_10_10_1,
6722 &l99_eos_o_10_10_10_1,
6723 &l99_eos_o_10_10_10_1,
6724 &l99_eos_o_10_10_10_1,
6725 &l99_eos_o_10_10_10_1,
6726 &l99_eos_o_10_10_10_1,
6736 &disp_o_10_10_11_2),
6737 "24001/eos LB 16 buckets via: "
6738 "label 99 over 10.10.10.1, "
6739 "MPLS disp adj over 10.10.11.1",
6740 "MPLS disp adj-v4 over 10.10.11.2");
6742 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6744 FIB_TEST(fib_test_validate_entry(fei,
6745 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6747 &l99_neos_o_10_10_10_1,
6748 &a_mpls_o_10_10_11_1),
6749 "24001/neos LB 2 buckets via: "
6750 "label 99 over 10.10.10.1, "
6751 "adj-mpls over 10.10.11.2");
6754 * remove the first path with the valid label
6756 fib_table_entry_path_remove(fib_index,
6761 tm->hw[0]->sw_if_index,
6762 ~0, // invalid fib index
6764 FIB_ROUTE_PATH_FLAG_NONE);
6766 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6767 FIB_TEST(fib_test_validate_entry(fei,
6768 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6772 "1.1.1.1/32 LB 2 buckets via: "
6773 "adj over 10.10.11.1, "
6774 "adj-v4 over 10.10.11.2");
6776 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6778 FIB_TEST(fib_test_validate_entry(fei,
6779 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6782 &disp_o_10_10_11_2),
6783 "24001/eos LB 2 buckets via: "
6784 "MPLS disp adj over 10.10.11.1, "
6785 "MPLS disp adj-v4 over 10.10.11.2");
6787 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6790 FIB_TEST(fib_test_validate_entry(fei,
6791 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6793 &a_mpls_o_10_10_11_1),
6794 "24001/neos LB 1 buckets via: "
6795 "adj-mpls over 10.10.11.2");
6798 * remove the other path with a valid label
6800 fib_test_lb_bucket_t bucket_drop = {
6803 fib_test_lb_bucket_t mpls_bucket_drop = {
6806 .adj = DPO_PROTO_MPLS,
6810 fib_table_entry_path_remove(fib_index,
6815 tm->hw[1]->sw_if_index,
6816 ~0, // invalid fib index
6818 FIB_ROUTE_PATH_FLAG_NONE);
6820 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6821 FIB_TEST(fib_test_validate_entry(fei,
6822 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6825 "1.1.1.1/32 LB 1 buckets via: "
6826 "adj over 10.10.11.2");
6828 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6830 FIB_TEST(fib_test_validate_entry(fei,
6831 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6833 &disp_o_10_10_11_2),
6834 "24001/eos LB 1 buckets via: "
6835 "MPLS disp adj over 10.10.11.2");
6837 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6839 FIB_TEST(fib_test_validate_entry(fei,
6840 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6843 "24001/neos LB 1 buckets via: DROP");
6846 * add back the path with the valid label
6849 vec_add1(l99, fml99);
6851 fib_table_entry_path_add(fib_index,
6854 FIB_ENTRY_FLAG_NONE,
6857 tm->hw[0]->sw_if_index,
6858 ~0, // invalid fib index
6861 FIB_ROUTE_PATH_FLAG_NONE);
6863 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6864 FIB_TEST(fib_test_validate_entry(fei,
6865 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6867 &l99_eos_o_10_10_10_1,
6869 "1.1.1.1/32 LB 2 buckets via: "
6870 "label 99 over 10.10.10.1, "
6871 "adj over 10.10.11.2");
6873 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6875 FIB_TEST(fib_test_validate_entry(fei,
6876 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6878 &l99_eos_o_10_10_10_1,
6879 &disp_o_10_10_11_2),
6880 "24001/eos LB 2 buckets via: "
6881 "label 99 over 10.10.10.1, "
6882 "MPLS disp adj over 10.10.11.2");
6884 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6886 FIB_TEST(fib_test_validate_entry(fei,
6887 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6889 &l99_neos_o_10_10_10_1),
6890 "24001/neos LB 1 buckets via: "
6891 "label 99 over 10.10.10.1");
6894 * change the local label
6896 fib_table_entry_local_label_add(fib_index,
6900 fib_prefix_t pfx_25005_eos = {
6901 .fp_proto = FIB_PROTOCOL_MPLS,
6905 fib_prefix_t pfx_25005_neos = {
6906 .fp_proto = FIB_PROTOCOL_MPLS,
6908 .fp_eos = MPLS_NON_EOS,
6911 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6912 fib_table_lookup(fib_index, &pfx_24001_eos)),
6913 "24001/eos removed after label change");
6914 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6915 fib_table_lookup(fib_index, &pfx_24001_neos)),
6916 "24001/eos removed after label change");
6918 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6920 FIB_TEST(fib_test_validate_entry(fei,
6921 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6923 &l99_eos_o_10_10_10_1,
6924 &disp_o_10_10_11_2),
6925 "25005/eos LB 2 buckets via: "
6926 "label 99 over 10.10.10.1, "
6927 "MPLS disp adj over 10.10.11.2");
6929 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6931 FIB_TEST(fib_test_validate_entry(fei,
6932 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6934 &l99_neos_o_10_10_10_1),
6935 "25005/neos LB 1 buckets via: "
6936 "label 99 over 10.10.10.1");
6939 * remove the local label.
6940 * the check that the MPLS entries are gone is done by the fact the
6941 * MPLS table is no longer present.
6943 fib_table_entry_local_label_remove(fib_index,
6947 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6948 FIB_TEST(fib_test_validate_entry(fei,
6949 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6951 &l99_eos_o_10_10_10_1,
6953 "24001/eos LB 2 buckets via: "
6954 "label 99 over 10.10.10.1, "
6955 "adj over 10.10.11.2");
6957 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6958 mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)),
6959 "No more MPLS FIB entries => table removed");
6962 * add another via-entry for the recursive
6964 fib_prefix_t pfx_1_1_1_2_s_32 = {
6966 .fp_proto = FIB_PROTOCOL_IP4,
6968 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
6971 fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = {
6972 .type = FT_LB_LABEL_O_ADJ,
6974 .adj = ai_mpls_10_10_10_1,
6979 fib_mpls_label_t *l101 = NULL, fml101 = {
6982 vec_add1(l101, fml101);
6984 fei = fib_table_entry_update_one_path(fib_index,
6987 FIB_ENTRY_FLAG_NONE,
6990 tm->hw[0]->sw_if_index,
6991 ~0, // invalid fib index
6994 FIB_ROUTE_PATH_FLAG_NONE);
6996 FIB_TEST(fib_test_validate_entry(fei,
6997 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6999 &l101_eos_o_10_10_10_1),
7000 "1.1.1.2/32 LB 1 buckets via: "
7001 "label 101 over 10.10.10.1");
7003 dpo_id_t non_eos_1_1_1_2 = DPO_INVALID;
7004 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7006 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7008 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7010 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7013 fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = {
7014 .type = FT_LB_LABEL_O_LB,
7016 .lb = non_eos_1_1_1_2.dpoi_index,
7021 fib_mpls_label_t *l1601 = NULL, fml1601 = {
7024 vec_add1(l1601, fml1601);
7026 l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index;
7028 fei = fib_table_entry_path_add(fib_index,
7031 FIB_ENTRY_FLAG_NONE,
7033 &pfx_1_1_1_2_s_32.fp_addr,
7038 FIB_ROUTE_PATH_FLAG_NONE);
7040 FIB_TEST(fib_test_validate_entry(fei,
7041 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7043 &l1600_eos_o_1_1_1_1,
7044 &l1601_eos_o_1_1_1_2),
7045 "2.2.2.2/32 LB 2 buckets via: "
7046 "label 1600 via 1.1,1.1, "
7047 "label 16001 via 1.1.1.2");
7050 * update the via-entry so it no longer has an imp-null path.
7051 * the LB for the recursive can use an imp-null
7054 vec_add1(l_imp_null, fml_imp_null);
7056 fei = fib_table_entry_update_one_path(fib_index,
7059 FIB_ENTRY_FLAG_NONE,
7062 tm->hw[1]->sw_if_index,
7063 ~0, // invalid fib index
7066 FIB_ROUTE_PATH_FLAG_NONE);
7068 FIB_TEST(fib_test_validate_entry(fei,
7069 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7072 "1.1.1.2/32 LB 1 buckets via: "
7075 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7076 FIB_TEST(fib_test_validate_entry(fei,
7077 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7079 &l1600_eos_o_1_1_1_1,
7080 &l1601_eos_o_1_1_1_2),
7081 "2.2.2.2/32 LB 2 buckets via: "
7082 "label 1600 via 1.1,1.1, "
7083 "label 16001 via 1.1.1.2");
7086 * update the via-entry so it no longer has labelled paths.
7087 * the LB for the recursive should exclue this via form its LB
7089 fei = fib_table_entry_update_one_path(fib_index,
7092 FIB_ENTRY_FLAG_NONE,
7095 tm->hw[1]->sw_if_index,
7096 ~0, // invalid fib index
7099 FIB_ROUTE_PATH_FLAG_NONE);
7101 FIB_TEST(fib_test_validate_entry(fei,
7102 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7105 "1.1.1.2/32 LB 1 buckets via: "
7108 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7109 FIB_TEST(fib_test_validate_entry(fei,
7110 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7112 &l1600_eos_o_1_1_1_1),
7113 "2.2.2.2/32 LB 1 buckets via: "
7114 "label 1600 via 1.1,1.1");
7116 dpo_reset(&non_eos_1_1_1_1);
7117 dpo_reset(&non_eos_1_1_1_2);
7120 * Add a recursive with no out-labels. We expect to use the IP of the via
7122 fib_prefix_t pfx_2_2_2_3_s_32 = {
7124 .fp_proto = FIB_PROTOCOL_IP4,
7126 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
7129 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
7131 fib_table_entry_update_one_path(fib_index,
7134 FIB_ENTRY_FLAG_NONE,
7136 &pfx_1_1_1_1_s_32.fp_addr,
7141 FIB_ROUTE_PATH_FLAG_NONE);
7143 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7145 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7148 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
7151 .lb = ip_1_1_1_1.dpoi_index,
7155 fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
7156 FIB_TEST(fib_test_validate_entry(fei,
7157 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7160 "2.2.2.2.3/32 LB 1 buckets via: "
7164 * Add a recursive with an imp-null out-label.
7165 * We expect to use the IP of the via
7167 fib_prefix_t pfx_2_2_2_4_s_32 = {
7169 .fp_proto = FIB_PROTOCOL_IP4,
7171 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
7175 fib_table_entry_update_one_path(fib_index,
7178 FIB_ENTRY_FLAG_NONE,
7180 &pfx_1_1_1_1_s_32.fp_addr,
7185 FIB_ROUTE_PATH_FLAG_NONE);
7187 fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
7188 FIB_TEST(fib_test_validate_entry(fei,
7189 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7192 "2.2.2.2.4/32 LB 1 buckets via: "
7195 dpo_reset(&ip_1_1_1_1);
7198 * Create an entry with a deep label stack
7200 fib_prefix_t pfx_2_2_5_5_s_32 = {
7202 .fp_proto = FIB_PROTOCOL_IP4,
7204 .ip4.as_u32 = clib_host_to_net_u32(0x02020505),
7207 fib_test_lb_bucket_t ls_eos_o_10_10_10_1 = {
7208 .type = FT_LB_LABEL_STACK_O_ADJ,
7209 .label_stack_o_adj = {
7210 .adj = ai_mpls_10_10_11_1,
7211 .label_stack_size = 8,
7213 200, 201, 202, 203, 204, 205, 206, 207
7218 fib_mpls_label_t *label_stack = NULL;
7219 vec_validate(label_stack, 7);
7220 for (ii = 0; ii < 8; ii++)
7222 label_stack[ii].fml_value = ii + 200;
7225 fei = fib_table_entry_update_one_path(fib_index,
7228 FIB_ENTRY_FLAG_NONE,
7231 tm->hw[1]->sw_if_index,
7232 ~0, // invalid fib index
7235 FIB_ROUTE_PATH_FLAG_NONE);
7237 FIB_TEST(fib_test_validate_entry(fei,
7238 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7240 &ls_eos_o_10_10_10_1),
7241 "2.2.5.5/32 LB 1 buckets via: "
7243 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
7248 fib_table_entry_delete(fib_index,
7252 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7253 FIB_TEST(fib_test_validate_entry(fei,
7254 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7256 &l1600_eos_o_1_1_1_1),
7257 "2.2.2.2/32 LB 1 buckets via: "
7258 "label 1600 via 1.1,1.1");
7260 fib_table_entry_delete(fib_index,
7264 FIB_TEST(fib_test_validate_entry(fei,
7265 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7268 "2.2.2.2/32 LB 1 buckets via: DROP");
7270 fib_table_entry_delete(fib_index,
7273 fib_table_entry_delete(fib_index,
7276 fib_table_entry_delete(fib_index,
7280 adj_unlock(ai_mpls_10_10_10_1);
7281 adj_unlock(ai_mpls_10_10_11_2);
7282 adj_unlock(ai_v4_10_10_11_1);
7283 adj_unlock(ai_v4_10_10_11_2);
7284 adj_unlock(ai_mpls_10_10_11_1);
7286 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
7289 local0_pfx.fp_len = 32;
7290 fib_table_entry_delete(fib_index,
7292 FIB_SOURCE_INTERFACE);
7293 local0_pfx.fp_len = 24;
7294 fib_table_entry_delete(fib_index,
7296 FIB_SOURCE_INTERFACE);
7297 local1_pfx.fp_len = 32;
7298 fib_table_entry_delete(fib_index,
7300 FIB_SOURCE_INTERFACE);
7301 local1_pfx.fp_len = 24;
7302 fib_table_entry_delete(fib_index,
7304 FIB_SOURCE_INTERFACE);
7307 * +1 for the drop LB in the MPLS tables.
7309 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
7310 "Load-balance resources freed %d of %d",
7311 lb_count+1, pool_elts(load_balance_pool));
7316 #define N_TEST_CHILDREN 4
7317 #define PARENT_INDEX 0
7319 typedef struct fib_node_test_t_
7324 fib_node_back_walk_ctx_t *ctxs;
7328 static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1];
7330 #define PARENT() (&fib_test_nodes[PARENT_INDEX].node)
7332 #define FOR_EACH_TEST_CHILD(_tc) \
7333 for (ii = 1, (_tc) = &fib_test_nodes[1]; \
7334 ii < N_TEST_CHILDREN+1; \
7335 ii++, (_tc) = &fib_test_nodes[ii])
7338 fib_test_child_get_node (fib_node_index_t index)
7340 return (&fib_test_nodes[index].node);
7343 static int fib_test_walk_spawns_walks;
7345 static fib_node_back_walk_rc_t
7346 fib_test_child_back_walk_notify (fib_node_t *node,
7347 fib_node_back_walk_ctx_t *ctx)
7349 fib_node_test_t *tc = (fib_node_test_t*) node;
7351 vec_add1(tc->ctxs, *ctx);
7353 if (1 == fib_test_walk_spawns_walks)
7354 fib_walk_sync(FIB_NODE_TYPE_TEST, tc->index, ctx);
7355 if (2 == fib_test_walk_spawns_walks)
7356 fib_walk_async(FIB_NODE_TYPE_TEST, tc->index,
7357 FIB_WALK_PRIORITY_HIGH, ctx);
7359 return (FIB_NODE_BACK_WALK_CONTINUE);
7363 fib_test_child_last_lock_gone (fib_node_t *node)
7365 fib_node_test_t *tc = (fib_node_test_t *)node;
7371 * The FIB walk's graph node virtual function table
7373 static const fib_node_vft_t fib_test_child_vft = {
7374 .fnv_get = fib_test_child_get_node,
7375 .fnv_last_lock = fib_test_child_last_lock_gone,
7376 .fnv_back_walk = fib_test_child_back_walk_notify,
7380 * the function (that should have been static but isn't so I can do this)
7381 * that processes the walk from the async queue,
7383 f64 fib_walk_process_queues(vlib_main_t * vm,
7385 u32 fib_walk_queue_get_size(fib_walk_priority_t prio);
7388 fib_test_walk (void)
7390 fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {};
7391 fib_node_test_t *tc;
7395 vm = vlib_get_main();
7396 fib_node_register_type(FIB_NODE_TYPE_TEST, &fib_test_child_vft);
7399 * init a fake node on which we will add children
7401 fib_node_init(&fib_test_nodes[PARENT_INDEX].node,
7402 FIB_NODE_TYPE_TEST);
7404 FOR_EACH_TEST_CHILD(tc)
7406 fib_node_init(&tc->node, FIB_NODE_TYPE_TEST);
7407 fib_node_lock(&tc->node);
7410 tc->sibling = fib_node_child_add(FIB_NODE_TYPE_TEST,
7412 FIB_NODE_TYPE_TEST, ii);
7416 * enqueue a walk across the parents children.
7418 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7420 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7421 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7422 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7423 "Parent has %d children pre-walk",
7424 fib_node_list_get_size(PARENT()->fn_children));
7427 * give the walk a large amount of time so it gets to the end
7429 fib_walk_process_queues(vm, 1);
7431 FOR_EACH_TEST_CHILD(tc)
7433 FIB_TEST(1 == vec_len(tc->ctxs),
7434 "%d child visitsed %d times",
7435 ii, vec_len(tc->ctxs));
7438 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7439 "Queue is empty post walk");
7440 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7441 "Parent has %d children post walk",
7442 fib_node_list_get_size(PARENT()->fn_children));
7445 * walk again. should be no increase in the number of visits, since
7446 * the walk will have terminated.
7448 fib_walk_process_queues(vm, 1);
7450 FOR_EACH_TEST_CHILD(tc)
7452 FIB_TEST(0 == vec_len(tc->ctxs),
7453 "%d child visitsed %d times",
7454 ii, vec_len(tc->ctxs));
7458 * schedule a low and hig priority walk. expect the high to be performed
7460 * schedule the high prio walk first so that it is further from the head
7461 * of the dependency list. that way it won't merge with the low one.
7463 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7464 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7466 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7467 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7468 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7469 FIB_WALK_PRIORITY_LOW, &low_ctx);
7471 fib_walk_process_queues(vm, 1);
7473 FOR_EACH_TEST_CHILD(tc)
7475 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7476 "%d child visitsed by high prio walk", ii);
7477 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7478 "%d child visitsed by low prio walk", ii);
7481 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7482 "Queue is empty post prio walk");
7483 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7484 "Parent has %d children post prio walk",
7485 fib_node_list_get_size(PARENT()->fn_children));
7488 * schedule 2 walks of the same priority that can be megred.
7489 * expect that each child is thus visited only once.
7491 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7492 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7494 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7495 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7496 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7497 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7499 fib_walk_process_queues(vm, 1);
7501 FOR_EACH_TEST_CHILD(tc)
7503 FIB_TEST(1 == vec_len(tc->ctxs),
7504 "%d child visitsed %d times during merge walk",
7505 ii, vec_len(tc->ctxs));
7508 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7509 "Queue is empty post merge walk");
7510 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7511 "Parent has %d children post merge walk",
7512 fib_node_list_get_size(PARENT()->fn_children));
7515 * schedule 2 walks of the same priority that cannot be megred.
7516 * expect that each child is thus visited twice and in the order
7517 * in which the walks were scheduled.
7519 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7520 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7522 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7523 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7524 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7525 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7527 fib_walk_process_queues(vm, 1);
7529 FOR_EACH_TEST_CHILD(tc)
7531 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7532 "%d child visitsed by high prio walk", ii);
7533 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7534 "%d child visitsed by low prio walk", ii);
7537 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7538 "Queue is empty post no-merge walk");
7539 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7540 "Parent has %d children post no-merge walk",
7541 fib_node_list_get_size(PARENT()->fn_children));
7544 * schedule a walk that makes one one child progress.
7545 * we do this by giving the queue draining process zero
7546 * time quanta. it's a do..while loop, so it does something.
7548 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7550 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7551 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7552 fib_walk_process_queues(vm, 0);
7554 FOR_EACH_TEST_CHILD(tc)
7556 if (ii == N_TEST_CHILDREN)
7558 FIB_TEST(1 == vec_len(tc->ctxs),
7559 "%d child visitsed %d times in zero quanta walk",
7560 ii, vec_len(tc->ctxs));
7564 FIB_TEST(0 == vec_len(tc->ctxs),
7565 "%d child visitsed %d times in 0 quanta walk",
7566 ii, vec_len(tc->ctxs));
7569 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7570 "Queue is not empty post zero quanta walk");
7571 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7572 "Parent has %d children post zero qunta walk",
7573 fib_node_list_get_size(PARENT()->fn_children));
7578 fib_walk_process_queues(vm, 0);
7580 FOR_EACH_TEST_CHILD(tc)
7582 if (ii >= N_TEST_CHILDREN-1)
7584 FIB_TEST(1 == vec_len(tc->ctxs),
7585 "%d child visitsed %d times in 2nd zero quanta walk",
7586 ii, vec_len(tc->ctxs));
7590 FIB_TEST(0 == vec_len(tc->ctxs),
7591 "%d child visitsed %d times in 2nd 0 quanta walk",
7592 ii, vec_len(tc->ctxs));
7595 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7596 "Queue is not empty post zero quanta walk");
7597 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7598 "Parent has %d children post zero qunta walk",
7599 fib_node_list_get_size(PARENT()->fn_children));
7602 * schedule another walk that will catch-up and merge.
7604 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7605 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7606 fib_walk_process_queues(vm, 1);
7608 FOR_EACH_TEST_CHILD(tc)
7610 if (ii >= N_TEST_CHILDREN-1)
7612 FIB_TEST(2 == vec_len(tc->ctxs),
7613 "%d child visitsed %d times in 2nd zero quanta merge walk",
7614 ii, vec_len(tc->ctxs));
7619 FIB_TEST(1 == vec_len(tc->ctxs),
7620 "%d child visitsed %d times in 2nd 0 quanta merge walk",
7621 ii, vec_len(tc->ctxs));
7625 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7626 "Queue is not empty post 2nd zero quanta merge walk");
7627 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7628 "Parent has %d children post 2nd zero qunta merge walk",
7629 fib_node_list_get_size(PARENT()->fn_children));
7632 * park a async walk in the middle of the list, then have an sync walk catch
7633 * it. same expectations as async catches async.
7635 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7637 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7638 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7640 fib_walk_process_queues(vm, 0);
7641 fib_walk_process_queues(vm, 0);
7643 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7645 FOR_EACH_TEST_CHILD(tc)
7647 if (ii >= N_TEST_CHILDREN-1)
7649 FIB_TEST(2 == vec_len(tc->ctxs),
7650 "%d child visitsed %d times in sync catches async walk",
7651 ii, vec_len(tc->ctxs));
7656 FIB_TEST(1 == vec_len(tc->ctxs),
7657 "%d child visitsed %d times in sync catches async walk",
7658 ii, vec_len(tc->ctxs));
7662 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7663 "Queue is not empty post 2nd zero quanta merge walk");
7664 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7665 "Parent has %d children post 2nd zero qunta merge walk",
7666 fib_node_list_get_size(PARENT()->fn_children));
7669 * make the parent a child of one of its children, thus inducing a routing loop.
7671 fib_test_nodes[PARENT_INDEX].sibling =
7672 fib_node_child_add(FIB_NODE_TYPE_TEST,
7673 1, // the first child
7678 * execute a sync walk from the parent. each child visited spawns more sync
7679 * walks. we expect the walk to terminate.
7681 fib_test_walk_spawns_walks = 1;
7683 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7685 FOR_EACH_TEST_CHILD(tc)
7688 * child 1 - which is last in the list - has the loop.
7689 * the other children a re thus visitsed first. the we meet
7690 * child 1. we go round the loop again, visting the other children.
7691 * then we meet the walk in the dep list and bail. child 1 is not visitsed
7696 FIB_TEST(1 == vec_len(tc->ctxs),
7697 "child %d visitsed %d times during looped sync walk",
7698 ii, vec_len(tc->ctxs));
7702 FIB_TEST(2 == vec_len(tc->ctxs),
7703 "child %d visitsed %d times during looped sync walk",
7704 ii, vec_len(tc->ctxs));
7708 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7709 "Parent has %d children post sync loop walk",
7710 fib_node_list_get_size(PARENT()->fn_children));
7713 * the walk doesn't reach the max depth because the infra knows that sync
7714 * meets sync implies a loop and bails early.
7716 FIB_TEST(high_ctx.fnbw_depth == 9,
7717 "Walk context depth %d post sync loop walk",
7718 high_ctx.fnbw_depth);
7721 * execute an async walk of the graph loop, with each child spawns sync walks
7723 high_ctx.fnbw_depth = 0;
7724 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7725 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7727 fib_walk_process_queues(vm, 1);
7729 FOR_EACH_TEST_CHILD(tc)
7732 * we don't really care how many times the children are visisted, as long as
7733 * it is more than once.
7735 FIB_TEST(1 <= vec_len(tc->ctxs),
7736 "child %d visitsed %d times during looped aync spawns sync walk",
7737 ii, vec_len(tc->ctxs));
7742 * execute an async walk of the graph loop, with each child spawns async walks
7744 fib_test_walk_spawns_walks = 2;
7745 high_ctx.fnbw_depth = 0;
7746 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7747 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7749 fib_walk_process_queues(vm, 1);
7751 FOR_EACH_TEST_CHILD(tc)
7754 * we don't really care how many times the children are visisted, as long as
7755 * it is more than once.
7757 FIB_TEST(1 <= vec_len(tc->ctxs),
7758 "child %d visitsed %d times during looped async spawns async walk",
7759 ii, vec_len(tc->ctxs));
7764 fib_node_child_remove(FIB_NODE_TYPE_TEST,
7765 1, // the first child
7766 fib_test_nodes[PARENT_INDEX].sibling);
7771 FOR_EACH_TEST_CHILD(tc)
7773 fib_node_child_remove(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7775 fib_node_deinit(&tc->node);
7776 fib_node_unlock(&tc->node);
7778 fib_node_deinit(PARENT());
7781 * The parent will be destroyed when the last lock on it goes.
7782 * this test ensures all the walk objects are unlocking it.
7784 FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed),
7785 "Parent was destroyed");
7791 * declaration of the otherwise static callback functions
7793 void fib_bfd_notify (bfd_listen_event_e event,
7794 const bfd_session_t *session);
7795 void adj_bfd_notify (bfd_listen_event_e event,
7796 const bfd_session_t *session);
7799 * Test BFD session interaction with FIB
7804 fib_node_index_t fei;
7808 /* via 10.10.10.1 */
7809 ip46_address_t nh_10_10_10_1 = {
7810 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
7812 /* via 10.10.10.2 */
7813 ip46_address_t nh_10_10_10_2 = {
7814 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
7816 /* via 10.10.10.10 */
7817 ip46_address_t nh_10_10_10_10 = {
7818 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
7820 n_feis = fib_entry_pool_size();
7825 * add interface routes. we'll assume this works. it's tested elsewhere
7827 fib_prefix_t pfx_10_10_10_10_s_24 = {
7829 .fp_proto = FIB_PROTOCOL_IP4,
7830 .fp_addr = nh_10_10_10_10,
7833 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_24,
7834 FIB_SOURCE_INTERFACE,
7835 (FIB_ENTRY_FLAG_CONNECTED |
7836 FIB_ENTRY_FLAG_ATTACHED),
7839 tm->hw[0]->sw_if_index,
7840 ~0, // invalid fib index
7843 FIB_ROUTE_PATH_FLAG_NONE);
7845 fib_prefix_t pfx_10_10_10_10_s_32 = {
7847 .fp_proto = FIB_PROTOCOL_IP4,
7848 .fp_addr = nh_10_10_10_10,
7850 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_32,
7851 FIB_SOURCE_INTERFACE,
7852 (FIB_ENTRY_FLAG_CONNECTED |
7853 FIB_ENTRY_FLAG_LOCAL),
7856 tm->hw[0]->sw_if_index,
7857 ~0, // invalid fib index
7860 FIB_ROUTE_PATH_FLAG_NONE);
7863 * A BFD session via a neighbour we do not yet know
7865 bfd_session_t bfd_10_10_10_1 = {
7869 .peer_addr = nh_10_10_10_1,
7872 .hop_type = BFD_HOP_TYPE_MULTI,
7873 .local_state = BFD_STATE_init,
7876 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7879 * A new entry will be created that forwards via the adj
7881 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
7884 tm->hw[0]->sw_if_index);
7885 fib_prefix_t pfx_10_10_10_1_s_32 = {
7886 .fp_addr = nh_10_10_10_1,
7888 .fp_proto = FIB_PROTOCOL_IP4,
7890 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
7893 .adj = ai_10_10_10_1,
7897 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7898 FIB_TEST(fib_test_validate_entry(fei,
7899 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7902 "BFD sourced %U via %U",
7903 format_fib_prefix, &pfx_10_10_10_1_s_32,
7904 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
7907 * Delete the BFD session. Expect the fib_entry to be removed
7909 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7911 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7912 FIB_TEST(FIB_NODE_INDEX_INVALID == fei,
7913 "BFD sourced %U removed",
7914 format_fib_prefix, &pfx_10_10_10_1_s_32);
7917 * Add the BFD source back
7919 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7922 * source the entry via the ADJ fib
7924 fei = fib_table_entry_path_add(0,
7925 &pfx_10_10_10_1_s_32,
7927 FIB_ENTRY_FLAG_ATTACHED,
7930 tm->hw[0]->sw_if_index,
7931 ~0, // invalid fib index
7934 FIB_ROUTE_PATH_FLAG_NONE);
7937 * Delete the BFD session. Expect the fib_entry to remain
7939 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7941 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7942 FIB_TEST(fib_test_validate_entry(fei,
7943 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7946 "BFD sourced %U remains via %U",
7947 format_fib_prefix, &pfx_10_10_10_1_s_32,
7948 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
7951 * Add the BFD source back
7953 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7956 * Create another ADJ FIB
7958 fib_prefix_t pfx_10_10_10_2_s_32 = {
7959 .fp_addr = nh_10_10_10_2,
7961 .fp_proto = FIB_PROTOCOL_IP4,
7963 fib_table_entry_path_add(0,
7964 &pfx_10_10_10_2_s_32,
7966 FIB_ENTRY_FLAG_ATTACHED,
7969 tm->hw[0]->sw_if_index,
7970 ~0, // invalid fib index
7973 FIB_ROUTE_PATH_FLAG_NONE);
7975 * A BFD session for the new ADJ FIB
7977 bfd_session_t bfd_10_10_10_2 = {
7981 .peer_addr = nh_10_10_10_2,
7984 .hop_type = BFD_HOP_TYPE_MULTI,
7985 .local_state = BFD_STATE_init,
7988 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_2);
7991 * remove the adj-fib source whilst the session is present
7994 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
7995 fib_table_entry_path_add(0,
7996 &pfx_10_10_10_2_s_32,
7998 FIB_ENTRY_FLAG_ATTACHED,
8001 tm->hw[0]->sw_if_index,
8002 ~0, // invalid fib index
8005 FIB_ROUTE_PATH_FLAG_NONE);
8008 * Before adding a recursive via the BFD tracked ADJ-FIBs,
8009 * bring one of the sessions UP, leave the other down
8011 bfd_10_10_10_1.local_state = BFD_STATE_up;
8012 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8013 bfd_10_10_10_2.local_state = BFD_STATE_down;
8014 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8017 * A recursive prefix via both of the ADJ FIBs
8019 fib_prefix_t pfx_200_0_0_0_s_24 = {
8020 .fp_proto = FIB_PROTOCOL_IP4,
8023 .ip4.as_u32 = clib_host_to_net_u32(0xc8000000),
8026 const dpo_id_t *dpo_10_10_10_1, *dpo_10_10_10_2;
8029 fib_entry_contribute_ip_forwarding(
8030 fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32));
8032 fib_entry_contribute_ip_forwarding(
8033 fib_table_lookup_exact_match(0, &pfx_10_10_10_2_s_32));
8035 fib_test_lb_bucket_t lb_o_10_10_10_1 = {
8038 .lb = dpo_10_10_10_1->dpoi_index,
8041 fib_test_lb_bucket_t lb_o_10_10_10_2 = {
8044 .lb = dpo_10_10_10_2->dpoi_index,
8049 * A prefix via the adj-fib that is BFD down => DROP
8051 fei = fib_table_entry_path_add(0,
8052 &pfx_200_0_0_0_s_24,
8054 FIB_ENTRY_FLAG_NONE,
8058 0, // default fib index
8061 FIB_ROUTE_PATH_FLAG_NONE);
8062 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8063 "%U resolves via drop",
8064 format_fib_prefix, &pfx_200_0_0_0_s_24);
8067 * add a path via the UP BFD adj-fib.
8068 * we expect that the DOWN BFD ADJ FIB is not used.
8070 fei = fib_table_entry_path_add(0,
8071 &pfx_200_0_0_0_s_24,
8073 FIB_ENTRY_FLAG_NONE,
8077 0, // default fib index
8080 FIB_ROUTE_PATH_FLAG_NONE);
8082 FIB_TEST(fib_test_validate_entry(fei,
8083 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8086 "Recursive %U only UP BFD adj-fibs",
8087 format_fib_prefix, &pfx_200_0_0_0_s_24);
8090 * Send a BFD state change to UP - both sessions are now up
8091 * the recursive prefix should LB over both
8093 bfd_10_10_10_2.local_state = BFD_STATE_up;
8094 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8097 FIB_TEST(fib_test_validate_entry(fei,
8098 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8102 "Recursive %U via both UP BFD adj-fibs",
8103 format_fib_prefix, &pfx_200_0_0_0_s_24);
8106 * Send a BFD state change to DOWN
8107 * the recursive prefix should exclude the down
8109 bfd_10_10_10_2.local_state = BFD_STATE_down;
8110 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8113 FIB_TEST(fib_test_validate_entry(fei,
8114 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8117 "Recursive %U via only UP",
8118 format_fib_prefix, &pfx_200_0_0_0_s_24);
8121 * Delete the BFD session while it is in the DOWN state.
8122 * FIB should consider the entry's state as back up
8124 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_2);
8126 FIB_TEST(fib_test_validate_entry(fei,
8127 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8131 "Recursive %U via both UP BFD adj-fibs post down session delete",
8132 format_fib_prefix, &pfx_200_0_0_0_s_24);
8135 * Delete the BFD other session while it is in the UP state.
8137 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8139 FIB_TEST(fib_test_validate_entry(fei,
8140 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8144 "Recursive %U via both UP BFD adj-fibs post up session delete",
8145 format_fib_prefix, &pfx_200_0_0_0_s_24);
8150 fib_table_entry_delete(0, &pfx_200_0_0_0_s_24, FIB_SOURCE_API);
8151 fib_table_entry_delete(0, &pfx_10_10_10_1_s_32, FIB_SOURCE_ADJ);
8152 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
8154 fib_table_entry_delete(0, &pfx_10_10_10_10_s_32, FIB_SOURCE_INTERFACE);
8155 fib_table_entry_delete(0, &pfx_10_10_10_10_s_24, FIB_SOURCE_INTERFACE);
8157 adj_unlock(ai_10_10_10_1);
8159 * test no-one left behind
8161 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8162 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8165 * Single-hop BFD tests
8167 bfd_10_10_10_1.hop_type = BFD_HOP_TYPE_SINGLE;
8168 bfd_10_10_10_1.udp.key.sw_if_index = tm->hw[0]->sw_if_index;
8170 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8172 ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8175 tm->hw[0]->sw_if_index);
8177 * whilst the BFD session is not signalled, the adj is up
8179 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on uninit session");
8182 * bring the BFD session up
8184 bfd_10_10_10_1.local_state = BFD_STATE_up;
8185 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8186 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on UP session");
8189 * bring the BFD session down
8191 bfd_10_10_10_1.local_state = BFD_STATE_down;
8192 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8193 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on DOWN session");
8197 * add an attached next hop FIB entry via the down adj
8199 fib_prefix_t pfx_5_5_5_5_s_32 = {
8202 .as_u32 = clib_host_to_net_u32(0x05050505),
8206 .fp_proto = FIB_PROTOCOL_IP4,
8209 fei = fib_table_entry_path_add(0,
8212 FIB_ENTRY_FLAG_NONE,
8215 tm->hw[0]->sw_if_index,
8216 ~0, // invalid fib index
8219 FIB_ROUTE_PATH_FLAG_NONE);
8220 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8221 "%U resolves via drop",
8222 format_fib_prefix, &pfx_5_5_5_5_s_32);
8225 * Add a path via an ADJ that is up
8227 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8230 tm->hw[0]->sw_if_index);
8232 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
8235 .adj = ai_10_10_10_2,
8238 adj_o_10_10_10_1.adj.adj = ai_10_10_10_1;
8240 fei = fib_table_entry_path_add(0,
8243 FIB_ENTRY_FLAG_NONE,
8246 tm->hw[0]->sw_if_index,
8247 ~0, // invalid fib index
8250 FIB_ROUTE_PATH_FLAG_NONE);
8252 FIB_TEST(fib_test_validate_entry(fei,
8253 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8256 "BFD sourced %U via %U",
8257 format_fib_prefix, &pfx_5_5_5_5_s_32,
8258 format_ip_adjacency, ai_10_10_10_2, FORMAT_IP_ADJACENCY_NONE);
8261 * Bring up the down session - should now LB
8263 bfd_10_10_10_1.local_state = BFD_STATE_up;
8264 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8265 FIB_TEST(fib_test_validate_entry(fei,
8266 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8270 "BFD sourced %U via noth adjs",
8271 format_fib_prefix, &pfx_5_5_5_5_s_32);
8274 * remove the BFD session state from the adj
8276 adj_bfd_notify(BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8281 fib_table_entry_delete(0, &pfx_5_5_5_5_s_32, FIB_SOURCE_CLI);
8282 adj_unlock(ai_10_10_10_1);
8283 adj_unlock(ai_10_10_10_2);
8286 * test no-one left behind
8288 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8289 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8296 const mpls_label_t deag_label = 50;
8297 dpo_id_t dpo = DPO_INVALID;
8298 const mpls_disp_dpo_t *mdd;
8299 const u32 lfib_index = 0;
8300 const u32 fib_index = 0;
8301 const lookup_dpo_t *lkd;
8302 const dpo_id_t *dpo1;
8303 fib_node_index_t lfe;
8306 adj_index_t ai_mpls_10_10_10_1;
8309 lb_count = pool_elts(load_balance_pool);
8311 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
8315 * MPLS enable an interface so we get the MPLS table created
8317 mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL);
8318 mpls_sw_interface_enable_disable(&mpls_main,
8319 tm->hw[0]->sw_if_index,
8322 ip46_address_t nh_10_10_10_1 = {
8323 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
8325 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8328 tm->hw[0]->sw_if_index);
8331 * Test the specials stack properly.
8333 fib_prefix_t exp_null_v6_pfx = {
8334 .fp_proto = FIB_PROTOCOL_MPLS,
8336 .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8337 .fp_payload_proto = DPO_PROTO_IP6,
8339 lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx);
8340 FIB_TEST((FIB_NODE_INDEX_INVALID != lfe),
8342 format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8343 format_mpls_eos_bit, MPLS_EOS);
8344 fib_entry_contribute_forwarding(lfe,
8345 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8347 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8348 lkd = lookup_dpo_get(dpo1->dpoi_index);
8350 FIB_TEST((fib_index == lkd->lkd_fib_index),
8351 "%U/%U is deag in %d %U",
8352 format_mpls_unicast_label, deag_label,
8353 format_mpls_eos_bit, MPLS_EOS,
8355 format_dpo_id, &dpo, 0);
8356 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8357 "%U/%U is dst deag",
8358 format_mpls_unicast_label, deag_label,
8359 format_mpls_eos_bit, MPLS_EOS);
8360 FIB_TEST((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table),
8361 "%U/%U is lookup in interface's table",
8362 format_mpls_unicast_label, deag_label,
8363 format_mpls_eos_bit, MPLS_EOS);
8364 FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto),
8365 "%U/%U is %U dst deag",
8366 format_mpls_unicast_label, deag_label,
8367 format_mpls_eos_bit, MPLS_EOS,
8368 format_dpo_proto, lkd->lkd_proto);
8371 * A route deag route for EOS
8373 fib_prefix_t pfx = {
8374 .fp_proto = FIB_PROTOCOL_MPLS,
8376 .fp_label = deag_label,
8377 .fp_payload_proto = DPO_PROTO_IP4,
8379 lfe = fib_table_entry_path_add(lfib_index,
8382 FIB_ENTRY_FLAG_NONE,
8389 FIB_ROUTE_PATH_FLAG_NONE);
8391 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8393 format_mpls_unicast_label, deag_label,
8394 format_mpls_eos_bit, MPLS_EOS);
8396 fib_entry_contribute_forwarding(lfe,
8397 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8399 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8400 mdd = mpls_disp_dpo_get(dpo1->dpoi_index);
8402 FIB_TEST((FIB_MPLS_LSP_MODE_PIPE == mdd->mdd_mode),
8403 "%U/%U disp is pipe mode",
8404 format_mpls_unicast_label, deag_label,
8405 format_mpls_eos_bit, MPLS_EOS);
8407 lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index);
8409 FIB_TEST((fib_index == lkd->lkd_fib_index),
8410 "%U/%U is deag in %d %U",
8411 format_mpls_unicast_label, deag_label,
8412 format_mpls_eos_bit, MPLS_EOS,
8414 format_dpo_id, &dpo, 0);
8415 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8416 "%U/%U is dst deag",
8417 format_mpls_unicast_label, deag_label,
8418 format_mpls_eos_bit, MPLS_EOS);
8419 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8420 "%U/%U is %U dst deag",
8421 format_mpls_unicast_label, deag_label,
8422 format_mpls_eos_bit, MPLS_EOS,
8423 format_dpo_proto, lkd->lkd_proto);
8425 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8427 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8429 "%U/%U not present",
8430 format_mpls_unicast_label, deag_label,
8431 format_mpls_eos_bit, MPLS_EOS);
8435 * A route deag route for EOS with LSP mode uniform
8437 fib_mpls_label_t *l_pops = NULL, l_pop = {
8438 .fml_value = MPLS_LABEL_POP,
8439 .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM,
8441 vec_add1(l_pops, l_pop);
8442 lfe = fib_table_entry_path_add(lfib_index,
8445 FIB_ENTRY_FLAG_NONE,
8452 FIB_ROUTE_PATH_FLAG_NONE);
8454 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8456 format_mpls_unicast_label, deag_label,
8457 format_mpls_eos_bit, MPLS_EOS);
8459 fib_entry_contribute_forwarding(lfe,
8460 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8462 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8463 mdd = mpls_disp_dpo_get(dpo1->dpoi_index);
8465 FIB_TEST((FIB_MPLS_LSP_MODE_UNIFORM == mdd->mdd_mode),
8466 "%U/%U disp is uniform mode",
8467 format_mpls_unicast_label, deag_label,
8468 format_mpls_eos_bit, MPLS_EOS);
8470 lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index);
8472 FIB_TEST((fib_index == lkd->lkd_fib_index),
8473 "%U/%U is deag in %d %U",
8474 format_mpls_unicast_label, deag_label,
8475 format_mpls_eos_bit, MPLS_EOS,
8477 format_dpo_id, &dpo, 0);
8478 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8479 "%U/%U is dst deag",
8480 format_mpls_unicast_label, deag_label,
8481 format_mpls_eos_bit, MPLS_EOS);
8482 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8483 "%U/%U is %U dst deag",
8484 format_mpls_unicast_label, deag_label,
8485 format_mpls_eos_bit, MPLS_EOS,
8486 format_dpo_proto, lkd->lkd_proto);
8488 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8490 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8492 "%U/%U not present",
8493 format_mpls_unicast_label, deag_label,
8494 format_mpls_eos_bit, MPLS_EOS);
8498 * A route deag route for non-EOS
8500 pfx.fp_eos = MPLS_NON_EOS;
8501 lfe = fib_table_entry_path_add(lfib_index,
8504 FIB_ENTRY_FLAG_NONE,
8511 FIB_ROUTE_PATH_FLAG_NONE);
8513 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8515 format_mpls_unicast_label, deag_label,
8516 format_mpls_eos_bit, MPLS_NON_EOS);
8518 fib_entry_contribute_forwarding(lfe,
8519 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8521 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8522 lkd = lookup_dpo_get(dpo1->dpoi_index);
8524 FIB_TEST((fib_index == lkd->lkd_fib_index),
8525 "%U/%U is deag in %d %U",
8526 format_mpls_unicast_label, deag_label,
8527 format_mpls_eos_bit, MPLS_NON_EOS,
8529 format_dpo_id, &dpo, 0);
8530 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8531 "%U/%U is dst deag",
8532 format_mpls_unicast_label, deag_label,
8533 format_mpls_eos_bit, MPLS_NON_EOS);
8535 FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto),
8536 "%U/%U is %U dst deag",
8537 format_mpls_unicast_label, deag_label,
8538 format_mpls_eos_bit, MPLS_NON_EOS,
8539 format_dpo_proto, lkd->lkd_proto);
8541 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8543 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8545 "%U/%U not present",
8546 format_mpls_unicast_label, deag_label,
8547 format_mpls_eos_bit, MPLS_EOS);
8554 fib_prefix_t pfx_1200 = {
8556 .fp_proto = FIB_PROTOCOL_MPLS,
8558 .fp_eos = MPLS_NON_EOS,
8560 fib_test_lb_bucket_t neos_o_10_10_10_1 = {
8561 .type = FT_LB_LABEL_STACK_O_ADJ,
8562 .label_stack_o_adj = {
8563 .adj = ai_mpls_10_10_10_1,
8564 .label_stack_size = 4,
8568 .eos = MPLS_NON_EOS,
8571 dpo_id_t neos_1200 = DPO_INVALID;
8572 dpo_id_t ip_1200 = DPO_INVALID;
8573 fib_mpls_label_t *l200 = NULL;
8575 for (ii = 0; ii < 4; ii++)
8577 fib_mpls_label_t fml = {
8578 .fml_value = 200 + (ii * 100),
8580 vec_add1(l200, fml);
8583 lfe = fib_table_entry_update_one_path(fib_index,
8586 FIB_ENTRY_FLAG_NONE,
8589 tm->hw[0]->sw_if_index,
8590 ~0, // invalid fib index
8593 FIB_ROUTE_PATH_FLAG_NONE);
8595 FIB_TEST(fib_test_validate_entry(lfe,
8596 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8598 &neos_o_10_10_10_1),
8599 "1200/0 LB 1 buckets via: "
8603 * A recursive route via the MPLS x-connect
8605 fib_prefix_t pfx_2_2_2_3_s_32 = {
8607 .fp_proto = FIB_PROTOCOL_IP4,
8609 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
8612 fib_route_path_t *rpaths = NULL, rpath = {
8613 .frp_proto = DPO_PROTO_MPLS,
8614 .frp_local_label = 1200,
8615 .frp_eos = MPLS_NON_EOS,
8616 .frp_sw_if_index = ~0, // recurive
8617 .frp_fib_index = 0, // Default MPLS fib
8619 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
8620 .frp_label_stack = NULL,
8622 vec_add1(rpaths, rpath);
8624 fib_table_entry_path_add2(fib_index,
8627 FIB_ENTRY_FLAG_NONE,
8631 * A labelled recursive route via the MPLS x-connect
8633 fib_prefix_t pfx_2_2_2_4_s_32 = {
8635 .fp_proto = FIB_PROTOCOL_IP4,
8637 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
8640 fib_mpls_label_t *l999 = NULL, fml_999 = {
8643 vec_add1(l999, fml_999);
8644 rpaths[0].frp_label_stack = l999,
8646 fib_table_entry_path_add2(fib_index,
8649 FIB_ENTRY_FLAG_NONE,
8652 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8653 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8655 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8656 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8659 fib_test_lb_bucket_t ip_o_1200 = {
8662 .lb = ip_1200.dpoi_index,
8665 fib_test_lb_bucket_t mpls_o_1200 = {
8666 .type = FT_LB_LABEL_O_LB,
8668 .lb = neos_1200.dpoi_index,
8674 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
8675 FIB_TEST(fib_test_validate_entry(lfe,
8676 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8679 "2.2.2.2.3/32 LB 1 buckets via: label 1200 EOS");
8680 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
8681 FIB_TEST(fib_test_validate_entry(lfe,
8682 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8685 "2.2.2.2.4/32 LB 1 buckets via: label 1200 non-EOS");
8687 fib_table_entry_delete(fib_index, &pfx_1200, FIB_SOURCE_API);
8688 fib_table_entry_delete(fib_index, &pfx_2_2_2_3_s_32, FIB_SOURCE_API);
8689 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8691 dpo_reset(&neos_1200);
8692 dpo_reset(&ip_1200);
8695 * A recursive via a label that does not exist
8697 fib_test_lb_bucket_t bucket_drop = {
8700 .adj = DPO_PROTO_IP4,
8703 fib_test_lb_bucket_t mpls_bucket_drop = {
8706 .adj = DPO_PROTO_MPLS,
8710 rpaths[0].frp_label_stack = NULL;
8711 lfe = fib_table_entry_path_add2(fib_index,
8714 FIB_ENTRY_FLAG_NONE,
8717 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8718 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8720 ip_o_1200.lb.lb = ip_1200.dpoi_index;
8722 FIB_TEST(fib_test_validate_entry(lfe,
8723 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8726 "2.2.2.2.4/32 LB 1 buckets via: drop");
8727 lfe = fib_table_lookup(fib_index, &pfx_1200);
8728 FIB_TEST(fib_test_validate_entry(lfe,
8729 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8732 "1200/neos LB 1 buckets via: ip4-DROP");
8733 FIB_TEST(fib_test_validate_entry(lfe,
8734 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8737 "1200/neos LB 1 buckets via: mpls-DROP");
8739 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8741 dpo_reset(&ip_1200);
8744 * An rx-interface route.
8745 * like the tail of an mcast LSP
8747 dpo_id_t idpo = DPO_INVALID;
8749 interface_rx_dpo_add_or_lock(DPO_PROTO_IP4,
8750 tm->hw[0]->sw_if_index,
8753 fib_prefix_t pfx_2500 = {
8755 .fp_proto = FIB_PROTOCOL_MPLS,
8758 .fp_payload_proto = DPO_PROTO_IP4,
8760 fib_test_lb_bucket_t rx_intf_0 = {
8763 .adj = idpo.dpoi_index,
8767 lfe = fib_table_entry_update_one_path(fib_index,
8770 FIB_ENTRY_FLAG_NONE,
8773 tm->hw[0]->sw_if_index,
8774 ~0, // invalid fib index
8777 FIB_ROUTE_PATH_INTF_RX);
8778 FIB_TEST(fib_test_validate_entry(lfe,
8779 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8782 "2500 rx-interface 0");
8783 fib_table_entry_delete(fib_index, &pfx_2500, FIB_SOURCE_API);
8786 * An MPLS mulicast entry
8788 fib_prefix_t pfx_3500 = {
8790 .fp_proto = FIB_PROTOCOL_MPLS,
8793 .fp_payload_proto = DPO_PROTO_IP4,
8795 fib_test_rep_bucket_t mc_0 = {
8796 .type = FT_REP_LABEL_O_ADJ,
8798 .adj = ai_mpls_10_10_10_1,
8803 fib_test_rep_bucket_t mc_intf_0 = {
8804 .type = FT_REP_INTF,
8806 .adj = idpo.dpoi_index,
8809 fib_mpls_label_t *l3300 = NULL, fml_3300 = {
8812 vec_add1(l3300, fml_3300);
8814 lfe = fib_table_entry_update_one_path(lfib_index,
8817 FIB_ENTRY_FLAG_MULTICAST,
8820 tm->hw[0]->sw_if_index,
8821 ~0, // invalid fib index
8824 FIB_ROUTE_PATH_FLAG_NONE);
8825 FIB_TEST(fib_test_validate_entry(lfe,
8826 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8829 "3500 via replicate over 10.10.10.1");
8832 * MPLS Bud-node. Add a replication via an interface-receieve path
8834 lfe = fib_table_entry_path_add(lfib_index,
8837 FIB_ENTRY_FLAG_MULTICAST,
8840 tm->hw[0]->sw_if_index,
8841 ~0, // invalid fib index
8844 FIB_ROUTE_PATH_INTF_RX);
8845 FIB_TEST(fib_test_validate_entry(lfe,
8846 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8850 "3500 via replicate over 10.10.10.1 and interface-rx");
8853 * Add a replication via an interface-free for-us path
8855 fib_test_rep_bucket_t mc_disp = {
8856 .type = FT_REP_DISP_MFIB_LOOKUP,
8858 .adj = idpo.dpoi_index,
8861 lfe = fib_table_entry_path_add(lfib_index,
8864 FIB_ENTRY_FLAG_MULTICAST,
8871 FIB_ROUTE_PATH_RPF_ID);
8872 FIB_TEST(fib_test_validate_entry(lfe,
8873 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8878 "3500 via replicate over 10.10.10.1 and interface-rx");
8882 fib_table_entry_delete(fib_index, &pfx_3500, FIB_SOURCE_API);
8888 mpls_sw_interface_enable_disable(&mpls_main,
8889 tm->hw[0]->sw_if_index,
8891 mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
8893 FIB_TEST(0 == pool_elts(mpls_disp_dpo_pool),
8894 "mpls_disp_dpo resources freed %d of %d",
8895 0, pool_elts(mpls_disp_dpo_pool));
8896 FIB_TEST(lb_count == pool_elts(load_balance_pool),
8897 "Load-balance resources freed %d of %d",
8898 lb_count, pool_elts(load_balance_pool));
8899 FIB_TEST(0 == pool_elts(interface_rx_dpo_pool),
8900 "interface_rx_dpo resources freed %d of %d",
8901 0, pool_elts(interface_rx_dpo_pool));
8907 fib_test_inherit (void)
8909 fib_node_index_t fei;
8913 n_feis = fib_entry_pool_size();
8916 const ip46_address_t nh_10_10_10_1 = {
8917 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
8919 const ip46_address_t nh_10_10_10_2 = {
8920 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
8922 const ip46_address_t nh_10_10_10_16 = {
8923 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a10),
8925 const ip46_address_t nh_10_10_10_20 = {
8926 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a14),
8928 const ip46_address_t nh_10_10_10_21 = {
8929 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a15),
8931 const ip46_address_t nh_10_10_10_22 = {
8932 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a16),
8934 const ip46_address_t nh_10_10_10_255 = {
8935 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0aff),
8937 const ip46_address_t nh_10_10_10_0 = {
8938 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a00),
8940 const ip46_address_t nh_10_10_0_0 = {
8941 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0000),
8945 * prefixes at the base of a sub-tree
8947 const fib_prefix_t pfx_10_10_10_21_s_32 = {
8949 .fp_proto = FIB_PROTOCOL_IP4,
8950 .fp_addr = nh_10_10_10_21,
8952 const fib_prefix_t pfx_10_10_10_22_s_32 = {
8954 .fp_proto = FIB_PROTOCOL_IP4,
8955 .fp_addr = nh_10_10_10_22,
8957 const fib_prefix_t pfx_10_10_10_255_s_32 = {
8959 .fp_proto = FIB_PROTOCOL_IP4,
8960 .fp_addr = nh_10_10_10_255,
8963 fib_table_entry_special_add(0,
8964 &pfx_10_10_10_21_s_32,
8966 FIB_ENTRY_FLAG_DROP);
8967 fib_table_entry_special_add(0,
8968 &pfx_10_10_10_22_s_32,
8970 FIB_ENTRY_FLAG_DROP);
8971 fib_table_entry_special_add(0,
8972 &pfx_10_10_10_255_s_32,
8974 FIB_ENTRY_FLAG_DROP);
8977 * source an entry that pushes its state down the sub-tree
8979 const fib_prefix_t pfx_10_10_10_16_s_28 = {
8981 .fp_proto = FIB_PROTOCOL_IP4,
8982 .fp_addr = nh_10_10_10_16,
8984 fib_table_entry_update_one_path(0,
8985 &pfx_10_10_10_16_s_28,
8987 FIB_ENTRY_FLAG_COVERED_INHERIT,
8990 tm->hw[0]->sw_if_index,
8994 FIB_ROUTE_PATH_FLAG_NONE);
8997 * this covering entry and all those below it should have
8998 * the same forwarding information.
9000 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9003 tm->hw[0]->sw_if_index);
9004 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
9007 .adj = ai_10_10_10_1,
9011 fei = fib_table_lookup(0, &pfx_10_10_10_16_s_28);
9012 FIB_TEST(fib_test_validate_entry(fei,
9013 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9016 "%U via 10.10.10.1",
9017 format_fib_prefix, &pfx_10_10_10_16_s_28);
9018 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9019 FIB_TEST(fib_test_validate_entry(fei,
9020 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9023 "%U via 10.10.10.1",
9024 format_fib_prefix, &pfx_10_10_10_21_s_32);
9025 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9026 FIB_TEST(fib_test_validate_entry(fei,
9027 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9030 "%U via 10.10.10.1",
9031 format_fib_prefix, &pfx_10_10_10_22_s_32);
9032 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9033 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9034 "%U resolves via drop",
9035 format_fib_prefix, &pfx_10_10_10_255_s_32);
9038 * remove the inherting cover - covereds go back to drop
9040 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_API);
9042 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9043 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9044 "%U resolves via drop",
9045 format_fib_prefix, &pfx_10_10_10_21_s_32);
9048 * source an entry that pushes its state down the sub-tree
9050 const fib_prefix_t pfx_10_10_10_0_s_24 = {
9052 .fp_proto = FIB_PROTOCOL_IP4,
9053 .fp_addr = nh_10_10_10_0,
9055 fib_table_entry_update_one_path(0,
9056 &pfx_10_10_10_0_s_24,
9058 FIB_ENTRY_FLAG_COVERED_INHERIT,
9061 tm->hw[0]->sw_if_index,
9065 FIB_ROUTE_PATH_FLAG_NONE);
9068 * whole sub-tree now covered
9070 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9071 FIB_TEST(fib_test_validate_entry(fei,
9072 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9075 "%U via 10.10.10.1",
9076 format_fib_prefix, &pfx_10_10_10_0_s_24);
9077 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9078 FIB_TEST(fib_test_validate_entry(fei,
9079 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9082 "%U via 10.10.10.1",
9083 format_fib_prefix, &pfx_10_10_10_21_s_32);
9084 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9085 FIB_TEST(fib_test_validate_entry(fei,
9086 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9089 "%U via 10.10.10.1",
9090 format_fib_prefix, &pfx_10_10_10_22_s_32);
9091 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9092 FIB_TEST(fib_test_validate_entry(fei,
9093 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9096 "%U via 10.10.10.1",
9097 format_fib_prefix, &pfx_10_10_10_255_s_32);
9100 * insert a more specific into the sub-tree - expect inheritance
9101 * this one is directly covered by the root
9103 fib_table_entry_special_add(0,
9104 &pfx_10_10_10_16_s_28,
9106 FIB_ENTRY_FLAG_DROP);
9107 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9108 FIB_TEST(fib_test_validate_entry(fei,
9109 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9112 "%U via 10.10.10.1",
9113 format_fib_prefix, &pfx_10_10_10_16_s_28);
9116 * insert a more specific into the sub-tree - expect inheritance
9117 * this one is indirectly covered by the root
9119 const fib_prefix_t pfx_10_10_10_20_s_30 = {
9121 .fp_proto = FIB_PROTOCOL_IP4,
9122 .fp_addr = nh_10_10_10_20,
9124 fib_table_entry_special_add(0,
9125 &pfx_10_10_10_20_s_30,
9127 FIB_ENTRY_FLAG_DROP);
9128 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_20_s_30);
9129 FIB_TEST(fib_test_validate_entry(fei,
9130 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9133 "%U via 10.10.10.1",
9134 format_fib_prefix, &pfx_10_10_10_20_s_30);
9137 * remove the prefix from the middle of the sub-tree
9138 * the inherited source will be the only one remaining - expect
9139 * it to be withdrawn and hence the prefix is removed.
9141 fib_table_entry_special_remove(0,
9142 &pfx_10_10_10_20_s_30,
9144 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_20_s_30);
9145 FIB_TEST((FIB_NODE_INDEX_INVALID == fei),
9147 format_fib_prefix, &pfx_10_10_10_20_s_30);
9150 * inheriting source is modifed - expect the modification to be present
9151 * throughout the sub-tree
9153 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9156 tm->hw[0]->sw_if_index);
9157 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
9160 .adj = ai_10_10_10_2,
9164 fib_table_entry_update_one_path(0,
9165 &pfx_10_10_10_0_s_24,
9167 FIB_ENTRY_FLAG_COVERED_INHERIT,
9170 tm->hw[0]->sw_if_index,
9174 FIB_ROUTE_PATH_FLAG_NONE);
9175 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9176 FIB_TEST(fib_test_validate_entry(fei,
9177 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9180 "%U via 10.10.10.2",
9181 format_fib_prefix, &pfx_10_10_10_21_s_32);
9182 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9183 FIB_TEST(fib_test_validate_entry(fei,
9184 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9187 "%U via 10.10.10.2",
9188 format_fib_prefix, &pfx_10_10_10_22_s_32);
9189 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9190 FIB_TEST(fib_test_validate_entry(fei,
9191 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9194 "%U via 10.10.10.2",
9195 format_fib_prefix, &pfx_10_10_10_255_s_32);
9196 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9197 FIB_TEST(fib_test_validate_entry(fei,
9198 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9201 "%U via 10.10.10.2",
9202 format_fib_prefix, &pfx_10_10_10_0_s_24);
9205 * add the source that replaces inherited state.
9206 * inheriting source is not the best, so it doesn't push state.
9208 fib_table_entry_update_one_path(0,
9209 &pfx_10_10_10_0_s_24,
9210 FIB_SOURCE_PLUGIN_HI,
9211 FIB_ENTRY_FLAG_NONE,
9214 tm->hw[0]->sw_if_index,
9218 FIB_ROUTE_PATH_FLAG_NONE);
9219 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9220 FIB_TEST(fib_test_validate_entry(fei,
9221 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9224 "%U via 10.10.10.1",
9225 format_fib_prefix, &pfx_10_10_10_0_s_24);
9227 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9228 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9229 "%U resolves via drop",
9230 format_fib_prefix, &pfx_10_10_10_21_s_32);
9231 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9232 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9233 "%U resolves via drop",
9234 format_fib_prefix, &pfx_10_10_10_22_s_32);
9235 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9236 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9237 "%U resolves via drop",
9238 format_fib_prefix, &pfx_10_10_10_255_s_32);
9239 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9240 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9241 "%U resolves via drop",
9242 format_fib_prefix, &pfx_10_10_10_16_s_28);
9245 * withdraw the higher priority source and expect the inherited to return
9246 * throughout the sub-tree
9248 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, FIB_SOURCE_PLUGIN_HI);
9250 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9251 FIB_TEST(fib_test_validate_entry(fei,
9252 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9255 "%U via 10.10.10.2",
9256 format_fib_prefix, &pfx_10_10_10_21_s_32);
9257 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9258 FIB_TEST(fib_test_validate_entry(fei,
9259 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9262 "%U via 10.10.10.2",
9263 format_fib_prefix, &pfx_10_10_10_22_s_32);
9264 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9265 FIB_TEST(fib_test_validate_entry(fei,
9266 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9269 "%U via 10.10.10.2",
9270 format_fib_prefix, &pfx_10_10_10_255_s_32);
9271 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9272 FIB_TEST(fib_test_validate_entry(fei,
9273 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9276 "%U via 10.10.10.2",
9277 format_fib_prefix, &pfx_10_10_10_0_s_24);
9278 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9279 FIB_TEST(fib_test_validate_entry(fei,
9280 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9283 "%U via 10.10.10.2",
9284 format_fib_prefix, &pfx_10_10_10_16_s_28);
9287 * source a covered entry in the sub-tree with the same inherting source
9288 * - expect that it now owns the sub-tree and thus over-rides its cover
9290 fib_table_entry_update_one_path(0,
9291 &pfx_10_10_10_16_s_28,
9293 FIB_ENTRY_FLAG_COVERED_INHERIT,
9296 tm->hw[0]->sw_if_index,
9300 FIB_ROUTE_PATH_FLAG_NONE);
9301 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9302 FIB_TEST(fib_test_validate_entry(fei,
9303 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9306 "%U via 10.10.10.1",
9307 format_fib_prefix, &pfx_10_10_10_16_s_28);
9308 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9309 FIB_TEST(fib_test_validate_entry(fei,
9310 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9313 "%U via 10.10.10.2",
9314 format_fib_prefix, &pfx_10_10_10_22_s_32);
9315 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9316 FIB_TEST(fib_test_validate_entry(fei,
9317 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9320 "%U via 10.10.10.2",
9321 format_fib_prefix, &pfx_10_10_10_21_s_32);
9323 /* these two unaffected by the sub-tree change */
9324 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9325 FIB_TEST(fib_test_validate_entry(fei,
9326 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9329 "%U via 10.10.10.2",
9330 format_fib_prefix, &pfx_10_10_10_255_s_32);
9331 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9332 FIB_TEST(fib_test_validate_entry(fei,
9333 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9336 "%U via 10.10.10.2",
9337 format_fib_prefix, &pfx_10_10_10_0_s_24);
9340 * removes the more specific, expect the /24 to now re-owns the sub-tree
9342 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_API);
9344 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9345 FIB_TEST(fib_test_validate_entry(fei,
9346 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9349 "%U via 10.10.10.2",
9350 format_fib_prefix, &pfx_10_10_10_16_s_28);
9351 FIB_TEST(fib_test_validate_entry(fei,
9352 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9355 "%U via 10.10.10.2",
9356 format_fib_prefix, &pfx_10_10_10_21_s_32);
9357 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9358 FIB_TEST(fib_test_validate_entry(fei,
9359 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9362 "%U via 10.10.10.2",
9363 format_fib_prefix, &pfx_10_10_10_22_s_32);
9364 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9365 FIB_TEST(fib_test_validate_entry(fei,
9366 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9369 "%U via 10.10.10.2",
9370 format_fib_prefix, &pfx_10_10_10_255_s_32);
9371 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9372 FIB_TEST(fib_test_validate_entry(fei,
9373 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9376 "%U via 10.10.10.2",
9377 format_fib_prefix, &pfx_10_10_10_0_s_24);
9379 * modify the /24. expect the new forwarding to be pushed down
9381 fib_table_entry_update_one_path(0,
9382 &pfx_10_10_10_0_s_24,
9384 FIB_ENTRY_FLAG_COVERED_INHERIT,
9387 tm->hw[0]->sw_if_index,
9391 FIB_ROUTE_PATH_FLAG_NONE);
9392 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9393 FIB_TEST(fib_test_validate_entry(fei,
9394 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9397 "%U via 10.10.10.1",
9398 format_fib_prefix, &pfx_10_10_10_16_s_28);
9399 FIB_TEST(fib_test_validate_entry(fei,
9400 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9403 "%U via 10.10.10.1",
9404 format_fib_prefix, &pfx_10_10_10_21_s_32);
9405 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9406 FIB_TEST(fib_test_validate_entry(fei,
9407 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9410 "%U via 10.10.10.1",
9411 format_fib_prefix, &pfx_10_10_10_22_s_32);
9412 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9413 FIB_TEST(fib_test_validate_entry(fei,
9414 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9417 "%U via 10.10.10.1",
9418 format_fib_prefix, &pfx_10_10_10_255_s_32);
9419 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9420 FIB_TEST(fib_test_validate_entry(fei,
9421 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9424 "%U via 10.10.10.1",
9425 format_fib_prefix, &pfx_10_10_10_0_s_24);
9428 * add an entry less specific to /24. it should not own the /24's tree
9430 const fib_prefix_t pfx_10_10_0_0_s_16 = {
9432 .fp_proto = FIB_PROTOCOL_IP4,
9433 .fp_addr = nh_10_10_0_0,
9435 fib_table_entry_update_one_path(0,
9436 &pfx_10_10_0_0_s_16,
9438 FIB_ENTRY_FLAG_COVERED_INHERIT,
9441 tm->hw[0]->sw_if_index,
9445 FIB_ROUTE_PATH_FLAG_NONE);
9446 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9447 FIB_TEST(fib_test_validate_entry(fei,
9448 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9451 "%U via 10.10.10.1",
9452 format_fib_prefix, &pfx_10_10_10_16_s_28);
9453 FIB_TEST(fib_test_validate_entry(fei,
9454 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9457 "%U via 10.10.10.1",
9458 format_fib_prefix, &pfx_10_10_10_21_s_32);
9459 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9460 FIB_TEST(fib_test_validate_entry(fei,
9461 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9464 "%U via 10.10.10.1",
9465 format_fib_prefix, &pfx_10_10_10_22_s_32);
9466 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9467 FIB_TEST(fib_test_validate_entry(fei,
9468 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9471 "%U via 10.10.10.1",
9472 format_fib_prefix, &pfx_10_10_10_255_s_32);
9473 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9474 FIB_TEST(fib_test_validate_entry(fei,
9475 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9478 "%U via 10.10.10.1",
9479 format_fib_prefix, &pfx_10_10_10_0_s_24);
9480 fei = fib_table_lookup_exact_match(0, &pfx_10_10_0_0_s_16);
9481 FIB_TEST(fib_test_validate_entry(fei,
9482 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9485 "%U via 10.10.10.2",
9486 format_fib_prefix, &pfx_10_10_0_0_s_16);
9491 fib_table_entry_delete(0, &pfx_10_10_10_21_s_32, FIB_SOURCE_CLI);
9492 fib_table_entry_delete(0, &pfx_10_10_10_22_s_32, FIB_SOURCE_CLI);
9493 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_CLI);
9494 fib_table_entry_delete(0, &pfx_10_10_10_255_s_32, FIB_SOURCE_CLI);
9495 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, FIB_SOURCE_API);
9496 fib_table_entry_delete(0, &pfx_10_10_0_0_s_16, FIB_SOURCE_API);
9497 adj_unlock(ai_10_10_10_1);
9498 adj_unlock(ai_10_10_10_2);
9501 * test the v6 tree walk.
9502 * a /64 that covers everytinhg. a /96 that covers one /128
9503 * a second /128 covered only by the /64.
9505 const fib_prefix_t pfx_2001_s_64 = {
9507 .fp_proto = FIB_PROTOCOL_IP6,
9511 [0] = clib_host_to_net_u64(0x2001000000000000),
9512 [1] = clib_host_to_net_u64(0x0000000000000000),
9517 const fib_prefix_t pfx_2001_1_s_96 = {
9519 .fp_proto = FIB_PROTOCOL_IP6,
9523 [0] = clib_host_to_net_u64(0x2001000000000000),
9524 [1] = clib_host_to_net_u64(0x1000000000000000),
9529 const fib_prefix_t pfx_2001_1_1_s_128 = {
9531 .fp_proto = FIB_PROTOCOL_IP6,
9535 [0] = clib_host_to_net_u64(0x2001000000000000),
9536 [1] = clib_host_to_net_u64(0x1000000000000001),
9541 const fib_prefix_t pfx_2001_0_1_s_128 = {
9543 .fp_proto = FIB_PROTOCOL_IP6,
9547 [0] = clib_host_to_net_u64(0x2001000000000000),
9548 [1] = clib_host_to_net_u64(0x0000000000000001),
9553 const ip46_address_t nh_3000_1 = {
9556 [0] = clib_host_to_net_u64(0x3000000000000000),
9557 [1] = clib_host_to_net_u64(0x0000000000000001),
9561 const ip46_address_t nh_3000_2 = {
9564 [0] = clib_host_to_net_u64(0x3000000000000000),
9565 [1] = clib_host_to_net_u64(0x0000000000000002),
9569 adj_index_t ai_3000_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
9572 tm->hw[0]->sw_if_index);
9573 adj_index_t ai_3000_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
9576 tm->hw[0]->sw_if_index);
9577 fib_test_lb_bucket_t adj_o_3000_1 = {
9583 fib_test_lb_bucket_t adj_o_3000_2 = {
9590 fib_table_entry_special_add(0,
9591 &pfx_2001_0_1_s_128,
9593 FIB_ENTRY_FLAG_DROP);
9594 fib_table_entry_special_add(0,
9595 &pfx_2001_1_1_s_128,
9597 FIB_ENTRY_FLAG_DROP);
9600 * /96 has inherited forwarding pushed down to its covered /128
9602 fib_table_entry_update_one_path(0,
9605 FIB_ENTRY_FLAG_COVERED_INHERIT,
9608 tm->hw[0]->sw_if_index,
9612 FIB_ROUTE_PATH_FLAG_NONE);
9613 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_s_96);
9614 FIB_TEST(fib_test_validate_entry(fei,
9615 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
9619 format_fib_prefix, &pfx_2001_1_s_96);
9620 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_1_s_128);
9621 FIB_TEST(fib_test_validate_entry(fei,
9622 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
9626 format_fib_prefix, &pfx_2001_1_1_s_128);
9627 fei = fib_table_lookup_exact_match(0, &pfx_2001_0_1_s_128);
9628 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9629 "%U resolves via drop",
9630 format_fib_prefix, &pfx_2001_0_1_s_128);
9633 * /64 has inherited forwarding pushed down to all, but the /96
9634 * and its sub-tree remain unaffected.
9636 fib_table_entry_update_one_path(0,
9639 FIB_ENTRY_FLAG_COVERED_INHERIT,
9642 tm->hw[0]->sw_if_index,
9646 FIB_ROUTE_PATH_FLAG_NONE);
9648 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
9649 FIB_TEST(fib_test_validate_entry(fei,
9650 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
9654 format_fib_prefix, &pfx_2001_s_64);
9655 fei = fib_table_lookup_exact_match(0, &pfx_2001_0_1_s_128);
9656 FIB_TEST(fib_test_validate_entry(fei,
9657 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
9661 format_fib_prefix, &pfx_2001_0_1_s_128);
9663 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_s_96);
9664 FIB_TEST(fib_test_validate_entry(fei,
9665 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
9669 format_fib_prefix, &pfx_2001_1_s_96);
9670 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_1_s_128);
9671 FIB_TEST(fib_test_validate_entry(fei,
9672 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
9676 format_fib_prefix, &pfx_2001_1_1_s_128);
9681 fib_table_entry_delete(0, &pfx_2001_0_1_s_128, FIB_SOURCE_CLI);
9682 fib_table_entry_delete(0, &pfx_2001_1_1_s_128, FIB_SOURCE_CLI);
9683 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
9684 fib_table_entry_delete(0, &pfx_2001_1_s_96, FIB_SOURCE_API);
9685 adj_unlock(ai_3000_1);
9686 adj_unlock(ai_3000_2);
9689 * test no-one left behind
9691 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
9692 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
9696 static clib_error_t *
9697 fib_test (vlib_main_t * vm,
9698 unformat_input_t * input,
9699 vlib_cli_command_t * cmd_arg)
9704 fib_test_mk_intf(4);
9706 if (unformat (input, "debug"))
9708 fib_test_do_debug = 1;
9711 if (unformat (input, "ip"))
9713 res += fib_test_v4();
9714 res += fib_test_v6();
9716 else if (unformat (input, "label"))
9718 res += fib_test_label();
9720 else if (unformat (input, "ae"))
9722 res += fib_test_ae();
9724 else if (unformat (input, "pref"))
9726 res += fib_test_pref();
9728 else if (unformat (input, "lfib"))
9732 else if (unformat (input, "walk"))
9734 res += fib_test_walk();
9736 else if (unformat (input, "bfd"))
9738 res += fib_test_bfd();
9740 else if (unformat (input, "inherit"))
9742 res += fib_test_inherit();
9746 res += fib_test_v4();
9747 res += fib_test_v6();
9748 res += fib_test_ae();
9749 res += fib_test_bfd();
9750 res += fib_test_pref();
9751 res += fib_test_label();
9752 res += fib_test_inherit();
9756 * fib-walk process must be disabled in order for the walk tests to work
9758 fib_walk_process_disable();
9759 res += fib_test_walk();
9760 fib_walk_process_enable();
9765 return clib_error_return(0, "FIB Unit Test Failed");
9773 VLIB_CLI_COMMAND (test_fib_command, static) = {
9775 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
9776 .function = fib_test,
9780 fib_test_init (vlib_main_t *vm)
9785 VLIB_INIT_FUNCTION (fib_test_init);