2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 #include <vnet/fib/fib_test.h>
17 #include <vnet/fib/ip6_fib.h>
18 #include <vnet/fib/ip4_fib.h>
19 #include <vnet/fib/mpls_fib.h>
20 #include <vnet/adj/adj.h>
21 #include <vnet/dpo/load_balance.h>
22 #include <vnet/dpo/load_balance_map.h>
23 #include <vnet/dpo/mpls_label_dpo.h>
24 #include <vnet/dpo/lookup_dpo.h>
25 #include <vnet/dpo/drop_dpo.h>
26 #include <vnet/dpo/receive_dpo.h>
27 #include <vnet/dpo/ip_null_dpo.h>
28 #include <vnet/bfd/bfd_main.h>
29 #include <vnet/dpo/interface_rx_dpo.h>
30 #include <vnet/dpo/replicate_dpo.h>
31 #include <vnet/dpo/dvr_dpo.h>
32 #include <vnet/dpo/mpls_disposition.h>
33 #include <vnet/dpo/punt_dpo.h>
35 #include <vnet/mpls/mpls.h>
37 #include <vnet/fib/fib_test.h>
38 #include <vnet/fib/fib_path_list.h>
39 #include <vnet/fib/fib_entry_src.h>
40 #include <vnet/fib/fib_walk.h>
41 #include <vnet/fib/fib_node_list.h>
42 #include <vnet/fib/fib_urpf_list.h>
44 #include <vlib/unix/plugin.h>
49 * Add debugs for passing tests
51 static int fib_test_do_debug;
53 #define FIB_TEST_I(_cond, _comment, _args...) \
55 int _evald = (_cond); \
57 fformat(stderr, "FAIL:%d: " _comment "\n", \
61 if (fib_test_do_debug) \
62 fformat(stderr, "PASS:%d: " _comment "\n", \
67 #define FIB_TEST(_cond, _comment, _args...) \
69 if (FIB_TEST_I(_cond, _comment, ##_args)) { \
71 ASSERT(!("FAIL: " _comment)); \
76 * A 'i'm not fussed is this is not efficient' store of test data
78 typedef struct test_main_t_ {
82 u32 hw_if_indicies[4];
86 vnet_hw_interface_t * hw[4];
89 static test_main_t test_main;
91 /* fake ethernet device class, distinct from "fake-ethX" */
92 static u8 * format_test_interface_name (u8 * s, va_list * args)
94 u32 dev_instance = va_arg (*args, u32);
95 return format (s, "test-eth%d", dev_instance);
98 static uword placeholder_interface_tx (vlib_main_t * vm,
99 vlib_node_runtime_t * node,
100 vlib_frame_t * frame)
102 clib_warning ("you shouldn't be here, leaking buffers...");
103 return frame->n_vectors;
106 static clib_error_t *
107 test_interface_admin_up_down (vnet_main_t * vnm,
111 u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
112 VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
113 vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
117 VNET_DEVICE_CLASS (test_interface_device_class,static) = {
118 .name = "Test interface",
119 .format_device_name = format_test_interface_name,
120 .tx_function = placeholder_interface_tx,
121 .admin_up_down_function = test_interface_admin_up_down,
124 static u8 *hw_address;
127 fib_test_mk_intf (u32 ninterfaces)
129 clib_error_t * error = NULL;
130 test_main_t *tm = &test_main;
135 ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
140 vec_add1(hw_address, byte);
143 for (i = 0; i < ninterfaces; i++)
145 vnet_eth_interface_registration_t eir = {};
146 vnet_main_t *vnm = vnet_get_main();
150 eir.dev_class_index = test_interface_device_class.index;
151 eir.dev_instance = i;
152 eir.address = hw_address;
153 tm->hw_if_indicies[i] = vnet_eth_register_interface (vnm, &eir);
155 error = vnet_hw_interface_set_flags(vnet_get_main(),
156 tm->hw_if_indicies[i],
157 VNET_HW_INTERFACE_FLAG_LINK_UP);
158 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
159 tm->hw_if_indicies[i]);
161 error = vnet_sw_interface_set_flags(vnet_get_main(),
162 tm->hw[i]->sw_if_index,
163 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
164 FIB_TEST((NULL == error), "UP interface %d", i);
167 * re-eval after the inevitable realloc
169 for (i = 0; i < ninterfaces; i++)
171 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
172 tm->hw_if_indicies[i]);
178 #define FIB_TEST_REC_FORW(_rec_prefix, _via_prefix, _bucket) \
180 const dpo_id_t *_rec_dpo = fib_entry_contribute_ip_forwarding( \
181 fib_table_lookup_exact_match(fib_index, (_rec_prefix))); \
182 const dpo_id_t *_via_dpo = fib_entry_contribute_ip_forwarding( \
183 fib_table_lookup(fib_index, (_via_prefix))); \
184 FIB_TEST(!dpo_cmp(_via_dpo, \
185 load_balance_get_bucket(_rec_dpo->dpoi_index, \
187 "%U is recursive via %U", \
188 format_fib_prefix, (_rec_prefix), \
189 format_fib_prefix, _via_prefix); \
192 #define FIB_TEST_LB_BUCKET_VIA_ADJ(_prefix, _bucket, _ai) \
194 const dpo_id_t *_dpo = fib_entry_contribute_ip_forwarding( \
195 fib_table_lookup_exact_match(fib_index, (_prefix))); \
196 const dpo_id_t *_dpo1 = \
197 load_balance_get_bucket(_dpo->dpoi_index, _bucket); \
198 FIB_TEST(DPO_ADJACENCY == _dpo1->dpoi_type, "type is %U", \
199 format_dpo_type, _dpo1->dpoi_type); \
200 FIB_TEST((_ai == _dpo1->dpoi_index), \
201 "%U bucket %d resolves via %U", \
202 format_fib_prefix, (_prefix), \
204 format_dpo_id, _dpo1, 0); \
207 #define FIB_TEST_RPF(_cond, _comment, _args...) \
209 if (FIB_TEST_I(_cond, _comment, ##_args)) { \
216 fib_test_urpf_is_equal (fib_node_index_t fei,
217 fib_forward_chain_type_t fct,
220 dpo_id_t dpo = DPO_INVALID;
221 fib_urpf_list_t *urpf;
229 fib_entry_contribute_forwarding(fei, fct, &dpo);
230 ui = load_balance_get_urpf(dpo.dpoi_index);
232 urpf = fib_urpf_list_get(ui);
234 FIB_TEST_RPF(num == vec_len(urpf->furpf_itfs),
235 "RPF:%U len %d == %d",
236 format_fib_urpf_list, ui,
237 num, vec_len(urpf->furpf_itfs));
238 FIB_TEST_RPF(num == fib_urpf_check_size(ui),
239 "RPF:%U check-size %d == %d",
240 format_fib_urpf_list, ui,
241 num, vec_len(urpf->furpf_itfs));
243 for (ii = 0; ii < num; ii++)
245 adj_index_t ai = va_arg(ap, adj_index_t);
247 FIB_TEST_RPF(ai == urpf->furpf_itfs[ii],
248 "RPF:%d item:%d - %d == %d",
249 ui, ii, ai, urpf->furpf_itfs[ii]);
250 FIB_TEST_RPF(fib_urpf_check(ui, ai),
264 fib_test_build_rewrite (u8 *eth_addr)
268 vec_validate(rewrite, 13);
270 memcpy(rewrite, eth_addr, 6);
271 memcpy(rewrite+6, eth_addr, 6);
276 #define FIB_TEST_LB(_cond, _comment, _args...) \
278 if (FIB_TEST_I(_cond, _comment, ##_args)) { \
284 fib_test_validate_rep_v (const replicate_t *rep,
288 const fib_test_rep_bucket_t *exp;
293 FIB_TEST_LB((n_buckets == rep->rep_n_buckets),
294 "n_buckets = %d", rep->rep_n_buckets);
296 for (bucket = 0; bucket < n_buckets; bucket++)
298 exp = va_arg(*ap, fib_test_rep_bucket_t*);
300 dpo = replicate_get_bucket_i(rep, bucket);
304 case FT_REP_LABEL_O_ADJ:
306 const mpls_label_dpo_t *mld;
309 FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE)
311 "bucket %d stacks on %U",
313 format_dpo_type, dpo->dpoi_type);
315 mld = mpls_label_dpo_get(dpo->dpoi_index);
316 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
318 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
319 exp->label_o_adj.label),
320 "bucket %d stacks on label %d",
322 exp->label_o_adj.label);
324 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
325 exp->label_o_adj.eos),
326 "bucket %d stacks on label %d %U",
328 exp->label_o_adj.label,
329 format_mpls_eos_bit, exp->label_o_adj.eos);
331 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
332 "bucket %d label stacks on %U",
334 format_dpo_type, mld->mld_dpo.dpoi_type);
336 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
337 "bucket %d label stacks on adj %d",
339 exp->label_o_adj.adj);
343 FIB_TEST_LB((DPO_INTERFACE_RX == dpo->dpoi_type),
344 "bucket %d stacks on %U",
346 format_dpo_type, dpo->dpoi_type);
348 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
349 "bucket %d stacks on adj %d",
353 case FT_REP_DISP_MFIB_LOOKUP:
363 fib_test_validate_lb_v (const load_balance_t *lb,
371 FIB_TEST_LB((n_buckets == lb->lb_n_buckets), "n_buckets = %d", lb->lb_n_buckets);
373 for (bucket = 0; bucket < n_buckets; bucket++)
375 const fib_test_lb_bucket_t *exp;
377 exp = va_arg(*ap, fib_test_lb_bucket_t*);
378 dpo = load_balance_get_bucket_i(lb, bucket);
382 case FT_LB_LABEL_STACK_O_ADJ:
384 const mpls_label_dpo_t *mld;
385 mpls_label_dpo_flags_t mf;
389 mf = ((exp->label_stack_o_adj.mode ==
390 FIB_MPLS_LSP_MODE_UNIFORM) ?
391 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
392 MPLS_LABEL_DPO_FLAG_NONE);
393 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
394 "bucket %d stacks on %U",
396 format_dpo_type, dpo->dpoi_type);
398 mld = mpls_label_dpo_get(dpo->dpoi_index);
400 FIB_TEST_LB(exp->label_stack_o_adj.label_stack_size == mld->mld_n_labels,
404 for (ii = 0; ii < mld->mld_n_labels; ii++)
406 hdr = clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
407 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
408 exp->label_stack_o_adj.label_stack[ii]),
409 "bucket %d stacks on label %d",
411 exp->label_stack_o_adj.label_stack[ii]);
413 if (ii == mld->mld_n_labels-1)
415 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
416 exp->label_o_adj.eos),
417 "bucket %d stacks on label %d %U!=%U",
419 exp->label_stack_o_adj.label_stack[ii],
420 format_mpls_eos_bit, exp->label_o_adj.eos,
421 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
425 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) == MPLS_NON_EOS),
426 "bucket %d stacks on label %d %U",
428 exp->label_stack_o_adj.label_stack[ii],
429 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
433 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
434 "bucket %d label stacks on %U",
436 format_dpo_type, mld->mld_dpo.dpoi_type);
438 FIB_TEST_LB((exp->label_stack_o_adj.adj == mld->mld_dpo.dpoi_index),
439 "bucket %d label stacks on adj %d",
441 exp->label_stack_o_adj.adj);
444 case FT_LB_LABEL_CHAIN_O_ADJ:
446 const mpls_label_dpo_t *mld = NULL;
447 mpls_label_dpo_flags_t mf;
451 mf = ((exp->label_chain_o_adj.mode ==
452 FIB_MPLS_LSP_MODE_UNIFORM) ?
453 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
454 MPLS_LABEL_DPO_FLAG_NONE);
456 for (ii = 0; ii < exp->label_chain_o_adj.label_chain_size; ii++)
458 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
459 "bucket %d stacks on %U",
461 format_dpo_type, dpo->dpoi_type);
462 mld = mpls_label_dpo_get(dpo->dpoi_index);
464 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
465 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
466 exp->label_chain_o_adj.label_chain[ii]),
467 "bucket %d stacks on label %d",
469 exp->label_chain_o_adj.label_chain[ii]);
473 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
474 "bucket %d label stacks on %U",
476 format_dpo_type, mld->mld_dpo.dpoi_type);
478 FIB_TEST_LB((exp->label_chain_o_adj.adj == mld->mld_dpo.dpoi_index),
479 "bucket %d label stacks on adj %d",
481 exp->label_chain_o_adj.adj);
484 case FT_LB_LABEL_O_ADJ:
486 const mpls_label_dpo_t *mld;
488 FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE)
490 "bucket %d stacks on %U",
492 format_dpo_type, dpo->dpoi_type);
494 mld = mpls_label_dpo_get(dpo->dpoi_index);
495 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
497 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
498 exp->label_o_adj.label),
499 "bucket %d stacks on label %d not %d",
501 vnet_mpls_uc_get_label(hdr),
502 exp->label_o_adj.label);
504 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
505 exp->label_o_adj.eos),
506 "bucket %d stacks on label %d %U",
508 exp->label_o_adj.label,
509 format_mpls_eos_bit, exp->label_o_adj.eos);
511 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
512 "bucket %d label stacks on %U",
514 format_dpo_type, mld->mld_dpo.dpoi_type);
516 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
517 "bucket %d label stacks on adj %d",
519 exp->label_o_adj.adj);
522 case FT_LB_LABEL_O_LB:
524 const mpls_label_dpo_t *mld;
525 mpls_label_dpo_flags_t mf;
528 mf = ((exp->label_o_lb.mode ==
529 FIB_MPLS_LSP_MODE_UNIFORM) ?
530 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
531 MPLS_LABEL_DPO_FLAG_NONE);
532 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
533 "bucket %d stacks on %U",
535 format_dpo_type, dpo->dpoi_type);
537 mld = mpls_label_dpo_get(dpo->dpoi_index);
538 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
540 FIB_TEST_LB(1 == mld->mld_n_labels, "label stack size",
542 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
543 exp->label_o_lb.label),
544 "bucket %d stacks on label %d",
546 exp->label_o_lb.label);
548 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
549 exp->label_o_lb.eos),
550 "bucket %d stacks on label %d %U",
552 exp->label_o_lb.label,
553 format_mpls_eos_bit, exp->label_o_lb.eos);
555 FIB_TEST_LB((DPO_LOAD_BALANCE == mld->mld_dpo.dpoi_type),
556 "bucket %d label stacks on %U",
558 format_dpo_type, mld->mld_dpo.dpoi_type);
560 FIB_TEST_LB((exp->label_o_lb.lb == mld->mld_dpo.dpoi_index),
561 "bucket %d label stacks on LB %d",
567 res = FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
568 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
569 "bucket %d stacks on %U",
571 format_dpo_type, dpo->dpoi_type);
572 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
573 "bucket %d stacks on adj %d",
577 case FT_LB_MPLS_DISP_PIPE_O_ADJ:
579 const mpls_disp_dpo_t *mdd;
581 res = FIB_TEST_I((DPO_MPLS_DISPOSITION_PIPE == dpo->dpoi_type),
582 "bucket %d stacks on %U",
584 format_dpo_type, dpo->dpoi_type);
586 mdd = mpls_disp_dpo_get(dpo->dpoi_index);
590 res = FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
591 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
592 "bucket %d stacks on %U",
594 format_dpo_type, dpo->dpoi_type);
595 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
596 "bucket %d stacks on adj %d",
602 res = FIB_TEST_I((DPO_INTERFACE_RX == dpo->dpoi_type),
603 "bucket %d stacks on %U",
605 format_dpo_type, dpo->dpoi_type);
606 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
607 "bucket %d stacks on adj %d",
612 res = FIB_TEST_I((DPO_DVR == dpo->dpoi_type),
613 "bucket %d stacks on %U",
615 format_dpo_type, dpo->dpoi_type);
616 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
617 "bucket %d stacks on adj %d",
622 res = FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
623 "bucket %d stacks on %U",
625 format_dpo_type, dpo->dpoi_type);
626 FIB_TEST_LB((exp->lb.lb == dpo->dpoi_index),
627 "bucket %d stacks on lb %d not %d",
632 case FT_LB_BIER_TABLE:
633 FIB_TEST_LB((DPO_BIER_TABLE == dpo->dpoi_type),
634 "bucket %d stacks on %U",
636 format_dpo_type, dpo->dpoi_type);
637 FIB_TEST_LB((exp->bier.table == dpo->dpoi_index),
638 "bucket %d stacks on lb %d",
642 case FT_LB_BIER_FMASK:
643 FIB_TEST_LB((DPO_BIER_FMASK == dpo->dpoi_type),
644 "bucket %d stacks on %U",
646 format_dpo_type, dpo->dpoi_type);
647 FIB_TEST_LB((exp->bier.fmask == dpo->dpoi_index),
648 "bucket %d stacks on lb %d",
653 FIB_TEST_LB((DPO_DROP == dpo->dpoi_type),
654 "bucket %d stacks on %U",
656 format_dpo_type, dpo->dpoi_type);
659 FIB_TEST_LB((DPO_PUNT == dpo->dpoi_type),
660 "bucket %d stacks on %U",
662 format_dpo_type, dpo->dpoi_type);
670 fib_test_validate_lb (const dpo_id_t *dpo,
674 const load_balance_t *lb;
679 va_start(ap, n_buckets);
681 if (!FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
683 format_dpo_type, dpo->dpoi_type))
685 lb = load_balance_get(dpo->dpoi_index);
687 res = fib_test_validate_lb_v(lb, n_buckets, &ap);
700 fib_test_validate_entry (fib_node_index_t fei,
701 fib_forward_chain_type_t fct,
705 dpo_id_t dpo = DPO_INVALID;
706 const fib_prefix_t *pfx;
714 pfx = fib_entry_get_prefix(fei);
715 fib_index = fib_entry_get_fib_index(fei);
716 fib_entry_contribute_forwarding(fei, fct, &dpo);
718 if (DPO_REPLICATE == dpo.dpoi_type)
720 const replicate_t *rep;
722 va_start(ap, n_buckets);
723 rep = replicate_get(dpo.dpoi_index);
724 res = fib_test_validate_rep_v(rep, n_buckets, &ap);
729 const load_balance_t *lb;
731 FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type),
732 "%U Entry links to %U",
733 format_fib_prefix, pfx,
734 format_dpo_type, dpo.dpoi_type);
736 va_start(ap, n_buckets);
737 lb = load_balance_get(dpo.dpoi_index);
738 res = fib_test_validate_lb_v(lb, n_buckets, &ap);
742 * ensure that the LB contributed by the entry is the
743 * same as the LB in the forwarding tables
745 if (fct == fib_entry_get_default_chain_type(fib_entry_get(fei)))
747 switch (pfx->fp_proto)
749 case FIB_PROTOCOL_IP4:
750 fw_lbi = ip4_fib_forwarding_lookup(fib_index, &pfx->fp_addr.ip4);
752 case FIB_PROTOCOL_IP6:
753 fw_lbi = ip6_fib_table_fwding_lookup(fib_index, &pfx->fp_addr.ip6);
755 case FIB_PROTOCOL_MPLS:
757 mpls_unicast_header_t hdr = {
758 .label_exp_s_ttl = 0,
761 vnet_mpls_uc_set_label(&hdr.label_exp_s_ttl, pfx->fp_label);
762 vnet_mpls_uc_set_s(&hdr.label_exp_s_ttl, pfx->fp_eos);
763 hdr.label_exp_s_ttl = clib_host_to_net_u32(hdr.label_exp_s_ttl);
765 fw_lbi = mpls_fib_table_forwarding_lookup(fib_index, &hdr);
771 FIB_TEST_LB((fw_lbi == dpo.dpoi_index),
772 "Contributed LB = FW LB:\n fwd:%U\n cont:%U",
773 format_load_balance, fw_lbi, 0,
774 format_load_balance, dpo.dpoi_index, 0);
784 fib_test_multipath_v4 (const test_main_t *tm, const u32 fib_index,
785 const fib_prefix_t *pfx, const int n_paths,
786 const int expected_n_buckets)
788 const int path_list_pool_size = fib_path_list_pool_size();
789 const int path_list_db_size = fib_path_list_db_size();
790 const int entry_pool_size = fib_entry_pool_size();
791 fib_route_path_t *r_paths = NULL;
792 const load_balance_t *lb;
798 for (i = 0; i < n_paths; i++)
800 fib_route_path_t r_path = {
801 .frp_proto = DPO_PROTO_IP4,
803 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + i),
805 .frp_sw_if_index = tm->hw[0]->sw_if_index,
808 .frp_flags = FIB_ROUTE_PATH_ATTACHED,
810 vec_add1(r_paths, r_path);
813 fib_table_entry_update(fib_index,
819 fei = fib_table_lookup_exact_match(fib_index, pfx);
820 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "prefix present");
821 dpo = fib_entry_contribute_ip_forwarding(fei);
823 lb = load_balance_get(dpo->dpoi_index);
824 FIB_TEST((lb->lb_n_buckets == expected_n_buckets),
825 "prefix lb over %d paths", lb->lb_n_buckets);
827 fib_table_entry_delete(fib_index,
830 FIB_TEST(FIB_NODE_INDEX_INVALID ==
831 fib_table_lookup_exact_match(fib_index, pfx), "prefix removed");
835 * add-remove test. no change.
837 FIB_TEST((path_list_db_size == fib_path_list_db_size()),
838 "path list DB population:%d", fib_path_list_db_size());
839 FIB_TEST((path_list_pool_size == fib_path_list_pool_size()),
840 "path list pool size is %d", fib_path_list_pool_size());
841 FIB_TEST((entry_pool_size == fib_entry_pool_size()),
842 "entry pool size is %d", fib_entry_pool_size());
850 * In the default table check for the presence and correct forwarding
851 * of the special entries
853 fib_node_index_t dfrt, fei, ai, ai2, locked_ai, ai_01, ai_02, ai_03;
854 const dpo_id_t *dpo, *dpo1, *dpo2, *dpo_drop;
855 const ip_adjacency_t *adj;
856 const load_balance_t *lb;
864 ip46_address_t nh_10_10_10_1 = {
865 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
868 ip46_address_t nh_10_10_10_2 = {
869 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
872 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
873 pool_elts(load_balance_map_pool));
877 /* record the nubmer of load-balances in use before we start */
878 lb_count = pool_elts(load_balance_pool);
880 /* Find or create FIB table 11 */
881 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11,
884 for (ii = 0; ii < 4; ii++)
885 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[ii]->sw_if_index, fib_index);
887 fib_prefix_t pfx_0_0_0_0_s_0 = {
889 .fp_proto = FIB_PROTOCOL_IP4,
899 .fp_proto = FIB_PROTOCOL_IP4,
907 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
909 dfrt = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
910 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
911 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
912 "Default route is DROP");
915 fei = fib_table_lookup(fib_index, &pfx);
916 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all zeros route present");
917 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
918 "all 0s route is DROP");
920 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xffffffff);
922 fei = fib_table_lookup(fib_index, &pfx);
923 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all ones route present");
924 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
925 "all 1s route is DROP");
927 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xe0000000);
929 fei = fib_table_lookup(fib_index, &pfx);
930 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all-mcast route present");
931 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
932 "all-mcast route is DROP");
934 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xf0000000);
936 fei = fib_table_lookup(fib_index, &pfx);
937 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "class-e route present");
938 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
939 "class-e route is DROP");
942 * at this stage there are 5 entries in the test FIB (plus 5 in the default),
943 * all of which are special sourced and so none of which share path-lists.
944 * There are also 2 entries, and 2 non-shared path-lists, in the v6 default
945 * table, and 4 path-lists in the v6 MFIB table and 2 in v4.
949 u32 PNBR = 5+5+2+4+2;
952 * if the IGMP plugin is loaded this adds two more entries to the v4 MFIB
954 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
955 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
956 fib_path_list_pool_size());
957 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
958 fib_entry_pool_size());
961 * add interface routes.
962 * validate presence of /24 attached and /32 recieve.
963 * test for the presence of the receive address in the glean and local adj
965 fib_prefix_t local_pfx = {
967 .fp_proto = FIB_PROTOCOL_IP4,
970 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
975 fib_table_entry_update_one_path(fib_index, &local_pfx,
976 FIB_SOURCE_INTERFACE,
977 (FIB_ENTRY_FLAG_CONNECTED |
978 FIB_ENTRY_FLAG_ATTACHED),
981 tm->hw[0]->sw_if_index,
982 ~0, // invalid fib index
985 FIB_ROUTE_PATH_FLAG_NONE);
986 fei = fib_table_lookup(fib_index, &local_pfx);
987 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
988 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
989 fib_entry_get_flags(fei)),
990 "Flags set on attached interface");
992 ai = fib_entry_get_adj(fei);
993 FIB_TEST((FIB_NODE_INDEX_INVALID != ai),
994 "attached interface route adj present %d", ai);
996 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
997 "attached interface adj is glean");
999 local_pfx.fp_len = 32;
1000 fib_table_entry_update_one_path(fib_index, &local_pfx,
1001 FIB_SOURCE_INTERFACE,
1002 (FIB_ENTRY_FLAG_CONNECTED |
1003 FIB_ENTRY_FLAG_LOCAL),
1006 tm->hw[0]->sw_if_index,
1007 ~0, // invalid fib index
1010 FIB_ROUTE_PATH_FLAG_NONE);
1011 fei = fib_table_lookup(fib_index, &local_pfx);
1012 FIB_TEST(((FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_CONNECTED) ==
1013 fib_entry_get_flags(fei)),
1014 "Flags set on local interface");
1016 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
1018 dpo = fib_entry_contribute_ip_forwarding(fei);
1019 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1020 "RPF list for local length 0");
1021 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
1022 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
1023 "local interface adj is local");
1024 receive_dpo_t *rd = receive_dpo_get(dpo->dpoi_index);
1026 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
1028 "local interface adj is receive ok");
1030 FIB_TEST((2 == fib_table_get_num_entries(fib_index,
1032 FIB_SOURCE_INTERFACE)),
1033 "2 Interface Source'd prefixes");
1034 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
1035 &adj->sub_type.glean.rx_pfx.fp_addr)),
1036 "attached interface adj is receive ok");
1039 * +2 interface routes +2 non-shared path-lists
1041 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
1042 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
1043 fib_path_list_pool_size());
1044 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
1045 fib_entry_pool_size());
1048 * Modify the default route to be via an adj not yet known.
1049 * this sources the defalut route with the API source, which is
1050 * a higher preference to the DEFAULT_ROUTE source
1052 pfx.fp_addr.ip4.as_u32 = 0;
1054 fib_table_entry_path_add(fib_index, &pfx,
1056 FIB_ENTRY_FLAG_NONE,
1059 tm->hw[0]->sw_if_index,
1060 ~0, // invalid fib index
1063 FIB_ROUTE_PATH_FLAG_NONE);
1064 fei = fib_table_lookup(fib_index, &pfx);
1065 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
1066 "Flags set on API route");
1068 FIB_TEST((fei == dfrt), "default route same index");
1069 ai = fib_entry_get_adj(fei);
1070 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
1072 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1073 "adj is incomplete");
1074 FIB_TEST((0 == ip46_address_cmp(&nh_10_10_10_1, &adj->sub_type.nbr.next_hop)),
1075 "adj nbr next-hop ok");
1076 FIB_TEST((1 == fib_table_get_num_entries(fib_index,
1079 "1 API Source'd prefixes");
1082 * find the adj in the shared db
1084 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1087 tm->hw[0]->sw_if_index);
1088 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
1089 adj_unlock(locked_ai);
1092 * +1 shared path-list
1094 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
1095 fib_path_list_db_size());
1096 FIB_TEST((PNBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
1097 fib_path_list_pool_size());
1098 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
1099 fib_entry_pool_size());
1102 * remove the API source from the default route. We expected
1103 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
1105 pfx.fp_addr.ip4.as_u32 = 0;
1107 fib_table_entry_path_remove(fib_index, &pfx,
1111 tm->hw[0]->sw_if_index,
1112 ~0, // non-recursive path, so no FIB index
1114 FIB_ROUTE_PATH_FLAG_NONE);
1116 fei = fib_table_lookup(fib_index, &pfx);
1118 FIB_TEST((fei == dfrt), "default route same index");
1119 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
1120 "Default route is DROP");
1123 * -1 shared-path-list
1125 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
1126 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
1127 fib_path_list_pool_size());
1128 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
1129 fib_entry_pool_size());
1132 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
1134 fib_prefix_t pfx_10_10_10_1_s_32 = {
1136 .fp_proto = FIB_PROTOCOL_IP4,
1139 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
1142 fib_prefix_t pfx_10_10_10_2_s_32 = {
1144 .fp_proto = FIB_PROTOCOL_IP4,
1147 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
1150 fib_prefix_t pfx_11_11_11_11_s_32 = {
1152 .fp_proto = FIB_PROTOCOL_IP4,
1155 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
1159 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
1162 ip46_address_t nh_12_12_12_12 = {
1163 .ip4.as_u32 = clib_host_to_net_u32(0x0c0c0c0c),
1165 adj_index_t ai_12_12_12_12;
1168 * Add a route via an incomplete ADJ. then complete the ADJ
1169 * Expect the route LB is updated to use complete adj type.
1171 fei = fib_table_entry_update_one_path(fib_index,
1172 &pfx_11_11_11_11_s_32,
1174 FIB_ENTRY_FLAG_ATTACHED,
1176 &pfx_10_10_10_1_s_32.fp_addr,
1177 tm->hw[0]->sw_if_index,
1178 ~0, // invalid fib index
1181 FIB_ROUTE_PATH_FLAG_NONE);
1183 dpo = fib_entry_contribute_ip_forwarding(fei);
1184 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1185 FIB_TEST(DPO_ADJACENCY_INCOMPLETE == dpo1->dpoi_type,
1186 "11.11.11.11/32 via incomplete adj");
1188 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1190 &pfx_10_10_10_1_s_32.fp_addr,
1191 tm->hw[0]->sw_if_index);
1192 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
1193 adj = adj_get(ai_01);
1194 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1195 "adj is incomplete");
1196 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1197 &adj->sub_type.nbr.next_hop)),
1198 "adj nbr next-hop ok");
1200 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1201 fib_test_build_rewrite(eth_addr));
1202 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1204 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1205 &adj->sub_type.nbr.next_hop)),
1206 "adj nbr next-hop ok");
1207 ai = fib_entry_get_adj(fei);
1208 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
1210 dpo = fib_entry_contribute_ip_forwarding(fei);
1211 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1212 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type,
1213 "11.11.11.11/32 via complete adj");
1214 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1215 tm->hw[0]->sw_if_index),
1216 "RPF list for adj-fib contains adj");
1218 ai_12_12_12_12 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1221 tm->hw[1]->sw_if_index);
1222 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_12_12_12_12), "adj created");
1223 adj = adj_get(ai_12_12_12_12);
1224 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1225 "adj is incomplete");
1226 FIB_TEST((0 == ip46_address_cmp(&nh_12_12_12_12,
1227 &adj->sub_type.nbr.next_hop)),
1228 "adj nbr next-hop ok");
1229 adj_nbr_update_rewrite(ai_12_12_12_12, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1230 fib_test_build_rewrite(eth_addr));
1231 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1237 fei = fib_table_entry_path_add(fib_index,
1238 &pfx_10_10_10_1_s_32,
1240 FIB_ENTRY_FLAG_ATTACHED,
1242 &pfx_10_10_10_1_s_32.fp_addr,
1243 tm->hw[0]->sw_if_index,
1244 ~0, // invalid fib index
1247 FIB_ROUTE_PATH_FLAG_NONE);
1248 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
1249 "Flags set on adj-fib");
1250 ai = fib_entry_get_adj(fei);
1251 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj, %d", ai);
1253 fib_table_entry_path_remove(fib_index,
1254 &pfx_11_11_11_11_s_32,
1257 &pfx_10_10_10_1_s_32.fp_addr,
1258 tm->hw[0]->sw_if_index,
1259 ~0, // invalid fib index
1261 FIB_ROUTE_PATH_FLAG_NONE);
1265 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1267 &pfx_10_10_10_2_s_32.fp_addr,
1268 tm->hw[0]->sw_if_index);
1269 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
1270 adj = adj_get(ai_02);
1271 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1272 "adj is incomplete");
1273 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1274 &adj->sub_type.nbr.next_hop)),
1275 "adj nbr next-hop ok");
1277 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1278 fib_test_build_rewrite(eth_addr));
1279 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1281 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1282 &adj->sub_type.nbr.next_hop)),
1283 "adj nbr next-hop ok");
1284 FIB_TEST((ai_01 != ai_02), "ADJs are different");
1286 fib_table_entry_path_add(fib_index,
1287 &pfx_10_10_10_2_s_32,
1289 FIB_ENTRY_FLAG_ATTACHED,
1291 &pfx_10_10_10_2_s_32.fp_addr,
1292 tm->hw[0]->sw_if_index,
1293 ~0, // invalid fib index
1296 FIB_ROUTE_PATH_FLAG_NONE);
1298 fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32);
1299 ai = fib_entry_get_adj(fei);
1300 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
1303 * +2 adj-fibs, and their non-shared path-lists
1305 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
1306 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
1307 fib_path_list_pool_size());
1308 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
1309 fib_entry_pool_size());
1312 * Add 2 routes via the first ADJ. ensure path-list sharing
1314 fib_prefix_t pfx_1_1_1_1_s_32 = {
1316 .fp_proto = FIB_PROTOCOL_IP4,
1319 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1323 fib_table_entry_path_add(fib_index,
1326 FIB_ENTRY_FLAG_NONE,
1329 tm->hw[0]->sw_if_index,
1330 ~0, // invalid fib index
1333 FIB_ROUTE_PATH_FLAG_NONE);
1334 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
1335 ai = fib_entry_get_adj(fei);
1336 FIB_TEST((ai_01 == ai), "1.1.1.1 resolves via 10.10.10.1");
1339 * +1 entry and a shared path-list
1341 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
1342 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1343 fib_path_list_pool_size());
1344 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
1345 fib_entry_pool_size());
1348 fib_prefix_t pfx_1_1_2_0_s_24 = {
1350 .fp_proto = FIB_PROTOCOL_IP4,
1352 .ip4.as_u32 = clib_host_to_net_u32(0x01010200),
1356 fib_table_entry_path_add(fib_index,
1359 FIB_ENTRY_FLAG_NONE,
1362 tm->hw[0]->sw_if_index,
1363 ~0, // invalid fib index
1366 FIB_ROUTE_PATH_FLAG_NONE);
1367 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1368 ai = fib_entry_get_adj(fei);
1369 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1374 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
1375 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1376 fib_path_list_pool_size());
1377 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1378 fib_entry_pool_size());
1381 * modify 1.1.2.0/24 to use multipath.
1383 fib_table_entry_path_add(fib_index,
1386 FIB_ENTRY_FLAG_NONE,
1389 tm->hw[0]->sw_if_index,
1390 ~0, // invalid fib index
1393 FIB_ROUTE_PATH_FLAG_NONE);
1394 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1395 dpo = fib_entry_contribute_ip_forwarding(fei);
1396 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1397 1, tm->hw[0]->sw_if_index),
1398 "RPF list for 1.1.2.0/24 contains both adjs");
1400 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1401 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1402 FIB_TEST((ai_01 == dpo1->dpoi_index),
1403 "1.1.2.0/24 bucket 0 resolves via 10.10.10.1 (%d=%d)",
1404 ai_01, dpo1->dpoi_index);
1406 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 1);
1407 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1408 FIB_TEST((ai_02 == dpo1->dpoi_index),
1409 "1.1.2.0/24 bucket 1 resolves via 10.10.10.2");
1412 * +1 shared-pathlist
1414 FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty");
1415 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1416 fib_path_list_pool_size());
1417 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1418 fib_entry_pool_size());
1423 fib_table_entry_path_remove(fib_index,
1428 tm->hw[0]->sw_if_index,
1431 FIB_ROUTE_PATH_FLAG_NONE);
1432 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1433 dpo = fib_entry_contribute_ip_forwarding(fei);
1434 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1435 1, tm->hw[0]->sw_if_index),
1436 "RPF list for 1.1.2.0/24 contains one adj");
1438 ai = fib_entry_get_adj(fei);
1439 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1442 * +1 shared-pathlist
1444 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d",
1445 fib_path_list_db_size());
1446 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1447 fib_path_list_pool_size());
1448 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1449 fib_entry_pool_size());
1452 * Add 2 recursive routes:
1453 * 100.100.100.100/32 via 1.1.1.1/32 => the via entry is installed.
1454 * 100.100.100.101/32 via 1.1.1.1/32 => the via entry is installed.
1456 fib_prefix_t bgp_100_pfx = {
1458 .fp_proto = FIB_PROTOCOL_IP4,
1460 /* 100.100.100.100/32 */
1461 .ip4.as_u32 = clib_host_to_net_u32(0x64646464),
1465 ip46_address_t nh_1_1_1_1 = {
1466 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1469 fei = fib_table_entry_path_add(fib_index,
1472 FIB_ENTRY_FLAG_NONE,
1475 ~0, // no index provided.
1476 fib_index, // nexthop in same fib as route
1479 FIB_ROUTE_PATH_FLAG_NONE);
1481 FIB_TEST_REC_FORW(&bgp_100_pfx, &pfx_1_1_1_1_s_32, 0);
1482 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1483 tm->hw[0]->sw_if_index),
1484 "RPF list for adj-fib contains adj");
1487 * +1 entry and +1 shared-path-list
1489 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1490 fib_path_list_db_size());
1491 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1492 fib_path_list_pool_size());
1493 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
1494 fib_entry_pool_size());
1496 fib_prefix_t bgp_101_pfx = {
1498 .fp_proto = FIB_PROTOCOL_IP4,
1500 /* 100.100.100.101/32 */
1501 .ip4.as_u32 = clib_host_to_net_u32(0x64646465),
1505 fib_table_entry_path_add(fib_index,
1508 FIB_ENTRY_FLAG_NONE,
1511 ~0, // no index provided.
1512 fib_index, // nexthop in same fib as route
1515 FIB_ROUTE_PATH_FLAG_NONE);
1517 FIB_TEST_REC_FORW(&bgp_101_pfx, &pfx_1_1_1_1_s_32, 0);
1518 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1519 tm->hw[0]->sw_if_index),
1520 "RPF list for adj-fib contains adj");
1523 * +1 entry, but the recursive path-list is shared.
1525 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1526 fib_path_list_db_size());
1527 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1528 fib_path_list_pool_size());
1529 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
1530 fib_entry_pool_size());
1533 * An special route; one where the user (me) provides the
1534 * adjacency through which the route will resovle by setting the flags
1536 fib_prefix_t ex_pfx = {
1538 .fp_proto = FIB_PROTOCOL_IP4,
1541 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
1545 fib_table_entry_special_add(fib_index,
1548 FIB_ENTRY_FLAG_LOCAL);
1549 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1550 dpo = fib_entry_contribute_ip_forwarding(fei);
1551 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
1552 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
1553 "local interface adj is local");
1555 fib_table_entry_special_remove(fib_index,
1557 FIB_SOURCE_SPECIAL);
1558 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1559 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1560 "Exclusive reoute removed");
1563 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1564 * adjacency through which the route will resovle
1566 dpo_id_t ex_dpo = DPO_INVALID;
1568 lookup_dpo_add_or_lock_w_fib_index(fib_index,
1571 LOOKUP_INPUT_DST_ADDR,
1572 LOOKUP_TABLE_FROM_CONFIG,
1575 fib_table_entry_special_dpo_add(fib_index,
1578 FIB_ENTRY_FLAG_EXCLUSIVE,
1580 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1581 dpo = fib_entry_contribute_ip_forwarding(fei);
1582 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1583 "exclusive remote uses lookup DPO");
1586 * update the exclusive to use a different DPO
1588 ip_null_dpo_add_and_lock(DPO_PROTO_IP4,
1589 IP_NULL_ACTION_SEND_ICMP_UNREACH,
1591 fib_table_entry_special_dpo_update(fib_index,
1594 FIB_ENTRY_FLAG_EXCLUSIVE,
1596 dpo = fib_entry_contribute_ip_forwarding(fei);
1597 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1598 "exclusive remote uses now uses NULL DPO");
1600 fib_table_entry_special_remove(fib_index,
1602 FIB_SOURCE_SPECIAL);
1603 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1604 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1605 "Exclusive reoute removed");
1609 * Add a recursive route:
1610 * 200.200.200.200/32 via 1.1.1.2/32 => the via entry is NOT installed.
1612 fib_prefix_t bgp_200_pfx = {
1614 .fp_proto = FIB_PROTOCOL_IP4,
1616 /* 200.200.200.200/32 */
1617 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c8),
1621 fib_prefix_t pfx_1_1_1_2_s_32 = {
1623 .fp_proto = FIB_PROTOCOL_IP4,
1625 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
1629 fei = fib_table_entry_path_add(fib_index,
1632 FIB_ENTRY_FLAG_NONE,
1634 &pfx_1_1_1_2_s_32.fp_addr,
1635 ~0, // no index provided.
1636 fib_index, // nexthop in same fib as route
1639 FIB_ROUTE_PATH_FLAG_NONE);
1641 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
1642 "Recursive via unresolved is drop");
1645 * the adj should be recursive via drop, since the route resolves via
1646 * the default route, which is itself a DROP
1648 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
1649 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1650 FIB_TEST(load_balance_is_drop(dpo1), "1.1.1.2/32 is drop");
1651 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1652 "RPF list for 1.1.1.2/32 contains 0 adjs");
1655 * +2 entry and +1 shared-path-list
1657 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
1658 fib_path_list_db_size());
1659 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
1660 fib_path_list_pool_size());
1661 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
1662 fib_entry_pool_size());
1665 * Unequal Cost load-balance. 3:1 ratio. fits in a 4 bucket LB
1666 * The paths are sort by NH first. in this case the the path with greater
1667 * weight is first in the set. This ordering is to test the RPF sort|uniq logic
1669 fib_prefix_t pfx_1_2_3_4_s_32 = {
1671 .fp_proto = FIB_PROTOCOL_IP4,
1673 .ip4.as_u32 = clib_host_to_net_u32(0x01020304),
1676 fib_table_entry_path_add(fib_index,
1679 FIB_ENTRY_FLAG_NONE,
1682 tm->hw[0]->sw_if_index,
1686 FIB_ROUTE_PATH_FLAG_NONE);
1687 fei = fib_table_entry_path_add(fib_index,
1690 FIB_ENTRY_FLAG_NONE,
1693 tm->hw[1]->sw_if_index,
1697 FIB_ROUTE_PATH_FLAG_NONE);
1699 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.4/32 presnet");
1700 dpo = fib_entry_contribute_ip_forwarding(fei);
1701 lb = load_balance_get(dpo->dpoi_index);
1702 FIB_TEST((lb->lb_n_buckets == 4),
1703 "1.2.3.4/32 LB has %d bucket",
1706 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 0, ai_12_12_12_12);
1707 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 1, ai_12_12_12_12);
1708 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 2, ai_12_12_12_12);
1709 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 3, ai_01);
1711 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1712 tm->hw[0]->sw_if_index,
1713 tm->hw[1]->sw_if_index),
1714 "RPF list for 1.2.3.4/32 contains both adjs");
1718 * Unequal Cost load-balance. 4:1 ratio.
1719 * fits in a 16 bucket LB with ratio 13:3
1721 fib_prefix_t pfx_1_2_3_5_s_32 = {
1723 .fp_proto = FIB_PROTOCOL_IP4,
1725 .ip4.as_u32 = clib_host_to_net_u32(0x01020305),
1728 fib_table_entry_path_add(fib_index,
1731 FIB_ENTRY_FLAG_NONE,
1734 tm->hw[1]->sw_if_index,
1738 FIB_ROUTE_PATH_FLAG_NONE);
1739 fei = fib_table_entry_path_add(fib_index,
1742 FIB_ENTRY_FLAG_NONE,
1745 tm->hw[0]->sw_if_index,
1749 FIB_ROUTE_PATH_FLAG_NONE);
1751 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.5/32 presnet");
1752 dpo = fib_entry_contribute_ip_forwarding(fei);
1753 lb = load_balance_get(dpo->dpoi_index);
1754 FIB_TEST((lb->lb_n_buckets == 16),
1755 "1.2.3.5/32 LB has %d bucket",
1758 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 0, ai_01);
1759 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 1, ai_01);
1760 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 2, ai_01);
1761 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 3, ai_01);
1762 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 4, ai_01);
1763 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 5, ai_01);
1764 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 6, ai_01);
1765 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 7, ai_01);
1766 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 8, ai_01);
1767 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 9, ai_01);
1768 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 10, ai_01);
1769 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 11, ai_01);
1770 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 12, ai_01);
1771 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 13, ai_12_12_12_12);
1772 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 14, ai_12_12_12_12);
1773 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 15, ai_12_12_12_12);
1775 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1776 tm->hw[0]->sw_if_index,
1777 tm->hw[1]->sw_if_index),
1778 "RPF list for 1.2.3.4/32 contains both adjs");
1781 * Test UCMP with a large weight skew - this produces load-balance objects with large
1782 * numbers of buckets to accommodate the skew. By updating said load-balances we are
1783 * laso testing the LB in placce modify code when number of buckets is large.
1785 fib_prefix_t pfx_6_6_6_6_s_32 = {
1787 .fp_proto = FIB_PROTOCOL_IP4,
1790 .ip4.as_u32 = clib_host_to_net_u32(0x06060606),
1793 fib_test_lb_bucket_t ip_o_10_10_10_1 = {
1799 fib_test_lb_bucket_t ip_o_10_10_10_2 = {
1805 fib_test_lb_bucket_t ip_6_6_6_6_o_12_12_12_12 = {
1808 .adj = ai_12_12_12_12,
1811 fib_table_entry_update_one_path(fib_index,
1814 FIB_ENTRY_FLAG_NONE,
1817 tm->hw[0]->sw_if_index,
1818 ~0, // invalid fib index
1821 FIB_ROUTE_PATH_FLAG_NONE);
1823 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1824 FIB_TEST(!fib_test_validate_entry(fei,
1825 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1828 "6.6.6.6/32 via 10.10.10.1");
1830 fib_table_entry_path_add(fib_index,
1833 FIB_ENTRY_FLAG_NONE,
1836 tm->hw[0]->sw_if_index,
1837 ~0, // invalid fib index
1840 FIB_ROUTE_PATH_FLAG_NONE);
1842 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1843 FIB_TEST(!fib_test_validate_entry(fei,
1844 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1910 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1912 fib_table_entry_path_add(fib_index,
1915 FIB_ENTRY_FLAG_NONE,
1918 tm->hw[1]->sw_if_index,
1919 ~0, // invalid fib index
1922 FIB_ROUTE_PATH_FLAG_NONE);
1924 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1925 FIB_TEST(!fib_test_validate_entry(fei,
1926 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1993 &ip_6_6_6_6_o_12_12_12_12,
1994 &ip_6_6_6_6_o_12_12_12_12,
1995 &ip_6_6_6_6_o_12_12_12_12,
1996 &ip_6_6_6_6_o_12_12_12_12,
1997 &ip_6_6_6_6_o_12_12_12_12,
1998 &ip_6_6_6_6_o_12_12_12_12,
1999 &ip_6_6_6_6_o_12_12_12_12,
2000 &ip_6_6_6_6_o_12_12_12_12,
2001 &ip_6_6_6_6_o_12_12_12_12,
2002 &ip_6_6_6_6_o_12_12_12_12,
2003 &ip_6_6_6_6_o_12_12_12_12,
2004 &ip_6_6_6_6_o_12_12_12_12,
2005 &ip_6_6_6_6_o_12_12_12_12,
2006 &ip_6_6_6_6_o_12_12_12_12,
2007 &ip_6_6_6_6_o_12_12_12_12,
2008 &ip_6_6_6_6_o_12_12_12_12,
2009 &ip_6_6_6_6_o_12_12_12_12,
2010 &ip_6_6_6_6_o_12_12_12_12,
2011 &ip_6_6_6_6_o_12_12_12_12,
2012 &ip_6_6_6_6_o_12_12_12_12,
2013 &ip_6_6_6_6_o_12_12_12_12,
2014 &ip_6_6_6_6_o_12_12_12_12,
2015 &ip_6_6_6_6_o_12_12_12_12,
2016 &ip_6_6_6_6_o_12_12_12_12,
2017 &ip_6_6_6_6_o_12_12_12_12,
2018 &ip_6_6_6_6_o_12_12_12_12,
2019 &ip_6_6_6_6_o_12_12_12_12,
2020 &ip_6_6_6_6_o_12_12_12_12,
2021 &ip_6_6_6_6_o_12_12_12_12,
2022 &ip_6_6_6_6_o_12_12_12_12,
2023 &ip_6_6_6_6_o_12_12_12_12,
2024 &ip_6_6_6_6_o_12_12_12_12,
2025 &ip_6_6_6_6_o_12_12_12_12,
2026 &ip_6_6_6_6_o_12_12_12_12,
2027 &ip_6_6_6_6_o_12_12_12_12,
2028 &ip_6_6_6_6_o_12_12_12_12,
2029 &ip_6_6_6_6_o_12_12_12_12,
2030 &ip_6_6_6_6_o_12_12_12_12,
2031 &ip_6_6_6_6_o_12_12_12_12,
2032 &ip_6_6_6_6_o_12_12_12_12,
2033 &ip_6_6_6_6_o_12_12_12_12,
2034 &ip_6_6_6_6_o_12_12_12_12,
2035 &ip_6_6_6_6_o_12_12_12_12,
2036 &ip_6_6_6_6_o_12_12_12_12,
2037 &ip_6_6_6_6_o_12_12_12_12,
2038 &ip_6_6_6_6_o_12_12_12_12,
2039 &ip_6_6_6_6_o_12_12_12_12,
2040 &ip_6_6_6_6_o_12_12_12_12,
2041 &ip_6_6_6_6_o_12_12_12_12,
2042 &ip_6_6_6_6_o_12_12_12_12,
2043 &ip_6_6_6_6_o_12_12_12_12,
2044 &ip_6_6_6_6_o_12_12_12_12,
2045 &ip_6_6_6_6_o_12_12_12_12,
2046 &ip_6_6_6_6_o_12_12_12_12,
2047 &ip_6_6_6_6_o_12_12_12_12,
2048 &ip_6_6_6_6_o_12_12_12_12,
2049 &ip_6_6_6_6_o_12_12_12_12,
2050 &ip_6_6_6_6_o_12_12_12_12,
2051 &ip_6_6_6_6_o_12_12_12_12,
2052 &ip_6_6_6_6_o_12_12_12_12,
2053 &ip_6_6_6_6_o_12_12_12_12,
2054 &ip_6_6_6_6_o_12_12_12_12,
2055 &ip_6_6_6_6_o_12_12_12_12),
2056 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
2058 fib_table_entry_path_remove(fib_index,
2063 tm->hw[1]->sw_if_index,
2064 ~0, // invalid fib index
2066 FIB_ROUTE_PATH_FLAG_NONE);
2068 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
2069 FIB_TEST(!fib_test_validate_entry(fei,
2070 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2136 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
2138 fib_table_entry_path_remove(fib_index,
2143 tm->hw[0]->sw_if_index,
2144 ~0, // invalid fib index
2146 FIB_ROUTE_PATH_FLAG_NONE);
2148 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
2149 FIB_TEST(!fib_test_validate_entry(fei,
2150 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2153 "6.6.6.6/32 via 10.10.10.1");
2155 fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API);
2158 * A recursive via the two unequal cost entries
2160 fib_prefix_t bgp_44_s_32 = {
2162 .fp_proto = FIB_PROTOCOL_IP4,
2164 /* 200.200.200.201/32 */
2165 .ip4.as_u32 = clib_host_to_net_u32(0x44444444),
2168 fei = fib_table_entry_path_add(fib_index,
2171 FIB_ENTRY_FLAG_NONE,
2173 &pfx_1_2_3_4_s_32.fp_addr,
2178 FIB_ROUTE_PATH_FLAG_NONE);
2179 fei = fib_table_entry_path_add(fib_index,
2182 FIB_ENTRY_FLAG_NONE,
2184 &pfx_1_2_3_5_s_32.fp_addr,
2189 FIB_ROUTE_PATH_FLAG_NONE);
2191 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_4_s_32, 0);
2192 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_5_s_32, 1);
2193 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
2194 tm->hw[0]->sw_if_index,
2195 tm->hw[1]->sw_if_index),
2196 "RPF list for 1.2.3.4/32 contains both adjs");
2199 * test the uRPF check functions
2201 dpo_id_t dpo_44 = DPO_INVALID;
2204 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
2205 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
2207 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
2208 "uRPF check for 68.68.68.68/32 on %d OK",
2209 tm->hw[0]->sw_if_index);
2210 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
2211 "uRPF check for 68.68.68.68/32 on %d OK",
2212 tm->hw[1]->sw_if_index);
2213 FIB_TEST(!fib_urpf_check(urpfi, 99),
2214 "uRPF check for 68.68.68.68/32 on 99 not-OK",
2218 fib_table_entry_delete(fib_index,
2221 fib_table_entry_delete(fib_index,
2224 fib_table_entry_delete(fib_index,
2229 * Add a recursive route:
2230 * 200.200.200.201/32 via 1.1.1.200/32 => the via entry is NOT installed.
2232 fib_prefix_t bgp_201_pfx = {
2234 .fp_proto = FIB_PROTOCOL_IP4,
2236 /* 200.200.200.201/32 */
2237 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c9),
2241 fib_prefix_t pfx_1_1_1_200_s_32 = {
2243 .fp_proto = FIB_PROTOCOL_IP4,
2245 .ip4.as_u32 = clib_host_to_net_u32(0x010101c8),
2249 fei = fib_table_entry_path_add(fib_index,
2252 FIB_ENTRY_FLAG_NONE,
2254 &pfx_1_1_1_200_s_32.fp_addr,
2255 ~0, // no index provided.
2256 fib_index, // nexthop in same fib as route
2259 FIB_ROUTE_PATH_FLAG_NONE);
2261 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2262 "Recursive via unresolved is drop");
2264 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2265 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
2266 "Flags set on RR via non-attached");
2267 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
2268 "RPF list for BGP route empty");
2271 * +2 entry (BGP & RR) and +1 shared-path-list
2273 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2274 fib_path_list_db_size());
2275 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2276 fib_path_list_pool_size());
2277 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2278 fib_entry_pool_size());
2281 * insert a route that covers the missing 1.1.1.2/32. we epxect
2282 * 200.200.200.200/32 and 200.200.200.201/32 to resolve through it.
2284 fib_prefix_t pfx_1_1_1_0_s_24 = {
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_24);
2305 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2306 ai = fib_entry_get_adj(fei);
2307 FIB_TEST((ai_01 == ai), "1.1.1.0/24 resolves via 10.10.10.1");
2308 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2309 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2310 ai = fib_entry_get_adj(fei);
2311 FIB_TEST((ai_01 == ai), "1.1.1.2/32 resolves via 10.10.10.1");
2312 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2313 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2314 ai = fib_entry_get_adj(fei);
2315 FIB_TEST((ai_01 == ai), "1.1.1.200/24 resolves via 10.10.10.1");
2318 * +1 entry. 1.1.1.1/32 already uses 10.10.10.1 so no new pah-list
2320 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2321 fib_path_list_db_size());
2322 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2323 fib_path_list_pool_size());
2324 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
2325 fib_entry_pool_size());
2328 * the recursive adj for 200.200.200.200 should be updated.
2330 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2331 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2332 fei = fib_table_lookup(fib_index, &bgp_200_pfx);
2333 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
2334 tm->hw[0]->sw_if_index),
2335 "RPF list for BGP route has itf index 0");
2338 * insert a more specific route than 1.1.1.0/24 that also covers the
2339 * missing 1.1.1.2/32, but not 1.1.1.200/32. we expect
2340 * 200.200.200.200 to resolve through it.
2342 fib_prefix_t pfx_1_1_1_0_s_28 = {
2344 .fp_proto = FIB_PROTOCOL_IP4,
2347 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2351 fib_table_entry_path_add(fib_index,
2354 FIB_ENTRY_FLAG_NONE,
2357 tm->hw[0]->sw_if_index,
2358 ~0, // invalid fib index
2361 FIB_ROUTE_PATH_FLAG_NONE);
2362 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28);
2363 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2364 ai = fib_entry_get_adj(fei);
2365 FIB_TEST((ai_02 == ai), "1.1.1.0/24 resolves via 10.10.10.2");
2368 * +1 entry. +1 shared path-list
2370 FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d",
2371 fib_path_list_db_size());
2372 FIB_TEST((PNBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
2373 fib_path_list_pool_size());
2374 FIB_TEST((ENBR+14 == fib_entry_pool_size()), "entry pool size is %d",
2375 fib_entry_pool_size());
2378 * the recursive adj for 200.200.200.200 should be updated.
2379 * 200.200.200.201 remains unchanged.
2381 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2382 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2385 * remove this /28. 200.200.200.200/32 should revert back to via 1.1.1.0/24
2387 fib_table_entry_path_remove(fib_index,
2392 tm->hw[0]->sw_if_index,
2395 FIB_ROUTE_PATH_FLAG_NONE);
2396 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28) ==
2397 FIB_NODE_INDEX_INVALID),
2398 "1.1.1.0/28 removed");
2399 FIB_TEST((fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28) ==
2400 fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24)),
2401 "1.1.1.0/28 lookup via /24");
2402 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2403 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2406 * -1 entry. -1 shared path-list
2408 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2409 fib_path_list_db_size());
2410 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2411 fib_path_list_pool_size());
2412 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
2413 fib_entry_pool_size());
2416 * remove 1.1.1.0/24. 200.200.200.200/32 should revert back to via 0.0.0.0/0
2418 fib_table_entry_path_remove(fib_index,
2423 tm->hw[0]->sw_if_index,
2426 FIB_ROUTE_PATH_FLAG_NONE);
2427 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_24) ==
2428 FIB_NODE_INDEX_INVALID),
2429 "1.1.1.0/24 removed");
2431 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2432 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2433 "1.1.1.2/32 route is DROP");
2434 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2435 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2436 "1.1.1.200/32 route is DROP");
2438 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2439 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2441 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2442 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2448 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2449 fib_path_list_db_size());
2450 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2451 fib_path_list_pool_size());
2452 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2453 fib_entry_pool_size());
2456 * insert the missing 1.1.1.2/32
2458 fei = fib_table_entry_path_add(fib_index,
2461 FIB_ENTRY_FLAG_NONE,
2464 tm->hw[0]->sw_if_index,
2465 ~0, // invalid fib index
2468 FIB_ROUTE_PATH_FLAG_NONE);
2469 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2470 ai = fib_entry_get_adj(fei);
2471 FIB_TEST((ai = ai_01), "1.1.1.2/32 resolves via 10.10.10.1");
2473 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2474 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2476 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2479 * no change. 1.1.1.2/32 was already there RR sourced.
2481 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2482 fib_path_list_db_size());
2483 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2484 fib_path_list_pool_size());
2485 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2486 fib_entry_pool_size());
2489 * give 201 a resolved path.
2490 * it now has the unresolved 1.1.1.200 and the resolved 1.1.1.2,
2491 * only the latter contributes forwarding.
2493 fei = fib_table_entry_path_add(fib_index,
2496 FIB_ENTRY_FLAG_NONE,
2498 &pfx_1_1_1_2_s_32.fp_addr,
2503 FIB_ROUTE_PATH_FLAG_NONE);
2504 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_2_s_32, 0);
2505 fib_table_entry_path_remove(fib_index,
2509 &pfx_1_1_1_2_s_32.fp_addr,
2513 FIB_ROUTE_PATH_FLAG_NONE);
2516 * remove 200.200.200.201/32 which does not have a valid via FIB
2518 fib_table_entry_path_remove(fib_index,
2522 &pfx_1_1_1_200_s_32.fp_addr,
2523 ~0, // no index provided.
2526 FIB_ROUTE_PATH_FLAG_NONE);
2529 * -2 entries (BGP and RR). -1 shared path-list;
2531 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2532 FIB_NODE_INDEX_INVALID),
2533 "200.200.200.201/32 removed");
2534 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32) ==
2535 FIB_NODE_INDEX_INVALID),
2536 "1.1.1.200/32 removed");
2538 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2539 fib_path_list_db_size());
2540 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
2541 fib_path_list_pool_size());
2542 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2543 fib_entry_pool_size());
2546 * remove 200.200.200.200/32 which does have a valid via FIB
2548 fib_table_entry_path_remove(fib_index,
2552 &pfx_1_1_1_2_s_32.fp_addr,
2553 ~0, // no index provided.
2556 FIB_ROUTE_PATH_FLAG_NONE);
2558 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2559 FIB_NODE_INDEX_INVALID),
2560 "200.200.200.200/32 removed");
2561 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32) !=
2562 FIB_NODE_INDEX_INVALID),
2563 "1.1.1.2/32 still present");
2566 * -1 entry (BGP, the RR source is also API sourced). -1 shared path-list;
2568 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2569 fib_path_list_db_size());
2570 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2571 fib_path_list_pool_size());
2572 FIB_TEST((ENBR+9 == fib_entry_pool_size()), "entry pool size is %d",
2573 fib_entry_pool_size());
2576 * A recursive prefix that has a 2 path load-balance.
2577 * It also shares a next-hop with other BGP prefixes and hence
2578 * test the ref counting of RR sourced prefixes and 2 level LB.
2580 const fib_prefix_t bgp_102 = {
2582 .fp_proto = FIB_PROTOCOL_IP4,
2584 /* 100.100.100.101/32 */
2585 .ip4.as_u32 = clib_host_to_net_u32(0x64646466),
2588 fib_table_entry_path_add(fib_index,
2591 FIB_ENTRY_FLAG_NONE,
2593 &pfx_1_1_1_1_s_32.fp_addr,
2594 ~0, // no index provided.
2595 fib_index, // same as route
2598 FIB_ROUTE_PATH_FLAG_NONE);
2599 fib_table_entry_path_add(fib_index,
2602 FIB_ENTRY_FLAG_NONE,
2604 &pfx_1_1_1_2_s_32.fp_addr,
2605 ~0, // no index provided.
2606 fib_index, // same as route's FIB
2609 FIB_ROUTE_PATH_FLAG_NONE);
2610 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2611 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "100.100.100.102/32 presnet");
2612 dpo = fib_entry_contribute_ip_forwarding(fei);
2614 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2615 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2616 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32);
2617 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2619 lb = load_balance_get(dpo->dpoi_index);
2620 FIB_TEST((lb->lb_n_buckets == 2), "Recursive LB has %d bucket", lb->lb_n_buckets);
2621 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2622 "First via 10.10.10.1");
2623 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 1)),
2624 "Second via 10.10.10.1");
2626 fib_table_entry_path_remove(fib_index,
2630 &pfx_1_1_1_1_s_32.fp_addr,
2631 ~0, // no index provided.
2632 fib_index, // same as route's FIB
2634 FIB_ROUTE_PATH_FLAG_NONE);
2635 fib_table_entry_path_remove(fib_index,
2639 &pfx_1_1_1_2_s_32.fp_addr,
2640 ~0, // no index provided.
2641 fib_index, // same as route's FIB
2643 FIB_ROUTE_PATH_FLAG_NONE);
2644 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2645 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "100.100.100.102/32 removed");
2648 * remove the remaining recursives
2650 fib_table_entry_path_remove(fib_index,
2654 &pfx_1_1_1_1_s_32.fp_addr,
2655 ~0, // no index provided.
2656 fib_index, // same as route's FIB
2658 FIB_ROUTE_PATH_FLAG_NONE);
2659 fib_table_entry_path_remove(fib_index,
2663 &pfx_1_1_1_1_s_32.fp_addr,
2664 ~0, // no index provided.
2665 fib_index, // same as route's FIB
2667 FIB_ROUTE_PATH_FLAG_NONE);
2668 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_100_pfx) ==
2669 FIB_NODE_INDEX_INVALID),
2670 "100.100.100.100/32 removed");
2671 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_101_pfx) ==
2672 FIB_NODE_INDEX_INVALID),
2673 "100.100.100.101/32 removed");
2676 * -2 entry (2*BGP, the RR source is also API sourced). -1 shared path-list;
2678 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2679 fib_path_list_db_size());
2680 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2681 fib_path_list_pool_size());
2682 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2683 fib_entry_pool_size());
2686 * Add a recursive route via a connected cover, using an adj-fib that does exist
2688 fib_table_entry_path_add(fib_index,
2691 FIB_ENTRY_FLAG_NONE,
2694 ~0, // no index provided.
2695 fib_index, // Same as route's FIB
2698 FIB_ROUTE_PATH_FLAG_NONE);
2701 * +1 entry. +1 shared path-list (recursive via 10.10.10.1)
2703 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2704 fib_path_list_db_size());
2705 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2706 fib_path_list_pool_size());
2707 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
2708 fib_entry_pool_size());
2710 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2711 dpo = fib_entry_contribute_ip_forwarding(fei);
2713 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
2714 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2716 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2717 "200.200.200.200/32 is recursive via adj for 10.10.10.1");
2719 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
2720 "Flags set on RR via existing attached");
2723 * Add a recursive route via a connected cover, using and adj-fib that does
2726 ip46_address_t nh_10_10_10_3 = {
2727 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
2729 fib_prefix_t pfx_10_10_10_3 = {
2731 .fp_proto = FIB_PROTOCOL_IP4,
2732 .fp_addr = nh_10_10_10_3,
2735 fib_table_entry_path_add(fib_index,
2738 FIB_ENTRY_FLAG_NONE,
2741 ~0, // no index provided.
2745 FIB_ROUTE_PATH_FLAG_NONE);
2748 * +2 entries (BGP and RR). +1 shared path-list (recursive via 10.10.10.3) and
2749 * one unshared non-recursive via 10.10.10.3
2751 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2752 fib_path_list_db_size());
2753 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2754 fib_path_list_pool_size());
2755 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2756 fib_entry_pool_size());
2758 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
2761 tm->hw[0]->sw_if_index);
2763 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2764 dpo = fib_entry_contribute_ip_forwarding(fei);
2765 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3);
2766 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2768 ai = fib_entry_get_adj(fei);
2769 FIB_TEST((ai == ai_03), "adj for 10.10.10.3/32 is via adj for 10.10.10.3");
2770 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
2771 fib_entry_get_flags(fei)),
2772 "Flags set on RR via non-existing attached");
2774 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2775 "adj for 200.200.200.200/32 is recursive via adj for 10.10.10.3");
2780 * remove the recursives
2782 fib_table_entry_path_remove(fib_index,
2787 ~0, // no index provided.
2788 fib_index, // same as route's FIB
2790 FIB_ROUTE_PATH_FLAG_NONE);
2791 fib_table_entry_path_remove(fib_index,
2796 ~0, // no index provided.
2797 fib_index, // same as route's FIB
2799 FIB_ROUTE_PATH_FLAG_NONE);
2801 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2802 FIB_NODE_INDEX_INVALID),
2803 "200.200.200.201/32 removed");
2804 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2805 FIB_NODE_INDEX_INVALID),
2806 "200.200.200.200/32 removed");
2807 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3) ==
2808 FIB_NODE_INDEX_INVALID),
2809 "10.10.10.3/32 removed");
2812 * -3 entries (2*BGP and RR). -2 shared path-list (recursive via 10.10.10.3 &
2813 * 10.10.10.1) and one unshared non-recursive via 10.10.10.3
2815 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2816 fib_path_list_db_size());
2817 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2818 fib_path_list_pool_size());
2819 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2820 fib_entry_pool_size());
2825 * Add 5.5.5.5/32 -> 5.5.5.6/32 -> 5.5.5.7/32 -> 5.5.5.5/32
2827 fib_prefix_t pfx_5_5_5_5_s_32 = {
2829 .fp_proto = FIB_PROTOCOL_IP4,
2831 .ip4.as_u32 = clib_host_to_net_u32(0x05050505),
2834 fib_prefix_t pfx_5_5_5_6_s_32 = {
2836 .fp_proto = FIB_PROTOCOL_IP4,
2838 .ip4.as_u32 = clib_host_to_net_u32(0x05050506),
2841 fib_prefix_t pfx_5_5_5_7_s_32 = {
2843 .fp_proto = FIB_PROTOCOL_IP4,
2845 .ip4.as_u32 = clib_host_to_net_u32(0x05050507),
2849 fib_table_entry_path_add(fib_index,
2852 FIB_ENTRY_FLAG_NONE,
2854 &pfx_5_5_5_6_s_32.fp_addr,
2855 ~0, // no index provided.
2859 FIB_ROUTE_PATH_FLAG_NONE);
2860 fib_table_entry_path_add(fib_index,
2863 FIB_ENTRY_FLAG_NONE,
2865 &pfx_5_5_5_7_s_32.fp_addr,
2866 ~0, // no index provided.
2870 FIB_ROUTE_PATH_FLAG_NONE);
2871 fib_table_entry_path_add(fib_index,
2874 FIB_ENTRY_FLAG_NONE,
2876 &pfx_5_5_5_5_s_32.fp_addr,
2877 ~0, // no index provided.
2881 FIB_ROUTE_PATH_FLAG_NONE);
2883 * +3 entries, +3 shared path-list
2885 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2886 fib_path_list_db_size());
2887 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2888 fib_path_list_pool_size());
2889 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2890 fib_entry_pool_size());
2893 * All the entries have only looped paths, so they are all drop
2895 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2896 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2897 "LB for 5.5.5.7/32 is via adj for DROP");
2898 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2899 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2900 "LB for 5.5.5.5/32 is via adj for DROP");
2901 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2902 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2903 "LB for 5.5.5.6/32 is via adj for DROP");
2906 * provide 5.5.5.6/32 with alternate path.
2907 * this will allow only 5.5.5.6/32 to forward with this path, the others
2908 * are still drop since the loop is still present.
2910 fib_table_entry_path_add(fib_index,
2913 FIB_ENTRY_FLAG_NONE,
2916 tm->hw[0]->sw_if_index,
2920 FIB_ROUTE_PATH_FLAG_NONE);
2922 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2923 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2925 lb = load_balance_get(dpo1->dpoi_index);
2926 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.6 LB has %d bucket", lb->lb_n_buckets);
2928 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2929 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2930 FIB_TEST((ai_01 == dpo2->dpoi_index),
2931 "5.5.5.6 bucket 0 resolves via 10.10.10.2");
2933 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2934 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2935 "LB for 5.5.5.7/32 is via adj for DROP");
2936 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2937 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2938 "LB for 5.5.5.5/32 is via adj for DROP");
2941 * remove the alternate path for 5.5.5.6/32
2944 fib_table_entry_path_remove(fib_index,
2949 tm->hw[0]->sw_if_index,
2952 FIB_ROUTE_PATH_FLAG_NONE);
2954 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2955 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2956 "LB for 5.5.5.7/32 is via adj for DROP");
2957 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2958 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2959 "LB for 5.5.5.5/32 is via adj for DROP");
2960 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2961 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2962 "LB for 5.5.5.6/32 is via adj for DROP");
2965 * break the loop by giving 5.5.5.5/32 a new set of paths
2966 * expect all to forward via this new path.
2968 fib_table_entry_update_one_path(fib_index,
2971 FIB_ENTRY_FLAG_NONE,
2974 tm->hw[0]->sw_if_index,
2975 ~0, // invalid fib index
2978 FIB_ROUTE_PATH_FLAG_NONE);
2980 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2981 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2982 lb = load_balance_get(dpo1->dpoi_index);
2983 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.5 LB has %d bucket", lb->lb_n_buckets);
2985 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2986 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2987 FIB_TEST((ai_01 == dpo2->dpoi_index),
2988 "5.5.5.5 bucket 0 resolves via 10.10.10.2");
2990 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_7_s_32);
2991 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2993 lb = load_balance_get(dpo2->dpoi_index);
2994 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2995 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo2->dpoi_index, 0)),
2996 "5.5.5.5.7 via 5.5.5.5");
2998 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32);
2999 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3001 lb = load_balance_get(dpo1->dpoi_index);
3002 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
3003 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3004 "5.5.5.5.6 via 5.5.5.7");
3007 * revert back to the loop. so we can remove the prefixes with
3010 fib_table_entry_update_one_path(fib_index,
3013 FIB_ENTRY_FLAG_NONE,
3015 &pfx_5_5_5_6_s_32.fp_addr,
3016 ~0, // no index provided.
3020 FIB_ROUTE_PATH_FLAG_NONE);
3022 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
3023 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
3024 "LB for 5.5.5.7/32 is via adj for DROP");
3025 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
3026 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
3027 "LB for 5.5.5.5/32 is via adj for DROP");
3028 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
3029 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
3030 "LB for 5.5.5.6/32 is via adj for DROP");
3033 * remove all the 5.5.5.x/32 prefixes
3035 fib_table_entry_path_remove(fib_index,
3039 &pfx_5_5_5_6_s_32.fp_addr,
3040 ~0, // no index provided.
3041 fib_index, // same as route's FIB
3043 FIB_ROUTE_PATH_FLAG_NONE);
3044 fib_table_entry_path_remove(fib_index,
3048 &pfx_5_5_5_7_s_32.fp_addr,
3049 ~0, // no index provided.
3050 fib_index, // same as route's FIB
3052 FIB_ROUTE_PATH_FLAG_NONE);
3053 fib_table_entry_path_remove(fib_index,
3057 &pfx_5_5_5_5_s_32.fp_addr,
3058 ~0, // no index provided.
3059 fib_index, // same as route's FIB
3061 FIB_ROUTE_PATH_FLAG_NONE);
3062 fib_table_entry_path_remove(fib_index,
3067 ~0, // no index provided.
3068 fib_index, // same as route's FIB
3070 FIB_ROUTE_PATH_FLAG_NONE);
3073 * -3 entries, -3 shared path-list
3075 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3076 fib_path_list_db_size());
3077 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3078 fib_path_list_pool_size());
3079 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3080 fib_entry_pool_size());
3083 * Single level loop 5.5.5.5/32 via 5.5.5.5/32
3085 fib_table_entry_path_add(fib_index,
3088 FIB_ENTRY_FLAG_NONE,
3090 &pfx_5_5_5_6_s_32.fp_addr,
3091 ~0, // no index provided.
3095 FIB_ROUTE_PATH_FLAG_NONE);
3096 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
3097 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
3098 "1-level 5.5.5.6/32 loop is via adj for DROP");
3100 fib_table_entry_path_remove(fib_index,
3104 &pfx_5_5_5_6_s_32.fp_addr,
3105 ~0, // no index provided.
3106 fib_index, // same as route's FIB
3108 FIB_ROUTE_PATH_FLAG_NONE);
3109 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3110 fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32),
3111 "1-level 5.5.5.6/32 loop is removed");
3114 * A recursive route whose next-hop is covered by the prefix.
3115 * This would mean the via-fib, which inherits forwarding from its
3116 * cover, thus picks up forwarding from the prfix, which is via the
3117 * via-fib, and we have a loop.
3119 fib_prefix_t pfx_23_23_23_0_s_24 = {
3121 .fp_proto = FIB_PROTOCOL_IP4,
3123 .ip4.as_u32 = clib_host_to_net_u32(0x17171700),
3126 fib_prefix_t pfx_23_23_23_23_s_32 = {
3128 .fp_proto = FIB_PROTOCOL_IP4,
3130 .ip4.as_u32 = clib_host_to_net_u32(0x17171717),
3133 fei = fib_table_entry_path_add(fib_index,
3134 &pfx_23_23_23_0_s_24,
3136 FIB_ENTRY_FLAG_NONE,
3138 &pfx_23_23_23_23_s_32.fp_addr,
3143 FIB_ROUTE_PATH_FLAG_NONE);
3144 dpo = fib_entry_contribute_ip_forwarding(fei);
3145 FIB_TEST(load_balance_is_drop(dpo),
3146 "23.23.23.0/24 via covered is DROP");
3147 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3150 * add-remove test. no change.
3152 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3153 fib_path_list_db_size());
3154 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3155 fib_path_list_pool_size());
3156 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3157 fib_entry_pool_size());
3160 * Make the default route recursive via a unknown next-hop. Thus the
3161 * next hop's cover would be the default route
3163 fei = fib_table_entry_path_add(fib_index,
3166 FIB_ENTRY_FLAG_NONE,
3168 &pfx_23_23_23_23_s_32.fp_addr,
3173 FIB_ROUTE_PATH_FLAG_NONE);
3174 dpo = fib_entry_contribute_ip_forwarding(fei);
3175 FIB_TEST(load_balance_is_drop(dpo),
3176 "0.0.0.0.0/0 via is DROP");
3177 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3178 "no resolving interface for looped 0.0.0.0/0");
3180 fei = fib_table_lookup_exact_match(fib_index, &pfx_23_23_23_23_s_32);
3181 dpo = fib_entry_contribute_ip_forwarding(fei);
3182 FIB_TEST(load_balance_is_drop(dpo),
3183 "23.23.23.23/32 via is DROP");
3184 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3185 "no resolving interface for looped 23.23.23.23/32");
3187 fib_table_entry_delete(fib_index, &pfx_0_0_0_0_s_0, FIB_SOURCE_API);
3190 * A recursive route with recursion constraints.
3191 * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained
3193 fib_table_entry_path_add(fib_index,
3196 FIB_ENTRY_FLAG_NONE,
3203 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3205 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3206 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3208 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3209 dpo1 = fib_entry_contribute_ip_forwarding(fei);
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 * save the load-balance. we expect it to be inplace modified
3217 lb = load_balance_get(dpo1->dpoi_index);
3220 * add a covering prefix for the via fib that would otherwise serve
3221 * as the resolving route when the host is removed
3223 fib_table_entry_path_add(fib_index,
3226 FIB_ENTRY_FLAG_NONE,
3229 tm->hw[0]->sw_if_index,
3230 ~0, // invalid fib index
3233 FIB_ROUTE_PATH_FLAG_NONE);
3234 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28);
3235 ai = fib_entry_get_adj(fei);
3236 FIB_TEST((ai == ai_01),
3237 "adj for 1.1.1.0/28 is via adj for 1.1.1.1");
3240 * remove the host via FIB - expect the BGP prefix to be drop
3242 fib_table_entry_path_remove(fib_index,
3247 tm->hw[0]->sw_if_index,
3248 ~0, // invalid fib index
3250 FIB_ROUTE_PATH_FLAG_NONE);
3252 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3253 "adj for 200.200.200.200/32 is recursive via adj for DROP");
3256 * add the via-entry host reoute back. expect to resolve again
3258 fib_table_entry_path_add(fib_index,
3261 FIB_ENTRY_FLAG_NONE,
3264 tm->hw[0]->sw_if_index,
3265 ~0, // invalid fib index
3268 FIB_ROUTE_PATH_FLAG_NONE);
3269 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3270 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3273 * add another path for the recursive. it will then have 2.
3275 fib_prefix_t pfx_1_1_1_3_s_32 = {
3277 .fp_proto = FIB_PROTOCOL_IP4,
3279 .ip4.as_u32 = clib_host_to_net_u32(0x01010103),
3282 fib_table_entry_path_add(fib_index,
3285 FIB_ENTRY_FLAG_NONE,
3288 tm->hw[0]->sw_if_index,
3289 ~0, // invalid fib index
3292 FIB_ROUTE_PATH_FLAG_NONE);
3294 fib_table_entry_path_add(fib_index,
3297 FIB_ENTRY_FLAG_NONE,
3299 &pfx_1_1_1_3_s_32.fp_addr,
3304 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3307 * add a bunch load more entries using this path combo so that we get
3308 * an LB-map created.
3311 fib_prefix_t bgp_78s[N_P];
3312 for (ii = 0; ii < N_P; ii++)
3314 bgp_78s[ii].fp_len = 32;
3315 bgp_78s[ii].fp_proto = FIB_PROTOCOL_IP4;
3316 bgp_78s[ii].fp_addr.ip4.as_u32 = clib_host_to_net_u32(0x4e000000+ii);
3319 fib_table_entry_path_add(fib_index,
3322 FIB_ENTRY_FLAG_NONE,
3324 &pfx_1_1_1_3_s_32.fp_addr,
3329 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3330 fib_table_entry_path_add(fib_index,
3333 FIB_ENTRY_FLAG_NONE,
3340 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3343 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3344 dpo = fib_entry_contribute_ip_forwarding(fei);
3346 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3347 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3348 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)),
3349 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3350 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32);
3351 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3352 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)),
3353 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3");
3356 * expect the lb-map used by the recursive's load-balance is using both buckets
3358 load_balance_map_t *lbm;
3361 lb = load_balance_get(dpo->dpoi_index);
3363 load_balance_map_lock(lbmi);
3364 lbm = load_balance_map_get(lbmi);
3366 FIB_TEST(lbm->lbm_buckets[0] == 0,
3367 "LB maps's bucket 0 is %d",
3368 lbm->lbm_buckets[0]);
3369 FIB_TEST(lbm->lbm_buckets[1] == 1,
3370 "LB maps's bucket 1 is %d",
3371 lbm->lbm_buckets[1]);
3374 * withdraw one of the /32 via-entrys.
3375 * that ECMP path will be unresolved and forwarding should continue on the
3376 * other available path. this is an iBGP PIC edge failover.
3377 * Test the forwarding changes without re-fetching the adj from the
3378 * recursive entry. this ensures its the same one that is updated; i.e. an
3381 fib_table_entry_path_remove(fib_index,
3386 tm->hw[0]->sw_if_index,
3387 ~0, // invalid fib index
3389 FIB_ROUTE_PATH_FLAG_NONE);
3391 /* suspend so the update walk kicks int */
3392 vlib_process_suspend(vlib_get_main(), 1e-5);
3394 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3395 FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)),
3396 "post PIC 200.200.200.200/32 was inplace modified");
3398 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)),
3399 "post PIC adj for 200.200.200.200/32 is recursive"
3400 " via adj for 1.1.1.3");
3403 * the LB maps that was locked above should have been modified to remove
3404 * the path that was down, and thus its bucket points to a path that is
3407 FIB_TEST(lbm->lbm_buckets[0] == 1,
3408 "LB maps's bucket 0 is %d",
3409 lbm->lbm_buckets[0]);
3410 FIB_TEST(lbm->lbm_buckets[1] == 1,
3411 "LB maps's bucket 1 is %d",
3412 lbm->lbm_buckets[1]);
3414 load_balance_map_unlock(lbmi);
3417 * add it back. again
3419 fib_table_entry_path_add(fib_index,
3422 FIB_ENTRY_FLAG_NONE,
3425 tm->hw[0]->sw_if_index,
3426 ~0, // invalid fib index
3429 FIB_ROUTE_PATH_FLAG_NONE);
3431 /* suspend so the update walk kicks in */
3432 vlib_process_suspend(vlib_get_main(), 1e-5);
3434 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)),
3435 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3436 "via adj for 1.1.1.1");
3437 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)),
3438 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3439 "via adj for 1.1.1.3");
3441 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3442 dpo = fib_entry_contribute_ip_forwarding(fei);
3443 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3444 "post PIC 200.200.200.200/32 was inplace modified");
3447 * add a 3rd path. this makes the LB 16 buckets.
3449 fib_table_entry_path_add(fib_index,
3452 FIB_ENTRY_FLAG_NONE,
3454 &pfx_1_1_1_2_s_32.fp_addr,
3459 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3460 for (ii = 0; ii < N_P; ii++)
3462 fib_table_entry_path_add(fib_index,
3465 FIB_ENTRY_FLAG_NONE,
3467 &pfx_1_1_1_2_s_32.fp_addr,
3472 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3475 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3476 dpo = fib_entry_contribute_ip_forwarding(fei);
3477 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3478 "200.200.200.200/32 was inplace modified for 3rd path");
3479 FIB_TEST(16 == lb->lb_n_buckets,
3480 "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets");
3483 load_balance_map_lock(lbmi);
3484 lbm = load_balance_map_get(lbmi);
3486 for (ii = 0; ii < 16; ii++)
3488 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3489 "LB Map for 200.200.200.200/32 at %d is %d",
3490 ii, lbm->lbm_buckets[ii]);
3494 * trigger PIC by removing the first via-entry
3495 * the first 6 buckets of the map should map to the next 6
3497 fib_table_entry_path_remove(fib_index,
3502 tm->hw[0]->sw_if_index,
3505 FIB_ROUTE_PATH_FLAG_NONE);
3506 /* suspend so the update walk kicks int */
3507 vlib_process_suspend(vlib_get_main(), 1e-5);
3509 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3510 dpo = fib_entry_contribute_ip_forwarding(fei);
3511 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3512 "200.200.200.200/32 was inplace modified for 3rd path");
3513 FIB_TEST(2 == lb->lb_n_buckets,
3514 "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets");
3516 for (ii = 0; ii < 6; ii++)
3518 FIB_TEST(lbm->lbm_buckets[ii] == ii+6,
3519 "LB Map for 200.200.200.200/32 at %d is %d",
3520 ii, lbm->lbm_buckets[ii]);
3522 for (ii = 6; ii < 16; ii++)
3524 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3525 "LB Map for 200.200.200.200/32 at %d is %d",
3526 ii, lbm->lbm_buckets[ii]);
3528 load_balance_map_unlock(lbmi);
3533 fib_table_entry_path_add(fib_index,
3536 FIB_ENTRY_FLAG_NONE,
3539 tm->hw[0]->sw_if_index,
3543 FIB_ROUTE_PATH_FLAG_NONE);
3545 for (ii = 0; ii < N_P; ii++)
3547 fib_table_entry_delete(fib_index,
3550 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3551 fib_table_lookup_exact_match(fib_index, &bgp_78s[ii])),
3553 format_fib_prefix, &bgp_78s[ii]);
3555 fib_table_entry_path_remove(fib_index,
3559 &pfx_1_1_1_2_s_32.fp_addr,
3563 MPLS_LABEL_INVALID);
3564 fib_table_entry_path_remove(fib_index,
3572 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3573 fib_table_entry_path_remove(fib_index,
3577 &pfx_1_1_1_3_s_32.fp_addr,
3581 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3582 fib_table_entry_delete(fib_index,
3585 fib_table_entry_delete(fib_index,
3588 /* suspend so the update walk kicks int */
3589 vlib_process_suspend(vlib_get_main(), 1e-5);
3590 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3591 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)),
3592 "1.1.1.1/28 removed");
3593 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3594 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)),
3595 "1.1.1.3/32 removed");
3596 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3597 fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)),
3598 "200.200.200.200/32 removed");
3601 * add-remove test. no change.
3603 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3604 fib_path_list_db_size());
3605 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3606 fib_path_list_pool_size());
3607 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3608 fib_entry_pool_size());
3611 * A route whose paths are built up iteratively and then removed
3614 fib_prefix_t pfx_4_4_4_4_s_32 = {
3616 .fp_proto = FIB_PROTOCOL_IP4,
3619 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
3623 fib_table_entry_path_add(fib_index,
3626 FIB_ENTRY_FLAG_NONE,
3629 tm->hw[0]->sw_if_index,
3633 FIB_ROUTE_PATH_FLAG_NONE);
3634 fib_table_entry_path_add(fib_index,
3637 FIB_ENTRY_FLAG_NONE,
3640 tm->hw[0]->sw_if_index,
3644 FIB_ROUTE_PATH_FLAG_NONE);
3645 fib_table_entry_path_add(fib_index,
3648 FIB_ENTRY_FLAG_NONE,
3651 tm->hw[0]->sw_if_index,
3655 FIB_ROUTE_PATH_FLAG_NONE);
3656 FIB_TEST(FIB_NODE_INDEX_INVALID !=
3657 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3658 "4.4.4.4/32 present");
3660 fib_table_entry_delete(fib_index,
3663 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3664 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3665 "4.4.4.4/32 removed");
3668 * add-remove test. no change.
3670 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3671 fib_path_list_db_size());
3672 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3673 fib_path_list_pool_size());
3674 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3675 fib_entry_pool_size());
3678 * A route with multiple paths at once
3681 fib_test_multipath_v4(tm, fib_index, &pfx_4_4_4_4_s_32, 4, 4),
3682 "multipath with 4 nexthops");
3685 * A route with lots of multiple paths that will overflow max supported
3686 * lb buckets because of normalization
3689 fib_test_multipath_v4(tm, fib_index, &pfx_4_4_4_4_s_32,
3690 LB_MAX_BUCKETS / 2 + 23, LB_MAX_BUCKETS),
3691 "multipath with too many nexthops");
3694 * A route with more paths than max supported lb buckets
3697 fib_test_multipath_v4 (tm, fib_index, &pfx_4_4_4_4_s_32,
3698 LB_MAX_BUCKETS + 13, LB_MAX_BUCKETS),
3699 "multipath with too many nexthops");
3702 * A route deag route
3704 fib_table_entry_path_add(fib_index,
3707 FIB_ENTRY_FLAG_NONE,
3714 FIB_ROUTE_PATH_FLAG_NONE);
3716 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3717 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3719 dpo = fib_entry_contribute_ip_forwarding(fei);
3720 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3721 lookup_dpo_t *lkd = lookup_dpo_get(dpo->dpoi_index);
3723 FIB_TEST((fib_index == lkd->lkd_fib_index),
3724 "4.4.4.4/32 is deag in %d %U",
3726 format_dpo_id, dpo, 0);
3727 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
3728 "4.4.4.4/32 is source deag in %d %U",
3730 format_dpo_id, dpo, 0);
3732 fib_table_entry_delete(fib_index,
3735 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3736 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3737 "4.4.4.4/32 removed");
3740 * A route deag route in a source lookup table
3742 fib_table_entry_path_add(fib_index,
3745 FIB_ENTRY_FLAG_NONE,
3752 FIB_ROUTE_PATH_SOURCE_LOOKUP);
3754 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3755 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3757 dpo = fib_entry_contribute_ip_forwarding(fei);
3758 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3759 lkd = lookup_dpo_get(dpo->dpoi_index);
3761 FIB_TEST((fib_index == lkd->lkd_fib_index),
3762 "4.4.4.4/32 is deag in %d %U",
3764 format_dpo_id, dpo, 0);
3765 FIB_TEST((LOOKUP_INPUT_SRC_ADDR == lkd->lkd_input),
3766 "4.4.4.4/32 is source deag in %d %U",
3768 format_dpo_id, dpo, 0);
3770 fib_table_entry_delete(fib_index,
3773 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3774 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3775 "4.4.4.4/32 removed");
3778 * add-remove test. no change.
3780 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3781 fib_path_list_db_size());
3782 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3783 fib_path_list_pool_size());
3784 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3785 fib_entry_pool_size());
3789 * add a recursive with duplicate paths. Expect the duplicate to be ignored.
3791 fib_prefix_t pfx_34_1_1_1_s_32 = {
3793 .fp_proto = FIB_PROTOCOL_IP4,
3795 .ip4.as_u32 = clib_host_to_net_u32(0x22010101),
3798 fib_prefix_t pfx_34_34_1_1_s_32 = {
3800 .fp_proto = FIB_PROTOCOL_IP4,
3802 .ip4.as_u32 = clib_host_to_net_u32(0x22220101),
3805 fei = fib_table_entry_path_add(fib_index,
3806 &pfx_34_34_1_1_s_32,
3808 FIB_ENTRY_FLAG_NONE,
3811 tm->hw[0]->sw_if_index,
3815 FIB_ROUTE_PATH_FLAG_NONE);
3816 fei = fib_table_entry_path_add(fib_index,
3819 FIB_ENTRY_FLAG_NONE,
3821 &pfx_34_34_1_1_s_32.fp_addr,
3826 FIB_ROUTE_PATH_FLAG_NONE);
3827 fei = fib_table_entry_path_add(fib_index,
3830 FIB_ENTRY_FLAG_NONE,
3832 &pfx_34_34_1_1_s_32.fp_addr,
3837 FIB_ROUTE_PATH_FLAG_NONE);
3838 FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0);
3839 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3840 fib_table_entry_delete(fib_index,
3841 &pfx_34_34_1_1_s_32,
3846 * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32
3847 * all of which are via 10.10.10.1, Itf1
3849 fib_table_entry_path_remove(fib_index,
3854 tm->hw[0]->sw_if_index,
3857 FIB_ROUTE_PATH_FLAG_NONE);
3858 fib_table_entry_path_remove(fib_index,
3863 tm->hw[0]->sw_if_index,
3866 FIB_ROUTE_PATH_FLAG_NONE);
3867 fib_table_entry_path_remove(fib_index,
3872 tm->hw[0]->sw_if_index,
3875 FIB_ROUTE_PATH_FLAG_NONE);
3877 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3878 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32),
3879 "1.1.1.1/32 removed");
3880 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3881 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32),
3882 "1.1.1.2/32 removed");
3883 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3884 fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24),
3885 "1.1.2.0/24 removed");
3888 * -3 entries and -1 shared path-list
3890 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3891 fib_path_list_db_size());
3892 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3893 fib_path_list_pool_size());
3894 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3895 fib_entry_pool_size());
3898 * An attached-host route. Expect to link to the incomplete adj
3900 fib_prefix_t pfx_4_1_1_1_s_32 = {
3902 .fp_proto = FIB_PROTOCOL_IP4,
3905 .ip4.as_u32 = clib_host_to_net_u32(0x04010101),
3908 fib_table_entry_path_add(fib_index,
3911 FIB_ENTRY_FLAG_NONE,
3914 tm->hw[0]->sw_if_index,
3918 FIB_ROUTE_PATH_FLAG_NONE);
3920 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32);
3921 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present");
3922 ai = fib_entry_get_adj(fei);
3924 ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
3926 &pfx_4_1_1_1_s_32.fp_addr,
3927 tm->hw[0]->sw_if_index);
3928 FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ");
3932 * +1 entry and +1 shared path-list
3934 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3935 fib_path_list_db_size());
3936 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3937 fib_path_list_pool_size());
3938 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
3939 fib_entry_pool_size());
3941 fib_table_entry_delete(fib_index,
3945 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3946 fib_path_list_db_size());
3947 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3948 fib_path_list_pool_size());
3949 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3950 fib_entry_pool_size());
3953 * add a v6 prefix via v4 next-hops
3955 fib_prefix_t pfx_2001_s_64 = {
3957 .fp_proto = FIB_PROTOCOL_IP6,
3959 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
3962 fei = fib_table_entry_path_add(0, //default v6 table
3965 FIB_ENTRY_FLAG_NONE,
3968 tm->hw[0]->sw_if_index,
3972 FIB_ROUTE_PATH_FLAG_NONE);
3974 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
3975 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present");
3976 ai = fib_entry_get_adj(fei);
3978 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
3979 "2001::/64 via ARP-adj");
3980 FIB_TEST((adj->ia_link == VNET_LINK_IP6),
3981 "2001::/64 is link type v6");
3982 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4),
3983 "2001::/64 ADJ-adj is NH proto v4");
3984 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
3987 * add a uRPF exempt prefix:
3989 * - it's forwarding is drop
3990 * - it's uRPF list is not empty
3991 * - the uRPF list for the default route (it's cover) is empty
3993 fei = fib_table_entry_special_add(fib_index,
3995 FIB_SOURCE_URPF_EXEMPT,
3996 FIB_ENTRY_FLAG_DROP);
3997 dpo = fib_entry_contribute_ip_forwarding(fei);
3998 FIB_TEST(load_balance_is_drop(dpo),
3999 "uRPF exempt 4.1.1.1/32 DROP");
4000 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0),
4001 "uRPF list for exempt prefix has itf index 0");
4002 fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0);
4003 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
4004 "uRPF list for 0.0.0.0/0 empty");
4006 fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
4009 * An adj-fib that fails the refinement criteria - no connected cover
4011 fib_prefix_t pfx_12_10_10_2_s_32 = {
4013 .fp_proto = FIB_PROTOCOL_IP4,
4016 .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02),
4020 fib_table_entry_path_add(fib_index,
4021 &pfx_12_10_10_2_s_32,
4023 FIB_ENTRY_FLAG_ATTACHED,
4025 &pfx_12_10_10_2_s_32.fp_addr,
4026 tm->hw[0]->sw_if_index,
4027 ~0, // invalid fib index
4030 FIB_ROUTE_PATH_FLAG_NONE);
4032 fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32);
4033 dpo = fib_entry_contribute_ip_forwarding(fei);
4034 FIB_TEST(dpo_is_drop(dpo),
4035 "no connected cover adj-fib fails refinement: %U",
4036 format_dpo_id, dpo, 0);
4038 fib_table_entry_delete(fib_index,
4039 &pfx_12_10_10_2_s_32,
4043 * An adj-fib that fails the refinement criteria - cover is connected
4044 * but on a different interface
4046 fib_prefix_t pfx_10_10_10_127_s_32 = {
4048 .fp_proto = FIB_PROTOCOL_IP4,
4051 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f),
4055 fib_table_entry_path_add(fib_index,
4056 &pfx_10_10_10_127_s_32,
4058 FIB_ENTRY_FLAG_ATTACHED,
4060 &pfx_10_10_10_127_s_32.fp_addr,
4061 tm->hw[1]->sw_if_index,
4062 ~0, // invalid fib index
4065 FIB_ROUTE_PATH_FLAG_NONE);
4067 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32);
4068 dpo = fib_entry_contribute_ip_forwarding(fei);
4069 FIB_TEST(dpo_is_drop(dpo),
4070 "wrong interface adj-fib fails refinement");
4072 fib_table_entry_delete(fib_index,
4073 &pfx_10_10_10_127_s_32,
4077 * add a second path to an adj-fib
4078 * this is a sumiluation of another ARP entry created
4079 * on an interface on which the connected prefix does not exist.
4080 * The second path fails refinement. Expect to forward through the
4083 fib_prefix_t pfx_10_10_10_3_s_32 = {
4085 .fp_proto = FIB_PROTOCOL_IP4,
4088 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
4092 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
4095 tm->hw[0]->sw_if_index);
4097 fib_test_lb_bucket_t ip_o_10_10_10_3 = {
4103 fei = fib_table_entry_path_add(fib_index,
4104 &pfx_10_10_10_3_s_32,
4106 FIB_ENTRY_FLAG_NONE,
4109 tm->hw[0]->sw_if_index,
4113 FIB_ROUTE_PATH_FLAG_NONE);
4114 fei = fib_table_entry_path_add(fib_index,
4115 &pfx_10_10_10_3_s_32,
4117 FIB_ENTRY_FLAG_NONE,
4120 tm->hw[1]->sw_if_index,
4124 FIB_ROUTE_PATH_FLAG_NONE);
4125 FIB_TEST(!fib_test_validate_entry(fei,
4126 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4129 "10.10.10.3 via 10.10.10.3/Eth0 only");
4132 * remove the path that refines the cover, should go unresolved
4134 fib_table_entry_path_remove(fib_index,
4135 &pfx_10_10_10_3_s_32,
4139 tm->hw[0]->sw_if_index,
4142 FIB_ROUTE_PATH_FLAG_NONE);
4143 dpo = fib_entry_contribute_ip_forwarding(fei);
4144 FIB_TEST(dpo_is_drop(dpo),
4145 "wrong interface adj-fib fails refinement");
4148 * add back the path that refines the cover
4150 fei = fib_table_entry_path_add(fib_index,
4151 &pfx_10_10_10_3_s_32,
4153 FIB_ENTRY_FLAG_NONE,
4156 tm->hw[0]->sw_if_index,
4160 FIB_ROUTE_PATH_FLAG_NONE);
4161 FIB_TEST(!fib_test_validate_entry(fei,
4162 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4165 "10.10.10.3 via 10.10.10.3/Eth0 only");
4168 * remove the path that does not refine the cover
4170 fib_table_entry_path_remove(fib_index,
4171 &pfx_10_10_10_3_s_32,
4175 tm->hw[1]->sw_if_index,
4178 FIB_ROUTE_PATH_FLAG_NONE);
4179 FIB_TEST(!fib_test_validate_entry(fei,
4180 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4183 "10.10.10.3 via 10.10.10.3/Eth0 only");
4186 * remove the path that does refine, it's the last path, so
4187 * the entry should be gone
4189 fib_table_entry_path_remove(fib_index,
4190 &pfx_10_10_10_3_s_32,
4194 tm->hw[0]->sw_if_index,
4197 FIB_ROUTE_PATH_FLAG_NONE);
4198 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
4199 FIB_TEST((fei == FIB_NODE_INDEX_INVALID), "10.10.10.3 gone");
4204 * change the table's flow-hash config - expect the update to propagete to
4205 * the entries' load-balance objects
4207 flow_hash_config_t old_hash_config, new_hash_config;
4209 old_hash_config = fib_table_get_flow_hash_config(fib_index,
4211 new_hash_config = (IP_FLOW_HASH_SRC_ADDR |
4212 IP_FLOW_HASH_DST_ADDR);
4214 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
4215 dpo = fib_entry_contribute_ip_forwarding(fei);
4216 lb = load_balance_get(dpo->dpoi_index);
4217 FIB_TEST((lb->lb_hash_config == old_hash_config),
4218 "Table and LB hash config match: %U",
4219 format_ip_flow_hash_config, lb->lb_hash_config);
4221 fib_table_set_flow_hash_config(fib_index, FIB_PROTOCOL_IP4, new_hash_config);
4223 FIB_TEST((lb->lb_hash_config == new_hash_config),
4224 "Table and LB newhash config match: %U",
4225 format_ip_flow_hash_config, lb->lb_hash_config);
4228 * A route via DVR DPO
4230 fei = fib_table_entry_path_add(fib_index,
4231 &pfx_10_10_10_3_s_32,
4233 FIB_ENTRY_FLAG_NONE,
4236 tm->hw[0]->sw_if_index,
4240 FIB_ROUTE_PATH_DVR);
4241 dpo_id_t dvr_dpo = DPO_INVALID;
4242 dvr_dpo_add_or_lock(tm->hw[0]->sw_if_index, DPO_PROTO_IP4, &dvr_dpo);
4243 fib_test_lb_bucket_t ip_o_l2 = {
4246 .adj = dvr_dpo.dpoi_index,
4250 FIB_TEST(!fib_test_validate_entry(fei,
4251 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4254 "10.10.10.3 via L2 on Eth0");
4255 fib_table_entry_path_remove(fib_index,
4256 &pfx_10_10_10_3_s_32,
4260 tm->hw[0]->sw_if_index,
4263 FIB_ROUTE_PATH_DVR);
4264 dpo_reset(&dvr_dpo);
4267 * add the default route via a next-hop that will form a loop
4269 fib_prefix_t pfx_conn = {
4271 .fp_proto = FIB_PROTOCOL_IP4,
4274 .ip4.as_u32 = clib_host_to_net_u32(0x1e1e1e1e),
4278 dfrt = fib_table_entry_path_add(fib_index,
4281 FIB_ENTRY_FLAG_NONE,
4288 FIB_ROUTE_PATH_FLAG_NONE);
4290 * the default route is a drop, since it's looped
4292 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4293 "Default route is DROP");
4296 * add a connected cover for the next-hop, this breaks the recursion loop
4297 * for the default route
4299 fib_table_entry_path_add(fib_index,
4302 (FIB_ENTRY_FLAG_CONNECTED |
4303 FIB_ENTRY_FLAG_ATTACHED),
4306 tm->hw[0]->sw_if_index,
4310 FIB_ROUTE_PATH_FLAG_NONE);
4311 pfx_conn.fp_len = 32;
4312 fei = fib_table_lookup_exact_match(fib_index, &pfx_conn);
4314 u32 ai_30 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
4317 tm->hw[0]->sw_if_index);
4319 fib_test_lb_bucket_t ip_o_30_30_30_30 = {
4325 FIB_TEST(!fib_test_validate_entry(fei,
4326 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4329 "30.30.30.30 via adj");
4330 FIB_TEST_REC_FORW(&pfx_0_0_0_0_s_0, &pfx_conn, 0);
4332 pfx_conn.fp_len = 24;
4333 fib_table_entry_delete(fib_index,
4336 fib_table_entry_delete(fib_index,
4345 fib_table_entry_delete(fib_index,
4346 &pfx_10_10_10_1_s_32,
4348 fib_table_entry_delete(fib_index,
4349 &pfx_10_10_10_2_s_32,
4351 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4352 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32),
4353 "10.10.10.1/32 adj-fib removed");
4354 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4355 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32),
4356 "10.10.10.2/32 adj-fib removed");
4359 * -2 entries and -2 non-shared path-list
4361 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4362 fib_path_list_db_size());
4363 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
4364 fib_path_list_pool_size());
4365 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
4366 fib_entry_pool_size());
4369 * unlock the adjacencies for which this test provided a rewrite.
4370 * These are the last locks on these adjs. they should thus go away.
4374 adj_unlock(ai_12_12_12_12);
4376 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4381 * remove the interface prefixes
4383 local_pfx.fp_len = 32;
4384 fib_table_entry_special_remove(fib_index, &local_pfx,
4385 FIB_SOURCE_INTERFACE);
4386 fei = fib_table_lookup(fib_index, &local_pfx);
4388 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4389 fib_table_lookup_exact_match(fib_index, &local_pfx),
4390 "10.10.10.10/32 adj-fib removed");
4392 local_pfx.fp_len = 24;
4393 fib_table_entry_delete(fib_index, &local_pfx,
4394 FIB_SOURCE_INTERFACE);
4396 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4397 fib_table_lookup_exact_match(fib_index, &local_pfx),
4398 "10.10.10.10/24 adj-fib removed");
4401 * -2 entries and -2 non-shared path-list
4403 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4404 fib_path_list_db_size());
4405 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
4406 fib_path_list_pool_size());
4407 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
4408 fib_entry_pool_size());
4411 * Last but not least, remove the VRF
4413 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4416 "NO API Source'd prefixes");
4417 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4420 "NO RR Source'd prefixes");
4421 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4423 FIB_SOURCE_INTERFACE)),
4424 "NO INterface Source'd prefixes");
4426 for (ii = 0; ii < 4; ii++)
4427 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[ii]->sw_if_index, 0);
4429 fib_table_unlock(fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
4431 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4432 fib_path_list_db_size());
4433 FIB_TEST((PNBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
4434 fib_path_list_pool_size());
4435 FIB_TEST((ENBR-5 == fib_entry_pool_size()), "entry pool size is %d",
4436 fib_entry_pool_size());
4437 FIB_TEST((ENBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
4438 pool_elts(fib_urpf_list_pool));
4439 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
4440 pool_elts(load_balance_map_pool));
4441 FIB_TEST((lb_count == pool_elts(load_balance_pool)), "LB pool size is %d",
4442 pool_elts(load_balance_pool));
4443 FIB_TEST((0 == pool_elts(dvr_dpo_pool)), "L2 DPO pool size is %d",
4444 pool_elts(dvr_dpo_pool));
4453 * In the default table check for the presence and correct forwarding
4454 * of the special entries
4456 fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02;
4457 const dpo_id_t *dpo, *dpo_drop;
4458 const ip_adjacency_t *adj;
4459 const receive_dpo_t *rd;
4465 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4468 /* via 2001:0:0:1::2 */
4469 ip46_address_t nh_2001_2 = {
4472 [0] = clib_host_to_net_u64(0x2001000000000001),
4473 [1] = clib_host_to_net_u64(0x0000000000000002),
4480 dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
4482 /* Find or create FIB table 11 */
4483 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11,
4486 for (ii = 0; ii < 4; ii++)
4487 fib_table_bind (FIB_PROTOCOL_IP6, tm->hw[ii]->sw_if_index, fib_index);
4489 fib_prefix_t pfx_0_0 = {
4491 .fp_proto = FIB_PROTOCOL_IP6,
4499 dfrt = fib_table_lookup(fib_index, &pfx_0_0);
4500 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
4501 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4502 "Default route is DROP");
4504 dpo = fib_entry_contribute_ip_forwarding(dfrt);
4505 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4507 &pfx_0_0.fp_addr.ip6)),
4508 "default-route; fwd and non-fwd tables match");
4510 // FIXME - check specials.
4513 * At this stage there is one v4 FIB with 5 routes and two v6 FIBs
4514 * each with 2 entries and a v6 mfib with 4 path-lists and v4 mfib with 2.
4515 * All entries are special so no path-list sharing.
4518 u32 PNPS = (5+4+4+2);
4520 * if the IGMP plugin is loaded this adds two more entries to the v4 MFIB
4522 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
4523 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is %d",
4524 fib_path_list_pool_size());
4525 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
4526 fib_entry_pool_size());
4529 * add interface routes.
4530 * validate presence of /64 attached and /128 recieve.
4531 * test for the presence of the receive address in the glean and local adj
4533 * receive on 2001:0:0:1::1/128
4535 fib_prefix_t local_pfx = {
4537 .fp_proto = FIB_PROTOCOL_IP6,
4541 [0] = clib_host_to_net_u64(0x2001000000000001),
4542 [1] = clib_host_to_net_u64(0x0000000000000001),
4548 fib_table_entry_update_one_path(fib_index, &local_pfx,
4549 FIB_SOURCE_INTERFACE,
4550 (FIB_ENTRY_FLAG_CONNECTED |
4551 FIB_ENTRY_FLAG_ATTACHED),
4554 tm->hw[0]->sw_if_index,
4558 FIB_ROUTE_PATH_FLAG_NONE);
4559 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4561 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4563 ai = fib_entry_get_adj(fei);
4564 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
4566 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4567 "attached interface adj is glean");
4568 dpo = fib_entry_contribute_ip_forwarding(fei);
4569 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4571 &local_pfx.fp_addr.ip6)),
4572 "attached-route; fwd and non-fwd tables match");
4574 local_pfx.fp_len = 128;
4575 fib_table_entry_update_one_path(fib_index, &local_pfx,
4576 FIB_SOURCE_INTERFACE,
4577 (FIB_ENTRY_FLAG_CONNECTED |
4578 FIB_ENTRY_FLAG_LOCAL),
4581 tm->hw[0]->sw_if_index,
4582 ~0, // invalid fib index
4585 FIB_ROUTE_PATH_FLAG_NONE);
4586 fei = fib_table_lookup(fib_index, &local_pfx);
4588 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4590 dpo = fib_entry_contribute_ip_forwarding(fei);
4591 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4592 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4593 "local interface adj is local");
4594 rd = receive_dpo_get(dpo->dpoi_index);
4596 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4598 "local interface adj is receive ok");
4600 dpo = fib_entry_contribute_ip_forwarding(fei);
4601 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4603 &local_pfx.fp_addr.ip6)),
4604 "local-route; fwd and non-fwd tables match");
4605 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4606 &adj->sub_type.glean.rx_pfx.fp_addr)),
4607 "attached interface adj is receive ok");
4610 * +2 entries. +2 unshared path-lists
4612 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
4613 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
4614 fib_path_list_pool_size());
4615 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4616 fib_entry_pool_size());
4619 * Modify the default route to be via an adj not yet known.
4620 * this sources the defalut route with the API source, which is
4621 * a higher preference to the DEFAULT_ROUTE source
4623 fib_table_entry_path_add(fib_index, &pfx_0_0,
4625 FIB_ENTRY_FLAG_NONE,
4628 tm->hw[0]->sw_if_index,
4632 FIB_ROUTE_PATH_FLAG_NONE);
4633 fei = fib_table_lookup(fib_index, &pfx_0_0);
4635 FIB_TEST((fei == dfrt), "default route same index");
4636 ai = fib_entry_get_adj(fei);
4637 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
4639 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4640 "adj is incomplete");
4641 FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)),
4642 "adj nbr next-hop ok");
4645 * find the adj in the shared db
4647 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4650 tm->hw[0]->sw_if_index);
4651 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
4652 adj_unlock(locked_ai);
4655 * no more entries. +1 shared path-list
4657 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4658 fib_path_list_db_size());
4659 FIB_TEST((PNPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
4660 fib_path_list_pool_size());
4661 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4662 fib_entry_pool_size());
4665 * remove the API source from the default route. We expected
4666 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
4668 fib_table_entry_path_remove(fib_index, &pfx_0_0,
4672 tm->hw[0]->sw_if_index,
4675 FIB_ROUTE_PATH_FLAG_NONE);
4676 fei = fib_table_lookup(fib_index, &pfx_0_0);
4678 FIB_TEST((fei == dfrt), "default route same index");
4679 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4680 "Default route is DROP");
4683 * no more entries. -1 shared path-list
4685 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4686 fib_path_list_db_size());
4687 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
4688 fib_path_list_pool_size());
4689 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4690 fib_entry_pool_size());
4693 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4695 fib_prefix_t pfx_2001_1_2_s_128 = {
4697 .fp_proto = FIB_PROTOCOL_IP6,
4701 [0] = clib_host_to_net_u64(0x2001000000000001),
4702 [1] = clib_host_to_net_u64(0x0000000000000002),
4707 fib_prefix_t pfx_2001_1_3_s_128 = {
4709 .fp_proto = FIB_PROTOCOL_IP6,
4713 [0] = clib_host_to_net_u64(0x2001000000000001),
4714 [1] = clib_host_to_net_u64(0x0000000000000003),
4720 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
4723 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4725 &pfx_2001_1_2_s_128.fp_addr,
4726 tm->hw[0]->sw_if_index);
4727 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
4728 adj = adj_get(ai_01);
4729 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4730 "adj is incomplete");
4731 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4732 &adj->sub_type.nbr.next_hop)),
4733 "adj nbr next-hop ok");
4735 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4736 fib_test_build_rewrite(eth_addr));
4737 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4739 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4740 &adj->sub_type.nbr.next_hop)),
4741 "adj nbr next-hop ok");
4743 fib_table_entry_path_add(fib_index,
4744 &pfx_2001_1_2_s_128,
4746 FIB_ENTRY_FLAG_ATTACHED,
4748 &pfx_2001_1_2_s_128.fp_addr,
4749 tm->hw[0]->sw_if_index,
4753 FIB_ROUTE_PATH_FLAG_NONE);
4755 fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
4756 ai = fib_entry_get_adj(fei);
4757 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4761 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4763 &pfx_2001_1_3_s_128.fp_addr,
4764 tm->hw[0]->sw_if_index);
4765 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
4766 adj = adj_get(ai_02);
4767 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4768 "adj is incomplete");
4769 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4770 &adj->sub_type.nbr.next_hop)),
4771 "adj nbr next-hop ok");
4773 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4774 fib_test_build_rewrite(eth_addr));
4775 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4777 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4778 &adj->sub_type.nbr.next_hop)),
4779 "adj nbr next-hop ok");
4780 FIB_TEST((ai_01 != ai_02), "ADJs are different");
4782 fib_table_entry_path_add(fib_index,
4783 &pfx_2001_1_3_s_128,
4785 FIB_ENTRY_FLAG_ATTACHED,
4787 &pfx_2001_1_3_s_128.fp_addr,
4788 tm->hw[0]->sw_if_index,
4792 FIB_ROUTE_PATH_FLAG_NONE);
4794 fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
4795 ai = fib_entry_get_adj(fei);
4796 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4799 * +2 entries, +2 unshread path-lists.
4801 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4802 fib_path_list_db_size());
4803 FIB_TEST((PNPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
4804 fib_path_list_pool_size());
4805 FIB_TEST((ENPS+4 == fib_entry_pool_size()), "entry pool size is %d",
4806 fib_entry_pool_size());
4809 * Add a 2 routes via the first ADJ. ensure path-list sharing
4811 fib_prefix_t pfx_2001_a_s_64 = {
4813 .fp_proto = FIB_PROTOCOL_IP6,
4817 [0] = clib_host_to_net_u64(0x200100000000000a),
4818 [1] = clib_host_to_net_u64(0x0000000000000000),
4823 fib_prefix_t pfx_2001_b_s_64 = {
4825 .fp_proto = FIB_PROTOCOL_IP6,
4829 [0] = clib_host_to_net_u64(0x200100000000000b),
4830 [1] = clib_host_to_net_u64(0x0000000000000000),
4836 fib_table_entry_path_add(fib_index,
4839 FIB_ENTRY_FLAG_NONE,
4842 tm->hw[0]->sw_if_index,
4846 FIB_ROUTE_PATH_FLAG_NONE);
4847 fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64);
4848 ai = fib_entry_get_adj(fei);
4849 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4850 fib_table_entry_path_add(fib_index,
4853 FIB_ENTRY_FLAG_NONE,
4856 tm->hw[0]->sw_if_index,
4860 FIB_ROUTE_PATH_FLAG_NONE);
4861 fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64);
4862 ai = fib_entry_get_adj(fei);
4863 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4866 * +2 entries, +1 shared path-list.
4868 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4869 fib_path_list_db_size());
4870 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4871 fib_path_list_pool_size());
4872 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
4873 fib_entry_pool_size());
4876 * add a v4 prefix via a v6 next-hop
4878 fib_prefix_t pfx_1_1_1_1_s_32 = {
4880 .fp_proto = FIB_PROTOCOL_IP4,
4882 .ip4.as_u32 = 0x01010101,
4885 fei = fib_table_entry_path_add(0, // default table
4888 FIB_ENTRY_FLAG_NONE,
4891 tm->hw[0]->sw_if_index,
4895 FIB_ROUTE_PATH_FLAG_NONE);
4896 FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32),
4897 "1.1.1.1/32 o v6 route present");
4898 ai = fib_entry_get_adj(fei);
4900 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
4901 "1.1.1.1/32 via ARP-adj");
4902 FIB_TEST((adj->ia_link == VNET_LINK_IP4),
4903 "1.1.1.1/32 ADJ-adj is link type v4");
4904 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6),
4905 "1.1.1.1/32 ADJ-adj is NH proto v6");
4906 fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API);
4911 fib_prefix_t pfx_2001_c_s_64 = {
4913 .fp_proto = FIB_PROTOCOL_IP6,
4917 [0] = clib_host_to_net_u64(0x200100000000000c),
4918 [1] = clib_host_to_net_u64(0x0000000000000000),
4923 fib_table_entry_path_add(fib_index,
4926 FIB_ENTRY_FLAG_ATTACHED,
4929 tm->hw[0]->sw_if_index,
4933 FIB_ROUTE_PATH_FLAG_NONE);
4934 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4935 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present");
4936 ai = fib_entry_get_adj(fei);
4938 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN),
4939 "2001:0:0:c/64 attached resolves via glean");
4941 fib_table_entry_path_remove(fib_index,
4946 tm->hw[0]->sw_if_index,
4949 FIB_ROUTE_PATH_FLAG_NONE);
4950 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4951 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached route removed");
4954 * Shutdown the interface on which we have a connected and through
4955 * which the routes are reachable.
4956 * This will result in the connected, adj-fibs, and routes linking to drop
4957 * The local/for-us prefix continues to receive.
4959 clib_error_t * error;
4961 error = vnet_sw_interface_set_flags(vnet_get_main(),
4962 tm->hw[0]->sw_if_index,
4963 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4964 FIB_TEST((NULL == error), "Interface shutdown OK");
4966 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4967 dpo = fib_entry_contribute_ip_forwarding(fei);
4968 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4969 "2001::b/64 resolves via drop");
4971 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4972 dpo = fib_entry_contribute_ip_forwarding(fei);
4973 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4974 "2001::a/64 resolves via drop");
4975 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4976 dpo = fib_entry_contribute_ip_forwarding(fei);
4977 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4978 "2001:0:0:1::3/64 resolves via drop");
4979 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4980 dpo = fib_entry_contribute_ip_forwarding(fei);
4981 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4982 "2001:0:0:1::2/64 resolves via drop");
4983 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4984 dpo = fib_entry_contribute_ip_forwarding(fei);
4985 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4986 "2001:0:0:1::1/128 not drop");
4987 local_pfx.fp_len = 64;
4988 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4989 dpo = fib_entry_contribute_ip_forwarding(fei);
4990 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4991 "2001:0:0:1/64 resolves via drop");
4996 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4997 fib_path_list_db_size());
4998 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4999 fib_path_list_pool_size());
5000 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
5001 fib_entry_pool_size());
5004 * shutdown one of the other interfaces, then add a connected.
5005 * and swap one of the routes to it.
5007 error = vnet_sw_interface_set_flags(vnet_get_main(),
5008 tm->hw[1]->sw_if_index,
5009 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5010 FIB_TEST((NULL == error), "Interface 1 shutdown OK");
5012 fib_prefix_t connected_pfx = {
5014 .fp_proto = FIB_PROTOCOL_IP6,
5017 /* 2001:0:0:2::1/64 */
5019 [0] = clib_host_to_net_u64(0x2001000000000002),
5020 [1] = clib_host_to_net_u64(0x0000000000000001),
5025 fib_table_entry_update_one_path(fib_index, &connected_pfx,
5026 FIB_SOURCE_INTERFACE,
5027 (FIB_ENTRY_FLAG_CONNECTED |
5028 FIB_ENTRY_FLAG_ATTACHED),
5031 tm->hw[1]->sw_if_index,
5035 FIB_ROUTE_PATH_FLAG_NONE);
5036 fei = fib_table_lookup_exact_match(fib_index, &connected_pfx);
5037 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
5038 dpo = fib_entry_contribute_ip_forwarding(fei);
5039 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
5040 FIB_TEST(!dpo_cmp(dpo, dpo_drop),
5041 "2001:0:0:2/64 not resolves via drop");
5043 connected_pfx.fp_len = 128;
5044 fib_table_entry_update_one_path(fib_index, &connected_pfx,
5045 FIB_SOURCE_INTERFACE,
5046 (FIB_ENTRY_FLAG_CONNECTED |
5047 FIB_ENTRY_FLAG_LOCAL),
5050 tm->hw[0]->sw_if_index,
5051 ~0, // invalid fib index
5054 FIB_ROUTE_PATH_FLAG_NONE);
5055 fei = fib_table_lookup(fib_index, &connected_pfx);
5057 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
5058 dpo = fib_entry_contribute_ip_forwarding(fei);
5059 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
5060 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
5061 "local interface adj is local");
5062 rd = receive_dpo_get(dpo->dpoi_index);
5063 FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr,
5065 "local interface adj is receive ok");
5068 * +2 entries, +2 unshared path-lists
5070 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
5071 fib_path_list_db_size());
5072 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
5073 fib_path_list_pool_size());
5074 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
5075 fib_entry_pool_size());
5079 * bring the interface back up. we expected the routes to return
5080 * to normal forwarding.
5082 error = vnet_sw_interface_set_flags(vnet_get_main(),
5083 tm->hw[0]->sw_if_index,
5084 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5085 FIB_TEST((NULL == error), "Interface bring-up OK");
5086 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5087 ai = fib_entry_get_adj(fei);
5088 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
5089 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5090 ai = fib_entry_get_adj(fei);
5091 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
5092 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5093 ai = fib_entry_get_adj(fei);
5094 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
5095 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5096 ai = fib_entry_get_adj(fei);
5097 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
5098 local_pfx.fp_len = 64;
5099 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5100 ai = fib_entry_get_adj(fei);
5102 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
5103 "attached interface adj is glean");
5106 * Same test as above, but this time the HW interface goes down
5108 error = vnet_hw_interface_set_flags(vnet_get_main(),
5109 tm->hw_if_indicies[0],
5110 ~VNET_HW_INTERFACE_FLAG_LINK_UP);
5111 FIB_TEST((NULL == error), "Interface shutdown OK");
5113 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5114 dpo = fib_entry_contribute_ip_forwarding(fei);
5115 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5116 "2001::b/64 resolves via drop");
5117 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5118 dpo = fib_entry_contribute_ip_forwarding(fei);
5119 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5120 "2001::a/64 resolves via drop");
5121 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5122 dpo = fib_entry_contribute_ip_forwarding(fei);
5123 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5124 "2001:0:0:1::3/128 resolves via drop");
5125 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5126 dpo = fib_entry_contribute_ip_forwarding(fei);
5127 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5128 "2001:0:0:1::2/128 resolves via drop");
5129 local_pfx.fp_len = 128;
5130 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5131 dpo = fib_entry_contribute_ip_forwarding(fei);
5132 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5133 "2001:0:0:1::1/128 not drop");
5134 local_pfx.fp_len = 64;
5135 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5136 dpo = fib_entry_contribute_ip_forwarding(fei);
5137 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5138 "2001:0:0:1/64 resolves via drop");
5140 error = vnet_hw_interface_set_flags(vnet_get_main(),
5141 tm->hw_if_indicies[0],
5142 VNET_HW_INTERFACE_FLAG_LINK_UP);
5143 FIB_TEST((NULL == error), "Interface bring-up OK");
5144 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5145 ai = fib_entry_get_adj(fei);
5146 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
5147 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5148 ai = fib_entry_get_adj(fei);
5149 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
5150 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5151 ai = fib_entry_get_adj(fei);
5152 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
5153 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5154 ai = fib_entry_get_adj(fei);
5155 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
5156 local_pfx.fp_len = 64;
5157 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5158 ai = fib_entry_get_adj(fei);
5160 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
5161 "attached interface adj is glean");
5164 * Delete the interface that the routes reolve through.
5165 * Again no routes are removed. They all point to drop.
5167 * This is considered an error case. The control plane should
5168 * not remove interfaces through which routes resolve, but
5169 * such things can happen. ALL affected routes will drop.
5171 vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]);
5173 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5174 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5175 "2001::b/64 resolves via drop");
5176 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5177 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5178 "2001::b/64 resolves via drop");
5179 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5180 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5181 "2001:0:0:1::3/64 resolves via drop");
5182 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5183 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5184 "2001:0:0:1::2/64 resolves via drop");
5185 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5186 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5187 "2001:0:0:1::1/128 is drop");
5188 local_pfx.fp_len = 64;
5189 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5190 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5191 "2001:0:0:1/64 resolves via drop");
5196 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
5197 fib_path_list_db_size());
5198 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
5199 fib_path_list_pool_size());
5200 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
5201 fib_entry_pool_size());
5204 * Add the interface back. routes stay unresolved.
5206 vnet_eth_interface_registration_t eir = {};
5207 eir.dev_class_index = test_interface_device_class.index;
5208 eir.dev_instance = 0;
5209 eir.address = hw_address;
5210 tm->hw_if_indicies[0] = vnet_eth_register_interface (vnet_get_main(), &eir);
5212 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5213 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5214 "2001::b/64 resolves via drop");
5215 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5216 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5217 "2001::b/64 resolves via drop");
5218 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5219 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5220 "2001:0:0:1::3/64 resolves via drop");
5221 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5222 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5223 "2001:0:0:1::2/64 resolves via drop");
5224 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5225 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5226 "2001:0:0:1::1/128 is drop");
5227 local_pfx.fp_len = 64;
5228 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5229 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5230 "2001:0:0:1/64 resolves via drop");
5233 * CLEANUP ALL the routes
5235 fib_table_entry_delete(fib_index,
5238 fib_table_entry_delete(fib_index,
5241 fib_table_entry_delete(fib_index,
5244 fib_table_entry_delete(fib_index,
5245 &pfx_2001_1_3_s_128,
5247 fib_table_entry_delete(fib_index,
5248 &pfx_2001_1_2_s_128,
5250 local_pfx.fp_len = 64;
5251 fib_table_entry_delete(fib_index, &local_pfx,
5252 FIB_SOURCE_INTERFACE);
5253 local_pfx.fp_len = 128;
5254 fib_table_entry_special_remove(fib_index, &local_pfx,
5255 FIB_SOURCE_INTERFACE);
5256 connected_pfx.fp_len = 64;
5257 fib_table_entry_delete(fib_index, &connected_pfx,
5258 FIB_SOURCE_INTERFACE);
5259 connected_pfx.fp_len = 128;
5260 fib_table_entry_special_remove(fib_index, &connected_pfx,
5261 FIB_SOURCE_INTERFACE);
5263 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5264 fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)),
5265 "2001::a/64 removed");
5266 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5267 fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)),
5268 "2001::b/64 removed");
5269 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5270 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)),
5271 "2001:0:0:1::3/128 removed");
5272 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5273 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)),
5274 "2001:0:0:1::3/128 removed");
5275 local_pfx.fp_len = 64;
5276 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5277 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5278 "2001:0:0:1/64 removed");
5279 local_pfx.fp_len = 128;
5280 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5281 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5282 "2001:0:0:1::1/128 removed");
5283 connected_pfx.fp_len = 64;
5284 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5285 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5286 "2001:0:0:2/64 removed");
5287 connected_pfx.fp_len = 128;
5288 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5289 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5290 "2001:0:0:2::1/128 removed");
5293 * -8 entries. -7 path-lists (1 was shared).
5295 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5296 fib_path_list_db_size());
5297 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is%d",
5298 fib_path_list_pool_size());
5299 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
5300 fib_entry_pool_size());
5303 * now remove the VRF
5306 for (ii = 0; ii < 4; ii++)
5307 fib_table_bind (FIB_PROTOCOL_IP6, tm->hw[ii]->sw_if_index, 0);
5309 fib_table_unlock(fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
5311 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5312 fib_path_list_db_size());
5313 FIB_TEST((PNPS-2 == fib_path_list_pool_size()), "path list pool size is%d",
5314 fib_path_list_pool_size());
5315 FIB_TEST((ENPS-2 == fib_entry_pool_size()), "entry pool size is %d",
5316 fib_entry_pool_size());
5322 * return the interfaces to up state
5324 error = vnet_sw_interface_set_flags(vnet_get_main(),
5325 tm->hw[0]->sw_if_index,
5326 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5327 error = vnet_sw_interface_set_flags(vnet_get_main(),
5328 tm->hw[1]->sw_if_index,
5329 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5331 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5333 FIB_TEST((0 == adj_glean_db_size()), "ADJ DB size is %d",
5334 adj_glean_db_size());
5340 * Test Attached Exports
5345 const dpo_id_t *dpo, *dpo_drop;
5346 const u32 fib_index = 0;
5347 fib_node_index_t dfrt, fei;
5354 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5358 * add interface routes. We'll assume this works. It's more rigorously
5361 fib_prefix_t local_pfx = {
5363 .fp_proto = FIB_PROTOCOL_IP4,
5367 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5372 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[0]->sw_if_index, fib_index);
5374 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
5376 fib_table_entry_update_one_path(fib_index, &local_pfx,
5377 FIB_SOURCE_INTERFACE,
5378 (FIB_ENTRY_FLAG_CONNECTED |
5379 FIB_ENTRY_FLAG_ATTACHED),
5382 tm->hw[0]->sw_if_index,
5386 FIB_ROUTE_PATH_FLAG_NONE);
5387 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5388 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5389 "attached interface route present");
5391 local_pfx.fp_len = 32;
5392 fib_table_entry_update_one_path(fib_index, &local_pfx,
5393 FIB_SOURCE_INTERFACE,
5394 (FIB_ENTRY_FLAG_CONNECTED |
5395 FIB_ENTRY_FLAG_LOCAL),
5398 tm->hw[0]->sw_if_index,
5399 ~0, // invalid fib index
5402 FIB_ROUTE_PATH_FLAG_NONE);
5403 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5405 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5406 "local interface route present");
5409 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
5411 fib_prefix_t pfx_10_10_10_1_s_32 = {
5413 .fp_proto = FIB_PROTOCOL_IP4,
5416 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5419 fib_node_index_t ai;
5421 fib_table_entry_path_add(fib_index,
5422 &pfx_10_10_10_1_s_32,
5424 FIB_ENTRY_FLAG_ATTACHED,
5426 &pfx_10_10_10_1_s_32.fp_addr,
5427 tm->hw[0]->sw_if_index,
5428 ~0, // invalid fib index
5431 FIB_ROUTE_PATH_FLAG_NONE);
5433 fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
5434 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
5435 ai = fib_entry_get_adj(fei);
5438 * create another FIB table into which routes will be imported
5440 u32 import_fib_index1;
5442 import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4,
5446 * Add default route in the import FIB
5448 fib_prefix_t pfx_0_0_0_0_s_0 = {
5450 .fp_proto = FIB_PROTOCOL_IP4,
5458 dfrt = fib_table_lookup(import_fib_index1, &pfx_0_0_0_0_s_0);
5459 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
5461 fib_table_entry_path_add(import_fib_index1,
5464 FIB_ENTRY_FLAG_NONE,
5467 tm->hw[0]->sw_if_index,
5468 ~0, // invalid fib index
5471 FIB_ROUTE_PATH_FLAG_NONE);
5472 fei = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
5473 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "default route present");
5474 FIB_TEST((fei != dfrt), "default route added");
5477 * delete default route and check for the presence in the import table
5479 fib_table_entry_delete(import_fib_index1, &pfx_0_0_0_0_s_0, FIB_SOURCE_API);
5480 fei = fib_table_lookup(import_fib_index1, &pfx_0_0_0_0_s_0);
5481 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "default route present");
5482 FIB_TEST((fei == dfrt), "default route removed");
5485 * Add an attached route in the import FIB
5487 local_pfx.fp_len = 24;
5488 fib_table_entry_update_one_path(import_fib_index1,
5491 FIB_ENTRY_FLAG_NONE,
5494 tm->hw[0]->sw_if_index,
5495 ~0, // invalid fib index
5498 FIB_ROUTE_PATH_FLAG_NONE);
5499 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5500 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5503 * check for the presence of the adj-fibs in the import table
5505 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5506 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5507 FIB_TEST((ai == fib_entry_get_adj(fei)),
5508 "adj-fib1 Import uses same adj as export");
5511 * check for the presence of the local in the import table
5513 local_pfx.fp_len = 32;
5514 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5515 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5518 * Add another adj-fin in the export table. Expect this
5519 * to get magically exported;
5521 fib_prefix_t pfx_10_10_10_2_s_32 = {
5523 .fp_proto = FIB_PROTOCOL_IP4,
5526 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5530 fib_table_entry_path_add(fib_index,
5531 &pfx_10_10_10_2_s_32,
5533 FIB_ENTRY_FLAG_ATTACHED,
5535 &pfx_10_10_10_2_s_32.fp_addr,
5536 tm->hw[0]->sw_if_index,
5537 ~0, // invalid fib index
5540 FIB_ROUTE_PATH_FLAG_NONE);
5541 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5542 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
5543 ai = fib_entry_get_adj(fei);
5545 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5546 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5547 FIB_TEST((ai == fib_entry_get_adj(fei)),
5548 "Import uses same adj as export");
5549 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(fei)),
5550 "ADJ-fib2 imported flags %d",
5551 fib_entry_get_flags(fei));
5554 * create a 2nd FIB table into which routes will be imported
5556 u32 import_fib_index2;
5558 import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12,
5562 * Add an attached route in the import FIB
5564 local_pfx.fp_len = 24;
5565 fib_table_entry_update_one_path(import_fib_index2,
5568 FIB_ENTRY_FLAG_NONE,
5571 tm->hw[0]->sw_if_index,
5572 ~0, // invalid fib index
5575 FIB_ROUTE_PATH_FLAG_NONE);
5576 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5577 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5580 * check for the presence of all the adj-fibs and local in the import table
5582 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5583 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5584 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5585 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5586 local_pfx.fp_len = 32;
5587 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5588 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5591 * add a 3rd adj-fib. expect it to be exported to both tables.
5593 fib_prefix_t pfx_10_10_10_3_s_32 = {
5595 .fp_proto = FIB_PROTOCOL_IP4,
5598 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
5602 fib_table_entry_path_add(fib_index,
5603 &pfx_10_10_10_3_s_32,
5605 FIB_ENTRY_FLAG_ATTACHED,
5607 &pfx_10_10_10_3_s_32.fp_addr,
5608 tm->hw[0]->sw_if_index,
5609 ~0, // invalid fib index
5612 FIB_ROUTE_PATH_FLAG_NONE);
5613 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5614 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
5615 ai = fib_entry_get_adj(fei);
5617 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5618 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1");
5619 FIB_TEST((ai == fib_entry_get_adj(fei)),
5620 "Import uses same adj as export");
5621 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5622 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2");
5623 FIB_TEST((ai == fib_entry_get_adj(fei)),
5624 "Import uses same adj as export");
5627 * remove the 3rd adj fib. we expect it to be removed from both FIBs
5629 fib_table_entry_delete(fib_index,
5630 &pfx_10_10_10_3_s_32,
5633 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5634 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved");
5636 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5637 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1");
5639 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5640 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2");
5643 * remove the attached route from the 2nd FIB. expect the imported
5644 * entries to be removed
5646 local_pfx.fp_len = 24;
5647 fib_table_entry_delete(import_fib_index2,
5650 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5651 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed");
5653 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5654 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2");
5655 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5656 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2");
5657 local_pfx.fp_len = 32;
5658 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5659 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2");
5661 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5662 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1");
5663 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5664 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1");
5665 local_pfx.fp_len = 32;
5666 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5667 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1");
5670 * modify the route in FIB1 so it is no longer attached. expect the imported
5671 * entries to be removed
5673 local_pfx.fp_len = 24;
5674 fib_table_entry_update_one_path(import_fib_index1,
5677 FIB_ENTRY_FLAG_NONE,
5679 &pfx_10_10_10_2_s_32.fp_addr,
5680 tm->hw[0]->sw_if_index,
5681 ~0, // invalid fib index
5684 FIB_ROUTE_PATH_FLAG_NONE);
5685 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5686 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5687 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5688 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5689 local_pfx.fp_len = 32;
5690 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5691 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5694 * modify it back to attached. expect the adj-fibs back
5696 local_pfx.fp_len = 24;
5697 fib_table_entry_update_one_path(import_fib_index1,
5700 FIB_ENTRY_FLAG_NONE,
5703 tm->hw[0]->sw_if_index,
5704 ~0, // invalid fib index
5707 FIB_ROUTE_PATH_FLAG_NONE);
5708 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5709 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1");
5710 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5711 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1");
5712 local_pfx.fp_len = 32;
5713 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5714 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1");
5717 * add a covering attached next-hop for the interface address, so we have
5718 * a valid adj to find when we check the forwarding tables
5720 fib_prefix_t pfx_10_0_0_0_s_8 = {
5722 .fp_proto = FIB_PROTOCOL_IP4,
5725 .ip4.as_u32 = clib_host_to_net_u32(0x0a000000),
5729 fei = fib_table_entry_update_one_path(fib_index,
5732 FIB_ENTRY_FLAG_NONE,
5734 &pfx_10_10_10_3_s_32.fp_addr,
5735 tm->hw[0]->sw_if_index,
5736 ~0, // invalid fib index
5739 FIB_ROUTE_PATH_FLAG_NONE);
5740 dpo = fib_entry_contribute_ip_forwarding(fei);
5743 * remove the route in the export fib. expect the adj-fibs to be removed
5745 local_pfx.fp_len = 24;
5746 fib_table_entry_delete(fib_index,
5748 FIB_SOURCE_INTERFACE);
5750 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5751 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1");
5752 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5753 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5754 local_pfx.fp_len = 32;
5755 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5756 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5759 * the adj-fibs in the export VRF are present in the FIB table,
5760 * but not installed in forwarding, since they have no attached cover.
5761 * Consequently a lookup in the MTRIE gives the adj for the covering
5764 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5765 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "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 \n%U not \n%U",
5771 format_load_balance, lbi, 0,
5772 format_dpo_id, dpo, 0);
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);
5776 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4);
5777 FIB_TEST(lbi == dpo->dpoi_index,
5778 "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0);
5781 * add the export prefix back, but not as attached.
5782 * No adj-fibs in export nor import tables
5784 local_pfx.fp_len = 24;
5785 fei = fib_table_entry_update_one_path(fib_index,
5788 FIB_ENTRY_FLAG_NONE,
5790 &pfx_10_10_10_1_s_32.fp_addr,
5791 tm->hw[0]->sw_if_index,
5792 ~0, // invalid fib index
5795 FIB_ROUTE_PATH_FLAG_NONE);
5796 dpo = fib_entry_contribute_ip_forwarding(fei);
5798 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5799 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export");
5800 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5801 FIB_TEST(lbi == dpo->dpoi_index,
5802 "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0);
5803 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5804 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5805 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5806 FIB_TEST(lbi == dpo->dpoi_index,
5807 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5809 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5810 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5811 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5812 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5813 local_pfx.fp_len = 32;
5814 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5815 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5818 * modify the export prefix so it is attached. expect all covereds to return
5820 local_pfx.fp_len = 24;
5821 fib_table_entry_update_one_path(fib_index,
5824 FIB_ENTRY_FLAG_NONE,
5827 tm->hw[0]->sw_if_index,
5828 ~0, // invalid fib index
5831 FIB_ROUTE_PATH_FLAG_NONE);
5833 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5834 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5835 dpo = fib_entry_contribute_ip_forwarding(fei);
5836 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5837 "Adj-fib1 is not drop in export");
5838 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5839 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5840 local_pfx.fp_len = 32;
5841 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5842 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5843 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5844 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5845 dpo = fib_entry_contribute_ip_forwarding(fei);
5846 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5847 "Adj-fib1 is not drop in export: %U %U",
5848 format_dpo_id, dpo, 0,
5849 format_dpo_id, load_balance_get_bucket(dpo->dpoi_index, 0), 0);
5850 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5851 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5852 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5853 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5854 local_pfx.fp_len = 32;
5855 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5856 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5859 * modify the export prefix so connected. no change.
5861 local_pfx.fp_len = 24;
5862 fib_table_entry_update_one_path(fib_index, &local_pfx,
5863 FIB_SOURCE_INTERFACE,
5864 (FIB_ENTRY_FLAG_CONNECTED |
5865 FIB_ENTRY_FLAG_ATTACHED),
5868 tm->hw[0]->sw_if_index,
5872 FIB_ROUTE_PATH_FLAG_NONE);
5874 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5875 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5876 dpo = fib_entry_contribute_ip_forwarding(fei);
5877 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5878 "Adj-fib1 is not drop in export");
5879 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5880 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5881 local_pfx.fp_len = 32;
5882 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5883 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5884 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5885 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5886 dpo = fib_entry_contribute_ip_forwarding(fei);
5887 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5888 "Adj-fib1 is not drop in export");
5889 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5890 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5891 local_pfx.fp_len = 32;
5892 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5893 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5898 fib_table_entry_delete(fib_index,
5901 fib_table_entry_delete(fib_index,
5902 &pfx_10_10_10_1_s_32,
5904 fib_table_entry_delete(fib_index,
5905 &pfx_10_10_10_2_s_32,
5907 local_pfx.fp_len = 32;
5908 fib_table_entry_delete(fib_index,
5910 FIB_SOURCE_INTERFACE);
5911 local_pfx.fp_len = 24;
5912 fib_table_entry_delete(fib_index,
5915 fib_table_entry_delete(fib_index,
5917 FIB_SOURCE_INTERFACE);
5918 local_pfx.fp_len = 24;
5919 fib_table_entry_delete(import_fib_index1,
5923 fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
5924 fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
5926 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5933 * Test Path Preference
5936 fib_test_pref (void)
5944 const fib_prefix_t pfx_1_1_1_1_s_32 = {
5946 .fp_proto = FIB_PROTOCOL_IP4,
5949 .as_u32 = clib_host_to_net_u32(0x01010101),
5954 for (i = 0; i <= 2; i++)
5955 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[i]->sw_if_index, 0);
5958 * 2 high, 2 medium and 2 low preference non-recursive paths
5960 fib_route_path_t nr_path_hi_1 = {
5961 .frp_proto = DPO_PROTO_IP4,
5962 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5963 .frp_fib_index = ~0,
5965 .frp_preference = 0,
5966 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5968 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5971 fib_route_path_t nr_path_hi_2 = {
5972 .frp_proto = DPO_PROTO_IP4,
5973 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5974 .frp_fib_index = ~0,
5976 .frp_preference = 0,
5977 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5979 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5982 fib_route_path_t nr_path_med_1 = {
5983 .frp_proto = DPO_PROTO_IP4,
5984 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5985 .frp_fib_index = ~0,
5987 .frp_preference = 1,
5988 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5990 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5993 fib_route_path_t nr_path_med_2 = {
5994 .frp_proto = DPO_PROTO_IP4,
5995 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5996 .frp_fib_index = ~0,
5998 .frp_preference = 1,
5999 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
6001 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
6004 fib_route_path_t nr_path_low_1 = {
6005 .frp_proto = DPO_PROTO_IP4,
6006 .frp_sw_if_index = tm->hw[2]->sw_if_index,
6007 .frp_fib_index = ~0,
6009 .frp_preference = 2,
6010 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
6012 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b01),
6015 fib_route_path_t nr_path_low_2 = {
6016 .frp_proto = DPO_PROTO_IP4,
6017 .frp_sw_if_index = tm->hw[2]->sw_if_index,
6018 .frp_fib_index = ~0,
6020 .frp_preference = 2,
6021 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
6023 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b02),
6026 fib_route_path_t *nr_paths = NULL;
6028 vec_add1(nr_paths, nr_path_hi_1);
6029 vec_add1(nr_paths, nr_path_hi_2);
6030 vec_add1(nr_paths, nr_path_med_1);
6031 vec_add1(nr_paths, nr_path_med_2);
6032 vec_add1(nr_paths, nr_path_low_1);
6033 vec_add1(nr_paths, nr_path_low_2);
6035 adj_index_t ai_hi_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6037 &nr_path_hi_1.frp_addr,
6038 nr_path_hi_1.frp_sw_if_index);
6039 adj_index_t ai_hi_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6041 &nr_path_hi_2.frp_addr,
6042 nr_path_hi_2.frp_sw_if_index);
6043 adj_index_t ai_med_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6045 &nr_path_med_1.frp_addr,
6046 nr_path_med_1.frp_sw_if_index);
6047 adj_index_t ai_med_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6049 &nr_path_med_2.frp_addr,
6050 nr_path_med_2.frp_sw_if_index);
6051 adj_index_t ai_low_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6053 &nr_path_low_1.frp_addr,
6054 nr_path_low_1.frp_sw_if_index);
6055 adj_index_t ai_low_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6057 &nr_path_low_2.frp_addr,
6058 nr_path_low_2.frp_sw_if_index);
6060 fib_test_lb_bucket_t ip_hi_1 = {
6066 fib_test_lb_bucket_t ip_hi_2 = {
6072 fib_test_lb_bucket_t ip_med_1 = {
6078 fib_test_lb_bucket_t ip_med_2 = {
6084 fib_test_lb_bucket_t ip_low_1 = {
6090 fib_test_lb_bucket_t ip_low_2 = {
6097 fib_node_index_t fei;
6099 fei = fib_table_entry_path_add2(0,
6102 FIB_ENTRY_FLAG_NONE,
6105 FIB_TEST(!fib_test_validate_entry(fei,
6106 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6110 "1.1.1.1/32 via high preference paths");
6113 * bring down the interface on which the high preference path lie
6115 vnet_sw_interface_set_flags(vnet_get_main(),
6116 tm->hw[0]->sw_if_index,
6119 FIB_TEST(!fib_test_validate_entry(fei,
6120 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6124 "1.1.1.1/32 via medium preference paths");
6127 * bring down the interface on which the medium preference path lie
6129 vnet_sw_interface_set_flags(vnet_get_main(),
6130 tm->hw[1]->sw_if_index,
6133 FIB_TEST(!fib_test_validate_entry(fei,
6134 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6138 "1.1.1.1/32 via low preference paths");
6141 * bring up the interface on which the high preference path lie
6143 vnet_sw_interface_set_flags(vnet_get_main(),
6144 tm->hw[0]->sw_if_index,
6145 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6147 FIB_TEST(!fib_test_validate_entry(fei,
6148 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6152 "1.1.1.1/32 via high preference paths");
6155 * bring up the interface on which the medium preference path lie
6157 vnet_sw_interface_set_flags(vnet_get_main(),
6158 tm->hw[1]->sw_if_index,
6159 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6161 FIB_TEST(!fib_test_validate_entry(fei,
6162 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6166 "1.1.1.1/32 via high preference paths");
6168 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
6169 fib_entry_contribute_forwarding(fei,
6170 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6174 * 3 recursive paths of different preference
6176 const fib_prefix_t pfx_1_1_1_2_s_32 = {
6178 .fp_proto = FIB_PROTOCOL_IP4,
6181 .as_u32 = clib_host_to_net_u32(0x01010102),
6185 const fib_prefix_t pfx_1_1_1_3_s_32 = {
6187 .fp_proto = FIB_PROTOCOL_IP4,
6190 .as_u32 = clib_host_to_net_u32(0x01010103),
6194 fei = fib_table_entry_path_add2(0,
6197 FIB_ENTRY_FLAG_NONE,
6199 dpo_id_t ip_1_1_1_2 = DPO_INVALID;
6200 fib_entry_contribute_forwarding(fei,
6201 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6203 fei = fib_table_entry_path_add2(0,
6206 FIB_ENTRY_FLAG_NONE,
6208 dpo_id_t ip_1_1_1_3 = DPO_INVALID;
6209 fib_entry_contribute_forwarding(fei,
6210 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6213 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
6216 .lb = ip_1_1_1_1.dpoi_index,
6219 fib_test_lb_bucket_t ip_o_1_1_1_2 = {
6222 .lb = ip_1_1_1_2.dpoi_index,
6225 fib_test_lb_bucket_t ip_o_1_1_1_3 = {
6228 .lb = ip_1_1_1_3.dpoi_index,
6231 fib_route_path_t r_path_hi = {
6232 .frp_proto = DPO_PROTO_IP4,
6233 .frp_sw_if_index = ~0,
6236 .frp_preference = 0,
6237 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
6238 .frp_addr = pfx_1_1_1_1_s_32.fp_addr,
6240 fib_route_path_t r_path_med = {
6241 .frp_proto = DPO_PROTO_IP4,
6242 .frp_sw_if_index = ~0,
6245 .frp_preference = 10,
6246 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
6247 .frp_addr = pfx_1_1_1_2_s_32.fp_addr,
6249 fib_route_path_t r_path_low = {
6250 .frp_proto = DPO_PROTO_IP4,
6251 .frp_sw_if_index = ~0,
6254 .frp_preference = 255,
6255 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
6256 .frp_addr = pfx_1_1_1_3_s_32.fp_addr,
6258 fib_route_path_t *r_paths = NULL;
6260 vec_add1(r_paths, r_path_hi);
6261 vec_add1(r_paths, r_path_low);
6262 vec_add1(r_paths, r_path_med);
6265 * add many recursive so we get the LB MAp created
6268 fib_prefix_t pfx_r[N_PFXS];
6269 unsigned int n_pfxs;
6270 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6272 pfx_r[n_pfxs].fp_len = 32;
6273 pfx_r[n_pfxs].fp_proto = FIB_PROTOCOL_IP4;
6274 pfx_r[n_pfxs].fp_addr.ip4.as_u32 =
6275 clib_host_to_net_u32(0x02000000 + n_pfxs);
6277 fei = fib_table_entry_path_add2(0,
6280 FIB_ENTRY_FLAG_NONE,
6283 FIB_TEST(!fib_test_validate_entry(fei,
6284 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6287 "recursive via high preference paths");
6290 * withdraw hig pref resolving entry
6292 fib_table_entry_delete(0,
6296 /* suspend so the update walk kicks int */
6297 vlib_process_suspend(vlib_get_main(), 1e-5);
6299 FIB_TEST(!fib_test_validate_entry(fei,
6300 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6303 "recursive via medium preference paths");
6306 * withdraw medium pref resolving entry
6308 fib_table_entry_delete(0,
6312 /* suspend so the update walk kicks int */
6313 vlib_process_suspend(vlib_get_main(), 1e-5);
6315 FIB_TEST(!fib_test_validate_entry(fei,
6316 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6319 "recursive via low preference paths");
6322 * add back paths for next iteration
6324 fei = fib_table_entry_update(0,
6327 FIB_ENTRY_FLAG_NONE,
6329 fei = fib_table_entry_update(0,
6332 FIB_ENTRY_FLAG_NONE,
6335 /* suspend so the update walk kicks int */
6336 vlib_process_suspend(vlib_get_main(), 1e-5);
6338 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6339 FIB_TEST(!fib_test_validate_entry(fei,
6340 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6343 "recursive via high preference paths");
6347 fib_table_entry_delete(0,
6351 /* suspend so the update walk kicks int */
6352 vlib_process_suspend(vlib_get_main(), 1e-5);
6354 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6356 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6358 FIB_TEST(!fib_test_validate_entry(fei,
6359 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6362 "recursive via medium preference paths");
6364 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6366 fib_table_entry_delete(0,
6374 fib_table_entry_delete(0,
6377 fib_table_entry_delete(0,
6381 dpo_reset(&ip_1_1_1_1);
6382 dpo_reset(&ip_1_1_1_2);
6383 dpo_reset(&ip_1_1_1_3);
6384 adj_unlock(ai_low_2);
6385 adj_unlock(ai_low_1);
6386 adj_unlock(ai_med_2);
6387 adj_unlock(ai_med_1);
6388 adj_unlock(ai_hi_2);
6389 adj_unlock(ai_hi_1);
6395 * Test the recursive route route handling for GRE tunnels
6398 fib_test_label (void)
6400 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;
6401 const u32 fib_index = 0;
6402 int lb_count, ii, res;
6406 lb_count = pool_elts(load_balance_pool);
6410 * add interface routes. We'll assume this works. It's more rigorously
6413 fib_prefix_t local0_pfx = {
6415 .fp_proto = FIB_PROTOCOL_IP4,
6419 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
6424 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6427 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[0]->sw_if_index, fib_index);
6429 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6430 FIB_SOURCE_INTERFACE,
6431 (FIB_ENTRY_FLAG_CONNECTED |
6432 FIB_ENTRY_FLAG_ATTACHED),
6435 tm->hw[0]->sw_if_index,
6439 FIB_ROUTE_PATH_FLAG_NONE);
6440 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6441 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6442 "attached interface route present");
6444 local0_pfx.fp_len = 32;
6445 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6446 FIB_SOURCE_INTERFACE,
6447 (FIB_ENTRY_FLAG_CONNECTED |
6448 FIB_ENTRY_FLAG_LOCAL),
6451 tm->hw[0]->sw_if_index,
6452 ~0, // invalid fib index
6455 FIB_ROUTE_PATH_FLAG_NONE);
6456 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6458 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6459 "local interface route present");
6461 fib_prefix_t local1_pfx = {
6463 .fp_proto = FIB_PROTOCOL_IP4,
6467 .as_u32 = clib_host_to_net_u32(0x0a0a0b0a),
6472 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[1]->sw_if_index, fib_index);
6474 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6475 FIB_SOURCE_INTERFACE,
6476 (FIB_ENTRY_FLAG_CONNECTED |
6477 FIB_ENTRY_FLAG_ATTACHED),
6480 tm->hw[1]->sw_if_index,
6484 FIB_ROUTE_PATH_FLAG_NONE);
6485 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6486 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6487 "attached interface route present");
6489 local1_pfx.fp_len = 32;
6490 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6491 FIB_SOURCE_INTERFACE,
6492 (FIB_ENTRY_FLAG_CONNECTED |
6493 FIB_ENTRY_FLAG_LOCAL),
6496 tm->hw[1]->sw_if_index,
6497 ~0, // invalid fib index
6500 FIB_ROUTE_PATH_FLAG_NONE);
6501 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6503 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6504 "local interface route present");
6506 ip46_address_t nh_10_10_10_1 = {
6508 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
6511 ip46_address_t nh_10_10_11_1 = {
6513 .as_u32 = clib_host_to_net_u32(0x0a0a0b01),
6516 ip46_address_t nh_10_10_11_2 = {
6518 .as_u32 = clib_host_to_net_u32(0x0a0a0b02),
6522 ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6525 tm->hw[1]->sw_if_index);
6526 ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6529 tm->hw[1]->sw_if_index);
6530 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6533 tm->hw[0]->sw_if_index);
6534 ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6537 tm->hw[1]->sw_if_index);
6538 ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6541 tm->hw[1]->sw_if_index);
6544 * Add an etry with one path with a real out-going label
6546 fib_prefix_t pfx_1_1_1_1_s_32 = {
6548 .fp_proto = FIB_PROTOCOL_IP4,
6550 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
6553 fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = {
6554 .type = FT_LB_LABEL_O_ADJ,
6556 .adj = ai_mpls_10_10_10_1,
6561 fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = {
6562 .type = FT_LB_LABEL_O_ADJ,
6564 .adj = ai_mpls_10_10_10_1,
6566 .eos = MPLS_NON_EOS,
6569 fib_mpls_label_t *l99 = NULL, fml99 = {
6572 vec_add1(l99, fml99);
6574 fib_table_entry_update_one_path(fib_index,
6577 FIB_ENTRY_FLAG_NONE,
6580 tm->hw[0]->sw_if_index,
6581 ~0, // invalid fib index
6584 FIB_ROUTE_PATH_FLAG_NONE);
6586 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6587 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created");
6589 FIB_TEST(!fib_test_validate_entry(fei,
6590 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6592 &l99_eos_o_10_10_10_1),
6593 "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1");
6596 * add a path with an implicit NULL label
6598 fib_test_lb_bucket_t a_o_10_10_11_1 = {
6601 .adj = ai_v4_10_10_11_1,
6604 fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = {
6607 .adj = ai_mpls_10_10_11_1,
6610 fib_mpls_label_t *l_imp_null = NULL, fml_imp_null = {
6611 .fml_value = MPLS_IETF_IMPLICIT_NULL_LABEL,
6613 vec_add1(l_imp_null, fml_imp_null);
6615 fei = fib_table_entry_path_add(fib_index,
6618 FIB_ENTRY_FLAG_NONE,
6621 tm->hw[1]->sw_if_index,
6622 ~0, // invalid fib index
6625 FIB_ROUTE_PATH_FLAG_NONE);
6627 FIB_TEST(!fib_test_validate_entry(fei,
6628 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6630 &l99_eos_o_10_10_10_1,
6632 "1.1.1.1/32 LB 2 buckets via: "
6633 "label 99 over 10.10.10.1, "
6634 "adj over 10.10.11.1");
6637 * assign the route a local label
6639 fib_table_entry_local_label_add(fib_index,
6643 fib_prefix_t pfx_24001_eos = {
6644 .fp_proto = FIB_PROTOCOL_MPLS,
6648 fib_prefix_t pfx_24001_neos = {
6649 .fp_proto = FIB_PROTOCOL_MPLS,
6651 .fp_eos = MPLS_NON_EOS,
6653 fib_test_lb_bucket_t disp_o_10_10_11_1 = {
6654 .type = FT_LB_MPLS_DISP_PIPE_O_ADJ,
6656 .adj = ai_v4_10_10_11_1,
6661 * The EOS entry should link to both the paths,
6662 * and use an ip adj for the imp-null
6663 * The NON-EOS entry should link to both the paths,
6664 * and use an mpls adj for the imp-null
6666 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6668 FIB_TEST(!fib_test_validate_entry(fei,
6669 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6671 &l99_eos_o_10_10_10_1,
6672 &disp_o_10_10_11_1),
6673 "24001/eos LB 2 buckets via: "
6674 "label 99 over 10.10.10.1, "
6675 "mpls disp adj over 10.10.11.1");
6678 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6680 FIB_TEST(!fib_test_validate_entry(fei,
6681 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6683 &l99_neos_o_10_10_10_1,
6684 &a_mpls_o_10_10_11_1),
6685 "24001/neos LB 1 bucket via: "
6686 "label 99 over 10.10.10.1 ",
6687 "mpls-adj via 10.10.11.1");
6690 * add an unlabelled path, this is excluded from the neos chains,
6692 fib_test_lb_bucket_t adj_o_10_10_11_2 = {
6695 .adj = ai_v4_10_10_11_2,
6698 fib_test_lb_bucket_t disp_o_10_10_11_2 = {
6699 .type = FT_LB_MPLS_DISP_PIPE_O_ADJ,
6701 .adj = ai_v4_10_10_11_2,
6706 fei = fib_table_entry_path_add(fib_index,
6709 FIB_ENTRY_FLAG_NONE,
6712 tm->hw[1]->sw_if_index,
6713 ~0, // invalid fib index
6716 FIB_ROUTE_PATH_FLAG_NONE);
6718 FIB_TEST(!fib_test_validate_entry(fei,
6719 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6720 16, // 3 choices spread over 16 buckets
6721 &l99_eos_o_10_10_10_1,
6722 &l99_eos_o_10_10_10_1,
6723 &l99_eos_o_10_10_10_1,
6724 &l99_eos_o_10_10_10_1,
6725 &l99_eos_o_10_10_10_1,
6726 &l99_eos_o_10_10_10_1,
6737 "1.1.1.1/32 LB 16 buckets via: "
6738 "label 99 over 10.10.10.1, "
6739 "adj over 10.10.11.1",
6740 "adj over 10.10.11.2");
6743 * get and lock a reference to the non-eos of the via entry 1.1.1.1/32
6745 dpo_id_t non_eos_1_1_1_1 = DPO_INVALID;
6746 fib_entry_contribute_forwarding(fei,
6747 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6751 * n-eos has only the 2 labelled paths
6753 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6756 FIB_TEST(!fib_test_validate_entry(fei,
6757 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6759 &l99_neos_o_10_10_10_1,
6760 &a_mpls_o_10_10_11_1),
6761 "24001/neos LB 2 buckets via: "
6762 "label 99 over 10.10.10.1, "
6763 "adj-mpls over 10.10.11.2");
6766 * A labelled recursive
6768 fib_prefix_t pfx_2_2_2_2_s_32 = {
6770 .fp_proto = FIB_PROTOCOL_IP4,
6772 .ip4.as_u32 = clib_host_to_net_u32(0x02020202),
6775 fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = {
6776 .type = FT_LB_LABEL_O_LB,
6778 .lb = non_eos_1_1_1_1.dpoi_index,
6781 .mode = FIB_MPLS_LSP_MODE_UNIFORM,
6784 fib_mpls_label_t *l1600 = NULL, fml1600 = {
6786 .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM,
6788 vec_add1(l1600, fml1600);
6790 fei = fib_table_entry_update_one_path(fib_index,
6793 FIB_ENTRY_FLAG_NONE,
6795 &pfx_1_1_1_1_s_32.fp_addr,
6800 FIB_ROUTE_PATH_FLAG_NONE);
6802 FIB_TEST(!fib_test_validate_entry(fei,
6803 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6805 &l1600_eos_o_1_1_1_1),
6806 "2.2.2.2.2/32 LB 1 buckets via: "
6807 "label 1600 over 1.1.1.1");
6809 dpo_id_t dpo_44 = DPO_INVALID;
6812 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
6813 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
6815 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
6816 "uRPF check for 2.2.2.2/32 on %d OK",
6817 tm->hw[0]->sw_if_index);
6818 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
6819 "uRPF check for 2.2.2.2/32 on %d OK",
6820 tm->hw[1]->sw_if_index);
6821 FIB_TEST(!fib_urpf_check(urpfi, 99),
6822 "uRPF check for 2.2.2.2/32 on 99 not-OK",
6825 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44);
6826 FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index),
6827 "Shared uRPF on IP and non-EOS chain");
6832 * we are holding a lock on the non-eos LB of the via-entry.
6833 * do a PIC-core failover by shutting the link of the via-entry.
6835 * shut down the link with the valid label
6837 vnet_sw_interface_set_flags(vnet_get_main(),
6838 tm->hw[0]->sw_if_index,
6841 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6842 FIB_TEST(!fib_test_validate_entry(fei,
6843 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6847 "1.1.1.1/32 LB 2 buckets via: "
6848 "adj over 10.10.11.1, ",
6849 "adj-v4 over 10.10.11.2");
6851 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6853 FIB_TEST(!fib_test_validate_entry(fei,
6854 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6857 &disp_o_10_10_11_2),
6858 "24001/eos LB 2 buckets via: "
6859 "mpls-disp adj over 10.10.11.1, ",
6860 "mpls-disp adj-v4 over 10.10.11.2");
6862 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6864 FIB_TEST(!fib_test_validate_entry(fei,
6865 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6867 &a_mpls_o_10_10_11_1),
6868 "24001/neos LB 1 buckets via: "
6869 "adj-mpls over 10.10.11.2");
6872 * test that the pre-failover load-balance has been in-place
6875 dpo_id_t current = DPO_INVALID;
6876 fib_entry_contribute_forwarding(fei,
6877 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6880 FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1,
6882 "PIC-core LB inplace modified %U %U",
6883 format_dpo_id, &non_eos_1_1_1_1, 0,
6884 format_dpo_id, ¤t, 0);
6886 dpo_reset(&non_eos_1_1_1_1);
6887 dpo_reset(¤t);
6890 * no-shut the link with the valid label
6892 vnet_sw_interface_set_flags(vnet_get_main(),
6893 tm->hw[0]->sw_if_index,
6894 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6896 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6897 FIB_TEST(!fib_test_validate_entry(fei,
6898 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6899 16, // 3 choices spread over 16 buckets
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,
6905 &l99_eos_o_10_10_10_1,
6916 "1.1.1.1/32 LB 16 buckets via: "
6917 "label 99 over 10.10.10.1, "
6918 "adj over 10.10.11.1",
6919 "adj-v4 over 10.10.11.2");
6922 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6924 FIB_TEST(!fib_test_validate_entry(fei,
6925 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6926 16, // 3 choices spread over 16 buckets
6927 &l99_eos_o_10_10_10_1,
6928 &l99_eos_o_10_10_10_1,
6929 &l99_eos_o_10_10_10_1,
6930 &l99_eos_o_10_10_10_1,
6931 &l99_eos_o_10_10_10_1,
6932 &l99_eos_o_10_10_10_1,
6942 &disp_o_10_10_11_2),
6943 "24001/eos LB 16 buckets via: "
6944 "label 99 over 10.10.10.1, "
6945 "MPLS disp adj over 10.10.11.1",
6946 "MPLS disp adj-v4 over 10.10.11.2");
6948 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6950 FIB_TEST(!fib_test_validate_entry(fei,
6951 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6953 &l99_neos_o_10_10_10_1,
6954 &a_mpls_o_10_10_11_1),
6955 "24001/neos LB 2 buckets via: "
6956 "label 99 over 10.10.10.1, "
6957 "adj-mpls over 10.10.11.2");
6960 * remove the first path with the valid label
6962 fib_table_entry_path_remove(fib_index,
6967 tm->hw[0]->sw_if_index,
6968 ~0, // invalid fib index
6970 FIB_ROUTE_PATH_FLAG_NONE);
6972 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6973 FIB_TEST(!fib_test_validate_entry(fei,
6974 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6978 "1.1.1.1/32 LB 2 buckets via: "
6979 "adj over 10.10.11.1, "
6980 "adj-v4 over 10.10.11.2");
6982 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6984 FIB_TEST(!fib_test_validate_entry(fei,
6985 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6988 &disp_o_10_10_11_2),
6989 "24001/eos LB 2 buckets via: "
6990 "MPLS disp adj over 10.10.11.1, "
6991 "MPLS disp adj-v4 over 10.10.11.2");
6993 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6996 FIB_TEST(!fib_test_validate_entry(fei,
6997 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6999 &a_mpls_o_10_10_11_1),
7000 "24001/neos LB 1 buckets via: "
7001 "adj-mpls over 10.10.11.2");
7004 * remove the other path with a valid label
7006 fib_test_lb_bucket_t bucket_drop = {
7009 fib_test_lb_bucket_t mpls_bucket_drop = {
7012 .adj = DPO_PROTO_MPLS,
7016 fib_table_entry_path_remove(fib_index,
7021 tm->hw[1]->sw_if_index,
7022 ~0, // invalid fib index
7024 FIB_ROUTE_PATH_FLAG_NONE);
7026 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
7027 FIB_TEST(!fib_test_validate_entry(fei,
7028 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7031 "1.1.1.1/32 LB 1 buckets via: "
7032 "adj over 10.10.11.2");
7034 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7036 FIB_TEST(!fib_test_validate_entry(fei,
7037 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7039 &disp_o_10_10_11_2),
7040 "24001/eos LB 1 buckets via: "
7041 "MPLS disp adj over 10.10.11.2");
7043 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7045 FIB_TEST(!fib_test_validate_entry(fei,
7046 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7049 "24001/neos LB 1 buckets via: DROP");
7052 * add back the path with the valid label
7055 vec_add1(l99, fml99);
7057 fib_table_entry_path_add(fib_index,
7060 FIB_ENTRY_FLAG_NONE,
7063 tm->hw[0]->sw_if_index,
7064 ~0, // invalid fib index
7067 FIB_ROUTE_PATH_FLAG_NONE);
7069 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
7070 FIB_TEST(!fib_test_validate_entry(fei,
7071 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7073 &l99_eos_o_10_10_10_1,
7075 "1.1.1.1/32 LB 2 buckets via: "
7076 "label 99 over 10.10.10.1, "
7077 "adj over 10.10.11.2");
7079 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7081 FIB_TEST(!fib_test_validate_entry(fei,
7082 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7084 &l99_eos_o_10_10_10_1,
7085 &disp_o_10_10_11_2),
7086 "24001/eos LB 2 buckets via: "
7087 "label 99 over 10.10.10.1, "
7088 "MPLS disp adj over 10.10.11.2");
7090 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7092 FIB_TEST(!fib_test_validate_entry(fei,
7093 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7095 &l99_neos_o_10_10_10_1),
7096 "24001/neos LB 1 buckets via: "
7097 "label 99 over 10.10.10.1");
7100 * change the local label
7102 fib_table_entry_local_label_add(fib_index,
7106 fib_prefix_t pfx_25005_eos = {
7107 .fp_proto = FIB_PROTOCOL_MPLS,
7111 fib_prefix_t pfx_25005_neos = {
7112 .fp_proto = FIB_PROTOCOL_MPLS,
7114 .fp_eos = MPLS_NON_EOS,
7117 FIB_TEST((FIB_NODE_INDEX_INVALID ==
7118 fib_table_lookup(fib_index, &pfx_24001_eos)),
7119 "24001/eos removed after label change");
7120 FIB_TEST((FIB_NODE_INDEX_INVALID ==
7121 fib_table_lookup(fib_index, &pfx_24001_neos)),
7122 "24001/eos removed after label change");
7124 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7126 FIB_TEST(!fib_test_validate_entry(fei,
7127 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7129 &l99_eos_o_10_10_10_1,
7130 &disp_o_10_10_11_2),
7131 "25005/eos LB 2 buckets via: "
7132 "label 99 over 10.10.10.1, "
7133 "MPLS disp adj over 10.10.11.2");
7135 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7137 FIB_TEST(!fib_test_validate_entry(fei,
7138 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7140 &l99_neos_o_10_10_10_1),
7141 "25005/neos LB 1 buckets via: "
7142 "label 99 over 10.10.10.1");
7145 * remove the local label.
7146 * the check that the MPLS entries are gone is done by the fact the
7147 * MPLS table is no longer present.
7149 fib_table_entry_local_label_remove(fib_index,
7153 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
7154 FIB_TEST(!fib_test_validate_entry(fei,
7155 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7157 &l99_eos_o_10_10_10_1,
7159 "24001/eos LB 2 buckets via: "
7160 "label 99 over 10.10.10.1, "
7161 "adj over 10.10.11.2");
7163 FIB_TEST((FIB_NODE_INDEX_INVALID ==
7164 mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)),
7165 "No more MPLS FIB entries => table removed");
7168 * add another via-entry for the recursive
7170 fib_prefix_t pfx_1_1_1_2_s_32 = {
7172 .fp_proto = FIB_PROTOCOL_IP4,
7174 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
7177 fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = {
7178 .type = FT_LB_LABEL_O_ADJ,
7180 .adj = ai_mpls_10_10_10_1,
7185 fib_mpls_label_t *l101 = NULL, fml101 = {
7188 vec_add1(l101, fml101);
7190 fei = fib_table_entry_update_one_path(fib_index,
7193 FIB_ENTRY_FLAG_NONE,
7196 tm->hw[0]->sw_if_index,
7197 ~0, // invalid fib index
7200 FIB_ROUTE_PATH_FLAG_NONE);
7202 FIB_TEST(!fib_test_validate_entry(fei,
7203 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7205 &l101_eos_o_10_10_10_1),
7206 "1.1.1.2/32 LB 1 buckets via: "
7207 "label 101 over 10.10.10.1");
7209 dpo_id_t non_eos_1_1_1_2 = DPO_INVALID;
7210 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7212 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7214 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7216 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7219 fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = {
7220 .type = FT_LB_LABEL_O_LB,
7222 .lb = non_eos_1_1_1_2.dpoi_index,
7227 fib_mpls_label_t *l1601 = NULL, fml1601 = {
7230 vec_add1(l1601, fml1601);
7232 l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index;
7234 fei = fib_table_entry_path_add(fib_index,
7237 FIB_ENTRY_FLAG_NONE,
7239 &pfx_1_1_1_2_s_32.fp_addr,
7244 FIB_ROUTE_PATH_FLAG_NONE);
7246 FIB_TEST(!fib_test_validate_entry(fei,
7247 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7249 &l1600_eos_o_1_1_1_1,
7250 &l1601_eos_o_1_1_1_2),
7251 "2.2.2.2/32 LB 2 buckets via: "
7252 "label 1600 via 1.1,1.1, "
7253 "label 16001 via 1.1.1.2");
7256 * update the via-entry so it no longer has an imp-null path.
7257 * the LB for the recursive can use an imp-null
7260 vec_add1(l_imp_null, fml_imp_null);
7262 fei = fib_table_entry_update_one_path(fib_index,
7265 FIB_ENTRY_FLAG_NONE,
7268 tm->hw[1]->sw_if_index,
7269 ~0, // invalid fib index
7272 FIB_ROUTE_PATH_FLAG_NONE);
7274 FIB_TEST(!fib_test_validate_entry(fei,
7275 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7278 "1.1.1.2/32 LB 1 buckets via: "
7281 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7282 FIB_TEST(!fib_test_validate_entry(fei,
7283 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7285 &l1600_eos_o_1_1_1_1,
7286 &l1601_eos_o_1_1_1_2),
7287 "2.2.2.2/32 LB 2 buckets via: "
7288 "label 1600 via 1.1,1.1, "
7289 "label 16001 via 1.1.1.2");
7292 * update the via-entry so it no longer has labelled paths.
7293 * the LB for the recursive should exclue this via form its LB
7295 fei = fib_table_entry_update_one_path(fib_index,
7298 FIB_ENTRY_FLAG_NONE,
7301 tm->hw[1]->sw_if_index,
7302 ~0, // invalid fib index
7305 FIB_ROUTE_PATH_FLAG_NONE);
7307 FIB_TEST(!fib_test_validate_entry(fei,
7308 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7311 "1.1.1.2/32 LB 1 buckets via: "
7314 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7315 FIB_TEST(!fib_test_validate_entry(fei,
7316 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7318 &l1600_eos_o_1_1_1_1),
7319 "2.2.2.2/32 LB 1 buckets via: "
7320 "label 1600 via 1.1,1.1");
7322 dpo_reset(&non_eos_1_1_1_1);
7323 dpo_reset(&non_eos_1_1_1_2);
7326 * Add a recursive with no out-labels. We expect to use the IP of the via
7328 fib_prefix_t pfx_2_2_2_3_s_32 = {
7330 .fp_proto = FIB_PROTOCOL_IP4,
7332 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
7335 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
7337 fib_table_entry_update_one_path(fib_index,
7340 FIB_ENTRY_FLAG_NONE,
7342 &pfx_1_1_1_1_s_32.fp_addr,
7347 FIB_ROUTE_PATH_FLAG_NONE);
7349 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7351 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7354 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
7357 .lb = ip_1_1_1_1.dpoi_index,
7361 fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
7362 FIB_TEST(!fib_test_validate_entry(fei,
7363 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7366 "2.2.2.2.3/32 LB 1 buckets via: "
7370 * Add a recursive with an imp-null out-label.
7371 * We expect to use the IP of the via
7373 fib_prefix_t pfx_2_2_2_4_s_32 = {
7375 .fp_proto = FIB_PROTOCOL_IP4,
7377 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
7381 fib_table_entry_update_one_path(fib_index,
7384 FIB_ENTRY_FLAG_NONE,
7386 &pfx_1_1_1_1_s_32.fp_addr,
7391 FIB_ROUTE_PATH_FLAG_NONE);
7393 fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
7394 FIB_TEST(!fib_test_validate_entry(fei,
7395 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7398 "2.2.2.2.4/32 LB 1 buckets via: "
7401 dpo_reset(&ip_1_1_1_1);
7404 * Create an entry with a deep label stack
7406 fib_prefix_t pfx_2_2_5_5_s_32 = {
7408 .fp_proto = FIB_PROTOCOL_IP4,
7410 .ip4.as_u32 = clib_host_to_net_u32(0x02020505),
7413 fib_test_lb_bucket_t ls_eos_o_10_10_10_1 = {
7414 .type = FT_LB_LABEL_STACK_O_ADJ,
7415 .label_stack_o_adj = {
7416 .adj = ai_mpls_10_10_11_1,
7417 .label_stack_size = 8,
7419 200, 201, 202, 203, 204, 205, 206, 207
7424 fib_mpls_label_t *label_stack = NULL;
7425 vec_validate(label_stack, 7);
7426 for (ii = 0; ii < 8; ii++)
7428 label_stack[ii].fml_value = ii + 200;
7431 fei = fib_table_entry_update_one_path(fib_index,
7434 FIB_ENTRY_FLAG_NONE,
7437 tm->hw[1]->sw_if_index,
7438 ~0, // invalid fib index
7441 FIB_ROUTE_PATH_FLAG_NONE);
7443 FIB_TEST(!fib_test_validate_entry(fei,
7444 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7446 &ls_eos_o_10_10_10_1),
7447 "2.2.5.5/32 LB 1 buckets via: "
7449 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
7452 * A prefix with outgoing labels. We'll RR source a /32 it covers
7453 * and test that the RR source picks up the out-going labels
7455 fib_prefix_t pfx_100_s_8 = {
7457 .fp_proto = FIB_PROTOCOL_IP4,
7459 .ip4.as_u32 = clib_host_to_net_u32(0x64000000),
7462 fib_test_lb_bucket_t l_100_eos_o_10_10_10_1 = {
7463 .type = FT_LB_LABEL_O_ADJ,
7465 .adj = ai_mpls_10_10_11_1,
7470 fib_mpls_label_t *l1602 = NULL, fml1602 = {
7473 vec_add1(l1602, fml1602);
7474 fei = fib_table_entry_update_one_path(fib_index,
7477 FIB_ENTRY_FLAG_NONE,
7480 tm->hw[1]->sw_if_index,
7481 ~0, // invalid fib index
7484 FIB_ROUTE_PATH_FLAG_NONE);
7486 FIB_TEST(!fib_test_validate_entry(fei,
7487 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7489 &l_100_eos_o_10_10_10_1),
7490 "100.0.0.0/8 LB 1 buckets via: lbl 101 "
7493 fib_prefix_t pfx_100_1_1_1_s_32 = {
7495 .fp_proto = FIB_PROTOCOL_IP4,
7497 .ip4.as_u32 = clib_host_to_net_u32(0x64010101),
7501 fei = fib_table_entry_special_add(fib_index,
7502 &pfx_100_1_1_1_s_32,
7504 FIB_ENTRY_FLAG_NONE);
7506 FIB_TEST(!fib_test_validate_entry(fei,
7507 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7509 &l_100_eos_o_10_10_10_1),
7510 "100.1.1.1/32 LB 1 buckets via: "
7513 fib_table_entry_delete(fib_index,
7516 fib_table_entry_delete_index(fei, FIB_SOURCE_RR);
7521 fib_table_entry_delete(fib_index,
7525 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7526 FIB_TEST(!fib_test_validate_entry(fei,
7527 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7529 &l1600_eos_o_1_1_1_1),
7530 "2.2.2.2/32 LB 1 buckets via: "
7531 "label 1600 via 1.1,1.1");
7533 fib_table_entry_delete(fib_index,
7537 FIB_TEST(!fib_test_validate_entry(fei,
7538 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7541 "2.2.2.2/32 LB 1 buckets via: DROP");
7543 fib_table_entry_delete(fib_index,
7546 fib_table_entry_delete(fib_index,
7549 fib_table_entry_delete(fib_index,
7553 adj_unlock(ai_mpls_10_10_10_1);
7554 adj_unlock(ai_mpls_10_10_11_2);
7555 adj_unlock(ai_v4_10_10_11_1);
7556 adj_unlock(ai_v4_10_10_11_2);
7557 adj_unlock(ai_mpls_10_10_11_1);
7559 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
7562 local0_pfx.fp_len = 32;
7563 fib_table_entry_delete(fib_index,
7565 FIB_SOURCE_INTERFACE);
7566 local0_pfx.fp_len = 24;
7567 fib_table_entry_delete(fib_index,
7569 FIB_SOURCE_INTERFACE);
7570 local1_pfx.fp_len = 32;
7571 fib_table_entry_delete(fib_index,
7573 FIB_SOURCE_INTERFACE);
7574 local1_pfx.fp_len = 24;
7575 fib_table_entry_delete(fib_index,
7577 FIB_SOURCE_INTERFACE);
7580 * +1 for the drop LB in the MPLS tables.
7582 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
7583 "Load-balance resources freed %d of %d",
7584 lb_count+1, pool_elts(load_balance_pool));
7589 #define N_TEST_CHILDREN 4
7590 #define PARENT_INDEX 0
7592 typedef struct fib_node_test_t_
7597 fib_node_back_walk_ctx_t *ctxs;
7601 static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1];
7603 #define PARENT() (&fib_test_nodes[PARENT_INDEX].node)
7605 #define FOR_EACH_TEST_CHILD(_tc) \
7606 for (ii = 1, (_tc) = &fib_test_nodes[1]; \
7607 ii < N_TEST_CHILDREN+1; \
7608 ii++, (_tc) = &fib_test_nodes[ii])
7611 fib_test_child_get_node (fib_node_index_t index)
7613 return (&fib_test_nodes[index].node);
7616 static int fib_test_walk_spawns_walks;
7617 static fib_node_type_t test_node_type;
7619 static fib_node_back_walk_rc_t
7620 fib_test_child_back_walk_notify (fib_node_t *node,
7621 fib_node_back_walk_ctx_t *ctx)
7623 fib_node_test_t *tc = (fib_node_test_t*) node;
7625 vec_add1(tc->ctxs, *ctx);
7627 if (1 == fib_test_walk_spawns_walks)
7628 fib_walk_sync(test_node_type, tc->index, ctx);
7629 if (2 == fib_test_walk_spawns_walks)
7630 fib_walk_async(test_node_type, tc->index,
7631 FIB_WALK_PRIORITY_HIGH, ctx);
7633 return (FIB_NODE_BACK_WALK_CONTINUE);
7637 fib_test_child_last_lock_gone (fib_node_t *node)
7639 fib_node_test_t *tc = (fib_node_test_t *)node;
7645 * The FIB walk's graph node virtual function table
7647 static const fib_node_vft_t fib_test_child_vft = {
7648 .fnv_get = fib_test_child_get_node,
7649 .fnv_last_lock = fib_test_child_last_lock_gone,
7650 .fnv_back_walk = fib_test_child_back_walk_notify,
7654 * the function (that should have been static but isn't so I can do this)
7655 * that processes the walk from the async queue,
7657 f64 fib_walk_process_queues(vlib_main_t * vm,
7659 u32 fib_walk_queue_get_size(fib_walk_priority_t prio);
7662 fib_test_walk (void)
7664 fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {};
7665 fib_node_test_t *tc;
7670 vm = vlib_get_main();
7671 test_node_type = fib_node_register_new_type("fib-test", &fib_test_child_vft);
7674 * init a fake node on which we will add children
7676 fib_node_init(&fib_test_nodes[PARENT_INDEX].node,
7679 FOR_EACH_TEST_CHILD(tc)
7681 fib_node_init(&tc->node, test_node_type);
7682 fib_node_lock(&tc->node);
7685 tc->sibling = fib_node_child_add(test_node_type,
7687 test_node_type, ii);
7691 * enqueue a walk across the parents children.
7693 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7695 fib_walk_async(test_node_type, PARENT_INDEX,
7696 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7697 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7698 "Parent has %d children pre-walk",
7699 fib_node_list_get_size(PARENT()->fn_children));
7702 * give the walk a large amount of time so it gets to the end
7704 fib_walk_process_queues(vm, 1);
7706 FOR_EACH_TEST_CHILD(tc)
7708 FIB_TEST(1 == vec_len(tc->ctxs),
7709 "%d child visitsed %d times",
7710 ii, vec_len(tc->ctxs));
7713 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7714 "Queue is empty post walk");
7715 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7716 "Parent has %d children post walk",
7717 fib_node_list_get_size(PARENT()->fn_children));
7720 * walk again. should be no increase in the number of visits, since
7721 * the walk will have terminated.
7723 fib_walk_process_queues(vm, 1);
7725 FOR_EACH_TEST_CHILD(tc)
7727 FIB_TEST(0 == vec_len(tc->ctxs),
7728 "%d child visitsed %d times",
7729 ii, vec_len(tc->ctxs));
7733 * schedule a low and hig priority walk. expect the high to be performed
7735 * schedule the high prio walk first so that it is further from the head
7736 * of the dependency list. that way it won't merge with the low one.
7738 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7739 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7741 fib_walk_async(test_node_type, PARENT_INDEX,
7742 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7743 fib_walk_async(test_node_type, PARENT_INDEX,
7744 FIB_WALK_PRIORITY_LOW, &low_ctx);
7746 fib_walk_process_queues(vm, 1);
7748 FOR_EACH_TEST_CHILD(tc)
7750 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7751 "%d child visitsed by high prio walk", ii);
7752 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7753 "%d child visitsed by low prio walk", ii);
7756 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7757 "Queue is empty post prio walk");
7758 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7759 "Parent has %d children post prio walk",
7760 fib_node_list_get_size(PARENT()->fn_children));
7763 * schedule 2 walks of the same priority that can be megred.
7764 * expect that each child is thus visited only once.
7766 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7767 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7769 fib_walk_async(test_node_type, PARENT_INDEX,
7770 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7771 fib_walk_async(test_node_type, PARENT_INDEX,
7772 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7774 fib_walk_process_queues(vm, 1);
7776 FOR_EACH_TEST_CHILD(tc)
7778 FIB_TEST(1 == vec_len(tc->ctxs),
7779 "%d child visitsed %d times during merge walk",
7780 ii, vec_len(tc->ctxs));
7783 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7784 "Queue is empty post merge walk");
7785 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7786 "Parent has %d children post merge walk",
7787 fib_node_list_get_size(PARENT()->fn_children));
7790 * schedule 2 walks of the same priority that cannot be megred.
7791 * expect that each child is thus visited twice and in the order
7792 * in which the walks were scheduled.
7794 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7795 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7797 fib_walk_async(test_node_type, PARENT_INDEX,
7798 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7799 fib_walk_async(test_node_type, PARENT_INDEX,
7800 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7802 fib_walk_process_queues(vm, 1);
7804 FOR_EACH_TEST_CHILD(tc)
7806 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7807 "%d child visitsed by high prio walk", ii);
7808 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7809 "%d child visitsed by low prio walk", ii);
7812 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7813 "Queue is empty post no-merge walk");
7814 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7815 "Parent has %d children post no-merge walk",
7816 fib_node_list_get_size(PARENT()->fn_children));
7819 * schedule a walk that makes one one child progress.
7820 * we do this by giving the queue draining process zero
7821 * time quanta. it's a do..while loop, so it does something.
7823 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7825 fib_walk_async(test_node_type, PARENT_INDEX,
7826 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7827 fib_walk_process_queues(vm, 0);
7829 FOR_EACH_TEST_CHILD(tc)
7831 if (ii == N_TEST_CHILDREN)
7833 FIB_TEST(1 == vec_len(tc->ctxs),
7834 "%d child visitsed %d times in zero quanta walk",
7835 ii, vec_len(tc->ctxs));
7839 FIB_TEST(0 == vec_len(tc->ctxs),
7840 "%d child visitsed %d times in 0 quanta walk",
7841 ii, vec_len(tc->ctxs));
7844 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7845 "Queue is not empty post zero quanta walk");
7846 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7847 "Parent has %d children post zero qunta walk",
7848 fib_node_list_get_size(PARENT()->fn_children));
7853 fib_walk_process_queues(vm, 0);
7855 FOR_EACH_TEST_CHILD(tc)
7857 if (ii >= N_TEST_CHILDREN-1)
7859 FIB_TEST(1 == vec_len(tc->ctxs),
7860 "%d child visitsed %d times in 2nd zero quanta walk",
7861 ii, vec_len(tc->ctxs));
7865 FIB_TEST(0 == vec_len(tc->ctxs),
7866 "%d child visitsed %d times in 2nd 0 quanta walk",
7867 ii, vec_len(tc->ctxs));
7870 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7871 "Queue is not empty post zero quanta walk");
7872 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7873 "Parent has %d children post zero qunta walk",
7874 fib_node_list_get_size(PARENT()->fn_children));
7877 * schedule another walk that will catch-up and merge.
7879 fib_walk_async(test_node_type, PARENT_INDEX,
7880 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7881 fib_walk_process_queues(vm, 1);
7883 FOR_EACH_TEST_CHILD(tc)
7885 if (ii >= N_TEST_CHILDREN-1)
7887 FIB_TEST(2 == vec_len(tc->ctxs),
7888 "%d child visitsed %d times in 2nd zero quanta merge walk",
7889 ii, vec_len(tc->ctxs));
7894 FIB_TEST(1 == vec_len(tc->ctxs),
7895 "%d child visitsed %d times in 2nd 0 quanta merge walk",
7896 ii, vec_len(tc->ctxs));
7900 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7901 "Queue is not empty post 2nd zero quanta merge walk");
7902 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7903 "Parent has %d children post 2nd zero qunta merge walk",
7904 fib_node_list_get_size(PARENT()->fn_children));
7907 * park a async walk in the middle of the list, then have an sync walk catch
7908 * it. same expectations as async catches async.
7910 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7912 fib_walk_async(test_node_type, PARENT_INDEX,
7913 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7915 fib_walk_process_queues(vm, 0);
7916 fib_walk_process_queues(vm, 0);
7918 fib_walk_sync(test_node_type, PARENT_INDEX, &high_ctx);
7920 FOR_EACH_TEST_CHILD(tc)
7922 if (ii >= N_TEST_CHILDREN-1)
7924 FIB_TEST(2 == vec_len(tc->ctxs),
7925 "%d child visitsed %d times in sync catches async walk",
7926 ii, vec_len(tc->ctxs));
7931 FIB_TEST(1 == vec_len(tc->ctxs),
7932 "%d child visitsed %d times in sync catches async walk",
7933 ii, vec_len(tc->ctxs));
7937 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7938 "Queue is not empty post 2nd zero quanta merge walk");
7939 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7940 "Parent has %d children post 2nd zero qunta merge walk",
7941 fib_node_list_get_size(PARENT()->fn_children));
7944 * make the parent a child of one of its children, thus inducing a routing loop.
7946 fib_test_nodes[PARENT_INDEX].sibling =
7947 fib_node_child_add(test_node_type,
7948 1, // the first child
7953 * execute a sync walk from the parent. each child visited spawns more sync
7954 * walks. we expect the walk to terminate.
7956 fib_test_walk_spawns_walks = 1;
7958 fib_walk_sync(test_node_type, PARENT_INDEX, &high_ctx);
7960 FOR_EACH_TEST_CHILD(tc)
7963 * child 1 - which is last in the list - has the loop.
7964 * the other children a re thus visitsed first. the we meet
7965 * child 1. we go round the loop again, visting the other children.
7966 * then we meet the walk in the dep list and bail. child 1 is not visitsed
7971 FIB_TEST(1 == vec_len(tc->ctxs),
7972 "child %d visitsed %d times during looped sync walk",
7973 ii, vec_len(tc->ctxs));
7977 FIB_TEST(2 == vec_len(tc->ctxs),
7978 "child %d visitsed %d times during looped sync walk",
7979 ii, vec_len(tc->ctxs));
7983 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7984 "Parent has %d children post sync loop walk",
7985 fib_node_list_get_size(PARENT()->fn_children));
7988 * the walk doesn't reach the max depth because the infra knows that sync
7989 * meets sync implies a loop and bails early.
7991 FIB_TEST(high_ctx.fnbw_depth == 9,
7992 "Walk context depth %d post sync loop walk",
7993 high_ctx.fnbw_depth);
7996 * execute an async walk of the graph loop, with each child spawns sync walks
7998 high_ctx.fnbw_depth = 0;
7999 fib_walk_async(test_node_type, PARENT_INDEX,
8000 FIB_WALK_PRIORITY_HIGH, &high_ctx);
8002 fib_walk_process_queues(vm, 1);
8004 FOR_EACH_TEST_CHILD(tc)
8007 * we don't really care how many times the children are visited, as long as
8008 * it is more than once.
8010 FIB_TEST(1 <= vec_len(tc->ctxs),
8011 "child %d visitsed %d times during looped aync spawns sync walk",
8012 ii, vec_len(tc->ctxs));
8017 * execute an async walk of the graph loop, with each child spawns async walks
8019 fib_test_walk_spawns_walks = 2;
8020 high_ctx.fnbw_depth = 0;
8021 fib_walk_async(test_node_type, PARENT_INDEX,
8022 FIB_WALK_PRIORITY_HIGH, &high_ctx);
8024 fib_walk_process_queues(vm, 1);
8026 FOR_EACH_TEST_CHILD(tc)
8029 * we don't really care how many times the children are visited, as long as
8030 * it is more than once.
8032 FIB_TEST(1 <= vec_len(tc->ctxs),
8033 "child %d visitsed %d times during looped async spawns async walk",
8034 ii, vec_len(tc->ctxs));
8039 fib_node_child_remove(test_node_type,
8040 1, // the first child
8041 fib_test_nodes[PARENT_INDEX].sibling);
8046 FOR_EACH_TEST_CHILD(tc)
8048 fib_node_child_remove(test_node_type, PARENT_INDEX,
8050 fib_node_deinit(&tc->node);
8051 fib_node_unlock(&tc->node);
8053 fib_node_deinit(PARENT());
8056 * The parent will be destroyed when the last lock on it goes.
8057 * this test ensures all the walk objects are unlocking it.
8059 FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed),
8060 "Parent was destroyed");
8066 * declaration of the otherwise static callback functions
8068 void fib_bfd_notify (bfd_listen_event_e event,
8069 const bfd_session_t *session);
8070 void adj_bfd_notify (bfd_listen_event_e event,
8071 const bfd_session_t *session);
8074 * Test BFD session interaction with FIB
8079 fib_node_index_t fei;
8084 /* via 10.10.10.1 */
8085 ip46_address_t nh_10_10_10_1 = {
8086 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
8088 /* via 10.10.10.2 */
8089 ip46_address_t nh_10_10_10_2 = {
8090 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
8092 /* via 10.10.10.10 */
8093 ip46_address_t nh_10_10_10_10 = {
8094 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
8096 n_feis = fib_entry_pool_size();
8101 * add interface routes. we'll assume this works. it's tested elsewhere
8103 fib_prefix_t pfx_10_10_10_10_s_24 = {
8105 .fp_proto = FIB_PROTOCOL_IP4,
8106 .fp_addr = nh_10_10_10_10,
8109 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_24,
8110 FIB_SOURCE_INTERFACE,
8111 (FIB_ENTRY_FLAG_CONNECTED |
8112 FIB_ENTRY_FLAG_ATTACHED),
8115 tm->hw[0]->sw_if_index,
8116 ~0, // invalid fib index
8119 FIB_ROUTE_PATH_FLAG_NONE);
8121 fib_prefix_t pfx_10_10_10_10_s_32 = {
8123 .fp_proto = FIB_PROTOCOL_IP4,
8124 .fp_addr = nh_10_10_10_10,
8126 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_32,
8127 FIB_SOURCE_INTERFACE,
8128 (FIB_ENTRY_FLAG_CONNECTED |
8129 FIB_ENTRY_FLAG_LOCAL),
8132 tm->hw[0]->sw_if_index,
8133 ~0, // invalid fib index
8136 FIB_ROUTE_PATH_FLAG_NONE);
8139 * A BFD session via a neighbour we do not yet know
8141 bfd_session_t bfd_10_10_10_1 = {
8145 .peer_addr = nh_10_10_10_1,
8148 .hop_type = BFD_HOP_TYPE_MULTI,
8149 .local_state = BFD_STATE_init,
8152 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8155 * A new entry will be created that forwards via the adj
8157 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8160 tm->hw[0]->sw_if_index);
8161 fib_prefix_t pfx_10_10_10_1_s_32 = {
8162 .fp_addr = nh_10_10_10_1,
8164 .fp_proto = FIB_PROTOCOL_IP4,
8166 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
8169 .adj = ai_10_10_10_1,
8173 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
8174 FIB_TEST(!fib_test_validate_entry(fei,
8175 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8178 "BFD sourced %U via %U",
8179 format_fib_prefix, &pfx_10_10_10_1_s_32,
8180 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
8183 * Delete the BFD session. Expect the fib_entry to be removed
8185 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8187 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
8188 FIB_TEST(FIB_NODE_INDEX_INVALID == fei,
8189 "BFD sourced %U removed",
8190 format_fib_prefix, &pfx_10_10_10_1_s_32);
8193 * Add the BFD source back
8195 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8198 * source the entry via the ADJ fib
8200 fei = fib_table_entry_path_add(0,
8201 &pfx_10_10_10_1_s_32,
8203 FIB_ENTRY_FLAG_ATTACHED,
8206 tm->hw[0]->sw_if_index,
8207 ~0, // invalid fib index
8210 FIB_ROUTE_PATH_FLAG_NONE);
8213 * Delete the BFD session. Expect the fib_entry to remain
8215 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8217 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
8218 FIB_TEST(!fib_test_validate_entry(fei,
8219 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8222 "BFD sourced %U remains via %U",
8223 format_fib_prefix, &pfx_10_10_10_1_s_32,
8224 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
8227 * Add the BFD source back
8229 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8232 * Create another ADJ FIB
8234 fib_prefix_t pfx_10_10_10_2_s_32 = {
8235 .fp_addr = nh_10_10_10_2,
8237 .fp_proto = FIB_PROTOCOL_IP4,
8239 fib_table_entry_path_add(0,
8240 &pfx_10_10_10_2_s_32,
8242 FIB_ENTRY_FLAG_ATTACHED,
8245 tm->hw[0]->sw_if_index,
8246 ~0, // invalid fib index
8249 FIB_ROUTE_PATH_FLAG_NONE);
8251 * A BFD session for the new ADJ FIB
8253 bfd_session_t bfd_10_10_10_2 = {
8257 .peer_addr = nh_10_10_10_2,
8260 .hop_type = BFD_HOP_TYPE_MULTI,
8261 .local_state = BFD_STATE_init,
8264 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_2);
8267 * remove the adj-fib source whilst the session is present
8270 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
8271 fib_table_entry_path_add(0,
8272 &pfx_10_10_10_2_s_32,
8274 FIB_ENTRY_FLAG_ATTACHED,
8277 tm->hw[0]->sw_if_index,
8278 ~0, // invalid fib index
8281 FIB_ROUTE_PATH_FLAG_NONE);
8284 * Before adding a recursive via the BFD tracked ADJ-FIBs,
8285 * bring one of the sessions UP, leave the other down
8287 bfd_10_10_10_1.local_state = BFD_STATE_up;
8288 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8289 bfd_10_10_10_2.local_state = BFD_STATE_down;
8290 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8293 * A recursive prefix via both of the ADJ FIBs
8295 fib_prefix_t pfx_200_0_0_0_s_24 = {
8296 .fp_proto = FIB_PROTOCOL_IP4,
8299 .ip4.as_u32 = clib_host_to_net_u32(0xc8000000),
8302 const dpo_id_t *dpo_10_10_10_1, *dpo_10_10_10_2;
8305 fib_entry_contribute_ip_forwarding(
8306 fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32));
8308 fib_entry_contribute_ip_forwarding(
8309 fib_table_lookup_exact_match(0, &pfx_10_10_10_2_s_32));
8311 fib_test_lb_bucket_t lb_o_10_10_10_1 = {
8314 .lb = dpo_10_10_10_1->dpoi_index,
8317 fib_test_lb_bucket_t lb_o_10_10_10_2 = {
8320 .lb = dpo_10_10_10_2->dpoi_index,
8325 * A prefix via the adj-fib that is BFD down => DROP
8327 fei = fib_table_entry_path_add(0,
8328 &pfx_200_0_0_0_s_24,
8330 FIB_ENTRY_FLAG_NONE,
8334 0, // default fib index
8337 FIB_ROUTE_PATH_FLAG_NONE);
8338 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8339 "%U resolves via drop",
8340 format_fib_prefix, &pfx_200_0_0_0_s_24);
8343 * add a path via the UP BFD adj-fib.
8344 * we expect that the DOWN BFD ADJ FIB is not used.
8346 fei = fib_table_entry_path_add(0,
8347 &pfx_200_0_0_0_s_24,
8349 FIB_ENTRY_FLAG_NONE,
8353 0, // default fib index
8356 FIB_ROUTE_PATH_FLAG_NONE);
8358 FIB_TEST(!fib_test_validate_entry(fei,
8359 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8362 "Recursive %U only UP BFD adj-fibs",
8363 format_fib_prefix, &pfx_200_0_0_0_s_24);
8366 * Send a BFD state change to UP - both sessions are now up
8367 * the recursive prefix should LB over both
8369 bfd_10_10_10_2.local_state = BFD_STATE_up;
8370 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &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",
8379 format_fib_prefix, &pfx_200_0_0_0_s_24);
8382 * Send a BFD state change to DOWN
8383 * the recursive prefix should exclude the down
8385 bfd_10_10_10_2.local_state = BFD_STATE_down;
8386 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8389 FIB_TEST(!fib_test_validate_entry(fei,
8390 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8393 "Recursive %U via only UP",
8394 format_fib_prefix, &pfx_200_0_0_0_s_24);
8397 * Delete the BFD session while it is in the DOWN state.
8398 * FIB should consider the entry's state as back up
8400 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_2);
8402 FIB_TEST(!fib_test_validate_entry(fei,
8403 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8407 "Recursive %U via both UP BFD adj-fibs post down session delete",
8408 format_fib_prefix, &pfx_200_0_0_0_s_24);
8411 * Delete the BFD other session while it is in the UP state.
8413 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8415 FIB_TEST(!fib_test_validate_entry(fei,
8416 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8420 "Recursive %U via both UP BFD adj-fibs post up session delete",
8421 format_fib_prefix, &pfx_200_0_0_0_s_24);
8426 fib_table_entry_delete(0, &pfx_200_0_0_0_s_24, FIB_SOURCE_API);
8427 fib_table_entry_delete(0, &pfx_10_10_10_1_s_32, FIB_SOURCE_ADJ);
8428 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
8430 fib_table_entry_delete(0, &pfx_10_10_10_10_s_32, FIB_SOURCE_INTERFACE);
8431 fib_table_entry_delete(0, &pfx_10_10_10_10_s_24, FIB_SOURCE_INTERFACE);
8433 adj_unlock(ai_10_10_10_1);
8435 * test no-one left behind
8437 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8438 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8441 * Single-hop BFD tests
8443 bfd_10_10_10_1.hop_type = BFD_HOP_TYPE_SINGLE;
8444 bfd_10_10_10_1.udp.key.sw_if_index = tm->hw[0]->sw_if_index;
8446 ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8449 tm->hw[0]->sw_if_index);
8450 bfd_10_10_10_1.udp.adj_index = ai_10_10_10_1;
8452 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8455 * whilst the BFD session is not signalled, the adj is up
8457 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on uninit session");
8460 * bring the BFD session up
8462 bfd_10_10_10_1.local_state = BFD_STATE_up;
8463 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8464 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on UP session");
8467 * bring the BFD session down
8469 bfd_10_10_10_1.local_state = BFD_STATE_down;
8470 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8471 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on DOWN session");
8474 * add an attached next hop FIB entry via the down adj
8476 fib_prefix_t pfx_5_5_5_5_s_32 = {
8479 .as_u32 = clib_host_to_net_u32(0x05050505),
8483 .fp_proto = FIB_PROTOCOL_IP4,
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);
8497 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8498 "%U resolves via drop",
8499 format_fib_prefix, &pfx_5_5_5_5_s_32);
8502 * Add a path via an ADJ that is up
8504 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8507 tm->hw[0]->sw_if_index);
8509 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
8512 .adj = ai_10_10_10_2,
8515 adj_o_10_10_10_1.adj.adj = ai_10_10_10_1;
8517 fei = fib_table_entry_path_add(0,
8520 FIB_ENTRY_FLAG_NONE,
8523 tm->hw[0]->sw_if_index,
8524 ~0, // invalid fib index
8527 FIB_ROUTE_PATH_FLAG_NONE);
8529 FIB_TEST(!fib_test_validate_entry(fei,
8530 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8533 "BFD sourced %U via %U",
8534 format_fib_prefix, &pfx_5_5_5_5_s_32,
8535 format_ip_adjacency, ai_10_10_10_2, FORMAT_IP_ADJACENCY_NONE);
8538 * Bring up the down session - should now LB
8540 bfd_10_10_10_1.local_state = BFD_STATE_up;
8541 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8542 FIB_TEST(!fib_test_validate_entry(fei,
8543 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8547 "BFD sourced %U via noth adjs",
8548 format_fib_prefix, &pfx_5_5_5_5_s_32);
8551 * remove the BFD session state from the adj
8553 adj_bfd_notify(BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8558 fib_table_entry_delete(0, &pfx_5_5_5_5_s_32, FIB_SOURCE_CLI);
8559 adj_unlock(ai_10_10_10_1);
8560 adj_unlock(ai_10_10_10_2);
8563 * test no-one left behind
8565 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8566 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8574 const mpls_label_t deag_label = 50;
8575 adj_index_t ai_mpls_10_10_10_1;
8576 dpo_id_t dpo = DPO_INVALID;
8577 const u32 lfib_index = 0;
8578 const u32 fib_index = 0;
8579 const dpo_id_t *dpo1;
8580 fib_node_index_t lfe;
8587 lb_count = pool_elts(load_balance_pool);
8589 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
8593 * MPLS enable an interface so we get the MPLS table created
8595 mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL);
8596 mpls_sw_interface_enable_disable(&mpls_main,
8597 tm->hw[0]->sw_if_index,
8600 ip46_address_t nh_10_10_10_1 = {
8601 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
8603 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8606 tm->hw[0]->sw_if_index);
8609 * Test the specials stack properly.
8611 fib_prefix_t exp_null_v6_pfx = {
8612 .fp_proto = FIB_PROTOCOL_MPLS,
8614 .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8615 .fp_payload_proto = DPO_PROTO_IP6,
8617 lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx);
8618 FIB_TEST((FIB_NODE_INDEX_INVALID != lfe),
8620 format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8621 format_mpls_eos_bit, MPLS_EOS);
8622 fib_entry_contribute_forwarding(lfe,
8623 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8625 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8626 lkd = lookup_dpo_get(dpo1->dpoi_index);
8628 FIB_TEST((fib_index == lkd->lkd_fib_index),
8629 "%U/%U is deag in %d %U",
8630 format_mpls_unicast_label, deag_label,
8631 format_mpls_eos_bit, MPLS_EOS,
8633 format_dpo_id, &dpo, 0);
8634 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8635 "%U/%U is dst deag",
8636 format_mpls_unicast_label, deag_label,
8637 format_mpls_eos_bit, MPLS_EOS);
8638 FIB_TEST((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table),
8639 "%U/%U is lookup in interface's table",
8640 format_mpls_unicast_label, deag_label,
8641 format_mpls_eos_bit, MPLS_EOS);
8642 FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto),
8643 "%U/%U is %U dst deag",
8644 format_mpls_unicast_label, deag_label,
8645 format_mpls_eos_bit, MPLS_EOS,
8646 format_dpo_proto, lkd->lkd_proto);
8649 * A route deag route for EOS
8651 fib_prefix_t pfx = {
8652 .fp_proto = FIB_PROTOCOL_MPLS,
8654 .fp_label = deag_label,
8655 .fp_payload_proto = DPO_PROTO_IP4,
8657 mpls_disp_dpo_t *mdd;
8658 lfe = fib_table_entry_path_add(lfib_index,
8661 FIB_ENTRY_FLAG_NONE,
8668 FIB_ROUTE_PATH_FLAG_NONE);
8670 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8672 format_mpls_unicast_label, deag_label,
8673 format_mpls_eos_bit, MPLS_EOS);
8675 fib_entry_contribute_forwarding(lfe,
8676 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8678 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8679 mdd = mpls_disp_dpo_get(dpo1->dpoi_index);
8681 FIB_TEST((FIB_MPLS_LSP_MODE_PIPE == mdd->mdd_mode),
8682 "%U/%U disp is pipe mode",
8683 format_mpls_unicast_label, deag_label,
8684 format_mpls_eos_bit, MPLS_EOS);
8686 lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index);
8688 FIB_TEST((fib_index == lkd->lkd_fib_index),
8689 "%U/%U is deag in %d %U",
8690 format_mpls_unicast_label, deag_label,
8691 format_mpls_eos_bit, MPLS_EOS,
8693 format_dpo_id, &dpo, 0);
8694 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8695 "%U/%U is dst deag",
8696 format_mpls_unicast_label, deag_label,
8697 format_mpls_eos_bit, MPLS_EOS);
8698 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8699 "%U/%U is %U dst deag",
8700 format_mpls_unicast_label, deag_label,
8701 format_mpls_eos_bit, MPLS_EOS,
8702 format_dpo_proto, lkd->lkd_proto);
8704 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8706 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8708 "%U/%U not present",
8709 format_mpls_unicast_label, deag_label,
8710 format_mpls_eos_bit, MPLS_EOS);
8714 * A route deag route for EOS with LSP mode uniform
8716 fib_mpls_label_t *l_pops = NULL, l_pop = {
8717 .fml_value = MPLS_LABEL_POP,
8718 .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM,
8720 vec_add1(l_pops, l_pop);
8721 lfe = fib_table_entry_path_add(lfib_index,
8724 FIB_ENTRY_FLAG_NONE,
8731 FIB_ROUTE_PATH_FLAG_NONE);
8733 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8735 format_mpls_unicast_label, deag_label,
8736 format_mpls_eos_bit, MPLS_EOS);
8738 fib_entry_contribute_forwarding(lfe,
8739 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8741 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8742 mdd = mpls_disp_dpo_get(dpo1->dpoi_index);
8744 FIB_TEST((FIB_MPLS_LSP_MODE_UNIFORM == mdd->mdd_mode),
8745 "%U/%U disp is uniform mode",
8746 format_mpls_unicast_label, deag_label,
8747 format_mpls_eos_bit, MPLS_EOS);
8749 lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index);
8751 FIB_TEST((fib_index == lkd->lkd_fib_index),
8752 "%U/%U is deag in %d %U",
8753 format_mpls_unicast_label, deag_label,
8754 format_mpls_eos_bit, MPLS_EOS,
8756 format_dpo_id, &dpo, 0);
8757 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8758 "%U/%U is dst deag",
8759 format_mpls_unicast_label, deag_label,
8760 format_mpls_eos_bit, MPLS_EOS);
8761 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8762 "%U/%U is %U dst deag",
8763 format_mpls_unicast_label, deag_label,
8764 format_mpls_eos_bit, MPLS_EOS,
8765 format_dpo_proto, lkd->lkd_proto);
8767 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8769 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8771 "%U/%U not present",
8772 format_mpls_unicast_label, deag_label,
8773 format_mpls_eos_bit, MPLS_EOS);
8777 * A route deag route for non-EOS
8779 pfx.fp_eos = MPLS_NON_EOS;
8780 lfe = fib_table_entry_path_add(lfib_index,
8783 FIB_ENTRY_FLAG_NONE,
8790 FIB_ROUTE_PATH_FLAG_NONE);
8792 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8794 format_mpls_unicast_label, deag_label,
8795 format_mpls_eos_bit, MPLS_NON_EOS);
8797 fib_entry_contribute_forwarding(lfe,
8798 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8800 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8801 lkd = lookup_dpo_get(dpo1->dpoi_index);
8803 FIB_TEST((fib_index == lkd->lkd_fib_index),
8804 "%U/%U is deag in %d %U",
8805 format_mpls_unicast_label, deag_label,
8806 format_mpls_eos_bit, MPLS_NON_EOS,
8808 format_dpo_id, &dpo, 0);
8809 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8810 "%U/%U is dst deag",
8811 format_mpls_unicast_label, deag_label,
8812 format_mpls_eos_bit, MPLS_NON_EOS);
8814 FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto),
8815 "%U/%U is %U dst deag",
8816 format_mpls_unicast_label, deag_label,
8817 format_mpls_eos_bit, MPLS_NON_EOS,
8818 format_dpo_proto, lkd->lkd_proto);
8820 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8822 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8824 "%U/%U not present",
8825 format_mpls_unicast_label, deag_label,
8826 format_mpls_eos_bit, MPLS_EOS);
8833 fib_prefix_t pfx_1200 = {
8835 .fp_proto = FIB_PROTOCOL_MPLS,
8837 .fp_eos = MPLS_NON_EOS,
8839 fib_test_lb_bucket_t neos_o_10_10_10_1 = {
8840 .type = FT_LB_LABEL_STACK_O_ADJ,
8841 .label_stack_o_adj = {
8842 .adj = ai_mpls_10_10_10_1,
8843 .label_stack_size = 4,
8847 .eos = MPLS_NON_EOS,
8850 dpo_id_t neos_1200 = DPO_INVALID;
8851 dpo_id_t ip_1200 = DPO_INVALID;
8852 fib_mpls_label_t *l200 = NULL;
8854 for (ii = 0; ii < 4; ii++)
8856 fib_mpls_label_t fml = {
8857 .fml_value = 200 + (ii * 100),
8859 vec_add1(l200, fml);
8862 lfe = fib_table_entry_update_one_path(fib_index,
8865 FIB_ENTRY_FLAG_NONE,
8868 tm->hw[0]->sw_if_index,
8869 ~0, // invalid fib index
8872 FIB_ROUTE_PATH_FLAG_NONE);
8874 FIB_TEST(!fib_test_validate_entry(lfe,
8875 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8877 &neos_o_10_10_10_1),
8878 "1200/0 LB 1 buckets via: "
8882 * A recursive route via the MPLS x-connect
8884 fib_prefix_t pfx_2_2_2_3_s_32 = {
8886 .fp_proto = FIB_PROTOCOL_IP4,
8888 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
8891 fib_route_path_t *rpaths = NULL, rpath = {
8892 .frp_proto = DPO_PROTO_MPLS,
8893 .frp_local_label = 1200,
8894 .frp_eos = MPLS_NON_EOS,
8895 .frp_sw_if_index = ~0, // recurive
8896 .frp_fib_index = 0, // Default MPLS fib
8898 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
8899 .frp_label_stack = NULL,
8901 vec_add1(rpaths, rpath);
8903 fib_table_entry_path_add2(fib_index,
8906 FIB_ENTRY_FLAG_NONE,
8910 * A labelled recursive route via the MPLS x-connect
8912 fib_prefix_t pfx_2_2_2_4_s_32 = {
8914 .fp_proto = FIB_PROTOCOL_IP4,
8916 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
8919 fib_mpls_label_t *l999 = NULL, fml_999 = {
8922 vec_add1(l999, fml_999);
8923 rpaths[0].frp_label_stack = l999,
8925 fib_table_entry_path_add2(fib_index,
8928 FIB_ENTRY_FLAG_NONE,
8931 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8932 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8934 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8935 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8938 fib_test_lb_bucket_t ip_o_1200 = {
8941 .lb = ip_1200.dpoi_index,
8944 fib_test_lb_bucket_t mpls_o_1200 = {
8945 .type = FT_LB_LABEL_O_LB,
8947 .lb = neos_1200.dpoi_index,
8953 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
8954 FIB_TEST(!fib_test_validate_entry(lfe,
8955 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8958 "2.2.2.2.3/32 LB 1 buckets via: label 1200 EOS");
8959 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
8960 FIB_TEST(!fib_test_validate_entry(lfe,
8961 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8964 "2.2.2.2.4/32 LB 1 buckets via: label 1200 non-EOS");
8966 fib_table_entry_delete(fib_index, &pfx_1200, FIB_SOURCE_API);
8967 fib_table_entry_delete(fib_index, &pfx_2_2_2_3_s_32, FIB_SOURCE_API);
8968 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8970 dpo_reset(&neos_1200);
8971 dpo_reset(&ip_1200);
8974 * A recursive via a label that does not exist
8976 fib_test_lb_bucket_t bucket_drop = {
8979 .adj = DPO_PROTO_IP4,
8982 fib_test_lb_bucket_t mpls_bucket_drop = {
8985 .adj = DPO_PROTO_MPLS,
8989 rpaths[0].frp_label_stack = NULL;
8990 lfe = fib_table_entry_path_add2(fib_index,
8993 FIB_ENTRY_FLAG_NONE,
8996 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8997 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8999 ip_o_1200.lb.lb = ip_1200.dpoi_index;
9001 FIB_TEST(!fib_test_validate_entry(lfe,
9002 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9005 "2.2.2.2.4/32 LB 1 buckets via: drop");
9006 lfe = fib_table_lookup(fib_index, &pfx_1200);
9007 FIB_TEST(!fib_test_validate_entry(lfe,
9008 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9011 "1200/neos LB 1 buckets via: ip4-DROP");
9012 FIB_TEST(!fib_test_validate_entry(lfe,
9013 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
9016 "1200/neos LB 1 buckets via: mpls-DROP");
9018 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
9020 dpo_reset(&ip_1200);
9023 * An rx-interface route.
9024 * like the tail of an mcast LSP
9026 dpo_id_t idpo = DPO_INVALID;
9028 interface_rx_dpo_add_or_lock(DPO_PROTO_IP4,
9029 tm->hw[0]->sw_if_index,
9032 fib_prefix_t pfx_2500 = {
9034 .fp_proto = FIB_PROTOCOL_MPLS,
9037 .fp_payload_proto = DPO_PROTO_IP4,
9039 fib_test_lb_bucket_t rx_intf_0 = {
9042 .adj = idpo.dpoi_index,
9046 lfe = fib_table_entry_update_one_path(fib_index,
9049 FIB_ENTRY_FLAG_NONE,
9052 tm->hw[0]->sw_if_index,
9053 ~0, // invalid fib index
9056 FIB_ROUTE_PATH_INTF_RX);
9057 FIB_TEST(!fib_test_validate_entry(lfe,
9058 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9061 "2500 rx-interface 0");
9062 fib_table_entry_delete(fib_index, &pfx_2500, FIB_SOURCE_API);
9065 * An MPLS mulicast entry
9067 fib_prefix_t pfx_3500 = {
9069 .fp_proto = FIB_PROTOCOL_MPLS,
9072 .fp_payload_proto = DPO_PROTO_IP4,
9074 fib_test_rep_bucket_t mc_0 = {
9075 .type = FT_REP_LABEL_O_ADJ,
9077 .adj = ai_mpls_10_10_10_1,
9082 fib_test_rep_bucket_t mc_intf_0 = {
9083 .type = FT_REP_INTF,
9085 .adj = idpo.dpoi_index,
9088 fib_mpls_label_t *l3300 = NULL, fml_3300 = {
9091 vec_add1(l3300, fml_3300);
9093 lfe = fib_table_entry_update_one_path(lfib_index,
9096 FIB_ENTRY_FLAG_MULTICAST,
9099 tm->hw[0]->sw_if_index,
9100 ~0, // invalid fib index
9103 FIB_ROUTE_PATH_FLAG_NONE);
9104 FIB_TEST(!fib_test_validate_entry(lfe,
9105 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9108 "3500 via replicate over 10.10.10.1");
9111 * MPLS Bud-node. Add a replication via an interface-receieve path
9113 lfe = fib_table_entry_path_add(lfib_index,
9116 FIB_ENTRY_FLAG_MULTICAST,
9119 tm->hw[0]->sw_if_index,
9120 ~0, // invalid fib index
9123 FIB_ROUTE_PATH_INTF_RX);
9124 FIB_TEST(!fib_test_validate_entry(lfe,
9125 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9129 "3500 via replicate over 10.10.10.1 and interface-rx");
9132 * Add a replication via an interface-free for-us path
9134 fib_test_rep_bucket_t mc_disp = {
9135 .type = FT_REP_DISP_MFIB_LOOKUP,
9137 .adj = idpo.dpoi_index,
9140 lfe = fib_table_entry_path_add(lfib_index,
9143 FIB_ENTRY_FLAG_MULTICAST,
9150 FIB_ROUTE_PATH_RPF_ID);
9151 FIB_TEST(!fib_test_validate_entry(lfe,
9152 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9157 "3500 via replicate over 10.10.10.1 and interface-rx");
9161 fib_table_entry_delete(fib_index, &pfx_3500, FIB_SOURCE_API);
9167 mpls_sw_interface_enable_disable(&mpls_main,
9168 tm->hw[0]->sw_if_index,
9170 mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
9172 FIB_TEST(0 == pool_elts(mpls_disp_dpo_pool),
9173 "mpls_disp_dpo resources freed %d of %d",
9174 0, pool_elts(mpls_disp_dpo_pool));
9175 FIB_TEST(lb_count == pool_elts(load_balance_pool),
9176 "Load-balance resources freed %d of %d",
9177 lb_count, pool_elts(load_balance_pool));
9178 FIB_TEST(0 == pool_elts(interface_rx_dpo_pool),
9179 "interface_rx_dpo resources freed %d of %d",
9180 0, pool_elts(interface_rx_dpo_pool));
9186 fib_test_inherit (void)
9188 fib_node_index_t fei;
9195 for (i = 0; i <= 2; i++)
9197 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[i]->sw_if_index, 0);
9198 fib_table_bind (FIB_PROTOCOL_IP6, tm->hw[i]->sw_if_index, 0);
9200 n_feis = fib_entry_pool_size();
9202 const ip46_address_t nh_10_10_10_1 = {
9203 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
9205 const ip46_address_t nh_10_10_10_2 = {
9206 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
9208 const ip46_address_t nh_10_10_10_3 = {
9209 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
9211 const ip46_address_t nh_10_10_10_16 = {
9212 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a10),
9214 const ip46_address_t nh_10_10_10_20 = {
9215 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a14),
9217 const ip46_address_t nh_10_10_10_21 = {
9218 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a15),
9220 const ip46_address_t nh_10_10_10_22 = {
9221 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a16),
9223 const ip46_address_t nh_10_10_10_255 = {
9224 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0aff),
9226 const ip46_address_t nh_10_10_10_0 = {
9227 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a00),
9229 const ip46_address_t nh_10_10_0_0 = {
9230 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0000),
9232 const ip46_address_t nh_11_11_11_11 = {
9233 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
9235 const ip46_address_t nh_11_11_11_0 = {
9236 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b00),
9240 * prefixes at the base of a sub-tree
9242 const fib_prefix_t pfx_10_10_10_21_s_32 = {
9244 .fp_proto = FIB_PROTOCOL_IP4,
9245 .fp_addr = nh_10_10_10_21,
9247 const fib_prefix_t pfx_10_10_10_22_s_32 = {
9249 .fp_proto = FIB_PROTOCOL_IP4,
9250 .fp_addr = nh_10_10_10_22,
9252 const fib_prefix_t pfx_10_10_10_255_s_32 = {
9254 .fp_proto = FIB_PROTOCOL_IP4,
9255 .fp_addr = nh_10_10_10_255,
9257 const u32 N_PLS = fib_path_list_pool_size();
9259 fib_table_entry_special_add(0,
9260 &pfx_10_10_10_21_s_32,
9262 FIB_ENTRY_FLAG_DROP);
9263 fib_table_entry_special_add(0,
9264 &pfx_10_10_10_22_s_32,
9266 FIB_ENTRY_FLAG_DROP);
9267 fib_table_entry_special_add(0,
9268 &pfx_10_10_10_255_s_32,
9270 FIB_ENTRY_FLAG_DROP);
9273 * source an entry that pushes its state down the sub-tree
9275 const fib_prefix_t pfx_10_10_10_16_s_28 = {
9277 .fp_proto = FIB_PROTOCOL_IP4,
9278 .fp_addr = nh_10_10_10_16,
9280 fib_table_entry_update_one_path(0,
9281 &pfx_10_10_10_16_s_28,
9283 FIB_ENTRY_FLAG_COVERED_INHERIT,
9286 tm->hw[0]->sw_if_index,
9290 FIB_ROUTE_PATH_FLAG_NONE);
9293 * this covering entry and all those below it should have
9294 * the same forwarding information.
9296 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9299 tm->hw[0]->sw_if_index);
9300 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
9303 .adj = ai_10_10_10_1,
9307 fei = fib_table_lookup(0, &pfx_10_10_10_16_s_28);
9308 FIB_TEST(!fib_test_validate_entry(fei,
9309 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9312 "%U via 10.10.10.1",
9313 format_fib_prefix, &pfx_10_10_10_16_s_28);
9314 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9315 FIB_TEST(!fib_test_validate_entry(fei,
9316 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9319 "%U via 10.10.10.1",
9320 format_fib_prefix, &pfx_10_10_10_21_s_32);
9321 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9322 FIB_TEST(!fib_test_validate_entry(fei,
9323 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9326 "%U via 10.10.10.1",
9327 format_fib_prefix, &pfx_10_10_10_22_s_32);
9328 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9329 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9330 "%U resolves via drop",
9331 format_fib_prefix, &pfx_10_10_10_255_s_32);
9334 * remove the inherting cover - covereds go back to drop
9336 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_API);
9338 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9339 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9340 "%U resolves via drop",
9341 format_fib_prefix, &pfx_10_10_10_21_s_32);
9344 * source an entry that pushes its state down the sub-tree
9346 const fib_prefix_t pfx_10_10_10_0_s_24 = {
9348 .fp_proto = FIB_PROTOCOL_IP4,
9349 .fp_addr = nh_10_10_10_0,
9351 fib_table_entry_update_one_path(0,
9352 &pfx_10_10_10_0_s_24,
9354 FIB_ENTRY_FLAG_COVERED_INHERIT,
9357 tm->hw[0]->sw_if_index,
9361 FIB_ROUTE_PATH_FLAG_NONE);
9364 * whole sub-tree now covered
9366 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9367 FIB_TEST(!fib_test_validate_entry(fei,
9368 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9371 "%U via 10.10.10.1",
9372 format_fib_prefix, &pfx_10_10_10_0_s_24);
9373 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9374 FIB_TEST(!fib_test_validate_entry(fei,
9375 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9378 "%U via 10.10.10.1",
9379 format_fib_prefix, &pfx_10_10_10_21_s_32);
9380 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9381 FIB_TEST(!fib_test_validate_entry(fei,
9382 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9385 "%U via 10.10.10.1",
9386 format_fib_prefix, &pfx_10_10_10_22_s_32);
9387 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9388 FIB_TEST(!fib_test_validate_entry(fei,
9389 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9392 "%U via 10.10.10.1",
9393 format_fib_prefix, &pfx_10_10_10_255_s_32);
9396 * insert a more specific into the sub-tree - expect inheritance
9397 * this one is directly covered by the root
9399 fib_table_entry_special_add(0,
9400 &pfx_10_10_10_16_s_28,
9402 FIB_ENTRY_FLAG_DROP);
9403 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9404 FIB_TEST(!fib_test_validate_entry(fei,
9405 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9408 "%U via 10.10.10.1",
9409 format_fib_prefix, &pfx_10_10_10_16_s_28);
9412 * insert a more specific into the sub-tree - expect inheritance
9413 * this one is indirectly covered by the root
9415 const fib_prefix_t pfx_10_10_10_20_s_30 = {
9417 .fp_proto = FIB_PROTOCOL_IP4,
9418 .fp_addr = nh_10_10_10_20,
9420 fib_table_entry_special_add(0,
9421 &pfx_10_10_10_20_s_30,
9423 FIB_ENTRY_FLAG_DROP);
9424 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_20_s_30);
9425 FIB_TEST(!fib_test_validate_entry(fei,
9426 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9429 "%U via 10.10.10.1",
9430 format_fib_prefix, &pfx_10_10_10_20_s_30);
9433 * remove the prefix from the middle of the sub-tree
9434 * the inherited source will be the only one remaining - expect
9435 * it to be withdrawn and hence the prefix is removed.
9437 fib_table_entry_special_remove(0,
9438 &pfx_10_10_10_20_s_30,
9440 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_20_s_30);
9441 FIB_TEST((FIB_NODE_INDEX_INVALID == fei),
9443 format_fib_prefix, &pfx_10_10_10_20_s_30);
9446 * inheriting source is modifed - expect the modification to be present
9447 * throughout the sub-tree
9449 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9452 tm->hw[0]->sw_if_index);
9453 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
9456 .adj = ai_10_10_10_2,
9460 fib_table_entry_update_one_path(0,
9461 &pfx_10_10_10_0_s_24,
9463 FIB_ENTRY_FLAG_COVERED_INHERIT,
9466 tm->hw[0]->sw_if_index,
9470 FIB_ROUTE_PATH_FLAG_NONE);
9471 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9472 FIB_TEST(!fib_test_validate_entry(fei,
9473 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9476 "%U via 10.10.10.2",
9477 format_fib_prefix, &pfx_10_10_10_21_s_32);
9478 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9479 FIB_TEST(!fib_test_validate_entry(fei,
9480 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9483 "%U via 10.10.10.2",
9484 format_fib_prefix, &pfx_10_10_10_22_s_32);
9485 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9486 FIB_TEST(!fib_test_validate_entry(fei,
9487 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9490 "%U via 10.10.10.2",
9491 format_fib_prefix, &pfx_10_10_10_255_s_32);
9492 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9493 FIB_TEST(!fib_test_validate_entry(fei,
9494 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9497 "%U via 10.10.10.2",
9498 format_fib_prefix, &pfx_10_10_10_0_s_24);
9500 fib_source_t hi_src = fib_source_allocate("test", 0x50,
9501 FIB_SOURCE_BH_SIMPLE);
9504 * add the source that replaces inherited state.
9505 * inheriting source is not the best, so it doesn't push state.
9507 fib_table_entry_update_one_path(0,
9508 &pfx_10_10_10_0_s_24,
9510 FIB_ENTRY_FLAG_NONE,
9513 tm->hw[0]->sw_if_index,
9517 FIB_ROUTE_PATH_FLAG_NONE);
9518 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9519 FIB_TEST(!fib_test_validate_entry(fei,
9520 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9523 "%U via 10.10.10.1",
9524 format_fib_prefix, &pfx_10_10_10_0_s_24);
9526 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9527 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9528 "%U resolves via drop",
9529 format_fib_prefix, &pfx_10_10_10_21_s_32);
9530 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9531 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9532 "%U resolves via drop",
9533 format_fib_prefix, &pfx_10_10_10_22_s_32);
9534 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9535 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9536 "%U resolves via drop",
9537 format_fib_prefix, &pfx_10_10_10_255_s_32);
9538 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9539 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9540 "%U resolves via drop",
9541 format_fib_prefix, &pfx_10_10_10_16_s_28);
9544 * withdraw the higher priority source and expect the inherited to return
9545 * throughout the sub-tree
9547 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, hi_src);
9549 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9550 FIB_TEST(!fib_test_validate_entry(fei,
9551 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9554 "%U via 10.10.10.2",
9555 format_fib_prefix, &pfx_10_10_10_21_s_32);
9556 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9557 FIB_TEST(!fib_test_validate_entry(fei,
9558 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9561 "%U via 10.10.10.2",
9562 format_fib_prefix, &pfx_10_10_10_22_s_32);
9563 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9564 FIB_TEST(!fib_test_validate_entry(fei,
9565 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9568 "%U via 10.10.10.2",
9569 format_fib_prefix, &pfx_10_10_10_255_s_32);
9570 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9571 FIB_TEST(!fib_test_validate_entry(fei,
9572 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9575 "%U via 10.10.10.2",
9576 format_fib_prefix, &pfx_10_10_10_0_s_24);
9577 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9578 FIB_TEST(!fib_test_validate_entry(fei,
9579 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9582 "%U via 10.10.10.2",
9583 format_fib_prefix, &pfx_10_10_10_16_s_28);
9586 * source a covered entry in the sub-tree with the same inherting source
9587 * - expect that it now owns the sub-tree and thus over-rides its cover
9589 fib_table_entry_update_one_path(0,
9590 &pfx_10_10_10_16_s_28,
9592 FIB_ENTRY_FLAG_COVERED_INHERIT,
9595 tm->hw[0]->sw_if_index,
9599 FIB_ROUTE_PATH_FLAG_NONE);
9600 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9601 FIB_TEST(!fib_test_validate_entry(fei,
9602 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9605 "%U via 10.10.10.1",
9606 format_fib_prefix, &pfx_10_10_10_16_s_28);
9607 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9608 FIB_TEST(!fib_test_validate_entry(fei,
9609 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9612 "%U via 10.10.10.2",
9613 format_fib_prefix, &pfx_10_10_10_22_s_32);
9614 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9615 FIB_TEST(!fib_test_validate_entry(fei,
9616 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9619 "%U via 10.10.10.2",
9620 format_fib_prefix, &pfx_10_10_10_21_s_32);
9622 /* these two unaffected by the sub-tree change */
9623 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9624 FIB_TEST(!fib_test_validate_entry(fei,
9625 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9628 "%U via 10.10.10.2",
9629 format_fib_prefix, &pfx_10_10_10_255_s_32);
9630 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9631 FIB_TEST(!fib_test_validate_entry(fei,
9632 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9635 "%U via 10.10.10.2",
9636 format_fib_prefix, &pfx_10_10_10_0_s_24);
9639 * removes the more specific, expect the /24 to now re-owns the sub-tree
9641 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_API);
9643 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
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_16_s_28);
9650 FIB_TEST(!fib_test_validate_entry(fei,
9651 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9654 "%U via 10.10.10.2",
9655 format_fib_prefix, &pfx_10_10_10_21_s_32);
9656 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9657 FIB_TEST(!fib_test_validate_entry(fei,
9658 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9661 "%U via 10.10.10.2",
9662 format_fib_prefix, &pfx_10_10_10_22_s_32);
9663 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9664 FIB_TEST(!fib_test_validate_entry(fei,
9665 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9668 "%U via 10.10.10.2",
9669 format_fib_prefix, &pfx_10_10_10_255_s_32);
9670 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9671 FIB_TEST(!fib_test_validate_entry(fei,
9672 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9675 "%U via 10.10.10.2",
9676 format_fib_prefix, &pfx_10_10_10_0_s_24);
9678 * modify the /24. expect the new forwarding to be pushed down
9680 fib_table_entry_update_one_path(0,
9681 &pfx_10_10_10_0_s_24,
9683 FIB_ENTRY_FLAG_COVERED_INHERIT,
9686 tm->hw[0]->sw_if_index,
9690 FIB_ROUTE_PATH_FLAG_NONE);
9691 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
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_16_s_28);
9698 FIB_TEST(!fib_test_validate_entry(fei,
9699 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9702 "%U via 10.10.10.1",
9703 format_fib_prefix, &pfx_10_10_10_21_s_32);
9704 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9705 FIB_TEST(!fib_test_validate_entry(fei,
9706 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9709 "%U via 10.10.10.1",
9710 format_fib_prefix, &pfx_10_10_10_22_s_32);
9711 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9712 FIB_TEST(!fib_test_validate_entry(fei,
9713 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9716 "%U via 10.10.10.1",
9717 format_fib_prefix, &pfx_10_10_10_255_s_32);
9718 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
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_0_s_24);
9727 * add an entry less specific to /24. it should not own the /24's tree
9729 const fib_prefix_t pfx_10_10_0_0_s_16 = {
9731 .fp_proto = FIB_PROTOCOL_IP4,
9732 .fp_addr = nh_10_10_0_0,
9734 fib_table_entry_update_one_path(0,
9735 &pfx_10_10_0_0_s_16,
9737 FIB_ENTRY_FLAG_COVERED_INHERIT,
9740 tm->hw[0]->sw_if_index,
9744 FIB_ROUTE_PATH_FLAG_NONE);
9745 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9746 FIB_TEST(!fib_test_validate_entry(fei,
9747 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9750 "%U via 10.10.10.1",
9751 format_fib_prefix, &pfx_10_10_10_16_s_28);
9752 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9753 FIB_TEST(!fib_test_validate_entry(fei,
9754 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9757 "%U via 10.10.10.1",
9758 format_fib_prefix, &pfx_10_10_10_22_s_32);
9759 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9760 FIB_TEST(!fib_test_validate_entry(fei,
9761 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9764 "%U via 10.10.10.1",
9765 format_fib_prefix, &pfx_10_10_10_255_s_32);
9766 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9767 FIB_TEST(!fib_test_validate_entry(fei,
9768 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9771 "%U via 10.10.10.1",
9772 format_fib_prefix, &pfx_10_10_10_0_s_24);
9773 fei = fib_table_lookup_exact_match(0, &pfx_10_10_0_0_s_16);
9774 FIB_TEST(!fib_test_validate_entry(fei,
9775 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9778 "%U via 10.10.10.2",
9779 format_fib_prefix, &pfx_10_10_0_0_s_16);
9782 * Add/remove an interposer source to a new /32
9784 const fib_prefix_t pfx_11_11_11_11_s_32 = {
9786 .fp_proto = FIB_PROTOCOL_IP4,
9787 .fp_addr = nh_11_11_11_11,
9790 fib_table_entry_update_one_path(0,
9791 &pfx_11_11_11_11_s_32,
9793 FIB_ENTRY_FLAG_NONE,
9796 tm->hw[0]->sw_if_index,
9800 FIB_ROUTE_PATH_FLAG_NONE);
9802 dpo_id_t interposer = DPO_INVALID;
9803 fib_mpls_label_t *l99 = NULL, fml_99 = {
9806 vec_add1(l99, fml_99);
9808 mpls_label_dpo_create(l99,
9811 MPLS_LABEL_DPO_FLAG_NONE,
9812 punt_dpo_get(DPO_PROTO_MPLS),
9815 adj_index_t ai_10_10_10_3 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9818 tm->hw[0]->sw_if_index);
9819 fib_test_lb_bucket_t adj_o_10_10_10_3 = {
9822 .adj = ai_10_10_10_3,
9825 fib_test_lb_bucket_t l99_o_10_10_10_3 = {
9826 .type = FT_LB_LABEL_O_ADJ,
9828 .adj = ai_10_10_10_3,
9834 fei = fib_table_entry_special_dpo_add(0,
9835 &pfx_11_11_11_11_s_32,
9837 FIB_ENTRY_FLAG_INTERPOSE,
9839 FIB_TEST(!fib_test_validate_entry(fei,
9840 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9843 "%U via interposer adj",
9844 format_fib_prefix,&pfx_11_11_11_11_s_32);
9846 fib_table_entry_special_remove(0,
9847 &pfx_11_11_11_11_s_32,
9848 FIB_SOURCE_SPECIAL);
9849 FIB_TEST(!fib_test_validate_entry(fei,
9850 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9853 "%U via 10.10.10.1",
9854 format_fib_prefix, &pfx_11_11_11_11_s_32);
9855 dpo_reset(&interposer);
9856 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
9859 * add an interposer to a source with path-extensions
9861 fib_mpls_label_t *l3300 = NULL, fml_3300 = {
9864 vec_add1(l3300, fml_3300);
9865 fib_table_entry_update_one_path(0,
9866 &pfx_11_11_11_11_s_32,
9868 FIB_ENTRY_FLAG_NONE,
9871 tm->hw[0]->sw_if_index,
9875 FIB_ROUTE_PATH_FLAG_NONE);
9877 mpls_label_dpo_create(l99,
9880 MPLS_LABEL_DPO_FLAG_NONE,
9881 punt_dpo_get(DPO_PROTO_MPLS),
9884 adj_index_t ai_mpls_10_10_10_3 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9887 tm->hw[0]->sw_if_index);
9888 fib_test_lb_bucket_t l3300_o_10_10_10_3 = {
9889 .type = FT_LB_LABEL_O_ADJ,
9891 .adj = ai_mpls_10_10_10_3,
9896 fib_test_lb_bucket_t lchain_o_10_10_10_3 = {
9897 .type = FT_LB_LABEL_CHAIN_O_ADJ,
9898 .label_chain_o_adj = {
9899 .adj = ai_mpls_10_10_10_3,
9900 .label_chain_size = 2,
9908 fei = fib_table_entry_special_dpo_add(0,
9909 &pfx_11_11_11_11_s_32,
9911 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 & mpls on adj",
9919 format_fib_prefix, &pfx_11_11_11_11_s_32);
9921 fib_table_entry_special_remove(0,
9922 &pfx_11_11_11_11_s_32,
9923 FIB_SOURCE_SPECIAL);
9924 FIB_TEST(!fib_test_validate_entry(fei,
9925 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9927 &l3300_o_10_10_10_3),
9928 "%U via 10.10.10.1",
9929 format_fib_prefix, &pfx_11_11_11_11_s_32);
9930 adj_unlock(ai_mpls_10_10_10_3);
9933 * remove and re-add the second best API source while the interpose
9936 fei = fib_table_entry_special_dpo_add(0,
9937 &pfx_11_11_11_11_s_32,
9939 FIB_ENTRY_FLAG_INTERPOSE,
9941 FIB_TEST(!fib_test_validate_entry(fei,
9942 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9944 &lchain_o_10_10_10_3),
9945 "%U via interposer adj",
9946 format_fib_prefix,&pfx_11_11_11_11_s_32);
9948 FIB_TEST(3 == pool_elts(mpls_label_dpo_pool),
9949 "MPLS label pool: %d",
9950 pool_elts(mpls_label_dpo_pool));
9952 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
9955 * the interpose does not get stacked when there are not valid paths
9957 fib_test_lb_bucket_t bucket_drop = {
9960 .adj = DPO_PROTO_IP4,
9963 FIB_TEST(!fib_test_validate_entry(fei,
9964 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9968 format_fib_prefix,&pfx_11_11_11_11_s_32);
9970 fib_table_entry_update_one_path(0,
9971 &pfx_11_11_11_11_s_32,
9973 FIB_ENTRY_FLAG_NONE,
9976 tm->hw[0]->sw_if_index,
9980 FIB_ROUTE_PATH_FLAG_NONE);
9981 FIB_TEST(!fib_test_validate_entry(fei,
9982 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9985 "%U via interposer adj",
9986 format_fib_prefix,&pfx_11_11_11_11_s_32);
9987 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
9990 * add a cover for the interposed entry, so that we test it selects
9991 * the covers forwarding.
9993 const fib_prefix_t pfx_11_11_11_0_s_24 = {
9995 .fp_proto = FIB_PROTOCOL_IP4,
9996 .fp_addr = nh_11_11_11_0,
9998 fib_table_entry_update_one_path(0,
9999 &pfx_11_11_11_0_s_24,
10001 FIB_ENTRY_FLAG_NONE,
10004 tm->hw[0]->sw_if_index,
10008 FIB_ROUTE_PATH_FLAG_NONE);
10009 FIB_TEST(!fib_test_validate_entry(fei,
10010 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10012 &l99_o_10_10_10_3),
10013 "%U via interposer adj",
10014 format_fib_prefix,&pfx_11_11_11_11_s_32);
10017 * multiple interpose sources on the same entry. Only the high
10018 * priority source gets to add the interpose.
10020 fib_table_entry_update_one_path(0,
10021 &pfx_11_11_11_11_s_32,
10023 FIB_ENTRY_FLAG_NONE,
10026 tm->hw[0]->sw_if_index,
10030 FIB_ROUTE_PATH_FLAG_NONE);
10032 dpo_id_t interposer2 = DPO_INVALID;
10033 fib_mpls_label_t *l100 = NULL, fml_100 = {
10036 vec_add1(l100, fml_100);
10038 mpls_label_dpo_create(l100,
10041 MPLS_LABEL_DPO_FLAG_NONE,
10042 punt_dpo_get(DPO_PROTO_MPLS),
10045 fei = fib_table_entry_special_dpo_add(0,
10046 &pfx_11_11_11_11_s_32,
10047 FIB_SOURCE_CLASSIFY,
10048 FIB_ENTRY_FLAG_INTERPOSE,
10051 fib_test_lb_bucket_t lc100_o_10_10_10_3 = {
10052 .type = FT_LB_LABEL_CHAIN_O_ADJ,
10053 .label_chain_o_adj = {
10054 .adj = ai_10_10_10_3,
10055 .label_chain_size = 2,
10063 FIB_TEST(!fib_test_validate_entry(fei,
10064 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10066 &lc100_o_10_10_10_3),
10067 "%U via interposer label 99",
10068 format_fib_prefix,&pfx_11_11_11_11_s_32);
10070 fib_test_lb_bucket_t l100_o_10_10_10_3 = {
10071 .type = FT_LB_LABEL_O_ADJ,
10073 .adj = ai_10_10_10_3,
10079 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_SPECIAL);
10081 FIB_TEST(!fib_test_validate_entry(fei,
10082 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10084 &l100_o_10_10_10_3),
10085 "%U via interposer label 99",
10086 format_fib_prefix,&pfx_11_11_11_11_s_32);
10088 fib_table_entry_delete(0, &pfx_11_11_11_0_s_24, FIB_SOURCE_API);
10089 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
10090 FIB_TEST(!fib_test_validate_entry(fei,
10091 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10095 format_fib_prefix,&pfx_11_11_11_11_s_32);
10096 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_CLASSIFY);
10099 * update a source to/from interpose.
10101 /* fib_table_entry_update_one_path(0, */
10102 /* &pfx_11_11_11_0_s_24, */
10103 /* FIB_SOURCE_API, */
10104 /* FIB_ENTRY_FLAG_NONE, */
10105 /* DPO_PROTO_IP4, */
10106 /* &nh_10_10_10_3, */
10107 /* tm->hw[0]->sw_if_index, */
10111 /* FIB_ROUTE_PATH_FLAG_NONE); */
10112 /* fei = fib_table_entry_special_dpo_add(0, */
10113 /* &pfx_11_11_11_11_s_32, */
10114 /* FIB_SOURCE_API, */
10115 /* FIB_ENTRY_FLAG_INTERPOSE, */
10116 /* &interposer); */
10117 /* FIB_TEST(!fib_test_validate_entry(fei, */
10118 /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */
10120 /* &l99_o_10_10_10_3), */
10121 /* "%U via interposer label 99", */
10122 /* format_fib_prefix,&pfx_11_11_11_11_s_32); */
10124 /* FIB_TEST(3 == pool_elts(mpls_label_dpo_pool), */
10125 /* "MPLS label pool: %d", */
10126 /* pool_elts(mpls_label_dpo_pool)); */
10127 /* FIB_TEST((2 == mpls_label_dpo_get(interposer.dpoi_index)->mld_locks), */
10128 /* "Interposer %d locks", */
10129 /* mpls_label_dpo_get(interposer.dpoi_index)->mld_locks); */
10131 /* fib_table_entry_update_one_path(0, */
10132 /* &pfx_11_11_11_11_s_32, */
10133 /* FIB_SOURCE_API, */
10134 /* FIB_ENTRY_FLAG_NONE, */
10135 /* DPO_PROTO_IP4, */
10136 /* &nh_10_10_10_2, */
10137 /* tm->hw[0]->sw_if_index, */
10141 /* FIB_ROUTE_PATH_FLAG_NONE); */
10142 /* FIB_TEST(!fib_test_validate_entry(fei, */
10143 /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */
10145 /* &adj_o_10_10_10_2), */
10146 /* "%U via 10.10.10.2", */
10147 /* format_fib_prefix,&pfx_11_11_11_11_s_32); */
10149 /* FIB_TEST((1 == mpls_label_dpo_get(interposer.dpoi_index)->mld_locks), */
10150 /* "Interposer %d locks", */
10151 /* mpls_label_dpo_get(interposer.dpoi_index)->mld_locks); */
10152 /* FIB_TEST(2 == pool_elts(mpls_label_dpo_pool), */
10153 /* "MPLS label pool: %d", */
10154 /* pool_elts(mpls_label_dpo_pool)); */
10156 /* fei = fib_table_entry_special_dpo_add(0, */
10157 /* &pfx_11_11_11_11_s_32, */
10158 /* FIB_SOURCE_API, */
10159 /* FIB_ENTRY_FLAG_INTERPOSE, */
10160 /* &interposer); */
10161 /* FIB_TEST(!fib_test_validate_entry(fei, */
10162 /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */
10164 /* &l99_o_10_10_10_3), */
10165 /* "%U via interposer label 99", */
10166 /* format_fib_prefix,&pfx_11_11_11_11_s_32); */
10168 /* fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API); */
10171 * Add/remove an interposer source from the top of the subtrie. The
10172 * interposer source is not inherited.
10174 fib_table_entry_update_one_path(0,
10175 &pfx_10_10_10_0_s_24,
10177 FIB_ENTRY_FLAG_COVERED_INHERIT,
10180 tm->hw[0]->sw_if_index,
10184 FIB_ROUTE_PATH_FLAG_NONE);
10185 fei = fib_table_entry_special_dpo_add(0,
10186 &pfx_10_10_10_0_s_24,
10187 FIB_SOURCE_SPECIAL,
10188 FIB_ENTRY_FLAG_INTERPOSE,
10190 FIB_TEST(!fib_test_validate_entry(fei,
10191 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10193 &l99_o_10_10_10_3),
10194 "%U via interposer label",
10195 format_fib_prefix,&pfx_10_10_10_0_s_24);
10196 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
10197 FIB_TEST(!fib_test_validate_entry(fei,
10198 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10202 format_fib_prefix, &pfx_10_10_10_21_s_32);
10204 fib_table_entry_special_remove(0,
10205 &pfx_10_10_10_0_s_24,
10206 FIB_SOURCE_SPECIAL);
10207 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
10208 FIB_TEST(!fib_test_validate_entry(fei,
10209 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10211 &adj_o_10_10_10_3),
10212 "%U via 10.10.10.1",
10213 format_fib_prefix, &pfx_10_10_10_0_s_24);
10214 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
10215 FIB_TEST(!fib_test_validate_entry(fei,
10216 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10218 &adj_o_10_10_10_3),
10219 "%U via via 10.10.10.1",
10220 format_fib_prefix, &pfx_10_10_10_21_s_32);
10223 * Add/remove an interposer source from the top of the subtrie. The
10224 * interposer source is inherited.
10226 fei = fib_table_entry_special_dpo_add(0,
10227 &pfx_10_10_10_0_s_24,
10228 FIB_SOURCE_SPECIAL,
10229 (FIB_ENTRY_FLAG_COVERED_INHERIT |
10230 FIB_ENTRY_FLAG_INTERPOSE),
10232 FIB_TEST(!fib_test_validate_entry(fei,
10233 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10235 &l99_o_10_10_10_3),
10236 "%U via interposer label",
10237 format_fib_prefix,&pfx_10_10_10_0_s_24);
10239 /* interposer gets forwarding from the drop cli source */
10240 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
10241 FIB_TEST(!fib_test_validate_entry(fei,
10242 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10246 format_fib_prefix,&pfx_10_10_10_21_s_32);
10248 fib_table_entry_update_one_path(0,
10249 &pfx_10_10_10_21_s_32,
10251 FIB_ENTRY_FLAG_NONE,
10254 tm->hw[0]->sw_if_index,
10258 FIB_ROUTE_PATH_FLAG_NONE);
10259 fib_table_entry_delete(0, &pfx_10_10_10_21_s_32, FIB_SOURCE_CLI);
10260 /* interposer gets forwarding from the API source */
10261 FIB_TEST(!fib_test_validate_entry(fei,
10262 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10264 &l99_o_10_10_10_3),
10265 "%U via interposer label",
10266 format_fib_prefix,&pfx_10_10_10_21_s_32);
10271 fib_table_entry_delete(0, &pfx_10_10_10_22_s_32, FIB_SOURCE_CLI);
10272 fib_table_entry_delete(0, &pfx_10_10_10_21_s_32, FIB_SOURCE_API);
10273 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_CLI);
10274 fib_table_entry_delete(0, &pfx_10_10_10_255_s_32, FIB_SOURCE_CLI);
10275 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, FIB_SOURCE_API);
10276 fib_table_entry_delete(0, &pfx_10_10_0_0_s_16, FIB_SOURCE_API);
10277 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, FIB_SOURCE_SPECIAL);
10278 adj_unlock(ai_10_10_10_1);
10279 adj_unlock(ai_10_10_10_2);
10280 adj_unlock(ai_10_10_10_3);
10281 dpo_reset(&interposer);
10282 dpo_reset(&interposer2);
10283 FIB_TEST(0 == pool_elts(mpls_label_dpo_pool),
10284 "MPLS label pool empty: %d",
10285 pool_elts(mpls_label_dpo_pool));
10286 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
10287 FIB_TEST(N_PLS == fib_path_list_pool_size(),
10288 "number of path-lists: %d = %d",
10289 N_PLS, fib_path_list_pool_size());
10292 * test the v6 tree walk.
10293 * a /64 that covers everything. a /96 that covers one /128
10294 * a second /128 covered only by the /64.
10296 const fib_prefix_t pfx_2001_s_64 = {
10298 .fp_proto = FIB_PROTOCOL_IP6,
10302 [0] = clib_host_to_net_u64(0x2001000000000000),
10303 [1] = clib_host_to_net_u64(0x0000000000000000),
10308 const fib_prefix_t pfx_2001_1_s_96 = {
10310 .fp_proto = FIB_PROTOCOL_IP6,
10314 [0] = clib_host_to_net_u64(0x2001000000000000),
10315 [1] = clib_host_to_net_u64(0x1000000000000000),
10320 const fib_prefix_t pfx_2001_1_1_s_128 = {
10322 .fp_proto = FIB_PROTOCOL_IP6,
10326 [0] = clib_host_to_net_u64(0x2001000000000000),
10327 [1] = clib_host_to_net_u64(0x1000000000000001),
10332 const fib_prefix_t pfx_2001_0_1_s_128 = {
10334 .fp_proto = FIB_PROTOCOL_IP6,
10338 [0] = clib_host_to_net_u64(0x2001000000000000),
10339 [1] = clib_host_to_net_u64(0x0000000000000001),
10344 const ip46_address_t nh_3000_1 = {
10347 [0] = clib_host_to_net_u64(0x3000000000000000),
10348 [1] = clib_host_to_net_u64(0x0000000000000001),
10352 const ip46_address_t nh_3000_2 = {
10355 [0] = clib_host_to_net_u64(0x3000000000000000),
10356 [1] = clib_host_to_net_u64(0x0000000000000002),
10360 adj_index_t ai_3000_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
10363 tm->hw[0]->sw_if_index);
10364 adj_index_t ai_3000_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
10367 tm->hw[0]->sw_if_index);
10368 fib_test_lb_bucket_t adj_o_3000_1 = {
10374 fib_test_lb_bucket_t adj_o_3000_2 = {
10381 fib_table_entry_special_add(0,
10382 &pfx_2001_0_1_s_128,
10384 FIB_ENTRY_FLAG_DROP);
10385 fib_table_entry_special_add(0,
10386 &pfx_2001_1_1_s_128,
10388 FIB_ENTRY_FLAG_DROP);
10391 * /96 has inherited forwarding pushed down to its covered /128
10393 fib_table_entry_update_one_path(0,
10396 FIB_ENTRY_FLAG_COVERED_INHERIT,
10399 tm->hw[0]->sw_if_index,
10403 FIB_ROUTE_PATH_FLAG_NONE);
10404 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_s_96);
10405 FIB_TEST(!fib_test_validate_entry(fei,
10406 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10410 format_fib_prefix, &pfx_2001_1_s_96);
10411 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_1_s_128);
10412 FIB_TEST(!fib_test_validate_entry(fei,
10413 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10417 format_fib_prefix, &pfx_2001_1_1_s_128);
10418 fei = fib_table_lookup_exact_match(0, &pfx_2001_0_1_s_128);
10419 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
10420 "%U resolves via drop",
10421 format_fib_prefix, &pfx_2001_0_1_s_128);
10424 * /64 has inherited forwarding pushed down to all, but the /96
10425 * and its sub-tree remain unaffected.
10427 fib_table_entry_update_one_path(0,
10430 FIB_ENTRY_FLAG_COVERED_INHERIT,
10433 tm->hw[0]->sw_if_index,
10437 FIB_ROUTE_PATH_FLAG_NONE);
10439 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
10440 FIB_TEST(!fib_test_validate_entry(fei,
10441 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10445 format_fib_prefix, &pfx_2001_s_64);
10446 fei = fib_table_lookup_exact_match(0, &pfx_2001_0_1_s_128);
10447 FIB_TEST(!fib_test_validate_entry(fei,
10448 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10452 format_fib_prefix, &pfx_2001_0_1_s_128);
10454 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_s_96);
10455 FIB_TEST(!fib_test_validate_entry(fei,
10456 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10460 format_fib_prefix, &pfx_2001_1_s_96);
10461 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_1_s_128);
10462 FIB_TEST(!fib_test_validate_entry(fei,
10463 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10467 format_fib_prefix, &pfx_2001_1_1_s_128);
10472 fib_table_entry_delete(0, &pfx_2001_0_1_s_128, FIB_SOURCE_CLI);
10473 fib_table_entry_delete(0, &pfx_2001_1_1_s_128, FIB_SOURCE_CLI);
10474 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
10475 fib_table_entry_delete(0, &pfx_2001_1_s_96, FIB_SOURCE_API);
10476 adj_unlock(ai_3000_1);
10477 adj_unlock(ai_3000_2);
10480 * test no-one left behind
10482 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
10483 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
10489 fib_test_sticky (void)
10491 fib_route_path_t *r_paths = NULL;
10492 test_main_t *tm = &test_main;
10493 u32 ii, lb_count, pl_count;
10494 dpo_id_t dpo = DPO_INVALID;
10495 fib_node_index_t pl_index;
10499 fib_test_lb_bucket_t buckets[N_PATHS];
10500 bfd_session_t bfds[N_PATHS] = {{0}};
10502 lb_count = pool_elts(load_balance_pool);
10503 pl_count = fib_path_list_pool_size();
10505 for (ii = 0; ii < N_PATHS; ii++)
10507 ip46_address_t nh = {
10508 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
10512 ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
10514 &nh, tm->hw[0]->sw_if_index);
10516 buckets[ii].type = FT_LB_ADJ;
10517 buckets[ii].adj.adj = ai;
10519 bfds[ii].udp.key.peer_addr = nh;
10520 bfds[ii].udp.key.sw_if_index = tm->hw[0]->sw_if_index;
10521 bfds[ii].hop_type = BFD_HOP_TYPE_SINGLE;
10522 bfds[ii].local_state = BFD_STATE_init;
10523 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfds[ii]);
10524 bfds[ii].local_state = BFD_STATE_up;
10525 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[ii]);
10528 for (ii = 0; ii < N_PATHS; ii++)
10530 fib_route_path_t r_path = {
10531 .frp_proto = DPO_PROTO_IP4,
10533 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
10535 .frp_sw_if_index = tm->hw[0]->sw_if_index,
10537 .frp_fib_index = ~0,
10539 vec_add1(r_paths, r_path);
10542 pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths);
10543 fib_path_list_lock(pl_index);
10545 fib_path_list_contribute_forwarding(pl_index,
10546 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10547 FIB_PATH_LIST_FWD_FLAG_STICKY,
10550 FIB_TEST(!fib_test_validate_lb(&dpo,
10570 /* take down paths */
10571 bfds[0].local_state = BFD_STATE_down;
10572 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[0]);
10574 fib_path_list_contribute_forwarding(pl_index,
10575 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10576 FIB_PATH_LIST_FWD_FLAG_STICKY,
10579 FIB_TEST(!fib_test_validate_lb(&dpo,
10597 "Failed at shut-down path 0");
10599 bfds[7].local_state = BFD_STATE_down;
10600 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[7]);
10602 fib_path_list_contribute_forwarding(pl_index,
10603 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10604 FIB_PATH_LIST_FWD_FLAG_STICKY,
10607 FIB_TEST(!fib_test_validate_lb(&dpo,
10625 "Failed at shut-down path 7");
10627 /* paths back up */
10628 bfds[0].local_state = BFD_STATE_up;
10629 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[0]);
10630 bfds[7].local_state = BFD_STATE_up;
10631 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[7]);
10633 fib_path_list_contribute_forwarding(pl_index,
10634 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10635 FIB_PATH_LIST_FWD_FLAG_STICKY,
10638 FIB_TEST(!fib_test_validate_lb(&dpo,
10658 fib_path_list_unlock(pl_index);
10661 * non-power of 2 number of buckets
10663 fib_route_path_t *r_paths2 = NULL;
10665 r_paths2 = vec_dup(r_paths);
10666 vec_set_len (r_paths2, 3);
10668 pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths2);
10669 fib_path_list_lock(pl_index);
10671 fib_path_list_contribute_forwarding(pl_index,
10672 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10673 FIB_PATH_LIST_FWD_FLAG_STICKY,
10676 FIB_TEST(!fib_test_validate_lb(&dpo,
10696 bfds[1].local_state = BFD_STATE_down;
10697 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10699 fib_path_list_contribute_forwarding(pl_index,
10700 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10701 FIB_PATH_LIST_FWD_FLAG_STICKY,
10705 * path 1's buckets alternate between path 0 and 2
10707 FIB_TEST(!fib_test_validate_lb(&dpo,
10726 bfds[1].local_state = BFD_STATE_up;
10727 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10729 fib_path_list_unlock(pl_index);
10734 fib_route_path_t *r_paths3 = NULL;
10736 r_paths3 = vec_dup(r_paths);
10737 vec_set_len (r_paths3, 3);
10739 r_paths3[0].frp_weight = 3;
10741 pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths3);
10742 fib_path_list_lock(pl_index);
10744 fib_path_list_contribute_forwarding(pl_index,
10745 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10746 FIB_PATH_LIST_FWD_FLAG_STICKY,
10749 FIB_TEST(!fib_test_validate_lb(&dpo,
10769 bfds[1].local_state = BFD_STATE_down;
10770 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10772 fib_path_list_contribute_forwarding(pl_index,
10773 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10774 FIB_PATH_LIST_FWD_FLAG_STICKY,
10776 /* No attempt to Un-equal distribute the down path's buckets */
10777 FIB_TEST(!fib_test_validate_lb(&dpo,
10796 bfds[1].local_state = BFD_STATE_up;
10797 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10800 fib_path_list_unlock(pl_index);
10803 vec_free(r_paths2);
10804 vec_free(r_paths3);
10806 FIB_TEST(lb_count == pool_elts(load_balance_pool), "no leaked LBs");
10807 FIB_TEST(pl_count == fib_path_list_pool_size(), "no leaked PLs");
10812 static clib_error_t *
10813 fib_test (vlib_main_t * vm,
10814 unformat_input_t * input,
10815 vlib_cli_command_t * cmd_arg)
10821 fib_test_mk_intf(4);
10823 if (unformat (input, "debug"))
10825 fib_test_do_debug = 1;
10828 if (unformat (input, "ip4"))
10830 res += fib_test_v4();
10832 else if (unformat (input, "ip6"))
10834 res += fib_test_v6();
10836 else if (unformat (input, "ip"))
10838 res += fib_test_v4();
10839 res += fib_test_v6();
10841 else if (unformat (input, "label"))
10843 res += fib_test_label();
10845 else if (unformat (input, "ae"))
10847 res += fib_test_ae();
10849 else if (unformat (input, "pref"))
10851 res += fib_test_pref();
10853 else if (unformat (input, "lfib"))
10855 res += lfib_test();
10857 else if (unformat (input, "walk"))
10859 res += fib_test_walk();
10861 else if (unformat (input, "bfd"))
10863 res += fib_test_bfd();
10865 else if (unformat (input, "inherit"))
10867 res += fib_test_inherit();
10869 else if (unformat (input, "sticky"))
10871 res += fib_test_sticky();
10875 res += fib_test_v4();
10876 res += fib_test_v6();
10877 res += fib_test_ae();
10878 res += fib_test_bfd();
10879 res += fib_test_pref();
10880 res += fib_test_label();
10881 res += fib_test_inherit();
10882 res += lfib_test();
10885 * fib-walk process must be disabled in order for the walk tests to work
10887 fib_walk_process_disable();
10888 res += fib_test_walk();
10889 fib_walk_process_enable();
10895 return clib_error_return(0, "FIB Unit Test Failed");
10903 VLIB_CLI_COMMAND (test_fib_command, static) = {
10904 .path = "test fib",
10905 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
10906 .function = fib_test,
10910 fib_test_init (vlib_main_t *vm)
10915 VLIB_INIT_FUNCTION (fib_test_init);