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++)
147 error = ethernet_register_interface(vnet_get_main(),
148 test_interface_device_class.index,
151 &tm->hw_if_indicies[i],
152 /* flag change */ 0);
154 FIB_TEST((NULL == error), "ADD interface %d", i);
156 error = vnet_hw_interface_set_flags(vnet_get_main(),
157 tm->hw_if_indicies[i],
158 VNET_HW_INTERFACE_FLAG_LINK_UP);
159 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
160 tm->hw_if_indicies[i]);
161 vec_validate (ip4_main.fib_index_by_sw_if_index,
162 tm->hw[i]->sw_if_index);
163 vec_validate (ip6_main.fib_index_by_sw_if_index,
164 tm->hw[i]->sw_if_index);
165 ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
166 ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
168 error = vnet_sw_interface_set_flags(vnet_get_main(),
169 tm->hw[i]->sw_if_index,
170 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
171 FIB_TEST((NULL == error), "UP interface %d", i);
174 * re-eval after the inevitable realloc
176 for (i = 0; i < ninterfaces; i++)
178 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
179 tm->hw_if_indicies[i]);
185 #define FIB_TEST_REC_FORW(_rec_prefix, _via_prefix, _bucket) \
187 const dpo_id_t *_rec_dpo = fib_entry_contribute_ip_forwarding( \
188 fib_table_lookup_exact_match(fib_index, (_rec_prefix))); \
189 const dpo_id_t *_via_dpo = fib_entry_contribute_ip_forwarding( \
190 fib_table_lookup(fib_index, (_via_prefix))); \
191 FIB_TEST(!dpo_cmp(_via_dpo, \
192 load_balance_get_bucket(_rec_dpo->dpoi_index, \
194 "%U is recursive via %U", \
195 format_fib_prefix, (_rec_prefix), \
196 format_fib_prefix, _via_prefix); \
199 #define FIB_TEST_LB_BUCKET_VIA_ADJ(_prefix, _bucket, _ai) \
201 const dpo_id_t *_dpo = fib_entry_contribute_ip_forwarding( \
202 fib_table_lookup_exact_match(fib_index, (_prefix))); \
203 const dpo_id_t *_dpo1 = \
204 load_balance_get_bucket(_dpo->dpoi_index, _bucket); \
205 FIB_TEST(DPO_ADJACENCY == _dpo1->dpoi_type, "type is %U", \
206 format_dpo_type, _dpo1->dpoi_type); \
207 FIB_TEST((_ai == _dpo1->dpoi_index), \
208 "%U bucket %d resolves via %U", \
209 format_fib_prefix, (_prefix), \
211 format_dpo_id, _dpo1, 0); \
214 #define FIB_TEST_RPF(_cond, _comment, _args...) \
216 if (FIB_TEST_I(_cond, _comment, ##_args)) { \
223 fib_test_urpf_is_equal (fib_node_index_t fei,
224 fib_forward_chain_type_t fct,
227 dpo_id_t dpo = DPO_INVALID;
228 fib_urpf_list_t *urpf;
236 fib_entry_contribute_forwarding(fei, fct, &dpo);
237 ui = load_balance_get_urpf(dpo.dpoi_index);
239 urpf = fib_urpf_list_get(ui);
241 FIB_TEST_RPF(num == vec_len(urpf->furpf_itfs),
242 "RPF:%U len %d == %d",
243 format_fib_urpf_list, ui,
244 num, vec_len(urpf->furpf_itfs));
245 FIB_TEST_RPF(num == fib_urpf_check_size(ui),
246 "RPF:%U check-size %d == %d",
247 format_fib_urpf_list, ui,
248 num, vec_len(urpf->furpf_itfs));
250 for (ii = 0; ii < num; ii++)
252 adj_index_t ai = va_arg(ap, adj_index_t);
254 FIB_TEST_RPF(ai == urpf->furpf_itfs[ii],
255 "RPF:%d item:%d - %d == %d",
256 ui, ii, ai, urpf->furpf_itfs[ii]);
257 FIB_TEST_RPF(fib_urpf_check(ui, ai),
271 fib_test_build_rewrite (u8 *eth_addr)
275 vec_validate(rewrite, 13);
277 memcpy(rewrite, eth_addr, 6);
278 memcpy(rewrite+6, eth_addr, 6);
283 #define FIB_TEST_LB(_cond, _comment, _args...) \
285 if (FIB_TEST_I(_cond, _comment, ##_args)) { \
291 fib_test_validate_rep_v (const replicate_t *rep,
295 const fib_test_rep_bucket_t *exp;
300 FIB_TEST_LB((n_buckets == rep->rep_n_buckets),
301 "n_buckets = %d", rep->rep_n_buckets);
303 for (bucket = 0; bucket < n_buckets; bucket++)
305 exp = va_arg(*ap, fib_test_rep_bucket_t*);
307 dpo = replicate_get_bucket_i(rep, bucket);
311 case FT_REP_LABEL_O_ADJ:
313 const mpls_label_dpo_t *mld;
316 FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE)
318 "bucket %d stacks on %U",
320 format_dpo_type, dpo->dpoi_type);
322 mld = mpls_label_dpo_get(dpo->dpoi_index);
323 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
325 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
326 exp->label_o_adj.label),
327 "bucket %d stacks on label %d",
329 exp->label_o_adj.label);
331 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
332 exp->label_o_adj.eos),
333 "bucket %d stacks on label %d %U",
335 exp->label_o_adj.label,
336 format_mpls_eos_bit, exp->label_o_adj.eos);
338 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
339 "bucket %d label stacks on %U",
341 format_dpo_type, mld->mld_dpo.dpoi_type);
343 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
344 "bucket %d label stacks on adj %d",
346 exp->label_o_adj.adj);
350 FIB_TEST_LB((DPO_INTERFACE_RX == dpo->dpoi_type),
351 "bucket %d stacks on %U",
353 format_dpo_type, dpo->dpoi_type);
355 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
356 "bucket %d stacks on adj %d",
360 case FT_REP_DISP_MFIB_LOOKUP:
370 fib_test_validate_lb_v (const load_balance_t *lb,
378 FIB_TEST_LB((n_buckets == lb->lb_n_buckets), "n_buckets = %d", lb->lb_n_buckets);
380 for (bucket = 0; bucket < n_buckets; bucket++)
382 const fib_test_lb_bucket_t *exp;
384 exp = va_arg(*ap, fib_test_lb_bucket_t*);
385 dpo = load_balance_get_bucket_i(lb, bucket);
389 case FT_LB_LABEL_STACK_O_ADJ:
391 const mpls_label_dpo_t *mld;
392 mpls_label_dpo_flags_t mf;
396 mf = ((exp->label_stack_o_adj.mode ==
397 FIB_MPLS_LSP_MODE_UNIFORM) ?
398 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
399 MPLS_LABEL_DPO_FLAG_NONE);
400 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
401 "bucket %d stacks on %U",
403 format_dpo_type, dpo->dpoi_type);
405 mld = mpls_label_dpo_get(dpo->dpoi_index);
407 FIB_TEST_LB(exp->label_stack_o_adj.label_stack_size == mld->mld_n_labels,
411 for (ii = 0; ii < mld->mld_n_labels; ii++)
413 hdr = clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
414 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
415 exp->label_stack_o_adj.label_stack[ii]),
416 "bucket %d stacks on label %d",
418 exp->label_stack_o_adj.label_stack[ii]);
420 if (ii == mld->mld_n_labels-1)
422 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
423 exp->label_o_adj.eos),
424 "bucket %d stacks on label %d %U!=%U",
426 exp->label_stack_o_adj.label_stack[ii],
427 format_mpls_eos_bit, exp->label_o_adj.eos,
428 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
432 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) == MPLS_NON_EOS),
433 "bucket %d stacks on label %d %U",
435 exp->label_stack_o_adj.label_stack[ii],
436 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
440 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
441 "bucket %d label stacks on %U",
443 format_dpo_type, mld->mld_dpo.dpoi_type);
445 FIB_TEST_LB((exp->label_stack_o_adj.adj == mld->mld_dpo.dpoi_index),
446 "bucket %d label stacks on adj %d",
448 exp->label_stack_o_adj.adj);
451 case FT_LB_LABEL_CHAIN_O_ADJ:
453 const mpls_label_dpo_t *mld = NULL;
454 mpls_label_dpo_flags_t mf;
458 mf = ((exp->label_chain_o_adj.mode ==
459 FIB_MPLS_LSP_MODE_UNIFORM) ?
460 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
461 MPLS_LABEL_DPO_FLAG_NONE);
463 for (ii = 0; ii < exp->label_chain_o_adj.label_chain_size; ii++)
465 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
466 "bucket %d stacks on %U",
468 format_dpo_type, dpo->dpoi_type);
469 mld = mpls_label_dpo_get(dpo->dpoi_index);
471 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
472 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
473 exp->label_chain_o_adj.label_chain[ii]),
474 "bucket %d stacks on label %d",
476 exp->label_chain_o_adj.label_chain[ii]);
480 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
481 "bucket %d label stacks on %U",
483 format_dpo_type, mld->mld_dpo.dpoi_type);
485 FIB_TEST_LB((exp->label_chain_o_adj.adj == mld->mld_dpo.dpoi_index),
486 "bucket %d label stacks on adj %d",
488 exp->label_chain_o_adj.adj);
491 case FT_LB_LABEL_O_ADJ:
493 const mpls_label_dpo_t *mld;
495 FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE)
497 "bucket %d stacks on %U",
499 format_dpo_type, dpo->dpoi_type);
501 mld = mpls_label_dpo_get(dpo->dpoi_index);
502 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
504 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
505 exp->label_o_adj.label),
506 "bucket %d stacks on label %d not %d",
508 vnet_mpls_uc_get_label(hdr),
509 exp->label_o_adj.label);
511 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
512 exp->label_o_adj.eos),
513 "bucket %d stacks on label %d %U",
515 exp->label_o_adj.label,
516 format_mpls_eos_bit, exp->label_o_adj.eos);
518 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
519 "bucket %d label stacks on %U",
521 format_dpo_type, mld->mld_dpo.dpoi_type);
523 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
524 "bucket %d label stacks on adj %d",
526 exp->label_o_adj.adj);
529 case FT_LB_LABEL_O_LB:
531 const mpls_label_dpo_t *mld;
532 mpls_label_dpo_flags_t mf;
535 mf = ((exp->label_o_lb.mode ==
536 FIB_MPLS_LSP_MODE_UNIFORM) ?
537 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
538 MPLS_LABEL_DPO_FLAG_NONE);
539 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
540 "bucket %d stacks on %U",
542 format_dpo_type, dpo->dpoi_type);
544 mld = mpls_label_dpo_get(dpo->dpoi_index);
545 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
547 FIB_TEST_LB(1 == mld->mld_n_labels, "label stack size",
549 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
550 exp->label_o_lb.label),
551 "bucket %d stacks on label %d",
553 exp->label_o_lb.label);
555 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
556 exp->label_o_lb.eos),
557 "bucket %d stacks on label %d %U",
559 exp->label_o_lb.label,
560 format_mpls_eos_bit, exp->label_o_lb.eos);
562 FIB_TEST_LB((DPO_LOAD_BALANCE == mld->mld_dpo.dpoi_type),
563 "bucket %d label stacks on %U",
565 format_dpo_type, mld->mld_dpo.dpoi_type);
567 FIB_TEST_LB((exp->label_o_lb.lb == mld->mld_dpo.dpoi_index),
568 "bucket %d label stacks on LB %d",
574 res = FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
575 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
576 "bucket %d stacks on %U",
578 format_dpo_type, dpo->dpoi_type);
579 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
580 "bucket %d stacks on adj %d",
584 case FT_LB_MPLS_DISP_PIPE_O_ADJ:
586 const mpls_disp_dpo_t *mdd;
588 res = FIB_TEST_I((DPO_MPLS_DISPOSITION_PIPE == dpo->dpoi_type),
589 "bucket %d stacks on %U",
591 format_dpo_type, dpo->dpoi_type);
593 mdd = mpls_disp_dpo_get(dpo->dpoi_index);
597 res = FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
598 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
599 "bucket %d stacks on %U",
601 format_dpo_type, dpo->dpoi_type);
602 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
603 "bucket %d stacks on adj %d",
609 res = FIB_TEST_I((DPO_INTERFACE_RX == dpo->dpoi_type),
610 "bucket %d stacks on %U",
612 format_dpo_type, dpo->dpoi_type);
613 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
614 "bucket %d stacks on adj %d",
619 res = FIB_TEST_I((DPO_DVR == dpo->dpoi_type),
620 "bucket %d stacks on %U",
622 format_dpo_type, dpo->dpoi_type);
623 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
624 "bucket %d stacks on adj %d",
629 res = FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
630 "bucket %d stacks on %U",
632 format_dpo_type, dpo->dpoi_type);
633 FIB_TEST_LB((exp->lb.lb == dpo->dpoi_index),
634 "bucket %d stacks on lb %d not %d",
639 case FT_LB_BIER_TABLE:
640 FIB_TEST_LB((DPO_BIER_TABLE == dpo->dpoi_type),
641 "bucket %d stacks on %U",
643 format_dpo_type, dpo->dpoi_type);
644 FIB_TEST_LB((exp->bier.table == dpo->dpoi_index),
645 "bucket %d stacks on lb %d",
649 case FT_LB_BIER_FMASK:
650 FIB_TEST_LB((DPO_BIER_FMASK == dpo->dpoi_type),
651 "bucket %d stacks on %U",
653 format_dpo_type, dpo->dpoi_type);
654 FIB_TEST_LB((exp->bier.fmask == dpo->dpoi_index),
655 "bucket %d stacks on lb %d",
660 FIB_TEST_LB((DPO_DROP == dpo->dpoi_type),
661 "bucket %d stacks on %U",
663 format_dpo_type, dpo->dpoi_type);
666 FIB_TEST_LB((DPO_PUNT == dpo->dpoi_type),
667 "bucket %d stacks on %U",
669 format_dpo_type, dpo->dpoi_type);
677 fib_test_validate_lb (const dpo_id_t *dpo,
681 const load_balance_t *lb;
686 va_start(ap, n_buckets);
688 if (!FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
690 format_dpo_type, dpo->dpoi_type))
692 lb = load_balance_get(dpo->dpoi_index);
694 res = fib_test_validate_lb_v(lb, n_buckets, &ap);
707 fib_test_validate_entry (fib_node_index_t fei,
708 fib_forward_chain_type_t fct,
712 dpo_id_t dpo = DPO_INVALID;
713 const fib_prefix_t *pfx;
721 pfx = fib_entry_get_prefix(fei);
722 fib_index = fib_entry_get_fib_index(fei);
723 fib_entry_contribute_forwarding(fei, fct, &dpo);
725 if (DPO_REPLICATE == dpo.dpoi_type)
727 const replicate_t *rep;
729 va_start(ap, n_buckets);
730 rep = replicate_get(dpo.dpoi_index);
731 res = fib_test_validate_rep_v(rep, n_buckets, &ap);
736 const load_balance_t *lb;
738 FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type),
739 "%U Entry links to %U",
740 format_fib_prefix, pfx,
741 format_dpo_type, dpo.dpoi_type);
743 va_start(ap, n_buckets);
744 lb = load_balance_get(dpo.dpoi_index);
745 res = fib_test_validate_lb_v(lb, n_buckets, &ap);
749 * ensure that the LB contributed by the entry is the
750 * same as the LB in the forwarding tables
752 if (fct == fib_entry_get_default_chain_type(fib_entry_get(fei)))
754 switch (pfx->fp_proto)
756 case FIB_PROTOCOL_IP4:
757 fw_lbi = ip4_fib_forwarding_lookup(fib_index, &pfx->fp_addr.ip4);
759 case FIB_PROTOCOL_IP6:
760 fw_lbi = ip6_fib_table_fwding_lookup(fib_index, &pfx->fp_addr.ip6);
762 case FIB_PROTOCOL_MPLS:
764 mpls_unicast_header_t hdr = {
765 .label_exp_s_ttl = 0,
768 vnet_mpls_uc_set_label(&hdr.label_exp_s_ttl, pfx->fp_label);
769 vnet_mpls_uc_set_s(&hdr.label_exp_s_ttl, pfx->fp_eos);
770 hdr.label_exp_s_ttl = clib_host_to_net_u32(hdr.label_exp_s_ttl);
772 fw_lbi = mpls_fib_table_forwarding_lookup(fib_index, &hdr);
778 FIB_TEST_LB((fw_lbi == dpo.dpoi_index),
779 "Contributed LB = FW LB:\n fwd:%U\n cont:%U",
780 format_load_balance, fw_lbi, 0,
781 format_load_balance, dpo.dpoi_index, 0);
794 * In the default table check for the presence and correct forwarding
795 * of the special entries
797 fib_node_index_t dfrt, fei, ai, ai2, locked_ai, ai_01, ai_02, ai_03;
798 const dpo_id_t *dpo, *dpo1, *dpo2, *dpo_drop;
799 const ip_adjacency_t *adj;
800 const load_balance_t *lb;
808 ip46_address_t nh_10_10_10_1 = {
809 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
812 ip46_address_t nh_10_10_10_2 = {
813 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
816 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
817 pool_elts(load_balance_map_pool));
821 /* record the nubmer of load-balances in use before we start */
822 lb_count = pool_elts(load_balance_pool);
824 /* Find or create FIB table 11 */
825 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11,
828 for (ii = 0; ii < 4; ii++)
830 ip4_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
833 fib_prefix_t pfx_0_0_0_0_s_0 = {
835 .fp_proto = FIB_PROTOCOL_IP4,
845 .fp_proto = FIB_PROTOCOL_IP4,
853 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
855 dfrt = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
856 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
857 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
858 "Default route is DROP");
861 fei = fib_table_lookup(fib_index, &pfx);
862 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all zeros route present");
863 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
864 "all 0s route is DROP");
866 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xffffffff);
868 fei = fib_table_lookup(fib_index, &pfx);
869 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all ones route present");
870 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
871 "all 1s route is DROP");
873 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xe0000000);
875 fei = fib_table_lookup(fib_index, &pfx);
876 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all-mcast route present");
877 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
878 "all-mcast route is DROP");
880 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xf0000000);
882 fei = fib_table_lookup(fib_index, &pfx);
883 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "class-e route present");
884 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
885 "class-e route is DROP");
888 * at this stage there are 5 entries in the test FIB (plus 5 in the default),
889 * all of which are special sourced and so none of which share path-lists.
890 * There are also 2 entries, and 2 non-shared path-lists, in the v6 default
891 * table, and 4 path-lists in the v6 MFIB table and 2 in v4.
895 u32 PNBR = 5+5+2+4+2;
898 * if the IGMP plugin is loaded this adds two more entries to the v4 MFIB
900 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
901 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
902 fib_path_list_pool_size());
903 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
904 fib_entry_pool_size());
907 * add interface routes.
908 * validate presence of /24 attached and /32 recieve.
909 * test for the presence of the receive address in the glean and local adj
911 fib_prefix_t local_pfx = {
913 .fp_proto = FIB_PROTOCOL_IP4,
916 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
921 fib_table_entry_update_one_path(fib_index, &local_pfx,
922 FIB_SOURCE_INTERFACE,
923 (FIB_ENTRY_FLAG_CONNECTED |
924 FIB_ENTRY_FLAG_ATTACHED),
927 tm->hw[0]->sw_if_index,
928 ~0, // invalid fib index
931 FIB_ROUTE_PATH_FLAG_NONE);
932 fei = fib_table_lookup(fib_index, &local_pfx);
933 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
934 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
935 fib_entry_get_flags(fei)),
936 "Flags set on attached interface");
938 ai = fib_entry_get_adj(fei);
939 FIB_TEST((FIB_NODE_INDEX_INVALID != ai),
940 "attached interface route adj present %d", ai);
942 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
943 "attached interface adj is glean");
945 local_pfx.fp_len = 32;
946 fib_table_entry_update_one_path(fib_index, &local_pfx,
947 FIB_SOURCE_INTERFACE,
948 (FIB_ENTRY_FLAG_CONNECTED |
949 FIB_ENTRY_FLAG_LOCAL),
952 tm->hw[0]->sw_if_index,
953 ~0, // invalid fib index
956 FIB_ROUTE_PATH_FLAG_NONE);
957 fei = fib_table_lookup(fib_index, &local_pfx);
958 FIB_TEST(((FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_CONNECTED) ==
959 fib_entry_get_flags(fei)),
960 "Flags set on local interface");
962 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
964 dpo = fib_entry_contribute_ip_forwarding(fei);
965 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
966 "RPF list for local length 0");
967 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
968 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
969 "local interface adj is local");
970 receive_dpo_t *rd = receive_dpo_get(dpo->dpoi_index);
972 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
974 "local interface adj is receive ok");
976 FIB_TEST((2 == fib_table_get_num_entries(fib_index,
978 FIB_SOURCE_INTERFACE)),
979 "2 Interface Source'd prefixes");
980 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
981 &adj->sub_type.glean.rx_pfx.fp_addr)),
982 "attached interface adj is receive ok");
985 * +2 interface routes +2 non-shared path-lists
987 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
988 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
989 fib_path_list_pool_size());
990 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
991 fib_entry_pool_size());
994 * Modify the default route to be via an adj not yet known.
995 * this sources the defalut route with the API source, which is
996 * a higher preference to the DEFAULT_ROUTE source
998 pfx.fp_addr.ip4.as_u32 = 0;
1000 fib_table_entry_path_add(fib_index, &pfx,
1002 FIB_ENTRY_FLAG_NONE,
1005 tm->hw[0]->sw_if_index,
1006 ~0, // invalid fib index
1009 FIB_ROUTE_PATH_FLAG_NONE);
1010 fei = fib_table_lookup(fib_index, &pfx);
1011 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
1012 "Flags set on API route");
1014 FIB_TEST((fei == dfrt), "default route same index");
1015 ai = fib_entry_get_adj(fei);
1016 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
1018 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1019 "adj is incomplete");
1020 FIB_TEST((0 == ip46_address_cmp(&nh_10_10_10_1, &adj->sub_type.nbr.next_hop)),
1021 "adj nbr next-hop ok");
1022 FIB_TEST((1 == fib_table_get_num_entries(fib_index,
1025 "1 API Source'd prefixes");
1028 * find the adj in the shared db
1030 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1033 tm->hw[0]->sw_if_index);
1034 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
1035 adj_unlock(locked_ai);
1038 * +1 shared path-list
1040 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
1041 fib_path_list_db_size());
1042 FIB_TEST((PNBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
1043 fib_path_list_pool_size());
1044 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
1045 fib_entry_pool_size());
1048 * remove the API source from the default route. We expected
1049 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
1051 pfx.fp_addr.ip4.as_u32 = 0;
1053 fib_table_entry_path_remove(fib_index, &pfx,
1057 tm->hw[0]->sw_if_index,
1058 ~0, // non-recursive path, so no FIB index
1060 FIB_ROUTE_PATH_FLAG_NONE);
1062 fei = fib_table_lookup(fib_index, &pfx);
1064 FIB_TEST((fei == dfrt), "default route same index");
1065 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
1066 "Default route is DROP");
1069 * -1 shared-path-list
1071 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
1072 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
1073 fib_path_list_pool_size());
1074 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
1075 fib_entry_pool_size());
1078 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
1080 fib_prefix_t pfx_10_10_10_1_s_32 = {
1082 .fp_proto = FIB_PROTOCOL_IP4,
1085 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
1088 fib_prefix_t pfx_10_10_10_2_s_32 = {
1090 .fp_proto = FIB_PROTOCOL_IP4,
1093 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
1096 fib_prefix_t pfx_11_11_11_11_s_32 = {
1098 .fp_proto = FIB_PROTOCOL_IP4,
1101 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
1105 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
1108 ip46_address_t nh_12_12_12_12 = {
1109 .ip4.as_u32 = clib_host_to_net_u32(0x0c0c0c0c),
1111 adj_index_t ai_12_12_12_12;
1114 * Add a route via an incomplete ADJ. then complete the ADJ
1115 * Expect the route LB is updated to use complete adj type.
1117 fei = fib_table_entry_update_one_path(fib_index,
1118 &pfx_11_11_11_11_s_32,
1120 FIB_ENTRY_FLAG_ATTACHED,
1122 &pfx_10_10_10_1_s_32.fp_addr,
1123 tm->hw[0]->sw_if_index,
1124 ~0, // invalid fib index
1127 FIB_ROUTE_PATH_FLAG_NONE);
1129 dpo = fib_entry_contribute_ip_forwarding(fei);
1130 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1131 FIB_TEST(DPO_ADJACENCY_INCOMPLETE == dpo1->dpoi_type,
1132 "11.11.11.11/32 via incomplete adj");
1134 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1136 &pfx_10_10_10_1_s_32.fp_addr,
1137 tm->hw[0]->sw_if_index);
1138 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
1139 adj = adj_get(ai_01);
1140 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1141 "adj is incomplete");
1142 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1143 &adj->sub_type.nbr.next_hop)),
1144 "adj nbr next-hop ok");
1146 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1147 fib_test_build_rewrite(eth_addr));
1148 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1150 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1151 &adj->sub_type.nbr.next_hop)),
1152 "adj nbr next-hop ok");
1153 ai = fib_entry_get_adj(fei);
1154 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
1156 dpo = fib_entry_contribute_ip_forwarding(fei);
1157 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1158 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type,
1159 "11.11.11.11/32 via complete adj");
1160 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1161 tm->hw[0]->sw_if_index),
1162 "RPF list for adj-fib contains adj");
1164 ai_12_12_12_12 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1167 tm->hw[1]->sw_if_index);
1168 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_12_12_12_12), "adj created");
1169 adj = adj_get(ai_12_12_12_12);
1170 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1171 "adj is incomplete");
1172 FIB_TEST((0 == ip46_address_cmp(&nh_12_12_12_12,
1173 &adj->sub_type.nbr.next_hop)),
1174 "adj nbr next-hop ok");
1175 adj_nbr_update_rewrite(ai_12_12_12_12, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1176 fib_test_build_rewrite(eth_addr));
1177 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1183 fei = fib_table_entry_path_add(fib_index,
1184 &pfx_10_10_10_1_s_32,
1186 FIB_ENTRY_FLAG_ATTACHED,
1188 &pfx_10_10_10_1_s_32.fp_addr,
1189 tm->hw[0]->sw_if_index,
1190 ~0, // invalid fib index
1193 FIB_ROUTE_PATH_FLAG_NONE);
1194 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
1195 "Flags set on adj-fib");
1196 ai = fib_entry_get_adj(fei);
1197 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj, %d", ai);
1199 fib_table_entry_path_remove(fib_index,
1200 &pfx_11_11_11_11_s_32,
1203 &pfx_10_10_10_1_s_32.fp_addr,
1204 tm->hw[0]->sw_if_index,
1205 ~0, // invalid fib index
1207 FIB_ROUTE_PATH_FLAG_NONE);
1211 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1213 &pfx_10_10_10_2_s_32.fp_addr,
1214 tm->hw[0]->sw_if_index);
1215 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
1216 adj = adj_get(ai_02);
1217 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1218 "adj is incomplete");
1219 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1220 &adj->sub_type.nbr.next_hop)),
1221 "adj nbr next-hop ok");
1223 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1224 fib_test_build_rewrite(eth_addr));
1225 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1227 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1228 &adj->sub_type.nbr.next_hop)),
1229 "adj nbr next-hop ok");
1230 FIB_TEST((ai_01 != ai_02), "ADJs are different");
1232 fib_table_entry_path_add(fib_index,
1233 &pfx_10_10_10_2_s_32,
1235 FIB_ENTRY_FLAG_ATTACHED,
1237 &pfx_10_10_10_2_s_32.fp_addr,
1238 tm->hw[0]->sw_if_index,
1239 ~0, // invalid fib index
1242 FIB_ROUTE_PATH_FLAG_NONE);
1244 fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32);
1245 ai = fib_entry_get_adj(fei);
1246 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
1249 * +2 adj-fibs, and their non-shared path-lists
1251 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
1252 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
1253 fib_path_list_pool_size());
1254 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
1255 fib_entry_pool_size());
1258 * Add 2 routes via the first ADJ. ensure path-list sharing
1260 fib_prefix_t pfx_1_1_1_1_s_32 = {
1262 .fp_proto = FIB_PROTOCOL_IP4,
1265 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1269 fib_table_entry_path_add(fib_index,
1272 FIB_ENTRY_FLAG_NONE,
1275 tm->hw[0]->sw_if_index,
1276 ~0, // invalid fib index
1279 FIB_ROUTE_PATH_FLAG_NONE);
1280 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
1281 ai = fib_entry_get_adj(fei);
1282 FIB_TEST((ai_01 == ai), "1.1.1.1 resolves via 10.10.10.1");
1285 * +1 entry and a shared path-list
1287 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
1288 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1289 fib_path_list_pool_size());
1290 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
1291 fib_entry_pool_size());
1294 fib_prefix_t pfx_1_1_2_0_s_24 = {
1296 .fp_proto = FIB_PROTOCOL_IP4,
1298 .ip4.as_u32 = clib_host_to_net_u32(0x01010200),
1302 fib_table_entry_path_add(fib_index,
1305 FIB_ENTRY_FLAG_NONE,
1308 tm->hw[0]->sw_if_index,
1309 ~0, // invalid fib index
1312 FIB_ROUTE_PATH_FLAG_NONE);
1313 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1314 ai = fib_entry_get_adj(fei);
1315 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1320 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
1321 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1322 fib_path_list_pool_size());
1323 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1324 fib_entry_pool_size());
1327 * modify 1.1.2.0/24 to use multipath.
1329 fib_table_entry_path_add(fib_index,
1332 FIB_ENTRY_FLAG_NONE,
1335 tm->hw[0]->sw_if_index,
1336 ~0, // invalid fib index
1339 FIB_ROUTE_PATH_FLAG_NONE);
1340 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1341 dpo = fib_entry_contribute_ip_forwarding(fei);
1342 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1343 1, tm->hw[0]->sw_if_index),
1344 "RPF list for 1.1.2.0/24 contains both adjs");
1346 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1347 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1348 FIB_TEST((ai_01 == dpo1->dpoi_index),
1349 "1.1.2.0/24 bucket 0 resolves via 10.10.10.1 (%d=%d)",
1350 ai_01, dpo1->dpoi_index);
1352 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 1);
1353 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1354 FIB_TEST((ai_02 == dpo1->dpoi_index),
1355 "1.1.2.0/24 bucket 1 resolves via 10.10.10.2");
1358 * +1 shared-pathlist
1360 FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty");
1361 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1362 fib_path_list_pool_size());
1363 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1364 fib_entry_pool_size());
1369 fib_table_entry_path_remove(fib_index,
1374 tm->hw[0]->sw_if_index,
1377 FIB_ROUTE_PATH_FLAG_NONE);
1378 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1379 dpo = fib_entry_contribute_ip_forwarding(fei);
1380 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1381 1, tm->hw[0]->sw_if_index),
1382 "RPF list for 1.1.2.0/24 contains one adj");
1384 ai = fib_entry_get_adj(fei);
1385 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1388 * +1 shared-pathlist
1390 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d",
1391 fib_path_list_db_size());
1392 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1393 fib_path_list_pool_size());
1394 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1395 fib_entry_pool_size());
1398 * Add 2 recursive routes:
1399 * 100.100.100.100/32 via 1.1.1.1/32 => the via entry is installed.
1400 * 100.100.100.101/32 via 1.1.1.1/32 => the via entry is installed.
1402 fib_prefix_t bgp_100_pfx = {
1404 .fp_proto = FIB_PROTOCOL_IP4,
1406 /* 100.100.100.100/32 */
1407 .ip4.as_u32 = clib_host_to_net_u32(0x64646464),
1411 ip46_address_t nh_1_1_1_1 = {
1412 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1415 fei = fib_table_entry_path_add(fib_index,
1418 FIB_ENTRY_FLAG_NONE,
1421 ~0, // no index provided.
1422 fib_index, // nexthop in same fib as route
1425 FIB_ROUTE_PATH_FLAG_NONE);
1427 FIB_TEST_REC_FORW(&bgp_100_pfx, &pfx_1_1_1_1_s_32, 0);
1428 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1429 tm->hw[0]->sw_if_index),
1430 "RPF list for adj-fib contains adj");
1433 * +1 entry and +1 shared-path-list
1435 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1436 fib_path_list_db_size());
1437 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1438 fib_path_list_pool_size());
1439 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
1440 fib_entry_pool_size());
1442 fib_prefix_t bgp_101_pfx = {
1444 .fp_proto = FIB_PROTOCOL_IP4,
1446 /* 100.100.100.101/32 */
1447 .ip4.as_u32 = clib_host_to_net_u32(0x64646465),
1451 fib_table_entry_path_add(fib_index,
1454 FIB_ENTRY_FLAG_NONE,
1457 ~0, // no index provided.
1458 fib_index, // nexthop in same fib as route
1461 FIB_ROUTE_PATH_FLAG_NONE);
1463 FIB_TEST_REC_FORW(&bgp_101_pfx, &pfx_1_1_1_1_s_32, 0);
1464 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1465 tm->hw[0]->sw_if_index),
1466 "RPF list for adj-fib contains adj");
1469 * +1 entry, but the recursive path-list is shared.
1471 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1472 fib_path_list_db_size());
1473 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1474 fib_path_list_pool_size());
1475 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
1476 fib_entry_pool_size());
1479 * An special route; one where the user (me) provides the
1480 * adjacency through which the route will resovle by setting the flags
1482 fib_prefix_t ex_pfx = {
1484 .fp_proto = FIB_PROTOCOL_IP4,
1487 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
1491 fib_table_entry_special_add(fib_index,
1494 FIB_ENTRY_FLAG_LOCAL);
1495 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1496 dpo = fib_entry_contribute_ip_forwarding(fei);
1497 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
1498 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
1499 "local interface adj is local");
1501 fib_table_entry_special_remove(fib_index,
1503 FIB_SOURCE_SPECIAL);
1504 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1505 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1506 "Exclusive reoute removed");
1509 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1510 * adjacency through which the route will resovle
1512 dpo_id_t ex_dpo = DPO_INVALID;
1514 lookup_dpo_add_or_lock_w_fib_index(fib_index,
1517 LOOKUP_INPUT_DST_ADDR,
1518 LOOKUP_TABLE_FROM_CONFIG,
1521 fib_table_entry_special_dpo_add(fib_index,
1524 FIB_ENTRY_FLAG_EXCLUSIVE,
1526 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1527 dpo = fib_entry_contribute_ip_forwarding(fei);
1528 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1529 "exclusive remote uses lookup DPO");
1532 * update the exclusive to use a different DPO
1534 ip_null_dpo_add_and_lock(DPO_PROTO_IP4,
1535 IP_NULL_ACTION_SEND_ICMP_UNREACH,
1537 fib_table_entry_special_dpo_update(fib_index,
1540 FIB_ENTRY_FLAG_EXCLUSIVE,
1542 dpo = fib_entry_contribute_ip_forwarding(fei);
1543 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1544 "exclusive remote uses now uses NULL DPO");
1546 fib_table_entry_special_remove(fib_index,
1548 FIB_SOURCE_SPECIAL);
1549 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1550 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1551 "Exclusive reoute removed");
1555 * Add a recursive route:
1556 * 200.200.200.200/32 via 1.1.1.2/32 => the via entry is NOT installed.
1558 fib_prefix_t bgp_200_pfx = {
1560 .fp_proto = FIB_PROTOCOL_IP4,
1562 /* 200.200.200.200/32 */
1563 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c8),
1567 fib_prefix_t pfx_1_1_1_2_s_32 = {
1569 .fp_proto = FIB_PROTOCOL_IP4,
1571 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
1575 fei = fib_table_entry_path_add(fib_index,
1578 FIB_ENTRY_FLAG_NONE,
1580 &pfx_1_1_1_2_s_32.fp_addr,
1581 ~0, // no index provided.
1582 fib_index, // nexthop in same fib as route
1585 FIB_ROUTE_PATH_FLAG_NONE);
1587 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
1588 "Recursive via unresolved is drop");
1591 * the adj should be recursive via drop, since the route resolves via
1592 * the default route, which is itself a DROP
1594 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
1595 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1596 FIB_TEST(load_balance_is_drop(dpo1), "1.1.1.2/32 is drop");
1597 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1598 "RPF list for 1.1.1.2/32 contains 0 adjs");
1601 * +2 entry and +1 shared-path-list
1603 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
1604 fib_path_list_db_size());
1605 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
1606 fib_path_list_pool_size());
1607 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
1608 fib_entry_pool_size());
1611 * Unequal Cost load-balance. 3:1 ratio. fits in a 4 bucket LB
1612 * The paths are sort by NH first. in this case the the path with greater
1613 * weight is first in the set. This ordering is to test the RPF sort|uniq logic
1615 fib_prefix_t pfx_1_2_3_4_s_32 = {
1617 .fp_proto = FIB_PROTOCOL_IP4,
1619 .ip4.as_u32 = clib_host_to_net_u32(0x01020304),
1622 fib_table_entry_path_add(fib_index,
1625 FIB_ENTRY_FLAG_NONE,
1628 tm->hw[0]->sw_if_index,
1632 FIB_ROUTE_PATH_FLAG_NONE);
1633 fei = fib_table_entry_path_add(fib_index,
1636 FIB_ENTRY_FLAG_NONE,
1639 tm->hw[1]->sw_if_index,
1643 FIB_ROUTE_PATH_FLAG_NONE);
1645 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.4/32 presnet");
1646 dpo = fib_entry_contribute_ip_forwarding(fei);
1647 lb = load_balance_get(dpo->dpoi_index);
1648 FIB_TEST((lb->lb_n_buckets == 4),
1649 "1.2.3.4/32 LB has %d bucket",
1652 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 0, ai_12_12_12_12);
1653 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 1, ai_12_12_12_12);
1654 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 2, ai_12_12_12_12);
1655 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 3, ai_01);
1657 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1658 tm->hw[0]->sw_if_index,
1659 tm->hw[1]->sw_if_index),
1660 "RPF list for 1.2.3.4/32 contains both adjs");
1664 * Unequal Cost load-balance. 4:1 ratio.
1665 * fits in a 16 bucket LB with ratio 13:3
1667 fib_prefix_t pfx_1_2_3_5_s_32 = {
1669 .fp_proto = FIB_PROTOCOL_IP4,
1671 .ip4.as_u32 = clib_host_to_net_u32(0x01020305),
1674 fib_table_entry_path_add(fib_index,
1677 FIB_ENTRY_FLAG_NONE,
1680 tm->hw[1]->sw_if_index,
1684 FIB_ROUTE_PATH_FLAG_NONE);
1685 fei = fib_table_entry_path_add(fib_index,
1688 FIB_ENTRY_FLAG_NONE,
1691 tm->hw[0]->sw_if_index,
1695 FIB_ROUTE_PATH_FLAG_NONE);
1697 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.5/32 presnet");
1698 dpo = fib_entry_contribute_ip_forwarding(fei);
1699 lb = load_balance_get(dpo->dpoi_index);
1700 FIB_TEST((lb->lb_n_buckets == 16),
1701 "1.2.3.5/32 LB has %d bucket",
1704 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 0, ai_01);
1705 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 1, ai_01);
1706 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 2, ai_01);
1707 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 3, ai_01);
1708 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 4, ai_01);
1709 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 5, ai_01);
1710 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 6, ai_01);
1711 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 7, ai_01);
1712 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 8, ai_01);
1713 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 9, ai_01);
1714 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 10, ai_01);
1715 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 11, ai_01);
1716 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 12, ai_01);
1717 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 13, ai_12_12_12_12);
1718 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 14, ai_12_12_12_12);
1719 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 15, ai_12_12_12_12);
1721 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1722 tm->hw[0]->sw_if_index,
1723 tm->hw[1]->sw_if_index),
1724 "RPF list for 1.2.3.4/32 contains both adjs");
1727 * Test UCMP with a large weight skew - this produces load-balance objects with large
1728 * numbers of buckets to accommodate the skew. By updating said load-balances we are
1729 * laso testing the LB in placce modify code when number of buckets is large.
1731 fib_prefix_t pfx_6_6_6_6_s_32 = {
1733 .fp_proto = FIB_PROTOCOL_IP4,
1736 .ip4.as_u32 = clib_host_to_net_u32(0x06060606),
1739 fib_test_lb_bucket_t ip_o_10_10_10_1 = {
1745 fib_test_lb_bucket_t ip_o_10_10_10_2 = {
1751 fib_test_lb_bucket_t ip_6_6_6_6_o_12_12_12_12 = {
1754 .adj = ai_12_12_12_12,
1757 fib_table_entry_update_one_path(fib_index,
1760 FIB_ENTRY_FLAG_NONE,
1763 tm->hw[0]->sw_if_index,
1764 ~0, // invalid fib index
1767 FIB_ROUTE_PATH_FLAG_NONE);
1769 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1770 FIB_TEST(!fib_test_validate_entry(fei,
1771 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1774 "6.6.6.6/32 via 10.10.10.1");
1776 fib_table_entry_path_add(fib_index,
1779 FIB_ENTRY_FLAG_NONE,
1782 tm->hw[0]->sw_if_index,
1783 ~0, // invalid fib index
1786 FIB_ROUTE_PATH_FLAG_NONE);
1788 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1789 FIB_TEST(!fib_test_validate_entry(fei,
1790 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1856 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1858 fib_table_entry_path_add(fib_index,
1861 FIB_ENTRY_FLAG_NONE,
1864 tm->hw[1]->sw_if_index,
1865 ~0, // invalid fib index
1868 FIB_ROUTE_PATH_FLAG_NONE);
1870 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1871 FIB_TEST(!fib_test_validate_entry(fei,
1872 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
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 &ip_6_6_6_6_o_12_12_12_12,
1994 &ip_6_6_6_6_o_12_12_12_12,
1995 &ip_6_6_6_6_o_12_12_12_12,
1996 &ip_6_6_6_6_o_12_12_12_12,
1997 &ip_6_6_6_6_o_12_12_12_12,
1998 &ip_6_6_6_6_o_12_12_12_12,
1999 &ip_6_6_6_6_o_12_12_12_12,
2000 &ip_6_6_6_6_o_12_12_12_12,
2001 &ip_6_6_6_6_o_12_12_12_12),
2002 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
2004 fib_table_entry_path_remove(fib_index,
2009 tm->hw[1]->sw_if_index,
2010 ~0, // invalid fib index
2012 FIB_ROUTE_PATH_FLAG_NONE);
2014 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
2015 FIB_TEST(!fib_test_validate_entry(fei,
2016 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2082 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
2084 fib_table_entry_path_remove(fib_index,
2089 tm->hw[0]->sw_if_index,
2090 ~0, // invalid fib index
2092 FIB_ROUTE_PATH_FLAG_NONE);
2094 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
2095 FIB_TEST(!fib_test_validate_entry(fei,
2096 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2099 "6.6.6.6/32 via 10.10.10.1");
2101 fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API);
2104 * A recursive via the two unequal cost entries
2106 fib_prefix_t bgp_44_s_32 = {
2108 .fp_proto = FIB_PROTOCOL_IP4,
2110 /* 200.200.200.201/32 */
2111 .ip4.as_u32 = clib_host_to_net_u32(0x44444444),
2114 fei = fib_table_entry_path_add(fib_index,
2117 FIB_ENTRY_FLAG_NONE,
2119 &pfx_1_2_3_4_s_32.fp_addr,
2124 FIB_ROUTE_PATH_FLAG_NONE);
2125 fei = fib_table_entry_path_add(fib_index,
2128 FIB_ENTRY_FLAG_NONE,
2130 &pfx_1_2_3_5_s_32.fp_addr,
2135 FIB_ROUTE_PATH_FLAG_NONE);
2137 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_4_s_32, 0);
2138 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_5_s_32, 1);
2139 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
2140 tm->hw[0]->sw_if_index,
2141 tm->hw[1]->sw_if_index),
2142 "RPF list for 1.2.3.4/32 contains both adjs");
2145 * test the uRPF check functions
2147 dpo_id_t dpo_44 = DPO_INVALID;
2150 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
2151 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
2153 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
2154 "uRPF check for 68.68.68.68/32 on %d OK",
2155 tm->hw[0]->sw_if_index);
2156 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
2157 "uRPF check for 68.68.68.68/32 on %d OK",
2158 tm->hw[1]->sw_if_index);
2159 FIB_TEST(!fib_urpf_check(urpfi, 99),
2160 "uRPF check for 68.68.68.68/32 on 99 not-OK",
2164 fib_table_entry_delete(fib_index,
2167 fib_table_entry_delete(fib_index,
2170 fib_table_entry_delete(fib_index,
2175 * Add a recursive route:
2176 * 200.200.200.201/32 via 1.1.1.200/32 => the via entry is NOT installed.
2178 fib_prefix_t bgp_201_pfx = {
2180 .fp_proto = FIB_PROTOCOL_IP4,
2182 /* 200.200.200.201/32 */
2183 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c9),
2187 fib_prefix_t pfx_1_1_1_200_s_32 = {
2189 .fp_proto = FIB_PROTOCOL_IP4,
2191 .ip4.as_u32 = clib_host_to_net_u32(0x010101c8),
2195 fei = fib_table_entry_path_add(fib_index,
2198 FIB_ENTRY_FLAG_NONE,
2200 &pfx_1_1_1_200_s_32.fp_addr,
2201 ~0, // no index provided.
2202 fib_index, // nexthop in same fib as route
2205 FIB_ROUTE_PATH_FLAG_NONE);
2207 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2208 "Recursive via unresolved is drop");
2210 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2211 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
2212 "Flags set on RR via non-attached");
2213 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
2214 "RPF list for BGP route empty");
2217 * +2 entry (BGP & RR) and +1 shared-path-list
2219 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2220 fib_path_list_db_size());
2221 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2222 fib_path_list_pool_size());
2223 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2224 fib_entry_pool_size());
2227 * insert a route that covers the missing 1.1.1.2/32. we epxect
2228 * 200.200.200.200/32 and 200.200.200.201/32 to resolve through it.
2230 fib_prefix_t pfx_1_1_1_0_s_24 = {
2232 .fp_proto = FIB_PROTOCOL_IP4,
2235 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2239 fib_table_entry_path_add(fib_index,
2242 FIB_ENTRY_FLAG_NONE,
2245 tm->hw[0]->sw_if_index,
2246 ~0, // invalid fib index
2249 FIB_ROUTE_PATH_FLAG_NONE);
2250 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24);
2251 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2252 ai = fib_entry_get_adj(fei);
2253 FIB_TEST((ai_01 == ai), "1.1.1.0/24 resolves via 10.10.10.1");
2254 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2255 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2256 ai = fib_entry_get_adj(fei);
2257 FIB_TEST((ai_01 == ai), "1.1.1.2/32 resolves via 10.10.10.1");
2258 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2259 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2260 ai = fib_entry_get_adj(fei);
2261 FIB_TEST((ai_01 == ai), "1.1.1.200/24 resolves via 10.10.10.1");
2264 * +1 entry. 1.1.1.1/32 already uses 10.10.10.1 so no new pah-list
2266 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2267 fib_path_list_db_size());
2268 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2269 fib_path_list_pool_size());
2270 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
2271 fib_entry_pool_size());
2274 * the recursive adj for 200.200.200.200 should be updated.
2276 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2277 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2278 fei = fib_table_lookup(fib_index, &bgp_200_pfx);
2279 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
2280 tm->hw[0]->sw_if_index),
2281 "RPF list for BGP route has itf index 0");
2284 * insert a more specific route than 1.1.1.0/24 that also covers the
2285 * missing 1.1.1.2/32, but not 1.1.1.200/32. we expect
2286 * 200.200.200.200 to resolve through it.
2288 fib_prefix_t pfx_1_1_1_0_s_28 = {
2290 .fp_proto = FIB_PROTOCOL_IP4,
2293 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2297 fib_table_entry_path_add(fib_index,
2300 FIB_ENTRY_FLAG_NONE,
2303 tm->hw[0]->sw_if_index,
2304 ~0, // invalid fib index
2307 FIB_ROUTE_PATH_FLAG_NONE);
2308 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28);
2309 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2310 ai = fib_entry_get_adj(fei);
2311 FIB_TEST((ai_02 == ai), "1.1.1.0/24 resolves via 10.10.10.2");
2314 * +1 entry. +1 shared path-list
2316 FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d",
2317 fib_path_list_db_size());
2318 FIB_TEST((PNBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
2319 fib_path_list_pool_size());
2320 FIB_TEST((ENBR+14 == fib_entry_pool_size()), "entry pool size is %d",
2321 fib_entry_pool_size());
2324 * the recursive adj for 200.200.200.200 should be updated.
2325 * 200.200.200.201 remains unchanged.
2327 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2328 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2331 * remove this /28. 200.200.200.200/32 should revert back to via 1.1.1.0/24
2333 fib_table_entry_path_remove(fib_index,
2338 tm->hw[0]->sw_if_index,
2341 FIB_ROUTE_PATH_FLAG_NONE);
2342 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28) ==
2343 FIB_NODE_INDEX_INVALID),
2344 "1.1.1.0/28 removed");
2345 FIB_TEST((fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28) ==
2346 fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24)),
2347 "1.1.1.0/28 lookup via /24");
2348 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2349 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2352 * -1 entry. -1 shared path-list
2354 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2355 fib_path_list_db_size());
2356 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2357 fib_path_list_pool_size());
2358 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
2359 fib_entry_pool_size());
2362 * remove 1.1.1.0/24. 200.200.200.200/32 should revert back to via 0.0.0.0/0
2364 fib_table_entry_path_remove(fib_index,
2369 tm->hw[0]->sw_if_index,
2372 FIB_ROUTE_PATH_FLAG_NONE);
2373 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_24) ==
2374 FIB_NODE_INDEX_INVALID),
2375 "1.1.1.0/24 removed");
2377 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2378 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2379 "1.1.1.2/32 route is DROP");
2380 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2381 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2382 "1.1.1.200/32 route is DROP");
2384 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2385 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2387 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2388 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2394 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2395 fib_path_list_db_size());
2396 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2397 fib_path_list_pool_size());
2398 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2399 fib_entry_pool_size());
2402 * insert the missing 1.1.1.2/32
2404 fei = fib_table_entry_path_add(fib_index,
2407 FIB_ENTRY_FLAG_NONE,
2410 tm->hw[0]->sw_if_index,
2411 ~0, // invalid fib index
2414 FIB_ROUTE_PATH_FLAG_NONE);
2415 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2416 ai = fib_entry_get_adj(fei);
2417 FIB_TEST((ai = ai_01), "1.1.1.2/32 resolves via 10.10.10.1");
2419 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2420 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2422 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2425 * no change. 1.1.1.2/32 was already there RR sourced.
2427 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2428 fib_path_list_db_size());
2429 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2430 fib_path_list_pool_size());
2431 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2432 fib_entry_pool_size());
2435 * give 201 a resolved path.
2436 * it now has the unresolved 1.1.1.200 and the resolved 1.1.1.2,
2437 * only the latter contributes forwarding.
2439 fei = fib_table_entry_path_add(fib_index,
2442 FIB_ENTRY_FLAG_NONE,
2444 &pfx_1_1_1_2_s_32.fp_addr,
2449 FIB_ROUTE_PATH_FLAG_NONE);
2450 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_2_s_32, 0);
2451 fib_table_entry_path_remove(fib_index,
2455 &pfx_1_1_1_2_s_32.fp_addr,
2459 FIB_ROUTE_PATH_FLAG_NONE);
2462 * remove 200.200.200.201/32 which does not have a valid via FIB
2464 fib_table_entry_path_remove(fib_index,
2468 &pfx_1_1_1_200_s_32.fp_addr,
2469 ~0, // no index provided.
2472 FIB_ROUTE_PATH_FLAG_NONE);
2475 * -2 entries (BGP and RR). -1 shared path-list;
2477 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2478 FIB_NODE_INDEX_INVALID),
2479 "200.200.200.201/32 removed");
2480 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32) ==
2481 FIB_NODE_INDEX_INVALID),
2482 "1.1.1.200/32 removed");
2484 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2485 fib_path_list_db_size());
2486 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
2487 fib_path_list_pool_size());
2488 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2489 fib_entry_pool_size());
2492 * remove 200.200.200.200/32 which does have a valid via FIB
2494 fib_table_entry_path_remove(fib_index,
2498 &pfx_1_1_1_2_s_32.fp_addr,
2499 ~0, // no index provided.
2502 FIB_ROUTE_PATH_FLAG_NONE);
2504 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2505 FIB_NODE_INDEX_INVALID),
2506 "200.200.200.200/32 removed");
2507 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32) !=
2508 FIB_NODE_INDEX_INVALID),
2509 "1.1.1.2/32 still present");
2512 * -1 entry (BGP, the RR source is also API sourced). -1 shared path-list;
2514 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2515 fib_path_list_db_size());
2516 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2517 fib_path_list_pool_size());
2518 FIB_TEST((ENBR+9 == fib_entry_pool_size()), "entry pool size is %d",
2519 fib_entry_pool_size());
2522 * A recursive prefix that has a 2 path load-balance.
2523 * It also shares a next-hop with other BGP prefixes and hence
2524 * test the ref counting of RR sourced prefixes and 2 level LB.
2526 const fib_prefix_t bgp_102 = {
2528 .fp_proto = FIB_PROTOCOL_IP4,
2530 /* 100.100.100.101/32 */
2531 .ip4.as_u32 = clib_host_to_net_u32(0x64646466),
2534 fib_table_entry_path_add(fib_index,
2537 FIB_ENTRY_FLAG_NONE,
2539 &pfx_1_1_1_1_s_32.fp_addr,
2540 ~0, // no index provided.
2541 fib_index, // same as route
2544 FIB_ROUTE_PATH_FLAG_NONE);
2545 fib_table_entry_path_add(fib_index,
2548 FIB_ENTRY_FLAG_NONE,
2550 &pfx_1_1_1_2_s_32.fp_addr,
2551 ~0, // no index provided.
2552 fib_index, // same as route's FIB
2555 FIB_ROUTE_PATH_FLAG_NONE);
2556 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2557 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "100.100.100.102/32 presnet");
2558 dpo = fib_entry_contribute_ip_forwarding(fei);
2560 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2561 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2562 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32);
2563 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2565 lb = load_balance_get(dpo->dpoi_index);
2566 FIB_TEST((lb->lb_n_buckets == 2), "Recursive LB has %d bucket", lb->lb_n_buckets);
2567 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2568 "First via 10.10.10.1");
2569 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 1)),
2570 "Second via 10.10.10.1");
2572 fib_table_entry_path_remove(fib_index,
2576 &pfx_1_1_1_1_s_32.fp_addr,
2577 ~0, // no index provided.
2578 fib_index, // same as route's FIB
2580 FIB_ROUTE_PATH_FLAG_NONE);
2581 fib_table_entry_path_remove(fib_index,
2585 &pfx_1_1_1_2_s_32.fp_addr,
2586 ~0, // no index provided.
2587 fib_index, // same as route's FIB
2589 FIB_ROUTE_PATH_FLAG_NONE);
2590 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2591 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "100.100.100.102/32 removed");
2594 * remove the remaining recursives
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_table_entry_path_remove(fib_index,
2609 &pfx_1_1_1_1_s_32.fp_addr,
2610 ~0, // no index provided.
2611 fib_index, // same as route's FIB
2613 FIB_ROUTE_PATH_FLAG_NONE);
2614 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_100_pfx) ==
2615 FIB_NODE_INDEX_INVALID),
2616 "100.100.100.100/32 removed");
2617 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_101_pfx) ==
2618 FIB_NODE_INDEX_INVALID),
2619 "100.100.100.101/32 removed");
2622 * -2 entry (2*BGP, the RR source is also API sourced). -1 shared path-list;
2624 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2625 fib_path_list_db_size());
2626 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2627 fib_path_list_pool_size());
2628 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2629 fib_entry_pool_size());
2632 * Add a recursive route via a connected cover, using an adj-fib that does exist
2634 fib_table_entry_path_add(fib_index,
2637 FIB_ENTRY_FLAG_NONE,
2640 ~0, // no index provided.
2641 fib_index, // Same as route's FIB
2644 FIB_ROUTE_PATH_FLAG_NONE);
2647 * +1 entry. +1 shared path-list (recursive via 10.10.10.1)
2649 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2650 fib_path_list_db_size());
2651 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2652 fib_path_list_pool_size());
2653 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
2654 fib_entry_pool_size());
2656 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2657 dpo = fib_entry_contribute_ip_forwarding(fei);
2659 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
2660 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2662 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2663 "200.200.200.200/32 is recursive via adj for 10.10.10.1");
2665 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
2666 "Flags set on RR via existing attached");
2669 * Add a recursive route via a connected cover, using and adj-fib that does
2672 ip46_address_t nh_10_10_10_3 = {
2673 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
2675 fib_prefix_t pfx_10_10_10_3 = {
2677 .fp_proto = FIB_PROTOCOL_IP4,
2678 .fp_addr = nh_10_10_10_3,
2681 fib_table_entry_path_add(fib_index,
2684 FIB_ENTRY_FLAG_NONE,
2687 ~0, // no index provided.
2691 FIB_ROUTE_PATH_FLAG_NONE);
2694 * +2 entries (BGP and RR). +1 shared path-list (recursive via 10.10.10.3) and
2695 * one unshared non-recursive via 10.10.10.3
2697 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2698 fib_path_list_db_size());
2699 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2700 fib_path_list_pool_size());
2701 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2702 fib_entry_pool_size());
2704 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
2707 tm->hw[0]->sw_if_index);
2709 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2710 dpo = fib_entry_contribute_ip_forwarding(fei);
2711 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3);
2712 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2714 ai = fib_entry_get_adj(fei);
2715 FIB_TEST((ai == ai_03), "adj for 10.10.10.3/32 is via adj for 10.10.10.3");
2716 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
2717 fib_entry_get_flags(fei)),
2718 "Flags set on RR via non-existing attached");
2720 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2721 "adj for 200.200.200.200/32 is recursive via adj for 10.10.10.3");
2726 * remove the recursives
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);
2737 fib_table_entry_path_remove(fib_index,
2742 ~0, // no index provided.
2743 fib_index, // same as route's FIB
2745 FIB_ROUTE_PATH_FLAG_NONE);
2747 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2748 FIB_NODE_INDEX_INVALID),
2749 "200.200.200.201/32 removed");
2750 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2751 FIB_NODE_INDEX_INVALID),
2752 "200.200.200.200/32 removed");
2753 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3) ==
2754 FIB_NODE_INDEX_INVALID),
2755 "10.10.10.3/32 removed");
2758 * -3 entries (2*BGP and RR). -2 shared path-list (recursive via 10.10.10.3 &
2759 * 10.10.10.1) and one unshared non-recursive via 10.10.10.3
2761 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2762 fib_path_list_db_size());
2763 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2764 fib_path_list_pool_size());
2765 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2766 fib_entry_pool_size());
2771 * Add 5.5.5.5/32 -> 5.5.5.6/32 -> 5.5.5.7/32 -> 5.5.5.5/32
2773 fib_prefix_t pfx_5_5_5_5_s_32 = {
2775 .fp_proto = FIB_PROTOCOL_IP4,
2777 .ip4.as_u32 = clib_host_to_net_u32(0x05050505),
2780 fib_prefix_t pfx_5_5_5_6_s_32 = {
2782 .fp_proto = FIB_PROTOCOL_IP4,
2784 .ip4.as_u32 = clib_host_to_net_u32(0x05050506),
2787 fib_prefix_t pfx_5_5_5_7_s_32 = {
2789 .fp_proto = FIB_PROTOCOL_IP4,
2791 .ip4.as_u32 = clib_host_to_net_u32(0x05050507),
2795 fib_table_entry_path_add(fib_index,
2798 FIB_ENTRY_FLAG_NONE,
2800 &pfx_5_5_5_6_s_32.fp_addr,
2801 ~0, // no index provided.
2805 FIB_ROUTE_PATH_FLAG_NONE);
2806 fib_table_entry_path_add(fib_index,
2809 FIB_ENTRY_FLAG_NONE,
2811 &pfx_5_5_5_7_s_32.fp_addr,
2812 ~0, // no index provided.
2816 FIB_ROUTE_PATH_FLAG_NONE);
2817 fib_table_entry_path_add(fib_index,
2820 FIB_ENTRY_FLAG_NONE,
2822 &pfx_5_5_5_5_s_32.fp_addr,
2823 ~0, // no index provided.
2827 FIB_ROUTE_PATH_FLAG_NONE);
2829 * +3 entries, +3 shared path-list
2831 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2832 fib_path_list_db_size());
2833 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2834 fib_path_list_pool_size());
2835 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2836 fib_entry_pool_size());
2839 * All the entries have only looped paths, so they are all drop
2841 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2842 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2843 "LB for 5.5.5.7/32 is via adj for DROP");
2844 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2845 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2846 "LB for 5.5.5.5/32 is via adj for DROP");
2847 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2848 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2849 "LB for 5.5.5.6/32 is via adj for DROP");
2852 * provide 5.5.5.6/32 with alternate path.
2853 * this will allow only 5.5.5.6/32 to forward with this path, the others
2854 * are still drop since the loop is still present.
2856 fib_table_entry_path_add(fib_index,
2859 FIB_ENTRY_FLAG_NONE,
2862 tm->hw[0]->sw_if_index,
2866 FIB_ROUTE_PATH_FLAG_NONE);
2868 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2869 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2871 lb = load_balance_get(dpo1->dpoi_index);
2872 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.6 LB has %d bucket", lb->lb_n_buckets);
2874 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2875 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2876 FIB_TEST((ai_01 == dpo2->dpoi_index),
2877 "5.5.5.6 bucket 0 resolves via 10.10.10.2");
2879 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2880 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2881 "LB for 5.5.5.7/32 is via adj for DROP");
2882 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2883 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2884 "LB for 5.5.5.5/32 is via adj for DROP");
2887 * remove the alternate path for 5.5.5.6/32
2890 fib_table_entry_path_remove(fib_index,
2895 tm->hw[0]->sw_if_index,
2898 FIB_ROUTE_PATH_FLAG_NONE);
2900 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2901 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2902 "LB for 5.5.5.7/32 is via adj for DROP");
2903 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2904 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2905 "LB for 5.5.5.5/32 is via adj for DROP");
2906 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2907 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2908 "LB for 5.5.5.6/32 is via adj for DROP");
2911 * break the loop by giving 5.5.5.5/32 a new set of paths
2912 * expect all to forward via this new path.
2914 fib_table_entry_update_one_path(fib_index,
2917 FIB_ENTRY_FLAG_NONE,
2920 tm->hw[0]->sw_if_index,
2921 ~0, // invalid fib index
2924 FIB_ROUTE_PATH_FLAG_NONE);
2926 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2927 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2928 lb = load_balance_get(dpo1->dpoi_index);
2929 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.5 LB has %d bucket", lb->lb_n_buckets);
2931 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2932 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2933 FIB_TEST((ai_01 == dpo2->dpoi_index),
2934 "5.5.5.5 bucket 0 resolves via 10.10.10.2");
2936 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_7_s_32);
2937 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2939 lb = load_balance_get(dpo2->dpoi_index);
2940 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2941 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo2->dpoi_index, 0)),
2942 "5.5.5.5.7 via 5.5.5.5");
2944 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32);
2945 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2947 lb = load_balance_get(dpo1->dpoi_index);
2948 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2949 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2950 "5.5.5.5.6 via 5.5.5.7");
2953 * revert back to the loop. so we can remove the prefixes with
2956 fib_table_entry_update_one_path(fib_index,
2959 FIB_ENTRY_FLAG_NONE,
2961 &pfx_5_5_5_6_s_32.fp_addr,
2962 ~0, // no index provided.
2966 FIB_ROUTE_PATH_FLAG_NONE);
2968 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2969 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2970 "LB for 5.5.5.7/32 is via adj for DROP");
2971 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2972 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2973 "LB for 5.5.5.5/32 is via adj for DROP");
2974 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2975 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2976 "LB for 5.5.5.6/32 is via adj for DROP");
2979 * remove all the 5.5.5.x/32 prefixes
2981 fib_table_entry_path_remove(fib_index,
2985 &pfx_5_5_5_6_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_7_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,
3003 &pfx_5_5_5_5_s_32.fp_addr,
3004 ~0, // no index provided.
3005 fib_index, // same as route's FIB
3007 FIB_ROUTE_PATH_FLAG_NONE);
3008 fib_table_entry_path_remove(fib_index,
3013 ~0, // no index provided.
3014 fib_index, // same as route's FIB
3016 FIB_ROUTE_PATH_FLAG_NONE);
3019 * -3 entries, -3 shared path-list
3021 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3022 fib_path_list_db_size());
3023 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3024 fib_path_list_pool_size());
3025 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3026 fib_entry_pool_size());
3029 * Single level loop 5.5.5.5/32 via 5.5.5.5/32
3031 fib_table_entry_path_add(fib_index,
3034 FIB_ENTRY_FLAG_NONE,
3036 &pfx_5_5_5_6_s_32.fp_addr,
3037 ~0, // no index provided.
3041 FIB_ROUTE_PATH_FLAG_NONE);
3042 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
3043 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
3044 "1-level 5.5.5.6/32 loop is via adj for DROP");
3046 fib_table_entry_path_remove(fib_index,
3050 &pfx_5_5_5_6_s_32.fp_addr,
3051 ~0, // no index provided.
3052 fib_index, // same as route's FIB
3054 FIB_ROUTE_PATH_FLAG_NONE);
3055 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3056 fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32),
3057 "1-level 5.5.5.6/32 loop is removed");
3060 * A recursive route whose next-hop is covered by the prefix.
3061 * This would mean the via-fib, which inherits forwarding from its
3062 * cover, thus picks up forwarding from the prfix, which is via the
3063 * via-fib, and we have a loop.
3065 fib_prefix_t pfx_23_23_23_0_s_24 = {
3067 .fp_proto = FIB_PROTOCOL_IP4,
3069 .ip4.as_u32 = clib_host_to_net_u32(0x17171700),
3072 fib_prefix_t pfx_23_23_23_23_s_32 = {
3074 .fp_proto = FIB_PROTOCOL_IP4,
3076 .ip4.as_u32 = clib_host_to_net_u32(0x17171717),
3079 fei = fib_table_entry_path_add(fib_index,
3080 &pfx_23_23_23_0_s_24,
3082 FIB_ENTRY_FLAG_NONE,
3084 &pfx_23_23_23_23_s_32.fp_addr,
3089 FIB_ROUTE_PATH_FLAG_NONE);
3090 dpo = fib_entry_contribute_ip_forwarding(fei);
3091 FIB_TEST(load_balance_is_drop(dpo),
3092 "23.23.23.0/24 via covered is DROP");
3093 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3096 * add-remove test. no change.
3098 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3099 fib_path_list_db_size());
3100 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3101 fib_path_list_pool_size());
3102 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3103 fib_entry_pool_size());
3106 * Make the default route recursive via a unknown next-hop. Thus the
3107 * next hop's cover would be the default route
3109 fei = fib_table_entry_path_add(fib_index,
3112 FIB_ENTRY_FLAG_NONE,
3114 &pfx_23_23_23_23_s_32.fp_addr,
3119 FIB_ROUTE_PATH_FLAG_NONE);
3120 dpo = fib_entry_contribute_ip_forwarding(fei);
3121 FIB_TEST(load_balance_is_drop(dpo),
3122 "0.0.0.0.0/0 via is DROP");
3123 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3124 "no resolving interface for looped 0.0.0.0/0");
3126 fei = fib_table_lookup_exact_match(fib_index, &pfx_23_23_23_23_s_32);
3127 dpo = fib_entry_contribute_ip_forwarding(fei);
3128 FIB_TEST(load_balance_is_drop(dpo),
3129 "23.23.23.23/32 via is DROP");
3130 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3131 "no resolving interface for looped 23.23.23.23/32");
3133 fib_table_entry_delete(fib_index, &pfx_0_0_0_0_s_0, FIB_SOURCE_API);
3136 * A recursive route with recursion constraints.
3137 * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained
3139 fib_table_entry_path_add(fib_index,
3142 FIB_ENTRY_FLAG_NONE,
3149 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3151 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3152 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3154 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3155 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3157 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3158 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3161 * save the load-balance. we expect it to be inplace modified
3163 lb = load_balance_get(dpo1->dpoi_index);
3166 * add a covering prefix for the via fib that would otherwise serve
3167 * as the resolving route when the host is removed
3169 fib_table_entry_path_add(fib_index,
3172 FIB_ENTRY_FLAG_NONE,
3175 tm->hw[0]->sw_if_index,
3176 ~0, // invalid fib index
3179 FIB_ROUTE_PATH_FLAG_NONE);
3180 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28);
3181 ai = fib_entry_get_adj(fei);
3182 FIB_TEST((ai == ai_01),
3183 "adj for 1.1.1.0/28 is via adj for 1.1.1.1");
3186 * remove the host via FIB - expect the BGP prefix to be drop
3188 fib_table_entry_path_remove(fib_index,
3193 tm->hw[0]->sw_if_index,
3194 ~0, // invalid fib index
3196 FIB_ROUTE_PATH_FLAG_NONE);
3198 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3199 "adj for 200.200.200.200/32 is recursive via adj for DROP");
3202 * add the via-entry host reoute back. expect to resolve again
3204 fib_table_entry_path_add(fib_index,
3207 FIB_ENTRY_FLAG_NONE,
3210 tm->hw[0]->sw_if_index,
3211 ~0, // invalid fib index
3214 FIB_ROUTE_PATH_FLAG_NONE);
3215 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3216 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3219 * add another path for the recursive. it will then have 2.
3221 fib_prefix_t pfx_1_1_1_3_s_32 = {
3223 .fp_proto = FIB_PROTOCOL_IP4,
3225 .ip4.as_u32 = clib_host_to_net_u32(0x01010103),
3228 fib_table_entry_path_add(fib_index,
3231 FIB_ENTRY_FLAG_NONE,
3234 tm->hw[0]->sw_if_index,
3235 ~0, // invalid fib index
3238 FIB_ROUTE_PATH_FLAG_NONE);
3240 fib_table_entry_path_add(fib_index,
3243 FIB_ENTRY_FLAG_NONE,
3245 &pfx_1_1_1_3_s_32.fp_addr,
3250 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3253 * add a bunch load more entries using this path combo so that we get
3254 * an LB-map created.
3257 fib_prefix_t bgp_78s[N_P];
3258 for (ii = 0; ii < N_P; ii++)
3260 bgp_78s[ii].fp_len = 32;
3261 bgp_78s[ii].fp_proto = FIB_PROTOCOL_IP4;
3262 bgp_78s[ii].fp_addr.ip4.as_u32 = clib_host_to_net_u32(0x4e000000+ii);
3265 fib_table_entry_path_add(fib_index,
3268 FIB_ENTRY_FLAG_NONE,
3270 &pfx_1_1_1_3_s_32.fp_addr,
3275 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3276 fib_table_entry_path_add(fib_index,
3279 FIB_ENTRY_FLAG_NONE,
3286 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3289 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3290 dpo = fib_entry_contribute_ip_forwarding(fei);
3292 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3293 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3294 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)),
3295 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3296 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32);
3297 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3298 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)),
3299 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3");
3302 * expect the lb-map used by the recursive's load-balance is using both buckets
3304 load_balance_map_t *lbm;
3307 lb = load_balance_get(dpo->dpoi_index);
3309 load_balance_map_lock(lbmi);
3310 lbm = load_balance_map_get(lbmi);
3312 FIB_TEST(lbm->lbm_buckets[0] == 0,
3313 "LB maps's bucket 0 is %d",
3314 lbm->lbm_buckets[0]);
3315 FIB_TEST(lbm->lbm_buckets[1] == 1,
3316 "LB maps's bucket 1 is %d",
3317 lbm->lbm_buckets[1]);
3320 * withdraw one of the /32 via-entrys.
3321 * that ECMP path will be unresolved and forwarding should continue on the
3322 * other available path. this is an iBGP PIC edge failover.
3323 * Test the forwarding changes without re-fetching the adj from the
3324 * recursive entry. this ensures its the same one that is updated; i.e. an
3327 fib_table_entry_path_remove(fib_index,
3332 tm->hw[0]->sw_if_index,
3333 ~0, // invalid fib index
3335 FIB_ROUTE_PATH_FLAG_NONE);
3337 /* suspend so the update walk kicks int */
3338 vlib_process_suspend(vlib_get_main(), 1e-5);
3340 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3341 FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)),
3342 "post PIC 200.200.200.200/32 was inplace modified");
3344 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)),
3345 "post PIC adj for 200.200.200.200/32 is recursive"
3346 " via adj for 1.1.1.3");
3349 * the LB maps that was locked above should have been modified to remove
3350 * the path that was down, and thus its bucket points to a path that is
3353 FIB_TEST(lbm->lbm_buckets[0] == 1,
3354 "LB maps's bucket 0 is %d",
3355 lbm->lbm_buckets[0]);
3356 FIB_TEST(lbm->lbm_buckets[1] == 1,
3357 "LB maps's bucket 1 is %d",
3358 lbm->lbm_buckets[1]);
3360 load_balance_map_unlock(lbmi);
3363 * add it back. again
3365 fib_table_entry_path_add(fib_index,
3368 FIB_ENTRY_FLAG_NONE,
3371 tm->hw[0]->sw_if_index,
3372 ~0, // invalid fib index
3375 FIB_ROUTE_PATH_FLAG_NONE);
3377 /* suspend so the update walk kicks in */
3378 vlib_process_suspend(vlib_get_main(), 1e-5);
3380 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)),
3381 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3382 "via adj for 1.1.1.1");
3383 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)),
3384 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3385 "via adj for 1.1.1.3");
3387 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3388 dpo = fib_entry_contribute_ip_forwarding(fei);
3389 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3390 "post PIC 200.200.200.200/32 was inplace modified");
3393 * add a 3rd path. this makes the LB 16 buckets.
3395 fib_table_entry_path_add(fib_index,
3398 FIB_ENTRY_FLAG_NONE,
3400 &pfx_1_1_1_2_s_32.fp_addr,
3405 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3406 for (ii = 0; ii < N_P; ii++)
3408 fib_table_entry_path_add(fib_index,
3411 FIB_ENTRY_FLAG_NONE,
3413 &pfx_1_1_1_2_s_32.fp_addr,
3418 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3421 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3422 dpo = fib_entry_contribute_ip_forwarding(fei);
3423 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3424 "200.200.200.200/32 was inplace modified for 3rd path");
3425 FIB_TEST(16 == lb->lb_n_buckets,
3426 "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets");
3429 load_balance_map_lock(lbmi);
3430 lbm = load_balance_map_get(lbmi);
3432 for (ii = 0; ii < 16; ii++)
3434 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3435 "LB Map for 200.200.200.200/32 at %d is %d",
3436 ii, lbm->lbm_buckets[ii]);
3440 * trigger PIC by removing the first via-entry
3441 * the first 6 buckets of the map should map to the next 6
3443 fib_table_entry_path_remove(fib_index,
3448 tm->hw[0]->sw_if_index,
3451 FIB_ROUTE_PATH_FLAG_NONE);
3452 /* suspend so the update walk kicks int */
3453 vlib_process_suspend(vlib_get_main(), 1e-5);
3455 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3456 dpo = fib_entry_contribute_ip_forwarding(fei);
3457 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3458 "200.200.200.200/32 was inplace modified for 3rd path");
3459 FIB_TEST(2 == lb->lb_n_buckets,
3460 "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets");
3462 for (ii = 0; ii < 6; ii++)
3464 FIB_TEST(lbm->lbm_buckets[ii] == ii+6,
3465 "LB Map for 200.200.200.200/32 at %d is %d",
3466 ii, lbm->lbm_buckets[ii]);
3468 for (ii = 6; ii < 16; ii++)
3470 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3471 "LB Map for 200.200.200.200/32 at %d is %d",
3472 ii, lbm->lbm_buckets[ii]);
3474 load_balance_map_unlock(lbmi);
3479 fib_table_entry_path_add(fib_index,
3482 FIB_ENTRY_FLAG_NONE,
3485 tm->hw[0]->sw_if_index,
3489 FIB_ROUTE_PATH_FLAG_NONE);
3491 for (ii = 0; ii < N_P; ii++)
3493 fib_table_entry_delete(fib_index,
3496 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3497 fib_table_lookup_exact_match(fib_index, &bgp_78s[ii])),
3499 format_fib_prefix, &bgp_78s[ii]);
3501 fib_table_entry_path_remove(fib_index,
3505 &pfx_1_1_1_2_s_32.fp_addr,
3509 MPLS_LABEL_INVALID);
3510 fib_table_entry_path_remove(fib_index,
3518 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3519 fib_table_entry_path_remove(fib_index,
3523 &pfx_1_1_1_3_s_32.fp_addr,
3527 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3528 fib_table_entry_delete(fib_index,
3531 fib_table_entry_delete(fib_index,
3534 /* suspend so the update walk kicks int */
3535 vlib_process_suspend(vlib_get_main(), 1e-5);
3536 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3537 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)),
3538 "1.1.1.1/28 removed");
3539 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3540 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)),
3541 "1.1.1.3/32 removed");
3542 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3543 fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)),
3544 "200.200.200.200/32 removed");
3547 * add-remove test. no change.
3549 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3550 fib_path_list_db_size());
3551 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3552 fib_path_list_pool_size());
3553 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3554 fib_entry_pool_size());
3557 * A route whose paths are built up iteratively and then removed
3560 fib_prefix_t pfx_4_4_4_4_s_32 = {
3562 .fp_proto = FIB_PROTOCOL_IP4,
3565 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
3569 fib_table_entry_path_add(fib_index,
3572 FIB_ENTRY_FLAG_NONE,
3575 tm->hw[0]->sw_if_index,
3579 FIB_ROUTE_PATH_FLAG_NONE);
3580 fib_table_entry_path_add(fib_index,
3583 FIB_ENTRY_FLAG_NONE,
3586 tm->hw[0]->sw_if_index,
3590 FIB_ROUTE_PATH_FLAG_NONE);
3591 fib_table_entry_path_add(fib_index,
3594 FIB_ENTRY_FLAG_NONE,
3597 tm->hw[0]->sw_if_index,
3601 FIB_ROUTE_PATH_FLAG_NONE);
3602 FIB_TEST(FIB_NODE_INDEX_INVALID !=
3603 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3604 "4.4.4.4/32 present");
3606 fib_table_entry_delete(fib_index,
3609 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3610 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3611 "4.4.4.4/32 removed");
3614 * add-remove test. no change.
3616 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3617 fib_path_list_db_size());
3618 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3619 fib_path_list_pool_size());
3620 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3621 fib_entry_pool_size());
3624 * A route with multiple paths at once
3626 fib_route_path_t *r_paths = NULL;
3628 for (ii = 0; ii < 4; ii++)
3630 fib_route_path_t r_path = {
3631 .frp_proto = DPO_PROTO_IP4,
3633 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
3635 .frp_sw_if_index = tm->hw[0]->sw_if_index,
3637 .frp_fib_index = ~0,
3639 vec_add1(r_paths, r_path);
3642 fib_table_entry_update(fib_index,
3645 FIB_ENTRY_FLAG_NONE,
3648 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3649 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3650 dpo = fib_entry_contribute_ip_forwarding(fei);
3652 lb = load_balance_get(dpo->dpoi_index);
3653 FIB_TEST((lb->lb_n_buckets == 4), "4.4.4.4/32 lb over %d paths", lb->lb_n_buckets);
3655 fib_table_entry_delete(fib_index,
3658 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3659 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3660 "4.4.4.4/32 removed");
3664 * add-remove test. no change.
3666 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3667 fib_path_list_db_size());
3668 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3669 fib_path_list_pool_size());
3670 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3671 fib_entry_pool_size());
3674 * A route deag route
3676 fib_table_entry_path_add(fib_index,
3679 FIB_ENTRY_FLAG_NONE,
3686 FIB_ROUTE_PATH_FLAG_NONE);
3688 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3689 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3691 dpo = fib_entry_contribute_ip_forwarding(fei);
3692 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3693 lookup_dpo_t *lkd = lookup_dpo_get(dpo->dpoi_index);
3695 FIB_TEST((fib_index == lkd->lkd_fib_index),
3696 "4.4.4.4/32 is deag in %d %U",
3698 format_dpo_id, dpo, 0);
3699 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
3700 "4.4.4.4/32 is source deag in %d %U",
3702 format_dpo_id, dpo, 0);
3704 fib_table_entry_delete(fib_index,
3707 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3708 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3709 "4.4.4.4/32 removed");
3713 * A route deag route in a source lookup table
3715 fib_table_entry_path_add(fib_index,
3718 FIB_ENTRY_FLAG_NONE,
3725 FIB_ROUTE_PATH_SOURCE_LOOKUP);
3727 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3728 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3730 dpo = fib_entry_contribute_ip_forwarding(fei);
3731 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3732 lkd = lookup_dpo_get(dpo->dpoi_index);
3734 FIB_TEST((fib_index == lkd->lkd_fib_index),
3735 "4.4.4.4/32 is deag in %d %U",
3737 format_dpo_id, dpo, 0);
3738 FIB_TEST((LOOKUP_INPUT_SRC_ADDR == lkd->lkd_input),
3739 "4.4.4.4/32 is source deag in %d %U",
3741 format_dpo_id, dpo, 0);
3743 fib_table_entry_delete(fib_index,
3746 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3747 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3748 "4.4.4.4/32 removed");
3752 * add-remove test. no change.
3754 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3755 fib_path_list_db_size());
3756 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3757 fib_path_list_pool_size());
3758 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3759 fib_entry_pool_size());
3763 * add a recursive with duplicate paths. Expect the duplicate to be ignored.
3765 fib_prefix_t pfx_34_1_1_1_s_32 = {
3767 .fp_proto = FIB_PROTOCOL_IP4,
3769 .ip4.as_u32 = clib_host_to_net_u32(0x22010101),
3772 fib_prefix_t pfx_34_34_1_1_s_32 = {
3774 .fp_proto = FIB_PROTOCOL_IP4,
3776 .ip4.as_u32 = clib_host_to_net_u32(0x22220101),
3779 fei = fib_table_entry_path_add(fib_index,
3780 &pfx_34_34_1_1_s_32,
3782 FIB_ENTRY_FLAG_NONE,
3785 tm->hw[0]->sw_if_index,
3789 FIB_ROUTE_PATH_FLAG_NONE);
3790 fei = fib_table_entry_path_add(fib_index,
3793 FIB_ENTRY_FLAG_NONE,
3795 &pfx_34_34_1_1_s_32.fp_addr,
3800 FIB_ROUTE_PATH_FLAG_NONE);
3801 fei = fib_table_entry_path_add(fib_index,
3804 FIB_ENTRY_FLAG_NONE,
3806 &pfx_34_34_1_1_s_32.fp_addr,
3811 FIB_ROUTE_PATH_FLAG_NONE);
3812 FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0);
3813 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3814 fib_table_entry_delete(fib_index,
3815 &pfx_34_34_1_1_s_32,
3820 * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32
3821 * all of which are via 10.10.10.1, Itf1
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);
3841 fib_table_entry_path_remove(fib_index,
3846 tm->hw[0]->sw_if_index,
3849 FIB_ROUTE_PATH_FLAG_NONE);
3851 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3852 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32),
3853 "1.1.1.1/32 removed");
3854 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3855 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32),
3856 "1.1.1.2/32 removed");
3857 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3858 fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24),
3859 "1.1.2.0/24 removed");
3862 * -3 entries and -1 shared path-list
3864 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3865 fib_path_list_db_size());
3866 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3867 fib_path_list_pool_size());
3868 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3869 fib_entry_pool_size());
3872 * An attached-host route. Expect to link to the incomplete adj
3874 fib_prefix_t pfx_4_1_1_1_s_32 = {
3876 .fp_proto = FIB_PROTOCOL_IP4,
3879 .ip4.as_u32 = clib_host_to_net_u32(0x04010101),
3882 fib_table_entry_path_add(fib_index,
3885 FIB_ENTRY_FLAG_NONE,
3888 tm->hw[0]->sw_if_index,
3892 FIB_ROUTE_PATH_FLAG_NONE);
3894 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32);
3895 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present");
3896 ai = fib_entry_get_adj(fei);
3898 ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
3900 &pfx_4_1_1_1_s_32.fp_addr,
3901 tm->hw[0]->sw_if_index);
3902 FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ");
3906 * +1 entry and +1 shared path-list
3908 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3909 fib_path_list_db_size());
3910 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3911 fib_path_list_pool_size());
3912 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
3913 fib_entry_pool_size());
3915 fib_table_entry_delete(fib_index,
3919 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3920 fib_path_list_db_size());
3921 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3922 fib_path_list_pool_size());
3923 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3924 fib_entry_pool_size());
3927 * add a v6 prefix via v4 next-hops
3929 fib_prefix_t pfx_2001_s_64 = {
3931 .fp_proto = FIB_PROTOCOL_IP6,
3933 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
3936 fei = fib_table_entry_path_add(0, //default v6 table
3939 FIB_ENTRY_FLAG_NONE,
3942 tm->hw[0]->sw_if_index,
3946 FIB_ROUTE_PATH_FLAG_NONE);
3948 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
3949 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present");
3950 ai = fib_entry_get_adj(fei);
3952 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
3953 "2001::/64 via ARP-adj");
3954 FIB_TEST((adj->ia_link == VNET_LINK_IP6),
3955 "2001::/64 is link type v6");
3956 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4),
3957 "2001::/64 ADJ-adj is NH proto v4");
3958 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
3961 * add a uRPF exempt prefix:
3963 * - it's forwarding is drop
3964 * - it's uRPF list is not empty
3965 * - the uRPF list for the default route (it's cover) is empty
3967 fei = fib_table_entry_special_add(fib_index,
3969 FIB_SOURCE_URPF_EXEMPT,
3970 FIB_ENTRY_FLAG_DROP);
3971 dpo = fib_entry_contribute_ip_forwarding(fei);
3972 FIB_TEST(load_balance_is_drop(dpo),
3973 "uRPF exempt 4.1.1.1/32 DROP");
3974 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0),
3975 "uRPF list for exempt prefix has itf index 0");
3976 fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0);
3977 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
3978 "uRPF list for 0.0.0.0/0 empty");
3980 fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
3983 * An adj-fib that fails the refinement criteria - no connected cover
3985 fib_prefix_t pfx_12_10_10_2_s_32 = {
3987 .fp_proto = FIB_PROTOCOL_IP4,
3990 .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02),
3994 fib_table_entry_path_add(fib_index,
3995 &pfx_12_10_10_2_s_32,
3997 FIB_ENTRY_FLAG_ATTACHED,
3999 &pfx_12_10_10_2_s_32.fp_addr,
4000 tm->hw[0]->sw_if_index,
4001 ~0, // invalid fib index
4004 FIB_ROUTE_PATH_FLAG_NONE);
4006 fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32);
4007 dpo = fib_entry_contribute_ip_forwarding(fei);
4008 FIB_TEST(dpo_is_drop(dpo),
4009 "no connected cover adj-fib fails refinement: %U",
4010 format_dpo_id, dpo, 0);
4012 fib_table_entry_delete(fib_index,
4013 &pfx_12_10_10_2_s_32,
4017 * An adj-fib that fails the refinement criteria - cover is connected
4018 * but on a different interface
4020 fib_prefix_t pfx_10_10_10_127_s_32 = {
4022 .fp_proto = FIB_PROTOCOL_IP4,
4025 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f),
4029 fib_table_entry_path_add(fib_index,
4030 &pfx_10_10_10_127_s_32,
4032 FIB_ENTRY_FLAG_ATTACHED,
4034 &pfx_10_10_10_127_s_32.fp_addr,
4035 tm->hw[1]->sw_if_index,
4036 ~0, // invalid fib index
4039 FIB_ROUTE_PATH_FLAG_NONE);
4041 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32);
4042 dpo = fib_entry_contribute_ip_forwarding(fei);
4043 FIB_TEST(dpo_is_drop(dpo),
4044 "wrong interface adj-fib fails refinement");
4046 fib_table_entry_delete(fib_index,
4047 &pfx_10_10_10_127_s_32,
4051 * add a second path to an adj-fib
4052 * this is a sumiluation of another ARP entry created
4053 * on an interface on which the connected prefix does not exist.
4054 * The second path fails refinement. Expect to forward through the
4057 fib_prefix_t pfx_10_10_10_3_s_32 = {
4059 .fp_proto = FIB_PROTOCOL_IP4,
4062 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
4066 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
4069 tm->hw[0]->sw_if_index);
4071 fib_test_lb_bucket_t ip_o_10_10_10_3 = {
4077 fei = fib_table_entry_path_add(fib_index,
4078 &pfx_10_10_10_3_s_32,
4080 FIB_ENTRY_FLAG_NONE,
4083 tm->hw[0]->sw_if_index,
4087 FIB_ROUTE_PATH_FLAG_NONE);
4088 fei = fib_table_entry_path_add(fib_index,
4089 &pfx_10_10_10_3_s_32,
4091 FIB_ENTRY_FLAG_NONE,
4094 tm->hw[1]->sw_if_index,
4098 FIB_ROUTE_PATH_FLAG_NONE);
4099 FIB_TEST(!fib_test_validate_entry(fei,
4100 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4103 "10.10.10.3 via 10.10.10.3/Eth0 only");
4106 * remove the path that refines the cover, should go unresolved
4108 fib_table_entry_path_remove(fib_index,
4109 &pfx_10_10_10_3_s_32,
4113 tm->hw[0]->sw_if_index,
4116 FIB_ROUTE_PATH_FLAG_NONE);
4117 dpo = fib_entry_contribute_ip_forwarding(fei);
4118 FIB_TEST(dpo_is_drop(dpo),
4119 "wrong interface adj-fib fails refinement");
4122 * add back the path that refines the cover
4124 fei = fib_table_entry_path_add(fib_index,
4125 &pfx_10_10_10_3_s_32,
4127 FIB_ENTRY_FLAG_NONE,
4130 tm->hw[0]->sw_if_index,
4134 FIB_ROUTE_PATH_FLAG_NONE);
4135 FIB_TEST(!fib_test_validate_entry(fei,
4136 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4139 "10.10.10.3 via 10.10.10.3/Eth0 only");
4142 * remove the path that does not refine the cover
4144 fib_table_entry_path_remove(fib_index,
4145 &pfx_10_10_10_3_s_32,
4149 tm->hw[1]->sw_if_index,
4152 FIB_ROUTE_PATH_FLAG_NONE);
4153 FIB_TEST(!fib_test_validate_entry(fei,
4154 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4157 "10.10.10.3 via 10.10.10.3/Eth0 only");
4160 * remove the path that does refine, it's the last path, so
4161 * the entry should be gone
4163 fib_table_entry_path_remove(fib_index,
4164 &pfx_10_10_10_3_s_32,
4168 tm->hw[0]->sw_if_index,
4171 FIB_ROUTE_PATH_FLAG_NONE);
4172 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
4173 FIB_TEST((fei == FIB_NODE_INDEX_INVALID), "10.10.10.3 gone");
4178 * change the table's flow-hash config - expect the update to propagete to
4179 * the entries' load-balance objects
4181 flow_hash_config_t old_hash_config, new_hash_config;
4183 old_hash_config = fib_table_get_flow_hash_config(fib_index,
4185 new_hash_config = (IP_FLOW_HASH_SRC_ADDR |
4186 IP_FLOW_HASH_DST_ADDR);
4188 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
4189 dpo = fib_entry_contribute_ip_forwarding(fei);
4190 lb = load_balance_get(dpo->dpoi_index);
4191 FIB_TEST((lb->lb_hash_config == old_hash_config),
4192 "Table and LB hash config match: %U",
4193 format_ip_flow_hash_config, lb->lb_hash_config);
4195 fib_table_set_flow_hash_config(fib_index, FIB_PROTOCOL_IP4, new_hash_config);
4197 FIB_TEST((lb->lb_hash_config == new_hash_config),
4198 "Table and LB newhash config match: %U",
4199 format_ip_flow_hash_config, lb->lb_hash_config);
4202 * A route via DVR DPO
4204 fei = fib_table_entry_path_add(fib_index,
4205 &pfx_10_10_10_3_s_32,
4207 FIB_ENTRY_FLAG_NONE,
4210 tm->hw[0]->sw_if_index,
4214 FIB_ROUTE_PATH_DVR);
4215 dpo_id_t dvr_dpo = DPO_INVALID;
4216 dvr_dpo_add_or_lock(tm->hw[0]->sw_if_index, DPO_PROTO_IP4, &dvr_dpo);
4217 fib_test_lb_bucket_t ip_o_l2 = {
4220 .adj = dvr_dpo.dpoi_index,
4224 FIB_TEST(!fib_test_validate_entry(fei,
4225 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4228 "10.10.10.3 via L2 on Eth0");
4229 fib_table_entry_path_remove(fib_index,
4230 &pfx_10_10_10_3_s_32,
4234 tm->hw[0]->sw_if_index,
4237 FIB_ROUTE_PATH_DVR);
4238 dpo_reset(&dvr_dpo);
4241 * add the default route via a next-hop that will form a loop
4243 fib_prefix_t pfx_conn = {
4245 .fp_proto = FIB_PROTOCOL_IP4,
4248 .ip4.as_u32 = clib_host_to_net_u32(0x1e1e1e1e),
4252 dfrt = fib_table_entry_path_add(fib_index,
4255 FIB_ENTRY_FLAG_NONE,
4262 FIB_ROUTE_PATH_FLAG_NONE);
4264 * the default route is a drop, since it's looped
4266 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4267 "Default route is DROP");
4270 * add a connected cover for the next-hop, this breaks the recursion loop
4271 * for the default route
4273 fib_table_entry_path_add(fib_index,
4276 (FIB_ENTRY_FLAG_CONNECTED |
4277 FIB_ENTRY_FLAG_ATTACHED),
4280 tm->hw[0]->sw_if_index,
4284 FIB_ROUTE_PATH_FLAG_NONE);
4285 pfx_conn.fp_len = 32;
4286 fei = fib_table_lookup_exact_match(fib_index, &pfx_conn);
4288 u32 ai_30 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
4291 tm->hw[0]->sw_if_index);
4293 fib_test_lb_bucket_t ip_o_30_30_30_30 = {
4299 FIB_TEST(!fib_test_validate_entry(fei,
4300 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4303 "30.30.30.30 via adj");
4304 FIB_TEST_REC_FORW(&pfx_0_0_0_0_s_0, &pfx_conn, 0);
4306 pfx_conn.fp_len = 24;
4307 fib_table_entry_delete(fib_index,
4310 fib_table_entry_delete(fib_index,
4319 fib_table_entry_delete(fib_index,
4320 &pfx_10_10_10_1_s_32,
4322 fib_table_entry_delete(fib_index,
4323 &pfx_10_10_10_2_s_32,
4325 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4326 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32),
4327 "10.10.10.1/32 adj-fib removed");
4328 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4329 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32),
4330 "10.10.10.2/32 adj-fib removed");
4333 * -2 entries and -2 non-shared path-list
4335 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4336 fib_path_list_db_size());
4337 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
4338 fib_path_list_pool_size());
4339 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
4340 fib_entry_pool_size());
4343 * unlock the adjacencies for which this test provided a rewrite.
4344 * These are the last locks on these adjs. they should thus go away.
4348 adj_unlock(ai_12_12_12_12);
4350 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4355 * remove the interface prefixes
4357 local_pfx.fp_len = 32;
4358 fib_table_entry_special_remove(fib_index, &local_pfx,
4359 FIB_SOURCE_INTERFACE);
4360 fei = fib_table_lookup(fib_index, &local_pfx);
4362 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4363 fib_table_lookup_exact_match(fib_index, &local_pfx),
4364 "10.10.10.10/32 adj-fib removed");
4366 local_pfx.fp_len = 24;
4367 fib_table_entry_delete(fib_index, &local_pfx,
4368 FIB_SOURCE_INTERFACE);
4370 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4371 fib_table_lookup_exact_match(fib_index, &local_pfx),
4372 "10.10.10.10/24 adj-fib removed");
4375 * -2 entries and -2 non-shared path-list
4377 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4378 fib_path_list_db_size());
4379 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
4380 fib_path_list_pool_size());
4381 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
4382 fib_entry_pool_size());
4385 * Last but not least, remove the VRF
4387 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4390 "NO API Source'd prefixes");
4391 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4394 "NO RR Source'd prefixes");
4395 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4397 FIB_SOURCE_INTERFACE)),
4398 "NO INterface Source'd prefixes");
4400 fib_table_unlock(fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
4402 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4403 fib_path_list_db_size());
4404 FIB_TEST((PNBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
4405 fib_path_list_pool_size());
4406 FIB_TEST((ENBR-5 == fib_entry_pool_size()), "entry pool size is %d",
4407 fib_entry_pool_size());
4408 FIB_TEST((ENBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
4409 pool_elts(fib_urpf_list_pool));
4410 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
4411 pool_elts(load_balance_map_pool));
4412 FIB_TEST((lb_count == pool_elts(load_balance_pool)), "LB pool size is %d",
4413 pool_elts(load_balance_pool));
4414 FIB_TEST((0 == pool_elts(dvr_dpo_pool)), "L2 DPO pool size is %d",
4415 pool_elts(dvr_dpo_pool));
4424 * In the default table check for the presence and correct forwarding
4425 * of the special entries
4427 fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02;
4428 const dpo_id_t *dpo, *dpo_drop;
4429 const ip_adjacency_t *adj;
4430 const receive_dpo_t *rd;
4436 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4439 /* via 2001:0:0:1::2 */
4440 ip46_address_t nh_2001_2 = {
4443 [0] = clib_host_to_net_u64(0x2001000000000001),
4444 [1] = clib_host_to_net_u64(0x0000000000000002),
4451 dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
4453 /* Find or create FIB table 11 */
4454 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11,
4457 for (ii = 0; ii < 4; ii++)
4459 ip6_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
4462 fib_prefix_t pfx_0_0 = {
4464 .fp_proto = FIB_PROTOCOL_IP6,
4472 dfrt = fib_table_lookup(fib_index, &pfx_0_0);
4473 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
4474 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4475 "Default route is DROP");
4477 dpo = fib_entry_contribute_ip_forwarding(dfrt);
4478 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4480 &pfx_0_0.fp_addr.ip6)),
4481 "default-route; fwd and non-fwd tables match");
4483 // FIXME - check specials.
4486 * At this stage there is one v4 FIB with 5 routes and two v6 FIBs
4487 * each with 2 entries and a v6 mfib with 4 path-lists and v4 mfib with 2.
4488 * All entries are special so no path-list sharing.
4491 u32 PNPS = (5+4+4+2);
4493 * if the IGMP plugin is loaded this adds two more entries to the v4 MFIB
4495 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
4496 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is %d",
4497 fib_path_list_pool_size());
4498 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
4499 fib_entry_pool_size());
4502 * add interface routes.
4503 * validate presence of /64 attached and /128 recieve.
4504 * test for the presence of the receive address in the glean and local adj
4506 * receive on 2001:0:0:1::1/128
4508 fib_prefix_t local_pfx = {
4510 .fp_proto = FIB_PROTOCOL_IP6,
4514 [0] = clib_host_to_net_u64(0x2001000000000001),
4515 [1] = clib_host_to_net_u64(0x0000000000000001),
4521 fib_table_entry_update_one_path(fib_index, &local_pfx,
4522 FIB_SOURCE_INTERFACE,
4523 (FIB_ENTRY_FLAG_CONNECTED |
4524 FIB_ENTRY_FLAG_ATTACHED),
4527 tm->hw[0]->sw_if_index,
4531 FIB_ROUTE_PATH_FLAG_NONE);
4532 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4534 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4536 ai = fib_entry_get_adj(fei);
4537 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
4539 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4540 "attached interface adj is glean");
4541 dpo = fib_entry_contribute_ip_forwarding(fei);
4542 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4544 &local_pfx.fp_addr.ip6)),
4545 "attached-route; fwd and non-fwd tables match");
4547 local_pfx.fp_len = 128;
4548 fib_table_entry_update_one_path(fib_index, &local_pfx,
4549 FIB_SOURCE_INTERFACE,
4550 (FIB_ENTRY_FLAG_CONNECTED |
4551 FIB_ENTRY_FLAG_LOCAL),
4554 tm->hw[0]->sw_if_index,
4555 ~0, // invalid fib index
4558 FIB_ROUTE_PATH_FLAG_NONE);
4559 fei = fib_table_lookup(fib_index, &local_pfx);
4561 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4563 dpo = fib_entry_contribute_ip_forwarding(fei);
4564 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4565 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4566 "local interface adj is local");
4567 rd = receive_dpo_get(dpo->dpoi_index);
4569 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4571 "local interface adj is receive ok");
4573 dpo = fib_entry_contribute_ip_forwarding(fei);
4574 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4576 &local_pfx.fp_addr.ip6)),
4577 "local-route; fwd and non-fwd tables match");
4578 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4579 &adj->sub_type.glean.rx_pfx.fp_addr)),
4580 "attached interface adj is receive ok");
4583 * +2 entries. +2 unshared path-lists
4585 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
4586 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
4587 fib_path_list_pool_size());
4588 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4589 fib_entry_pool_size());
4592 * Modify the default route to be via an adj not yet known.
4593 * this sources the defalut route with the API source, which is
4594 * a higher preference to the DEFAULT_ROUTE source
4596 fib_table_entry_path_add(fib_index, &pfx_0_0,
4598 FIB_ENTRY_FLAG_NONE,
4601 tm->hw[0]->sw_if_index,
4605 FIB_ROUTE_PATH_FLAG_NONE);
4606 fei = fib_table_lookup(fib_index, &pfx_0_0);
4608 FIB_TEST((fei == dfrt), "default route same index");
4609 ai = fib_entry_get_adj(fei);
4610 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
4612 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4613 "adj is incomplete");
4614 FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)),
4615 "adj nbr next-hop ok");
4618 * find the adj in the shared db
4620 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4623 tm->hw[0]->sw_if_index);
4624 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
4625 adj_unlock(locked_ai);
4628 * no more entries. +1 shared path-list
4630 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4631 fib_path_list_db_size());
4632 FIB_TEST((PNPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
4633 fib_path_list_pool_size());
4634 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4635 fib_entry_pool_size());
4638 * remove the API source from the default route. We expected
4639 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
4641 fib_table_entry_path_remove(fib_index, &pfx_0_0,
4645 tm->hw[0]->sw_if_index,
4648 FIB_ROUTE_PATH_FLAG_NONE);
4649 fei = fib_table_lookup(fib_index, &pfx_0_0);
4651 FIB_TEST((fei == dfrt), "default route same index");
4652 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4653 "Default route is DROP");
4656 * no more entries. -1 shared path-list
4658 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4659 fib_path_list_db_size());
4660 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
4661 fib_path_list_pool_size());
4662 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4663 fib_entry_pool_size());
4666 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4668 fib_prefix_t pfx_2001_1_2_s_128 = {
4670 .fp_proto = FIB_PROTOCOL_IP6,
4674 [0] = clib_host_to_net_u64(0x2001000000000001),
4675 [1] = clib_host_to_net_u64(0x0000000000000002),
4680 fib_prefix_t pfx_2001_1_3_s_128 = {
4682 .fp_proto = FIB_PROTOCOL_IP6,
4686 [0] = clib_host_to_net_u64(0x2001000000000001),
4687 [1] = clib_host_to_net_u64(0x0000000000000003),
4693 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
4696 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4698 &pfx_2001_1_2_s_128.fp_addr,
4699 tm->hw[0]->sw_if_index);
4700 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
4701 adj = adj_get(ai_01);
4702 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4703 "adj is incomplete");
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 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4709 fib_test_build_rewrite(eth_addr));
4710 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4712 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4713 &adj->sub_type.nbr.next_hop)),
4714 "adj nbr next-hop ok");
4716 fib_table_entry_path_add(fib_index,
4717 &pfx_2001_1_2_s_128,
4719 FIB_ENTRY_FLAG_ATTACHED,
4721 &pfx_2001_1_2_s_128.fp_addr,
4722 tm->hw[0]->sw_if_index,
4726 FIB_ROUTE_PATH_FLAG_NONE);
4728 fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
4729 ai = fib_entry_get_adj(fei);
4730 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4734 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4736 &pfx_2001_1_3_s_128.fp_addr,
4737 tm->hw[0]->sw_if_index);
4738 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
4739 adj = adj_get(ai_02);
4740 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4741 "adj is incomplete");
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");
4746 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4747 fib_test_build_rewrite(eth_addr));
4748 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4750 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4751 &adj->sub_type.nbr.next_hop)),
4752 "adj nbr next-hop ok");
4753 FIB_TEST((ai_01 != ai_02), "ADJs are different");
4755 fib_table_entry_path_add(fib_index,
4756 &pfx_2001_1_3_s_128,
4758 FIB_ENTRY_FLAG_ATTACHED,
4760 &pfx_2001_1_3_s_128.fp_addr,
4761 tm->hw[0]->sw_if_index,
4765 FIB_ROUTE_PATH_FLAG_NONE);
4767 fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
4768 ai = fib_entry_get_adj(fei);
4769 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4772 * +2 entries, +2 unshread path-lists.
4774 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4775 fib_path_list_db_size());
4776 FIB_TEST((PNPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
4777 fib_path_list_pool_size());
4778 FIB_TEST((ENPS+4 == fib_entry_pool_size()), "entry pool size is %d",
4779 fib_entry_pool_size());
4782 * Add a 2 routes via the first ADJ. ensure path-list sharing
4784 fib_prefix_t pfx_2001_a_s_64 = {
4786 .fp_proto = FIB_PROTOCOL_IP6,
4790 [0] = clib_host_to_net_u64(0x200100000000000a),
4791 [1] = clib_host_to_net_u64(0x0000000000000000),
4796 fib_prefix_t pfx_2001_b_s_64 = {
4798 .fp_proto = FIB_PROTOCOL_IP6,
4802 [0] = clib_host_to_net_u64(0x200100000000000b),
4803 [1] = clib_host_to_net_u64(0x0000000000000000),
4809 fib_table_entry_path_add(fib_index,
4812 FIB_ENTRY_FLAG_NONE,
4815 tm->hw[0]->sw_if_index,
4819 FIB_ROUTE_PATH_FLAG_NONE);
4820 fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64);
4821 ai = fib_entry_get_adj(fei);
4822 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4823 fib_table_entry_path_add(fib_index,
4826 FIB_ENTRY_FLAG_NONE,
4829 tm->hw[0]->sw_if_index,
4833 FIB_ROUTE_PATH_FLAG_NONE);
4834 fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64);
4835 ai = fib_entry_get_adj(fei);
4836 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4839 * +2 entries, +1 shared path-list.
4841 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4842 fib_path_list_db_size());
4843 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4844 fib_path_list_pool_size());
4845 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
4846 fib_entry_pool_size());
4849 * add a v4 prefix via a v6 next-hop
4851 fib_prefix_t pfx_1_1_1_1_s_32 = {
4853 .fp_proto = FIB_PROTOCOL_IP4,
4855 .ip4.as_u32 = 0x01010101,
4858 fei = fib_table_entry_path_add(0, // default table
4861 FIB_ENTRY_FLAG_NONE,
4864 tm->hw[0]->sw_if_index,
4868 FIB_ROUTE_PATH_FLAG_NONE);
4869 FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32),
4870 "1.1.1.1/32 o v6 route present");
4871 ai = fib_entry_get_adj(fei);
4873 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
4874 "1.1.1.1/32 via ARP-adj");
4875 FIB_TEST((adj->ia_link == VNET_LINK_IP4),
4876 "1.1.1.1/32 ADJ-adj is link type v4");
4877 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6),
4878 "1.1.1.1/32 ADJ-adj is NH proto v6");
4879 fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API);
4884 fib_prefix_t pfx_2001_c_s_64 = {
4886 .fp_proto = FIB_PROTOCOL_IP6,
4890 [0] = clib_host_to_net_u64(0x200100000000000c),
4891 [1] = clib_host_to_net_u64(0x0000000000000000),
4896 fib_table_entry_path_add(fib_index,
4899 FIB_ENTRY_FLAG_ATTACHED,
4902 tm->hw[0]->sw_if_index,
4906 FIB_ROUTE_PATH_FLAG_NONE);
4907 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4908 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present");
4909 ai = fib_entry_get_adj(fei);
4911 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN),
4912 "2001:0:0:c/64 attached resolves via glean");
4914 fib_table_entry_path_remove(fib_index,
4919 tm->hw[0]->sw_if_index,
4922 FIB_ROUTE_PATH_FLAG_NONE);
4923 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4924 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached route removed");
4927 * Shutdown the interface on which we have a connected and through
4928 * which the routes are reachable.
4929 * This will result in the connected, adj-fibs, and routes linking to drop
4930 * The local/for-us prefix continues to receive.
4932 clib_error_t * error;
4934 error = vnet_sw_interface_set_flags(vnet_get_main(),
4935 tm->hw[0]->sw_if_index,
4936 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4937 FIB_TEST((NULL == error), "Interface shutdown OK");
4939 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4940 dpo = fib_entry_contribute_ip_forwarding(fei);
4941 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4942 "2001::b/64 resolves via drop");
4944 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4945 dpo = fib_entry_contribute_ip_forwarding(fei);
4946 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4947 "2001::a/64 resolves via drop");
4948 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4949 dpo = fib_entry_contribute_ip_forwarding(fei);
4950 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4951 "2001:0:0:1::3/64 resolves via drop");
4952 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4953 dpo = fib_entry_contribute_ip_forwarding(fei);
4954 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4955 "2001:0:0:1::2/64 resolves via drop");
4956 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4957 dpo = fib_entry_contribute_ip_forwarding(fei);
4958 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4959 "2001:0:0:1::1/128 not drop");
4960 local_pfx.fp_len = 64;
4961 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4962 dpo = fib_entry_contribute_ip_forwarding(fei);
4963 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4964 "2001:0:0:1/64 resolves via drop");
4969 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4970 fib_path_list_db_size());
4971 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4972 fib_path_list_pool_size());
4973 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
4974 fib_entry_pool_size());
4977 * shutdown one of the other interfaces, then add a connected.
4978 * and swap one of the routes to it.
4980 error = vnet_sw_interface_set_flags(vnet_get_main(),
4981 tm->hw[1]->sw_if_index,
4982 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4983 FIB_TEST((NULL == error), "Interface 1 shutdown OK");
4985 fib_prefix_t connected_pfx = {
4987 .fp_proto = FIB_PROTOCOL_IP6,
4990 /* 2001:0:0:2::1/64 */
4992 [0] = clib_host_to_net_u64(0x2001000000000002),
4993 [1] = clib_host_to_net_u64(0x0000000000000001),
4998 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4999 FIB_SOURCE_INTERFACE,
5000 (FIB_ENTRY_FLAG_CONNECTED |
5001 FIB_ENTRY_FLAG_ATTACHED),
5004 tm->hw[1]->sw_if_index,
5008 FIB_ROUTE_PATH_FLAG_NONE);
5009 fei = fib_table_lookup_exact_match(fib_index, &connected_pfx);
5010 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
5011 dpo = fib_entry_contribute_ip_forwarding(fei);
5012 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
5013 FIB_TEST(!dpo_cmp(dpo, dpo_drop),
5014 "2001:0:0:2/64 not resolves via drop");
5016 connected_pfx.fp_len = 128;
5017 fib_table_entry_update_one_path(fib_index, &connected_pfx,
5018 FIB_SOURCE_INTERFACE,
5019 (FIB_ENTRY_FLAG_CONNECTED |
5020 FIB_ENTRY_FLAG_LOCAL),
5023 tm->hw[0]->sw_if_index,
5024 ~0, // invalid fib index
5027 FIB_ROUTE_PATH_FLAG_NONE);
5028 fei = fib_table_lookup(fib_index, &connected_pfx);
5030 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
5031 dpo = fib_entry_contribute_ip_forwarding(fei);
5032 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
5033 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
5034 "local interface adj is local");
5035 rd = receive_dpo_get(dpo->dpoi_index);
5036 FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr,
5038 "local interface adj is receive ok");
5041 * +2 entries, +2 unshared path-lists
5043 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
5044 fib_path_list_db_size());
5045 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
5046 fib_path_list_pool_size());
5047 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
5048 fib_entry_pool_size());
5052 * bring the interface back up. we expected the routes to return
5053 * to normal forwarding.
5055 error = vnet_sw_interface_set_flags(vnet_get_main(),
5056 tm->hw[0]->sw_if_index,
5057 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5058 FIB_TEST((NULL == error), "Interface bring-up OK");
5059 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5060 ai = fib_entry_get_adj(fei);
5061 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
5062 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5063 ai = fib_entry_get_adj(fei);
5064 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
5065 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5066 ai = fib_entry_get_adj(fei);
5067 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
5068 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5069 ai = fib_entry_get_adj(fei);
5070 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
5071 local_pfx.fp_len = 64;
5072 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5073 ai = fib_entry_get_adj(fei);
5075 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
5076 "attached interface adj is glean");
5079 * Same test as above, but this time the HW interface goes down
5081 error = vnet_hw_interface_set_flags(vnet_get_main(),
5082 tm->hw_if_indicies[0],
5083 ~VNET_HW_INTERFACE_FLAG_LINK_UP);
5084 FIB_TEST((NULL == error), "Interface shutdown OK");
5086 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
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::b/64 resolves via drop");
5090 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
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::a/64 resolves via drop");
5094 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5095 dpo = fib_entry_contribute_ip_forwarding(fei);
5096 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5097 "2001:0:0:1::3/128 resolves via drop");
5098 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5099 dpo = fib_entry_contribute_ip_forwarding(fei);
5100 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5101 "2001:0:0:1::2/128 resolves via drop");
5102 local_pfx.fp_len = 128;
5103 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5104 dpo = fib_entry_contribute_ip_forwarding(fei);
5105 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5106 "2001:0:0:1::1/128 not drop");
5107 local_pfx.fp_len = 64;
5108 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5109 dpo = fib_entry_contribute_ip_forwarding(fei);
5110 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5111 "2001:0:0:1/64 resolves via drop");
5113 error = vnet_hw_interface_set_flags(vnet_get_main(),
5114 tm->hw_if_indicies[0],
5115 VNET_HW_INTERFACE_FLAG_LINK_UP);
5116 FIB_TEST((NULL == error), "Interface bring-up OK");
5117 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5118 ai = fib_entry_get_adj(fei);
5119 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
5120 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5121 ai = fib_entry_get_adj(fei);
5122 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
5123 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5124 ai = fib_entry_get_adj(fei);
5125 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
5126 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5127 ai = fib_entry_get_adj(fei);
5128 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
5129 local_pfx.fp_len = 64;
5130 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5131 ai = fib_entry_get_adj(fei);
5133 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
5134 "attached interface adj is glean");
5137 * Delete the interface that the routes reolve through.
5138 * Again no routes are removed. They all point to drop.
5140 * This is considered an error case. The control plane should
5141 * not remove interfaces through which routes resolve, but
5142 * such things can happen. ALL affected routes will drop.
5144 vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]);
5146 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5147 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5148 "2001::b/64 resolves via drop");
5149 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5150 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5151 "2001::b/64 resolves via drop");
5152 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5153 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5154 "2001:0:0:1::3/64 resolves via drop");
5155 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5156 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5157 "2001:0:0:1::2/64 resolves via drop");
5158 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5159 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5160 "2001:0:0:1::1/128 is drop");
5161 local_pfx.fp_len = 64;
5162 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5163 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5164 "2001:0:0:1/64 resolves via drop");
5169 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
5170 fib_path_list_db_size());
5171 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
5172 fib_path_list_pool_size());
5173 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
5174 fib_entry_pool_size());
5177 * Add the interface back. routes stay unresolved.
5179 error = ethernet_register_interface(vnet_get_main(),
5180 test_interface_device_class.index,
5183 &tm->hw_if_indicies[0],
5184 /* flag change */ 0);
5186 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5187 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5188 "2001::b/64 resolves via drop");
5189 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5190 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5191 "2001::b/64 resolves via drop");
5192 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5193 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5194 "2001:0:0:1::3/64 resolves via drop");
5195 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5196 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5197 "2001:0:0:1::2/64 resolves via drop");
5198 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5199 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5200 "2001:0:0:1::1/128 is drop");
5201 local_pfx.fp_len = 64;
5202 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5203 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5204 "2001:0:0:1/64 resolves via drop");
5207 * CLEANUP ALL the routes
5209 fib_table_entry_delete(fib_index,
5212 fib_table_entry_delete(fib_index,
5215 fib_table_entry_delete(fib_index,
5218 fib_table_entry_delete(fib_index,
5219 &pfx_2001_1_3_s_128,
5221 fib_table_entry_delete(fib_index,
5222 &pfx_2001_1_2_s_128,
5224 local_pfx.fp_len = 64;
5225 fib_table_entry_delete(fib_index, &local_pfx,
5226 FIB_SOURCE_INTERFACE);
5227 local_pfx.fp_len = 128;
5228 fib_table_entry_special_remove(fib_index, &local_pfx,
5229 FIB_SOURCE_INTERFACE);
5230 connected_pfx.fp_len = 64;
5231 fib_table_entry_delete(fib_index, &connected_pfx,
5232 FIB_SOURCE_INTERFACE);
5233 connected_pfx.fp_len = 128;
5234 fib_table_entry_special_remove(fib_index, &connected_pfx,
5235 FIB_SOURCE_INTERFACE);
5237 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5238 fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)),
5239 "2001::a/64 removed");
5240 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5241 fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)),
5242 "2001::b/64 removed");
5243 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5244 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)),
5245 "2001:0:0:1::3/128 removed");
5246 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5247 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)),
5248 "2001:0:0:1::3/128 removed");
5249 local_pfx.fp_len = 64;
5250 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5251 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5252 "2001:0:0:1/64 removed");
5253 local_pfx.fp_len = 128;
5254 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5255 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5256 "2001:0:0:1::1/128 removed");
5257 connected_pfx.fp_len = 64;
5258 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5259 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5260 "2001:0:0:2/64 removed");
5261 connected_pfx.fp_len = 128;
5262 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5263 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5264 "2001:0:0:2::1/128 removed");
5267 * -8 entries. -7 path-lists (1 was shared).
5269 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5270 fib_path_list_db_size());
5271 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is%d",
5272 fib_path_list_pool_size());
5273 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
5274 fib_entry_pool_size());
5277 * now remove the VRF
5279 fib_table_unlock(fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
5281 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5282 fib_path_list_db_size());
5283 FIB_TEST((PNPS-2 == fib_path_list_pool_size()), "path list pool size is%d",
5284 fib_path_list_pool_size());
5285 FIB_TEST((ENPS-2 == fib_entry_pool_size()), "entry pool size is %d",
5286 fib_entry_pool_size());
5292 * return the interfaces to up state
5294 error = vnet_sw_interface_set_flags(vnet_get_main(),
5295 tm->hw[0]->sw_if_index,
5296 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5297 error = vnet_sw_interface_set_flags(vnet_get_main(),
5298 tm->hw[1]->sw_if_index,
5299 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5301 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5303 FIB_TEST((0 == adj_glean_db_size()), "ADJ DB size is %d",
5304 adj_glean_db_size());
5310 * Test Attached Exports
5315 const dpo_id_t *dpo, *dpo_drop;
5316 const u32 fib_index = 0;
5317 fib_node_index_t fei;
5326 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5330 * add interface routes. We'll assume this works. It's more rigorously
5333 fib_prefix_t local_pfx = {
5335 .fp_proto = FIB_PROTOCOL_IP4,
5339 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5344 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
5345 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
5347 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
5349 fib_table_entry_update_one_path(fib_index, &local_pfx,
5350 FIB_SOURCE_INTERFACE,
5351 (FIB_ENTRY_FLAG_CONNECTED |
5352 FIB_ENTRY_FLAG_ATTACHED),
5355 tm->hw[0]->sw_if_index,
5359 FIB_ROUTE_PATH_FLAG_NONE);
5360 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5361 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5362 "attached interface route present");
5364 local_pfx.fp_len = 32;
5365 fib_table_entry_update_one_path(fib_index, &local_pfx,
5366 FIB_SOURCE_INTERFACE,
5367 (FIB_ENTRY_FLAG_CONNECTED |
5368 FIB_ENTRY_FLAG_LOCAL),
5371 tm->hw[0]->sw_if_index,
5372 ~0, // invalid fib index
5375 FIB_ROUTE_PATH_FLAG_NONE);
5376 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5378 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5379 "local interface route present");
5382 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
5384 fib_prefix_t pfx_10_10_10_1_s_32 = {
5386 .fp_proto = FIB_PROTOCOL_IP4,
5389 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5392 fib_node_index_t ai;
5394 fib_table_entry_path_add(fib_index,
5395 &pfx_10_10_10_1_s_32,
5397 FIB_ENTRY_FLAG_ATTACHED,
5399 &pfx_10_10_10_1_s_32.fp_addr,
5400 tm->hw[0]->sw_if_index,
5401 ~0, // invalid fib index
5404 FIB_ROUTE_PATH_FLAG_NONE);
5406 fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
5407 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
5408 ai = fib_entry_get_adj(fei);
5411 * create another FIB table into which routes will be imported
5413 u32 import_fib_index1;
5415 import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4,
5420 * Add an attached route in the import FIB
5422 local_pfx.fp_len = 24;
5423 fib_table_entry_update_one_path(import_fib_index1,
5426 FIB_ENTRY_FLAG_NONE,
5429 tm->hw[0]->sw_if_index,
5430 ~0, // invalid fib index
5433 FIB_ROUTE_PATH_FLAG_NONE);
5434 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5435 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5438 * check for the presence of the adj-fibs in the import table
5440 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5441 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5442 FIB_TEST((ai == fib_entry_get_adj(fei)),
5443 "adj-fib1 Import uses same adj as export");
5446 * check for the presence of the local in the import table
5448 local_pfx.fp_len = 32;
5449 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5450 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5453 * Add another adj-fin in the export table. Expect this
5454 * to get magically exported;
5456 fib_prefix_t pfx_10_10_10_2_s_32 = {
5458 .fp_proto = FIB_PROTOCOL_IP4,
5461 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5465 fib_table_entry_path_add(fib_index,
5466 &pfx_10_10_10_2_s_32,
5468 FIB_ENTRY_FLAG_ATTACHED,
5470 &pfx_10_10_10_2_s_32.fp_addr,
5471 tm->hw[0]->sw_if_index,
5472 ~0, // invalid fib index
5475 FIB_ROUTE_PATH_FLAG_NONE);
5476 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5477 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
5478 ai = fib_entry_get_adj(fei);
5480 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5481 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5482 FIB_TEST((ai == fib_entry_get_adj(fei)),
5483 "Import uses same adj as export");
5484 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(fei)),
5485 "ADJ-fib2 imported flags %d",
5486 fib_entry_get_flags(fei));
5489 * create a 2nd FIB table into which routes will be imported
5491 u32 import_fib_index2;
5493 import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12,
5497 * Add an attached route in the import FIB
5499 local_pfx.fp_len = 24;
5500 fib_table_entry_update_one_path(import_fib_index2,
5503 FIB_ENTRY_FLAG_NONE,
5506 tm->hw[0]->sw_if_index,
5507 ~0, // invalid fib index
5510 FIB_ROUTE_PATH_FLAG_NONE);
5511 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5512 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5515 * check for the presence of all the adj-fibs and local in the import table
5517 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5518 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5519 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5520 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5521 local_pfx.fp_len = 32;
5522 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5523 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5526 * add a 3rd adj-fib. expect it to be exported to both tables.
5528 fib_prefix_t pfx_10_10_10_3_s_32 = {
5530 .fp_proto = FIB_PROTOCOL_IP4,
5533 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
5537 fib_table_entry_path_add(fib_index,
5538 &pfx_10_10_10_3_s_32,
5540 FIB_ENTRY_FLAG_ATTACHED,
5542 &pfx_10_10_10_3_s_32.fp_addr,
5543 tm->hw[0]->sw_if_index,
5544 ~0, // invalid fib index
5547 FIB_ROUTE_PATH_FLAG_NONE);
5548 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5549 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
5550 ai = fib_entry_get_adj(fei);
5552 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5553 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1");
5554 FIB_TEST((ai == fib_entry_get_adj(fei)),
5555 "Import uses same adj as export");
5556 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5557 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2");
5558 FIB_TEST((ai == fib_entry_get_adj(fei)),
5559 "Import uses same adj as export");
5562 * remove the 3rd adj fib. we expect it to be removed from both FIBs
5564 fib_table_entry_delete(fib_index,
5565 &pfx_10_10_10_3_s_32,
5568 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5569 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved");
5571 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5572 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1");
5574 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5575 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2");
5578 * remove the attached route from the 2nd FIB. expect the imported
5579 * entries to be removed
5581 local_pfx.fp_len = 24;
5582 fib_table_entry_delete(import_fib_index2,
5585 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5586 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed");
5588 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5589 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2");
5590 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5591 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2");
5592 local_pfx.fp_len = 32;
5593 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5594 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2");
5596 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5597 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1");
5598 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5599 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1");
5600 local_pfx.fp_len = 32;
5601 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5602 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1");
5605 * modify the route in FIB1 so it is no longer attached. expect the imported
5606 * entries to be removed
5608 local_pfx.fp_len = 24;
5609 fib_table_entry_update_one_path(import_fib_index1,
5612 FIB_ENTRY_FLAG_NONE,
5614 &pfx_10_10_10_2_s_32.fp_addr,
5615 tm->hw[0]->sw_if_index,
5616 ~0, // invalid fib index
5619 FIB_ROUTE_PATH_FLAG_NONE);
5620 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5621 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5622 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5623 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5624 local_pfx.fp_len = 32;
5625 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5626 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5629 * modify it back to attached. expect the adj-fibs back
5631 local_pfx.fp_len = 24;
5632 fib_table_entry_update_one_path(import_fib_index1,
5635 FIB_ENTRY_FLAG_NONE,
5638 tm->hw[0]->sw_if_index,
5639 ~0, // invalid fib index
5642 FIB_ROUTE_PATH_FLAG_NONE);
5643 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5644 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1");
5645 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5646 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1");
5647 local_pfx.fp_len = 32;
5648 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5649 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1");
5652 * add a covering attached next-hop for the interface address, so we have
5653 * a valid adj to find when we check the forwarding tables
5655 fib_prefix_t pfx_10_0_0_0_s_8 = {
5657 .fp_proto = FIB_PROTOCOL_IP4,
5660 .ip4.as_u32 = clib_host_to_net_u32(0x0a000000),
5664 fei = fib_table_entry_update_one_path(fib_index,
5667 FIB_ENTRY_FLAG_NONE,
5669 &pfx_10_10_10_3_s_32.fp_addr,
5670 tm->hw[0]->sw_if_index,
5671 ~0, // invalid fib index
5674 FIB_ROUTE_PATH_FLAG_NONE);
5675 dpo = fib_entry_contribute_ip_forwarding(fei);
5678 * remove the route in the export fib. expect the adj-fibs to be removed
5680 local_pfx.fp_len = 24;
5681 fib_table_entry_delete(fib_index,
5683 FIB_SOURCE_INTERFACE);
5685 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5686 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1");
5687 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5688 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5689 local_pfx.fp_len = 32;
5690 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5691 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5694 * the adj-fibs in the export VRF are present in the FIB table,
5695 * but not installed in forwarding, since they have no attached cover.
5696 * Consequently a lookup in the MTRIE gives the adj for the covering
5699 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5700 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5703 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5704 FIB_TEST(lbi == dpo->dpoi_index,
5705 "10.10.10.1 forwards on \n%U not \n%U",
5706 format_load_balance, lbi, 0,
5707 format_dpo_id, dpo, 0);
5708 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5709 FIB_TEST(lbi == dpo->dpoi_index,
5710 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5711 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4);
5712 FIB_TEST(lbi == dpo->dpoi_index,
5713 "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0);
5716 * add the export prefix back, but not as attached.
5717 * No adj-fibs in export nor import tables
5719 local_pfx.fp_len = 24;
5720 fei = fib_table_entry_update_one_path(fib_index,
5723 FIB_ENTRY_FLAG_NONE,
5725 &pfx_10_10_10_1_s_32.fp_addr,
5726 tm->hw[0]->sw_if_index,
5727 ~0, // invalid fib index
5730 FIB_ROUTE_PATH_FLAG_NONE);
5731 dpo = fib_entry_contribute_ip_forwarding(fei);
5733 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5734 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export");
5735 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5736 FIB_TEST(lbi == dpo->dpoi_index,
5737 "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0);
5738 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5739 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5740 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5741 FIB_TEST(lbi == dpo->dpoi_index,
5742 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5744 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5745 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5746 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5747 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5748 local_pfx.fp_len = 32;
5749 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5750 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5753 * modify the export prefix so it is attached. expect all covereds to return
5755 local_pfx.fp_len = 24;
5756 fib_table_entry_update_one_path(fib_index,
5759 FIB_ENTRY_FLAG_NONE,
5762 tm->hw[0]->sw_if_index,
5763 ~0, // invalid fib index
5766 FIB_ROUTE_PATH_FLAG_NONE);
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 reinstalled in export");
5770 dpo = fib_entry_contribute_ip_forwarding(fei);
5771 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5772 "Adj-fib1 is not drop in export");
5773 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5774 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5775 local_pfx.fp_len = 32;
5776 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5777 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5778 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5779 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5780 dpo = fib_entry_contribute_ip_forwarding(fei);
5781 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5782 "Adj-fib1 is not drop in export: %U %U",
5783 format_dpo_id, dpo, 0,
5784 format_dpo_id, load_balance_get_bucket(dpo->dpoi_index, 0), 0);
5785 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5786 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5787 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5788 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5789 local_pfx.fp_len = 32;
5790 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5791 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5794 * modify the export prefix so connected. no change.
5796 local_pfx.fp_len = 24;
5797 fib_table_entry_update_one_path(fib_index, &local_pfx,
5798 FIB_SOURCE_INTERFACE,
5799 (FIB_ENTRY_FLAG_CONNECTED |
5800 FIB_ENTRY_FLAG_ATTACHED),
5803 tm->hw[0]->sw_if_index,
5807 FIB_ROUTE_PATH_FLAG_NONE);
5809 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5810 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5811 dpo = fib_entry_contribute_ip_forwarding(fei);
5812 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5813 "Adj-fib1 is not drop in export");
5814 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5815 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5816 local_pfx.fp_len = 32;
5817 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5818 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5819 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5820 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5821 dpo = fib_entry_contribute_ip_forwarding(fei);
5822 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5823 "Adj-fib1 is not drop in export");
5824 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5825 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5826 local_pfx.fp_len = 32;
5827 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5828 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5833 fib_table_entry_delete(fib_index,
5836 fib_table_entry_delete(fib_index,
5837 &pfx_10_10_10_1_s_32,
5839 fib_table_entry_delete(fib_index,
5840 &pfx_10_10_10_2_s_32,
5842 local_pfx.fp_len = 32;
5843 fib_table_entry_delete(fib_index,
5845 FIB_SOURCE_INTERFACE);
5846 local_pfx.fp_len = 24;
5847 fib_table_entry_delete(fib_index,
5850 fib_table_entry_delete(fib_index,
5852 FIB_SOURCE_INTERFACE);
5853 local_pfx.fp_len = 24;
5854 fib_table_entry_delete(import_fib_index1,
5858 fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
5859 fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
5861 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5868 * Test Path Preference
5871 fib_test_pref (void)
5881 const fib_prefix_t pfx_1_1_1_1_s_32 = {
5883 .fp_proto = FIB_PROTOCOL_IP4,
5886 .as_u32 = clib_host_to_net_u32(0x01010101),
5891 vec_validate(im->fib_index_by_sw_if_index, tm->hw[2]->sw_if_index);
5893 for (i = 0; i <= 2; i++)
5894 im->fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
5897 * 2 high, 2 medium and 2 low preference non-recursive paths
5899 fib_route_path_t nr_path_hi_1 = {
5900 .frp_proto = DPO_PROTO_IP4,
5901 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5902 .frp_fib_index = ~0,
5904 .frp_preference = 0,
5905 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5907 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5910 fib_route_path_t nr_path_hi_2 = {
5911 .frp_proto = DPO_PROTO_IP4,
5912 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5913 .frp_fib_index = ~0,
5915 .frp_preference = 0,
5916 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5918 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5921 fib_route_path_t nr_path_med_1 = {
5922 .frp_proto = DPO_PROTO_IP4,
5923 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5924 .frp_fib_index = ~0,
5926 .frp_preference = 1,
5927 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5929 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5932 fib_route_path_t nr_path_med_2 = {
5933 .frp_proto = DPO_PROTO_IP4,
5934 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5935 .frp_fib_index = ~0,
5937 .frp_preference = 1,
5938 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5940 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5943 fib_route_path_t nr_path_low_1 = {
5944 .frp_proto = DPO_PROTO_IP4,
5945 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5946 .frp_fib_index = ~0,
5948 .frp_preference = 2,
5949 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5951 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b01),
5954 fib_route_path_t nr_path_low_2 = {
5955 .frp_proto = DPO_PROTO_IP4,
5956 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5957 .frp_fib_index = ~0,
5959 .frp_preference = 2,
5960 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5962 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b02),
5965 fib_route_path_t *nr_paths = NULL;
5967 vec_add1(nr_paths, nr_path_hi_1);
5968 vec_add1(nr_paths, nr_path_hi_2);
5969 vec_add1(nr_paths, nr_path_med_1);
5970 vec_add1(nr_paths, nr_path_med_2);
5971 vec_add1(nr_paths, nr_path_low_1);
5972 vec_add1(nr_paths, nr_path_low_2);
5974 adj_index_t ai_hi_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5976 &nr_path_hi_1.frp_addr,
5977 nr_path_hi_1.frp_sw_if_index);
5978 adj_index_t ai_hi_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5980 &nr_path_hi_2.frp_addr,
5981 nr_path_hi_2.frp_sw_if_index);
5982 adj_index_t ai_med_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5984 &nr_path_med_1.frp_addr,
5985 nr_path_med_1.frp_sw_if_index);
5986 adj_index_t ai_med_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5988 &nr_path_med_2.frp_addr,
5989 nr_path_med_2.frp_sw_if_index);
5990 adj_index_t ai_low_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5992 &nr_path_low_1.frp_addr,
5993 nr_path_low_1.frp_sw_if_index);
5994 adj_index_t ai_low_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5996 &nr_path_low_2.frp_addr,
5997 nr_path_low_2.frp_sw_if_index);
5999 fib_test_lb_bucket_t ip_hi_1 = {
6005 fib_test_lb_bucket_t ip_hi_2 = {
6011 fib_test_lb_bucket_t ip_med_1 = {
6017 fib_test_lb_bucket_t ip_med_2 = {
6023 fib_test_lb_bucket_t ip_low_1 = {
6029 fib_test_lb_bucket_t ip_low_2 = {
6036 fib_node_index_t fei;
6038 fei = fib_table_entry_path_add2(0,
6041 FIB_ENTRY_FLAG_NONE,
6044 FIB_TEST(!fib_test_validate_entry(fei,
6045 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6049 "1.1.1.1/32 via high preference paths");
6052 * bring down the interface on which the high preference path lie
6054 vnet_sw_interface_set_flags(vnet_get_main(),
6055 tm->hw[0]->sw_if_index,
6058 FIB_TEST(!fib_test_validate_entry(fei,
6059 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6063 "1.1.1.1/32 via medium preference paths");
6066 * bring down the interface on which the medium preference path lie
6068 vnet_sw_interface_set_flags(vnet_get_main(),
6069 tm->hw[1]->sw_if_index,
6072 FIB_TEST(!fib_test_validate_entry(fei,
6073 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6077 "1.1.1.1/32 via low preference paths");
6080 * bring up the interface on which the high preference path lie
6082 vnet_sw_interface_set_flags(vnet_get_main(),
6083 tm->hw[0]->sw_if_index,
6084 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6086 FIB_TEST(!fib_test_validate_entry(fei,
6087 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6091 "1.1.1.1/32 via high preference paths");
6094 * bring up the interface on which the medium preference path lie
6096 vnet_sw_interface_set_flags(vnet_get_main(),
6097 tm->hw[1]->sw_if_index,
6098 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6100 FIB_TEST(!fib_test_validate_entry(fei,
6101 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6105 "1.1.1.1/32 via high preference paths");
6107 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
6108 fib_entry_contribute_forwarding(fei,
6109 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6113 * 3 recursive paths of different preference
6115 const fib_prefix_t pfx_1_1_1_2_s_32 = {
6117 .fp_proto = FIB_PROTOCOL_IP4,
6120 .as_u32 = clib_host_to_net_u32(0x01010102),
6124 const fib_prefix_t pfx_1_1_1_3_s_32 = {
6126 .fp_proto = FIB_PROTOCOL_IP4,
6129 .as_u32 = clib_host_to_net_u32(0x01010103),
6133 fei = fib_table_entry_path_add2(0,
6136 FIB_ENTRY_FLAG_NONE,
6138 dpo_id_t ip_1_1_1_2 = DPO_INVALID;
6139 fib_entry_contribute_forwarding(fei,
6140 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6142 fei = fib_table_entry_path_add2(0,
6145 FIB_ENTRY_FLAG_NONE,
6147 dpo_id_t ip_1_1_1_3 = DPO_INVALID;
6148 fib_entry_contribute_forwarding(fei,
6149 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6152 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
6155 .lb = ip_1_1_1_1.dpoi_index,
6158 fib_test_lb_bucket_t ip_o_1_1_1_2 = {
6161 .lb = ip_1_1_1_2.dpoi_index,
6164 fib_test_lb_bucket_t ip_o_1_1_1_3 = {
6167 .lb = ip_1_1_1_3.dpoi_index,
6170 fib_route_path_t r_path_hi = {
6171 .frp_proto = DPO_PROTO_IP4,
6172 .frp_sw_if_index = ~0,
6175 .frp_preference = 0,
6176 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
6177 .frp_addr = pfx_1_1_1_1_s_32.fp_addr,
6179 fib_route_path_t r_path_med = {
6180 .frp_proto = DPO_PROTO_IP4,
6181 .frp_sw_if_index = ~0,
6184 .frp_preference = 10,
6185 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
6186 .frp_addr = pfx_1_1_1_2_s_32.fp_addr,
6188 fib_route_path_t r_path_low = {
6189 .frp_proto = DPO_PROTO_IP4,
6190 .frp_sw_if_index = ~0,
6193 .frp_preference = 255,
6194 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
6195 .frp_addr = pfx_1_1_1_3_s_32.fp_addr,
6197 fib_route_path_t *r_paths = NULL;
6199 vec_add1(r_paths, r_path_hi);
6200 vec_add1(r_paths, r_path_low);
6201 vec_add1(r_paths, r_path_med);
6204 * add many recursive so we get the LB MAp created
6207 fib_prefix_t pfx_r[N_PFXS];
6208 unsigned int n_pfxs;
6209 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6211 pfx_r[n_pfxs].fp_len = 32;
6212 pfx_r[n_pfxs].fp_proto = FIB_PROTOCOL_IP4;
6213 pfx_r[n_pfxs].fp_addr.ip4.as_u32 =
6214 clib_host_to_net_u32(0x02000000 + n_pfxs);
6216 fei = fib_table_entry_path_add2(0,
6219 FIB_ENTRY_FLAG_NONE,
6222 FIB_TEST(!fib_test_validate_entry(fei,
6223 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6226 "recursive via high preference paths");
6229 * withdraw hig pref resolving entry
6231 fib_table_entry_delete(0,
6235 /* suspend so the update walk kicks int */
6236 vlib_process_suspend(vlib_get_main(), 1e-5);
6238 FIB_TEST(!fib_test_validate_entry(fei,
6239 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6242 "recursive via medium preference paths");
6245 * withdraw medium pref resolving entry
6247 fib_table_entry_delete(0,
6251 /* suspend so the update walk kicks int */
6252 vlib_process_suspend(vlib_get_main(), 1e-5);
6254 FIB_TEST(!fib_test_validate_entry(fei,
6255 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6258 "recursive via low preference paths");
6261 * add back paths for next iteration
6263 fei = fib_table_entry_update(0,
6266 FIB_ENTRY_FLAG_NONE,
6268 fei = fib_table_entry_update(0,
6271 FIB_ENTRY_FLAG_NONE,
6274 /* suspend so the update walk kicks int */
6275 vlib_process_suspend(vlib_get_main(), 1e-5);
6277 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6278 FIB_TEST(!fib_test_validate_entry(fei,
6279 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6282 "recursive via high preference paths");
6286 fib_table_entry_delete(0,
6290 /* suspend so the update walk kicks int */
6291 vlib_process_suspend(vlib_get_main(), 1e-5);
6293 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6295 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6297 FIB_TEST(!fib_test_validate_entry(fei,
6298 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6301 "recursive via medium preference paths");
6303 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6305 fib_table_entry_delete(0,
6313 fib_table_entry_delete(0,
6316 fib_table_entry_delete(0,
6320 dpo_reset(&ip_1_1_1_1);
6321 dpo_reset(&ip_1_1_1_2);
6322 dpo_reset(&ip_1_1_1_3);
6323 adj_unlock(ai_low_2);
6324 adj_unlock(ai_low_1);
6325 adj_unlock(ai_med_2);
6326 adj_unlock(ai_med_1);
6327 adj_unlock(ai_hi_2);
6328 adj_unlock(ai_hi_1);
6334 * Test the recursive route route handling for GRE tunnels
6337 fib_test_label (void)
6339 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;
6340 const u32 fib_index = 0;
6341 int lb_count, ii, res;
6346 lb_count = pool_elts(load_balance_pool);
6351 * add interface routes. We'll assume this works. It's more rigorously
6354 fib_prefix_t local0_pfx = {
6356 .fp_proto = FIB_PROTOCOL_IP4,
6360 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
6365 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6368 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
6369 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
6371 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6372 FIB_SOURCE_INTERFACE,
6373 (FIB_ENTRY_FLAG_CONNECTED |
6374 FIB_ENTRY_FLAG_ATTACHED),
6377 tm->hw[0]->sw_if_index,
6381 FIB_ROUTE_PATH_FLAG_NONE);
6382 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6383 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6384 "attached interface route present");
6386 local0_pfx.fp_len = 32;
6387 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6388 FIB_SOURCE_INTERFACE,
6389 (FIB_ENTRY_FLAG_CONNECTED |
6390 FIB_ENTRY_FLAG_LOCAL),
6393 tm->hw[0]->sw_if_index,
6394 ~0, // invalid fib index
6397 FIB_ROUTE_PATH_FLAG_NONE);
6398 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6400 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6401 "local interface route present");
6403 fib_prefix_t local1_pfx = {
6405 .fp_proto = FIB_PROTOCOL_IP4,
6409 .as_u32 = clib_host_to_net_u32(0x0a0a0b0a),
6414 vec_validate(im->fib_index_by_sw_if_index, tm->hw[1]->sw_if_index);
6415 im->fib_index_by_sw_if_index[tm->hw[1]->sw_if_index] = fib_index;
6417 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6418 FIB_SOURCE_INTERFACE,
6419 (FIB_ENTRY_FLAG_CONNECTED |
6420 FIB_ENTRY_FLAG_ATTACHED),
6423 tm->hw[1]->sw_if_index,
6427 FIB_ROUTE_PATH_FLAG_NONE);
6428 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6429 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6430 "attached interface route present");
6432 local1_pfx.fp_len = 32;
6433 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6434 FIB_SOURCE_INTERFACE,
6435 (FIB_ENTRY_FLAG_CONNECTED |
6436 FIB_ENTRY_FLAG_LOCAL),
6439 tm->hw[1]->sw_if_index,
6440 ~0, // invalid fib index
6443 FIB_ROUTE_PATH_FLAG_NONE);
6444 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6446 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6447 "local interface route present");
6449 ip46_address_t nh_10_10_10_1 = {
6451 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
6454 ip46_address_t nh_10_10_11_1 = {
6456 .as_u32 = clib_host_to_net_u32(0x0a0a0b01),
6459 ip46_address_t nh_10_10_11_2 = {
6461 .as_u32 = clib_host_to_net_u32(0x0a0a0b02),
6465 ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6468 tm->hw[1]->sw_if_index);
6469 ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6472 tm->hw[1]->sw_if_index);
6473 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6476 tm->hw[0]->sw_if_index);
6477 ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6480 tm->hw[1]->sw_if_index);
6481 ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6484 tm->hw[1]->sw_if_index);
6487 * Add an etry with one path with a real out-going label
6489 fib_prefix_t pfx_1_1_1_1_s_32 = {
6491 .fp_proto = FIB_PROTOCOL_IP4,
6493 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
6496 fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = {
6497 .type = FT_LB_LABEL_O_ADJ,
6499 .adj = ai_mpls_10_10_10_1,
6504 fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = {
6505 .type = FT_LB_LABEL_O_ADJ,
6507 .adj = ai_mpls_10_10_10_1,
6509 .eos = MPLS_NON_EOS,
6512 fib_mpls_label_t *l99 = NULL, fml99 = {
6515 vec_add1(l99, fml99);
6517 fib_table_entry_update_one_path(fib_index,
6520 FIB_ENTRY_FLAG_NONE,
6523 tm->hw[0]->sw_if_index,
6524 ~0, // invalid fib index
6527 FIB_ROUTE_PATH_FLAG_NONE);
6529 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6530 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created");
6532 FIB_TEST(!fib_test_validate_entry(fei,
6533 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6535 &l99_eos_o_10_10_10_1),
6536 "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1");
6539 * add a path with an implicit NULL label
6541 fib_test_lb_bucket_t a_o_10_10_11_1 = {
6544 .adj = ai_v4_10_10_11_1,
6547 fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = {
6550 .adj = ai_mpls_10_10_11_1,
6553 fib_mpls_label_t *l_imp_null = NULL, fml_imp_null = {
6554 .fml_value = MPLS_IETF_IMPLICIT_NULL_LABEL,
6556 vec_add1(l_imp_null, fml_imp_null);
6558 fei = fib_table_entry_path_add(fib_index,
6561 FIB_ENTRY_FLAG_NONE,
6564 tm->hw[1]->sw_if_index,
6565 ~0, // invalid fib index
6568 FIB_ROUTE_PATH_FLAG_NONE);
6570 FIB_TEST(!fib_test_validate_entry(fei,
6571 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6573 &l99_eos_o_10_10_10_1,
6575 "1.1.1.1/32 LB 2 buckets via: "
6576 "label 99 over 10.10.10.1, "
6577 "adj over 10.10.11.1");
6580 * assign the route a local label
6582 fib_table_entry_local_label_add(fib_index,
6586 fib_prefix_t pfx_24001_eos = {
6587 .fp_proto = FIB_PROTOCOL_MPLS,
6591 fib_prefix_t pfx_24001_neos = {
6592 .fp_proto = FIB_PROTOCOL_MPLS,
6594 .fp_eos = MPLS_NON_EOS,
6596 fib_test_lb_bucket_t disp_o_10_10_11_1 = {
6597 .type = FT_LB_MPLS_DISP_PIPE_O_ADJ,
6599 .adj = ai_v4_10_10_11_1,
6604 * The EOS entry should link to both the paths,
6605 * and use an ip adj for the imp-null
6606 * The NON-EOS entry should link to both the paths,
6607 * and use an mpls adj for the imp-null
6609 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6611 FIB_TEST(!fib_test_validate_entry(fei,
6612 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6614 &l99_eos_o_10_10_10_1,
6615 &disp_o_10_10_11_1),
6616 "24001/eos LB 2 buckets via: "
6617 "label 99 over 10.10.10.1, "
6618 "mpls disp adj over 10.10.11.1");
6621 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6623 FIB_TEST(!fib_test_validate_entry(fei,
6624 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6626 &l99_neos_o_10_10_10_1,
6627 &a_mpls_o_10_10_11_1),
6628 "24001/neos LB 1 bucket via: "
6629 "label 99 over 10.10.10.1 ",
6630 "mpls-adj via 10.10.11.1");
6633 * add an unlabelled path, this is excluded from the neos chains,
6635 fib_test_lb_bucket_t adj_o_10_10_11_2 = {
6638 .adj = ai_v4_10_10_11_2,
6641 fib_test_lb_bucket_t disp_o_10_10_11_2 = {
6642 .type = FT_LB_MPLS_DISP_PIPE_O_ADJ,
6644 .adj = ai_v4_10_10_11_2,
6649 fei = fib_table_entry_path_add(fib_index,
6652 FIB_ENTRY_FLAG_NONE,
6655 tm->hw[1]->sw_if_index,
6656 ~0, // invalid fib index
6659 FIB_ROUTE_PATH_FLAG_NONE);
6661 FIB_TEST(!fib_test_validate_entry(fei,
6662 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6663 16, // 3 choices spread over 16 buckets
6664 &l99_eos_o_10_10_10_1,
6665 &l99_eos_o_10_10_10_1,
6666 &l99_eos_o_10_10_10_1,
6667 &l99_eos_o_10_10_10_1,
6668 &l99_eos_o_10_10_10_1,
6669 &l99_eos_o_10_10_10_1,
6680 "1.1.1.1/32 LB 16 buckets via: "
6681 "label 99 over 10.10.10.1, "
6682 "adj over 10.10.11.1",
6683 "adj over 10.10.11.2");
6686 * get and lock a reference to the non-eos of the via entry 1.1.1.1/32
6688 dpo_id_t non_eos_1_1_1_1 = DPO_INVALID;
6689 fib_entry_contribute_forwarding(fei,
6690 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6694 * n-eos has only the 2 labelled paths
6696 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6699 FIB_TEST(!fib_test_validate_entry(fei,
6700 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6702 &l99_neos_o_10_10_10_1,
6703 &a_mpls_o_10_10_11_1),
6704 "24001/neos LB 2 buckets via: "
6705 "label 99 over 10.10.10.1, "
6706 "adj-mpls over 10.10.11.2");
6709 * A labelled recursive
6711 fib_prefix_t pfx_2_2_2_2_s_32 = {
6713 .fp_proto = FIB_PROTOCOL_IP4,
6715 .ip4.as_u32 = clib_host_to_net_u32(0x02020202),
6718 fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = {
6719 .type = FT_LB_LABEL_O_LB,
6721 .lb = non_eos_1_1_1_1.dpoi_index,
6724 .mode = FIB_MPLS_LSP_MODE_UNIFORM,
6727 fib_mpls_label_t *l1600 = NULL, fml1600 = {
6729 .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM,
6731 vec_add1(l1600, fml1600);
6733 fei = fib_table_entry_update_one_path(fib_index,
6736 FIB_ENTRY_FLAG_NONE,
6738 &pfx_1_1_1_1_s_32.fp_addr,
6743 FIB_ROUTE_PATH_FLAG_NONE);
6745 FIB_TEST(!fib_test_validate_entry(fei,
6746 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6748 &l1600_eos_o_1_1_1_1),
6749 "2.2.2.2.2/32 LB 1 buckets via: "
6750 "label 1600 over 1.1.1.1");
6752 dpo_id_t dpo_44 = DPO_INVALID;
6755 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
6756 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
6758 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
6759 "uRPF check for 2.2.2.2/32 on %d OK",
6760 tm->hw[0]->sw_if_index);
6761 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
6762 "uRPF check for 2.2.2.2/32 on %d OK",
6763 tm->hw[1]->sw_if_index);
6764 FIB_TEST(!fib_urpf_check(urpfi, 99),
6765 "uRPF check for 2.2.2.2/32 on 99 not-OK",
6768 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44);
6769 FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index),
6770 "Shared uRPF on IP and non-EOS chain");
6775 * we are holding a lock on the non-eos LB of the via-entry.
6776 * do a PIC-core failover by shutting the link of the via-entry.
6778 * shut down the link with the valid label
6780 vnet_sw_interface_set_flags(vnet_get_main(),
6781 tm->hw[0]->sw_if_index,
6784 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6785 FIB_TEST(!fib_test_validate_entry(fei,
6786 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6790 "1.1.1.1/32 LB 2 buckets via: "
6791 "adj over 10.10.11.1, ",
6792 "adj-v4 over 10.10.11.2");
6794 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6796 FIB_TEST(!fib_test_validate_entry(fei,
6797 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6800 &disp_o_10_10_11_2),
6801 "24001/eos LB 2 buckets via: "
6802 "mpls-disp adj over 10.10.11.1, ",
6803 "mpls-disp adj-v4 over 10.10.11.2");
6805 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6807 FIB_TEST(!fib_test_validate_entry(fei,
6808 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6810 &a_mpls_o_10_10_11_1),
6811 "24001/neos LB 1 buckets via: "
6812 "adj-mpls over 10.10.11.2");
6815 * test that the pre-failover load-balance has been in-place
6818 dpo_id_t current = DPO_INVALID;
6819 fib_entry_contribute_forwarding(fei,
6820 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6823 FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1,
6825 "PIC-core LB inplace modified %U %U",
6826 format_dpo_id, &non_eos_1_1_1_1, 0,
6827 format_dpo_id, ¤t, 0);
6829 dpo_reset(&non_eos_1_1_1_1);
6830 dpo_reset(¤t);
6833 * no-shut the link with the valid label
6835 vnet_sw_interface_set_flags(vnet_get_main(),
6836 tm->hw[0]->sw_if_index,
6837 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6839 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6840 FIB_TEST(!fib_test_validate_entry(fei,
6841 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6842 16, // 3 choices spread over 16 buckets
6843 &l99_eos_o_10_10_10_1,
6844 &l99_eos_o_10_10_10_1,
6845 &l99_eos_o_10_10_10_1,
6846 &l99_eos_o_10_10_10_1,
6847 &l99_eos_o_10_10_10_1,
6848 &l99_eos_o_10_10_10_1,
6859 "1.1.1.1/32 LB 16 buckets via: "
6860 "label 99 over 10.10.10.1, "
6861 "adj over 10.10.11.1",
6862 "adj-v4 over 10.10.11.2");
6865 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6867 FIB_TEST(!fib_test_validate_entry(fei,
6868 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6869 16, // 3 choices spread over 16 buckets
6870 &l99_eos_o_10_10_10_1,
6871 &l99_eos_o_10_10_10_1,
6872 &l99_eos_o_10_10_10_1,
6873 &l99_eos_o_10_10_10_1,
6874 &l99_eos_o_10_10_10_1,
6875 &l99_eos_o_10_10_10_1,
6885 &disp_o_10_10_11_2),
6886 "24001/eos LB 16 buckets via: "
6887 "label 99 over 10.10.10.1, "
6888 "MPLS disp adj over 10.10.11.1",
6889 "MPLS disp adj-v4 over 10.10.11.2");
6891 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6893 FIB_TEST(!fib_test_validate_entry(fei,
6894 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6896 &l99_neos_o_10_10_10_1,
6897 &a_mpls_o_10_10_11_1),
6898 "24001/neos LB 2 buckets via: "
6899 "label 99 over 10.10.10.1, "
6900 "adj-mpls over 10.10.11.2");
6903 * remove the first path with the valid label
6905 fib_table_entry_path_remove(fib_index,
6910 tm->hw[0]->sw_if_index,
6911 ~0, // invalid fib index
6913 FIB_ROUTE_PATH_FLAG_NONE);
6915 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6916 FIB_TEST(!fib_test_validate_entry(fei,
6917 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6921 "1.1.1.1/32 LB 2 buckets via: "
6922 "adj over 10.10.11.1, "
6923 "adj-v4 over 10.10.11.2");
6925 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6927 FIB_TEST(!fib_test_validate_entry(fei,
6928 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6931 &disp_o_10_10_11_2),
6932 "24001/eos LB 2 buckets via: "
6933 "MPLS disp adj over 10.10.11.1, "
6934 "MPLS disp adj-v4 over 10.10.11.2");
6936 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6939 FIB_TEST(!fib_test_validate_entry(fei,
6940 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6942 &a_mpls_o_10_10_11_1),
6943 "24001/neos LB 1 buckets via: "
6944 "adj-mpls over 10.10.11.2");
6947 * remove the other path with a valid label
6949 fib_test_lb_bucket_t bucket_drop = {
6952 fib_test_lb_bucket_t mpls_bucket_drop = {
6955 .adj = DPO_PROTO_MPLS,
6959 fib_table_entry_path_remove(fib_index,
6964 tm->hw[1]->sw_if_index,
6965 ~0, // invalid fib index
6967 FIB_ROUTE_PATH_FLAG_NONE);
6969 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6970 FIB_TEST(!fib_test_validate_entry(fei,
6971 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6974 "1.1.1.1/32 LB 1 buckets via: "
6975 "adj over 10.10.11.2");
6977 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6979 FIB_TEST(!fib_test_validate_entry(fei,
6980 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6982 &disp_o_10_10_11_2),
6983 "24001/eos LB 1 buckets via: "
6984 "MPLS disp adj over 10.10.11.2");
6986 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6988 FIB_TEST(!fib_test_validate_entry(fei,
6989 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6992 "24001/neos LB 1 buckets via: DROP");
6995 * add back the path with the valid label
6998 vec_add1(l99, fml99);
7000 fib_table_entry_path_add(fib_index,
7003 FIB_ENTRY_FLAG_NONE,
7006 tm->hw[0]->sw_if_index,
7007 ~0, // invalid fib index
7010 FIB_ROUTE_PATH_FLAG_NONE);
7012 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
7013 FIB_TEST(!fib_test_validate_entry(fei,
7014 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7016 &l99_eos_o_10_10_10_1,
7018 "1.1.1.1/32 LB 2 buckets via: "
7019 "label 99 over 10.10.10.1, "
7020 "adj over 10.10.11.2");
7022 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7024 FIB_TEST(!fib_test_validate_entry(fei,
7025 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7027 &l99_eos_o_10_10_10_1,
7028 &disp_o_10_10_11_2),
7029 "24001/eos LB 2 buckets via: "
7030 "label 99 over 10.10.10.1, "
7031 "MPLS disp adj over 10.10.11.2");
7033 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7035 FIB_TEST(!fib_test_validate_entry(fei,
7036 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7038 &l99_neos_o_10_10_10_1),
7039 "24001/neos LB 1 buckets via: "
7040 "label 99 over 10.10.10.1");
7043 * change the local label
7045 fib_table_entry_local_label_add(fib_index,
7049 fib_prefix_t pfx_25005_eos = {
7050 .fp_proto = FIB_PROTOCOL_MPLS,
7054 fib_prefix_t pfx_25005_neos = {
7055 .fp_proto = FIB_PROTOCOL_MPLS,
7057 .fp_eos = MPLS_NON_EOS,
7060 FIB_TEST((FIB_NODE_INDEX_INVALID ==
7061 fib_table_lookup(fib_index, &pfx_24001_eos)),
7062 "24001/eos removed after label change");
7063 FIB_TEST((FIB_NODE_INDEX_INVALID ==
7064 fib_table_lookup(fib_index, &pfx_24001_neos)),
7065 "24001/eos removed after label change");
7067 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7069 FIB_TEST(!fib_test_validate_entry(fei,
7070 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7072 &l99_eos_o_10_10_10_1,
7073 &disp_o_10_10_11_2),
7074 "25005/eos LB 2 buckets via: "
7075 "label 99 over 10.10.10.1, "
7076 "MPLS disp adj over 10.10.11.2");
7078 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7080 FIB_TEST(!fib_test_validate_entry(fei,
7081 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7083 &l99_neos_o_10_10_10_1),
7084 "25005/neos LB 1 buckets via: "
7085 "label 99 over 10.10.10.1");
7088 * remove the local label.
7089 * the check that the MPLS entries are gone is done by the fact the
7090 * MPLS table is no longer present.
7092 fib_table_entry_local_label_remove(fib_index,
7096 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
7097 FIB_TEST(!fib_test_validate_entry(fei,
7098 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7100 &l99_eos_o_10_10_10_1,
7102 "24001/eos LB 2 buckets via: "
7103 "label 99 over 10.10.10.1, "
7104 "adj over 10.10.11.2");
7106 FIB_TEST((FIB_NODE_INDEX_INVALID ==
7107 mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)),
7108 "No more MPLS FIB entries => table removed");
7111 * add another via-entry for the recursive
7113 fib_prefix_t pfx_1_1_1_2_s_32 = {
7115 .fp_proto = FIB_PROTOCOL_IP4,
7117 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
7120 fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = {
7121 .type = FT_LB_LABEL_O_ADJ,
7123 .adj = ai_mpls_10_10_10_1,
7128 fib_mpls_label_t *l101 = NULL, fml101 = {
7131 vec_add1(l101, fml101);
7133 fei = fib_table_entry_update_one_path(fib_index,
7136 FIB_ENTRY_FLAG_NONE,
7139 tm->hw[0]->sw_if_index,
7140 ~0, // invalid fib index
7143 FIB_ROUTE_PATH_FLAG_NONE);
7145 FIB_TEST(!fib_test_validate_entry(fei,
7146 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7148 &l101_eos_o_10_10_10_1),
7149 "1.1.1.2/32 LB 1 buckets via: "
7150 "label 101 over 10.10.10.1");
7152 dpo_id_t non_eos_1_1_1_2 = DPO_INVALID;
7153 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7155 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7157 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7159 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7162 fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = {
7163 .type = FT_LB_LABEL_O_LB,
7165 .lb = non_eos_1_1_1_2.dpoi_index,
7170 fib_mpls_label_t *l1601 = NULL, fml1601 = {
7173 vec_add1(l1601, fml1601);
7175 l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index;
7177 fei = fib_table_entry_path_add(fib_index,
7180 FIB_ENTRY_FLAG_NONE,
7182 &pfx_1_1_1_2_s_32.fp_addr,
7187 FIB_ROUTE_PATH_FLAG_NONE);
7189 FIB_TEST(!fib_test_validate_entry(fei,
7190 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7192 &l1600_eos_o_1_1_1_1,
7193 &l1601_eos_o_1_1_1_2),
7194 "2.2.2.2/32 LB 2 buckets via: "
7195 "label 1600 via 1.1,1.1, "
7196 "label 16001 via 1.1.1.2");
7199 * update the via-entry so it no longer has an imp-null path.
7200 * the LB for the recursive can use an imp-null
7203 vec_add1(l_imp_null, fml_imp_null);
7205 fei = fib_table_entry_update_one_path(fib_index,
7208 FIB_ENTRY_FLAG_NONE,
7211 tm->hw[1]->sw_if_index,
7212 ~0, // invalid fib index
7215 FIB_ROUTE_PATH_FLAG_NONE);
7217 FIB_TEST(!fib_test_validate_entry(fei,
7218 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7221 "1.1.1.2/32 LB 1 buckets via: "
7224 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7225 FIB_TEST(!fib_test_validate_entry(fei,
7226 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7228 &l1600_eos_o_1_1_1_1,
7229 &l1601_eos_o_1_1_1_2),
7230 "2.2.2.2/32 LB 2 buckets via: "
7231 "label 1600 via 1.1,1.1, "
7232 "label 16001 via 1.1.1.2");
7235 * update the via-entry so it no longer has labelled paths.
7236 * the LB for the recursive should exclue this via form its LB
7238 fei = fib_table_entry_update_one_path(fib_index,
7241 FIB_ENTRY_FLAG_NONE,
7244 tm->hw[1]->sw_if_index,
7245 ~0, // invalid fib index
7248 FIB_ROUTE_PATH_FLAG_NONE);
7250 FIB_TEST(!fib_test_validate_entry(fei,
7251 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7254 "1.1.1.2/32 LB 1 buckets via: "
7257 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7258 FIB_TEST(!fib_test_validate_entry(fei,
7259 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7261 &l1600_eos_o_1_1_1_1),
7262 "2.2.2.2/32 LB 1 buckets via: "
7263 "label 1600 via 1.1,1.1");
7265 dpo_reset(&non_eos_1_1_1_1);
7266 dpo_reset(&non_eos_1_1_1_2);
7269 * Add a recursive with no out-labels. We expect to use the IP of the via
7271 fib_prefix_t pfx_2_2_2_3_s_32 = {
7273 .fp_proto = FIB_PROTOCOL_IP4,
7275 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
7278 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
7280 fib_table_entry_update_one_path(fib_index,
7283 FIB_ENTRY_FLAG_NONE,
7285 &pfx_1_1_1_1_s_32.fp_addr,
7290 FIB_ROUTE_PATH_FLAG_NONE);
7292 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7294 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7297 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
7300 .lb = ip_1_1_1_1.dpoi_index,
7304 fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
7305 FIB_TEST(!fib_test_validate_entry(fei,
7306 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7309 "2.2.2.2.3/32 LB 1 buckets via: "
7313 * Add a recursive with an imp-null out-label.
7314 * We expect to use the IP of the via
7316 fib_prefix_t pfx_2_2_2_4_s_32 = {
7318 .fp_proto = FIB_PROTOCOL_IP4,
7320 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
7324 fib_table_entry_update_one_path(fib_index,
7327 FIB_ENTRY_FLAG_NONE,
7329 &pfx_1_1_1_1_s_32.fp_addr,
7334 FIB_ROUTE_PATH_FLAG_NONE);
7336 fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
7337 FIB_TEST(!fib_test_validate_entry(fei,
7338 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7341 "2.2.2.2.4/32 LB 1 buckets via: "
7344 dpo_reset(&ip_1_1_1_1);
7347 * Create an entry with a deep label stack
7349 fib_prefix_t pfx_2_2_5_5_s_32 = {
7351 .fp_proto = FIB_PROTOCOL_IP4,
7353 .ip4.as_u32 = clib_host_to_net_u32(0x02020505),
7356 fib_test_lb_bucket_t ls_eos_o_10_10_10_1 = {
7357 .type = FT_LB_LABEL_STACK_O_ADJ,
7358 .label_stack_o_adj = {
7359 .adj = ai_mpls_10_10_11_1,
7360 .label_stack_size = 8,
7362 200, 201, 202, 203, 204, 205, 206, 207
7367 fib_mpls_label_t *label_stack = NULL;
7368 vec_validate(label_stack, 7);
7369 for (ii = 0; ii < 8; ii++)
7371 label_stack[ii].fml_value = ii + 200;
7374 fei = fib_table_entry_update_one_path(fib_index,
7377 FIB_ENTRY_FLAG_NONE,
7380 tm->hw[1]->sw_if_index,
7381 ~0, // invalid fib index
7384 FIB_ROUTE_PATH_FLAG_NONE);
7386 FIB_TEST(!fib_test_validate_entry(fei,
7387 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7389 &ls_eos_o_10_10_10_1),
7390 "2.2.5.5/32 LB 1 buckets via: "
7392 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
7395 * A prefix with outgoing labels. We'll RR source a /32 it covers
7396 * and test that the RR source picks up the out-going labels
7398 fib_prefix_t pfx_100_s_8 = {
7400 .fp_proto = FIB_PROTOCOL_IP4,
7402 .ip4.as_u32 = clib_host_to_net_u32(0x64000000),
7405 fib_test_lb_bucket_t l_100_eos_o_10_10_10_1 = {
7406 .type = FT_LB_LABEL_O_ADJ,
7408 .adj = ai_mpls_10_10_11_1,
7413 fib_mpls_label_t *l1602 = NULL, fml1602 = {
7416 vec_add1(l1602, fml1602);
7417 fei = fib_table_entry_update_one_path(fib_index,
7420 FIB_ENTRY_FLAG_NONE,
7423 tm->hw[1]->sw_if_index,
7424 ~0, // invalid fib index
7427 FIB_ROUTE_PATH_FLAG_NONE);
7429 FIB_TEST(!fib_test_validate_entry(fei,
7430 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7432 &l_100_eos_o_10_10_10_1),
7433 "100.0.0.0/8 LB 1 buckets via: lbl 101 "
7436 fib_prefix_t pfx_100_1_1_1_s_32 = {
7438 .fp_proto = FIB_PROTOCOL_IP4,
7440 .ip4.as_u32 = clib_host_to_net_u32(0x64010101),
7444 fei = fib_table_entry_special_add(fib_index,
7445 &pfx_100_1_1_1_s_32,
7447 FIB_ENTRY_FLAG_NONE);
7449 FIB_TEST(!fib_test_validate_entry(fei,
7450 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7452 &l_100_eos_o_10_10_10_1),
7453 "100.1.1.1/32 LB 1 buckets via: "
7456 fib_table_entry_delete(fib_index,
7459 fib_table_entry_delete_index(fei, FIB_SOURCE_RR);
7464 fib_table_entry_delete(fib_index,
7468 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7469 FIB_TEST(!fib_test_validate_entry(fei,
7470 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7472 &l1600_eos_o_1_1_1_1),
7473 "2.2.2.2/32 LB 1 buckets via: "
7474 "label 1600 via 1.1,1.1");
7476 fib_table_entry_delete(fib_index,
7480 FIB_TEST(!fib_test_validate_entry(fei,
7481 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7484 "2.2.2.2/32 LB 1 buckets via: DROP");
7486 fib_table_entry_delete(fib_index,
7489 fib_table_entry_delete(fib_index,
7492 fib_table_entry_delete(fib_index,
7496 adj_unlock(ai_mpls_10_10_10_1);
7497 adj_unlock(ai_mpls_10_10_11_2);
7498 adj_unlock(ai_v4_10_10_11_1);
7499 adj_unlock(ai_v4_10_10_11_2);
7500 adj_unlock(ai_mpls_10_10_11_1);
7502 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
7505 local0_pfx.fp_len = 32;
7506 fib_table_entry_delete(fib_index,
7508 FIB_SOURCE_INTERFACE);
7509 local0_pfx.fp_len = 24;
7510 fib_table_entry_delete(fib_index,
7512 FIB_SOURCE_INTERFACE);
7513 local1_pfx.fp_len = 32;
7514 fib_table_entry_delete(fib_index,
7516 FIB_SOURCE_INTERFACE);
7517 local1_pfx.fp_len = 24;
7518 fib_table_entry_delete(fib_index,
7520 FIB_SOURCE_INTERFACE);
7523 * +1 for the drop LB in the MPLS tables.
7525 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
7526 "Load-balance resources freed %d of %d",
7527 lb_count+1, pool_elts(load_balance_pool));
7532 #define N_TEST_CHILDREN 4
7533 #define PARENT_INDEX 0
7535 typedef struct fib_node_test_t_
7540 fib_node_back_walk_ctx_t *ctxs;
7544 static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1];
7546 #define PARENT() (&fib_test_nodes[PARENT_INDEX].node)
7548 #define FOR_EACH_TEST_CHILD(_tc) \
7549 for (ii = 1, (_tc) = &fib_test_nodes[1]; \
7550 ii < N_TEST_CHILDREN+1; \
7551 ii++, (_tc) = &fib_test_nodes[ii])
7554 fib_test_child_get_node (fib_node_index_t index)
7556 return (&fib_test_nodes[index].node);
7559 static int fib_test_walk_spawns_walks;
7561 static fib_node_back_walk_rc_t
7562 fib_test_child_back_walk_notify (fib_node_t *node,
7563 fib_node_back_walk_ctx_t *ctx)
7565 fib_node_test_t *tc = (fib_node_test_t*) node;
7567 vec_add1(tc->ctxs, *ctx);
7569 if (1 == fib_test_walk_spawns_walks)
7570 fib_walk_sync(FIB_NODE_TYPE_TEST, tc->index, ctx);
7571 if (2 == fib_test_walk_spawns_walks)
7572 fib_walk_async(FIB_NODE_TYPE_TEST, tc->index,
7573 FIB_WALK_PRIORITY_HIGH, ctx);
7575 return (FIB_NODE_BACK_WALK_CONTINUE);
7579 fib_test_child_last_lock_gone (fib_node_t *node)
7581 fib_node_test_t *tc = (fib_node_test_t *)node;
7587 * The FIB walk's graph node virtual function table
7589 static const fib_node_vft_t fib_test_child_vft = {
7590 .fnv_get = fib_test_child_get_node,
7591 .fnv_last_lock = fib_test_child_last_lock_gone,
7592 .fnv_back_walk = fib_test_child_back_walk_notify,
7596 * the function (that should have been static but isn't so I can do this)
7597 * that processes the walk from the async queue,
7599 f64 fib_walk_process_queues(vlib_main_t * vm,
7601 u32 fib_walk_queue_get_size(fib_walk_priority_t prio);
7604 fib_test_walk (void)
7606 fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {};
7607 fib_node_test_t *tc;
7612 vm = vlib_get_main();
7613 fib_node_register_type(FIB_NODE_TYPE_TEST, &fib_test_child_vft);
7616 * init a fake node on which we will add children
7618 fib_node_init(&fib_test_nodes[PARENT_INDEX].node,
7619 FIB_NODE_TYPE_TEST);
7621 FOR_EACH_TEST_CHILD(tc)
7623 fib_node_init(&tc->node, FIB_NODE_TYPE_TEST);
7624 fib_node_lock(&tc->node);
7627 tc->sibling = fib_node_child_add(FIB_NODE_TYPE_TEST,
7629 FIB_NODE_TYPE_TEST, ii);
7633 * enqueue a walk across the parents children.
7635 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7637 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7638 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7639 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7640 "Parent has %d children pre-walk",
7641 fib_node_list_get_size(PARENT()->fn_children));
7644 * give the walk a large amount of time so it gets to the end
7646 fib_walk_process_queues(vm, 1);
7648 FOR_EACH_TEST_CHILD(tc)
7650 FIB_TEST(1 == vec_len(tc->ctxs),
7651 "%d child visitsed %d times",
7652 ii, vec_len(tc->ctxs));
7655 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7656 "Queue is empty post walk");
7657 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7658 "Parent has %d children post walk",
7659 fib_node_list_get_size(PARENT()->fn_children));
7662 * walk again. should be no increase in the number of visits, since
7663 * the walk will have terminated.
7665 fib_walk_process_queues(vm, 1);
7667 FOR_EACH_TEST_CHILD(tc)
7669 FIB_TEST(0 == vec_len(tc->ctxs),
7670 "%d child visitsed %d times",
7671 ii, vec_len(tc->ctxs));
7675 * schedule a low and hig priority walk. expect the high to be performed
7677 * schedule the high prio walk first so that it is further from the head
7678 * of the dependency list. that way it won't merge with the low one.
7680 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7681 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7683 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7684 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7685 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7686 FIB_WALK_PRIORITY_LOW, &low_ctx);
7688 fib_walk_process_queues(vm, 1);
7690 FOR_EACH_TEST_CHILD(tc)
7692 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7693 "%d child visitsed by high prio walk", ii);
7694 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7695 "%d child visitsed by low prio walk", ii);
7698 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7699 "Queue is empty post prio walk");
7700 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7701 "Parent has %d children post prio walk",
7702 fib_node_list_get_size(PARENT()->fn_children));
7705 * schedule 2 walks of the same priority that can be megred.
7706 * expect that each child is thus visited only once.
7708 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7709 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7711 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7712 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7713 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7714 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7716 fib_walk_process_queues(vm, 1);
7718 FOR_EACH_TEST_CHILD(tc)
7720 FIB_TEST(1 == vec_len(tc->ctxs),
7721 "%d child visitsed %d times during merge walk",
7722 ii, vec_len(tc->ctxs));
7725 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7726 "Queue is empty post merge walk");
7727 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7728 "Parent has %d children post merge walk",
7729 fib_node_list_get_size(PARENT()->fn_children));
7732 * schedule 2 walks of the same priority that cannot be megred.
7733 * expect that each child is thus visited twice and in the order
7734 * in which the walks were scheduled.
7736 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7737 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7739 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7740 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7741 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7742 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7744 fib_walk_process_queues(vm, 1);
7746 FOR_EACH_TEST_CHILD(tc)
7748 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7749 "%d child visitsed by high prio walk", ii);
7750 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7751 "%d child visitsed by low prio walk", ii);
7754 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7755 "Queue is empty post no-merge walk");
7756 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7757 "Parent has %d children post no-merge walk",
7758 fib_node_list_get_size(PARENT()->fn_children));
7761 * schedule a walk that makes one one child progress.
7762 * we do this by giving the queue draining process zero
7763 * time quanta. it's a do..while loop, so it does something.
7765 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7767 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7768 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7769 fib_walk_process_queues(vm, 0);
7771 FOR_EACH_TEST_CHILD(tc)
7773 if (ii == N_TEST_CHILDREN)
7775 FIB_TEST(1 == vec_len(tc->ctxs),
7776 "%d child visitsed %d times in zero quanta walk",
7777 ii, vec_len(tc->ctxs));
7781 FIB_TEST(0 == vec_len(tc->ctxs),
7782 "%d child visitsed %d times in 0 quanta walk",
7783 ii, vec_len(tc->ctxs));
7786 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7787 "Queue is not empty post zero quanta walk");
7788 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7789 "Parent has %d children post zero qunta walk",
7790 fib_node_list_get_size(PARENT()->fn_children));
7795 fib_walk_process_queues(vm, 0);
7797 FOR_EACH_TEST_CHILD(tc)
7799 if (ii >= N_TEST_CHILDREN-1)
7801 FIB_TEST(1 == vec_len(tc->ctxs),
7802 "%d child visitsed %d times in 2nd zero quanta walk",
7803 ii, vec_len(tc->ctxs));
7807 FIB_TEST(0 == vec_len(tc->ctxs),
7808 "%d child visitsed %d times in 2nd 0 quanta walk",
7809 ii, vec_len(tc->ctxs));
7812 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7813 "Queue is not empty post zero quanta walk");
7814 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7815 "Parent has %d children post zero qunta walk",
7816 fib_node_list_get_size(PARENT()->fn_children));
7819 * schedule another walk that will catch-up and merge.
7821 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7822 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7823 fib_walk_process_queues(vm, 1);
7825 FOR_EACH_TEST_CHILD(tc)
7827 if (ii >= N_TEST_CHILDREN-1)
7829 FIB_TEST(2 == vec_len(tc->ctxs),
7830 "%d child visitsed %d times in 2nd zero quanta merge walk",
7831 ii, vec_len(tc->ctxs));
7836 FIB_TEST(1 == vec_len(tc->ctxs),
7837 "%d child visitsed %d times in 2nd 0 quanta merge walk",
7838 ii, vec_len(tc->ctxs));
7842 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7843 "Queue is not empty post 2nd zero quanta merge walk");
7844 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7845 "Parent has %d children post 2nd zero qunta merge walk",
7846 fib_node_list_get_size(PARENT()->fn_children));
7849 * park a async walk in the middle of the list, then have an sync walk catch
7850 * it. same expectations as async catches async.
7852 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7854 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7855 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7857 fib_walk_process_queues(vm, 0);
7858 fib_walk_process_queues(vm, 0);
7860 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7862 FOR_EACH_TEST_CHILD(tc)
7864 if (ii >= N_TEST_CHILDREN-1)
7866 FIB_TEST(2 == vec_len(tc->ctxs),
7867 "%d child visitsed %d times in sync catches async walk",
7868 ii, vec_len(tc->ctxs));
7873 FIB_TEST(1 == vec_len(tc->ctxs),
7874 "%d child visitsed %d times in sync catches async walk",
7875 ii, vec_len(tc->ctxs));
7879 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7880 "Queue is not empty post 2nd zero quanta merge walk");
7881 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7882 "Parent has %d children post 2nd zero qunta merge walk",
7883 fib_node_list_get_size(PARENT()->fn_children));
7886 * make the parent a child of one of its children, thus inducing a routing loop.
7888 fib_test_nodes[PARENT_INDEX].sibling =
7889 fib_node_child_add(FIB_NODE_TYPE_TEST,
7890 1, // the first child
7895 * execute a sync walk from the parent. each child visited spawns more sync
7896 * walks. we expect the walk to terminate.
7898 fib_test_walk_spawns_walks = 1;
7900 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7902 FOR_EACH_TEST_CHILD(tc)
7905 * child 1 - which is last in the list - has the loop.
7906 * the other children a re thus visitsed first. the we meet
7907 * child 1. we go round the loop again, visting the other children.
7908 * then we meet the walk in the dep list and bail. child 1 is not visitsed
7913 FIB_TEST(1 == vec_len(tc->ctxs),
7914 "child %d visitsed %d times during looped sync walk",
7915 ii, vec_len(tc->ctxs));
7919 FIB_TEST(2 == vec_len(tc->ctxs),
7920 "child %d visitsed %d times during looped sync walk",
7921 ii, vec_len(tc->ctxs));
7925 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7926 "Parent has %d children post sync loop walk",
7927 fib_node_list_get_size(PARENT()->fn_children));
7930 * the walk doesn't reach the max depth because the infra knows that sync
7931 * meets sync implies a loop and bails early.
7933 FIB_TEST(high_ctx.fnbw_depth == 9,
7934 "Walk context depth %d post sync loop walk",
7935 high_ctx.fnbw_depth);
7938 * execute an async walk of the graph loop, with each child spawns sync walks
7940 high_ctx.fnbw_depth = 0;
7941 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7942 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7944 fib_walk_process_queues(vm, 1);
7946 FOR_EACH_TEST_CHILD(tc)
7949 * we don't really care how many times the children are visited, as long as
7950 * it is more than once.
7952 FIB_TEST(1 <= vec_len(tc->ctxs),
7953 "child %d visitsed %d times during looped aync spawns sync walk",
7954 ii, vec_len(tc->ctxs));
7959 * execute an async walk of the graph loop, with each child spawns async walks
7961 fib_test_walk_spawns_walks = 2;
7962 high_ctx.fnbw_depth = 0;
7963 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7964 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7966 fib_walk_process_queues(vm, 1);
7968 FOR_EACH_TEST_CHILD(tc)
7971 * we don't really care how many times the children are visited, as long as
7972 * it is more than once.
7974 FIB_TEST(1 <= vec_len(tc->ctxs),
7975 "child %d visitsed %d times during looped async spawns async walk",
7976 ii, vec_len(tc->ctxs));
7981 fib_node_child_remove(FIB_NODE_TYPE_TEST,
7982 1, // the first child
7983 fib_test_nodes[PARENT_INDEX].sibling);
7988 FOR_EACH_TEST_CHILD(tc)
7990 fib_node_child_remove(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7992 fib_node_deinit(&tc->node);
7993 fib_node_unlock(&tc->node);
7995 fib_node_deinit(PARENT());
7998 * The parent will be destroyed when the last lock on it goes.
7999 * this test ensures all the walk objects are unlocking it.
8001 FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed),
8002 "Parent was destroyed");
8008 * declaration of the otherwise static callback functions
8010 void fib_bfd_notify (bfd_listen_event_e event,
8011 const bfd_session_t *session);
8012 void adj_bfd_notify (bfd_listen_event_e event,
8013 const bfd_session_t *session);
8016 * Test BFD session interaction with FIB
8021 fib_node_index_t fei;
8026 /* via 10.10.10.1 */
8027 ip46_address_t nh_10_10_10_1 = {
8028 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
8030 /* via 10.10.10.2 */
8031 ip46_address_t nh_10_10_10_2 = {
8032 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
8034 /* via 10.10.10.10 */
8035 ip46_address_t nh_10_10_10_10 = {
8036 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
8038 n_feis = fib_entry_pool_size();
8043 * add interface routes. we'll assume this works. it's tested elsewhere
8045 fib_prefix_t pfx_10_10_10_10_s_24 = {
8047 .fp_proto = FIB_PROTOCOL_IP4,
8048 .fp_addr = nh_10_10_10_10,
8051 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_24,
8052 FIB_SOURCE_INTERFACE,
8053 (FIB_ENTRY_FLAG_CONNECTED |
8054 FIB_ENTRY_FLAG_ATTACHED),
8057 tm->hw[0]->sw_if_index,
8058 ~0, // invalid fib index
8061 FIB_ROUTE_PATH_FLAG_NONE);
8063 fib_prefix_t pfx_10_10_10_10_s_32 = {
8065 .fp_proto = FIB_PROTOCOL_IP4,
8066 .fp_addr = nh_10_10_10_10,
8068 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_32,
8069 FIB_SOURCE_INTERFACE,
8070 (FIB_ENTRY_FLAG_CONNECTED |
8071 FIB_ENTRY_FLAG_LOCAL),
8074 tm->hw[0]->sw_if_index,
8075 ~0, // invalid fib index
8078 FIB_ROUTE_PATH_FLAG_NONE);
8081 * A BFD session via a neighbour we do not yet know
8083 bfd_session_t bfd_10_10_10_1 = {
8087 .peer_addr = nh_10_10_10_1,
8090 .hop_type = BFD_HOP_TYPE_MULTI,
8091 .local_state = BFD_STATE_init,
8094 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8097 * A new entry will be created that forwards via the adj
8099 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8102 tm->hw[0]->sw_if_index);
8103 fib_prefix_t pfx_10_10_10_1_s_32 = {
8104 .fp_addr = nh_10_10_10_1,
8106 .fp_proto = FIB_PROTOCOL_IP4,
8108 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
8111 .adj = ai_10_10_10_1,
8115 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
8116 FIB_TEST(!fib_test_validate_entry(fei,
8117 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8120 "BFD sourced %U via %U",
8121 format_fib_prefix, &pfx_10_10_10_1_s_32,
8122 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
8125 * Delete the BFD session. Expect the fib_entry to be removed
8127 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8129 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
8130 FIB_TEST(FIB_NODE_INDEX_INVALID == fei,
8131 "BFD sourced %U removed",
8132 format_fib_prefix, &pfx_10_10_10_1_s_32);
8135 * Add the BFD source back
8137 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8140 * source the entry via the ADJ fib
8142 fei = fib_table_entry_path_add(0,
8143 &pfx_10_10_10_1_s_32,
8145 FIB_ENTRY_FLAG_ATTACHED,
8148 tm->hw[0]->sw_if_index,
8149 ~0, // invalid fib index
8152 FIB_ROUTE_PATH_FLAG_NONE);
8155 * Delete the BFD session. Expect the fib_entry to remain
8157 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8159 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
8160 FIB_TEST(!fib_test_validate_entry(fei,
8161 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8164 "BFD sourced %U remains via %U",
8165 format_fib_prefix, &pfx_10_10_10_1_s_32,
8166 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
8169 * Add the BFD source back
8171 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8174 * Create another ADJ FIB
8176 fib_prefix_t pfx_10_10_10_2_s_32 = {
8177 .fp_addr = nh_10_10_10_2,
8179 .fp_proto = FIB_PROTOCOL_IP4,
8181 fib_table_entry_path_add(0,
8182 &pfx_10_10_10_2_s_32,
8184 FIB_ENTRY_FLAG_ATTACHED,
8187 tm->hw[0]->sw_if_index,
8188 ~0, // invalid fib index
8191 FIB_ROUTE_PATH_FLAG_NONE);
8193 * A BFD session for the new ADJ FIB
8195 bfd_session_t bfd_10_10_10_2 = {
8199 .peer_addr = nh_10_10_10_2,
8202 .hop_type = BFD_HOP_TYPE_MULTI,
8203 .local_state = BFD_STATE_init,
8206 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_2);
8209 * remove the adj-fib source whilst the session is present
8212 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
8213 fib_table_entry_path_add(0,
8214 &pfx_10_10_10_2_s_32,
8216 FIB_ENTRY_FLAG_ATTACHED,
8219 tm->hw[0]->sw_if_index,
8220 ~0, // invalid fib index
8223 FIB_ROUTE_PATH_FLAG_NONE);
8226 * Before adding a recursive via the BFD tracked ADJ-FIBs,
8227 * bring one of the sessions UP, leave the other down
8229 bfd_10_10_10_1.local_state = BFD_STATE_up;
8230 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8231 bfd_10_10_10_2.local_state = BFD_STATE_down;
8232 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8235 * A recursive prefix via both of the ADJ FIBs
8237 fib_prefix_t pfx_200_0_0_0_s_24 = {
8238 .fp_proto = FIB_PROTOCOL_IP4,
8241 .ip4.as_u32 = clib_host_to_net_u32(0xc8000000),
8244 const dpo_id_t *dpo_10_10_10_1, *dpo_10_10_10_2;
8247 fib_entry_contribute_ip_forwarding(
8248 fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32));
8250 fib_entry_contribute_ip_forwarding(
8251 fib_table_lookup_exact_match(0, &pfx_10_10_10_2_s_32));
8253 fib_test_lb_bucket_t lb_o_10_10_10_1 = {
8256 .lb = dpo_10_10_10_1->dpoi_index,
8259 fib_test_lb_bucket_t lb_o_10_10_10_2 = {
8262 .lb = dpo_10_10_10_2->dpoi_index,
8267 * A prefix via the adj-fib that is BFD down => DROP
8269 fei = fib_table_entry_path_add(0,
8270 &pfx_200_0_0_0_s_24,
8272 FIB_ENTRY_FLAG_NONE,
8276 0, // default fib index
8279 FIB_ROUTE_PATH_FLAG_NONE);
8280 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8281 "%U resolves via drop",
8282 format_fib_prefix, &pfx_200_0_0_0_s_24);
8285 * add a path via the UP BFD adj-fib.
8286 * we expect that the DOWN BFD ADJ FIB is not used.
8288 fei = fib_table_entry_path_add(0,
8289 &pfx_200_0_0_0_s_24,
8291 FIB_ENTRY_FLAG_NONE,
8295 0, // default fib index
8298 FIB_ROUTE_PATH_FLAG_NONE);
8300 FIB_TEST(!fib_test_validate_entry(fei,
8301 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8304 "Recursive %U only UP BFD adj-fibs",
8305 format_fib_prefix, &pfx_200_0_0_0_s_24);
8308 * Send a BFD state change to UP - both sessions are now up
8309 * the recursive prefix should LB over both
8311 bfd_10_10_10_2.local_state = BFD_STATE_up;
8312 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8315 FIB_TEST(!fib_test_validate_entry(fei,
8316 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8320 "Recursive %U via both UP BFD adj-fibs",
8321 format_fib_prefix, &pfx_200_0_0_0_s_24);
8324 * Send a BFD state change to DOWN
8325 * the recursive prefix should exclude the down
8327 bfd_10_10_10_2.local_state = BFD_STATE_down;
8328 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8331 FIB_TEST(!fib_test_validate_entry(fei,
8332 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8335 "Recursive %U via only UP",
8336 format_fib_prefix, &pfx_200_0_0_0_s_24);
8339 * Delete the BFD session while it is in the DOWN state.
8340 * FIB should consider the entry's state as back up
8342 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_2);
8344 FIB_TEST(!fib_test_validate_entry(fei,
8345 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8349 "Recursive %U via both UP BFD adj-fibs post down session delete",
8350 format_fib_prefix, &pfx_200_0_0_0_s_24);
8353 * Delete the BFD other session while it is in the UP state.
8355 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8357 FIB_TEST(!fib_test_validate_entry(fei,
8358 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8362 "Recursive %U via both UP BFD adj-fibs post up session delete",
8363 format_fib_prefix, &pfx_200_0_0_0_s_24);
8368 fib_table_entry_delete(0, &pfx_200_0_0_0_s_24, FIB_SOURCE_API);
8369 fib_table_entry_delete(0, &pfx_10_10_10_1_s_32, FIB_SOURCE_ADJ);
8370 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
8372 fib_table_entry_delete(0, &pfx_10_10_10_10_s_32, FIB_SOURCE_INTERFACE);
8373 fib_table_entry_delete(0, &pfx_10_10_10_10_s_24, FIB_SOURCE_INTERFACE);
8375 adj_unlock(ai_10_10_10_1);
8377 * test no-one left behind
8379 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8380 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8383 * Single-hop BFD tests
8385 bfd_10_10_10_1.hop_type = BFD_HOP_TYPE_SINGLE;
8386 bfd_10_10_10_1.udp.key.sw_if_index = tm->hw[0]->sw_if_index;
8388 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8390 ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8393 tm->hw[0]->sw_if_index);
8395 * whilst the BFD session is not signalled, the adj is up
8397 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on uninit session");
8400 * bring the BFD session up
8402 bfd_10_10_10_1.local_state = BFD_STATE_up;
8403 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8404 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on UP session");
8407 * bring the BFD session down
8409 bfd_10_10_10_1.local_state = BFD_STATE_down;
8410 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8411 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on DOWN session");
8414 * add an attached next hop FIB entry via the down adj
8416 fib_prefix_t pfx_5_5_5_5_s_32 = {
8419 .as_u32 = clib_host_to_net_u32(0x05050505),
8423 .fp_proto = FIB_PROTOCOL_IP4,
8426 fei = fib_table_entry_path_add(0,
8429 FIB_ENTRY_FLAG_NONE,
8432 tm->hw[0]->sw_if_index,
8433 ~0, // invalid fib index
8436 FIB_ROUTE_PATH_FLAG_NONE);
8437 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8438 "%U resolves via drop",
8439 format_fib_prefix, &pfx_5_5_5_5_s_32);
8442 * Add a path via an ADJ that is up
8444 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8447 tm->hw[0]->sw_if_index);
8449 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
8452 .adj = ai_10_10_10_2,
8455 adj_o_10_10_10_1.adj.adj = ai_10_10_10_1;
8457 fei = fib_table_entry_path_add(0,
8460 FIB_ENTRY_FLAG_NONE,
8463 tm->hw[0]->sw_if_index,
8464 ~0, // invalid fib index
8467 FIB_ROUTE_PATH_FLAG_NONE);
8469 FIB_TEST(!fib_test_validate_entry(fei,
8470 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8473 "BFD sourced %U via %U",
8474 format_fib_prefix, &pfx_5_5_5_5_s_32,
8475 format_ip_adjacency, ai_10_10_10_2, FORMAT_IP_ADJACENCY_NONE);
8478 * Bring up the down session - should now LB
8480 bfd_10_10_10_1.local_state = BFD_STATE_up;
8481 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8482 FIB_TEST(!fib_test_validate_entry(fei,
8483 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8487 "BFD sourced %U via noth adjs",
8488 format_fib_prefix, &pfx_5_5_5_5_s_32);
8491 * remove the BFD session state from the adj
8493 adj_bfd_notify(BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8498 fib_table_entry_delete(0, &pfx_5_5_5_5_s_32, FIB_SOURCE_CLI);
8499 adj_unlock(ai_10_10_10_1);
8500 adj_unlock(ai_10_10_10_2);
8503 * test no-one left behind
8505 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8506 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8514 const mpls_label_t deag_label = 50;
8515 adj_index_t ai_mpls_10_10_10_1;
8516 dpo_id_t dpo = DPO_INVALID;
8517 const u32 lfib_index = 0;
8518 const u32 fib_index = 0;
8519 const dpo_id_t *dpo1;
8520 fib_node_index_t lfe;
8527 lb_count = pool_elts(load_balance_pool);
8529 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
8533 * MPLS enable an interface so we get the MPLS table created
8535 mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL);
8536 mpls_sw_interface_enable_disable(&mpls_main,
8537 tm->hw[0]->sw_if_index,
8540 ip46_address_t nh_10_10_10_1 = {
8541 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
8543 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8546 tm->hw[0]->sw_if_index);
8549 * Test the specials stack properly.
8551 fib_prefix_t exp_null_v6_pfx = {
8552 .fp_proto = FIB_PROTOCOL_MPLS,
8554 .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8555 .fp_payload_proto = DPO_PROTO_IP6,
8557 lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx);
8558 FIB_TEST((FIB_NODE_INDEX_INVALID != lfe),
8560 format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8561 format_mpls_eos_bit, MPLS_EOS);
8562 fib_entry_contribute_forwarding(lfe,
8563 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8565 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8566 lkd = lookup_dpo_get(dpo1->dpoi_index);
8568 FIB_TEST((fib_index == lkd->lkd_fib_index),
8569 "%U/%U is deag in %d %U",
8570 format_mpls_unicast_label, deag_label,
8571 format_mpls_eos_bit, MPLS_EOS,
8573 format_dpo_id, &dpo, 0);
8574 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8575 "%U/%U is dst deag",
8576 format_mpls_unicast_label, deag_label,
8577 format_mpls_eos_bit, MPLS_EOS);
8578 FIB_TEST((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table),
8579 "%U/%U is lookup in interface's table",
8580 format_mpls_unicast_label, deag_label,
8581 format_mpls_eos_bit, MPLS_EOS);
8582 FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto),
8583 "%U/%U is %U dst deag",
8584 format_mpls_unicast_label, deag_label,
8585 format_mpls_eos_bit, MPLS_EOS,
8586 format_dpo_proto, lkd->lkd_proto);
8589 * A route deag route for EOS
8591 fib_prefix_t pfx = {
8592 .fp_proto = FIB_PROTOCOL_MPLS,
8594 .fp_label = deag_label,
8595 .fp_payload_proto = DPO_PROTO_IP4,
8597 mpls_disp_dpo_t *mdd;
8598 lfe = fib_table_entry_path_add(lfib_index,
8601 FIB_ENTRY_FLAG_NONE,
8608 FIB_ROUTE_PATH_FLAG_NONE);
8610 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8612 format_mpls_unicast_label, deag_label,
8613 format_mpls_eos_bit, MPLS_EOS);
8615 fib_entry_contribute_forwarding(lfe,
8616 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8618 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8619 mdd = mpls_disp_dpo_get(dpo1->dpoi_index);
8621 FIB_TEST((FIB_MPLS_LSP_MODE_PIPE == mdd->mdd_mode),
8622 "%U/%U disp is pipe mode",
8623 format_mpls_unicast_label, deag_label,
8624 format_mpls_eos_bit, MPLS_EOS);
8626 lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index);
8628 FIB_TEST((fib_index == lkd->lkd_fib_index),
8629 "%U/%U is deag in %d %U",
8630 format_mpls_unicast_label, deag_label,
8631 format_mpls_eos_bit, MPLS_EOS,
8633 format_dpo_id, &dpo, 0);
8634 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8635 "%U/%U is dst deag",
8636 format_mpls_unicast_label, deag_label,
8637 format_mpls_eos_bit, MPLS_EOS);
8638 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8639 "%U/%U is %U dst deag",
8640 format_mpls_unicast_label, deag_label,
8641 format_mpls_eos_bit, MPLS_EOS,
8642 format_dpo_proto, lkd->lkd_proto);
8644 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8646 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8648 "%U/%U not present",
8649 format_mpls_unicast_label, deag_label,
8650 format_mpls_eos_bit, MPLS_EOS);
8654 * A route deag route for EOS with LSP mode uniform
8656 fib_mpls_label_t *l_pops = NULL, l_pop = {
8657 .fml_value = MPLS_LABEL_POP,
8658 .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM,
8660 vec_add1(l_pops, l_pop);
8661 lfe = fib_table_entry_path_add(lfib_index,
8664 FIB_ENTRY_FLAG_NONE,
8671 FIB_ROUTE_PATH_FLAG_NONE);
8673 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8675 format_mpls_unicast_label, deag_label,
8676 format_mpls_eos_bit, MPLS_EOS);
8678 fib_entry_contribute_forwarding(lfe,
8679 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8681 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8682 mdd = mpls_disp_dpo_get(dpo1->dpoi_index);
8684 FIB_TEST((FIB_MPLS_LSP_MODE_UNIFORM == mdd->mdd_mode),
8685 "%U/%U disp is uniform mode",
8686 format_mpls_unicast_label, deag_label,
8687 format_mpls_eos_bit, MPLS_EOS);
8689 lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index);
8691 FIB_TEST((fib_index == lkd->lkd_fib_index),
8692 "%U/%U is deag in %d %U",
8693 format_mpls_unicast_label, deag_label,
8694 format_mpls_eos_bit, MPLS_EOS,
8696 format_dpo_id, &dpo, 0);
8697 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8698 "%U/%U is dst deag",
8699 format_mpls_unicast_label, deag_label,
8700 format_mpls_eos_bit, MPLS_EOS);
8701 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8702 "%U/%U is %U dst deag",
8703 format_mpls_unicast_label, deag_label,
8704 format_mpls_eos_bit, MPLS_EOS,
8705 format_dpo_proto, lkd->lkd_proto);
8707 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8709 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8711 "%U/%U not present",
8712 format_mpls_unicast_label, deag_label,
8713 format_mpls_eos_bit, MPLS_EOS);
8717 * A route deag route for non-EOS
8719 pfx.fp_eos = MPLS_NON_EOS;
8720 lfe = fib_table_entry_path_add(lfib_index,
8723 FIB_ENTRY_FLAG_NONE,
8730 FIB_ROUTE_PATH_FLAG_NONE);
8732 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8734 format_mpls_unicast_label, deag_label,
8735 format_mpls_eos_bit, MPLS_NON_EOS);
8737 fib_entry_contribute_forwarding(lfe,
8738 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8740 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8741 lkd = lookup_dpo_get(dpo1->dpoi_index);
8743 FIB_TEST((fib_index == lkd->lkd_fib_index),
8744 "%U/%U is deag in %d %U",
8745 format_mpls_unicast_label, deag_label,
8746 format_mpls_eos_bit, MPLS_NON_EOS,
8748 format_dpo_id, &dpo, 0);
8749 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8750 "%U/%U is dst deag",
8751 format_mpls_unicast_label, deag_label,
8752 format_mpls_eos_bit, MPLS_NON_EOS);
8754 FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto),
8755 "%U/%U is %U dst deag",
8756 format_mpls_unicast_label, deag_label,
8757 format_mpls_eos_bit, MPLS_NON_EOS,
8758 format_dpo_proto, lkd->lkd_proto);
8760 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8762 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8764 "%U/%U not present",
8765 format_mpls_unicast_label, deag_label,
8766 format_mpls_eos_bit, MPLS_EOS);
8773 fib_prefix_t pfx_1200 = {
8775 .fp_proto = FIB_PROTOCOL_MPLS,
8777 .fp_eos = MPLS_NON_EOS,
8779 fib_test_lb_bucket_t neos_o_10_10_10_1 = {
8780 .type = FT_LB_LABEL_STACK_O_ADJ,
8781 .label_stack_o_adj = {
8782 .adj = ai_mpls_10_10_10_1,
8783 .label_stack_size = 4,
8787 .eos = MPLS_NON_EOS,
8790 dpo_id_t neos_1200 = DPO_INVALID;
8791 dpo_id_t ip_1200 = DPO_INVALID;
8792 fib_mpls_label_t *l200 = NULL;
8794 for (ii = 0; ii < 4; ii++)
8796 fib_mpls_label_t fml = {
8797 .fml_value = 200 + (ii * 100),
8799 vec_add1(l200, fml);
8802 lfe = fib_table_entry_update_one_path(fib_index,
8805 FIB_ENTRY_FLAG_NONE,
8808 tm->hw[0]->sw_if_index,
8809 ~0, // invalid fib index
8812 FIB_ROUTE_PATH_FLAG_NONE);
8814 FIB_TEST(!fib_test_validate_entry(lfe,
8815 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8817 &neos_o_10_10_10_1),
8818 "1200/0 LB 1 buckets via: "
8822 * A recursive route via the MPLS x-connect
8824 fib_prefix_t pfx_2_2_2_3_s_32 = {
8826 .fp_proto = FIB_PROTOCOL_IP4,
8828 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
8831 fib_route_path_t *rpaths = NULL, rpath = {
8832 .frp_proto = DPO_PROTO_MPLS,
8833 .frp_local_label = 1200,
8834 .frp_eos = MPLS_NON_EOS,
8835 .frp_sw_if_index = ~0, // recurive
8836 .frp_fib_index = 0, // Default MPLS fib
8838 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
8839 .frp_label_stack = NULL,
8841 vec_add1(rpaths, rpath);
8843 fib_table_entry_path_add2(fib_index,
8846 FIB_ENTRY_FLAG_NONE,
8850 * A labelled recursive route via the MPLS x-connect
8852 fib_prefix_t pfx_2_2_2_4_s_32 = {
8854 .fp_proto = FIB_PROTOCOL_IP4,
8856 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
8859 fib_mpls_label_t *l999 = NULL, fml_999 = {
8862 vec_add1(l999, fml_999);
8863 rpaths[0].frp_label_stack = l999,
8865 fib_table_entry_path_add2(fib_index,
8868 FIB_ENTRY_FLAG_NONE,
8871 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8872 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8874 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8875 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8878 fib_test_lb_bucket_t ip_o_1200 = {
8881 .lb = ip_1200.dpoi_index,
8884 fib_test_lb_bucket_t mpls_o_1200 = {
8885 .type = FT_LB_LABEL_O_LB,
8887 .lb = neos_1200.dpoi_index,
8893 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
8894 FIB_TEST(!fib_test_validate_entry(lfe,
8895 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8898 "2.2.2.2.3/32 LB 1 buckets via: label 1200 EOS");
8899 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
8900 FIB_TEST(!fib_test_validate_entry(lfe,
8901 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8904 "2.2.2.2.4/32 LB 1 buckets via: label 1200 non-EOS");
8906 fib_table_entry_delete(fib_index, &pfx_1200, FIB_SOURCE_API);
8907 fib_table_entry_delete(fib_index, &pfx_2_2_2_3_s_32, FIB_SOURCE_API);
8908 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8910 dpo_reset(&neos_1200);
8911 dpo_reset(&ip_1200);
8914 * A recursive via a label that does not exist
8916 fib_test_lb_bucket_t bucket_drop = {
8919 .adj = DPO_PROTO_IP4,
8922 fib_test_lb_bucket_t mpls_bucket_drop = {
8925 .adj = DPO_PROTO_MPLS,
8929 rpaths[0].frp_label_stack = NULL;
8930 lfe = fib_table_entry_path_add2(fib_index,
8933 FIB_ENTRY_FLAG_NONE,
8936 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8937 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8939 ip_o_1200.lb.lb = ip_1200.dpoi_index;
8941 FIB_TEST(!fib_test_validate_entry(lfe,
8942 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8945 "2.2.2.2.4/32 LB 1 buckets via: drop");
8946 lfe = fib_table_lookup(fib_index, &pfx_1200);
8947 FIB_TEST(!fib_test_validate_entry(lfe,
8948 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8951 "1200/neos LB 1 buckets via: ip4-DROP");
8952 FIB_TEST(!fib_test_validate_entry(lfe,
8953 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8956 "1200/neos LB 1 buckets via: mpls-DROP");
8958 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8960 dpo_reset(&ip_1200);
8963 * An rx-interface route.
8964 * like the tail of an mcast LSP
8966 dpo_id_t idpo = DPO_INVALID;
8968 interface_rx_dpo_add_or_lock(DPO_PROTO_IP4,
8969 tm->hw[0]->sw_if_index,
8972 fib_prefix_t pfx_2500 = {
8974 .fp_proto = FIB_PROTOCOL_MPLS,
8977 .fp_payload_proto = DPO_PROTO_IP4,
8979 fib_test_lb_bucket_t rx_intf_0 = {
8982 .adj = idpo.dpoi_index,
8986 lfe = fib_table_entry_update_one_path(fib_index,
8989 FIB_ENTRY_FLAG_NONE,
8992 tm->hw[0]->sw_if_index,
8993 ~0, // invalid fib index
8996 FIB_ROUTE_PATH_INTF_RX);
8997 FIB_TEST(!fib_test_validate_entry(lfe,
8998 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9001 "2500 rx-interface 0");
9002 fib_table_entry_delete(fib_index, &pfx_2500, FIB_SOURCE_API);
9005 * An MPLS mulicast entry
9007 fib_prefix_t pfx_3500 = {
9009 .fp_proto = FIB_PROTOCOL_MPLS,
9012 .fp_payload_proto = DPO_PROTO_IP4,
9014 fib_test_rep_bucket_t mc_0 = {
9015 .type = FT_REP_LABEL_O_ADJ,
9017 .adj = ai_mpls_10_10_10_1,
9022 fib_test_rep_bucket_t mc_intf_0 = {
9023 .type = FT_REP_INTF,
9025 .adj = idpo.dpoi_index,
9028 fib_mpls_label_t *l3300 = NULL, fml_3300 = {
9031 vec_add1(l3300, fml_3300);
9033 lfe = fib_table_entry_update_one_path(lfib_index,
9036 FIB_ENTRY_FLAG_MULTICAST,
9039 tm->hw[0]->sw_if_index,
9040 ~0, // invalid fib index
9043 FIB_ROUTE_PATH_FLAG_NONE);
9044 FIB_TEST(!fib_test_validate_entry(lfe,
9045 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9048 "3500 via replicate over 10.10.10.1");
9051 * MPLS Bud-node. Add a replication via an interface-receieve path
9053 lfe = fib_table_entry_path_add(lfib_index,
9056 FIB_ENTRY_FLAG_MULTICAST,
9059 tm->hw[0]->sw_if_index,
9060 ~0, // invalid fib index
9063 FIB_ROUTE_PATH_INTF_RX);
9064 FIB_TEST(!fib_test_validate_entry(lfe,
9065 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9069 "3500 via replicate over 10.10.10.1 and interface-rx");
9072 * Add a replication via an interface-free for-us path
9074 fib_test_rep_bucket_t mc_disp = {
9075 .type = FT_REP_DISP_MFIB_LOOKUP,
9077 .adj = idpo.dpoi_index,
9080 lfe = fib_table_entry_path_add(lfib_index,
9083 FIB_ENTRY_FLAG_MULTICAST,
9090 FIB_ROUTE_PATH_RPF_ID);
9091 FIB_TEST(!fib_test_validate_entry(lfe,
9092 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9097 "3500 via replicate over 10.10.10.1 and interface-rx");
9101 fib_table_entry_delete(fib_index, &pfx_3500, FIB_SOURCE_API);
9107 mpls_sw_interface_enable_disable(&mpls_main,
9108 tm->hw[0]->sw_if_index,
9110 mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
9112 FIB_TEST(0 == pool_elts(mpls_disp_dpo_pool),
9113 "mpls_disp_dpo resources freed %d of %d",
9114 0, pool_elts(mpls_disp_dpo_pool));
9115 FIB_TEST(lb_count == pool_elts(load_balance_pool),
9116 "Load-balance resources freed %d of %d",
9117 lb_count, pool_elts(load_balance_pool));
9118 FIB_TEST(0 == pool_elts(interface_rx_dpo_pool),
9119 "interface_rx_dpo resources freed %d of %d",
9120 0, pool_elts(interface_rx_dpo_pool));
9126 fib_test_inherit (void)
9128 fib_node_index_t fei;
9139 vec_validate(im4->fib_index_by_sw_if_index, tm->hw[2]->sw_if_index);
9140 vec_validate(im6->fib_index_by_sw_if_index, tm->hw[2]->sw_if_index);
9142 for (i = 0; i <= 2; i++)
9144 im4->fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
9145 im6->fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
9147 n_feis = fib_entry_pool_size();
9149 const ip46_address_t nh_10_10_10_1 = {
9150 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
9152 const ip46_address_t nh_10_10_10_2 = {
9153 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
9155 const ip46_address_t nh_10_10_10_3 = {
9156 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
9158 const ip46_address_t nh_10_10_10_16 = {
9159 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a10),
9161 const ip46_address_t nh_10_10_10_20 = {
9162 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a14),
9164 const ip46_address_t nh_10_10_10_21 = {
9165 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a15),
9167 const ip46_address_t nh_10_10_10_22 = {
9168 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a16),
9170 const ip46_address_t nh_10_10_10_255 = {
9171 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0aff),
9173 const ip46_address_t nh_10_10_10_0 = {
9174 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a00),
9176 const ip46_address_t nh_10_10_0_0 = {
9177 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0000),
9179 const ip46_address_t nh_11_11_11_11 = {
9180 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
9182 const ip46_address_t nh_11_11_11_0 = {
9183 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b00),
9187 * prefixes at the base of a sub-tree
9189 const fib_prefix_t pfx_10_10_10_21_s_32 = {
9191 .fp_proto = FIB_PROTOCOL_IP4,
9192 .fp_addr = nh_10_10_10_21,
9194 const fib_prefix_t pfx_10_10_10_22_s_32 = {
9196 .fp_proto = FIB_PROTOCOL_IP4,
9197 .fp_addr = nh_10_10_10_22,
9199 const fib_prefix_t pfx_10_10_10_255_s_32 = {
9201 .fp_proto = FIB_PROTOCOL_IP4,
9202 .fp_addr = nh_10_10_10_255,
9204 const u32 N_PLS = fib_path_list_pool_size();
9206 fib_table_entry_special_add(0,
9207 &pfx_10_10_10_21_s_32,
9209 FIB_ENTRY_FLAG_DROP);
9210 fib_table_entry_special_add(0,
9211 &pfx_10_10_10_22_s_32,
9213 FIB_ENTRY_FLAG_DROP);
9214 fib_table_entry_special_add(0,
9215 &pfx_10_10_10_255_s_32,
9217 FIB_ENTRY_FLAG_DROP);
9220 * source an entry that pushes its state down the sub-tree
9222 const fib_prefix_t pfx_10_10_10_16_s_28 = {
9224 .fp_proto = FIB_PROTOCOL_IP4,
9225 .fp_addr = nh_10_10_10_16,
9227 fib_table_entry_update_one_path(0,
9228 &pfx_10_10_10_16_s_28,
9230 FIB_ENTRY_FLAG_COVERED_INHERIT,
9233 tm->hw[0]->sw_if_index,
9237 FIB_ROUTE_PATH_FLAG_NONE);
9240 * this covering entry and all those below it should have
9241 * the same forwarding information.
9243 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9246 tm->hw[0]->sw_if_index);
9247 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
9250 .adj = ai_10_10_10_1,
9254 fei = fib_table_lookup(0, &pfx_10_10_10_16_s_28);
9255 FIB_TEST(!fib_test_validate_entry(fei,
9256 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9259 "%U via 10.10.10.1",
9260 format_fib_prefix, &pfx_10_10_10_16_s_28);
9261 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9262 FIB_TEST(!fib_test_validate_entry(fei,
9263 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9266 "%U via 10.10.10.1",
9267 format_fib_prefix, &pfx_10_10_10_21_s_32);
9268 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9269 FIB_TEST(!fib_test_validate_entry(fei,
9270 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9273 "%U via 10.10.10.1",
9274 format_fib_prefix, &pfx_10_10_10_22_s_32);
9275 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9276 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9277 "%U resolves via drop",
9278 format_fib_prefix, &pfx_10_10_10_255_s_32);
9281 * remove the inherting cover - covereds go back to drop
9283 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_API);
9285 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9286 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9287 "%U resolves via drop",
9288 format_fib_prefix, &pfx_10_10_10_21_s_32);
9291 * source an entry that pushes its state down the sub-tree
9293 const fib_prefix_t pfx_10_10_10_0_s_24 = {
9295 .fp_proto = FIB_PROTOCOL_IP4,
9296 .fp_addr = nh_10_10_10_0,
9298 fib_table_entry_update_one_path(0,
9299 &pfx_10_10_10_0_s_24,
9301 FIB_ENTRY_FLAG_COVERED_INHERIT,
9304 tm->hw[0]->sw_if_index,
9308 FIB_ROUTE_PATH_FLAG_NONE);
9311 * whole sub-tree now covered
9313 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9314 FIB_TEST(!fib_test_validate_entry(fei,
9315 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9318 "%U via 10.10.10.1",
9319 format_fib_prefix, &pfx_10_10_10_0_s_24);
9320 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9321 FIB_TEST(!fib_test_validate_entry(fei,
9322 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9325 "%U via 10.10.10.1",
9326 format_fib_prefix, &pfx_10_10_10_21_s_32);
9327 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9328 FIB_TEST(!fib_test_validate_entry(fei,
9329 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9332 "%U via 10.10.10.1",
9333 format_fib_prefix, &pfx_10_10_10_22_s_32);
9334 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9335 FIB_TEST(!fib_test_validate_entry(fei,
9336 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9339 "%U via 10.10.10.1",
9340 format_fib_prefix, &pfx_10_10_10_255_s_32);
9343 * insert a more specific into the sub-tree - expect inheritance
9344 * this one is directly covered by the root
9346 fib_table_entry_special_add(0,
9347 &pfx_10_10_10_16_s_28,
9349 FIB_ENTRY_FLAG_DROP);
9350 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9351 FIB_TEST(!fib_test_validate_entry(fei,
9352 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9355 "%U via 10.10.10.1",
9356 format_fib_prefix, &pfx_10_10_10_16_s_28);
9359 * insert a more specific into the sub-tree - expect inheritance
9360 * this one is indirectly covered by the root
9362 const fib_prefix_t pfx_10_10_10_20_s_30 = {
9364 .fp_proto = FIB_PROTOCOL_IP4,
9365 .fp_addr = nh_10_10_10_20,
9367 fib_table_entry_special_add(0,
9368 &pfx_10_10_10_20_s_30,
9370 FIB_ENTRY_FLAG_DROP);
9371 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_20_s_30);
9372 FIB_TEST(!fib_test_validate_entry(fei,
9373 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9376 "%U via 10.10.10.1",
9377 format_fib_prefix, &pfx_10_10_10_20_s_30);
9380 * remove the prefix from the middle of the sub-tree
9381 * the inherited source will be the only one remaining - expect
9382 * it to be withdrawn and hence the prefix is removed.
9384 fib_table_entry_special_remove(0,
9385 &pfx_10_10_10_20_s_30,
9387 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_20_s_30);
9388 FIB_TEST((FIB_NODE_INDEX_INVALID == fei),
9390 format_fib_prefix, &pfx_10_10_10_20_s_30);
9393 * inheriting source is modifed - expect the modification to be present
9394 * throughout the sub-tree
9396 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9399 tm->hw[0]->sw_if_index);
9400 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
9403 .adj = ai_10_10_10_2,
9407 fib_table_entry_update_one_path(0,
9408 &pfx_10_10_10_0_s_24,
9410 FIB_ENTRY_FLAG_COVERED_INHERIT,
9413 tm->hw[0]->sw_if_index,
9417 FIB_ROUTE_PATH_FLAG_NONE);
9418 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9419 FIB_TEST(!fib_test_validate_entry(fei,
9420 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9423 "%U via 10.10.10.2",
9424 format_fib_prefix, &pfx_10_10_10_21_s_32);
9425 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9426 FIB_TEST(!fib_test_validate_entry(fei,
9427 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9430 "%U via 10.10.10.2",
9431 format_fib_prefix, &pfx_10_10_10_22_s_32);
9432 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9433 FIB_TEST(!fib_test_validate_entry(fei,
9434 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9437 "%U via 10.10.10.2",
9438 format_fib_prefix, &pfx_10_10_10_255_s_32);
9439 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9440 FIB_TEST(!fib_test_validate_entry(fei,
9441 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9444 "%U via 10.10.10.2",
9445 format_fib_prefix, &pfx_10_10_10_0_s_24);
9447 fib_source_t hi_src = fib_source_allocate("test", 0x50,
9448 FIB_SOURCE_BH_SIMPLE);
9451 * add the source that replaces inherited state.
9452 * inheriting source is not the best, so it doesn't push state.
9454 fib_table_entry_update_one_path(0,
9455 &pfx_10_10_10_0_s_24,
9457 FIB_ENTRY_FLAG_NONE,
9460 tm->hw[0]->sw_if_index,
9464 FIB_ROUTE_PATH_FLAG_NONE);
9465 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9466 FIB_TEST(!fib_test_validate_entry(fei,
9467 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9470 "%U via 10.10.10.1",
9471 format_fib_prefix, &pfx_10_10_10_0_s_24);
9473 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9474 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9475 "%U resolves via drop",
9476 format_fib_prefix, &pfx_10_10_10_21_s_32);
9477 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9478 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9479 "%U resolves via drop",
9480 format_fib_prefix, &pfx_10_10_10_22_s_32);
9481 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9482 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9483 "%U resolves via drop",
9484 format_fib_prefix, &pfx_10_10_10_255_s_32);
9485 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9486 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9487 "%U resolves via drop",
9488 format_fib_prefix, &pfx_10_10_10_16_s_28);
9491 * withdraw the higher priority source and expect the inherited to return
9492 * throughout the sub-tree
9494 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, hi_src);
9496 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9497 FIB_TEST(!fib_test_validate_entry(fei,
9498 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9501 "%U via 10.10.10.2",
9502 format_fib_prefix, &pfx_10_10_10_21_s_32);
9503 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9504 FIB_TEST(!fib_test_validate_entry(fei,
9505 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9508 "%U via 10.10.10.2",
9509 format_fib_prefix, &pfx_10_10_10_22_s_32);
9510 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9511 FIB_TEST(!fib_test_validate_entry(fei,
9512 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9515 "%U via 10.10.10.2",
9516 format_fib_prefix, &pfx_10_10_10_255_s_32);
9517 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9518 FIB_TEST(!fib_test_validate_entry(fei,
9519 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9522 "%U via 10.10.10.2",
9523 format_fib_prefix, &pfx_10_10_10_0_s_24);
9524 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9525 FIB_TEST(!fib_test_validate_entry(fei,
9526 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9529 "%U via 10.10.10.2",
9530 format_fib_prefix, &pfx_10_10_10_16_s_28);
9533 * source a covered entry in the sub-tree with the same inherting source
9534 * - expect that it now owns the sub-tree and thus over-rides its cover
9536 fib_table_entry_update_one_path(0,
9537 &pfx_10_10_10_16_s_28,
9539 FIB_ENTRY_FLAG_COVERED_INHERIT,
9542 tm->hw[0]->sw_if_index,
9546 FIB_ROUTE_PATH_FLAG_NONE);
9547 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9548 FIB_TEST(!fib_test_validate_entry(fei,
9549 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9552 "%U via 10.10.10.1",
9553 format_fib_prefix, &pfx_10_10_10_16_s_28);
9554 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9555 FIB_TEST(!fib_test_validate_entry(fei,
9556 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9559 "%U via 10.10.10.2",
9560 format_fib_prefix, &pfx_10_10_10_22_s_32);
9561 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9562 FIB_TEST(!fib_test_validate_entry(fei,
9563 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9566 "%U via 10.10.10.2",
9567 format_fib_prefix, &pfx_10_10_10_21_s_32);
9569 /* these two unaffected by the sub-tree change */
9570 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9571 FIB_TEST(!fib_test_validate_entry(fei,
9572 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9575 "%U via 10.10.10.2",
9576 format_fib_prefix, &pfx_10_10_10_255_s_32);
9577 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9578 FIB_TEST(!fib_test_validate_entry(fei,
9579 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9582 "%U via 10.10.10.2",
9583 format_fib_prefix, &pfx_10_10_10_0_s_24);
9586 * removes the more specific, expect the /24 to now re-owns the sub-tree
9588 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_API);
9590 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9591 FIB_TEST(!fib_test_validate_entry(fei,
9592 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9595 "%U via 10.10.10.2",
9596 format_fib_prefix, &pfx_10_10_10_16_s_28);
9597 FIB_TEST(!fib_test_validate_entry(fei,
9598 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9601 "%U via 10.10.10.2",
9602 format_fib_prefix, &pfx_10_10_10_21_s_32);
9603 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9604 FIB_TEST(!fib_test_validate_entry(fei,
9605 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9608 "%U via 10.10.10.2",
9609 format_fib_prefix, &pfx_10_10_10_22_s_32);
9610 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9611 FIB_TEST(!fib_test_validate_entry(fei,
9612 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9615 "%U via 10.10.10.2",
9616 format_fib_prefix, &pfx_10_10_10_255_s_32);
9617 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9618 FIB_TEST(!fib_test_validate_entry(fei,
9619 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9622 "%U via 10.10.10.2",
9623 format_fib_prefix, &pfx_10_10_10_0_s_24);
9625 * modify the /24. expect the new forwarding to be pushed down
9627 fib_table_entry_update_one_path(0,
9628 &pfx_10_10_10_0_s_24,
9630 FIB_ENTRY_FLAG_COVERED_INHERIT,
9633 tm->hw[0]->sw_if_index,
9637 FIB_ROUTE_PATH_FLAG_NONE);
9638 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9639 FIB_TEST(!fib_test_validate_entry(fei,
9640 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9643 "%U via 10.10.10.1",
9644 format_fib_prefix, &pfx_10_10_10_16_s_28);
9645 FIB_TEST(!fib_test_validate_entry(fei,
9646 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9649 "%U via 10.10.10.1",
9650 format_fib_prefix, &pfx_10_10_10_21_s_32);
9651 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9652 FIB_TEST(!fib_test_validate_entry(fei,
9653 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9656 "%U via 10.10.10.1",
9657 format_fib_prefix, &pfx_10_10_10_22_s_32);
9658 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9659 FIB_TEST(!fib_test_validate_entry(fei,
9660 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9663 "%U via 10.10.10.1",
9664 format_fib_prefix, &pfx_10_10_10_255_s_32);
9665 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9666 FIB_TEST(!fib_test_validate_entry(fei,
9667 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9670 "%U via 10.10.10.1",
9671 format_fib_prefix, &pfx_10_10_10_0_s_24);
9674 * add an entry less specific to /24. it should not own the /24's tree
9676 const fib_prefix_t pfx_10_10_0_0_s_16 = {
9678 .fp_proto = FIB_PROTOCOL_IP4,
9679 .fp_addr = nh_10_10_0_0,
9681 fib_table_entry_update_one_path(0,
9682 &pfx_10_10_0_0_s_16,
9684 FIB_ENTRY_FLAG_COVERED_INHERIT,
9687 tm->hw[0]->sw_if_index,
9691 FIB_ROUTE_PATH_FLAG_NONE);
9692 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9693 FIB_TEST(!fib_test_validate_entry(fei,
9694 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9697 "%U via 10.10.10.1",
9698 format_fib_prefix, &pfx_10_10_10_16_s_28);
9699 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9700 FIB_TEST(!fib_test_validate_entry(fei,
9701 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9704 "%U via 10.10.10.1",
9705 format_fib_prefix, &pfx_10_10_10_22_s_32);
9706 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9707 FIB_TEST(!fib_test_validate_entry(fei,
9708 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9711 "%U via 10.10.10.1",
9712 format_fib_prefix, &pfx_10_10_10_255_s_32);
9713 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9714 FIB_TEST(!fib_test_validate_entry(fei,
9715 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9718 "%U via 10.10.10.1",
9719 format_fib_prefix, &pfx_10_10_10_0_s_24);
9720 fei = fib_table_lookup_exact_match(0, &pfx_10_10_0_0_s_16);
9721 FIB_TEST(!fib_test_validate_entry(fei,
9722 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9725 "%U via 10.10.10.2",
9726 format_fib_prefix, &pfx_10_10_0_0_s_16);
9729 * Add/remove an interposer source to a new /32
9731 const fib_prefix_t pfx_11_11_11_11_s_32 = {
9733 .fp_proto = FIB_PROTOCOL_IP4,
9734 .fp_addr = nh_11_11_11_11,
9737 fib_table_entry_update_one_path(0,
9738 &pfx_11_11_11_11_s_32,
9740 FIB_ENTRY_FLAG_NONE,
9743 tm->hw[0]->sw_if_index,
9747 FIB_ROUTE_PATH_FLAG_NONE);
9749 dpo_id_t interposer = DPO_INVALID;
9750 fib_mpls_label_t *l99 = NULL, fml_99 = {
9753 vec_add1(l99, fml_99);
9755 mpls_label_dpo_create(l99,
9758 MPLS_LABEL_DPO_FLAG_NONE,
9759 punt_dpo_get(DPO_PROTO_MPLS),
9762 adj_index_t ai_10_10_10_3 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9765 tm->hw[0]->sw_if_index);
9766 fib_test_lb_bucket_t adj_o_10_10_10_3 = {
9769 .adj = ai_10_10_10_3,
9772 fib_test_lb_bucket_t l99_o_10_10_10_3 = {
9773 .type = FT_LB_LABEL_O_ADJ,
9775 .adj = ai_10_10_10_3,
9781 fei = fib_table_entry_special_dpo_add(0,
9782 &pfx_11_11_11_11_s_32,
9784 FIB_ENTRY_FLAG_INTERPOSE,
9786 FIB_TEST(!fib_test_validate_entry(fei,
9787 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9790 "%U via interposer adj",
9791 format_fib_prefix,&pfx_11_11_11_11_s_32);
9793 fib_table_entry_special_remove(0,
9794 &pfx_11_11_11_11_s_32,
9795 FIB_SOURCE_SPECIAL);
9796 FIB_TEST(!fib_test_validate_entry(fei,
9797 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9800 "%U via 10.10.10.1",
9801 format_fib_prefix, &pfx_11_11_11_11_s_32);
9802 dpo_reset(&interposer);
9803 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
9806 * add an interposer to a source with path-extensions
9808 fib_mpls_label_t *l3300 = NULL, fml_3300 = {
9811 vec_add1(l3300, fml_3300);
9812 fib_table_entry_update_one_path(0,
9813 &pfx_11_11_11_11_s_32,
9815 FIB_ENTRY_FLAG_NONE,
9818 tm->hw[0]->sw_if_index,
9822 FIB_ROUTE_PATH_FLAG_NONE);
9824 mpls_label_dpo_create(l99,
9827 MPLS_LABEL_DPO_FLAG_NONE,
9828 punt_dpo_get(DPO_PROTO_MPLS),
9831 adj_index_t ai_mpls_10_10_10_3 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9834 tm->hw[0]->sw_if_index);
9835 fib_test_lb_bucket_t l3300_o_10_10_10_3 = {
9836 .type = FT_LB_LABEL_O_ADJ,
9838 .adj = ai_mpls_10_10_10_3,
9843 fib_test_lb_bucket_t lchain_o_10_10_10_3 = {
9844 .type = FT_LB_LABEL_CHAIN_O_ADJ,
9845 .label_chain_o_adj = {
9846 .adj = ai_mpls_10_10_10_3,
9847 .label_chain_size = 2,
9855 fei = fib_table_entry_special_dpo_add(0,
9856 &pfx_11_11_11_11_s_32,
9858 FIB_ENTRY_FLAG_INTERPOSE,
9861 FIB_TEST(!fib_test_validate_entry(fei,
9862 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9864 &lchain_o_10_10_10_3),
9865 "%U via interposer & mpls on adj",
9866 format_fib_prefix, &pfx_11_11_11_11_s_32);
9868 fib_table_entry_special_remove(0,
9869 &pfx_11_11_11_11_s_32,
9870 FIB_SOURCE_SPECIAL);
9871 FIB_TEST(!fib_test_validate_entry(fei,
9872 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9874 &l3300_o_10_10_10_3),
9875 "%U via 10.10.10.1",
9876 format_fib_prefix, &pfx_11_11_11_11_s_32);
9877 adj_unlock(ai_mpls_10_10_10_3);
9880 * remove and re-add the second best API source while the interpose
9883 fei = fib_table_entry_special_dpo_add(0,
9884 &pfx_11_11_11_11_s_32,
9886 FIB_ENTRY_FLAG_INTERPOSE,
9888 FIB_TEST(!fib_test_validate_entry(fei,
9889 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9891 &lchain_o_10_10_10_3),
9892 "%U via interposer adj",
9893 format_fib_prefix,&pfx_11_11_11_11_s_32);
9895 FIB_TEST(3 == pool_elts(mpls_label_dpo_pool),
9896 "MPLS label pool: %d",
9897 pool_elts(mpls_label_dpo_pool));
9899 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
9902 * the interpose does not get stacked when there are not valid paths
9904 fib_test_lb_bucket_t bucket_drop = {
9907 .adj = DPO_PROTO_IP4,
9910 FIB_TEST(!fib_test_validate_entry(fei,
9911 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9915 format_fib_prefix,&pfx_11_11_11_11_s_32);
9917 fib_table_entry_update_one_path(0,
9918 &pfx_11_11_11_11_s_32,
9920 FIB_ENTRY_FLAG_NONE,
9923 tm->hw[0]->sw_if_index,
9927 FIB_ROUTE_PATH_FLAG_NONE);
9928 FIB_TEST(!fib_test_validate_entry(fei,
9929 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9932 "%U via interposer adj",
9933 format_fib_prefix,&pfx_11_11_11_11_s_32);
9934 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
9937 * add a cover for the interposed entry, so that we test it selects
9938 * the covers forwarding.
9940 const fib_prefix_t pfx_11_11_11_0_s_24 = {
9942 .fp_proto = FIB_PROTOCOL_IP4,
9943 .fp_addr = nh_11_11_11_0,
9945 fib_table_entry_update_one_path(0,
9946 &pfx_11_11_11_0_s_24,
9948 FIB_ENTRY_FLAG_NONE,
9951 tm->hw[0]->sw_if_index,
9955 FIB_ROUTE_PATH_FLAG_NONE);
9956 FIB_TEST(!fib_test_validate_entry(fei,
9957 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9960 "%U via interposer adj",
9961 format_fib_prefix,&pfx_11_11_11_11_s_32);
9964 * multiple interpose sources on the same entry. Only the high
9965 * priority source gets to add the interpose.
9967 fib_table_entry_update_one_path(0,
9968 &pfx_11_11_11_11_s_32,
9970 FIB_ENTRY_FLAG_NONE,
9973 tm->hw[0]->sw_if_index,
9977 FIB_ROUTE_PATH_FLAG_NONE);
9979 dpo_id_t interposer2 = DPO_INVALID;
9980 fib_mpls_label_t *l100 = NULL, fml_100 = {
9983 vec_add1(l100, fml_100);
9985 mpls_label_dpo_create(l100,
9988 MPLS_LABEL_DPO_FLAG_NONE,
9989 punt_dpo_get(DPO_PROTO_MPLS),
9992 fei = fib_table_entry_special_dpo_add(0,
9993 &pfx_11_11_11_11_s_32,
9994 FIB_SOURCE_CLASSIFY,
9995 FIB_ENTRY_FLAG_INTERPOSE,
9998 fib_test_lb_bucket_t lc100_o_10_10_10_3 = {
9999 .type = FT_LB_LABEL_CHAIN_O_ADJ,
10000 .label_chain_o_adj = {
10001 .adj = ai_10_10_10_3,
10002 .label_chain_size = 2,
10010 FIB_TEST(!fib_test_validate_entry(fei,
10011 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10013 &lc100_o_10_10_10_3),
10014 "%U via interposer label 99",
10015 format_fib_prefix,&pfx_11_11_11_11_s_32);
10017 fib_test_lb_bucket_t l100_o_10_10_10_3 = {
10018 .type = FT_LB_LABEL_O_ADJ,
10020 .adj = ai_10_10_10_3,
10026 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_SPECIAL);
10028 FIB_TEST(!fib_test_validate_entry(fei,
10029 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10031 &l100_o_10_10_10_3),
10032 "%U via interposer label 99",
10033 format_fib_prefix,&pfx_11_11_11_11_s_32);
10035 fib_table_entry_delete(0, &pfx_11_11_11_0_s_24, FIB_SOURCE_API);
10036 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
10037 FIB_TEST(!fib_test_validate_entry(fei,
10038 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10042 format_fib_prefix,&pfx_11_11_11_11_s_32);
10043 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_CLASSIFY);
10046 * update a source to/from interpose.
10048 /* fib_table_entry_update_one_path(0, */
10049 /* &pfx_11_11_11_0_s_24, */
10050 /* FIB_SOURCE_API, */
10051 /* FIB_ENTRY_FLAG_NONE, */
10052 /* DPO_PROTO_IP4, */
10053 /* &nh_10_10_10_3, */
10054 /* tm->hw[0]->sw_if_index, */
10058 /* FIB_ROUTE_PATH_FLAG_NONE); */
10059 /* fei = fib_table_entry_special_dpo_add(0, */
10060 /* &pfx_11_11_11_11_s_32, */
10061 /* FIB_SOURCE_API, */
10062 /* FIB_ENTRY_FLAG_INTERPOSE, */
10063 /* &interposer); */
10064 /* FIB_TEST(!fib_test_validate_entry(fei, */
10065 /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */
10067 /* &l99_o_10_10_10_3), */
10068 /* "%U via interposer label 99", */
10069 /* format_fib_prefix,&pfx_11_11_11_11_s_32); */
10071 /* FIB_TEST(3 == pool_elts(mpls_label_dpo_pool), */
10072 /* "MPLS label pool: %d", */
10073 /* pool_elts(mpls_label_dpo_pool)); */
10074 /* FIB_TEST((2 == mpls_label_dpo_get(interposer.dpoi_index)->mld_locks), */
10075 /* "Interposer %d locks", */
10076 /* mpls_label_dpo_get(interposer.dpoi_index)->mld_locks); */
10078 /* fib_table_entry_update_one_path(0, */
10079 /* &pfx_11_11_11_11_s_32, */
10080 /* FIB_SOURCE_API, */
10081 /* FIB_ENTRY_FLAG_NONE, */
10082 /* DPO_PROTO_IP4, */
10083 /* &nh_10_10_10_2, */
10084 /* tm->hw[0]->sw_if_index, */
10088 /* FIB_ROUTE_PATH_FLAG_NONE); */
10089 /* FIB_TEST(!fib_test_validate_entry(fei, */
10090 /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */
10092 /* &adj_o_10_10_10_2), */
10093 /* "%U via 10.10.10.2", */
10094 /* format_fib_prefix,&pfx_11_11_11_11_s_32); */
10096 /* FIB_TEST((1 == mpls_label_dpo_get(interposer.dpoi_index)->mld_locks), */
10097 /* "Interposer %d locks", */
10098 /* mpls_label_dpo_get(interposer.dpoi_index)->mld_locks); */
10099 /* FIB_TEST(2 == pool_elts(mpls_label_dpo_pool), */
10100 /* "MPLS label pool: %d", */
10101 /* pool_elts(mpls_label_dpo_pool)); */
10103 /* fei = fib_table_entry_special_dpo_add(0, */
10104 /* &pfx_11_11_11_11_s_32, */
10105 /* FIB_SOURCE_API, */
10106 /* FIB_ENTRY_FLAG_INTERPOSE, */
10107 /* &interposer); */
10108 /* FIB_TEST(!fib_test_validate_entry(fei, */
10109 /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */
10111 /* &l99_o_10_10_10_3), */
10112 /* "%U via interposer label 99", */
10113 /* format_fib_prefix,&pfx_11_11_11_11_s_32); */
10115 /* fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API); */
10118 * Add/remove an interposer source from the top of the subtrie. The
10119 * interposer source is not inherited.
10121 fib_table_entry_update_one_path(0,
10122 &pfx_10_10_10_0_s_24,
10124 FIB_ENTRY_FLAG_COVERED_INHERIT,
10127 tm->hw[0]->sw_if_index,
10131 FIB_ROUTE_PATH_FLAG_NONE);
10132 fei = fib_table_entry_special_dpo_add(0,
10133 &pfx_10_10_10_0_s_24,
10134 FIB_SOURCE_SPECIAL,
10135 FIB_ENTRY_FLAG_INTERPOSE,
10137 FIB_TEST(!fib_test_validate_entry(fei,
10138 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10140 &l99_o_10_10_10_3),
10141 "%U via interposer label",
10142 format_fib_prefix,&pfx_10_10_10_0_s_24);
10143 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
10144 FIB_TEST(!fib_test_validate_entry(fei,
10145 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10149 format_fib_prefix, &pfx_10_10_10_21_s_32);
10151 fib_table_entry_special_remove(0,
10152 &pfx_10_10_10_0_s_24,
10153 FIB_SOURCE_SPECIAL);
10154 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
10155 FIB_TEST(!fib_test_validate_entry(fei,
10156 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10158 &adj_o_10_10_10_3),
10159 "%U via 10.10.10.1",
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,
10165 &adj_o_10_10_10_3),
10166 "%U via via 10.10.10.1",
10167 format_fib_prefix, &pfx_10_10_10_21_s_32);
10170 * Add/remove an interposer source from the top of the subtrie. The
10171 * interposer source is inherited.
10173 fei = fib_table_entry_special_dpo_add(0,
10174 &pfx_10_10_10_0_s_24,
10175 FIB_SOURCE_SPECIAL,
10176 (FIB_ENTRY_FLAG_COVERED_INHERIT |
10177 FIB_ENTRY_FLAG_INTERPOSE),
10179 FIB_TEST(!fib_test_validate_entry(fei,
10180 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10182 &l99_o_10_10_10_3),
10183 "%U via interposer label",
10184 format_fib_prefix,&pfx_10_10_10_0_s_24);
10186 /* interposer gets forwarding from the drop cli source */
10187 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
10188 FIB_TEST(!fib_test_validate_entry(fei,
10189 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10193 format_fib_prefix,&pfx_10_10_10_21_s_32);
10195 fib_table_entry_update_one_path(0,
10196 &pfx_10_10_10_21_s_32,
10198 FIB_ENTRY_FLAG_NONE,
10201 tm->hw[0]->sw_if_index,
10205 FIB_ROUTE_PATH_FLAG_NONE);
10206 fib_table_entry_delete(0, &pfx_10_10_10_21_s_32, FIB_SOURCE_CLI);
10207 /* interposer gets forwarding from the API source */
10208 FIB_TEST(!fib_test_validate_entry(fei,
10209 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10211 &l99_o_10_10_10_3),
10212 "%U via interposer label",
10213 format_fib_prefix,&pfx_10_10_10_21_s_32);
10218 fib_table_entry_delete(0, &pfx_10_10_10_22_s_32, FIB_SOURCE_CLI);
10219 fib_table_entry_delete(0, &pfx_10_10_10_21_s_32, FIB_SOURCE_API);
10220 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_CLI);
10221 fib_table_entry_delete(0, &pfx_10_10_10_255_s_32, FIB_SOURCE_CLI);
10222 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, FIB_SOURCE_API);
10223 fib_table_entry_delete(0, &pfx_10_10_0_0_s_16, FIB_SOURCE_API);
10224 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, FIB_SOURCE_SPECIAL);
10225 adj_unlock(ai_10_10_10_1);
10226 adj_unlock(ai_10_10_10_2);
10227 adj_unlock(ai_10_10_10_3);
10228 dpo_reset(&interposer);
10229 dpo_reset(&interposer2);
10230 FIB_TEST(0 == pool_elts(mpls_label_dpo_pool),
10231 "MPLS label pool empty: %d",
10232 pool_elts(mpls_label_dpo_pool));
10233 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
10234 FIB_TEST(N_PLS == fib_path_list_pool_size(),
10235 "number of path-lists: %d = %d",
10236 N_PLS, fib_path_list_pool_size());
10239 * test the v6 tree walk.
10240 * a /64 that covers everything. a /96 that covers one /128
10241 * a second /128 covered only by the /64.
10243 const fib_prefix_t pfx_2001_s_64 = {
10245 .fp_proto = FIB_PROTOCOL_IP6,
10249 [0] = clib_host_to_net_u64(0x2001000000000000),
10250 [1] = clib_host_to_net_u64(0x0000000000000000),
10255 const fib_prefix_t pfx_2001_1_s_96 = {
10257 .fp_proto = FIB_PROTOCOL_IP6,
10261 [0] = clib_host_to_net_u64(0x2001000000000000),
10262 [1] = clib_host_to_net_u64(0x1000000000000000),
10267 const fib_prefix_t pfx_2001_1_1_s_128 = {
10269 .fp_proto = FIB_PROTOCOL_IP6,
10273 [0] = clib_host_to_net_u64(0x2001000000000000),
10274 [1] = clib_host_to_net_u64(0x1000000000000001),
10279 const fib_prefix_t pfx_2001_0_1_s_128 = {
10281 .fp_proto = FIB_PROTOCOL_IP6,
10285 [0] = clib_host_to_net_u64(0x2001000000000000),
10286 [1] = clib_host_to_net_u64(0x0000000000000001),
10291 const ip46_address_t nh_3000_1 = {
10294 [0] = clib_host_to_net_u64(0x3000000000000000),
10295 [1] = clib_host_to_net_u64(0x0000000000000001),
10299 const ip46_address_t nh_3000_2 = {
10302 [0] = clib_host_to_net_u64(0x3000000000000000),
10303 [1] = clib_host_to_net_u64(0x0000000000000002),
10307 adj_index_t ai_3000_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
10310 tm->hw[0]->sw_if_index);
10311 adj_index_t ai_3000_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
10314 tm->hw[0]->sw_if_index);
10315 fib_test_lb_bucket_t adj_o_3000_1 = {
10321 fib_test_lb_bucket_t adj_o_3000_2 = {
10328 fib_table_entry_special_add(0,
10329 &pfx_2001_0_1_s_128,
10331 FIB_ENTRY_FLAG_DROP);
10332 fib_table_entry_special_add(0,
10333 &pfx_2001_1_1_s_128,
10335 FIB_ENTRY_FLAG_DROP);
10338 * /96 has inherited forwarding pushed down to its covered /128
10340 fib_table_entry_update_one_path(0,
10343 FIB_ENTRY_FLAG_COVERED_INHERIT,
10346 tm->hw[0]->sw_if_index,
10350 FIB_ROUTE_PATH_FLAG_NONE);
10351 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_s_96);
10352 FIB_TEST(!fib_test_validate_entry(fei,
10353 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10357 format_fib_prefix, &pfx_2001_1_s_96);
10358 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_1_s_128);
10359 FIB_TEST(!fib_test_validate_entry(fei,
10360 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10364 format_fib_prefix, &pfx_2001_1_1_s_128);
10365 fei = fib_table_lookup_exact_match(0, &pfx_2001_0_1_s_128);
10366 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
10367 "%U resolves via drop",
10368 format_fib_prefix, &pfx_2001_0_1_s_128);
10371 * /64 has inherited forwarding pushed down to all, but the /96
10372 * and its sub-tree remain unaffected.
10374 fib_table_entry_update_one_path(0,
10377 FIB_ENTRY_FLAG_COVERED_INHERIT,
10380 tm->hw[0]->sw_if_index,
10384 FIB_ROUTE_PATH_FLAG_NONE);
10386 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
10387 FIB_TEST(!fib_test_validate_entry(fei,
10388 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10392 format_fib_prefix, &pfx_2001_s_64);
10393 fei = fib_table_lookup_exact_match(0, &pfx_2001_0_1_s_128);
10394 FIB_TEST(!fib_test_validate_entry(fei,
10395 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10399 format_fib_prefix, &pfx_2001_0_1_s_128);
10401 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_s_96);
10402 FIB_TEST(!fib_test_validate_entry(fei,
10403 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10407 format_fib_prefix, &pfx_2001_1_s_96);
10408 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_1_s_128);
10409 FIB_TEST(!fib_test_validate_entry(fei,
10410 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10414 format_fib_prefix, &pfx_2001_1_1_s_128);
10419 fib_table_entry_delete(0, &pfx_2001_0_1_s_128, FIB_SOURCE_CLI);
10420 fib_table_entry_delete(0, &pfx_2001_1_1_s_128, FIB_SOURCE_CLI);
10421 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
10422 fib_table_entry_delete(0, &pfx_2001_1_s_96, FIB_SOURCE_API);
10423 adj_unlock(ai_3000_1);
10424 adj_unlock(ai_3000_2);
10427 * test no-one left behind
10429 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
10430 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
10436 fib_test_sticky (void)
10438 fib_route_path_t *r_paths = NULL;
10439 test_main_t *tm = &test_main;
10440 u32 ii, lb_count, pl_count;
10441 dpo_id_t dpo = DPO_INVALID;
10442 fib_node_index_t pl_index;
10446 fib_test_lb_bucket_t buckets[N_PATHS];
10447 bfd_session_t bfds[N_PATHS] = {{0}};
10449 lb_count = pool_elts(load_balance_pool);
10450 pl_count = fib_path_list_pool_size();
10452 for (ii = 0; ii < N_PATHS; ii++)
10454 ip46_address_t nh = {
10455 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
10459 ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
10461 &nh, tm->hw[0]->sw_if_index);
10463 buckets[ii].type = FT_LB_ADJ;
10464 buckets[ii].adj.adj = ai;
10466 bfds[ii].udp.key.peer_addr = nh;
10467 bfds[ii].udp.key.sw_if_index = tm->hw[0]->sw_if_index;
10468 bfds[ii].hop_type = BFD_HOP_TYPE_SINGLE;
10469 bfds[ii].local_state = BFD_STATE_init;
10470 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfds[ii]);
10471 bfds[ii].local_state = BFD_STATE_up;
10472 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[ii]);
10475 for (ii = 0; ii < N_PATHS; ii++)
10477 fib_route_path_t r_path = {
10478 .frp_proto = DPO_PROTO_IP4,
10480 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
10482 .frp_sw_if_index = tm->hw[0]->sw_if_index,
10484 .frp_fib_index = ~0,
10486 vec_add1(r_paths, r_path);
10489 pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths);
10490 fib_path_list_lock(pl_index);
10492 fib_path_list_contribute_forwarding(pl_index,
10493 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10494 FIB_PATH_LIST_FWD_FLAG_STICKY,
10497 FIB_TEST(!fib_test_validate_lb(&dpo,
10517 /* take down paths */
10518 bfds[0].local_state = BFD_STATE_down;
10519 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[0]);
10521 fib_path_list_contribute_forwarding(pl_index,
10522 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10523 FIB_PATH_LIST_FWD_FLAG_STICKY,
10526 FIB_TEST(!fib_test_validate_lb(&dpo,
10544 "Failed at shut-down path 0");
10546 bfds[7].local_state = BFD_STATE_down;
10547 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[7]);
10549 fib_path_list_contribute_forwarding(pl_index,
10550 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10551 FIB_PATH_LIST_FWD_FLAG_STICKY,
10554 FIB_TEST(!fib_test_validate_lb(&dpo,
10572 "Failed at shut-down path 7");
10574 /* paths back up */
10575 bfds[0].local_state = BFD_STATE_up;
10576 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[0]);
10577 bfds[7].local_state = BFD_STATE_up;
10578 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[7]);
10580 fib_path_list_contribute_forwarding(pl_index,
10581 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10582 FIB_PATH_LIST_FWD_FLAG_STICKY,
10585 FIB_TEST(!fib_test_validate_lb(&dpo,
10605 fib_path_list_unlock(pl_index);
10608 * non-power of 2 number of buckets
10610 fib_route_path_t *r_paths2 = NULL;
10612 r_paths2 = vec_dup(r_paths);
10613 _vec_len(r_paths2) = 3;
10615 pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths2);
10616 fib_path_list_lock(pl_index);
10618 fib_path_list_contribute_forwarding(pl_index,
10619 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10620 FIB_PATH_LIST_FWD_FLAG_STICKY,
10623 FIB_TEST(!fib_test_validate_lb(&dpo,
10643 bfds[1].local_state = BFD_STATE_down;
10644 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10646 fib_path_list_contribute_forwarding(pl_index,
10647 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10648 FIB_PATH_LIST_FWD_FLAG_STICKY,
10652 * path 1's buckets alternate between path 0 and 2
10654 FIB_TEST(!fib_test_validate_lb(&dpo,
10673 bfds[1].local_state = BFD_STATE_up;
10674 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10676 fib_path_list_unlock(pl_index);
10681 fib_route_path_t *r_paths3 = NULL;
10683 r_paths3 = vec_dup(r_paths);
10684 _vec_len(r_paths3) = 3;
10686 r_paths3[0].frp_weight = 3;
10688 pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths3);
10689 fib_path_list_lock(pl_index);
10691 fib_path_list_contribute_forwarding(pl_index,
10692 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10693 FIB_PATH_LIST_FWD_FLAG_STICKY,
10696 FIB_TEST(!fib_test_validate_lb(&dpo,
10716 bfds[1].local_state = BFD_STATE_down;
10717 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10719 fib_path_list_contribute_forwarding(pl_index,
10720 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10721 FIB_PATH_LIST_FWD_FLAG_STICKY,
10723 /* No attempt to Un-equal distribute the down path's buckets */
10724 FIB_TEST(!fib_test_validate_lb(&dpo,
10743 bfds[1].local_state = BFD_STATE_up;
10744 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10747 fib_path_list_unlock(pl_index);
10750 vec_free(r_paths2);
10751 vec_free(r_paths3);
10753 FIB_TEST(lb_count == pool_elts(load_balance_pool), "no leaked LBs");
10754 FIB_TEST(pl_count == fib_path_list_pool_size(), "no leaked PLs");
10759 static clib_error_t *
10760 fib_test (vlib_main_t * vm,
10761 unformat_input_t * input,
10762 vlib_cli_command_t * cmd_arg)
10768 fib_test_mk_intf(4);
10770 if (unformat (input, "debug"))
10772 fib_test_do_debug = 1;
10775 if (unformat (input, "ip4"))
10777 res += fib_test_v4();
10779 else if (unformat (input, "ip6"))
10781 res += fib_test_v6();
10783 else if (unformat (input, "ip"))
10785 res += fib_test_v4();
10786 res += fib_test_v6();
10788 else if (unformat (input, "label"))
10790 res += fib_test_label();
10792 else if (unformat (input, "ae"))
10794 res += fib_test_ae();
10796 else if (unformat (input, "pref"))
10798 res += fib_test_pref();
10800 else if (unformat (input, "lfib"))
10802 res += lfib_test();
10804 else if (unformat (input, "walk"))
10806 res += fib_test_walk();
10808 else if (unformat (input, "bfd"))
10810 res += fib_test_bfd();
10812 else if (unformat (input, "inherit"))
10814 res += fib_test_inherit();
10816 else if (unformat (input, "sticky"))
10818 res += fib_test_sticky();
10822 res += fib_test_v4();
10823 res += fib_test_v6();
10824 res += fib_test_ae();
10825 res += fib_test_bfd();
10826 res += fib_test_pref();
10827 res += fib_test_label();
10828 res += fib_test_inherit();
10829 res += lfib_test();
10832 * fib-walk process must be disabled in order for the walk tests to work
10834 fib_walk_process_disable();
10835 res += fib_test_walk();
10836 fib_walk_process_enable();
10842 return clib_error_return(0, "FIB Unit Test Failed");
10850 VLIB_CLI_COMMAND (test_fib_command, static) = {
10851 .path = "test fib",
10852 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
10853 .function = fib_test,
10857 fib_test_init (vlib_main_t *vm)
10862 VLIB_INIT_FUNCTION (fib_test_init);