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 ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
162 ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
164 error = vnet_sw_interface_set_flags(vnet_get_main(),
165 tm->hw[i]->sw_if_index,
166 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
167 FIB_TEST((NULL == error), "UP interface %d", i);
170 * re-eval after the inevitable realloc
172 for (i = 0; i < ninterfaces; i++)
174 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
175 tm->hw_if_indicies[i]);
181 #define FIB_TEST_REC_FORW(_rec_prefix, _via_prefix, _bucket) \
183 const dpo_id_t *_rec_dpo = fib_entry_contribute_ip_forwarding( \
184 fib_table_lookup_exact_match(fib_index, (_rec_prefix))); \
185 const dpo_id_t *_via_dpo = fib_entry_contribute_ip_forwarding( \
186 fib_table_lookup(fib_index, (_via_prefix))); \
187 FIB_TEST(!dpo_cmp(_via_dpo, \
188 load_balance_get_bucket(_rec_dpo->dpoi_index, \
190 "%U is recursive via %U", \
191 format_fib_prefix, (_rec_prefix), \
192 format_fib_prefix, _via_prefix); \
195 #define FIB_TEST_LB_BUCKET_VIA_ADJ(_prefix, _bucket, _ai) \
197 const dpo_id_t *_dpo = fib_entry_contribute_ip_forwarding( \
198 fib_table_lookup_exact_match(fib_index, (_prefix))); \
199 const dpo_id_t *_dpo1 = \
200 load_balance_get_bucket(_dpo->dpoi_index, _bucket); \
201 FIB_TEST(DPO_ADJACENCY == _dpo1->dpoi_type, "type is %U", \
202 format_dpo_type, _dpo1->dpoi_type); \
203 FIB_TEST((_ai == _dpo1->dpoi_index), \
204 "%U bucket %d resolves via %U", \
205 format_fib_prefix, (_prefix), \
207 format_dpo_id, _dpo1, 0); \
210 #define FIB_TEST_RPF(_cond, _comment, _args...) \
212 if (FIB_TEST_I(_cond, _comment, ##_args)) { \
219 fib_test_urpf_is_equal (fib_node_index_t fei,
220 fib_forward_chain_type_t fct,
223 dpo_id_t dpo = DPO_INVALID;
224 fib_urpf_list_t *urpf;
232 fib_entry_contribute_forwarding(fei, fct, &dpo);
233 ui = load_balance_get_urpf(dpo.dpoi_index);
235 urpf = fib_urpf_list_get(ui);
237 FIB_TEST_RPF(num == vec_len(urpf->furpf_itfs),
238 "RPF:%U len %d == %d",
239 format_fib_urpf_list, ui,
240 num, vec_len(urpf->furpf_itfs));
241 FIB_TEST_RPF(num == fib_urpf_check_size(ui),
242 "RPF:%U check-size %d == %d",
243 format_fib_urpf_list, ui,
244 num, vec_len(urpf->furpf_itfs));
246 for (ii = 0; ii < num; ii++)
248 adj_index_t ai = va_arg(ap, adj_index_t);
250 FIB_TEST_RPF(ai == urpf->furpf_itfs[ii],
251 "RPF:%d item:%d - %d == %d",
252 ui, ii, ai, urpf->furpf_itfs[ii]);
253 FIB_TEST_RPF(fib_urpf_check(ui, ai),
267 fib_test_build_rewrite (u8 *eth_addr)
271 vec_validate(rewrite, 13);
273 memcpy(rewrite, eth_addr, 6);
274 memcpy(rewrite+6, eth_addr, 6);
279 #define FIB_TEST_LB(_cond, _comment, _args...) \
281 if (FIB_TEST_I(_cond, _comment, ##_args)) { \
287 fib_test_validate_rep_v (const replicate_t *rep,
291 const fib_test_rep_bucket_t *exp;
296 FIB_TEST_LB((n_buckets == rep->rep_n_buckets),
297 "n_buckets = %d", rep->rep_n_buckets);
299 for (bucket = 0; bucket < n_buckets; bucket++)
301 exp = va_arg(*ap, fib_test_rep_bucket_t*);
303 dpo = replicate_get_bucket_i(rep, bucket);
307 case FT_REP_LABEL_O_ADJ:
309 const mpls_label_dpo_t *mld;
312 FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE)
314 "bucket %d stacks on %U",
316 format_dpo_type, dpo->dpoi_type);
318 mld = mpls_label_dpo_get(dpo->dpoi_index);
319 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
321 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
322 exp->label_o_adj.label),
323 "bucket %d stacks on label %d",
325 exp->label_o_adj.label);
327 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
328 exp->label_o_adj.eos),
329 "bucket %d stacks on label %d %U",
331 exp->label_o_adj.label,
332 format_mpls_eos_bit, exp->label_o_adj.eos);
334 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
335 "bucket %d label stacks on %U",
337 format_dpo_type, mld->mld_dpo.dpoi_type);
339 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
340 "bucket %d label stacks on adj %d",
342 exp->label_o_adj.adj);
346 FIB_TEST_LB((DPO_INTERFACE_RX == dpo->dpoi_type),
347 "bucket %d stacks on %U",
349 format_dpo_type, dpo->dpoi_type);
351 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
352 "bucket %d stacks on adj %d",
356 case FT_REP_DISP_MFIB_LOOKUP:
366 fib_test_validate_lb_v (const load_balance_t *lb,
374 FIB_TEST_LB((n_buckets == lb->lb_n_buckets), "n_buckets = %d", lb->lb_n_buckets);
376 for (bucket = 0; bucket < n_buckets; bucket++)
378 const fib_test_lb_bucket_t *exp;
380 exp = va_arg(*ap, fib_test_lb_bucket_t*);
381 dpo = load_balance_get_bucket_i(lb, bucket);
385 case FT_LB_LABEL_STACK_O_ADJ:
387 const mpls_label_dpo_t *mld;
388 mpls_label_dpo_flags_t mf;
392 mf = ((exp->label_stack_o_adj.mode ==
393 FIB_MPLS_LSP_MODE_UNIFORM) ?
394 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
395 MPLS_LABEL_DPO_FLAG_NONE);
396 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
397 "bucket %d stacks on %U",
399 format_dpo_type, dpo->dpoi_type);
401 mld = mpls_label_dpo_get(dpo->dpoi_index);
403 FIB_TEST_LB(exp->label_stack_o_adj.label_stack_size == mld->mld_n_labels,
407 for (ii = 0; ii < mld->mld_n_labels; ii++)
409 hdr = clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
410 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
411 exp->label_stack_o_adj.label_stack[ii]),
412 "bucket %d stacks on label %d",
414 exp->label_stack_o_adj.label_stack[ii]);
416 if (ii == mld->mld_n_labels-1)
418 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
419 exp->label_o_adj.eos),
420 "bucket %d stacks on label %d %U!=%U",
422 exp->label_stack_o_adj.label_stack[ii],
423 format_mpls_eos_bit, exp->label_o_adj.eos,
424 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
428 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) == MPLS_NON_EOS),
429 "bucket %d stacks on label %d %U",
431 exp->label_stack_o_adj.label_stack[ii],
432 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
436 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
437 "bucket %d label stacks on %U",
439 format_dpo_type, mld->mld_dpo.dpoi_type);
441 FIB_TEST_LB((exp->label_stack_o_adj.adj == mld->mld_dpo.dpoi_index),
442 "bucket %d label stacks on adj %d",
444 exp->label_stack_o_adj.adj);
447 case FT_LB_LABEL_CHAIN_O_ADJ:
449 const mpls_label_dpo_t *mld = NULL;
450 mpls_label_dpo_flags_t mf;
454 mf = ((exp->label_chain_o_adj.mode ==
455 FIB_MPLS_LSP_MODE_UNIFORM) ?
456 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
457 MPLS_LABEL_DPO_FLAG_NONE);
459 for (ii = 0; ii < exp->label_chain_o_adj.label_chain_size; ii++)
461 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
462 "bucket %d stacks on %U",
464 format_dpo_type, dpo->dpoi_type);
465 mld = mpls_label_dpo_get(dpo->dpoi_index);
467 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
468 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
469 exp->label_chain_o_adj.label_chain[ii]),
470 "bucket %d stacks on label %d",
472 exp->label_chain_o_adj.label_chain[ii]);
476 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
477 "bucket %d label stacks on %U",
479 format_dpo_type, mld->mld_dpo.dpoi_type);
481 FIB_TEST_LB((exp->label_chain_o_adj.adj == mld->mld_dpo.dpoi_index),
482 "bucket %d label stacks on adj %d",
484 exp->label_chain_o_adj.adj);
487 case FT_LB_LABEL_O_ADJ:
489 const mpls_label_dpo_t *mld;
491 FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE)
493 "bucket %d stacks on %U",
495 format_dpo_type, dpo->dpoi_type);
497 mld = mpls_label_dpo_get(dpo->dpoi_index);
498 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
500 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
501 exp->label_o_adj.label),
502 "bucket %d stacks on label %d not %d",
504 vnet_mpls_uc_get_label(hdr),
505 exp->label_o_adj.label);
507 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
508 exp->label_o_adj.eos),
509 "bucket %d stacks on label %d %U",
511 exp->label_o_adj.label,
512 format_mpls_eos_bit, exp->label_o_adj.eos);
514 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
515 "bucket %d label stacks on %U",
517 format_dpo_type, mld->mld_dpo.dpoi_type);
519 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
520 "bucket %d label stacks on adj %d",
522 exp->label_o_adj.adj);
525 case FT_LB_LABEL_O_LB:
527 const mpls_label_dpo_t *mld;
528 mpls_label_dpo_flags_t mf;
531 mf = ((exp->label_o_lb.mode ==
532 FIB_MPLS_LSP_MODE_UNIFORM) ?
533 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
534 MPLS_LABEL_DPO_FLAG_NONE);
535 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
536 "bucket %d stacks on %U",
538 format_dpo_type, dpo->dpoi_type);
540 mld = mpls_label_dpo_get(dpo->dpoi_index);
541 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
543 FIB_TEST_LB(1 == mld->mld_n_labels, "label stack size",
545 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
546 exp->label_o_lb.label),
547 "bucket %d stacks on label %d",
549 exp->label_o_lb.label);
551 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
552 exp->label_o_lb.eos),
553 "bucket %d stacks on label %d %U",
555 exp->label_o_lb.label,
556 format_mpls_eos_bit, exp->label_o_lb.eos);
558 FIB_TEST_LB((DPO_LOAD_BALANCE == mld->mld_dpo.dpoi_type),
559 "bucket %d label stacks on %U",
561 format_dpo_type, mld->mld_dpo.dpoi_type);
563 FIB_TEST_LB((exp->label_o_lb.lb == mld->mld_dpo.dpoi_index),
564 "bucket %d label stacks on LB %d",
570 res = FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
571 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
572 "bucket %d stacks on %U",
574 format_dpo_type, dpo->dpoi_type);
575 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
576 "bucket %d stacks on adj %d",
580 case FT_LB_MPLS_DISP_PIPE_O_ADJ:
582 const mpls_disp_dpo_t *mdd;
584 res = FIB_TEST_I((DPO_MPLS_DISPOSITION_PIPE == dpo->dpoi_type),
585 "bucket %d stacks on %U",
587 format_dpo_type, dpo->dpoi_type);
589 mdd = mpls_disp_dpo_get(dpo->dpoi_index);
593 res = FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
594 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
595 "bucket %d stacks on %U",
597 format_dpo_type, dpo->dpoi_type);
598 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
599 "bucket %d stacks on adj %d",
605 res = FIB_TEST_I((DPO_INTERFACE_RX == dpo->dpoi_type),
606 "bucket %d stacks on %U",
608 format_dpo_type, dpo->dpoi_type);
609 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
610 "bucket %d stacks on adj %d",
615 res = FIB_TEST_I((DPO_DVR == dpo->dpoi_type),
616 "bucket %d stacks on %U",
618 format_dpo_type, dpo->dpoi_type);
619 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
620 "bucket %d stacks on adj %d",
625 res = FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
626 "bucket %d stacks on %U",
628 format_dpo_type, dpo->dpoi_type);
629 FIB_TEST_LB((exp->lb.lb == dpo->dpoi_index),
630 "bucket %d stacks on lb %d not %d",
635 case FT_LB_BIER_TABLE:
636 FIB_TEST_LB((DPO_BIER_TABLE == dpo->dpoi_type),
637 "bucket %d stacks on %U",
639 format_dpo_type, dpo->dpoi_type);
640 FIB_TEST_LB((exp->bier.table == dpo->dpoi_index),
641 "bucket %d stacks on lb %d",
645 case FT_LB_BIER_FMASK:
646 FIB_TEST_LB((DPO_BIER_FMASK == dpo->dpoi_type),
647 "bucket %d stacks on %U",
649 format_dpo_type, dpo->dpoi_type);
650 FIB_TEST_LB((exp->bier.fmask == dpo->dpoi_index),
651 "bucket %d stacks on lb %d",
656 FIB_TEST_LB((DPO_DROP == dpo->dpoi_type),
657 "bucket %d stacks on %U",
659 format_dpo_type, dpo->dpoi_type);
662 FIB_TEST_LB((DPO_PUNT == dpo->dpoi_type),
663 "bucket %d stacks on %U",
665 format_dpo_type, dpo->dpoi_type);
673 fib_test_validate_lb (const dpo_id_t *dpo,
677 const load_balance_t *lb;
682 va_start(ap, n_buckets);
684 if (!FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
686 format_dpo_type, dpo->dpoi_type))
688 lb = load_balance_get(dpo->dpoi_index);
690 res = fib_test_validate_lb_v(lb, n_buckets, &ap);
703 fib_test_validate_entry (fib_node_index_t fei,
704 fib_forward_chain_type_t fct,
708 dpo_id_t dpo = DPO_INVALID;
709 const fib_prefix_t *pfx;
717 pfx = fib_entry_get_prefix(fei);
718 fib_index = fib_entry_get_fib_index(fei);
719 fib_entry_contribute_forwarding(fei, fct, &dpo);
721 if (DPO_REPLICATE == dpo.dpoi_type)
723 const replicate_t *rep;
725 va_start(ap, n_buckets);
726 rep = replicate_get(dpo.dpoi_index);
727 res = fib_test_validate_rep_v(rep, n_buckets, &ap);
732 const load_balance_t *lb;
734 FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type),
735 "%U Entry links to %U",
736 format_fib_prefix, pfx,
737 format_dpo_type, dpo.dpoi_type);
739 va_start(ap, n_buckets);
740 lb = load_balance_get(dpo.dpoi_index);
741 res = fib_test_validate_lb_v(lb, n_buckets, &ap);
745 * ensure that the LB contributed by the entry is the
746 * same as the LB in the forwarding tables
748 if (fct == fib_entry_get_default_chain_type(fib_entry_get(fei)))
750 switch (pfx->fp_proto)
752 case FIB_PROTOCOL_IP4:
753 fw_lbi = ip4_fib_forwarding_lookup(fib_index, &pfx->fp_addr.ip4);
755 case FIB_PROTOCOL_IP6:
756 fw_lbi = ip6_fib_table_fwding_lookup(fib_index, &pfx->fp_addr.ip6);
758 case FIB_PROTOCOL_MPLS:
760 mpls_unicast_header_t hdr = {
761 .label_exp_s_ttl = 0,
764 vnet_mpls_uc_set_label(&hdr.label_exp_s_ttl, pfx->fp_label);
765 vnet_mpls_uc_set_s(&hdr.label_exp_s_ttl, pfx->fp_eos);
766 hdr.label_exp_s_ttl = clib_host_to_net_u32(hdr.label_exp_s_ttl);
768 fw_lbi = mpls_fib_table_forwarding_lookup(fib_index, &hdr);
774 FIB_TEST_LB((fw_lbi == dpo.dpoi_index),
775 "Contributed LB = FW LB:\n fwd:%U\n cont:%U",
776 format_load_balance, fw_lbi, 0,
777 format_load_balance, dpo.dpoi_index, 0);
790 * In the default table check for the presence and correct forwarding
791 * of the special entries
793 fib_node_index_t dfrt, fei, ai, ai2, locked_ai, ai_01, ai_02, ai_03;
794 const dpo_id_t *dpo, *dpo1, *dpo2, *dpo_drop;
795 const ip_adjacency_t *adj;
796 const load_balance_t *lb;
804 ip46_address_t nh_10_10_10_1 = {
805 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
808 ip46_address_t nh_10_10_10_2 = {
809 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
812 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
813 pool_elts(load_balance_map_pool));
817 /* record the nubmer of load-balances in use before we start */
818 lb_count = pool_elts(load_balance_pool);
820 /* Find or create FIB table 11 */
821 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11,
824 for (ii = 0; ii < 4; ii++)
826 ip4_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
829 fib_prefix_t pfx_0_0_0_0_s_0 = {
831 .fp_proto = FIB_PROTOCOL_IP4,
841 .fp_proto = FIB_PROTOCOL_IP4,
849 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
851 dfrt = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
852 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
853 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
854 "Default route is DROP");
857 fei = fib_table_lookup(fib_index, &pfx);
858 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all zeros route present");
859 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
860 "all 0s route is DROP");
862 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xffffffff);
864 fei = fib_table_lookup(fib_index, &pfx);
865 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all ones route present");
866 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
867 "all 1s route is DROP");
869 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xe0000000);
871 fei = fib_table_lookup(fib_index, &pfx);
872 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all-mcast route present");
873 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
874 "all-mcast route is DROP");
876 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xf0000000);
878 fei = fib_table_lookup(fib_index, &pfx);
879 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "class-e route present");
880 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
881 "class-e route is DROP");
884 * at this stage there are 5 entries in the test FIB (plus 5 in the default),
885 * all of which are special sourced and so none of which share path-lists.
886 * There are also 2 entries, and 2 non-shared path-lists, in the v6 default
887 * table, and 4 path-lists in the v6 MFIB table and 2 in v4.
891 u32 PNBR = 5+5+2+4+2;
894 * if the IGMP plugin is loaded this adds two more entries to the v4 MFIB
896 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
897 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
898 fib_path_list_pool_size());
899 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
900 fib_entry_pool_size());
903 * add interface routes.
904 * validate presence of /24 attached and /32 recieve.
905 * test for the presence of the receive address in the glean and local adj
907 fib_prefix_t local_pfx = {
909 .fp_proto = FIB_PROTOCOL_IP4,
912 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
917 fib_table_entry_update_one_path(fib_index, &local_pfx,
918 FIB_SOURCE_INTERFACE,
919 (FIB_ENTRY_FLAG_CONNECTED |
920 FIB_ENTRY_FLAG_ATTACHED),
923 tm->hw[0]->sw_if_index,
924 ~0, // invalid fib index
927 FIB_ROUTE_PATH_FLAG_NONE);
928 fei = fib_table_lookup(fib_index, &local_pfx);
929 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
930 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
931 fib_entry_get_flags(fei)),
932 "Flags set on attached interface");
934 ai = fib_entry_get_adj(fei);
935 FIB_TEST((FIB_NODE_INDEX_INVALID != ai),
936 "attached interface route adj present %d", ai);
938 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
939 "attached interface adj is glean");
941 local_pfx.fp_len = 32;
942 fib_table_entry_update_one_path(fib_index, &local_pfx,
943 FIB_SOURCE_INTERFACE,
944 (FIB_ENTRY_FLAG_CONNECTED |
945 FIB_ENTRY_FLAG_LOCAL),
948 tm->hw[0]->sw_if_index,
949 ~0, // invalid fib index
952 FIB_ROUTE_PATH_FLAG_NONE);
953 fei = fib_table_lookup(fib_index, &local_pfx);
954 FIB_TEST(((FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_CONNECTED) ==
955 fib_entry_get_flags(fei)),
956 "Flags set on local interface");
958 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
960 dpo = fib_entry_contribute_ip_forwarding(fei);
961 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
962 "RPF list for local length 0");
963 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
964 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
965 "local interface adj is local");
966 receive_dpo_t *rd = receive_dpo_get(dpo->dpoi_index);
968 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
970 "local interface adj is receive ok");
972 FIB_TEST((2 == fib_table_get_num_entries(fib_index,
974 FIB_SOURCE_INTERFACE)),
975 "2 Interface Source'd prefixes");
976 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
977 &adj->sub_type.glean.rx_pfx.fp_addr)),
978 "attached interface adj is receive ok");
981 * +2 interface routes +2 non-shared path-lists
983 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
984 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
985 fib_path_list_pool_size());
986 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
987 fib_entry_pool_size());
990 * Modify the default route to be via an adj not yet known.
991 * this sources the defalut route with the API source, which is
992 * a higher preference to the DEFAULT_ROUTE source
994 pfx.fp_addr.ip4.as_u32 = 0;
996 fib_table_entry_path_add(fib_index, &pfx,
1001 tm->hw[0]->sw_if_index,
1002 ~0, // invalid fib index
1005 FIB_ROUTE_PATH_FLAG_NONE);
1006 fei = fib_table_lookup(fib_index, &pfx);
1007 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
1008 "Flags set on API route");
1010 FIB_TEST((fei == dfrt), "default route same index");
1011 ai = fib_entry_get_adj(fei);
1012 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
1014 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1015 "adj is incomplete");
1016 FIB_TEST((0 == ip46_address_cmp(&nh_10_10_10_1, &adj->sub_type.nbr.next_hop)),
1017 "adj nbr next-hop ok");
1018 FIB_TEST((1 == fib_table_get_num_entries(fib_index,
1021 "1 API Source'd prefixes");
1024 * find the adj in the shared db
1026 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1029 tm->hw[0]->sw_if_index);
1030 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
1031 adj_unlock(locked_ai);
1034 * +1 shared path-list
1036 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
1037 fib_path_list_db_size());
1038 FIB_TEST((PNBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
1039 fib_path_list_pool_size());
1040 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
1041 fib_entry_pool_size());
1044 * remove the API source from the default route. We expected
1045 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
1047 pfx.fp_addr.ip4.as_u32 = 0;
1049 fib_table_entry_path_remove(fib_index, &pfx,
1053 tm->hw[0]->sw_if_index,
1054 ~0, // non-recursive path, so no FIB index
1056 FIB_ROUTE_PATH_FLAG_NONE);
1058 fei = fib_table_lookup(fib_index, &pfx);
1060 FIB_TEST((fei == dfrt), "default route same index");
1061 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
1062 "Default route is DROP");
1065 * -1 shared-path-list
1067 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
1068 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
1069 fib_path_list_pool_size());
1070 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
1071 fib_entry_pool_size());
1074 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
1076 fib_prefix_t pfx_10_10_10_1_s_32 = {
1078 .fp_proto = FIB_PROTOCOL_IP4,
1081 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
1084 fib_prefix_t pfx_10_10_10_2_s_32 = {
1086 .fp_proto = FIB_PROTOCOL_IP4,
1089 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
1092 fib_prefix_t pfx_11_11_11_11_s_32 = {
1094 .fp_proto = FIB_PROTOCOL_IP4,
1097 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
1101 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
1104 ip46_address_t nh_12_12_12_12 = {
1105 .ip4.as_u32 = clib_host_to_net_u32(0x0c0c0c0c),
1107 adj_index_t ai_12_12_12_12;
1110 * Add a route via an incomplete ADJ. then complete the ADJ
1111 * Expect the route LB is updated to use complete adj type.
1113 fei = fib_table_entry_update_one_path(fib_index,
1114 &pfx_11_11_11_11_s_32,
1116 FIB_ENTRY_FLAG_ATTACHED,
1118 &pfx_10_10_10_1_s_32.fp_addr,
1119 tm->hw[0]->sw_if_index,
1120 ~0, // invalid fib index
1123 FIB_ROUTE_PATH_FLAG_NONE);
1125 dpo = fib_entry_contribute_ip_forwarding(fei);
1126 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1127 FIB_TEST(DPO_ADJACENCY_INCOMPLETE == dpo1->dpoi_type,
1128 "11.11.11.11/32 via incomplete adj");
1130 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1132 &pfx_10_10_10_1_s_32.fp_addr,
1133 tm->hw[0]->sw_if_index);
1134 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
1135 adj = adj_get(ai_01);
1136 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1137 "adj is incomplete");
1138 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1139 &adj->sub_type.nbr.next_hop)),
1140 "adj nbr next-hop ok");
1142 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1143 fib_test_build_rewrite(eth_addr));
1144 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1146 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1147 &adj->sub_type.nbr.next_hop)),
1148 "adj nbr next-hop ok");
1149 ai = fib_entry_get_adj(fei);
1150 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
1152 dpo = fib_entry_contribute_ip_forwarding(fei);
1153 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1154 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type,
1155 "11.11.11.11/32 via complete adj");
1156 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1157 tm->hw[0]->sw_if_index),
1158 "RPF list for adj-fib contains adj");
1160 ai_12_12_12_12 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1163 tm->hw[1]->sw_if_index);
1164 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_12_12_12_12), "adj created");
1165 adj = adj_get(ai_12_12_12_12);
1166 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1167 "adj is incomplete");
1168 FIB_TEST((0 == ip46_address_cmp(&nh_12_12_12_12,
1169 &adj->sub_type.nbr.next_hop)),
1170 "adj nbr next-hop ok");
1171 adj_nbr_update_rewrite(ai_12_12_12_12, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1172 fib_test_build_rewrite(eth_addr));
1173 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1179 fei = fib_table_entry_path_add(fib_index,
1180 &pfx_10_10_10_1_s_32,
1182 FIB_ENTRY_FLAG_ATTACHED,
1184 &pfx_10_10_10_1_s_32.fp_addr,
1185 tm->hw[0]->sw_if_index,
1186 ~0, // invalid fib index
1189 FIB_ROUTE_PATH_FLAG_NONE);
1190 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
1191 "Flags set on adj-fib");
1192 ai = fib_entry_get_adj(fei);
1193 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj, %d", ai);
1195 fib_table_entry_path_remove(fib_index,
1196 &pfx_11_11_11_11_s_32,
1199 &pfx_10_10_10_1_s_32.fp_addr,
1200 tm->hw[0]->sw_if_index,
1201 ~0, // invalid fib index
1203 FIB_ROUTE_PATH_FLAG_NONE);
1207 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1209 &pfx_10_10_10_2_s_32.fp_addr,
1210 tm->hw[0]->sw_if_index);
1211 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
1212 adj = adj_get(ai_02);
1213 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1214 "adj is incomplete");
1215 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1216 &adj->sub_type.nbr.next_hop)),
1217 "adj nbr next-hop ok");
1219 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1220 fib_test_build_rewrite(eth_addr));
1221 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1223 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1224 &adj->sub_type.nbr.next_hop)),
1225 "adj nbr next-hop ok");
1226 FIB_TEST((ai_01 != ai_02), "ADJs are different");
1228 fib_table_entry_path_add(fib_index,
1229 &pfx_10_10_10_2_s_32,
1231 FIB_ENTRY_FLAG_ATTACHED,
1233 &pfx_10_10_10_2_s_32.fp_addr,
1234 tm->hw[0]->sw_if_index,
1235 ~0, // invalid fib index
1238 FIB_ROUTE_PATH_FLAG_NONE);
1240 fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32);
1241 ai = fib_entry_get_adj(fei);
1242 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
1245 * +2 adj-fibs, and their non-shared path-lists
1247 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
1248 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
1249 fib_path_list_pool_size());
1250 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
1251 fib_entry_pool_size());
1254 * Add 2 routes via the first ADJ. ensure path-list sharing
1256 fib_prefix_t pfx_1_1_1_1_s_32 = {
1258 .fp_proto = FIB_PROTOCOL_IP4,
1261 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1265 fib_table_entry_path_add(fib_index,
1268 FIB_ENTRY_FLAG_NONE,
1271 tm->hw[0]->sw_if_index,
1272 ~0, // invalid fib index
1275 FIB_ROUTE_PATH_FLAG_NONE);
1276 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
1277 ai = fib_entry_get_adj(fei);
1278 FIB_TEST((ai_01 == ai), "1.1.1.1 resolves via 10.10.10.1");
1281 * +1 entry and a shared path-list
1283 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
1284 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1285 fib_path_list_pool_size());
1286 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
1287 fib_entry_pool_size());
1290 fib_prefix_t pfx_1_1_2_0_s_24 = {
1292 .fp_proto = FIB_PROTOCOL_IP4,
1294 .ip4.as_u32 = clib_host_to_net_u32(0x01010200),
1298 fib_table_entry_path_add(fib_index,
1301 FIB_ENTRY_FLAG_NONE,
1304 tm->hw[0]->sw_if_index,
1305 ~0, // invalid fib index
1308 FIB_ROUTE_PATH_FLAG_NONE);
1309 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1310 ai = fib_entry_get_adj(fei);
1311 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1316 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
1317 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1318 fib_path_list_pool_size());
1319 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1320 fib_entry_pool_size());
1323 * modify 1.1.2.0/24 to use multipath.
1325 fib_table_entry_path_add(fib_index,
1328 FIB_ENTRY_FLAG_NONE,
1331 tm->hw[0]->sw_if_index,
1332 ~0, // invalid fib index
1335 FIB_ROUTE_PATH_FLAG_NONE);
1336 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1337 dpo = fib_entry_contribute_ip_forwarding(fei);
1338 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1339 1, tm->hw[0]->sw_if_index),
1340 "RPF list for 1.1.2.0/24 contains both adjs");
1342 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1343 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1344 FIB_TEST((ai_01 == dpo1->dpoi_index),
1345 "1.1.2.0/24 bucket 0 resolves via 10.10.10.1 (%d=%d)",
1346 ai_01, dpo1->dpoi_index);
1348 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 1);
1349 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1350 FIB_TEST((ai_02 == dpo1->dpoi_index),
1351 "1.1.2.0/24 bucket 1 resolves via 10.10.10.2");
1354 * +1 shared-pathlist
1356 FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty");
1357 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1358 fib_path_list_pool_size());
1359 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1360 fib_entry_pool_size());
1365 fib_table_entry_path_remove(fib_index,
1370 tm->hw[0]->sw_if_index,
1373 FIB_ROUTE_PATH_FLAG_NONE);
1374 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1375 dpo = fib_entry_contribute_ip_forwarding(fei);
1376 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1377 1, tm->hw[0]->sw_if_index),
1378 "RPF list for 1.1.2.0/24 contains one adj");
1380 ai = fib_entry_get_adj(fei);
1381 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1384 * +1 shared-pathlist
1386 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d",
1387 fib_path_list_db_size());
1388 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1389 fib_path_list_pool_size());
1390 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1391 fib_entry_pool_size());
1394 * Add 2 recursive routes:
1395 * 100.100.100.100/32 via 1.1.1.1/32 => the via entry is installed.
1396 * 100.100.100.101/32 via 1.1.1.1/32 => the via entry is installed.
1398 fib_prefix_t bgp_100_pfx = {
1400 .fp_proto = FIB_PROTOCOL_IP4,
1402 /* 100.100.100.100/32 */
1403 .ip4.as_u32 = clib_host_to_net_u32(0x64646464),
1407 ip46_address_t nh_1_1_1_1 = {
1408 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1411 fei = fib_table_entry_path_add(fib_index,
1414 FIB_ENTRY_FLAG_NONE,
1417 ~0, // no index provided.
1418 fib_index, // nexthop in same fib as route
1421 FIB_ROUTE_PATH_FLAG_NONE);
1423 FIB_TEST_REC_FORW(&bgp_100_pfx, &pfx_1_1_1_1_s_32, 0);
1424 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1425 tm->hw[0]->sw_if_index),
1426 "RPF list for adj-fib contains adj");
1429 * +1 entry and +1 shared-path-list
1431 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1432 fib_path_list_db_size());
1433 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1434 fib_path_list_pool_size());
1435 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
1436 fib_entry_pool_size());
1438 fib_prefix_t bgp_101_pfx = {
1440 .fp_proto = FIB_PROTOCOL_IP4,
1442 /* 100.100.100.101/32 */
1443 .ip4.as_u32 = clib_host_to_net_u32(0x64646465),
1447 fib_table_entry_path_add(fib_index,
1450 FIB_ENTRY_FLAG_NONE,
1453 ~0, // no index provided.
1454 fib_index, // nexthop in same fib as route
1457 FIB_ROUTE_PATH_FLAG_NONE);
1459 FIB_TEST_REC_FORW(&bgp_101_pfx, &pfx_1_1_1_1_s_32, 0);
1460 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1461 tm->hw[0]->sw_if_index),
1462 "RPF list for adj-fib contains adj");
1465 * +1 entry, but the recursive path-list is shared.
1467 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1468 fib_path_list_db_size());
1469 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1470 fib_path_list_pool_size());
1471 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
1472 fib_entry_pool_size());
1475 * An special route; one where the user (me) provides the
1476 * adjacency through which the route will resovle by setting the flags
1478 fib_prefix_t ex_pfx = {
1480 .fp_proto = FIB_PROTOCOL_IP4,
1483 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
1487 fib_table_entry_special_add(fib_index,
1490 FIB_ENTRY_FLAG_LOCAL);
1491 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1492 dpo = fib_entry_contribute_ip_forwarding(fei);
1493 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
1494 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
1495 "local interface adj is local");
1497 fib_table_entry_special_remove(fib_index,
1499 FIB_SOURCE_SPECIAL);
1500 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1501 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1502 "Exclusive reoute removed");
1505 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1506 * adjacency through which the route will resovle
1508 dpo_id_t ex_dpo = DPO_INVALID;
1510 lookup_dpo_add_or_lock_w_fib_index(fib_index,
1513 LOOKUP_INPUT_DST_ADDR,
1514 LOOKUP_TABLE_FROM_CONFIG,
1517 fib_table_entry_special_dpo_add(fib_index,
1520 FIB_ENTRY_FLAG_EXCLUSIVE,
1522 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1523 dpo = fib_entry_contribute_ip_forwarding(fei);
1524 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1525 "exclusive remote uses lookup DPO");
1528 * update the exclusive to use a different DPO
1530 ip_null_dpo_add_and_lock(DPO_PROTO_IP4,
1531 IP_NULL_ACTION_SEND_ICMP_UNREACH,
1533 fib_table_entry_special_dpo_update(fib_index,
1536 FIB_ENTRY_FLAG_EXCLUSIVE,
1538 dpo = fib_entry_contribute_ip_forwarding(fei);
1539 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1540 "exclusive remote uses now uses NULL DPO");
1542 fib_table_entry_special_remove(fib_index,
1544 FIB_SOURCE_SPECIAL);
1545 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1546 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1547 "Exclusive reoute removed");
1551 * Add a recursive route:
1552 * 200.200.200.200/32 via 1.1.1.2/32 => the via entry is NOT installed.
1554 fib_prefix_t bgp_200_pfx = {
1556 .fp_proto = FIB_PROTOCOL_IP4,
1558 /* 200.200.200.200/32 */
1559 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c8),
1563 fib_prefix_t pfx_1_1_1_2_s_32 = {
1565 .fp_proto = FIB_PROTOCOL_IP4,
1567 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
1571 fei = fib_table_entry_path_add(fib_index,
1574 FIB_ENTRY_FLAG_NONE,
1576 &pfx_1_1_1_2_s_32.fp_addr,
1577 ~0, // no index provided.
1578 fib_index, // nexthop in same fib as route
1581 FIB_ROUTE_PATH_FLAG_NONE);
1583 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
1584 "Recursive via unresolved is drop");
1587 * the adj should be recursive via drop, since the route resolves via
1588 * the default route, which is itself a DROP
1590 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
1591 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1592 FIB_TEST(load_balance_is_drop(dpo1), "1.1.1.2/32 is drop");
1593 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1594 "RPF list for 1.1.1.2/32 contains 0 adjs");
1597 * +2 entry and +1 shared-path-list
1599 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
1600 fib_path_list_db_size());
1601 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
1602 fib_path_list_pool_size());
1603 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
1604 fib_entry_pool_size());
1607 * Unequal Cost load-balance. 3:1 ratio. fits in a 4 bucket LB
1608 * The paths are sort by NH first. in this case the the path with greater
1609 * weight is first in the set. This ordering is to test the RPF sort|uniq logic
1611 fib_prefix_t pfx_1_2_3_4_s_32 = {
1613 .fp_proto = FIB_PROTOCOL_IP4,
1615 .ip4.as_u32 = clib_host_to_net_u32(0x01020304),
1618 fib_table_entry_path_add(fib_index,
1621 FIB_ENTRY_FLAG_NONE,
1624 tm->hw[0]->sw_if_index,
1628 FIB_ROUTE_PATH_FLAG_NONE);
1629 fei = fib_table_entry_path_add(fib_index,
1632 FIB_ENTRY_FLAG_NONE,
1635 tm->hw[1]->sw_if_index,
1639 FIB_ROUTE_PATH_FLAG_NONE);
1641 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.4/32 presnet");
1642 dpo = fib_entry_contribute_ip_forwarding(fei);
1643 lb = load_balance_get(dpo->dpoi_index);
1644 FIB_TEST((lb->lb_n_buckets == 4),
1645 "1.2.3.4/32 LB has %d bucket",
1648 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 0, ai_12_12_12_12);
1649 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 1, ai_12_12_12_12);
1650 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 2, ai_12_12_12_12);
1651 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 3, ai_01);
1653 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1654 tm->hw[0]->sw_if_index,
1655 tm->hw[1]->sw_if_index),
1656 "RPF list for 1.2.3.4/32 contains both adjs");
1660 * Unequal Cost load-balance. 4:1 ratio.
1661 * fits in a 16 bucket LB with ratio 13:3
1663 fib_prefix_t pfx_1_2_3_5_s_32 = {
1665 .fp_proto = FIB_PROTOCOL_IP4,
1667 .ip4.as_u32 = clib_host_to_net_u32(0x01020305),
1670 fib_table_entry_path_add(fib_index,
1673 FIB_ENTRY_FLAG_NONE,
1676 tm->hw[1]->sw_if_index,
1680 FIB_ROUTE_PATH_FLAG_NONE);
1681 fei = fib_table_entry_path_add(fib_index,
1684 FIB_ENTRY_FLAG_NONE,
1687 tm->hw[0]->sw_if_index,
1691 FIB_ROUTE_PATH_FLAG_NONE);
1693 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.5/32 presnet");
1694 dpo = fib_entry_contribute_ip_forwarding(fei);
1695 lb = load_balance_get(dpo->dpoi_index);
1696 FIB_TEST((lb->lb_n_buckets == 16),
1697 "1.2.3.5/32 LB has %d bucket",
1700 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 0, ai_01);
1701 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 1, ai_01);
1702 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 2, ai_01);
1703 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 3, ai_01);
1704 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 4, ai_01);
1705 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 5, ai_01);
1706 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 6, ai_01);
1707 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 7, ai_01);
1708 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 8, ai_01);
1709 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 9, ai_01);
1710 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 10, ai_01);
1711 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 11, ai_01);
1712 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 12, ai_01);
1713 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 13, ai_12_12_12_12);
1714 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 14, ai_12_12_12_12);
1715 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 15, ai_12_12_12_12);
1717 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1718 tm->hw[0]->sw_if_index,
1719 tm->hw[1]->sw_if_index),
1720 "RPF list for 1.2.3.4/32 contains both adjs");
1723 * Test UCMP with a large weight skew - this produces load-balance objects with large
1724 * numbers of buckets to accommodate the skew. By updating said load-balances we are
1725 * laso testing the LB in placce modify code when number of buckets is large.
1727 fib_prefix_t pfx_6_6_6_6_s_32 = {
1729 .fp_proto = FIB_PROTOCOL_IP4,
1732 .ip4.as_u32 = clib_host_to_net_u32(0x06060606),
1735 fib_test_lb_bucket_t ip_o_10_10_10_1 = {
1741 fib_test_lb_bucket_t ip_o_10_10_10_2 = {
1747 fib_test_lb_bucket_t ip_6_6_6_6_o_12_12_12_12 = {
1750 .adj = ai_12_12_12_12,
1753 fib_table_entry_update_one_path(fib_index,
1756 FIB_ENTRY_FLAG_NONE,
1759 tm->hw[0]->sw_if_index,
1760 ~0, // invalid fib index
1763 FIB_ROUTE_PATH_FLAG_NONE);
1765 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1766 FIB_TEST(!fib_test_validate_entry(fei,
1767 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1770 "6.6.6.6/32 via 10.10.10.1");
1772 fib_table_entry_path_add(fib_index,
1775 FIB_ENTRY_FLAG_NONE,
1778 tm->hw[0]->sw_if_index,
1779 ~0, // invalid fib index
1782 FIB_ROUTE_PATH_FLAG_NONE);
1784 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1785 FIB_TEST(!fib_test_validate_entry(fei,
1786 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1852 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1854 fib_table_entry_path_add(fib_index,
1857 FIB_ENTRY_FLAG_NONE,
1860 tm->hw[1]->sw_if_index,
1861 ~0, // invalid fib index
1864 FIB_ROUTE_PATH_FLAG_NONE);
1866 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1867 FIB_TEST(!fib_test_validate_entry(fei,
1868 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1935 &ip_6_6_6_6_o_12_12_12_12,
1936 &ip_6_6_6_6_o_12_12_12_12,
1937 &ip_6_6_6_6_o_12_12_12_12,
1938 &ip_6_6_6_6_o_12_12_12_12,
1939 &ip_6_6_6_6_o_12_12_12_12,
1940 &ip_6_6_6_6_o_12_12_12_12,
1941 &ip_6_6_6_6_o_12_12_12_12,
1942 &ip_6_6_6_6_o_12_12_12_12,
1943 &ip_6_6_6_6_o_12_12_12_12,
1944 &ip_6_6_6_6_o_12_12_12_12,
1945 &ip_6_6_6_6_o_12_12_12_12,
1946 &ip_6_6_6_6_o_12_12_12_12,
1947 &ip_6_6_6_6_o_12_12_12_12,
1948 &ip_6_6_6_6_o_12_12_12_12,
1949 &ip_6_6_6_6_o_12_12_12_12,
1950 &ip_6_6_6_6_o_12_12_12_12,
1951 &ip_6_6_6_6_o_12_12_12_12,
1952 &ip_6_6_6_6_o_12_12_12_12,
1953 &ip_6_6_6_6_o_12_12_12_12,
1954 &ip_6_6_6_6_o_12_12_12_12,
1955 &ip_6_6_6_6_o_12_12_12_12,
1956 &ip_6_6_6_6_o_12_12_12_12,
1957 &ip_6_6_6_6_o_12_12_12_12,
1958 &ip_6_6_6_6_o_12_12_12_12,
1959 &ip_6_6_6_6_o_12_12_12_12,
1960 &ip_6_6_6_6_o_12_12_12_12,
1961 &ip_6_6_6_6_o_12_12_12_12,
1962 &ip_6_6_6_6_o_12_12_12_12,
1963 &ip_6_6_6_6_o_12_12_12_12,
1964 &ip_6_6_6_6_o_12_12_12_12,
1965 &ip_6_6_6_6_o_12_12_12_12,
1966 &ip_6_6_6_6_o_12_12_12_12,
1967 &ip_6_6_6_6_o_12_12_12_12,
1968 &ip_6_6_6_6_o_12_12_12_12,
1969 &ip_6_6_6_6_o_12_12_12_12,
1970 &ip_6_6_6_6_o_12_12_12_12,
1971 &ip_6_6_6_6_o_12_12_12_12,
1972 &ip_6_6_6_6_o_12_12_12_12,
1973 &ip_6_6_6_6_o_12_12_12_12,
1974 &ip_6_6_6_6_o_12_12_12_12,
1975 &ip_6_6_6_6_o_12_12_12_12,
1976 &ip_6_6_6_6_o_12_12_12_12,
1977 &ip_6_6_6_6_o_12_12_12_12,
1978 &ip_6_6_6_6_o_12_12_12_12,
1979 &ip_6_6_6_6_o_12_12_12_12,
1980 &ip_6_6_6_6_o_12_12_12_12,
1981 &ip_6_6_6_6_o_12_12_12_12,
1982 &ip_6_6_6_6_o_12_12_12_12,
1983 &ip_6_6_6_6_o_12_12_12_12,
1984 &ip_6_6_6_6_o_12_12_12_12,
1985 &ip_6_6_6_6_o_12_12_12_12,
1986 &ip_6_6_6_6_o_12_12_12_12,
1987 &ip_6_6_6_6_o_12_12_12_12,
1988 &ip_6_6_6_6_o_12_12_12_12,
1989 &ip_6_6_6_6_o_12_12_12_12,
1990 &ip_6_6_6_6_o_12_12_12_12,
1991 &ip_6_6_6_6_o_12_12_12_12,
1992 &ip_6_6_6_6_o_12_12_12_12,
1993 &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 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
2000 fib_table_entry_path_remove(fib_index,
2005 tm->hw[1]->sw_if_index,
2006 ~0, // invalid fib index
2008 FIB_ROUTE_PATH_FLAG_NONE);
2010 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
2011 FIB_TEST(!fib_test_validate_entry(fei,
2012 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2078 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
2080 fib_table_entry_path_remove(fib_index,
2085 tm->hw[0]->sw_if_index,
2086 ~0, // invalid fib index
2088 FIB_ROUTE_PATH_FLAG_NONE);
2090 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
2091 FIB_TEST(!fib_test_validate_entry(fei,
2092 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2095 "6.6.6.6/32 via 10.10.10.1");
2097 fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API);
2100 * A recursive via the two unequal cost entries
2102 fib_prefix_t bgp_44_s_32 = {
2104 .fp_proto = FIB_PROTOCOL_IP4,
2106 /* 200.200.200.201/32 */
2107 .ip4.as_u32 = clib_host_to_net_u32(0x44444444),
2110 fei = fib_table_entry_path_add(fib_index,
2113 FIB_ENTRY_FLAG_NONE,
2115 &pfx_1_2_3_4_s_32.fp_addr,
2120 FIB_ROUTE_PATH_FLAG_NONE);
2121 fei = fib_table_entry_path_add(fib_index,
2124 FIB_ENTRY_FLAG_NONE,
2126 &pfx_1_2_3_5_s_32.fp_addr,
2131 FIB_ROUTE_PATH_FLAG_NONE);
2133 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_4_s_32, 0);
2134 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_5_s_32, 1);
2135 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
2136 tm->hw[0]->sw_if_index,
2137 tm->hw[1]->sw_if_index),
2138 "RPF list for 1.2.3.4/32 contains both adjs");
2141 * test the uRPF check functions
2143 dpo_id_t dpo_44 = DPO_INVALID;
2146 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
2147 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
2149 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
2150 "uRPF check for 68.68.68.68/32 on %d OK",
2151 tm->hw[0]->sw_if_index);
2152 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
2153 "uRPF check for 68.68.68.68/32 on %d OK",
2154 tm->hw[1]->sw_if_index);
2155 FIB_TEST(!fib_urpf_check(urpfi, 99),
2156 "uRPF check for 68.68.68.68/32 on 99 not-OK",
2160 fib_table_entry_delete(fib_index,
2163 fib_table_entry_delete(fib_index,
2166 fib_table_entry_delete(fib_index,
2171 * Add a recursive route:
2172 * 200.200.200.201/32 via 1.1.1.200/32 => the via entry is NOT installed.
2174 fib_prefix_t bgp_201_pfx = {
2176 .fp_proto = FIB_PROTOCOL_IP4,
2178 /* 200.200.200.201/32 */
2179 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c9),
2183 fib_prefix_t pfx_1_1_1_200_s_32 = {
2185 .fp_proto = FIB_PROTOCOL_IP4,
2187 .ip4.as_u32 = clib_host_to_net_u32(0x010101c8),
2191 fei = fib_table_entry_path_add(fib_index,
2194 FIB_ENTRY_FLAG_NONE,
2196 &pfx_1_1_1_200_s_32.fp_addr,
2197 ~0, // no index provided.
2198 fib_index, // nexthop in same fib as route
2201 FIB_ROUTE_PATH_FLAG_NONE);
2203 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2204 "Recursive via unresolved is drop");
2206 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2207 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
2208 "Flags set on RR via non-attached");
2209 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
2210 "RPF list for BGP route empty");
2213 * +2 entry (BGP & RR) and +1 shared-path-list
2215 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2216 fib_path_list_db_size());
2217 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2218 fib_path_list_pool_size());
2219 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2220 fib_entry_pool_size());
2223 * insert a route that covers the missing 1.1.1.2/32. we epxect
2224 * 200.200.200.200/32 and 200.200.200.201/32 to resolve through it.
2226 fib_prefix_t pfx_1_1_1_0_s_24 = {
2228 .fp_proto = FIB_PROTOCOL_IP4,
2231 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2235 fib_table_entry_path_add(fib_index,
2238 FIB_ENTRY_FLAG_NONE,
2241 tm->hw[0]->sw_if_index,
2242 ~0, // invalid fib index
2245 FIB_ROUTE_PATH_FLAG_NONE);
2246 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24);
2247 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2248 ai = fib_entry_get_adj(fei);
2249 FIB_TEST((ai_01 == ai), "1.1.1.0/24 resolves via 10.10.10.1");
2250 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2251 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2252 ai = fib_entry_get_adj(fei);
2253 FIB_TEST((ai_01 == ai), "1.1.1.2/32 resolves via 10.10.10.1");
2254 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_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.200/24 resolves via 10.10.10.1");
2260 * +1 entry. 1.1.1.1/32 already uses 10.10.10.1 so no new pah-list
2262 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2263 fib_path_list_db_size());
2264 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2265 fib_path_list_pool_size());
2266 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
2267 fib_entry_pool_size());
2270 * the recursive adj for 200.200.200.200 should be updated.
2272 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2273 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2274 fei = fib_table_lookup(fib_index, &bgp_200_pfx);
2275 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
2276 tm->hw[0]->sw_if_index),
2277 "RPF list for BGP route has itf index 0");
2280 * insert a more specific route than 1.1.1.0/24 that also covers the
2281 * missing 1.1.1.2/32, but not 1.1.1.200/32. we expect
2282 * 200.200.200.200 to resolve through it.
2284 fib_prefix_t pfx_1_1_1_0_s_28 = {
2286 .fp_proto = FIB_PROTOCOL_IP4,
2289 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2293 fib_table_entry_path_add(fib_index,
2296 FIB_ENTRY_FLAG_NONE,
2299 tm->hw[0]->sw_if_index,
2300 ~0, // invalid fib index
2303 FIB_ROUTE_PATH_FLAG_NONE);
2304 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28);
2305 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2306 ai = fib_entry_get_adj(fei);
2307 FIB_TEST((ai_02 == ai), "1.1.1.0/24 resolves via 10.10.10.2");
2310 * +1 entry. +1 shared path-list
2312 FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d",
2313 fib_path_list_db_size());
2314 FIB_TEST((PNBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
2315 fib_path_list_pool_size());
2316 FIB_TEST((ENBR+14 == fib_entry_pool_size()), "entry pool size is %d",
2317 fib_entry_pool_size());
2320 * the recursive adj for 200.200.200.200 should be updated.
2321 * 200.200.200.201 remains unchanged.
2323 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2324 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2327 * remove this /28. 200.200.200.200/32 should revert back to via 1.1.1.0/24
2329 fib_table_entry_path_remove(fib_index,
2334 tm->hw[0]->sw_if_index,
2337 FIB_ROUTE_PATH_FLAG_NONE);
2338 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28) ==
2339 FIB_NODE_INDEX_INVALID),
2340 "1.1.1.0/28 removed");
2341 FIB_TEST((fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28) ==
2342 fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24)),
2343 "1.1.1.0/28 lookup via /24");
2344 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2345 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2348 * -1 entry. -1 shared path-list
2350 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2351 fib_path_list_db_size());
2352 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2353 fib_path_list_pool_size());
2354 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
2355 fib_entry_pool_size());
2358 * remove 1.1.1.0/24. 200.200.200.200/32 should revert back to via 0.0.0.0/0
2360 fib_table_entry_path_remove(fib_index,
2365 tm->hw[0]->sw_if_index,
2368 FIB_ROUTE_PATH_FLAG_NONE);
2369 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_24) ==
2370 FIB_NODE_INDEX_INVALID),
2371 "1.1.1.0/24 removed");
2373 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2374 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2375 "1.1.1.2/32 route is DROP");
2376 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2377 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2378 "1.1.1.200/32 route is DROP");
2380 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2381 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2383 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2384 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2390 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2391 fib_path_list_db_size());
2392 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2393 fib_path_list_pool_size());
2394 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2395 fib_entry_pool_size());
2398 * insert the missing 1.1.1.2/32
2400 fei = fib_table_entry_path_add(fib_index,
2403 FIB_ENTRY_FLAG_NONE,
2406 tm->hw[0]->sw_if_index,
2407 ~0, // invalid fib index
2410 FIB_ROUTE_PATH_FLAG_NONE);
2411 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2412 ai = fib_entry_get_adj(fei);
2413 FIB_TEST((ai = ai_01), "1.1.1.2/32 resolves via 10.10.10.1");
2415 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2416 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2418 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2421 * no change. 1.1.1.2/32 was already there RR sourced.
2423 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2424 fib_path_list_db_size());
2425 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2426 fib_path_list_pool_size());
2427 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2428 fib_entry_pool_size());
2431 * give 201 a resolved path.
2432 * it now has the unresolved 1.1.1.200 and the resolved 1.1.1.2,
2433 * only the latter contributes forwarding.
2435 fei = fib_table_entry_path_add(fib_index,
2438 FIB_ENTRY_FLAG_NONE,
2440 &pfx_1_1_1_2_s_32.fp_addr,
2445 FIB_ROUTE_PATH_FLAG_NONE);
2446 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_2_s_32, 0);
2447 fib_table_entry_path_remove(fib_index,
2451 &pfx_1_1_1_2_s_32.fp_addr,
2455 FIB_ROUTE_PATH_FLAG_NONE);
2458 * remove 200.200.200.201/32 which does not have a valid via FIB
2460 fib_table_entry_path_remove(fib_index,
2464 &pfx_1_1_1_200_s_32.fp_addr,
2465 ~0, // no index provided.
2468 FIB_ROUTE_PATH_FLAG_NONE);
2471 * -2 entries (BGP and RR). -1 shared path-list;
2473 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2474 FIB_NODE_INDEX_INVALID),
2475 "200.200.200.201/32 removed");
2476 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32) ==
2477 FIB_NODE_INDEX_INVALID),
2478 "1.1.1.200/32 removed");
2480 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2481 fib_path_list_db_size());
2482 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
2483 fib_path_list_pool_size());
2484 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2485 fib_entry_pool_size());
2488 * remove 200.200.200.200/32 which does have a valid via FIB
2490 fib_table_entry_path_remove(fib_index,
2494 &pfx_1_1_1_2_s_32.fp_addr,
2495 ~0, // no index provided.
2498 FIB_ROUTE_PATH_FLAG_NONE);
2500 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2501 FIB_NODE_INDEX_INVALID),
2502 "200.200.200.200/32 removed");
2503 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32) !=
2504 FIB_NODE_INDEX_INVALID),
2505 "1.1.1.2/32 still present");
2508 * -1 entry (BGP, the RR source is also API sourced). -1 shared path-list;
2510 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2511 fib_path_list_db_size());
2512 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2513 fib_path_list_pool_size());
2514 FIB_TEST((ENBR+9 == fib_entry_pool_size()), "entry pool size is %d",
2515 fib_entry_pool_size());
2518 * A recursive prefix that has a 2 path load-balance.
2519 * It also shares a next-hop with other BGP prefixes and hence
2520 * test the ref counting of RR sourced prefixes and 2 level LB.
2522 const fib_prefix_t bgp_102 = {
2524 .fp_proto = FIB_PROTOCOL_IP4,
2526 /* 100.100.100.101/32 */
2527 .ip4.as_u32 = clib_host_to_net_u32(0x64646466),
2530 fib_table_entry_path_add(fib_index,
2533 FIB_ENTRY_FLAG_NONE,
2535 &pfx_1_1_1_1_s_32.fp_addr,
2536 ~0, // no index provided.
2537 fib_index, // same as route
2540 FIB_ROUTE_PATH_FLAG_NONE);
2541 fib_table_entry_path_add(fib_index,
2544 FIB_ENTRY_FLAG_NONE,
2546 &pfx_1_1_1_2_s_32.fp_addr,
2547 ~0, // no index provided.
2548 fib_index, // same as route's FIB
2551 FIB_ROUTE_PATH_FLAG_NONE);
2552 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2553 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "100.100.100.102/32 presnet");
2554 dpo = fib_entry_contribute_ip_forwarding(fei);
2556 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2557 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2558 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32);
2559 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2561 lb = load_balance_get(dpo->dpoi_index);
2562 FIB_TEST((lb->lb_n_buckets == 2), "Recursive LB has %d bucket", lb->lb_n_buckets);
2563 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2564 "First via 10.10.10.1");
2565 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 1)),
2566 "Second via 10.10.10.1");
2568 fib_table_entry_path_remove(fib_index,
2572 &pfx_1_1_1_1_s_32.fp_addr,
2573 ~0, // no index provided.
2574 fib_index, // same as route's FIB
2576 FIB_ROUTE_PATH_FLAG_NONE);
2577 fib_table_entry_path_remove(fib_index,
2581 &pfx_1_1_1_2_s_32.fp_addr,
2582 ~0, // no index provided.
2583 fib_index, // same as route's FIB
2585 FIB_ROUTE_PATH_FLAG_NONE);
2586 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2587 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "100.100.100.102/32 removed");
2590 * remove the remaining recursives
2592 fib_table_entry_path_remove(fib_index,
2596 &pfx_1_1_1_1_s_32.fp_addr,
2597 ~0, // no index provided.
2598 fib_index, // same as route's FIB
2600 FIB_ROUTE_PATH_FLAG_NONE);
2601 fib_table_entry_path_remove(fib_index,
2605 &pfx_1_1_1_1_s_32.fp_addr,
2606 ~0, // no index provided.
2607 fib_index, // same as route's FIB
2609 FIB_ROUTE_PATH_FLAG_NONE);
2610 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_100_pfx) ==
2611 FIB_NODE_INDEX_INVALID),
2612 "100.100.100.100/32 removed");
2613 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_101_pfx) ==
2614 FIB_NODE_INDEX_INVALID),
2615 "100.100.100.101/32 removed");
2618 * -2 entry (2*BGP, the RR source is also API sourced). -1 shared path-list;
2620 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2621 fib_path_list_db_size());
2622 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2623 fib_path_list_pool_size());
2624 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2625 fib_entry_pool_size());
2628 * Add a recursive route via a connected cover, using an adj-fib that does exist
2630 fib_table_entry_path_add(fib_index,
2633 FIB_ENTRY_FLAG_NONE,
2636 ~0, // no index provided.
2637 fib_index, // Same as route's FIB
2640 FIB_ROUTE_PATH_FLAG_NONE);
2643 * +1 entry. +1 shared path-list (recursive via 10.10.10.1)
2645 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2646 fib_path_list_db_size());
2647 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2648 fib_path_list_pool_size());
2649 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
2650 fib_entry_pool_size());
2652 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2653 dpo = fib_entry_contribute_ip_forwarding(fei);
2655 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
2656 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2658 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2659 "200.200.200.200/32 is recursive via adj for 10.10.10.1");
2661 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
2662 "Flags set on RR via existing attached");
2665 * Add a recursive route via a connected cover, using and adj-fib that does
2668 ip46_address_t nh_10_10_10_3 = {
2669 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
2671 fib_prefix_t pfx_10_10_10_3 = {
2673 .fp_proto = FIB_PROTOCOL_IP4,
2674 .fp_addr = nh_10_10_10_3,
2677 fib_table_entry_path_add(fib_index,
2680 FIB_ENTRY_FLAG_NONE,
2683 ~0, // no index provided.
2687 FIB_ROUTE_PATH_FLAG_NONE);
2690 * +2 entries (BGP and RR). +1 shared path-list (recursive via 10.10.10.3) and
2691 * one unshared non-recursive via 10.10.10.3
2693 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2694 fib_path_list_db_size());
2695 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2696 fib_path_list_pool_size());
2697 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2698 fib_entry_pool_size());
2700 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
2703 tm->hw[0]->sw_if_index);
2705 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2706 dpo = fib_entry_contribute_ip_forwarding(fei);
2707 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3);
2708 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2710 ai = fib_entry_get_adj(fei);
2711 FIB_TEST((ai == ai_03), "adj for 10.10.10.3/32 is via adj for 10.10.10.3");
2712 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
2713 fib_entry_get_flags(fei)),
2714 "Flags set on RR via non-existing attached");
2716 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2717 "adj for 200.200.200.200/32 is recursive via adj for 10.10.10.3");
2722 * remove the recursives
2724 fib_table_entry_path_remove(fib_index,
2729 ~0, // no index provided.
2730 fib_index, // same as route's FIB
2732 FIB_ROUTE_PATH_FLAG_NONE);
2733 fib_table_entry_path_remove(fib_index,
2738 ~0, // no index provided.
2739 fib_index, // same as route's FIB
2741 FIB_ROUTE_PATH_FLAG_NONE);
2743 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2744 FIB_NODE_INDEX_INVALID),
2745 "200.200.200.201/32 removed");
2746 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2747 FIB_NODE_INDEX_INVALID),
2748 "200.200.200.200/32 removed");
2749 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3) ==
2750 FIB_NODE_INDEX_INVALID),
2751 "10.10.10.3/32 removed");
2754 * -3 entries (2*BGP and RR). -2 shared path-list (recursive via 10.10.10.3 &
2755 * 10.10.10.1) and one unshared non-recursive via 10.10.10.3
2757 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2758 fib_path_list_db_size());
2759 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2760 fib_path_list_pool_size());
2761 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2762 fib_entry_pool_size());
2767 * Add 5.5.5.5/32 -> 5.5.5.6/32 -> 5.5.5.7/32 -> 5.5.5.5/32
2769 fib_prefix_t pfx_5_5_5_5_s_32 = {
2771 .fp_proto = FIB_PROTOCOL_IP4,
2773 .ip4.as_u32 = clib_host_to_net_u32(0x05050505),
2776 fib_prefix_t pfx_5_5_5_6_s_32 = {
2778 .fp_proto = FIB_PROTOCOL_IP4,
2780 .ip4.as_u32 = clib_host_to_net_u32(0x05050506),
2783 fib_prefix_t pfx_5_5_5_7_s_32 = {
2785 .fp_proto = FIB_PROTOCOL_IP4,
2787 .ip4.as_u32 = clib_host_to_net_u32(0x05050507),
2791 fib_table_entry_path_add(fib_index,
2794 FIB_ENTRY_FLAG_NONE,
2796 &pfx_5_5_5_6_s_32.fp_addr,
2797 ~0, // no index provided.
2801 FIB_ROUTE_PATH_FLAG_NONE);
2802 fib_table_entry_path_add(fib_index,
2805 FIB_ENTRY_FLAG_NONE,
2807 &pfx_5_5_5_7_s_32.fp_addr,
2808 ~0, // no index provided.
2812 FIB_ROUTE_PATH_FLAG_NONE);
2813 fib_table_entry_path_add(fib_index,
2816 FIB_ENTRY_FLAG_NONE,
2818 &pfx_5_5_5_5_s_32.fp_addr,
2819 ~0, // no index provided.
2823 FIB_ROUTE_PATH_FLAG_NONE);
2825 * +3 entries, +3 shared path-list
2827 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2828 fib_path_list_db_size());
2829 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2830 fib_path_list_pool_size());
2831 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2832 fib_entry_pool_size());
2835 * All the entries have only looped paths, so they are all drop
2837 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2838 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2839 "LB for 5.5.5.7/32 is via adj for DROP");
2840 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2841 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2842 "LB for 5.5.5.5/32 is via adj for DROP");
2843 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2844 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2845 "LB for 5.5.5.6/32 is via adj for DROP");
2848 * provide 5.5.5.6/32 with alternate path.
2849 * this will allow only 5.5.5.6/32 to forward with this path, the others
2850 * are still drop since the loop is still present.
2852 fib_table_entry_path_add(fib_index,
2855 FIB_ENTRY_FLAG_NONE,
2858 tm->hw[0]->sw_if_index,
2862 FIB_ROUTE_PATH_FLAG_NONE);
2864 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2865 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2867 lb = load_balance_get(dpo1->dpoi_index);
2868 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.6 LB has %d bucket", lb->lb_n_buckets);
2870 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2871 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2872 FIB_TEST((ai_01 == dpo2->dpoi_index),
2873 "5.5.5.6 bucket 0 resolves via 10.10.10.2");
2875 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2876 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2877 "LB for 5.5.5.7/32 is via adj for DROP");
2878 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2879 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2880 "LB for 5.5.5.5/32 is via adj for DROP");
2883 * remove the alternate path for 5.5.5.6/32
2886 fib_table_entry_path_remove(fib_index,
2891 tm->hw[0]->sw_if_index,
2894 FIB_ROUTE_PATH_FLAG_NONE);
2896 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2897 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2898 "LB for 5.5.5.7/32 is via adj for DROP");
2899 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2900 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2901 "LB for 5.5.5.5/32 is via adj for DROP");
2902 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2903 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2904 "LB for 5.5.5.6/32 is via adj for DROP");
2907 * break the loop by giving 5.5.5.5/32 a new set of paths
2908 * expect all to forward via this new path.
2910 fib_table_entry_update_one_path(fib_index,
2913 FIB_ENTRY_FLAG_NONE,
2916 tm->hw[0]->sw_if_index,
2917 ~0, // invalid fib index
2920 FIB_ROUTE_PATH_FLAG_NONE);
2922 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2923 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2924 lb = load_balance_get(dpo1->dpoi_index);
2925 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.5 LB has %d bucket", lb->lb_n_buckets);
2927 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2928 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2929 FIB_TEST((ai_01 == dpo2->dpoi_index),
2930 "5.5.5.5 bucket 0 resolves via 10.10.10.2");
2932 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_7_s_32);
2933 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2935 lb = load_balance_get(dpo2->dpoi_index);
2936 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2937 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo2->dpoi_index, 0)),
2938 "5.5.5.5.7 via 5.5.5.5");
2940 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32);
2941 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2943 lb = load_balance_get(dpo1->dpoi_index);
2944 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2945 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2946 "5.5.5.5.6 via 5.5.5.7");
2949 * revert back to the loop. so we can remove the prefixes with
2952 fib_table_entry_update_one_path(fib_index,
2955 FIB_ENTRY_FLAG_NONE,
2957 &pfx_5_5_5_6_s_32.fp_addr,
2958 ~0, // no index provided.
2962 FIB_ROUTE_PATH_FLAG_NONE);
2964 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2965 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2966 "LB for 5.5.5.7/32 is via adj for DROP");
2967 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2968 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2969 "LB for 5.5.5.5/32 is via adj for DROP");
2970 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2971 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2972 "LB for 5.5.5.6/32 is via adj for DROP");
2975 * remove all the 5.5.5.x/32 prefixes
2977 fib_table_entry_path_remove(fib_index,
2981 &pfx_5_5_5_6_s_32.fp_addr,
2982 ~0, // no index provided.
2983 fib_index, // same as route's FIB
2985 FIB_ROUTE_PATH_FLAG_NONE);
2986 fib_table_entry_path_remove(fib_index,
2990 &pfx_5_5_5_7_s_32.fp_addr,
2991 ~0, // no index provided.
2992 fib_index, // same as route's FIB
2994 FIB_ROUTE_PATH_FLAG_NONE);
2995 fib_table_entry_path_remove(fib_index,
2999 &pfx_5_5_5_5_s_32.fp_addr,
3000 ~0, // no index provided.
3001 fib_index, // same as route's FIB
3003 FIB_ROUTE_PATH_FLAG_NONE);
3004 fib_table_entry_path_remove(fib_index,
3009 ~0, // no index provided.
3010 fib_index, // same as route's FIB
3012 FIB_ROUTE_PATH_FLAG_NONE);
3015 * -3 entries, -3 shared path-list
3017 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3018 fib_path_list_db_size());
3019 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3020 fib_path_list_pool_size());
3021 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3022 fib_entry_pool_size());
3025 * Single level loop 5.5.5.5/32 via 5.5.5.5/32
3027 fib_table_entry_path_add(fib_index,
3030 FIB_ENTRY_FLAG_NONE,
3032 &pfx_5_5_5_6_s_32.fp_addr,
3033 ~0, // no index provided.
3037 FIB_ROUTE_PATH_FLAG_NONE);
3038 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
3039 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
3040 "1-level 5.5.5.6/32 loop is via adj for DROP");
3042 fib_table_entry_path_remove(fib_index,
3046 &pfx_5_5_5_6_s_32.fp_addr,
3047 ~0, // no index provided.
3048 fib_index, // same as route's FIB
3050 FIB_ROUTE_PATH_FLAG_NONE);
3051 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3052 fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32),
3053 "1-level 5.5.5.6/32 loop is removed");
3056 * A recursive route whose next-hop is covered by the prefix.
3057 * This would mean the via-fib, which inherits forwarding from its
3058 * cover, thus picks up forwarding from the prfix, which is via the
3059 * via-fib, and we have a loop.
3061 fib_prefix_t pfx_23_23_23_0_s_24 = {
3063 .fp_proto = FIB_PROTOCOL_IP4,
3065 .ip4.as_u32 = clib_host_to_net_u32(0x17171700),
3068 fib_prefix_t pfx_23_23_23_23_s_32 = {
3070 .fp_proto = FIB_PROTOCOL_IP4,
3072 .ip4.as_u32 = clib_host_to_net_u32(0x17171717),
3075 fei = fib_table_entry_path_add(fib_index,
3076 &pfx_23_23_23_0_s_24,
3078 FIB_ENTRY_FLAG_NONE,
3080 &pfx_23_23_23_23_s_32.fp_addr,
3085 FIB_ROUTE_PATH_FLAG_NONE);
3086 dpo = fib_entry_contribute_ip_forwarding(fei);
3087 FIB_TEST(load_balance_is_drop(dpo),
3088 "23.23.23.0/24 via covered is DROP");
3089 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3092 * add-remove test. no change.
3094 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3095 fib_path_list_db_size());
3096 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3097 fib_path_list_pool_size());
3098 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3099 fib_entry_pool_size());
3102 * Make the default route recursive via a unknown next-hop. Thus the
3103 * next hop's cover would be the default route
3105 fei = fib_table_entry_path_add(fib_index,
3108 FIB_ENTRY_FLAG_NONE,
3110 &pfx_23_23_23_23_s_32.fp_addr,
3115 FIB_ROUTE_PATH_FLAG_NONE);
3116 dpo = fib_entry_contribute_ip_forwarding(fei);
3117 FIB_TEST(load_balance_is_drop(dpo),
3118 "0.0.0.0.0/0 via is DROP");
3119 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3120 "no resolving interface for looped 0.0.0.0/0");
3122 fei = fib_table_lookup_exact_match(fib_index, &pfx_23_23_23_23_s_32);
3123 dpo = fib_entry_contribute_ip_forwarding(fei);
3124 FIB_TEST(load_balance_is_drop(dpo),
3125 "23.23.23.23/32 via is DROP");
3126 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3127 "no resolving interface for looped 23.23.23.23/32");
3129 fib_table_entry_delete(fib_index, &pfx_0_0_0_0_s_0, FIB_SOURCE_API);
3132 * A recursive route with recursion constraints.
3133 * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained
3135 fib_table_entry_path_add(fib_index,
3138 FIB_ENTRY_FLAG_NONE,
3145 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3147 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3148 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3150 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3151 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3153 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3154 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3157 * save the load-balance. we expect it to be inplace modified
3159 lb = load_balance_get(dpo1->dpoi_index);
3162 * add a covering prefix for the via fib that would otherwise serve
3163 * as the resolving route when the host is removed
3165 fib_table_entry_path_add(fib_index,
3168 FIB_ENTRY_FLAG_NONE,
3171 tm->hw[0]->sw_if_index,
3172 ~0, // invalid fib index
3175 FIB_ROUTE_PATH_FLAG_NONE);
3176 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28);
3177 ai = fib_entry_get_adj(fei);
3178 FIB_TEST((ai == ai_01),
3179 "adj for 1.1.1.0/28 is via adj for 1.1.1.1");
3182 * remove the host via FIB - expect the BGP prefix to be drop
3184 fib_table_entry_path_remove(fib_index,
3189 tm->hw[0]->sw_if_index,
3190 ~0, // invalid fib index
3192 FIB_ROUTE_PATH_FLAG_NONE);
3194 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3195 "adj for 200.200.200.200/32 is recursive via adj for DROP");
3198 * add the via-entry host reoute back. expect to resolve again
3200 fib_table_entry_path_add(fib_index,
3203 FIB_ENTRY_FLAG_NONE,
3206 tm->hw[0]->sw_if_index,
3207 ~0, // invalid fib index
3210 FIB_ROUTE_PATH_FLAG_NONE);
3211 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3212 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3215 * add another path for the recursive. it will then have 2.
3217 fib_prefix_t pfx_1_1_1_3_s_32 = {
3219 .fp_proto = FIB_PROTOCOL_IP4,
3221 .ip4.as_u32 = clib_host_to_net_u32(0x01010103),
3224 fib_table_entry_path_add(fib_index,
3227 FIB_ENTRY_FLAG_NONE,
3230 tm->hw[0]->sw_if_index,
3231 ~0, // invalid fib index
3234 FIB_ROUTE_PATH_FLAG_NONE);
3236 fib_table_entry_path_add(fib_index,
3239 FIB_ENTRY_FLAG_NONE,
3241 &pfx_1_1_1_3_s_32.fp_addr,
3246 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3249 * add a bunch load more entries using this path combo so that we get
3250 * an LB-map created.
3253 fib_prefix_t bgp_78s[N_P];
3254 for (ii = 0; ii < N_P; ii++)
3256 bgp_78s[ii].fp_len = 32;
3257 bgp_78s[ii].fp_proto = FIB_PROTOCOL_IP4;
3258 bgp_78s[ii].fp_addr.ip4.as_u32 = clib_host_to_net_u32(0x4e000000+ii);
3261 fib_table_entry_path_add(fib_index,
3264 FIB_ENTRY_FLAG_NONE,
3266 &pfx_1_1_1_3_s_32.fp_addr,
3271 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3272 fib_table_entry_path_add(fib_index,
3275 FIB_ENTRY_FLAG_NONE,
3282 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3285 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3286 dpo = fib_entry_contribute_ip_forwarding(fei);
3288 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3289 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3290 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)),
3291 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3292 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32);
3293 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3294 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)),
3295 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3");
3298 * expect the lb-map used by the recursive's load-balance is using both buckets
3300 load_balance_map_t *lbm;
3303 lb = load_balance_get(dpo->dpoi_index);
3305 load_balance_map_lock(lbmi);
3306 lbm = load_balance_map_get(lbmi);
3308 FIB_TEST(lbm->lbm_buckets[0] == 0,
3309 "LB maps's bucket 0 is %d",
3310 lbm->lbm_buckets[0]);
3311 FIB_TEST(lbm->lbm_buckets[1] == 1,
3312 "LB maps's bucket 1 is %d",
3313 lbm->lbm_buckets[1]);
3316 * withdraw one of the /32 via-entrys.
3317 * that ECMP path will be unresolved and forwarding should continue on the
3318 * other available path. this is an iBGP PIC edge failover.
3319 * Test the forwarding changes without re-fetching the adj from the
3320 * recursive entry. this ensures its the same one that is updated; i.e. an
3323 fib_table_entry_path_remove(fib_index,
3328 tm->hw[0]->sw_if_index,
3329 ~0, // invalid fib index
3331 FIB_ROUTE_PATH_FLAG_NONE);
3333 /* suspend so the update walk kicks int */
3334 vlib_process_suspend(vlib_get_main(), 1e-5);
3336 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3337 FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)),
3338 "post PIC 200.200.200.200/32 was inplace modified");
3340 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)),
3341 "post PIC adj for 200.200.200.200/32 is recursive"
3342 " via adj for 1.1.1.3");
3345 * the LB maps that was locked above should have been modified to remove
3346 * the path that was down, and thus its bucket points to a path that is
3349 FIB_TEST(lbm->lbm_buckets[0] == 1,
3350 "LB maps's bucket 0 is %d",
3351 lbm->lbm_buckets[0]);
3352 FIB_TEST(lbm->lbm_buckets[1] == 1,
3353 "LB maps's bucket 1 is %d",
3354 lbm->lbm_buckets[1]);
3356 load_balance_map_unlock(lbmi);
3359 * add it back. again
3361 fib_table_entry_path_add(fib_index,
3364 FIB_ENTRY_FLAG_NONE,
3367 tm->hw[0]->sw_if_index,
3368 ~0, // invalid fib index
3371 FIB_ROUTE_PATH_FLAG_NONE);
3373 /* suspend so the update walk kicks in */
3374 vlib_process_suspend(vlib_get_main(), 1e-5);
3376 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)),
3377 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3378 "via adj for 1.1.1.1");
3379 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)),
3380 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3381 "via adj for 1.1.1.3");
3383 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3384 dpo = fib_entry_contribute_ip_forwarding(fei);
3385 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3386 "post PIC 200.200.200.200/32 was inplace modified");
3389 * add a 3rd path. this makes the LB 16 buckets.
3391 fib_table_entry_path_add(fib_index,
3394 FIB_ENTRY_FLAG_NONE,
3396 &pfx_1_1_1_2_s_32.fp_addr,
3401 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3402 for (ii = 0; ii < N_P; ii++)
3404 fib_table_entry_path_add(fib_index,
3407 FIB_ENTRY_FLAG_NONE,
3409 &pfx_1_1_1_2_s_32.fp_addr,
3414 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3417 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3418 dpo = fib_entry_contribute_ip_forwarding(fei);
3419 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3420 "200.200.200.200/32 was inplace modified for 3rd path");
3421 FIB_TEST(16 == lb->lb_n_buckets,
3422 "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets");
3425 load_balance_map_lock(lbmi);
3426 lbm = load_balance_map_get(lbmi);
3428 for (ii = 0; ii < 16; ii++)
3430 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3431 "LB Map for 200.200.200.200/32 at %d is %d",
3432 ii, lbm->lbm_buckets[ii]);
3436 * trigger PIC by removing the first via-entry
3437 * the first 6 buckets of the map should map to the next 6
3439 fib_table_entry_path_remove(fib_index,
3444 tm->hw[0]->sw_if_index,
3447 FIB_ROUTE_PATH_FLAG_NONE);
3448 /* suspend so the update walk kicks int */
3449 vlib_process_suspend(vlib_get_main(), 1e-5);
3451 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3452 dpo = fib_entry_contribute_ip_forwarding(fei);
3453 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3454 "200.200.200.200/32 was inplace modified for 3rd path");
3455 FIB_TEST(2 == lb->lb_n_buckets,
3456 "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets");
3458 for (ii = 0; ii < 6; ii++)
3460 FIB_TEST(lbm->lbm_buckets[ii] == ii+6,
3461 "LB Map for 200.200.200.200/32 at %d is %d",
3462 ii, lbm->lbm_buckets[ii]);
3464 for (ii = 6; ii < 16; ii++)
3466 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3467 "LB Map for 200.200.200.200/32 at %d is %d",
3468 ii, lbm->lbm_buckets[ii]);
3470 load_balance_map_unlock(lbmi);
3475 fib_table_entry_path_add(fib_index,
3478 FIB_ENTRY_FLAG_NONE,
3481 tm->hw[0]->sw_if_index,
3485 FIB_ROUTE_PATH_FLAG_NONE);
3487 for (ii = 0; ii < N_P; ii++)
3489 fib_table_entry_delete(fib_index,
3492 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3493 fib_table_lookup_exact_match(fib_index, &bgp_78s[ii])),
3495 format_fib_prefix, &bgp_78s[ii]);
3497 fib_table_entry_path_remove(fib_index,
3501 &pfx_1_1_1_2_s_32.fp_addr,
3505 MPLS_LABEL_INVALID);
3506 fib_table_entry_path_remove(fib_index,
3514 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3515 fib_table_entry_path_remove(fib_index,
3519 &pfx_1_1_1_3_s_32.fp_addr,
3523 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3524 fib_table_entry_delete(fib_index,
3527 fib_table_entry_delete(fib_index,
3530 /* suspend so the update walk kicks int */
3531 vlib_process_suspend(vlib_get_main(), 1e-5);
3532 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3533 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)),
3534 "1.1.1.1/28 removed");
3535 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3536 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)),
3537 "1.1.1.3/32 removed");
3538 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3539 fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)),
3540 "200.200.200.200/32 removed");
3543 * add-remove test. no change.
3545 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3546 fib_path_list_db_size());
3547 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3548 fib_path_list_pool_size());
3549 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3550 fib_entry_pool_size());
3553 * A route whose paths are built up iteratively and then removed
3556 fib_prefix_t pfx_4_4_4_4_s_32 = {
3558 .fp_proto = FIB_PROTOCOL_IP4,
3561 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
3565 fib_table_entry_path_add(fib_index,
3568 FIB_ENTRY_FLAG_NONE,
3571 tm->hw[0]->sw_if_index,
3575 FIB_ROUTE_PATH_FLAG_NONE);
3576 fib_table_entry_path_add(fib_index,
3579 FIB_ENTRY_FLAG_NONE,
3582 tm->hw[0]->sw_if_index,
3586 FIB_ROUTE_PATH_FLAG_NONE);
3587 fib_table_entry_path_add(fib_index,
3590 FIB_ENTRY_FLAG_NONE,
3593 tm->hw[0]->sw_if_index,
3597 FIB_ROUTE_PATH_FLAG_NONE);
3598 FIB_TEST(FIB_NODE_INDEX_INVALID !=
3599 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3600 "4.4.4.4/32 present");
3602 fib_table_entry_delete(fib_index,
3605 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3606 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3607 "4.4.4.4/32 removed");
3610 * add-remove test. no change.
3612 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3613 fib_path_list_db_size());
3614 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3615 fib_path_list_pool_size());
3616 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3617 fib_entry_pool_size());
3620 * A route with multiple paths at once
3622 fib_route_path_t *r_paths = NULL;
3624 for (ii = 0; ii < 4; ii++)
3626 fib_route_path_t r_path = {
3627 .frp_proto = DPO_PROTO_IP4,
3629 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
3631 .frp_sw_if_index = tm->hw[0]->sw_if_index,
3633 .frp_fib_index = ~0,
3635 vec_add1(r_paths, r_path);
3638 fib_table_entry_update(fib_index,
3641 FIB_ENTRY_FLAG_NONE,
3644 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3645 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3646 dpo = fib_entry_contribute_ip_forwarding(fei);
3648 lb = load_balance_get(dpo->dpoi_index);
3649 FIB_TEST((lb->lb_n_buckets == 4), "4.4.4.4/32 lb over %d paths", lb->lb_n_buckets);
3651 fib_table_entry_delete(fib_index,
3654 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3655 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3656 "4.4.4.4/32 removed");
3660 * add-remove test. no change.
3662 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3663 fib_path_list_db_size());
3664 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3665 fib_path_list_pool_size());
3666 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3667 fib_entry_pool_size());
3670 * A route deag route
3672 fib_table_entry_path_add(fib_index,
3675 FIB_ENTRY_FLAG_NONE,
3682 FIB_ROUTE_PATH_FLAG_NONE);
3684 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3685 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3687 dpo = fib_entry_contribute_ip_forwarding(fei);
3688 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3689 lookup_dpo_t *lkd = lookup_dpo_get(dpo->dpoi_index);
3691 FIB_TEST((fib_index == lkd->lkd_fib_index),
3692 "4.4.4.4/32 is deag in %d %U",
3694 format_dpo_id, dpo, 0);
3695 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
3696 "4.4.4.4/32 is source deag in %d %U",
3698 format_dpo_id, dpo, 0);
3700 fib_table_entry_delete(fib_index,
3703 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3704 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3705 "4.4.4.4/32 removed");
3709 * A route deag route in a source lookup table
3711 fib_table_entry_path_add(fib_index,
3714 FIB_ENTRY_FLAG_NONE,
3721 FIB_ROUTE_PATH_SOURCE_LOOKUP);
3723 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3724 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3726 dpo = fib_entry_contribute_ip_forwarding(fei);
3727 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3728 lkd = lookup_dpo_get(dpo->dpoi_index);
3730 FIB_TEST((fib_index == lkd->lkd_fib_index),
3731 "4.4.4.4/32 is deag in %d %U",
3733 format_dpo_id, dpo, 0);
3734 FIB_TEST((LOOKUP_INPUT_SRC_ADDR == lkd->lkd_input),
3735 "4.4.4.4/32 is source deag in %d %U",
3737 format_dpo_id, dpo, 0);
3739 fib_table_entry_delete(fib_index,
3742 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3743 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3744 "4.4.4.4/32 removed");
3748 * add-remove test. no change.
3750 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3751 fib_path_list_db_size());
3752 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3753 fib_path_list_pool_size());
3754 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3755 fib_entry_pool_size());
3759 * add a recursive with duplicate paths. Expect the duplicate to be ignored.
3761 fib_prefix_t pfx_34_1_1_1_s_32 = {
3763 .fp_proto = FIB_PROTOCOL_IP4,
3765 .ip4.as_u32 = clib_host_to_net_u32(0x22010101),
3768 fib_prefix_t pfx_34_34_1_1_s_32 = {
3770 .fp_proto = FIB_PROTOCOL_IP4,
3772 .ip4.as_u32 = clib_host_to_net_u32(0x22220101),
3775 fei = fib_table_entry_path_add(fib_index,
3776 &pfx_34_34_1_1_s_32,
3778 FIB_ENTRY_FLAG_NONE,
3781 tm->hw[0]->sw_if_index,
3785 FIB_ROUTE_PATH_FLAG_NONE);
3786 fei = fib_table_entry_path_add(fib_index,
3789 FIB_ENTRY_FLAG_NONE,
3791 &pfx_34_34_1_1_s_32.fp_addr,
3796 FIB_ROUTE_PATH_FLAG_NONE);
3797 fei = fib_table_entry_path_add(fib_index,
3800 FIB_ENTRY_FLAG_NONE,
3802 &pfx_34_34_1_1_s_32.fp_addr,
3807 FIB_ROUTE_PATH_FLAG_NONE);
3808 FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0);
3809 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3810 fib_table_entry_delete(fib_index,
3811 &pfx_34_34_1_1_s_32,
3816 * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32
3817 * all of which are via 10.10.10.1, Itf1
3819 fib_table_entry_path_remove(fib_index,
3824 tm->hw[0]->sw_if_index,
3827 FIB_ROUTE_PATH_FLAG_NONE);
3828 fib_table_entry_path_remove(fib_index,
3833 tm->hw[0]->sw_if_index,
3836 FIB_ROUTE_PATH_FLAG_NONE);
3837 fib_table_entry_path_remove(fib_index,
3842 tm->hw[0]->sw_if_index,
3845 FIB_ROUTE_PATH_FLAG_NONE);
3847 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3848 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32),
3849 "1.1.1.1/32 removed");
3850 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3851 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32),
3852 "1.1.1.2/32 removed");
3853 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3854 fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24),
3855 "1.1.2.0/24 removed");
3858 * -3 entries and -1 shared path-list
3860 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3861 fib_path_list_db_size());
3862 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3863 fib_path_list_pool_size());
3864 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3865 fib_entry_pool_size());
3868 * An attached-host route. Expect to link to the incomplete adj
3870 fib_prefix_t pfx_4_1_1_1_s_32 = {
3872 .fp_proto = FIB_PROTOCOL_IP4,
3875 .ip4.as_u32 = clib_host_to_net_u32(0x04010101),
3878 fib_table_entry_path_add(fib_index,
3881 FIB_ENTRY_FLAG_NONE,
3884 tm->hw[0]->sw_if_index,
3888 FIB_ROUTE_PATH_FLAG_NONE);
3890 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32);
3891 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present");
3892 ai = fib_entry_get_adj(fei);
3894 ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
3896 &pfx_4_1_1_1_s_32.fp_addr,
3897 tm->hw[0]->sw_if_index);
3898 FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ");
3902 * +1 entry and +1 shared path-list
3904 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3905 fib_path_list_db_size());
3906 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3907 fib_path_list_pool_size());
3908 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
3909 fib_entry_pool_size());
3911 fib_table_entry_delete(fib_index,
3915 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3916 fib_path_list_db_size());
3917 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3918 fib_path_list_pool_size());
3919 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3920 fib_entry_pool_size());
3923 * add a v6 prefix via v4 next-hops
3925 fib_prefix_t pfx_2001_s_64 = {
3927 .fp_proto = FIB_PROTOCOL_IP6,
3929 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
3932 fei = fib_table_entry_path_add(0, //default v6 table
3935 FIB_ENTRY_FLAG_NONE,
3938 tm->hw[0]->sw_if_index,
3942 FIB_ROUTE_PATH_FLAG_NONE);
3944 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
3945 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present");
3946 ai = fib_entry_get_adj(fei);
3948 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
3949 "2001::/64 via ARP-adj");
3950 FIB_TEST((adj->ia_link == VNET_LINK_IP6),
3951 "2001::/64 is link type v6");
3952 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4),
3953 "2001::/64 ADJ-adj is NH proto v4");
3954 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
3957 * add a uRPF exempt prefix:
3959 * - it's forwarding is drop
3960 * - it's uRPF list is not empty
3961 * - the uRPF list for the default route (it's cover) is empty
3963 fei = fib_table_entry_special_add(fib_index,
3965 FIB_SOURCE_URPF_EXEMPT,
3966 FIB_ENTRY_FLAG_DROP);
3967 dpo = fib_entry_contribute_ip_forwarding(fei);
3968 FIB_TEST(load_balance_is_drop(dpo),
3969 "uRPF exempt 4.1.1.1/32 DROP");
3970 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0),
3971 "uRPF list for exempt prefix has itf index 0");
3972 fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0);
3973 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
3974 "uRPF list for 0.0.0.0/0 empty");
3976 fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
3979 * An adj-fib that fails the refinement criteria - no connected cover
3981 fib_prefix_t pfx_12_10_10_2_s_32 = {
3983 .fp_proto = FIB_PROTOCOL_IP4,
3986 .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02),
3990 fib_table_entry_path_add(fib_index,
3991 &pfx_12_10_10_2_s_32,
3993 FIB_ENTRY_FLAG_ATTACHED,
3995 &pfx_12_10_10_2_s_32.fp_addr,
3996 tm->hw[0]->sw_if_index,
3997 ~0, // invalid fib index
4000 FIB_ROUTE_PATH_FLAG_NONE);
4002 fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32);
4003 dpo = fib_entry_contribute_ip_forwarding(fei);
4004 FIB_TEST(dpo_is_drop(dpo),
4005 "no connected cover adj-fib fails refinement: %U",
4006 format_dpo_id, dpo, 0);
4008 fib_table_entry_delete(fib_index,
4009 &pfx_12_10_10_2_s_32,
4013 * An adj-fib that fails the refinement criteria - cover is connected
4014 * but on a different interface
4016 fib_prefix_t pfx_10_10_10_127_s_32 = {
4018 .fp_proto = FIB_PROTOCOL_IP4,
4021 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f),
4025 fib_table_entry_path_add(fib_index,
4026 &pfx_10_10_10_127_s_32,
4028 FIB_ENTRY_FLAG_ATTACHED,
4030 &pfx_10_10_10_127_s_32.fp_addr,
4031 tm->hw[1]->sw_if_index,
4032 ~0, // invalid fib index
4035 FIB_ROUTE_PATH_FLAG_NONE);
4037 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32);
4038 dpo = fib_entry_contribute_ip_forwarding(fei);
4039 FIB_TEST(dpo_is_drop(dpo),
4040 "wrong interface adj-fib fails refinement");
4042 fib_table_entry_delete(fib_index,
4043 &pfx_10_10_10_127_s_32,
4047 * add a second path to an adj-fib
4048 * this is a sumiluation of another ARP entry created
4049 * on an interface on which the connected prefix does not exist.
4050 * The second path fails refinement. Expect to forward through the
4053 fib_prefix_t pfx_10_10_10_3_s_32 = {
4055 .fp_proto = FIB_PROTOCOL_IP4,
4058 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
4062 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
4065 tm->hw[0]->sw_if_index);
4067 fib_test_lb_bucket_t ip_o_10_10_10_3 = {
4073 fei = fib_table_entry_path_add(fib_index,
4074 &pfx_10_10_10_3_s_32,
4076 FIB_ENTRY_FLAG_NONE,
4079 tm->hw[0]->sw_if_index,
4083 FIB_ROUTE_PATH_FLAG_NONE);
4084 fei = fib_table_entry_path_add(fib_index,
4085 &pfx_10_10_10_3_s_32,
4087 FIB_ENTRY_FLAG_NONE,
4090 tm->hw[1]->sw_if_index,
4094 FIB_ROUTE_PATH_FLAG_NONE);
4095 FIB_TEST(!fib_test_validate_entry(fei,
4096 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4099 "10.10.10.3 via 10.10.10.3/Eth0 only");
4102 * remove the path that refines the cover, should go unresolved
4104 fib_table_entry_path_remove(fib_index,
4105 &pfx_10_10_10_3_s_32,
4109 tm->hw[0]->sw_if_index,
4112 FIB_ROUTE_PATH_FLAG_NONE);
4113 dpo = fib_entry_contribute_ip_forwarding(fei);
4114 FIB_TEST(dpo_is_drop(dpo),
4115 "wrong interface adj-fib fails refinement");
4118 * add back the path that refines the cover
4120 fei = fib_table_entry_path_add(fib_index,
4121 &pfx_10_10_10_3_s_32,
4123 FIB_ENTRY_FLAG_NONE,
4126 tm->hw[0]->sw_if_index,
4130 FIB_ROUTE_PATH_FLAG_NONE);
4131 FIB_TEST(!fib_test_validate_entry(fei,
4132 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4135 "10.10.10.3 via 10.10.10.3/Eth0 only");
4138 * remove the path that does not refine the cover
4140 fib_table_entry_path_remove(fib_index,
4141 &pfx_10_10_10_3_s_32,
4145 tm->hw[1]->sw_if_index,
4148 FIB_ROUTE_PATH_FLAG_NONE);
4149 FIB_TEST(!fib_test_validate_entry(fei,
4150 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4153 "10.10.10.3 via 10.10.10.3/Eth0 only");
4156 * remove the path that does refine, it's the last path, so
4157 * the entry should be gone
4159 fib_table_entry_path_remove(fib_index,
4160 &pfx_10_10_10_3_s_32,
4164 tm->hw[0]->sw_if_index,
4167 FIB_ROUTE_PATH_FLAG_NONE);
4168 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
4169 FIB_TEST((fei == FIB_NODE_INDEX_INVALID), "10.10.10.3 gone");
4174 * change the table's flow-hash config - expect the update to propagete to
4175 * the entries' load-balance objects
4177 flow_hash_config_t old_hash_config, new_hash_config;
4179 old_hash_config = fib_table_get_flow_hash_config(fib_index,
4181 new_hash_config = (IP_FLOW_HASH_SRC_ADDR |
4182 IP_FLOW_HASH_DST_ADDR);
4184 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
4185 dpo = fib_entry_contribute_ip_forwarding(fei);
4186 lb = load_balance_get(dpo->dpoi_index);
4187 FIB_TEST((lb->lb_hash_config == old_hash_config),
4188 "Table and LB hash config match: %U",
4189 format_ip_flow_hash_config, lb->lb_hash_config);
4191 fib_table_set_flow_hash_config(fib_index, FIB_PROTOCOL_IP4, new_hash_config);
4193 FIB_TEST((lb->lb_hash_config == new_hash_config),
4194 "Table and LB newhash config match: %U",
4195 format_ip_flow_hash_config, lb->lb_hash_config);
4198 * A route via DVR DPO
4200 fei = fib_table_entry_path_add(fib_index,
4201 &pfx_10_10_10_3_s_32,
4203 FIB_ENTRY_FLAG_NONE,
4206 tm->hw[0]->sw_if_index,
4210 FIB_ROUTE_PATH_DVR);
4211 dpo_id_t dvr_dpo = DPO_INVALID;
4212 dvr_dpo_add_or_lock(tm->hw[0]->sw_if_index, DPO_PROTO_IP4, &dvr_dpo);
4213 fib_test_lb_bucket_t ip_o_l2 = {
4216 .adj = dvr_dpo.dpoi_index,
4220 FIB_TEST(!fib_test_validate_entry(fei,
4221 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4224 "10.10.10.3 via L2 on Eth0");
4225 fib_table_entry_path_remove(fib_index,
4226 &pfx_10_10_10_3_s_32,
4230 tm->hw[0]->sw_if_index,
4233 FIB_ROUTE_PATH_DVR);
4234 dpo_reset(&dvr_dpo);
4237 * add the default route via a next-hop that will form a loop
4239 fib_prefix_t pfx_conn = {
4241 .fp_proto = FIB_PROTOCOL_IP4,
4244 .ip4.as_u32 = clib_host_to_net_u32(0x1e1e1e1e),
4248 dfrt = fib_table_entry_path_add(fib_index,
4251 FIB_ENTRY_FLAG_NONE,
4258 FIB_ROUTE_PATH_FLAG_NONE);
4260 * the default route is a drop, since it's looped
4262 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4263 "Default route is DROP");
4266 * add a connected cover for the next-hop, this breaks the recursion loop
4267 * for the default route
4269 fib_table_entry_path_add(fib_index,
4272 (FIB_ENTRY_FLAG_CONNECTED |
4273 FIB_ENTRY_FLAG_ATTACHED),
4276 tm->hw[0]->sw_if_index,
4280 FIB_ROUTE_PATH_FLAG_NONE);
4281 pfx_conn.fp_len = 32;
4282 fei = fib_table_lookup_exact_match(fib_index, &pfx_conn);
4284 u32 ai_30 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
4287 tm->hw[0]->sw_if_index);
4289 fib_test_lb_bucket_t ip_o_30_30_30_30 = {
4295 FIB_TEST(!fib_test_validate_entry(fei,
4296 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4299 "30.30.30.30 via adj");
4300 FIB_TEST_REC_FORW(&pfx_0_0_0_0_s_0, &pfx_conn, 0);
4302 pfx_conn.fp_len = 24;
4303 fib_table_entry_delete(fib_index,
4306 fib_table_entry_delete(fib_index,
4315 fib_table_entry_delete(fib_index,
4316 &pfx_10_10_10_1_s_32,
4318 fib_table_entry_delete(fib_index,
4319 &pfx_10_10_10_2_s_32,
4321 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4322 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32),
4323 "10.10.10.1/32 adj-fib removed");
4324 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4325 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32),
4326 "10.10.10.2/32 adj-fib removed");
4329 * -2 entries and -2 non-shared path-list
4331 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4332 fib_path_list_db_size());
4333 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
4334 fib_path_list_pool_size());
4335 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
4336 fib_entry_pool_size());
4339 * unlock the adjacencies for which this test provided a rewrite.
4340 * These are the last locks on these adjs. they should thus go away.
4344 adj_unlock(ai_12_12_12_12);
4346 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4351 * remove the interface prefixes
4353 local_pfx.fp_len = 32;
4354 fib_table_entry_special_remove(fib_index, &local_pfx,
4355 FIB_SOURCE_INTERFACE);
4356 fei = fib_table_lookup(fib_index, &local_pfx);
4358 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4359 fib_table_lookup_exact_match(fib_index, &local_pfx),
4360 "10.10.10.10/32 adj-fib removed");
4362 local_pfx.fp_len = 24;
4363 fib_table_entry_delete(fib_index, &local_pfx,
4364 FIB_SOURCE_INTERFACE);
4366 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4367 fib_table_lookup_exact_match(fib_index, &local_pfx),
4368 "10.10.10.10/24 adj-fib removed");
4371 * -2 entries and -2 non-shared path-list
4373 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4374 fib_path_list_db_size());
4375 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
4376 fib_path_list_pool_size());
4377 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
4378 fib_entry_pool_size());
4381 * Last but not least, remove the VRF
4383 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4386 "NO API Source'd prefixes");
4387 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4390 "NO RR Source'd prefixes");
4391 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4393 FIB_SOURCE_INTERFACE)),
4394 "NO INterface Source'd prefixes");
4396 fib_table_unlock(fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
4398 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4399 fib_path_list_db_size());
4400 FIB_TEST((PNBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
4401 fib_path_list_pool_size());
4402 FIB_TEST((ENBR-5 == fib_entry_pool_size()), "entry pool size is %d",
4403 fib_entry_pool_size());
4404 FIB_TEST((ENBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
4405 pool_elts(fib_urpf_list_pool));
4406 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
4407 pool_elts(load_balance_map_pool));
4408 FIB_TEST((lb_count == pool_elts(load_balance_pool)), "LB pool size is %d",
4409 pool_elts(load_balance_pool));
4410 FIB_TEST((0 == pool_elts(dvr_dpo_pool)), "L2 DPO pool size is %d",
4411 pool_elts(dvr_dpo_pool));
4420 * In the default table check for the presence and correct forwarding
4421 * of the special entries
4423 fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02;
4424 const dpo_id_t *dpo, *dpo_drop;
4425 const ip_adjacency_t *adj;
4426 const receive_dpo_t *rd;
4432 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4435 /* via 2001:0:0:1::2 */
4436 ip46_address_t nh_2001_2 = {
4439 [0] = clib_host_to_net_u64(0x2001000000000001),
4440 [1] = clib_host_to_net_u64(0x0000000000000002),
4447 dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
4449 /* Find or create FIB table 11 */
4450 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11,
4453 for (ii = 0; ii < 4; ii++)
4455 ip6_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
4458 fib_prefix_t pfx_0_0 = {
4460 .fp_proto = FIB_PROTOCOL_IP6,
4468 dfrt = fib_table_lookup(fib_index, &pfx_0_0);
4469 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
4470 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4471 "Default route is DROP");
4473 dpo = fib_entry_contribute_ip_forwarding(dfrt);
4474 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4476 &pfx_0_0.fp_addr.ip6)),
4477 "default-route; fwd and non-fwd tables match");
4479 // FIXME - check specials.
4482 * At this stage there is one v4 FIB with 5 routes and two v6 FIBs
4483 * each with 2 entries and a v6 mfib with 4 path-lists and v4 mfib with 2.
4484 * All entries are special so no path-list sharing.
4487 u32 PNPS = (5+4+4+2);
4489 * if the IGMP plugin is loaded this adds two more entries to the v4 MFIB
4491 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
4492 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is %d",
4493 fib_path_list_pool_size());
4494 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
4495 fib_entry_pool_size());
4498 * add interface routes.
4499 * validate presence of /64 attached and /128 recieve.
4500 * test for the presence of the receive address in the glean and local adj
4502 * receive on 2001:0:0:1::1/128
4504 fib_prefix_t local_pfx = {
4506 .fp_proto = FIB_PROTOCOL_IP6,
4510 [0] = clib_host_to_net_u64(0x2001000000000001),
4511 [1] = clib_host_to_net_u64(0x0000000000000001),
4517 fib_table_entry_update_one_path(fib_index, &local_pfx,
4518 FIB_SOURCE_INTERFACE,
4519 (FIB_ENTRY_FLAG_CONNECTED |
4520 FIB_ENTRY_FLAG_ATTACHED),
4523 tm->hw[0]->sw_if_index,
4527 FIB_ROUTE_PATH_FLAG_NONE);
4528 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4530 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4532 ai = fib_entry_get_adj(fei);
4533 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
4535 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4536 "attached interface adj is glean");
4537 dpo = fib_entry_contribute_ip_forwarding(fei);
4538 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4540 &local_pfx.fp_addr.ip6)),
4541 "attached-route; fwd and non-fwd tables match");
4543 local_pfx.fp_len = 128;
4544 fib_table_entry_update_one_path(fib_index, &local_pfx,
4545 FIB_SOURCE_INTERFACE,
4546 (FIB_ENTRY_FLAG_CONNECTED |
4547 FIB_ENTRY_FLAG_LOCAL),
4550 tm->hw[0]->sw_if_index,
4551 ~0, // invalid fib index
4554 FIB_ROUTE_PATH_FLAG_NONE);
4555 fei = fib_table_lookup(fib_index, &local_pfx);
4557 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4559 dpo = fib_entry_contribute_ip_forwarding(fei);
4560 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4561 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4562 "local interface adj is local");
4563 rd = receive_dpo_get(dpo->dpoi_index);
4565 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4567 "local interface adj is receive ok");
4569 dpo = fib_entry_contribute_ip_forwarding(fei);
4570 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4572 &local_pfx.fp_addr.ip6)),
4573 "local-route; fwd and non-fwd tables match");
4574 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4575 &adj->sub_type.glean.rx_pfx.fp_addr)),
4576 "attached interface adj is receive ok");
4579 * +2 entries. +2 unshared path-lists
4581 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
4582 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
4583 fib_path_list_pool_size());
4584 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4585 fib_entry_pool_size());
4588 * Modify the default route to be via an adj not yet known.
4589 * this sources the defalut route with the API source, which is
4590 * a higher preference to the DEFAULT_ROUTE source
4592 fib_table_entry_path_add(fib_index, &pfx_0_0,
4594 FIB_ENTRY_FLAG_NONE,
4597 tm->hw[0]->sw_if_index,
4601 FIB_ROUTE_PATH_FLAG_NONE);
4602 fei = fib_table_lookup(fib_index, &pfx_0_0);
4604 FIB_TEST((fei == dfrt), "default route same index");
4605 ai = fib_entry_get_adj(fei);
4606 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
4608 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4609 "adj is incomplete");
4610 FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)),
4611 "adj nbr next-hop ok");
4614 * find the adj in the shared db
4616 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4619 tm->hw[0]->sw_if_index);
4620 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
4621 adj_unlock(locked_ai);
4624 * no more entries. +1 shared path-list
4626 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4627 fib_path_list_db_size());
4628 FIB_TEST((PNPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
4629 fib_path_list_pool_size());
4630 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4631 fib_entry_pool_size());
4634 * remove the API source from the default route. We expected
4635 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
4637 fib_table_entry_path_remove(fib_index, &pfx_0_0,
4641 tm->hw[0]->sw_if_index,
4644 FIB_ROUTE_PATH_FLAG_NONE);
4645 fei = fib_table_lookup(fib_index, &pfx_0_0);
4647 FIB_TEST((fei == dfrt), "default route same index");
4648 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4649 "Default route is DROP");
4652 * no more entries. -1 shared path-list
4654 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4655 fib_path_list_db_size());
4656 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
4657 fib_path_list_pool_size());
4658 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4659 fib_entry_pool_size());
4662 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4664 fib_prefix_t pfx_2001_1_2_s_128 = {
4666 .fp_proto = FIB_PROTOCOL_IP6,
4670 [0] = clib_host_to_net_u64(0x2001000000000001),
4671 [1] = clib_host_to_net_u64(0x0000000000000002),
4676 fib_prefix_t pfx_2001_1_3_s_128 = {
4678 .fp_proto = FIB_PROTOCOL_IP6,
4682 [0] = clib_host_to_net_u64(0x2001000000000001),
4683 [1] = clib_host_to_net_u64(0x0000000000000003),
4689 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
4692 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4694 &pfx_2001_1_2_s_128.fp_addr,
4695 tm->hw[0]->sw_if_index);
4696 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
4697 adj = adj_get(ai_01);
4698 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4699 "adj is incomplete");
4700 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4701 &adj->sub_type.nbr.next_hop)),
4702 "adj nbr next-hop ok");
4704 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4705 fib_test_build_rewrite(eth_addr));
4706 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4708 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4709 &adj->sub_type.nbr.next_hop)),
4710 "adj nbr next-hop ok");
4712 fib_table_entry_path_add(fib_index,
4713 &pfx_2001_1_2_s_128,
4715 FIB_ENTRY_FLAG_ATTACHED,
4717 &pfx_2001_1_2_s_128.fp_addr,
4718 tm->hw[0]->sw_if_index,
4722 FIB_ROUTE_PATH_FLAG_NONE);
4724 fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
4725 ai = fib_entry_get_adj(fei);
4726 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4730 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4732 &pfx_2001_1_3_s_128.fp_addr,
4733 tm->hw[0]->sw_if_index);
4734 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
4735 adj = adj_get(ai_02);
4736 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4737 "adj is incomplete");
4738 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4739 &adj->sub_type.nbr.next_hop)),
4740 "adj nbr next-hop ok");
4742 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4743 fib_test_build_rewrite(eth_addr));
4744 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4746 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4747 &adj->sub_type.nbr.next_hop)),
4748 "adj nbr next-hop ok");
4749 FIB_TEST((ai_01 != ai_02), "ADJs are different");
4751 fib_table_entry_path_add(fib_index,
4752 &pfx_2001_1_3_s_128,
4754 FIB_ENTRY_FLAG_ATTACHED,
4756 &pfx_2001_1_3_s_128.fp_addr,
4757 tm->hw[0]->sw_if_index,
4761 FIB_ROUTE_PATH_FLAG_NONE);
4763 fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
4764 ai = fib_entry_get_adj(fei);
4765 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4768 * +2 entries, +2 unshread path-lists.
4770 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4771 fib_path_list_db_size());
4772 FIB_TEST((PNPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
4773 fib_path_list_pool_size());
4774 FIB_TEST((ENPS+4 == fib_entry_pool_size()), "entry pool size is %d",
4775 fib_entry_pool_size());
4778 * Add a 2 routes via the first ADJ. ensure path-list sharing
4780 fib_prefix_t pfx_2001_a_s_64 = {
4782 .fp_proto = FIB_PROTOCOL_IP6,
4786 [0] = clib_host_to_net_u64(0x200100000000000a),
4787 [1] = clib_host_to_net_u64(0x0000000000000000),
4792 fib_prefix_t pfx_2001_b_s_64 = {
4794 .fp_proto = FIB_PROTOCOL_IP6,
4798 [0] = clib_host_to_net_u64(0x200100000000000b),
4799 [1] = clib_host_to_net_u64(0x0000000000000000),
4805 fib_table_entry_path_add(fib_index,
4808 FIB_ENTRY_FLAG_NONE,
4811 tm->hw[0]->sw_if_index,
4815 FIB_ROUTE_PATH_FLAG_NONE);
4816 fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64);
4817 ai = fib_entry_get_adj(fei);
4818 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4819 fib_table_entry_path_add(fib_index,
4822 FIB_ENTRY_FLAG_NONE,
4825 tm->hw[0]->sw_if_index,
4829 FIB_ROUTE_PATH_FLAG_NONE);
4830 fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64);
4831 ai = fib_entry_get_adj(fei);
4832 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4835 * +2 entries, +1 shared path-list.
4837 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4838 fib_path_list_db_size());
4839 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4840 fib_path_list_pool_size());
4841 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
4842 fib_entry_pool_size());
4845 * add a v4 prefix via a v6 next-hop
4847 fib_prefix_t pfx_1_1_1_1_s_32 = {
4849 .fp_proto = FIB_PROTOCOL_IP4,
4851 .ip4.as_u32 = 0x01010101,
4854 fei = fib_table_entry_path_add(0, // default table
4857 FIB_ENTRY_FLAG_NONE,
4860 tm->hw[0]->sw_if_index,
4864 FIB_ROUTE_PATH_FLAG_NONE);
4865 FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32),
4866 "1.1.1.1/32 o v6 route present");
4867 ai = fib_entry_get_adj(fei);
4869 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
4870 "1.1.1.1/32 via ARP-adj");
4871 FIB_TEST((adj->ia_link == VNET_LINK_IP4),
4872 "1.1.1.1/32 ADJ-adj is link type v4");
4873 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6),
4874 "1.1.1.1/32 ADJ-adj is NH proto v6");
4875 fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API);
4880 fib_prefix_t pfx_2001_c_s_64 = {
4882 .fp_proto = FIB_PROTOCOL_IP6,
4886 [0] = clib_host_to_net_u64(0x200100000000000c),
4887 [1] = clib_host_to_net_u64(0x0000000000000000),
4892 fib_table_entry_path_add(fib_index,
4895 FIB_ENTRY_FLAG_ATTACHED,
4898 tm->hw[0]->sw_if_index,
4902 FIB_ROUTE_PATH_FLAG_NONE);
4903 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4904 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present");
4905 ai = fib_entry_get_adj(fei);
4907 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN),
4908 "2001:0:0:c/64 attached resolves via glean");
4910 fib_table_entry_path_remove(fib_index,
4915 tm->hw[0]->sw_if_index,
4918 FIB_ROUTE_PATH_FLAG_NONE);
4919 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4920 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached route removed");
4923 * Shutdown the interface on which we have a connected and through
4924 * which the routes are reachable.
4925 * This will result in the connected, adj-fibs, and routes linking to drop
4926 * The local/for-us prefix continues to receive.
4928 clib_error_t * error;
4930 error = vnet_sw_interface_set_flags(vnet_get_main(),
4931 tm->hw[0]->sw_if_index,
4932 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4933 FIB_TEST((NULL == error), "Interface shutdown OK");
4935 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4936 dpo = fib_entry_contribute_ip_forwarding(fei);
4937 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4938 "2001::b/64 resolves via drop");
4940 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4941 dpo = fib_entry_contribute_ip_forwarding(fei);
4942 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4943 "2001::a/64 resolves via drop");
4944 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4945 dpo = fib_entry_contribute_ip_forwarding(fei);
4946 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4947 "2001:0:0:1::3/64 resolves via drop");
4948 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_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::2/64 resolves via drop");
4952 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
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::1/128 not drop");
4956 local_pfx.fp_len = 64;
4957 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4958 dpo = fib_entry_contribute_ip_forwarding(fei);
4959 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4960 "2001:0:0:1/64 resolves via drop");
4965 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4966 fib_path_list_db_size());
4967 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4968 fib_path_list_pool_size());
4969 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
4970 fib_entry_pool_size());
4973 * shutdown one of the other interfaces, then add a connected.
4974 * and swap one of the routes to it.
4976 error = vnet_sw_interface_set_flags(vnet_get_main(),
4977 tm->hw[1]->sw_if_index,
4978 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4979 FIB_TEST((NULL == error), "Interface 1 shutdown OK");
4981 fib_prefix_t connected_pfx = {
4983 .fp_proto = FIB_PROTOCOL_IP6,
4986 /* 2001:0:0:2::1/64 */
4988 [0] = clib_host_to_net_u64(0x2001000000000002),
4989 [1] = clib_host_to_net_u64(0x0000000000000001),
4994 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4995 FIB_SOURCE_INTERFACE,
4996 (FIB_ENTRY_FLAG_CONNECTED |
4997 FIB_ENTRY_FLAG_ATTACHED),
5000 tm->hw[1]->sw_if_index,
5004 FIB_ROUTE_PATH_FLAG_NONE);
5005 fei = fib_table_lookup_exact_match(fib_index, &connected_pfx);
5006 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
5007 dpo = fib_entry_contribute_ip_forwarding(fei);
5008 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
5009 FIB_TEST(!dpo_cmp(dpo, dpo_drop),
5010 "2001:0:0:2/64 not resolves via drop");
5012 connected_pfx.fp_len = 128;
5013 fib_table_entry_update_one_path(fib_index, &connected_pfx,
5014 FIB_SOURCE_INTERFACE,
5015 (FIB_ENTRY_FLAG_CONNECTED |
5016 FIB_ENTRY_FLAG_LOCAL),
5019 tm->hw[0]->sw_if_index,
5020 ~0, // invalid fib index
5023 FIB_ROUTE_PATH_FLAG_NONE);
5024 fei = fib_table_lookup(fib_index, &connected_pfx);
5026 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
5027 dpo = fib_entry_contribute_ip_forwarding(fei);
5028 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
5029 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
5030 "local interface adj is local");
5031 rd = receive_dpo_get(dpo->dpoi_index);
5032 FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr,
5034 "local interface adj is receive ok");
5037 * +2 entries, +2 unshared path-lists
5039 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
5040 fib_path_list_db_size());
5041 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
5042 fib_path_list_pool_size());
5043 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
5044 fib_entry_pool_size());
5048 * bring the interface back up. we expected the routes to return
5049 * to normal forwarding.
5051 error = vnet_sw_interface_set_flags(vnet_get_main(),
5052 tm->hw[0]->sw_if_index,
5053 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5054 FIB_TEST((NULL == error), "Interface bring-up OK");
5055 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5056 ai = fib_entry_get_adj(fei);
5057 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
5058 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5059 ai = fib_entry_get_adj(fei);
5060 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
5061 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5062 ai = fib_entry_get_adj(fei);
5063 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
5064 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5065 ai = fib_entry_get_adj(fei);
5066 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
5067 local_pfx.fp_len = 64;
5068 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5069 ai = fib_entry_get_adj(fei);
5071 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
5072 "attached interface adj is glean");
5075 * Same test as above, but this time the HW interface goes down
5077 error = vnet_hw_interface_set_flags(vnet_get_main(),
5078 tm->hw_if_indicies[0],
5079 ~VNET_HW_INTERFACE_FLAG_LINK_UP);
5080 FIB_TEST((NULL == error), "Interface shutdown OK");
5082 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5083 dpo = fib_entry_contribute_ip_forwarding(fei);
5084 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5085 "2001::b/64 resolves via drop");
5086 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_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::a/64 resolves via drop");
5090 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5091 dpo = fib_entry_contribute_ip_forwarding(fei);
5092 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5093 "2001:0:0:1::3/128 resolves via drop");
5094 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_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::2/128 resolves via drop");
5098 local_pfx.fp_len = 128;
5099 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5100 dpo = fib_entry_contribute_ip_forwarding(fei);
5101 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5102 "2001:0:0:1::1/128 not drop");
5103 local_pfx.fp_len = 64;
5104 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5105 dpo = fib_entry_contribute_ip_forwarding(fei);
5106 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5107 "2001:0:0:1/64 resolves via drop");
5109 error = vnet_hw_interface_set_flags(vnet_get_main(),
5110 tm->hw_if_indicies[0],
5111 VNET_HW_INTERFACE_FLAG_LINK_UP);
5112 FIB_TEST((NULL == error), "Interface bring-up OK");
5113 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5114 ai = fib_entry_get_adj(fei);
5115 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
5116 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5117 ai = fib_entry_get_adj(fei);
5118 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
5119 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5120 ai = fib_entry_get_adj(fei);
5121 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
5122 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5123 ai = fib_entry_get_adj(fei);
5124 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
5125 local_pfx.fp_len = 64;
5126 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5127 ai = fib_entry_get_adj(fei);
5129 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
5130 "attached interface adj is glean");
5133 * Delete the interface that the routes reolve through.
5134 * Again no routes are removed. They all point to drop.
5136 * This is considered an error case. The control plane should
5137 * not remove interfaces through which routes resolve, but
5138 * such things can happen. ALL affected routes will drop.
5140 vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]);
5142 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5143 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5144 "2001::b/64 resolves via drop");
5145 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5146 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5147 "2001::b/64 resolves via drop");
5148 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5149 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5150 "2001:0:0:1::3/64 resolves via drop");
5151 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5152 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5153 "2001:0:0:1::2/64 resolves via drop");
5154 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5155 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5156 "2001:0:0:1::1/128 is drop");
5157 local_pfx.fp_len = 64;
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/64 resolves via drop");
5165 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
5166 fib_path_list_db_size());
5167 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
5168 fib_path_list_pool_size());
5169 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
5170 fib_entry_pool_size());
5173 * Add the interface back. routes stay unresolved.
5175 error = ethernet_register_interface(vnet_get_main(),
5176 test_interface_device_class.index,
5179 &tm->hw_if_indicies[0],
5180 /* flag change */ 0);
5182 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5183 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5184 "2001::b/64 resolves via drop");
5185 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5186 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5187 "2001::b/64 resolves via drop");
5188 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5189 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5190 "2001:0:0:1::3/64 resolves via drop");
5191 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5192 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5193 "2001:0:0:1::2/64 resolves via drop");
5194 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5195 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5196 "2001:0:0:1::1/128 is drop");
5197 local_pfx.fp_len = 64;
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/64 resolves via drop");
5203 * CLEANUP ALL the routes
5205 fib_table_entry_delete(fib_index,
5208 fib_table_entry_delete(fib_index,
5211 fib_table_entry_delete(fib_index,
5214 fib_table_entry_delete(fib_index,
5215 &pfx_2001_1_3_s_128,
5217 fib_table_entry_delete(fib_index,
5218 &pfx_2001_1_2_s_128,
5220 local_pfx.fp_len = 64;
5221 fib_table_entry_delete(fib_index, &local_pfx,
5222 FIB_SOURCE_INTERFACE);
5223 local_pfx.fp_len = 128;
5224 fib_table_entry_special_remove(fib_index, &local_pfx,
5225 FIB_SOURCE_INTERFACE);
5226 connected_pfx.fp_len = 64;
5227 fib_table_entry_delete(fib_index, &connected_pfx,
5228 FIB_SOURCE_INTERFACE);
5229 connected_pfx.fp_len = 128;
5230 fib_table_entry_special_remove(fib_index, &connected_pfx,
5231 FIB_SOURCE_INTERFACE);
5233 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5234 fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)),
5235 "2001::a/64 removed");
5236 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5237 fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)),
5238 "2001::b/64 removed");
5239 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5240 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)),
5241 "2001:0:0:1::3/128 removed");
5242 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5243 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)),
5244 "2001:0:0:1::3/128 removed");
5245 local_pfx.fp_len = 64;
5246 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5247 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5248 "2001:0:0:1/64 removed");
5249 local_pfx.fp_len = 128;
5250 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5251 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5252 "2001:0:0:1::1/128 removed");
5253 connected_pfx.fp_len = 64;
5254 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5255 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5256 "2001:0:0:2/64 removed");
5257 connected_pfx.fp_len = 128;
5258 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5259 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5260 "2001:0:0:2::1/128 removed");
5263 * -8 entries. -7 path-lists (1 was shared).
5265 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5266 fib_path_list_db_size());
5267 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is%d",
5268 fib_path_list_pool_size());
5269 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
5270 fib_entry_pool_size());
5273 * now remove the VRF
5275 fib_table_unlock(fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
5277 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5278 fib_path_list_db_size());
5279 FIB_TEST((PNPS-2 == fib_path_list_pool_size()), "path list pool size is%d",
5280 fib_path_list_pool_size());
5281 FIB_TEST((ENPS-2 == fib_entry_pool_size()), "entry pool size is %d",
5282 fib_entry_pool_size());
5288 * return the interfaces to up state
5290 error = vnet_sw_interface_set_flags(vnet_get_main(),
5291 tm->hw[0]->sw_if_index,
5292 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5293 error = vnet_sw_interface_set_flags(vnet_get_main(),
5294 tm->hw[1]->sw_if_index,
5295 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5297 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5299 FIB_TEST((0 == adj_glean_db_size()), "ADJ DB size is %d",
5300 adj_glean_db_size());
5306 * Test Attached Exports
5311 const dpo_id_t *dpo, *dpo_drop;
5312 const u32 fib_index = 0;
5313 fib_node_index_t dfrt, fei;
5322 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5326 * add interface routes. We'll assume this works. It's more rigorously
5329 fib_prefix_t local_pfx = {
5331 .fp_proto = FIB_PROTOCOL_IP4,
5335 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5340 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
5342 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
5344 fib_table_entry_update_one_path(fib_index, &local_pfx,
5345 FIB_SOURCE_INTERFACE,
5346 (FIB_ENTRY_FLAG_CONNECTED |
5347 FIB_ENTRY_FLAG_ATTACHED),
5350 tm->hw[0]->sw_if_index,
5354 FIB_ROUTE_PATH_FLAG_NONE);
5355 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5356 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5357 "attached interface route present");
5359 local_pfx.fp_len = 32;
5360 fib_table_entry_update_one_path(fib_index, &local_pfx,
5361 FIB_SOURCE_INTERFACE,
5362 (FIB_ENTRY_FLAG_CONNECTED |
5363 FIB_ENTRY_FLAG_LOCAL),
5366 tm->hw[0]->sw_if_index,
5367 ~0, // invalid fib index
5370 FIB_ROUTE_PATH_FLAG_NONE);
5371 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5373 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5374 "local interface route present");
5377 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
5379 fib_prefix_t pfx_10_10_10_1_s_32 = {
5381 .fp_proto = FIB_PROTOCOL_IP4,
5384 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5387 fib_node_index_t ai;
5389 fib_table_entry_path_add(fib_index,
5390 &pfx_10_10_10_1_s_32,
5392 FIB_ENTRY_FLAG_ATTACHED,
5394 &pfx_10_10_10_1_s_32.fp_addr,
5395 tm->hw[0]->sw_if_index,
5396 ~0, // invalid fib index
5399 FIB_ROUTE_PATH_FLAG_NONE);
5401 fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
5402 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
5403 ai = fib_entry_get_adj(fei);
5406 * create another FIB table into which routes will be imported
5408 u32 import_fib_index1;
5410 import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4,
5414 * Add default route in the import FIB
5416 fib_prefix_t pfx_0_0_0_0_s_0 = {
5418 .fp_proto = FIB_PROTOCOL_IP4,
5426 dfrt = fib_table_lookup(import_fib_index1, &pfx_0_0_0_0_s_0);
5427 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
5429 fib_table_entry_path_add(import_fib_index1,
5432 FIB_ENTRY_FLAG_NONE,
5435 tm->hw[0]->sw_if_index,
5436 ~0, // invalid fib index
5439 FIB_ROUTE_PATH_FLAG_NONE);
5440 fei = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
5441 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "default route present");
5442 FIB_TEST((fei != dfrt), "default route added");
5445 * delete default route and check for the presence in the import table
5447 fib_table_entry_delete(import_fib_index1, &pfx_0_0_0_0_s_0, FIB_SOURCE_API);
5448 fei = fib_table_lookup(import_fib_index1, &pfx_0_0_0_0_s_0);
5449 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "default route present");
5450 FIB_TEST((fei == dfrt), "default route removed");
5453 * Add an attached route in the import FIB
5455 local_pfx.fp_len = 24;
5456 fib_table_entry_update_one_path(import_fib_index1,
5459 FIB_ENTRY_FLAG_NONE,
5462 tm->hw[0]->sw_if_index,
5463 ~0, // invalid fib index
5466 FIB_ROUTE_PATH_FLAG_NONE);
5467 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5468 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5471 * check for the presence of the adj-fibs in the import table
5473 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5474 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5475 FIB_TEST((ai == fib_entry_get_adj(fei)),
5476 "adj-fib1 Import uses same adj as export");
5479 * check for the presence of the local in the import table
5481 local_pfx.fp_len = 32;
5482 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5483 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5486 * Add another adj-fin in the export table. Expect this
5487 * to get magically exported;
5489 fib_prefix_t pfx_10_10_10_2_s_32 = {
5491 .fp_proto = FIB_PROTOCOL_IP4,
5494 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5498 fib_table_entry_path_add(fib_index,
5499 &pfx_10_10_10_2_s_32,
5501 FIB_ENTRY_FLAG_ATTACHED,
5503 &pfx_10_10_10_2_s_32.fp_addr,
5504 tm->hw[0]->sw_if_index,
5505 ~0, // invalid fib index
5508 FIB_ROUTE_PATH_FLAG_NONE);
5509 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5510 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
5511 ai = fib_entry_get_adj(fei);
5513 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5514 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5515 FIB_TEST((ai == fib_entry_get_adj(fei)),
5516 "Import uses same adj as export");
5517 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(fei)),
5518 "ADJ-fib2 imported flags %d",
5519 fib_entry_get_flags(fei));
5522 * create a 2nd FIB table into which routes will be imported
5524 u32 import_fib_index2;
5526 import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12,
5530 * Add an attached route in the import FIB
5532 local_pfx.fp_len = 24;
5533 fib_table_entry_update_one_path(import_fib_index2,
5536 FIB_ENTRY_FLAG_NONE,
5539 tm->hw[0]->sw_if_index,
5540 ~0, // invalid fib index
5543 FIB_ROUTE_PATH_FLAG_NONE);
5544 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5545 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5548 * check for the presence of all the adj-fibs and local in the import table
5550 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5551 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5552 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5553 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5554 local_pfx.fp_len = 32;
5555 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5556 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5559 * add a 3rd adj-fib. expect it to be exported to both tables.
5561 fib_prefix_t pfx_10_10_10_3_s_32 = {
5563 .fp_proto = FIB_PROTOCOL_IP4,
5566 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
5570 fib_table_entry_path_add(fib_index,
5571 &pfx_10_10_10_3_s_32,
5573 FIB_ENTRY_FLAG_ATTACHED,
5575 &pfx_10_10_10_3_s_32.fp_addr,
5576 tm->hw[0]->sw_if_index,
5577 ~0, // invalid fib index
5580 FIB_ROUTE_PATH_FLAG_NONE);
5581 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5582 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
5583 ai = fib_entry_get_adj(fei);
5585 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5586 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1");
5587 FIB_TEST((ai == fib_entry_get_adj(fei)),
5588 "Import uses same adj as export");
5589 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5590 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2");
5591 FIB_TEST((ai == fib_entry_get_adj(fei)),
5592 "Import uses same adj as export");
5595 * remove the 3rd adj fib. we expect it to be removed from both FIBs
5597 fib_table_entry_delete(fib_index,
5598 &pfx_10_10_10_3_s_32,
5601 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5602 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved");
5604 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5605 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1");
5607 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5608 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2");
5611 * remove the attached route from the 2nd FIB. expect the imported
5612 * entries to be removed
5614 local_pfx.fp_len = 24;
5615 fib_table_entry_delete(import_fib_index2,
5618 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5619 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed");
5621 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5622 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2");
5623 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5624 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2");
5625 local_pfx.fp_len = 32;
5626 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5627 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2");
5629 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5630 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1");
5631 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5632 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1");
5633 local_pfx.fp_len = 32;
5634 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5635 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1");
5638 * modify the route in FIB1 so it is no longer attached. expect the imported
5639 * entries to be removed
5641 local_pfx.fp_len = 24;
5642 fib_table_entry_update_one_path(import_fib_index1,
5645 FIB_ENTRY_FLAG_NONE,
5647 &pfx_10_10_10_2_s_32.fp_addr,
5648 tm->hw[0]->sw_if_index,
5649 ~0, // invalid fib index
5652 FIB_ROUTE_PATH_FLAG_NONE);
5653 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5654 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5655 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5656 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5657 local_pfx.fp_len = 32;
5658 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5659 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5662 * modify it back to attached. expect the adj-fibs back
5664 local_pfx.fp_len = 24;
5665 fib_table_entry_update_one_path(import_fib_index1,
5668 FIB_ENTRY_FLAG_NONE,
5671 tm->hw[0]->sw_if_index,
5672 ~0, // invalid fib index
5675 FIB_ROUTE_PATH_FLAG_NONE);
5676 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5677 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1");
5678 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5679 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1");
5680 local_pfx.fp_len = 32;
5681 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5682 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1");
5685 * add a covering attached next-hop for the interface address, so we have
5686 * a valid adj to find when we check the forwarding tables
5688 fib_prefix_t pfx_10_0_0_0_s_8 = {
5690 .fp_proto = FIB_PROTOCOL_IP4,
5693 .ip4.as_u32 = clib_host_to_net_u32(0x0a000000),
5697 fei = fib_table_entry_update_one_path(fib_index,
5700 FIB_ENTRY_FLAG_NONE,
5702 &pfx_10_10_10_3_s_32.fp_addr,
5703 tm->hw[0]->sw_if_index,
5704 ~0, // invalid fib index
5707 FIB_ROUTE_PATH_FLAG_NONE);
5708 dpo = fib_entry_contribute_ip_forwarding(fei);
5711 * remove the route in the export fib. expect the adj-fibs to be removed
5713 local_pfx.fp_len = 24;
5714 fib_table_entry_delete(fib_index,
5716 FIB_SOURCE_INTERFACE);
5718 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5719 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1");
5720 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5721 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5722 local_pfx.fp_len = 32;
5723 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5724 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5727 * the adj-fibs in the export VRF are present in the FIB table,
5728 * but not installed in forwarding, since they have no attached cover.
5729 * Consequently a lookup in the MTRIE gives the adj for the covering
5732 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5733 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5736 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5737 FIB_TEST(lbi == dpo->dpoi_index,
5738 "10.10.10.1 forwards on \n%U not \n%U",
5739 format_load_balance, lbi, 0,
5740 format_dpo_id, dpo, 0);
5741 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5742 FIB_TEST(lbi == dpo->dpoi_index,
5743 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5744 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4);
5745 FIB_TEST(lbi == dpo->dpoi_index,
5746 "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0);
5749 * add the export prefix back, but not as attached.
5750 * No adj-fibs in export nor import tables
5752 local_pfx.fp_len = 24;
5753 fei = fib_table_entry_update_one_path(fib_index,
5756 FIB_ENTRY_FLAG_NONE,
5758 &pfx_10_10_10_1_s_32.fp_addr,
5759 tm->hw[0]->sw_if_index,
5760 ~0, // invalid fib index
5763 FIB_ROUTE_PATH_FLAG_NONE);
5764 dpo = fib_entry_contribute_ip_forwarding(fei);
5766 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5767 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export");
5768 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5769 FIB_TEST(lbi == dpo->dpoi_index,
5770 "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0);
5771 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5772 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5773 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5774 FIB_TEST(lbi == dpo->dpoi_index,
5775 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5777 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5778 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5779 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5780 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5781 local_pfx.fp_len = 32;
5782 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5783 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5786 * modify the export prefix so it is attached. expect all covereds to return
5788 local_pfx.fp_len = 24;
5789 fib_table_entry_update_one_path(fib_index,
5792 FIB_ENTRY_FLAG_NONE,
5795 tm->hw[0]->sw_if_index,
5796 ~0, // invalid fib index
5799 FIB_ROUTE_PATH_FLAG_NONE);
5801 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5802 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5803 dpo = fib_entry_contribute_ip_forwarding(fei);
5804 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5805 "Adj-fib1 is not drop in export");
5806 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5807 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5808 local_pfx.fp_len = 32;
5809 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5810 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5811 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5812 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5813 dpo = fib_entry_contribute_ip_forwarding(fei);
5814 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5815 "Adj-fib1 is not drop in export: %U %U",
5816 format_dpo_id, dpo, 0,
5817 format_dpo_id, load_balance_get_bucket(dpo->dpoi_index, 0), 0);
5818 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5819 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5820 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5821 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5822 local_pfx.fp_len = 32;
5823 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5824 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5827 * modify the export prefix so connected. no change.
5829 local_pfx.fp_len = 24;
5830 fib_table_entry_update_one_path(fib_index, &local_pfx,
5831 FIB_SOURCE_INTERFACE,
5832 (FIB_ENTRY_FLAG_CONNECTED |
5833 FIB_ENTRY_FLAG_ATTACHED),
5836 tm->hw[0]->sw_if_index,
5840 FIB_ROUTE_PATH_FLAG_NONE);
5842 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5843 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5844 dpo = fib_entry_contribute_ip_forwarding(fei);
5845 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5846 "Adj-fib1 is not drop in export");
5847 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5848 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5849 local_pfx.fp_len = 32;
5850 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5851 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5852 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5853 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5854 dpo = fib_entry_contribute_ip_forwarding(fei);
5855 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5856 "Adj-fib1 is not drop in export");
5857 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5858 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5859 local_pfx.fp_len = 32;
5860 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5861 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5866 fib_table_entry_delete(fib_index,
5869 fib_table_entry_delete(fib_index,
5870 &pfx_10_10_10_1_s_32,
5872 fib_table_entry_delete(fib_index,
5873 &pfx_10_10_10_2_s_32,
5875 local_pfx.fp_len = 32;
5876 fib_table_entry_delete(fib_index,
5878 FIB_SOURCE_INTERFACE);
5879 local_pfx.fp_len = 24;
5880 fib_table_entry_delete(fib_index,
5883 fib_table_entry_delete(fib_index,
5885 FIB_SOURCE_INTERFACE);
5886 local_pfx.fp_len = 24;
5887 fib_table_entry_delete(import_fib_index1,
5891 fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
5892 fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
5894 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5901 * Test Path Preference
5904 fib_test_pref (void)
5914 const fib_prefix_t pfx_1_1_1_1_s_32 = {
5916 .fp_proto = FIB_PROTOCOL_IP4,
5919 .as_u32 = clib_host_to_net_u32(0x01010101),
5924 for (i = 0; i <= 2; i++)
5925 im->fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
5928 * 2 high, 2 medium and 2 low preference non-recursive paths
5930 fib_route_path_t nr_path_hi_1 = {
5931 .frp_proto = DPO_PROTO_IP4,
5932 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5933 .frp_fib_index = ~0,
5935 .frp_preference = 0,
5936 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5938 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5941 fib_route_path_t nr_path_hi_2 = {
5942 .frp_proto = DPO_PROTO_IP4,
5943 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5944 .frp_fib_index = ~0,
5946 .frp_preference = 0,
5947 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5949 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5952 fib_route_path_t nr_path_med_1 = {
5953 .frp_proto = DPO_PROTO_IP4,
5954 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5955 .frp_fib_index = ~0,
5957 .frp_preference = 1,
5958 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5960 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5963 fib_route_path_t nr_path_med_2 = {
5964 .frp_proto = DPO_PROTO_IP4,
5965 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5966 .frp_fib_index = ~0,
5968 .frp_preference = 1,
5969 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5971 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5974 fib_route_path_t nr_path_low_1 = {
5975 .frp_proto = DPO_PROTO_IP4,
5976 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5977 .frp_fib_index = ~0,
5979 .frp_preference = 2,
5980 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5982 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b01),
5985 fib_route_path_t nr_path_low_2 = {
5986 .frp_proto = DPO_PROTO_IP4,
5987 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5988 .frp_fib_index = ~0,
5990 .frp_preference = 2,
5991 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5993 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b02),
5996 fib_route_path_t *nr_paths = NULL;
5998 vec_add1(nr_paths, nr_path_hi_1);
5999 vec_add1(nr_paths, nr_path_hi_2);
6000 vec_add1(nr_paths, nr_path_med_1);
6001 vec_add1(nr_paths, nr_path_med_2);
6002 vec_add1(nr_paths, nr_path_low_1);
6003 vec_add1(nr_paths, nr_path_low_2);
6005 adj_index_t ai_hi_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6007 &nr_path_hi_1.frp_addr,
6008 nr_path_hi_1.frp_sw_if_index);
6009 adj_index_t ai_hi_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6011 &nr_path_hi_2.frp_addr,
6012 nr_path_hi_2.frp_sw_if_index);
6013 adj_index_t ai_med_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6015 &nr_path_med_1.frp_addr,
6016 nr_path_med_1.frp_sw_if_index);
6017 adj_index_t ai_med_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6019 &nr_path_med_2.frp_addr,
6020 nr_path_med_2.frp_sw_if_index);
6021 adj_index_t ai_low_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6023 &nr_path_low_1.frp_addr,
6024 nr_path_low_1.frp_sw_if_index);
6025 adj_index_t ai_low_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6027 &nr_path_low_2.frp_addr,
6028 nr_path_low_2.frp_sw_if_index);
6030 fib_test_lb_bucket_t ip_hi_1 = {
6036 fib_test_lb_bucket_t ip_hi_2 = {
6042 fib_test_lb_bucket_t ip_med_1 = {
6048 fib_test_lb_bucket_t ip_med_2 = {
6054 fib_test_lb_bucket_t ip_low_1 = {
6060 fib_test_lb_bucket_t ip_low_2 = {
6067 fib_node_index_t fei;
6069 fei = fib_table_entry_path_add2(0,
6072 FIB_ENTRY_FLAG_NONE,
6075 FIB_TEST(!fib_test_validate_entry(fei,
6076 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6080 "1.1.1.1/32 via high preference paths");
6083 * bring down the interface on which the high preference path lie
6085 vnet_sw_interface_set_flags(vnet_get_main(),
6086 tm->hw[0]->sw_if_index,
6089 FIB_TEST(!fib_test_validate_entry(fei,
6090 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6094 "1.1.1.1/32 via medium preference paths");
6097 * bring down the interface on which the medium preference path lie
6099 vnet_sw_interface_set_flags(vnet_get_main(),
6100 tm->hw[1]->sw_if_index,
6103 FIB_TEST(!fib_test_validate_entry(fei,
6104 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6108 "1.1.1.1/32 via low preference paths");
6111 * bring up the interface on which the high preference path lie
6113 vnet_sw_interface_set_flags(vnet_get_main(),
6114 tm->hw[0]->sw_if_index,
6115 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6117 FIB_TEST(!fib_test_validate_entry(fei,
6118 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6122 "1.1.1.1/32 via high preference paths");
6125 * bring up the interface on which the medium preference path lie
6127 vnet_sw_interface_set_flags(vnet_get_main(),
6128 tm->hw[1]->sw_if_index,
6129 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6131 FIB_TEST(!fib_test_validate_entry(fei,
6132 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6136 "1.1.1.1/32 via high preference paths");
6138 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
6139 fib_entry_contribute_forwarding(fei,
6140 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6144 * 3 recursive paths of different preference
6146 const fib_prefix_t pfx_1_1_1_2_s_32 = {
6148 .fp_proto = FIB_PROTOCOL_IP4,
6151 .as_u32 = clib_host_to_net_u32(0x01010102),
6155 const fib_prefix_t pfx_1_1_1_3_s_32 = {
6157 .fp_proto = FIB_PROTOCOL_IP4,
6160 .as_u32 = clib_host_to_net_u32(0x01010103),
6164 fei = fib_table_entry_path_add2(0,
6167 FIB_ENTRY_FLAG_NONE,
6169 dpo_id_t ip_1_1_1_2 = DPO_INVALID;
6170 fib_entry_contribute_forwarding(fei,
6171 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6173 fei = fib_table_entry_path_add2(0,
6176 FIB_ENTRY_FLAG_NONE,
6178 dpo_id_t ip_1_1_1_3 = DPO_INVALID;
6179 fib_entry_contribute_forwarding(fei,
6180 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6183 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
6186 .lb = ip_1_1_1_1.dpoi_index,
6189 fib_test_lb_bucket_t ip_o_1_1_1_2 = {
6192 .lb = ip_1_1_1_2.dpoi_index,
6195 fib_test_lb_bucket_t ip_o_1_1_1_3 = {
6198 .lb = ip_1_1_1_3.dpoi_index,
6201 fib_route_path_t r_path_hi = {
6202 .frp_proto = DPO_PROTO_IP4,
6203 .frp_sw_if_index = ~0,
6206 .frp_preference = 0,
6207 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
6208 .frp_addr = pfx_1_1_1_1_s_32.fp_addr,
6210 fib_route_path_t r_path_med = {
6211 .frp_proto = DPO_PROTO_IP4,
6212 .frp_sw_if_index = ~0,
6215 .frp_preference = 10,
6216 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
6217 .frp_addr = pfx_1_1_1_2_s_32.fp_addr,
6219 fib_route_path_t r_path_low = {
6220 .frp_proto = DPO_PROTO_IP4,
6221 .frp_sw_if_index = ~0,
6224 .frp_preference = 255,
6225 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
6226 .frp_addr = pfx_1_1_1_3_s_32.fp_addr,
6228 fib_route_path_t *r_paths = NULL;
6230 vec_add1(r_paths, r_path_hi);
6231 vec_add1(r_paths, r_path_low);
6232 vec_add1(r_paths, r_path_med);
6235 * add many recursive so we get the LB MAp created
6238 fib_prefix_t pfx_r[N_PFXS];
6239 unsigned int n_pfxs;
6240 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6242 pfx_r[n_pfxs].fp_len = 32;
6243 pfx_r[n_pfxs].fp_proto = FIB_PROTOCOL_IP4;
6244 pfx_r[n_pfxs].fp_addr.ip4.as_u32 =
6245 clib_host_to_net_u32(0x02000000 + n_pfxs);
6247 fei = fib_table_entry_path_add2(0,
6250 FIB_ENTRY_FLAG_NONE,
6253 FIB_TEST(!fib_test_validate_entry(fei,
6254 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6257 "recursive via high preference paths");
6260 * withdraw hig pref resolving entry
6262 fib_table_entry_delete(0,
6266 /* suspend so the update walk kicks int */
6267 vlib_process_suspend(vlib_get_main(), 1e-5);
6269 FIB_TEST(!fib_test_validate_entry(fei,
6270 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6273 "recursive via medium preference paths");
6276 * withdraw medium pref resolving entry
6278 fib_table_entry_delete(0,
6282 /* suspend so the update walk kicks int */
6283 vlib_process_suspend(vlib_get_main(), 1e-5);
6285 FIB_TEST(!fib_test_validate_entry(fei,
6286 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6289 "recursive via low preference paths");
6292 * add back paths for next iteration
6294 fei = fib_table_entry_update(0,
6297 FIB_ENTRY_FLAG_NONE,
6299 fei = fib_table_entry_update(0,
6302 FIB_ENTRY_FLAG_NONE,
6305 /* suspend so the update walk kicks int */
6306 vlib_process_suspend(vlib_get_main(), 1e-5);
6308 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6309 FIB_TEST(!fib_test_validate_entry(fei,
6310 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6313 "recursive via high preference paths");
6317 fib_table_entry_delete(0,
6321 /* suspend so the update walk kicks int */
6322 vlib_process_suspend(vlib_get_main(), 1e-5);
6324 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6326 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6328 FIB_TEST(!fib_test_validate_entry(fei,
6329 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6332 "recursive via medium preference paths");
6334 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6336 fib_table_entry_delete(0,
6344 fib_table_entry_delete(0,
6347 fib_table_entry_delete(0,
6351 dpo_reset(&ip_1_1_1_1);
6352 dpo_reset(&ip_1_1_1_2);
6353 dpo_reset(&ip_1_1_1_3);
6354 adj_unlock(ai_low_2);
6355 adj_unlock(ai_low_1);
6356 adj_unlock(ai_med_2);
6357 adj_unlock(ai_med_1);
6358 adj_unlock(ai_hi_2);
6359 adj_unlock(ai_hi_1);
6365 * Test the recursive route route handling for GRE tunnels
6368 fib_test_label (void)
6370 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;
6371 const u32 fib_index = 0;
6372 int lb_count, ii, res;
6377 lb_count = pool_elts(load_balance_pool);
6382 * add interface routes. We'll assume this works. It's more rigorously
6385 fib_prefix_t local0_pfx = {
6387 .fp_proto = FIB_PROTOCOL_IP4,
6391 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
6396 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6399 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
6401 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6402 FIB_SOURCE_INTERFACE,
6403 (FIB_ENTRY_FLAG_CONNECTED |
6404 FIB_ENTRY_FLAG_ATTACHED),
6407 tm->hw[0]->sw_if_index,
6411 FIB_ROUTE_PATH_FLAG_NONE);
6412 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6413 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6414 "attached interface route present");
6416 local0_pfx.fp_len = 32;
6417 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6418 FIB_SOURCE_INTERFACE,
6419 (FIB_ENTRY_FLAG_CONNECTED |
6420 FIB_ENTRY_FLAG_LOCAL),
6423 tm->hw[0]->sw_if_index,
6424 ~0, // invalid fib index
6427 FIB_ROUTE_PATH_FLAG_NONE);
6428 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6430 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6431 "local interface route present");
6433 fib_prefix_t local1_pfx = {
6435 .fp_proto = FIB_PROTOCOL_IP4,
6439 .as_u32 = clib_host_to_net_u32(0x0a0a0b0a),
6444 im->fib_index_by_sw_if_index[tm->hw[1]->sw_if_index] = fib_index;
6446 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6447 FIB_SOURCE_INTERFACE,
6448 (FIB_ENTRY_FLAG_CONNECTED |
6449 FIB_ENTRY_FLAG_ATTACHED),
6452 tm->hw[1]->sw_if_index,
6456 FIB_ROUTE_PATH_FLAG_NONE);
6457 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6458 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6459 "attached interface route present");
6461 local1_pfx.fp_len = 32;
6462 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6463 FIB_SOURCE_INTERFACE,
6464 (FIB_ENTRY_FLAG_CONNECTED |
6465 FIB_ENTRY_FLAG_LOCAL),
6468 tm->hw[1]->sw_if_index,
6469 ~0, // invalid fib index
6472 FIB_ROUTE_PATH_FLAG_NONE);
6473 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6475 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6476 "local interface route present");
6478 ip46_address_t nh_10_10_10_1 = {
6480 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
6483 ip46_address_t nh_10_10_11_1 = {
6485 .as_u32 = clib_host_to_net_u32(0x0a0a0b01),
6488 ip46_address_t nh_10_10_11_2 = {
6490 .as_u32 = clib_host_to_net_u32(0x0a0a0b02),
6494 ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6497 tm->hw[1]->sw_if_index);
6498 ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6501 tm->hw[1]->sw_if_index);
6502 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6505 tm->hw[0]->sw_if_index);
6506 ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6509 tm->hw[1]->sw_if_index);
6510 ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6513 tm->hw[1]->sw_if_index);
6516 * Add an etry with one path with a real out-going label
6518 fib_prefix_t pfx_1_1_1_1_s_32 = {
6520 .fp_proto = FIB_PROTOCOL_IP4,
6522 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
6525 fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = {
6526 .type = FT_LB_LABEL_O_ADJ,
6528 .adj = ai_mpls_10_10_10_1,
6533 fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = {
6534 .type = FT_LB_LABEL_O_ADJ,
6536 .adj = ai_mpls_10_10_10_1,
6538 .eos = MPLS_NON_EOS,
6541 fib_mpls_label_t *l99 = NULL, fml99 = {
6544 vec_add1(l99, fml99);
6546 fib_table_entry_update_one_path(fib_index,
6549 FIB_ENTRY_FLAG_NONE,
6552 tm->hw[0]->sw_if_index,
6553 ~0, // invalid fib index
6556 FIB_ROUTE_PATH_FLAG_NONE);
6558 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6559 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created");
6561 FIB_TEST(!fib_test_validate_entry(fei,
6562 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6564 &l99_eos_o_10_10_10_1),
6565 "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1");
6568 * add a path with an implicit NULL label
6570 fib_test_lb_bucket_t a_o_10_10_11_1 = {
6573 .adj = ai_v4_10_10_11_1,
6576 fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = {
6579 .adj = ai_mpls_10_10_11_1,
6582 fib_mpls_label_t *l_imp_null = NULL, fml_imp_null = {
6583 .fml_value = MPLS_IETF_IMPLICIT_NULL_LABEL,
6585 vec_add1(l_imp_null, fml_imp_null);
6587 fei = fib_table_entry_path_add(fib_index,
6590 FIB_ENTRY_FLAG_NONE,
6593 tm->hw[1]->sw_if_index,
6594 ~0, // invalid fib index
6597 FIB_ROUTE_PATH_FLAG_NONE);
6599 FIB_TEST(!fib_test_validate_entry(fei,
6600 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6602 &l99_eos_o_10_10_10_1,
6604 "1.1.1.1/32 LB 2 buckets via: "
6605 "label 99 over 10.10.10.1, "
6606 "adj over 10.10.11.1");
6609 * assign the route a local label
6611 fib_table_entry_local_label_add(fib_index,
6615 fib_prefix_t pfx_24001_eos = {
6616 .fp_proto = FIB_PROTOCOL_MPLS,
6620 fib_prefix_t pfx_24001_neos = {
6621 .fp_proto = FIB_PROTOCOL_MPLS,
6623 .fp_eos = MPLS_NON_EOS,
6625 fib_test_lb_bucket_t disp_o_10_10_11_1 = {
6626 .type = FT_LB_MPLS_DISP_PIPE_O_ADJ,
6628 .adj = ai_v4_10_10_11_1,
6633 * The EOS entry should link to both the paths,
6634 * and use an ip adj for the imp-null
6635 * The NON-EOS entry should link to both the paths,
6636 * and use an mpls adj for the imp-null
6638 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6640 FIB_TEST(!fib_test_validate_entry(fei,
6641 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6643 &l99_eos_o_10_10_10_1,
6644 &disp_o_10_10_11_1),
6645 "24001/eos LB 2 buckets via: "
6646 "label 99 over 10.10.10.1, "
6647 "mpls disp adj over 10.10.11.1");
6650 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6652 FIB_TEST(!fib_test_validate_entry(fei,
6653 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6655 &l99_neos_o_10_10_10_1,
6656 &a_mpls_o_10_10_11_1),
6657 "24001/neos LB 1 bucket via: "
6658 "label 99 over 10.10.10.1 ",
6659 "mpls-adj via 10.10.11.1");
6662 * add an unlabelled path, this is excluded from the neos chains,
6664 fib_test_lb_bucket_t adj_o_10_10_11_2 = {
6667 .adj = ai_v4_10_10_11_2,
6670 fib_test_lb_bucket_t disp_o_10_10_11_2 = {
6671 .type = FT_LB_MPLS_DISP_PIPE_O_ADJ,
6673 .adj = ai_v4_10_10_11_2,
6678 fei = fib_table_entry_path_add(fib_index,
6681 FIB_ENTRY_FLAG_NONE,
6684 tm->hw[1]->sw_if_index,
6685 ~0, // invalid fib index
6688 FIB_ROUTE_PATH_FLAG_NONE);
6690 FIB_TEST(!fib_test_validate_entry(fei,
6691 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6692 16, // 3 choices spread over 16 buckets
6693 &l99_eos_o_10_10_10_1,
6694 &l99_eos_o_10_10_10_1,
6695 &l99_eos_o_10_10_10_1,
6696 &l99_eos_o_10_10_10_1,
6697 &l99_eos_o_10_10_10_1,
6698 &l99_eos_o_10_10_10_1,
6709 "1.1.1.1/32 LB 16 buckets via: "
6710 "label 99 over 10.10.10.1, "
6711 "adj over 10.10.11.1",
6712 "adj over 10.10.11.2");
6715 * get and lock a reference to the non-eos of the via entry 1.1.1.1/32
6717 dpo_id_t non_eos_1_1_1_1 = DPO_INVALID;
6718 fib_entry_contribute_forwarding(fei,
6719 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6723 * n-eos has only the 2 labelled paths
6725 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6728 FIB_TEST(!fib_test_validate_entry(fei,
6729 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6731 &l99_neos_o_10_10_10_1,
6732 &a_mpls_o_10_10_11_1),
6733 "24001/neos LB 2 buckets via: "
6734 "label 99 over 10.10.10.1, "
6735 "adj-mpls over 10.10.11.2");
6738 * A labelled recursive
6740 fib_prefix_t pfx_2_2_2_2_s_32 = {
6742 .fp_proto = FIB_PROTOCOL_IP4,
6744 .ip4.as_u32 = clib_host_to_net_u32(0x02020202),
6747 fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = {
6748 .type = FT_LB_LABEL_O_LB,
6750 .lb = non_eos_1_1_1_1.dpoi_index,
6753 .mode = FIB_MPLS_LSP_MODE_UNIFORM,
6756 fib_mpls_label_t *l1600 = NULL, fml1600 = {
6758 .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM,
6760 vec_add1(l1600, fml1600);
6762 fei = fib_table_entry_update_one_path(fib_index,
6765 FIB_ENTRY_FLAG_NONE,
6767 &pfx_1_1_1_1_s_32.fp_addr,
6772 FIB_ROUTE_PATH_FLAG_NONE);
6774 FIB_TEST(!fib_test_validate_entry(fei,
6775 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6777 &l1600_eos_o_1_1_1_1),
6778 "2.2.2.2.2/32 LB 1 buckets via: "
6779 "label 1600 over 1.1.1.1");
6781 dpo_id_t dpo_44 = DPO_INVALID;
6784 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
6785 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
6787 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
6788 "uRPF check for 2.2.2.2/32 on %d OK",
6789 tm->hw[0]->sw_if_index);
6790 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
6791 "uRPF check for 2.2.2.2/32 on %d OK",
6792 tm->hw[1]->sw_if_index);
6793 FIB_TEST(!fib_urpf_check(urpfi, 99),
6794 "uRPF check for 2.2.2.2/32 on 99 not-OK",
6797 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44);
6798 FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index),
6799 "Shared uRPF on IP and non-EOS chain");
6804 * we are holding a lock on the non-eos LB of the via-entry.
6805 * do a PIC-core failover by shutting the link of the via-entry.
6807 * shut down the link with the valid label
6809 vnet_sw_interface_set_flags(vnet_get_main(),
6810 tm->hw[0]->sw_if_index,
6813 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6814 FIB_TEST(!fib_test_validate_entry(fei,
6815 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6819 "1.1.1.1/32 LB 2 buckets via: "
6820 "adj over 10.10.11.1, ",
6821 "adj-v4 over 10.10.11.2");
6823 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6825 FIB_TEST(!fib_test_validate_entry(fei,
6826 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6829 &disp_o_10_10_11_2),
6830 "24001/eos LB 2 buckets via: "
6831 "mpls-disp adj over 10.10.11.1, ",
6832 "mpls-disp adj-v4 over 10.10.11.2");
6834 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6836 FIB_TEST(!fib_test_validate_entry(fei,
6837 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6839 &a_mpls_o_10_10_11_1),
6840 "24001/neos LB 1 buckets via: "
6841 "adj-mpls over 10.10.11.2");
6844 * test that the pre-failover load-balance has been in-place
6847 dpo_id_t current = DPO_INVALID;
6848 fib_entry_contribute_forwarding(fei,
6849 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6852 FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1,
6854 "PIC-core LB inplace modified %U %U",
6855 format_dpo_id, &non_eos_1_1_1_1, 0,
6856 format_dpo_id, ¤t, 0);
6858 dpo_reset(&non_eos_1_1_1_1);
6859 dpo_reset(¤t);
6862 * no-shut the link with the valid label
6864 vnet_sw_interface_set_flags(vnet_get_main(),
6865 tm->hw[0]->sw_if_index,
6866 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6868 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6869 FIB_TEST(!fib_test_validate_entry(fei,
6870 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6871 16, // 3 choices spread over 16 buckets
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,
6876 &l99_eos_o_10_10_10_1,
6877 &l99_eos_o_10_10_10_1,
6888 "1.1.1.1/32 LB 16 buckets via: "
6889 "label 99 over 10.10.10.1, "
6890 "adj over 10.10.11.1",
6891 "adj-v4 over 10.10.11.2");
6894 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6896 FIB_TEST(!fib_test_validate_entry(fei,
6897 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6898 16, // 3 choices spread over 16 buckets
6899 &l99_eos_o_10_10_10_1,
6900 &l99_eos_o_10_10_10_1,
6901 &l99_eos_o_10_10_10_1,
6902 &l99_eos_o_10_10_10_1,
6903 &l99_eos_o_10_10_10_1,
6904 &l99_eos_o_10_10_10_1,
6914 &disp_o_10_10_11_2),
6915 "24001/eos LB 16 buckets via: "
6916 "label 99 over 10.10.10.1, "
6917 "MPLS disp adj over 10.10.11.1",
6918 "MPLS disp adj-v4 over 10.10.11.2");
6920 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6922 FIB_TEST(!fib_test_validate_entry(fei,
6923 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6925 &l99_neos_o_10_10_10_1,
6926 &a_mpls_o_10_10_11_1),
6927 "24001/neos LB 2 buckets via: "
6928 "label 99 over 10.10.10.1, "
6929 "adj-mpls over 10.10.11.2");
6932 * remove the first path with the valid label
6934 fib_table_entry_path_remove(fib_index,
6939 tm->hw[0]->sw_if_index,
6940 ~0, // invalid fib index
6942 FIB_ROUTE_PATH_FLAG_NONE);
6944 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6945 FIB_TEST(!fib_test_validate_entry(fei,
6946 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6950 "1.1.1.1/32 LB 2 buckets via: "
6951 "adj over 10.10.11.1, "
6952 "adj-v4 over 10.10.11.2");
6954 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6956 FIB_TEST(!fib_test_validate_entry(fei,
6957 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6960 &disp_o_10_10_11_2),
6961 "24001/eos LB 2 buckets via: "
6962 "MPLS disp adj over 10.10.11.1, "
6963 "MPLS disp adj-v4 over 10.10.11.2");
6965 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6968 FIB_TEST(!fib_test_validate_entry(fei,
6969 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6971 &a_mpls_o_10_10_11_1),
6972 "24001/neos LB 1 buckets via: "
6973 "adj-mpls over 10.10.11.2");
6976 * remove the other path with a valid label
6978 fib_test_lb_bucket_t bucket_drop = {
6981 fib_test_lb_bucket_t mpls_bucket_drop = {
6984 .adj = DPO_PROTO_MPLS,
6988 fib_table_entry_path_remove(fib_index,
6993 tm->hw[1]->sw_if_index,
6994 ~0, // invalid fib index
6996 FIB_ROUTE_PATH_FLAG_NONE);
6998 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6999 FIB_TEST(!fib_test_validate_entry(fei,
7000 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7003 "1.1.1.1/32 LB 1 buckets via: "
7004 "adj over 10.10.11.2");
7006 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7008 FIB_TEST(!fib_test_validate_entry(fei,
7009 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7011 &disp_o_10_10_11_2),
7012 "24001/eos LB 1 buckets via: "
7013 "MPLS disp adj over 10.10.11.2");
7015 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7017 FIB_TEST(!fib_test_validate_entry(fei,
7018 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7021 "24001/neos LB 1 buckets via: DROP");
7024 * add back the path with the valid label
7027 vec_add1(l99, fml99);
7029 fib_table_entry_path_add(fib_index,
7032 FIB_ENTRY_FLAG_NONE,
7035 tm->hw[0]->sw_if_index,
7036 ~0, // invalid fib index
7039 FIB_ROUTE_PATH_FLAG_NONE);
7041 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
7042 FIB_TEST(!fib_test_validate_entry(fei,
7043 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7045 &l99_eos_o_10_10_10_1,
7047 "1.1.1.1/32 LB 2 buckets via: "
7048 "label 99 over 10.10.10.1, "
7049 "adj over 10.10.11.2");
7051 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7053 FIB_TEST(!fib_test_validate_entry(fei,
7054 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7056 &l99_eos_o_10_10_10_1,
7057 &disp_o_10_10_11_2),
7058 "24001/eos LB 2 buckets via: "
7059 "label 99 over 10.10.10.1, "
7060 "MPLS disp adj over 10.10.11.2");
7062 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7064 FIB_TEST(!fib_test_validate_entry(fei,
7065 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7067 &l99_neos_o_10_10_10_1),
7068 "24001/neos LB 1 buckets via: "
7069 "label 99 over 10.10.10.1");
7072 * change the local label
7074 fib_table_entry_local_label_add(fib_index,
7078 fib_prefix_t pfx_25005_eos = {
7079 .fp_proto = FIB_PROTOCOL_MPLS,
7083 fib_prefix_t pfx_25005_neos = {
7084 .fp_proto = FIB_PROTOCOL_MPLS,
7086 .fp_eos = MPLS_NON_EOS,
7089 FIB_TEST((FIB_NODE_INDEX_INVALID ==
7090 fib_table_lookup(fib_index, &pfx_24001_eos)),
7091 "24001/eos removed after label change");
7092 FIB_TEST((FIB_NODE_INDEX_INVALID ==
7093 fib_table_lookup(fib_index, &pfx_24001_neos)),
7094 "24001/eos removed after label change");
7096 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7098 FIB_TEST(!fib_test_validate_entry(fei,
7099 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7101 &l99_eos_o_10_10_10_1,
7102 &disp_o_10_10_11_2),
7103 "25005/eos LB 2 buckets via: "
7104 "label 99 over 10.10.10.1, "
7105 "MPLS disp adj over 10.10.11.2");
7107 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7109 FIB_TEST(!fib_test_validate_entry(fei,
7110 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7112 &l99_neos_o_10_10_10_1),
7113 "25005/neos LB 1 buckets via: "
7114 "label 99 over 10.10.10.1");
7117 * remove the local label.
7118 * the check that the MPLS entries are gone is done by the fact the
7119 * MPLS table is no longer present.
7121 fib_table_entry_local_label_remove(fib_index,
7125 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
7126 FIB_TEST(!fib_test_validate_entry(fei,
7127 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7129 &l99_eos_o_10_10_10_1,
7131 "24001/eos LB 2 buckets via: "
7132 "label 99 over 10.10.10.1, "
7133 "adj over 10.10.11.2");
7135 FIB_TEST((FIB_NODE_INDEX_INVALID ==
7136 mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)),
7137 "No more MPLS FIB entries => table removed");
7140 * add another via-entry for the recursive
7142 fib_prefix_t pfx_1_1_1_2_s_32 = {
7144 .fp_proto = FIB_PROTOCOL_IP4,
7146 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
7149 fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = {
7150 .type = FT_LB_LABEL_O_ADJ,
7152 .adj = ai_mpls_10_10_10_1,
7157 fib_mpls_label_t *l101 = NULL, fml101 = {
7160 vec_add1(l101, fml101);
7162 fei = fib_table_entry_update_one_path(fib_index,
7165 FIB_ENTRY_FLAG_NONE,
7168 tm->hw[0]->sw_if_index,
7169 ~0, // invalid fib index
7172 FIB_ROUTE_PATH_FLAG_NONE);
7174 FIB_TEST(!fib_test_validate_entry(fei,
7175 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7177 &l101_eos_o_10_10_10_1),
7178 "1.1.1.2/32 LB 1 buckets via: "
7179 "label 101 over 10.10.10.1");
7181 dpo_id_t non_eos_1_1_1_2 = DPO_INVALID;
7182 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7184 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7186 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7188 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7191 fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = {
7192 .type = FT_LB_LABEL_O_LB,
7194 .lb = non_eos_1_1_1_2.dpoi_index,
7199 fib_mpls_label_t *l1601 = NULL, fml1601 = {
7202 vec_add1(l1601, fml1601);
7204 l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index;
7206 fei = fib_table_entry_path_add(fib_index,
7209 FIB_ENTRY_FLAG_NONE,
7211 &pfx_1_1_1_2_s_32.fp_addr,
7216 FIB_ROUTE_PATH_FLAG_NONE);
7218 FIB_TEST(!fib_test_validate_entry(fei,
7219 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7221 &l1600_eos_o_1_1_1_1,
7222 &l1601_eos_o_1_1_1_2),
7223 "2.2.2.2/32 LB 2 buckets via: "
7224 "label 1600 via 1.1,1.1, "
7225 "label 16001 via 1.1.1.2");
7228 * update the via-entry so it no longer has an imp-null path.
7229 * the LB for the recursive can use an imp-null
7232 vec_add1(l_imp_null, fml_imp_null);
7234 fei = fib_table_entry_update_one_path(fib_index,
7237 FIB_ENTRY_FLAG_NONE,
7240 tm->hw[1]->sw_if_index,
7241 ~0, // invalid fib index
7244 FIB_ROUTE_PATH_FLAG_NONE);
7246 FIB_TEST(!fib_test_validate_entry(fei,
7247 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7250 "1.1.1.2/32 LB 1 buckets via: "
7253 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7254 FIB_TEST(!fib_test_validate_entry(fei,
7255 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7257 &l1600_eos_o_1_1_1_1,
7258 &l1601_eos_o_1_1_1_2),
7259 "2.2.2.2/32 LB 2 buckets via: "
7260 "label 1600 via 1.1,1.1, "
7261 "label 16001 via 1.1.1.2");
7264 * update the via-entry so it no longer has labelled paths.
7265 * the LB for the recursive should exclue this via form its LB
7267 fei = fib_table_entry_update_one_path(fib_index,
7270 FIB_ENTRY_FLAG_NONE,
7273 tm->hw[1]->sw_if_index,
7274 ~0, // invalid fib index
7277 FIB_ROUTE_PATH_FLAG_NONE);
7279 FIB_TEST(!fib_test_validate_entry(fei,
7280 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7283 "1.1.1.2/32 LB 1 buckets via: "
7286 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7287 FIB_TEST(!fib_test_validate_entry(fei,
7288 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7290 &l1600_eos_o_1_1_1_1),
7291 "2.2.2.2/32 LB 1 buckets via: "
7292 "label 1600 via 1.1,1.1");
7294 dpo_reset(&non_eos_1_1_1_1);
7295 dpo_reset(&non_eos_1_1_1_2);
7298 * Add a recursive with no out-labels. We expect to use the IP of the via
7300 fib_prefix_t pfx_2_2_2_3_s_32 = {
7302 .fp_proto = FIB_PROTOCOL_IP4,
7304 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
7307 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
7309 fib_table_entry_update_one_path(fib_index,
7312 FIB_ENTRY_FLAG_NONE,
7314 &pfx_1_1_1_1_s_32.fp_addr,
7319 FIB_ROUTE_PATH_FLAG_NONE);
7321 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7323 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7326 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
7329 .lb = ip_1_1_1_1.dpoi_index,
7333 fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
7334 FIB_TEST(!fib_test_validate_entry(fei,
7335 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7338 "2.2.2.2.3/32 LB 1 buckets via: "
7342 * Add a recursive with an imp-null out-label.
7343 * We expect to use the IP of the via
7345 fib_prefix_t pfx_2_2_2_4_s_32 = {
7347 .fp_proto = FIB_PROTOCOL_IP4,
7349 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
7353 fib_table_entry_update_one_path(fib_index,
7356 FIB_ENTRY_FLAG_NONE,
7358 &pfx_1_1_1_1_s_32.fp_addr,
7363 FIB_ROUTE_PATH_FLAG_NONE);
7365 fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
7366 FIB_TEST(!fib_test_validate_entry(fei,
7367 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7370 "2.2.2.2.4/32 LB 1 buckets via: "
7373 dpo_reset(&ip_1_1_1_1);
7376 * Create an entry with a deep label stack
7378 fib_prefix_t pfx_2_2_5_5_s_32 = {
7380 .fp_proto = FIB_PROTOCOL_IP4,
7382 .ip4.as_u32 = clib_host_to_net_u32(0x02020505),
7385 fib_test_lb_bucket_t ls_eos_o_10_10_10_1 = {
7386 .type = FT_LB_LABEL_STACK_O_ADJ,
7387 .label_stack_o_adj = {
7388 .adj = ai_mpls_10_10_11_1,
7389 .label_stack_size = 8,
7391 200, 201, 202, 203, 204, 205, 206, 207
7396 fib_mpls_label_t *label_stack = NULL;
7397 vec_validate(label_stack, 7);
7398 for (ii = 0; ii < 8; ii++)
7400 label_stack[ii].fml_value = ii + 200;
7403 fei = fib_table_entry_update_one_path(fib_index,
7406 FIB_ENTRY_FLAG_NONE,
7409 tm->hw[1]->sw_if_index,
7410 ~0, // invalid fib index
7413 FIB_ROUTE_PATH_FLAG_NONE);
7415 FIB_TEST(!fib_test_validate_entry(fei,
7416 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7418 &ls_eos_o_10_10_10_1),
7419 "2.2.5.5/32 LB 1 buckets via: "
7421 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
7424 * A prefix with outgoing labels. We'll RR source a /32 it covers
7425 * and test that the RR source picks up the out-going labels
7427 fib_prefix_t pfx_100_s_8 = {
7429 .fp_proto = FIB_PROTOCOL_IP4,
7431 .ip4.as_u32 = clib_host_to_net_u32(0x64000000),
7434 fib_test_lb_bucket_t l_100_eos_o_10_10_10_1 = {
7435 .type = FT_LB_LABEL_O_ADJ,
7437 .adj = ai_mpls_10_10_11_1,
7442 fib_mpls_label_t *l1602 = NULL, fml1602 = {
7445 vec_add1(l1602, fml1602);
7446 fei = fib_table_entry_update_one_path(fib_index,
7449 FIB_ENTRY_FLAG_NONE,
7452 tm->hw[1]->sw_if_index,
7453 ~0, // invalid fib index
7456 FIB_ROUTE_PATH_FLAG_NONE);
7458 FIB_TEST(!fib_test_validate_entry(fei,
7459 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7461 &l_100_eos_o_10_10_10_1),
7462 "100.0.0.0/8 LB 1 buckets via: lbl 101 "
7465 fib_prefix_t pfx_100_1_1_1_s_32 = {
7467 .fp_proto = FIB_PROTOCOL_IP4,
7469 .ip4.as_u32 = clib_host_to_net_u32(0x64010101),
7473 fei = fib_table_entry_special_add(fib_index,
7474 &pfx_100_1_1_1_s_32,
7476 FIB_ENTRY_FLAG_NONE);
7478 FIB_TEST(!fib_test_validate_entry(fei,
7479 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7481 &l_100_eos_o_10_10_10_1),
7482 "100.1.1.1/32 LB 1 buckets via: "
7485 fib_table_entry_delete(fib_index,
7488 fib_table_entry_delete_index(fei, FIB_SOURCE_RR);
7493 fib_table_entry_delete(fib_index,
7497 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7498 FIB_TEST(!fib_test_validate_entry(fei,
7499 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7501 &l1600_eos_o_1_1_1_1),
7502 "2.2.2.2/32 LB 1 buckets via: "
7503 "label 1600 via 1.1,1.1");
7505 fib_table_entry_delete(fib_index,
7509 FIB_TEST(!fib_test_validate_entry(fei,
7510 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7513 "2.2.2.2/32 LB 1 buckets via: DROP");
7515 fib_table_entry_delete(fib_index,
7518 fib_table_entry_delete(fib_index,
7521 fib_table_entry_delete(fib_index,
7525 adj_unlock(ai_mpls_10_10_10_1);
7526 adj_unlock(ai_mpls_10_10_11_2);
7527 adj_unlock(ai_v4_10_10_11_1);
7528 adj_unlock(ai_v4_10_10_11_2);
7529 adj_unlock(ai_mpls_10_10_11_1);
7531 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
7534 local0_pfx.fp_len = 32;
7535 fib_table_entry_delete(fib_index,
7537 FIB_SOURCE_INTERFACE);
7538 local0_pfx.fp_len = 24;
7539 fib_table_entry_delete(fib_index,
7541 FIB_SOURCE_INTERFACE);
7542 local1_pfx.fp_len = 32;
7543 fib_table_entry_delete(fib_index,
7545 FIB_SOURCE_INTERFACE);
7546 local1_pfx.fp_len = 24;
7547 fib_table_entry_delete(fib_index,
7549 FIB_SOURCE_INTERFACE);
7552 * +1 for the drop LB in the MPLS tables.
7554 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
7555 "Load-balance resources freed %d of %d",
7556 lb_count+1, pool_elts(load_balance_pool));
7561 #define N_TEST_CHILDREN 4
7562 #define PARENT_INDEX 0
7564 typedef struct fib_node_test_t_
7569 fib_node_back_walk_ctx_t *ctxs;
7573 static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1];
7575 #define PARENT() (&fib_test_nodes[PARENT_INDEX].node)
7577 #define FOR_EACH_TEST_CHILD(_tc) \
7578 for (ii = 1, (_tc) = &fib_test_nodes[1]; \
7579 ii < N_TEST_CHILDREN+1; \
7580 ii++, (_tc) = &fib_test_nodes[ii])
7583 fib_test_child_get_node (fib_node_index_t index)
7585 return (&fib_test_nodes[index].node);
7588 static int fib_test_walk_spawns_walks;
7590 static fib_node_back_walk_rc_t
7591 fib_test_child_back_walk_notify (fib_node_t *node,
7592 fib_node_back_walk_ctx_t *ctx)
7594 fib_node_test_t *tc = (fib_node_test_t*) node;
7596 vec_add1(tc->ctxs, *ctx);
7598 if (1 == fib_test_walk_spawns_walks)
7599 fib_walk_sync(FIB_NODE_TYPE_TEST, tc->index, ctx);
7600 if (2 == fib_test_walk_spawns_walks)
7601 fib_walk_async(FIB_NODE_TYPE_TEST, tc->index,
7602 FIB_WALK_PRIORITY_HIGH, ctx);
7604 return (FIB_NODE_BACK_WALK_CONTINUE);
7608 fib_test_child_last_lock_gone (fib_node_t *node)
7610 fib_node_test_t *tc = (fib_node_test_t *)node;
7616 * The FIB walk's graph node virtual function table
7618 static const fib_node_vft_t fib_test_child_vft = {
7619 .fnv_get = fib_test_child_get_node,
7620 .fnv_last_lock = fib_test_child_last_lock_gone,
7621 .fnv_back_walk = fib_test_child_back_walk_notify,
7625 * the function (that should have been static but isn't so I can do this)
7626 * that processes the walk from the async queue,
7628 f64 fib_walk_process_queues(vlib_main_t * vm,
7630 u32 fib_walk_queue_get_size(fib_walk_priority_t prio);
7633 fib_test_walk (void)
7635 fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {};
7636 fib_node_test_t *tc;
7641 vm = vlib_get_main();
7642 fib_node_register_type(FIB_NODE_TYPE_TEST, &fib_test_child_vft);
7645 * init a fake node on which we will add children
7647 fib_node_init(&fib_test_nodes[PARENT_INDEX].node,
7648 FIB_NODE_TYPE_TEST);
7650 FOR_EACH_TEST_CHILD(tc)
7652 fib_node_init(&tc->node, FIB_NODE_TYPE_TEST);
7653 fib_node_lock(&tc->node);
7656 tc->sibling = fib_node_child_add(FIB_NODE_TYPE_TEST,
7658 FIB_NODE_TYPE_TEST, ii);
7662 * enqueue a walk across the parents children.
7664 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7666 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7667 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7668 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7669 "Parent has %d children pre-walk",
7670 fib_node_list_get_size(PARENT()->fn_children));
7673 * give the walk a large amount of time so it gets to the end
7675 fib_walk_process_queues(vm, 1);
7677 FOR_EACH_TEST_CHILD(tc)
7679 FIB_TEST(1 == vec_len(tc->ctxs),
7680 "%d child visitsed %d times",
7681 ii, vec_len(tc->ctxs));
7684 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7685 "Queue is empty post walk");
7686 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7687 "Parent has %d children post walk",
7688 fib_node_list_get_size(PARENT()->fn_children));
7691 * walk again. should be no increase in the number of visits, since
7692 * the walk will have terminated.
7694 fib_walk_process_queues(vm, 1);
7696 FOR_EACH_TEST_CHILD(tc)
7698 FIB_TEST(0 == vec_len(tc->ctxs),
7699 "%d child visitsed %d times",
7700 ii, vec_len(tc->ctxs));
7704 * schedule a low and hig priority walk. expect the high to be performed
7706 * schedule the high prio walk first so that it is further from the head
7707 * of the dependency list. that way it won't merge with the low one.
7709 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7710 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7712 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7713 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7714 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7715 FIB_WALK_PRIORITY_LOW, &low_ctx);
7717 fib_walk_process_queues(vm, 1);
7719 FOR_EACH_TEST_CHILD(tc)
7721 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7722 "%d child visitsed by high prio walk", ii);
7723 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7724 "%d child visitsed by low prio walk", ii);
7727 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7728 "Queue is empty post prio walk");
7729 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7730 "Parent has %d children post prio walk",
7731 fib_node_list_get_size(PARENT()->fn_children));
7734 * schedule 2 walks of the same priority that can be megred.
7735 * expect that each child is thus visited only once.
7737 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7738 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7740 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7741 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7742 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7743 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7745 fib_walk_process_queues(vm, 1);
7747 FOR_EACH_TEST_CHILD(tc)
7749 FIB_TEST(1 == vec_len(tc->ctxs),
7750 "%d child visitsed %d times during merge walk",
7751 ii, vec_len(tc->ctxs));
7754 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7755 "Queue is empty post merge walk");
7756 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7757 "Parent has %d children post merge walk",
7758 fib_node_list_get_size(PARENT()->fn_children));
7761 * schedule 2 walks of the same priority that cannot be megred.
7762 * expect that each child is thus visited twice and in the order
7763 * in which the walks were scheduled.
7765 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7766 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7768 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7769 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7770 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7771 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7773 fib_walk_process_queues(vm, 1);
7775 FOR_EACH_TEST_CHILD(tc)
7777 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7778 "%d child visitsed by high prio walk", ii);
7779 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7780 "%d child visitsed by low prio walk", ii);
7783 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7784 "Queue is empty post no-merge walk");
7785 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7786 "Parent has %d children post no-merge walk",
7787 fib_node_list_get_size(PARENT()->fn_children));
7790 * schedule a walk that makes one one child progress.
7791 * we do this by giving the queue draining process zero
7792 * time quanta. it's a do..while loop, so it does something.
7794 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7796 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7797 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7798 fib_walk_process_queues(vm, 0);
7800 FOR_EACH_TEST_CHILD(tc)
7802 if (ii == N_TEST_CHILDREN)
7804 FIB_TEST(1 == vec_len(tc->ctxs),
7805 "%d child visitsed %d times in zero quanta walk",
7806 ii, vec_len(tc->ctxs));
7810 FIB_TEST(0 == vec_len(tc->ctxs),
7811 "%d child visitsed %d times in 0 quanta walk",
7812 ii, vec_len(tc->ctxs));
7815 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7816 "Queue is not empty post zero quanta walk");
7817 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7818 "Parent has %d children post zero qunta walk",
7819 fib_node_list_get_size(PARENT()->fn_children));
7824 fib_walk_process_queues(vm, 0);
7826 FOR_EACH_TEST_CHILD(tc)
7828 if (ii >= N_TEST_CHILDREN-1)
7830 FIB_TEST(1 == vec_len(tc->ctxs),
7831 "%d child visitsed %d times in 2nd zero quanta walk",
7832 ii, vec_len(tc->ctxs));
7836 FIB_TEST(0 == vec_len(tc->ctxs),
7837 "%d child visitsed %d times in 2nd 0 quanta walk",
7838 ii, vec_len(tc->ctxs));
7841 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7842 "Queue is not empty post zero quanta walk");
7843 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7844 "Parent has %d children post zero qunta walk",
7845 fib_node_list_get_size(PARENT()->fn_children));
7848 * schedule another walk that will catch-up and merge.
7850 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7851 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7852 fib_walk_process_queues(vm, 1);
7854 FOR_EACH_TEST_CHILD(tc)
7856 if (ii >= N_TEST_CHILDREN-1)
7858 FIB_TEST(2 == vec_len(tc->ctxs),
7859 "%d child visitsed %d times in 2nd zero quanta merge walk",
7860 ii, vec_len(tc->ctxs));
7865 FIB_TEST(1 == vec_len(tc->ctxs),
7866 "%d child visitsed %d times in 2nd 0 quanta merge walk",
7867 ii, vec_len(tc->ctxs));
7871 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7872 "Queue is not empty post 2nd zero quanta merge walk");
7873 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7874 "Parent has %d children post 2nd zero qunta merge walk",
7875 fib_node_list_get_size(PARENT()->fn_children));
7878 * park a async walk in the middle of the list, then have an sync walk catch
7879 * it. same expectations as async catches async.
7881 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7883 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7884 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7886 fib_walk_process_queues(vm, 0);
7887 fib_walk_process_queues(vm, 0);
7889 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7891 FOR_EACH_TEST_CHILD(tc)
7893 if (ii >= N_TEST_CHILDREN-1)
7895 FIB_TEST(2 == vec_len(tc->ctxs),
7896 "%d child visitsed %d times in sync catches async walk",
7897 ii, vec_len(tc->ctxs));
7902 FIB_TEST(1 == vec_len(tc->ctxs),
7903 "%d child visitsed %d times in sync catches async walk",
7904 ii, vec_len(tc->ctxs));
7908 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7909 "Queue is not empty post 2nd zero quanta merge walk");
7910 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7911 "Parent has %d children post 2nd zero qunta merge walk",
7912 fib_node_list_get_size(PARENT()->fn_children));
7915 * make the parent a child of one of its children, thus inducing a routing loop.
7917 fib_test_nodes[PARENT_INDEX].sibling =
7918 fib_node_child_add(FIB_NODE_TYPE_TEST,
7919 1, // the first child
7924 * execute a sync walk from the parent. each child visited spawns more sync
7925 * walks. we expect the walk to terminate.
7927 fib_test_walk_spawns_walks = 1;
7929 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7931 FOR_EACH_TEST_CHILD(tc)
7934 * child 1 - which is last in the list - has the loop.
7935 * the other children a re thus visitsed first. the we meet
7936 * child 1. we go round the loop again, visting the other children.
7937 * then we meet the walk in the dep list and bail. child 1 is not visitsed
7942 FIB_TEST(1 == vec_len(tc->ctxs),
7943 "child %d visitsed %d times during looped sync walk",
7944 ii, vec_len(tc->ctxs));
7948 FIB_TEST(2 == vec_len(tc->ctxs),
7949 "child %d visitsed %d times during looped sync walk",
7950 ii, vec_len(tc->ctxs));
7954 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7955 "Parent has %d children post sync loop walk",
7956 fib_node_list_get_size(PARENT()->fn_children));
7959 * the walk doesn't reach the max depth because the infra knows that sync
7960 * meets sync implies a loop and bails early.
7962 FIB_TEST(high_ctx.fnbw_depth == 9,
7963 "Walk context depth %d post sync loop walk",
7964 high_ctx.fnbw_depth);
7967 * execute an async walk of the graph loop, with each child spawns sync walks
7969 high_ctx.fnbw_depth = 0;
7970 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7971 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7973 fib_walk_process_queues(vm, 1);
7975 FOR_EACH_TEST_CHILD(tc)
7978 * we don't really care how many times the children are visited, as long as
7979 * it is more than once.
7981 FIB_TEST(1 <= vec_len(tc->ctxs),
7982 "child %d visitsed %d times during looped aync spawns sync walk",
7983 ii, vec_len(tc->ctxs));
7988 * execute an async walk of the graph loop, with each child spawns async walks
7990 fib_test_walk_spawns_walks = 2;
7991 high_ctx.fnbw_depth = 0;
7992 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7993 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7995 fib_walk_process_queues(vm, 1);
7997 FOR_EACH_TEST_CHILD(tc)
8000 * we don't really care how many times the children are visited, as long as
8001 * it is more than once.
8003 FIB_TEST(1 <= vec_len(tc->ctxs),
8004 "child %d visitsed %d times during looped async spawns async walk",
8005 ii, vec_len(tc->ctxs));
8010 fib_node_child_remove(FIB_NODE_TYPE_TEST,
8011 1, // the first child
8012 fib_test_nodes[PARENT_INDEX].sibling);
8017 FOR_EACH_TEST_CHILD(tc)
8019 fib_node_child_remove(FIB_NODE_TYPE_TEST, PARENT_INDEX,
8021 fib_node_deinit(&tc->node);
8022 fib_node_unlock(&tc->node);
8024 fib_node_deinit(PARENT());
8027 * The parent will be destroyed when the last lock on it goes.
8028 * this test ensures all the walk objects are unlocking it.
8030 FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed),
8031 "Parent was destroyed");
8037 * declaration of the otherwise static callback functions
8039 void fib_bfd_notify (bfd_listen_event_e event,
8040 const bfd_session_t *session);
8041 void adj_bfd_notify (bfd_listen_event_e event,
8042 const bfd_session_t *session);
8045 * Test BFD session interaction with FIB
8050 fib_node_index_t fei;
8055 /* via 10.10.10.1 */
8056 ip46_address_t nh_10_10_10_1 = {
8057 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
8059 /* via 10.10.10.2 */
8060 ip46_address_t nh_10_10_10_2 = {
8061 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
8063 /* via 10.10.10.10 */
8064 ip46_address_t nh_10_10_10_10 = {
8065 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
8067 n_feis = fib_entry_pool_size();
8072 * add interface routes. we'll assume this works. it's tested elsewhere
8074 fib_prefix_t pfx_10_10_10_10_s_24 = {
8076 .fp_proto = FIB_PROTOCOL_IP4,
8077 .fp_addr = nh_10_10_10_10,
8080 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_24,
8081 FIB_SOURCE_INTERFACE,
8082 (FIB_ENTRY_FLAG_CONNECTED |
8083 FIB_ENTRY_FLAG_ATTACHED),
8086 tm->hw[0]->sw_if_index,
8087 ~0, // invalid fib index
8090 FIB_ROUTE_PATH_FLAG_NONE);
8092 fib_prefix_t pfx_10_10_10_10_s_32 = {
8094 .fp_proto = FIB_PROTOCOL_IP4,
8095 .fp_addr = nh_10_10_10_10,
8097 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_32,
8098 FIB_SOURCE_INTERFACE,
8099 (FIB_ENTRY_FLAG_CONNECTED |
8100 FIB_ENTRY_FLAG_LOCAL),
8103 tm->hw[0]->sw_if_index,
8104 ~0, // invalid fib index
8107 FIB_ROUTE_PATH_FLAG_NONE);
8110 * A BFD session via a neighbour we do not yet know
8112 bfd_session_t bfd_10_10_10_1 = {
8116 .peer_addr = nh_10_10_10_1,
8119 .hop_type = BFD_HOP_TYPE_MULTI,
8120 .local_state = BFD_STATE_init,
8123 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8126 * A new entry will be created that forwards via the adj
8128 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8131 tm->hw[0]->sw_if_index);
8132 fib_prefix_t pfx_10_10_10_1_s_32 = {
8133 .fp_addr = nh_10_10_10_1,
8135 .fp_proto = FIB_PROTOCOL_IP4,
8137 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
8140 .adj = ai_10_10_10_1,
8144 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
8145 FIB_TEST(!fib_test_validate_entry(fei,
8146 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8149 "BFD sourced %U via %U",
8150 format_fib_prefix, &pfx_10_10_10_1_s_32,
8151 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
8154 * Delete the BFD session. Expect the fib_entry to be removed
8156 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8158 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
8159 FIB_TEST(FIB_NODE_INDEX_INVALID == fei,
8160 "BFD sourced %U removed",
8161 format_fib_prefix, &pfx_10_10_10_1_s_32);
8164 * Add the BFD source back
8166 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8169 * source the entry via the ADJ fib
8171 fei = fib_table_entry_path_add(0,
8172 &pfx_10_10_10_1_s_32,
8174 FIB_ENTRY_FLAG_ATTACHED,
8177 tm->hw[0]->sw_if_index,
8178 ~0, // invalid fib index
8181 FIB_ROUTE_PATH_FLAG_NONE);
8184 * Delete the BFD session. Expect the fib_entry to remain
8186 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8188 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
8189 FIB_TEST(!fib_test_validate_entry(fei,
8190 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8193 "BFD sourced %U remains via %U",
8194 format_fib_prefix, &pfx_10_10_10_1_s_32,
8195 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
8198 * Add the BFD source back
8200 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8203 * Create another ADJ FIB
8205 fib_prefix_t pfx_10_10_10_2_s_32 = {
8206 .fp_addr = nh_10_10_10_2,
8208 .fp_proto = FIB_PROTOCOL_IP4,
8210 fib_table_entry_path_add(0,
8211 &pfx_10_10_10_2_s_32,
8213 FIB_ENTRY_FLAG_ATTACHED,
8216 tm->hw[0]->sw_if_index,
8217 ~0, // invalid fib index
8220 FIB_ROUTE_PATH_FLAG_NONE);
8222 * A BFD session for the new ADJ FIB
8224 bfd_session_t bfd_10_10_10_2 = {
8228 .peer_addr = nh_10_10_10_2,
8231 .hop_type = BFD_HOP_TYPE_MULTI,
8232 .local_state = BFD_STATE_init,
8235 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_2);
8238 * remove the adj-fib source whilst the session is present
8241 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
8242 fib_table_entry_path_add(0,
8243 &pfx_10_10_10_2_s_32,
8245 FIB_ENTRY_FLAG_ATTACHED,
8248 tm->hw[0]->sw_if_index,
8249 ~0, // invalid fib index
8252 FIB_ROUTE_PATH_FLAG_NONE);
8255 * Before adding a recursive via the BFD tracked ADJ-FIBs,
8256 * bring one of the sessions UP, leave the other down
8258 bfd_10_10_10_1.local_state = BFD_STATE_up;
8259 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8260 bfd_10_10_10_2.local_state = BFD_STATE_down;
8261 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8264 * A recursive prefix via both of the ADJ FIBs
8266 fib_prefix_t pfx_200_0_0_0_s_24 = {
8267 .fp_proto = FIB_PROTOCOL_IP4,
8270 .ip4.as_u32 = clib_host_to_net_u32(0xc8000000),
8273 const dpo_id_t *dpo_10_10_10_1, *dpo_10_10_10_2;
8276 fib_entry_contribute_ip_forwarding(
8277 fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32));
8279 fib_entry_contribute_ip_forwarding(
8280 fib_table_lookup_exact_match(0, &pfx_10_10_10_2_s_32));
8282 fib_test_lb_bucket_t lb_o_10_10_10_1 = {
8285 .lb = dpo_10_10_10_1->dpoi_index,
8288 fib_test_lb_bucket_t lb_o_10_10_10_2 = {
8291 .lb = dpo_10_10_10_2->dpoi_index,
8296 * A prefix via the adj-fib that is BFD down => DROP
8298 fei = fib_table_entry_path_add(0,
8299 &pfx_200_0_0_0_s_24,
8301 FIB_ENTRY_FLAG_NONE,
8305 0, // default fib index
8308 FIB_ROUTE_PATH_FLAG_NONE);
8309 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8310 "%U resolves via drop",
8311 format_fib_prefix, &pfx_200_0_0_0_s_24);
8314 * add a path via the UP BFD adj-fib.
8315 * we expect that the DOWN BFD ADJ FIB is not used.
8317 fei = fib_table_entry_path_add(0,
8318 &pfx_200_0_0_0_s_24,
8320 FIB_ENTRY_FLAG_NONE,
8324 0, // default fib index
8327 FIB_ROUTE_PATH_FLAG_NONE);
8329 FIB_TEST(!fib_test_validate_entry(fei,
8330 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8333 "Recursive %U only UP BFD adj-fibs",
8334 format_fib_prefix, &pfx_200_0_0_0_s_24);
8337 * Send a BFD state change to UP - both sessions are now up
8338 * the recursive prefix should LB over both
8340 bfd_10_10_10_2.local_state = BFD_STATE_up;
8341 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &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",
8350 format_fib_prefix, &pfx_200_0_0_0_s_24);
8353 * Send a BFD state change to DOWN
8354 * the recursive prefix should exclude the down
8356 bfd_10_10_10_2.local_state = BFD_STATE_down;
8357 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8360 FIB_TEST(!fib_test_validate_entry(fei,
8361 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8364 "Recursive %U via only UP",
8365 format_fib_prefix, &pfx_200_0_0_0_s_24);
8368 * Delete the BFD session while it is in the DOWN state.
8369 * FIB should consider the entry's state as back up
8371 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_2);
8373 FIB_TEST(!fib_test_validate_entry(fei,
8374 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8378 "Recursive %U via both UP BFD adj-fibs post down session delete",
8379 format_fib_prefix, &pfx_200_0_0_0_s_24);
8382 * Delete the BFD other session while it is in the UP state.
8384 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8386 FIB_TEST(!fib_test_validate_entry(fei,
8387 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8391 "Recursive %U via both UP BFD adj-fibs post up session delete",
8392 format_fib_prefix, &pfx_200_0_0_0_s_24);
8397 fib_table_entry_delete(0, &pfx_200_0_0_0_s_24, FIB_SOURCE_API);
8398 fib_table_entry_delete(0, &pfx_10_10_10_1_s_32, FIB_SOURCE_ADJ);
8399 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
8401 fib_table_entry_delete(0, &pfx_10_10_10_10_s_32, FIB_SOURCE_INTERFACE);
8402 fib_table_entry_delete(0, &pfx_10_10_10_10_s_24, FIB_SOURCE_INTERFACE);
8404 adj_unlock(ai_10_10_10_1);
8406 * test no-one left behind
8408 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8409 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8412 * Single-hop BFD tests
8414 bfd_10_10_10_1.hop_type = BFD_HOP_TYPE_SINGLE;
8415 bfd_10_10_10_1.udp.key.sw_if_index = tm->hw[0]->sw_if_index;
8417 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8419 ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8422 tm->hw[0]->sw_if_index);
8424 * whilst the BFD session is not signalled, the adj is up
8426 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on uninit session");
8429 * bring the BFD session up
8431 bfd_10_10_10_1.local_state = BFD_STATE_up;
8432 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8433 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on UP session");
8436 * bring the BFD session down
8438 bfd_10_10_10_1.local_state = BFD_STATE_down;
8439 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8440 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on DOWN session");
8443 * add an attached next hop FIB entry via the down adj
8445 fib_prefix_t pfx_5_5_5_5_s_32 = {
8448 .as_u32 = clib_host_to_net_u32(0x05050505),
8452 .fp_proto = FIB_PROTOCOL_IP4,
8455 fei = fib_table_entry_path_add(0,
8458 FIB_ENTRY_FLAG_NONE,
8461 tm->hw[0]->sw_if_index,
8462 ~0, // invalid fib index
8465 FIB_ROUTE_PATH_FLAG_NONE);
8466 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8467 "%U resolves via drop",
8468 format_fib_prefix, &pfx_5_5_5_5_s_32);
8471 * Add a path via an ADJ that is up
8473 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8476 tm->hw[0]->sw_if_index);
8478 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
8481 .adj = ai_10_10_10_2,
8484 adj_o_10_10_10_1.adj.adj = ai_10_10_10_1;
8486 fei = fib_table_entry_path_add(0,
8489 FIB_ENTRY_FLAG_NONE,
8492 tm->hw[0]->sw_if_index,
8493 ~0, // invalid fib index
8496 FIB_ROUTE_PATH_FLAG_NONE);
8498 FIB_TEST(!fib_test_validate_entry(fei,
8499 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8502 "BFD sourced %U via %U",
8503 format_fib_prefix, &pfx_5_5_5_5_s_32,
8504 format_ip_adjacency, ai_10_10_10_2, FORMAT_IP_ADJACENCY_NONE);
8507 * Bring up the down session - should now LB
8509 bfd_10_10_10_1.local_state = BFD_STATE_up;
8510 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8511 FIB_TEST(!fib_test_validate_entry(fei,
8512 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8516 "BFD sourced %U via noth adjs",
8517 format_fib_prefix, &pfx_5_5_5_5_s_32);
8520 * remove the BFD session state from the adj
8522 adj_bfd_notify(BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8527 fib_table_entry_delete(0, &pfx_5_5_5_5_s_32, FIB_SOURCE_CLI);
8528 adj_unlock(ai_10_10_10_1);
8529 adj_unlock(ai_10_10_10_2);
8532 * test no-one left behind
8534 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8535 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8543 const mpls_label_t deag_label = 50;
8544 adj_index_t ai_mpls_10_10_10_1;
8545 dpo_id_t dpo = DPO_INVALID;
8546 const u32 lfib_index = 0;
8547 const u32 fib_index = 0;
8548 const dpo_id_t *dpo1;
8549 fib_node_index_t lfe;
8556 lb_count = pool_elts(load_balance_pool);
8558 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
8562 * MPLS enable an interface so we get the MPLS table created
8564 mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL);
8565 mpls_sw_interface_enable_disable(&mpls_main,
8566 tm->hw[0]->sw_if_index,
8569 ip46_address_t nh_10_10_10_1 = {
8570 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
8572 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8575 tm->hw[0]->sw_if_index);
8578 * Test the specials stack properly.
8580 fib_prefix_t exp_null_v6_pfx = {
8581 .fp_proto = FIB_PROTOCOL_MPLS,
8583 .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8584 .fp_payload_proto = DPO_PROTO_IP6,
8586 lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx);
8587 FIB_TEST((FIB_NODE_INDEX_INVALID != lfe),
8589 format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8590 format_mpls_eos_bit, MPLS_EOS);
8591 fib_entry_contribute_forwarding(lfe,
8592 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8594 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8595 lkd = lookup_dpo_get(dpo1->dpoi_index);
8597 FIB_TEST((fib_index == lkd->lkd_fib_index),
8598 "%U/%U is deag in %d %U",
8599 format_mpls_unicast_label, deag_label,
8600 format_mpls_eos_bit, MPLS_EOS,
8602 format_dpo_id, &dpo, 0);
8603 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8604 "%U/%U is dst deag",
8605 format_mpls_unicast_label, deag_label,
8606 format_mpls_eos_bit, MPLS_EOS);
8607 FIB_TEST((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table),
8608 "%U/%U is lookup in interface's table",
8609 format_mpls_unicast_label, deag_label,
8610 format_mpls_eos_bit, MPLS_EOS);
8611 FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto),
8612 "%U/%U is %U dst deag",
8613 format_mpls_unicast_label, deag_label,
8614 format_mpls_eos_bit, MPLS_EOS,
8615 format_dpo_proto, lkd->lkd_proto);
8618 * A route deag route for EOS
8620 fib_prefix_t pfx = {
8621 .fp_proto = FIB_PROTOCOL_MPLS,
8623 .fp_label = deag_label,
8624 .fp_payload_proto = DPO_PROTO_IP4,
8626 mpls_disp_dpo_t *mdd;
8627 lfe = fib_table_entry_path_add(lfib_index,
8630 FIB_ENTRY_FLAG_NONE,
8637 FIB_ROUTE_PATH_FLAG_NONE);
8639 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8641 format_mpls_unicast_label, deag_label,
8642 format_mpls_eos_bit, MPLS_EOS);
8644 fib_entry_contribute_forwarding(lfe,
8645 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8647 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8648 mdd = mpls_disp_dpo_get(dpo1->dpoi_index);
8650 FIB_TEST((FIB_MPLS_LSP_MODE_PIPE == mdd->mdd_mode),
8651 "%U/%U disp is pipe mode",
8652 format_mpls_unicast_label, deag_label,
8653 format_mpls_eos_bit, MPLS_EOS);
8655 lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index);
8657 FIB_TEST((fib_index == lkd->lkd_fib_index),
8658 "%U/%U is deag in %d %U",
8659 format_mpls_unicast_label, deag_label,
8660 format_mpls_eos_bit, MPLS_EOS,
8662 format_dpo_id, &dpo, 0);
8663 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8664 "%U/%U is dst deag",
8665 format_mpls_unicast_label, deag_label,
8666 format_mpls_eos_bit, MPLS_EOS);
8667 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8668 "%U/%U is %U dst deag",
8669 format_mpls_unicast_label, deag_label,
8670 format_mpls_eos_bit, MPLS_EOS,
8671 format_dpo_proto, lkd->lkd_proto);
8673 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8675 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8677 "%U/%U not present",
8678 format_mpls_unicast_label, deag_label,
8679 format_mpls_eos_bit, MPLS_EOS);
8683 * A route deag route for EOS with LSP mode uniform
8685 fib_mpls_label_t *l_pops = NULL, l_pop = {
8686 .fml_value = MPLS_LABEL_POP,
8687 .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM,
8689 vec_add1(l_pops, l_pop);
8690 lfe = fib_table_entry_path_add(lfib_index,
8693 FIB_ENTRY_FLAG_NONE,
8700 FIB_ROUTE_PATH_FLAG_NONE);
8702 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8704 format_mpls_unicast_label, deag_label,
8705 format_mpls_eos_bit, MPLS_EOS);
8707 fib_entry_contribute_forwarding(lfe,
8708 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8710 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8711 mdd = mpls_disp_dpo_get(dpo1->dpoi_index);
8713 FIB_TEST((FIB_MPLS_LSP_MODE_UNIFORM == mdd->mdd_mode),
8714 "%U/%U disp is uniform mode",
8715 format_mpls_unicast_label, deag_label,
8716 format_mpls_eos_bit, MPLS_EOS);
8718 lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index);
8720 FIB_TEST((fib_index == lkd->lkd_fib_index),
8721 "%U/%U is deag in %d %U",
8722 format_mpls_unicast_label, deag_label,
8723 format_mpls_eos_bit, MPLS_EOS,
8725 format_dpo_id, &dpo, 0);
8726 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8727 "%U/%U is dst deag",
8728 format_mpls_unicast_label, deag_label,
8729 format_mpls_eos_bit, MPLS_EOS);
8730 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8731 "%U/%U is %U dst deag",
8732 format_mpls_unicast_label, deag_label,
8733 format_mpls_eos_bit, MPLS_EOS,
8734 format_dpo_proto, lkd->lkd_proto);
8736 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8738 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8740 "%U/%U not present",
8741 format_mpls_unicast_label, deag_label,
8742 format_mpls_eos_bit, MPLS_EOS);
8746 * A route deag route for non-EOS
8748 pfx.fp_eos = MPLS_NON_EOS;
8749 lfe = fib_table_entry_path_add(lfib_index,
8752 FIB_ENTRY_FLAG_NONE,
8759 FIB_ROUTE_PATH_FLAG_NONE);
8761 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8763 format_mpls_unicast_label, deag_label,
8764 format_mpls_eos_bit, MPLS_NON_EOS);
8766 fib_entry_contribute_forwarding(lfe,
8767 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8769 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8770 lkd = lookup_dpo_get(dpo1->dpoi_index);
8772 FIB_TEST((fib_index == lkd->lkd_fib_index),
8773 "%U/%U is deag in %d %U",
8774 format_mpls_unicast_label, deag_label,
8775 format_mpls_eos_bit, MPLS_NON_EOS,
8777 format_dpo_id, &dpo, 0);
8778 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8779 "%U/%U is dst deag",
8780 format_mpls_unicast_label, deag_label,
8781 format_mpls_eos_bit, MPLS_NON_EOS);
8783 FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto),
8784 "%U/%U is %U dst deag",
8785 format_mpls_unicast_label, deag_label,
8786 format_mpls_eos_bit, MPLS_NON_EOS,
8787 format_dpo_proto, lkd->lkd_proto);
8789 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8791 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8793 "%U/%U not present",
8794 format_mpls_unicast_label, deag_label,
8795 format_mpls_eos_bit, MPLS_EOS);
8802 fib_prefix_t pfx_1200 = {
8804 .fp_proto = FIB_PROTOCOL_MPLS,
8806 .fp_eos = MPLS_NON_EOS,
8808 fib_test_lb_bucket_t neos_o_10_10_10_1 = {
8809 .type = FT_LB_LABEL_STACK_O_ADJ,
8810 .label_stack_o_adj = {
8811 .adj = ai_mpls_10_10_10_1,
8812 .label_stack_size = 4,
8816 .eos = MPLS_NON_EOS,
8819 dpo_id_t neos_1200 = DPO_INVALID;
8820 dpo_id_t ip_1200 = DPO_INVALID;
8821 fib_mpls_label_t *l200 = NULL;
8823 for (ii = 0; ii < 4; ii++)
8825 fib_mpls_label_t fml = {
8826 .fml_value = 200 + (ii * 100),
8828 vec_add1(l200, fml);
8831 lfe = fib_table_entry_update_one_path(fib_index,
8834 FIB_ENTRY_FLAG_NONE,
8837 tm->hw[0]->sw_if_index,
8838 ~0, // invalid fib index
8841 FIB_ROUTE_PATH_FLAG_NONE);
8843 FIB_TEST(!fib_test_validate_entry(lfe,
8844 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8846 &neos_o_10_10_10_1),
8847 "1200/0 LB 1 buckets via: "
8851 * A recursive route via the MPLS x-connect
8853 fib_prefix_t pfx_2_2_2_3_s_32 = {
8855 .fp_proto = FIB_PROTOCOL_IP4,
8857 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
8860 fib_route_path_t *rpaths = NULL, rpath = {
8861 .frp_proto = DPO_PROTO_MPLS,
8862 .frp_local_label = 1200,
8863 .frp_eos = MPLS_NON_EOS,
8864 .frp_sw_if_index = ~0, // recurive
8865 .frp_fib_index = 0, // Default MPLS fib
8867 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
8868 .frp_label_stack = NULL,
8870 vec_add1(rpaths, rpath);
8872 fib_table_entry_path_add2(fib_index,
8875 FIB_ENTRY_FLAG_NONE,
8879 * A labelled recursive route via the MPLS x-connect
8881 fib_prefix_t pfx_2_2_2_4_s_32 = {
8883 .fp_proto = FIB_PROTOCOL_IP4,
8885 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
8888 fib_mpls_label_t *l999 = NULL, fml_999 = {
8891 vec_add1(l999, fml_999);
8892 rpaths[0].frp_label_stack = l999,
8894 fib_table_entry_path_add2(fib_index,
8897 FIB_ENTRY_FLAG_NONE,
8900 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8901 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8903 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8904 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8907 fib_test_lb_bucket_t ip_o_1200 = {
8910 .lb = ip_1200.dpoi_index,
8913 fib_test_lb_bucket_t mpls_o_1200 = {
8914 .type = FT_LB_LABEL_O_LB,
8916 .lb = neos_1200.dpoi_index,
8922 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
8923 FIB_TEST(!fib_test_validate_entry(lfe,
8924 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8927 "2.2.2.2.3/32 LB 1 buckets via: label 1200 EOS");
8928 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
8929 FIB_TEST(!fib_test_validate_entry(lfe,
8930 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8933 "2.2.2.2.4/32 LB 1 buckets via: label 1200 non-EOS");
8935 fib_table_entry_delete(fib_index, &pfx_1200, FIB_SOURCE_API);
8936 fib_table_entry_delete(fib_index, &pfx_2_2_2_3_s_32, FIB_SOURCE_API);
8937 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8939 dpo_reset(&neos_1200);
8940 dpo_reset(&ip_1200);
8943 * A recursive via a label that does not exist
8945 fib_test_lb_bucket_t bucket_drop = {
8948 .adj = DPO_PROTO_IP4,
8951 fib_test_lb_bucket_t mpls_bucket_drop = {
8954 .adj = DPO_PROTO_MPLS,
8958 rpaths[0].frp_label_stack = NULL;
8959 lfe = fib_table_entry_path_add2(fib_index,
8962 FIB_ENTRY_FLAG_NONE,
8965 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8966 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8968 ip_o_1200.lb.lb = ip_1200.dpoi_index;
8970 FIB_TEST(!fib_test_validate_entry(lfe,
8971 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8974 "2.2.2.2.4/32 LB 1 buckets via: drop");
8975 lfe = fib_table_lookup(fib_index, &pfx_1200);
8976 FIB_TEST(!fib_test_validate_entry(lfe,
8977 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8980 "1200/neos LB 1 buckets via: ip4-DROP");
8981 FIB_TEST(!fib_test_validate_entry(lfe,
8982 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8985 "1200/neos LB 1 buckets via: mpls-DROP");
8987 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8989 dpo_reset(&ip_1200);
8992 * An rx-interface route.
8993 * like the tail of an mcast LSP
8995 dpo_id_t idpo = DPO_INVALID;
8997 interface_rx_dpo_add_or_lock(DPO_PROTO_IP4,
8998 tm->hw[0]->sw_if_index,
9001 fib_prefix_t pfx_2500 = {
9003 .fp_proto = FIB_PROTOCOL_MPLS,
9006 .fp_payload_proto = DPO_PROTO_IP4,
9008 fib_test_lb_bucket_t rx_intf_0 = {
9011 .adj = idpo.dpoi_index,
9015 lfe = fib_table_entry_update_one_path(fib_index,
9018 FIB_ENTRY_FLAG_NONE,
9021 tm->hw[0]->sw_if_index,
9022 ~0, // invalid fib index
9025 FIB_ROUTE_PATH_INTF_RX);
9026 FIB_TEST(!fib_test_validate_entry(lfe,
9027 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9030 "2500 rx-interface 0");
9031 fib_table_entry_delete(fib_index, &pfx_2500, FIB_SOURCE_API);
9034 * An MPLS mulicast entry
9036 fib_prefix_t pfx_3500 = {
9038 .fp_proto = FIB_PROTOCOL_MPLS,
9041 .fp_payload_proto = DPO_PROTO_IP4,
9043 fib_test_rep_bucket_t mc_0 = {
9044 .type = FT_REP_LABEL_O_ADJ,
9046 .adj = ai_mpls_10_10_10_1,
9051 fib_test_rep_bucket_t mc_intf_0 = {
9052 .type = FT_REP_INTF,
9054 .adj = idpo.dpoi_index,
9057 fib_mpls_label_t *l3300 = NULL, fml_3300 = {
9060 vec_add1(l3300, fml_3300);
9062 lfe = fib_table_entry_update_one_path(lfib_index,
9065 FIB_ENTRY_FLAG_MULTICAST,
9068 tm->hw[0]->sw_if_index,
9069 ~0, // invalid fib index
9072 FIB_ROUTE_PATH_FLAG_NONE);
9073 FIB_TEST(!fib_test_validate_entry(lfe,
9074 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9077 "3500 via replicate over 10.10.10.1");
9080 * MPLS Bud-node. Add a replication via an interface-receieve path
9082 lfe = fib_table_entry_path_add(lfib_index,
9085 FIB_ENTRY_FLAG_MULTICAST,
9088 tm->hw[0]->sw_if_index,
9089 ~0, // invalid fib index
9092 FIB_ROUTE_PATH_INTF_RX);
9093 FIB_TEST(!fib_test_validate_entry(lfe,
9094 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9098 "3500 via replicate over 10.10.10.1 and interface-rx");
9101 * Add a replication via an interface-free for-us path
9103 fib_test_rep_bucket_t mc_disp = {
9104 .type = FT_REP_DISP_MFIB_LOOKUP,
9106 .adj = idpo.dpoi_index,
9109 lfe = fib_table_entry_path_add(lfib_index,
9112 FIB_ENTRY_FLAG_MULTICAST,
9119 FIB_ROUTE_PATH_RPF_ID);
9120 FIB_TEST(!fib_test_validate_entry(lfe,
9121 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9126 "3500 via replicate over 10.10.10.1 and interface-rx");
9130 fib_table_entry_delete(fib_index, &pfx_3500, FIB_SOURCE_API);
9136 mpls_sw_interface_enable_disable(&mpls_main,
9137 tm->hw[0]->sw_if_index,
9139 mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
9141 FIB_TEST(0 == pool_elts(mpls_disp_dpo_pool),
9142 "mpls_disp_dpo resources freed %d of %d",
9143 0, pool_elts(mpls_disp_dpo_pool));
9144 FIB_TEST(lb_count == pool_elts(load_balance_pool),
9145 "Load-balance resources freed %d of %d",
9146 lb_count, pool_elts(load_balance_pool));
9147 FIB_TEST(0 == pool_elts(interface_rx_dpo_pool),
9148 "interface_rx_dpo resources freed %d of %d",
9149 0, pool_elts(interface_rx_dpo_pool));
9155 fib_test_inherit (void)
9157 fib_node_index_t fei;
9168 for (i = 0; i <= 2; i++)
9170 im4->fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
9171 im6->fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
9173 n_feis = fib_entry_pool_size();
9175 const ip46_address_t nh_10_10_10_1 = {
9176 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
9178 const ip46_address_t nh_10_10_10_2 = {
9179 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
9181 const ip46_address_t nh_10_10_10_3 = {
9182 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
9184 const ip46_address_t nh_10_10_10_16 = {
9185 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a10),
9187 const ip46_address_t nh_10_10_10_20 = {
9188 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a14),
9190 const ip46_address_t nh_10_10_10_21 = {
9191 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a15),
9193 const ip46_address_t nh_10_10_10_22 = {
9194 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a16),
9196 const ip46_address_t nh_10_10_10_255 = {
9197 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0aff),
9199 const ip46_address_t nh_10_10_10_0 = {
9200 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a00),
9202 const ip46_address_t nh_10_10_0_0 = {
9203 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0000),
9205 const ip46_address_t nh_11_11_11_11 = {
9206 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
9208 const ip46_address_t nh_11_11_11_0 = {
9209 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b00),
9213 * prefixes at the base of a sub-tree
9215 const fib_prefix_t pfx_10_10_10_21_s_32 = {
9217 .fp_proto = FIB_PROTOCOL_IP4,
9218 .fp_addr = nh_10_10_10_21,
9220 const fib_prefix_t pfx_10_10_10_22_s_32 = {
9222 .fp_proto = FIB_PROTOCOL_IP4,
9223 .fp_addr = nh_10_10_10_22,
9225 const fib_prefix_t pfx_10_10_10_255_s_32 = {
9227 .fp_proto = FIB_PROTOCOL_IP4,
9228 .fp_addr = nh_10_10_10_255,
9230 const u32 N_PLS = fib_path_list_pool_size();
9232 fib_table_entry_special_add(0,
9233 &pfx_10_10_10_21_s_32,
9235 FIB_ENTRY_FLAG_DROP);
9236 fib_table_entry_special_add(0,
9237 &pfx_10_10_10_22_s_32,
9239 FIB_ENTRY_FLAG_DROP);
9240 fib_table_entry_special_add(0,
9241 &pfx_10_10_10_255_s_32,
9243 FIB_ENTRY_FLAG_DROP);
9246 * source an entry that pushes its state down the sub-tree
9248 const fib_prefix_t pfx_10_10_10_16_s_28 = {
9250 .fp_proto = FIB_PROTOCOL_IP4,
9251 .fp_addr = nh_10_10_10_16,
9253 fib_table_entry_update_one_path(0,
9254 &pfx_10_10_10_16_s_28,
9256 FIB_ENTRY_FLAG_COVERED_INHERIT,
9259 tm->hw[0]->sw_if_index,
9263 FIB_ROUTE_PATH_FLAG_NONE);
9266 * this covering entry and all those below it should have
9267 * the same forwarding information.
9269 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9272 tm->hw[0]->sw_if_index);
9273 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
9276 .adj = ai_10_10_10_1,
9280 fei = fib_table_lookup(0, &pfx_10_10_10_16_s_28);
9281 FIB_TEST(!fib_test_validate_entry(fei,
9282 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9285 "%U via 10.10.10.1",
9286 format_fib_prefix, &pfx_10_10_10_16_s_28);
9287 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9288 FIB_TEST(!fib_test_validate_entry(fei,
9289 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9292 "%U via 10.10.10.1",
9293 format_fib_prefix, &pfx_10_10_10_21_s_32);
9294 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9295 FIB_TEST(!fib_test_validate_entry(fei,
9296 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9299 "%U via 10.10.10.1",
9300 format_fib_prefix, &pfx_10_10_10_22_s_32);
9301 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9302 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9303 "%U resolves via drop",
9304 format_fib_prefix, &pfx_10_10_10_255_s_32);
9307 * remove the inherting cover - covereds go back to drop
9309 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_API);
9311 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9312 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9313 "%U resolves via drop",
9314 format_fib_prefix, &pfx_10_10_10_21_s_32);
9317 * source an entry that pushes its state down the sub-tree
9319 const fib_prefix_t pfx_10_10_10_0_s_24 = {
9321 .fp_proto = FIB_PROTOCOL_IP4,
9322 .fp_addr = nh_10_10_10_0,
9324 fib_table_entry_update_one_path(0,
9325 &pfx_10_10_10_0_s_24,
9327 FIB_ENTRY_FLAG_COVERED_INHERIT,
9330 tm->hw[0]->sw_if_index,
9334 FIB_ROUTE_PATH_FLAG_NONE);
9337 * whole sub-tree now covered
9339 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9340 FIB_TEST(!fib_test_validate_entry(fei,
9341 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9344 "%U via 10.10.10.1",
9345 format_fib_prefix, &pfx_10_10_10_0_s_24);
9346 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9347 FIB_TEST(!fib_test_validate_entry(fei,
9348 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9351 "%U via 10.10.10.1",
9352 format_fib_prefix, &pfx_10_10_10_21_s_32);
9353 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9354 FIB_TEST(!fib_test_validate_entry(fei,
9355 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9358 "%U via 10.10.10.1",
9359 format_fib_prefix, &pfx_10_10_10_22_s_32);
9360 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9361 FIB_TEST(!fib_test_validate_entry(fei,
9362 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9365 "%U via 10.10.10.1",
9366 format_fib_prefix, &pfx_10_10_10_255_s_32);
9369 * insert a more specific into the sub-tree - expect inheritance
9370 * this one is directly covered by the root
9372 fib_table_entry_special_add(0,
9373 &pfx_10_10_10_16_s_28,
9375 FIB_ENTRY_FLAG_DROP);
9376 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9377 FIB_TEST(!fib_test_validate_entry(fei,
9378 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9381 "%U via 10.10.10.1",
9382 format_fib_prefix, &pfx_10_10_10_16_s_28);
9385 * insert a more specific into the sub-tree - expect inheritance
9386 * this one is indirectly covered by the root
9388 const fib_prefix_t pfx_10_10_10_20_s_30 = {
9390 .fp_proto = FIB_PROTOCOL_IP4,
9391 .fp_addr = nh_10_10_10_20,
9393 fib_table_entry_special_add(0,
9394 &pfx_10_10_10_20_s_30,
9396 FIB_ENTRY_FLAG_DROP);
9397 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_20_s_30);
9398 FIB_TEST(!fib_test_validate_entry(fei,
9399 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9402 "%U via 10.10.10.1",
9403 format_fib_prefix, &pfx_10_10_10_20_s_30);
9406 * remove the prefix from the middle of the sub-tree
9407 * the inherited source will be the only one remaining - expect
9408 * it to be withdrawn and hence the prefix is removed.
9410 fib_table_entry_special_remove(0,
9411 &pfx_10_10_10_20_s_30,
9413 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_20_s_30);
9414 FIB_TEST((FIB_NODE_INDEX_INVALID == fei),
9416 format_fib_prefix, &pfx_10_10_10_20_s_30);
9419 * inheriting source is modifed - expect the modification to be present
9420 * throughout the sub-tree
9422 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9425 tm->hw[0]->sw_if_index);
9426 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
9429 .adj = ai_10_10_10_2,
9433 fib_table_entry_update_one_path(0,
9434 &pfx_10_10_10_0_s_24,
9436 FIB_ENTRY_FLAG_COVERED_INHERIT,
9439 tm->hw[0]->sw_if_index,
9443 FIB_ROUTE_PATH_FLAG_NONE);
9444 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9445 FIB_TEST(!fib_test_validate_entry(fei,
9446 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9449 "%U via 10.10.10.2",
9450 format_fib_prefix, &pfx_10_10_10_21_s_32);
9451 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9452 FIB_TEST(!fib_test_validate_entry(fei,
9453 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9456 "%U via 10.10.10.2",
9457 format_fib_prefix, &pfx_10_10_10_22_s_32);
9458 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9459 FIB_TEST(!fib_test_validate_entry(fei,
9460 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9463 "%U via 10.10.10.2",
9464 format_fib_prefix, &pfx_10_10_10_255_s_32);
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.2",
9471 format_fib_prefix, &pfx_10_10_10_0_s_24);
9473 fib_source_t hi_src = fib_source_allocate("test", 0x50,
9474 FIB_SOURCE_BH_SIMPLE);
9477 * add the source that replaces inherited state.
9478 * inheriting source is not the best, so it doesn't push state.
9480 fib_table_entry_update_one_path(0,
9481 &pfx_10_10_10_0_s_24,
9483 FIB_ENTRY_FLAG_NONE,
9486 tm->hw[0]->sw_if_index,
9490 FIB_ROUTE_PATH_FLAG_NONE);
9491 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9492 FIB_TEST(!fib_test_validate_entry(fei,
9493 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9496 "%U via 10.10.10.1",
9497 format_fib_prefix, &pfx_10_10_10_0_s_24);
9499 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9500 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9501 "%U resolves via drop",
9502 format_fib_prefix, &pfx_10_10_10_21_s_32);
9503 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9504 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9505 "%U resolves via drop",
9506 format_fib_prefix, &pfx_10_10_10_22_s_32);
9507 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9508 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9509 "%U resolves via drop",
9510 format_fib_prefix, &pfx_10_10_10_255_s_32);
9511 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9512 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9513 "%U resolves via drop",
9514 format_fib_prefix, &pfx_10_10_10_16_s_28);
9517 * withdraw the higher priority source and expect the inherited to return
9518 * throughout the sub-tree
9520 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, hi_src);
9522 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9523 FIB_TEST(!fib_test_validate_entry(fei,
9524 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9527 "%U via 10.10.10.2",
9528 format_fib_prefix, &pfx_10_10_10_21_s_32);
9529 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9530 FIB_TEST(!fib_test_validate_entry(fei,
9531 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9534 "%U via 10.10.10.2",
9535 format_fib_prefix, &pfx_10_10_10_22_s_32);
9536 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9537 FIB_TEST(!fib_test_validate_entry(fei,
9538 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9541 "%U via 10.10.10.2",
9542 format_fib_prefix, &pfx_10_10_10_255_s_32);
9543 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9544 FIB_TEST(!fib_test_validate_entry(fei,
9545 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9548 "%U via 10.10.10.2",
9549 format_fib_prefix, &pfx_10_10_10_0_s_24);
9550 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9551 FIB_TEST(!fib_test_validate_entry(fei,
9552 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9555 "%U via 10.10.10.2",
9556 format_fib_prefix, &pfx_10_10_10_16_s_28);
9559 * source a covered entry in the sub-tree with the same inherting source
9560 * - expect that it now owns the sub-tree and thus over-rides its cover
9562 fib_table_entry_update_one_path(0,
9563 &pfx_10_10_10_16_s_28,
9565 FIB_ENTRY_FLAG_COVERED_INHERIT,
9568 tm->hw[0]->sw_if_index,
9572 FIB_ROUTE_PATH_FLAG_NONE);
9573 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9574 FIB_TEST(!fib_test_validate_entry(fei,
9575 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9578 "%U via 10.10.10.1",
9579 format_fib_prefix, &pfx_10_10_10_16_s_28);
9580 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9581 FIB_TEST(!fib_test_validate_entry(fei,
9582 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9585 "%U via 10.10.10.2",
9586 format_fib_prefix, &pfx_10_10_10_22_s_32);
9587 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9588 FIB_TEST(!fib_test_validate_entry(fei,
9589 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9592 "%U via 10.10.10.2",
9593 format_fib_prefix, &pfx_10_10_10_21_s_32);
9595 /* these two unaffected by the sub-tree change */
9596 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
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_255_s_32);
9603 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
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_0_s_24);
9612 * removes the more specific, expect the /24 to now re-owns the sub-tree
9614 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_API);
9616 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9617 FIB_TEST(!fib_test_validate_entry(fei,
9618 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9621 "%U via 10.10.10.2",
9622 format_fib_prefix, &pfx_10_10_10_16_s_28);
9623 FIB_TEST(!fib_test_validate_entry(fei,
9624 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9627 "%U via 10.10.10.2",
9628 format_fib_prefix, &pfx_10_10_10_21_s_32);
9629 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9630 FIB_TEST(!fib_test_validate_entry(fei,
9631 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9634 "%U via 10.10.10.2",
9635 format_fib_prefix, &pfx_10_10_10_22_s_32);
9636 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9637 FIB_TEST(!fib_test_validate_entry(fei,
9638 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9641 "%U via 10.10.10.2",
9642 format_fib_prefix, &pfx_10_10_10_255_s_32);
9643 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9644 FIB_TEST(!fib_test_validate_entry(fei,
9645 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9648 "%U via 10.10.10.2",
9649 format_fib_prefix, &pfx_10_10_10_0_s_24);
9651 * modify the /24. expect the new forwarding to be pushed down
9653 fib_table_entry_update_one_path(0,
9654 &pfx_10_10_10_0_s_24,
9656 FIB_ENTRY_FLAG_COVERED_INHERIT,
9659 tm->hw[0]->sw_if_index,
9663 FIB_ROUTE_PATH_FLAG_NONE);
9664 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9665 FIB_TEST(!fib_test_validate_entry(fei,
9666 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9669 "%U via 10.10.10.1",
9670 format_fib_prefix, &pfx_10_10_10_16_s_28);
9671 FIB_TEST(!fib_test_validate_entry(fei,
9672 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9675 "%U via 10.10.10.1",
9676 format_fib_prefix, &pfx_10_10_10_21_s_32);
9677 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9678 FIB_TEST(!fib_test_validate_entry(fei,
9679 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9682 "%U via 10.10.10.1",
9683 format_fib_prefix, &pfx_10_10_10_22_s_32);
9684 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9685 FIB_TEST(!fib_test_validate_entry(fei,
9686 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9689 "%U via 10.10.10.1",
9690 format_fib_prefix, &pfx_10_10_10_255_s_32);
9691 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9692 FIB_TEST(!fib_test_validate_entry(fei,
9693 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9696 "%U via 10.10.10.1",
9697 format_fib_prefix, &pfx_10_10_10_0_s_24);
9700 * add an entry less specific to /24. it should not own the /24's tree
9702 const fib_prefix_t pfx_10_10_0_0_s_16 = {
9704 .fp_proto = FIB_PROTOCOL_IP4,
9705 .fp_addr = nh_10_10_0_0,
9707 fib_table_entry_update_one_path(0,
9708 &pfx_10_10_0_0_s_16,
9710 FIB_ENTRY_FLAG_COVERED_INHERIT,
9713 tm->hw[0]->sw_if_index,
9717 FIB_ROUTE_PATH_FLAG_NONE);
9718 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9719 FIB_TEST(!fib_test_validate_entry(fei,
9720 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9723 "%U via 10.10.10.1",
9724 format_fib_prefix, &pfx_10_10_10_16_s_28);
9725 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9726 FIB_TEST(!fib_test_validate_entry(fei,
9727 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9730 "%U via 10.10.10.1",
9731 format_fib_prefix, &pfx_10_10_10_22_s_32);
9732 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9733 FIB_TEST(!fib_test_validate_entry(fei,
9734 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9737 "%U via 10.10.10.1",
9738 format_fib_prefix, &pfx_10_10_10_255_s_32);
9739 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9740 FIB_TEST(!fib_test_validate_entry(fei,
9741 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9744 "%U via 10.10.10.1",
9745 format_fib_prefix, &pfx_10_10_10_0_s_24);
9746 fei = fib_table_lookup_exact_match(0, &pfx_10_10_0_0_s_16);
9747 FIB_TEST(!fib_test_validate_entry(fei,
9748 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9751 "%U via 10.10.10.2",
9752 format_fib_prefix, &pfx_10_10_0_0_s_16);
9755 * Add/remove an interposer source to a new /32
9757 const fib_prefix_t pfx_11_11_11_11_s_32 = {
9759 .fp_proto = FIB_PROTOCOL_IP4,
9760 .fp_addr = nh_11_11_11_11,
9763 fib_table_entry_update_one_path(0,
9764 &pfx_11_11_11_11_s_32,
9766 FIB_ENTRY_FLAG_NONE,
9769 tm->hw[0]->sw_if_index,
9773 FIB_ROUTE_PATH_FLAG_NONE);
9775 dpo_id_t interposer = DPO_INVALID;
9776 fib_mpls_label_t *l99 = NULL, fml_99 = {
9779 vec_add1(l99, fml_99);
9781 mpls_label_dpo_create(l99,
9784 MPLS_LABEL_DPO_FLAG_NONE,
9785 punt_dpo_get(DPO_PROTO_MPLS),
9788 adj_index_t ai_10_10_10_3 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9791 tm->hw[0]->sw_if_index);
9792 fib_test_lb_bucket_t adj_o_10_10_10_3 = {
9795 .adj = ai_10_10_10_3,
9798 fib_test_lb_bucket_t l99_o_10_10_10_3 = {
9799 .type = FT_LB_LABEL_O_ADJ,
9801 .adj = ai_10_10_10_3,
9807 fei = fib_table_entry_special_dpo_add(0,
9808 &pfx_11_11_11_11_s_32,
9810 FIB_ENTRY_FLAG_INTERPOSE,
9812 FIB_TEST(!fib_test_validate_entry(fei,
9813 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9816 "%U via interposer adj",
9817 format_fib_prefix,&pfx_11_11_11_11_s_32);
9819 fib_table_entry_special_remove(0,
9820 &pfx_11_11_11_11_s_32,
9821 FIB_SOURCE_SPECIAL);
9822 FIB_TEST(!fib_test_validate_entry(fei,
9823 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9826 "%U via 10.10.10.1",
9827 format_fib_prefix, &pfx_11_11_11_11_s_32);
9828 dpo_reset(&interposer);
9829 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
9832 * add an interposer to a source with path-extensions
9834 fib_mpls_label_t *l3300 = NULL, fml_3300 = {
9837 vec_add1(l3300, fml_3300);
9838 fib_table_entry_update_one_path(0,
9839 &pfx_11_11_11_11_s_32,
9841 FIB_ENTRY_FLAG_NONE,
9844 tm->hw[0]->sw_if_index,
9848 FIB_ROUTE_PATH_FLAG_NONE);
9850 mpls_label_dpo_create(l99,
9853 MPLS_LABEL_DPO_FLAG_NONE,
9854 punt_dpo_get(DPO_PROTO_MPLS),
9857 adj_index_t ai_mpls_10_10_10_3 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9860 tm->hw[0]->sw_if_index);
9861 fib_test_lb_bucket_t l3300_o_10_10_10_3 = {
9862 .type = FT_LB_LABEL_O_ADJ,
9864 .adj = ai_mpls_10_10_10_3,
9869 fib_test_lb_bucket_t lchain_o_10_10_10_3 = {
9870 .type = FT_LB_LABEL_CHAIN_O_ADJ,
9871 .label_chain_o_adj = {
9872 .adj = ai_mpls_10_10_10_3,
9873 .label_chain_size = 2,
9881 fei = fib_table_entry_special_dpo_add(0,
9882 &pfx_11_11_11_11_s_32,
9884 FIB_ENTRY_FLAG_INTERPOSE,
9887 FIB_TEST(!fib_test_validate_entry(fei,
9888 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9890 &lchain_o_10_10_10_3),
9891 "%U via interposer & mpls on adj",
9892 format_fib_prefix, &pfx_11_11_11_11_s_32);
9894 fib_table_entry_special_remove(0,
9895 &pfx_11_11_11_11_s_32,
9896 FIB_SOURCE_SPECIAL);
9897 FIB_TEST(!fib_test_validate_entry(fei,
9898 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9900 &l3300_o_10_10_10_3),
9901 "%U via 10.10.10.1",
9902 format_fib_prefix, &pfx_11_11_11_11_s_32);
9903 adj_unlock(ai_mpls_10_10_10_3);
9906 * remove and re-add the second best API source while the interpose
9909 fei = fib_table_entry_special_dpo_add(0,
9910 &pfx_11_11_11_11_s_32,
9912 FIB_ENTRY_FLAG_INTERPOSE,
9914 FIB_TEST(!fib_test_validate_entry(fei,
9915 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9917 &lchain_o_10_10_10_3),
9918 "%U via interposer adj",
9919 format_fib_prefix,&pfx_11_11_11_11_s_32);
9921 FIB_TEST(3 == pool_elts(mpls_label_dpo_pool),
9922 "MPLS label pool: %d",
9923 pool_elts(mpls_label_dpo_pool));
9925 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
9928 * the interpose does not get stacked when there are not valid paths
9930 fib_test_lb_bucket_t bucket_drop = {
9933 .adj = DPO_PROTO_IP4,
9936 FIB_TEST(!fib_test_validate_entry(fei,
9937 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9941 format_fib_prefix,&pfx_11_11_11_11_s_32);
9943 fib_table_entry_update_one_path(0,
9944 &pfx_11_11_11_11_s_32,
9946 FIB_ENTRY_FLAG_NONE,
9949 tm->hw[0]->sw_if_index,
9953 FIB_ROUTE_PATH_FLAG_NONE);
9954 FIB_TEST(!fib_test_validate_entry(fei,
9955 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9958 "%U via interposer adj",
9959 format_fib_prefix,&pfx_11_11_11_11_s_32);
9960 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
9963 * add a cover for the interposed entry, so that we test it selects
9964 * the covers forwarding.
9966 const fib_prefix_t pfx_11_11_11_0_s_24 = {
9968 .fp_proto = FIB_PROTOCOL_IP4,
9969 .fp_addr = nh_11_11_11_0,
9971 fib_table_entry_update_one_path(0,
9972 &pfx_11_11_11_0_s_24,
9974 FIB_ENTRY_FLAG_NONE,
9977 tm->hw[0]->sw_if_index,
9981 FIB_ROUTE_PATH_FLAG_NONE);
9982 FIB_TEST(!fib_test_validate_entry(fei,
9983 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9986 "%U via interposer adj",
9987 format_fib_prefix,&pfx_11_11_11_11_s_32);
9990 * multiple interpose sources on the same entry. Only the high
9991 * priority source gets to add the interpose.
9993 fib_table_entry_update_one_path(0,
9994 &pfx_11_11_11_11_s_32,
9996 FIB_ENTRY_FLAG_NONE,
9999 tm->hw[0]->sw_if_index,
10003 FIB_ROUTE_PATH_FLAG_NONE);
10005 dpo_id_t interposer2 = DPO_INVALID;
10006 fib_mpls_label_t *l100 = NULL, fml_100 = {
10009 vec_add1(l100, fml_100);
10011 mpls_label_dpo_create(l100,
10014 MPLS_LABEL_DPO_FLAG_NONE,
10015 punt_dpo_get(DPO_PROTO_MPLS),
10018 fei = fib_table_entry_special_dpo_add(0,
10019 &pfx_11_11_11_11_s_32,
10020 FIB_SOURCE_CLASSIFY,
10021 FIB_ENTRY_FLAG_INTERPOSE,
10024 fib_test_lb_bucket_t lc100_o_10_10_10_3 = {
10025 .type = FT_LB_LABEL_CHAIN_O_ADJ,
10026 .label_chain_o_adj = {
10027 .adj = ai_10_10_10_3,
10028 .label_chain_size = 2,
10036 FIB_TEST(!fib_test_validate_entry(fei,
10037 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10039 &lc100_o_10_10_10_3),
10040 "%U via interposer label 99",
10041 format_fib_prefix,&pfx_11_11_11_11_s_32);
10043 fib_test_lb_bucket_t l100_o_10_10_10_3 = {
10044 .type = FT_LB_LABEL_O_ADJ,
10046 .adj = ai_10_10_10_3,
10052 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_SPECIAL);
10054 FIB_TEST(!fib_test_validate_entry(fei,
10055 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10057 &l100_o_10_10_10_3),
10058 "%U via interposer label 99",
10059 format_fib_prefix,&pfx_11_11_11_11_s_32);
10061 fib_table_entry_delete(0, &pfx_11_11_11_0_s_24, FIB_SOURCE_API);
10062 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
10063 FIB_TEST(!fib_test_validate_entry(fei,
10064 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10068 format_fib_prefix,&pfx_11_11_11_11_s_32);
10069 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_CLASSIFY);
10072 * update a source to/from interpose.
10074 /* fib_table_entry_update_one_path(0, */
10075 /* &pfx_11_11_11_0_s_24, */
10076 /* FIB_SOURCE_API, */
10077 /* FIB_ENTRY_FLAG_NONE, */
10078 /* DPO_PROTO_IP4, */
10079 /* &nh_10_10_10_3, */
10080 /* tm->hw[0]->sw_if_index, */
10084 /* FIB_ROUTE_PATH_FLAG_NONE); */
10085 /* fei = fib_table_entry_special_dpo_add(0, */
10086 /* &pfx_11_11_11_11_s_32, */
10087 /* FIB_SOURCE_API, */
10088 /* FIB_ENTRY_FLAG_INTERPOSE, */
10089 /* &interposer); */
10090 /* FIB_TEST(!fib_test_validate_entry(fei, */
10091 /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */
10093 /* &l99_o_10_10_10_3), */
10094 /* "%U via interposer label 99", */
10095 /* format_fib_prefix,&pfx_11_11_11_11_s_32); */
10097 /* FIB_TEST(3 == pool_elts(mpls_label_dpo_pool), */
10098 /* "MPLS label pool: %d", */
10099 /* pool_elts(mpls_label_dpo_pool)); */
10100 /* FIB_TEST((2 == mpls_label_dpo_get(interposer.dpoi_index)->mld_locks), */
10101 /* "Interposer %d locks", */
10102 /* mpls_label_dpo_get(interposer.dpoi_index)->mld_locks); */
10104 /* fib_table_entry_update_one_path(0, */
10105 /* &pfx_11_11_11_11_s_32, */
10106 /* FIB_SOURCE_API, */
10107 /* FIB_ENTRY_FLAG_NONE, */
10108 /* DPO_PROTO_IP4, */
10109 /* &nh_10_10_10_2, */
10110 /* tm->hw[0]->sw_if_index, */
10114 /* FIB_ROUTE_PATH_FLAG_NONE); */
10115 /* FIB_TEST(!fib_test_validate_entry(fei, */
10116 /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */
10118 /* &adj_o_10_10_10_2), */
10119 /* "%U via 10.10.10.2", */
10120 /* format_fib_prefix,&pfx_11_11_11_11_s_32); */
10122 /* FIB_TEST((1 == mpls_label_dpo_get(interposer.dpoi_index)->mld_locks), */
10123 /* "Interposer %d locks", */
10124 /* mpls_label_dpo_get(interposer.dpoi_index)->mld_locks); */
10125 /* FIB_TEST(2 == pool_elts(mpls_label_dpo_pool), */
10126 /* "MPLS label pool: %d", */
10127 /* pool_elts(mpls_label_dpo_pool)); */
10129 /* fei = fib_table_entry_special_dpo_add(0, */
10130 /* &pfx_11_11_11_11_s_32, */
10131 /* FIB_SOURCE_API, */
10132 /* FIB_ENTRY_FLAG_INTERPOSE, */
10133 /* &interposer); */
10134 /* FIB_TEST(!fib_test_validate_entry(fei, */
10135 /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */
10137 /* &l99_o_10_10_10_3), */
10138 /* "%U via interposer label 99", */
10139 /* format_fib_prefix,&pfx_11_11_11_11_s_32); */
10141 /* fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API); */
10144 * Add/remove an interposer source from the top of the subtrie. The
10145 * interposer source is not inherited.
10147 fib_table_entry_update_one_path(0,
10148 &pfx_10_10_10_0_s_24,
10150 FIB_ENTRY_FLAG_COVERED_INHERIT,
10153 tm->hw[0]->sw_if_index,
10157 FIB_ROUTE_PATH_FLAG_NONE);
10158 fei = fib_table_entry_special_dpo_add(0,
10159 &pfx_10_10_10_0_s_24,
10160 FIB_SOURCE_SPECIAL,
10161 FIB_ENTRY_FLAG_INTERPOSE,
10163 FIB_TEST(!fib_test_validate_entry(fei,
10164 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10166 &l99_o_10_10_10_3),
10167 "%U via interposer label",
10168 format_fib_prefix,&pfx_10_10_10_0_s_24);
10169 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
10170 FIB_TEST(!fib_test_validate_entry(fei,
10171 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10175 format_fib_prefix, &pfx_10_10_10_21_s_32);
10177 fib_table_entry_special_remove(0,
10178 &pfx_10_10_10_0_s_24,
10179 FIB_SOURCE_SPECIAL);
10180 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
10181 FIB_TEST(!fib_test_validate_entry(fei,
10182 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10184 &adj_o_10_10_10_3),
10185 "%U via 10.10.10.1",
10186 format_fib_prefix, &pfx_10_10_10_0_s_24);
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,
10191 &adj_o_10_10_10_3),
10192 "%U via via 10.10.10.1",
10193 format_fib_prefix, &pfx_10_10_10_21_s_32);
10196 * Add/remove an interposer source from the top of the subtrie. The
10197 * interposer source is inherited.
10199 fei = fib_table_entry_special_dpo_add(0,
10200 &pfx_10_10_10_0_s_24,
10201 FIB_SOURCE_SPECIAL,
10202 (FIB_ENTRY_FLAG_COVERED_INHERIT |
10203 FIB_ENTRY_FLAG_INTERPOSE),
10205 FIB_TEST(!fib_test_validate_entry(fei,
10206 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10208 &l99_o_10_10_10_3),
10209 "%U via interposer label",
10210 format_fib_prefix,&pfx_10_10_10_0_s_24);
10212 /* interposer gets forwarding from the drop cli source */
10213 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
10214 FIB_TEST(!fib_test_validate_entry(fei,
10215 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10219 format_fib_prefix,&pfx_10_10_10_21_s_32);
10221 fib_table_entry_update_one_path(0,
10222 &pfx_10_10_10_21_s_32,
10224 FIB_ENTRY_FLAG_NONE,
10227 tm->hw[0]->sw_if_index,
10231 FIB_ROUTE_PATH_FLAG_NONE);
10232 fib_table_entry_delete(0, &pfx_10_10_10_21_s_32, FIB_SOURCE_CLI);
10233 /* interposer gets forwarding from the API source */
10234 FIB_TEST(!fib_test_validate_entry(fei,
10235 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10237 &l99_o_10_10_10_3),
10238 "%U via interposer label",
10239 format_fib_prefix,&pfx_10_10_10_21_s_32);
10244 fib_table_entry_delete(0, &pfx_10_10_10_22_s_32, FIB_SOURCE_CLI);
10245 fib_table_entry_delete(0, &pfx_10_10_10_21_s_32, FIB_SOURCE_API);
10246 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_CLI);
10247 fib_table_entry_delete(0, &pfx_10_10_10_255_s_32, FIB_SOURCE_CLI);
10248 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, FIB_SOURCE_API);
10249 fib_table_entry_delete(0, &pfx_10_10_0_0_s_16, FIB_SOURCE_API);
10250 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, FIB_SOURCE_SPECIAL);
10251 adj_unlock(ai_10_10_10_1);
10252 adj_unlock(ai_10_10_10_2);
10253 adj_unlock(ai_10_10_10_3);
10254 dpo_reset(&interposer);
10255 dpo_reset(&interposer2);
10256 FIB_TEST(0 == pool_elts(mpls_label_dpo_pool),
10257 "MPLS label pool empty: %d",
10258 pool_elts(mpls_label_dpo_pool));
10259 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
10260 FIB_TEST(N_PLS == fib_path_list_pool_size(),
10261 "number of path-lists: %d = %d",
10262 N_PLS, fib_path_list_pool_size());
10265 * test the v6 tree walk.
10266 * a /64 that covers everything. a /96 that covers one /128
10267 * a second /128 covered only by the /64.
10269 const fib_prefix_t pfx_2001_s_64 = {
10271 .fp_proto = FIB_PROTOCOL_IP6,
10275 [0] = clib_host_to_net_u64(0x2001000000000000),
10276 [1] = clib_host_to_net_u64(0x0000000000000000),
10281 const fib_prefix_t pfx_2001_1_s_96 = {
10283 .fp_proto = FIB_PROTOCOL_IP6,
10287 [0] = clib_host_to_net_u64(0x2001000000000000),
10288 [1] = clib_host_to_net_u64(0x1000000000000000),
10293 const fib_prefix_t pfx_2001_1_1_s_128 = {
10295 .fp_proto = FIB_PROTOCOL_IP6,
10299 [0] = clib_host_to_net_u64(0x2001000000000000),
10300 [1] = clib_host_to_net_u64(0x1000000000000001),
10305 const fib_prefix_t pfx_2001_0_1_s_128 = {
10307 .fp_proto = FIB_PROTOCOL_IP6,
10311 [0] = clib_host_to_net_u64(0x2001000000000000),
10312 [1] = clib_host_to_net_u64(0x0000000000000001),
10317 const ip46_address_t nh_3000_1 = {
10320 [0] = clib_host_to_net_u64(0x3000000000000000),
10321 [1] = clib_host_to_net_u64(0x0000000000000001),
10325 const ip46_address_t nh_3000_2 = {
10328 [0] = clib_host_to_net_u64(0x3000000000000000),
10329 [1] = clib_host_to_net_u64(0x0000000000000002),
10333 adj_index_t ai_3000_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
10336 tm->hw[0]->sw_if_index);
10337 adj_index_t ai_3000_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
10340 tm->hw[0]->sw_if_index);
10341 fib_test_lb_bucket_t adj_o_3000_1 = {
10347 fib_test_lb_bucket_t adj_o_3000_2 = {
10354 fib_table_entry_special_add(0,
10355 &pfx_2001_0_1_s_128,
10357 FIB_ENTRY_FLAG_DROP);
10358 fib_table_entry_special_add(0,
10359 &pfx_2001_1_1_s_128,
10361 FIB_ENTRY_FLAG_DROP);
10364 * /96 has inherited forwarding pushed down to its covered /128
10366 fib_table_entry_update_one_path(0,
10369 FIB_ENTRY_FLAG_COVERED_INHERIT,
10372 tm->hw[0]->sw_if_index,
10376 FIB_ROUTE_PATH_FLAG_NONE);
10377 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_s_96);
10378 FIB_TEST(!fib_test_validate_entry(fei,
10379 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10383 format_fib_prefix, &pfx_2001_1_s_96);
10384 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_1_s_128);
10385 FIB_TEST(!fib_test_validate_entry(fei,
10386 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10390 format_fib_prefix, &pfx_2001_1_1_s_128);
10391 fei = fib_table_lookup_exact_match(0, &pfx_2001_0_1_s_128);
10392 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
10393 "%U resolves via drop",
10394 format_fib_prefix, &pfx_2001_0_1_s_128);
10397 * /64 has inherited forwarding pushed down to all, but the /96
10398 * and its sub-tree remain unaffected.
10400 fib_table_entry_update_one_path(0,
10403 FIB_ENTRY_FLAG_COVERED_INHERIT,
10406 tm->hw[0]->sw_if_index,
10410 FIB_ROUTE_PATH_FLAG_NONE);
10412 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
10413 FIB_TEST(!fib_test_validate_entry(fei,
10414 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10418 format_fib_prefix, &pfx_2001_s_64);
10419 fei = fib_table_lookup_exact_match(0, &pfx_2001_0_1_s_128);
10420 FIB_TEST(!fib_test_validate_entry(fei,
10421 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10425 format_fib_prefix, &pfx_2001_0_1_s_128);
10427 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_s_96);
10428 FIB_TEST(!fib_test_validate_entry(fei,
10429 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10433 format_fib_prefix, &pfx_2001_1_s_96);
10434 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_1_s_128);
10435 FIB_TEST(!fib_test_validate_entry(fei,
10436 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10440 format_fib_prefix, &pfx_2001_1_1_s_128);
10445 fib_table_entry_delete(0, &pfx_2001_0_1_s_128, FIB_SOURCE_CLI);
10446 fib_table_entry_delete(0, &pfx_2001_1_1_s_128, FIB_SOURCE_CLI);
10447 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
10448 fib_table_entry_delete(0, &pfx_2001_1_s_96, FIB_SOURCE_API);
10449 adj_unlock(ai_3000_1);
10450 adj_unlock(ai_3000_2);
10453 * test no-one left behind
10455 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
10456 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
10462 fib_test_sticky (void)
10464 fib_route_path_t *r_paths = NULL;
10465 test_main_t *tm = &test_main;
10466 u32 ii, lb_count, pl_count;
10467 dpo_id_t dpo = DPO_INVALID;
10468 fib_node_index_t pl_index;
10472 fib_test_lb_bucket_t buckets[N_PATHS];
10473 bfd_session_t bfds[N_PATHS] = {{0}};
10475 lb_count = pool_elts(load_balance_pool);
10476 pl_count = fib_path_list_pool_size();
10478 for (ii = 0; ii < N_PATHS; ii++)
10480 ip46_address_t nh = {
10481 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
10485 ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
10487 &nh, tm->hw[0]->sw_if_index);
10489 buckets[ii].type = FT_LB_ADJ;
10490 buckets[ii].adj.adj = ai;
10492 bfds[ii].udp.key.peer_addr = nh;
10493 bfds[ii].udp.key.sw_if_index = tm->hw[0]->sw_if_index;
10494 bfds[ii].hop_type = BFD_HOP_TYPE_SINGLE;
10495 bfds[ii].local_state = BFD_STATE_init;
10496 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfds[ii]);
10497 bfds[ii].local_state = BFD_STATE_up;
10498 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[ii]);
10501 for (ii = 0; ii < N_PATHS; ii++)
10503 fib_route_path_t r_path = {
10504 .frp_proto = DPO_PROTO_IP4,
10506 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
10508 .frp_sw_if_index = tm->hw[0]->sw_if_index,
10510 .frp_fib_index = ~0,
10512 vec_add1(r_paths, r_path);
10515 pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths);
10516 fib_path_list_lock(pl_index);
10518 fib_path_list_contribute_forwarding(pl_index,
10519 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10520 FIB_PATH_LIST_FWD_FLAG_STICKY,
10523 FIB_TEST(!fib_test_validate_lb(&dpo,
10543 /* take down paths */
10544 bfds[0].local_state = BFD_STATE_down;
10545 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[0]);
10547 fib_path_list_contribute_forwarding(pl_index,
10548 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10549 FIB_PATH_LIST_FWD_FLAG_STICKY,
10552 FIB_TEST(!fib_test_validate_lb(&dpo,
10570 "Failed at shut-down path 0");
10572 bfds[7].local_state = BFD_STATE_down;
10573 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[7]);
10575 fib_path_list_contribute_forwarding(pl_index,
10576 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10577 FIB_PATH_LIST_FWD_FLAG_STICKY,
10580 FIB_TEST(!fib_test_validate_lb(&dpo,
10598 "Failed at shut-down path 7");
10600 /* paths back up */
10601 bfds[0].local_state = BFD_STATE_up;
10602 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[0]);
10603 bfds[7].local_state = BFD_STATE_up;
10604 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[7]);
10606 fib_path_list_contribute_forwarding(pl_index,
10607 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10608 FIB_PATH_LIST_FWD_FLAG_STICKY,
10611 FIB_TEST(!fib_test_validate_lb(&dpo,
10631 fib_path_list_unlock(pl_index);
10634 * non-power of 2 number of buckets
10636 fib_route_path_t *r_paths2 = NULL;
10638 r_paths2 = vec_dup(r_paths);
10639 _vec_len(r_paths2) = 3;
10641 pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths2);
10642 fib_path_list_lock(pl_index);
10644 fib_path_list_contribute_forwarding(pl_index,
10645 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10646 FIB_PATH_LIST_FWD_FLAG_STICKY,
10649 FIB_TEST(!fib_test_validate_lb(&dpo,
10669 bfds[1].local_state = BFD_STATE_down;
10670 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10672 fib_path_list_contribute_forwarding(pl_index,
10673 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10674 FIB_PATH_LIST_FWD_FLAG_STICKY,
10678 * path 1's buckets alternate between path 0 and 2
10680 FIB_TEST(!fib_test_validate_lb(&dpo,
10699 bfds[1].local_state = BFD_STATE_up;
10700 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10702 fib_path_list_unlock(pl_index);
10707 fib_route_path_t *r_paths3 = NULL;
10709 r_paths3 = vec_dup(r_paths);
10710 _vec_len(r_paths3) = 3;
10712 r_paths3[0].frp_weight = 3;
10714 pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths3);
10715 fib_path_list_lock(pl_index);
10717 fib_path_list_contribute_forwarding(pl_index,
10718 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10719 FIB_PATH_LIST_FWD_FLAG_STICKY,
10722 FIB_TEST(!fib_test_validate_lb(&dpo,
10742 bfds[1].local_state = BFD_STATE_down;
10743 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10745 fib_path_list_contribute_forwarding(pl_index,
10746 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10747 FIB_PATH_LIST_FWD_FLAG_STICKY,
10749 /* No attempt to Un-equal distribute the down path's buckets */
10750 FIB_TEST(!fib_test_validate_lb(&dpo,
10769 bfds[1].local_state = BFD_STATE_up;
10770 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10773 fib_path_list_unlock(pl_index);
10776 vec_free(r_paths2);
10777 vec_free(r_paths3);
10779 FIB_TEST(lb_count == pool_elts(load_balance_pool), "no leaked LBs");
10780 FIB_TEST(pl_count == fib_path_list_pool_size(), "no leaked PLs");
10785 static clib_error_t *
10786 fib_test (vlib_main_t * vm,
10787 unformat_input_t * input,
10788 vlib_cli_command_t * cmd_arg)
10794 fib_test_mk_intf(4);
10796 if (unformat (input, "debug"))
10798 fib_test_do_debug = 1;
10801 if (unformat (input, "ip4"))
10803 res += fib_test_v4();
10805 else if (unformat (input, "ip6"))
10807 res += fib_test_v6();
10809 else if (unformat (input, "ip"))
10811 res += fib_test_v4();
10812 res += fib_test_v6();
10814 else if (unformat (input, "label"))
10816 res += fib_test_label();
10818 else if (unformat (input, "ae"))
10820 res += fib_test_ae();
10822 else if (unformat (input, "pref"))
10824 res += fib_test_pref();
10826 else if (unformat (input, "lfib"))
10828 res += lfib_test();
10830 else if (unformat (input, "walk"))
10832 res += fib_test_walk();
10834 else if (unformat (input, "bfd"))
10836 res += fib_test_bfd();
10838 else if (unformat (input, "inherit"))
10840 res += fib_test_inherit();
10842 else if (unformat (input, "sticky"))
10844 res += fib_test_sticky();
10848 res += fib_test_v4();
10849 res += fib_test_v6();
10850 res += fib_test_ae();
10851 res += fib_test_bfd();
10852 res += fib_test_pref();
10853 res += fib_test_label();
10854 res += fib_test_inherit();
10855 res += lfib_test();
10858 * fib-walk process must be disabled in order for the walk tests to work
10860 fib_walk_process_disable();
10861 res += fib_test_walk();
10862 fib_walk_process_enable();
10868 return clib_error_return(0, "FIB Unit Test Failed");
10876 VLIB_CLI_COMMAND (test_fib_command, static) = {
10877 .path = "test fib",
10878 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
10879 .function = fib_test,
10883 fib_test_init (vlib_main_t *vm)
10888 VLIB_INIT_FUNCTION (fib_test_init);