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>
33 #include <vnet/dpo/punt_dpo.h>
35 #include <vnet/mpls/mpls.h>
37 #include <vnet/fib/fib_test.h>
38 #include <vnet/fib/fib_path_list.h>
39 #include <vnet/fib/fib_entry_src.h>
40 #include <vnet/fib/fib_walk.h>
41 #include <vnet/fib/fib_node_list.h>
42 #include <vnet/fib/fib_urpf_list.h>
44 #include <vlib/unix/plugin.h>
49 * Add debugs for passing tests
51 static int fib_test_do_debug;
53 #define FIB_TEST_I(_cond, _comment, _args...) \
55 int _evald = (_cond); \
57 fformat(stderr, "FAIL:%d: " _comment "\n", \
61 if (fib_test_do_debug) \
62 fformat(stderr, "PASS:%d: " _comment "\n", \
67 #define FIB_TEST(_cond, _comment, _args...) \
69 if (FIB_TEST_I(_cond, _comment, ##_args)) { \
71 ASSERT(!("FAIL: " _comment)); \
76 * A 'i'm not fussed is this is not efficient' store of test data
78 typedef struct test_main_t_ {
82 u32 hw_if_indicies[4];
86 vnet_hw_interface_t * hw[4];
89 static test_main_t test_main;
91 /* fake ethernet device class, distinct from "fake-ethX" */
92 static u8 * format_test_interface_name (u8 * s, va_list * args)
94 u32 dev_instance = va_arg (*args, u32);
95 return format (s, "test-eth%d", dev_instance);
98 static uword placeholder_interface_tx (vlib_main_t * vm,
99 vlib_node_runtime_t * node,
100 vlib_frame_t * frame)
102 clib_warning ("you shouldn't be here, leaking buffers...");
103 return frame->n_vectors;
106 static clib_error_t *
107 test_interface_admin_up_down (vnet_main_t * vnm,
111 u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
112 VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
113 vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
117 VNET_DEVICE_CLASS (test_interface_device_class,static) = {
118 .name = "Test interface",
119 .format_device_name = format_test_interface_name,
120 .tx_function = placeholder_interface_tx,
121 .admin_up_down_function = test_interface_admin_up_down,
124 static u8 *hw_address;
127 fib_test_mk_intf (u32 ninterfaces)
129 clib_error_t * error = NULL;
130 test_main_t *tm = &test_main;
135 ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
140 vec_add1(hw_address, byte);
143 for (i = 0; i < ninterfaces; i++)
145 vnet_eth_interface_registration_t eir = {};
146 vnet_main_t *vnm = vnet_get_main();
150 eir.dev_class_index = test_interface_device_class.index;
151 eir.dev_instance = i;
152 eir.address = hw_address;
153 tm->hw_if_indicies[i] = vnet_eth_register_interface (vnm, &eir);
155 error = vnet_hw_interface_set_flags(vnet_get_main(),
156 tm->hw_if_indicies[i],
157 VNET_HW_INTERFACE_FLAG_LINK_UP);
158 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
159 tm->hw_if_indicies[i]);
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)) { \
216 fib_test_urpf_is_equal (fib_node_index_t fei,
217 fib_forward_chain_type_t fct,
220 dpo_id_t dpo = DPO_INVALID;
221 fib_urpf_list_t *urpf;
229 fib_entry_contribute_forwarding(fei, fct, &dpo);
230 ui = load_balance_get_urpf(dpo.dpoi_index);
232 urpf = fib_urpf_list_get(ui);
234 FIB_TEST_RPF(num == vec_len(urpf->furpf_itfs),
235 "RPF:%U len %d == %d",
236 format_fib_urpf_list, ui,
237 num, vec_len(urpf->furpf_itfs));
238 FIB_TEST_RPF(num == fib_urpf_check_size(ui),
239 "RPF:%U check-size %d == %d",
240 format_fib_urpf_list, ui,
241 num, vec_len(urpf->furpf_itfs));
243 for (ii = 0; ii < num; ii++)
245 adj_index_t ai = va_arg(ap, adj_index_t);
247 FIB_TEST_RPF(ai == urpf->furpf_itfs[ii],
248 "RPF:%d item:%d - %d == %d",
249 ui, ii, ai, urpf->furpf_itfs[ii]);
250 FIB_TEST_RPF(fib_urpf_check(ui, ai),
264 fib_test_build_rewrite (u8 *eth_addr)
268 vec_validate(rewrite, 13);
270 memcpy(rewrite, eth_addr, 6);
271 memcpy(rewrite+6, eth_addr, 6);
276 #define FIB_TEST_LB(_cond, _comment, _args...) \
278 if (FIB_TEST_I(_cond, _comment, ##_args)) { \
284 fib_test_validate_rep_v (const replicate_t *rep,
288 const fib_test_rep_bucket_t *exp;
293 FIB_TEST_LB((n_buckets == rep->rep_n_buckets),
294 "n_buckets = %d", rep->rep_n_buckets);
296 for (bucket = 0; bucket < n_buckets; bucket++)
298 exp = va_arg(*ap, fib_test_rep_bucket_t*);
300 dpo = replicate_get_bucket_i(rep, bucket);
304 case FT_REP_LABEL_O_ADJ:
306 const mpls_label_dpo_t *mld;
309 FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE)
311 "bucket %d stacks on %U",
313 format_dpo_type, dpo->dpoi_type);
315 mld = mpls_label_dpo_get(dpo->dpoi_index);
316 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
318 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
319 exp->label_o_adj.label),
320 "bucket %d stacks on label %d",
322 exp->label_o_adj.label);
324 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
325 exp->label_o_adj.eos),
326 "bucket %d stacks on label %d %U",
328 exp->label_o_adj.label,
329 format_mpls_eos_bit, exp->label_o_adj.eos);
331 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
332 "bucket %d label stacks on %U",
334 format_dpo_type, mld->mld_dpo.dpoi_type);
336 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
337 "bucket %d label stacks on adj %d",
339 exp->label_o_adj.adj);
343 FIB_TEST_LB((DPO_INTERFACE_RX == dpo->dpoi_type),
344 "bucket %d stacks on %U",
346 format_dpo_type, dpo->dpoi_type);
348 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
349 "bucket %d stacks on adj %d",
353 case FT_REP_DISP_MFIB_LOOKUP:
363 fib_test_validate_lb_v (const load_balance_t *lb,
371 FIB_TEST_LB((n_buckets == lb->lb_n_buckets), "n_buckets = %d", lb->lb_n_buckets);
373 for (bucket = 0; bucket < n_buckets; bucket++)
375 const fib_test_lb_bucket_t *exp;
377 exp = va_arg(*ap, fib_test_lb_bucket_t*);
378 dpo = load_balance_get_bucket_i(lb, bucket);
382 case FT_LB_LABEL_STACK_O_ADJ:
384 const mpls_label_dpo_t *mld;
385 mpls_label_dpo_flags_t mf;
389 mf = ((exp->label_stack_o_adj.mode ==
390 FIB_MPLS_LSP_MODE_UNIFORM) ?
391 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
392 MPLS_LABEL_DPO_FLAG_NONE);
393 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
394 "bucket %d stacks on %U",
396 format_dpo_type, dpo->dpoi_type);
398 mld = mpls_label_dpo_get(dpo->dpoi_index);
400 FIB_TEST_LB(exp->label_stack_o_adj.label_stack_size == mld->mld_n_labels,
404 for (ii = 0; ii < mld->mld_n_labels; ii++)
406 hdr = clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
407 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
408 exp->label_stack_o_adj.label_stack[ii]),
409 "bucket %d stacks on label %d",
411 exp->label_stack_o_adj.label_stack[ii]);
413 if (ii == mld->mld_n_labels-1)
415 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
416 exp->label_o_adj.eos),
417 "bucket %d stacks on label %d %U!=%U",
419 exp->label_stack_o_adj.label_stack[ii],
420 format_mpls_eos_bit, exp->label_o_adj.eos,
421 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
425 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) == MPLS_NON_EOS),
426 "bucket %d stacks on label %d %U",
428 exp->label_stack_o_adj.label_stack[ii],
429 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
433 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
434 "bucket %d label stacks on %U",
436 format_dpo_type, mld->mld_dpo.dpoi_type);
438 FIB_TEST_LB((exp->label_stack_o_adj.adj == mld->mld_dpo.dpoi_index),
439 "bucket %d label stacks on adj %d",
441 exp->label_stack_o_adj.adj);
444 case FT_LB_LABEL_CHAIN_O_ADJ:
446 const mpls_label_dpo_t *mld = NULL;
447 mpls_label_dpo_flags_t mf;
451 mf = ((exp->label_chain_o_adj.mode ==
452 FIB_MPLS_LSP_MODE_UNIFORM) ?
453 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
454 MPLS_LABEL_DPO_FLAG_NONE);
456 for (ii = 0; ii < exp->label_chain_o_adj.label_chain_size; ii++)
458 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
459 "bucket %d stacks on %U",
461 format_dpo_type, dpo->dpoi_type);
462 mld = mpls_label_dpo_get(dpo->dpoi_index);
464 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
465 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
466 exp->label_chain_o_adj.label_chain[ii]),
467 "bucket %d stacks on label %d",
469 exp->label_chain_o_adj.label_chain[ii]);
473 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
474 "bucket %d label stacks on %U",
476 format_dpo_type, mld->mld_dpo.dpoi_type);
478 FIB_TEST_LB((exp->label_chain_o_adj.adj == mld->mld_dpo.dpoi_index),
479 "bucket %d label stacks on adj %d",
481 exp->label_chain_o_adj.adj);
484 case FT_LB_LABEL_O_ADJ:
486 const mpls_label_dpo_t *mld;
488 FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE)
490 "bucket %d stacks on %U",
492 format_dpo_type, dpo->dpoi_type);
494 mld = mpls_label_dpo_get(dpo->dpoi_index);
495 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
497 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
498 exp->label_o_adj.label),
499 "bucket %d stacks on label %d not %d",
501 vnet_mpls_uc_get_label(hdr),
502 exp->label_o_adj.label);
504 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
505 exp->label_o_adj.eos),
506 "bucket %d stacks on label %d %U",
508 exp->label_o_adj.label,
509 format_mpls_eos_bit, exp->label_o_adj.eos);
511 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
512 "bucket %d label stacks on %U",
514 format_dpo_type, mld->mld_dpo.dpoi_type);
516 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
517 "bucket %d label stacks on adj %d",
519 exp->label_o_adj.adj);
522 case FT_LB_LABEL_O_LB:
524 const mpls_label_dpo_t *mld;
525 mpls_label_dpo_flags_t mf;
528 mf = ((exp->label_o_lb.mode ==
529 FIB_MPLS_LSP_MODE_UNIFORM) ?
530 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
531 MPLS_LABEL_DPO_FLAG_NONE);
532 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
533 "bucket %d stacks on %U",
535 format_dpo_type, dpo->dpoi_type);
537 mld = mpls_label_dpo_get(dpo->dpoi_index);
538 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
540 FIB_TEST_LB(1 == mld->mld_n_labels, "label stack size",
542 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
543 exp->label_o_lb.label),
544 "bucket %d stacks on label %d",
546 exp->label_o_lb.label);
548 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
549 exp->label_o_lb.eos),
550 "bucket %d stacks on label %d %U",
552 exp->label_o_lb.label,
553 format_mpls_eos_bit, exp->label_o_lb.eos);
555 FIB_TEST_LB((DPO_LOAD_BALANCE == mld->mld_dpo.dpoi_type),
556 "bucket %d label stacks on %U",
558 format_dpo_type, mld->mld_dpo.dpoi_type);
560 FIB_TEST_LB((exp->label_o_lb.lb == mld->mld_dpo.dpoi_index),
561 "bucket %d label stacks on LB %d",
567 res = FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
568 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
569 "bucket %d stacks on %U",
571 format_dpo_type, dpo->dpoi_type);
572 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
573 "bucket %d stacks on adj %d",
577 case FT_LB_MPLS_DISP_PIPE_O_ADJ:
579 const mpls_disp_dpo_t *mdd;
581 res = FIB_TEST_I((DPO_MPLS_DISPOSITION_PIPE == dpo->dpoi_type),
582 "bucket %d stacks on %U",
584 format_dpo_type, dpo->dpoi_type);
586 mdd = mpls_disp_dpo_get(dpo->dpoi_index);
590 res = FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
591 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
592 "bucket %d stacks on %U",
594 format_dpo_type, dpo->dpoi_type);
595 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
596 "bucket %d stacks on adj %d",
602 res = FIB_TEST_I((DPO_INTERFACE_RX == dpo->dpoi_type),
603 "bucket %d stacks on %U",
605 format_dpo_type, dpo->dpoi_type);
606 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
607 "bucket %d stacks on adj %d",
612 res = FIB_TEST_I((DPO_DVR == dpo->dpoi_type),
613 "bucket %d stacks on %U",
615 format_dpo_type, dpo->dpoi_type);
616 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
617 "bucket %d stacks on adj %d",
622 res = FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
623 "bucket %d stacks on %U",
625 format_dpo_type, dpo->dpoi_type);
626 FIB_TEST_LB((exp->lb.lb == dpo->dpoi_index),
627 "bucket %d stacks on lb %d not %d",
632 case FT_LB_BIER_TABLE:
633 FIB_TEST_LB((DPO_BIER_TABLE == dpo->dpoi_type),
634 "bucket %d stacks on %U",
636 format_dpo_type, dpo->dpoi_type);
637 FIB_TEST_LB((exp->bier.table == dpo->dpoi_index),
638 "bucket %d stacks on lb %d",
642 case FT_LB_BIER_FMASK:
643 FIB_TEST_LB((DPO_BIER_FMASK == dpo->dpoi_type),
644 "bucket %d stacks on %U",
646 format_dpo_type, dpo->dpoi_type);
647 FIB_TEST_LB((exp->bier.fmask == dpo->dpoi_index),
648 "bucket %d stacks on lb %d",
653 FIB_TEST_LB((DPO_DROP == dpo->dpoi_type),
654 "bucket %d stacks on %U",
656 format_dpo_type, dpo->dpoi_type);
659 FIB_TEST_LB((DPO_PUNT == dpo->dpoi_type),
660 "bucket %d stacks on %U",
662 format_dpo_type, dpo->dpoi_type);
670 fib_test_validate_lb (const dpo_id_t *dpo,
674 const load_balance_t *lb;
679 va_start(ap, n_buckets);
681 if (!FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
683 format_dpo_type, dpo->dpoi_type))
685 lb = load_balance_get(dpo->dpoi_index);
687 res = fib_test_validate_lb_v(lb, n_buckets, &ap);
700 fib_test_validate_entry (fib_node_index_t fei,
701 fib_forward_chain_type_t fct,
705 dpo_id_t dpo = DPO_INVALID;
706 const fib_prefix_t *pfx;
714 pfx = fib_entry_get_prefix(fei);
715 fib_index = fib_entry_get_fib_index(fei);
716 fib_entry_contribute_forwarding(fei, fct, &dpo);
718 if (DPO_REPLICATE == dpo.dpoi_type)
720 const replicate_t *rep;
722 va_start(ap, n_buckets);
723 rep = replicate_get(dpo.dpoi_index);
724 res = fib_test_validate_rep_v(rep, n_buckets, &ap);
729 const load_balance_t *lb;
731 FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type),
732 "%U Entry links to %U",
733 format_fib_prefix, pfx,
734 format_dpo_type, dpo.dpoi_type);
736 va_start(ap, n_buckets);
737 lb = load_balance_get(dpo.dpoi_index);
738 res = fib_test_validate_lb_v(lb, n_buckets, &ap);
742 * ensure that the LB contributed by the entry is the
743 * same as the LB in the forwarding tables
745 if (fct == fib_entry_get_default_chain_type(fib_entry_get(fei)))
747 switch (pfx->fp_proto)
749 case FIB_PROTOCOL_IP4:
750 fw_lbi = ip4_fib_forwarding_lookup(fib_index, &pfx->fp_addr.ip4);
752 case FIB_PROTOCOL_IP6:
753 fw_lbi = ip6_fib_table_fwding_lookup(fib_index, &pfx->fp_addr.ip6);
755 case FIB_PROTOCOL_MPLS:
757 mpls_unicast_header_t hdr = {
758 .label_exp_s_ttl = 0,
761 vnet_mpls_uc_set_label(&hdr.label_exp_s_ttl, pfx->fp_label);
762 vnet_mpls_uc_set_s(&hdr.label_exp_s_ttl, pfx->fp_eos);
763 hdr.label_exp_s_ttl = clib_host_to_net_u32(hdr.label_exp_s_ttl);
765 fw_lbi = mpls_fib_table_forwarding_lookup(fib_index, &hdr);
771 FIB_TEST_LB((fw_lbi == dpo.dpoi_index),
772 "Contributed LB = FW LB:\n fwd:%U\n cont:%U",
773 format_load_balance, fw_lbi, 0,
774 format_load_balance, dpo.dpoi_index, 0);
787 * In the default table check for the presence and correct forwarding
788 * of the special entries
790 fib_node_index_t dfrt, fei, ai, ai2, locked_ai, ai_01, ai_02, ai_03;
791 const dpo_id_t *dpo, *dpo1, *dpo2, *dpo_drop;
792 const ip_adjacency_t *adj;
793 const load_balance_t *lb;
801 ip46_address_t nh_10_10_10_1 = {
802 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
805 ip46_address_t nh_10_10_10_2 = {
806 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
809 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
810 pool_elts(load_balance_map_pool));
814 /* record the nubmer of load-balances in use before we start */
815 lb_count = pool_elts(load_balance_pool);
817 /* Find or create FIB table 11 */
818 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11,
821 for (ii = 0; ii < 4; ii++)
822 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[ii]->sw_if_index, fib_index);
824 fib_prefix_t pfx_0_0_0_0_s_0 = {
826 .fp_proto = FIB_PROTOCOL_IP4,
836 .fp_proto = FIB_PROTOCOL_IP4,
844 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
846 dfrt = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
847 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
848 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
849 "Default route is DROP");
852 fei = fib_table_lookup(fib_index, &pfx);
853 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all zeros route present");
854 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
855 "all 0s route is DROP");
857 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xffffffff);
859 fei = fib_table_lookup(fib_index, &pfx);
860 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all ones route present");
861 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
862 "all 1s route is DROP");
864 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xe0000000);
866 fei = fib_table_lookup(fib_index, &pfx);
867 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all-mcast route present");
868 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
869 "all-mcast route is DROP");
871 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xf0000000);
873 fei = fib_table_lookup(fib_index, &pfx);
874 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "class-e route present");
875 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
876 "class-e route is DROP");
879 * at this stage there are 5 entries in the test FIB (plus 5 in the default),
880 * all of which are special sourced and so none of which share path-lists.
881 * There are also 2 entries, and 2 non-shared path-lists, in the v6 default
882 * table, and 4 path-lists in the v6 MFIB table and 2 in v4.
886 u32 PNBR = 5+5+2+4+2;
889 * if the IGMP plugin is loaded this adds two more entries to the v4 MFIB
891 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
892 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
893 fib_path_list_pool_size());
894 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
895 fib_entry_pool_size());
898 * add interface routes.
899 * validate presence of /24 attached and /32 recieve.
900 * test for the presence of the receive address in the glean and local adj
902 fib_prefix_t local_pfx = {
904 .fp_proto = FIB_PROTOCOL_IP4,
907 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
912 fib_table_entry_update_one_path(fib_index, &local_pfx,
913 FIB_SOURCE_INTERFACE,
914 (FIB_ENTRY_FLAG_CONNECTED |
915 FIB_ENTRY_FLAG_ATTACHED),
918 tm->hw[0]->sw_if_index,
919 ~0, // invalid fib index
922 FIB_ROUTE_PATH_FLAG_NONE);
923 fei = fib_table_lookup(fib_index, &local_pfx);
924 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
925 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
926 fib_entry_get_flags(fei)),
927 "Flags set on attached interface");
929 ai = fib_entry_get_adj(fei);
930 FIB_TEST((FIB_NODE_INDEX_INVALID != ai),
931 "attached interface route adj present %d", ai);
933 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
934 "attached interface adj is glean");
936 local_pfx.fp_len = 32;
937 fib_table_entry_update_one_path(fib_index, &local_pfx,
938 FIB_SOURCE_INTERFACE,
939 (FIB_ENTRY_FLAG_CONNECTED |
940 FIB_ENTRY_FLAG_LOCAL),
943 tm->hw[0]->sw_if_index,
944 ~0, // invalid fib index
947 FIB_ROUTE_PATH_FLAG_NONE);
948 fei = fib_table_lookup(fib_index, &local_pfx);
949 FIB_TEST(((FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_CONNECTED) ==
950 fib_entry_get_flags(fei)),
951 "Flags set on local interface");
953 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
955 dpo = fib_entry_contribute_ip_forwarding(fei);
956 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
957 "RPF list for local length 0");
958 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
959 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
960 "local interface adj is local");
961 receive_dpo_t *rd = receive_dpo_get(dpo->dpoi_index);
963 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
965 "local interface adj is receive ok");
967 FIB_TEST((2 == fib_table_get_num_entries(fib_index,
969 FIB_SOURCE_INTERFACE)),
970 "2 Interface Source'd prefixes");
971 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
972 &adj->sub_type.glean.rx_pfx.fp_addr)),
973 "attached interface adj is receive ok");
976 * +2 interface routes +2 non-shared path-lists
978 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
979 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
980 fib_path_list_pool_size());
981 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
982 fib_entry_pool_size());
985 * Modify the default route to be via an adj not yet known.
986 * this sources the defalut route with the API source, which is
987 * a higher preference to the DEFAULT_ROUTE source
989 pfx.fp_addr.ip4.as_u32 = 0;
991 fib_table_entry_path_add(fib_index, &pfx,
996 tm->hw[0]->sw_if_index,
997 ~0, // invalid fib index
1000 FIB_ROUTE_PATH_FLAG_NONE);
1001 fei = fib_table_lookup(fib_index, &pfx);
1002 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
1003 "Flags set on API route");
1005 FIB_TEST((fei == dfrt), "default route same index");
1006 ai = fib_entry_get_adj(fei);
1007 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
1009 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1010 "adj is incomplete");
1011 FIB_TEST((0 == ip46_address_cmp(&nh_10_10_10_1, &adj->sub_type.nbr.next_hop)),
1012 "adj nbr next-hop ok");
1013 FIB_TEST((1 == fib_table_get_num_entries(fib_index,
1016 "1 API Source'd prefixes");
1019 * find the adj in the shared db
1021 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1024 tm->hw[0]->sw_if_index);
1025 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
1026 adj_unlock(locked_ai);
1029 * +1 shared path-list
1031 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
1032 fib_path_list_db_size());
1033 FIB_TEST((PNBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
1034 fib_path_list_pool_size());
1035 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
1036 fib_entry_pool_size());
1039 * remove the API source from the default route. We expected
1040 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
1042 pfx.fp_addr.ip4.as_u32 = 0;
1044 fib_table_entry_path_remove(fib_index, &pfx,
1048 tm->hw[0]->sw_if_index,
1049 ~0, // non-recursive path, so no FIB index
1051 FIB_ROUTE_PATH_FLAG_NONE);
1053 fei = fib_table_lookup(fib_index, &pfx);
1055 FIB_TEST((fei == dfrt), "default route same index");
1056 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
1057 "Default route is DROP");
1060 * -1 shared-path-list
1062 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
1063 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
1064 fib_path_list_pool_size());
1065 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
1066 fib_entry_pool_size());
1069 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
1071 fib_prefix_t pfx_10_10_10_1_s_32 = {
1073 .fp_proto = FIB_PROTOCOL_IP4,
1076 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
1079 fib_prefix_t pfx_10_10_10_2_s_32 = {
1081 .fp_proto = FIB_PROTOCOL_IP4,
1084 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
1087 fib_prefix_t pfx_11_11_11_11_s_32 = {
1089 .fp_proto = FIB_PROTOCOL_IP4,
1092 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
1096 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
1099 ip46_address_t nh_12_12_12_12 = {
1100 .ip4.as_u32 = clib_host_to_net_u32(0x0c0c0c0c),
1102 adj_index_t ai_12_12_12_12;
1105 * Add a route via an incomplete ADJ. then complete the ADJ
1106 * Expect the route LB is updated to use complete adj type.
1108 fei = fib_table_entry_update_one_path(fib_index,
1109 &pfx_11_11_11_11_s_32,
1111 FIB_ENTRY_FLAG_ATTACHED,
1113 &pfx_10_10_10_1_s_32.fp_addr,
1114 tm->hw[0]->sw_if_index,
1115 ~0, // invalid fib index
1118 FIB_ROUTE_PATH_FLAG_NONE);
1120 dpo = fib_entry_contribute_ip_forwarding(fei);
1121 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1122 FIB_TEST(DPO_ADJACENCY_INCOMPLETE == dpo1->dpoi_type,
1123 "11.11.11.11/32 via incomplete adj");
1125 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1127 &pfx_10_10_10_1_s_32.fp_addr,
1128 tm->hw[0]->sw_if_index);
1129 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
1130 adj = adj_get(ai_01);
1131 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1132 "adj is incomplete");
1133 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1134 &adj->sub_type.nbr.next_hop)),
1135 "adj nbr next-hop ok");
1137 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1138 fib_test_build_rewrite(eth_addr));
1139 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1141 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1142 &adj->sub_type.nbr.next_hop)),
1143 "adj nbr next-hop ok");
1144 ai = fib_entry_get_adj(fei);
1145 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
1147 dpo = fib_entry_contribute_ip_forwarding(fei);
1148 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1149 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type,
1150 "11.11.11.11/32 via complete adj");
1151 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1152 tm->hw[0]->sw_if_index),
1153 "RPF list for adj-fib contains adj");
1155 ai_12_12_12_12 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1158 tm->hw[1]->sw_if_index);
1159 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_12_12_12_12), "adj created");
1160 adj = adj_get(ai_12_12_12_12);
1161 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1162 "adj is incomplete");
1163 FIB_TEST((0 == ip46_address_cmp(&nh_12_12_12_12,
1164 &adj->sub_type.nbr.next_hop)),
1165 "adj nbr next-hop ok");
1166 adj_nbr_update_rewrite(ai_12_12_12_12, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1167 fib_test_build_rewrite(eth_addr));
1168 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1174 fei = fib_table_entry_path_add(fib_index,
1175 &pfx_10_10_10_1_s_32,
1177 FIB_ENTRY_FLAG_ATTACHED,
1179 &pfx_10_10_10_1_s_32.fp_addr,
1180 tm->hw[0]->sw_if_index,
1181 ~0, // invalid fib index
1184 FIB_ROUTE_PATH_FLAG_NONE);
1185 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
1186 "Flags set on adj-fib");
1187 ai = fib_entry_get_adj(fei);
1188 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj, %d", ai);
1190 fib_table_entry_path_remove(fib_index,
1191 &pfx_11_11_11_11_s_32,
1194 &pfx_10_10_10_1_s_32.fp_addr,
1195 tm->hw[0]->sw_if_index,
1196 ~0, // invalid fib index
1198 FIB_ROUTE_PATH_FLAG_NONE);
1202 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1204 &pfx_10_10_10_2_s_32.fp_addr,
1205 tm->hw[0]->sw_if_index);
1206 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
1207 adj = adj_get(ai_02);
1208 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1209 "adj is incomplete");
1210 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1211 &adj->sub_type.nbr.next_hop)),
1212 "adj nbr next-hop ok");
1214 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1215 fib_test_build_rewrite(eth_addr));
1216 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1218 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1219 &adj->sub_type.nbr.next_hop)),
1220 "adj nbr next-hop ok");
1221 FIB_TEST((ai_01 != ai_02), "ADJs are different");
1223 fib_table_entry_path_add(fib_index,
1224 &pfx_10_10_10_2_s_32,
1226 FIB_ENTRY_FLAG_ATTACHED,
1228 &pfx_10_10_10_2_s_32.fp_addr,
1229 tm->hw[0]->sw_if_index,
1230 ~0, // invalid fib index
1233 FIB_ROUTE_PATH_FLAG_NONE);
1235 fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32);
1236 ai = fib_entry_get_adj(fei);
1237 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
1240 * +2 adj-fibs, and their non-shared path-lists
1242 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
1243 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
1244 fib_path_list_pool_size());
1245 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
1246 fib_entry_pool_size());
1249 * Add 2 routes via the first ADJ. ensure path-list sharing
1251 fib_prefix_t pfx_1_1_1_1_s_32 = {
1253 .fp_proto = FIB_PROTOCOL_IP4,
1256 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
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_1_1_s_32);
1272 ai = fib_entry_get_adj(fei);
1273 FIB_TEST((ai_01 == ai), "1.1.1.1 resolves via 10.10.10.1");
1276 * +1 entry and a shared path-list
1278 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
1279 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1280 fib_path_list_pool_size());
1281 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
1282 fib_entry_pool_size());
1285 fib_prefix_t pfx_1_1_2_0_s_24 = {
1287 .fp_proto = FIB_PROTOCOL_IP4,
1289 .ip4.as_u32 = clib_host_to_net_u32(0x01010200),
1293 fib_table_entry_path_add(fib_index,
1296 FIB_ENTRY_FLAG_NONE,
1299 tm->hw[0]->sw_if_index,
1300 ~0, // invalid fib index
1303 FIB_ROUTE_PATH_FLAG_NONE);
1304 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1305 ai = fib_entry_get_adj(fei);
1306 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1311 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
1312 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1313 fib_path_list_pool_size());
1314 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1315 fib_entry_pool_size());
1318 * modify 1.1.2.0/24 to use multipath.
1320 fib_table_entry_path_add(fib_index,
1323 FIB_ENTRY_FLAG_NONE,
1326 tm->hw[0]->sw_if_index,
1327 ~0, // invalid fib index
1330 FIB_ROUTE_PATH_FLAG_NONE);
1331 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1332 dpo = fib_entry_contribute_ip_forwarding(fei);
1333 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1334 1, tm->hw[0]->sw_if_index),
1335 "RPF list for 1.1.2.0/24 contains both adjs");
1337 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1338 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1339 FIB_TEST((ai_01 == dpo1->dpoi_index),
1340 "1.1.2.0/24 bucket 0 resolves via 10.10.10.1 (%d=%d)",
1341 ai_01, dpo1->dpoi_index);
1343 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 1);
1344 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1345 FIB_TEST((ai_02 == dpo1->dpoi_index),
1346 "1.1.2.0/24 bucket 1 resolves via 10.10.10.2");
1349 * +1 shared-pathlist
1351 FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty");
1352 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1353 fib_path_list_pool_size());
1354 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1355 fib_entry_pool_size());
1360 fib_table_entry_path_remove(fib_index,
1365 tm->hw[0]->sw_if_index,
1368 FIB_ROUTE_PATH_FLAG_NONE);
1369 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1370 dpo = fib_entry_contribute_ip_forwarding(fei);
1371 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1372 1, tm->hw[0]->sw_if_index),
1373 "RPF list for 1.1.2.0/24 contains one adj");
1375 ai = fib_entry_get_adj(fei);
1376 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1379 * +1 shared-pathlist
1381 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d",
1382 fib_path_list_db_size());
1383 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1384 fib_path_list_pool_size());
1385 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1386 fib_entry_pool_size());
1389 * Add 2 recursive routes:
1390 * 100.100.100.100/32 via 1.1.1.1/32 => the via entry is installed.
1391 * 100.100.100.101/32 via 1.1.1.1/32 => the via entry is installed.
1393 fib_prefix_t bgp_100_pfx = {
1395 .fp_proto = FIB_PROTOCOL_IP4,
1397 /* 100.100.100.100/32 */
1398 .ip4.as_u32 = clib_host_to_net_u32(0x64646464),
1402 ip46_address_t nh_1_1_1_1 = {
1403 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1406 fei = fib_table_entry_path_add(fib_index,
1409 FIB_ENTRY_FLAG_NONE,
1412 ~0, // no index provided.
1413 fib_index, // nexthop in same fib as route
1416 FIB_ROUTE_PATH_FLAG_NONE);
1418 FIB_TEST_REC_FORW(&bgp_100_pfx, &pfx_1_1_1_1_s_32, 0);
1419 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1420 tm->hw[0]->sw_if_index),
1421 "RPF list for adj-fib contains adj");
1424 * +1 entry and +1 shared-path-list
1426 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1427 fib_path_list_db_size());
1428 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1429 fib_path_list_pool_size());
1430 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
1431 fib_entry_pool_size());
1433 fib_prefix_t bgp_101_pfx = {
1435 .fp_proto = FIB_PROTOCOL_IP4,
1437 /* 100.100.100.101/32 */
1438 .ip4.as_u32 = clib_host_to_net_u32(0x64646465),
1442 fib_table_entry_path_add(fib_index,
1445 FIB_ENTRY_FLAG_NONE,
1448 ~0, // no index provided.
1449 fib_index, // nexthop in same fib as route
1452 FIB_ROUTE_PATH_FLAG_NONE);
1454 FIB_TEST_REC_FORW(&bgp_101_pfx, &pfx_1_1_1_1_s_32, 0);
1455 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1456 tm->hw[0]->sw_if_index),
1457 "RPF list for adj-fib contains adj");
1460 * +1 entry, but the recursive path-list is shared.
1462 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1463 fib_path_list_db_size());
1464 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1465 fib_path_list_pool_size());
1466 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
1467 fib_entry_pool_size());
1470 * An special route; one where the user (me) provides the
1471 * adjacency through which the route will resovle by setting the flags
1473 fib_prefix_t ex_pfx = {
1475 .fp_proto = FIB_PROTOCOL_IP4,
1478 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
1482 fib_table_entry_special_add(fib_index,
1485 FIB_ENTRY_FLAG_LOCAL);
1486 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1487 dpo = fib_entry_contribute_ip_forwarding(fei);
1488 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
1489 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
1490 "local interface adj is local");
1492 fib_table_entry_special_remove(fib_index,
1494 FIB_SOURCE_SPECIAL);
1495 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1496 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1497 "Exclusive reoute removed");
1500 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1501 * adjacency through which the route will resovle
1503 dpo_id_t ex_dpo = DPO_INVALID;
1505 lookup_dpo_add_or_lock_w_fib_index(fib_index,
1508 LOOKUP_INPUT_DST_ADDR,
1509 LOOKUP_TABLE_FROM_CONFIG,
1512 fib_table_entry_special_dpo_add(fib_index,
1515 FIB_ENTRY_FLAG_EXCLUSIVE,
1517 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1518 dpo = fib_entry_contribute_ip_forwarding(fei);
1519 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1520 "exclusive remote uses lookup DPO");
1523 * update the exclusive to use a different DPO
1525 ip_null_dpo_add_and_lock(DPO_PROTO_IP4,
1526 IP_NULL_ACTION_SEND_ICMP_UNREACH,
1528 fib_table_entry_special_dpo_update(fib_index,
1531 FIB_ENTRY_FLAG_EXCLUSIVE,
1533 dpo = fib_entry_contribute_ip_forwarding(fei);
1534 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1535 "exclusive remote uses now uses NULL DPO");
1537 fib_table_entry_special_remove(fib_index,
1539 FIB_SOURCE_SPECIAL);
1540 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1541 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1542 "Exclusive reoute removed");
1546 * Add a recursive route:
1547 * 200.200.200.200/32 via 1.1.1.2/32 => the via entry is NOT installed.
1549 fib_prefix_t bgp_200_pfx = {
1551 .fp_proto = FIB_PROTOCOL_IP4,
1553 /* 200.200.200.200/32 */
1554 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c8),
1558 fib_prefix_t pfx_1_1_1_2_s_32 = {
1560 .fp_proto = FIB_PROTOCOL_IP4,
1562 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
1566 fei = fib_table_entry_path_add(fib_index,
1569 FIB_ENTRY_FLAG_NONE,
1571 &pfx_1_1_1_2_s_32.fp_addr,
1572 ~0, // no index provided.
1573 fib_index, // nexthop in same fib as route
1576 FIB_ROUTE_PATH_FLAG_NONE);
1578 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
1579 "Recursive via unresolved is drop");
1582 * the adj should be recursive via drop, since the route resolves via
1583 * the default route, which is itself a DROP
1585 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
1586 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1587 FIB_TEST(load_balance_is_drop(dpo1), "1.1.1.2/32 is drop");
1588 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1589 "RPF list for 1.1.1.2/32 contains 0 adjs");
1592 * +2 entry and +1 shared-path-list
1594 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
1595 fib_path_list_db_size());
1596 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
1597 fib_path_list_pool_size());
1598 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
1599 fib_entry_pool_size());
1602 * Unequal Cost load-balance. 3:1 ratio. fits in a 4 bucket LB
1603 * The paths are sort by NH first. in this case the the path with greater
1604 * weight is first in the set. This ordering is to test the RPF sort|uniq logic
1606 fib_prefix_t pfx_1_2_3_4_s_32 = {
1608 .fp_proto = FIB_PROTOCOL_IP4,
1610 .ip4.as_u32 = clib_host_to_net_u32(0x01020304),
1613 fib_table_entry_path_add(fib_index,
1616 FIB_ENTRY_FLAG_NONE,
1619 tm->hw[0]->sw_if_index,
1623 FIB_ROUTE_PATH_FLAG_NONE);
1624 fei = fib_table_entry_path_add(fib_index,
1627 FIB_ENTRY_FLAG_NONE,
1630 tm->hw[1]->sw_if_index,
1634 FIB_ROUTE_PATH_FLAG_NONE);
1636 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.4/32 presnet");
1637 dpo = fib_entry_contribute_ip_forwarding(fei);
1638 lb = load_balance_get(dpo->dpoi_index);
1639 FIB_TEST((lb->lb_n_buckets == 4),
1640 "1.2.3.4/32 LB has %d bucket",
1643 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 0, ai_12_12_12_12);
1644 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 1, ai_12_12_12_12);
1645 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 2, ai_12_12_12_12);
1646 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 3, ai_01);
1648 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1649 tm->hw[0]->sw_if_index,
1650 tm->hw[1]->sw_if_index),
1651 "RPF list for 1.2.3.4/32 contains both adjs");
1655 * Unequal Cost load-balance. 4:1 ratio.
1656 * fits in a 16 bucket LB with ratio 13:3
1658 fib_prefix_t pfx_1_2_3_5_s_32 = {
1660 .fp_proto = FIB_PROTOCOL_IP4,
1662 .ip4.as_u32 = clib_host_to_net_u32(0x01020305),
1665 fib_table_entry_path_add(fib_index,
1668 FIB_ENTRY_FLAG_NONE,
1671 tm->hw[1]->sw_if_index,
1675 FIB_ROUTE_PATH_FLAG_NONE);
1676 fei = fib_table_entry_path_add(fib_index,
1679 FIB_ENTRY_FLAG_NONE,
1682 tm->hw[0]->sw_if_index,
1686 FIB_ROUTE_PATH_FLAG_NONE);
1688 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.5/32 presnet");
1689 dpo = fib_entry_contribute_ip_forwarding(fei);
1690 lb = load_balance_get(dpo->dpoi_index);
1691 FIB_TEST((lb->lb_n_buckets == 16),
1692 "1.2.3.5/32 LB has %d bucket",
1695 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 0, ai_01);
1696 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 1, ai_01);
1697 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 2, ai_01);
1698 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 3, ai_01);
1699 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 4, ai_01);
1700 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 5, ai_01);
1701 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 6, ai_01);
1702 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 7, ai_01);
1703 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 8, ai_01);
1704 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 9, ai_01);
1705 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 10, ai_01);
1706 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 11, ai_01);
1707 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 12, ai_01);
1708 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 13, ai_12_12_12_12);
1709 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 14, ai_12_12_12_12);
1710 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 15, ai_12_12_12_12);
1712 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1713 tm->hw[0]->sw_if_index,
1714 tm->hw[1]->sw_if_index),
1715 "RPF list for 1.2.3.4/32 contains both adjs");
1718 * Test UCMP with a large weight skew - this produces load-balance objects with large
1719 * numbers of buckets to accommodate the skew. By updating said load-balances we are
1720 * laso testing the LB in placce modify code when number of buckets is large.
1722 fib_prefix_t pfx_6_6_6_6_s_32 = {
1724 .fp_proto = FIB_PROTOCOL_IP4,
1727 .ip4.as_u32 = clib_host_to_net_u32(0x06060606),
1730 fib_test_lb_bucket_t ip_o_10_10_10_1 = {
1736 fib_test_lb_bucket_t ip_o_10_10_10_2 = {
1742 fib_test_lb_bucket_t ip_6_6_6_6_o_12_12_12_12 = {
1745 .adj = ai_12_12_12_12,
1748 fib_table_entry_update_one_path(fib_index,
1751 FIB_ENTRY_FLAG_NONE,
1754 tm->hw[0]->sw_if_index,
1755 ~0, // invalid fib index
1758 FIB_ROUTE_PATH_FLAG_NONE);
1760 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1761 FIB_TEST(!fib_test_validate_entry(fei,
1762 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1765 "6.6.6.6/32 via 10.10.10.1");
1767 fib_table_entry_path_add(fib_index,
1770 FIB_ENTRY_FLAG_NONE,
1773 tm->hw[0]->sw_if_index,
1774 ~0, // invalid fib index
1777 FIB_ROUTE_PATH_FLAG_NONE);
1779 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1780 FIB_TEST(!fib_test_validate_entry(fei,
1781 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1847 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1849 fib_table_entry_path_add(fib_index,
1852 FIB_ENTRY_FLAG_NONE,
1855 tm->hw[1]->sw_if_index,
1856 ~0, // invalid fib index
1859 FIB_ROUTE_PATH_FLAG_NONE);
1861 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1862 FIB_TEST(!fib_test_validate_entry(fei,
1863 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1930 &ip_6_6_6_6_o_12_12_12_12,
1931 &ip_6_6_6_6_o_12_12_12_12,
1932 &ip_6_6_6_6_o_12_12_12_12,
1933 &ip_6_6_6_6_o_12_12_12_12,
1934 &ip_6_6_6_6_o_12_12_12_12,
1935 &ip_6_6_6_6_o_12_12_12_12,
1936 &ip_6_6_6_6_o_12_12_12_12,
1937 &ip_6_6_6_6_o_12_12_12_12,
1938 &ip_6_6_6_6_o_12_12_12_12,
1939 &ip_6_6_6_6_o_12_12_12_12,
1940 &ip_6_6_6_6_o_12_12_12_12,
1941 &ip_6_6_6_6_o_12_12_12_12,
1942 &ip_6_6_6_6_o_12_12_12_12,
1943 &ip_6_6_6_6_o_12_12_12_12,
1944 &ip_6_6_6_6_o_12_12_12_12,
1945 &ip_6_6_6_6_o_12_12_12_12,
1946 &ip_6_6_6_6_o_12_12_12_12,
1947 &ip_6_6_6_6_o_12_12_12_12,
1948 &ip_6_6_6_6_o_12_12_12_12,
1949 &ip_6_6_6_6_o_12_12_12_12,
1950 &ip_6_6_6_6_o_12_12_12_12,
1951 &ip_6_6_6_6_o_12_12_12_12,
1952 &ip_6_6_6_6_o_12_12_12_12,
1953 &ip_6_6_6_6_o_12_12_12_12,
1954 &ip_6_6_6_6_o_12_12_12_12,
1955 &ip_6_6_6_6_o_12_12_12_12,
1956 &ip_6_6_6_6_o_12_12_12_12,
1957 &ip_6_6_6_6_o_12_12_12_12,
1958 &ip_6_6_6_6_o_12_12_12_12,
1959 &ip_6_6_6_6_o_12_12_12_12,
1960 &ip_6_6_6_6_o_12_12_12_12,
1961 &ip_6_6_6_6_o_12_12_12_12,
1962 &ip_6_6_6_6_o_12_12_12_12,
1963 &ip_6_6_6_6_o_12_12_12_12,
1964 &ip_6_6_6_6_o_12_12_12_12,
1965 &ip_6_6_6_6_o_12_12_12_12,
1966 &ip_6_6_6_6_o_12_12_12_12,
1967 &ip_6_6_6_6_o_12_12_12_12,
1968 &ip_6_6_6_6_o_12_12_12_12,
1969 &ip_6_6_6_6_o_12_12_12_12,
1970 &ip_6_6_6_6_o_12_12_12_12,
1971 &ip_6_6_6_6_o_12_12_12_12,
1972 &ip_6_6_6_6_o_12_12_12_12,
1973 &ip_6_6_6_6_o_12_12_12_12,
1974 &ip_6_6_6_6_o_12_12_12_12,
1975 &ip_6_6_6_6_o_12_12_12_12,
1976 &ip_6_6_6_6_o_12_12_12_12,
1977 &ip_6_6_6_6_o_12_12_12_12,
1978 &ip_6_6_6_6_o_12_12_12_12,
1979 &ip_6_6_6_6_o_12_12_12_12,
1980 &ip_6_6_6_6_o_12_12_12_12,
1981 &ip_6_6_6_6_o_12_12_12_12,
1982 &ip_6_6_6_6_o_12_12_12_12,
1983 &ip_6_6_6_6_o_12_12_12_12,
1984 &ip_6_6_6_6_o_12_12_12_12,
1985 &ip_6_6_6_6_o_12_12_12_12,
1986 &ip_6_6_6_6_o_12_12_12_12,
1987 &ip_6_6_6_6_o_12_12_12_12,
1988 &ip_6_6_6_6_o_12_12_12_12,
1989 &ip_6_6_6_6_o_12_12_12_12,
1990 &ip_6_6_6_6_o_12_12_12_12,
1991 &ip_6_6_6_6_o_12_12_12_12,
1992 &ip_6_6_6_6_o_12_12_12_12),
1993 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1995 fib_table_entry_path_remove(fib_index,
2000 tm->hw[1]->sw_if_index,
2001 ~0, // invalid fib index
2003 FIB_ROUTE_PATH_FLAG_NONE);
2005 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
2006 FIB_TEST(!fib_test_validate_entry(fei,
2007 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2073 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
2075 fib_table_entry_path_remove(fib_index,
2080 tm->hw[0]->sw_if_index,
2081 ~0, // invalid fib index
2083 FIB_ROUTE_PATH_FLAG_NONE);
2085 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
2086 FIB_TEST(!fib_test_validate_entry(fei,
2087 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2090 "6.6.6.6/32 via 10.10.10.1");
2092 fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API);
2095 * A recursive via the two unequal cost entries
2097 fib_prefix_t bgp_44_s_32 = {
2099 .fp_proto = FIB_PROTOCOL_IP4,
2101 /* 200.200.200.201/32 */
2102 .ip4.as_u32 = clib_host_to_net_u32(0x44444444),
2105 fei = fib_table_entry_path_add(fib_index,
2108 FIB_ENTRY_FLAG_NONE,
2110 &pfx_1_2_3_4_s_32.fp_addr,
2115 FIB_ROUTE_PATH_FLAG_NONE);
2116 fei = fib_table_entry_path_add(fib_index,
2119 FIB_ENTRY_FLAG_NONE,
2121 &pfx_1_2_3_5_s_32.fp_addr,
2126 FIB_ROUTE_PATH_FLAG_NONE);
2128 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_4_s_32, 0);
2129 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_5_s_32, 1);
2130 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
2131 tm->hw[0]->sw_if_index,
2132 tm->hw[1]->sw_if_index),
2133 "RPF list for 1.2.3.4/32 contains both adjs");
2136 * test the uRPF check functions
2138 dpo_id_t dpo_44 = DPO_INVALID;
2141 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
2142 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
2144 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
2145 "uRPF check for 68.68.68.68/32 on %d OK",
2146 tm->hw[0]->sw_if_index);
2147 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
2148 "uRPF check for 68.68.68.68/32 on %d OK",
2149 tm->hw[1]->sw_if_index);
2150 FIB_TEST(!fib_urpf_check(urpfi, 99),
2151 "uRPF check for 68.68.68.68/32 on 99 not-OK",
2155 fib_table_entry_delete(fib_index,
2158 fib_table_entry_delete(fib_index,
2161 fib_table_entry_delete(fib_index,
2166 * Add a recursive route:
2167 * 200.200.200.201/32 via 1.1.1.200/32 => the via entry is NOT installed.
2169 fib_prefix_t bgp_201_pfx = {
2171 .fp_proto = FIB_PROTOCOL_IP4,
2173 /* 200.200.200.201/32 */
2174 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c9),
2178 fib_prefix_t pfx_1_1_1_200_s_32 = {
2180 .fp_proto = FIB_PROTOCOL_IP4,
2182 .ip4.as_u32 = clib_host_to_net_u32(0x010101c8),
2186 fei = fib_table_entry_path_add(fib_index,
2189 FIB_ENTRY_FLAG_NONE,
2191 &pfx_1_1_1_200_s_32.fp_addr,
2192 ~0, // no index provided.
2193 fib_index, // nexthop in same fib as route
2196 FIB_ROUTE_PATH_FLAG_NONE);
2198 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2199 "Recursive via unresolved is drop");
2201 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2202 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
2203 "Flags set on RR via non-attached");
2204 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
2205 "RPF list for BGP route empty");
2208 * +2 entry (BGP & RR) and +1 shared-path-list
2210 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2211 fib_path_list_db_size());
2212 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2213 fib_path_list_pool_size());
2214 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2215 fib_entry_pool_size());
2218 * insert a route that covers the missing 1.1.1.2/32. we epxect
2219 * 200.200.200.200/32 and 200.200.200.201/32 to resolve through it.
2221 fib_prefix_t pfx_1_1_1_0_s_24 = {
2223 .fp_proto = FIB_PROTOCOL_IP4,
2226 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2230 fib_table_entry_path_add(fib_index,
2233 FIB_ENTRY_FLAG_NONE,
2236 tm->hw[0]->sw_if_index,
2237 ~0, // invalid fib index
2240 FIB_ROUTE_PATH_FLAG_NONE);
2241 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24);
2242 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2243 ai = fib_entry_get_adj(fei);
2244 FIB_TEST((ai_01 == ai), "1.1.1.0/24 resolves via 10.10.10.1");
2245 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2246 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2247 ai = fib_entry_get_adj(fei);
2248 FIB_TEST((ai_01 == ai), "1.1.1.2/32 resolves via 10.10.10.1");
2249 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2250 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2251 ai = fib_entry_get_adj(fei);
2252 FIB_TEST((ai_01 == ai), "1.1.1.200/24 resolves via 10.10.10.1");
2255 * +1 entry. 1.1.1.1/32 already uses 10.10.10.1 so no new pah-list
2257 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2258 fib_path_list_db_size());
2259 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2260 fib_path_list_pool_size());
2261 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
2262 fib_entry_pool_size());
2265 * the recursive adj for 200.200.200.200 should be updated.
2267 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2268 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2269 fei = fib_table_lookup(fib_index, &bgp_200_pfx);
2270 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
2271 tm->hw[0]->sw_if_index),
2272 "RPF list for BGP route has itf index 0");
2275 * insert a more specific route than 1.1.1.0/24 that also covers the
2276 * missing 1.1.1.2/32, but not 1.1.1.200/32. we expect
2277 * 200.200.200.200 to resolve through it.
2279 fib_prefix_t pfx_1_1_1_0_s_28 = {
2281 .fp_proto = FIB_PROTOCOL_IP4,
2284 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2288 fib_table_entry_path_add(fib_index,
2291 FIB_ENTRY_FLAG_NONE,
2294 tm->hw[0]->sw_if_index,
2295 ~0, // invalid fib index
2298 FIB_ROUTE_PATH_FLAG_NONE);
2299 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28);
2300 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2301 ai = fib_entry_get_adj(fei);
2302 FIB_TEST((ai_02 == ai), "1.1.1.0/24 resolves via 10.10.10.2");
2305 * +1 entry. +1 shared path-list
2307 FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d",
2308 fib_path_list_db_size());
2309 FIB_TEST((PNBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
2310 fib_path_list_pool_size());
2311 FIB_TEST((ENBR+14 == fib_entry_pool_size()), "entry pool size is %d",
2312 fib_entry_pool_size());
2315 * the recursive adj for 200.200.200.200 should be updated.
2316 * 200.200.200.201 remains unchanged.
2318 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2319 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2322 * remove this /28. 200.200.200.200/32 should revert back to via 1.1.1.0/24
2324 fib_table_entry_path_remove(fib_index,
2329 tm->hw[0]->sw_if_index,
2332 FIB_ROUTE_PATH_FLAG_NONE);
2333 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28) ==
2334 FIB_NODE_INDEX_INVALID),
2335 "1.1.1.0/28 removed");
2336 FIB_TEST((fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28) ==
2337 fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24)),
2338 "1.1.1.0/28 lookup via /24");
2339 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2340 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2343 * -1 entry. -1 shared path-list
2345 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2346 fib_path_list_db_size());
2347 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2348 fib_path_list_pool_size());
2349 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
2350 fib_entry_pool_size());
2353 * remove 1.1.1.0/24. 200.200.200.200/32 should revert back to via 0.0.0.0/0
2355 fib_table_entry_path_remove(fib_index,
2360 tm->hw[0]->sw_if_index,
2363 FIB_ROUTE_PATH_FLAG_NONE);
2364 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_24) ==
2365 FIB_NODE_INDEX_INVALID),
2366 "1.1.1.0/24 removed");
2368 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2369 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2370 "1.1.1.2/32 route is DROP");
2371 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2372 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2373 "1.1.1.200/32 route is DROP");
2375 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2376 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2378 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2379 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2385 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2386 fib_path_list_db_size());
2387 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2388 fib_path_list_pool_size());
2389 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2390 fib_entry_pool_size());
2393 * insert the missing 1.1.1.2/32
2395 fei = fib_table_entry_path_add(fib_index,
2398 FIB_ENTRY_FLAG_NONE,
2401 tm->hw[0]->sw_if_index,
2402 ~0, // invalid fib index
2405 FIB_ROUTE_PATH_FLAG_NONE);
2406 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2407 ai = fib_entry_get_adj(fei);
2408 FIB_TEST((ai = ai_01), "1.1.1.2/32 resolves via 10.10.10.1");
2410 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2411 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2413 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2416 * no change. 1.1.1.2/32 was already there RR sourced.
2418 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2419 fib_path_list_db_size());
2420 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2421 fib_path_list_pool_size());
2422 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2423 fib_entry_pool_size());
2426 * give 201 a resolved path.
2427 * it now has the unresolved 1.1.1.200 and the resolved 1.1.1.2,
2428 * only the latter contributes forwarding.
2430 fei = fib_table_entry_path_add(fib_index,
2433 FIB_ENTRY_FLAG_NONE,
2435 &pfx_1_1_1_2_s_32.fp_addr,
2440 FIB_ROUTE_PATH_FLAG_NONE);
2441 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_2_s_32, 0);
2442 fib_table_entry_path_remove(fib_index,
2446 &pfx_1_1_1_2_s_32.fp_addr,
2450 FIB_ROUTE_PATH_FLAG_NONE);
2453 * remove 200.200.200.201/32 which does not have a valid via FIB
2455 fib_table_entry_path_remove(fib_index,
2459 &pfx_1_1_1_200_s_32.fp_addr,
2460 ~0, // no index provided.
2463 FIB_ROUTE_PATH_FLAG_NONE);
2466 * -2 entries (BGP and RR). -1 shared path-list;
2468 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2469 FIB_NODE_INDEX_INVALID),
2470 "200.200.200.201/32 removed");
2471 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32) ==
2472 FIB_NODE_INDEX_INVALID),
2473 "1.1.1.200/32 removed");
2475 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2476 fib_path_list_db_size());
2477 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
2478 fib_path_list_pool_size());
2479 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2480 fib_entry_pool_size());
2483 * remove 200.200.200.200/32 which does have a valid via FIB
2485 fib_table_entry_path_remove(fib_index,
2489 &pfx_1_1_1_2_s_32.fp_addr,
2490 ~0, // no index provided.
2493 FIB_ROUTE_PATH_FLAG_NONE);
2495 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2496 FIB_NODE_INDEX_INVALID),
2497 "200.200.200.200/32 removed");
2498 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32) !=
2499 FIB_NODE_INDEX_INVALID),
2500 "1.1.1.2/32 still present");
2503 * -1 entry (BGP, the RR source is also API sourced). -1 shared path-list;
2505 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2506 fib_path_list_db_size());
2507 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2508 fib_path_list_pool_size());
2509 FIB_TEST((ENBR+9 == fib_entry_pool_size()), "entry pool size is %d",
2510 fib_entry_pool_size());
2513 * A recursive prefix that has a 2 path load-balance.
2514 * It also shares a next-hop with other BGP prefixes and hence
2515 * test the ref counting of RR sourced prefixes and 2 level LB.
2517 const fib_prefix_t bgp_102 = {
2519 .fp_proto = FIB_PROTOCOL_IP4,
2521 /* 100.100.100.101/32 */
2522 .ip4.as_u32 = clib_host_to_net_u32(0x64646466),
2525 fib_table_entry_path_add(fib_index,
2528 FIB_ENTRY_FLAG_NONE,
2530 &pfx_1_1_1_1_s_32.fp_addr,
2531 ~0, // no index provided.
2532 fib_index, // same as route
2535 FIB_ROUTE_PATH_FLAG_NONE);
2536 fib_table_entry_path_add(fib_index,
2539 FIB_ENTRY_FLAG_NONE,
2541 &pfx_1_1_1_2_s_32.fp_addr,
2542 ~0, // no index provided.
2543 fib_index, // same as route's FIB
2546 FIB_ROUTE_PATH_FLAG_NONE);
2547 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2548 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "100.100.100.102/32 presnet");
2549 dpo = fib_entry_contribute_ip_forwarding(fei);
2551 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2552 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2553 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32);
2554 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2556 lb = load_balance_get(dpo->dpoi_index);
2557 FIB_TEST((lb->lb_n_buckets == 2), "Recursive LB has %d bucket", lb->lb_n_buckets);
2558 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2559 "First via 10.10.10.1");
2560 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 1)),
2561 "Second via 10.10.10.1");
2563 fib_table_entry_path_remove(fib_index,
2567 &pfx_1_1_1_1_s_32.fp_addr,
2568 ~0, // no index provided.
2569 fib_index, // same as route's FIB
2571 FIB_ROUTE_PATH_FLAG_NONE);
2572 fib_table_entry_path_remove(fib_index,
2576 &pfx_1_1_1_2_s_32.fp_addr,
2577 ~0, // no index provided.
2578 fib_index, // same as route's FIB
2580 FIB_ROUTE_PATH_FLAG_NONE);
2581 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2582 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "100.100.100.102/32 removed");
2585 * remove the remaining recursives
2587 fib_table_entry_path_remove(fib_index,
2591 &pfx_1_1_1_1_s_32.fp_addr,
2592 ~0, // no index provided.
2593 fib_index, // same as route's FIB
2595 FIB_ROUTE_PATH_FLAG_NONE);
2596 fib_table_entry_path_remove(fib_index,
2600 &pfx_1_1_1_1_s_32.fp_addr,
2601 ~0, // no index provided.
2602 fib_index, // same as route's FIB
2604 FIB_ROUTE_PATH_FLAG_NONE);
2605 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_100_pfx) ==
2606 FIB_NODE_INDEX_INVALID),
2607 "100.100.100.100/32 removed");
2608 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_101_pfx) ==
2609 FIB_NODE_INDEX_INVALID),
2610 "100.100.100.101/32 removed");
2613 * -2 entry (2*BGP, the RR source is also API sourced). -1 shared path-list;
2615 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2616 fib_path_list_db_size());
2617 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2618 fib_path_list_pool_size());
2619 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2620 fib_entry_pool_size());
2623 * Add a recursive route via a connected cover, using an adj-fib that does exist
2625 fib_table_entry_path_add(fib_index,
2628 FIB_ENTRY_FLAG_NONE,
2631 ~0, // no index provided.
2632 fib_index, // Same as route's FIB
2635 FIB_ROUTE_PATH_FLAG_NONE);
2638 * +1 entry. +1 shared path-list (recursive via 10.10.10.1)
2640 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2641 fib_path_list_db_size());
2642 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2643 fib_path_list_pool_size());
2644 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
2645 fib_entry_pool_size());
2647 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2648 dpo = fib_entry_contribute_ip_forwarding(fei);
2650 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
2651 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2653 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2654 "200.200.200.200/32 is recursive via adj for 10.10.10.1");
2656 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
2657 "Flags set on RR via existing attached");
2660 * Add a recursive route via a connected cover, using and adj-fib that does
2663 ip46_address_t nh_10_10_10_3 = {
2664 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
2666 fib_prefix_t pfx_10_10_10_3 = {
2668 .fp_proto = FIB_PROTOCOL_IP4,
2669 .fp_addr = nh_10_10_10_3,
2672 fib_table_entry_path_add(fib_index,
2675 FIB_ENTRY_FLAG_NONE,
2678 ~0, // no index provided.
2682 FIB_ROUTE_PATH_FLAG_NONE);
2685 * +2 entries (BGP and RR). +1 shared path-list (recursive via 10.10.10.3) and
2686 * one unshared non-recursive via 10.10.10.3
2688 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2689 fib_path_list_db_size());
2690 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2691 fib_path_list_pool_size());
2692 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2693 fib_entry_pool_size());
2695 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
2698 tm->hw[0]->sw_if_index);
2700 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2701 dpo = fib_entry_contribute_ip_forwarding(fei);
2702 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3);
2703 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2705 ai = fib_entry_get_adj(fei);
2706 FIB_TEST((ai == ai_03), "adj for 10.10.10.3/32 is via adj for 10.10.10.3");
2707 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
2708 fib_entry_get_flags(fei)),
2709 "Flags set on RR via non-existing attached");
2711 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2712 "adj for 200.200.200.200/32 is recursive via adj for 10.10.10.3");
2717 * remove the recursives
2719 fib_table_entry_path_remove(fib_index,
2724 ~0, // no index provided.
2725 fib_index, // same as route's FIB
2727 FIB_ROUTE_PATH_FLAG_NONE);
2728 fib_table_entry_path_remove(fib_index,
2733 ~0, // no index provided.
2734 fib_index, // same as route's FIB
2736 FIB_ROUTE_PATH_FLAG_NONE);
2738 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2739 FIB_NODE_INDEX_INVALID),
2740 "200.200.200.201/32 removed");
2741 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2742 FIB_NODE_INDEX_INVALID),
2743 "200.200.200.200/32 removed");
2744 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3) ==
2745 FIB_NODE_INDEX_INVALID),
2746 "10.10.10.3/32 removed");
2749 * -3 entries (2*BGP and RR). -2 shared path-list (recursive via 10.10.10.3 &
2750 * 10.10.10.1) and one unshared non-recursive via 10.10.10.3
2752 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2753 fib_path_list_db_size());
2754 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2755 fib_path_list_pool_size());
2756 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2757 fib_entry_pool_size());
2762 * Add 5.5.5.5/32 -> 5.5.5.6/32 -> 5.5.5.7/32 -> 5.5.5.5/32
2764 fib_prefix_t pfx_5_5_5_5_s_32 = {
2766 .fp_proto = FIB_PROTOCOL_IP4,
2768 .ip4.as_u32 = clib_host_to_net_u32(0x05050505),
2771 fib_prefix_t pfx_5_5_5_6_s_32 = {
2773 .fp_proto = FIB_PROTOCOL_IP4,
2775 .ip4.as_u32 = clib_host_to_net_u32(0x05050506),
2778 fib_prefix_t pfx_5_5_5_7_s_32 = {
2780 .fp_proto = FIB_PROTOCOL_IP4,
2782 .ip4.as_u32 = clib_host_to_net_u32(0x05050507),
2786 fib_table_entry_path_add(fib_index,
2789 FIB_ENTRY_FLAG_NONE,
2791 &pfx_5_5_5_6_s_32.fp_addr,
2792 ~0, // no index provided.
2796 FIB_ROUTE_PATH_FLAG_NONE);
2797 fib_table_entry_path_add(fib_index,
2800 FIB_ENTRY_FLAG_NONE,
2802 &pfx_5_5_5_7_s_32.fp_addr,
2803 ~0, // no index provided.
2807 FIB_ROUTE_PATH_FLAG_NONE);
2808 fib_table_entry_path_add(fib_index,
2811 FIB_ENTRY_FLAG_NONE,
2813 &pfx_5_5_5_5_s_32.fp_addr,
2814 ~0, // no index provided.
2818 FIB_ROUTE_PATH_FLAG_NONE);
2820 * +3 entries, +3 shared path-list
2822 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2823 fib_path_list_db_size());
2824 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2825 fib_path_list_pool_size());
2826 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2827 fib_entry_pool_size());
2830 * All the entries have only looped paths, so they are all drop
2832 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2833 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2834 "LB for 5.5.5.7/32 is via adj for DROP");
2835 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2836 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2837 "LB for 5.5.5.5/32 is via adj for DROP");
2838 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2839 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2840 "LB for 5.5.5.6/32 is via adj for DROP");
2843 * provide 5.5.5.6/32 with alternate path.
2844 * this will allow only 5.5.5.6/32 to forward with this path, the others
2845 * are still drop since the loop is still present.
2847 fib_table_entry_path_add(fib_index,
2850 FIB_ENTRY_FLAG_NONE,
2853 tm->hw[0]->sw_if_index,
2857 FIB_ROUTE_PATH_FLAG_NONE);
2859 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2860 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2862 lb = load_balance_get(dpo1->dpoi_index);
2863 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.6 LB has %d bucket", lb->lb_n_buckets);
2865 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2866 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2867 FIB_TEST((ai_01 == dpo2->dpoi_index),
2868 "5.5.5.6 bucket 0 resolves via 10.10.10.2");
2870 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2871 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2872 "LB for 5.5.5.7/32 is via adj for DROP");
2873 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2874 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2875 "LB for 5.5.5.5/32 is via adj for DROP");
2878 * remove the alternate path for 5.5.5.6/32
2881 fib_table_entry_path_remove(fib_index,
2886 tm->hw[0]->sw_if_index,
2889 FIB_ROUTE_PATH_FLAG_NONE);
2891 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2892 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2893 "LB for 5.5.5.7/32 is via adj for DROP");
2894 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2895 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2896 "LB for 5.5.5.5/32 is via adj for DROP");
2897 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2898 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2899 "LB for 5.5.5.6/32 is via adj for DROP");
2902 * break the loop by giving 5.5.5.5/32 a new set of paths
2903 * expect all to forward via this new path.
2905 fib_table_entry_update_one_path(fib_index,
2908 FIB_ENTRY_FLAG_NONE,
2911 tm->hw[0]->sw_if_index,
2912 ~0, // invalid fib index
2915 FIB_ROUTE_PATH_FLAG_NONE);
2917 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2918 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2919 lb = load_balance_get(dpo1->dpoi_index);
2920 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.5 LB has %d bucket", lb->lb_n_buckets);
2922 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2923 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2924 FIB_TEST((ai_01 == dpo2->dpoi_index),
2925 "5.5.5.5 bucket 0 resolves via 10.10.10.2");
2927 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_7_s_32);
2928 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2930 lb = load_balance_get(dpo2->dpoi_index);
2931 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2932 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo2->dpoi_index, 0)),
2933 "5.5.5.5.7 via 5.5.5.5");
2935 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32);
2936 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2938 lb = load_balance_get(dpo1->dpoi_index);
2939 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2940 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2941 "5.5.5.5.6 via 5.5.5.7");
2944 * revert back to the loop. so we can remove the prefixes with
2947 fib_table_entry_update_one_path(fib_index,
2950 FIB_ENTRY_FLAG_NONE,
2952 &pfx_5_5_5_6_s_32.fp_addr,
2953 ~0, // no index provided.
2957 FIB_ROUTE_PATH_FLAG_NONE);
2959 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2960 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2961 "LB for 5.5.5.7/32 is via adj for DROP");
2962 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2963 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2964 "LB for 5.5.5.5/32 is via adj for DROP");
2965 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2966 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2967 "LB for 5.5.5.6/32 is via adj for DROP");
2970 * remove all the 5.5.5.x/32 prefixes
2972 fib_table_entry_path_remove(fib_index,
2976 &pfx_5_5_5_6_s_32.fp_addr,
2977 ~0, // no index provided.
2978 fib_index, // same as route's FIB
2980 FIB_ROUTE_PATH_FLAG_NONE);
2981 fib_table_entry_path_remove(fib_index,
2985 &pfx_5_5_5_7_s_32.fp_addr,
2986 ~0, // no index provided.
2987 fib_index, // same as route's FIB
2989 FIB_ROUTE_PATH_FLAG_NONE);
2990 fib_table_entry_path_remove(fib_index,
2994 &pfx_5_5_5_5_s_32.fp_addr,
2995 ~0, // no index provided.
2996 fib_index, // same as route's FIB
2998 FIB_ROUTE_PATH_FLAG_NONE);
2999 fib_table_entry_path_remove(fib_index,
3004 ~0, // no index provided.
3005 fib_index, // same as route's FIB
3007 FIB_ROUTE_PATH_FLAG_NONE);
3010 * -3 entries, -3 shared path-list
3012 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3013 fib_path_list_db_size());
3014 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3015 fib_path_list_pool_size());
3016 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3017 fib_entry_pool_size());
3020 * Single level loop 5.5.5.5/32 via 5.5.5.5/32
3022 fib_table_entry_path_add(fib_index,
3025 FIB_ENTRY_FLAG_NONE,
3027 &pfx_5_5_5_6_s_32.fp_addr,
3028 ~0, // no index provided.
3032 FIB_ROUTE_PATH_FLAG_NONE);
3033 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
3034 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
3035 "1-level 5.5.5.6/32 loop is via adj for DROP");
3037 fib_table_entry_path_remove(fib_index,
3041 &pfx_5_5_5_6_s_32.fp_addr,
3042 ~0, // no index provided.
3043 fib_index, // same as route's FIB
3045 FIB_ROUTE_PATH_FLAG_NONE);
3046 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3047 fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32),
3048 "1-level 5.5.5.6/32 loop is removed");
3051 * A recursive route whose next-hop is covered by the prefix.
3052 * This would mean the via-fib, which inherits forwarding from its
3053 * cover, thus picks up forwarding from the prfix, which is via the
3054 * via-fib, and we have a loop.
3056 fib_prefix_t pfx_23_23_23_0_s_24 = {
3058 .fp_proto = FIB_PROTOCOL_IP4,
3060 .ip4.as_u32 = clib_host_to_net_u32(0x17171700),
3063 fib_prefix_t pfx_23_23_23_23_s_32 = {
3065 .fp_proto = FIB_PROTOCOL_IP4,
3067 .ip4.as_u32 = clib_host_to_net_u32(0x17171717),
3070 fei = fib_table_entry_path_add(fib_index,
3071 &pfx_23_23_23_0_s_24,
3073 FIB_ENTRY_FLAG_NONE,
3075 &pfx_23_23_23_23_s_32.fp_addr,
3080 FIB_ROUTE_PATH_FLAG_NONE);
3081 dpo = fib_entry_contribute_ip_forwarding(fei);
3082 FIB_TEST(load_balance_is_drop(dpo),
3083 "23.23.23.0/24 via covered is DROP");
3084 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3087 * add-remove test. no change.
3089 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3090 fib_path_list_db_size());
3091 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3092 fib_path_list_pool_size());
3093 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3094 fib_entry_pool_size());
3097 * Make the default route recursive via a unknown next-hop. Thus the
3098 * next hop's cover would be the default route
3100 fei = fib_table_entry_path_add(fib_index,
3103 FIB_ENTRY_FLAG_NONE,
3105 &pfx_23_23_23_23_s_32.fp_addr,
3110 FIB_ROUTE_PATH_FLAG_NONE);
3111 dpo = fib_entry_contribute_ip_forwarding(fei);
3112 FIB_TEST(load_balance_is_drop(dpo),
3113 "0.0.0.0.0/0 via is DROP");
3114 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3115 "no resolving interface for looped 0.0.0.0/0");
3117 fei = fib_table_lookup_exact_match(fib_index, &pfx_23_23_23_23_s_32);
3118 dpo = fib_entry_contribute_ip_forwarding(fei);
3119 FIB_TEST(load_balance_is_drop(dpo),
3120 "23.23.23.23/32 via is DROP");
3121 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3122 "no resolving interface for looped 23.23.23.23/32");
3124 fib_table_entry_delete(fib_index, &pfx_0_0_0_0_s_0, FIB_SOURCE_API);
3127 * A recursive route with recursion constraints.
3128 * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained
3130 fib_table_entry_path_add(fib_index,
3133 FIB_ENTRY_FLAG_NONE,
3140 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3142 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3143 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3145 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3146 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3148 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3149 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3152 * save the load-balance. we expect it to be inplace modified
3154 lb = load_balance_get(dpo1->dpoi_index);
3157 * add a covering prefix for the via fib that would otherwise serve
3158 * as the resolving route when the host is removed
3160 fib_table_entry_path_add(fib_index,
3163 FIB_ENTRY_FLAG_NONE,
3166 tm->hw[0]->sw_if_index,
3167 ~0, // invalid fib index
3170 FIB_ROUTE_PATH_FLAG_NONE);
3171 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28);
3172 ai = fib_entry_get_adj(fei);
3173 FIB_TEST((ai == ai_01),
3174 "adj for 1.1.1.0/28 is via adj for 1.1.1.1");
3177 * remove the host via FIB - expect the BGP prefix to be drop
3179 fib_table_entry_path_remove(fib_index,
3184 tm->hw[0]->sw_if_index,
3185 ~0, // invalid fib index
3187 FIB_ROUTE_PATH_FLAG_NONE);
3189 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3190 "adj for 200.200.200.200/32 is recursive via adj for DROP");
3193 * add the via-entry host reoute back. expect to resolve again
3195 fib_table_entry_path_add(fib_index,
3198 FIB_ENTRY_FLAG_NONE,
3201 tm->hw[0]->sw_if_index,
3202 ~0, // invalid fib index
3205 FIB_ROUTE_PATH_FLAG_NONE);
3206 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3207 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3210 * add another path for the recursive. it will then have 2.
3212 fib_prefix_t pfx_1_1_1_3_s_32 = {
3214 .fp_proto = FIB_PROTOCOL_IP4,
3216 .ip4.as_u32 = clib_host_to_net_u32(0x01010103),
3219 fib_table_entry_path_add(fib_index,
3222 FIB_ENTRY_FLAG_NONE,
3225 tm->hw[0]->sw_if_index,
3226 ~0, // invalid fib index
3229 FIB_ROUTE_PATH_FLAG_NONE);
3231 fib_table_entry_path_add(fib_index,
3234 FIB_ENTRY_FLAG_NONE,
3236 &pfx_1_1_1_3_s_32.fp_addr,
3241 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3244 * add a bunch load more entries using this path combo so that we get
3245 * an LB-map created.
3248 fib_prefix_t bgp_78s[N_P];
3249 for (ii = 0; ii < N_P; ii++)
3251 bgp_78s[ii].fp_len = 32;
3252 bgp_78s[ii].fp_proto = FIB_PROTOCOL_IP4;
3253 bgp_78s[ii].fp_addr.ip4.as_u32 = clib_host_to_net_u32(0x4e000000+ii);
3256 fib_table_entry_path_add(fib_index,
3259 FIB_ENTRY_FLAG_NONE,
3261 &pfx_1_1_1_3_s_32.fp_addr,
3266 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3267 fib_table_entry_path_add(fib_index,
3270 FIB_ENTRY_FLAG_NONE,
3277 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3280 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3281 dpo = fib_entry_contribute_ip_forwarding(fei);
3283 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3284 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3285 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)),
3286 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3287 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32);
3288 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3289 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)),
3290 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3");
3293 * expect the lb-map used by the recursive's load-balance is using both buckets
3295 load_balance_map_t *lbm;
3298 lb = load_balance_get(dpo->dpoi_index);
3300 load_balance_map_lock(lbmi);
3301 lbm = load_balance_map_get(lbmi);
3303 FIB_TEST(lbm->lbm_buckets[0] == 0,
3304 "LB maps's bucket 0 is %d",
3305 lbm->lbm_buckets[0]);
3306 FIB_TEST(lbm->lbm_buckets[1] == 1,
3307 "LB maps's bucket 1 is %d",
3308 lbm->lbm_buckets[1]);
3311 * withdraw one of the /32 via-entrys.
3312 * that ECMP path will be unresolved and forwarding should continue on the
3313 * other available path. this is an iBGP PIC edge failover.
3314 * Test the forwarding changes without re-fetching the adj from the
3315 * recursive entry. this ensures its the same one that is updated; i.e. an
3318 fib_table_entry_path_remove(fib_index,
3323 tm->hw[0]->sw_if_index,
3324 ~0, // invalid fib index
3326 FIB_ROUTE_PATH_FLAG_NONE);
3328 /* suspend so the update walk kicks int */
3329 vlib_process_suspend(vlib_get_main(), 1e-5);
3331 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3332 FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)),
3333 "post PIC 200.200.200.200/32 was inplace modified");
3335 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)),
3336 "post PIC adj for 200.200.200.200/32 is recursive"
3337 " via adj for 1.1.1.3");
3340 * the LB maps that was locked above should have been modified to remove
3341 * the path that was down, and thus its bucket points to a path that is
3344 FIB_TEST(lbm->lbm_buckets[0] == 1,
3345 "LB maps's bucket 0 is %d",
3346 lbm->lbm_buckets[0]);
3347 FIB_TEST(lbm->lbm_buckets[1] == 1,
3348 "LB maps's bucket 1 is %d",
3349 lbm->lbm_buckets[1]);
3351 load_balance_map_unlock(lbmi);
3354 * add it back. again
3356 fib_table_entry_path_add(fib_index,
3359 FIB_ENTRY_FLAG_NONE,
3362 tm->hw[0]->sw_if_index,
3363 ~0, // invalid fib index
3366 FIB_ROUTE_PATH_FLAG_NONE);
3368 /* suspend so the update walk kicks in */
3369 vlib_process_suspend(vlib_get_main(), 1e-5);
3371 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)),
3372 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3373 "via adj for 1.1.1.1");
3374 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)),
3375 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3376 "via adj for 1.1.1.3");
3378 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3379 dpo = fib_entry_contribute_ip_forwarding(fei);
3380 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3381 "post PIC 200.200.200.200/32 was inplace modified");
3384 * add a 3rd path. this makes the LB 16 buckets.
3386 fib_table_entry_path_add(fib_index,
3389 FIB_ENTRY_FLAG_NONE,
3391 &pfx_1_1_1_2_s_32.fp_addr,
3396 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3397 for (ii = 0; ii < N_P; ii++)
3399 fib_table_entry_path_add(fib_index,
3402 FIB_ENTRY_FLAG_NONE,
3404 &pfx_1_1_1_2_s_32.fp_addr,
3409 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3412 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3413 dpo = fib_entry_contribute_ip_forwarding(fei);
3414 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3415 "200.200.200.200/32 was inplace modified for 3rd path");
3416 FIB_TEST(16 == lb->lb_n_buckets,
3417 "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets");
3420 load_balance_map_lock(lbmi);
3421 lbm = load_balance_map_get(lbmi);
3423 for (ii = 0; ii < 16; ii++)
3425 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3426 "LB Map for 200.200.200.200/32 at %d is %d",
3427 ii, lbm->lbm_buckets[ii]);
3431 * trigger PIC by removing the first via-entry
3432 * the first 6 buckets of the map should map to the next 6
3434 fib_table_entry_path_remove(fib_index,
3439 tm->hw[0]->sw_if_index,
3442 FIB_ROUTE_PATH_FLAG_NONE);
3443 /* suspend so the update walk kicks int */
3444 vlib_process_suspend(vlib_get_main(), 1e-5);
3446 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3447 dpo = fib_entry_contribute_ip_forwarding(fei);
3448 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3449 "200.200.200.200/32 was inplace modified for 3rd path");
3450 FIB_TEST(2 == lb->lb_n_buckets,
3451 "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets");
3453 for (ii = 0; ii < 6; ii++)
3455 FIB_TEST(lbm->lbm_buckets[ii] == ii+6,
3456 "LB Map for 200.200.200.200/32 at %d is %d",
3457 ii, lbm->lbm_buckets[ii]);
3459 for (ii = 6; ii < 16; ii++)
3461 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3462 "LB Map for 200.200.200.200/32 at %d is %d",
3463 ii, lbm->lbm_buckets[ii]);
3465 load_balance_map_unlock(lbmi);
3470 fib_table_entry_path_add(fib_index,
3473 FIB_ENTRY_FLAG_NONE,
3476 tm->hw[0]->sw_if_index,
3480 FIB_ROUTE_PATH_FLAG_NONE);
3482 for (ii = 0; ii < N_P; ii++)
3484 fib_table_entry_delete(fib_index,
3487 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3488 fib_table_lookup_exact_match(fib_index, &bgp_78s[ii])),
3490 format_fib_prefix, &bgp_78s[ii]);
3492 fib_table_entry_path_remove(fib_index,
3496 &pfx_1_1_1_2_s_32.fp_addr,
3500 MPLS_LABEL_INVALID);
3501 fib_table_entry_path_remove(fib_index,
3509 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3510 fib_table_entry_path_remove(fib_index,
3514 &pfx_1_1_1_3_s_32.fp_addr,
3518 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3519 fib_table_entry_delete(fib_index,
3522 fib_table_entry_delete(fib_index,
3525 /* suspend so the update walk kicks int */
3526 vlib_process_suspend(vlib_get_main(), 1e-5);
3527 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3528 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)),
3529 "1.1.1.1/28 removed");
3530 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3531 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)),
3532 "1.1.1.3/32 removed");
3533 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3534 fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)),
3535 "200.200.200.200/32 removed");
3538 * add-remove test. no change.
3540 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3541 fib_path_list_db_size());
3542 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3543 fib_path_list_pool_size());
3544 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3545 fib_entry_pool_size());
3548 * A route whose paths are built up iteratively and then removed
3551 fib_prefix_t pfx_4_4_4_4_s_32 = {
3553 .fp_proto = FIB_PROTOCOL_IP4,
3556 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
3560 fib_table_entry_path_add(fib_index,
3563 FIB_ENTRY_FLAG_NONE,
3566 tm->hw[0]->sw_if_index,
3570 FIB_ROUTE_PATH_FLAG_NONE);
3571 fib_table_entry_path_add(fib_index,
3574 FIB_ENTRY_FLAG_NONE,
3577 tm->hw[0]->sw_if_index,
3581 FIB_ROUTE_PATH_FLAG_NONE);
3582 fib_table_entry_path_add(fib_index,
3585 FIB_ENTRY_FLAG_NONE,
3588 tm->hw[0]->sw_if_index,
3592 FIB_ROUTE_PATH_FLAG_NONE);
3593 FIB_TEST(FIB_NODE_INDEX_INVALID !=
3594 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3595 "4.4.4.4/32 present");
3597 fib_table_entry_delete(fib_index,
3600 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3601 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3602 "4.4.4.4/32 removed");
3605 * add-remove test. no change.
3607 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3608 fib_path_list_db_size());
3609 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3610 fib_path_list_pool_size());
3611 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3612 fib_entry_pool_size());
3615 * A route with multiple paths at once
3617 fib_route_path_t *r_paths = NULL;
3619 for (ii = 0; ii < 4; ii++)
3621 fib_route_path_t r_path = {
3622 .frp_proto = DPO_PROTO_IP4,
3624 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
3626 .frp_sw_if_index = tm->hw[0]->sw_if_index,
3628 .frp_fib_index = ~0,
3630 vec_add1(r_paths, r_path);
3633 fib_table_entry_update(fib_index,
3636 FIB_ENTRY_FLAG_NONE,
3639 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3640 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3641 dpo = fib_entry_contribute_ip_forwarding(fei);
3643 lb = load_balance_get(dpo->dpoi_index);
3644 FIB_TEST((lb->lb_n_buckets == 4), "4.4.4.4/32 lb over %d paths", lb->lb_n_buckets);
3646 fib_table_entry_delete(fib_index,
3649 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3650 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3651 "4.4.4.4/32 removed");
3655 * add-remove test. no change.
3657 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3658 fib_path_list_db_size());
3659 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3660 fib_path_list_pool_size());
3661 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3662 fib_entry_pool_size());
3665 * A route deag route
3667 fib_table_entry_path_add(fib_index,
3670 FIB_ENTRY_FLAG_NONE,
3677 FIB_ROUTE_PATH_FLAG_NONE);
3679 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3680 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3682 dpo = fib_entry_contribute_ip_forwarding(fei);
3683 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3684 lookup_dpo_t *lkd = lookup_dpo_get(dpo->dpoi_index);
3686 FIB_TEST((fib_index == lkd->lkd_fib_index),
3687 "4.4.4.4/32 is deag in %d %U",
3689 format_dpo_id, dpo, 0);
3690 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
3691 "4.4.4.4/32 is source deag in %d %U",
3693 format_dpo_id, dpo, 0);
3695 fib_table_entry_delete(fib_index,
3698 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3699 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3700 "4.4.4.4/32 removed");
3704 * A route deag route in a source lookup table
3706 fib_table_entry_path_add(fib_index,
3709 FIB_ENTRY_FLAG_NONE,
3716 FIB_ROUTE_PATH_SOURCE_LOOKUP);
3718 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3719 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3721 dpo = fib_entry_contribute_ip_forwarding(fei);
3722 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3723 lkd = lookup_dpo_get(dpo->dpoi_index);
3725 FIB_TEST((fib_index == lkd->lkd_fib_index),
3726 "4.4.4.4/32 is deag in %d %U",
3728 format_dpo_id, dpo, 0);
3729 FIB_TEST((LOOKUP_INPUT_SRC_ADDR == lkd->lkd_input),
3730 "4.4.4.4/32 is source deag in %d %U",
3732 format_dpo_id, dpo, 0);
3734 fib_table_entry_delete(fib_index,
3737 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3738 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3739 "4.4.4.4/32 removed");
3743 * add-remove test. no change.
3745 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3746 fib_path_list_db_size());
3747 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3748 fib_path_list_pool_size());
3749 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3750 fib_entry_pool_size());
3754 * add a recursive with duplicate paths. Expect the duplicate to be ignored.
3756 fib_prefix_t pfx_34_1_1_1_s_32 = {
3758 .fp_proto = FIB_PROTOCOL_IP4,
3760 .ip4.as_u32 = clib_host_to_net_u32(0x22010101),
3763 fib_prefix_t pfx_34_34_1_1_s_32 = {
3765 .fp_proto = FIB_PROTOCOL_IP4,
3767 .ip4.as_u32 = clib_host_to_net_u32(0x22220101),
3770 fei = fib_table_entry_path_add(fib_index,
3771 &pfx_34_34_1_1_s_32,
3773 FIB_ENTRY_FLAG_NONE,
3776 tm->hw[0]->sw_if_index,
3780 FIB_ROUTE_PATH_FLAG_NONE);
3781 fei = fib_table_entry_path_add(fib_index,
3784 FIB_ENTRY_FLAG_NONE,
3786 &pfx_34_34_1_1_s_32.fp_addr,
3791 FIB_ROUTE_PATH_FLAG_NONE);
3792 fei = fib_table_entry_path_add(fib_index,
3795 FIB_ENTRY_FLAG_NONE,
3797 &pfx_34_34_1_1_s_32.fp_addr,
3802 FIB_ROUTE_PATH_FLAG_NONE);
3803 FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0);
3804 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3805 fib_table_entry_delete(fib_index,
3806 &pfx_34_34_1_1_s_32,
3811 * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32
3812 * all of which are via 10.10.10.1, Itf1
3814 fib_table_entry_path_remove(fib_index,
3819 tm->hw[0]->sw_if_index,
3822 FIB_ROUTE_PATH_FLAG_NONE);
3823 fib_table_entry_path_remove(fib_index,
3828 tm->hw[0]->sw_if_index,
3831 FIB_ROUTE_PATH_FLAG_NONE);
3832 fib_table_entry_path_remove(fib_index,
3837 tm->hw[0]->sw_if_index,
3840 FIB_ROUTE_PATH_FLAG_NONE);
3842 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3843 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32),
3844 "1.1.1.1/32 removed");
3845 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3846 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32),
3847 "1.1.1.2/32 removed");
3848 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3849 fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24),
3850 "1.1.2.0/24 removed");
3853 * -3 entries and -1 shared path-list
3855 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3856 fib_path_list_db_size());
3857 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3858 fib_path_list_pool_size());
3859 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3860 fib_entry_pool_size());
3863 * An attached-host route. Expect to link to the incomplete adj
3865 fib_prefix_t pfx_4_1_1_1_s_32 = {
3867 .fp_proto = FIB_PROTOCOL_IP4,
3870 .ip4.as_u32 = clib_host_to_net_u32(0x04010101),
3873 fib_table_entry_path_add(fib_index,
3876 FIB_ENTRY_FLAG_NONE,
3879 tm->hw[0]->sw_if_index,
3883 FIB_ROUTE_PATH_FLAG_NONE);
3885 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32);
3886 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present");
3887 ai = fib_entry_get_adj(fei);
3889 ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
3891 &pfx_4_1_1_1_s_32.fp_addr,
3892 tm->hw[0]->sw_if_index);
3893 FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ");
3897 * +1 entry and +1 shared path-list
3899 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3900 fib_path_list_db_size());
3901 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3902 fib_path_list_pool_size());
3903 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
3904 fib_entry_pool_size());
3906 fib_table_entry_delete(fib_index,
3910 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3911 fib_path_list_db_size());
3912 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3913 fib_path_list_pool_size());
3914 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3915 fib_entry_pool_size());
3918 * add a v6 prefix via v4 next-hops
3920 fib_prefix_t pfx_2001_s_64 = {
3922 .fp_proto = FIB_PROTOCOL_IP6,
3924 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
3927 fei = fib_table_entry_path_add(0, //default v6 table
3930 FIB_ENTRY_FLAG_NONE,
3933 tm->hw[0]->sw_if_index,
3937 FIB_ROUTE_PATH_FLAG_NONE);
3939 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
3940 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present");
3941 ai = fib_entry_get_adj(fei);
3943 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
3944 "2001::/64 via ARP-adj");
3945 FIB_TEST((adj->ia_link == VNET_LINK_IP6),
3946 "2001::/64 is link type v6");
3947 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4),
3948 "2001::/64 ADJ-adj is NH proto v4");
3949 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
3952 * add a uRPF exempt prefix:
3954 * - it's forwarding is drop
3955 * - it's uRPF list is not empty
3956 * - the uRPF list for the default route (it's cover) is empty
3958 fei = fib_table_entry_special_add(fib_index,
3960 FIB_SOURCE_URPF_EXEMPT,
3961 FIB_ENTRY_FLAG_DROP);
3962 dpo = fib_entry_contribute_ip_forwarding(fei);
3963 FIB_TEST(load_balance_is_drop(dpo),
3964 "uRPF exempt 4.1.1.1/32 DROP");
3965 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0),
3966 "uRPF list for exempt prefix has itf index 0");
3967 fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0);
3968 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
3969 "uRPF list for 0.0.0.0/0 empty");
3971 fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
3974 * An adj-fib that fails the refinement criteria - no connected cover
3976 fib_prefix_t pfx_12_10_10_2_s_32 = {
3978 .fp_proto = FIB_PROTOCOL_IP4,
3981 .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02),
3985 fib_table_entry_path_add(fib_index,
3986 &pfx_12_10_10_2_s_32,
3988 FIB_ENTRY_FLAG_ATTACHED,
3990 &pfx_12_10_10_2_s_32.fp_addr,
3991 tm->hw[0]->sw_if_index,
3992 ~0, // invalid fib index
3995 FIB_ROUTE_PATH_FLAG_NONE);
3997 fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32);
3998 dpo = fib_entry_contribute_ip_forwarding(fei);
3999 FIB_TEST(dpo_is_drop(dpo),
4000 "no connected cover adj-fib fails refinement: %U",
4001 format_dpo_id, dpo, 0);
4003 fib_table_entry_delete(fib_index,
4004 &pfx_12_10_10_2_s_32,
4008 * An adj-fib that fails the refinement criteria - cover is connected
4009 * but on a different interface
4011 fib_prefix_t pfx_10_10_10_127_s_32 = {
4013 .fp_proto = FIB_PROTOCOL_IP4,
4016 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f),
4020 fib_table_entry_path_add(fib_index,
4021 &pfx_10_10_10_127_s_32,
4023 FIB_ENTRY_FLAG_ATTACHED,
4025 &pfx_10_10_10_127_s_32.fp_addr,
4026 tm->hw[1]->sw_if_index,
4027 ~0, // invalid fib index
4030 FIB_ROUTE_PATH_FLAG_NONE);
4032 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32);
4033 dpo = fib_entry_contribute_ip_forwarding(fei);
4034 FIB_TEST(dpo_is_drop(dpo),
4035 "wrong interface adj-fib fails refinement");
4037 fib_table_entry_delete(fib_index,
4038 &pfx_10_10_10_127_s_32,
4042 * add a second path to an adj-fib
4043 * this is a sumiluation of another ARP entry created
4044 * on an interface on which the connected prefix does not exist.
4045 * The second path fails refinement. Expect to forward through the
4048 fib_prefix_t pfx_10_10_10_3_s_32 = {
4050 .fp_proto = FIB_PROTOCOL_IP4,
4053 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
4057 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
4060 tm->hw[0]->sw_if_index);
4062 fib_test_lb_bucket_t ip_o_10_10_10_3 = {
4068 fei = fib_table_entry_path_add(fib_index,
4069 &pfx_10_10_10_3_s_32,
4071 FIB_ENTRY_FLAG_NONE,
4074 tm->hw[0]->sw_if_index,
4078 FIB_ROUTE_PATH_FLAG_NONE);
4079 fei = fib_table_entry_path_add(fib_index,
4080 &pfx_10_10_10_3_s_32,
4082 FIB_ENTRY_FLAG_NONE,
4085 tm->hw[1]->sw_if_index,
4089 FIB_ROUTE_PATH_FLAG_NONE);
4090 FIB_TEST(!fib_test_validate_entry(fei,
4091 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4094 "10.10.10.3 via 10.10.10.3/Eth0 only");
4097 * remove the path that refines the cover, should go unresolved
4099 fib_table_entry_path_remove(fib_index,
4100 &pfx_10_10_10_3_s_32,
4104 tm->hw[0]->sw_if_index,
4107 FIB_ROUTE_PATH_FLAG_NONE);
4108 dpo = fib_entry_contribute_ip_forwarding(fei);
4109 FIB_TEST(dpo_is_drop(dpo),
4110 "wrong interface adj-fib fails refinement");
4113 * add back the path that refines the cover
4115 fei = fib_table_entry_path_add(fib_index,
4116 &pfx_10_10_10_3_s_32,
4118 FIB_ENTRY_FLAG_NONE,
4121 tm->hw[0]->sw_if_index,
4125 FIB_ROUTE_PATH_FLAG_NONE);
4126 FIB_TEST(!fib_test_validate_entry(fei,
4127 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4130 "10.10.10.3 via 10.10.10.3/Eth0 only");
4133 * remove the path that does not refine the cover
4135 fib_table_entry_path_remove(fib_index,
4136 &pfx_10_10_10_3_s_32,
4140 tm->hw[1]->sw_if_index,
4143 FIB_ROUTE_PATH_FLAG_NONE);
4144 FIB_TEST(!fib_test_validate_entry(fei,
4145 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4148 "10.10.10.3 via 10.10.10.3/Eth0 only");
4151 * remove the path that does refine, it's the last path, so
4152 * the entry should be gone
4154 fib_table_entry_path_remove(fib_index,
4155 &pfx_10_10_10_3_s_32,
4159 tm->hw[0]->sw_if_index,
4162 FIB_ROUTE_PATH_FLAG_NONE);
4163 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
4164 FIB_TEST((fei == FIB_NODE_INDEX_INVALID), "10.10.10.3 gone");
4169 * change the table's flow-hash config - expect the update to propagete to
4170 * the entries' load-balance objects
4172 flow_hash_config_t old_hash_config, new_hash_config;
4174 old_hash_config = fib_table_get_flow_hash_config(fib_index,
4176 new_hash_config = (IP_FLOW_HASH_SRC_ADDR |
4177 IP_FLOW_HASH_DST_ADDR);
4179 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
4180 dpo = fib_entry_contribute_ip_forwarding(fei);
4181 lb = load_balance_get(dpo->dpoi_index);
4182 FIB_TEST((lb->lb_hash_config == old_hash_config),
4183 "Table and LB hash config match: %U",
4184 format_ip_flow_hash_config, lb->lb_hash_config);
4186 fib_table_set_flow_hash_config(fib_index, FIB_PROTOCOL_IP4, new_hash_config);
4188 FIB_TEST((lb->lb_hash_config == new_hash_config),
4189 "Table and LB newhash config match: %U",
4190 format_ip_flow_hash_config, lb->lb_hash_config);
4193 * A route via DVR DPO
4195 fei = fib_table_entry_path_add(fib_index,
4196 &pfx_10_10_10_3_s_32,
4198 FIB_ENTRY_FLAG_NONE,
4201 tm->hw[0]->sw_if_index,
4205 FIB_ROUTE_PATH_DVR);
4206 dpo_id_t dvr_dpo = DPO_INVALID;
4207 dvr_dpo_add_or_lock(tm->hw[0]->sw_if_index, DPO_PROTO_IP4, &dvr_dpo);
4208 fib_test_lb_bucket_t ip_o_l2 = {
4211 .adj = dvr_dpo.dpoi_index,
4215 FIB_TEST(!fib_test_validate_entry(fei,
4216 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4219 "10.10.10.3 via L2 on Eth0");
4220 fib_table_entry_path_remove(fib_index,
4221 &pfx_10_10_10_3_s_32,
4225 tm->hw[0]->sw_if_index,
4228 FIB_ROUTE_PATH_DVR);
4229 dpo_reset(&dvr_dpo);
4232 * add the default route via a next-hop that will form a loop
4234 fib_prefix_t pfx_conn = {
4236 .fp_proto = FIB_PROTOCOL_IP4,
4239 .ip4.as_u32 = clib_host_to_net_u32(0x1e1e1e1e),
4243 dfrt = fib_table_entry_path_add(fib_index,
4246 FIB_ENTRY_FLAG_NONE,
4253 FIB_ROUTE_PATH_FLAG_NONE);
4255 * the default route is a drop, since it's looped
4257 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4258 "Default route is DROP");
4261 * add a connected cover for the next-hop, this breaks the recursion loop
4262 * for the default route
4264 fib_table_entry_path_add(fib_index,
4267 (FIB_ENTRY_FLAG_CONNECTED |
4268 FIB_ENTRY_FLAG_ATTACHED),
4271 tm->hw[0]->sw_if_index,
4275 FIB_ROUTE_PATH_FLAG_NONE);
4276 pfx_conn.fp_len = 32;
4277 fei = fib_table_lookup_exact_match(fib_index, &pfx_conn);
4279 u32 ai_30 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
4282 tm->hw[0]->sw_if_index);
4284 fib_test_lb_bucket_t ip_o_30_30_30_30 = {
4290 FIB_TEST(!fib_test_validate_entry(fei,
4291 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4294 "30.30.30.30 via adj");
4295 FIB_TEST_REC_FORW(&pfx_0_0_0_0_s_0, &pfx_conn, 0);
4297 pfx_conn.fp_len = 24;
4298 fib_table_entry_delete(fib_index,
4301 fib_table_entry_delete(fib_index,
4310 fib_table_entry_delete(fib_index,
4311 &pfx_10_10_10_1_s_32,
4313 fib_table_entry_delete(fib_index,
4314 &pfx_10_10_10_2_s_32,
4316 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4317 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32),
4318 "10.10.10.1/32 adj-fib removed");
4319 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4320 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32),
4321 "10.10.10.2/32 adj-fib removed");
4324 * -2 entries and -2 non-shared path-list
4326 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4327 fib_path_list_db_size());
4328 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
4329 fib_path_list_pool_size());
4330 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
4331 fib_entry_pool_size());
4334 * unlock the adjacencies for which this test provided a rewrite.
4335 * These are the last locks on these adjs. they should thus go away.
4339 adj_unlock(ai_12_12_12_12);
4341 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4346 * remove the interface prefixes
4348 local_pfx.fp_len = 32;
4349 fib_table_entry_special_remove(fib_index, &local_pfx,
4350 FIB_SOURCE_INTERFACE);
4351 fei = fib_table_lookup(fib_index, &local_pfx);
4353 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4354 fib_table_lookup_exact_match(fib_index, &local_pfx),
4355 "10.10.10.10/32 adj-fib removed");
4357 local_pfx.fp_len = 24;
4358 fib_table_entry_delete(fib_index, &local_pfx,
4359 FIB_SOURCE_INTERFACE);
4361 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4362 fib_table_lookup_exact_match(fib_index, &local_pfx),
4363 "10.10.10.10/24 adj-fib removed");
4366 * -2 entries and -2 non-shared path-list
4368 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4369 fib_path_list_db_size());
4370 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
4371 fib_path_list_pool_size());
4372 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
4373 fib_entry_pool_size());
4376 * Last but not least, remove the VRF
4378 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4381 "NO API Source'd prefixes");
4382 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4385 "NO RR Source'd prefixes");
4386 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4388 FIB_SOURCE_INTERFACE)),
4389 "NO INterface Source'd prefixes");
4391 for (ii = 0; ii < 4; ii++)
4392 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[ii]->sw_if_index, 0);
4394 fib_table_unlock(fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
4396 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4397 fib_path_list_db_size());
4398 FIB_TEST((PNBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
4399 fib_path_list_pool_size());
4400 FIB_TEST((ENBR-5 == fib_entry_pool_size()), "entry pool size is %d",
4401 fib_entry_pool_size());
4402 FIB_TEST((ENBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
4403 pool_elts(fib_urpf_list_pool));
4404 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
4405 pool_elts(load_balance_map_pool));
4406 FIB_TEST((lb_count == pool_elts(load_balance_pool)), "LB pool size is %d",
4407 pool_elts(load_balance_pool));
4408 FIB_TEST((0 == pool_elts(dvr_dpo_pool)), "L2 DPO pool size is %d",
4409 pool_elts(dvr_dpo_pool));
4418 * In the default table check for the presence and correct forwarding
4419 * of the special entries
4421 fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02;
4422 const dpo_id_t *dpo, *dpo_drop;
4423 const ip_adjacency_t *adj;
4424 const receive_dpo_t *rd;
4430 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4433 /* via 2001:0:0:1::2 */
4434 ip46_address_t nh_2001_2 = {
4437 [0] = clib_host_to_net_u64(0x2001000000000001),
4438 [1] = clib_host_to_net_u64(0x0000000000000002),
4445 dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
4447 /* Find or create FIB table 11 */
4448 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11,
4451 for (ii = 0; ii < 4; ii++)
4452 fib_table_bind (FIB_PROTOCOL_IP6, tm->hw[ii]->sw_if_index, fib_index);
4454 fib_prefix_t pfx_0_0 = {
4456 .fp_proto = FIB_PROTOCOL_IP6,
4464 dfrt = fib_table_lookup(fib_index, &pfx_0_0);
4465 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
4466 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4467 "Default route is DROP");
4469 dpo = fib_entry_contribute_ip_forwarding(dfrt);
4470 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4472 &pfx_0_0.fp_addr.ip6)),
4473 "default-route; fwd and non-fwd tables match");
4475 // FIXME - check specials.
4478 * At this stage there is one v4 FIB with 5 routes and two v6 FIBs
4479 * each with 2 entries and a v6 mfib with 4 path-lists and v4 mfib with 2.
4480 * All entries are special so no path-list sharing.
4483 u32 PNPS = (5+4+4+2);
4485 * if the IGMP plugin is loaded this adds two more entries to the v4 MFIB
4487 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
4488 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is %d",
4489 fib_path_list_pool_size());
4490 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
4491 fib_entry_pool_size());
4494 * add interface routes.
4495 * validate presence of /64 attached and /128 recieve.
4496 * test for the presence of the receive address in the glean and local adj
4498 * receive on 2001:0:0:1::1/128
4500 fib_prefix_t local_pfx = {
4502 .fp_proto = FIB_PROTOCOL_IP6,
4506 [0] = clib_host_to_net_u64(0x2001000000000001),
4507 [1] = clib_host_to_net_u64(0x0000000000000001),
4513 fib_table_entry_update_one_path(fib_index, &local_pfx,
4514 FIB_SOURCE_INTERFACE,
4515 (FIB_ENTRY_FLAG_CONNECTED |
4516 FIB_ENTRY_FLAG_ATTACHED),
4519 tm->hw[0]->sw_if_index,
4523 FIB_ROUTE_PATH_FLAG_NONE);
4524 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4526 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4528 ai = fib_entry_get_adj(fei);
4529 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
4531 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4532 "attached interface adj is glean");
4533 dpo = fib_entry_contribute_ip_forwarding(fei);
4534 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4536 &local_pfx.fp_addr.ip6)),
4537 "attached-route; fwd and non-fwd tables match");
4539 local_pfx.fp_len = 128;
4540 fib_table_entry_update_one_path(fib_index, &local_pfx,
4541 FIB_SOURCE_INTERFACE,
4542 (FIB_ENTRY_FLAG_CONNECTED |
4543 FIB_ENTRY_FLAG_LOCAL),
4546 tm->hw[0]->sw_if_index,
4547 ~0, // invalid fib index
4550 FIB_ROUTE_PATH_FLAG_NONE);
4551 fei = fib_table_lookup(fib_index, &local_pfx);
4553 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4555 dpo = fib_entry_contribute_ip_forwarding(fei);
4556 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4557 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4558 "local interface adj is local");
4559 rd = receive_dpo_get(dpo->dpoi_index);
4561 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4563 "local interface adj is receive ok");
4565 dpo = fib_entry_contribute_ip_forwarding(fei);
4566 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4568 &local_pfx.fp_addr.ip6)),
4569 "local-route; fwd and non-fwd tables match");
4570 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4571 &adj->sub_type.glean.rx_pfx.fp_addr)),
4572 "attached interface adj is receive ok");
4575 * +2 entries. +2 unshared path-lists
4577 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
4578 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
4579 fib_path_list_pool_size());
4580 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4581 fib_entry_pool_size());
4584 * Modify the default route to be via an adj not yet known.
4585 * this sources the defalut route with the API source, which is
4586 * a higher preference to the DEFAULT_ROUTE source
4588 fib_table_entry_path_add(fib_index, &pfx_0_0,
4590 FIB_ENTRY_FLAG_NONE,
4593 tm->hw[0]->sw_if_index,
4597 FIB_ROUTE_PATH_FLAG_NONE);
4598 fei = fib_table_lookup(fib_index, &pfx_0_0);
4600 FIB_TEST((fei == dfrt), "default route same index");
4601 ai = fib_entry_get_adj(fei);
4602 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
4604 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4605 "adj is incomplete");
4606 FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)),
4607 "adj nbr next-hop ok");
4610 * find the adj in the shared db
4612 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4615 tm->hw[0]->sw_if_index);
4616 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
4617 adj_unlock(locked_ai);
4620 * no more entries. +1 shared path-list
4622 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4623 fib_path_list_db_size());
4624 FIB_TEST((PNPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
4625 fib_path_list_pool_size());
4626 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4627 fib_entry_pool_size());
4630 * remove the API source from the default route. We expected
4631 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
4633 fib_table_entry_path_remove(fib_index, &pfx_0_0,
4637 tm->hw[0]->sw_if_index,
4640 FIB_ROUTE_PATH_FLAG_NONE);
4641 fei = fib_table_lookup(fib_index, &pfx_0_0);
4643 FIB_TEST((fei == dfrt), "default route same index");
4644 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4645 "Default route is DROP");
4648 * no more entries. -1 shared path-list
4650 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4651 fib_path_list_db_size());
4652 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
4653 fib_path_list_pool_size());
4654 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4655 fib_entry_pool_size());
4658 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4660 fib_prefix_t pfx_2001_1_2_s_128 = {
4662 .fp_proto = FIB_PROTOCOL_IP6,
4666 [0] = clib_host_to_net_u64(0x2001000000000001),
4667 [1] = clib_host_to_net_u64(0x0000000000000002),
4672 fib_prefix_t pfx_2001_1_3_s_128 = {
4674 .fp_proto = FIB_PROTOCOL_IP6,
4678 [0] = clib_host_to_net_u64(0x2001000000000001),
4679 [1] = clib_host_to_net_u64(0x0000000000000003),
4685 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
4688 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4690 &pfx_2001_1_2_s_128.fp_addr,
4691 tm->hw[0]->sw_if_index);
4692 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
4693 adj = adj_get(ai_01);
4694 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4695 "adj is incomplete");
4696 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4697 &adj->sub_type.nbr.next_hop)),
4698 "adj nbr next-hop ok");
4700 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4701 fib_test_build_rewrite(eth_addr));
4702 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4704 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4705 &adj->sub_type.nbr.next_hop)),
4706 "adj nbr next-hop ok");
4708 fib_table_entry_path_add(fib_index,
4709 &pfx_2001_1_2_s_128,
4711 FIB_ENTRY_FLAG_ATTACHED,
4713 &pfx_2001_1_2_s_128.fp_addr,
4714 tm->hw[0]->sw_if_index,
4718 FIB_ROUTE_PATH_FLAG_NONE);
4720 fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
4721 ai = fib_entry_get_adj(fei);
4722 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4726 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4728 &pfx_2001_1_3_s_128.fp_addr,
4729 tm->hw[0]->sw_if_index);
4730 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
4731 adj = adj_get(ai_02);
4732 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4733 "adj is incomplete");
4734 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4735 &adj->sub_type.nbr.next_hop)),
4736 "adj nbr next-hop ok");
4738 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4739 fib_test_build_rewrite(eth_addr));
4740 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4742 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4743 &adj->sub_type.nbr.next_hop)),
4744 "adj nbr next-hop ok");
4745 FIB_TEST((ai_01 != ai_02), "ADJs are different");
4747 fib_table_entry_path_add(fib_index,
4748 &pfx_2001_1_3_s_128,
4750 FIB_ENTRY_FLAG_ATTACHED,
4752 &pfx_2001_1_3_s_128.fp_addr,
4753 tm->hw[0]->sw_if_index,
4757 FIB_ROUTE_PATH_FLAG_NONE);
4759 fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
4760 ai = fib_entry_get_adj(fei);
4761 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4764 * +2 entries, +2 unshread path-lists.
4766 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4767 fib_path_list_db_size());
4768 FIB_TEST((PNPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
4769 fib_path_list_pool_size());
4770 FIB_TEST((ENPS+4 == fib_entry_pool_size()), "entry pool size is %d",
4771 fib_entry_pool_size());
4774 * Add a 2 routes via the first ADJ. ensure path-list sharing
4776 fib_prefix_t pfx_2001_a_s_64 = {
4778 .fp_proto = FIB_PROTOCOL_IP6,
4782 [0] = clib_host_to_net_u64(0x200100000000000a),
4783 [1] = clib_host_to_net_u64(0x0000000000000000),
4788 fib_prefix_t pfx_2001_b_s_64 = {
4790 .fp_proto = FIB_PROTOCOL_IP6,
4794 [0] = clib_host_to_net_u64(0x200100000000000b),
4795 [1] = clib_host_to_net_u64(0x0000000000000000),
4801 fib_table_entry_path_add(fib_index,
4804 FIB_ENTRY_FLAG_NONE,
4807 tm->hw[0]->sw_if_index,
4811 FIB_ROUTE_PATH_FLAG_NONE);
4812 fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64);
4813 ai = fib_entry_get_adj(fei);
4814 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4815 fib_table_entry_path_add(fib_index,
4818 FIB_ENTRY_FLAG_NONE,
4821 tm->hw[0]->sw_if_index,
4825 FIB_ROUTE_PATH_FLAG_NONE);
4826 fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64);
4827 ai = fib_entry_get_adj(fei);
4828 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4831 * +2 entries, +1 shared path-list.
4833 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4834 fib_path_list_db_size());
4835 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4836 fib_path_list_pool_size());
4837 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
4838 fib_entry_pool_size());
4841 * add a v4 prefix via a v6 next-hop
4843 fib_prefix_t pfx_1_1_1_1_s_32 = {
4845 .fp_proto = FIB_PROTOCOL_IP4,
4847 .ip4.as_u32 = 0x01010101,
4850 fei = fib_table_entry_path_add(0, // default table
4853 FIB_ENTRY_FLAG_NONE,
4856 tm->hw[0]->sw_if_index,
4860 FIB_ROUTE_PATH_FLAG_NONE);
4861 FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32),
4862 "1.1.1.1/32 o v6 route present");
4863 ai = fib_entry_get_adj(fei);
4865 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
4866 "1.1.1.1/32 via ARP-adj");
4867 FIB_TEST((adj->ia_link == VNET_LINK_IP4),
4868 "1.1.1.1/32 ADJ-adj is link type v4");
4869 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6),
4870 "1.1.1.1/32 ADJ-adj is NH proto v6");
4871 fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API);
4876 fib_prefix_t pfx_2001_c_s_64 = {
4878 .fp_proto = FIB_PROTOCOL_IP6,
4882 [0] = clib_host_to_net_u64(0x200100000000000c),
4883 [1] = clib_host_to_net_u64(0x0000000000000000),
4888 fib_table_entry_path_add(fib_index,
4891 FIB_ENTRY_FLAG_ATTACHED,
4894 tm->hw[0]->sw_if_index,
4898 FIB_ROUTE_PATH_FLAG_NONE);
4899 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4900 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present");
4901 ai = fib_entry_get_adj(fei);
4903 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN),
4904 "2001:0:0:c/64 attached resolves via glean");
4906 fib_table_entry_path_remove(fib_index,
4911 tm->hw[0]->sw_if_index,
4914 FIB_ROUTE_PATH_FLAG_NONE);
4915 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4916 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached route removed");
4919 * Shutdown the interface on which we have a connected and through
4920 * which the routes are reachable.
4921 * This will result in the connected, adj-fibs, and routes linking to drop
4922 * The local/for-us prefix continues to receive.
4924 clib_error_t * error;
4926 error = vnet_sw_interface_set_flags(vnet_get_main(),
4927 tm->hw[0]->sw_if_index,
4928 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4929 FIB_TEST((NULL == error), "Interface shutdown OK");
4931 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4932 dpo = fib_entry_contribute_ip_forwarding(fei);
4933 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4934 "2001::b/64 resolves via drop");
4936 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4937 dpo = fib_entry_contribute_ip_forwarding(fei);
4938 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4939 "2001::a/64 resolves via drop");
4940 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
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:0:0:1::3/64 resolves via drop");
4944 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
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:0:0:1::2/64 resolves via drop");
4948 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
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::1/128 not drop");
4952 local_pfx.fp_len = 64;
4953 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4954 dpo = fib_entry_contribute_ip_forwarding(fei);
4955 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4956 "2001:0:0:1/64 resolves via drop");
4961 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4962 fib_path_list_db_size());
4963 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4964 fib_path_list_pool_size());
4965 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
4966 fib_entry_pool_size());
4969 * shutdown one of the other interfaces, then add a connected.
4970 * and swap one of the routes to it.
4972 error = vnet_sw_interface_set_flags(vnet_get_main(),
4973 tm->hw[1]->sw_if_index,
4974 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4975 FIB_TEST((NULL == error), "Interface 1 shutdown OK");
4977 fib_prefix_t connected_pfx = {
4979 .fp_proto = FIB_PROTOCOL_IP6,
4982 /* 2001:0:0:2::1/64 */
4984 [0] = clib_host_to_net_u64(0x2001000000000002),
4985 [1] = clib_host_to_net_u64(0x0000000000000001),
4990 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4991 FIB_SOURCE_INTERFACE,
4992 (FIB_ENTRY_FLAG_CONNECTED |
4993 FIB_ENTRY_FLAG_ATTACHED),
4996 tm->hw[1]->sw_if_index,
5000 FIB_ROUTE_PATH_FLAG_NONE);
5001 fei = fib_table_lookup_exact_match(fib_index, &connected_pfx);
5002 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
5003 dpo = fib_entry_contribute_ip_forwarding(fei);
5004 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
5005 FIB_TEST(!dpo_cmp(dpo, dpo_drop),
5006 "2001:0:0:2/64 not resolves via drop");
5008 connected_pfx.fp_len = 128;
5009 fib_table_entry_update_one_path(fib_index, &connected_pfx,
5010 FIB_SOURCE_INTERFACE,
5011 (FIB_ENTRY_FLAG_CONNECTED |
5012 FIB_ENTRY_FLAG_LOCAL),
5015 tm->hw[0]->sw_if_index,
5016 ~0, // invalid fib index
5019 FIB_ROUTE_PATH_FLAG_NONE);
5020 fei = fib_table_lookup(fib_index, &connected_pfx);
5022 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
5023 dpo = fib_entry_contribute_ip_forwarding(fei);
5024 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
5025 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
5026 "local interface adj is local");
5027 rd = receive_dpo_get(dpo->dpoi_index);
5028 FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr,
5030 "local interface adj is receive ok");
5033 * +2 entries, +2 unshared path-lists
5035 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
5036 fib_path_list_db_size());
5037 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
5038 fib_path_list_pool_size());
5039 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
5040 fib_entry_pool_size());
5044 * bring the interface back up. we expected the routes to return
5045 * to normal forwarding.
5047 error = vnet_sw_interface_set_flags(vnet_get_main(),
5048 tm->hw[0]->sw_if_index,
5049 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5050 FIB_TEST((NULL == error), "Interface bring-up OK");
5051 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5052 ai = fib_entry_get_adj(fei);
5053 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
5054 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5055 ai = fib_entry_get_adj(fei);
5056 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
5057 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5058 ai = fib_entry_get_adj(fei);
5059 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
5060 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5061 ai = fib_entry_get_adj(fei);
5062 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
5063 local_pfx.fp_len = 64;
5064 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5065 ai = fib_entry_get_adj(fei);
5067 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
5068 "attached interface adj is glean");
5071 * Same test as above, but this time the HW interface goes down
5073 error = vnet_hw_interface_set_flags(vnet_get_main(),
5074 tm->hw_if_indicies[0],
5075 ~VNET_HW_INTERFACE_FLAG_LINK_UP);
5076 FIB_TEST((NULL == error), "Interface shutdown OK");
5078 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5079 dpo = fib_entry_contribute_ip_forwarding(fei);
5080 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5081 "2001::b/64 resolves via drop");
5082 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5083 dpo = fib_entry_contribute_ip_forwarding(fei);
5084 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5085 "2001::a/64 resolves via drop");
5086 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5087 dpo = fib_entry_contribute_ip_forwarding(fei);
5088 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5089 "2001:0:0:1::3/128 resolves via drop");
5090 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5091 dpo = fib_entry_contribute_ip_forwarding(fei);
5092 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5093 "2001:0:0:1::2/128 resolves via drop");
5094 local_pfx.fp_len = 128;
5095 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5096 dpo = fib_entry_contribute_ip_forwarding(fei);
5097 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5098 "2001:0:0:1::1/128 not drop");
5099 local_pfx.fp_len = 64;
5100 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5101 dpo = fib_entry_contribute_ip_forwarding(fei);
5102 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5103 "2001:0:0:1/64 resolves via drop");
5105 error = vnet_hw_interface_set_flags(vnet_get_main(),
5106 tm->hw_if_indicies[0],
5107 VNET_HW_INTERFACE_FLAG_LINK_UP);
5108 FIB_TEST((NULL == error), "Interface bring-up OK");
5109 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5110 ai = fib_entry_get_adj(fei);
5111 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
5112 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5113 ai = fib_entry_get_adj(fei);
5114 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
5115 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5116 ai = fib_entry_get_adj(fei);
5117 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
5118 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5119 ai = fib_entry_get_adj(fei);
5120 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
5121 local_pfx.fp_len = 64;
5122 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5123 ai = fib_entry_get_adj(fei);
5125 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
5126 "attached interface adj is glean");
5129 * Delete the interface that the routes reolve through.
5130 * Again no routes are removed. They all point to drop.
5132 * This is considered an error case. The control plane should
5133 * not remove interfaces through which routes resolve, but
5134 * such things can happen. ALL affected routes will drop.
5136 vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]);
5138 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5139 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5140 "2001::b/64 resolves via drop");
5141 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5142 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5143 "2001::b/64 resolves via drop");
5144 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5145 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5146 "2001:0:0:1::3/64 resolves via drop");
5147 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5148 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5149 "2001:0:0:1::2/64 resolves via drop");
5150 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5151 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5152 "2001:0:0:1::1/128 is drop");
5153 local_pfx.fp_len = 64;
5154 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5155 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5156 "2001:0:0:1/64 resolves via drop");
5161 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
5162 fib_path_list_db_size());
5163 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
5164 fib_path_list_pool_size());
5165 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
5166 fib_entry_pool_size());
5169 * Add the interface back. routes stay unresolved.
5171 vnet_eth_interface_registration_t eir = {};
5172 eir.dev_class_index = test_interface_device_class.index;
5173 eir.dev_instance = 0;
5174 eir.address = hw_address;
5175 tm->hw_if_indicies[0] = vnet_eth_register_interface (vnet_get_main(), &eir);
5177 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5178 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5179 "2001::b/64 resolves via drop");
5180 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5181 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5182 "2001::b/64 resolves via drop");
5183 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5184 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5185 "2001:0:0:1::3/64 resolves via drop");
5186 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5187 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5188 "2001:0:0:1::2/64 resolves via drop");
5189 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5190 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5191 "2001:0:0:1::1/128 is drop");
5192 local_pfx.fp_len = 64;
5193 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5194 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5195 "2001:0:0:1/64 resolves via drop");
5198 * CLEANUP ALL the routes
5200 fib_table_entry_delete(fib_index,
5203 fib_table_entry_delete(fib_index,
5206 fib_table_entry_delete(fib_index,
5209 fib_table_entry_delete(fib_index,
5210 &pfx_2001_1_3_s_128,
5212 fib_table_entry_delete(fib_index,
5213 &pfx_2001_1_2_s_128,
5215 local_pfx.fp_len = 64;
5216 fib_table_entry_delete(fib_index, &local_pfx,
5217 FIB_SOURCE_INTERFACE);
5218 local_pfx.fp_len = 128;
5219 fib_table_entry_special_remove(fib_index, &local_pfx,
5220 FIB_SOURCE_INTERFACE);
5221 connected_pfx.fp_len = 64;
5222 fib_table_entry_delete(fib_index, &connected_pfx,
5223 FIB_SOURCE_INTERFACE);
5224 connected_pfx.fp_len = 128;
5225 fib_table_entry_special_remove(fib_index, &connected_pfx,
5226 FIB_SOURCE_INTERFACE);
5228 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5229 fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)),
5230 "2001::a/64 removed");
5231 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5232 fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)),
5233 "2001::b/64 removed");
5234 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5235 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)),
5236 "2001:0:0:1::3/128 removed");
5237 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5238 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)),
5239 "2001:0:0:1::3/128 removed");
5240 local_pfx.fp_len = 64;
5241 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5242 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5243 "2001:0:0:1/64 removed");
5244 local_pfx.fp_len = 128;
5245 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5246 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5247 "2001:0:0:1::1/128 removed");
5248 connected_pfx.fp_len = 64;
5249 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5250 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5251 "2001:0:0:2/64 removed");
5252 connected_pfx.fp_len = 128;
5253 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5254 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5255 "2001:0:0:2::1/128 removed");
5258 * -8 entries. -7 path-lists (1 was shared).
5260 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5261 fib_path_list_db_size());
5262 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is%d",
5263 fib_path_list_pool_size());
5264 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
5265 fib_entry_pool_size());
5268 * now remove the VRF
5271 for (ii = 0; ii < 4; ii++)
5272 fib_table_bind (FIB_PROTOCOL_IP6, tm->hw[ii]->sw_if_index, 0);
5274 fib_table_unlock(fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
5276 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5277 fib_path_list_db_size());
5278 FIB_TEST((PNPS-2 == fib_path_list_pool_size()), "path list pool size is%d",
5279 fib_path_list_pool_size());
5280 FIB_TEST((ENPS-2 == fib_entry_pool_size()), "entry pool size is %d",
5281 fib_entry_pool_size());
5287 * return the interfaces to up state
5289 error = vnet_sw_interface_set_flags(vnet_get_main(),
5290 tm->hw[0]->sw_if_index,
5291 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5292 error = vnet_sw_interface_set_flags(vnet_get_main(),
5293 tm->hw[1]->sw_if_index,
5294 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5296 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5298 FIB_TEST((0 == adj_glean_db_size()), "ADJ DB size is %d",
5299 adj_glean_db_size());
5305 * Test Attached Exports
5310 const dpo_id_t *dpo, *dpo_drop;
5311 const u32 fib_index = 0;
5312 fib_node_index_t dfrt, fei;
5319 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5323 * add interface routes. We'll assume this works. It's more rigorously
5326 fib_prefix_t local_pfx = {
5328 .fp_proto = FIB_PROTOCOL_IP4,
5332 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5337 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[0]->sw_if_index, fib_index);
5339 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
5341 fib_table_entry_update_one_path(fib_index, &local_pfx,
5342 FIB_SOURCE_INTERFACE,
5343 (FIB_ENTRY_FLAG_CONNECTED |
5344 FIB_ENTRY_FLAG_ATTACHED),
5347 tm->hw[0]->sw_if_index,
5351 FIB_ROUTE_PATH_FLAG_NONE);
5352 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5353 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5354 "attached interface route present");
5356 local_pfx.fp_len = 32;
5357 fib_table_entry_update_one_path(fib_index, &local_pfx,
5358 FIB_SOURCE_INTERFACE,
5359 (FIB_ENTRY_FLAG_CONNECTED |
5360 FIB_ENTRY_FLAG_LOCAL),
5363 tm->hw[0]->sw_if_index,
5364 ~0, // invalid fib index
5367 FIB_ROUTE_PATH_FLAG_NONE);
5368 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5370 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5371 "local interface route present");
5374 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
5376 fib_prefix_t pfx_10_10_10_1_s_32 = {
5378 .fp_proto = FIB_PROTOCOL_IP4,
5381 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5384 fib_node_index_t ai;
5386 fib_table_entry_path_add(fib_index,
5387 &pfx_10_10_10_1_s_32,
5389 FIB_ENTRY_FLAG_ATTACHED,
5391 &pfx_10_10_10_1_s_32.fp_addr,
5392 tm->hw[0]->sw_if_index,
5393 ~0, // invalid fib index
5396 FIB_ROUTE_PATH_FLAG_NONE);
5398 fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
5399 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
5400 ai = fib_entry_get_adj(fei);
5403 * create another FIB table into which routes will be imported
5405 u32 import_fib_index1;
5407 import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4,
5411 * Add default route in the import FIB
5413 fib_prefix_t pfx_0_0_0_0_s_0 = {
5415 .fp_proto = FIB_PROTOCOL_IP4,
5423 dfrt = fib_table_lookup(import_fib_index1, &pfx_0_0_0_0_s_0);
5424 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
5426 fib_table_entry_path_add(import_fib_index1,
5429 FIB_ENTRY_FLAG_NONE,
5432 tm->hw[0]->sw_if_index,
5433 ~0, // invalid fib index
5436 FIB_ROUTE_PATH_FLAG_NONE);
5437 fei = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
5438 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "default route present");
5439 FIB_TEST((fei != dfrt), "default route added");
5442 * delete default route and check for the presence in the import table
5444 fib_table_entry_delete(import_fib_index1, &pfx_0_0_0_0_s_0, FIB_SOURCE_API);
5445 fei = fib_table_lookup(import_fib_index1, &pfx_0_0_0_0_s_0);
5446 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "default route present");
5447 FIB_TEST((fei == dfrt), "default route removed");
5450 * Add an attached route in the import FIB
5452 local_pfx.fp_len = 24;
5453 fib_table_entry_update_one_path(import_fib_index1,
5456 FIB_ENTRY_FLAG_NONE,
5459 tm->hw[0]->sw_if_index,
5460 ~0, // invalid fib index
5463 FIB_ROUTE_PATH_FLAG_NONE);
5464 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5465 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5468 * check for the presence of the adj-fibs in the import table
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 imported");
5472 FIB_TEST((ai == fib_entry_get_adj(fei)),
5473 "adj-fib1 Import uses same adj as export");
5476 * check for the presence of the local in the import table
5478 local_pfx.fp_len = 32;
5479 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5480 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5483 * Add another adj-fin in the export table. Expect this
5484 * to get magically exported;
5486 fib_prefix_t pfx_10_10_10_2_s_32 = {
5488 .fp_proto = FIB_PROTOCOL_IP4,
5491 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5495 fib_table_entry_path_add(fib_index,
5496 &pfx_10_10_10_2_s_32,
5498 FIB_ENTRY_FLAG_ATTACHED,
5500 &pfx_10_10_10_2_s_32.fp_addr,
5501 tm->hw[0]->sw_if_index,
5502 ~0, // invalid fib index
5505 FIB_ROUTE_PATH_FLAG_NONE);
5506 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5507 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
5508 ai = fib_entry_get_adj(fei);
5510 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5511 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5512 FIB_TEST((ai == fib_entry_get_adj(fei)),
5513 "Import uses same adj as export");
5514 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(fei)),
5515 "ADJ-fib2 imported flags %d",
5516 fib_entry_get_flags(fei));
5519 * create a 2nd FIB table into which routes will be imported
5521 u32 import_fib_index2;
5523 import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12,
5527 * Add an attached route in the import FIB
5529 local_pfx.fp_len = 24;
5530 fib_table_entry_update_one_path(import_fib_index2,
5533 FIB_ENTRY_FLAG_NONE,
5536 tm->hw[0]->sw_if_index,
5537 ~0, // invalid fib index
5540 FIB_ROUTE_PATH_FLAG_NONE);
5541 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5542 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5545 * check for the presence of all the adj-fibs and local in the import table
5547 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5548 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5549 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5550 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5551 local_pfx.fp_len = 32;
5552 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5553 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5556 * add a 3rd adj-fib. expect it to be exported to both tables.
5558 fib_prefix_t pfx_10_10_10_3_s_32 = {
5560 .fp_proto = FIB_PROTOCOL_IP4,
5563 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
5567 fib_table_entry_path_add(fib_index,
5568 &pfx_10_10_10_3_s_32,
5570 FIB_ENTRY_FLAG_ATTACHED,
5572 &pfx_10_10_10_3_s_32.fp_addr,
5573 tm->hw[0]->sw_if_index,
5574 ~0, // invalid fib index
5577 FIB_ROUTE_PATH_FLAG_NONE);
5578 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5579 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
5580 ai = fib_entry_get_adj(fei);
5582 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5583 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1");
5584 FIB_TEST((ai == fib_entry_get_adj(fei)),
5585 "Import uses same adj as export");
5586 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5587 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2");
5588 FIB_TEST((ai == fib_entry_get_adj(fei)),
5589 "Import uses same adj as export");
5592 * remove the 3rd adj fib. we expect it to be removed from both FIBs
5594 fib_table_entry_delete(fib_index,
5595 &pfx_10_10_10_3_s_32,
5598 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5599 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved");
5601 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5602 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1");
5604 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5605 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2");
5608 * remove the attached route from the 2nd FIB. expect the imported
5609 * entries to be removed
5611 local_pfx.fp_len = 24;
5612 fib_table_entry_delete(import_fib_index2,
5615 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5616 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed");
5618 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5619 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2");
5620 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5621 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2");
5622 local_pfx.fp_len = 32;
5623 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5624 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2");
5626 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5627 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1");
5628 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5629 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1");
5630 local_pfx.fp_len = 32;
5631 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5632 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1");
5635 * modify the route in FIB1 so it is no longer attached. expect the imported
5636 * entries to be removed
5638 local_pfx.fp_len = 24;
5639 fib_table_entry_update_one_path(import_fib_index1,
5642 FIB_ENTRY_FLAG_NONE,
5644 &pfx_10_10_10_2_s_32.fp_addr,
5645 tm->hw[0]->sw_if_index,
5646 ~0, // invalid fib index
5649 FIB_ROUTE_PATH_FLAG_NONE);
5650 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5651 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5652 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5653 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5654 local_pfx.fp_len = 32;
5655 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5656 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5659 * modify it back to attached. expect the adj-fibs back
5661 local_pfx.fp_len = 24;
5662 fib_table_entry_update_one_path(import_fib_index1,
5665 FIB_ENTRY_FLAG_NONE,
5668 tm->hw[0]->sw_if_index,
5669 ~0, // invalid fib index
5672 FIB_ROUTE_PATH_FLAG_NONE);
5673 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5674 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1");
5675 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5676 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1");
5677 local_pfx.fp_len = 32;
5678 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5679 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1");
5682 * add a covering attached next-hop for the interface address, so we have
5683 * a valid adj to find when we check the forwarding tables
5685 fib_prefix_t pfx_10_0_0_0_s_8 = {
5687 .fp_proto = FIB_PROTOCOL_IP4,
5690 .ip4.as_u32 = clib_host_to_net_u32(0x0a000000),
5694 fei = fib_table_entry_update_one_path(fib_index,
5697 FIB_ENTRY_FLAG_NONE,
5699 &pfx_10_10_10_3_s_32.fp_addr,
5700 tm->hw[0]->sw_if_index,
5701 ~0, // invalid fib index
5704 FIB_ROUTE_PATH_FLAG_NONE);
5705 dpo = fib_entry_contribute_ip_forwarding(fei);
5708 * remove the route in the export fib. expect the adj-fibs to be removed
5710 local_pfx.fp_len = 24;
5711 fib_table_entry_delete(fib_index,
5713 FIB_SOURCE_INTERFACE);
5715 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5716 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1");
5717 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5718 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5719 local_pfx.fp_len = 32;
5720 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5721 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5724 * the adj-fibs in the export VRF are present in the FIB table,
5725 * but not installed in forwarding, since they have no attached cover.
5726 * Consequently a lookup in the MTRIE gives the adj for the covering
5729 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5730 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5733 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5734 FIB_TEST(lbi == dpo->dpoi_index,
5735 "10.10.10.1 forwards on \n%U not \n%U",
5736 format_load_balance, lbi, 0,
5737 format_dpo_id, dpo, 0);
5738 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5739 FIB_TEST(lbi == dpo->dpoi_index,
5740 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5741 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4);
5742 FIB_TEST(lbi == dpo->dpoi_index,
5743 "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0);
5746 * add the export prefix back, but not as attached.
5747 * No adj-fibs in export nor import tables
5749 local_pfx.fp_len = 24;
5750 fei = fib_table_entry_update_one_path(fib_index,
5753 FIB_ENTRY_FLAG_NONE,
5755 &pfx_10_10_10_1_s_32.fp_addr,
5756 tm->hw[0]->sw_if_index,
5757 ~0, // invalid fib index
5760 FIB_ROUTE_PATH_FLAG_NONE);
5761 dpo = fib_entry_contribute_ip_forwarding(fei);
5763 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5764 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export");
5765 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5766 FIB_TEST(lbi == dpo->dpoi_index,
5767 "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0);
5768 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5769 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5770 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5771 FIB_TEST(lbi == dpo->dpoi_index,
5772 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5774 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5775 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5776 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5777 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5778 local_pfx.fp_len = 32;
5779 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5780 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5783 * modify the export prefix so it is attached. expect all covereds to return
5785 local_pfx.fp_len = 24;
5786 fib_table_entry_update_one_path(fib_index,
5789 FIB_ENTRY_FLAG_NONE,
5792 tm->hw[0]->sw_if_index,
5793 ~0, // invalid fib index
5796 FIB_ROUTE_PATH_FLAG_NONE);
5798 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5799 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5800 dpo = fib_entry_contribute_ip_forwarding(fei);
5801 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5802 "Adj-fib1 is not drop in export");
5803 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5804 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5805 local_pfx.fp_len = 32;
5806 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5807 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5808 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5809 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5810 dpo = fib_entry_contribute_ip_forwarding(fei);
5811 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5812 "Adj-fib1 is not drop in export: %U %U",
5813 format_dpo_id, dpo, 0,
5814 format_dpo_id, load_balance_get_bucket(dpo->dpoi_index, 0), 0);
5815 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5816 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5817 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5818 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5819 local_pfx.fp_len = 32;
5820 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5821 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5824 * modify the export prefix so connected. no change.
5826 local_pfx.fp_len = 24;
5827 fib_table_entry_update_one_path(fib_index, &local_pfx,
5828 FIB_SOURCE_INTERFACE,
5829 (FIB_ENTRY_FLAG_CONNECTED |
5830 FIB_ENTRY_FLAG_ATTACHED),
5833 tm->hw[0]->sw_if_index,
5837 FIB_ROUTE_PATH_FLAG_NONE);
5839 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5840 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5841 dpo = fib_entry_contribute_ip_forwarding(fei);
5842 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5843 "Adj-fib1 is not drop in export");
5844 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5845 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5846 local_pfx.fp_len = 32;
5847 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5848 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5849 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5850 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5851 dpo = fib_entry_contribute_ip_forwarding(fei);
5852 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5853 "Adj-fib1 is not drop in export");
5854 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5855 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5856 local_pfx.fp_len = 32;
5857 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5858 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5863 fib_table_entry_delete(fib_index,
5866 fib_table_entry_delete(fib_index,
5867 &pfx_10_10_10_1_s_32,
5869 fib_table_entry_delete(fib_index,
5870 &pfx_10_10_10_2_s_32,
5872 local_pfx.fp_len = 32;
5873 fib_table_entry_delete(fib_index,
5875 FIB_SOURCE_INTERFACE);
5876 local_pfx.fp_len = 24;
5877 fib_table_entry_delete(fib_index,
5880 fib_table_entry_delete(fib_index,
5882 FIB_SOURCE_INTERFACE);
5883 local_pfx.fp_len = 24;
5884 fib_table_entry_delete(import_fib_index1,
5888 fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
5889 fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
5891 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5898 * Test Path Preference
5901 fib_test_pref (void)
5909 const fib_prefix_t pfx_1_1_1_1_s_32 = {
5911 .fp_proto = FIB_PROTOCOL_IP4,
5914 .as_u32 = clib_host_to_net_u32(0x01010101),
5919 for (i = 0; i <= 2; i++)
5920 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[i]->sw_if_index, 0);
5923 * 2 high, 2 medium and 2 low preference non-recursive paths
5925 fib_route_path_t nr_path_hi_1 = {
5926 .frp_proto = DPO_PROTO_IP4,
5927 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5928 .frp_fib_index = ~0,
5930 .frp_preference = 0,
5931 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5933 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5936 fib_route_path_t nr_path_hi_2 = {
5937 .frp_proto = DPO_PROTO_IP4,
5938 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5939 .frp_fib_index = ~0,
5941 .frp_preference = 0,
5942 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5944 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5947 fib_route_path_t nr_path_med_1 = {
5948 .frp_proto = DPO_PROTO_IP4,
5949 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5950 .frp_fib_index = ~0,
5952 .frp_preference = 1,
5953 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5955 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5958 fib_route_path_t nr_path_med_2 = {
5959 .frp_proto = DPO_PROTO_IP4,
5960 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5961 .frp_fib_index = ~0,
5963 .frp_preference = 1,
5964 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5966 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5969 fib_route_path_t nr_path_low_1 = {
5970 .frp_proto = DPO_PROTO_IP4,
5971 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5972 .frp_fib_index = ~0,
5974 .frp_preference = 2,
5975 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5977 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b01),
5980 fib_route_path_t nr_path_low_2 = {
5981 .frp_proto = DPO_PROTO_IP4,
5982 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5983 .frp_fib_index = ~0,
5985 .frp_preference = 2,
5986 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5988 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b02),
5991 fib_route_path_t *nr_paths = NULL;
5993 vec_add1(nr_paths, nr_path_hi_1);
5994 vec_add1(nr_paths, nr_path_hi_2);
5995 vec_add1(nr_paths, nr_path_med_1);
5996 vec_add1(nr_paths, nr_path_med_2);
5997 vec_add1(nr_paths, nr_path_low_1);
5998 vec_add1(nr_paths, nr_path_low_2);
6000 adj_index_t ai_hi_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6002 &nr_path_hi_1.frp_addr,
6003 nr_path_hi_1.frp_sw_if_index);
6004 adj_index_t ai_hi_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6006 &nr_path_hi_2.frp_addr,
6007 nr_path_hi_2.frp_sw_if_index);
6008 adj_index_t ai_med_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6010 &nr_path_med_1.frp_addr,
6011 nr_path_med_1.frp_sw_if_index);
6012 adj_index_t ai_med_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6014 &nr_path_med_2.frp_addr,
6015 nr_path_med_2.frp_sw_if_index);
6016 adj_index_t ai_low_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6018 &nr_path_low_1.frp_addr,
6019 nr_path_low_1.frp_sw_if_index);
6020 adj_index_t ai_low_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6022 &nr_path_low_2.frp_addr,
6023 nr_path_low_2.frp_sw_if_index);
6025 fib_test_lb_bucket_t ip_hi_1 = {
6031 fib_test_lb_bucket_t ip_hi_2 = {
6037 fib_test_lb_bucket_t ip_med_1 = {
6043 fib_test_lb_bucket_t ip_med_2 = {
6049 fib_test_lb_bucket_t ip_low_1 = {
6055 fib_test_lb_bucket_t ip_low_2 = {
6062 fib_node_index_t fei;
6064 fei = fib_table_entry_path_add2(0,
6067 FIB_ENTRY_FLAG_NONE,
6070 FIB_TEST(!fib_test_validate_entry(fei,
6071 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6075 "1.1.1.1/32 via high preference paths");
6078 * bring down the interface on which the high preference path lie
6080 vnet_sw_interface_set_flags(vnet_get_main(),
6081 tm->hw[0]->sw_if_index,
6084 FIB_TEST(!fib_test_validate_entry(fei,
6085 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6089 "1.1.1.1/32 via medium preference paths");
6092 * bring down the interface on which the medium preference path lie
6094 vnet_sw_interface_set_flags(vnet_get_main(),
6095 tm->hw[1]->sw_if_index,
6098 FIB_TEST(!fib_test_validate_entry(fei,
6099 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6103 "1.1.1.1/32 via low preference paths");
6106 * bring up the interface on which the high preference path lie
6108 vnet_sw_interface_set_flags(vnet_get_main(),
6109 tm->hw[0]->sw_if_index,
6110 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6112 FIB_TEST(!fib_test_validate_entry(fei,
6113 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6117 "1.1.1.1/32 via high preference paths");
6120 * bring up the interface on which the medium preference path lie
6122 vnet_sw_interface_set_flags(vnet_get_main(),
6123 tm->hw[1]->sw_if_index,
6124 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6126 FIB_TEST(!fib_test_validate_entry(fei,
6127 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6131 "1.1.1.1/32 via high preference paths");
6133 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
6134 fib_entry_contribute_forwarding(fei,
6135 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6139 * 3 recursive paths of different preference
6141 const fib_prefix_t pfx_1_1_1_2_s_32 = {
6143 .fp_proto = FIB_PROTOCOL_IP4,
6146 .as_u32 = clib_host_to_net_u32(0x01010102),
6150 const fib_prefix_t pfx_1_1_1_3_s_32 = {
6152 .fp_proto = FIB_PROTOCOL_IP4,
6155 .as_u32 = clib_host_to_net_u32(0x01010103),
6159 fei = fib_table_entry_path_add2(0,
6162 FIB_ENTRY_FLAG_NONE,
6164 dpo_id_t ip_1_1_1_2 = DPO_INVALID;
6165 fib_entry_contribute_forwarding(fei,
6166 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6168 fei = fib_table_entry_path_add2(0,
6171 FIB_ENTRY_FLAG_NONE,
6173 dpo_id_t ip_1_1_1_3 = DPO_INVALID;
6174 fib_entry_contribute_forwarding(fei,
6175 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6178 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
6181 .lb = ip_1_1_1_1.dpoi_index,
6184 fib_test_lb_bucket_t ip_o_1_1_1_2 = {
6187 .lb = ip_1_1_1_2.dpoi_index,
6190 fib_test_lb_bucket_t ip_o_1_1_1_3 = {
6193 .lb = ip_1_1_1_3.dpoi_index,
6196 fib_route_path_t r_path_hi = {
6197 .frp_proto = DPO_PROTO_IP4,
6198 .frp_sw_if_index = ~0,
6201 .frp_preference = 0,
6202 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
6203 .frp_addr = pfx_1_1_1_1_s_32.fp_addr,
6205 fib_route_path_t r_path_med = {
6206 .frp_proto = DPO_PROTO_IP4,
6207 .frp_sw_if_index = ~0,
6210 .frp_preference = 10,
6211 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
6212 .frp_addr = pfx_1_1_1_2_s_32.fp_addr,
6214 fib_route_path_t r_path_low = {
6215 .frp_proto = DPO_PROTO_IP4,
6216 .frp_sw_if_index = ~0,
6219 .frp_preference = 255,
6220 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
6221 .frp_addr = pfx_1_1_1_3_s_32.fp_addr,
6223 fib_route_path_t *r_paths = NULL;
6225 vec_add1(r_paths, r_path_hi);
6226 vec_add1(r_paths, r_path_low);
6227 vec_add1(r_paths, r_path_med);
6230 * add many recursive so we get the LB MAp created
6233 fib_prefix_t pfx_r[N_PFXS];
6234 unsigned int n_pfxs;
6235 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6237 pfx_r[n_pfxs].fp_len = 32;
6238 pfx_r[n_pfxs].fp_proto = FIB_PROTOCOL_IP4;
6239 pfx_r[n_pfxs].fp_addr.ip4.as_u32 =
6240 clib_host_to_net_u32(0x02000000 + n_pfxs);
6242 fei = fib_table_entry_path_add2(0,
6245 FIB_ENTRY_FLAG_NONE,
6248 FIB_TEST(!fib_test_validate_entry(fei,
6249 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6252 "recursive via high preference paths");
6255 * withdraw hig pref resolving entry
6257 fib_table_entry_delete(0,
6261 /* suspend so the update walk kicks int */
6262 vlib_process_suspend(vlib_get_main(), 1e-5);
6264 FIB_TEST(!fib_test_validate_entry(fei,
6265 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6268 "recursive via medium preference paths");
6271 * withdraw medium pref resolving entry
6273 fib_table_entry_delete(0,
6277 /* suspend so the update walk kicks int */
6278 vlib_process_suspend(vlib_get_main(), 1e-5);
6280 FIB_TEST(!fib_test_validate_entry(fei,
6281 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6284 "recursive via low preference paths");
6287 * add back paths for next iteration
6289 fei = fib_table_entry_update(0,
6292 FIB_ENTRY_FLAG_NONE,
6294 fei = fib_table_entry_update(0,
6297 FIB_ENTRY_FLAG_NONE,
6300 /* suspend so the update walk kicks int */
6301 vlib_process_suspend(vlib_get_main(), 1e-5);
6303 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6304 FIB_TEST(!fib_test_validate_entry(fei,
6305 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6308 "recursive via high preference paths");
6312 fib_table_entry_delete(0,
6316 /* suspend so the update walk kicks int */
6317 vlib_process_suspend(vlib_get_main(), 1e-5);
6319 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6321 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6323 FIB_TEST(!fib_test_validate_entry(fei,
6324 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6327 "recursive via medium preference paths");
6329 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6331 fib_table_entry_delete(0,
6339 fib_table_entry_delete(0,
6342 fib_table_entry_delete(0,
6346 dpo_reset(&ip_1_1_1_1);
6347 dpo_reset(&ip_1_1_1_2);
6348 dpo_reset(&ip_1_1_1_3);
6349 adj_unlock(ai_low_2);
6350 adj_unlock(ai_low_1);
6351 adj_unlock(ai_med_2);
6352 adj_unlock(ai_med_1);
6353 adj_unlock(ai_hi_2);
6354 adj_unlock(ai_hi_1);
6360 * Test the recursive route route handling for GRE tunnels
6363 fib_test_label (void)
6365 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;
6366 const u32 fib_index = 0;
6367 int lb_count, ii, res;
6371 lb_count = pool_elts(load_balance_pool);
6375 * add interface routes. We'll assume this works. It's more rigorously
6378 fib_prefix_t local0_pfx = {
6380 .fp_proto = FIB_PROTOCOL_IP4,
6384 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
6389 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6392 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[0]->sw_if_index, fib_index);
6394 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6395 FIB_SOURCE_INTERFACE,
6396 (FIB_ENTRY_FLAG_CONNECTED |
6397 FIB_ENTRY_FLAG_ATTACHED),
6400 tm->hw[0]->sw_if_index,
6404 FIB_ROUTE_PATH_FLAG_NONE);
6405 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6406 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6407 "attached interface route present");
6409 local0_pfx.fp_len = 32;
6410 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6411 FIB_SOURCE_INTERFACE,
6412 (FIB_ENTRY_FLAG_CONNECTED |
6413 FIB_ENTRY_FLAG_LOCAL),
6416 tm->hw[0]->sw_if_index,
6417 ~0, // invalid fib index
6420 FIB_ROUTE_PATH_FLAG_NONE);
6421 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6423 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6424 "local interface route present");
6426 fib_prefix_t local1_pfx = {
6428 .fp_proto = FIB_PROTOCOL_IP4,
6432 .as_u32 = clib_host_to_net_u32(0x0a0a0b0a),
6437 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[1]->sw_if_index, fib_index);
6439 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6440 FIB_SOURCE_INTERFACE,
6441 (FIB_ENTRY_FLAG_CONNECTED |
6442 FIB_ENTRY_FLAG_ATTACHED),
6445 tm->hw[1]->sw_if_index,
6449 FIB_ROUTE_PATH_FLAG_NONE);
6450 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6451 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6452 "attached interface route present");
6454 local1_pfx.fp_len = 32;
6455 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6456 FIB_SOURCE_INTERFACE,
6457 (FIB_ENTRY_FLAG_CONNECTED |
6458 FIB_ENTRY_FLAG_LOCAL),
6461 tm->hw[1]->sw_if_index,
6462 ~0, // invalid fib index
6465 FIB_ROUTE_PATH_FLAG_NONE);
6466 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6468 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6469 "local interface route present");
6471 ip46_address_t nh_10_10_10_1 = {
6473 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
6476 ip46_address_t nh_10_10_11_1 = {
6478 .as_u32 = clib_host_to_net_u32(0x0a0a0b01),
6481 ip46_address_t nh_10_10_11_2 = {
6483 .as_u32 = clib_host_to_net_u32(0x0a0a0b02),
6487 ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6490 tm->hw[1]->sw_if_index);
6491 ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6494 tm->hw[1]->sw_if_index);
6495 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6498 tm->hw[0]->sw_if_index);
6499 ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6502 tm->hw[1]->sw_if_index);
6503 ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6506 tm->hw[1]->sw_if_index);
6509 * Add an etry with one path with a real out-going label
6511 fib_prefix_t pfx_1_1_1_1_s_32 = {
6513 .fp_proto = FIB_PROTOCOL_IP4,
6515 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
6518 fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = {
6519 .type = FT_LB_LABEL_O_ADJ,
6521 .adj = ai_mpls_10_10_10_1,
6526 fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = {
6527 .type = FT_LB_LABEL_O_ADJ,
6529 .adj = ai_mpls_10_10_10_1,
6531 .eos = MPLS_NON_EOS,
6534 fib_mpls_label_t *l99 = NULL, fml99 = {
6537 vec_add1(l99, fml99);
6539 fib_table_entry_update_one_path(fib_index,
6542 FIB_ENTRY_FLAG_NONE,
6545 tm->hw[0]->sw_if_index,
6546 ~0, // invalid fib index
6549 FIB_ROUTE_PATH_FLAG_NONE);
6551 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6552 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created");
6554 FIB_TEST(!fib_test_validate_entry(fei,
6555 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6557 &l99_eos_o_10_10_10_1),
6558 "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1");
6561 * add a path with an implicit NULL label
6563 fib_test_lb_bucket_t a_o_10_10_11_1 = {
6566 .adj = ai_v4_10_10_11_1,
6569 fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = {
6572 .adj = ai_mpls_10_10_11_1,
6575 fib_mpls_label_t *l_imp_null = NULL, fml_imp_null = {
6576 .fml_value = MPLS_IETF_IMPLICIT_NULL_LABEL,
6578 vec_add1(l_imp_null, fml_imp_null);
6580 fei = fib_table_entry_path_add(fib_index,
6583 FIB_ENTRY_FLAG_NONE,
6586 tm->hw[1]->sw_if_index,
6587 ~0, // invalid fib index
6590 FIB_ROUTE_PATH_FLAG_NONE);
6592 FIB_TEST(!fib_test_validate_entry(fei,
6593 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6595 &l99_eos_o_10_10_10_1,
6597 "1.1.1.1/32 LB 2 buckets via: "
6598 "label 99 over 10.10.10.1, "
6599 "adj over 10.10.11.1");
6602 * assign the route a local label
6604 fib_table_entry_local_label_add(fib_index,
6608 fib_prefix_t pfx_24001_eos = {
6609 .fp_proto = FIB_PROTOCOL_MPLS,
6613 fib_prefix_t pfx_24001_neos = {
6614 .fp_proto = FIB_PROTOCOL_MPLS,
6616 .fp_eos = MPLS_NON_EOS,
6618 fib_test_lb_bucket_t disp_o_10_10_11_1 = {
6619 .type = FT_LB_MPLS_DISP_PIPE_O_ADJ,
6621 .adj = ai_v4_10_10_11_1,
6626 * The EOS entry should link to both the paths,
6627 * and use an ip adj for the imp-null
6628 * The NON-EOS entry should link to both the paths,
6629 * and use an mpls adj for the imp-null
6631 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6633 FIB_TEST(!fib_test_validate_entry(fei,
6634 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6636 &l99_eos_o_10_10_10_1,
6637 &disp_o_10_10_11_1),
6638 "24001/eos LB 2 buckets via: "
6639 "label 99 over 10.10.10.1, "
6640 "mpls disp adj over 10.10.11.1");
6643 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6645 FIB_TEST(!fib_test_validate_entry(fei,
6646 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6648 &l99_neos_o_10_10_10_1,
6649 &a_mpls_o_10_10_11_1),
6650 "24001/neos LB 1 bucket via: "
6651 "label 99 over 10.10.10.1 ",
6652 "mpls-adj via 10.10.11.1");
6655 * add an unlabelled path, this is excluded from the neos chains,
6657 fib_test_lb_bucket_t adj_o_10_10_11_2 = {
6660 .adj = ai_v4_10_10_11_2,
6663 fib_test_lb_bucket_t disp_o_10_10_11_2 = {
6664 .type = FT_LB_MPLS_DISP_PIPE_O_ADJ,
6666 .adj = ai_v4_10_10_11_2,
6671 fei = fib_table_entry_path_add(fib_index,
6674 FIB_ENTRY_FLAG_NONE,
6677 tm->hw[1]->sw_if_index,
6678 ~0, // invalid fib index
6681 FIB_ROUTE_PATH_FLAG_NONE);
6683 FIB_TEST(!fib_test_validate_entry(fei,
6684 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6685 16, // 3 choices spread over 16 buckets
6686 &l99_eos_o_10_10_10_1,
6687 &l99_eos_o_10_10_10_1,
6688 &l99_eos_o_10_10_10_1,
6689 &l99_eos_o_10_10_10_1,
6690 &l99_eos_o_10_10_10_1,
6691 &l99_eos_o_10_10_10_1,
6702 "1.1.1.1/32 LB 16 buckets via: "
6703 "label 99 over 10.10.10.1, "
6704 "adj over 10.10.11.1",
6705 "adj over 10.10.11.2");
6708 * get and lock a reference to the non-eos of the via entry 1.1.1.1/32
6710 dpo_id_t non_eos_1_1_1_1 = DPO_INVALID;
6711 fib_entry_contribute_forwarding(fei,
6712 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6716 * n-eos has only the 2 labelled paths
6718 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6721 FIB_TEST(!fib_test_validate_entry(fei,
6722 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6724 &l99_neos_o_10_10_10_1,
6725 &a_mpls_o_10_10_11_1),
6726 "24001/neos LB 2 buckets via: "
6727 "label 99 over 10.10.10.1, "
6728 "adj-mpls over 10.10.11.2");
6731 * A labelled recursive
6733 fib_prefix_t pfx_2_2_2_2_s_32 = {
6735 .fp_proto = FIB_PROTOCOL_IP4,
6737 .ip4.as_u32 = clib_host_to_net_u32(0x02020202),
6740 fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = {
6741 .type = FT_LB_LABEL_O_LB,
6743 .lb = non_eos_1_1_1_1.dpoi_index,
6746 .mode = FIB_MPLS_LSP_MODE_UNIFORM,
6749 fib_mpls_label_t *l1600 = NULL, fml1600 = {
6751 .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM,
6753 vec_add1(l1600, fml1600);
6755 fei = fib_table_entry_update_one_path(fib_index,
6758 FIB_ENTRY_FLAG_NONE,
6760 &pfx_1_1_1_1_s_32.fp_addr,
6765 FIB_ROUTE_PATH_FLAG_NONE);
6767 FIB_TEST(!fib_test_validate_entry(fei,
6768 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6770 &l1600_eos_o_1_1_1_1),
6771 "2.2.2.2.2/32 LB 1 buckets via: "
6772 "label 1600 over 1.1.1.1");
6774 dpo_id_t dpo_44 = DPO_INVALID;
6777 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
6778 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
6780 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
6781 "uRPF check for 2.2.2.2/32 on %d OK",
6782 tm->hw[0]->sw_if_index);
6783 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
6784 "uRPF check for 2.2.2.2/32 on %d OK",
6785 tm->hw[1]->sw_if_index);
6786 FIB_TEST(!fib_urpf_check(urpfi, 99),
6787 "uRPF check for 2.2.2.2/32 on 99 not-OK",
6790 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44);
6791 FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index),
6792 "Shared uRPF on IP and non-EOS chain");
6797 * we are holding a lock on the non-eos LB of the via-entry.
6798 * do a PIC-core failover by shutting the link of the via-entry.
6800 * shut down the link with the valid label
6802 vnet_sw_interface_set_flags(vnet_get_main(),
6803 tm->hw[0]->sw_if_index,
6806 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6807 FIB_TEST(!fib_test_validate_entry(fei,
6808 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6812 "1.1.1.1/32 LB 2 buckets via: "
6813 "adj over 10.10.11.1, ",
6814 "adj-v4 over 10.10.11.2");
6816 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6818 FIB_TEST(!fib_test_validate_entry(fei,
6819 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6822 &disp_o_10_10_11_2),
6823 "24001/eos LB 2 buckets via: "
6824 "mpls-disp adj over 10.10.11.1, ",
6825 "mpls-disp adj-v4 over 10.10.11.2");
6827 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6829 FIB_TEST(!fib_test_validate_entry(fei,
6830 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6832 &a_mpls_o_10_10_11_1),
6833 "24001/neos LB 1 buckets via: "
6834 "adj-mpls over 10.10.11.2");
6837 * test that the pre-failover load-balance has been in-place
6840 dpo_id_t current = DPO_INVALID;
6841 fib_entry_contribute_forwarding(fei,
6842 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6845 FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1,
6847 "PIC-core LB inplace modified %U %U",
6848 format_dpo_id, &non_eos_1_1_1_1, 0,
6849 format_dpo_id, ¤t, 0);
6851 dpo_reset(&non_eos_1_1_1_1);
6852 dpo_reset(¤t);
6855 * no-shut the link with the valid label
6857 vnet_sw_interface_set_flags(vnet_get_main(),
6858 tm->hw[0]->sw_if_index,
6859 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6861 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6862 FIB_TEST(!fib_test_validate_entry(fei,
6863 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6864 16, // 3 choices spread over 16 buckets
6865 &l99_eos_o_10_10_10_1,
6866 &l99_eos_o_10_10_10_1,
6867 &l99_eos_o_10_10_10_1,
6868 &l99_eos_o_10_10_10_1,
6869 &l99_eos_o_10_10_10_1,
6870 &l99_eos_o_10_10_10_1,
6881 "1.1.1.1/32 LB 16 buckets via: "
6882 "label 99 over 10.10.10.1, "
6883 "adj over 10.10.11.1",
6884 "adj-v4 over 10.10.11.2");
6887 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6889 FIB_TEST(!fib_test_validate_entry(fei,
6890 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6891 16, // 3 choices spread over 16 buckets
6892 &l99_eos_o_10_10_10_1,
6893 &l99_eos_o_10_10_10_1,
6894 &l99_eos_o_10_10_10_1,
6895 &l99_eos_o_10_10_10_1,
6896 &l99_eos_o_10_10_10_1,
6897 &l99_eos_o_10_10_10_1,
6907 &disp_o_10_10_11_2),
6908 "24001/eos LB 16 buckets via: "
6909 "label 99 over 10.10.10.1, "
6910 "MPLS disp adj over 10.10.11.1",
6911 "MPLS disp adj-v4 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 &a_mpls_o_10_10_11_1),
6920 "24001/neos LB 2 buckets via: "
6921 "label 99 over 10.10.10.1, "
6922 "adj-mpls over 10.10.11.2");
6925 * remove the first path with the valid label
6927 fib_table_entry_path_remove(fib_index,
6932 tm->hw[0]->sw_if_index,
6933 ~0, // invalid fib index
6935 FIB_ROUTE_PATH_FLAG_NONE);
6937 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6938 FIB_TEST(!fib_test_validate_entry(fei,
6939 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6943 "1.1.1.1/32 LB 2 buckets via: "
6944 "adj over 10.10.11.1, "
6945 "adj-v4 over 10.10.11.2");
6947 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6949 FIB_TEST(!fib_test_validate_entry(fei,
6950 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6953 &disp_o_10_10_11_2),
6954 "24001/eos LB 2 buckets via: "
6955 "MPLS disp adj over 10.10.11.1, "
6956 "MPLS disp adj-v4 over 10.10.11.2");
6958 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6961 FIB_TEST(!fib_test_validate_entry(fei,
6962 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6964 &a_mpls_o_10_10_11_1),
6965 "24001/neos LB 1 buckets via: "
6966 "adj-mpls over 10.10.11.2");
6969 * remove the other path with a valid label
6971 fib_test_lb_bucket_t bucket_drop = {
6974 fib_test_lb_bucket_t mpls_bucket_drop = {
6977 .adj = DPO_PROTO_MPLS,
6981 fib_table_entry_path_remove(fib_index,
6986 tm->hw[1]->sw_if_index,
6987 ~0, // invalid fib index
6989 FIB_ROUTE_PATH_FLAG_NONE);
6991 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6992 FIB_TEST(!fib_test_validate_entry(fei,
6993 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6996 "1.1.1.1/32 LB 1 buckets via: "
6997 "adj over 10.10.11.2");
6999 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7001 FIB_TEST(!fib_test_validate_entry(fei,
7002 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7004 &disp_o_10_10_11_2),
7005 "24001/eos LB 1 buckets via: "
7006 "MPLS disp adj over 10.10.11.2");
7008 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7010 FIB_TEST(!fib_test_validate_entry(fei,
7011 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7014 "24001/neos LB 1 buckets via: DROP");
7017 * add back the path with the valid label
7020 vec_add1(l99, fml99);
7022 fib_table_entry_path_add(fib_index,
7025 FIB_ENTRY_FLAG_NONE,
7028 tm->hw[0]->sw_if_index,
7029 ~0, // invalid fib index
7032 FIB_ROUTE_PATH_FLAG_NONE);
7034 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
7035 FIB_TEST(!fib_test_validate_entry(fei,
7036 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7038 &l99_eos_o_10_10_10_1,
7040 "1.1.1.1/32 LB 2 buckets via: "
7041 "label 99 over 10.10.10.1, "
7042 "adj over 10.10.11.2");
7044 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7046 FIB_TEST(!fib_test_validate_entry(fei,
7047 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7049 &l99_eos_o_10_10_10_1,
7050 &disp_o_10_10_11_2),
7051 "24001/eos LB 2 buckets via: "
7052 "label 99 over 10.10.10.1, "
7053 "MPLS disp adj over 10.10.11.2");
7055 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7057 FIB_TEST(!fib_test_validate_entry(fei,
7058 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7060 &l99_neos_o_10_10_10_1),
7061 "24001/neos LB 1 buckets via: "
7062 "label 99 over 10.10.10.1");
7065 * change the local label
7067 fib_table_entry_local_label_add(fib_index,
7071 fib_prefix_t pfx_25005_eos = {
7072 .fp_proto = FIB_PROTOCOL_MPLS,
7076 fib_prefix_t pfx_25005_neos = {
7077 .fp_proto = FIB_PROTOCOL_MPLS,
7079 .fp_eos = MPLS_NON_EOS,
7082 FIB_TEST((FIB_NODE_INDEX_INVALID ==
7083 fib_table_lookup(fib_index, &pfx_24001_eos)),
7084 "24001/eos removed after label change");
7085 FIB_TEST((FIB_NODE_INDEX_INVALID ==
7086 fib_table_lookup(fib_index, &pfx_24001_neos)),
7087 "24001/eos removed after label change");
7089 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7091 FIB_TEST(!fib_test_validate_entry(fei,
7092 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7094 &l99_eos_o_10_10_10_1,
7095 &disp_o_10_10_11_2),
7096 "25005/eos LB 2 buckets via: "
7097 "label 99 over 10.10.10.1, "
7098 "MPLS disp adj over 10.10.11.2");
7100 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7102 FIB_TEST(!fib_test_validate_entry(fei,
7103 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7105 &l99_neos_o_10_10_10_1),
7106 "25005/neos LB 1 buckets via: "
7107 "label 99 over 10.10.10.1");
7110 * remove the local label.
7111 * the check that the MPLS entries are gone is done by the fact the
7112 * MPLS table is no longer present.
7114 fib_table_entry_local_label_remove(fib_index,
7118 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
7119 FIB_TEST(!fib_test_validate_entry(fei,
7120 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7122 &l99_eos_o_10_10_10_1,
7124 "24001/eos LB 2 buckets via: "
7125 "label 99 over 10.10.10.1, "
7126 "adj over 10.10.11.2");
7128 FIB_TEST((FIB_NODE_INDEX_INVALID ==
7129 mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)),
7130 "No more MPLS FIB entries => table removed");
7133 * add another via-entry for the recursive
7135 fib_prefix_t pfx_1_1_1_2_s_32 = {
7137 .fp_proto = FIB_PROTOCOL_IP4,
7139 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
7142 fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = {
7143 .type = FT_LB_LABEL_O_ADJ,
7145 .adj = ai_mpls_10_10_10_1,
7150 fib_mpls_label_t *l101 = NULL, fml101 = {
7153 vec_add1(l101, fml101);
7155 fei = fib_table_entry_update_one_path(fib_index,
7158 FIB_ENTRY_FLAG_NONE,
7161 tm->hw[0]->sw_if_index,
7162 ~0, // invalid fib index
7165 FIB_ROUTE_PATH_FLAG_NONE);
7167 FIB_TEST(!fib_test_validate_entry(fei,
7168 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7170 &l101_eos_o_10_10_10_1),
7171 "1.1.1.2/32 LB 1 buckets via: "
7172 "label 101 over 10.10.10.1");
7174 dpo_id_t non_eos_1_1_1_2 = DPO_INVALID;
7175 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7177 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7179 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7181 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7184 fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = {
7185 .type = FT_LB_LABEL_O_LB,
7187 .lb = non_eos_1_1_1_2.dpoi_index,
7192 fib_mpls_label_t *l1601 = NULL, fml1601 = {
7195 vec_add1(l1601, fml1601);
7197 l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index;
7199 fei = fib_table_entry_path_add(fib_index,
7202 FIB_ENTRY_FLAG_NONE,
7204 &pfx_1_1_1_2_s_32.fp_addr,
7209 FIB_ROUTE_PATH_FLAG_NONE);
7211 FIB_TEST(!fib_test_validate_entry(fei,
7212 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7214 &l1600_eos_o_1_1_1_1,
7215 &l1601_eos_o_1_1_1_2),
7216 "2.2.2.2/32 LB 2 buckets via: "
7217 "label 1600 via 1.1,1.1, "
7218 "label 16001 via 1.1.1.2");
7221 * update the via-entry so it no longer has an imp-null path.
7222 * the LB for the recursive can use an imp-null
7225 vec_add1(l_imp_null, fml_imp_null);
7227 fei = fib_table_entry_update_one_path(fib_index,
7230 FIB_ENTRY_FLAG_NONE,
7233 tm->hw[1]->sw_if_index,
7234 ~0, // invalid fib index
7237 FIB_ROUTE_PATH_FLAG_NONE);
7239 FIB_TEST(!fib_test_validate_entry(fei,
7240 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7243 "1.1.1.2/32 LB 1 buckets via: "
7246 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7247 FIB_TEST(!fib_test_validate_entry(fei,
7248 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7250 &l1600_eos_o_1_1_1_1,
7251 &l1601_eos_o_1_1_1_2),
7252 "2.2.2.2/32 LB 2 buckets via: "
7253 "label 1600 via 1.1,1.1, "
7254 "label 16001 via 1.1.1.2");
7257 * update the via-entry so it no longer has labelled paths.
7258 * the LB for the recursive should exclue this via form its LB
7260 fei = fib_table_entry_update_one_path(fib_index,
7263 FIB_ENTRY_FLAG_NONE,
7266 tm->hw[1]->sw_if_index,
7267 ~0, // invalid fib index
7270 FIB_ROUTE_PATH_FLAG_NONE);
7272 FIB_TEST(!fib_test_validate_entry(fei,
7273 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7276 "1.1.1.2/32 LB 1 buckets via: "
7279 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7280 FIB_TEST(!fib_test_validate_entry(fei,
7281 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7283 &l1600_eos_o_1_1_1_1),
7284 "2.2.2.2/32 LB 1 buckets via: "
7285 "label 1600 via 1.1,1.1");
7287 dpo_reset(&non_eos_1_1_1_1);
7288 dpo_reset(&non_eos_1_1_1_2);
7291 * Add a recursive with no out-labels. We expect to use the IP of the via
7293 fib_prefix_t pfx_2_2_2_3_s_32 = {
7295 .fp_proto = FIB_PROTOCOL_IP4,
7297 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
7300 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
7302 fib_table_entry_update_one_path(fib_index,
7305 FIB_ENTRY_FLAG_NONE,
7307 &pfx_1_1_1_1_s_32.fp_addr,
7312 FIB_ROUTE_PATH_FLAG_NONE);
7314 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7316 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7319 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
7322 .lb = ip_1_1_1_1.dpoi_index,
7326 fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
7327 FIB_TEST(!fib_test_validate_entry(fei,
7328 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7331 "2.2.2.2.3/32 LB 1 buckets via: "
7335 * Add a recursive with an imp-null out-label.
7336 * We expect to use the IP of the via
7338 fib_prefix_t pfx_2_2_2_4_s_32 = {
7340 .fp_proto = FIB_PROTOCOL_IP4,
7342 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
7346 fib_table_entry_update_one_path(fib_index,
7349 FIB_ENTRY_FLAG_NONE,
7351 &pfx_1_1_1_1_s_32.fp_addr,
7356 FIB_ROUTE_PATH_FLAG_NONE);
7358 fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
7359 FIB_TEST(!fib_test_validate_entry(fei,
7360 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7363 "2.2.2.2.4/32 LB 1 buckets via: "
7366 dpo_reset(&ip_1_1_1_1);
7369 * Create an entry with a deep label stack
7371 fib_prefix_t pfx_2_2_5_5_s_32 = {
7373 .fp_proto = FIB_PROTOCOL_IP4,
7375 .ip4.as_u32 = clib_host_to_net_u32(0x02020505),
7378 fib_test_lb_bucket_t ls_eos_o_10_10_10_1 = {
7379 .type = FT_LB_LABEL_STACK_O_ADJ,
7380 .label_stack_o_adj = {
7381 .adj = ai_mpls_10_10_11_1,
7382 .label_stack_size = 8,
7384 200, 201, 202, 203, 204, 205, 206, 207
7389 fib_mpls_label_t *label_stack = NULL;
7390 vec_validate(label_stack, 7);
7391 for (ii = 0; ii < 8; ii++)
7393 label_stack[ii].fml_value = ii + 200;
7396 fei = fib_table_entry_update_one_path(fib_index,
7399 FIB_ENTRY_FLAG_NONE,
7402 tm->hw[1]->sw_if_index,
7403 ~0, // invalid fib index
7406 FIB_ROUTE_PATH_FLAG_NONE);
7408 FIB_TEST(!fib_test_validate_entry(fei,
7409 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7411 &ls_eos_o_10_10_10_1),
7412 "2.2.5.5/32 LB 1 buckets via: "
7414 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
7417 * A prefix with outgoing labels. We'll RR source a /32 it covers
7418 * and test that the RR source picks up the out-going labels
7420 fib_prefix_t pfx_100_s_8 = {
7422 .fp_proto = FIB_PROTOCOL_IP4,
7424 .ip4.as_u32 = clib_host_to_net_u32(0x64000000),
7427 fib_test_lb_bucket_t l_100_eos_o_10_10_10_1 = {
7428 .type = FT_LB_LABEL_O_ADJ,
7430 .adj = ai_mpls_10_10_11_1,
7435 fib_mpls_label_t *l1602 = NULL, fml1602 = {
7438 vec_add1(l1602, fml1602);
7439 fei = fib_table_entry_update_one_path(fib_index,
7442 FIB_ENTRY_FLAG_NONE,
7445 tm->hw[1]->sw_if_index,
7446 ~0, // invalid fib index
7449 FIB_ROUTE_PATH_FLAG_NONE);
7451 FIB_TEST(!fib_test_validate_entry(fei,
7452 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7454 &l_100_eos_o_10_10_10_1),
7455 "100.0.0.0/8 LB 1 buckets via: lbl 101 "
7458 fib_prefix_t pfx_100_1_1_1_s_32 = {
7460 .fp_proto = FIB_PROTOCOL_IP4,
7462 .ip4.as_u32 = clib_host_to_net_u32(0x64010101),
7466 fei = fib_table_entry_special_add(fib_index,
7467 &pfx_100_1_1_1_s_32,
7469 FIB_ENTRY_FLAG_NONE);
7471 FIB_TEST(!fib_test_validate_entry(fei,
7472 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7474 &l_100_eos_o_10_10_10_1),
7475 "100.1.1.1/32 LB 1 buckets via: "
7478 fib_table_entry_delete(fib_index,
7481 fib_table_entry_delete_index(fei, FIB_SOURCE_RR);
7486 fib_table_entry_delete(fib_index,
7490 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7491 FIB_TEST(!fib_test_validate_entry(fei,
7492 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7494 &l1600_eos_o_1_1_1_1),
7495 "2.2.2.2/32 LB 1 buckets via: "
7496 "label 1600 via 1.1,1.1");
7498 fib_table_entry_delete(fib_index,
7502 FIB_TEST(!fib_test_validate_entry(fei,
7503 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7506 "2.2.2.2/32 LB 1 buckets via: DROP");
7508 fib_table_entry_delete(fib_index,
7511 fib_table_entry_delete(fib_index,
7514 fib_table_entry_delete(fib_index,
7518 adj_unlock(ai_mpls_10_10_10_1);
7519 adj_unlock(ai_mpls_10_10_11_2);
7520 adj_unlock(ai_v4_10_10_11_1);
7521 adj_unlock(ai_v4_10_10_11_2);
7522 adj_unlock(ai_mpls_10_10_11_1);
7524 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
7527 local0_pfx.fp_len = 32;
7528 fib_table_entry_delete(fib_index,
7530 FIB_SOURCE_INTERFACE);
7531 local0_pfx.fp_len = 24;
7532 fib_table_entry_delete(fib_index,
7534 FIB_SOURCE_INTERFACE);
7535 local1_pfx.fp_len = 32;
7536 fib_table_entry_delete(fib_index,
7538 FIB_SOURCE_INTERFACE);
7539 local1_pfx.fp_len = 24;
7540 fib_table_entry_delete(fib_index,
7542 FIB_SOURCE_INTERFACE);
7545 * +1 for the drop LB in the MPLS tables.
7547 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
7548 "Load-balance resources freed %d of %d",
7549 lb_count+1, pool_elts(load_balance_pool));
7554 #define N_TEST_CHILDREN 4
7555 #define PARENT_INDEX 0
7557 typedef struct fib_node_test_t_
7562 fib_node_back_walk_ctx_t *ctxs;
7566 static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1];
7568 #define PARENT() (&fib_test_nodes[PARENT_INDEX].node)
7570 #define FOR_EACH_TEST_CHILD(_tc) \
7571 for (ii = 1, (_tc) = &fib_test_nodes[1]; \
7572 ii < N_TEST_CHILDREN+1; \
7573 ii++, (_tc) = &fib_test_nodes[ii])
7576 fib_test_child_get_node (fib_node_index_t index)
7578 return (&fib_test_nodes[index].node);
7581 static int fib_test_walk_spawns_walks;
7582 static fib_node_type_t test_node_type;
7584 static fib_node_back_walk_rc_t
7585 fib_test_child_back_walk_notify (fib_node_t *node,
7586 fib_node_back_walk_ctx_t *ctx)
7588 fib_node_test_t *tc = (fib_node_test_t*) node;
7590 vec_add1(tc->ctxs, *ctx);
7592 if (1 == fib_test_walk_spawns_walks)
7593 fib_walk_sync(test_node_type, tc->index, ctx);
7594 if (2 == fib_test_walk_spawns_walks)
7595 fib_walk_async(test_node_type, tc->index,
7596 FIB_WALK_PRIORITY_HIGH, ctx);
7598 return (FIB_NODE_BACK_WALK_CONTINUE);
7602 fib_test_child_last_lock_gone (fib_node_t *node)
7604 fib_node_test_t *tc = (fib_node_test_t *)node;
7610 * The FIB walk's graph node virtual function table
7612 static const fib_node_vft_t fib_test_child_vft = {
7613 .fnv_get = fib_test_child_get_node,
7614 .fnv_last_lock = fib_test_child_last_lock_gone,
7615 .fnv_back_walk = fib_test_child_back_walk_notify,
7619 * the function (that should have been static but isn't so I can do this)
7620 * that processes the walk from the async queue,
7622 f64 fib_walk_process_queues(vlib_main_t * vm,
7624 u32 fib_walk_queue_get_size(fib_walk_priority_t prio);
7627 fib_test_walk (void)
7629 fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {};
7630 fib_node_test_t *tc;
7635 vm = vlib_get_main();
7636 test_node_type = fib_node_register_new_type("fib-test", &fib_test_child_vft);
7639 * init a fake node on which we will add children
7641 fib_node_init(&fib_test_nodes[PARENT_INDEX].node,
7644 FOR_EACH_TEST_CHILD(tc)
7646 fib_node_init(&tc->node, test_node_type);
7647 fib_node_lock(&tc->node);
7650 tc->sibling = fib_node_child_add(test_node_type,
7652 test_node_type, ii);
7656 * enqueue a walk across the parents children.
7658 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7660 fib_walk_async(test_node_type, PARENT_INDEX,
7661 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7662 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7663 "Parent has %d children pre-walk",
7664 fib_node_list_get_size(PARENT()->fn_children));
7667 * give the walk a large amount of time so it gets to the end
7669 fib_walk_process_queues(vm, 1);
7671 FOR_EACH_TEST_CHILD(tc)
7673 FIB_TEST(1 == vec_len(tc->ctxs),
7674 "%d child visitsed %d times",
7675 ii, vec_len(tc->ctxs));
7678 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7679 "Queue is empty post walk");
7680 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7681 "Parent has %d children post walk",
7682 fib_node_list_get_size(PARENT()->fn_children));
7685 * walk again. should be no increase in the number of visits, since
7686 * the walk will have terminated.
7688 fib_walk_process_queues(vm, 1);
7690 FOR_EACH_TEST_CHILD(tc)
7692 FIB_TEST(0 == vec_len(tc->ctxs),
7693 "%d child visitsed %d times",
7694 ii, vec_len(tc->ctxs));
7698 * schedule a low and hig priority walk. expect the high to be performed
7700 * schedule the high prio walk first so that it is further from the head
7701 * of the dependency list. that way it won't merge with the low one.
7703 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7704 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7706 fib_walk_async(test_node_type, PARENT_INDEX,
7707 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7708 fib_walk_async(test_node_type, PARENT_INDEX,
7709 FIB_WALK_PRIORITY_LOW, &low_ctx);
7711 fib_walk_process_queues(vm, 1);
7713 FOR_EACH_TEST_CHILD(tc)
7715 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7716 "%d child visitsed by high prio walk", ii);
7717 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7718 "%d child visitsed by low prio walk", ii);
7721 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7722 "Queue is empty post prio walk");
7723 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7724 "Parent has %d children post prio walk",
7725 fib_node_list_get_size(PARENT()->fn_children));
7728 * schedule 2 walks of the same priority that can be megred.
7729 * expect that each child is thus visited only once.
7731 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7732 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7734 fib_walk_async(test_node_type, PARENT_INDEX,
7735 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7736 fib_walk_async(test_node_type, PARENT_INDEX,
7737 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7739 fib_walk_process_queues(vm, 1);
7741 FOR_EACH_TEST_CHILD(tc)
7743 FIB_TEST(1 == vec_len(tc->ctxs),
7744 "%d child visitsed %d times during merge walk",
7745 ii, vec_len(tc->ctxs));
7748 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7749 "Queue is empty post merge walk");
7750 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7751 "Parent has %d children post merge walk",
7752 fib_node_list_get_size(PARENT()->fn_children));
7755 * schedule 2 walks of the same priority that cannot be megred.
7756 * expect that each child is thus visited twice and in the order
7757 * in which the walks were scheduled.
7759 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7760 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7762 fib_walk_async(test_node_type, PARENT_INDEX,
7763 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7764 fib_walk_async(test_node_type, PARENT_INDEX,
7765 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7767 fib_walk_process_queues(vm, 1);
7769 FOR_EACH_TEST_CHILD(tc)
7771 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7772 "%d child visitsed by high prio walk", ii);
7773 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7774 "%d child visitsed by low prio walk", ii);
7777 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7778 "Queue is empty post no-merge walk");
7779 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7780 "Parent has %d children post no-merge walk",
7781 fib_node_list_get_size(PARENT()->fn_children));
7784 * schedule a walk that makes one one child progress.
7785 * we do this by giving the queue draining process zero
7786 * time quanta. it's a do..while loop, so it does something.
7788 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7790 fib_walk_async(test_node_type, PARENT_INDEX,
7791 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7792 fib_walk_process_queues(vm, 0);
7794 FOR_EACH_TEST_CHILD(tc)
7796 if (ii == N_TEST_CHILDREN)
7798 FIB_TEST(1 == vec_len(tc->ctxs),
7799 "%d child visitsed %d times in zero quanta walk",
7800 ii, vec_len(tc->ctxs));
7804 FIB_TEST(0 == vec_len(tc->ctxs),
7805 "%d child visitsed %d times in 0 quanta walk",
7806 ii, vec_len(tc->ctxs));
7809 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7810 "Queue is not empty post zero quanta walk");
7811 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7812 "Parent has %d children post zero qunta walk",
7813 fib_node_list_get_size(PARENT()->fn_children));
7818 fib_walk_process_queues(vm, 0);
7820 FOR_EACH_TEST_CHILD(tc)
7822 if (ii >= N_TEST_CHILDREN-1)
7824 FIB_TEST(1 == vec_len(tc->ctxs),
7825 "%d child visitsed %d times in 2nd zero quanta walk",
7826 ii, vec_len(tc->ctxs));
7830 FIB_TEST(0 == vec_len(tc->ctxs),
7831 "%d child visitsed %d times in 2nd 0 quanta walk",
7832 ii, vec_len(tc->ctxs));
7835 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7836 "Queue is not empty post zero quanta walk");
7837 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7838 "Parent has %d children post zero qunta walk",
7839 fib_node_list_get_size(PARENT()->fn_children));
7842 * schedule another walk that will catch-up and merge.
7844 fib_walk_async(test_node_type, PARENT_INDEX,
7845 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7846 fib_walk_process_queues(vm, 1);
7848 FOR_EACH_TEST_CHILD(tc)
7850 if (ii >= N_TEST_CHILDREN-1)
7852 FIB_TEST(2 == vec_len(tc->ctxs),
7853 "%d child visitsed %d times in 2nd zero quanta merge walk",
7854 ii, vec_len(tc->ctxs));
7859 FIB_TEST(1 == vec_len(tc->ctxs),
7860 "%d child visitsed %d times in 2nd 0 quanta merge walk",
7861 ii, vec_len(tc->ctxs));
7865 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7866 "Queue is not empty post 2nd zero quanta merge walk");
7867 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7868 "Parent has %d children post 2nd zero qunta merge walk",
7869 fib_node_list_get_size(PARENT()->fn_children));
7872 * park a async walk in the middle of the list, then have an sync walk catch
7873 * it. same expectations as async catches async.
7875 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7877 fib_walk_async(test_node_type, PARENT_INDEX,
7878 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7880 fib_walk_process_queues(vm, 0);
7881 fib_walk_process_queues(vm, 0);
7883 fib_walk_sync(test_node_type, PARENT_INDEX, &high_ctx);
7885 FOR_EACH_TEST_CHILD(tc)
7887 if (ii >= N_TEST_CHILDREN-1)
7889 FIB_TEST(2 == vec_len(tc->ctxs),
7890 "%d child visitsed %d times in sync catches async walk",
7891 ii, vec_len(tc->ctxs));
7896 FIB_TEST(1 == vec_len(tc->ctxs),
7897 "%d child visitsed %d times in sync catches async walk",
7898 ii, vec_len(tc->ctxs));
7902 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7903 "Queue is not empty post 2nd zero quanta merge walk");
7904 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7905 "Parent has %d children post 2nd zero qunta merge walk",
7906 fib_node_list_get_size(PARENT()->fn_children));
7909 * make the parent a child of one of its children, thus inducing a routing loop.
7911 fib_test_nodes[PARENT_INDEX].sibling =
7912 fib_node_child_add(test_node_type,
7913 1, // the first child
7918 * execute a sync walk from the parent. each child visited spawns more sync
7919 * walks. we expect the walk to terminate.
7921 fib_test_walk_spawns_walks = 1;
7923 fib_walk_sync(test_node_type, PARENT_INDEX, &high_ctx);
7925 FOR_EACH_TEST_CHILD(tc)
7928 * child 1 - which is last in the list - has the loop.
7929 * the other children a re thus visitsed first. the we meet
7930 * child 1. we go round the loop again, visting the other children.
7931 * then we meet the walk in the dep list and bail. child 1 is not visitsed
7936 FIB_TEST(1 == vec_len(tc->ctxs),
7937 "child %d visitsed %d times during looped sync walk",
7938 ii, vec_len(tc->ctxs));
7942 FIB_TEST(2 == vec_len(tc->ctxs),
7943 "child %d visitsed %d times during looped sync walk",
7944 ii, vec_len(tc->ctxs));
7948 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7949 "Parent has %d children post sync loop walk",
7950 fib_node_list_get_size(PARENT()->fn_children));
7953 * the walk doesn't reach the max depth because the infra knows that sync
7954 * meets sync implies a loop and bails early.
7956 FIB_TEST(high_ctx.fnbw_depth == 9,
7957 "Walk context depth %d post sync loop walk",
7958 high_ctx.fnbw_depth);
7961 * execute an async walk of the graph loop, with each child spawns sync walks
7963 high_ctx.fnbw_depth = 0;
7964 fib_walk_async(test_node_type, PARENT_INDEX,
7965 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7967 fib_walk_process_queues(vm, 1);
7969 FOR_EACH_TEST_CHILD(tc)
7972 * we don't really care how many times the children are visited, as long as
7973 * it is more than once.
7975 FIB_TEST(1 <= vec_len(tc->ctxs),
7976 "child %d visitsed %d times during looped aync spawns sync walk",
7977 ii, vec_len(tc->ctxs));
7982 * execute an async walk of the graph loop, with each child spawns async walks
7984 fib_test_walk_spawns_walks = 2;
7985 high_ctx.fnbw_depth = 0;
7986 fib_walk_async(test_node_type, PARENT_INDEX,
7987 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7989 fib_walk_process_queues(vm, 1);
7991 FOR_EACH_TEST_CHILD(tc)
7994 * we don't really care how many times the children are visited, as long as
7995 * it is more than once.
7997 FIB_TEST(1 <= vec_len(tc->ctxs),
7998 "child %d visitsed %d times during looped async spawns async walk",
7999 ii, vec_len(tc->ctxs));
8004 fib_node_child_remove(test_node_type,
8005 1, // the first child
8006 fib_test_nodes[PARENT_INDEX].sibling);
8011 FOR_EACH_TEST_CHILD(tc)
8013 fib_node_child_remove(test_node_type, PARENT_INDEX,
8015 fib_node_deinit(&tc->node);
8016 fib_node_unlock(&tc->node);
8018 fib_node_deinit(PARENT());
8021 * The parent will be destroyed when the last lock on it goes.
8022 * this test ensures all the walk objects are unlocking it.
8024 FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed),
8025 "Parent was destroyed");
8031 * declaration of the otherwise static callback functions
8033 void fib_bfd_notify (bfd_listen_event_e event,
8034 const bfd_session_t *session);
8035 void adj_bfd_notify (bfd_listen_event_e event,
8036 const bfd_session_t *session);
8039 * Test BFD session interaction with FIB
8044 fib_node_index_t fei;
8049 /* via 10.10.10.1 */
8050 ip46_address_t nh_10_10_10_1 = {
8051 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
8053 /* via 10.10.10.2 */
8054 ip46_address_t nh_10_10_10_2 = {
8055 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
8057 /* via 10.10.10.10 */
8058 ip46_address_t nh_10_10_10_10 = {
8059 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
8061 n_feis = fib_entry_pool_size();
8066 * add interface routes. we'll assume this works. it's tested elsewhere
8068 fib_prefix_t pfx_10_10_10_10_s_24 = {
8070 .fp_proto = FIB_PROTOCOL_IP4,
8071 .fp_addr = nh_10_10_10_10,
8074 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_24,
8075 FIB_SOURCE_INTERFACE,
8076 (FIB_ENTRY_FLAG_CONNECTED |
8077 FIB_ENTRY_FLAG_ATTACHED),
8080 tm->hw[0]->sw_if_index,
8081 ~0, // invalid fib index
8084 FIB_ROUTE_PATH_FLAG_NONE);
8086 fib_prefix_t pfx_10_10_10_10_s_32 = {
8088 .fp_proto = FIB_PROTOCOL_IP4,
8089 .fp_addr = nh_10_10_10_10,
8091 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_32,
8092 FIB_SOURCE_INTERFACE,
8093 (FIB_ENTRY_FLAG_CONNECTED |
8094 FIB_ENTRY_FLAG_LOCAL),
8097 tm->hw[0]->sw_if_index,
8098 ~0, // invalid fib index
8101 FIB_ROUTE_PATH_FLAG_NONE);
8104 * A BFD session via a neighbour we do not yet know
8106 bfd_session_t bfd_10_10_10_1 = {
8110 .peer_addr = nh_10_10_10_1,
8113 .hop_type = BFD_HOP_TYPE_MULTI,
8114 .local_state = BFD_STATE_init,
8117 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8120 * A new entry will be created that forwards via the adj
8122 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8125 tm->hw[0]->sw_if_index);
8126 fib_prefix_t pfx_10_10_10_1_s_32 = {
8127 .fp_addr = nh_10_10_10_1,
8129 .fp_proto = FIB_PROTOCOL_IP4,
8131 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
8134 .adj = ai_10_10_10_1,
8138 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
8139 FIB_TEST(!fib_test_validate_entry(fei,
8140 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8143 "BFD sourced %U via %U",
8144 format_fib_prefix, &pfx_10_10_10_1_s_32,
8145 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
8148 * Delete the BFD session. Expect the fib_entry to be removed
8150 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8152 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
8153 FIB_TEST(FIB_NODE_INDEX_INVALID == fei,
8154 "BFD sourced %U removed",
8155 format_fib_prefix, &pfx_10_10_10_1_s_32);
8158 * Add the BFD source back
8160 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8163 * source the entry via the ADJ fib
8165 fei = fib_table_entry_path_add(0,
8166 &pfx_10_10_10_1_s_32,
8168 FIB_ENTRY_FLAG_ATTACHED,
8171 tm->hw[0]->sw_if_index,
8172 ~0, // invalid fib index
8175 FIB_ROUTE_PATH_FLAG_NONE);
8178 * Delete the BFD session. Expect the fib_entry to remain
8180 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8182 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
8183 FIB_TEST(!fib_test_validate_entry(fei,
8184 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8187 "BFD sourced %U remains via %U",
8188 format_fib_prefix, &pfx_10_10_10_1_s_32,
8189 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
8192 * Add the BFD source back
8194 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8197 * Create another ADJ FIB
8199 fib_prefix_t pfx_10_10_10_2_s_32 = {
8200 .fp_addr = nh_10_10_10_2,
8202 .fp_proto = FIB_PROTOCOL_IP4,
8204 fib_table_entry_path_add(0,
8205 &pfx_10_10_10_2_s_32,
8207 FIB_ENTRY_FLAG_ATTACHED,
8210 tm->hw[0]->sw_if_index,
8211 ~0, // invalid fib index
8214 FIB_ROUTE_PATH_FLAG_NONE);
8216 * A BFD session for the new ADJ FIB
8218 bfd_session_t bfd_10_10_10_2 = {
8222 .peer_addr = nh_10_10_10_2,
8225 .hop_type = BFD_HOP_TYPE_MULTI,
8226 .local_state = BFD_STATE_init,
8229 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_2);
8232 * remove the adj-fib source whilst the session is present
8235 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
8236 fib_table_entry_path_add(0,
8237 &pfx_10_10_10_2_s_32,
8239 FIB_ENTRY_FLAG_ATTACHED,
8242 tm->hw[0]->sw_if_index,
8243 ~0, // invalid fib index
8246 FIB_ROUTE_PATH_FLAG_NONE);
8249 * Before adding a recursive via the BFD tracked ADJ-FIBs,
8250 * bring one of the sessions UP, leave the other down
8252 bfd_10_10_10_1.local_state = BFD_STATE_up;
8253 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8254 bfd_10_10_10_2.local_state = BFD_STATE_down;
8255 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8258 * A recursive prefix via both of the ADJ FIBs
8260 fib_prefix_t pfx_200_0_0_0_s_24 = {
8261 .fp_proto = FIB_PROTOCOL_IP4,
8264 .ip4.as_u32 = clib_host_to_net_u32(0xc8000000),
8267 const dpo_id_t *dpo_10_10_10_1, *dpo_10_10_10_2;
8270 fib_entry_contribute_ip_forwarding(
8271 fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32));
8273 fib_entry_contribute_ip_forwarding(
8274 fib_table_lookup_exact_match(0, &pfx_10_10_10_2_s_32));
8276 fib_test_lb_bucket_t lb_o_10_10_10_1 = {
8279 .lb = dpo_10_10_10_1->dpoi_index,
8282 fib_test_lb_bucket_t lb_o_10_10_10_2 = {
8285 .lb = dpo_10_10_10_2->dpoi_index,
8290 * A prefix via the adj-fib that is BFD down => DROP
8292 fei = fib_table_entry_path_add(0,
8293 &pfx_200_0_0_0_s_24,
8295 FIB_ENTRY_FLAG_NONE,
8299 0, // default fib index
8302 FIB_ROUTE_PATH_FLAG_NONE);
8303 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8304 "%U resolves via drop",
8305 format_fib_prefix, &pfx_200_0_0_0_s_24);
8308 * add a path via the UP BFD adj-fib.
8309 * we expect that the DOWN BFD ADJ FIB is not used.
8311 fei = fib_table_entry_path_add(0,
8312 &pfx_200_0_0_0_s_24,
8314 FIB_ENTRY_FLAG_NONE,
8318 0, // default fib index
8321 FIB_ROUTE_PATH_FLAG_NONE);
8323 FIB_TEST(!fib_test_validate_entry(fei,
8324 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8327 "Recursive %U only UP BFD adj-fibs",
8328 format_fib_prefix, &pfx_200_0_0_0_s_24);
8331 * Send a BFD state change to UP - both sessions are now up
8332 * the recursive prefix should LB over both
8334 bfd_10_10_10_2.local_state = BFD_STATE_up;
8335 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8338 FIB_TEST(!fib_test_validate_entry(fei,
8339 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8343 "Recursive %U via both UP BFD adj-fibs",
8344 format_fib_prefix, &pfx_200_0_0_0_s_24);
8347 * Send a BFD state change to DOWN
8348 * the recursive prefix should exclude the down
8350 bfd_10_10_10_2.local_state = BFD_STATE_down;
8351 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8354 FIB_TEST(!fib_test_validate_entry(fei,
8355 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8358 "Recursive %U via only UP",
8359 format_fib_prefix, &pfx_200_0_0_0_s_24);
8362 * Delete the BFD session while it is in the DOWN state.
8363 * FIB should consider the entry's state as back up
8365 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_2);
8367 FIB_TEST(!fib_test_validate_entry(fei,
8368 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8372 "Recursive %U via both UP BFD adj-fibs post down session delete",
8373 format_fib_prefix, &pfx_200_0_0_0_s_24);
8376 * Delete the BFD other session while it is in the UP state.
8378 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8380 FIB_TEST(!fib_test_validate_entry(fei,
8381 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8385 "Recursive %U via both UP BFD adj-fibs post up session delete",
8386 format_fib_prefix, &pfx_200_0_0_0_s_24);
8391 fib_table_entry_delete(0, &pfx_200_0_0_0_s_24, FIB_SOURCE_API);
8392 fib_table_entry_delete(0, &pfx_10_10_10_1_s_32, FIB_SOURCE_ADJ);
8393 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
8395 fib_table_entry_delete(0, &pfx_10_10_10_10_s_32, FIB_SOURCE_INTERFACE);
8396 fib_table_entry_delete(0, &pfx_10_10_10_10_s_24, FIB_SOURCE_INTERFACE);
8398 adj_unlock(ai_10_10_10_1);
8400 * test no-one left behind
8402 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8403 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8406 * Single-hop BFD tests
8408 bfd_10_10_10_1.hop_type = BFD_HOP_TYPE_SINGLE;
8409 bfd_10_10_10_1.udp.key.sw_if_index = tm->hw[0]->sw_if_index;
8411 ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8414 tm->hw[0]->sw_if_index);
8415 bfd_10_10_10_1.udp.adj_index = ai_10_10_10_1;
8417 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8420 * whilst the BFD session is not signalled, the adj is up
8422 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on uninit session");
8425 * bring the BFD session up
8427 bfd_10_10_10_1.local_state = BFD_STATE_up;
8428 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8429 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on UP session");
8432 * bring the BFD session down
8434 bfd_10_10_10_1.local_state = BFD_STATE_down;
8435 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8436 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on DOWN session");
8439 * add an attached next hop FIB entry via the down adj
8441 fib_prefix_t pfx_5_5_5_5_s_32 = {
8444 .as_u32 = clib_host_to_net_u32(0x05050505),
8448 .fp_proto = FIB_PROTOCOL_IP4,
8451 fei = fib_table_entry_path_add(0,
8454 FIB_ENTRY_FLAG_NONE,
8457 tm->hw[0]->sw_if_index,
8458 ~0, // invalid fib index
8461 FIB_ROUTE_PATH_FLAG_NONE);
8462 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8463 "%U resolves via drop",
8464 format_fib_prefix, &pfx_5_5_5_5_s_32);
8467 * Add a path via an ADJ that is up
8469 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8472 tm->hw[0]->sw_if_index);
8474 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
8477 .adj = ai_10_10_10_2,
8480 adj_o_10_10_10_1.adj.adj = ai_10_10_10_1;
8482 fei = fib_table_entry_path_add(0,
8485 FIB_ENTRY_FLAG_NONE,
8488 tm->hw[0]->sw_if_index,
8489 ~0, // invalid fib index
8492 FIB_ROUTE_PATH_FLAG_NONE);
8494 FIB_TEST(!fib_test_validate_entry(fei,
8495 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8498 "BFD sourced %U via %U",
8499 format_fib_prefix, &pfx_5_5_5_5_s_32,
8500 format_ip_adjacency, ai_10_10_10_2, FORMAT_IP_ADJACENCY_NONE);
8503 * Bring up the down session - should now LB
8505 bfd_10_10_10_1.local_state = BFD_STATE_up;
8506 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8507 FIB_TEST(!fib_test_validate_entry(fei,
8508 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8512 "BFD sourced %U via noth adjs",
8513 format_fib_prefix, &pfx_5_5_5_5_s_32);
8516 * remove the BFD session state from the adj
8518 adj_bfd_notify(BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8523 fib_table_entry_delete(0, &pfx_5_5_5_5_s_32, FIB_SOURCE_CLI);
8524 adj_unlock(ai_10_10_10_1);
8525 adj_unlock(ai_10_10_10_2);
8528 * test no-one left behind
8530 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8531 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8539 const mpls_label_t deag_label = 50;
8540 adj_index_t ai_mpls_10_10_10_1;
8541 dpo_id_t dpo = DPO_INVALID;
8542 const u32 lfib_index = 0;
8543 const u32 fib_index = 0;
8544 const dpo_id_t *dpo1;
8545 fib_node_index_t lfe;
8552 lb_count = pool_elts(load_balance_pool);
8554 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
8558 * MPLS enable an interface so we get the MPLS table created
8560 mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL);
8561 mpls_sw_interface_enable_disable(&mpls_main,
8562 tm->hw[0]->sw_if_index,
8565 ip46_address_t nh_10_10_10_1 = {
8566 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
8568 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8571 tm->hw[0]->sw_if_index);
8574 * Test the specials stack properly.
8576 fib_prefix_t exp_null_v6_pfx = {
8577 .fp_proto = FIB_PROTOCOL_MPLS,
8579 .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8580 .fp_payload_proto = DPO_PROTO_IP6,
8582 lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx);
8583 FIB_TEST((FIB_NODE_INDEX_INVALID != lfe),
8585 format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8586 format_mpls_eos_bit, MPLS_EOS);
8587 fib_entry_contribute_forwarding(lfe,
8588 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8590 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8591 lkd = lookup_dpo_get(dpo1->dpoi_index);
8593 FIB_TEST((fib_index == lkd->lkd_fib_index),
8594 "%U/%U is deag in %d %U",
8595 format_mpls_unicast_label, deag_label,
8596 format_mpls_eos_bit, MPLS_EOS,
8598 format_dpo_id, &dpo, 0);
8599 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8600 "%U/%U is dst deag",
8601 format_mpls_unicast_label, deag_label,
8602 format_mpls_eos_bit, MPLS_EOS);
8603 FIB_TEST((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table),
8604 "%U/%U is lookup in interface's table",
8605 format_mpls_unicast_label, deag_label,
8606 format_mpls_eos_bit, MPLS_EOS);
8607 FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto),
8608 "%U/%U is %U dst deag",
8609 format_mpls_unicast_label, deag_label,
8610 format_mpls_eos_bit, MPLS_EOS,
8611 format_dpo_proto, lkd->lkd_proto);
8614 * A route deag route for EOS
8616 fib_prefix_t pfx = {
8617 .fp_proto = FIB_PROTOCOL_MPLS,
8619 .fp_label = deag_label,
8620 .fp_payload_proto = DPO_PROTO_IP4,
8622 mpls_disp_dpo_t *mdd;
8623 lfe = fib_table_entry_path_add(lfib_index,
8626 FIB_ENTRY_FLAG_NONE,
8633 FIB_ROUTE_PATH_FLAG_NONE);
8635 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8637 format_mpls_unicast_label, deag_label,
8638 format_mpls_eos_bit, MPLS_EOS);
8640 fib_entry_contribute_forwarding(lfe,
8641 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8643 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8644 mdd = mpls_disp_dpo_get(dpo1->dpoi_index);
8646 FIB_TEST((FIB_MPLS_LSP_MODE_PIPE == mdd->mdd_mode),
8647 "%U/%U disp is pipe mode",
8648 format_mpls_unicast_label, deag_label,
8649 format_mpls_eos_bit, MPLS_EOS);
8651 lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index);
8653 FIB_TEST((fib_index == lkd->lkd_fib_index),
8654 "%U/%U is deag in %d %U",
8655 format_mpls_unicast_label, deag_label,
8656 format_mpls_eos_bit, MPLS_EOS,
8658 format_dpo_id, &dpo, 0);
8659 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8660 "%U/%U is dst deag",
8661 format_mpls_unicast_label, deag_label,
8662 format_mpls_eos_bit, MPLS_EOS);
8663 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8664 "%U/%U is %U dst deag",
8665 format_mpls_unicast_label, deag_label,
8666 format_mpls_eos_bit, MPLS_EOS,
8667 format_dpo_proto, lkd->lkd_proto);
8669 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8671 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8673 "%U/%U not present",
8674 format_mpls_unicast_label, deag_label,
8675 format_mpls_eos_bit, MPLS_EOS);
8679 * A route deag route for EOS with LSP mode uniform
8681 fib_mpls_label_t *l_pops = NULL, l_pop = {
8682 .fml_value = MPLS_LABEL_POP,
8683 .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM,
8685 vec_add1(l_pops, l_pop);
8686 lfe = fib_table_entry_path_add(lfib_index,
8689 FIB_ENTRY_FLAG_NONE,
8696 FIB_ROUTE_PATH_FLAG_NONE);
8698 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8700 format_mpls_unicast_label, deag_label,
8701 format_mpls_eos_bit, MPLS_EOS);
8703 fib_entry_contribute_forwarding(lfe,
8704 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8706 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8707 mdd = mpls_disp_dpo_get(dpo1->dpoi_index);
8709 FIB_TEST((FIB_MPLS_LSP_MODE_UNIFORM == mdd->mdd_mode),
8710 "%U/%U disp is uniform mode",
8711 format_mpls_unicast_label, deag_label,
8712 format_mpls_eos_bit, MPLS_EOS);
8714 lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index);
8716 FIB_TEST((fib_index == lkd->lkd_fib_index),
8717 "%U/%U is deag in %d %U",
8718 format_mpls_unicast_label, deag_label,
8719 format_mpls_eos_bit, MPLS_EOS,
8721 format_dpo_id, &dpo, 0);
8722 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8723 "%U/%U is dst deag",
8724 format_mpls_unicast_label, deag_label,
8725 format_mpls_eos_bit, MPLS_EOS);
8726 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8727 "%U/%U is %U dst deag",
8728 format_mpls_unicast_label, deag_label,
8729 format_mpls_eos_bit, MPLS_EOS,
8730 format_dpo_proto, lkd->lkd_proto);
8732 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8734 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8736 "%U/%U not present",
8737 format_mpls_unicast_label, deag_label,
8738 format_mpls_eos_bit, MPLS_EOS);
8742 * A route deag route for non-EOS
8744 pfx.fp_eos = MPLS_NON_EOS;
8745 lfe = fib_table_entry_path_add(lfib_index,
8748 FIB_ENTRY_FLAG_NONE,
8755 FIB_ROUTE_PATH_FLAG_NONE);
8757 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8759 format_mpls_unicast_label, deag_label,
8760 format_mpls_eos_bit, MPLS_NON_EOS);
8762 fib_entry_contribute_forwarding(lfe,
8763 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8765 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8766 lkd = lookup_dpo_get(dpo1->dpoi_index);
8768 FIB_TEST((fib_index == lkd->lkd_fib_index),
8769 "%U/%U is deag in %d %U",
8770 format_mpls_unicast_label, deag_label,
8771 format_mpls_eos_bit, MPLS_NON_EOS,
8773 format_dpo_id, &dpo, 0);
8774 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8775 "%U/%U is dst deag",
8776 format_mpls_unicast_label, deag_label,
8777 format_mpls_eos_bit, MPLS_NON_EOS);
8779 FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto),
8780 "%U/%U is %U dst deag",
8781 format_mpls_unicast_label, deag_label,
8782 format_mpls_eos_bit, MPLS_NON_EOS,
8783 format_dpo_proto, lkd->lkd_proto);
8785 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8787 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8789 "%U/%U not present",
8790 format_mpls_unicast_label, deag_label,
8791 format_mpls_eos_bit, MPLS_EOS);
8798 fib_prefix_t pfx_1200 = {
8800 .fp_proto = FIB_PROTOCOL_MPLS,
8802 .fp_eos = MPLS_NON_EOS,
8804 fib_test_lb_bucket_t neos_o_10_10_10_1 = {
8805 .type = FT_LB_LABEL_STACK_O_ADJ,
8806 .label_stack_o_adj = {
8807 .adj = ai_mpls_10_10_10_1,
8808 .label_stack_size = 4,
8812 .eos = MPLS_NON_EOS,
8815 dpo_id_t neos_1200 = DPO_INVALID;
8816 dpo_id_t ip_1200 = DPO_INVALID;
8817 fib_mpls_label_t *l200 = NULL;
8819 for (ii = 0; ii < 4; ii++)
8821 fib_mpls_label_t fml = {
8822 .fml_value = 200 + (ii * 100),
8824 vec_add1(l200, fml);
8827 lfe = fib_table_entry_update_one_path(fib_index,
8830 FIB_ENTRY_FLAG_NONE,
8833 tm->hw[0]->sw_if_index,
8834 ~0, // invalid fib index
8837 FIB_ROUTE_PATH_FLAG_NONE);
8839 FIB_TEST(!fib_test_validate_entry(lfe,
8840 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8842 &neos_o_10_10_10_1),
8843 "1200/0 LB 1 buckets via: "
8847 * A recursive route via the MPLS x-connect
8849 fib_prefix_t pfx_2_2_2_3_s_32 = {
8851 .fp_proto = FIB_PROTOCOL_IP4,
8853 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
8856 fib_route_path_t *rpaths = NULL, rpath = {
8857 .frp_proto = DPO_PROTO_MPLS,
8858 .frp_local_label = 1200,
8859 .frp_eos = MPLS_NON_EOS,
8860 .frp_sw_if_index = ~0, // recurive
8861 .frp_fib_index = 0, // Default MPLS fib
8863 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
8864 .frp_label_stack = NULL,
8866 vec_add1(rpaths, rpath);
8868 fib_table_entry_path_add2(fib_index,
8871 FIB_ENTRY_FLAG_NONE,
8875 * A labelled recursive route via the MPLS x-connect
8877 fib_prefix_t pfx_2_2_2_4_s_32 = {
8879 .fp_proto = FIB_PROTOCOL_IP4,
8881 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
8884 fib_mpls_label_t *l999 = NULL, fml_999 = {
8887 vec_add1(l999, fml_999);
8888 rpaths[0].frp_label_stack = l999,
8890 fib_table_entry_path_add2(fib_index,
8893 FIB_ENTRY_FLAG_NONE,
8896 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8897 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8899 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8900 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8903 fib_test_lb_bucket_t ip_o_1200 = {
8906 .lb = ip_1200.dpoi_index,
8909 fib_test_lb_bucket_t mpls_o_1200 = {
8910 .type = FT_LB_LABEL_O_LB,
8912 .lb = neos_1200.dpoi_index,
8918 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
8919 FIB_TEST(!fib_test_validate_entry(lfe,
8920 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8923 "2.2.2.2.3/32 LB 1 buckets via: label 1200 EOS");
8924 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
8925 FIB_TEST(!fib_test_validate_entry(lfe,
8926 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8929 "2.2.2.2.4/32 LB 1 buckets via: label 1200 non-EOS");
8931 fib_table_entry_delete(fib_index, &pfx_1200, FIB_SOURCE_API);
8932 fib_table_entry_delete(fib_index, &pfx_2_2_2_3_s_32, FIB_SOURCE_API);
8933 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8935 dpo_reset(&neos_1200);
8936 dpo_reset(&ip_1200);
8939 * A recursive via a label that does not exist
8941 fib_test_lb_bucket_t bucket_drop = {
8944 .adj = DPO_PROTO_IP4,
8947 fib_test_lb_bucket_t mpls_bucket_drop = {
8950 .adj = DPO_PROTO_MPLS,
8954 rpaths[0].frp_label_stack = NULL;
8955 lfe = fib_table_entry_path_add2(fib_index,
8958 FIB_ENTRY_FLAG_NONE,
8961 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8962 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8964 ip_o_1200.lb.lb = ip_1200.dpoi_index;
8966 FIB_TEST(!fib_test_validate_entry(lfe,
8967 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8970 "2.2.2.2.4/32 LB 1 buckets via: drop");
8971 lfe = fib_table_lookup(fib_index, &pfx_1200);
8972 FIB_TEST(!fib_test_validate_entry(lfe,
8973 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8976 "1200/neos LB 1 buckets via: ip4-DROP");
8977 FIB_TEST(!fib_test_validate_entry(lfe,
8978 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8981 "1200/neos LB 1 buckets via: mpls-DROP");
8983 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8985 dpo_reset(&ip_1200);
8988 * An rx-interface route.
8989 * like the tail of an mcast LSP
8991 dpo_id_t idpo = DPO_INVALID;
8993 interface_rx_dpo_add_or_lock(DPO_PROTO_IP4,
8994 tm->hw[0]->sw_if_index,
8997 fib_prefix_t pfx_2500 = {
8999 .fp_proto = FIB_PROTOCOL_MPLS,
9002 .fp_payload_proto = DPO_PROTO_IP4,
9004 fib_test_lb_bucket_t rx_intf_0 = {
9007 .adj = idpo.dpoi_index,
9011 lfe = fib_table_entry_update_one_path(fib_index,
9014 FIB_ENTRY_FLAG_NONE,
9017 tm->hw[0]->sw_if_index,
9018 ~0, // invalid fib index
9021 FIB_ROUTE_PATH_INTF_RX);
9022 FIB_TEST(!fib_test_validate_entry(lfe,
9023 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9026 "2500 rx-interface 0");
9027 fib_table_entry_delete(fib_index, &pfx_2500, FIB_SOURCE_API);
9030 * An MPLS mulicast entry
9032 fib_prefix_t pfx_3500 = {
9034 .fp_proto = FIB_PROTOCOL_MPLS,
9037 .fp_payload_proto = DPO_PROTO_IP4,
9039 fib_test_rep_bucket_t mc_0 = {
9040 .type = FT_REP_LABEL_O_ADJ,
9042 .adj = ai_mpls_10_10_10_1,
9047 fib_test_rep_bucket_t mc_intf_0 = {
9048 .type = FT_REP_INTF,
9050 .adj = idpo.dpoi_index,
9053 fib_mpls_label_t *l3300 = NULL, fml_3300 = {
9056 vec_add1(l3300, fml_3300);
9058 lfe = fib_table_entry_update_one_path(lfib_index,
9061 FIB_ENTRY_FLAG_MULTICAST,
9064 tm->hw[0]->sw_if_index,
9065 ~0, // invalid fib index
9068 FIB_ROUTE_PATH_FLAG_NONE);
9069 FIB_TEST(!fib_test_validate_entry(lfe,
9070 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9073 "3500 via replicate over 10.10.10.1");
9076 * MPLS Bud-node. Add a replication via an interface-receieve path
9078 lfe = fib_table_entry_path_add(lfib_index,
9081 FIB_ENTRY_FLAG_MULTICAST,
9084 tm->hw[0]->sw_if_index,
9085 ~0, // invalid fib index
9088 FIB_ROUTE_PATH_INTF_RX);
9089 FIB_TEST(!fib_test_validate_entry(lfe,
9090 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9094 "3500 via replicate over 10.10.10.1 and interface-rx");
9097 * Add a replication via an interface-free for-us path
9099 fib_test_rep_bucket_t mc_disp = {
9100 .type = FT_REP_DISP_MFIB_LOOKUP,
9102 .adj = idpo.dpoi_index,
9105 lfe = fib_table_entry_path_add(lfib_index,
9108 FIB_ENTRY_FLAG_MULTICAST,
9115 FIB_ROUTE_PATH_RPF_ID);
9116 FIB_TEST(!fib_test_validate_entry(lfe,
9117 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9122 "3500 via replicate over 10.10.10.1 and interface-rx");
9126 fib_table_entry_delete(fib_index, &pfx_3500, FIB_SOURCE_API);
9132 mpls_sw_interface_enable_disable(&mpls_main,
9133 tm->hw[0]->sw_if_index,
9135 mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
9137 FIB_TEST(0 == pool_elts(mpls_disp_dpo_pool),
9138 "mpls_disp_dpo resources freed %d of %d",
9139 0, pool_elts(mpls_disp_dpo_pool));
9140 FIB_TEST(lb_count == pool_elts(load_balance_pool),
9141 "Load-balance resources freed %d of %d",
9142 lb_count, pool_elts(load_balance_pool));
9143 FIB_TEST(0 == pool_elts(interface_rx_dpo_pool),
9144 "interface_rx_dpo resources freed %d of %d",
9145 0, pool_elts(interface_rx_dpo_pool));
9151 fib_test_inherit (void)
9153 fib_node_index_t fei;
9160 for (i = 0; i <= 2; i++)
9162 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[i]->sw_if_index, 0);
9163 fib_table_bind (FIB_PROTOCOL_IP6, tm->hw[i]->sw_if_index, 0);
9165 n_feis = fib_entry_pool_size();
9167 const ip46_address_t nh_10_10_10_1 = {
9168 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
9170 const ip46_address_t nh_10_10_10_2 = {
9171 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
9173 const ip46_address_t nh_10_10_10_3 = {
9174 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
9176 const ip46_address_t nh_10_10_10_16 = {
9177 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a10),
9179 const ip46_address_t nh_10_10_10_20 = {
9180 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a14),
9182 const ip46_address_t nh_10_10_10_21 = {
9183 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a15),
9185 const ip46_address_t nh_10_10_10_22 = {
9186 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a16),
9188 const ip46_address_t nh_10_10_10_255 = {
9189 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0aff),
9191 const ip46_address_t nh_10_10_10_0 = {
9192 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a00),
9194 const ip46_address_t nh_10_10_0_0 = {
9195 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0000),
9197 const ip46_address_t nh_11_11_11_11 = {
9198 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
9200 const ip46_address_t nh_11_11_11_0 = {
9201 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b00),
9205 * prefixes at the base of a sub-tree
9207 const fib_prefix_t pfx_10_10_10_21_s_32 = {
9209 .fp_proto = FIB_PROTOCOL_IP4,
9210 .fp_addr = nh_10_10_10_21,
9212 const fib_prefix_t pfx_10_10_10_22_s_32 = {
9214 .fp_proto = FIB_PROTOCOL_IP4,
9215 .fp_addr = nh_10_10_10_22,
9217 const fib_prefix_t pfx_10_10_10_255_s_32 = {
9219 .fp_proto = FIB_PROTOCOL_IP4,
9220 .fp_addr = nh_10_10_10_255,
9222 const u32 N_PLS = fib_path_list_pool_size();
9224 fib_table_entry_special_add(0,
9225 &pfx_10_10_10_21_s_32,
9227 FIB_ENTRY_FLAG_DROP);
9228 fib_table_entry_special_add(0,
9229 &pfx_10_10_10_22_s_32,
9231 FIB_ENTRY_FLAG_DROP);
9232 fib_table_entry_special_add(0,
9233 &pfx_10_10_10_255_s_32,
9235 FIB_ENTRY_FLAG_DROP);
9238 * source an entry that pushes its state down the sub-tree
9240 const fib_prefix_t pfx_10_10_10_16_s_28 = {
9242 .fp_proto = FIB_PROTOCOL_IP4,
9243 .fp_addr = nh_10_10_10_16,
9245 fib_table_entry_update_one_path(0,
9246 &pfx_10_10_10_16_s_28,
9248 FIB_ENTRY_FLAG_COVERED_INHERIT,
9251 tm->hw[0]->sw_if_index,
9255 FIB_ROUTE_PATH_FLAG_NONE);
9258 * this covering entry and all those below it should have
9259 * the same forwarding information.
9261 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9264 tm->hw[0]->sw_if_index);
9265 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
9268 .adj = ai_10_10_10_1,
9272 fei = fib_table_lookup(0, &pfx_10_10_10_16_s_28);
9273 FIB_TEST(!fib_test_validate_entry(fei,
9274 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9277 "%U via 10.10.10.1",
9278 format_fib_prefix, &pfx_10_10_10_16_s_28);
9279 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9280 FIB_TEST(!fib_test_validate_entry(fei,
9281 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9284 "%U via 10.10.10.1",
9285 format_fib_prefix, &pfx_10_10_10_21_s_32);
9286 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9287 FIB_TEST(!fib_test_validate_entry(fei,
9288 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9291 "%U via 10.10.10.1",
9292 format_fib_prefix, &pfx_10_10_10_22_s_32);
9293 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9294 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9295 "%U resolves via drop",
9296 format_fib_prefix, &pfx_10_10_10_255_s_32);
9299 * remove the inherting cover - covereds go back to drop
9301 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_API);
9303 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9304 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9305 "%U resolves via drop",
9306 format_fib_prefix, &pfx_10_10_10_21_s_32);
9309 * source an entry that pushes its state down the sub-tree
9311 const fib_prefix_t pfx_10_10_10_0_s_24 = {
9313 .fp_proto = FIB_PROTOCOL_IP4,
9314 .fp_addr = nh_10_10_10_0,
9316 fib_table_entry_update_one_path(0,
9317 &pfx_10_10_10_0_s_24,
9319 FIB_ENTRY_FLAG_COVERED_INHERIT,
9322 tm->hw[0]->sw_if_index,
9326 FIB_ROUTE_PATH_FLAG_NONE);
9329 * whole sub-tree now covered
9331 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9332 FIB_TEST(!fib_test_validate_entry(fei,
9333 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9336 "%U via 10.10.10.1",
9337 format_fib_prefix, &pfx_10_10_10_0_s_24);
9338 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9339 FIB_TEST(!fib_test_validate_entry(fei,
9340 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9343 "%U via 10.10.10.1",
9344 format_fib_prefix, &pfx_10_10_10_21_s_32);
9345 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9346 FIB_TEST(!fib_test_validate_entry(fei,
9347 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9350 "%U via 10.10.10.1",
9351 format_fib_prefix, &pfx_10_10_10_22_s_32);
9352 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9353 FIB_TEST(!fib_test_validate_entry(fei,
9354 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9357 "%U via 10.10.10.1",
9358 format_fib_prefix, &pfx_10_10_10_255_s_32);
9361 * insert a more specific into the sub-tree - expect inheritance
9362 * this one is directly covered by the root
9364 fib_table_entry_special_add(0,
9365 &pfx_10_10_10_16_s_28,
9367 FIB_ENTRY_FLAG_DROP);
9368 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9369 FIB_TEST(!fib_test_validate_entry(fei,
9370 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9373 "%U via 10.10.10.1",
9374 format_fib_prefix, &pfx_10_10_10_16_s_28);
9377 * insert a more specific into the sub-tree - expect inheritance
9378 * this one is indirectly covered by the root
9380 const fib_prefix_t pfx_10_10_10_20_s_30 = {
9382 .fp_proto = FIB_PROTOCOL_IP4,
9383 .fp_addr = nh_10_10_10_20,
9385 fib_table_entry_special_add(0,
9386 &pfx_10_10_10_20_s_30,
9388 FIB_ENTRY_FLAG_DROP);
9389 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_20_s_30);
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_20_s_30);
9398 * remove the prefix from the middle of the sub-tree
9399 * the inherited source will be the only one remaining - expect
9400 * it to be withdrawn and hence the prefix is removed.
9402 fib_table_entry_special_remove(0,
9403 &pfx_10_10_10_20_s_30,
9405 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_20_s_30);
9406 FIB_TEST((FIB_NODE_INDEX_INVALID == fei),
9408 format_fib_prefix, &pfx_10_10_10_20_s_30);
9411 * inheriting source is modifed - expect the modification to be present
9412 * throughout the sub-tree
9414 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9417 tm->hw[0]->sw_if_index);
9418 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
9421 .adj = ai_10_10_10_2,
9425 fib_table_entry_update_one_path(0,
9426 &pfx_10_10_10_0_s_24,
9428 FIB_ENTRY_FLAG_COVERED_INHERIT,
9431 tm->hw[0]->sw_if_index,
9435 FIB_ROUTE_PATH_FLAG_NONE);
9436 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9437 FIB_TEST(!fib_test_validate_entry(fei,
9438 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9441 "%U via 10.10.10.2",
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.2",
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.2",
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.2",
9463 format_fib_prefix, &pfx_10_10_10_0_s_24);
9465 fib_source_t hi_src = fib_source_allocate("test", 0x50,
9466 FIB_SOURCE_BH_SIMPLE);
9469 * add the source that replaces inherited state.
9470 * inheriting source is not the best, so it doesn't push state.
9472 fib_table_entry_update_one_path(0,
9473 &pfx_10_10_10_0_s_24,
9475 FIB_ENTRY_FLAG_NONE,
9478 tm->hw[0]->sw_if_index,
9482 FIB_ROUTE_PATH_FLAG_NONE);
9483 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9484 FIB_TEST(!fib_test_validate_entry(fei,
9485 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9488 "%U via 10.10.10.1",
9489 format_fib_prefix, &pfx_10_10_10_0_s_24);
9491 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9492 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9493 "%U resolves via drop",
9494 format_fib_prefix, &pfx_10_10_10_21_s_32);
9495 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9496 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9497 "%U resolves via drop",
9498 format_fib_prefix, &pfx_10_10_10_22_s_32);
9499 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9500 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9501 "%U resolves via drop",
9502 format_fib_prefix, &pfx_10_10_10_255_s_32);
9503 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9504 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9505 "%U resolves via drop",
9506 format_fib_prefix, &pfx_10_10_10_16_s_28);
9509 * withdraw the higher priority source and expect the inherited to return
9510 * throughout the sub-tree
9512 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, hi_src);
9514 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9515 FIB_TEST(!fib_test_validate_entry(fei,
9516 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9519 "%U via 10.10.10.2",
9520 format_fib_prefix, &pfx_10_10_10_21_s_32);
9521 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9522 FIB_TEST(!fib_test_validate_entry(fei,
9523 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9526 "%U via 10.10.10.2",
9527 format_fib_prefix, &pfx_10_10_10_22_s_32);
9528 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9529 FIB_TEST(!fib_test_validate_entry(fei,
9530 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9533 "%U via 10.10.10.2",
9534 format_fib_prefix, &pfx_10_10_10_255_s_32);
9535 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9536 FIB_TEST(!fib_test_validate_entry(fei,
9537 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9540 "%U via 10.10.10.2",
9541 format_fib_prefix, &pfx_10_10_10_0_s_24);
9542 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9543 FIB_TEST(!fib_test_validate_entry(fei,
9544 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9547 "%U via 10.10.10.2",
9548 format_fib_prefix, &pfx_10_10_10_16_s_28);
9551 * source a covered entry in the sub-tree with the same inherting source
9552 * - expect that it now owns the sub-tree and thus over-rides its cover
9554 fib_table_entry_update_one_path(0,
9555 &pfx_10_10_10_16_s_28,
9557 FIB_ENTRY_FLAG_COVERED_INHERIT,
9560 tm->hw[0]->sw_if_index,
9564 FIB_ROUTE_PATH_FLAG_NONE);
9565 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9566 FIB_TEST(!fib_test_validate_entry(fei,
9567 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9570 "%U via 10.10.10.1",
9571 format_fib_prefix, &pfx_10_10_10_16_s_28);
9572 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9573 FIB_TEST(!fib_test_validate_entry(fei,
9574 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9577 "%U via 10.10.10.2",
9578 format_fib_prefix, &pfx_10_10_10_22_s_32);
9579 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9580 FIB_TEST(!fib_test_validate_entry(fei,
9581 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9584 "%U via 10.10.10.2",
9585 format_fib_prefix, &pfx_10_10_10_21_s_32);
9587 /* these two unaffected by the sub-tree change */
9588 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9589 FIB_TEST(!fib_test_validate_entry(fei,
9590 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9593 "%U via 10.10.10.2",
9594 format_fib_prefix, &pfx_10_10_10_255_s_32);
9595 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9596 FIB_TEST(!fib_test_validate_entry(fei,
9597 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9600 "%U via 10.10.10.2",
9601 format_fib_prefix, &pfx_10_10_10_0_s_24);
9604 * removes the more specific, expect the /24 to now re-owns the sub-tree
9606 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_API);
9608 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9609 FIB_TEST(!fib_test_validate_entry(fei,
9610 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9613 "%U via 10.10.10.2",
9614 format_fib_prefix, &pfx_10_10_10_16_s_28);
9615 FIB_TEST(!fib_test_validate_entry(fei,
9616 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9619 "%U via 10.10.10.2",
9620 format_fib_prefix, &pfx_10_10_10_21_s_32);
9621 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9622 FIB_TEST(!fib_test_validate_entry(fei,
9623 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9626 "%U via 10.10.10.2",
9627 format_fib_prefix, &pfx_10_10_10_22_s_32);
9628 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9629 FIB_TEST(!fib_test_validate_entry(fei,
9630 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9633 "%U via 10.10.10.2",
9634 format_fib_prefix, &pfx_10_10_10_255_s_32);
9635 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9636 FIB_TEST(!fib_test_validate_entry(fei,
9637 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9640 "%U via 10.10.10.2",
9641 format_fib_prefix, &pfx_10_10_10_0_s_24);
9643 * modify the /24. expect the new forwarding to be pushed down
9645 fib_table_entry_update_one_path(0,
9646 &pfx_10_10_10_0_s_24,
9648 FIB_ENTRY_FLAG_COVERED_INHERIT,
9651 tm->hw[0]->sw_if_index,
9655 FIB_ROUTE_PATH_FLAG_NONE);
9656 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9657 FIB_TEST(!fib_test_validate_entry(fei,
9658 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9661 "%U via 10.10.10.1",
9662 format_fib_prefix, &pfx_10_10_10_16_s_28);
9663 FIB_TEST(!fib_test_validate_entry(fei,
9664 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9667 "%U via 10.10.10.1",
9668 format_fib_prefix, &pfx_10_10_10_21_s_32);
9669 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9670 FIB_TEST(!fib_test_validate_entry(fei,
9671 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9674 "%U via 10.10.10.1",
9675 format_fib_prefix, &pfx_10_10_10_22_s_32);
9676 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9677 FIB_TEST(!fib_test_validate_entry(fei,
9678 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9681 "%U via 10.10.10.1",
9682 format_fib_prefix, &pfx_10_10_10_255_s_32);
9683 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9684 FIB_TEST(!fib_test_validate_entry(fei,
9685 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9688 "%U via 10.10.10.1",
9689 format_fib_prefix, &pfx_10_10_10_0_s_24);
9692 * add an entry less specific to /24. it should not own the /24's tree
9694 const fib_prefix_t pfx_10_10_0_0_s_16 = {
9696 .fp_proto = FIB_PROTOCOL_IP4,
9697 .fp_addr = nh_10_10_0_0,
9699 fib_table_entry_update_one_path(0,
9700 &pfx_10_10_0_0_s_16,
9702 FIB_ENTRY_FLAG_COVERED_INHERIT,
9705 tm->hw[0]->sw_if_index,
9709 FIB_ROUTE_PATH_FLAG_NONE);
9710 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9711 FIB_TEST(!fib_test_validate_entry(fei,
9712 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9715 "%U via 10.10.10.1",
9716 format_fib_prefix, &pfx_10_10_10_16_s_28);
9717 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9718 FIB_TEST(!fib_test_validate_entry(fei,
9719 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9722 "%U via 10.10.10.1",
9723 format_fib_prefix, &pfx_10_10_10_22_s_32);
9724 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9725 FIB_TEST(!fib_test_validate_entry(fei,
9726 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9729 "%U via 10.10.10.1",
9730 format_fib_prefix, &pfx_10_10_10_255_s_32);
9731 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9732 FIB_TEST(!fib_test_validate_entry(fei,
9733 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9736 "%U via 10.10.10.1",
9737 format_fib_prefix, &pfx_10_10_10_0_s_24);
9738 fei = fib_table_lookup_exact_match(0, &pfx_10_10_0_0_s_16);
9739 FIB_TEST(!fib_test_validate_entry(fei,
9740 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9743 "%U via 10.10.10.2",
9744 format_fib_prefix, &pfx_10_10_0_0_s_16);
9747 * Add/remove an interposer source to a new /32
9749 const fib_prefix_t pfx_11_11_11_11_s_32 = {
9751 .fp_proto = FIB_PROTOCOL_IP4,
9752 .fp_addr = nh_11_11_11_11,
9755 fib_table_entry_update_one_path(0,
9756 &pfx_11_11_11_11_s_32,
9758 FIB_ENTRY_FLAG_NONE,
9761 tm->hw[0]->sw_if_index,
9765 FIB_ROUTE_PATH_FLAG_NONE);
9767 dpo_id_t interposer = DPO_INVALID;
9768 fib_mpls_label_t *l99 = NULL, fml_99 = {
9771 vec_add1(l99, fml_99);
9773 mpls_label_dpo_create(l99,
9776 MPLS_LABEL_DPO_FLAG_NONE,
9777 punt_dpo_get(DPO_PROTO_MPLS),
9780 adj_index_t ai_10_10_10_3 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9783 tm->hw[0]->sw_if_index);
9784 fib_test_lb_bucket_t adj_o_10_10_10_3 = {
9787 .adj = ai_10_10_10_3,
9790 fib_test_lb_bucket_t l99_o_10_10_10_3 = {
9791 .type = FT_LB_LABEL_O_ADJ,
9793 .adj = ai_10_10_10_3,
9799 fei = fib_table_entry_special_dpo_add(0,
9800 &pfx_11_11_11_11_s_32,
9802 FIB_ENTRY_FLAG_INTERPOSE,
9804 FIB_TEST(!fib_test_validate_entry(fei,
9805 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9808 "%U via interposer adj",
9809 format_fib_prefix,&pfx_11_11_11_11_s_32);
9811 fib_table_entry_special_remove(0,
9812 &pfx_11_11_11_11_s_32,
9813 FIB_SOURCE_SPECIAL);
9814 FIB_TEST(!fib_test_validate_entry(fei,
9815 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9818 "%U via 10.10.10.1",
9819 format_fib_prefix, &pfx_11_11_11_11_s_32);
9820 dpo_reset(&interposer);
9821 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
9824 * add an interposer to a source with path-extensions
9826 fib_mpls_label_t *l3300 = NULL, fml_3300 = {
9829 vec_add1(l3300, fml_3300);
9830 fib_table_entry_update_one_path(0,
9831 &pfx_11_11_11_11_s_32,
9833 FIB_ENTRY_FLAG_NONE,
9836 tm->hw[0]->sw_if_index,
9840 FIB_ROUTE_PATH_FLAG_NONE);
9842 mpls_label_dpo_create(l99,
9845 MPLS_LABEL_DPO_FLAG_NONE,
9846 punt_dpo_get(DPO_PROTO_MPLS),
9849 adj_index_t ai_mpls_10_10_10_3 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9852 tm->hw[0]->sw_if_index);
9853 fib_test_lb_bucket_t l3300_o_10_10_10_3 = {
9854 .type = FT_LB_LABEL_O_ADJ,
9856 .adj = ai_mpls_10_10_10_3,
9861 fib_test_lb_bucket_t lchain_o_10_10_10_3 = {
9862 .type = FT_LB_LABEL_CHAIN_O_ADJ,
9863 .label_chain_o_adj = {
9864 .adj = ai_mpls_10_10_10_3,
9865 .label_chain_size = 2,
9873 fei = fib_table_entry_special_dpo_add(0,
9874 &pfx_11_11_11_11_s_32,
9876 FIB_ENTRY_FLAG_INTERPOSE,
9879 FIB_TEST(!fib_test_validate_entry(fei,
9880 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9882 &lchain_o_10_10_10_3),
9883 "%U via interposer & mpls on adj",
9884 format_fib_prefix, &pfx_11_11_11_11_s_32);
9886 fib_table_entry_special_remove(0,
9887 &pfx_11_11_11_11_s_32,
9888 FIB_SOURCE_SPECIAL);
9889 FIB_TEST(!fib_test_validate_entry(fei,
9890 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9892 &l3300_o_10_10_10_3),
9893 "%U via 10.10.10.1",
9894 format_fib_prefix, &pfx_11_11_11_11_s_32);
9895 adj_unlock(ai_mpls_10_10_10_3);
9898 * remove and re-add the second best API source while the interpose
9901 fei = fib_table_entry_special_dpo_add(0,
9902 &pfx_11_11_11_11_s_32,
9904 FIB_ENTRY_FLAG_INTERPOSE,
9906 FIB_TEST(!fib_test_validate_entry(fei,
9907 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9909 &lchain_o_10_10_10_3),
9910 "%U via interposer adj",
9911 format_fib_prefix,&pfx_11_11_11_11_s_32);
9913 FIB_TEST(3 == pool_elts(mpls_label_dpo_pool),
9914 "MPLS label pool: %d",
9915 pool_elts(mpls_label_dpo_pool));
9917 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
9920 * the interpose does not get stacked when there are not valid paths
9922 fib_test_lb_bucket_t bucket_drop = {
9925 .adj = DPO_PROTO_IP4,
9928 FIB_TEST(!fib_test_validate_entry(fei,
9929 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9933 format_fib_prefix,&pfx_11_11_11_11_s_32);
9935 fib_table_entry_update_one_path(0,
9936 &pfx_11_11_11_11_s_32,
9938 FIB_ENTRY_FLAG_NONE,
9941 tm->hw[0]->sw_if_index,
9945 FIB_ROUTE_PATH_FLAG_NONE);
9946 FIB_TEST(!fib_test_validate_entry(fei,
9947 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9950 "%U via interposer adj",
9951 format_fib_prefix,&pfx_11_11_11_11_s_32);
9952 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
9955 * add a cover for the interposed entry, so that we test it selects
9956 * the covers forwarding.
9958 const fib_prefix_t pfx_11_11_11_0_s_24 = {
9960 .fp_proto = FIB_PROTOCOL_IP4,
9961 .fp_addr = nh_11_11_11_0,
9963 fib_table_entry_update_one_path(0,
9964 &pfx_11_11_11_0_s_24,
9966 FIB_ENTRY_FLAG_NONE,
9969 tm->hw[0]->sw_if_index,
9973 FIB_ROUTE_PATH_FLAG_NONE);
9974 FIB_TEST(!fib_test_validate_entry(fei,
9975 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9978 "%U via interposer adj",
9979 format_fib_prefix,&pfx_11_11_11_11_s_32);
9982 * multiple interpose sources on the same entry. Only the high
9983 * priority source gets to add the interpose.
9985 fib_table_entry_update_one_path(0,
9986 &pfx_11_11_11_11_s_32,
9988 FIB_ENTRY_FLAG_NONE,
9991 tm->hw[0]->sw_if_index,
9995 FIB_ROUTE_PATH_FLAG_NONE);
9997 dpo_id_t interposer2 = DPO_INVALID;
9998 fib_mpls_label_t *l100 = NULL, fml_100 = {
10001 vec_add1(l100, fml_100);
10003 mpls_label_dpo_create(l100,
10006 MPLS_LABEL_DPO_FLAG_NONE,
10007 punt_dpo_get(DPO_PROTO_MPLS),
10010 fei = fib_table_entry_special_dpo_add(0,
10011 &pfx_11_11_11_11_s_32,
10012 FIB_SOURCE_CLASSIFY,
10013 FIB_ENTRY_FLAG_INTERPOSE,
10016 fib_test_lb_bucket_t lc100_o_10_10_10_3 = {
10017 .type = FT_LB_LABEL_CHAIN_O_ADJ,
10018 .label_chain_o_adj = {
10019 .adj = ai_10_10_10_3,
10020 .label_chain_size = 2,
10028 FIB_TEST(!fib_test_validate_entry(fei,
10029 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10031 &lc100_o_10_10_10_3),
10032 "%U via interposer label 99",
10033 format_fib_prefix,&pfx_11_11_11_11_s_32);
10035 fib_test_lb_bucket_t l100_o_10_10_10_3 = {
10036 .type = FT_LB_LABEL_O_ADJ,
10038 .adj = ai_10_10_10_3,
10044 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_SPECIAL);
10046 FIB_TEST(!fib_test_validate_entry(fei,
10047 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10049 &l100_o_10_10_10_3),
10050 "%U via interposer label 99",
10051 format_fib_prefix,&pfx_11_11_11_11_s_32);
10053 fib_table_entry_delete(0, &pfx_11_11_11_0_s_24, FIB_SOURCE_API);
10054 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
10055 FIB_TEST(!fib_test_validate_entry(fei,
10056 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10060 format_fib_prefix,&pfx_11_11_11_11_s_32);
10061 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_CLASSIFY);
10064 * update a source to/from interpose.
10066 /* fib_table_entry_update_one_path(0, */
10067 /* &pfx_11_11_11_0_s_24, */
10068 /* FIB_SOURCE_API, */
10069 /* FIB_ENTRY_FLAG_NONE, */
10070 /* DPO_PROTO_IP4, */
10071 /* &nh_10_10_10_3, */
10072 /* tm->hw[0]->sw_if_index, */
10076 /* FIB_ROUTE_PATH_FLAG_NONE); */
10077 /* fei = fib_table_entry_special_dpo_add(0, */
10078 /* &pfx_11_11_11_11_s_32, */
10079 /* FIB_SOURCE_API, */
10080 /* FIB_ENTRY_FLAG_INTERPOSE, */
10081 /* &interposer); */
10082 /* FIB_TEST(!fib_test_validate_entry(fei, */
10083 /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */
10085 /* &l99_o_10_10_10_3), */
10086 /* "%U via interposer label 99", */
10087 /* format_fib_prefix,&pfx_11_11_11_11_s_32); */
10089 /* FIB_TEST(3 == pool_elts(mpls_label_dpo_pool), */
10090 /* "MPLS label pool: %d", */
10091 /* pool_elts(mpls_label_dpo_pool)); */
10092 /* FIB_TEST((2 == mpls_label_dpo_get(interposer.dpoi_index)->mld_locks), */
10093 /* "Interposer %d locks", */
10094 /* mpls_label_dpo_get(interposer.dpoi_index)->mld_locks); */
10096 /* fib_table_entry_update_one_path(0, */
10097 /* &pfx_11_11_11_11_s_32, */
10098 /* FIB_SOURCE_API, */
10099 /* FIB_ENTRY_FLAG_NONE, */
10100 /* DPO_PROTO_IP4, */
10101 /* &nh_10_10_10_2, */
10102 /* tm->hw[0]->sw_if_index, */
10106 /* FIB_ROUTE_PATH_FLAG_NONE); */
10107 /* FIB_TEST(!fib_test_validate_entry(fei, */
10108 /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */
10110 /* &adj_o_10_10_10_2), */
10111 /* "%U via 10.10.10.2", */
10112 /* format_fib_prefix,&pfx_11_11_11_11_s_32); */
10114 /* FIB_TEST((1 == mpls_label_dpo_get(interposer.dpoi_index)->mld_locks), */
10115 /* "Interposer %d locks", */
10116 /* mpls_label_dpo_get(interposer.dpoi_index)->mld_locks); */
10117 /* FIB_TEST(2 == pool_elts(mpls_label_dpo_pool), */
10118 /* "MPLS label pool: %d", */
10119 /* pool_elts(mpls_label_dpo_pool)); */
10121 /* fei = fib_table_entry_special_dpo_add(0, */
10122 /* &pfx_11_11_11_11_s_32, */
10123 /* FIB_SOURCE_API, */
10124 /* FIB_ENTRY_FLAG_INTERPOSE, */
10125 /* &interposer); */
10126 /* FIB_TEST(!fib_test_validate_entry(fei, */
10127 /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */
10129 /* &l99_o_10_10_10_3), */
10130 /* "%U via interposer label 99", */
10131 /* format_fib_prefix,&pfx_11_11_11_11_s_32); */
10133 /* fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API); */
10136 * Add/remove an interposer source from the top of the subtrie. The
10137 * interposer source is not inherited.
10139 fib_table_entry_update_one_path(0,
10140 &pfx_10_10_10_0_s_24,
10142 FIB_ENTRY_FLAG_COVERED_INHERIT,
10145 tm->hw[0]->sw_if_index,
10149 FIB_ROUTE_PATH_FLAG_NONE);
10150 fei = fib_table_entry_special_dpo_add(0,
10151 &pfx_10_10_10_0_s_24,
10152 FIB_SOURCE_SPECIAL,
10153 FIB_ENTRY_FLAG_INTERPOSE,
10155 FIB_TEST(!fib_test_validate_entry(fei,
10156 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10158 &l99_o_10_10_10_3),
10159 "%U via interposer label",
10160 format_fib_prefix,&pfx_10_10_10_0_s_24);
10161 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
10162 FIB_TEST(!fib_test_validate_entry(fei,
10163 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10167 format_fib_prefix, &pfx_10_10_10_21_s_32);
10169 fib_table_entry_special_remove(0,
10170 &pfx_10_10_10_0_s_24,
10171 FIB_SOURCE_SPECIAL);
10172 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
10173 FIB_TEST(!fib_test_validate_entry(fei,
10174 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10176 &adj_o_10_10_10_3),
10177 "%U via 10.10.10.1",
10178 format_fib_prefix, &pfx_10_10_10_0_s_24);
10179 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
10180 FIB_TEST(!fib_test_validate_entry(fei,
10181 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10183 &adj_o_10_10_10_3),
10184 "%U via via 10.10.10.1",
10185 format_fib_prefix, &pfx_10_10_10_21_s_32);
10188 * Add/remove an interposer source from the top of the subtrie. The
10189 * interposer source is inherited.
10191 fei = fib_table_entry_special_dpo_add(0,
10192 &pfx_10_10_10_0_s_24,
10193 FIB_SOURCE_SPECIAL,
10194 (FIB_ENTRY_FLAG_COVERED_INHERIT |
10195 FIB_ENTRY_FLAG_INTERPOSE),
10197 FIB_TEST(!fib_test_validate_entry(fei,
10198 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10200 &l99_o_10_10_10_3),
10201 "%U via interposer label",
10202 format_fib_prefix,&pfx_10_10_10_0_s_24);
10204 /* interposer gets forwarding from the drop cli source */
10205 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
10206 FIB_TEST(!fib_test_validate_entry(fei,
10207 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10211 format_fib_prefix,&pfx_10_10_10_21_s_32);
10213 fib_table_entry_update_one_path(0,
10214 &pfx_10_10_10_21_s_32,
10216 FIB_ENTRY_FLAG_NONE,
10219 tm->hw[0]->sw_if_index,
10223 FIB_ROUTE_PATH_FLAG_NONE);
10224 fib_table_entry_delete(0, &pfx_10_10_10_21_s_32, FIB_SOURCE_CLI);
10225 /* interposer gets forwarding from the API source */
10226 FIB_TEST(!fib_test_validate_entry(fei,
10227 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10229 &l99_o_10_10_10_3),
10230 "%U via interposer label",
10231 format_fib_prefix,&pfx_10_10_10_21_s_32);
10236 fib_table_entry_delete(0, &pfx_10_10_10_22_s_32, FIB_SOURCE_CLI);
10237 fib_table_entry_delete(0, &pfx_10_10_10_21_s_32, FIB_SOURCE_API);
10238 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_CLI);
10239 fib_table_entry_delete(0, &pfx_10_10_10_255_s_32, FIB_SOURCE_CLI);
10240 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, FIB_SOURCE_API);
10241 fib_table_entry_delete(0, &pfx_10_10_0_0_s_16, FIB_SOURCE_API);
10242 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, FIB_SOURCE_SPECIAL);
10243 adj_unlock(ai_10_10_10_1);
10244 adj_unlock(ai_10_10_10_2);
10245 adj_unlock(ai_10_10_10_3);
10246 dpo_reset(&interposer);
10247 dpo_reset(&interposer2);
10248 FIB_TEST(0 == pool_elts(mpls_label_dpo_pool),
10249 "MPLS label pool empty: %d",
10250 pool_elts(mpls_label_dpo_pool));
10251 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
10252 FIB_TEST(N_PLS == fib_path_list_pool_size(),
10253 "number of path-lists: %d = %d",
10254 N_PLS, fib_path_list_pool_size());
10257 * test the v6 tree walk.
10258 * a /64 that covers everything. a /96 that covers one /128
10259 * a second /128 covered only by the /64.
10261 const fib_prefix_t pfx_2001_s_64 = {
10263 .fp_proto = FIB_PROTOCOL_IP6,
10267 [0] = clib_host_to_net_u64(0x2001000000000000),
10268 [1] = clib_host_to_net_u64(0x0000000000000000),
10273 const fib_prefix_t pfx_2001_1_s_96 = {
10275 .fp_proto = FIB_PROTOCOL_IP6,
10279 [0] = clib_host_to_net_u64(0x2001000000000000),
10280 [1] = clib_host_to_net_u64(0x1000000000000000),
10285 const fib_prefix_t pfx_2001_1_1_s_128 = {
10287 .fp_proto = FIB_PROTOCOL_IP6,
10291 [0] = clib_host_to_net_u64(0x2001000000000000),
10292 [1] = clib_host_to_net_u64(0x1000000000000001),
10297 const fib_prefix_t pfx_2001_0_1_s_128 = {
10299 .fp_proto = FIB_PROTOCOL_IP6,
10303 [0] = clib_host_to_net_u64(0x2001000000000000),
10304 [1] = clib_host_to_net_u64(0x0000000000000001),
10309 const ip46_address_t nh_3000_1 = {
10312 [0] = clib_host_to_net_u64(0x3000000000000000),
10313 [1] = clib_host_to_net_u64(0x0000000000000001),
10317 const ip46_address_t nh_3000_2 = {
10320 [0] = clib_host_to_net_u64(0x3000000000000000),
10321 [1] = clib_host_to_net_u64(0x0000000000000002),
10325 adj_index_t ai_3000_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
10328 tm->hw[0]->sw_if_index);
10329 adj_index_t ai_3000_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
10332 tm->hw[0]->sw_if_index);
10333 fib_test_lb_bucket_t adj_o_3000_1 = {
10339 fib_test_lb_bucket_t adj_o_3000_2 = {
10346 fib_table_entry_special_add(0,
10347 &pfx_2001_0_1_s_128,
10349 FIB_ENTRY_FLAG_DROP);
10350 fib_table_entry_special_add(0,
10351 &pfx_2001_1_1_s_128,
10353 FIB_ENTRY_FLAG_DROP);
10356 * /96 has inherited forwarding pushed down to its covered /128
10358 fib_table_entry_update_one_path(0,
10361 FIB_ENTRY_FLAG_COVERED_INHERIT,
10364 tm->hw[0]->sw_if_index,
10368 FIB_ROUTE_PATH_FLAG_NONE);
10369 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_s_96);
10370 FIB_TEST(!fib_test_validate_entry(fei,
10371 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10375 format_fib_prefix, &pfx_2001_1_s_96);
10376 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_1_s_128);
10377 FIB_TEST(!fib_test_validate_entry(fei,
10378 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10382 format_fib_prefix, &pfx_2001_1_1_s_128);
10383 fei = fib_table_lookup_exact_match(0, &pfx_2001_0_1_s_128);
10384 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
10385 "%U resolves via drop",
10386 format_fib_prefix, &pfx_2001_0_1_s_128);
10389 * /64 has inherited forwarding pushed down to all, but the /96
10390 * and its sub-tree remain unaffected.
10392 fib_table_entry_update_one_path(0,
10395 FIB_ENTRY_FLAG_COVERED_INHERIT,
10398 tm->hw[0]->sw_if_index,
10402 FIB_ROUTE_PATH_FLAG_NONE);
10404 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
10405 FIB_TEST(!fib_test_validate_entry(fei,
10406 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10410 format_fib_prefix, &pfx_2001_s_64);
10411 fei = fib_table_lookup_exact_match(0, &pfx_2001_0_1_s_128);
10412 FIB_TEST(!fib_test_validate_entry(fei,
10413 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10417 format_fib_prefix, &pfx_2001_0_1_s_128);
10419 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_s_96);
10420 FIB_TEST(!fib_test_validate_entry(fei,
10421 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10425 format_fib_prefix, &pfx_2001_1_s_96);
10426 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_1_s_128);
10427 FIB_TEST(!fib_test_validate_entry(fei,
10428 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10432 format_fib_prefix, &pfx_2001_1_1_s_128);
10437 fib_table_entry_delete(0, &pfx_2001_0_1_s_128, FIB_SOURCE_CLI);
10438 fib_table_entry_delete(0, &pfx_2001_1_1_s_128, FIB_SOURCE_CLI);
10439 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
10440 fib_table_entry_delete(0, &pfx_2001_1_s_96, FIB_SOURCE_API);
10441 adj_unlock(ai_3000_1);
10442 adj_unlock(ai_3000_2);
10445 * test no-one left behind
10447 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
10448 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
10454 fib_test_sticky (void)
10456 fib_route_path_t *r_paths = NULL;
10457 test_main_t *tm = &test_main;
10458 u32 ii, lb_count, pl_count;
10459 dpo_id_t dpo = DPO_INVALID;
10460 fib_node_index_t pl_index;
10464 fib_test_lb_bucket_t buckets[N_PATHS];
10465 bfd_session_t bfds[N_PATHS] = {{0}};
10467 lb_count = pool_elts(load_balance_pool);
10468 pl_count = fib_path_list_pool_size();
10470 for (ii = 0; ii < N_PATHS; ii++)
10472 ip46_address_t nh = {
10473 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
10477 ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
10479 &nh, tm->hw[0]->sw_if_index);
10481 buckets[ii].type = FT_LB_ADJ;
10482 buckets[ii].adj.adj = ai;
10484 bfds[ii].udp.key.peer_addr = nh;
10485 bfds[ii].udp.key.sw_if_index = tm->hw[0]->sw_if_index;
10486 bfds[ii].hop_type = BFD_HOP_TYPE_SINGLE;
10487 bfds[ii].local_state = BFD_STATE_init;
10488 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfds[ii]);
10489 bfds[ii].local_state = BFD_STATE_up;
10490 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[ii]);
10493 for (ii = 0; ii < N_PATHS; ii++)
10495 fib_route_path_t r_path = {
10496 .frp_proto = DPO_PROTO_IP4,
10498 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
10500 .frp_sw_if_index = tm->hw[0]->sw_if_index,
10502 .frp_fib_index = ~0,
10504 vec_add1(r_paths, r_path);
10507 pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths);
10508 fib_path_list_lock(pl_index);
10510 fib_path_list_contribute_forwarding(pl_index,
10511 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10512 FIB_PATH_LIST_FWD_FLAG_STICKY,
10515 FIB_TEST(!fib_test_validate_lb(&dpo,
10535 /* take down paths */
10536 bfds[0].local_state = BFD_STATE_down;
10537 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[0]);
10539 fib_path_list_contribute_forwarding(pl_index,
10540 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10541 FIB_PATH_LIST_FWD_FLAG_STICKY,
10544 FIB_TEST(!fib_test_validate_lb(&dpo,
10562 "Failed at shut-down path 0");
10564 bfds[7].local_state = BFD_STATE_down;
10565 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[7]);
10567 fib_path_list_contribute_forwarding(pl_index,
10568 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10569 FIB_PATH_LIST_FWD_FLAG_STICKY,
10572 FIB_TEST(!fib_test_validate_lb(&dpo,
10590 "Failed at shut-down path 7");
10592 /* paths back up */
10593 bfds[0].local_state = BFD_STATE_up;
10594 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[0]);
10595 bfds[7].local_state = BFD_STATE_up;
10596 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[7]);
10598 fib_path_list_contribute_forwarding(pl_index,
10599 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10600 FIB_PATH_LIST_FWD_FLAG_STICKY,
10603 FIB_TEST(!fib_test_validate_lb(&dpo,
10623 fib_path_list_unlock(pl_index);
10626 * non-power of 2 number of buckets
10628 fib_route_path_t *r_paths2 = NULL;
10630 r_paths2 = vec_dup(r_paths);
10631 vec_set_len (r_paths2, 3);
10633 pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths2);
10634 fib_path_list_lock(pl_index);
10636 fib_path_list_contribute_forwarding(pl_index,
10637 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10638 FIB_PATH_LIST_FWD_FLAG_STICKY,
10641 FIB_TEST(!fib_test_validate_lb(&dpo,
10661 bfds[1].local_state = BFD_STATE_down;
10662 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10664 fib_path_list_contribute_forwarding(pl_index,
10665 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10666 FIB_PATH_LIST_FWD_FLAG_STICKY,
10670 * path 1's buckets alternate between path 0 and 2
10672 FIB_TEST(!fib_test_validate_lb(&dpo,
10691 bfds[1].local_state = BFD_STATE_up;
10692 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10694 fib_path_list_unlock(pl_index);
10699 fib_route_path_t *r_paths3 = NULL;
10701 r_paths3 = vec_dup(r_paths);
10702 vec_set_len (r_paths3, 3);
10704 r_paths3[0].frp_weight = 3;
10706 pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths3);
10707 fib_path_list_lock(pl_index);
10709 fib_path_list_contribute_forwarding(pl_index,
10710 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10711 FIB_PATH_LIST_FWD_FLAG_STICKY,
10714 FIB_TEST(!fib_test_validate_lb(&dpo,
10734 bfds[1].local_state = BFD_STATE_down;
10735 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10737 fib_path_list_contribute_forwarding(pl_index,
10738 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10739 FIB_PATH_LIST_FWD_FLAG_STICKY,
10741 /* No attempt to Un-equal distribute the down path's buckets */
10742 FIB_TEST(!fib_test_validate_lb(&dpo,
10761 bfds[1].local_state = BFD_STATE_up;
10762 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10765 fib_path_list_unlock(pl_index);
10768 vec_free(r_paths2);
10769 vec_free(r_paths3);
10771 FIB_TEST(lb_count == pool_elts(load_balance_pool), "no leaked LBs");
10772 FIB_TEST(pl_count == fib_path_list_pool_size(), "no leaked PLs");
10777 static clib_error_t *
10778 fib_test (vlib_main_t * vm,
10779 unformat_input_t * input,
10780 vlib_cli_command_t * cmd_arg)
10786 fib_test_mk_intf(4);
10788 if (unformat (input, "debug"))
10790 fib_test_do_debug = 1;
10793 if (unformat (input, "ip4"))
10795 res += fib_test_v4();
10797 else if (unformat (input, "ip6"))
10799 res += fib_test_v6();
10801 else if (unformat (input, "ip"))
10803 res += fib_test_v4();
10804 res += fib_test_v6();
10806 else if (unformat (input, "label"))
10808 res += fib_test_label();
10810 else if (unformat (input, "ae"))
10812 res += fib_test_ae();
10814 else if (unformat (input, "pref"))
10816 res += fib_test_pref();
10818 else if (unformat (input, "lfib"))
10820 res += lfib_test();
10822 else if (unformat (input, "walk"))
10824 res += fib_test_walk();
10826 else if (unformat (input, "bfd"))
10828 res += fib_test_bfd();
10830 else if (unformat (input, "inherit"))
10832 res += fib_test_inherit();
10834 else if (unformat (input, "sticky"))
10836 res += fib_test_sticky();
10840 res += fib_test_v4();
10841 res += fib_test_v6();
10842 res += fib_test_ae();
10843 res += fib_test_bfd();
10844 res += fib_test_pref();
10845 res += fib_test_label();
10846 res += fib_test_inherit();
10847 res += lfib_test();
10850 * fib-walk process must be disabled in order for the walk tests to work
10852 fib_walk_process_disable();
10853 res += fib_test_walk();
10854 fib_walk_process_enable();
10860 return clib_error_return(0, "FIB Unit Test Failed");
10868 VLIB_CLI_COMMAND (test_fib_command, static) = {
10869 .path = "test fib",
10870 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
10871 .function = fib_test,
10875 fib_test_init (vlib_main_t *vm)
10880 VLIB_INIT_FUNCTION (fib_test_init);