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>
44 * Add debugs for passing tests
46 static int fib_test_do_debug;
48 #define FIB_TEST_I(_cond, _comment, _args...) \
50 int _evald = (_cond); \
52 fformat(stderr, "FAIL:%d: " _comment "\n", \
55 if (fib_test_do_debug) \
56 fformat(stderr, "PASS:%d: " _comment "\n", \
61 #define FIB_TEST(_cond, _comment, _args...) \
63 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
65 ASSERT(!("FAIL: " _comment)); \
70 * A 'i'm not fussed is this is not efficient' store of test data
72 typedef struct test_main_t_ {
76 u32 hw_if_indicies[4];
80 vnet_hw_interface_t * hw[4];
83 static test_main_t test_main;
85 /* fake ethernet device class, distinct from "fake-ethX" */
86 static u8 * format_test_interface_name (u8 * s, va_list * args)
88 u32 dev_instance = va_arg (*args, u32);
89 return format (s, "test-eth%d", dev_instance);
92 static uword dummy_interface_tx (vlib_main_t * vm,
93 vlib_node_runtime_t * node,
96 clib_warning ("you shouldn't be here, leaking buffers...");
97 return frame->n_vectors;
100 static clib_error_t *
101 test_interface_admin_up_down (vnet_main_t * vnm,
105 u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
106 VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
107 vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
111 VNET_DEVICE_CLASS (test_interface_device_class,static) = {
112 .name = "Test interface",
113 .format_device_name = format_test_interface_name,
114 .tx_function = dummy_interface_tx,
115 .admin_up_down_function = test_interface_admin_up_down,
118 static u8 *hw_address;
121 fib_test_mk_intf (u32 ninterfaces)
123 clib_error_t * error = NULL;
124 test_main_t *tm = &test_main;
128 ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
133 vec_add1(hw_address, byte);
136 for (i = 0; i < ninterfaces; i++)
140 error = ethernet_register_interface(vnet_get_main(),
141 test_interface_device_class.index,
144 &tm->hw_if_indicies[i],
145 /* flag change */ 0);
147 FIB_TEST((NULL == error), "ADD interface %d", i);
149 error = vnet_hw_interface_set_flags(vnet_get_main(),
150 tm->hw_if_indicies[i],
151 VNET_HW_INTERFACE_FLAG_LINK_UP);
152 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
153 tm->hw_if_indicies[i]);
154 vec_validate (ip4_main.fib_index_by_sw_if_index,
155 tm->hw[i]->sw_if_index);
156 vec_validate (ip6_main.fib_index_by_sw_if_index,
157 tm->hw[i]->sw_if_index);
158 ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
159 ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
161 error = vnet_sw_interface_set_flags(vnet_get_main(),
162 tm->hw[i]->sw_if_index,
163 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
164 FIB_TEST((NULL == error), "UP interface %d", i);
167 * re-eval after the inevitable realloc
169 for (i = 0; i < ninterfaces; i++)
171 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
172 tm->hw_if_indicies[i]);
178 #define FIB_TEST_REC_FORW(_rec_prefix, _via_prefix, _bucket) \
180 const dpo_id_t *_rec_dpo = fib_entry_contribute_ip_forwarding( \
181 fib_table_lookup_exact_match(fib_index, (_rec_prefix))); \
182 const dpo_id_t *_via_dpo = fib_entry_contribute_ip_forwarding( \
183 fib_table_lookup(fib_index, (_via_prefix))); \
184 FIB_TEST(!dpo_cmp(_via_dpo, \
185 load_balance_get_bucket(_rec_dpo->dpoi_index, \
187 "%U is recursive via %U", \
188 format_fib_prefix, (_rec_prefix), \
189 format_fib_prefix, _via_prefix); \
192 #define FIB_TEST_LB_BUCKET_VIA_ADJ(_prefix, _bucket, _ai) \
194 const dpo_id_t *_dpo = fib_entry_contribute_ip_forwarding( \
195 fib_table_lookup_exact_match(fib_index, (_prefix))); \
196 const dpo_id_t *_dpo1 = \
197 load_balance_get_bucket(_dpo->dpoi_index, _bucket); \
198 FIB_TEST(DPO_ADJACENCY == _dpo1->dpoi_type, "type is %U", \
199 format_dpo_type, _dpo1->dpoi_type); \
200 FIB_TEST((_ai == _dpo1->dpoi_index), \
201 "%U bucket %d resolves via %U", \
202 format_fib_prefix, (_prefix), \
204 format_dpo_id, _dpo1, 0); \
207 #define FIB_TEST_RPF(_cond, _comment, _args...) \
209 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
215 fib_test_urpf_is_equal (fib_node_index_t fei,
216 fib_forward_chain_type_t fct,
219 dpo_id_t dpo = DPO_INVALID;
220 fib_urpf_list_t *urpf;
227 fib_entry_contribute_forwarding(fei, fct, &dpo);
228 ui = load_balance_get_urpf(dpo.dpoi_index);
230 urpf = fib_urpf_list_get(ui);
232 FIB_TEST_RPF(num == vec_len(urpf->furpf_itfs),
233 "RPF:%U len %d == %d",
234 format_fib_urpf_list, ui,
235 num, vec_len(urpf->furpf_itfs));
236 FIB_TEST_RPF(num == fib_urpf_check_size(ui),
237 "RPF:%U check-size %d == %d",
238 format_fib_urpf_list, ui,
239 num, vec_len(urpf->furpf_itfs));
241 for (ii = 0; ii < num; ii++)
243 adj_index_t ai = va_arg(ap, adj_index_t);
245 FIB_TEST_RPF(ai == urpf->furpf_itfs[ii],
246 "RPF:%d item:%d - %d == %d",
247 ui, ii, ai, urpf->furpf_itfs[ii]);
248 FIB_TEST_RPF(fib_urpf_check(ui, ai),
261 fib_test_build_rewrite (u8 *eth_addr)
265 vec_validate(rewrite, 13);
267 memcpy(rewrite, eth_addr, 6);
268 memcpy(rewrite+6, eth_addr, 6);
273 #define FIB_TEST_LB(_cond, _comment, _args...) \
275 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
281 fib_test_validate_rep_v (const replicate_t *rep,
285 const fib_test_rep_bucket_t *exp;
289 FIB_TEST_LB((n_buckets == rep->rep_n_buckets),
290 "n_buckets = %d", rep->rep_n_buckets);
292 for (bucket = 0; bucket < n_buckets; bucket++)
294 exp = va_arg(*ap, fib_test_rep_bucket_t*);
296 dpo = replicate_get_bucket_i(rep, bucket);
300 case FT_REP_LABEL_O_ADJ:
302 const mpls_label_dpo_t *mld;
304 FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE)
306 "bucket %d stacks on %U",
308 format_dpo_type, dpo->dpoi_type);
310 mld = mpls_label_dpo_get(dpo->dpoi_index);
311 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
313 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
314 exp->label_o_adj.label),
315 "bucket %d stacks on label %d",
317 exp->label_o_adj.label);
319 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
320 exp->label_o_adj.eos),
321 "bucket %d stacks on label %d %U",
323 exp->label_o_adj.label,
324 format_mpls_eos_bit, exp->label_o_adj.eos);
326 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
327 "bucket %d label stacks on %U",
329 format_dpo_type, mld->mld_dpo.dpoi_type);
331 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
332 "bucket %d label stacks on adj %d",
334 exp->label_o_adj.adj);
338 FIB_TEST_LB((DPO_INTERFACE_RX == dpo->dpoi_type),
339 "bucket %d stacks on %U",
341 format_dpo_type, dpo->dpoi_type);
343 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
344 "bucket %d stacks on adj %d",
348 case FT_REP_DISP_MFIB_LOOKUP:
358 fib_test_validate_lb_v (const load_balance_t *lb,
365 FIB_TEST_LB((n_buckets == lb->lb_n_buckets), "n_buckets = %d", lb->lb_n_buckets);
367 for (bucket = 0; bucket < n_buckets; bucket++)
369 const fib_test_lb_bucket_t *exp;
371 exp = va_arg(*ap, fib_test_lb_bucket_t*);
372 dpo = load_balance_get_bucket_i(lb, bucket);
376 case FT_LB_LABEL_STACK_O_ADJ:
378 const mpls_label_dpo_t *mld;
379 mpls_label_dpo_flags_t mf;
383 mf = ((exp->label_stack_o_adj.mode ==
384 FIB_MPLS_LSP_MODE_UNIFORM) ?
385 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
386 MPLS_LABEL_DPO_FLAG_NONE);
387 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
388 "bucket %d stacks on %U",
390 format_dpo_type, dpo->dpoi_type);
392 mld = mpls_label_dpo_get(dpo->dpoi_index);
394 FIB_TEST_LB(exp->label_stack_o_adj.label_stack_size == mld->mld_n_labels,
398 for (ii = 0; ii < mld->mld_n_labels; ii++)
400 hdr = clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
401 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
402 exp->label_stack_o_adj.label_stack[ii]),
403 "bucket %d stacks on label %d",
405 exp->label_stack_o_adj.label_stack[ii]);
407 if (ii == mld->mld_n_labels-1)
409 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
410 exp->label_o_adj.eos),
411 "bucket %d stacks on label %d %U!=%U",
413 exp->label_stack_o_adj.label_stack[ii],
414 format_mpls_eos_bit, exp->label_o_adj.eos,
415 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
419 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) == MPLS_NON_EOS),
420 "bucket %d stacks on label %d %U",
422 exp->label_stack_o_adj.label_stack[ii],
423 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
427 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
428 "bucket %d label stacks on %U",
430 format_dpo_type, mld->mld_dpo.dpoi_type);
432 FIB_TEST_LB((exp->label_stack_o_adj.adj == mld->mld_dpo.dpoi_index),
433 "bucket %d label stacks on adj %d",
435 exp->label_stack_o_adj.adj);
438 case FT_LB_LABEL_O_ADJ:
440 const mpls_label_dpo_t *mld;
442 FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE)
444 "bucket %d stacks on %U",
446 format_dpo_type, dpo->dpoi_type);
448 mld = mpls_label_dpo_get(dpo->dpoi_index);
449 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
451 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
452 exp->label_o_adj.label),
453 "bucket %d stacks on label %d",
455 exp->label_o_adj.label);
457 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
458 exp->label_o_adj.eos),
459 "bucket %d stacks on label %d %U",
461 exp->label_o_adj.label,
462 format_mpls_eos_bit, exp->label_o_adj.eos);
464 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
465 "bucket %d label stacks on %U",
467 format_dpo_type, mld->mld_dpo.dpoi_type);
469 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
470 "bucket %d label stacks on adj %d",
472 exp->label_o_adj.adj);
475 case FT_LB_LABEL_O_LB:
477 const mpls_label_dpo_t *mld;
478 mpls_label_dpo_flags_t mf;
481 mf = ((exp->label_o_lb.mode ==
482 FIB_MPLS_LSP_MODE_UNIFORM) ?
483 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
484 MPLS_LABEL_DPO_FLAG_NONE);
485 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
486 "bucket %d stacks on %U",
488 format_dpo_type, dpo->dpoi_type);
490 mld = mpls_label_dpo_get(dpo->dpoi_index);
491 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
493 FIB_TEST_LB(1 == mld->mld_n_labels, "label stack size",
495 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
496 exp->label_o_lb.label),
497 "bucket %d stacks on label %d",
499 exp->label_o_lb.label);
501 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
502 exp->label_o_lb.eos),
503 "bucket %d stacks on label %d %U",
505 exp->label_o_lb.label,
506 format_mpls_eos_bit, exp->label_o_lb.eos);
508 FIB_TEST_LB((DPO_LOAD_BALANCE == mld->mld_dpo.dpoi_type),
509 "bucket %d label stacks on %U",
511 format_dpo_type, mld->mld_dpo.dpoi_type);
513 FIB_TEST_LB((exp->label_o_lb.lb == mld->mld_dpo.dpoi_index),
514 "bucket %d label stacks on LB %d",
520 FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
521 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
522 "bucket %d stacks on %U",
524 format_dpo_type, dpo->dpoi_type);
525 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
526 "bucket %d stacks on adj %d",
530 case FT_LB_MPLS_DISP_PIPE_O_ADJ:
532 const mpls_disp_dpo_t *mdd;
534 FIB_TEST_I((DPO_MPLS_DISPOSITION_PIPE == dpo->dpoi_type),
535 "bucket %d stacks on %U",
537 format_dpo_type, dpo->dpoi_type);
539 mdd = mpls_disp_dpo_get(dpo->dpoi_index);
543 FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
544 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
545 "bucket %d stacks on %U",
547 format_dpo_type, dpo->dpoi_type);
548 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
549 "bucket %d stacks on adj %d",
555 FIB_TEST_I((DPO_INTERFACE_RX == dpo->dpoi_type),
556 "bucket %d stacks on %U",
558 format_dpo_type, dpo->dpoi_type);
559 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
560 "bucket %d stacks on adj %d",
565 FIB_TEST_I((DPO_DVR == dpo->dpoi_type),
566 "bucket %d stacks on %U",
568 format_dpo_type, dpo->dpoi_type);
569 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
570 "bucket %d stacks on adj %d",
575 FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
576 "bucket %d stacks on %U",
578 format_dpo_type, dpo->dpoi_type);
579 FIB_TEST_LB((exp->lb.lb == dpo->dpoi_index),
580 "bucket %d stacks on lb %d not %d",
585 case FT_LB_BIER_TABLE:
586 FIB_TEST_LB((DPO_BIER_TABLE == dpo->dpoi_type),
587 "bucket %d stacks on %U",
589 format_dpo_type, dpo->dpoi_type);
590 FIB_TEST_LB((exp->bier.table == dpo->dpoi_index),
591 "bucket %d stacks on lb %d",
595 case FT_LB_BIER_FMASK:
596 FIB_TEST_LB((DPO_BIER_FMASK == dpo->dpoi_type),
597 "bucket %d stacks on %U",
599 format_dpo_type, dpo->dpoi_type);
600 FIB_TEST_LB((exp->bier.fmask == dpo->dpoi_index),
601 "bucket %d stacks on lb %d",
606 FIB_TEST_LB((DPO_DROP == dpo->dpoi_type),
607 "bucket %d stacks on %U",
609 format_dpo_type, dpo->dpoi_type);
617 fib_test_validate_lb (const dpo_id_t *dpo,
621 const load_balance_t *lb;
625 va_start(ap, n_buckets);
627 if (FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
629 format_dpo_type, dpo->dpoi_type))
631 lb = load_balance_get(dpo->dpoi_index);
633 res = fib_test_validate_lb_v(lb, n_buckets, &ap);
646 fib_test_validate_entry (fib_node_index_t fei,
647 fib_forward_chain_type_t fct,
651 dpo_id_t dpo = DPO_INVALID;
658 va_start(ap, n_buckets);
660 fib_entry_get_prefix(fei, &pfx);
661 fib_index = fib_entry_get_fib_index(fei);
662 fib_entry_contribute_forwarding(fei, fct, &dpo);
664 if (DPO_REPLICATE == dpo.dpoi_type)
666 const replicate_t *rep;
668 rep = replicate_get(dpo.dpoi_index);
669 res = fib_test_validate_rep_v(rep, n_buckets, &ap);
673 const load_balance_t *lb;
675 FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type),
676 "%U Entry links to %U",
677 format_fib_prefix, &pfx,
678 format_dpo_type, dpo.dpoi_type);
680 lb = load_balance_get(dpo.dpoi_index);
681 res = fib_test_validate_lb_v(lb, n_buckets, &ap);
684 * ensure that the LB contributed by the entry is the
685 * same as the LB in the forwarding tables
687 if (fct == fib_entry_get_default_chain_type(fib_entry_get(fei)))
689 switch (pfx.fp_proto)
691 case FIB_PROTOCOL_IP4:
692 fw_lbi = ip4_fib_forwarding_lookup(fib_index, &pfx.fp_addr.ip4);
694 case FIB_PROTOCOL_IP6:
695 fw_lbi = ip6_fib_table_fwding_lookup(&ip6_main, fib_index, &pfx.fp_addr.ip6);
697 case FIB_PROTOCOL_MPLS:
699 mpls_unicast_header_t hdr = {
700 .label_exp_s_ttl = 0,
703 vnet_mpls_uc_set_label(&hdr.label_exp_s_ttl, pfx.fp_label);
704 vnet_mpls_uc_set_s(&hdr.label_exp_s_ttl, pfx.fp_eos);
705 hdr.label_exp_s_ttl = clib_host_to_net_u32(hdr.label_exp_s_ttl);
707 fw_lbi = mpls_fib_table_forwarding_lookup(fib_index, &hdr);
713 FIB_TEST_LB((fw_lbi == dpo.dpoi_index),
714 "Contributed LB = FW LB:\n fwd:%U\n cont:%U",
715 format_load_balance, fw_lbi, 0,
716 format_load_balance, dpo.dpoi_index, 0);
731 * In the default table check for the presence and correct forwarding
732 * of the special entries
734 fib_node_index_t dfrt, fei, ai, ai2, locked_ai, ai_01, ai_02, ai_03;
735 const dpo_id_t *dpo, *dpo1, *dpo2, *dpo_drop;
736 const ip_adjacency_t *adj;
737 const load_balance_t *lb;
744 ip46_address_t nh_10_10_10_1 = {
745 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
748 ip46_address_t nh_10_10_10_2 = {
749 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
752 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
753 pool_elts(load_balance_map_pool));
757 /* record the nubmer of load-balances in use before we start */
758 lb_count = pool_elts(load_balance_pool);
760 /* Find or create FIB table 11 */
761 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11,
764 for (ii = 0; ii < 4; ii++)
766 ip4_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
769 fib_prefix_t pfx_0_0_0_0_s_0 = {
771 .fp_proto = FIB_PROTOCOL_IP4,
781 .fp_proto = FIB_PROTOCOL_IP4,
789 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
791 dfrt = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
792 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
793 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
794 "Default route is DROP");
797 fei = fib_table_lookup(fib_index, &pfx);
798 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all zeros route present");
799 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
800 "all 0s route is DROP");
802 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xffffffff);
804 fei = fib_table_lookup(fib_index, &pfx);
805 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all ones route present");
806 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
807 "all 1s route is DROP");
809 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xe0000000);
811 fei = fib_table_lookup(fib_index, &pfx);
812 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all-mcast route present");
813 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
814 "all-mcast route is DROP");
816 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xf0000000);
818 fei = fib_table_lookup(fib_index, &pfx);
819 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "class-e route present");
820 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
821 "class-e route is DROP");
824 * at this stage there are 5 entries in the test FIB (plus 5 in the default),
825 * all of which are special sourced and so none of which share path-lists.
826 * There are also 2 entries, and 2 non-shared path-lists, in the v6 default
827 * table, and 4 path-lists in the v6 MFIB table
831 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
832 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
833 fib_path_list_pool_size());
834 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
835 fib_entry_pool_size());
838 * add interface routes.
839 * validate presence of /24 attached and /32 recieve.
840 * test for the presence of the receive address in the glean and local adj
842 fib_prefix_t local_pfx = {
844 .fp_proto = FIB_PROTOCOL_IP4,
847 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
852 fib_table_entry_update_one_path(fib_index, &local_pfx,
853 FIB_SOURCE_INTERFACE,
854 (FIB_ENTRY_FLAG_CONNECTED |
855 FIB_ENTRY_FLAG_ATTACHED),
858 tm->hw[0]->sw_if_index,
859 ~0, // invalid fib index
862 FIB_ROUTE_PATH_FLAG_NONE);
863 fei = fib_table_lookup(fib_index, &local_pfx);
864 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
865 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
866 fib_entry_get_flags(fei)),
867 "Flags set on attached interface");
869 ai = fib_entry_get_adj(fei);
870 FIB_TEST((FIB_NODE_INDEX_INVALID != ai),
871 "attached interface route adj present %d", ai);
873 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
874 "attached interface adj is glean");
875 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
876 &adj->sub_type.glean.receive_addr)),
877 "attached interface adj is receive ok");
879 local_pfx.fp_len = 32;
880 fib_table_entry_update_one_path(fib_index, &local_pfx,
881 FIB_SOURCE_INTERFACE,
882 (FIB_ENTRY_FLAG_CONNECTED |
883 FIB_ENTRY_FLAG_LOCAL),
886 tm->hw[0]->sw_if_index,
887 ~0, // invalid fib index
890 FIB_ROUTE_PATH_FLAG_NONE);
891 fei = fib_table_lookup(fib_index, &local_pfx);
892 FIB_TEST(((FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_CONNECTED) ==
893 fib_entry_get_flags(fei)),
894 "Flags set on local interface");
896 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
898 dpo = fib_entry_contribute_ip_forwarding(fei);
899 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
900 "RPF list for local length 0");
901 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
902 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
903 "local interface adj is local");
904 receive_dpo_t *rd = receive_dpo_get(dpo->dpoi_index);
906 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
908 "local interface adj is receive ok");
910 FIB_TEST((2 == fib_table_get_num_entries(fib_index,
912 FIB_SOURCE_INTERFACE)),
913 "2 Interface Source'd prefixes");
916 * +2 interface routes +2 non-shared path-lists
918 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
919 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
920 fib_path_list_pool_size());
921 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
922 fib_entry_pool_size());
925 * Modify the default route to be via an adj not yet known.
926 * this sources the defalut route with the API source, which is
927 * a higher preference to the DEFAULT_ROUTE source
929 pfx.fp_addr.ip4.as_u32 = 0;
931 fib_table_entry_path_add(fib_index, &pfx,
936 tm->hw[0]->sw_if_index,
937 ~0, // invalid fib index
940 FIB_ROUTE_PATH_FLAG_NONE);
941 fei = fib_table_lookup(fib_index, &pfx);
942 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
943 "Flags set on API route");
945 FIB_TEST((fei == dfrt), "default route same index");
946 ai = fib_entry_get_adj(fei);
947 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
949 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
950 "adj is incomplete");
951 FIB_TEST((0 == ip46_address_cmp(&nh_10_10_10_1, &adj->sub_type.nbr.next_hop)),
952 "adj nbr next-hop ok");
953 FIB_TEST((1 == fib_table_get_num_entries(fib_index,
956 "1 API Source'd prefixes");
959 * find the adj in the shared db
961 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
964 tm->hw[0]->sw_if_index);
965 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
966 adj_unlock(locked_ai);
969 * +1 shared path-list
971 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
972 fib_path_list_db_size());
973 FIB_TEST((PNBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
974 fib_path_list_pool_size());
975 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
976 fib_entry_pool_size());
979 * remove the API source from the default route. We expected
980 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
982 pfx.fp_addr.ip4.as_u32 = 0;
984 fib_table_entry_path_remove(fib_index, &pfx,
988 tm->hw[0]->sw_if_index,
989 ~0, // non-recursive path, so no FIB index
991 FIB_ROUTE_PATH_FLAG_NONE);
993 fei = fib_table_lookup(fib_index, &pfx);
995 FIB_TEST((fei == dfrt), "default route same index");
996 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
997 "Default route is DROP");
1000 * -1 shared-path-list
1002 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
1003 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
1004 fib_path_list_pool_size());
1005 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
1006 fib_entry_pool_size());
1009 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
1011 fib_prefix_t pfx_10_10_10_1_s_32 = {
1013 .fp_proto = FIB_PROTOCOL_IP4,
1016 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
1019 fib_prefix_t pfx_10_10_10_2_s_32 = {
1021 .fp_proto = FIB_PROTOCOL_IP4,
1024 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
1027 fib_prefix_t pfx_11_11_11_11_s_32 = {
1029 .fp_proto = FIB_PROTOCOL_IP4,
1032 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
1036 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
1039 ip46_address_t nh_12_12_12_12 = {
1040 .ip4.as_u32 = clib_host_to_net_u32(0x0c0c0c0c),
1042 adj_index_t ai_12_12_12_12;
1045 * Add a route via an incomplete ADJ. then complete the ADJ
1046 * Expect the route LB is updated to use complete adj type.
1048 fei = fib_table_entry_update_one_path(fib_index,
1049 &pfx_11_11_11_11_s_32,
1051 FIB_ENTRY_FLAG_ATTACHED,
1053 &pfx_10_10_10_1_s_32.fp_addr,
1054 tm->hw[0]->sw_if_index,
1055 ~0, // invalid fib index
1058 FIB_ROUTE_PATH_FLAG_NONE);
1060 dpo = fib_entry_contribute_ip_forwarding(fei);
1061 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1062 FIB_TEST(DPO_ADJACENCY_INCOMPLETE == dpo1->dpoi_type,
1063 "11.11.11.11/32 via incomplete adj");
1065 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1067 &pfx_10_10_10_1_s_32.fp_addr,
1068 tm->hw[0]->sw_if_index);
1069 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
1070 adj = adj_get(ai_01);
1071 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1072 "adj is incomplete");
1073 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1074 &adj->sub_type.nbr.next_hop)),
1075 "adj nbr next-hop ok");
1077 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1078 fib_test_build_rewrite(eth_addr));
1079 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1081 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1082 &adj->sub_type.nbr.next_hop)),
1083 "adj nbr next-hop ok");
1084 ai = fib_entry_get_adj(fei);
1085 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
1087 dpo = fib_entry_contribute_ip_forwarding(fei);
1088 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1089 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type,
1090 "11.11.11.11/32 via complete adj");
1091 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1092 tm->hw[0]->sw_if_index),
1093 "RPF list for adj-fib contains adj");
1095 ai_12_12_12_12 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1098 tm->hw[1]->sw_if_index);
1099 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_12_12_12_12), "adj created");
1100 adj = adj_get(ai_12_12_12_12);
1101 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1102 "adj is incomplete");
1103 FIB_TEST((0 == ip46_address_cmp(&nh_12_12_12_12,
1104 &adj->sub_type.nbr.next_hop)),
1105 "adj nbr next-hop ok");
1106 adj_nbr_update_rewrite(ai_12_12_12_12, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1107 fib_test_build_rewrite(eth_addr));
1108 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1114 fei = fib_table_entry_path_add(fib_index,
1115 &pfx_10_10_10_1_s_32,
1117 FIB_ENTRY_FLAG_ATTACHED,
1119 &pfx_10_10_10_1_s_32.fp_addr,
1120 tm->hw[0]->sw_if_index,
1121 ~0, // invalid fib index
1124 FIB_ROUTE_PATH_FLAG_NONE);
1125 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
1126 "Flags set on adj-fib");
1127 ai = fib_entry_get_adj(fei);
1128 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj, %d", ai);
1130 fib_table_entry_path_remove(fib_index,
1131 &pfx_11_11_11_11_s_32,
1134 &pfx_10_10_10_1_s_32.fp_addr,
1135 tm->hw[0]->sw_if_index,
1136 ~0, // invalid fib index
1138 FIB_ROUTE_PATH_FLAG_NONE);
1142 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1144 &pfx_10_10_10_2_s_32.fp_addr,
1145 tm->hw[0]->sw_if_index);
1146 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
1147 adj = adj_get(ai_02);
1148 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1149 "adj is incomplete");
1150 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1151 &adj->sub_type.nbr.next_hop)),
1152 "adj nbr next-hop ok");
1154 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1155 fib_test_build_rewrite(eth_addr));
1156 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1158 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1159 &adj->sub_type.nbr.next_hop)),
1160 "adj nbr next-hop ok");
1161 FIB_TEST((ai_01 != ai_02), "ADJs are different");
1163 fib_table_entry_path_add(fib_index,
1164 &pfx_10_10_10_2_s_32,
1166 FIB_ENTRY_FLAG_ATTACHED,
1168 &pfx_10_10_10_2_s_32.fp_addr,
1169 tm->hw[0]->sw_if_index,
1170 ~0, // invalid fib index
1173 FIB_ROUTE_PATH_FLAG_NONE);
1175 fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32);
1176 ai = fib_entry_get_adj(fei);
1177 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
1180 * +2 adj-fibs, and their non-shared path-lists
1182 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
1183 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
1184 fib_path_list_pool_size());
1185 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
1186 fib_entry_pool_size());
1189 * Add 2 routes via the first ADJ. ensure path-list sharing
1191 fib_prefix_t pfx_1_1_1_1_s_32 = {
1193 .fp_proto = FIB_PROTOCOL_IP4,
1196 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1200 fib_table_entry_path_add(fib_index,
1203 FIB_ENTRY_FLAG_NONE,
1206 tm->hw[0]->sw_if_index,
1207 ~0, // invalid fib index
1210 FIB_ROUTE_PATH_FLAG_NONE);
1211 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
1212 ai = fib_entry_get_adj(fei);
1213 FIB_TEST((ai_01 == ai), "1.1.1.1 resolves via 10.10.10.1");
1216 * +1 entry and a shared path-list
1218 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
1219 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1220 fib_path_list_pool_size());
1221 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
1222 fib_entry_pool_size());
1225 fib_prefix_t pfx_1_1_2_0_s_24 = {
1227 .fp_proto = FIB_PROTOCOL_IP4,
1229 .ip4.as_u32 = clib_host_to_net_u32(0x01010200),
1233 fib_table_entry_path_add(fib_index,
1236 FIB_ENTRY_FLAG_NONE,
1239 tm->hw[0]->sw_if_index,
1240 ~0, // invalid fib index
1243 FIB_ROUTE_PATH_FLAG_NONE);
1244 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1245 ai = fib_entry_get_adj(fei);
1246 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1251 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
1252 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1253 fib_path_list_pool_size());
1254 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1255 fib_entry_pool_size());
1258 * modify 1.1.2.0/24 to use multipath.
1260 fib_table_entry_path_add(fib_index,
1263 FIB_ENTRY_FLAG_NONE,
1266 tm->hw[0]->sw_if_index,
1267 ~0, // invalid fib index
1270 FIB_ROUTE_PATH_FLAG_NONE);
1271 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1272 dpo = fib_entry_contribute_ip_forwarding(fei);
1273 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1274 1, tm->hw[0]->sw_if_index),
1275 "RPF list for 1.1.2.0/24 contains both adjs");
1277 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1278 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1279 FIB_TEST((ai_01 == dpo1->dpoi_index),
1280 "1.1.2.0/24 bucket 0 resolves via 10.10.10.1 (%d=%d)",
1281 ai_01, dpo1->dpoi_index);
1283 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 1);
1284 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1285 FIB_TEST((ai_02 == dpo1->dpoi_index),
1286 "1.1.2.0/24 bucket 1 resolves via 10.10.10.2");
1289 * +1 shared-pathlist
1291 FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty");
1292 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1293 fib_path_list_pool_size());
1294 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1295 fib_entry_pool_size());
1300 fib_table_entry_path_remove(fib_index,
1305 tm->hw[0]->sw_if_index,
1308 FIB_ROUTE_PATH_FLAG_NONE);
1309 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1310 dpo = fib_entry_contribute_ip_forwarding(fei);
1311 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1312 1, tm->hw[0]->sw_if_index),
1313 "RPF list for 1.1.2.0/24 contains one adj");
1315 ai = fib_entry_get_adj(fei);
1316 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1319 * +1 shared-pathlist
1321 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d",
1322 fib_path_list_db_size());
1323 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1324 fib_path_list_pool_size());
1325 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1326 fib_entry_pool_size());
1329 * Add 2 recursive routes:
1330 * 100.100.100.100/32 via 1.1.1.1/32 => the via entry is installed.
1331 * 100.100.100.101/32 via 1.1.1.1/32 => the via entry is installed.
1333 fib_prefix_t bgp_100_pfx = {
1335 .fp_proto = FIB_PROTOCOL_IP4,
1337 /* 100.100.100.100/32 */
1338 .ip4.as_u32 = clib_host_to_net_u32(0x64646464),
1342 ip46_address_t nh_1_1_1_1 = {
1343 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1346 fei = fib_table_entry_path_add(fib_index,
1349 FIB_ENTRY_FLAG_NONE,
1352 ~0, // no index provided.
1353 fib_index, // nexthop in same fib as route
1356 FIB_ROUTE_PATH_FLAG_NONE);
1358 FIB_TEST_REC_FORW(&bgp_100_pfx, &pfx_1_1_1_1_s_32, 0);
1359 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1360 tm->hw[0]->sw_if_index),
1361 "RPF list for adj-fib contains adj");
1364 * +1 entry and +1 shared-path-list
1366 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1367 fib_path_list_db_size());
1368 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1369 fib_path_list_pool_size());
1370 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
1371 fib_entry_pool_size());
1373 fib_prefix_t bgp_101_pfx = {
1375 .fp_proto = FIB_PROTOCOL_IP4,
1377 /* 100.100.100.101/32 */
1378 .ip4.as_u32 = clib_host_to_net_u32(0x64646465),
1382 fib_table_entry_path_add(fib_index,
1385 FIB_ENTRY_FLAG_NONE,
1388 ~0, // no index provided.
1389 fib_index, // nexthop in same fib as route
1392 FIB_ROUTE_PATH_FLAG_NONE);
1394 FIB_TEST_REC_FORW(&bgp_101_pfx, &pfx_1_1_1_1_s_32, 0);
1395 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1396 tm->hw[0]->sw_if_index),
1397 "RPF list for adj-fib contains adj");
1400 * +1 entry, but the recursive path-list is shared.
1402 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1403 fib_path_list_db_size());
1404 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1405 fib_path_list_pool_size());
1406 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
1407 fib_entry_pool_size());
1410 * An special route; one where the user (me) provides the
1411 * adjacency through which the route will resovle by setting the flags
1413 fib_prefix_t ex_pfx = {
1415 .fp_proto = FIB_PROTOCOL_IP4,
1418 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
1422 fib_table_entry_special_add(fib_index,
1425 FIB_ENTRY_FLAG_LOCAL);
1426 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1427 dpo = fib_entry_contribute_ip_forwarding(fei);
1428 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
1429 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
1430 "local interface adj is local");
1432 fib_table_entry_special_remove(fib_index,
1434 FIB_SOURCE_SPECIAL);
1435 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1436 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1437 "Exclusive reoute removed");
1440 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1441 * adjacency through which the route will resovle
1443 dpo_id_t ex_dpo = DPO_INVALID;
1445 lookup_dpo_add_or_lock_w_fib_index(fib_index,
1448 LOOKUP_INPUT_DST_ADDR,
1449 LOOKUP_TABLE_FROM_CONFIG,
1452 fib_table_entry_special_dpo_add(fib_index,
1455 FIB_ENTRY_FLAG_EXCLUSIVE,
1457 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1458 dpo = fib_entry_contribute_ip_forwarding(fei);
1459 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1460 "exclusive remote uses lookup DPO");
1463 * update the exclusive to use a different DPO
1465 ip_null_dpo_add_and_lock(DPO_PROTO_IP4,
1466 IP_NULL_ACTION_SEND_ICMP_UNREACH,
1468 fib_table_entry_special_dpo_update(fib_index,
1471 FIB_ENTRY_FLAG_EXCLUSIVE,
1473 dpo = fib_entry_contribute_ip_forwarding(fei);
1474 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1475 "exclusive remote uses now uses NULL DPO");
1477 fib_table_entry_special_remove(fib_index,
1479 FIB_SOURCE_SPECIAL);
1480 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1481 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1482 "Exclusive reoute removed");
1486 * Add a recursive route:
1487 * 200.200.200.200/32 via 1.1.1.2/32 => the via entry is NOT installed.
1489 fib_prefix_t bgp_200_pfx = {
1491 .fp_proto = FIB_PROTOCOL_IP4,
1493 /* 200.200.200.200/32 */
1494 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c8),
1498 fib_prefix_t pfx_1_1_1_2_s_32 = {
1500 .fp_proto = FIB_PROTOCOL_IP4,
1502 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
1506 fei = fib_table_entry_path_add(fib_index,
1509 FIB_ENTRY_FLAG_NONE,
1511 &pfx_1_1_1_2_s_32.fp_addr,
1512 ~0, // no index provided.
1513 fib_index, // nexthop in same fib as route
1516 FIB_ROUTE_PATH_FLAG_NONE);
1518 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
1519 "Recursive via unresolved is drop");
1522 * the adj should be recursive via drop, since the route resolves via
1523 * the default route, which is itself a DROP
1525 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
1526 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1527 FIB_TEST(load_balance_is_drop(dpo1), "1.1.1.2/32 is drop");
1528 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1529 "RPF list for 1.1.1.2/32 contains 0 adjs");
1532 * +2 entry and +1 shared-path-list
1534 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
1535 fib_path_list_db_size());
1536 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
1537 fib_path_list_pool_size());
1538 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
1539 fib_entry_pool_size());
1542 * Unequal Cost load-balance. 3:1 ratio. fits in a 4 bucket LB
1543 * The paths are sort by NH first. in this case the the path with greater
1544 * weight is first in the set. This ordering is to test the RPF sort|uniq logic
1546 fib_prefix_t pfx_1_2_3_4_s_32 = {
1548 .fp_proto = FIB_PROTOCOL_IP4,
1550 .ip4.as_u32 = clib_host_to_net_u32(0x01020304),
1553 fib_table_entry_path_add(fib_index,
1556 FIB_ENTRY_FLAG_NONE,
1559 tm->hw[0]->sw_if_index,
1563 FIB_ROUTE_PATH_FLAG_NONE);
1564 fei = fib_table_entry_path_add(fib_index,
1567 FIB_ENTRY_FLAG_NONE,
1570 tm->hw[1]->sw_if_index,
1574 FIB_ROUTE_PATH_FLAG_NONE);
1576 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.4/32 presnet");
1577 dpo = fib_entry_contribute_ip_forwarding(fei);
1578 lb = load_balance_get(dpo->dpoi_index);
1579 FIB_TEST((lb->lb_n_buckets == 4),
1580 "1.2.3.4/32 LB has %d bucket",
1583 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 0, ai_12_12_12_12);
1584 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 1, ai_12_12_12_12);
1585 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 2, ai_12_12_12_12);
1586 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 3, ai_01);
1588 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1589 tm->hw[0]->sw_if_index,
1590 tm->hw[1]->sw_if_index),
1591 "RPF list for 1.2.3.4/32 contains both adjs");
1595 * Unequal Cost load-balance. 4:1 ratio.
1596 * fits in a 16 bucket LB with ratio 13:3
1598 fib_prefix_t pfx_1_2_3_5_s_32 = {
1600 .fp_proto = FIB_PROTOCOL_IP4,
1602 .ip4.as_u32 = clib_host_to_net_u32(0x01020305),
1605 fib_table_entry_path_add(fib_index,
1608 FIB_ENTRY_FLAG_NONE,
1611 tm->hw[1]->sw_if_index,
1615 FIB_ROUTE_PATH_FLAG_NONE);
1616 fei = fib_table_entry_path_add(fib_index,
1619 FIB_ENTRY_FLAG_NONE,
1622 tm->hw[0]->sw_if_index,
1626 FIB_ROUTE_PATH_FLAG_NONE);
1628 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.5/32 presnet");
1629 dpo = fib_entry_contribute_ip_forwarding(fei);
1630 lb = load_balance_get(dpo->dpoi_index);
1631 FIB_TEST((lb->lb_n_buckets == 16),
1632 "1.2.3.5/32 LB has %d bucket",
1635 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 0, ai_01);
1636 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 1, ai_01);
1637 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 2, ai_01);
1638 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 3, ai_01);
1639 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 4, ai_01);
1640 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 5, ai_01);
1641 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 6, ai_01);
1642 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 7, ai_01);
1643 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 8, ai_01);
1644 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 9, ai_01);
1645 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 10, ai_01);
1646 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 11, ai_01);
1647 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 12, ai_01);
1648 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 13, ai_12_12_12_12);
1649 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 14, ai_12_12_12_12);
1650 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 15, ai_12_12_12_12);
1652 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1653 tm->hw[0]->sw_if_index,
1654 tm->hw[1]->sw_if_index),
1655 "RPF list for 1.2.3.4/32 contains both adjs");
1658 * Test UCMP with a large weight skew - this produces load-balance objects with large
1659 * numbers of buckets to accommodate the skew. By updating said load-balances we are
1660 * laso testing the LB in placce modify code when number of buckets is large.
1662 fib_prefix_t pfx_6_6_6_6_s_32 = {
1664 .fp_proto = FIB_PROTOCOL_IP4,
1667 .ip4.as_u32 = clib_host_to_net_u32(0x06060606),
1670 fib_test_lb_bucket_t ip_o_10_10_10_1 = {
1676 fib_test_lb_bucket_t ip_o_10_10_10_2 = {
1682 fib_test_lb_bucket_t ip_6_6_6_6_o_12_12_12_12 = {
1685 .adj = ai_12_12_12_12,
1688 fib_table_entry_update_one_path(fib_index,
1691 FIB_ENTRY_FLAG_NONE,
1694 tm->hw[0]->sw_if_index,
1695 ~0, // invalid fib index
1698 FIB_ROUTE_PATH_FLAG_NONE);
1700 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1701 FIB_TEST(fib_test_validate_entry(fei,
1702 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1705 "6.6.6.6/32 via 10.10.10.1");
1707 fib_table_entry_path_add(fib_index,
1710 FIB_ENTRY_FLAG_NONE,
1713 tm->hw[0]->sw_if_index,
1714 ~0, // invalid fib index
1717 FIB_ROUTE_PATH_FLAG_NONE);
1719 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1720 FIB_TEST(fib_test_validate_entry(fei,
1721 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1787 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1789 fib_table_entry_path_add(fib_index,
1792 FIB_ENTRY_FLAG_NONE,
1795 tm->hw[1]->sw_if_index,
1796 ~0, // invalid fib index
1799 FIB_ROUTE_PATH_FLAG_NONE);
1801 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1802 FIB_TEST(fib_test_validate_entry(fei,
1803 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1870 &ip_6_6_6_6_o_12_12_12_12,
1871 &ip_6_6_6_6_o_12_12_12_12,
1872 &ip_6_6_6_6_o_12_12_12_12,
1873 &ip_6_6_6_6_o_12_12_12_12,
1874 &ip_6_6_6_6_o_12_12_12_12,
1875 &ip_6_6_6_6_o_12_12_12_12,
1876 &ip_6_6_6_6_o_12_12_12_12,
1877 &ip_6_6_6_6_o_12_12_12_12,
1878 &ip_6_6_6_6_o_12_12_12_12,
1879 &ip_6_6_6_6_o_12_12_12_12,
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 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1935 fib_table_entry_path_remove(fib_index,
1940 tm->hw[1]->sw_if_index,
1941 ~0, // invalid fib index
1943 FIB_ROUTE_PATH_FLAG_NONE);
1945 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1946 FIB_TEST(fib_test_validate_entry(fei,
1947 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2013 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
2015 fib_table_entry_path_remove(fib_index,
2020 tm->hw[0]->sw_if_index,
2021 ~0, // invalid fib index
2023 FIB_ROUTE_PATH_FLAG_NONE);
2025 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
2026 FIB_TEST(fib_test_validate_entry(fei,
2027 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2030 "6.6.6.6/32 via 10.10.10.1");
2032 fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API);
2035 * A recursive via the two unequal cost entries
2037 fib_prefix_t bgp_44_s_32 = {
2039 .fp_proto = FIB_PROTOCOL_IP4,
2041 /* 200.200.200.201/32 */
2042 .ip4.as_u32 = clib_host_to_net_u32(0x44444444),
2045 fei = fib_table_entry_path_add(fib_index,
2048 FIB_ENTRY_FLAG_NONE,
2050 &pfx_1_2_3_4_s_32.fp_addr,
2055 FIB_ROUTE_PATH_FLAG_NONE);
2056 fei = fib_table_entry_path_add(fib_index,
2059 FIB_ENTRY_FLAG_NONE,
2061 &pfx_1_2_3_5_s_32.fp_addr,
2066 FIB_ROUTE_PATH_FLAG_NONE);
2068 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_4_s_32, 0);
2069 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_5_s_32, 1);
2070 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
2071 tm->hw[0]->sw_if_index,
2072 tm->hw[1]->sw_if_index),
2073 "RPF list for 1.2.3.4/32 contains both adjs");
2076 * test the uRPF check functions
2078 dpo_id_t dpo_44 = DPO_INVALID;
2081 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
2082 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
2084 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
2085 "uRPF check for 68.68.68.68/32 on %d OK",
2086 tm->hw[0]->sw_if_index);
2087 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
2088 "uRPF check for 68.68.68.68/32 on %d OK",
2089 tm->hw[1]->sw_if_index);
2090 FIB_TEST(!fib_urpf_check(urpfi, 99),
2091 "uRPF check for 68.68.68.68/32 on 99 not-OK",
2095 fib_table_entry_delete(fib_index,
2098 fib_table_entry_delete(fib_index,
2101 fib_table_entry_delete(fib_index,
2106 * Add a recursive route:
2107 * 200.200.200.201/32 via 1.1.1.200/32 => the via entry is NOT installed.
2109 fib_prefix_t bgp_201_pfx = {
2111 .fp_proto = FIB_PROTOCOL_IP4,
2113 /* 200.200.200.201/32 */
2114 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c9),
2118 fib_prefix_t pfx_1_1_1_200_s_32 = {
2120 .fp_proto = FIB_PROTOCOL_IP4,
2122 .ip4.as_u32 = clib_host_to_net_u32(0x010101c8),
2126 fei = fib_table_entry_path_add(fib_index,
2129 FIB_ENTRY_FLAG_NONE,
2131 &pfx_1_1_1_200_s_32.fp_addr,
2132 ~0, // no index provided.
2133 fib_index, // nexthop in same fib as route
2136 FIB_ROUTE_PATH_FLAG_NONE);
2138 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2139 "Recursive via unresolved is drop");
2141 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2142 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
2143 "Flags set on RR via non-attached");
2144 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
2145 "RPF list for BGP route empty");
2148 * +2 entry (BGP & RR) and +1 shared-path-list
2150 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2151 fib_path_list_db_size());
2152 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2153 fib_path_list_pool_size());
2154 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2155 fib_entry_pool_size());
2158 * insert a route that covers the missing 1.1.1.2/32. we epxect
2159 * 200.200.200.200/32 and 200.200.200.201/32 to resolve through it.
2161 fib_prefix_t pfx_1_1_1_0_s_24 = {
2163 .fp_proto = FIB_PROTOCOL_IP4,
2166 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2170 fib_table_entry_path_add(fib_index,
2173 FIB_ENTRY_FLAG_NONE,
2176 tm->hw[0]->sw_if_index,
2177 ~0, // invalid fib index
2180 FIB_ROUTE_PATH_FLAG_NONE);
2181 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24);
2182 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2183 ai = fib_entry_get_adj(fei);
2184 FIB_TEST((ai_01 == ai), "1.1.1.0/24 resolves via 10.10.10.1");
2185 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2186 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2187 ai = fib_entry_get_adj(fei);
2188 FIB_TEST((ai_01 == ai), "1.1.1.2/32 resolves via 10.10.10.1");
2189 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2190 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2191 ai = fib_entry_get_adj(fei);
2192 FIB_TEST((ai_01 == ai), "1.1.1.200/24 resolves via 10.10.10.1");
2195 * +1 entry. 1.1.1.1/32 already uses 10.10.10.1 so no new pah-list
2197 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2198 fib_path_list_db_size());
2199 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2200 fib_path_list_pool_size());
2201 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
2202 fib_entry_pool_size());
2205 * the recursive adj for 200.200.200.200 should be updated.
2207 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2208 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2209 fei = fib_table_lookup(fib_index, &bgp_200_pfx);
2210 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
2211 tm->hw[0]->sw_if_index),
2212 "RPF list for BGP route has itf index 0");
2215 * insert a more specific route than 1.1.1.0/24 that also covers the
2216 * missing 1.1.1.2/32, but not 1.1.1.200/32. we epxect
2217 * 200.200.200.200 to resolve through it.
2219 fib_prefix_t pfx_1_1_1_0_s_28 = {
2221 .fp_proto = FIB_PROTOCOL_IP4,
2224 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2228 fib_table_entry_path_add(fib_index,
2231 FIB_ENTRY_FLAG_NONE,
2234 tm->hw[0]->sw_if_index,
2235 ~0, // invalid fib index
2238 FIB_ROUTE_PATH_FLAG_NONE);
2239 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28);
2240 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2241 ai = fib_entry_get_adj(fei);
2242 FIB_TEST((ai_02 == ai), "1.1.1.0/24 resolves via 10.10.10.2");
2245 * +1 entry. +1 shared path-list
2247 FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d",
2248 fib_path_list_db_size());
2249 FIB_TEST((PNBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
2250 fib_path_list_pool_size());
2251 FIB_TEST((ENBR+14 == fib_entry_pool_size()), "entry pool size is %d",
2252 fib_entry_pool_size());
2255 * the recursive adj for 200.200.200.200 should be updated.
2256 * 200.200.200.201 remains unchanged.
2258 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2259 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2262 * remove this /28. 200.200.200.200/32 should revert back to via 1.1.1.0/24
2264 fib_table_entry_path_remove(fib_index,
2269 tm->hw[0]->sw_if_index,
2272 FIB_ROUTE_PATH_FLAG_NONE);
2273 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28) ==
2274 FIB_NODE_INDEX_INVALID),
2275 "1.1.1.0/28 removed");
2276 FIB_TEST((fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28) ==
2277 fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24)),
2278 "1.1.1.0/28 lookup via /24");
2279 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2280 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2283 * -1 entry. -1 shared path-list
2285 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2286 fib_path_list_db_size());
2287 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2288 fib_path_list_pool_size());
2289 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
2290 fib_entry_pool_size());
2293 * remove 1.1.1.0/24. 200.200.200.200/32 should revert back to via 0.0.0.0/0
2295 fib_table_entry_path_remove(fib_index,
2300 tm->hw[0]->sw_if_index,
2303 FIB_ROUTE_PATH_FLAG_NONE);
2304 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_24) ==
2305 FIB_NODE_INDEX_INVALID),
2306 "1.1.1.0/24 removed");
2308 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2309 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2310 "1.1.1.2/32 route is DROP");
2311 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2312 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2313 "1.1.1.200/32 route is DROP");
2315 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2316 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2318 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2319 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2325 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2326 fib_path_list_db_size());
2327 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2328 fib_path_list_pool_size());
2329 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2330 fib_entry_pool_size());
2333 * insert the missing 1.1.1.2/32
2335 fei = fib_table_entry_path_add(fib_index,
2338 FIB_ENTRY_FLAG_NONE,
2341 tm->hw[0]->sw_if_index,
2342 ~0, // invalid fib index
2345 FIB_ROUTE_PATH_FLAG_NONE);
2346 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2347 ai = fib_entry_get_adj(fei);
2348 FIB_TEST((ai = ai_01), "1.1.1.2/32 resolves via 10.10.10.1");
2350 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2351 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2353 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2356 * no change. 1.1.1.2/32 was already there RR sourced.
2358 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2359 fib_path_list_db_size());
2360 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2361 fib_path_list_pool_size());
2362 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2363 fib_entry_pool_size());
2366 * give 201 a resolved path.
2367 * it now has the unresolved 1.1.1.200 and the resolved 1.1.1.2,
2368 * only the latter contributes forwarding.
2370 fei = fib_table_entry_path_add(fib_index,
2373 FIB_ENTRY_FLAG_NONE,
2375 &pfx_1_1_1_2_s_32.fp_addr,
2380 FIB_ROUTE_PATH_FLAG_NONE);
2381 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_2_s_32, 0);
2382 fib_table_entry_path_remove(fib_index,
2386 &pfx_1_1_1_2_s_32.fp_addr,
2390 FIB_ROUTE_PATH_FLAG_NONE);
2393 * remove 200.200.200.201/32 which does not have a valid via FIB
2395 fib_table_entry_path_remove(fib_index,
2399 &pfx_1_1_1_200_s_32.fp_addr,
2400 ~0, // no index provided.
2403 FIB_ROUTE_PATH_FLAG_NONE);
2406 * -2 entries (BGP and RR). -1 shared path-list;
2408 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2409 FIB_NODE_INDEX_INVALID),
2410 "200.200.200.201/32 removed");
2411 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32) ==
2412 FIB_NODE_INDEX_INVALID),
2413 "1.1.1.200/32 removed");
2415 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2416 fib_path_list_db_size());
2417 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
2418 fib_path_list_pool_size());
2419 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2420 fib_entry_pool_size());
2423 * remove 200.200.200.200/32 which does have a valid via FIB
2425 fib_table_entry_path_remove(fib_index,
2429 &pfx_1_1_1_2_s_32.fp_addr,
2430 ~0, // no index provided.
2433 FIB_ROUTE_PATH_FLAG_NONE);
2435 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2436 FIB_NODE_INDEX_INVALID),
2437 "200.200.200.200/32 removed");
2438 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32) !=
2439 FIB_NODE_INDEX_INVALID),
2440 "1.1.1.2/32 still present");
2443 * -1 entry (BGP, the RR source is also API sourced). -1 shared path-list;
2445 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2446 fib_path_list_db_size());
2447 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2448 fib_path_list_pool_size());
2449 FIB_TEST((ENBR+9 == fib_entry_pool_size()), "entry pool size is %d",
2450 fib_entry_pool_size());
2453 * A recursive prefix that has a 2 path load-balance.
2454 * It also shares a next-hop with other BGP prefixes and hence
2455 * test the ref counting of RR sourced prefixes and 2 level LB.
2457 const fib_prefix_t bgp_102 = {
2459 .fp_proto = FIB_PROTOCOL_IP4,
2461 /* 100.100.100.101/32 */
2462 .ip4.as_u32 = clib_host_to_net_u32(0x64646466),
2465 fib_table_entry_path_add(fib_index,
2468 FIB_ENTRY_FLAG_NONE,
2470 &pfx_1_1_1_1_s_32.fp_addr,
2471 ~0, // no index provided.
2472 fib_index, // same as route
2475 FIB_ROUTE_PATH_FLAG_NONE);
2476 fib_table_entry_path_add(fib_index,
2479 FIB_ENTRY_FLAG_NONE,
2481 &pfx_1_1_1_2_s_32.fp_addr,
2482 ~0, // no index provided.
2483 fib_index, // same as route's FIB
2486 FIB_ROUTE_PATH_FLAG_NONE);
2487 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2488 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "100.100.100.102/32 presnet");
2489 dpo = fib_entry_contribute_ip_forwarding(fei);
2491 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2492 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2493 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32);
2494 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2496 lb = load_balance_get(dpo->dpoi_index);
2497 FIB_TEST((lb->lb_n_buckets == 2), "Recursive LB has %d bucket", lb->lb_n_buckets);
2498 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2499 "First via 10.10.10.1");
2500 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 1)),
2501 "Second via 10.10.10.1");
2503 fib_table_entry_path_remove(fib_index,
2507 &pfx_1_1_1_1_s_32.fp_addr,
2508 ~0, // no index provided.
2509 fib_index, // same as route's FIB
2511 FIB_ROUTE_PATH_FLAG_NONE);
2512 fib_table_entry_path_remove(fib_index,
2516 &pfx_1_1_1_2_s_32.fp_addr,
2517 ~0, // no index provided.
2518 fib_index, // same as route's FIB
2520 FIB_ROUTE_PATH_FLAG_NONE);
2521 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2522 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "100.100.100.102/32 removed");
2525 * remove the remaining recursives
2527 fib_table_entry_path_remove(fib_index,
2531 &pfx_1_1_1_1_s_32.fp_addr,
2532 ~0, // no index provided.
2533 fib_index, // same as route's FIB
2535 FIB_ROUTE_PATH_FLAG_NONE);
2536 fib_table_entry_path_remove(fib_index,
2540 &pfx_1_1_1_1_s_32.fp_addr,
2541 ~0, // no index provided.
2542 fib_index, // same as route's FIB
2544 FIB_ROUTE_PATH_FLAG_NONE);
2545 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_100_pfx) ==
2546 FIB_NODE_INDEX_INVALID),
2547 "100.100.100.100/32 removed");
2548 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_101_pfx) ==
2549 FIB_NODE_INDEX_INVALID),
2550 "100.100.100.101/32 removed");
2553 * -2 entry (2*BGP, the RR source is also API sourced). -1 shared path-list;
2555 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2556 fib_path_list_db_size());
2557 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2558 fib_path_list_pool_size());
2559 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2560 fib_entry_pool_size());
2563 * Add a recursive route via a connected cover, using an adj-fib that does exist
2565 fib_table_entry_path_add(fib_index,
2568 FIB_ENTRY_FLAG_NONE,
2571 ~0, // no index provided.
2572 fib_index, // Same as route's FIB
2575 FIB_ROUTE_PATH_FLAG_NONE);
2578 * +1 entry. +1 shared path-list (recursive via 10.10.10.1)
2580 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2581 fib_path_list_db_size());
2582 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2583 fib_path_list_pool_size());
2584 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
2585 fib_entry_pool_size());
2587 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2588 dpo = fib_entry_contribute_ip_forwarding(fei);
2590 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
2591 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2593 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2594 "200.200.200.200/32 is recursive via adj for 10.10.10.1");
2596 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
2597 "Flags set on RR via existing attached");
2600 * Add a recursive route via a connected cover, using and adj-fib that does
2603 ip46_address_t nh_10_10_10_3 = {
2604 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
2606 fib_prefix_t pfx_10_10_10_3 = {
2608 .fp_proto = FIB_PROTOCOL_IP4,
2609 .fp_addr = nh_10_10_10_3,
2612 fib_table_entry_path_add(fib_index,
2615 FIB_ENTRY_FLAG_NONE,
2618 ~0, // no index provided.
2622 FIB_ROUTE_PATH_FLAG_NONE);
2625 * +2 entries (BGP and RR). +1 shared path-list (recursive via 10.10.10.3) and
2626 * one unshared non-recursive via 10.10.10.3
2628 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2629 fib_path_list_db_size());
2630 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2631 fib_path_list_pool_size());
2632 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2633 fib_entry_pool_size());
2635 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
2638 tm->hw[0]->sw_if_index);
2640 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2641 dpo = fib_entry_contribute_ip_forwarding(fei);
2642 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3);
2643 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2645 ai = fib_entry_get_adj(fei);
2646 FIB_TEST((ai == ai_03), "adj for 10.10.10.3/32 is via adj for 10.10.10.3");
2647 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
2648 fib_entry_get_flags(fei)),
2649 "Flags set on RR via non-existing attached");
2651 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2652 "adj for 200.200.200.200/32 is recursive via adj for 10.10.10.3");
2657 * remove the recursives
2659 fib_table_entry_path_remove(fib_index,
2664 ~0, // no index provided.
2665 fib_index, // same as route's FIB
2667 FIB_ROUTE_PATH_FLAG_NONE);
2668 fib_table_entry_path_remove(fib_index,
2673 ~0, // no index provided.
2674 fib_index, // same as route's FIB
2676 FIB_ROUTE_PATH_FLAG_NONE);
2678 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2679 FIB_NODE_INDEX_INVALID),
2680 "200.200.200.201/32 removed");
2681 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2682 FIB_NODE_INDEX_INVALID),
2683 "200.200.200.200/32 removed");
2684 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3) ==
2685 FIB_NODE_INDEX_INVALID),
2686 "10.10.10.3/32 removed");
2689 * -3 entries (2*BGP and RR). -2 shared path-list (recursive via 10.10.10.3 &
2690 * 10.10.10.1) and one unshared non-recursive via 10.10.10.3
2692 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2693 fib_path_list_db_size());
2694 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2695 fib_path_list_pool_size());
2696 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2697 fib_entry_pool_size());
2702 * Add 5.5.5.5/32 -> 5.5.5.6/32 -> 5.5.5.7/32 -> 5.5.5.5/32
2704 fib_prefix_t pfx_5_5_5_5_s_32 = {
2706 .fp_proto = FIB_PROTOCOL_IP4,
2708 .ip4.as_u32 = clib_host_to_net_u32(0x05050505),
2711 fib_prefix_t pfx_5_5_5_6_s_32 = {
2713 .fp_proto = FIB_PROTOCOL_IP4,
2715 .ip4.as_u32 = clib_host_to_net_u32(0x05050506),
2718 fib_prefix_t pfx_5_5_5_7_s_32 = {
2720 .fp_proto = FIB_PROTOCOL_IP4,
2722 .ip4.as_u32 = clib_host_to_net_u32(0x05050507),
2726 fib_table_entry_path_add(fib_index,
2729 FIB_ENTRY_FLAG_NONE,
2731 &pfx_5_5_5_6_s_32.fp_addr,
2732 ~0, // no index provided.
2736 FIB_ROUTE_PATH_FLAG_NONE);
2737 fib_table_entry_path_add(fib_index,
2740 FIB_ENTRY_FLAG_NONE,
2742 &pfx_5_5_5_7_s_32.fp_addr,
2743 ~0, // no index provided.
2747 FIB_ROUTE_PATH_FLAG_NONE);
2748 fib_table_entry_path_add(fib_index,
2751 FIB_ENTRY_FLAG_NONE,
2753 &pfx_5_5_5_5_s_32.fp_addr,
2754 ~0, // no index provided.
2758 FIB_ROUTE_PATH_FLAG_NONE);
2760 * +3 entries, +3 shared path-list
2762 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2763 fib_path_list_db_size());
2764 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2765 fib_path_list_pool_size());
2766 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2767 fib_entry_pool_size());
2770 * All the entries have only looped paths, so they are all drop
2772 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2773 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2774 "LB for 5.5.5.7/32 is via adj for DROP");
2775 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2776 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2777 "LB for 5.5.5.5/32 is via adj for DROP");
2778 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2779 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2780 "LB for 5.5.5.6/32 is via adj for DROP");
2783 * provide 5.5.5.6/32 with alternate path.
2784 * this will allow only 5.5.5.6/32 to forward with this path, the others
2785 * are still drop since the loop is still present.
2787 fib_table_entry_path_add(fib_index,
2790 FIB_ENTRY_FLAG_NONE,
2793 tm->hw[0]->sw_if_index,
2797 FIB_ROUTE_PATH_FLAG_NONE);
2799 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2800 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2802 lb = load_balance_get(dpo1->dpoi_index);
2803 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.6 LB has %d bucket", lb->lb_n_buckets);
2805 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2806 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2807 FIB_TEST((ai_01 == dpo2->dpoi_index),
2808 "5.5.5.6 bucket 0 resolves via 10.10.10.2");
2810 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2811 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2812 "LB for 5.5.5.7/32 is via adj for DROP");
2813 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2814 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2815 "LB for 5.5.5.5/32 is via adj for DROP");
2818 * remove the alternate path for 5.5.5.6/32
2821 fib_table_entry_path_remove(fib_index,
2826 tm->hw[0]->sw_if_index,
2829 FIB_ROUTE_PATH_FLAG_NONE);
2831 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2832 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2833 "LB for 5.5.5.7/32 is via adj for DROP");
2834 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2835 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2836 "LB for 5.5.5.5/32 is via adj for DROP");
2837 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2838 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2839 "LB for 5.5.5.6/32 is via adj for DROP");
2842 * break the loop by giving 5.5.5.5/32 a new set of paths
2843 * expect all to forward via this new path.
2845 fib_table_entry_update_one_path(fib_index,
2848 FIB_ENTRY_FLAG_NONE,
2851 tm->hw[0]->sw_if_index,
2852 ~0, // invalid fib index
2855 FIB_ROUTE_PATH_FLAG_NONE);
2857 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2858 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2859 lb = load_balance_get(dpo1->dpoi_index);
2860 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.5 LB has %d bucket", lb->lb_n_buckets);
2862 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2863 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2864 FIB_TEST((ai_01 == dpo2->dpoi_index),
2865 "5.5.5.5 bucket 0 resolves via 10.10.10.2");
2867 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_7_s_32);
2868 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2870 lb = load_balance_get(dpo2->dpoi_index);
2871 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2872 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo2->dpoi_index, 0)),
2873 "5.5.5.5.7 via 5.5.5.5");
2875 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32);
2876 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2878 lb = load_balance_get(dpo1->dpoi_index);
2879 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2880 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2881 "5.5.5.5.6 via 5.5.5.7");
2884 * revert back to the loop. so we can remove the prefixes with
2887 fib_table_entry_update_one_path(fib_index,
2890 FIB_ENTRY_FLAG_NONE,
2892 &pfx_5_5_5_6_s_32.fp_addr,
2893 ~0, // no index provided.
2897 FIB_ROUTE_PATH_FLAG_NONE);
2899 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2900 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2901 "LB for 5.5.5.7/32 is via adj for DROP");
2902 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2903 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2904 "LB for 5.5.5.5/32 is via adj for DROP");
2905 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2906 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2907 "LB for 5.5.5.6/32 is via adj for DROP");
2910 * remove all the 5.5.5.x/32 prefixes
2912 fib_table_entry_path_remove(fib_index,
2916 &pfx_5_5_5_6_s_32.fp_addr,
2917 ~0, // no index provided.
2918 fib_index, // same as route's FIB
2920 FIB_ROUTE_PATH_FLAG_NONE);
2921 fib_table_entry_path_remove(fib_index,
2925 &pfx_5_5_5_7_s_32.fp_addr,
2926 ~0, // no index provided.
2927 fib_index, // same as route's FIB
2929 FIB_ROUTE_PATH_FLAG_NONE);
2930 fib_table_entry_path_remove(fib_index,
2934 &pfx_5_5_5_5_s_32.fp_addr,
2935 ~0, // no index provided.
2936 fib_index, // same as route's FIB
2938 FIB_ROUTE_PATH_FLAG_NONE);
2939 fib_table_entry_path_remove(fib_index,
2944 ~0, // no index provided.
2945 fib_index, // same as route's FIB
2947 FIB_ROUTE_PATH_FLAG_NONE);
2950 * -3 entries, -3 shared path-list
2952 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2953 fib_path_list_db_size());
2954 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2955 fib_path_list_pool_size());
2956 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2957 fib_entry_pool_size());
2960 * Single level loop 5.5.5.5/32 via 5.5.5.5/32
2962 fib_table_entry_path_add(fib_index,
2965 FIB_ENTRY_FLAG_NONE,
2967 &pfx_5_5_5_6_s_32.fp_addr,
2968 ~0, // no index provided.
2972 FIB_ROUTE_PATH_FLAG_NONE);
2973 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2974 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2975 "1-level 5.5.5.6/32 loop is via adj for DROP");
2977 fib_table_entry_path_remove(fib_index,
2981 &pfx_5_5_5_6_s_32.fp_addr,
2982 ~0, // no index provided.
2983 fib_index, // same as route's FIB
2985 FIB_ROUTE_PATH_FLAG_NONE);
2986 FIB_TEST(FIB_NODE_INDEX_INVALID ==
2987 fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32),
2988 "1-level 5.5.5.6/32 loop is removed");
2991 * A recursive route whose next-hop is covered by the prefix.
2992 * This would mean the via-fib, which inherits forwarding from its
2993 * cover, thus picks up forwarding from the prfix, which is via the
2994 * via-fib, and we have a loop.
2996 fib_prefix_t pfx_23_23_23_0_s_24 = {
2998 .fp_proto = FIB_PROTOCOL_IP4,
3000 .ip4.as_u32 = clib_host_to_net_u32(0x17171700),
3003 fib_prefix_t pfx_23_23_23_23_s_32 = {
3005 .fp_proto = FIB_PROTOCOL_IP4,
3007 .ip4.as_u32 = clib_host_to_net_u32(0x17171717),
3010 fei = fib_table_entry_path_add(fib_index,
3011 &pfx_23_23_23_0_s_24,
3013 FIB_ENTRY_FLAG_NONE,
3015 &pfx_23_23_23_23_s_32.fp_addr,
3020 FIB_ROUTE_PATH_FLAG_NONE);
3021 dpo = fib_entry_contribute_ip_forwarding(fei);
3022 FIB_TEST(load_balance_is_drop(dpo),
3023 "23.23.23.0/24 via covered is DROP");
3024 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3027 * add-remove test. no change.
3029 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3030 fib_path_list_db_size());
3031 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3032 fib_path_list_pool_size());
3033 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3034 fib_entry_pool_size());
3037 * Make the default route recursive via a unknown next-hop. Thus the
3038 * next hop's cover would be the default route
3040 fei = fib_table_entry_path_add(fib_index,
3043 FIB_ENTRY_FLAG_NONE,
3045 &pfx_23_23_23_23_s_32.fp_addr,
3050 FIB_ROUTE_PATH_FLAG_NONE);
3051 dpo = fib_entry_contribute_ip_forwarding(fei);
3052 FIB_TEST(load_balance_is_drop(dpo),
3053 "0.0.0.0.0/0 via is DROP");
3054 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3055 "no resolving interface for looped 0.0.0.0/0");
3057 fei = fib_table_lookup_exact_match(fib_index, &pfx_23_23_23_23_s_32);
3058 dpo = fib_entry_contribute_ip_forwarding(fei);
3059 FIB_TEST(load_balance_is_drop(dpo),
3060 "23.23.23.23/32 via is DROP");
3061 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3062 "no resolving interface for looped 23.23.23.23/32");
3064 fib_table_entry_delete(fib_index, &pfx_0_0_0_0_s_0, FIB_SOURCE_API);
3067 * A recursive route with recursion constraints.
3068 * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained
3070 fib_table_entry_path_add(fib_index,
3073 FIB_ENTRY_FLAG_NONE,
3080 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3082 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3083 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3085 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3086 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3088 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3089 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3092 * save the load-balance. we expect it to be inplace modified
3094 lb = load_balance_get(dpo1->dpoi_index);
3097 * add a covering prefix for the via fib that would otherwise serve
3098 * as the resolving route when the host is removed
3100 fib_table_entry_path_add(fib_index,
3103 FIB_ENTRY_FLAG_NONE,
3106 tm->hw[0]->sw_if_index,
3107 ~0, // invalid fib index
3110 FIB_ROUTE_PATH_FLAG_NONE);
3111 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28);
3112 ai = fib_entry_get_adj(fei);
3113 FIB_TEST((ai == ai_01),
3114 "adj for 1.1.1.0/28 is via adj for 1.1.1.1");
3117 * remove the host via FIB - expect the BGP prefix to be drop
3119 fib_table_entry_path_remove(fib_index,
3124 tm->hw[0]->sw_if_index,
3125 ~0, // invalid fib index
3127 FIB_ROUTE_PATH_FLAG_NONE);
3129 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3130 "adj for 200.200.200.200/32 is recursive via adj for DROP");
3133 * add the via-entry host reoute back. expect to resolve again
3135 fib_table_entry_path_add(fib_index,
3138 FIB_ENTRY_FLAG_NONE,
3141 tm->hw[0]->sw_if_index,
3142 ~0, // invalid fib index
3145 FIB_ROUTE_PATH_FLAG_NONE);
3146 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3147 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3150 * add another path for the recursive. it will then have 2.
3152 fib_prefix_t pfx_1_1_1_3_s_32 = {
3154 .fp_proto = FIB_PROTOCOL_IP4,
3156 .ip4.as_u32 = clib_host_to_net_u32(0x01010103),
3159 fib_table_entry_path_add(fib_index,
3162 FIB_ENTRY_FLAG_NONE,
3165 tm->hw[0]->sw_if_index,
3166 ~0, // invalid fib index
3169 FIB_ROUTE_PATH_FLAG_NONE);
3171 fib_table_entry_path_add(fib_index,
3174 FIB_ENTRY_FLAG_NONE,
3176 &pfx_1_1_1_3_s_32.fp_addr,
3181 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3184 * add a bunch load more entries using this path combo so that we get
3185 * an LB-map created.
3188 fib_prefix_t bgp_78s[N_P];
3189 for (ii = 0; ii < N_P; ii++)
3191 bgp_78s[ii].fp_len = 32;
3192 bgp_78s[ii].fp_proto = FIB_PROTOCOL_IP4;
3193 bgp_78s[ii].fp_addr.ip4.as_u32 = clib_host_to_net_u32(0x4e000000+ii);
3196 fib_table_entry_path_add(fib_index,
3199 FIB_ENTRY_FLAG_NONE,
3201 &pfx_1_1_1_3_s_32.fp_addr,
3206 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3207 fib_table_entry_path_add(fib_index,
3210 FIB_ENTRY_FLAG_NONE,
3217 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3220 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3221 dpo = fib_entry_contribute_ip_forwarding(fei);
3223 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3224 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3225 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)),
3226 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3227 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32);
3228 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3229 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)),
3230 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3");
3233 * expect the lb-map used by the recursive's load-balance is using both buckets
3235 load_balance_map_t *lbm;
3238 lb = load_balance_get(dpo->dpoi_index);
3240 load_balance_map_lock(lbmi);
3241 lbm = load_balance_map_get(lbmi);
3243 FIB_TEST(lbm->lbm_buckets[0] == 0,
3244 "LB maps's bucket 0 is %d",
3245 lbm->lbm_buckets[0]);
3246 FIB_TEST(lbm->lbm_buckets[1] == 1,
3247 "LB maps's bucket 1 is %d",
3248 lbm->lbm_buckets[1]);
3251 * withdraw one of the /32 via-entrys.
3252 * that ECMP path will be unresolved and forwarding should continue on the
3253 * other available path. this is an iBGP PIC edge failover.
3254 * Test the forwarding changes without re-fetching the adj from the
3255 * recursive entry. this ensures its the same one that is updated; i.e. an
3258 fib_table_entry_path_remove(fib_index,
3263 tm->hw[0]->sw_if_index,
3264 ~0, // invalid fib index
3266 FIB_ROUTE_PATH_FLAG_NONE);
3268 /* suspend so the update walk kicks int */
3269 vlib_process_suspend(vlib_get_main(), 1e-5);
3271 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3272 FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)),
3273 "post PIC 200.200.200.200/32 was inplace modified");
3275 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)),
3276 "post PIC adj for 200.200.200.200/32 is recursive"
3277 " via adj for 1.1.1.3");
3280 * the LB maps that was locked above should have been modified to remove
3281 * the path that was down, and thus its bucket points to a path that is
3284 FIB_TEST(lbm->lbm_buckets[0] == 1,
3285 "LB maps's bucket 0 is %d",
3286 lbm->lbm_buckets[0]);
3287 FIB_TEST(lbm->lbm_buckets[1] == 1,
3288 "LB maps's bucket 1 is %d",
3289 lbm->lbm_buckets[1]);
3291 load_balance_map_unlock(lbmi);
3294 * add it back. again
3296 fib_table_entry_path_add(fib_index,
3299 FIB_ENTRY_FLAG_NONE,
3302 tm->hw[0]->sw_if_index,
3303 ~0, // invalid fib index
3306 FIB_ROUTE_PATH_FLAG_NONE);
3308 /* suspend so the update walk kicks in */
3309 vlib_process_suspend(vlib_get_main(), 1e-5);
3311 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)),
3312 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3313 "via adj for 1.1.1.1");
3314 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)),
3315 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3316 "via adj for 1.1.1.3");
3318 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3319 dpo = fib_entry_contribute_ip_forwarding(fei);
3320 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3321 "post PIC 200.200.200.200/32 was inplace modified");
3324 * add a 3rd path. this makes the LB 16 buckets.
3326 fib_table_entry_path_add(fib_index,
3329 FIB_ENTRY_FLAG_NONE,
3331 &pfx_1_1_1_2_s_32.fp_addr,
3336 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3337 for (ii = 0; ii < N_P; ii++)
3339 fib_table_entry_path_add(fib_index,
3342 FIB_ENTRY_FLAG_NONE,
3344 &pfx_1_1_1_2_s_32.fp_addr,
3349 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3352 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3353 dpo = fib_entry_contribute_ip_forwarding(fei);
3354 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3355 "200.200.200.200/32 was inplace modified for 3rd path");
3356 FIB_TEST(16 == lb->lb_n_buckets,
3357 "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets");
3360 load_balance_map_lock(lbmi);
3361 lbm = load_balance_map_get(lbmi);
3363 for (ii = 0; ii < 16; ii++)
3365 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3366 "LB Map for 200.200.200.200/32 at %d is %d",
3367 ii, lbm->lbm_buckets[ii]);
3371 * trigger PIC by removing the first via-entry
3372 * the first 6 buckets of the map should map to the next 6
3374 fib_table_entry_path_remove(fib_index,
3379 tm->hw[0]->sw_if_index,
3382 FIB_ROUTE_PATH_FLAG_NONE);
3383 /* suspend so the update walk kicks int */
3384 vlib_process_suspend(vlib_get_main(), 1e-5);
3386 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3387 dpo = fib_entry_contribute_ip_forwarding(fei);
3388 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3389 "200.200.200.200/32 was inplace modified for 3rd path");
3390 FIB_TEST(2 == lb->lb_n_buckets,
3391 "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets");
3393 for (ii = 0; ii < 6; ii++)
3395 FIB_TEST(lbm->lbm_buckets[ii] == ii+6,
3396 "LB Map for 200.200.200.200/32 at %d is %d",
3397 ii, lbm->lbm_buckets[ii]);
3399 for (ii = 6; ii < 16; ii++)
3401 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3402 "LB Map for 200.200.200.200/32 at %d is %d",
3403 ii, lbm->lbm_buckets[ii]);
3405 load_balance_map_unlock(lbmi);
3410 fib_table_entry_path_add(fib_index,
3413 FIB_ENTRY_FLAG_NONE,
3416 tm->hw[0]->sw_if_index,
3420 FIB_ROUTE_PATH_FLAG_NONE);
3422 for (ii = 0; ii < N_P; ii++)
3424 fib_table_entry_delete(fib_index,
3427 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3428 fib_table_lookup_exact_match(fib_index, &bgp_78s[ii])),
3430 format_fib_prefix, &bgp_78s[ii]);
3432 fib_table_entry_path_remove(fib_index,
3436 &pfx_1_1_1_2_s_32.fp_addr,
3440 MPLS_LABEL_INVALID);
3441 fib_table_entry_path_remove(fib_index,
3449 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3450 fib_table_entry_path_remove(fib_index,
3454 &pfx_1_1_1_3_s_32.fp_addr,
3458 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3459 fib_table_entry_delete(fib_index,
3462 fib_table_entry_delete(fib_index,
3465 /* suspend so the update walk kicks int */
3466 vlib_process_suspend(vlib_get_main(), 1e-5);
3467 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3468 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)),
3469 "1.1.1.1/28 removed");
3470 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3471 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)),
3472 "1.1.1.3/32 removed");
3473 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3474 fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)),
3475 "200.200.200.200/32 removed");
3478 * add-remove test. no change.
3480 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3481 fib_path_list_db_size());
3482 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3483 fib_path_list_pool_size());
3484 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3485 fib_entry_pool_size());
3488 * A route whose paths are built up iteratively and then removed
3491 fib_prefix_t pfx_4_4_4_4_s_32 = {
3493 .fp_proto = FIB_PROTOCOL_IP4,
3496 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
3500 fib_table_entry_path_add(fib_index,
3503 FIB_ENTRY_FLAG_NONE,
3506 tm->hw[0]->sw_if_index,
3510 FIB_ROUTE_PATH_FLAG_NONE);
3511 fib_table_entry_path_add(fib_index,
3514 FIB_ENTRY_FLAG_NONE,
3517 tm->hw[0]->sw_if_index,
3521 FIB_ROUTE_PATH_FLAG_NONE);
3522 fib_table_entry_path_add(fib_index,
3525 FIB_ENTRY_FLAG_NONE,
3528 tm->hw[0]->sw_if_index,
3532 FIB_ROUTE_PATH_FLAG_NONE);
3533 FIB_TEST(FIB_NODE_INDEX_INVALID !=
3534 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3535 "4.4.4.4/32 present");
3537 fib_table_entry_delete(fib_index,
3540 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3541 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3542 "4.4.4.4/32 removed");
3545 * add-remove test. no change.
3547 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3548 fib_path_list_db_size());
3549 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3550 fib_path_list_pool_size());
3551 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3552 fib_entry_pool_size());
3555 * A route with multiple paths at once
3557 fib_route_path_t *r_paths = NULL;
3559 for (ii = 0; ii < 4; ii++)
3561 fib_route_path_t r_path = {
3562 .frp_proto = DPO_PROTO_IP4,
3564 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
3566 .frp_sw_if_index = tm->hw[0]->sw_if_index,
3568 .frp_fib_index = ~0,
3570 vec_add1(r_paths, r_path);
3573 fib_table_entry_update(fib_index,
3576 FIB_ENTRY_FLAG_NONE,
3579 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3580 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3581 dpo = fib_entry_contribute_ip_forwarding(fei);
3583 lb = load_balance_get(dpo->dpoi_index);
3584 FIB_TEST((lb->lb_n_buckets == 4), "4.4.4.4/32 lb over %d paths", lb->lb_n_buckets);
3586 fib_table_entry_delete(fib_index,
3589 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3590 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3591 "4.4.4.4/32 removed");
3595 * add-remove test. no change.
3597 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3598 fib_path_list_db_size());
3599 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3600 fib_path_list_pool_size());
3601 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3602 fib_entry_pool_size());
3605 * A route deag route
3607 fib_table_entry_path_add(fib_index,
3610 FIB_ENTRY_FLAG_NONE,
3617 FIB_ROUTE_PATH_FLAG_NONE);
3619 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3620 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3622 dpo = fib_entry_contribute_ip_forwarding(fei);
3623 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3624 lookup_dpo_t *lkd = lookup_dpo_get(dpo->dpoi_index);
3626 FIB_TEST((fib_index == lkd->lkd_fib_index),
3627 "4.4.4.4/32 is deag in %d %U",
3629 format_dpo_id, dpo, 0);
3630 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
3631 "4.4.4.4/32 is source deag in %d %U",
3633 format_dpo_id, dpo, 0);
3635 fib_table_entry_delete(fib_index,
3638 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3639 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3640 "4.4.4.4/32 removed");
3644 * A route deag route in a source lookup table
3646 fib_table_entry_path_add(fib_index,
3649 FIB_ENTRY_FLAG_NONE,
3656 FIB_ROUTE_PATH_SOURCE_LOOKUP);
3658 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3659 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3661 dpo = fib_entry_contribute_ip_forwarding(fei);
3662 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3663 lkd = lookup_dpo_get(dpo->dpoi_index);
3665 FIB_TEST((fib_index == lkd->lkd_fib_index),
3666 "4.4.4.4/32 is deag in %d %U",
3668 format_dpo_id, dpo, 0);
3669 FIB_TEST((LOOKUP_INPUT_SRC_ADDR == lkd->lkd_input),
3670 "4.4.4.4/32 is source deag in %d %U",
3672 format_dpo_id, dpo, 0);
3674 fib_table_entry_delete(fib_index,
3677 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3678 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3679 "4.4.4.4/32 removed");
3683 * add-remove test. no change.
3685 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3686 fib_path_list_db_size());
3687 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3688 fib_path_list_pool_size());
3689 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3690 fib_entry_pool_size());
3694 * add a recursive with duplicate paths. Expect the duplicate to be ignored.
3696 fib_prefix_t pfx_34_1_1_1_s_32 = {
3698 .fp_proto = FIB_PROTOCOL_IP4,
3700 .ip4.as_u32 = clib_host_to_net_u32(0x22010101),
3703 fib_prefix_t pfx_34_34_1_1_s_32 = {
3705 .fp_proto = FIB_PROTOCOL_IP4,
3707 .ip4.as_u32 = clib_host_to_net_u32(0x22220101),
3710 fei = fib_table_entry_path_add(fib_index,
3711 &pfx_34_34_1_1_s_32,
3713 FIB_ENTRY_FLAG_NONE,
3716 tm->hw[0]->sw_if_index,
3720 FIB_ROUTE_PATH_FLAG_NONE);
3721 fei = fib_table_entry_path_add(fib_index,
3724 FIB_ENTRY_FLAG_NONE,
3726 &pfx_34_34_1_1_s_32.fp_addr,
3731 FIB_ROUTE_PATH_FLAG_NONE);
3732 fei = fib_table_entry_path_add(fib_index,
3735 FIB_ENTRY_FLAG_NONE,
3737 &pfx_34_34_1_1_s_32.fp_addr,
3742 FIB_ROUTE_PATH_FLAG_NONE);
3743 FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0);
3744 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3745 fib_table_entry_delete(fib_index,
3746 &pfx_34_34_1_1_s_32,
3751 * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32
3752 * all of which are via 10.10.10.1, Itf1
3754 fib_table_entry_path_remove(fib_index,
3759 tm->hw[0]->sw_if_index,
3762 FIB_ROUTE_PATH_FLAG_NONE);
3763 fib_table_entry_path_remove(fib_index,
3768 tm->hw[0]->sw_if_index,
3771 FIB_ROUTE_PATH_FLAG_NONE);
3772 fib_table_entry_path_remove(fib_index,
3777 tm->hw[0]->sw_if_index,
3780 FIB_ROUTE_PATH_FLAG_NONE);
3782 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3783 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32),
3784 "1.1.1.1/32 removed");
3785 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3786 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32),
3787 "1.1.1.2/32 removed");
3788 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3789 fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24),
3790 "1.1.2.0/24 removed");
3793 * -3 entries and -1 shared path-list
3795 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3796 fib_path_list_db_size());
3797 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3798 fib_path_list_pool_size());
3799 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3800 fib_entry_pool_size());
3803 * An attached-host route. Expect to link to the incomplete adj
3805 fib_prefix_t pfx_4_1_1_1_s_32 = {
3807 .fp_proto = FIB_PROTOCOL_IP4,
3810 .ip4.as_u32 = clib_host_to_net_u32(0x04010101),
3813 fib_table_entry_path_add(fib_index,
3816 FIB_ENTRY_FLAG_NONE,
3819 tm->hw[0]->sw_if_index,
3823 FIB_ROUTE_PATH_FLAG_NONE);
3825 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32);
3826 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present");
3827 ai = fib_entry_get_adj(fei);
3829 ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
3831 &pfx_4_1_1_1_s_32.fp_addr,
3832 tm->hw[0]->sw_if_index);
3833 FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ");
3837 * +1 entry and +1 shared path-list
3839 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3840 fib_path_list_db_size());
3841 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3842 fib_path_list_pool_size());
3843 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
3844 fib_entry_pool_size());
3846 fib_table_entry_delete(fib_index,
3850 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3851 fib_path_list_db_size());
3852 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3853 fib_path_list_pool_size());
3854 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3855 fib_entry_pool_size());
3858 * add a v6 prefix via v4 next-hops
3860 fib_prefix_t pfx_2001_s_64 = {
3862 .fp_proto = FIB_PROTOCOL_IP6,
3864 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
3867 fei = fib_table_entry_path_add(0, //default v6 table
3870 FIB_ENTRY_FLAG_NONE,
3873 tm->hw[0]->sw_if_index,
3877 FIB_ROUTE_PATH_FLAG_NONE);
3879 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
3880 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present");
3881 ai = fib_entry_get_adj(fei);
3883 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
3884 "2001::/64 via ARP-adj");
3885 FIB_TEST((adj->ia_link == VNET_LINK_IP6),
3886 "2001::/64 is link type v6");
3887 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4),
3888 "2001::/64 ADJ-adj is NH proto v4");
3889 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
3892 * add a uRPF exempt prefix:
3894 * - it's forwarding is drop
3895 * - it's uRPF list is not empty
3896 * - the uRPF list for the default route (it's cover) is empty
3898 fei = fib_table_entry_special_add(fib_index,
3900 FIB_SOURCE_URPF_EXEMPT,
3901 FIB_ENTRY_FLAG_DROP);
3902 dpo = fib_entry_contribute_ip_forwarding(fei);
3903 FIB_TEST(load_balance_is_drop(dpo),
3904 "uRPF exempt 4.1.1.1/32 DROP");
3905 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0),
3906 "uRPF list for exempt prefix has itf index 0");
3907 fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0);
3908 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
3909 "uRPF list for 0.0.0.0/0 empty");
3911 fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
3914 * An adj-fib that fails the refinement criteria - no connected cover
3916 fib_prefix_t pfx_12_10_10_2_s_32 = {
3918 .fp_proto = FIB_PROTOCOL_IP4,
3921 .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02),
3925 fib_table_entry_path_add(fib_index,
3926 &pfx_12_10_10_2_s_32,
3928 FIB_ENTRY_FLAG_ATTACHED,
3930 &pfx_12_10_10_2_s_32.fp_addr,
3931 tm->hw[0]->sw_if_index,
3932 ~0, // invalid fib index
3935 FIB_ROUTE_PATH_FLAG_NONE);
3937 fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32);
3938 dpo = fib_entry_contribute_ip_forwarding(fei);
3939 FIB_TEST(!dpo_id_is_valid(dpo),
3940 "no connected cover adj-fib fails refinement");
3942 fib_table_entry_delete(fib_index,
3943 &pfx_12_10_10_2_s_32,
3947 * An adj-fib that fails the refinement criteria - cover is connected
3948 * but on a different interface
3950 fib_prefix_t pfx_10_10_10_127_s_32 = {
3952 .fp_proto = FIB_PROTOCOL_IP4,
3955 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f),
3959 fib_table_entry_path_add(fib_index,
3960 &pfx_10_10_10_127_s_32,
3962 FIB_ENTRY_FLAG_ATTACHED,
3964 &pfx_10_10_10_127_s_32.fp_addr,
3965 tm->hw[1]->sw_if_index,
3966 ~0, // invalid fib index
3969 FIB_ROUTE_PATH_FLAG_NONE);
3971 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32);
3972 dpo = fib_entry_contribute_ip_forwarding(fei);
3973 FIB_TEST(!dpo_id_is_valid(dpo),
3974 "wrong interface adj-fib fails refinement");
3976 fib_table_entry_delete(fib_index,
3977 &pfx_10_10_10_127_s_32,
3981 * add a second path to an adj-fib
3982 * this is a sumiluation of another ARP entry created
3983 * on an interface on which the connected prefi does not exist.
3984 * The second path fails refinement. Expect to forward through the
3987 fib_prefix_t pfx_10_10_10_3_s_32 = {
3989 .fp_proto = FIB_PROTOCOL_IP4,
3992 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
3996 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
3999 tm->hw[0]->sw_if_index);
4001 fib_test_lb_bucket_t ip_o_10_10_10_3 = {
4007 fei = fib_table_entry_path_add(fib_index,
4008 &pfx_10_10_10_3_s_32,
4010 FIB_ENTRY_FLAG_NONE,
4013 tm->hw[0]->sw_if_index,
4017 FIB_ROUTE_PATH_FLAG_NONE);
4018 fei = fib_table_entry_path_add(fib_index,
4019 &pfx_10_10_10_3_s_32,
4021 FIB_ENTRY_FLAG_NONE,
4024 tm->hw[1]->sw_if_index,
4028 FIB_ROUTE_PATH_FLAG_NONE);
4029 FIB_TEST(fib_test_validate_entry(fei,
4030 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4033 "10.10.10.3 via 10.10.10.3/Eth0 only");
4036 * remove the path that refines the cover, should go unresolved
4038 fib_table_entry_path_remove(fib_index,
4039 &pfx_10_10_10_3_s_32,
4043 tm->hw[0]->sw_if_index,
4046 FIB_ROUTE_PATH_FLAG_NONE);
4047 dpo = fib_entry_contribute_ip_forwarding(fei);
4048 FIB_TEST(!dpo_id_is_valid(dpo),
4049 "wrong interface adj-fib fails refinement");
4052 * add back the path that refines the cover
4054 fei = fib_table_entry_path_add(fib_index,
4055 &pfx_10_10_10_3_s_32,
4057 FIB_ENTRY_FLAG_NONE,
4060 tm->hw[0]->sw_if_index,
4064 FIB_ROUTE_PATH_FLAG_NONE);
4065 FIB_TEST(fib_test_validate_entry(fei,
4066 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4069 "10.10.10.3 via 10.10.10.3/Eth0 only");
4072 * remove the path that does not refine the cover
4074 fib_table_entry_path_remove(fib_index,
4075 &pfx_10_10_10_3_s_32,
4079 tm->hw[1]->sw_if_index,
4082 FIB_ROUTE_PATH_FLAG_NONE);
4083 FIB_TEST(fib_test_validate_entry(fei,
4084 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4087 "10.10.10.3 via 10.10.10.3/Eth0 only");
4090 * remove the path that does refine, it's the last path, so
4091 * the entry should be gone
4093 fib_table_entry_path_remove(fib_index,
4094 &pfx_10_10_10_3_s_32,
4098 tm->hw[0]->sw_if_index,
4101 FIB_ROUTE_PATH_FLAG_NONE);
4102 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
4103 FIB_TEST((fei == FIB_NODE_INDEX_INVALID), "10.10.10.3 gone");
4108 * change the table's flow-hash config - expect the update to propagete to
4109 * the entries' load-balance objects
4111 flow_hash_config_t old_hash_config, new_hash_config;
4113 old_hash_config = fib_table_get_flow_hash_config(fib_index,
4115 new_hash_config = (IP_FLOW_HASH_SRC_ADDR |
4116 IP_FLOW_HASH_DST_ADDR);
4118 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
4119 dpo = fib_entry_contribute_ip_forwarding(fei);
4120 lb = load_balance_get(dpo->dpoi_index);
4121 FIB_TEST((lb->lb_hash_config == old_hash_config),
4122 "Table and LB hash config match: %U",
4123 format_ip_flow_hash_config, lb->lb_hash_config);
4125 fib_table_set_flow_hash_config(fib_index, FIB_PROTOCOL_IP4, new_hash_config);
4127 FIB_TEST((lb->lb_hash_config == new_hash_config),
4128 "Table and LB newhash config match: %U",
4129 format_ip_flow_hash_config, lb->lb_hash_config);
4132 * A route via DVR DPO
4134 fei = fib_table_entry_path_add(fib_index,
4135 &pfx_10_10_10_3_s_32,
4137 FIB_ENTRY_FLAG_NONE,
4140 tm->hw[0]->sw_if_index,
4144 FIB_ROUTE_PATH_DVR);
4145 dpo_id_t dvr_dpo = DPO_INVALID;
4146 dvr_dpo_add_or_lock(tm->hw[0]->sw_if_index, DPO_PROTO_IP4, &dvr_dpo);
4147 fib_test_lb_bucket_t ip_o_l2 = {
4150 .adj = dvr_dpo.dpoi_index,
4154 FIB_TEST(fib_test_validate_entry(fei,
4155 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4158 "10.10.10.3 via L2 on Eth0");
4159 fib_table_entry_path_remove(fib_index,
4160 &pfx_10_10_10_3_s_32,
4164 tm->hw[0]->sw_if_index,
4167 FIB_ROUTE_PATH_DVR);
4168 dpo_reset(&dvr_dpo);
4174 fib_table_entry_delete(fib_index,
4175 &pfx_10_10_10_1_s_32,
4177 fib_table_entry_delete(fib_index,
4178 &pfx_10_10_10_2_s_32,
4180 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4181 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32),
4182 "10.10.10.1/32 adj-fib removed");
4183 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4184 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32),
4185 "10.10.10.2/32 adj-fib removed");
4188 * -2 entries and -2 non-shared path-list
4190 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4191 fib_path_list_db_size());
4192 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
4193 fib_path_list_pool_size());
4194 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
4195 fib_entry_pool_size());
4198 * unlock the adjacencies for which this test provided a rewrite.
4199 * These are the last locks on these adjs. they should thus go away.
4203 adj_unlock(ai_12_12_12_12);
4205 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4210 * remove the interface prefixes
4212 local_pfx.fp_len = 32;
4213 fib_table_entry_special_remove(fib_index, &local_pfx,
4214 FIB_SOURCE_INTERFACE);
4215 fei = fib_table_lookup(fib_index, &local_pfx);
4217 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4218 fib_table_lookup_exact_match(fib_index, &local_pfx),
4219 "10.10.10.10/32 adj-fib removed");
4221 local_pfx.fp_len = 24;
4222 fib_table_entry_delete(fib_index, &local_pfx,
4223 FIB_SOURCE_INTERFACE);
4225 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4226 fib_table_lookup_exact_match(fib_index, &local_pfx),
4227 "10.10.10.10/24 adj-fib removed");
4230 * -2 entries and -2 non-shared path-list
4232 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4233 fib_path_list_db_size());
4234 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
4235 fib_path_list_pool_size());
4236 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
4237 fib_entry_pool_size());
4240 * Last but not least, remove the VRF
4242 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4245 "NO API Source'd prefixes");
4246 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4249 "NO RR Source'd prefixes");
4250 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4252 FIB_SOURCE_INTERFACE)),
4253 "NO INterface Source'd prefixes");
4255 fib_table_unlock(fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
4257 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4258 fib_path_list_db_size());
4259 FIB_TEST((PNBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
4260 fib_path_list_pool_size());
4261 FIB_TEST((ENBR-5 == fib_entry_pool_size()), "entry pool size is %d",
4262 fib_entry_pool_size());
4263 FIB_TEST((ENBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
4264 pool_elts(fib_urpf_list_pool));
4265 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
4266 pool_elts(load_balance_map_pool));
4267 FIB_TEST((lb_count == pool_elts(load_balance_pool)), "LB pool size is %d",
4268 pool_elts(load_balance_pool));
4269 FIB_TEST((0 == pool_elts(dvr_dpo_pool)), "L2 DPO pool size is %d",
4270 pool_elts(dvr_dpo_pool));
4279 * In the default table check for the presence and correct forwarding
4280 * of the special entries
4282 fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02;
4283 const dpo_id_t *dpo, *dpo_drop;
4284 const ip_adjacency_t *adj;
4285 const receive_dpo_t *rd;
4290 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4293 /* via 2001:0:0:1::2 */
4294 ip46_address_t nh_2001_2 = {
4297 [0] = clib_host_to_net_u64(0x2001000000000001),
4298 [1] = clib_host_to_net_u64(0x0000000000000002),
4305 dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
4307 /* Find or create FIB table 11 */
4308 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11,
4311 for (ii = 0; ii < 4; ii++)
4313 ip6_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
4316 fib_prefix_t pfx_0_0 = {
4318 .fp_proto = FIB_PROTOCOL_IP6,
4326 dfrt = fib_table_lookup(fib_index, &pfx_0_0);
4327 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
4328 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4329 "Default route is DROP");
4331 dpo = fib_entry_contribute_ip_forwarding(dfrt);
4332 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4335 &pfx_0_0.fp_addr.ip6)),
4336 "default-route; fwd and non-fwd tables match");
4338 // FIXME - check specials.
4341 * At this stage there is one v4 FIB with 5 routes and two v6 FIBs
4342 * each with 2 entries and a v6 mfib with 4 path-lists.
4343 * All entries are special so no path-list sharing.
4346 #define PNPS (5+4+4)
4347 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
4348 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is %d",
4349 fib_path_list_pool_size());
4350 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
4351 fib_entry_pool_size());
4354 * add interface routes.
4355 * validate presence of /64 attached and /128 recieve.
4356 * test for the presence of the receive address in the glean and local adj
4358 * receive on 2001:0:0:1::1/128
4360 fib_prefix_t local_pfx = {
4362 .fp_proto = FIB_PROTOCOL_IP6,
4366 [0] = clib_host_to_net_u64(0x2001000000000001),
4367 [1] = clib_host_to_net_u64(0x0000000000000001),
4373 fib_table_entry_update_one_path(fib_index, &local_pfx,
4374 FIB_SOURCE_INTERFACE,
4375 (FIB_ENTRY_FLAG_CONNECTED |
4376 FIB_ENTRY_FLAG_ATTACHED),
4379 tm->hw[0]->sw_if_index,
4383 FIB_ROUTE_PATH_FLAG_NONE);
4384 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4386 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4388 ai = fib_entry_get_adj(fei);
4389 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
4391 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4392 "attached interface adj is glean");
4393 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4394 &adj->sub_type.glean.receive_addr)),
4395 "attached interface adj is receive ok");
4396 dpo = fib_entry_contribute_ip_forwarding(fei);
4397 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4400 &local_pfx.fp_addr.ip6)),
4401 "attached-route; fwd and non-fwd tables match");
4403 local_pfx.fp_len = 128;
4404 fib_table_entry_update_one_path(fib_index, &local_pfx,
4405 FIB_SOURCE_INTERFACE,
4406 (FIB_ENTRY_FLAG_CONNECTED |
4407 FIB_ENTRY_FLAG_LOCAL),
4410 tm->hw[0]->sw_if_index,
4411 ~0, // invalid fib index
4414 FIB_ROUTE_PATH_FLAG_NONE);
4415 fei = fib_table_lookup(fib_index, &local_pfx);
4417 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4419 dpo = fib_entry_contribute_ip_forwarding(fei);
4420 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4421 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4422 "local interface adj is local");
4423 rd = receive_dpo_get(dpo->dpoi_index);
4425 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4427 "local interface adj is receive ok");
4429 dpo = fib_entry_contribute_ip_forwarding(fei);
4430 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4433 &local_pfx.fp_addr.ip6)),
4434 "local-route; fwd and non-fwd tables match");
4437 * +2 entries. +2 unshared path-lists
4439 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
4440 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
4441 fib_path_list_pool_size());
4442 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4443 fib_entry_pool_size());
4446 * Modify the default route to be via an adj not yet known.
4447 * this sources the defalut route with the API source, which is
4448 * a higher preference to the DEFAULT_ROUTE source
4450 fib_table_entry_path_add(fib_index, &pfx_0_0,
4452 FIB_ENTRY_FLAG_NONE,
4455 tm->hw[0]->sw_if_index,
4459 FIB_ROUTE_PATH_FLAG_NONE);
4460 fei = fib_table_lookup(fib_index, &pfx_0_0);
4462 FIB_TEST((fei == dfrt), "default route same index");
4463 ai = fib_entry_get_adj(fei);
4464 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
4466 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4467 "adj is incomplete");
4468 FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)),
4469 "adj nbr next-hop ok");
4472 * find the adj in the shared db
4474 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4477 tm->hw[0]->sw_if_index);
4478 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
4479 adj_unlock(locked_ai);
4482 * no more entires. +1 shared path-list
4484 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4485 fib_path_list_db_size());
4486 FIB_TEST((PNPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
4487 fib_path_list_pool_size());
4488 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4489 fib_entry_pool_size());
4492 * remove the API source from the default route. We expected
4493 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
4495 fib_table_entry_path_remove(fib_index, &pfx_0_0,
4499 tm->hw[0]->sw_if_index,
4502 FIB_ROUTE_PATH_FLAG_NONE);
4503 fei = fib_table_lookup(fib_index, &pfx_0_0);
4505 FIB_TEST((fei == dfrt), "default route same index");
4506 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4507 "Default route is DROP");
4510 * no more entires. -1 shared path-list
4512 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4513 fib_path_list_db_size());
4514 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
4515 fib_path_list_pool_size());
4516 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4517 fib_entry_pool_size());
4520 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4522 fib_prefix_t pfx_2001_1_2_s_128 = {
4524 .fp_proto = FIB_PROTOCOL_IP6,
4528 [0] = clib_host_to_net_u64(0x2001000000000001),
4529 [1] = clib_host_to_net_u64(0x0000000000000002),
4534 fib_prefix_t pfx_2001_1_3_s_128 = {
4536 .fp_proto = FIB_PROTOCOL_IP6,
4540 [0] = clib_host_to_net_u64(0x2001000000000001),
4541 [1] = clib_host_to_net_u64(0x0000000000000003),
4547 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
4550 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4552 &pfx_2001_1_2_s_128.fp_addr,
4553 tm->hw[0]->sw_if_index);
4554 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
4555 adj = adj_get(ai_01);
4556 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4557 "adj is incomplete");
4558 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4559 &adj->sub_type.nbr.next_hop)),
4560 "adj nbr next-hop ok");
4562 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4563 fib_test_build_rewrite(eth_addr));
4564 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4566 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4567 &adj->sub_type.nbr.next_hop)),
4568 "adj nbr next-hop ok");
4570 fib_table_entry_path_add(fib_index,
4571 &pfx_2001_1_2_s_128,
4573 FIB_ENTRY_FLAG_ATTACHED,
4575 &pfx_2001_1_2_s_128.fp_addr,
4576 tm->hw[0]->sw_if_index,
4580 FIB_ROUTE_PATH_FLAG_NONE);
4582 fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
4583 ai = fib_entry_get_adj(fei);
4584 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4588 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4590 &pfx_2001_1_3_s_128.fp_addr,
4591 tm->hw[0]->sw_if_index);
4592 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
4593 adj = adj_get(ai_02);
4594 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4595 "adj is incomplete");
4596 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4597 &adj->sub_type.nbr.next_hop)),
4598 "adj nbr next-hop ok");
4600 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4601 fib_test_build_rewrite(eth_addr));
4602 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4604 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4605 &adj->sub_type.nbr.next_hop)),
4606 "adj nbr next-hop ok");
4607 FIB_TEST((ai_01 != ai_02), "ADJs are different");
4609 fib_table_entry_path_add(fib_index,
4610 &pfx_2001_1_3_s_128,
4612 FIB_ENTRY_FLAG_ATTACHED,
4614 &pfx_2001_1_3_s_128.fp_addr,
4615 tm->hw[0]->sw_if_index,
4619 FIB_ROUTE_PATH_FLAG_NONE);
4621 fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
4622 ai = fib_entry_get_adj(fei);
4623 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4626 * +2 entries, +2 unshread path-lists.
4628 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4629 fib_path_list_db_size());
4630 FIB_TEST((PNPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
4631 fib_path_list_pool_size());
4632 FIB_TEST((ENPS+4 == fib_entry_pool_size()), "entry pool size is %d",
4633 fib_entry_pool_size());
4636 * Add a 2 routes via the first ADJ. ensure path-list sharing
4638 fib_prefix_t pfx_2001_a_s_64 = {
4640 .fp_proto = FIB_PROTOCOL_IP6,
4644 [0] = clib_host_to_net_u64(0x200100000000000a),
4645 [1] = clib_host_to_net_u64(0x0000000000000000),
4650 fib_prefix_t pfx_2001_b_s_64 = {
4652 .fp_proto = FIB_PROTOCOL_IP6,
4656 [0] = clib_host_to_net_u64(0x200100000000000b),
4657 [1] = clib_host_to_net_u64(0x0000000000000000),
4663 fib_table_entry_path_add(fib_index,
4666 FIB_ENTRY_FLAG_NONE,
4669 tm->hw[0]->sw_if_index,
4673 FIB_ROUTE_PATH_FLAG_NONE);
4674 fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64);
4675 ai = fib_entry_get_adj(fei);
4676 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4677 fib_table_entry_path_add(fib_index,
4680 FIB_ENTRY_FLAG_NONE,
4683 tm->hw[0]->sw_if_index,
4687 FIB_ROUTE_PATH_FLAG_NONE);
4688 fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64);
4689 ai = fib_entry_get_adj(fei);
4690 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4693 * +2 entries, +1 shared path-list.
4695 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4696 fib_path_list_db_size());
4697 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4698 fib_path_list_pool_size());
4699 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
4700 fib_entry_pool_size());
4703 * add a v4 prefix via a v6 next-hop
4705 fib_prefix_t pfx_1_1_1_1_s_32 = {
4707 .fp_proto = FIB_PROTOCOL_IP4,
4709 .ip4.as_u32 = 0x01010101,
4712 fei = fib_table_entry_path_add(0, // default table
4715 FIB_ENTRY_FLAG_NONE,
4718 tm->hw[0]->sw_if_index,
4722 FIB_ROUTE_PATH_FLAG_NONE);
4723 FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32),
4724 "1.1.1.1/32 o v6 route present");
4725 ai = fib_entry_get_adj(fei);
4727 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
4728 "1.1.1.1/32 via ARP-adj");
4729 FIB_TEST((adj->ia_link == VNET_LINK_IP4),
4730 "1.1.1.1/32 ADJ-adj is link type v4");
4731 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6),
4732 "1.1.1.1/32 ADJ-adj is NH proto v6");
4733 fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API);
4738 fib_prefix_t pfx_2001_c_s_64 = {
4740 .fp_proto = FIB_PROTOCOL_IP6,
4744 [0] = clib_host_to_net_u64(0x200100000000000c),
4745 [1] = clib_host_to_net_u64(0x0000000000000000),
4750 fib_table_entry_path_add(fib_index,
4753 FIB_ENTRY_FLAG_ATTACHED,
4756 tm->hw[0]->sw_if_index,
4760 FIB_ROUTE_PATH_FLAG_NONE);
4761 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4762 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present");
4763 ai = fib_entry_get_adj(fei);
4765 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN),
4766 "2001:0:0:c/64 attached resolves via glean");
4768 fib_table_entry_path_remove(fib_index,
4773 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 removed");
4781 * Shutdown the interface on which we have a connected and through
4782 * which the routes are reachable.
4783 * This will result in the connected, adj-fibs, and routes linking to drop
4784 * The local/for-us prefix continues to receive.
4786 clib_error_t * error;
4788 error = vnet_sw_interface_set_flags(vnet_get_main(),
4789 tm->hw[0]->sw_if_index,
4790 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4791 FIB_TEST((NULL == error), "Interface shutdown OK");
4793 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4794 dpo = fib_entry_contribute_ip_forwarding(fei);
4795 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4796 "2001::b/64 resolves via drop");
4798 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4799 dpo = fib_entry_contribute_ip_forwarding(fei);
4800 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4801 "2001::a/64 resolves via drop");
4802 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4803 dpo = fib_entry_contribute_ip_forwarding(fei);
4804 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4805 "2001:0:0:1::3/64 resolves via drop");
4806 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4807 dpo = fib_entry_contribute_ip_forwarding(fei);
4808 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4809 "2001:0:0:1::2/64 resolves via drop");
4810 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4811 dpo = fib_entry_contribute_ip_forwarding(fei);
4812 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4813 "2001:0:0:1::1/128 not drop");
4814 local_pfx.fp_len = 64;
4815 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4816 dpo = fib_entry_contribute_ip_forwarding(fei);
4817 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4818 "2001:0:0:1/64 resolves via drop");
4823 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4824 fib_path_list_db_size());
4825 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4826 fib_path_list_pool_size());
4827 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
4828 fib_entry_pool_size());
4831 * shutdown one of the other interfaces, then add a connected.
4832 * and swap one of the routes to it.
4834 error = vnet_sw_interface_set_flags(vnet_get_main(),
4835 tm->hw[1]->sw_if_index,
4836 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4837 FIB_TEST((NULL == error), "Interface 1 shutdown OK");
4839 fib_prefix_t connected_pfx = {
4841 .fp_proto = FIB_PROTOCOL_IP6,
4844 /* 2001:0:0:2::1/64 */
4846 [0] = clib_host_to_net_u64(0x2001000000000002),
4847 [1] = clib_host_to_net_u64(0x0000000000000001),
4852 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4853 FIB_SOURCE_INTERFACE,
4854 (FIB_ENTRY_FLAG_CONNECTED |
4855 FIB_ENTRY_FLAG_ATTACHED),
4858 tm->hw[1]->sw_if_index,
4862 FIB_ROUTE_PATH_FLAG_NONE);
4863 fei = fib_table_lookup_exact_match(fib_index, &connected_pfx);
4864 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4865 dpo = fib_entry_contribute_ip_forwarding(fei);
4866 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4867 FIB_TEST(!dpo_cmp(dpo, dpo_drop),
4868 "2001:0:0:2/64 not resolves via drop");
4870 connected_pfx.fp_len = 128;
4871 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4872 FIB_SOURCE_INTERFACE,
4873 (FIB_ENTRY_FLAG_CONNECTED |
4874 FIB_ENTRY_FLAG_LOCAL),
4877 tm->hw[0]->sw_if_index,
4878 ~0, // invalid fib index
4881 FIB_ROUTE_PATH_FLAG_NONE);
4882 fei = fib_table_lookup(fib_index, &connected_pfx);
4884 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4885 dpo = fib_entry_contribute_ip_forwarding(fei);
4886 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4887 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4888 "local interface adj is local");
4889 rd = receive_dpo_get(dpo->dpoi_index);
4890 FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr,
4892 "local interface adj is receive ok");
4895 * +2 entries, +2 unshared path-lists
4897 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4898 fib_path_list_db_size());
4899 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
4900 fib_path_list_pool_size());
4901 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
4902 fib_entry_pool_size());
4906 * bring the interface back up. we expected the routes to return
4907 * to normal forwarding.
4909 error = vnet_sw_interface_set_flags(vnet_get_main(),
4910 tm->hw[0]->sw_if_index,
4911 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4912 FIB_TEST((NULL == error), "Interface bring-up OK");
4913 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4914 ai = fib_entry_get_adj(fei);
4915 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4916 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4917 ai = fib_entry_get_adj(fei);
4918 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4919 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4920 ai = fib_entry_get_adj(fei);
4921 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4922 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4923 ai = fib_entry_get_adj(fei);
4924 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4925 local_pfx.fp_len = 64;
4926 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4927 ai = fib_entry_get_adj(fei);
4929 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4930 "attached interface adj is glean");
4933 * Same test as above, but this time the HW interface goes down
4935 error = vnet_hw_interface_set_flags(vnet_get_main(),
4936 tm->hw_if_indicies[0],
4937 ~VNET_HW_INTERFACE_FLAG_LINK_UP);
4938 FIB_TEST((NULL == error), "Interface shutdown OK");
4940 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4941 dpo = fib_entry_contribute_ip_forwarding(fei);
4942 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4943 "2001::b/64 resolves via drop");
4944 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4945 dpo = fib_entry_contribute_ip_forwarding(fei);
4946 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4947 "2001::a/64 resolves via drop");
4948 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4949 dpo = fib_entry_contribute_ip_forwarding(fei);
4950 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4951 "2001:0:0:1::3/128 resolves via drop");
4952 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4953 dpo = fib_entry_contribute_ip_forwarding(fei);
4954 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4955 "2001:0:0:1::2/128 resolves via drop");
4956 local_pfx.fp_len = 128;
4957 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4958 dpo = fib_entry_contribute_ip_forwarding(fei);
4959 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4960 "2001:0:0:1::1/128 not drop");
4961 local_pfx.fp_len = 64;
4962 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4963 dpo = fib_entry_contribute_ip_forwarding(fei);
4964 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4965 "2001:0:0:1/64 resolves via drop");
4967 error = vnet_hw_interface_set_flags(vnet_get_main(),
4968 tm->hw_if_indicies[0],
4969 VNET_HW_INTERFACE_FLAG_LINK_UP);
4970 FIB_TEST((NULL == error), "Interface bring-up OK");
4971 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4972 ai = fib_entry_get_adj(fei);
4973 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4974 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4975 ai = fib_entry_get_adj(fei);
4976 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4977 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4978 ai = fib_entry_get_adj(fei);
4979 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4980 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4981 ai = fib_entry_get_adj(fei);
4982 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4983 local_pfx.fp_len = 64;
4984 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4985 ai = fib_entry_get_adj(fei);
4987 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4988 "attached interface adj is glean");
4991 * Delete the interface that the routes reolve through.
4992 * Again no routes are removed. They all point to drop.
4994 * This is considered an error case. The control plane should
4995 * not remove interfaces through which routes resolve, but
4996 * such things can happen. ALL affected routes will drop.
4998 vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]);
5000 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5001 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5002 "2001::b/64 resolves via drop");
5003 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5004 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5005 "2001::b/64 resolves via drop");
5006 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5007 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5008 "2001:0:0:1::3/64 resolves via drop");
5009 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5010 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5011 "2001:0:0:1::2/64 resolves via drop");
5012 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5013 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5014 "2001:0:0:1::1/128 is drop");
5015 local_pfx.fp_len = 64;
5016 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5017 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5018 "2001:0:0:1/64 resolves via drop");
5023 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
5024 fib_path_list_db_size());
5025 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
5026 fib_path_list_pool_size());
5027 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
5028 fib_entry_pool_size());
5031 * Add the interface back. routes stay unresolved.
5033 error = ethernet_register_interface(vnet_get_main(),
5034 test_interface_device_class.index,
5037 &tm->hw_if_indicies[0],
5038 /* flag change */ 0);
5040 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5041 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5042 "2001::b/64 resolves via drop");
5043 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5044 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5045 "2001::b/64 resolves via drop");
5046 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5047 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5048 "2001:0:0:1::3/64 resolves via drop");
5049 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5050 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5051 "2001:0:0:1::2/64 resolves via drop");
5052 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5053 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5054 "2001:0:0:1::1/128 is drop");
5055 local_pfx.fp_len = 64;
5056 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5057 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5058 "2001:0:0:1/64 resolves via drop");
5061 * CLEANUP ALL the routes
5063 fib_table_entry_delete(fib_index,
5066 fib_table_entry_delete(fib_index,
5069 fib_table_entry_delete(fib_index,
5072 fib_table_entry_delete(fib_index,
5073 &pfx_2001_1_3_s_128,
5075 fib_table_entry_delete(fib_index,
5076 &pfx_2001_1_2_s_128,
5078 local_pfx.fp_len = 64;
5079 fib_table_entry_delete(fib_index, &local_pfx,
5080 FIB_SOURCE_INTERFACE);
5081 local_pfx.fp_len = 128;
5082 fib_table_entry_special_remove(fib_index, &local_pfx,
5083 FIB_SOURCE_INTERFACE);
5084 connected_pfx.fp_len = 64;
5085 fib_table_entry_delete(fib_index, &connected_pfx,
5086 FIB_SOURCE_INTERFACE);
5087 connected_pfx.fp_len = 128;
5088 fib_table_entry_special_remove(fib_index, &connected_pfx,
5089 FIB_SOURCE_INTERFACE);
5091 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5092 fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)),
5093 "2001::a/64 removed");
5094 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5095 fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)),
5096 "2001::b/64 removed");
5097 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5098 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)),
5099 "2001:0:0:1::3/128 removed");
5100 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5101 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)),
5102 "2001:0:0:1::3/128 removed");
5103 local_pfx.fp_len = 64;
5104 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5105 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5106 "2001:0:0:1/64 removed");
5107 local_pfx.fp_len = 128;
5108 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5109 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5110 "2001:0:0:1::1/128 removed");
5111 connected_pfx.fp_len = 64;
5112 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5113 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5114 "2001:0:0:2/64 removed");
5115 connected_pfx.fp_len = 128;
5116 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5117 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5118 "2001:0:0:2::1/128 removed");
5121 * -8 entries. -7 path-lists (1 was shared).
5123 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5124 fib_path_list_db_size());
5125 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is%d",
5126 fib_path_list_pool_size());
5127 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
5128 fib_entry_pool_size());
5131 * now remove the VRF
5133 fib_table_unlock(fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
5135 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5136 fib_path_list_db_size());
5137 FIB_TEST((PNPS-2 == fib_path_list_pool_size()), "path list pool size is%d",
5138 fib_path_list_pool_size());
5139 FIB_TEST((ENPS-2 == fib_entry_pool_size()), "entry pool size is %d",
5140 fib_entry_pool_size());
5146 * return the interfaces to up state
5148 error = vnet_sw_interface_set_flags(vnet_get_main(),
5149 tm->hw[0]->sw_if_index,
5150 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5151 error = vnet_sw_interface_set_flags(vnet_get_main(),
5152 tm->hw[1]->sw_if_index,
5153 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5155 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5162 * Test Attached Exports
5167 const dpo_id_t *dpo, *dpo_drop;
5168 const u32 fib_index = 0;
5169 fib_node_index_t fei;
5176 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5180 * add interface routes. We'll assume this works. It's more rigorously
5183 fib_prefix_t local_pfx = {
5185 .fp_proto = FIB_PROTOCOL_IP4,
5189 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5194 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
5195 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
5197 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
5199 fib_table_entry_update_one_path(fib_index, &local_pfx,
5200 FIB_SOURCE_INTERFACE,
5201 (FIB_ENTRY_FLAG_CONNECTED |
5202 FIB_ENTRY_FLAG_ATTACHED),
5205 tm->hw[0]->sw_if_index,
5209 FIB_ROUTE_PATH_FLAG_NONE);
5210 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5211 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5212 "attached interface route present");
5214 local_pfx.fp_len = 32;
5215 fib_table_entry_update_one_path(fib_index, &local_pfx,
5216 FIB_SOURCE_INTERFACE,
5217 (FIB_ENTRY_FLAG_CONNECTED |
5218 FIB_ENTRY_FLAG_LOCAL),
5221 tm->hw[0]->sw_if_index,
5222 ~0, // invalid fib index
5225 FIB_ROUTE_PATH_FLAG_NONE);
5226 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5228 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5229 "local interface route present");
5232 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
5234 fib_prefix_t pfx_10_10_10_1_s_32 = {
5236 .fp_proto = FIB_PROTOCOL_IP4,
5239 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5242 fib_node_index_t ai;
5244 fib_table_entry_path_add(fib_index,
5245 &pfx_10_10_10_1_s_32,
5247 FIB_ENTRY_FLAG_ATTACHED,
5249 &pfx_10_10_10_1_s_32.fp_addr,
5250 tm->hw[0]->sw_if_index,
5251 ~0, // invalid fib index
5254 FIB_ROUTE_PATH_FLAG_NONE);
5256 fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
5257 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
5258 ai = fib_entry_get_adj(fei);
5261 * create another FIB table into which routes will be imported
5263 u32 import_fib_index1;
5265 import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4,
5270 * Add an attached route in the import FIB
5272 local_pfx.fp_len = 24;
5273 fib_table_entry_update_one_path(import_fib_index1,
5276 FIB_ENTRY_FLAG_NONE,
5279 tm->hw[0]->sw_if_index,
5280 ~0, // invalid fib index
5283 FIB_ROUTE_PATH_FLAG_NONE);
5284 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5285 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5288 * check for the presence of the adj-fibs in the import table
5290 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5291 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5292 FIB_TEST((ai == fib_entry_get_adj(fei)),
5293 "adj-fib1 Import uses same adj as export");
5296 * check for the presence of the local in the import table
5298 local_pfx.fp_len = 32;
5299 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5300 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5303 * Add another adj-fin in the export table. Expect this
5304 * to get magically exported;
5306 fib_prefix_t pfx_10_10_10_2_s_32 = {
5308 .fp_proto = FIB_PROTOCOL_IP4,
5311 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5315 fib_table_entry_path_add(fib_index,
5316 &pfx_10_10_10_2_s_32,
5318 FIB_ENTRY_FLAG_ATTACHED,
5320 &pfx_10_10_10_2_s_32.fp_addr,
5321 tm->hw[0]->sw_if_index,
5322 ~0, // invalid fib index
5325 FIB_ROUTE_PATH_FLAG_NONE);
5326 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5327 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
5328 ai = fib_entry_get_adj(fei);
5330 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5331 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5332 FIB_TEST((ai == fib_entry_get_adj(fei)),
5333 "Import uses same adj as export");
5334 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(fei)),
5335 "ADJ-fib2 imported flags %d",
5336 fib_entry_get_flags(fei));
5339 * create a 2nd FIB table into which routes will be imported
5341 u32 import_fib_index2;
5343 import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12,
5347 * Add an attached route in the import FIB
5349 local_pfx.fp_len = 24;
5350 fib_table_entry_update_one_path(import_fib_index2,
5353 FIB_ENTRY_FLAG_NONE,
5356 tm->hw[0]->sw_if_index,
5357 ~0, // invalid fib index
5360 FIB_ROUTE_PATH_FLAG_NONE);
5361 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5362 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5365 * check for the presence of all the adj-fibs and local in the import table
5367 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5368 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5369 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5370 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5371 local_pfx.fp_len = 32;
5372 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5373 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5376 * add a 3rd adj-fib. expect it to be exported to both tables.
5378 fib_prefix_t pfx_10_10_10_3_s_32 = {
5380 .fp_proto = FIB_PROTOCOL_IP4,
5383 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
5387 fib_table_entry_path_add(fib_index,
5388 &pfx_10_10_10_3_s_32,
5390 FIB_ENTRY_FLAG_ATTACHED,
5392 &pfx_10_10_10_3_s_32.fp_addr,
5393 tm->hw[0]->sw_if_index,
5394 ~0, // invalid fib index
5397 FIB_ROUTE_PATH_FLAG_NONE);
5398 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5399 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
5400 ai = fib_entry_get_adj(fei);
5402 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5403 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1");
5404 FIB_TEST((ai == fib_entry_get_adj(fei)),
5405 "Import uses same adj as export");
5406 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5407 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2");
5408 FIB_TEST((ai == fib_entry_get_adj(fei)),
5409 "Import uses same adj as export");
5412 * remove the 3rd adj fib. we expect it to be removed from both FIBs
5414 fib_table_entry_delete(fib_index,
5415 &pfx_10_10_10_3_s_32,
5418 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5419 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved");
5421 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5422 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1");
5424 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5425 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2");
5428 * remove the attached route from the 2nd FIB. expect the imported
5429 * entires to be removed
5431 local_pfx.fp_len = 24;
5432 fib_table_entry_delete(import_fib_index2,
5435 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5436 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed");
5438 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5439 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2");
5440 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5441 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2");
5442 local_pfx.fp_len = 32;
5443 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5444 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2");
5446 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5447 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1");
5448 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5449 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1");
5450 local_pfx.fp_len = 32;
5451 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5452 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1");
5455 * modify the route in FIB1 so it is no longer attached. expect the imported
5456 * entires to be removed
5458 local_pfx.fp_len = 24;
5459 fib_table_entry_update_one_path(import_fib_index1,
5462 FIB_ENTRY_FLAG_NONE,
5464 &pfx_10_10_10_2_s_32.fp_addr,
5465 tm->hw[0]->sw_if_index,
5466 ~0, // invalid fib index
5469 FIB_ROUTE_PATH_FLAG_NONE);
5470 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5471 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5472 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5473 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5474 local_pfx.fp_len = 32;
5475 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5476 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5479 * modify it back to attached. expect the adj-fibs back
5481 local_pfx.fp_len = 24;
5482 fib_table_entry_update_one_path(import_fib_index1,
5485 FIB_ENTRY_FLAG_NONE,
5488 tm->hw[0]->sw_if_index,
5489 ~0, // invalid fib index
5492 FIB_ROUTE_PATH_FLAG_NONE);
5493 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5494 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1");
5495 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5496 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1");
5497 local_pfx.fp_len = 32;
5498 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5499 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1");
5502 * add a covering attached next-hop for the interface address, so we have
5503 * a valid adj to find when we check the forwarding tables
5505 fib_prefix_t pfx_10_0_0_0_s_8 = {
5507 .fp_proto = FIB_PROTOCOL_IP4,
5510 .ip4.as_u32 = clib_host_to_net_u32(0x0a000000),
5514 fei = fib_table_entry_update_one_path(fib_index,
5517 FIB_ENTRY_FLAG_NONE,
5519 &pfx_10_10_10_3_s_32.fp_addr,
5520 tm->hw[0]->sw_if_index,
5521 ~0, // invalid fib index
5524 FIB_ROUTE_PATH_FLAG_NONE);
5525 dpo = fib_entry_contribute_ip_forwarding(fei);
5528 * remove the route in the export fib. expect the adj-fibs to be removed
5530 local_pfx.fp_len = 24;
5531 fib_table_entry_delete(fib_index,
5533 FIB_SOURCE_INTERFACE);
5535 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5536 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1");
5537 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5538 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5539 local_pfx.fp_len = 32;
5540 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5541 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5544 * the adj-fibs in the export VRF are present in the FIB table,
5545 * but not installed in forwarding, since they have no attached cover.
5546 * Consequently a lookup in the MTRIE gives the adj for the covering
5549 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5550 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5553 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5554 FIB_TEST(lbi == dpo->dpoi_index,
5555 "10.10.10.1 forwards on \n%U not \n%U",
5556 format_load_balance, lbi, 0,
5557 format_dpo_id, dpo, 0);
5558 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5559 FIB_TEST(lbi == dpo->dpoi_index,
5560 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5561 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4);
5562 FIB_TEST(lbi == dpo->dpoi_index,
5563 "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0);
5566 * add the export prefix back, but not as attached.
5567 * No adj-fibs in export nor import tables
5569 local_pfx.fp_len = 24;
5570 fei = fib_table_entry_update_one_path(fib_index,
5573 FIB_ENTRY_FLAG_NONE,
5575 &pfx_10_10_10_1_s_32.fp_addr,
5576 tm->hw[0]->sw_if_index,
5577 ~0, // invalid fib index
5580 FIB_ROUTE_PATH_FLAG_NONE);
5581 dpo = fib_entry_contribute_ip_forwarding(fei);
5583 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5584 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export");
5585 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5586 FIB_TEST(lbi == dpo->dpoi_index,
5587 "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0);
5588 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5589 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5590 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5591 FIB_TEST(lbi == dpo->dpoi_index,
5592 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5594 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5595 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5596 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5597 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5598 local_pfx.fp_len = 32;
5599 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5600 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5603 * modify the export prefix so it is attached. expect all covereds to return
5605 local_pfx.fp_len = 24;
5606 fib_table_entry_update_one_path(fib_index,
5609 FIB_ENTRY_FLAG_NONE,
5612 tm->hw[0]->sw_if_index,
5613 ~0, // invalid fib index
5616 FIB_ROUTE_PATH_FLAG_NONE);
5618 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5619 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5620 dpo = fib_entry_contribute_ip_forwarding(fei);
5621 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5622 "Adj-fib1 is not drop in export");
5623 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5624 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5625 local_pfx.fp_len = 32;
5626 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5627 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5628 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5629 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5630 dpo = fib_entry_contribute_ip_forwarding(fei);
5631 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5632 "Adj-fib1 is not drop in export");
5633 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5634 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5635 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5636 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5637 local_pfx.fp_len = 32;
5638 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5639 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5642 * modify the export prefix so connected. no change.
5644 local_pfx.fp_len = 24;
5645 fib_table_entry_update_one_path(fib_index, &local_pfx,
5646 FIB_SOURCE_INTERFACE,
5647 (FIB_ENTRY_FLAG_CONNECTED |
5648 FIB_ENTRY_FLAG_ATTACHED),
5651 tm->hw[0]->sw_if_index,
5655 FIB_ROUTE_PATH_FLAG_NONE);
5657 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5658 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5659 dpo = fib_entry_contribute_ip_forwarding(fei);
5660 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5661 "Adj-fib1 is not drop in export");
5662 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5663 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5664 local_pfx.fp_len = 32;
5665 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5666 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5667 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5668 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5669 dpo = fib_entry_contribute_ip_forwarding(fei);
5670 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5671 "Adj-fib1 is not drop in export");
5672 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5673 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5674 local_pfx.fp_len = 32;
5675 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5676 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5681 fib_table_entry_delete(fib_index,
5684 fib_table_entry_delete(fib_index,
5685 &pfx_10_10_10_1_s_32,
5687 fib_table_entry_delete(fib_index,
5688 &pfx_10_10_10_2_s_32,
5690 local_pfx.fp_len = 32;
5691 fib_table_entry_delete(fib_index,
5693 FIB_SOURCE_INTERFACE);
5694 local_pfx.fp_len = 24;
5695 fib_table_entry_delete(fib_index,
5698 fib_table_entry_delete(fib_index,
5700 FIB_SOURCE_INTERFACE);
5701 local_pfx.fp_len = 24;
5702 fib_table_entry_delete(import_fib_index1,
5706 fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
5707 fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
5709 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5716 * Test Path Preference
5719 fib_test_pref (void)
5721 test_main_t *tm = &test_main;
5723 const fib_prefix_t pfx_1_1_1_1_s_32 = {
5725 .fp_proto = FIB_PROTOCOL_IP4,
5728 .as_u32 = clib_host_to_net_u32(0x01010101),
5734 * 2 high, 2 medium and 2 low preference non-recursive paths
5736 fib_route_path_t nr_path_hi_1 = {
5737 .frp_proto = DPO_PROTO_IP4,
5738 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5739 .frp_fib_index = ~0,
5741 .frp_preference = 0,
5742 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5744 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5747 fib_route_path_t nr_path_hi_2 = {
5748 .frp_proto = DPO_PROTO_IP4,
5749 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5750 .frp_fib_index = ~0,
5752 .frp_preference = 0,
5753 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5755 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5758 fib_route_path_t nr_path_med_1 = {
5759 .frp_proto = DPO_PROTO_IP4,
5760 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5761 .frp_fib_index = ~0,
5763 .frp_preference = 1,
5764 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5766 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5769 fib_route_path_t nr_path_med_2 = {
5770 .frp_proto = DPO_PROTO_IP4,
5771 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5772 .frp_fib_index = ~0,
5774 .frp_preference = 1,
5775 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5777 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5780 fib_route_path_t nr_path_low_1 = {
5781 .frp_proto = DPO_PROTO_IP4,
5782 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5783 .frp_fib_index = ~0,
5785 .frp_preference = 2,
5786 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5788 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b01),
5791 fib_route_path_t nr_path_low_2 = {
5792 .frp_proto = DPO_PROTO_IP4,
5793 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5794 .frp_fib_index = ~0,
5796 .frp_preference = 2,
5797 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5799 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b02),
5802 fib_route_path_t *nr_paths = NULL;
5804 vec_add1(nr_paths, nr_path_hi_1);
5805 vec_add1(nr_paths, nr_path_hi_2);
5806 vec_add1(nr_paths, nr_path_med_1);
5807 vec_add1(nr_paths, nr_path_med_2);
5808 vec_add1(nr_paths, nr_path_low_1);
5809 vec_add1(nr_paths, nr_path_low_2);
5811 adj_index_t ai_hi_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5813 &nr_path_hi_1.frp_addr,
5814 nr_path_hi_1.frp_sw_if_index);
5815 adj_index_t ai_hi_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5817 &nr_path_hi_2.frp_addr,
5818 nr_path_hi_2.frp_sw_if_index);
5819 adj_index_t ai_med_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5821 &nr_path_med_1.frp_addr,
5822 nr_path_med_1.frp_sw_if_index);
5823 adj_index_t ai_med_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5825 &nr_path_med_2.frp_addr,
5826 nr_path_med_2.frp_sw_if_index);
5827 adj_index_t ai_low_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5829 &nr_path_low_1.frp_addr,
5830 nr_path_low_1.frp_sw_if_index);
5831 adj_index_t ai_low_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5833 &nr_path_low_2.frp_addr,
5834 nr_path_low_2.frp_sw_if_index);
5836 fib_test_lb_bucket_t ip_hi_1 = {
5842 fib_test_lb_bucket_t ip_hi_2 = {
5848 fib_test_lb_bucket_t ip_med_1 = {
5854 fib_test_lb_bucket_t ip_med_2 = {
5860 fib_test_lb_bucket_t ip_low_1 = {
5866 fib_test_lb_bucket_t ip_low_2 = {
5873 fib_node_index_t fei;
5875 fei = fib_table_entry_path_add2(0,
5878 FIB_ENTRY_FLAG_NONE,
5881 FIB_TEST(fib_test_validate_entry(fei,
5882 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5886 "1.1.1.1/32 via high preference paths");
5889 * bring down the interface on which the high preference path lie
5891 vnet_sw_interface_set_flags(vnet_get_main(),
5892 tm->hw[0]->sw_if_index,
5895 FIB_TEST(fib_test_validate_entry(fei,
5896 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5900 "1.1.1.1/32 via medium preference paths");
5903 * bring down the interface on which the medium preference path lie
5905 vnet_sw_interface_set_flags(vnet_get_main(),
5906 tm->hw[1]->sw_if_index,
5909 FIB_TEST(fib_test_validate_entry(fei,
5910 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5914 "1.1.1.1/32 via low preference paths");
5917 * bring up the interface on which the high preference path lie
5919 vnet_sw_interface_set_flags(vnet_get_main(),
5920 tm->hw[0]->sw_if_index,
5921 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5923 FIB_TEST(fib_test_validate_entry(fei,
5924 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5928 "1.1.1.1/32 via high preference paths");
5931 * bring up the interface on which the medium preference path lie
5933 vnet_sw_interface_set_flags(vnet_get_main(),
5934 tm->hw[1]->sw_if_index,
5935 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5937 FIB_TEST(fib_test_validate_entry(fei,
5938 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5942 "1.1.1.1/32 via high preference paths");
5944 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
5945 fib_entry_contribute_forwarding(fei,
5946 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5950 * 3 recursive paths of different preference
5952 const fib_prefix_t pfx_1_1_1_2_s_32 = {
5954 .fp_proto = FIB_PROTOCOL_IP4,
5957 .as_u32 = clib_host_to_net_u32(0x01010102),
5961 const fib_prefix_t pfx_1_1_1_3_s_32 = {
5963 .fp_proto = FIB_PROTOCOL_IP4,
5966 .as_u32 = clib_host_to_net_u32(0x01010103),
5970 fei = fib_table_entry_path_add2(0,
5973 FIB_ENTRY_FLAG_NONE,
5975 dpo_id_t ip_1_1_1_2 = DPO_INVALID;
5976 fib_entry_contribute_forwarding(fei,
5977 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5979 fei = fib_table_entry_path_add2(0,
5982 FIB_ENTRY_FLAG_NONE,
5984 dpo_id_t ip_1_1_1_3 = DPO_INVALID;
5985 fib_entry_contribute_forwarding(fei,
5986 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5989 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
5992 .lb = ip_1_1_1_1.dpoi_index,
5995 fib_test_lb_bucket_t ip_o_1_1_1_2 = {
5998 .lb = ip_1_1_1_2.dpoi_index,
6001 fib_test_lb_bucket_t ip_o_1_1_1_3 = {
6004 .lb = ip_1_1_1_3.dpoi_index,
6007 fib_route_path_t r_path_hi = {
6008 .frp_proto = DPO_PROTO_IP4,
6009 .frp_sw_if_index = ~0,
6012 .frp_preference = 0,
6013 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
6014 .frp_addr = pfx_1_1_1_1_s_32.fp_addr,
6016 fib_route_path_t r_path_med = {
6017 .frp_proto = DPO_PROTO_IP4,
6018 .frp_sw_if_index = ~0,
6021 .frp_preference = 10,
6022 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
6023 .frp_addr = pfx_1_1_1_2_s_32.fp_addr,
6025 fib_route_path_t r_path_low = {
6026 .frp_proto = DPO_PROTO_IP4,
6027 .frp_sw_if_index = ~0,
6030 .frp_preference = 255,
6031 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
6032 .frp_addr = pfx_1_1_1_3_s_32.fp_addr,
6034 fib_route_path_t *r_paths = NULL;
6036 vec_add1(r_paths, r_path_hi);
6037 vec_add1(r_paths, r_path_low);
6038 vec_add1(r_paths, r_path_med);
6041 * add many recursive so we get the LB MAp created
6044 fib_prefix_t pfx_r[N_PFXS];
6045 unsigned int n_pfxs;
6046 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6048 pfx_r[n_pfxs].fp_len = 32;
6049 pfx_r[n_pfxs].fp_proto = FIB_PROTOCOL_IP4;
6050 pfx_r[n_pfxs].fp_addr.ip4.as_u32 =
6051 clib_host_to_net_u32(0x02000000 + n_pfxs);
6053 fei = fib_table_entry_path_add2(0,
6056 FIB_ENTRY_FLAG_NONE,
6059 FIB_TEST(fib_test_validate_entry(fei,
6060 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6063 "recursive via high preference paths");
6066 * withdraw hig pref resolving entry
6068 fib_table_entry_delete(0,
6072 /* suspend so the update walk kicks int */
6073 vlib_process_suspend(vlib_get_main(), 1e-5);
6075 FIB_TEST(fib_test_validate_entry(fei,
6076 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6079 "recursive via medium preference paths");
6082 * withdraw medium 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 low preference paths");
6098 * add back paths for next iteration
6100 fei = fib_table_entry_update(0,
6103 FIB_ENTRY_FLAG_NONE,
6105 fei = fib_table_entry_update(0,
6108 FIB_ENTRY_FLAG_NONE,
6111 /* suspend so the update walk kicks int */
6112 vlib_process_suspend(vlib_get_main(), 1e-5);
6114 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6115 FIB_TEST(fib_test_validate_entry(fei,
6116 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6119 "recursive via high preference paths");
6123 fib_table_entry_delete(0,
6127 /* suspend so the update walk kicks int */
6128 vlib_process_suspend(vlib_get_main(), 1e-5);
6130 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6132 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6134 FIB_TEST(fib_test_validate_entry(fei,
6135 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6138 "recursive via medium preference paths");
6140 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6142 fib_table_entry_delete(0,
6150 fib_table_entry_delete(0,
6153 fib_table_entry_delete(0,
6157 dpo_reset(&ip_1_1_1_1);
6158 dpo_reset(&ip_1_1_1_2);
6159 dpo_reset(&ip_1_1_1_3);
6160 adj_unlock(ai_low_2);
6161 adj_unlock(ai_low_1);
6162 adj_unlock(ai_med_2);
6163 adj_unlock(ai_med_1);
6164 adj_unlock(ai_hi_2);
6165 adj_unlock(ai_hi_1);
6170 * Test the recursive route route handling for GRE tunnels
6173 fib_test_label (void)
6175 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;
6176 const u32 fib_index = 0;
6181 lb_count = pool_elts(load_balance_pool);
6186 * add interface routes. We'll assume this works. It's more rigorously
6189 fib_prefix_t local0_pfx = {
6191 .fp_proto = FIB_PROTOCOL_IP4,
6195 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
6200 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6203 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
6204 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
6206 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6207 FIB_SOURCE_INTERFACE,
6208 (FIB_ENTRY_FLAG_CONNECTED |
6209 FIB_ENTRY_FLAG_ATTACHED),
6212 tm->hw[0]->sw_if_index,
6216 FIB_ROUTE_PATH_FLAG_NONE);
6217 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6218 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6219 "attached interface route present");
6221 local0_pfx.fp_len = 32;
6222 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6223 FIB_SOURCE_INTERFACE,
6224 (FIB_ENTRY_FLAG_CONNECTED |
6225 FIB_ENTRY_FLAG_LOCAL),
6228 tm->hw[0]->sw_if_index,
6229 ~0, // invalid fib index
6232 FIB_ROUTE_PATH_FLAG_NONE);
6233 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6235 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6236 "local interface route present");
6238 fib_prefix_t local1_pfx = {
6240 .fp_proto = FIB_PROTOCOL_IP4,
6244 .as_u32 = clib_host_to_net_u32(0x0a0a0b0a),
6249 vec_validate(im->fib_index_by_sw_if_index, tm->hw[1]->sw_if_index);
6250 im->fib_index_by_sw_if_index[tm->hw[1]->sw_if_index] = fib_index;
6252 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6253 FIB_SOURCE_INTERFACE,
6254 (FIB_ENTRY_FLAG_CONNECTED |
6255 FIB_ENTRY_FLAG_ATTACHED),
6258 tm->hw[1]->sw_if_index,
6262 FIB_ROUTE_PATH_FLAG_NONE);
6263 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6264 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6265 "attached interface route present");
6267 local1_pfx.fp_len = 32;
6268 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6269 FIB_SOURCE_INTERFACE,
6270 (FIB_ENTRY_FLAG_CONNECTED |
6271 FIB_ENTRY_FLAG_LOCAL),
6274 tm->hw[1]->sw_if_index,
6275 ~0, // invalid fib index
6278 FIB_ROUTE_PATH_FLAG_NONE);
6279 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6281 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6282 "local interface route present");
6284 ip46_address_t nh_10_10_10_1 = {
6286 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
6289 ip46_address_t nh_10_10_11_1 = {
6291 .as_u32 = clib_host_to_net_u32(0x0a0a0b01),
6294 ip46_address_t nh_10_10_11_2 = {
6296 .as_u32 = clib_host_to_net_u32(0x0a0a0b02),
6300 ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6303 tm->hw[1]->sw_if_index);
6304 ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6307 tm->hw[1]->sw_if_index);
6308 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6311 tm->hw[0]->sw_if_index);
6312 ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6315 tm->hw[1]->sw_if_index);
6316 ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6319 tm->hw[1]->sw_if_index);
6322 * Add an etry with one path with a real out-going label
6324 fib_prefix_t pfx_1_1_1_1_s_32 = {
6326 .fp_proto = FIB_PROTOCOL_IP4,
6328 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
6331 fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = {
6332 .type = FT_LB_LABEL_O_ADJ,
6334 .adj = ai_mpls_10_10_10_1,
6339 fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = {
6340 .type = FT_LB_LABEL_O_ADJ,
6342 .adj = ai_mpls_10_10_10_1,
6344 .eos = MPLS_NON_EOS,
6347 fib_mpls_label_t *l99 = NULL, fml99 = {
6350 vec_add1(l99, fml99);
6352 fib_table_entry_update_one_path(fib_index,
6355 FIB_ENTRY_FLAG_NONE,
6358 tm->hw[0]->sw_if_index,
6359 ~0, // invalid fib index
6362 FIB_ROUTE_PATH_FLAG_NONE);
6364 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6365 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created");
6367 FIB_TEST(fib_test_validate_entry(fei,
6368 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6370 &l99_eos_o_10_10_10_1),
6371 "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1");
6374 * add a path with an implicit NULL label
6376 fib_test_lb_bucket_t a_o_10_10_11_1 = {
6379 .adj = ai_v4_10_10_11_1,
6382 fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = {
6385 .adj = ai_mpls_10_10_11_1,
6388 fib_mpls_label_t *l_imp_null = NULL, fml_imp_null = {
6389 .fml_value = MPLS_IETF_IMPLICIT_NULL_LABEL,
6391 vec_add1(l_imp_null, fml_imp_null);
6393 fei = fib_table_entry_path_add(fib_index,
6396 FIB_ENTRY_FLAG_NONE,
6399 tm->hw[1]->sw_if_index,
6400 ~0, // invalid fib index
6403 FIB_ROUTE_PATH_FLAG_NONE);
6405 FIB_TEST(fib_test_validate_entry(fei,
6406 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6408 &l99_eos_o_10_10_10_1,
6410 "1.1.1.1/32 LB 2 buckets via: "
6411 "label 99 over 10.10.10.1, "
6412 "adj over 10.10.11.1");
6415 * assign the route a local label
6417 fib_table_entry_local_label_add(fib_index,
6421 fib_prefix_t pfx_24001_eos = {
6422 .fp_proto = FIB_PROTOCOL_MPLS,
6426 fib_prefix_t pfx_24001_neos = {
6427 .fp_proto = FIB_PROTOCOL_MPLS,
6429 .fp_eos = MPLS_NON_EOS,
6431 fib_test_lb_bucket_t disp_o_10_10_11_1 = {
6432 .type = FT_LB_MPLS_DISP_PIPE_O_ADJ,
6434 .adj = ai_v4_10_10_11_1,
6439 * The EOS entry should link to both the paths,
6440 * and use an ip adj for the imp-null
6441 * The NON-EOS entry should link to both the paths,
6442 * and use an mpls adj for the imp-null
6444 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6446 FIB_TEST(fib_test_validate_entry(fei,
6447 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6449 &l99_eos_o_10_10_10_1,
6450 &disp_o_10_10_11_1),
6451 "24001/eos LB 2 buckets via: "
6452 "label 99 over 10.10.10.1, "
6453 "mpls disp adj over 10.10.11.1");
6456 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6458 FIB_TEST(fib_test_validate_entry(fei,
6459 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6461 &l99_neos_o_10_10_10_1,
6462 &a_mpls_o_10_10_11_1),
6463 "24001/neos LB 1 bucket via: "
6464 "label 99 over 10.10.10.1 ",
6465 "mpls-adj via 10.10.11.1");
6468 * add an unlabelled path, this is excluded from the neos chains,
6470 fib_test_lb_bucket_t adj_o_10_10_11_2 = {
6473 .adj = ai_v4_10_10_11_2,
6476 fib_test_lb_bucket_t disp_o_10_10_11_2 = {
6477 .type = FT_LB_MPLS_DISP_PIPE_O_ADJ,
6479 .adj = ai_v4_10_10_11_2,
6484 fei = fib_table_entry_path_add(fib_index,
6487 FIB_ENTRY_FLAG_NONE,
6490 tm->hw[1]->sw_if_index,
6491 ~0, // invalid fib index
6494 FIB_ROUTE_PATH_FLAG_NONE);
6496 FIB_TEST(fib_test_validate_entry(fei,
6497 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6498 16, // 3 choices spread over 16 buckets
6499 &l99_eos_o_10_10_10_1,
6500 &l99_eos_o_10_10_10_1,
6501 &l99_eos_o_10_10_10_1,
6502 &l99_eos_o_10_10_10_1,
6503 &l99_eos_o_10_10_10_1,
6504 &l99_eos_o_10_10_10_1,
6515 "1.1.1.1/32 LB 16 buckets via: "
6516 "label 99 over 10.10.10.1, "
6517 "adj over 10.10.11.1",
6518 "adj over 10.10.11.2");
6521 * get and lock a reference to the non-eos of the via entry 1.1.1.1/32
6523 dpo_id_t non_eos_1_1_1_1 = DPO_INVALID;
6524 fib_entry_contribute_forwarding(fei,
6525 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6529 * n-eos has only the 2 labelled paths
6531 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6534 FIB_TEST(fib_test_validate_entry(fei,
6535 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6537 &l99_neos_o_10_10_10_1,
6538 &a_mpls_o_10_10_11_1),
6539 "24001/neos LB 2 buckets via: "
6540 "label 99 over 10.10.10.1, "
6541 "adj-mpls over 10.10.11.2");
6544 * A labelled recursive
6546 fib_prefix_t pfx_2_2_2_2_s_32 = {
6548 .fp_proto = FIB_PROTOCOL_IP4,
6550 .ip4.as_u32 = clib_host_to_net_u32(0x02020202),
6553 fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = {
6554 .type = FT_LB_LABEL_O_LB,
6556 .lb = non_eos_1_1_1_1.dpoi_index,
6559 .mode = FIB_MPLS_LSP_MODE_UNIFORM,
6562 fib_mpls_label_t *l1600 = NULL, fml1600 = {
6564 .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM,
6566 vec_add1(l1600, fml1600);
6568 fei = fib_table_entry_update_one_path(fib_index,
6571 FIB_ENTRY_FLAG_NONE,
6573 &pfx_1_1_1_1_s_32.fp_addr,
6578 FIB_ROUTE_PATH_FLAG_NONE);
6580 FIB_TEST(fib_test_validate_entry(fei,
6581 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6583 &l1600_eos_o_1_1_1_1),
6584 "2.2.2.2.2/32 LB 1 buckets via: "
6585 "label 1600 over 1.1.1.1");
6587 dpo_id_t dpo_44 = DPO_INVALID;
6590 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
6591 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
6593 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
6594 "uRPF check for 2.2.2.2/32 on %d OK",
6595 tm->hw[0]->sw_if_index);
6596 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
6597 "uRPF check for 2.2.2.2/32 on %d OK",
6598 tm->hw[1]->sw_if_index);
6599 FIB_TEST(!fib_urpf_check(urpfi, 99),
6600 "uRPF check for 2.2.2.2/32 on 99 not-OK",
6603 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44);
6604 FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index),
6605 "Shared uRPF on IP and non-EOS chain");
6610 * we are holding a lock on the non-eos LB of the via-entry.
6611 * do a PIC-core failover by shutting the link of the via-entry.
6613 * shut down the link with the valid label
6615 vnet_sw_interface_set_flags(vnet_get_main(),
6616 tm->hw[0]->sw_if_index,
6619 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6620 FIB_TEST(fib_test_validate_entry(fei,
6621 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6625 "1.1.1.1/32 LB 2 buckets via: "
6626 "adj over 10.10.11.1, ",
6627 "adj-v4 over 10.10.11.2");
6629 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6631 FIB_TEST(fib_test_validate_entry(fei,
6632 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6635 &disp_o_10_10_11_2),
6636 "24001/eos LB 2 buckets via: "
6637 "mpls-disp adj over 10.10.11.1, ",
6638 "mpls-disp adj-v4 over 10.10.11.2");
6640 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6642 FIB_TEST(fib_test_validate_entry(fei,
6643 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6645 &a_mpls_o_10_10_11_1),
6646 "24001/neos LB 1 buckets via: "
6647 "adj-mpls over 10.10.11.2");
6650 * test that the pre-failover load-balance has been in-place
6653 dpo_id_t current = DPO_INVALID;
6654 fib_entry_contribute_forwarding(fei,
6655 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6658 FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1,
6660 "PIC-core LB inplace modified %U %U",
6661 format_dpo_id, &non_eos_1_1_1_1, 0,
6662 format_dpo_id, ¤t, 0);
6664 dpo_reset(&non_eos_1_1_1_1);
6665 dpo_reset(¤t);
6668 * no-shut the link with the valid label
6670 vnet_sw_interface_set_flags(vnet_get_main(),
6671 tm->hw[0]->sw_if_index,
6672 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6674 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6675 FIB_TEST(fib_test_validate_entry(fei,
6676 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6677 16, // 3 choices spread over 16 buckets
6678 &l99_eos_o_10_10_10_1,
6679 &l99_eos_o_10_10_10_1,
6680 &l99_eos_o_10_10_10_1,
6681 &l99_eos_o_10_10_10_1,
6682 &l99_eos_o_10_10_10_1,
6683 &l99_eos_o_10_10_10_1,
6694 "1.1.1.1/32 LB 16 buckets via: "
6695 "label 99 over 10.10.10.1, "
6696 "adj over 10.10.11.1",
6697 "adj-v4 over 10.10.11.2");
6700 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6702 FIB_TEST(fib_test_validate_entry(fei,
6703 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6704 16, // 3 choices spread over 16 buckets
6705 &l99_eos_o_10_10_10_1,
6706 &l99_eos_o_10_10_10_1,
6707 &l99_eos_o_10_10_10_1,
6708 &l99_eos_o_10_10_10_1,
6709 &l99_eos_o_10_10_10_1,
6710 &l99_eos_o_10_10_10_1,
6720 &disp_o_10_10_11_2),
6721 "24001/eos LB 16 buckets via: "
6722 "label 99 over 10.10.10.1, "
6723 "MPLS disp adj over 10.10.11.1",
6724 "MPLS disp adj-v4 over 10.10.11.2");
6726 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6728 FIB_TEST(fib_test_validate_entry(fei,
6729 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6731 &l99_neos_o_10_10_10_1,
6732 &a_mpls_o_10_10_11_1),
6733 "24001/neos LB 2 buckets via: "
6734 "label 99 over 10.10.10.1, "
6735 "adj-mpls over 10.10.11.2");
6738 * remove the first path with the valid label
6740 fib_table_entry_path_remove(fib_index,
6745 tm->hw[0]->sw_if_index,
6746 ~0, // invalid fib index
6748 FIB_ROUTE_PATH_FLAG_NONE);
6750 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6751 FIB_TEST(fib_test_validate_entry(fei,
6752 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6756 "1.1.1.1/32 LB 2 buckets via: "
6757 "adj over 10.10.11.1, "
6758 "adj-v4 over 10.10.11.2");
6760 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6762 FIB_TEST(fib_test_validate_entry(fei,
6763 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6766 &disp_o_10_10_11_2),
6767 "24001/eos LB 2 buckets via: "
6768 "MPLS disp adj over 10.10.11.1, "
6769 "MPLS disp adj-v4 over 10.10.11.2");
6771 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6774 FIB_TEST(fib_test_validate_entry(fei,
6775 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6777 &a_mpls_o_10_10_11_1),
6778 "24001/neos LB 1 buckets via: "
6779 "adj-mpls over 10.10.11.2");
6782 * remove the other path with a valid label
6784 fib_test_lb_bucket_t bucket_drop = {
6787 fib_test_lb_bucket_t mpls_bucket_drop = {
6790 .adj = DPO_PROTO_MPLS,
6794 fib_table_entry_path_remove(fib_index,
6799 tm->hw[1]->sw_if_index,
6800 ~0, // invalid fib index
6802 FIB_ROUTE_PATH_FLAG_NONE);
6804 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6805 FIB_TEST(fib_test_validate_entry(fei,
6806 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6809 "1.1.1.1/32 LB 1 buckets via: "
6810 "adj over 10.10.11.2");
6812 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6814 FIB_TEST(fib_test_validate_entry(fei,
6815 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6817 &disp_o_10_10_11_2),
6818 "24001/eos LB 1 buckets via: "
6819 "MPLS disp adj over 10.10.11.2");
6821 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6823 FIB_TEST(fib_test_validate_entry(fei,
6824 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6827 "24001/neos LB 1 buckets via: DROP");
6830 * add back the path with the valid label
6833 vec_add1(l99, fml99);
6835 fib_table_entry_path_add(fib_index,
6838 FIB_ENTRY_FLAG_NONE,
6841 tm->hw[0]->sw_if_index,
6842 ~0, // invalid fib index
6845 FIB_ROUTE_PATH_FLAG_NONE);
6847 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6848 FIB_TEST(fib_test_validate_entry(fei,
6849 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6851 &l99_eos_o_10_10_10_1,
6853 "1.1.1.1/32 LB 2 buckets via: "
6854 "label 99 over 10.10.10.1, "
6855 "adj over 10.10.11.2");
6857 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6859 FIB_TEST(fib_test_validate_entry(fei,
6860 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6862 &l99_eos_o_10_10_10_1,
6863 &disp_o_10_10_11_2),
6864 "24001/eos LB 2 buckets via: "
6865 "label 99 over 10.10.10.1, "
6866 "MPLS disp adj over 10.10.11.2");
6868 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6870 FIB_TEST(fib_test_validate_entry(fei,
6871 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6873 &l99_neos_o_10_10_10_1),
6874 "24001/neos LB 1 buckets via: "
6875 "label 99 over 10.10.10.1");
6878 * change the local label
6880 fib_table_entry_local_label_add(fib_index,
6884 fib_prefix_t pfx_25005_eos = {
6885 .fp_proto = FIB_PROTOCOL_MPLS,
6889 fib_prefix_t pfx_25005_neos = {
6890 .fp_proto = FIB_PROTOCOL_MPLS,
6892 .fp_eos = MPLS_NON_EOS,
6895 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6896 fib_table_lookup(fib_index, &pfx_24001_eos)),
6897 "24001/eos removed after label change");
6898 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6899 fib_table_lookup(fib_index, &pfx_24001_neos)),
6900 "24001/eos removed after label change");
6902 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6904 FIB_TEST(fib_test_validate_entry(fei,
6905 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6907 &l99_eos_o_10_10_10_1,
6908 &disp_o_10_10_11_2),
6909 "25005/eos LB 2 buckets via: "
6910 "label 99 over 10.10.10.1, "
6911 "MPLS disp adj over 10.10.11.2");
6913 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6915 FIB_TEST(fib_test_validate_entry(fei,
6916 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6918 &l99_neos_o_10_10_10_1),
6919 "25005/neos LB 1 buckets via: "
6920 "label 99 over 10.10.10.1");
6923 * remove the local label.
6924 * the check that the MPLS entries are gone is done by the fact the
6925 * MPLS table is no longer present.
6927 fib_table_entry_local_label_remove(fib_index,
6931 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6932 FIB_TEST(fib_test_validate_entry(fei,
6933 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6935 &l99_eos_o_10_10_10_1,
6937 "24001/eos LB 2 buckets via: "
6938 "label 99 over 10.10.10.1, "
6939 "adj over 10.10.11.2");
6941 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6942 mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)),
6943 "No more MPLS FIB entries => table removed");
6946 * add another via-entry for the recursive
6948 fib_prefix_t pfx_1_1_1_2_s_32 = {
6950 .fp_proto = FIB_PROTOCOL_IP4,
6952 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
6955 fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = {
6956 .type = FT_LB_LABEL_O_ADJ,
6958 .adj = ai_mpls_10_10_10_1,
6963 fib_mpls_label_t *l101 = NULL, fml101 = {
6966 vec_add1(l101, fml101);
6968 fei = fib_table_entry_update_one_path(fib_index,
6971 FIB_ENTRY_FLAG_NONE,
6974 tm->hw[0]->sw_if_index,
6975 ~0, // invalid fib index
6978 FIB_ROUTE_PATH_FLAG_NONE);
6980 FIB_TEST(fib_test_validate_entry(fei,
6981 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6983 &l101_eos_o_10_10_10_1),
6984 "1.1.1.2/32 LB 1 buckets via: "
6985 "label 101 over 10.10.10.1");
6987 dpo_id_t non_eos_1_1_1_2 = DPO_INVALID;
6988 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6990 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6992 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6994 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6997 fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = {
6998 .type = FT_LB_LABEL_O_LB,
7000 .lb = non_eos_1_1_1_2.dpoi_index,
7005 fib_mpls_label_t *l1601 = NULL, fml1601 = {
7008 vec_add1(l1601, fml1601);
7010 l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index;
7012 fei = fib_table_entry_path_add(fib_index,
7015 FIB_ENTRY_FLAG_NONE,
7017 &pfx_1_1_1_2_s_32.fp_addr,
7022 FIB_ROUTE_PATH_FLAG_NONE);
7024 FIB_TEST(fib_test_validate_entry(fei,
7025 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7027 &l1600_eos_o_1_1_1_1,
7028 &l1601_eos_o_1_1_1_2),
7029 "2.2.2.2/32 LB 2 buckets via: "
7030 "label 1600 via 1.1,1.1, "
7031 "label 16001 via 1.1.1.2");
7034 * update the via-entry so it no longer has an imp-null path.
7035 * the LB for the recursive can use an imp-null
7038 vec_add1(l_imp_null, fml_imp_null);
7040 fei = fib_table_entry_update_one_path(fib_index,
7043 FIB_ENTRY_FLAG_NONE,
7046 tm->hw[1]->sw_if_index,
7047 ~0, // invalid fib index
7050 FIB_ROUTE_PATH_FLAG_NONE);
7052 FIB_TEST(fib_test_validate_entry(fei,
7053 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7056 "1.1.1.2/32 LB 1 buckets via: "
7059 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7060 FIB_TEST(fib_test_validate_entry(fei,
7061 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7063 &l1600_eos_o_1_1_1_1,
7064 &l1601_eos_o_1_1_1_2),
7065 "2.2.2.2/32 LB 2 buckets via: "
7066 "label 1600 via 1.1,1.1, "
7067 "label 16001 via 1.1.1.2");
7070 * update the via-entry so it no longer has labelled paths.
7071 * the LB for the recursive should exclue this via form its LB
7073 fei = fib_table_entry_update_one_path(fib_index,
7076 FIB_ENTRY_FLAG_NONE,
7079 tm->hw[1]->sw_if_index,
7080 ~0, // invalid fib index
7083 FIB_ROUTE_PATH_FLAG_NONE);
7085 FIB_TEST(fib_test_validate_entry(fei,
7086 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7089 "1.1.1.2/32 LB 1 buckets via: "
7092 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7093 FIB_TEST(fib_test_validate_entry(fei,
7094 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7096 &l1600_eos_o_1_1_1_1),
7097 "2.2.2.2/32 LB 1 buckets via: "
7098 "label 1600 via 1.1,1.1");
7100 dpo_reset(&non_eos_1_1_1_1);
7101 dpo_reset(&non_eos_1_1_1_2);
7104 * Add a recursive with no out-labels. We expect to use the IP of the via
7106 fib_prefix_t pfx_2_2_2_3_s_32 = {
7108 .fp_proto = FIB_PROTOCOL_IP4,
7110 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
7113 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
7115 fib_table_entry_update_one_path(fib_index,
7118 FIB_ENTRY_FLAG_NONE,
7120 &pfx_1_1_1_1_s_32.fp_addr,
7125 FIB_ROUTE_PATH_FLAG_NONE);
7127 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7129 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7132 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
7135 .lb = ip_1_1_1_1.dpoi_index,
7139 fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
7140 FIB_TEST(fib_test_validate_entry(fei,
7141 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7144 "2.2.2.2.3/32 LB 1 buckets via: "
7148 * Add a recursive with an imp-null out-label.
7149 * We expect to use the IP of the via
7151 fib_prefix_t pfx_2_2_2_4_s_32 = {
7153 .fp_proto = FIB_PROTOCOL_IP4,
7155 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
7159 fib_table_entry_update_one_path(fib_index,
7162 FIB_ENTRY_FLAG_NONE,
7164 &pfx_1_1_1_1_s_32.fp_addr,
7169 FIB_ROUTE_PATH_FLAG_NONE);
7171 fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
7172 FIB_TEST(fib_test_validate_entry(fei,
7173 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7176 "2.2.2.2.4/32 LB 1 buckets via: "
7179 dpo_reset(&ip_1_1_1_1);
7182 * Create an entry with a deep label stack
7184 fib_prefix_t pfx_2_2_5_5_s_32 = {
7186 .fp_proto = FIB_PROTOCOL_IP4,
7188 .ip4.as_u32 = clib_host_to_net_u32(0x02020505),
7191 fib_test_lb_bucket_t ls_eos_o_10_10_10_1 = {
7192 .type = FT_LB_LABEL_STACK_O_ADJ,
7193 .label_stack_o_adj = {
7194 .adj = ai_mpls_10_10_11_1,
7195 .label_stack_size = 8,
7197 200, 201, 202, 203, 204, 205, 206, 207
7202 fib_mpls_label_t *label_stack = NULL;
7203 vec_validate(label_stack, 7);
7204 for (ii = 0; ii < 8; ii++)
7206 label_stack[ii].fml_value = ii + 200;
7209 fei = fib_table_entry_update_one_path(fib_index,
7212 FIB_ENTRY_FLAG_NONE,
7215 tm->hw[1]->sw_if_index,
7216 ~0, // invalid fib index
7219 FIB_ROUTE_PATH_FLAG_NONE);
7221 FIB_TEST(fib_test_validate_entry(fei,
7222 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7224 &ls_eos_o_10_10_10_1),
7225 "2.2.5.5/32 LB 1 buckets via: "
7227 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
7232 fib_table_entry_delete(fib_index,
7236 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7237 FIB_TEST(fib_test_validate_entry(fei,
7238 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7240 &l1600_eos_o_1_1_1_1),
7241 "2.2.2.2/32 LB 1 buckets via: "
7242 "label 1600 via 1.1,1.1");
7244 fib_table_entry_delete(fib_index,
7248 FIB_TEST(fib_test_validate_entry(fei,
7249 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7252 "2.2.2.2/32 LB 1 buckets via: DROP");
7254 fib_table_entry_delete(fib_index,
7257 fib_table_entry_delete(fib_index,
7260 fib_table_entry_delete(fib_index,
7264 adj_unlock(ai_mpls_10_10_10_1);
7265 adj_unlock(ai_mpls_10_10_11_2);
7266 adj_unlock(ai_v4_10_10_11_1);
7267 adj_unlock(ai_v4_10_10_11_2);
7268 adj_unlock(ai_mpls_10_10_11_1);
7270 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
7273 local0_pfx.fp_len = 32;
7274 fib_table_entry_delete(fib_index,
7276 FIB_SOURCE_INTERFACE);
7277 local0_pfx.fp_len = 24;
7278 fib_table_entry_delete(fib_index,
7280 FIB_SOURCE_INTERFACE);
7281 local1_pfx.fp_len = 32;
7282 fib_table_entry_delete(fib_index,
7284 FIB_SOURCE_INTERFACE);
7285 local1_pfx.fp_len = 24;
7286 fib_table_entry_delete(fib_index,
7288 FIB_SOURCE_INTERFACE);
7291 * +1 for the drop LB in the MPLS tables.
7293 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
7294 "Load-balance resources freed %d of %d",
7295 lb_count+1, pool_elts(load_balance_pool));
7300 #define N_TEST_CHILDREN 4
7301 #define PARENT_INDEX 0
7303 typedef struct fib_node_test_t_
7308 fib_node_back_walk_ctx_t *ctxs;
7312 static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1];
7314 #define PARENT() (&fib_test_nodes[PARENT_INDEX].node)
7316 #define FOR_EACH_TEST_CHILD(_tc) \
7317 for (ii = 1, (_tc) = &fib_test_nodes[1]; \
7318 ii < N_TEST_CHILDREN+1; \
7319 ii++, (_tc) = &fib_test_nodes[ii])
7322 fib_test_child_get_node (fib_node_index_t index)
7324 return (&fib_test_nodes[index].node);
7327 static int fib_test_walk_spawns_walks;
7329 static fib_node_back_walk_rc_t
7330 fib_test_child_back_walk_notify (fib_node_t *node,
7331 fib_node_back_walk_ctx_t *ctx)
7333 fib_node_test_t *tc = (fib_node_test_t*) node;
7335 vec_add1(tc->ctxs, *ctx);
7337 if (1 == fib_test_walk_spawns_walks)
7338 fib_walk_sync(FIB_NODE_TYPE_TEST, tc->index, ctx);
7339 if (2 == fib_test_walk_spawns_walks)
7340 fib_walk_async(FIB_NODE_TYPE_TEST, tc->index,
7341 FIB_WALK_PRIORITY_HIGH, ctx);
7343 return (FIB_NODE_BACK_WALK_CONTINUE);
7347 fib_test_child_last_lock_gone (fib_node_t *node)
7349 fib_node_test_t *tc = (fib_node_test_t *)node;
7355 * The FIB walk's graph node virtual function table
7357 static const fib_node_vft_t fib_test_child_vft = {
7358 .fnv_get = fib_test_child_get_node,
7359 .fnv_last_lock = fib_test_child_last_lock_gone,
7360 .fnv_back_walk = fib_test_child_back_walk_notify,
7364 * the function (that should have been static but isn't so I can do this)
7365 * that processes the walk from the async queue,
7367 f64 fib_walk_process_queues(vlib_main_t * vm,
7369 u32 fib_walk_queue_get_size(fib_walk_priority_t prio);
7372 fib_test_walk (void)
7374 fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {};
7375 fib_node_test_t *tc;
7379 vm = vlib_get_main();
7380 fib_node_register_type(FIB_NODE_TYPE_TEST, &fib_test_child_vft);
7383 * init a fake node on which we will add children
7385 fib_node_init(&fib_test_nodes[PARENT_INDEX].node,
7386 FIB_NODE_TYPE_TEST);
7388 FOR_EACH_TEST_CHILD(tc)
7390 fib_node_init(&tc->node, FIB_NODE_TYPE_TEST);
7391 fib_node_lock(&tc->node);
7394 tc->sibling = fib_node_child_add(FIB_NODE_TYPE_TEST,
7396 FIB_NODE_TYPE_TEST, ii);
7400 * enqueue a walk across the parents children.
7402 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7404 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7405 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7406 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7407 "Parent has %d children pre-walk",
7408 fib_node_list_get_size(PARENT()->fn_children));
7411 * give the walk a large amount of time so it gets to the end
7413 fib_walk_process_queues(vm, 1);
7415 FOR_EACH_TEST_CHILD(tc)
7417 FIB_TEST(1 == vec_len(tc->ctxs),
7418 "%d child visitsed %d times",
7419 ii, vec_len(tc->ctxs));
7422 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7423 "Queue is empty post walk");
7424 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7425 "Parent has %d children post walk",
7426 fib_node_list_get_size(PARENT()->fn_children));
7429 * walk again. should be no increase in the number of visits, since
7430 * the walk will have terminated.
7432 fib_walk_process_queues(vm, 1);
7434 FOR_EACH_TEST_CHILD(tc)
7436 FIB_TEST(0 == vec_len(tc->ctxs),
7437 "%d child visitsed %d times",
7438 ii, vec_len(tc->ctxs));
7442 * schedule a low and hig priority walk. expect the high to be performed
7444 * schedule the high prio walk first so that it is further from the head
7445 * of the dependency list. that way it won't merge with the low one.
7447 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7448 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7450 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7451 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7452 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7453 FIB_WALK_PRIORITY_LOW, &low_ctx);
7455 fib_walk_process_queues(vm, 1);
7457 FOR_EACH_TEST_CHILD(tc)
7459 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7460 "%d child visitsed by high prio walk", ii);
7461 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7462 "%d child visitsed by low prio walk", ii);
7465 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7466 "Queue is empty post prio walk");
7467 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7468 "Parent has %d children post prio walk",
7469 fib_node_list_get_size(PARENT()->fn_children));
7472 * schedule 2 walks of the same priority that can be megred.
7473 * expect that each child is thus visited only once.
7475 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7476 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7478 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7479 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7480 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7481 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7483 fib_walk_process_queues(vm, 1);
7485 FOR_EACH_TEST_CHILD(tc)
7487 FIB_TEST(1 == vec_len(tc->ctxs),
7488 "%d child visitsed %d times during merge walk",
7489 ii, vec_len(tc->ctxs));
7492 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7493 "Queue is empty post merge walk");
7494 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7495 "Parent has %d children post merge walk",
7496 fib_node_list_get_size(PARENT()->fn_children));
7499 * schedule 2 walks of the same priority that cannot be megred.
7500 * expect that each child is thus visited twice and in the order
7501 * in which the walks were scheduled.
7503 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7504 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7506 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7507 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7508 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7509 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7511 fib_walk_process_queues(vm, 1);
7513 FOR_EACH_TEST_CHILD(tc)
7515 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7516 "%d child visitsed by high prio walk", ii);
7517 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7518 "%d child visitsed by low prio walk", ii);
7521 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7522 "Queue is empty post no-merge walk");
7523 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7524 "Parent has %d children post no-merge walk",
7525 fib_node_list_get_size(PARENT()->fn_children));
7528 * schedule a walk that makes one one child progress.
7529 * we do this by giving the queue draining process zero
7530 * time quanta. it's a do..while loop, so it does something.
7532 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7534 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7535 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7536 fib_walk_process_queues(vm, 0);
7538 FOR_EACH_TEST_CHILD(tc)
7540 if (ii == N_TEST_CHILDREN)
7542 FIB_TEST(1 == vec_len(tc->ctxs),
7543 "%d child visitsed %d times in zero quanta walk",
7544 ii, vec_len(tc->ctxs));
7548 FIB_TEST(0 == vec_len(tc->ctxs),
7549 "%d child visitsed %d times in 0 quanta walk",
7550 ii, vec_len(tc->ctxs));
7553 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7554 "Queue is not empty post zero quanta walk");
7555 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7556 "Parent has %d children post zero qunta walk",
7557 fib_node_list_get_size(PARENT()->fn_children));
7562 fib_walk_process_queues(vm, 0);
7564 FOR_EACH_TEST_CHILD(tc)
7566 if (ii >= N_TEST_CHILDREN-1)
7568 FIB_TEST(1 == vec_len(tc->ctxs),
7569 "%d child visitsed %d times in 2nd zero quanta walk",
7570 ii, vec_len(tc->ctxs));
7574 FIB_TEST(0 == vec_len(tc->ctxs),
7575 "%d child visitsed %d times in 2nd 0 quanta walk",
7576 ii, vec_len(tc->ctxs));
7579 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7580 "Queue is not empty post zero quanta walk");
7581 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7582 "Parent has %d children post zero qunta walk",
7583 fib_node_list_get_size(PARENT()->fn_children));
7586 * schedule another walk that will catch-up and merge.
7588 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7589 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7590 fib_walk_process_queues(vm, 1);
7592 FOR_EACH_TEST_CHILD(tc)
7594 if (ii >= N_TEST_CHILDREN-1)
7596 FIB_TEST(2 == vec_len(tc->ctxs),
7597 "%d child visitsed %d times in 2nd zero quanta merge walk",
7598 ii, vec_len(tc->ctxs));
7603 FIB_TEST(1 == vec_len(tc->ctxs),
7604 "%d child visitsed %d times in 2nd 0 quanta merge walk",
7605 ii, vec_len(tc->ctxs));
7609 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7610 "Queue is not empty post 2nd zero quanta merge walk");
7611 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7612 "Parent has %d children post 2nd zero qunta merge walk",
7613 fib_node_list_get_size(PARENT()->fn_children));
7616 * park a async walk in the middle of the list, then have an sync walk catch
7617 * it. same expectations as async catches async.
7619 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7621 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7622 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7624 fib_walk_process_queues(vm, 0);
7625 fib_walk_process_queues(vm, 0);
7627 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7629 FOR_EACH_TEST_CHILD(tc)
7631 if (ii >= N_TEST_CHILDREN-1)
7633 FIB_TEST(2 == vec_len(tc->ctxs),
7634 "%d child visitsed %d times in sync catches async walk",
7635 ii, vec_len(tc->ctxs));
7640 FIB_TEST(1 == vec_len(tc->ctxs),
7641 "%d child visitsed %d times in sync catches async walk",
7642 ii, vec_len(tc->ctxs));
7646 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7647 "Queue is not empty post 2nd zero quanta merge walk");
7648 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7649 "Parent has %d children post 2nd zero qunta merge walk",
7650 fib_node_list_get_size(PARENT()->fn_children));
7653 * make the parent a child of one of its children, thus inducing a routing loop.
7655 fib_test_nodes[PARENT_INDEX].sibling =
7656 fib_node_child_add(FIB_NODE_TYPE_TEST,
7657 1, // the first child
7662 * execute a sync walk from the parent. each child visited spawns more sync
7663 * walks. we expect the walk to terminate.
7665 fib_test_walk_spawns_walks = 1;
7667 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7669 FOR_EACH_TEST_CHILD(tc)
7672 * child 1 - which is last in the list - has the loop.
7673 * the other children a re thus visitsed first. the we meet
7674 * child 1. we go round the loop again, visting the other children.
7675 * then we meet the walk in the dep list and bail. child 1 is not visitsed
7680 FIB_TEST(1 == vec_len(tc->ctxs),
7681 "child %d visitsed %d times during looped sync walk",
7682 ii, vec_len(tc->ctxs));
7686 FIB_TEST(2 == vec_len(tc->ctxs),
7687 "child %d visitsed %d times during looped sync walk",
7688 ii, vec_len(tc->ctxs));
7692 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7693 "Parent has %d children post sync loop walk",
7694 fib_node_list_get_size(PARENT()->fn_children));
7697 * the walk doesn't reach the max depth because the infra knows that sync
7698 * meets sync implies a loop and bails early.
7700 FIB_TEST(high_ctx.fnbw_depth == 9,
7701 "Walk context depth %d post sync loop walk",
7702 high_ctx.fnbw_depth);
7705 * execute an async walk of the graph loop, with each child spawns sync walks
7707 high_ctx.fnbw_depth = 0;
7708 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7709 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7711 fib_walk_process_queues(vm, 1);
7713 FOR_EACH_TEST_CHILD(tc)
7716 * we don't really care how many times the children are visisted, as long as
7717 * it is more than once.
7719 FIB_TEST(1 <= vec_len(tc->ctxs),
7720 "child %d visitsed %d times during looped aync spawns sync walk",
7721 ii, vec_len(tc->ctxs));
7726 * execute an async walk of the graph loop, with each child spawns async walks
7728 fib_test_walk_spawns_walks = 2;
7729 high_ctx.fnbw_depth = 0;
7730 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7731 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7733 fib_walk_process_queues(vm, 1);
7735 FOR_EACH_TEST_CHILD(tc)
7738 * we don't really care how many times the children are visisted, as long as
7739 * it is more than once.
7741 FIB_TEST(1 <= vec_len(tc->ctxs),
7742 "child %d visitsed %d times during looped async spawns async walk",
7743 ii, vec_len(tc->ctxs));
7748 fib_node_child_remove(FIB_NODE_TYPE_TEST,
7749 1, // the first child
7750 fib_test_nodes[PARENT_INDEX].sibling);
7755 FOR_EACH_TEST_CHILD(tc)
7757 fib_node_child_remove(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7759 fib_node_deinit(&tc->node);
7760 fib_node_unlock(&tc->node);
7762 fib_node_deinit(PARENT());
7765 * The parent will be destroyed when the last lock on it goes.
7766 * this test ensures all the walk objects are unlocking it.
7768 FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed),
7769 "Parent was destroyed");
7775 * declaration of the otherwise static callback functions
7777 void fib_bfd_notify (bfd_listen_event_e event,
7778 const bfd_session_t *session);
7779 void adj_bfd_notify (bfd_listen_event_e event,
7780 const bfd_session_t *session);
7783 * Test BFD session interaction with FIB
7788 fib_node_index_t fei;
7792 /* via 10.10.10.1 */
7793 ip46_address_t nh_10_10_10_1 = {
7794 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
7796 /* via 10.10.10.2 */
7797 ip46_address_t nh_10_10_10_2 = {
7798 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
7800 /* via 10.10.10.10 */
7801 ip46_address_t nh_10_10_10_10 = {
7802 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
7804 n_feis = fib_entry_pool_size();
7809 * add interface routes. we'll assume this works. it's tested elsewhere
7811 fib_prefix_t pfx_10_10_10_10_s_24 = {
7813 .fp_proto = FIB_PROTOCOL_IP4,
7814 .fp_addr = nh_10_10_10_10,
7817 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_24,
7818 FIB_SOURCE_INTERFACE,
7819 (FIB_ENTRY_FLAG_CONNECTED |
7820 FIB_ENTRY_FLAG_ATTACHED),
7823 tm->hw[0]->sw_if_index,
7824 ~0, // invalid fib index
7827 FIB_ROUTE_PATH_FLAG_NONE);
7829 fib_prefix_t pfx_10_10_10_10_s_32 = {
7831 .fp_proto = FIB_PROTOCOL_IP4,
7832 .fp_addr = nh_10_10_10_10,
7834 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_32,
7835 FIB_SOURCE_INTERFACE,
7836 (FIB_ENTRY_FLAG_CONNECTED |
7837 FIB_ENTRY_FLAG_LOCAL),
7840 tm->hw[0]->sw_if_index,
7841 ~0, // invalid fib index
7844 FIB_ROUTE_PATH_FLAG_NONE);
7847 * A BFD session via a neighbour we do not yet know
7849 bfd_session_t bfd_10_10_10_1 = {
7853 .peer_addr = nh_10_10_10_1,
7856 .hop_type = BFD_HOP_TYPE_MULTI,
7857 .local_state = BFD_STATE_init,
7860 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7863 * A new entry will be created that forwards via the adj
7865 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
7868 tm->hw[0]->sw_if_index);
7869 fib_prefix_t pfx_10_10_10_1_s_32 = {
7870 .fp_addr = nh_10_10_10_1,
7872 .fp_proto = FIB_PROTOCOL_IP4,
7874 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
7877 .adj = ai_10_10_10_1,
7881 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7882 FIB_TEST(fib_test_validate_entry(fei,
7883 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7886 "BFD sourced %U via %U",
7887 format_fib_prefix, &pfx_10_10_10_1_s_32,
7888 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
7891 * Delete the BFD session. Expect the fib_entry to be removed
7893 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7895 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7896 FIB_TEST(FIB_NODE_INDEX_INVALID == fei,
7897 "BFD sourced %U removed",
7898 format_fib_prefix, &pfx_10_10_10_1_s_32);
7901 * Add the BFD source back
7903 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7906 * source the entry via the ADJ fib
7908 fei = fib_table_entry_path_add(0,
7909 &pfx_10_10_10_1_s_32,
7911 FIB_ENTRY_FLAG_ATTACHED,
7914 tm->hw[0]->sw_if_index,
7915 ~0, // invalid fib index
7918 FIB_ROUTE_PATH_FLAG_NONE);
7921 * Delete the BFD session. Expect the fib_entry to remain
7923 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7925 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7926 FIB_TEST(fib_test_validate_entry(fei,
7927 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7930 "BFD sourced %U remains via %U",
7931 format_fib_prefix, &pfx_10_10_10_1_s_32,
7932 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
7935 * Add the BFD source back
7937 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7940 * Create another ADJ FIB
7942 fib_prefix_t pfx_10_10_10_2_s_32 = {
7943 .fp_addr = nh_10_10_10_2,
7945 .fp_proto = FIB_PROTOCOL_IP4,
7947 fib_table_entry_path_add(0,
7948 &pfx_10_10_10_2_s_32,
7950 FIB_ENTRY_FLAG_ATTACHED,
7953 tm->hw[0]->sw_if_index,
7954 ~0, // invalid fib index
7957 FIB_ROUTE_PATH_FLAG_NONE);
7959 * A BFD session for the new ADJ FIB
7961 bfd_session_t bfd_10_10_10_2 = {
7965 .peer_addr = nh_10_10_10_2,
7968 .hop_type = BFD_HOP_TYPE_MULTI,
7969 .local_state = BFD_STATE_init,
7972 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_2);
7975 * remove the adj-fib source whilst the session is present
7978 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
7979 fib_table_entry_path_add(0,
7980 &pfx_10_10_10_2_s_32,
7982 FIB_ENTRY_FLAG_ATTACHED,
7985 tm->hw[0]->sw_if_index,
7986 ~0, // invalid fib index
7989 FIB_ROUTE_PATH_FLAG_NONE);
7992 * Before adding a recursive via the BFD tracked ADJ-FIBs,
7993 * bring one of the sessions UP, leave the other down
7995 bfd_10_10_10_1.local_state = BFD_STATE_up;
7996 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
7997 bfd_10_10_10_2.local_state = BFD_STATE_down;
7998 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8001 * A recursive prefix via both of the ADJ FIBs
8003 fib_prefix_t pfx_200_0_0_0_s_24 = {
8004 .fp_proto = FIB_PROTOCOL_IP4,
8007 .ip4.as_u32 = clib_host_to_net_u32(0xc8000000),
8010 const dpo_id_t *dpo_10_10_10_1, *dpo_10_10_10_2;
8013 fib_entry_contribute_ip_forwarding(
8014 fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32));
8016 fib_entry_contribute_ip_forwarding(
8017 fib_table_lookup_exact_match(0, &pfx_10_10_10_2_s_32));
8019 fib_test_lb_bucket_t lb_o_10_10_10_1 = {
8022 .lb = dpo_10_10_10_1->dpoi_index,
8025 fib_test_lb_bucket_t lb_o_10_10_10_2 = {
8028 .lb = dpo_10_10_10_2->dpoi_index,
8033 * A prefix via the adj-fib that is BFD down => DROP
8035 fei = fib_table_entry_path_add(0,
8036 &pfx_200_0_0_0_s_24,
8038 FIB_ENTRY_FLAG_NONE,
8042 0, // default fib index
8045 FIB_ROUTE_PATH_FLAG_NONE);
8046 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8047 "%U resolves via drop",
8048 format_fib_prefix, &pfx_200_0_0_0_s_24);
8051 * add a path via the UP BFD adj-fib.
8052 * we expect that the DOWN BFD ADJ FIB is not used.
8054 fei = fib_table_entry_path_add(0,
8055 &pfx_200_0_0_0_s_24,
8057 FIB_ENTRY_FLAG_NONE,
8061 0, // default fib index
8064 FIB_ROUTE_PATH_FLAG_NONE);
8066 FIB_TEST(fib_test_validate_entry(fei,
8067 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8070 "Recursive %U only UP BFD adj-fibs",
8071 format_fib_prefix, &pfx_200_0_0_0_s_24);
8074 * Send a BFD state change to UP - both sessions are now up
8075 * the recursive prefix should LB over both
8077 bfd_10_10_10_2.local_state = BFD_STATE_up;
8078 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8081 FIB_TEST(fib_test_validate_entry(fei,
8082 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8086 "Recursive %U via both UP BFD adj-fibs",
8087 format_fib_prefix, &pfx_200_0_0_0_s_24);
8090 * Send a BFD state change to DOWN
8091 * the recursive prefix should exclude the down
8093 bfd_10_10_10_2.local_state = BFD_STATE_down;
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,
8101 "Recursive %U via only UP",
8102 format_fib_prefix, &pfx_200_0_0_0_s_24);
8105 * Delete the BFD session while it is in the DOWN state.
8106 * FIB should consider the entry's state as back up
8108 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_2);
8110 FIB_TEST(fib_test_validate_entry(fei,
8111 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8115 "Recursive %U via both UP BFD adj-fibs post down session delete",
8116 format_fib_prefix, &pfx_200_0_0_0_s_24);
8119 * Delete the BFD other session while it is in the UP state.
8121 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8123 FIB_TEST(fib_test_validate_entry(fei,
8124 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8128 "Recursive %U via both UP BFD adj-fibs post up session delete",
8129 format_fib_prefix, &pfx_200_0_0_0_s_24);
8134 fib_table_entry_delete(0, &pfx_200_0_0_0_s_24, FIB_SOURCE_API);
8135 fib_table_entry_delete(0, &pfx_10_10_10_1_s_32, FIB_SOURCE_ADJ);
8136 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
8138 fib_table_entry_delete(0, &pfx_10_10_10_10_s_32, FIB_SOURCE_INTERFACE);
8139 fib_table_entry_delete(0, &pfx_10_10_10_10_s_24, FIB_SOURCE_INTERFACE);
8141 adj_unlock(ai_10_10_10_1);
8143 * test no-one left behind
8145 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8146 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8149 * Single-hop BFD tests
8151 bfd_10_10_10_1.hop_type = BFD_HOP_TYPE_SINGLE;
8152 bfd_10_10_10_1.udp.key.sw_if_index = tm->hw[0]->sw_if_index;
8154 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8156 ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8159 tm->hw[0]->sw_if_index);
8161 * whilst the BFD session is not signalled, the adj is up
8163 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on uninit session");
8166 * bring the BFD session up
8168 bfd_10_10_10_1.local_state = BFD_STATE_up;
8169 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8170 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on UP session");
8173 * bring the BFD session down
8175 bfd_10_10_10_1.local_state = BFD_STATE_down;
8176 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8177 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on DOWN session");
8181 * add an attached next hop FIB entry via the down adj
8183 fib_prefix_t pfx_5_5_5_5_s_32 = {
8186 .as_u32 = clib_host_to_net_u32(0x05050505),
8190 .fp_proto = FIB_PROTOCOL_IP4,
8193 fei = fib_table_entry_path_add(0,
8196 FIB_ENTRY_FLAG_NONE,
8199 tm->hw[0]->sw_if_index,
8200 ~0, // invalid fib index
8203 FIB_ROUTE_PATH_FLAG_NONE);
8204 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8205 "%U resolves via drop",
8206 format_fib_prefix, &pfx_5_5_5_5_s_32);
8209 * Add a path via an ADJ that is up
8211 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8214 tm->hw[0]->sw_if_index);
8216 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
8219 .adj = ai_10_10_10_2,
8222 adj_o_10_10_10_1.adj.adj = ai_10_10_10_1;
8224 fei = fib_table_entry_path_add(0,
8227 FIB_ENTRY_FLAG_NONE,
8230 tm->hw[0]->sw_if_index,
8231 ~0, // invalid fib index
8234 FIB_ROUTE_PATH_FLAG_NONE);
8236 FIB_TEST(fib_test_validate_entry(fei,
8237 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8240 "BFD sourced %U via %U",
8241 format_fib_prefix, &pfx_5_5_5_5_s_32,
8242 format_ip_adjacency, ai_10_10_10_2, FORMAT_IP_ADJACENCY_NONE);
8245 * Bring up the down session - should now LB
8247 bfd_10_10_10_1.local_state = BFD_STATE_up;
8248 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8249 FIB_TEST(fib_test_validate_entry(fei,
8250 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8254 "BFD sourced %U via noth adjs",
8255 format_fib_prefix, &pfx_5_5_5_5_s_32);
8258 * remove the BFD session state from the adj
8260 adj_bfd_notify(BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8265 fib_table_entry_delete(0, &pfx_5_5_5_5_s_32, FIB_SOURCE_CLI);
8266 adj_unlock(ai_10_10_10_1);
8267 adj_unlock(ai_10_10_10_2);
8270 * test no-one left behind
8272 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8273 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8280 const mpls_label_t deag_label = 50;
8281 dpo_id_t dpo = DPO_INVALID;
8282 const mpls_disp_dpo_t *mdd;
8283 const u32 lfib_index = 0;
8284 const u32 fib_index = 0;
8285 const lookup_dpo_t *lkd;
8286 const dpo_id_t *dpo1;
8287 fib_node_index_t lfe;
8290 adj_index_t ai_mpls_10_10_10_1;
8293 lb_count = pool_elts(load_balance_pool);
8295 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
8299 * MPLS enable an interface so we get the MPLS table created
8301 mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL);
8302 mpls_sw_interface_enable_disable(&mpls_main,
8303 tm->hw[0]->sw_if_index,
8306 ip46_address_t nh_10_10_10_1 = {
8307 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
8309 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8312 tm->hw[0]->sw_if_index);
8315 * Test the specials stack properly.
8317 fib_prefix_t exp_null_v6_pfx = {
8318 .fp_proto = FIB_PROTOCOL_MPLS,
8320 .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8321 .fp_payload_proto = DPO_PROTO_IP6,
8323 lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx);
8324 FIB_TEST((FIB_NODE_INDEX_INVALID != lfe),
8326 format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8327 format_mpls_eos_bit, MPLS_EOS);
8328 fib_entry_contribute_forwarding(lfe,
8329 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8331 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8332 lkd = lookup_dpo_get(dpo1->dpoi_index);
8334 FIB_TEST((fib_index == lkd->lkd_fib_index),
8335 "%U/%U is deag in %d %U",
8336 format_mpls_unicast_label, deag_label,
8337 format_mpls_eos_bit, MPLS_EOS,
8339 format_dpo_id, &dpo, 0);
8340 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8341 "%U/%U is dst deag",
8342 format_mpls_unicast_label, deag_label,
8343 format_mpls_eos_bit, MPLS_EOS);
8344 FIB_TEST((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table),
8345 "%U/%U is lookup in interface's table",
8346 format_mpls_unicast_label, deag_label,
8347 format_mpls_eos_bit, MPLS_EOS);
8348 FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto),
8349 "%U/%U is %U dst deag",
8350 format_mpls_unicast_label, deag_label,
8351 format_mpls_eos_bit, MPLS_EOS,
8352 format_dpo_proto, lkd->lkd_proto);
8355 * A route deag route for EOS
8357 fib_prefix_t pfx = {
8358 .fp_proto = FIB_PROTOCOL_MPLS,
8360 .fp_label = deag_label,
8361 .fp_payload_proto = DPO_PROTO_IP4,
8363 lfe = fib_table_entry_path_add(lfib_index,
8366 FIB_ENTRY_FLAG_NONE,
8373 FIB_ROUTE_PATH_FLAG_NONE);
8375 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8377 format_mpls_unicast_label, deag_label,
8378 format_mpls_eos_bit, MPLS_EOS);
8380 fib_entry_contribute_forwarding(lfe,
8381 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8383 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8384 mdd = mpls_disp_dpo_get(dpo1->dpoi_index);
8386 FIB_TEST((FIB_MPLS_LSP_MODE_PIPE == mdd->mdd_mode),
8387 "%U/%U disp is pipe mode",
8388 format_mpls_unicast_label, deag_label,
8389 format_mpls_eos_bit, MPLS_EOS);
8391 lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index);
8393 FIB_TEST((fib_index == lkd->lkd_fib_index),
8394 "%U/%U is deag in %d %U",
8395 format_mpls_unicast_label, deag_label,
8396 format_mpls_eos_bit, MPLS_EOS,
8398 format_dpo_id, &dpo, 0);
8399 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8400 "%U/%U is dst deag",
8401 format_mpls_unicast_label, deag_label,
8402 format_mpls_eos_bit, MPLS_EOS);
8403 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8404 "%U/%U is %U dst deag",
8405 format_mpls_unicast_label, deag_label,
8406 format_mpls_eos_bit, MPLS_EOS,
8407 format_dpo_proto, lkd->lkd_proto);
8409 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8411 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8413 "%U/%U not present",
8414 format_mpls_unicast_label, deag_label,
8415 format_mpls_eos_bit, MPLS_EOS);
8419 * A route deag route for EOS with LSP mode uniform
8421 fib_mpls_label_t *l_pops = NULL, l_pop = {
8422 .fml_value = MPLS_LABEL_POP,
8423 .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM,
8425 vec_add1(l_pops, l_pop);
8426 lfe = fib_table_entry_path_add(lfib_index,
8429 FIB_ENTRY_FLAG_NONE,
8436 FIB_ROUTE_PATH_FLAG_NONE);
8438 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8440 format_mpls_unicast_label, deag_label,
8441 format_mpls_eos_bit, MPLS_EOS);
8443 fib_entry_contribute_forwarding(lfe,
8444 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8446 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8447 mdd = mpls_disp_dpo_get(dpo1->dpoi_index);
8449 FIB_TEST((FIB_MPLS_LSP_MODE_UNIFORM == mdd->mdd_mode),
8450 "%U/%U disp is uniform mode",
8451 format_mpls_unicast_label, deag_label,
8452 format_mpls_eos_bit, MPLS_EOS);
8454 lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index);
8456 FIB_TEST((fib_index == lkd->lkd_fib_index),
8457 "%U/%U is deag in %d %U",
8458 format_mpls_unicast_label, deag_label,
8459 format_mpls_eos_bit, MPLS_EOS,
8461 format_dpo_id, &dpo, 0);
8462 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8463 "%U/%U is dst deag",
8464 format_mpls_unicast_label, deag_label,
8465 format_mpls_eos_bit, MPLS_EOS);
8466 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8467 "%U/%U is %U dst deag",
8468 format_mpls_unicast_label, deag_label,
8469 format_mpls_eos_bit, MPLS_EOS,
8470 format_dpo_proto, lkd->lkd_proto);
8472 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8474 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8476 "%U/%U not present",
8477 format_mpls_unicast_label, deag_label,
8478 format_mpls_eos_bit, MPLS_EOS);
8482 * A route deag route for non-EOS
8484 pfx.fp_eos = MPLS_NON_EOS;
8485 lfe = fib_table_entry_path_add(lfib_index,
8488 FIB_ENTRY_FLAG_NONE,
8495 FIB_ROUTE_PATH_FLAG_NONE);
8497 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8499 format_mpls_unicast_label, deag_label,
8500 format_mpls_eos_bit, MPLS_NON_EOS);
8502 fib_entry_contribute_forwarding(lfe,
8503 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8505 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8506 lkd = lookup_dpo_get(dpo1->dpoi_index);
8508 FIB_TEST((fib_index == lkd->lkd_fib_index),
8509 "%U/%U is deag in %d %U",
8510 format_mpls_unicast_label, deag_label,
8511 format_mpls_eos_bit, MPLS_NON_EOS,
8513 format_dpo_id, &dpo, 0);
8514 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8515 "%U/%U is dst deag",
8516 format_mpls_unicast_label, deag_label,
8517 format_mpls_eos_bit, MPLS_NON_EOS);
8519 FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto),
8520 "%U/%U is %U dst deag",
8521 format_mpls_unicast_label, deag_label,
8522 format_mpls_eos_bit, MPLS_NON_EOS,
8523 format_dpo_proto, lkd->lkd_proto);
8525 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8527 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8529 "%U/%U not present",
8530 format_mpls_unicast_label, deag_label,
8531 format_mpls_eos_bit, MPLS_EOS);
8538 fib_prefix_t pfx_1200 = {
8540 .fp_proto = FIB_PROTOCOL_MPLS,
8542 .fp_eos = MPLS_NON_EOS,
8544 fib_test_lb_bucket_t neos_o_10_10_10_1 = {
8545 .type = FT_LB_LABEL_STACK_O_ADJ,
8546 .label_stack_o_adj = {
8547 .adj = ai_mpls_10_10_10_1,
8548 .label_stack_size = 4,
8552 .eos = MPLS_NON_EOS,
8555 dpo_id_t neos_1200 = DPO_INVALID;
8556 dpo_id_t ip_1200 = DPO_INVALID;
8557 fib_mpls_label_t *l200 = NULL;
8559 for (ii = 0; ii < 4; ii++)
8561 fib_mpls_label_t fml = {
8562 .fml_value = 200 + (ii * 100),
8564 vec_add1(l200, fml);
8567 lfe = fib_table_entry_update_one_path(fib_index,
8570 FIB_ENTRY_FLAG_NONE,
8573 tm->hw[0]->sw_if_index,
8574 ~0, // invalid fib index
8577 FIB_ROUTE_PATH_FLAG_NONE);
8579 FIB_TEST(fib_test_validate_entry(lfe,
8580 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8582 &neos_o_10_10_10_1),
8583 "1200/0 LB 1 buckets via: "
8587 * A recursive route via the MPLS x-connect
8589 fib_prefix_t pfx_2_2_2_3_s_32 = {
8591 .fp_proto = FIB_PROTOCOL_IP4,
8593 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
8596 fib_route_path_t *rpaths = NULL, rpath = {
8597 .frp_proto = DPO_PROTO_MPLS,
8598 .frp_local_label = 1200,
8599 .frp_eos = MPLS_NON_EOS,
8600 .frp_sw_if_index = ~0, // recurive
8601 .frp_fib_index = 0, // Default MPLS fib
8603 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
8604 .frp_label_stack = NULL,
8606 vec_add1(rpaths, rpath);
8608 fib_table_entry_path_add2(fib_index,
8611 FIB_ENTRY_FLAG_NONE,
8615 * A labelled recursive route via the MPLS x-connect
8617 fib_prefix_t pfx_2_2_2_4_s_32 = {
8619 .fp_proto = FIB_PROTOCOL_IP4,
8621 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
8624 fib_mpls_label_t *l999 = NULL, fml_999 = {
8627 vec_add1(l999, fml_999);
8628 rpaths[0].frp_label_stack = l999,
8630 fib_table_entry_path_add2(fib_index,
8633 FIB_ENTRY_FLAG_NONE,
8636 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8637 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8639 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8640 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8643 fib_test_lb_bucket_t ip_o_1200 = {
8646 .lb = ip_1200.dpoi_index,
8649 fib_test_lb_bucket_t mpls_o_1200 = {
8650 .type = FT_LB_LABEL_O_LB,
8652 .lb = neos_1200.dpoi_index,
8658 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
8659 FIB_TEST(fib_test_validate_entry(lfe,
8660 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8663 "2.2.2.2.3/32 LB 1 buckets via: label 1200 EOS");
8664 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
8665 FIB_TEST(fib_test_validate_entry(lfe,
8666 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8669 "2.2.2.2.4/32 LB 1 buckets via: label 1200 non-EOS");
8671 fib_table_entry_delete(fib_index, &pfx_1200, FIB_SOURCE_API);
8672 fib_table_entry_delete(fib_index, &pfx_2_2_2_3_s_32, FIB_SOURCE_API);
8673 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8675 dpo_reset(&neos_1200);
8676 dpo_reset(&ip_1200);
8679 * A recursive via a label that does not exist
8681 fib_test_lb_bucket_t bucket_drop = {
8684 .adj = DPO_PROTO_IP4,
8687 fib_test_lb_bucket_t mpls_bucket_drop = {
8690 .adj = DPO_PROTO_MPLS,
8694 rpaths[0].frp_label_stack = NULL;
8695 lfe = fib_table_entry_path_add2(fib_index,
8698 FIB_ENTRY_FLAG_NONE,
8701 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8702 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8704 ip_o_1200.lb.lb = ip_1200.dpoi_index;
8706 FIB_TEST(fib_test_validate_entry(lfe,
8707 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8710 "2.2.2.2.4/32 LB 1 buckets via: drop");
8711 lfe = fib_table_lookup(fib_index, &pfx_1200);
8712 FIB_TEST(fib_test_validate_entry(lfe,
8713 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8716 "1200/neos LB 1 buckets via: ip4-DROP");
8717 FIB_TEST(fib_test_validate_entry(lfe,
8718 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8721 "1200/neos LB 1 buckets via: mpls-DROP");
8723 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8725 dpo_reset(&ip_1200);
8728 * An rx-interface route.
8729 * like the tail of an mcast LSP
8731 dpo_id_t idpo = DPO_INVALID;
8733 interface_rx_dpo_add_or_lock(DPO_PROTO_IP4,
8734 tm->hw[0]->sw_if_index,
8737 fib_prefix_t pfx_2500 = {
8739 .fp_proto = FIB_PROTOCOL_MPLS,
8742 .fp_payload_proto = DPO_PROTO_IP4,
8744 fib_test_lb_bucket_t rx_intf_0 = {
8747 .adj = idpo.dpoi_index,
8751 lfe = fib_table_entry_update_one_path(fib_index,
8754 FIB_ENTRY_FLAG_NONE,
8757 tm->hw[0]->sw_if_index,
8758 ~0, // invalid fib index
8761 FIB_ROUTE_PATH_INTF_RX);
8762 FIB_TEST(fib_test_validate_entry(lfe,
8763 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8766 "2500 rx-interface 0");
8767 fib_table_entry_delete(fib_index, &pfx_2500, FIB_SOURCE_API);
8770 * An MPLS mulicast entry
8772 fib_prefix_t pfx_3500 = {
8774 .fp_proto = FIB_PROTOCOL_MPLS,
8777 .fp_payload_proto = DPO_PROTO_IP4,
8779 fib_test_rep_bucket_t mc_0 = {
8780 .type = FT_REP_LABEL_O_ADJ,
8782 .adj = ai_mpls_10_10_10_1,
8787 fib_test_rep_bucket_t mc_intf_0 = {
8788 .type = FT_REP_INTF,
8790 .adj = idpo.dpoi_index,
8793 fib_mpls_label_t *l3300 = NULL, fml_3300 = {
8796 vec_add1(l3300, fml_3300);
8798 lfe = fib_table_entry_update_one_path(lfib_index,
8801 FIB_ENTRY_FLAG_MULTICAST,
8804 tm->hw[0]->sw_if_index,
8805 ~0, // invalid fib index
8808 FIB_ROUTE_PATH_FLAG_NONE);
8809 FIB_TEST(fib_test_validate_entry(lfe,
8810 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8813 "3500 via replicate over 10.10.10.1");
8816 * MPLS Bud-node. Add a replication via an interface-receieve path
8818 lfe = fib_table_entry_path_add(lfib_index,
8821 FIB_ENTRY_FLAG_MULTICAST,
8824 tm->hw[0]->sw_if_index,
8825 ~0, // invalid fib index
8828 FIB_ROUTE_PATH_INTF_RX);
8829 FIB_TEST(fib_test_validate_entry(lfe,
8830 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8834 "3500 via replicate over 10.10.10.1 and interface-rx");
8837 * Add a replication via an interface-free for-us path
8839 fib_test_rep_bucket_t mc_disp = {
8840 .type = FT_REP_DISP_MFIB_LOOKUP,
8842 .adj = idpo.dpoi_index,
8845 lfe = fib_table_entry_path_add(lfib_index,
8848 FIB_ENTRY_FLAG_MULTICAST,
8855 FIB_ROUTE_PATH_RPF_ID);
8856 FIB_TEST(fib_test_validate_entry(lfe,
8857 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8862 "3500 via replicate over 10.10.10.1 and interface-rx");
8866 fib_table_entry_delete(fib_index, &pfx_3500, FIB_SOURCE_API);
8872 mpls_sw_interface_enable_disable(&mpls_main,
8873 tm->hw[0]->sw_if_index,
8875 mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
8877 FIB_TEST(0 == pool_elts(mpls_disp_dpo_pool),
8878 "mpls_disp_dpo resources freed %d of %d",
8879 0, pool_elts(mpls_disp_dpo_pool));
8880 FIB_TEST(lb_count == pool_elts(load_balance_pool),
8881 "Load-balance resources freed %d of %d",
8882 lb_count, pool_elts(load_balance_pool));
8883 FIB_TEST(0 == pool_elts(interface_rx_dpo_pool),
8884 "interface_rx_dpo resources freed %d of %d",
8885 0, pool_elts(interface_rx_dpo_pool));
8891 fib_test_inherit (void)
8893 fib_node_index_t fei;
8897 n_feis = fib_entry_pool_size();
8900 const ip46_address_t nh_10_10_10_1 = {
8901 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
8903 const ip46_address_t nh_10_10_10_2 = {
8904 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
8906 const ip46_address_t nh_10_10_10_16 = {
8907 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a10),
8909 const ip46_address_t nh_10_10_10_20 = {
8910 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a14),
8912 const ip46_address_t nh_10_10_10_21 = {
8913 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a15),
8915 const ip46_address_t nh_10_10_10_22 = {
8916 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a16),
8918 const ip46_address_t nh_10_10_10_255 = {
8919 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0aff),
8921 const ip46_address_t nh_10_10_10_0 = {
8922 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a00),
8924 const ip46_address_t nh_10_10_0_0 = {
8925 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0000),
8929 * prefixes at the base of a sub-tree
8931 const fib_prefix_t pfx_10_10_10_21_s_32 = {
8933 .fp_proto = FIB_PROTOCOL_IP4,
8934 .fp_addr = nh_10_10_10_21,
8936 const fib_prefix_t pfx_10_10_10_22_s_32 = {
8938 .fp_proto = FIB_PROTOCOL_IP4,
8939 .fp_addr = nh_10_10_10_22,
8941 const fib_prefix_t pfx_10_10_10_255_s_32 = {
8943 .fp_proto = FIB_PROTOCOL_IP4,
8944 .fp_addr = nh_10_10_10_255,
8947 fib_table_entry_special_add(0,
8948 &pfx_10_10_10_21_s_32,
8950 FIB_ENTRY_FLAG_DROP);
8951 fib_table_entry_special_add(0,
8952 &pfx_10_10_10_22_s_32,
8954 FIB_ENTRY_FLAG_DROP);
8955 fib_table_entry_special_add(0,
8956 &pfx_10_10_10_255_s_32,
8958 FIB_ENTRY_FLAG_DROP);
8961 * source an entry that pushes its state down the sub-tree
8963 const fib_prefix_t pfx_10_10_10_16_s_28 = {
8965 .fp_proto = FIB_PROTOCOL_IP4,
8966 .fp_addr = nh_10_10_10_16,
8968 fib_table_entry_update_one_path(0,
8969 &pfx_10_10_10_16_s_28,
8971 FIB_ENTRY_FLAG_COVERED_INHERIT,
8974 tm->hw[0]->sw_if_index,
8978 FIB_ROUTE_PATH_FLAG_NONE);
8981 * this covering entry and all those below it should have
8982 * the same forwarding information.
8984 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8987 tm->hw[0]->sw_if_index);
8988 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
8991 .adj = ai_10_10_10_1,
8995 fei = fib_table_lookup(0, &pfx_10_10_10_16_s_28);
8996 FIB_TEST(fib_test_validate_entry(fei,
8997 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9000 "%U via 10.10.10.1",
9001 format_fib_prefix, &pfx_10_10_10_16_s_28);
9002 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9003 FIB_TEST(fib_test_validate_entry(fei,
9004 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9007 "%U via 10.10.10.1",
9008 format_fib_prefix, &pfx_10_10_10_21_s_32);
9009 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9010 FIB_TEST(fib_test_validate_entry(fei,
9011 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9014 "%U via 10.10.10.1",
9015 format_fib_prefix, &pfx_10_10_10_22_s_32);
9016 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9017 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9018 "%U resolves via drop",
9019 format_fib_prefix, &pfx_10_10_10_255_s_32);
9022 * remove the inherting cover - covereds go back to drop
9024 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_API);
9026 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9027 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9028 "%U resolves via drop",
9029 format_fib_prefix, &pfx_10_10_10_21_s_32);
9032 * source an entry that pushes its state down the sub-tree
9034 const fib_prefix_t pfx_10_10_10_0_s_24 = {
9036 .fp_proto = FIB_PROTOCOL_IP4,
9037 .fp_addr = nh_10_10_10_0,
9039 fib_table_entry_update_one_path(0,
9040 &pfx_10_10_10_0_s_24,
9042 FIB_ENTRY_FLAG_COVERED_INHERIT,
9045 tm->hw[0]->sw_if_index,
9049 FIB_ROUTE_PATH_FLAG_NONE);
9052 * whole sub-tree now covered
9054 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9055 FIB_TEST(fib_test_validate_entry(fei,
9056 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9059 "%U via 10.10.10.1",
9060 format_fib_prefix, &pfx_10_10_10_0_s_24);
9061 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9062 FIB_TEST(fib_test_validate_entry(fei,
9063 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9066 "%U via 10.10.10.1",
9067 format_fib_prefix, &pfx_10_10_10_21_s_32);
9068 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9069 FIB_TEST(fib_test_validate_entry(fei,
9070 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9073 "%U via 10.10.10.1",
9074 format_fib_prefix, &pfx_10_10_10_22_s_32);
9075 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9076 FIB_TEST(fib_test_validate_entry(fei,
9077 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9080 "%U via 10.10.10.1",
9081 format_fib_prefix, &pfx_10_10_10_255_s_32);
9084 * insert a more specific into the sub-tree - expect inheritance
9085 * this one is directly covered by the root
9087 fib_table_entry_special_add(0,
9088 &pfx_10_10_10_16_s_28,
9090 FIB_ENTRY_FLAG_DROP);
9091 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
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_16_s_28);
9100 * insert a more specific into the sub-tree - expect inheritance
9101 * this one is indirectly covered by the root
9103 const fib_prefix_t pfx_10_10_10_20_s_30 = {
9105 .fp_proto = FIB_PROTOCOL_IP4,
9106 .fp_addr = nh_10_10_10_20,
9108 fib_table_entry_special_add(0,
9109 &pfx_10_10_10_20_s_30,
9111 FIB_ENTRY_FLAG_DROP);
9112 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_20_s_30);
9113 FIB_TEST(fib_test_validate_entry(fei,
9114 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9117 "%U via 10.10.10.1",
9118 format_fib_prefix, &pfx_10_10_10_20_s_30);
9121 * remove the prefix from the middle of the sub-tree
9122 * the inherited source will be the only one remaining - expect
9123 * it to be withdrawn and hence the prefix is removed.
9125 fib_table_entry_special_remove(0,
9126 &pfx_10_10_10_20_s_30,
9128 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_20_s_30);
9129 FIB_TEST((FIB_NODE_INDEX_INVALID == fei),
9131 format_fib_prefix, &pfx_10_10_10_20_s_30);
9134 * inheriting source is modifed - expect the modification to be present
9135 * throughout the sub-tree
9137 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9140 tm->hw[0]->sw_if_index);
9141 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
9144 .adj = ai_10_10_10_2,
9148 fib_table_entry_update_one_path(0,
9149 &pfx_10_10_10_0_s_24,
9151 FIB_ENTRY_FLAG_COVERED_INHERIT,
9154 tm->hw[0]->sw_if_index,
9158 FIB_ROUTE_PATH_FLAG_NONE);
9159 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9160 FIB_TEST(fib_test_validate_entry(fei,
9161 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9164 "%U via 10.10.10.2",
9165 format_fib_prefix, &pfx_10_10_10_21_s_32);
9166 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9167 FIB_TEST(fib_test_validate_entry(fei,
9168 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9171 "%U via 10.10.10.2",
9172 format_fib_prefix, &pfx_10_10_10_22_s_32);
9173 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9174 FIB_TEST(fib_test_validate_entry(fei,
9175 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9178 "%U via 10.10.10.2",
9179 format_fib_prefix, &pfx_10_10_10_255_s_32);
9180 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9181 FIB_TEST(fib_test_validate_entry(fei,
9182 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9185 "%U via 10.10.10.2",
9186 format_fib_prefix, &pfx_10_10_10_0_s_24);
9189 * add the source that replaces inherited state.
9190 * inheriting source is not the best, so it doesn't push state.
9192 fib_table_entry_update_one_path(0,
9193 &pfx_10_10_10_0_s_24,
9194 FIB_SOURCE_PLUGIN_HI,
9195 FIB_ENTRY_FLAG_NONE,
9198 tm->hw[0]->sw_if_index,
9202 FIB_ROUTE_PATH_FLAG_NONE);
9203 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9204 FIB_TEST(fib_test_validate_entry(fei,
9205 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9208 "%U via 10.10.10.1",
9209 format_fib_prefix, &pfx_10_10_10_0_s_24);
9211 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9212 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9213 "%U resolves via drop",
9214 format_fib_prefix, &pfx_10_10_10_21_s_32);
9215 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9216 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9217 "%U resolves via drop",
9218 format_fib_prefix, &pfx_10_10_10_22_s_32);
9219 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9220 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9221 "%U resolves via drop",
9222 format_fib_prefix, &pfx_10_10_10_255_s_32);
9223 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9224 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9225 "%U resolves via drop",
9226 format_fib_prefix, &pfx_10_10_10_16_s_28);
9229 * withdraw the higher priority source and expect the inherited to return
9230 * throughout the sub-tree
9232 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, FIB_SOURCE_PLUGIN_HI);
9234 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9235 FIB_TEST(fib_test_validate_entry(fei,
9236 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9239 "%U via 10.10.10.2",
9240 format_fib_prefix, &pfx_10_10_10_21_s_32);
9241 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9242 FIB_TEST(fib_test_validate_entry(fei,
9243 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9246 "%U via 10.10.10.2",
9247 format_fib_prefix, &pfx_10_10_10_22_s_32);
9248 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9249 FIB_TEST(fib_test_validate_entry(fei,
9250 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9253 "%U via 10.10.10.2",
9254 format_fib_prefix, &pfx_10_10_10_255_s_32);
9255 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9256 FIB_TEST(fib_test_validate_entry(fei,
9257 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9260 "%U via 10.10.10.2",
9261 format_fib_prefix, &pfx_10_10_10_0_s_24);
9262 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9263 FIB_TEST(fib_test_validate_entry(fei,
9264 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9267 "%U via 10.10.10.2",
9268 format_fib_prefix, &pfx_10_10_10_16_s_28);
9271 * source a covered entry in the sub-tree with the same inherting source
9272 * - expect that it now owns the sub-tree and thus over-rides its cover
9274 fib_table_entry_update_one_path(0,
9275 &pfx_10_10_10_16_s_28,
9277 FIB_ENTRY_FLAG_COVERED_INHERIT,
9280 tm->hw[0]->sw_if_index,
9284 FIB_ROUTE_PATH_FLAG_NONE);
9285 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9286 FIB_TEST(fib_test_validate_entry(fei,
9287 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9290 "%U via 10.10.10.1",
9291 format_fib_prefix, &pfx_10_10_10_16_s_28);
9292 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9293 FIB_TEST(fib_test_validate_entry(fei,
9294 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9297 "%U via 10.10.10.2",
9298 format_fib_prefix, &pfx_10_10_10_22_s_32);
9299 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9300 FIB_TEST(fib_test_validate_entry(fei,
9301 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9304 "%U via 10.10.10.2",
9305 format_fib_prefix, &pfx_10_10_10_21_s_32);
9307 /* these two unaffected by the sub-tree change */
9308 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_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_255_s_32);
9315 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
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_0_s_24);
9324 * removes the more specific, expect the /24 to now re-owns the sub-tree
9326 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_API);
9328 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9329 FIB_TEST(fib_test_validate_entry(fei,
9330 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9333 "%U via 10.10.10.2",
9334 format_fib_prefix, &pfx_10_10_10_16_s_28);
9335 FIB_TEST(fib_test_validate_entry(fei,
9336 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9339 "%U via 10.10.10.2",
9340 format_fib_prefix, &pfx_10_10_10_21_s_32);
9341 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9342 FIB_TEST(fib_test_validate_entry(fei,
9343 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9346 "%U via 10.10.10.2",
9347 format_fib_prefix, &pfx_10_10_10_22_s_32);
9348 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9349 FIB_TEST(fib_test_validate_entry(fei,
9350 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9353 "%U via 10.10.10.2",
9354 format_fib_prefix, &pfx_10_10_10_255_s_32);
9355 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9356 FIB_TEST(fib_test_validate_entry(fei,
9357 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9360 "%U via 10.10.10.2",
9361 format_fib_prefix, &pfx_10_10_10_0_s_24);
9363 * modify the /24. expect the new forwarding to be pushed down
9365 fib_table_entry_update_one_path(0,
9366 &pfx_10_10_10_0_s_24,
9368 FIB_ENTRY_FLAG_COVERED_INHERIT,
9371 tm->hw[0]->sw_if_index,
9375 FIB_ROUTE_PATH_FLAG_NONE);
9376 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9377 FIB_TEST(fib_test_validate_entry(fei,
9378 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9381 "%U via 10.10.10.1",
9382 format_fib_prefix, &pfx_10_10_10_16_s_28);
9383 FIB_TEST(fib_test_validate_entry(fei,
9384 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9387 "%U via 10.10.10.1",
9388 format_fib_prefix, &pfx_10_10_10_21_s_32);
9389 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9390 FIB_TEST(fib_test_validate_entry(fei,
9391 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9394 "%U via 10.10.10.1",
9395 format_fib_prefix, &pfx_10_10_10_22_s_32);
9396 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9397 FIB_TEST(fib_test_validate_entry(fei,
9398 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9401 "%U via 10.10.10.1",
9402 format_fib_prefix, &pfx_10_10_10_255_s_32);
9403 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9404 FIB_TEST(fib_test_validate_entry(fei,
9405 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9408 "%U via 10.10.10.1",
9409 format_fib_prefix, &pfx_10_10_10_0_s_24);
9412 * add an entry less specific to /24. it should not own the /24's tree
9414 const fib_prefix_t pfx_10_10_0_0_s_16 = {
9416 .fp_proto = FIB_PROTOCOL_IP4,
9417 .fp_addr = nh_10_10_0_0,
9419 fib_table_entry_update_one_path(0,
9420 &pfx_10_10_0_0_s_16,
9422 FIB_ENTRY_FLAG_COVERED_INHERIT,
9425 tm->hw[0]->sw_if_index,
9429 FIB_ROUTE_PATH_FLAG_NONE);
9430 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9431 FIB_TEST(fib_test_validate_entry(fei,
9432 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9435 "%U via 10.10.10.1",
9436 format_fib_prefix, &pfx_10_10_10_16_s_28);
9437 FIB_TEST(fib_test_validate_entry(fei,
9438 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9441 "%U via 10.10.10.1",
9442 format_fib_prefix, &pfx_10_10_10_21_s_32);
9443 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9444 FIB_TEST(fib_test_validate_entry(fei,
9445 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9448 "%U via 10.10.10.1",
9449 format_fib_prefix, &pfx_10_10_10_22_s_32);
9450 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9451 FIB_TEST(fib_test_validate_entry(fei,
9452 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9455 "%U via 10.10.10.1",
9456 format_fib_prefix, &pfx_10_10_10_255_s_32);
9457 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9458 FIB_TEST(fib_test_validate_entry(fei,
9459 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9462 "%U via 10.10.10.1",
9463 format_fib_prefix, &pfx_10_10_10_0_s_24);
9464 fei = fib_table_lookup_exact_match(0, &pfx_10_10_0_0_s_16);
9465 FIB_TEST(fib_test_validate_entry(fei,
9466 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9469 "%U via 10.10.10.2",
9470 format_fib_prefix, &pfx_10_10_0_0_s_16);
9475 fib_table_entry_delete(0, &pfx_10_10_10_21_s_32, FIB_SOURCE_CLI);
9476 fib_table_entry_delete(0, &pfx_10_10_10_22_s_32, FIB_SOURCE_CLI);
9477 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_CLI);
9478 fib_table_entry_delete(0, &pfx_10_10_10_255_s_32, FIB_SOURCE_CLI);
9479 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, FIB_SOURCE_API);
9480 fib_table_entry_delete(0, &pfx_10_10_0_0_s_16, FIB_SOURCE_API);
9481 adj_unlock(ai_10_10_10_1);
9482 adj_unlock(ai_10_10_10_2);
9485 * test the v6 tree walk.
9486 * a /64 that covers everytinhg. a /96 that covers one /128
9487 * a second /128 covered only by the /64.
9489 const fib_prefix_t pfx_2001_s_64 = {
9491 .fp_proto = FIB_PROTOCOL_IP6,
9495 [0] = clib_host_to_net_u64(0x2001000000000000),
9496 [1] = clib_host_to_net_u64(0x0000000000000000),
9501 const fib_prefix_t pfx_2001_1_s_96 = {
9503 .fp_proto = FIB_PROTOCOL_IP6,
9507 [0] = clib_host_to_net_u64(0x2001000000000000),
9508 [1] = clib_host_to_net_u64(0x1000000000000000),
9513 const fib_prefix_t pfx_2001_1_1_s_128 = {
9515 .fp_proto = FIB_PROTOCOL_IP6,
9519 [0] = clib_host_to_net_u64(0x2001000000000000),
9520 [1] = clib_host_to_net_u64(0x1000000000000001),
9525 const fib_prefix_t pfx_2001_0_1_s_128 = {
9527 .fp_proto = FIB_PROTOCOL_IP6,
9531 [0] = clib_host_to_net_u64(0x2001000000000000),
9532 [1] = clib_host_to_net_u64(0x0000000000000001),
9537 const ip46_address_t nh_3000_1 = {
9540 [0] = clib_host_to_net_u64(0x3000000000000000),
9541 [1] = clib_host_to_net_u64(0x0000000000000001),
9545 const ip46_address_t nh_3000_2 = {
9548 [0] = clib_host_to_net_u64(0x3000000000000000),
9549 [1] = clib_host_to_net_u64(0x0000000000000002),
9553 adj_index_t ai_3000_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
9556 tm->hw[0]->sw_if_index);
9557 adj_index_t ai_3000_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
9560 tm->hw[0]->sw_if_index);
9561 fib_test_lb_bucket_t adj_o_3000_1 = {
9567 fib_test_lb_bucket_t adj_o_3000_2 = {
9574 fib_table_entry_special_add(0,
9575 &pfx_2001_0_1_s_128,
9577 FIB_ENTRY_FLAG_DROP);
9578 fib_table_entry_special_add(0,
9579 &pfx_2001_1_1_s_128,
9581 FIB_ENTRY_FLAG_DROP);
9584 * /96 has inherited forwarding pushed down to its covered /128
9586 fib_table_entry_update_one_path(0,
9589 FIB_ENTRY_FLAG_COVERED_INHERIT,
9592 tm->hw[0]->sw_if_index,
9596 FIB_ROUTE_PATH_FLAG_NONE);
9597 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_s_96);
9598 FIB_TEST(fib_test_validate_entry(fei,
9599 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
9603 format_fib_prefix, &pfx_2001_1_s_96);
9604 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_1_s_128);
9605 FIB_TEST(fib_test_validate_entry(fei,
9606 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
9610 format_fib_prefix, &pfx_2001_1_1_s_128);
9611 fei = fib_table_lookup_exact_match(0, &pfx_2001_0_1_s_128);
9612 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9613 "%U resolves via drop",
9614 format_fib_prefix, &pfx_2001_0_1_s_128);
9617 * /64 has inherited forwarding pushed down to all, but the /96
9618 * and its sub-tree remain unaffected.
9620 fib_table_entry_update_one_path(0,
9623 FIB_ENTRY_FLAG_COVERED_INHERIT,
9626 tm->hw[0]->sw_if_index,
9630 FIB_ROUTE_PATH_FLAG_NONE);
9632 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
9633 FIB_TEST(fib_test_validate_entry(fei,
9634 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
9638 format_fib_prefix, &pfx_2001_s_64);
9639 fei = fib_table_lookup_exact_match(0, &pfx_2001_0_1_s_128);
9640 FIB_TEST(fib_test_validate_entry(fei,
9641 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
9645 format_fib_prefix, &pfx_2001_0_1_s_128);
9647 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_s_96);
9648 FIB_TEST(fib_test_validate_entry(fei,
9649 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
9653 format_fib_prefix, &pfx_2001_1_s_96);
9654 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_1_s_128);
9655 FIB_TEST(fib_test_validate_entry(fei,
9656 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
9660 format_fib_prefix, &pfx_2001_1_1_s_128);
9665 fib_table_entry_delete(0, &pfx_2001_0_1_s_128, FIB_SOURCE_CLI);
9666 fib_table_entry_delete(0, &pfx_2001_1_1_s_128, FIB_SOURCE_CLI);
9667 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
9668 fib_table_entry_delete(0, &pfx_2001_1_s_96, FIB_SOURCE_API);
9669 adj_unlock(ai_3000_1);
9670 adj_unlock(ai_3000_2);
9673 * test no-one left behind
9675 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
9676 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
9680 static clib_error_t *
9681 fib_test (vlib_main_t * vm,
9682 unformat_input_t * input,
9683 vlib_cli_command_t * cmd_arg)
9688 fib_test_mk_intf(4);
9690 if (unformat (input, "debug"))
9692 fib_test_do_debug = 1;
9695 if (unformat (input, "ip"))
9697 res += fib_test_v4();
9698 res += fib_test_v6();
9700 else if (unformat (input, "label"))
9702 res += fib_test_label();
9704 else if (unformat (input, "ae"))
9706 res += fib_test_ae();
9708 else if (unformat (input, "pref"))
9710 res += fib_test_pref();
9712 else if (unformat (input, "lfib"))
9716 else if (unformat (input, "walk"))
9718 res += fib_test_walk();
9720 else if (unformat (input, "bfd"))
9722 res += fib_test_bfd();
9724 else if (unformat (input, "inherit"))
9726 res += fib_test_inherit();
9730 res += fib_test_v4();
9731 res += fib_test_v6();
9732 res += fib_test_ae();
9733 res += fib_test_bfd();
9734 res += fib_test_pref();
9735 res += fib_test_label();
9736 res += fib_test_inherit();
9740 * fib-walk process must be disabled in order for the walk tests to work
9742 fib_walk_process_disable();
9743 res += fib_test_walk();
9744 fib_walk_process_enable();
9749 return clib_error_return(0, "FIB Unit Test Failed");
9757 VLIB_CLI_COMMAND (test_fib_command, static) = {
9759 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
9760 .function = fib_test,
9764 fib_test_init (vlib_main_t *vm)
9769 VLIB_INIT_FUNCTION (fib_test_init);