2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 #include <vnet/fib/fib_test.h>
17 #include <vnet/fib/ip6_fib.h>
18 #include <vnet/fib/ip4_fib.h>
19 #include <vnet/fib/mpls_fib.h>
20 #include <vnet/adj/adj.h>
21 #include <vnet/dpo/load_balance.h>
22 #include <vnet/dpo/load_balance_map.h>
23 #include <vnet/dpo/mpls_label_dpo.h>
24 #include <vnet/dpo/lookup_dpo.h>
25 #include <vnet/dpo/drop_dpo.h>
26 #include <vnet/dpo/receive_dpo.h>
27 #include <vnet/dpo/ip_null_dpo.h>
28 #include <vnet/bfd/bfd_main.h>
29 #include <vnet/dpo/interface_rx_dpo.h>
30 #include <vnet/dpo/replicate_dpo.h>
31 #include <vnet/dpo/dvr_dpo.h>
32 #include <vnet/dpo/mpls_disposition.h>
33 #include <vnet/dpo/punt_dpo.h>
35 #include <vnet/mpls/mpls.h>
37 #include <vnet/fib/fib_test.h>
38 #include <vnet/fib/fib_path_list.h>
39 #include <vnet/fib/fib_entry_src.h>
40 #include <vnet/fib/fib_walk.h>
41 #include <vnet/fib/fib_node_list.h>
42 #include <vnet/fib/fib_urpf_list.h>
44 #include <vlib/unix/plugin.h>
49 * Add debugs for passing tests
51 static int fib_test_do_debug;
53 #define FIB_TEST_I(_cond, _comment, _args...) \
55 int _evald = (_cond); \
57 fformat(stderr, "FAIL:%d: " _comment "\n", \
61 if (fib_test_do_debug) \
62 fformat(stderr, "PASS:%d: " _comment "\n", \
67 #define FIB_TEST(_cond, _comment, _args...) \
69 if (FIB_TEST_I(_cond, _comment, ##_args)) { \
71 ASSERT(!("FAIL: " _comment)); \
76 * A 'i'm not fussed is this is not efficient' store of test data
78 typedef struct test_main_t_ {
82 u32 hw_if_indicies[4];
86 vnet_hw_interface_t * hw[4];
89 static test_main_t test_main;
91 /* fake ethernet device class, distinct from "fake-ethX" */
92 static u8 * format_test_interface_name (u8 * s, va_list * args)
94 u32 dev_instance = va_arg (*args, u32);
95 return format (s, "test-eth%d", dev_instance);
98 static uword placeholder_interface_tx (vlib_main_t * vm,
99 vlib_node_runtime_t * node,
100 vlib_frame_t * frame)
102 clib_warning ("you shouldn't be here, leaking buffers...");
103 return frame->n_vectors;
106 static clib_error_t *
107 test_interface_admin_up_down (vnet_main_t * vnm,
111 u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
112 VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
113 vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
117 VNET_DEVICE_CLASS (test_interface_device_class,static) = {
118 .name = "Test interface",
119 .format_device_name = format_test_interface_name,
120 .tx_function = placeholder_interface_tx,
121 .admin_up_down_function = test_interface_admin_up_down,
124 static u8 *hw_address;
127 fib_test_mk_intf (u32 ninterfaces)
129 clib_error_t * error = NULL;
130 test_main_t *tm = &test_main;
135 ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
140 vec_add1(hw_address, byte);
143 for (i = 0; i < ninterfaces; i++)
147 error = ethernet_register_interface(vnet_get_main(),
148 test_interface_device_class.index,
151 &tm->hw_if_indicies[i],
152 /* flag change */ 0);
154 FIB_TEST((NULL == error), "ADD interface %d", i);
156 error = vnet_hw_interface_set_flags(vnet_get_main(),
157 tm->hw_if_indicies[i],
158 VNET_HW_INTERFACE_FLAG_LINK_UP);
159 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
160 tm->hw_if_indicies[i]);
162 error = vnet_sw_interface_set_flags(vnet_get_main(),
163 tm->hw[i]->sw_if_index,
164 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
165 FIB_TEST((NULL == error), "UP interface %d", i);
168 * re-eval after the inevitable realloc
170 for (i = 0; i < ninterfaces; i++)
172 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
173 tm->hw_if_indicies[i]);
179 #define FIB_TEST_REC_FORW(_rec_prefix, _via_prefix, _bucket) \
181 const dpo_id_t *_rec_dpo = fib_entry_contribute_ip_forwarding( \
182 fib_table_lookup_exact_match(fib_index, (_rec_prefix))); \
183 const dpo_id_t *_via_dpo = fib_entry_contribute_ip_forwarding( \
184 fib_table_lookup(fib_index, (_via_prefix))); \
185 FIB_TEST(!dpo_cmp(_via_dpo, \
186 load_balance_get_bucket(_rec_dpo->dpoi_index, \
188 "%U is recursive via %U", \
189 format_fib_prefix, (_rec_prefix), \
190 format_fib_prefix, _via_prefix); \
193 #define FIB_TEST_LB_BUCKET_VIA_ADJ(_prefix, _bucket, _ai) \
195 const dpo_id_t *_dpo = fib_entry_contribute_ip_forwarding( \
196 fib_table_lookup_exact_match(fib_index, (_prefix))); \
197 const dpo_id_t *_dpo1 = \
198 load_balance_get_bucket(_dpo->dpoi_index, _bucket); \
199 FIB_TEST(DPO_ADJACENCY == _dpo1->dpoi_type, "type is %U", \
200 format_dpo_type, _dpo1->dpoi_type); \
201 FIB_TEST((_ai == _dpo1->dpoi_index), \
202 "%U bucket %d resolves via %U", \
203 format_fib_prefix, (_prefix), \
205 format_dpo_id, _dpo1, 0); \
208 #define FIB_TEST_RPF(_cond, _comment, _args...) \
210 if (FIB_TEST_I(_cond, _comment, ##_args)) { \
217 fib_test_urpf_is_equal (fib_node_index_t fei,
218 fib_forward_chain_type_t fct,
221 dpo_id_t dpo = DPO_INVALID;
222 fib_urpf_list_t *urpf;
230 fib_entry_contribute_forwarding(fei, fct, &dpo);
231 ui = load_balance_get_urpf(dpo.dpoi_index);
233 urpf = fib_urpf_list_get(ui);
235 FIB_TEST_RPF(num == vec_len(urpf->furpf_itfs),
236 "RPF:%U len %d == %d",
237 format_fib_urpf_list, ui,
238 num, vec_len(urpf->furpf_itfs));
239 FIB_TEST_RPF(num == fib_urpf_check_size(ui),
240 "RPF:%U check-size %d == %d",
241 format_fib_urpf_list, ui,
242 num, vec_len(urpf->furpf_itfs));
244 for (ii = 0; ii < num; ii++)
246 adj_index_t ai = va_arg(ap, adj_index_t);
248 FIB_TEST_RPF(ai == urpf->furpf_itfs[ii],
249 "RPF:%d item:%d - %d == %d",
250 ui, ii, ai, urpf->furpf_itfs[ii]);
251 FIB_TEST_RPF(fib_urpf_check(ui, ai),
265 fib_test_build_rewrite (u8 *eth_addr)
269 vec_validate(rewrite, 13);
271 memcpy(rewrite, eth_addr, 6);
272 memcpy(rewrite+6, eth_addr, 6);
277 #define FIB_TEST_LB(_cond, _comment, _args...) \
279 if (FIB_TEST_I(_cond, _comment, ##_args)) { \
285 fib_test_validate_rep_v (const replicate_t *rep,
289 const fib_test_rep_bucket_t *exp;
294 FIB_TEST_LB((n_buckets == rep->rep_n_buckets),
295 "n_buckets = %d", rep->rep_n_buckets);
297 for (bucket = 0; bucket < n_buckets; bucket++)
299 exp = va_arg(*ap, fib_test_rep_bucket_t*);
301 dpo = replicate_get_bucket_i(rep, bucket);
305 case FT_REP_LABEL_O_ADJ:
307 const mpls_label_dpo_t *mld;
310 FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE)
312 "bucket %d stacks on %U",
314 format_dpo_type, dpo->dpoi_type);
316 mld = mpls_label_dpo_get(dpo->dpoi_index);
317 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
319 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
320 exp->label_o_adj.label),
321 "bucket %d stacks on label %d",
323 exp->label_o_adj.label);
325 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
326 exp->label_o_adj.eos),
327 "bucket %d stacks on label %d %U",
329 exp->label_o_adj.label,
330 format_mpls_eos_bit, exp->label_o_adj.eos);
332 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
333 "bucket %d label stacks on %U",
335 format_dpo_type, mld->mld_dpo.dpoi_type);
337 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
338 "bucket %d label stacks on adj %d",
340 exp->label_o_adj.adj);
344 FIB_TEST_LB((DPO_INTERFACE_RX == dpo->dpoi_type),
345 "bucket %d stacks on %U",
347 format_dpo_type, dpo->dpoi_type);
349 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
350 "bucket %d stacks on adj %d",
354 case FT_REP_DISP_MFIB_LOOKUP:
364 fib_test_validate_lb_v (const load_balance_t *lb,
372 FIB_TEST_LB((n_buckets == lb->lb_n_buckets), "n_buckets = %d", lb->lb_n_buckets);
374 for (bucket = 0; bucket < n_buckets; bucket++)
376 const fib_test_lb_bucket_t *exp;
378 exp = va_arg(*ap, fib_test_lb_bucket_t*);
379 dpo = load_balance_get_bucket_i(lb, bucket);
383 case FT_LB_LABEL_STACK_O_ADJ:
385 const mpls_label_dpo_t *mld;
386 mpls_label_dpo_flags_t mf;
390 mf = ((exp->label_stack_o_adj.mode ==
391 FIB_MPLS_LSP_MODE_UNIFORM) ?
392 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
393 MPLS_LABEL_DPO_FLAG_NONE);
394 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
395 "bucket %d stacks on %U",
397 format_dpo_type, dpo->dpoi_type);
399 mld = mpls_label_dpo_get(dpo->dpoi_index);
401 FIB_TEST_LB(exp->label_stack_o_adj.label_stack_size == mld->mld_n_labels,
405 for (ii = 0; ii < mld->mld_n_labels; ii++)
407 hdr = clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
408 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
409 exp->label_stack_o_adj.label_stack[ii]),
410 "bucket %d stacks on label %d",
412 exp->label_stack_o_adj.label_stack[ii]);
414 if (ii == mld->mld_n_labels-1)
416 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
417 exp->label_o_adj.eos),
418 "bucket %d stacks on label %d %U!=%U",
420 exp->label_stack_o_adj.label_stack[ii],
421 format_mpls_eos_bit, exp->label_o_adj.eos,
422 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
426 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) == MPLS_NON_EOS),
427 "bucket %d stacks on label %d %U",
429 exp->label_stack_o_adj.label_stack[ii],
430 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
434 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
435 "bucket %d label stacks on %U",
437 format_dpo_type, mld->mld_dpo.dpoi_type);
439 FIB_TEST_LB((exp->label_stack_o_adj.adj == mld->mld_dpo.dpoi_index),
440 "bucket %d label stacks on adj %d",
442 exp->label_stack_o_adj.adj);
445 case FT_LB_LABEL_CHAIN_O_ADJ:
447 const mpls_label_dpo_t *mld = NULL;
448 mpls_label_dpo_flags_t mf;
452 mf = ((exp->label_chain_o_adj.mode ==
453 FIB_MPLS_LSP_MODE_UNIFORM) ?
454 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
455 MPLS_LABEL_DPO_FLAG_NONE);
457 for (ii = 0; ii < exp->label_chain_o_adj.label_chain_size; ii++)
459 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
460 "bucket %d stacks on %U",
462 format_dpo_type, dpo->dpoi_type);
463 mld = mpls_label_dpo_get(dpo->dpoi_index);
465 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
466 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
467 exp->label_chain_o_adj.label_chain[ii]),
468 "bucket %d stacks on label %d",
470 exp->label_chain_o_adj.label_chain[ii]);
474 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
475 "bucket %d label stacks on %U",
477 format_dpo_type, mld->mld_dpo.dpoi_type);
479 FIB_TEST_LB((exp->label_chain_o_adj.adj == mld->mld_dpo.dpoi_index),
480 "bucket %d label stacks on adj %d",
482 exp->label_chain_o_adj.adj);
485 case FT_LB_LABEL_O_ADJ:
487 const mpls_label_dpo_t *mld;
489 FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE)
491 "bucket %d stacks on %U",
493 format_dpo_type, dpo->dpoi_type);
495 mld = mpls_label_dpo_get(dpo->dpoi_index);
496 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
498 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
499 exp->label_o_adj.label),
500 "bucket %d stacks on label %d not %d",
502 vnet_mpls_uc_get_label(hdr),
503 exp->label_o_adj.label);
505 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
506 exp->label_o_adj.eos),
507 "bucket %d stacks on label %d %U",
509 exp->label_o_adj.label,
510 format_mpls_eos_bit, exp->label_o_adj.eos);
512 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
513 "bucket %d label stacks on %U",
515 format_dpo_type, mld->mld_dpo.dpoi_type);
517 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
518 "bucket %d label stacks on adj %d",
520 exp->label_o_adj.adj);
523 case FT_LB_LABEL_O_LB:
525 const mpls_label_dpo_t *mld;
526 mpls_label_dpo_flags_t mf;
529 mf = ((exp->label_o_lb.mode ==
530 FIB_MPLS_LSP_MODE_UNIFORM) ?
531 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
532 MPLS_LABEL_DPO_FLAG_NONE);
533 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
534 "bucket %d stacks on %U",
536 format_dpo_type, dpo->dpoi_type);
538 mld = mpls_label_dpo_get(dpo->dpoi_index);
539 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
541 FIB_TEST_LB(1 == mld->mld_n_labels, "label stack size",
543 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
544 exp->label_o_lb.label),
545 "bucket %d stacks on label %d",
547 exp->label_o_lb.label);
549 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
550 exp->label_o_lb.eos),
551 "bucket %d stacks on label %d %U",
553 exp->label_o_lb.label,
554 format_mpls_eos_bit, exp->label_o_lb.eos);
556 FIB_TEST_LB((DPO_LOAD_BALANCE == mld->mld_dpo.dpoi_type),
557 "bucket %d label stacks on %U",
559 format_dpo_type, mld->mld_dpo.dpoi_type);
561 FIB_TEST_LB((exp->label_o_lb.lb == mld->mld_dpo.dpoi_index),
562 "bucket %d label stacks on LB %d",
568 res = FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
569 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
570 "bucket %d stacks on %U",
572 format_dpo_type, dpo->dpoi_type);
573 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
574 "bucket %d stacks on adj %d",
578 case FT_LB_MPLS_DISP_PIPE_O_ADJ:
580 const mpls_disp_dpo_t *mdd;
582 res = FIB_TEST_I((DPO_MPLS_DISPOSITION_PIPE == dpo->dpoi_type),
583 "bucket %d stacks on %U",
585 format_dpo_type, dpo->dpoi_type);
587 mdd = mpls_disp_dpo_get(dpo->dpoi_index);
591 res = FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
592 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
593 "bucket %d stacks on %U",
595 format_dpo_type, dpo->dpoi_type);
596 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
597 "bucket %d stacks on adj %d",
603 res = FIB_TEST_I((DPO_INTERFACE_RX == dpo->dpoi_type),
604 "bucket %d stacks on %U",
606 format_dpo_type, dpo->dpoi_type);
607 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
608 "bucket %d stacks on adj %d",
613 res = FIB_TEST_I((DPO_DVR == dpo->dpoi_type),
614 "bucket %d stacks on %U",
616 format_dpo_type, dpo->dpoi_type);
617 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
618 "bucket %d stacks on adj %d",
623 res = FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
624 "bucket %d stacks on %U",
626 format_dpo_type, dpo->dpoi_type);
627 FIB_TEST_LB((exp->lb.lb == dpo->dpoi_index),
628 "bucket %d stacks on lb %d not %d",
633 case FT_LB_BIER_TABLE:
634 FIB_TEST_LB((DPO_BIER_TABLE == dpo->dpoi_type),
635 "bucket %d stacks on %U",
637 format_dpo_type, dpo->dpoi_type);
638 FIB_TEST_LB((exp->bier.table == dpo->dpoi_index),
639 "bucket %d stacks on lb %d",
643 case FT_LB_BIER_FMASK:
644 FIB_TEST_LB((DPO_BIER_FMASK == dpo->dpoi_type),
645 "bucket %d stacks on %U",
647 format_dpo_type, dpo->dpoi_type);
648 FIB_TEST_LB((exp->bier.fmask == dpo->dpoi_index),
649 "bucket %d stacks on lb %d",
654 FIB_TEST_LB((DPO_DROP == dpo->dpoi_type),
655 "bucket %d stacks on %U",
657 format_dpo_type, dpo->dpoi_type);
660 FIB_TEST_LB((DPO_PUNT == dpo->dpoi_type),
661 "bucket %d stacks on %U",
663 format_dpo_type, dpo->dpoi_type);
671 fib_test_validate_lb (const dpo_id_t *dpo,
675 const load_balance_t *lb;
680 va_start(ap, n_buckets);
682 if (!FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
684 format_dpo_type, dpo->dpoi_type))
686 lb = load_balance_get(dpo->dpoi_index);
688 res = fib_test_validate_lb_v(lb, n_buckets, &ap);
701 fib_test_validate_entry (fib_node_index_t fei,
702 fib_forward_chain_type_t fct,
706 dpo_id_t dpo = DPO_INVALID;
707 const fib_prefix_t *pfx;
715 pfx = fib_entry_get_prefix(fei);
716 fib_index = fib_entry_get_fib_index(fei);
717 fib_entry_contribute_forwarding(fei, fct, &dpo);
719 if (DPO_REPLICATE == dpo.dpoi_type)
721 const replicate_t *rep;
723 va_start(ap, n_buckets);
724 rep = replicate_get(dpo.dpoi_index);
725 res = fib_test_validate_rep_v(rep, n_buckets, &ap);
730 const load_balance_t *lb;
732 FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type),
733 "%U Entry links to %U",
734 format_fib_prefix, pfx,
735 format_dpo_type, dpo.dpoi_type);
737 va_start(ap, n_buckets);
738 lb = load_balance_get(dpo.dpoi_index);
739 res = fib_test_validate_lb_v(lb, n_buckets, &ap);
743 * ensure that the LB contributed by the entry is the
744 * same as the LB in the forwarding tables
746 if (fct == fib_entry_get_default_chain_type(fib_entry_get(fei)))
748 switch (pfx->fp_proto)
750 case FIB_PROTOCOL_IP4:
751 fw_lbi = ip4_fib_forwarding_lookup(fib_index, &pfx->fp_addr.ip4);
753 case FIB_PROTOCOL_IP6:
754 fw_lbi = ip6_fib_table_fwding_lookup(fib_index, &pfx->fp_addr.ip6);
756 case FIB_PROTOCOL_MPLS:
758 mpls_unicast_header_t hdr = {
759 .label_exp_s_ttl = 0,
762 vnet_mpls_uc_set_label(&hdr.label_exp_s_ttl, pfx->fp_label);
763 vnet_mpls_uc_set_s(&hdr.label_exp_s_ttl, pfx->fp_eos);
764 hdr.label_exp_s_ttl = clib_host_to_net_u32(hdr.label_exp_s_ttl);
766 fw_lbi = mpls_fib_table_forwarding_lookup(fib_index, &hdr);
772 FIB_TEST_LB((fw_lbi == dpo.dpoi_index),
773 "Contributed LB = FW LB:\n fwd:%U\n cont:%U",
774 format_load_balance, fw_lbi, 0,
775 format_load_balance, dpo.dpoi_index, 0);
788 * In the default table check for the presence and correct forwarding
789 * of the special entries
791 fib_node_index_t dfrt, fei, ai, ai2, locked_ai, ai_01, ai_02, ai_03;
792 const dpo_id_t *dpo, *dpo1, *dpo2, *dpo_drop;
793 const ip_adjacency_t *adj;
794 const load_balance_t *lb;
802 ip46_address_t nh_10_10_10_1 = {
803 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
806 ip46_address_t nh_10_10_10_2 = {
807 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
810 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
811 pool_elts(load_balance_map_pool));
815 /* record the nubmer of load-balances in use before we start */
816 lb_count = pool_elts(load_balance_pool);
818 /* Find or create FIB table 11 */
819 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11,
822 for (ii = 0; ii < 4; ii++)
823 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[ii]->sw_if_index, fib_index);
825 fib_prefix_t pfx_0_0_0_0_s_0 = {
827 .fp_proto = FIB_PROTOCOL_IP4,
837 .fp_proto = FIB_PROTOCOL_IP4,
845 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
847 dfrt = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
848 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
849 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
850 "Default route is DROP");
853 fei = fib_table_lookup(fib_index, &pfx);
854 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all zeros route present");
855 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
856 "all 0s route is DROP");
858 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xffffffff);
860 fei = fib_table_lookup(fib_index, &pfx);
861 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all ones route present");
862 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
863 "all 1s route is DROP");
865 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xe0000000);
867 fei = fib_table_lookup(fib_index, &pfx);
868 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all-mcast route present");
869 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
870 "all-mcast route is DROP");
872 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xf0000000);
874 fei = fib_table_lookup(fib_index, &pfx);
875 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "class-e route present");
876 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
877 "class-e route is DROP");
880 * at this stage there are 5 entries in the test FIB (plus 5 in the default),
881 * all of which are special sourced and so none of which share path-lists.
882 * There are also 2 entries, and 2 non-shared path-lists, in the v6 default
883 * table, and 4 path-lists in the v6 MFIB table and 2 in v4.
887 u32 PNBR = 5+5+2+4+2;
890 * if the IGMP plugin is loaded this adds two more entries to the v4 MFIB
892 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
893 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
894 fib_path_list_pool_size());
895 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
896 fib_entry_pool_size());
899 * add interface routes.
900 * validate presence of /24 attached and /32 recieve.
901 * test for the presence of the receive address in the glean and local adj
903 fib_prefix_t local_pfx = {
905 .fp_proto = FIB_PROTOCOL_IP4,
908 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
913 fib_table_entry_update_one_path(fib_index, &local_pfx,
914 FIB_SOURCE_INTERFACE,
915 (FIB_ENTRY_FLAG_CONNECTED |
916 FIB_ENTRY_FLAG_ATTACHED),
919 tm->hw[0]->sw_if_index,
920 ~0, // invalid fib index
923 FIB_ROUTE_PATH_FLAG_NONE);
924 fei = fib_table_lookup(fib_index, &local_pfx);
925 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
926 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
927 fib_entry_get_flags(fei)),
928 "Flags set on attached interface");
930 ai = fib_entry_get_adj(fei);
931 FIB_TEST((FIB_NODE_INDEX_INVALID != ai),
932 "attached interface route adj present %d", ai);
934 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
935 "attached interface adj is glean");
937 local_pfx.fp_len = 32;
938 fib_table_entry_update_one_path(fib_index, &local_pfx,
939 FIB_SOURCE_INTERFACE,
940 (FIB_ENTRY_FLAG_CONNECTED |
941 FIB_ENTRY_FLAG_LOCAL),
944 tm->hw[0]->sw_if_index,
945 ~0, // invalid fib index
948 FIB_ROUTE_PATH_FLAG_NONE);
949 fei = fib_table_lookup(fib_index, &local_pfx);
950 FIB_TEST(((FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_CONNECTED) ==
951 fib_entry_get_flags(fei)),
952 "Flags set on local interface");
954 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
956 dpo = fib_entry_contribute_ip_forwarding(fei);
957 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
958 "RPF list for local length 0");
959 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
960 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
961 "local interface adj is local");
962 receive_dpo_t *rd = receive_dpo_get(dpo->dpoi_index);
964 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
966 "local interface adj is receive ok");
968 FIB_TEST((2 == fib_table_get_num_entries(fib_index,
970 FIB_SOURCE_INTERFACE)),
971 "2 Interface Source'd prefixes");
972 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
973 &adj->sub_type.glean.rx_pfx.fp_addr)),
974 "attached interface adj is receive ok");
977 * +2 interface routes +2 non-shared path-lists
979 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
980 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
981 fib_path_list_pool_size());
982 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
983 fib_entry_pool_size());
986 * Modify the default route to be via an adj not yet known.
987 * this sources the defalut route with the API source, which is
988 * a higher preference to the DEFAULT_ROUTE source
990 pfx.fp_addr.ip4.as_u32 = 0;
992 fib_table_entry_path_add(fib_index, &pfx,
997 tm->hw[0]->sw_if_index,
998 ~0, // invalid fib index
1001 FIB_ROUTE_PATH_FLAG_NONE);
1002 fei = fib_table_lookup(fib_index, &pfx);
1003 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
1004 "Flags set on API route");
1006 FIB_TEST((fei == dfrt), "default route same index");
1007 ai = fib_entry_get_adj(fei);
1008 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
1010 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1011 "adj is incomplete");
1012 FIB_TEST((0 == ip46_address_cmp(&nh_10_10_10_1, &adj->sub_type.nbr.next_hop)),
1013 "adj nbr next-hop ok");
1014 FIB_TEST((1 == fib_table_get_num_entries(fib_index,
1017 "1 API Source'd prefixes");
1020 * find the adj in the shared db
1022 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1025 tm->hw[0]->sw_if_index);
1026 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
1027 adj_unlock(locked_ai);
1030 * +1 shared path-list
1032 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
1033 fib_path_list_db_size());
1034 FIB_TEST((PNBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
1035 fib_path_list_pool_size());
1036 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
1037 fib_entry_pool_size());
1040 * remove the API source from the default route. We expected
1041 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
1043 pfx.fp_addr.ip4.as_u32 = 0;
1045 fib_table_entry_path_remove(fib_index, &pfx,
1049 tm->hw[0]->sw_if_index,
1050 ~0, // non-recursive path, so no FIB index
1052 FIB_ROUTE_PATH_FLAG_NONE);
1054 fei = fib_table_lookup(fib_index, &pfx);
1056 FIB_TEST((fei == dfrt), "default route same index");
1057 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
1058 "Default route is DROP");
1061 * -1 shared-path-list
1063 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
1064 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
1065 fib_path_list_pool_size());
1066 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
1067 fib_entry_pool_size());
1070 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
1072 fib_prefix_t pfx_10_10_10_1_s_32 = {
1074 .fp_proto = FIB_PROTOCOL_IP4,
1077 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
1080 fib_prefix_t pfx_10_10_10_2_s_32 = {
1082 .fp_proto = FIB_PROTOCOL_IP4,
1085 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
1088 fib_prefix_t pfx_11_11_11_11_s_32 = {
1090 .fp_proto = FIB_PROTOCOL_IP4,
1093 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
1097 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
1100 ip46_address_t nh_12_12_12_12 = {
1101 .ip4.as_u32 = clib_host_to_net_u32(0x0c0c0c0c),
1103 adj_index_t ai_12_12_12_12;
1106 * Add a route via an incomplete ADJ. then complete the ADJ
1107 * Expect the route LB is updated to use complete adj type.
1109 fei = fib_table_entry_update_one_path(fib_index,
1110 &pfx_11_11_11_11_s_32,
1112 FIB_ENTRY_FLAG_ATTACHED,
1114 &pfx_10_10_10_1_s_32.fp_addr,
1115 tm->hw[0]->sw_if_index,
1116 ~0, // invalid fib index
1119 FIB_ROUTE_PATH_FLAG_NONE);
1121 dpo = fib_entry_contribute_ip_forwarding(fei);
1122 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1123 FIB_TEST(DPO_ADJACENCY_INCOMPLETE == dpo1->dpoi_type,
1124 "11.11.11.11/32 via incomplete adj");
1126 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1128 &pfx_10_10_10_1_s_32.fp_addr,
1129 tm->hw[0]->sw_if_index);
1130 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
1131 adj = adj_get(ai_01);
1132 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1133 "adj is incomplete");
1134 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1135 &adj->sub_type.nbr.next_hop)),
1136 "adj nbr next-hop ok");
1138 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1139 fib_test_build_rewrite(eth_addr));
1140 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1142 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1143 &adj->sub_type.nbr.next_hop)),
1144 "adj nbr next-hop ok");
1145 ai = fib_entry_get_adj(fei);
1146 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
1148 dpo = fib_entry_contribute_ip_forwarding(fei);
1149 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1150 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type,
1151 "11.11.11.11/32 via complete adj");
1152 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1153 tm->hw[0]->sw_if_index),
1154 "RPF list for adj-fib contains adj");
1156 ai_12_12_12_12 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1159 tm->hw[1]->sw_if_index);
1160 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_12_12_12_12), "adj created");
1161 adj = adj_get(ai_12_12_12_12);
1162 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1163 "adj is incomplete");
1164 FIB_TEST((0 == ip46_address_cmp(&nh_12_12_12_12,
1165 &adj->sub_type.nbr.next_hop)),
1166 "adj nbr next-hop ok");
1167 adj_nbr_update_rewrite(ai_12_12_12_12, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1168 fib_test_build_rewrite(eth_addr));
1169 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1175 fei = fib_table_entry_path_add(fib_index,
1176 &pfx_10_10_10_1_s_32,
1178 FIB_ENTRY_FLAG_ATTACHED,
1180 &pfx_10_10_10_1_s_32.fp_addr,
1181 tm->hw[0]->sw_if_index,
1182 ~0, // invalid fib index
1185 FIB_ROUTE_PATH_FLAG_NONE);
1186 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
1187 "Flags set on adj-fib");
1188 ai = fib_entry_get_adj(fei);
1189 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj, %d", ai);
1191 fib_table_entry_path_remove(fib_index,
1192 &pfx_11_11_11_11_s_32,
1195 &pfx_10_10_10_1_s_32.fp_addr,
1196 tm->hw[0]->sw_if_index,
1197 ~0, // invalid fib index
1199 FIB_ROUTE_PATH_FLAG_NONE);
1203 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1205 &pfx_10_10_10_2_s_32.fp_addr,
1206 tm->hw[0]->sw_if_index);
1207 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
1208 adj = adj_get(ai_02);
1209 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1210 "adj is incomplete");
1211 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1212 &adj->sub_type.nbr.next_hop)),
1213 "adj nbr next-hop ok");
1215 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1216 fib_test_build_rewrite(eth_addr));
1217 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1219 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1220 &adj->sub_type.nbr.next_hop)),
1221 "adj nbr next-hop ok");
1222 FIB_TEST((ai_01 != ai_02), "ADJs are different");
1224 fib_table_entry_path_add(fib_index,
1225 &pfx_10_10_10_2_s_32,
1227 FIB_ENTRY_FLAG_ATTACHED,
1229 &pfx_10_10_10_2_s_32.fp_addr,
1230 tm->hw[0]->sw_if_index,
1231 ~0, // invalid fib index
1234 FIB_ROUTE_PATH_FLAG_NONE);
1236 fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32);
1237 ai = fib_entry_get_adj(fei);
1238 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
1241 * +2 adj-fibs, and their non-shared path-lists
1243 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
1244 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
1245 fib_path_list_pool_size());
1246 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
1247 fib_entry_pool_size());
1250 * Add 2 routes via the first ADJ. ensure path-list sharing
1252 fib_prefix_t pfx_1_1_1_1_s_32 = {
1254 .fp_proto = FIB_PROTOCOL_IP4,
1257 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1261 fib_table_entry_path_add(fib_index,
1264 FIB_ENTRY_FLAG_NONE,
1267 tm->hw[0]->sw_if_index,
1268 ~0, // invalid fib index
1271 FIB_ROUTE_PATH_FLAG_NONE);
1272 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
1273 ai = fib_entry_get_adj(fei);
1274 FIB_TEST((ai_01 == ai), "1.1.1.1 resolves via 10.10.10.1");
1277 * +1 entry and a shared path-list
1279 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
1280 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1281 fib_path_list_pool_size());
1282 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
1283 fib_entry_pool_size());
1286 fib_prefix_t pfx_1_1_2_0_s_24 = {
1288 .fp_proto = FIB_PROTOCOL_IP4,
1290 .ip4.as_u32 = clib_host_to_net_u32(0x01010200),
1294 fib_table_entry_path_add(fib_index,
1297 FIB_ENTRY_FLAG_NONE,
1300 tm->hw[0]->sw_if_index,
1301 ~0, // invalid fib index
1304 FIB_ROUTE_PATH_FLAG_NONE);
1305 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1306 ai = fib_entry_get_adj(fei);
1307 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1312 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
1313 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1314 fib_path_list_pool_size());
1315 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1316 fib_entry_pool_size());
1319 * modify 1.1.2.0/24 to use multipath.
1321 fib_table_entry_path_add(fib_index,
1324 FIB_ENTRY_FLAG_NONE,
1327 tm->hw[0]->sw_if_index,
1328 ~0, // invalid fib index
1331 FIB_ROUTE_PATH_FLAG_NONE);
1332 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1333 dpo = fib_entry_contribute_ip_forwarding(fei);
1334 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1335 1, tm->hw[0]->sw_if_index),
1336 "RPF list for 1.1.2.0/24 contains both adjs");
1338 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1339 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1340 FIB_TEST((ai_01 == dpo1->dpoi_index),
1341 "1.1.2.0/24 bucket 0 resolves via 10.10.10.1 (%d=%d)",
1342 ai_01, dpo1->dpoi_index);
1344 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 1);
1345 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1346 FIB_TEST((ai_02 == dpo1->dpoi_index),
1347 "1.1.2.0/24 bucket 1 resolves via 10.10.10.2");
1350 * +1 shared-pathlist
1352 FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty");
1353 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1354 fib_path_list_pool_size());
1355 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1356 fib_entry_pool_size());
1361 fib_table_entry_path_remove(fib_index,
1366 tm->hw[0]->sw_if_index,
1369 FIB_ROUTE_PATH_FLAG_NONE);
1370 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1371 dpo = fib_entry_contribute_ip_forwarding(fei);
1372 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1373 1, tm->hw[0]->sw_if_index),
1374 "RPF list for 1.1.2.0/24 contains one adj");
1376 ai = fib_entry_get_adj(fei);
1377 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1380 * +1 shared-pathlist
1382 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d",
1383 fib_path_list_db_size());
1384 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1385 fib_path_list_pool_size());
1386 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1387 fib_entry_pool_size());
1390 * Add 2 recursive routes:
1391 * 100.100.100.100/32 via 1.1.1.1/32 => the via entry is installed.
1392 * 100.100.100.101/32 via 1.1.1.1/32 => the via entry is installed.
1394 fib_prefix_t bgp_100_pfx = {
1396 .fp_proto = FIB_PROTOCOL_IP4,
1398 /* 100.100.100.100/32 */
1399 .ip4.as_u32 = clib_host_to_net_u32(0x64646464),
1403 ip46_address_t nh_1_1_1_1 = {
1404 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1407 fei = fib_table_entry_path_add(fib_index,
1410 FIB_ENTRY_FLAG_NONE,
1413 ~0, // no index provided.
1414 fib_index, // nexthop in same fib as route
1417 FIB_ROUTE_PATH_FLAG_NONE);
1419 FIB_TEST_REC_FORW(&bgp_100_pfx, &pfx_1_1_1_1_s_32, 0);
1420 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1421 tm->hw[0]->sw_if_index),
1422 "RPF list for adj-fib contains adj");
1425 * +1 entry and +1 shared-path-list
1427 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1428 fib_path_list_db_size());
1429 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1430 fib_path_list_pool_size());
1431 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
1432 fib_entry_pool_size());
1434 fib_prefix_t bgp_101_pfx = {
1436 .fp_proto = FIB_PROTOCOL_IP4,
1438 /* 100.100.100.101/32 */
1439 .ip4.as_u32 = clib_host_to_net_u32(0x64646465),
1443 fib_table_entry_path_add(fib_index,
1446 FIB_ENTRY_FLAG_NONE,
1449 ~0, // no index provided.
1450 fib_index, // nexthop in same fib as route
1453 FIB_ROUTE_PATH_FLAG_NONE);
1455 FIB_TEST_REC_FORW(&bgp_101_pfx, &pfx_1_1_1_1_s_32, 0);
1456 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1457 tm->hw[0]->sw_if_index),
1458 "RPF list for adj-fib contains adj");
1461 * +1 entry, but the recursive path-list is shared.
1463 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1464 fib_path_list_db_size());
1465 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1466 fib_path_list_pool_size());
1467 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
1468 fib_entry_pool_size());
1471 * An special route; one where the user (me) provides the
1472 * adjacency through which the route will resovle by setting the flags
1474 fib_prefix_t ex_pfx = {
1476 .fp_proto = FIB_PROTOCOL_IP4,
1479 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
1483 fib_table_entry_special_add(fib_index,
1486 FIB_ENTRY_FLAG_LOCAL);
1487 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1488 dpo = fib_entry_contribute_ip_forwarding(fei);
1489 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
1490 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
1491 "local interface adj is local");
1493 fib_table_entry_special_remove(fib_index,
1495 FIB_SOURCE_SPECIAL);
1496 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1497 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1498 "Exclusive reoute removed");
1501 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1502 * adjacency through which the route will resovle
1504 dpo_id_t ex_dpo = DPO_INVALID;
1506 lookup_dpo_add_or_lock_w_fib_index(fib_index,
1509 LOOKUP_INPUT_DST_ADDR,
1510 LOOKUP_TABLE_FROM_CONFIG,
1513 fib_table_entry_special_dpo_add(fib_index,
1516 FIB_ENTRY_FLAG_EXCLUSIVE,
1518 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1519 dpo = fib_entry_contribute_ip_forwarding(fei);
1520 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1521 "exclusive remote uses lookup DPO");
1524 * update the exclusive to use a different DPO
1526 ip_null_dpo_add_and_lock(DPO_PROTO_IP4,
1527 IP_NULL_ACTION_SEND_ICMP_UNREACH,
1529 fib_table_entry_special_dpo_update(fib_index,
1532 FIB_ENTRY_FLAG_EXCLUSIVE,
1534 dpo = fib_entry_contribute_ip_forwarding(fei);
1535 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1536 "exclusive remote uses now uses NULL DPO");
1538 fib_table_entry_special_remove(fib_index,
1540 FIB_SOURCE_SPECIAL);
1541 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1542 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1543 "Exclusive reoute removed");
1547 * Add a recursive route:
1548 * 200.200.200.200/32 via 1.1.1.2/32 => the via entry is NOT installed.
1550 fib_prefix_t bgp_200_pfx = {
1552 .fp_proto = FIB_PROTOCOL_IP4,
1554 /* 200.200.200.200/32 */
1555 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c8),
1559 fib_prefix_t pfx_1_1_1_2_s_32 = {
1561 .fp_proto = FIB_PROTOCOL_IP4,
1563 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
1567 fei = fib_table_entry_path_add(fib_index,
1570 FIB_ENTRY_FLAG_NONE,
1572 &pfx_1_1_1_2_s_32.fp_addr,
1573 ~0, // no index provided.
1574 fib_index, // nexthop in same fib as route
1577 FIB_ROUTE_PATH_FLAG_NONE);
1579 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
1580 "Recursive via unresolved is drop");
1583 * the adj should be recursive via drop, since the route resolves via
1584 * the default route, which is itself a DROP
1586 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
1587 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1588 FIB_TEST(load_balance_is_drop(dpo1), "1.1.1.2/32 is drop");
1589 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1590 "RPF list for 1.1.1.2/32 contains 0 adjs");
1593 * +2 entry and +1 shared-path-list
1595 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
1596 fib_path_list_db_size());
1597 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
1598 fib_path_list_pool_size());
1599 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
1600 fib_entry_pool_size());
1603 * Unequal Cost load-balance. 3:1 ratio. fits in a 4 bucket LB
1604 * The paths are sort by NH first. in this case the the path with greater
1605 * weight is first in the set. This ordering is to test the RPF sort|uniq logic
1607 fib_prefix_t pfx_1_2_3_4_s_32 = {
1609 .fp_proto = FIB_PROTOCOL_IP4,
1611 .ip4.as_u32 = clib_host_to_net_u32(0x01020304),
1614 fib_table_entry_path_add(fib_index,
1617 FIB_ENTRY_FLAG_NONE,
1620 tm->hw[0]->sw_if_index,
1624 FIB_ROUTE_PATH_FLAG_NONE);
1625 fei = fib_table_entry_path_add(fib_index,
1628 FIB_ENTRY_FLAG_NONE,
1631 tm->hw[1]->sw_if_index,
1635 FIB_ROUTE_PATH_FLAG_NONE);
1637 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.4/32 presnet");
1638 dpo = fib_entry_contribute_ip_forwarding(fei);
1639 lb = load_balance_get(dpo->dpoi_index);
1640 FIB_TEST((lb->lb_n_buckets == 4),
1641 "1.2.3.4/32 LB has %d bucket",
1644 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 0, ai_12_12_12_12);
1645 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 1, ai_12_12_12_12);
1646 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 2, ai_12_12_12_12);
1647 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 3, ai_01);
1649 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1650 tm->hw[0]->sw_if_index,
1651 tm->hw[1]->sw_if_index),
1652 "RPF list for 1.2.3.4/32 contains both adjs");
1656 * Unequal Cost load-balance. 4:1 ratio.
1657 * fits in a 16 bucket LB with ratio 13:3
1659 fib_prefix_t pfx_1_2_3_5_s_32 = {
1661 .fp_proto = FIB_PROTOCOL_IP4,
1663 .ip4.as_u32 = clib_host_to_net_u32(0x01020305),
1666 fib_table_entry_path_add(fib_index,
1669 FIB_ENTRY_FLAG_NONE,
1672 tm->hw[1]->sw_if_index,
1676 FIB_ROUTE_PATH_FLAG_NONE);
1677 fei = fib_table_entry_path_add(fib_index,
1680 FIB_ENTRY_FLAG_NONE,
1683 tm->hw[0]->sw_if_index,
1687 FIB_ROUTE_PATH_FLAG_NONE);
1689 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.5/32 presnet");
1690 dpo = fib_entry_contribute_ip_forwarding(fei);
1691 lb = load_balance_get(dpo->dpoi_index);
1692 FIB_TEST((lb->lb_n_buckets == 16),
1693 "1.2.3.5/32 LB has %d bucket",
1696 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 0, ai_01);
1697 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 1, ai_01);
1698 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 2, ai_01);
1699 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 3, ai_01);
1700 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 4, ai_01);
1701 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 5, ai_01);
1702 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 6, ai_01);
1703 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 7, ai_01);
1704 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 8, ai_01);
1705 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 9, ai_01);
1706 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 10, ai_01);
1707 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 11, ai_01);
1708 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 12, ai_01);
1709 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 13, ai_12_12_12_12);
1710 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 14, ai_12_12_12_12);
1711 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 15, ai_12_12_12_12);
1713 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1714 tm->hw[0]->sw_if_index,
1715 tm->hw[1]->sw_if_index),
1716 "RPF list for 1.2.3.4/32 contains both adjs");
1719 * Test UCMP with a large weight skew - this produces load-balance objects with large
1720 * numbers of buckets to accommodate the skew. By updating said load-balances we are
1721 * laso testing the LB in placce modify code when number of buckets is large.
1723 fib_prefix_t pfx_6_6_6_6_s_32 = {
1725 .fp_proto = FIB_PROTOCOL_IP4,
1728 .ip4.as_u32 = clib_host_to_net_u32(0x06060606),
1731 fib_test_lb_bucket_t ip_o_10_10_10_1 = {
1737 fib_test_lb_bucket_t ip_o_10_10_10_2 = {
1743 fib_test_lb_bucket_t ip_6_6_6_6_o_12_12_12_12 = {
1746 .adj = ai_12_12_12_12,
1749 fib_table_entry_update_one_path(fib_index,
1752 FIB_ENTRY_FLAG_NONE,
1755 tm->hw[0]->sw_if_index,
1756 ~0, // invalid fib index
1759 FIB_ROUTE_PATH_FLAG_NONE);
1761 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1762 FIB_TEST(!fib_test_validate_entry(fei,
1763 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1766 "6.6.6.6/32 via 10.10.10.1");
1768 fib_table_entry_path_add(fib_index,
1771 FIB_ENTRY_FLAG_NONE,
1774 tm->hw[0]->sw_if_index,
1775 ~0, // invalid fib index
1778 FIB_ROUTE_PATH_FLAG_NONE);
1780 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1781 FIB_TEST(!fib_test_validate_entry(fei,
1782 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1848 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1850 fib_table_entry_path_add(fib_index,
1853 FIB_ENTRY_FLAG_NONE,
1856 tm->hw[1]->sw_if_index,
1857 ~0, // invalid fib index
1860 FIB_ROUTE_PATH_FLAG_NONE);
1862 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1863 FIB_TEST(!fib_test_validate_entry(fei,
1864 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1931 &ip_6_6_6_6_o_12_12_12_12,
1932 &ip_6_6_6_6_o_12_12_12_12,
1933 &ip_6_6_6_6_o_12_12_12_12,
1934 &ip_6_6_6_6_o_12_12_12_12,
1935 &ip_6_6_6_6_o_12_12_12_12,
1936 &ip_6_6_6_6_o_12_12_12_12,
1937 &ip_6_6_6_6_o_12_12_12_12,
1938 &ip_6_6_6_6_o_12_12_12_12,
1939 &ip_6_6_6_6_o_12_12_12_12,
1940 &ip_6_6_6_6_o_12_12_12_12,
1941 &ip_6_6_6_6_o_12_12_12_12,
1942 &ip_6_6_6_6_o_12_12_12_12,
1943 &ip_6_6_6_6_o_12_12_12_12,
1944 &ip_6_6_6_6_o_12_12_12_12,
1945 &ip_6_6_6_6_o_12_12_12_12,
1946 &ip_6_6_6_6_o_12_12_12_12,
1947 &ip_6_6_6_6_o_12_12_12_12,
1948 &ip_6_6_6_6_o_12_12_12_12,
1949 &ip_6_6_6_6_o_12_12_12_12,
1950 &ip_6_6_6_6_o_12_12_12_12,
1951 &ip_6_6_6_6_o_12_12_12_12,
1952 &ip_6_6_6_6_o_12_12_12_12,
1953 &ip_6_6_6_6_o_12_12_12_12,
1954 &ip_6_6_6_6_o_12_12_12_12,
1955 &ip_6_6_6_6_o_12_12_12_12,
1956 &ip_6_6_6_6_o_12_12_12_12,
1957 &ip_6_6_6_6_o_12_12_12_12,
1958 &ip_6_6_6_6_o_12_12_12_12,
1959 &ip_6_6_6_6_o_12_12_12_12,
1960 &ip_6_6_6_6_o_12_12_12_12,
1961 &ip_6_6_6_6_o_12_12_12_12,
1962 &ip_6_6_6_6_o_12_12_12_12,
1963 &ip_6_6_6_6_o_12_12_12_12,
1964 &ip_6_6_6_6_o_12_12_12_12,
1965 &ip_6_6_6_6_o_12_12_12_12,
1966 &ip_6_6_6_6_o_12_12_12_12,
1967 &ip_6_6_6_6_o_12_12_12_12,
1968 &ip_6_6_6_6_o_12_12_12_12,
1969 &ip_6_6_6_6_o_12_12_12_12,
1970 &ip_6_6_6_6_o_12_12_12_12,
1971 &ip_6_6_6_6_o_12_12_12_12,
1972 &ip_6_6_6_6_o_12_12_12_12,
1973 &ip_6_6_6_6_o_12_12_12_12,
1974 &ip_6_6_6_6_o_12_12_12_12,
1975 &ip_6_6_6_6_o_12_12_12_12,
1976 &ip_6_6_6_6_o_12_12_12_12,
1977 &ip_6_6_6_6_o_12_12_12_12,
1978 &ip_6_6_6_6_o_12_12_12_12,
1979 &ip_6_6_6_6_o_12_12_12_12,
1980 &ip_6_6_6_6_o_12_12_12_12,
1981 &ip_6_6_6_6_o_12_12_12_12,
1982 &ip_6_6_6_6_o_12_12_12_12,
1983 &ip_6_6_6_6_o_12_12_12_12,
1984 &ip_6_6_6_6_o_12_12_12_12,
1985 &ip_6_6_6_6_o_12_12_12_12,
1986 &ip_6_6_6_6_o_12_12_12_12,
1987 &ip_6_6_6_6_o_12_12_12_12,
1988 &ip_6_6_6_6_o_12_12_12_12,
1989 &ip_6_6_6_6_o_12_12_12_12,
1990 &ip_6_6_6_6_o_12_12_12_12,
1991 &ip_6_6_6_6_o_12_12_12_12,
1992 &ip_6_6_6_6_o_12_12_12_12,
1993 &ip_6_6_6_6_o_12_12_12_12),
1994 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1996 fib_table_entry_path_remove(fib_index,
2001 tm->hw[1]->sw_if_index,
2002 ~0, // invalid fib index
2004 FIB_ROUTE_PATH_FLAG_NONE);
2006 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
2007 FIB_TEST(!fib_test_validate_entry(fei,
2008 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2074 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
2076 fib_table_entry_path_remove(fib_index,
2081 tm->hw[0]->sw_if_index,
2082 ~0, // invalid fib index
2084 FIB_ROUTE_PATH_FLAG_NONE);
2086 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
2087 FIB_TEST(!fib_test_validate_entry(fei,
2088 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2091 "6.6.6.6/32 via 10.10.10.1");
2093 fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API);
2096 * A recursive via the two unequal cost entries
2098 fib_prefix_t bgp_44_s_32 = {
2100 .fp_proto = FIB_PROTOCOL_IP4,
2102 /* 200.200.200.201/32 */
2103 .ip4.as_u32 = clib_host_to_net_u32(0x44444444),
2106 fei = fib_table_entry_path_add(fib_index,
2109 FIB_ENTRY_FLAG_NONE,
2111 &pfx_1_2_3_4_s_32.fp_addr,
2116 FIB_ROUTE_PATH_FLAG_NONE);
2117 fei = fib_table_entry_path_add(fib_index,
2120 FIB_ENTRY_FLAG_NONE,
2122 &pfx_1_2_3_5_s_32.fp_addr,
2127 FIB_ROUTE_PATH_FLAG_NONE);
2129 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_4_s_32, 0);
2130 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_5_s_32, 1);
2131 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
2132 tm->hw[0]->sw_if_index,
2133 tm->hw[1]->sw_if_index),
2134 "RPF list for 1.2.3.4/32 contains both adjs");
2137 * test the uRPF check functions
2139 dpo_id_t dpo_44 = DPO_INVALID;
2142 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
2143 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
2145 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
2146 "uRPF check for 68.68.68.68/32 on %d OK",
2147 tm->hw[0]->sw_if_index);
2148 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
2149 "uRPF check for 68.68.68.68/32 on %d OK",
2150 tm->hw[1]->sw_if_index);
2151 FIB_TEST(!fib_urpf_check(urpfi, 99),
2152 "uRPF check for 68.68.68.68/32 on 99 not-OK",
2156 fib_table_entry_delete(fib_index,
2159 fib_table_entry_delete(fib_index,
2162 fib_table_entry_delete(fib_index,
2167 * Add a recursive route:
2168 * 200.200.200.201/32 via 1.1.1.200/32 => the via entry is NOT installed.
2170 fib_prefix_t bgp_201_pfx = {
2172 .fp_proto = FIB_PROTOCOL_IP4,
2174 /* 200.200.200.201/32 */
2175 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c9),
2179 fib_prefix_t pfx_1_1_1_200_s_32 = {
2181 .fp_proto = FIB_PROTOCOL_IP4,
2183 .ip4.as_u32 = clib_host_to_net_u32(0x010101c8),
2187 fei = fib_table_entry_path_add(fib_index,
2190 FIB_ENTRY_FLAG_NONE,
2192 &pfx_1_1_1_200_s_32.fp_addr,
2193 ~0, // no index provided.
2194 fib_index, // nexthop in same fib as route
2197 FIB_ROUTE_PATH_FLAG_NONE);
2199 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2200 "Recursive via unresolved is drop");
2202 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2203 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
2204 "Flags set on RR via non-attached");
2205 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
2206 "RPF list for BGP route empty");
2209 * +2 entry (BGP & RR) and +1 shared-path-list
2211 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2212 fib_path_list_db_size());
2213 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2214 fib_path_list_pool_size());
2215 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2216 fib_entry_pool_size());
2219 * insert a route that covers the missing 1.1.1.2/32. we epxect
2220 * 200.200.200.200/32 and 200.200.200.201/32 to resolve through it.
2222 fib_prefix_t pfx_1_1_1_0_s_24 = {
2224 .fp_proto = FIB_PROTOCOL_IP4,
2227 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2231 fib_table_entry_path_add(fib_index,
2234 FIB_ENTRY_FLAG_NONE,
2237 tm->hw[0]->sw_if_index,
2238 ~0, // invalid fib index
2241 FIB_ROUTE_PATH_FLAG_NONE);
2242 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24);
2243 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2244 ai = fib_entry_get_adj(fei);
2245 FIB_TEST((ai_01 == ai), "1.1.1.0/24 resolves via 10.10.10.1");
2246 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2247 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2248 ai = fib_entry_get_adj(fei);
2249 FIB_TEST((ai_01 == ai), "1.1.1.2/32 resolves via 10.10.10.1");
2250 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2251 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2252 ai = fib_entry_get_adj(fei);
2253 FIB_TEST((ai_01 == ai), "1.1.1.200/24 resolves via 10.10.10.1");
2256 * +1 entry. 1.1.1.1/32 already uses 10.10.10.1 so no new pah-list
2258 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2259 fib_path_list_db_size());
2260 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2261 fib_path_list_pool_size());
2262 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
2263 fib_entry_pool_size());
2266 * the recursive adj for 200.200.200.200 should be updated.
2268 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2269 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2270 fei = fib_table_lookup(fib_index, &bgp_200_pfx);
2271 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
2272 tm->hw[0]->sw_if_index),
2273 "RPF list for BGP route has itf index 0");
2276 * insert a more specific route than 1.1.1.0/24 that also covers the
2277 * missing 1.1.1.2/32, but not 1.1.1.200/32. we expect
2278 * 200.200.200.200 to resolve through it.
2280 fib_prefix_t pfx_1_1_1_0_s_28 = {
2282 .fp_proto = FIB_PROTOCOL_IP4,
2285 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2289 fib_table_entry_path_add(fib_index,
2292 FIB_ENTRY_FLAG_NONE,
2295 tm->hw[0]->sw_if_index,
2296 ~0, // invalid fib index
2299 FIB_ROUTE_PATH_FLAG_NONE);
2300 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28);
2301 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2302 ai = fib_entry_get_adj(fei);
2303 FIB_TEST((ai_02 == ai), "1.1.1.0/24 resolves via 10.10.10.2");
2306 * +1 entry. +1 shared path-list
2308 FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d",
2309 fib_path_list_db_size());
2310 FIB_TEST((PNBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
2311 fib_path_list_pool_size());
2312 FIB_TEST((ENBR+14 == fib_entry_pool_size()), "entry pool size is %d",
2313 fib_entry_pool_size());
2316 * the recursive adj for 200.200.200.200 should be updated.
2317 * 200.200.200.201 remains unchanged.
2319 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2320 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2323 * remove this /28. 200.200.200.200/32 should revert back to via 1.1.1.0/24
2325 fib_table_entry_path_remove(fib_index,
2330 tm->hw[0]->sw_if_index,
2333 FIB_ROUTE_PATH_FLAG_NONE);
2334 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28) ==
2335 FIB_NODE_INDEX_INVALID),
2336 "1.1.1.0/28 removed");
2337 FIB_TEST((fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28) ==
2338 fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24)),
2339 "1.1.1.0/28 lookup via /24");
2340 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2341 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2344 * -1 entry. -1 shared path-list
2346 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2347 fib_path_list_db_size());
2348 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2349 fib_path_list_pool_size());
2350 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
2351 fib_entry_pool_size());
2354 * remove 1.1.1.0/24. 200.200.200.200/32 should revert back to via 0.0.0.0/0
2356 fib_table_entry_path_remove(fib_index,
2361 tm->hw[0]->sw_if_index,
2364 FIB_ROUTE_PATH_FLAG_NONE);
2365 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_24) ==
2366 FIB_NODE_INDEX_INVALID),
2367 "1.1.1.0/24 removed");
2369 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2370 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2371 "1.1.1.2/32 route is DROP");
2372 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2373 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2374 "1.1.1.200/32 route is DROP");
2376 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2377 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2379 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2380 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2386 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2387 fib_path_list_db_size());
2388 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2389 fib_path_list_pool_size());
2390 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2391 fib_entry_pool_size());
2394 * insert the missing 1.1.1.2/32
2396 fei = fib_table_entry_path_add(fib_index,
2399 FIB_ENTRY_FLAG_NONE,
2402 tm->hw[0]->sw_if_index,
2403 ~0, // invalid fib index
2406 FIB_ROUTE_PATH_FLAG_NONE);
2407 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2408 ai = fib_entry_get_adj(fei);
2409 FIB_TEST((ai = ai_01), "1.1.1.2/32 resolves via 10.10.10.1");
2411 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2412 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2414 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2417 * no change. 1.1.1.2/32 was already there RR sourced.
2419 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2420 fib_path_list_db_size());
2421 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2422 fib_path_list_pool_size());
2423 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2424 fib_entry_pool_size());
2427 * give 201 a resolved path.
2428 * it now has the unresolved 1.1.1.200 and the resolved 1.1.1.2,
2429 * only the latter contributes forwarding.
2431 fei = fib_table_entry_path_add(fib_index,
2434 FIB_ENTRY_FLAG_NONE,
2436 &pfx_1_1_1_2_s_32.fp_addr,
2441 FIB_ROUTE_PATH_FLAG_NONE);
2442 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_2_s_32, 0);
2443 fib_table_entry_path_remove(fib_index,
2447 &pfx_1_1_1_2_s_32.fp_addr,
2451 FIB_ROUTE_PATH_FLAG_NONE);
2454 * remove 200.200.200.201/32 which does not have a valid via FIB
2456 fib_table_entry_path_remove(fib_index,
2460 &pfx_1_1_1_200_s_32.fp_addr,
2461 ~0, // no index provided.
2464 FIB_ROUTE_PATH_FLAG_NONE);
2467 * -2 entries (BGP and RR). -1 shared path-list;
2469 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2470 FIB_NODE_INDEX_INVALID),
2471 "200.200.200.201/32 removed");
2472 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32) ==
2473 FIB_NODE_INDEX_INVALID),
2474 "1.1.1.200/32 removed");
2476 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2477 fib_path_list_db_size());
2478 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
2479 fib_path_list_pool_size());
2480 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2481 fib_entry_pool_size());
2484 * remove 200.200.200.200/32 which does have a valid via FIB
2486 fib_table_entry_path_remove(fib_index,
2490 &pfx_1_1_1_2_s_32.fp_addr,
2491 ~0, // no index provided.
2494 FIB_ROUTE_PATH_FLAG_NONE);
2496 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2497 FIB_NODE_INDEX_INVALID),
2498 "200.200.200.200/32 removed");
2499 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32) !=
2500 FIB_NODE_INDEX_INVALID),
2501 "1.1.1.2/32 still present");
2504 * -1 entry (BGP, the RR source is also API sourced). -1 shared path-list;
2506 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2507 fib_path_list_db_size());
2508 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2509 fib_path_list_pool_size());
2510 FIB_TEST((ENBR+9 == fib_entry_pool_size()), "entry pool size is %d",
2511 fib_entry_pool_size());
2514 * A recursive prefix that has a 2 path load-balance.
2515 * It also shares a next-hop with other BGP prefixes and hence
2516 * test the ref counting of RR sourced prefixes and 2 level LB.
2518 const fib_prefix_t bgp_102 = {
2520 .fp_proto = FIB_PROTOCOL_IP4,
2522 /* 100.100.100.101/32 */
2523 .ip4.as_u32 = clib_host_to_net_u32(0x64646466),
2526 fib_table_entry_path_add(fib_index,
2529 FIB_ENTRY_FLAG_NONE,
2531 &pfx_1_1_1_1_s_32.fp_addr,
2532 ~0, // no index provided.
2533 fib_index, // same as route
2536 FIB_ROUTE_PATH_FLAG_NONE);
2537 fib_table_entry_path_add(fib_index,
2540 FIB_ENTRY_FLAG_NONE,
2542 &pfx_1_1_1_2_s_32.fp_addr,
2543 ~0, // no index provided.
2544 fib_index, // same as route's FIB
2547 FIB_ROUTE_PATH_FLAG_NONE);
2548 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2549 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "100.100.100.102/32 presnet");
2550 dpo = fib_entry_contribute_ip_forwarding(fei);
2552 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2553 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2554 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32);
2555 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2557 lb = load_balance_get(dpo->dpoi_index);
2558 FIB_TEST((lb->lb_n_buckets == 2), "Recursive LB has %d bucket", lb->lb_n_buckets);
2559 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2560 "First via 10.10.10.1");
2561 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 1)),
2562 "Second via 10.10.10.1");
2564 fib_table_entry_path_remove(fib_index,
2568 &pfx_1_1_1_1_s_32.fp_addr,
2569 ~0, // no index provided.
2570 fib_index, // same as route's FIB
2572 FIB_ROUTE_PATH_FLAG_NONE);
2573 fib_table_entry_path_remove(fib_index,
2577 &pfx_1_1_1_2_s_32.fp_addr,
2578 ~0, // no index provided.
2579 fib_index, // same as route's FIB
2581 FIB_ROUTE_PATH_FLAG_NONE);
2582 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2583 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "100.100.100.102/32 removed");
2586 * remove the remaining recursives
2588 fib_table_entry_path_remove(fib_index,
2592 &pfx_1_1_1_1_s_32.fp_addr,
2593 ~0, // no index provided.
2594 fib_index, // same as route's FIB
2596 FIB_ROUTE_PATH_FLAG_NONE);
2597 fib_table_entry_path_remove(fib_index,
2601 &pfx_1_1_1_1_s_32.fp_addr,
2602 ~0, // no index provided.
2603 fib_index, // same as route's FIB
2605 FIB_ROUTE_PATH_FLAG_NONE);
2606 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_100_pfx) ==
2607 FIB_NODE_INDEX_INVALID),
2608 "100.100.100.100/32 removed");
2609 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_101_pfx) ==
2610 FIB_NODE_INDEX_INVALID),
2611 "100.100.100.101/32 removed");
2614 * -2 entry (2*BGP, the RR source is also API sourced). -1 shared path-list;
2616 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2617 fib_path_list_db_size());
2618 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2619 fib_path_list_pool_size());
2620 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2621 fib_entry_pool_size());
2624 * Add a recursive route via a connected cover, using an adj-fib that does exist
2626 fib_table_entry_path_add(fib_index,
2629 FIB_ENTRY_FLAG_NONE,
2632 ~0, // no index provided.
2633 fib_index, // Same as route's FIB
2636 FIB_ROUTE_PATH_FLAG_NONE);
2639 * +1 entry. +1 shared path-list (recursive via 10.10.10.1)
2641 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2642 fib_path_list_db_size());
2643 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2644 fib_path_list_pool_size());
2645 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
2646 fib_entry_pool_size());
2648 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2649 dpo = fib_entry_contribute_ip_forwarding(fei);
2651 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
2652 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2654 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2655 "200.200.200.200/32 is recursive via adj for 10.10.10.1");
2657 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
2658 "Flags set on RR via existing attached");
2661 * Add a recursive route via a connected cover, using and adj-fib that does
2664 ip46_address_t nh_10_10_10_3 = {
2665 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
2667 fib_prefix_t pfx_10_10_10_3 = {
2669 .fp_proto = FIB_PROTOCOL_IP4,
2670 .fp_addr = nh_10_10_10_3,
2673 fib_table_entry_path_add(fib_index,
2676 FIB_ENTRY_FLAG_NONE,
2679 ~0, // no index provided.
2683 FIB_ROUTE_PATH_FLAG_NONE);
2686 * +2 entries (BGP and RR). +1 shared path-list (recursive via 10.10.10.3) and
2687 * one unshared non-recursive via 10.10.10.3
2689 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2690 fib_path_list_db_size());
2691 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2692 fib_path_list_pool_size());
2693 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2694 fib_entry_pool_size());
2696 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
2699 tm->hw[0]->sw_if_index);
2701 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2702 dpo = fib_entry_contribute_ip_forwarding(fei);
2703 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3);
2704 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2706 ai = fib_entry_get_adj(fei);
2707 FIB_TEST((ai == ai_03), "adj for 10.10.10.3/32 is via adj for 10.10.10.3");
2708 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
2709 fib_entry_get_flags(fei)),
2710 "Flags set on RR via non-existing attached");
2712 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2713 "adj for 200.200.200.200/32 is recursive via adj for 10.10.10.3");
2718 * remove the recursives
2720 fib_table_entry_path_remove(fib_index,
2725 ~0, // no index provided.
2726 fib_index, // same as route's FIB
2728 FIB_ROUTE_PATH_FLAG_NONE);
2729 fib_table_entry_path_remove(fib_index,
2734 ~0, // no index provided.
2735 fib_index, // same as route's FIB
2737 FIB_ROUTE_PATH_FLAG_NONE);
2739 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2740 FIB_NODE_INDEX_INVALID),
2741 "200.200.200.201/32 removed");
2742 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2743 FIB_NODE_INDEX_INVALID),
2744 "200.200.200.200/32 removed");
2745 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3) ==
2746 FIB_NODE_INDEX_INVALID),
2747 "10.10.10.3/32 removed");
2750 * -3 entries (2*BGP and RR). -2 shared path-list (recursive via 10.10.10.3 &
2751 * 10.10.10.1) and one unshared non-recursive via 10.10.10.3
2753 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2754 fib_path_list_db_size());
2755 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2756 fib_path_list_pool_size());
2757 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2758 fib_entry_pool_size());
2763 * Add 5.5.5.5/32 -> 5.5.5.6/32 -> 5.5.5.7/32 -> 5.5.5.5/32
2765 fib_prefix_t pfx_5_5_5_5_s_32 = {
2767 .fp_proto = FIB_PROTOCOL_IP4,
2769 .ip4.as_u32 = clib_host_to_net_u32(0x05050505),
2772 fib_prefix_t pfx_5_5_5_6_s_32 = {
2774 .fp_proto = FIB_PROTOCOL_IP4,
2776 .ip4.as_u32 = clib_host_to_net_u32(0x05050506),
2779 fib_prefix_t pfx_5_5_5_7_s_32 = {
2781 .fp_proto = FIB_PROTOCOL_IP4,
2783 .ip4.as_u32 = clib_host_to_net_u32(0x05050507),
2787 fib_table_entry_path_add(fib_index,
2790 FIB_ENTRY_FLAG_NONE,
2792 &pfx_5_5_5_6_s_32.fp_addr,
2793 ~0, // no index provided.
2797 FIB_ROUTE_PATH_FLAG_NONE);
2798 fib_table_entry_path_add(fib_index,
2801 FIB_ENTRY_FLAG_NONE,
2803 &pfx_5_5_5_7_s_32.fp_addr,
2804 ~0, // no index provided.
2808 FIB_ROUTE_PATH_FLAG_NONE);
2809 fib_table_entry_path_add(fib_index,
2812 FIB_ENTRY_FLAG_NONE,
2814 &pfx_5_5_5_5_s_32.fp_addr,
2815 ~0, // no index provided.
2819 FIB_ROUTE_PATH_FLAG_NONE);
2821 * +3 entries, +3 shared path-list
2823 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2824 fib_path_list_db_size());
2825 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2826 fib_path_list_pool_size());
2827 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2828 fib_entry_pool_size());
2831 * All the entries have only looped paths, so they are all drop
2833 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2834 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2835 "LB for 5.5.5.7/32 is via adj for DROP");
2836 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2837 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2838 "LB for 5.5.5.5/32 is via adj for DROP");
2839 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2840 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2841 "LB for 5.5.5.6/32 is via adj for DROP");
2844 * provide 5.5.5.6/32 with alternate path.
2845 * this will allow only 5.5.5.6/32 to forward with this path, the others
2846 * are still drop since the loop is still present.
2848 fib_table_entry_path_add(fib_index,
2851 FIB_ENTRY_FLAG_NONE,
2854 tm->hw[0]->sw_if_index,
2858 FIB_ROUTE_PATH_FLAG_NONE);
2860 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2861 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2863 lb = load_balance_get(dpo1->dpoi_index);
2864 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.6 LB has %d bucket", lb->lb_n_buckets);
2866 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2867 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2868 FIB_TEST((ai_01 == dpo2->dpoi_index),
2869 "5.5.5.6 bucket 0 resolves via 10.10.10.2");
2871 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2872 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2873 "LB for 5.5.5.7/32 is via adj for DROP");
2874 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2875 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2876 "LB for 5.5.5.5/32 is via adj for DROP");
2879 * remove the alternate path for 5.5.5.6/32
2882 fib_table_entry_path_remove(fib_index,
2887 tm->hw[0]->sw_if_index,
2890 FIB_ROUTE_PATH_FLAG_NONE);
2892 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2893 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2894 "LB for 5.5.5.7/32 is via adj for DROP");
2895 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2896 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2897 "LB for 5.5.5.5/32 is via adj for DROP");
2898 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2899 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2900 "LB for 5.5.5.6/32 is via adj for DROP");
2903 * break the loop by giving 5.5.5.5/32 a new set of paths
2904 * expect all to forward via this new path.
2906 fib_table_entry_update_one_path(fib_index,
2909 FIB_ENTRY_FLAG_NONE,
2912 tm->hw[0]->sw_if_index,
2913 ~0, // invalid fib index
2916 FIB_ROUTE_PATH_FLAG_NONE);
2918 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2919 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2920 lb = load_balance_get(dpo1->dpoi_index);
2921 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.5 LB has %d bucket", lb->lb_n_buckets);
2923 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2924 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2925 FIB_TEST((ai_01 == dpo2->dpoi_index),
2926 "5.5.5.5 bucket 0 resolves via 10.10.10.2");
2928 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_7_s_32);
2929 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2931 lb = load_balance_get(dpo2->dpoi_index);
2932 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2933 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo2->dpoi_index, 0)),
2934 "5.5.5.5.7 via 5.5.5.5");
2936 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32);
2937 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2939 lb = load_balance_get(dpo1->dpoi_index);
2940 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2941 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2942 "5.5.5.5.6 via 5.5.5.7");
2945 * revert back to the loop. so we can remove the prefixes with
2948 fib_table_entry_update_one_path(fib_index,
2951 FIB_ENTRY_FLAG_NONE,
2953 &pfx_5_5_5_6_s_32.fp_addr,
2954 ~0, // no index provided.
2958 FIB_ROUTE_PATH_FLAG_NONE);
2960 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2961 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2962 "LB for 5.5.5.7/32 is via adj for DROP");
2963 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2964 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2965 "LB for 5.5.5.5/32 is via adj for DROP");
2966 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2967 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2968 "LB for 5.5.5.6/32 is via adj for DROP");
2971 * remove all the 5.5.5.x/32 prefixes
2973 fib_table_entry_path_remove(fib_index,
2977 &pfx_5_5_5_6_s_32.fp_addr,
2978 ~0, // no index provided.
2979 fib_index, // same as route's FIB
2981 FIB_ROUTE_PATH_FLAG_NONE);
2982 fib_table_entry_path_remove(fib_index,
2986 &pfx_5_5_5_7_s_32.fp_addr,
2987 ~0, // no index provided.
2988 fib_index, // same as route's FIB
2990 FIB_ROUTE_PATH_FLAG_NONE);
2991 fib_table_entry_path_remove(fib_index,
2995 &pfx_5_5_5_5_s_32.fp_addr,
2996 ~0, // no index provided.
2997 fib_index, // same as route's FIB
2999 FIB_ROUTE_PATH_FLAG_NONE);
3000 fib_table_entry_path_remove(fib_index,
3005 ~0, // no index provided.
3006 fib_index, // same as route's FIB
3008 FIB_ROUTE_PATH_FLAG_NONE);
3011 * -3 entries, -3 shared path-list
3013 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3014 fib_path_list_db_size());
3015 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3016 fib_path_list_pool_size());
3017 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3018 fib_entry_pool_size());
3021 * Single level loop 5.5.5.5/32 via 5.5.5.5/32
3023 fib_table_entry_path_add(fib_index,
3026 FIB_ENTRY_FLAG_NONE,
3028 &pfx_5_5_5_6_s_32.fp_addr,
3029 ~0, // no index provided.
3033 FIB_ROUTE_PATH_FLAG_NONE);
3034 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
3035 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
3036 "1-level 5.5.5.6/32 loop is via adj for DROP");
3038 fib_table_entry_path_remove(fib_index,
3042 &pfx_5_5_5_6_s_32.fp_addr,
3043 ~0, // no index provided.
3044 fib_index, // same as route's FIB
3046 FIB_ROUTE_PATH_FLAG_NONE);
3047 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3048 fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32),
3049 "1-level 5.5.5.6/32 loop is removed");
3052 * A recursive route whose next-hop is covered by the prefix.
3053 * This would mean the via-fib, which inherits forwarding from its
3054 * cover, thus picks up forwarding from the prfix, which is via the
3055 * via-fib, and we have a loop.
3057 fib_prefix_t pfx_23_23_23_0_s_24 = {
3059 .fp_proto = FIB_PROTOCOL_IP4,
3061 .ip4.as_u32 = clib_host_to_net_u32(0x17171700),
3064 fib_prefix_t pfx_23_23_23_23_s_32 = {
3066 .fp_proto = FIB_PROTOCOL_IP4,
3068 .ip4.as_u32 = clib_host_to_net_u32(0x17171717),
3071 fei = fib_table_entry_path_add(fib_index,
3072 &pfx_23_23_23_0_s_24,
3074 FIB_ENTRY_FLAG_NONE,
3076 &pfx_23_23_23_23_s_32.fp_addr,
3081 FIB_ROUTE_PATH_FLAG_NONE);
3082 dpo = fib_entry_contribute_ip_forwarding(fei);
3083 FIB_TEST(load_balance_is_drop(dpo),
3084 "23.23.23.0/24 via covered is DROP");
3085 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3088 * add-remove test. no change.
3090 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3091 fib_path_list_db_size());
3092 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3093 fib_path_list_pool_size());
3094 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3095 fib_entry_pool_size());
3098 * Make the default route recursive via a unknown next-hop. Thus the
3099 * next hop's cover would be the default route
3101 fei = fib_table_entry_path_add(fib_index,
3104 FIB_ENTRY_FLAG_NONE,
3106 &pfx_23_23_23_23_s_32.fp_addr,
3111 FIB_ROUTE_PATH_FLAG_NONE);
3112 dpo = fib_entry_contribute_ip_forwarding(fei);
3113 FIB_TEST(load_balance_is_drop(dpo),
3114 "0.0.0.0.0/0 via is DROP");
3115 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3116 "no resolving interface for looped 0.0.0.0/0");
3118 fei = fib_table_lookup_exact_match(fib_index, &pfx_23_23_23_23_s_32);
3119 dpo = fib_entry_contribute_ip_forwarding(fei);
3120 FIB_TEST(load_balance_is_drop(dpo),
3121 "23.23.23.23/32 via is DROP");
3122 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3123 "no resolving interface for looped 23.23.23.23/32");
3125 fib_table_entry_delete(fib_index, &pfx_0_0_0_0_s_0, FIB_SOURCE_API);
3128 * A recursive route with recursion constraints.
3129 * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained
3131 fib_table_entry_path_add(fib_index,
3134 FIB_ENTRY_FLAG_NONE,
3141 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3143 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3144 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3146 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3147 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3149 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3150 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3153 * save the load-balance. we expect it to be inplace modified
3155 lb = load_balance_get(dpo1->dpoi_index);
3158 * add a covering prefix for the via fib that would otherwise serve
3159 * as the resolving route when the host is removed
3161 fib_table_entry_path_add(fib_index,
3164 FIB_ENTRY_FLAG_NONE,
3167 tm->hw[0]->sw_if_index,
3168 ~0, // invalid fib index
3171 FIB_ROUTE_PATH_FLAG_NONE);
3172 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28);
3173 ai = fib_entry_get_adj(fei);
3174 FIB_TEST((ai == ai_01),
3175 "adj for 1.1.1.0/28 is via adj for 1.1.1.1");
3178 * remove the host via FIB - expect the BGP prefix to be drop
3180 fib_table_entry_path_remove(fib_index,
3185 tm->hw[0]->sw_if_index,
3186 ~0, // invalid fib index
3188 FIB_ROUTE_PATH_FLAG_NONE);
3190 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3191 "adj for 200.200.200.200/32 is recursive via adj for DROP");
3194 * add the via-entry host reoute back. expect to resolve again
3196 fib_table_entry_path_add(fib_index,
3199 FIB_ENTRY_FLAG_NONE,
3202 tm->hw[0]->sw_if_index,
3203 ~0, // invalid fib index
3206 FIB_ROUTE_PATH_FLAG_NONE);
3207 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3208 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3211 * add another path for the recursive. it will then have 2.
3213 fib_prefix_t pfx_1_1_1_3_s_32 = {
3215 .fp_proto = FIB_PROTOCOL_IP4,
3217 .ip4.as_u32 = clib_host_to_net_u32(0x01010103),
3220 fib_table_entry_path_add(fib_index,
3223 FIB_ENTRY_FLAG_NONE,
3226 tm->hw[0]->sw_if_index,
3227 ~0, // invalid fib index
3230 FIB_ROUTE_PATH_FLAG_NONE);
3232 fib_table_entry_path_add(fib_index,
3235 FIB_ENTRY_FLAG_NONE,
3237 &pfx_1_1_1_3_s_32.fp_addr,
3242 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3245 * add a bunch load more entries using this path combo so that we get
3246 * an LB-map created.
3249 fib_prefix_t bgp_78s[N_P];
3250 for (ii = 0; ii < N_P; ii++)
3252 bgp_78s[ii].fp_len = 32;
3253 bgp_78s[ii].fp_proto = FIB_PROTOCOL_IP4;
3254 bgp_78s[ii].fp_addr.ip4.as_u32 = clib_host_to_net_u32(0x4e000000+ii);
3257 fib_table_entry_path_add(fib_index,
3260 FIB_ENTRY_FLAG_NONE,
3262 &pfx_1_1_1_3_s_32.fp_addr,
3267 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3268 fib_table_entry_path_add(fib_index,
3271 FIB_ENTRY_FLAG_NONE,
3278 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3281 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3282 dpo = fib_entry_contribute_ip_forwarding(fei);
3284 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3285 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3286 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)),
3287 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3288 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32);
3289 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3290 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)),
3291 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3");
3294 * expect the lb-map used by the recursive's load-balance is using both buckets
3296 load_balance_map_t *lbm;
3299 lb = load_balance_get(dpo->dpoi_index);
3301 load_balance_map_lock(lbmi);
3302 lbm = load_balance_map_get(lbmi);
3304 FIB_TEST(lbm->lbm_buckets[0] == 0,
3305 "LB maps's bucket 0 is %d",
3306 lbm->lbm_buckets[0]);
3307 FIB_TEST(lbm->lbm_buckets[1] == 1,
3308 "LB maps's bucket 1 is %d",
3309 lbm->lbm_buckets[1]);
3312 * withdraw one of the /32 via-entrys.
3313 * that ECMP path will be unresolved and forwarding should continue on the
3314 * other available path. this is an iBGP PIC edge failover.
3315 * Test the forwarding changes without re-fetching the adj from the
3316 * recursive entry. this ensures its the same one that is updated; i.e. an
3319 fib_table_entry_path_remove(fib_index,
3324 tm->hw[0]->sw_if_index,
3325 ~0, // invalid fib index
3327 FIB_ROUTE_PATH_FLAG_NONE);
3329 /* suspend so the update walk kicks int */
3330 vlib_process_suspend(vlib_get_main(), 1e-5);
3332 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3333 FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)),
3334 "post PIC 200.200.200.200/32 was inplace modified");
3336 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)),
3337 "post PIC adj for 200.200.200.200/32 is recursive"
3338 " via adj for 1.1.1.3");
3341 * the LB maps that was locked above should have been modified to remove
3342 * the path that was down, and thus its bucket points to a path that is
3345 FIB_TEST(lbm->lbm_buckets[0] == 1,
3346 "LB maps's bucket 0 is %d",
3347 lbm->lbm_buckets[0]);
3348 FIB_TEST(lbm->lbm_buckets[1] == 1,
3349 "LB maps's bucket 1 is %d",
3350 lbm->lbm_buckets[1]);
3352 load_balance_map_unlock(lbmi);
3355 * add it back. again
3357 fib_table_entry_path_add(fib_index,
3360 FIB_ENTRY_FLAG_NONE,
3363 tm->hw[0]->sw_if_index,
3364 ~0, // invalid fib index
3367 FIB_ROUTE_PATH_FLAG_NONE);
3369 /* suspend so the update walk kicks in */
3370 vlib_process_suspend(vlib_get_main(), 1e-5);
3372 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)),
3373 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3374 "via adj for 1.1.1.1");
3375 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)),
3376 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3377 "via adj for 1.1.1.3");
3379 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3380 dpo = fib_entry_contribute_ip_forwarding(fei);
3381 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3382 "post PIC 200.200.200.200/32 was inplace modified");
3385 * add a 3rd path. this makes the LB 16 buckets.
3387 fib_table_entry_path_add(fib_index,
3390 FIB_ENTRY_FLAG_NONE,
3392 &pfx_1_1_1_2_s_32.fp_addr,
3397 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3398 for (ii = 0; ii < N_P; ii++)
3400 fib_table_entry_path_add(fib_index,
3403 FIB_ENTRY_FLAG_NONE,
3405 &pfx_1_1_1_2_s_32.fp_addr,
3410 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3413 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3414 dpo = fib_entry_contribute_ip_forwarding(fei);
3415 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3416 "200.200.200.200/32 was inplace modified for 3rd path");
3417 FIB_TEST(16 == lb->lb_n_buckets,
3418 "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets");
3421 load_balance_map_lock(lbmi);
3422 lbm = load_balance_map_get(lbmi);
3424 for (ii = 0; ii < 16; ii++)
3426 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3427 "LB Map for 200.200.200.200/32 at %d is %d",
3428 ii, lbm->lbm_buckets[ii]);
3432 * trigger PIC by removing the first via-entry
3433 * the first 6 buckets of the map should map to the next 6
3435 fib_table_entry_path_remove(fib_index,
3440 tm->hw[0]->sw_if_index,
3443 FIB_ROUTE_PATH_FLAG_NONE);
3444 /* suspend so the update walk kicks int */
3445 vlib_process_suspend(vlib_get_main(), 1e-5);
3447 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3448 dpo = fib_entry_contribute_ip_forwarding(fei);
3449 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3450 "200.200.200.200/32 was inplace modified for 3rd path");
3451 FIB_TEST(2 == lb->lb_n_buckets,
3452 "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets");
3454 for (ii = 0; ii < 6; ii++)
3456 FIB_TEST(lbm->lbm_buckets[ii] == ii+6,
3457 "LB Map for 200.200.200.200/32 at %d is %d",
3458 ii, lbm->lbm_buckets[ii]);
3460 for (ii = 6; ii < 16; ii++)
3462 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3463 "LB Map for 200.200.200.200/32 at %d is %d",
3464 ii, lbm->lbm_buckets[ii]);
3466 load_balance_map_unlock(lbmi);
3471 fib_table_entry_path_add(fib_index,
3474 FIB_ENTRY_FLAG_NONE,
3477 tm->hw[0]->sw_if_index,
3481 FIB_ROUTE_PATH_FLAG_NONE);
3483 for (ii = 0; ii < N_P; ii++)
3485 fib_table_entry_delete(fib_index,
3488 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3489 fib_table_lookup_exact_match(fib_index, &bgp_78s[ii])),
3491 format_fib_prefix, &bgp_78s[ii]);
3493 fib_table_entry_path_remove(fib_index,
3497 &pfx_1_1_1_2_s_32.fp_addr,
3501 MPLS_LABEL_INVALID);
3502 fib_table_entry_path_remove(fib_index,
3510 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3511 fib_table_entry_path_remove(fib_index,
3515 &pfx_1_1_1_3_s_32.fp_addr,
3519 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3520 fib_table_entry_delete(fib_index,
3523 fib_table_entry_delete(fib_index,
3526 /* suspend so the update walk kicks int */
3527 vlib_process_suspend(vlib_get_main(), 1e-5);
3528 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3529 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)),
3530 "1.1.1.1/28 removed");
3531 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3532 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)),
3533 "1.1.1.3/32 removed");
3534 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3535 fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)),
3536 "200.200.200.200/32 removed");
3539 * add-remove test. no change.
3541 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3542 fib_path_list_db_size());
3543 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3544 fib_path_list_pool_size());
3545 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3546 fib_entry_pool_size());
3549 * A route whose paths are built up iteratively and then removed
3552 fib_prefix_t pfx_4_4_4_4_s_32 = {
3554 .fp_proto = FIB_PROTOCOL_IP4,
3557 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
3561 fib_table_entry_path_add(fib_index,
3564 FIB_ENTRY_FLAG_NONE,
3567 tm->hw[0]->sw_if_index,
3571 FIB_ROUTE_PATH_FLAG_NONE);
3572 fib_table_entry_path_add(fib_index,
3575 FIB_ENTRY_FLAG_NONE,
3578 tm->hw[0]->sw_if_index,
3582 FIB_ROUTE_PATH_FLAG_NONE);
3583 fib_table_entry_path_add(fib_index,
3586 FIB_ENTRY_FLAG_NONE,
3589 tm->hw[0]->sw_if_index,
3593 FIB_ROUTE_PATH_FLAG_NONE);
3594 FIB_TEST(FIB_NODE_INDEX_INVALID !=
3595 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3596 "4.4.4.4/32 present");
3598 fib_table_entry_delete(fib_index,
3601 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3602 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3603 "4.4.4.4/32 removed");
3606 * add-remove test. no change.
3608 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3609 fib_path_list_db_size());
3610 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3611 fib_path_list_pool_size());
3612 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3613 fib_entry_pool_size());
3616 * A route with multiple paths at once
3618 fib_route_path_t *r_paths = NULL;
3620 for (ii = 0; ii < 4; ii++)
3622 fib_route_path_t r_path = {
3623 .frp_proto = DPO_PROTO_IP4,
3625 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
3627 .frp_sw_if_index = tm->hw[0]->sw_if_index,
3629 .frp_fib_index = ~0,
3631 vec_add1(r_paths, r_path);
3634 fib_table_entry_update(fib_index,
3637 FIB_ENTRY_FLAG_NONE,
3640 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3641 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3642 dpo = fib_entry_contribute_ip_forwarding(fei);
3644 lb = load_balance_get(dpo->dpoi_index);
3645 FIB_TEST((lb->lb_n_buckets == 4), "4.4.4.4/32 lb over %d paths", lb->lb_n_buckets);
3647 fib_table_entry_delete(fib_index,
3650 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3651 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3652 "4.4.4.4/32 removed");
3656 * add-remove test. no change.
3658 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3659 fib_path_list_db_size());
3660 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3661 fib_path_list_pool_size());
3662 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3663 fib_entry_pool_size());
3666 * A route deag route
3668 fib_table_entry_path_add(fib_index,
3671 FIB_ENTRY_FLAG_NONE,
3678 FIB_ROUTE_PATH_FLAG_NONE);
3680 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3681 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3683 dpo = fib_entry_contribute_ip_forwarding(fei);
3684 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3685 lookup_dpo_t *lkd = lookup_dpo_get(dpo->dpoi_index);
3687 FIB_TEST((fib_index == lkd->lkd_fib_index),
3688 "4.4.4.4/32 is deag in %d %U",
3690 format_dpo_id, dpo, 0);
3691 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
3692 "4.4.4.4/32 is source deag in %d %U",
3694 format_dpo_id, dpo, 0);
3696 fib_table_entry_delete(fib_index,
3699 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3700 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3701 "4.4.4.4/32 removed");
3705 * A route deag route in a source lookup table
3707 fib_table_entry_path_add(fib_index,
3710 FIB_ENTRY_FLAG_NONE,
3717 FIB_ROUTE_PATH_SOURCE_LOOKUP);
3719 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3720 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3722 dpo = fib_entry_contribute_ip_forwarding(fei);
3723 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3724 lkd = lookup_dpo_get(dpo->dpoi_index);
3726 FIB_TEST((fib_index == lkd->lkd_fib_index),
3727 "4.4.4.4/32 is deag in %d %U",
3729 format_dpo_id, dpo, 0);
3730 FIB_TEST((LOOKUP_INPUT_SRC_ADDR == lkd->lkd_input),
3731 "4.4.4.4/32 is source deag in %d %U",
3733 format_dpo_id, dpo, 0);
3735 fib_table_entry_delete(fib_index,
3738 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3739 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3740 "4.4.4.4/32 removed");
3744 * add-remove test. no change.
3746 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3747 fib_path_list_db_size());
3748 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3749 fib_path_list_pool_size());
3750 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3751 fib_entry_pool_size());
3755 * add a recursive with duplicate paths. Expect the duplicate to be ignored.
3757 fib_prefix_t pfx_34_1_1_1_s_32 = {
3759 .fp_proto = FIB_PROTOCOL_IP4,
3761 .ip4.as_u32 = clib_host_to_net_u32(0x22010101),
3764 fib_prefix_t pfx_34_34_1_1_s_32 = {
3766 .fp_proto = FIB_PROTOCOL_IP4,
3768 .ip4.as_u32 = clib_host_to_net_u32(0x22220101),
3771 fei = fib_table_entry_path_add(fib_index,
3772 &pfx_34_34_1_1_s_32,
3774 FIB_ENTRY_FLAG_NONE,
3777 tm->hw[0]->sw_if_index,
3781 FIB_ROUTE_PATH_FLAG_NONE);
3782 fei = fib_table_entry_path_add(fib_index,
3785 FIB_ENTRY_FLAG_NONE,
3787 &pfx_34_34_1_1_s_32.fp_addr,
3792 FIB_ROUTE_PATH_FLAG_NONE);
3793 fei = fib_table_entry_path_add(fib_index,
3796 FIB_ENTRY_FLAG_NONE,
3798 &pfx_34_34_1_1_s_32.fp_addr,
3803 FIB_ROUTE_PATH_FLAG_NONE);
3804 FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0);
3805 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3806 fib_table_entry_delete(fib_index,
3807 &pfx_34_34_1_1_s_32,
3812 * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32
3813 * all of which are via 10.10.10.1, Itf1
3815 fib_table_entry_path_remove(fib_index,
3820 tm->hw[0]->sw_if_index,
3823 FIB_ROUTE_PATH_FLAG_NONE);
3824 fib_table_entry_path_remove(fib_index,
3829 tm->hw[0]->sw_if_index,
3832 FIB_ROUTE_PATH_FLAG_NONE);
3833 fib_table_entry_path_remove(fib_index,
3838 tm->hw[0]->sw_if_index,
3841 FIB_ROUTE_PATH_FLAG_NONE);
3843 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3844 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32),
3845 "1.1.1.1/32 removed");
3846 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3847 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32),
3848 "1.1.1.2/32 removed");
3849 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3850 fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24),
3851 "1.1.2.0/24 removed");
3854 * -3 entries and -1 shared path-list
3856 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3857 fib_path_list_db_size());
3858 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3859 fib_path_list_pool_size());
3860 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3861 fib_entry_pool_size());
3864 * An attached-host route. Expect to link to the incomplete adj
3866 fib_prefix_t pfx_4_1_1_1_s_32 = {
3868 .fp_proto = FIB_PROTOCOL_IP4,
3871 .ip4.as_u32 = clib_host_to_net_u32(0x04010101),
3874 fib_table_entry_path_add(fib_index,
3877 FIB_ENTRY_FLAG_NONE,
3880 tm->hw[0]->sw_if_index,
3884 FIB_ROUTE_PATH_FLAG_NONE);
3886 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32);
3887 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present");
3888 ai = fib_entry_get_adj(fei);
3890 ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
3892 &pfx_4_1_1_1_s_32.fp_addr,
3893 tm->hw[0]->sw_if_index);
3894 FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ");
3898 * +1 entry and +1 shared path-list
3900 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3901 fib_path_list_db_size());
3902 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3903 fib_path_list_pool_size());
3904 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
3905 fib_entry_pool_size());
3907 fib_table_entry_delete(fib_index,
3911 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3912 fib_path_list_db_size());
3913 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3914 fib_path_list_pool_size());
3915 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3916 fib_entry_pool_size());
3919 * add a v6 prefix via v4 next-hops
3921 fib_prefix_t pfx_2001_s_64 = {
3923 .fp_proto = FIB_PROTOCOL_IP6,
3925 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
3928 fei = fib_table_entry_path_add(0, //default v6 table
3931 FIB_ENTRY_FLAG_NONE,
3934 tm->hw[0]->sw_if_index,
3938 FIB_ROUTE_PATH_FLAG_NONE);
3940 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
3941 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present");
3942 ai = fib_entry_get_adj(fei);
3944 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
3945 "2001::/64 via ARP-adj");
3946 FIB_TEST((adj->ia_link == VNET_LINK_IP6),
3947 "2001::/64 is link type v6");
3948 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4),
3949 "2001::/64 ADJ-adj is NH proto v4");
3950 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
3953 * add a uRPF exempt prefix:
3955 * - it's forwarding is drop
3956 * - it's uRPF list is not empty
3957 * - the uRPF list for the default route (it's cover) is empty
3959 fei = fib_table_entry_special_add(fib_index,
3961 FIB_SOURCE_URPF_EXEMPT,
3962 FIB_ENTRY_FLAG_DROP);
3963 dpo = fib_entry_contribute_ip_forwarding(fei);
3964 FIB_TEST(load_balance_is_drop(dpo),
3965 "uRPF exempt 4.1.1.1/32 DROP");
3966 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0),
3967 "uRPF list for exempt prefix has itf index 0");
3968 fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0);
3969 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
3970 "uRPF list for 0.0.0.0/0 empty");
3972 fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
3975 * An adj-fib that fails the refinement criteria - no connected cover
3977 fib_prefix_t pfx_12_10_10_2_s_32 = {
3979 .fp_proto = FIB_PROTOCOL_IP4,
3982 .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02),
3986 fib_table_entry_path_add(fib_index,
3987 &pfx_12_10_10_2_s_32,
3989 FIB_ENTRY_FLAG_ATTACHED,
3991 &pfx_12_10_10_2_s_32.fp_addr,
3992 tm->hw[0]->sw_if_index,
3993 ~0, // invalid fib index
3996 FIB_ROUTE_PATH_FLAG_NONE);
3998 fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32);
3999 dpo = fib_entry_contribute_ip_forwarding(fei);
4000 FIB_TEST(dpo_is_drop(dpo),
4001 "no connected cover adj-fib fails refinement: %U",
4002 format_dpo_id, dpo, 0);
4004 fib_table_entry_delete(fib_index,
4005 &pfx_12_10_10_2_s_32,
4009 * An adj-fib that fails the refinement criteria - cover is connected
4010 * but on a different interface
4012 fib_prefix_t pfx_10_10_10_127_s_32 = {
4014 .fp_proto = FIB_PROTOCOL_IP4,
4017 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f),
4021 fib_table_entry_path_add(fib_index,
4022 &pfx_10_10_10_127_s_32,
4024 FIB_ENTRY_FLAG_ATTACHED,
4026 &pfx_10_10_10_127_s_32.fp_addr,
4027 tm->hw[1]->sw_if_index,
4028 ~0, // invalid fib index
4031 FIB_ROUTE_PATH_FLAG_NONE);
4033 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32);
4034 dpo = fib_entry_contribute_ip_forwarding(fei);
4035 FIB_TEST(dpo_is_drop(dpo),
4036 "wrong interface adj-fib fails refinement");
4038 fib_table_entry_delete(fib_index,
4039 &pfx_10_10_10_127_s_32,
4043 * add a second path to an adj-fib
4044 * this is a sumiluation of another ARP entry created
4045 * on an interface on which the connected prefix does not exist.
4046 * The second path fails refinement. Expect to forward through the
4049 fib_prefix_t pfx_10_10_10_3_s_32 = {
4051 .fp_proto = FIB_PROTOCOL_IP4,
4054 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
4058 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
4061 tm->hw[0]->sw_if_index);
4063 fib_test_lb_bucket_t ip_o_10_10_10_3 = {
4069 fei = fib_table_entry_path_add(fib_index,
4070 &pfx_10_10_10_3_s_32,
4072 FIB_ENTRY_FLAG_NONE,
4075 tm->hw[0]->sw_if_index,
4079 FIB_ROUTE_PATH_FLAG_NONE);
4080 fei = fib_table_entry_path_add(fib_index,
4081 &pfx_10_10_10_3_s_32,
4083 FIB_ENTRY_FLAG_NONE,
4086 tm->hw[1]->sw_if_index,
4090 FIB_ROUTE_PATH_FLAG_NONE);
4091 FIB_TEST(!fib_test_validate_entry(fei,
4092 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4095 "10.10.10.3 via 10.10.10.3/Eth0 only");
4098 * remove the path that refines the cover, should go unresolved
4100 fib_table_entry_path_remove(fib_index,
4101 &pfx_10_10_10_3_s_32,
4105 tm->hw[0]->sw_if_index,
4108 FIB_ROUTE_PATH_FLAG_NONE);
4109 dpo = fib_entry_contribute_ip_forwarding(fei);
4110 FIB_TEST(dpo_is_drop(dpo),
4111 "wrong interface adj-fib fails refinement");
4114 * add back the path that refines the cover
4116 fei = fib_table_entry_path_add(fib_index,
4117 &pfx_10_10_10_3_s_32,
4119 FIB_ENTRY_FLAG_NONE,
4122 tm->hw[0]->sw_if_index,
4126 FIB_ROUTE_PATH_FLAG_NONE);
4127 FIB_TEST(!fib_test_validate_entry(fei,
4128 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4131 "10.10.10.3 via 10.10.10.3/Eth0 only");
4134 * remove the path that does not refine the cover
4136 fib_table_entry_path_remove(fib_index,
4137 &pfx_10_10_10_3_s_32,
4141 tm->hw[1]->sw_if_index,
4144 FIB_ROUTE_PATH_FLAG_NONE);
4145 FIB_TEST(!fib_test_validate_entry(fei,
4146 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4149 "10.10.10.3 via 10.10.10.3/Eth0 only");
4152 * remove the path that does refine, it's the last path, so
4153 * the entry should be gone
4155 fib_table_entry_path_remove(fib_index,
4156 &pfx_10_10_10_3_s_32,
4160 tm->hw[0]->sw_if_index,
4163 FIB_ROUTE_PATH_FLAG_NONE);
4164 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
4165 FIB_TEST((fei == FIB_NODE_INDEX_INVALID), "10.10.10.3 gone");
4170 * change the table's flow-hash config - expect the update to propagete to
4171 * the entries' load-balance objects
4173 flow_hash_config_t old_hash_config, new_hash_config;
4175 old_hash_config = fib_table_get_flow_hash_config(fib_index,
4177 new_hash_config = (IP_FLOW_HASH_SRC_ADDR |
4178 IP_FLOW_HASH_DST_ADDR);
4180 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
4181 dpo = fib_entry_contribute_ip_forwarding(fei);
4182 lb = load_balance_get(dpo->dpoi_index);
4183 FIB_TEST((lb->lb_hash_config == old_hash_config),
4184 "Table and LB hash config match: %U",
4185 format_ip_flow_hash_config, lb->lb_hash_config);
4187 fib_table_set_flow_hash_config(fib_index, FIB_PROTOCOL_IP4, new_hash_config);
4189 FIB_TEST((lb->lb_hash_config == new_hash_config),
4190 "Table and LB newhash config match: %U",
4191 format_ip_flow_hash_config, lb->lb_hash_config);
4194 * A route via DVR DPO
4196 fei = fib_table_entry_path_add(fib_index,
4197 &pfx_10_10_10_3_s_32,
4199 FIB_ENTRY_FLAG_NONE,
4202 tm->hw[0]->sw_if_index,
4206 FIB_ROUTE_PATH_DVR);
4207 dpo_id_t dvr_dpo = DPO_INVALID;
4208 dvr_dpo_add_or_lock(tm->hw[0]->sw_if_index, DPO_PROTO_IP4, &dvr_dpo);
4209 fib_test_lb_bucket_t ip_o_l2 = {
4212 .adj = dvr_dpo.dpoi_index,
4216 FIB_TEST(!fib_test_validate_entry(fei,
4217 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4220 "10.10.10.3 via L2 on Eth0");
4221 fib_table_entry_path_remove(fib_index,
4222 &pfx_10_10_10_3_s_32,
4226 tm->hw[0]->sw_if_index,
4229 FIB_ROUTE_PATH_DVR);
4230 dpo_reset(&dvr_dpo);
4233 * add the default route via a next-hop that will form a loop
4235 fib_prefix_t pfx_conn = {
4237 .fp_proto = FIB_PROTOCOL_IP4,
4240 .ip4.as_u32 = clib_host_to_net_u32(0x1e1e1e1e),
4244 dfrt = fib_table_entry_path_add(fib_index,
4247 FIB_ENTRY_FLAG_NONE,
4254 FIB_ROUTE_PATH_FLAG_NONE);
4256 * the default route is a drop, since it's looped
4258 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4259 "Default route is DROP");
4262 * add a connected cover for the next-hop, this breaks the recursion loop
4263 * for the default route
4265 fib_table_entry_path_add(fib_index,
4268 (FIB_ENTRY_FLAG_CONNECTED |
4269 FIB_ENTRY_FLAG_ATTACHED),
4272 tm->hw[0]->sw_if_index,
4276 FIB_ROUTE_PATH_FLAG_NONE);
4277 pfx_conn.fp_len = 32;
4278 fei = fib_table_lookup_exact_match(fib_index, &pfx_conn);
4280 u32 ai_30 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
4283 tm->hw[0]->sw_if_index);
4285 fib_test_lb_bucket_t ip_o_30_30_30_30 = {
4291 FIB_TEST(!fib_test_validate_entry(fei,
4292 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4295 "30.30.30.30 via adj");
4296 FIB_TEST_REC_FORW(&pfx_0_0_0_0_s_0, &pfx_conn, 0);
4298 pfx_conn.fp_len = 24;
4299 fib_table_entry_delete(fib_index,
4302 fib_table_entry_delete(fib_index,
4311 fib_table_entry_delete(fib_index,
4312 &pfx_10_10_10_1_s_32,
4314 fib_table_entry_delete(fib_index,
4315 &pfx_10_10_10_2_s_32,
4317 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4318 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32),
4319 "10.10.10.1/32 adj-fib removed");
4320 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4321 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32),
4322 "10.10.10.2/32 adj-fib removed");
4325 * -2 entries and -2 non-shared path-list
4327 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4328 fib_path_list_db_size());
4329 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
4330 fib_path_list_pool_size());
4331 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
4332 fib_entry_pool_size());
4335 * unlock the adjacencies for which this test provided a rewrite.
4336 * These are the last locks on these adjs. they should thus go away.
4340 adj_unlock(ai_12_12_12_12);
4342 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4347 * remove the interface prefixes
4349 local_pfx.fp_len = 32;
4350 fib_table_entry_special_remove(fib_index, &local_pfx,
4351 FIB_SOURCE_INTERFACE);
4352 fei = fib_table_lookup(fib_index, &local_pfx);
4354 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4355 fib_table_lookup_exact_match(fib_index, &local_pfx),
4356 "10.10.10.10/32 adj-fib removed");
4358 local_pfx.fp_len = 24;
4359 fib_table_entry_delete(fib_index, &local_pfx,
4360 FIB_SOURCE_INTERFACE);
4362 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4363 fib_table_lookup_exact_match(fib_index, &local_pfx),
4364 "10.10.10.10/24 adj-fib removed");
4367 * -2 entries and -2 non-shared path-list
4369 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4370 fib_path_list_db_size());
4371 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
4372 fib_path_list_pool_size());
4373 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
4374 fib_entry_pool_size());
4377 * Last but not least, remove the VRF
4379 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4382 "NO API Source'd prefixes");
4383 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4386 "NO RR Source'd prefixes");
4387 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4389 FIB_SOURCE_INTERFACE)),
4390 "NO INterface Source'd prefixes");
4392 for (ii = 0; ii < 4; ii++)
4393 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[ii]->sw_if_index, 0);
4395 fib_table_unlock(fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
4397 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4398 fib_path_list_db_size());
4399 FIB_TEST((PNBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
4400 fib_path_list_pool_size());
4401 FIB_TEST((ENBR-5 == fib_entry_pool_size()), "entry pool size is %d",
4402 fib_entry_pool_size());
4403 FIB_TEST((ENBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
4404 pool_elts(fib_urpf_list_pool));
4405 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
4406 pool_elts(load_balance_map_pool));
4407 FIB_TEST((lb_count == pool_elts(load_balance_pool)), "LB pool size is %d",
4408 pool_elts(load_balance_pool));
4409 FIB_TEST((0 == pool_elts(dvr_dpo_pool)), "L2 DPO pool size is %d",
4410 pool_elts(dvr_dpo_pool));
4419 * In the default table check for the presence and correct forwarding
4420 * of the special entries
4422 fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02;
4423 const dpo_id_t *dpo, *dpo_drop;
4424 const ip_adjacency_t *adj;
4425 const receive_dpo_t *rd;
4431 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4434 /* via 2001:0:0:1::2 */
4435 ip46_address_t nh_2001_2 = {
4438 [0] = clib_host_to_net_u64(0x2001000000000001),
4439 [1] = clib_host_to_net_u64(0x0000000000000002),
4446 dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
4448 /* Find or create FIB table 11 */
4449 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11,
4452 for (ii = 0; ii < 4; ii++)
4453 fib_table_bind (FIB_PROTOCOL_IP6, tm->hw[ii]->sw_if_index, fib_index);
4455 fib_prefix_t pfx_0_0 = {
4457 .fp_proto = FIB_PROTOCOL_IP6,
4465 dfrt = fib_table_lookup(fib_index, &pfx_0_0);
4466 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
4467 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4468 "Default route is DROP");
4470 dpo = fib_entry_contribute_ip_forwarding(dfrt);
4471 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4473 &pfx_0_0.fp_addr.ip6)),
4474 "default-route; fwd and non-fwd tables match");
4476 // FIXME - check specials.
4479 * At this stage there is one v4 FIB with 5 routes and two v6 FIBs
4480 * each with 2 entries and a v6 mfib with 4 path-lists and v4 mfib with 2.
4481 * All entries are special so no path-list sharing.
4484 u32 PNPS = (5+4+4+2);
4486 * if the IGMP plugin is loaded this adds two more entries to the v4 MFIB
4488 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
4489 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is %d",
4490 fib_path_list_pool_size());
4491 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
4492 fib_entry_pool_size());
4495 * add interface routes.
4496 * validate presence of /64 attached and /128 recieve.
4497 * test for the presence of the receive address in the glean and local adj
4499 * receive on 2001:0:0:1::1/128
4501 fib_prefix_t local_pfx = {
4503 .fp_proto = FIB_PROTOCOL_IP6,
4507 [0] = clib_host_to_net_u64(0x2001000000000001),
4508 [1] = clib_host_to_net_u64(0x0000000000000001),
4514 fib_table_entry_update_one_path(fib_index, &local_pfx,
4515 FIB_SOURCE_INTERFACE,
4516 (FIB_ENTRY_FLAG_CONNECTED |
4517 FIB_ENTRY_FLAG_ATTACHED),
4520 tm->hw[0]->sw_if_index,
4524 FIB_ROUTE_PATH_FLAG_NONE);
4525 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4527 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4529 ai = fib_entry_get_adj(fei);
4530 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
4532 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4533 "attached interface adj is glean");
4534 dpo = fib_entry_contribute_ip_forwarding(fei);
4535 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4537 &local_pfx.fp_addr.ip6)),
4538 "attached-route; fwd and non-fwd tables match");
4540 local_pfx.fp_len = 128;
4541 fib_table_entry_update_one_path(fib_index, &local_pfx,
4542 FIB_SOURCE_INTERFACE,
4543 (FIB_ENTRY_FLAG_CONNECTED |
4544 FIB_ENTRY_FLAG_LOCAL),
4547 tm->hw[0]->sw_if_index,
4548 ~0, // invalid fib index
4551 FIB_ROUTE_PATH_FLAG_NONE);
4552 fei = fib_table_lookup(fib_index, &local_pfx);
4554 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4556 dpo = fib_entry_contribute_ip_forwarding(fei);
4557 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4558 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4559 "local interface adj is local");
4560 rd = receive_dpo_get(dpo->dpoi_index);
4562 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4564 "local interface adj is receive ok");
4566 dpo = fib_entry_contribute_ip_forwarding(fei);
4567 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4569 &local_pfx.fp_addr.ip6)),
4570 "local-route; fwd and non-fwd tables match");
4571 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4572 &adj->sub_type.glean.rx_pfx.fp_addr)),
4573 "attached interface adj is receive ok");
4576 * +2 entries. +2 unshared path-lists
4578 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
4579 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
4580 fib_path_list_pool_size());
4581 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4582 fib_entry_pool_size());
4585 * Modify the default route to be via an adj not yet known.
4586 * this sources the defalut route with the API source, which is
4587 * a higher preference to the DEFAULT_ROUTE source
4589 fib_table_entry_path_add(fib_index, &pfx_0_0,
4591 FIB_ENTRY_FLAG_NONE,
4594 tm->hw[0]->sw_if_index,
4598 FIB_ROUTE_PATH_FLAG_NONE);
4599 fei = fib_table_lookup(fib_index, &pfx_0_0);
4601 FIB_TEST((fei == dfrt), "default route same index");
4602 ai = fib_entry_get_adj(fei);
4603 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
4605 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4606 "adj is incomplete");
4607 FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)),
4608 "adj nbr next-hop ok");
4611 * find the adj in the shared db
4613 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4616 tm->hw[0]->sw_if_index);
4617 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
4618 adj_unlock(locked_ai);
4621 * no more entries. +1 shared path-list
4623 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4624 fib_path_list_db_size());
4625 FIB_TEST((PNPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
4626 fib_path_list_pool_size());
4627 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4628 fib_entry_pool_size());
4631 * remove the API source from the default route. We expected
4632 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
4634 fib_table_entry_path_remove(fib_index, &pfx_0_0,
4638 tm->hw[0]->sw_if_index,
4641 FIB_ROUTE_PATH_FLAG_NONE);
4642 fei = fib_table_lookup(fib_index, &pfx_0_0);
4644 FIB_TEST((fei == dfrt), "default route same index");
4645 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4646 "Default route is DROP");
4649 * no more entries. -1 shared path-list
4651 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4652 fib_path_list_db_size());
4653 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
4654 fib_path_list_pool_size());
4655 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4656 fib_entry_pool_size());
4659 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4661 fib_prefix_t pfx_2001_1_2_s_128 = {
4663 .fp_proto = FIB_PROTOCOL_IP6,
4667 [0] = clib_host_to_net_u64(0x2001000000000001),
4668 [1] = clib_host_to_net_u64(0x0000000000000002),
4673 fib_prefix_t pfx_2001_1_3_s_128 = {
4675 .fp_proto = FIB_PROTOCOL_IP6,
4679 [0] = clib_host_to_net_u64(0x2001000000000001),
4680 [1] = clib_host_to_net_u64(0x0000000000000003),
4686 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
4689 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4691 &pfx_2001_1_2_s_128.fp_addr,
4692 tm->hw[0]->sw_if_index);
4693 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
4694 adj = adj_get(ai_01);
4695 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4696 "adj is incomplete");
4697 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4698 &adj->sub_type.nbr.next_hop)),
4699 "adj nbr next-hop ok");
4701 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4702 fib_test_build_rewrite(eth_addr));
4703 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4705 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4706 &adj->sub_type.nbr.next_hop)),
4707 "adj nbr next-hop ok");
4709 fib_table_entry_path_add(fib_index,
4710 &pfx_2001_1_2_s_128,
4712 FIB_ENTRY_FLAG_ATTACHED,
4714 &pfx_2001_1_2_s_128.fp_addr,
4715 tm->hw[0]->sw_if_index,
4719 FIB_ROUTE_PATH_FLAG_NONE);
4721 fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
4722 ai = fib_entry_get_adj(fei);
4723 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4727 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4729 &pfx_2001_1_3_s_128.fp_addr,
4730 tm->hw[0]->sw_if_index);
4731 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
4732 adj = adj_get(ai_02);
4733 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4734 "adj is incomplete");
4735 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4736 &adj->sub_type.nbr.next_hop)),
4737 "adj nbr next-hop ok");
4739 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4740 fib_test_build_rewrite(eth_addr));
4741 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4743 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4744 &adj->sub_type.nbr.next_hop)),
4745 "adj nbr next-hop ok");
4746 FIB_TEST((ai_01 != ai_02), "ADJs are different");
4748 fib_table_entry_path_add(fib_index,
4749 &pfx_2001_1_3_s_128,
4751 FIB_ENTRY_FLAG_ATTACHED,
4753 &pfx_2001_1_3_s_128.fp_addr,
4754 tm->hw[0]->sw_if_index,
4758 FIB_ROUTE_PATH_FLAG_NONE);
4760 fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
4761 ai = fib_entry_get_adj(fei);
4762 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4765 * +2 entries, +2 unshread path-lists.
4767 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4768 fib_path_list_db_size());
4769 FIB_TEST((PNPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
4770 fib_path_list_pool_size());
4771 FIB_TEST((ENPS+4 == fib_entry_pool_size()), "entry pool size is %d",
4772 fib_entry_pool_size());
4775 * Add a 2 routes via the first ADJ. ensure path-list sharing
4777 fib_prefix_t pfx_2001_a_s_64 = {
4779 .fp_proto = FIB_PROTOCOL_IP6,
4783 [0] = clib_host_to_net_u64(0x200100000000000a),
4784 [1] = clib_host_to_net_u64(0x0000000000000000),
4789 fib_prefix_t pfx_2001_b_s_64 = {
4791 .fp_proto = FIB_PROTOCOL_IP6,
4795 [0] = clib_host_to_net_u64(0x200100000000000b),
4796 [1] = clib_host_to_net_u64(0x0000000000000000),
4802 fib_table_entry_path_add(fib_index,
4805 FIB_ENTRY_FLAG_NONE,
4808 tm->hw[0]->sw_if_index,
4812 FIB_ROUTE_PATH_FLAG_NONE);
4813 fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64);
4814 ai = fib_entry_get_adj(fei);
4815 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4816 fib_table_entry_path_add(fib_index,
4819 FIB_ENTRY_FLAG_NONE,
4822 tm->hw[0]->sw_if_index,
4826 FIB_ROUTE_PATH_FLAG_NONE);
4827 fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64);
4828 ai = fib_entry_get_adj(fei);
4829 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4832 * +2 entries, +1 shared path-list.
4834 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4835 fib_path_list_db_size());
4836 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4837 fib_path_list_pool_size());
4838 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
4839 fib_entry_pool_size());
4842 * add a v4 prefix via a v6 next-hop
4844 fib_prefix_t pfx_1_1_1_1_s_32 = {
4846 .fp_proto = FIB_PROTOCOL_IP4,
4848 .ip4.as_u32 = 0x01010101,
4851 fei = fib_table_entry_path_add(0, // default table
4854 FIB_ENTRY_FLAG_NONE,
4857 tm->hw[0]->sw_if_index,
4861 FIB_ROUTE_PATH_FLAG_NONE);
4862 FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32),
4863 "1.1.1.1/32 o v6 route present");
4864 ai = fib_entry_get_adj(fei);
4866 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
4867 "1.1.1.1/32 via ARP-adj");
4868 FIB_TEST((adj->ia_link == VNET_LINK_IP4),
4869 "1.1.1.1/32 ADJ-adj is link type v4");
4870 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6),
4871 "1.1.1.1/32 ADJ-adj is NH proto v6");
4872 fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API);
4877 fib_prefix_t pfx_2001_c_s_64 = {
4879 .fp_proto = FIB_PROTOCOL_IP6,
4883 [0] = clib_host_to_net_u64(0x200100000000000c),
4884 [1] = clib_host_to_net_u64(0x0000000000000000),
4889 fib_table_entry_path_add(fib_index,
4892 FIB_ENTRY_FLAG_ATTACHED,
4895 tm->hw[0]->sw_if_index,
4899 FIB_ROUTE_PATH_FLAG_NONE);
4900 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4901 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present");
4902 ai = fib_entry_get_adj(fei);
4904 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN),
4905 "2001:0:0:c/64 attached resolves via glean");
4907 fib_table_entry_path_remove(fib_index,
4912 tm->hw[0]->sw_if_index,
4915 FIB_ROUTE_PATH_FLAG_NONE);
4916 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4917 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached route removed");
4920 * Shutdown the interface on which we have a connected and through
4921 * which the routes are reachable.
4922 * This will result in the connected, adj-fibs, and routes linking to drop
4923 * The local/for-us prefix continues to receive.
4925 clib_error_t * error;
4927 error = vnet_sw_interface_set_flags(vnet_get_main(),
4928 tm->hw[0]->sw_if_index,
4929 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4930 FIB_TEST((NULL == error), "Interface shutdown OK");
4932 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4933 dpo = fib_entry_contribute_ip_forwarding(fei);
4934 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4935 "2001::b/64 resolves via drop");
4937 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4938 dpo = fib_entry_contribute_ip_forwarding(fei);
4939 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4940 "2001::a/64 resolves via drop");
4941 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4942 dpo = fib_entry_contribute_ip_forwarding(fei);
4943 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4944 "2001:0:0:1::3/64 resolves via drop");
4945 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4946 dpo = fib_entry_contribute_ip_forwarding(fei);
4947 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4948 "2001:0:0:1::2/64 resolves via drop");
4949 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4950 dpo = fib_entry_contribute_ip_forwarding(fei);
4951 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4952 "2001:0:0:1::1/128 not drop");
4953 local_pfx.fp_len = 64;
4954 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4955 dpo = fib_entry_contribute_ip_forwarding(fei);
4956 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4957 "2001:0:0:1/64 resolves via drop");
4962 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4963 fib_path_list_db_size());
4964 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4965 fib_path_list_pool_size());
4966 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
4967 fib_entry_pool_size());
4970 * shutdown one of the other interfaces, then add a connected.
4971 * and swap one of the routes to it.
4973 error = vnet_sw_interface_set_flags(vnet_get_main(),
4974 tm->hw[1]->sw_if_index,
4975 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4976 FIB_TEST((NULL == error), "Interface 1 shutdown OK");
4978 fib_prefix_t connected_pfx = {
4980 .fp_proto = FIB_PROTOCOL_IP6,
4983 /* 2001:0:0:2::1/64 */
4985 [0] = clib_host_to_net_u64(0x2001000000000002),
4986 [1] = clib_host_to_net_u64(0x0000000000000001),
4991 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4992 FIB_SOURCE_INTERFACE,
4993 (FIB_ENTRY_FLAG_CONNECTED |
4994 FIB_ENTRY_FLAG_ATTACHED),
4997 tm->hw[1]->sw_if_index,
5001 FIB_ROUTE_PATH_FLAG_NONE);
5002 fei = fib_table_lookup_exact_match(fib_index, &connected_pfx);
5003 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
5004 dpo = fib_entry_contribute_ip_forwarding(fei);
5005 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
5006 FIB_TEST(!dpo_cmp(dpo, dpo_drop),
5007 "2001:0:0:2/64 not resolves via drop");
5009 connected_pfx.fp_len = 128;
5010 fib_table_entry_update_one_path(fib_index, &connected_pfx,
5011 FIB_SOURCE_INTERFACE,
5012 (FIB_ENTRY_FLAG_CONNECTED |
5013 FIB_ENTRY_FLAG_LOCAL),
5016 tm->hw[0]->sw_if_index,
5017 ~0, // invalid fib index
5020 FIB_ROUTE_PATH_FLAG_NONE);
5021 fei = fib_table_lookup(fib_index, &connected_pfx);
5023 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
5024 dpo = fib_entry_contribute_ip_forwarding(fei);
5025 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
5026 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
5027 "local interface adj is local");
5028 rd = receive_dpo_get(dpo->dpoi_index);
5029 FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr,
5031 "local interface adj is receive ok");
5034 * +2 entries, +2 unshared path-lists
5036 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
5037 fib_path_list_db_size());
5038 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
5039 fib_path_list_pool_size());
5040 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
5041 fib_entry_pool_size());
5045 * bring the interface back up. we expected the routes to return
5046 * to normal forwarding.
5048 error = vnet_sw_interface_set_flags(vnet_get_main(),
5049 tm->hw[0]->sw_if_index,
5050 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5051 FIB_TEST((NULL == error), "Interface bring-up OK");
5052 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5053 ai = fib_entry_get_adj(fei);
5054 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
5055 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5056 ai = fib_entry_get_adj(fei);
5057 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
5058 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5059 ai = fib_entry_get_adj(fei);
5060 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
5061 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5062 ai = fib_entry_get_adj(fei);
5063 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
5064 local_pfx.fp_len = 64;
5065 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5066 ai = fib_entry_get_adj(fei);
5068 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
5069 "attached interface adj is glean");
5072 * Same test as above, but this time the HW interface goes down
5074 error = vnet_hw_interface_set_flags(vnet_get_main(),
5075 tm->hw_if_indicies[0],
5076 ~VNET_HW_INTERFACE_FLAG_LINK_UP);
5077 FIB_TEST((NULL == error), "Interface shutdown OK");
5079 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5080 dpo = fib_entry_contribute_ip_forwarding(fei);
5081 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5082 "2001::b/64 resolves via drop");
5083 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5084 dpo = fib_entry_contribute_ip_forwarding(fei);
5085 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5086 "2001::a/64 resolves via drop");
5087 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5088 dpo = fib_entry_contribute_ip_forwarding(fei);
5089 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5090 "2001:0:0:1::3/128 resolves via drop");
5091 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5092 dpo = fib_entry_contribute_ip_forwarding(fei);
5093 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5094 "2001:0:0:1::2/128 resolves via drop");
5095 local_pfx.fp_len = 128;
5096 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5097 dpo = fib_entry_contribute_ip_forwarding(fei);
5098 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5099 "2001:0:0:1::1/128 not drop");
5100 local_pfx.fp_len = 64;
5101 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5102 dpo = fib_entry_contribute_ip_forwarding(fei);
5103 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5104 "2001:0:0:1/64 resolves via drop");
5106 error = vnet_hw_interface_set_flags(vnet_get_main(),
5107 tm->hw_if_indicies[0],
5108 VNET_HW_INTERFACE_FLAG_LINK_UP);
5109 FIB_TEST((NULL == error), "Interface bring-up OK");
5110 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5111 ai = fib_entry_get_adj(fei);
5112 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
5113 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5114 ai = fib_entry_get_adj(fei);
5115 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
5116 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5117 ai = fib_entry_get_adj(fei);
5118 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
5119 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5120 ai = fib_entry_get_adj(fei);
5121 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
5122 local_pfx.fp_len = 64;
5123 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5124 ai = fib_entry_get_adj(fei);
5126 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
5127 "attached interface adj is glean");
5130 * Delete the interface that the routes reolve through.
5131 * Again no routes are removed. They all point to drop.
5133 * This is considered an error case. The control plane should
5134 * not remove interfaces through which routes resolve, but
5135 * such things can happen. ALL affected routes will drop.
5137 vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]);
5139 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5140 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5141 "2001::b/64 resolves via drop");
5142 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5143 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5144 "2001::b/64 resolves via drop");
5145 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5146 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5147 "2001:0:0:1::3/64 resolves via drop");
5148 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5149 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5150 "2001:0:0:1::2/64 resolves via drop");
5151 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5152 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5153 "2001:0:0:1::1/128 is drop");
5154 local_pfx.fp_len = 64;
5155 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5156 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5157 "2001:0:0:1/64 resolves via drop");
5162 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
5163 fib_path_list_db_size());
5164 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
5165 fib_path_list_pool_size());
5166 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
5167 fib_entry_pool_size());
5170 * Add the interface back. routes stay unresolved.
5172 error = ethernet_register_interface(vnet_get_main(),
5173 test_interface_device_class.index,
5176 &tm->hw_if_indicies[0],
5177 /* flag change */ 0);
5179 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5180 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5181 "2001::b/64 resolves via drop");
5182 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5183 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5184 "2001::b/64 resolves via drop");
5185 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5186 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5187 "2001:0:0:1::3/64 resolves via drop");
5188 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5189 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5190 "2001:0:0:1::2/64 resolves via drop");
5191 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5192 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5193 "2001:0:0:1::1/128 is drop");
5194 local_pfx.fp_len = 64;
5195 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5196 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5197 "2001:0:0:1/64 resolves via drop");
5200 * CLEANUP ALL the routes
5202 fib_table_entry_delete(fib_index,
5205 fib_table_entry_delete(fib_index,
5208 fib_table_entry_delete(fib_index,
5211 fib_table_entry_delete(fib_index,
5212 &pfx_2001_1_3_s_128,
5214 fib_table_entry_delete(fib_index,
5215 &pfx_2001_1_2_s_128,
5217 local_pfx.fp_len = 64;
5218 fib_table_entry_delete(fib_index, &local_pfx,
5219 FIB_SOURCE_INTERFACE);
5220 local_pfx.fp_len = 128;
5221 fib_table_entry_special_remove(fib_index, &local_pfx,
5222 FIB_SOURCE_INTERFACE);
5223 connected_pfx.fp_len = 64;
5224 fib_table_entry_delete(fib_index, &connected_pfx,
5225 FIB_SOURCE_INTERFACE);
5226 connected_pfx.fp_len = 128;
5227 fib_table_entry_special_remove(fib_index, &connected_pfx,
5228 FIB_SOURCE_INTERFACE);
5230 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5231 fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)),
5232 "2001::a/64 removed");
5233 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5234 fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)),
5235 "2001::b/64 removed");
5236 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5237 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)),
5238 "2001:0:0:1::3/128 removed");
5239 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5240 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)),
5241 "2001:0:0:1::3/128 removed");
5242 local_pfx.fp_len = 64;
5243 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5244 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5245 "2001:0:0:1/64 removed");
5246 local_pfx.fp_len = 128;
5247 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5248 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5249 "2001:0:0:1::1/128 removed");
5250 connected_pfx.fp_len = 64;
5251 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5252 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5253 "2001:0:0:2/64 removed");
5254 connected_pfx.fp_len = 128;
5255 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5256 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5257 "2001:0:0:2::1/128 removed");
5260 * -8 entries. -7 path-lists (1 was shared).
5262 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5263 fib_path_list_db_size());
5264 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is%d",
5265 fib_path_list_pool_size());
5266 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
5267 fib_entry_pool_size());
5270 * now remove the VRF
5273 for (ii = 0; ii < 4; ii++)
5274 fib_table_bind (FIB_PROTOCOL_IP6, tm->hw[ii]->sw_if_index, 0);
5276 fib_table_unlock(fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
5278 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5279 fib_path_list_db_size());
5280 FIB_TEST((PNPS-2 == fib_path_list_pool_size()), "path list pool size is%d",
5281 fib_path_list_pool_size());
5282 FIB_TEST((ENPS-2 == fib_entry_pool_size()), "entry pool size is %d",
5283 fib_entry_pool_size());
5289 * return the interfaces to up state
5291 error = vnet_sw_interface_set_flags(vnet_get_main(),
5292 tm->hw[0]->sw_if_index,
5293 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5294 error = vnet_sw_interface_set_flags(vnet_get_main(),
5295 tm->hw[1]->sw_if_index,
5296 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5298 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5300 FIB_TEST((0 == adj_glean_db_size()), "ADJ DB size is %d",
5301 adj_glean_db_size());
5307 * Test Attached Exports
5312 const dpo_id_t *dpo, *dpo_drop;
5313 const u32 fib_index = 0;
5314 fib_node_index_t dfrt, fei;
5321 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5325 * add interface routes. We'll assume this works. It's more rigorously
5328 fib_prefix_t local_pfx = {
5330 .fp_proto = FIB_PROTOCOL_IP4,
5334 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5339 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[0]->sw_if_index, fib_index);
5341 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
5343 fib_table_entry_update_one_path(fib_index, &local_pfx,
5344 FIB_SOURCE_INTERFACE,
5345 (FIB_ENTRY_FLAG_CONNECTED |
5346 FIB_ENTRY_FLAG_ATTACHED),
5349 tm->hw[0]->sw_if_index,
5353 FIB_ROUTE_PATH_FLAG_NONE);
5354 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5355 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5356 "attached interface route present");
5358 local_pfx.fp_len = 32;
5359 fib_table_entry_update_one_path(fib_index, &local_pfx,
5360 FIB_SOURCE_INTERFACE,
5361 (FIB_ENTRY_FLAG_CONNECTED |
5362 FIB_ENTRY_FLAG_LOCAL),
5365 tm->hw[0]->sw_if_index,
5366 ~0, // invalid fib index
5369 FIB_ROUTE_PATH_FLAG_NONE);
5370 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5372 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5373 "local interface route present");
5376 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
5378 fib_prefix_t pfx_10_10_10_1_s_32 = {
5380 .fp_proto = FIB_PROTOCOL_IP4,
5383 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5386 fib_node_index_t ai;
5388 fib_table_entry_path_add(fib_index,
5389 &pfx_10_10_10_1_s_32,
5391 FIB_ENTRY_FLAG_ATTACHED,
5393 &pfx_10_10_10_1_s_32.fp_addr,
5394 tm->hw[0]->sw_if_index,
5395 ~0, // invalid fib index
5398 FIB_ROUTE_PATH_FLAG_NONE);
5400 fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
5401 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
5402 ai = fib_entry_get_adj(fei);
5405 * create another FIB table into which routes will be imported
5407 u32 import_fib_index1;
5409 import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4,
5413 * Add default route in the import FIB
5415 fib_prefix_t pfx_0_0_0_0_s_0 = {
5417 .fp_proto = FIB_PROTOCOL_IP4,
5425 dfrt = fib_table_lookup(import_fib_index1, &pfx_0_0_0_0_s_0);
5426 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
5428 fib_table_entry_path_add(import_fib_index1,
5431 FIB_ENTRY_FLAG_NONE,
5434 tm->hw[0]->sw_if_index,
5435 ~0, // invalid fib index
5438 FIB_ROUTE_PATH_FLAG_NONE);
5439 fei = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
5440 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "default route present");
5441 FIB_TEST((fei != dfrt), "default route added");
5444 * delete default route and check for the presence in the import table
5446 fib_table_entry_delete(import_fib_index1, &pfx_0_0_0_0_s_0, FIB_SOURCE_API);
5447 fei = fib_table_lookup(import_fib_index1, &pfx_0_0_0_0_s_0);
5448 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "default route present");
5449 FIB_TEST((fei == dfrt), "default route removed");
5452 * Add an attached route in the import FIB
5454 local_pfx.fp_len = 24;
5455 fib_table_entry_update_one_path(import_fib_index1,
5458 FIB_ENTRY_FLAG_NONE,
5461 tm->hw[0]->sw_if_index,
5462 ~0, // invalid fib index
5465 FIB_ROUTE_PATH_FLAG_NONE);
5466 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5467 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5470 * check for the presence of the adj-fibs in the import table
5472 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5473 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5474 FIB_TEST((ai == fib_entry_get_adj(fei)),
5475 "adj-fib1 Import uses same adj as export");
5478 * check for the presence of the local in the import table
5480 local_pfx.fp_len = 32;
5481 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5482 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5485 * Add another adj-fin in the export table. Expect this
5486 * to get magically exported;
5488 fib_prefix_t pfx_10_10_10_2_s_32 = {
5490 .fp_proto = FIB_PROTOCOL_IP4,
5493 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5497 fib_table_entry_path_add(fib_index,
5498 &pfx_10_10_10_2_s_32,
5500 FIB_ENTRY_FLAG_ATTACHED,
5502 &pfx_10_10_10_2_s_32.fp_addr,
5503 tm->hw[0]->sw_if_index,
5504 ~0, // invalid fib index
5507 FIB_ROUTE_PATH_FLAG_NONE);
5508 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5509 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
5510 ai = fib_entry_get_adj(fei);
5512 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5513 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5514 FIB_TEST((ai == fib_entry_get_adj(fei)),
5515 "Import uses same adj as export");
5516 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(fei)),
5517 "ADJ-fib2 imported flags %d",
5518 fib_entry_get_flags(fei));
5521 * create a 2nd FIB table into which routes will be imported
5523 u32 import_fib_index2;
5525 import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12,
5529 * Add an attached route in the import FIB
5531 local_pfx.fp_len = 24;
5532 fib_table_entry_update_one_path(import_fib_index2,
5535 FIB_ENTRY_FLAG_NONE,
5538 tm->hw[0]->sw_if_index,
5539 ~0, // invalid fib index
5542 FIB_ROUTE_PATH_FLAG_NONE);
5543 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5544 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5547 * check for the presence of all the adj-fibs and local in the import table
5549 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5550 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5551 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5552 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5553 local_pfx.fp_len = 32;
5554 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5555 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5558 * add a 3rd adj-fib. expect it to be exported to both tables.
5560 fib_prefix_t pfx_10_10_10_3_s_32 = {
5562 .fp_proto = FIB_PROTOCOL_IP4,
5565 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
5569 fib_table_entry_path_add(fib_index,
5570 &pfx_10_10_10_3_s_32,
5572 FIB_ENTRY_FLAG_ATTACHED,
5574 &pfx_10_10_10_3_s_32.fp_addr,
5575 tm->hw[0]->sw_if_index,
5576 ~0, // invalid fib index
5579 FIB_ROUTE_PATH_FLAG_NONE);
5580 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5581 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
5582 ai = fib_entry_get_adj(fei);
5584 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5585 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1");
5586 FIB_TEST((ai == fib_entry_get_adj(fei)),
5587 "Import uses same adj as export");
5588 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5589 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2");
5590 FIB_TEST((ai == fib_entry_get_adj(fei)),
5591 "Import uses same adj as export");
5594 * remove the 3rd adj fib. we expect it to be removed from both FIBs
5596 fib_table_entry_delete(fib_index,
5597 &pfx_10_10_10_3_s_32,
5600 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5601 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved");
5603 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5604 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1");
5606 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5607 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2");
5610 * remove the attached route from the 2nd FIB. expect the imported
5611 * entries to be removed
5613 local_pfx.fp_len = 24;
5614 fib_table_entry_delete(import_fib_index2,
5617 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5618 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed");
5620 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5621 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2");
5622 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5623 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2");
5624 local_pfx.fp_len = 32;
5625 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5626 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2");
5628 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5629 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1");
5630 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5631 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1");
5632 local_pfx.fp_len = 32;
5633 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5634 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1");
5637 * modify the route in FIB1 so it is no longer attached. expect the imported
5638 * entries to be removed
5640 local_pfx.fp_len = 24;
5641 fib_table_entry_update_one_path(import_fib_index1,
5644 FIB_ENTRY_FLAG_NONE,
5646 &pfx_10_10_10_2_s_32.fp_addr,
5647 tm->hw[0]->sw_if_index,
5648 ~0, // invalid fib index
5651 FIB_ROUTE_PATH_FLAG_NONE);
5652 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5653 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5654 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5655 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5656 local_pfx.fp_len = 32;
5657 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5658 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5661 * modify it back to attached. expect the adj-fibs back
5663 local_pfx.fp_len = 24;
5664 fib_table_entry_update_one_path(import_fib_index1,
5667 FIB_ENTRY_FLAG_NONE,
5670 tm->hw[0]->sw_if_index,
5671 ~0, // invalid fib index
5674 FIB_ROUTE_PATH_FLAG_NONE);
5675 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5676 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1");
5677 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5678 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1");
5679 local_pfx.fp_len = 32;
5680 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5681 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1");
5684 * add a covering attached next-hop for the interface address, so we have
5685 * a valid adj to find when we check the forwarding tables
5687 fib_prefix_t pfx_10_0_0_0_s_8 = {
5689 .fp_proto = FIB_PROTOCOL_IP4,
5692 .ip4.as_u32 = clib_host_to_net_u32(0x0a000000),
5696 fei = fib_table_entry_update_one_path(fib_index,
5699 FIB_ENTRY_FLAG_NONE,
5701 &pfx_10_10_10_3_s_32.fp_addr,
5702 tm->hw[0]->sw_if_index,
5703 ~0, // invalid fib index
5706 FIB_ROUTE_PATH_FLAG_NONE);
5707 dpo = fib_entry_contribute_ip_forwarding(fei);
5710 * remove the route in the export fib. expect the adj-fibs to be removed
5712 local_pfx.fp_len = 24;
5713 fib_table_entry_delete(fib_index,
5715 FIB_SOURCE_INTERFACE);
5717 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5718 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1");
5719 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5720 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5721 local_pfx.fp_len = 32;
5722 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5723 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5726 * the adj-fibs in the export VRF are present in the FIB table,
5727 * but not installed in forwarding, since they have no attached cover.
5728 * Consequently a lookup in the MTRIE gives the adj for the covering
5731 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5732 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5735 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5736 FIB_TEST(lbi == dpo->dpoi_index,
5737 "10.10.10.1 forwards on \n%U not \n%U",
5738 format_load_balance, lbi, 0,
5739 format_dpo_id, dpo, 0);
5740 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5741 FIB_TEST(lbi == dpo->dpoi_index,
5742 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5743 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4);
5744 FIB_TEST(lbi == dpo->dpoi_index,
5745 "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0);
5748 * add the export prefix back, but not as attached.
5749 * No adj-fibs in export nor import tables
5751 local_pfx.fp_len = 24;
5752 fei = fib_table_entry_update_one_path(fib_index,
5755 FIB_ENTRY_FLAG_NONE,
5757 &pfx_10_10_10_1_s_32.fp_addr,
5758 tm->hw[0]->sw_if_index,
5759 ~0, // invalid fib index
5762 FIB_ROUTE_PATH_FLAG_NONE);
5763 dpo = fib_entry_contribute_ip_forwarding(fei);
5765 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5766 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export");
5767 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5768 FIB_TEST(lbi == dpo->dpoi_index,
5769 "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0);
5770 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5771 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5772 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5773 FIB_TEST(lbi == dpo->dpoi_index,
5774 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5776 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5777 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5778 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5779 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5780 local_pfx.fp_len = 32;
5781 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5782 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5785 * modify the export prefix so it is attached. expect all covereds to return
5787 local_pfx.fp_len = 24;
5788 fib_table_entry_update_one_path(fib_index,
5791 FIB_ENTRY_FLAG_NONE,
5794 tm->hw[0]->sw_if_index,
5795 ~0, // invalid fib index
5798 FIB_ROUTE_PATH_FLAG_NONE);
5800 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5801 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5802 dpo = fib_entry_contribute_ip_forwarding(fei);
5803 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5804 "Adj-fib1 is not drop in export");
5805 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5806 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5807 local_pfx.fp_len = 32;
5808 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5809 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5810 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5811 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5812 dpo = fib_entry_contribute_ip_forwarding(fei);
5813 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5814 "Adj-fib1 is not drop in export: %U %U",
5815 format_dpo_id, dpo, 0,
5816 format_dpo_id, load_balance_get_bucket(dpo->dpoi_index, 0), 0);
5817 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5818 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5819 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5820 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5821 local_pfx.fp_len = 32;
5822 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5823 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5826 * modify the export prefix so connected. no change.
5828 local_pfx.fp_len = 24;
5829 fib_table_entry_update_one_path(fib_index, &local_pfx,
5830 FIB_SOURCE_INTERFACE,
5831 (FIB_ENTRY_FLAG_CONNECTED |
5832 FIB_ENTRY_FLAG_ATTACHED),
5835 tm->hw[0]->sw_if_index,
5839 FIB_ROUTE_PATH_FLAG_NONE);
5841 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5842 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5843 dpo = fib_entry_contribute_ip_forwarding(fei);
5844 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5845 "Adj-fib1 is not drop in export");
5846 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5847 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5848 local_pfx.fp_len = 32;
5849 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5850 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5851 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5852 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5853 dpo = fib_entry_contribute_ip_forwarding(fei);
5854 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5855 "Adj-fib1 is not drop in export");
5856 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5857 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5858 local_pfx.fp_len = 32;
5859 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5860 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5865 fib_table_entry_delete(fib_index,
5868 fib_table_entry_delete(fib_index,
5869 &pfx_10_10_10_1_s_32,
5871 fib_table_entry_delete(fib_index,
5872 &pfx_10_10_10_2_s_32,
5874 local_pfx.fp_len = 32;
5875 fib_table_entry_delete(fib_index,
5877 FIB_SOURCE_INTERFACE);
5878 local_pfx.fp_len = 24;
5879 fib_table_entry_delete(fib_index,
5882 fib_table_entry_delete(fib_index,
5884 FIB_SOURCE_INTERFACE);
5885 local_pfx.fp_len = 24;
5886 fib_table_entry_delete(import_fib_index1,
5890 fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
5891 fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
5893 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5900 * Test Path Preference
5903 fib_test_pref (void)
5911 const fib_prefix_t pfx_1_1_1_1_s_32 = {
5913 .fp_proto = FIB_PROTOCOL_IP4,
5916 .as_u32 = clib_host_to_net_u32(0x01010101),
5921 for (i = 0; i <= 2; i++)
5922 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[i]->sw_if_index, 0);
5925 * 2 high, 2 medium and 2 low preference non-recursive paths
5927 fib_route_path_t nr_path_hi_1 = {
5928 .frp_proto = DPO_PROTO_IP4,
5929 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5930 .frp_fib_index = ~0,
5932 .frp_preference = 0,
5933 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5935 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5938 fib_route_path_t nr_path_hi_2 = {
5939 .frp_proto = DPO_PROTO_IP4,
5940 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5941 .frp_fib_index = ~0,
5943 .frp_preference = 0,
5944 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5946 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5949 fib_route_path_t nr_path_med_1 = {
5950 .frp_proto = DPO_PROTO_IP4,
5951 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5952 .frp_fib_index = ~0,
5954 .frp_preference = 1,
5955 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5957 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5960 fib_route_path_t nr_path_med_2 = {
5961 .frp_proto = DPO_PROTO_IP4,
5962 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5963 .frp_fib_index = ~0,
5965 .frp_preference = 1,
5966 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5968 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5971 fib_route_path_t nr_path_low_1 = {
5972 .frp_proto = DPO_PROTO_IP4,
5973 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5974 .frp_fib_index = ~0,
5976 .frp_preference = 2,
5977 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5979 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b01),
5982 fib_route_path_t nr_path_low_2 = {
5983 .frp_proto = DPO_PROTO_IP4,
5984 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5985 .frp_fib_index = ~0,
5987 .frp_preference = 2,
5988 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5990 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b02),
5993 fib_route_path_t *nr_paths = NULL;
5995 vec_add1(nr_paths, nr_path_hi_1);
5996 vec_add1(nr_paths, nr_path_hi_2);
5997 vec_add1(nr_paths, nr_path_med_1);
5998 vec_add1(nr_paths, nr_path_med_2);
5999 vec_add1(nr_paths, nr_path_low_1);
6000 vec_add1(nr_paths, nr_path_low_2);
6002 adj_index_t ai_hi_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6004 &nr_path_hi_1.frp_addr,
6005 nr_path_hi_1.frp_sw_if_index);
6006 adj_index_t ai_hi_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6008 &nr_path_hi_2.frp_addr,
6009 nr_path_hi_2.frp_sw_if_index);
6010 adj_index_t ai_med_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6012 &nr_path_med_1.frp_addr,
6013 nr_path_med_1.frp_sw_if_index);
6014 adj_index_t ai_med_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6016 &nr_path_med_2.frp_addr,
6017 nr_path_med_2.frp_sw_if_index);
6018 adj_index_t ai_low_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6020 &nr_path_low_1.frp_addr,
6021 nr_path_low_1.frp_sw_if_index);
6022 adj_index_t ai_low_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6024 &nr_path_low_2.frp_addr,
6025 nr_path_low_2.frp_sw_if_index);
6027 fib_test_lb_bucket_t ip_hi_1 = {
6033 fib_test_lb_bucket_t ip_hi_2 = {
6039 fib_test_lb_bucket_t ip_med_1 = {
6045 fib_test_lb_bucket_t ip_med_2 = {
6051 fib_test_lb_bucket_t ip_low_1 = {
6057 fib_test_lb_bucket_t ip_low_2 = {
6064 fib_node_index_t fei;
6066 fei = fib_table_entry_path_add2(0,
6069 FIB_ENTRY_FLAG_NONE,
6072 FIB_TEST(!fib_test_validate_entry(fei,
6073 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6077 "1.1.1.1/32 via high preference paths");
6080 * bring down the interface on which the high preference path lie
6082 vnet_sw_interface_set_flags(vnet_get_main(),
6083 tm->hw[0]->sw_if_index,
6086 FIB_TEST(!fib_test_validate_entry(fei,
6087 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6091 "1.1.1.1/32 via medium preference paths");
6094 * bring down the interface on which the medium preference path lie
6096 vnet_sw_interface_set_flags(vnet_get_main(),
6097 tm->hw[1]->sw_if_index,
6100 FIB_TEST(!fib_test_validate_entry(fei,
6101 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6105 "1.1.1.1/32 via low preference paths");
6108 * bring up the interface on which the high preference path lie
6110 vnet_sw_interface_set_flags(vnet_get_main(),
6111 tm->hw[0]->sw_if_index,
6112 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6114 FIB_TEST(!fib_test_validate_entry(fei,
6115 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6119 "1.1.1.1/32 via high preference paths");
6122 * bring up the interface on which the medium preference path lie
6124 vnet_sw_interface_set_flags(vnet_get_main(),
6125 tm->hw[1]->sw_if_index,
6126 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6128 FIB_TEST(!fib_test_validate_entry(fei,
6129 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6133 "1.1.1.1/32 via high preference paths");
6135 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
6136 fib_entry_contribute_forwarding(fei,
6137 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6141 * 3 recursive paths of different preference
6143 const fib_prefix_t pfx_1_1_1_2_s_32 = {
6145 .fp_proto = FIB_PROTOCOL_IP4,
6148 .as_u32 = clib_host_to_net_u32(0x01010102),
6152 const fib_prefix_t pfx_1_1_1_3_s_32 = {
6154 .fp_proto = FIB_PROTOCOL_IP4,
6157 .as_u32 = clib_host_to_net_u32(0x01010103),
6161 fei = fib_table_entry_path_add2(0,
6164 FIB_ENTRY_FLAG_NONE,
6166 dpo_id_t ip_1_1_1_2 = DPO_INVALID;
6167 fib_entry_contribute_forwarding(fei,
6168 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6170 fei = fib_table_entry_path_add2(0,
6173 FIB_ENTRY_FLAG_NONE,
6175 dpo_id_t ip_1_1_1_3 = DPO_INVALID;
6176 fib_entry_contribute_forwarding(fei,
6177 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6180 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
6183 .lb = ip_1_1_1_1.dpoi_index,
6186 fib_test_lb_bucket_t ip_o_1_1_1_2 = {
6189 .lb = ip_1_1_1_2.dpoi_index,
6192 fib_test_lb_bucket_t ip_o_1_1_1_3 = {
6195 .lb = ip_1_1_1_3.dpoi_index,
6198 fib_route_path_t r_path_hi = {
6199 .frp_proto = DPO_PROTO_IP4,
6200 .frp_sw_if_index = ~0,
6203 .frp_preference = 0,
6204 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
6205 .frp_addr = pfx_1_1_1_1_s_32.fp_addr,
6207 fib_route_path_t r_path_med = {
6208 .frp_proto = DPO_PROTO_IP4,
6209 .frp_sw_if_index = ~0,
6212 .frp_preference = 10,
6213 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
6214 .frp_addr = pfx_1_1_1_2_s_32.fp_addr,
6216 fib_route_path_t r_path_low = {
6217 .frp_proto = DPO_PROTO_IP4,
6218 .frp_sw_if_index = ~0,
6221 .frp_preference = 255,
6222 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
6223 .frp_addr = pfx_1_1_1_3_s_32.fp_addr,
6225 fib_route_path_t *r_paths = NULL;
6227 vec_add1(r_paths, r_path_hi);
6228 vec_add1(r_paths, r_path_low);
6229 vec_add1(r_paths, r_path_med);
6232 * add many recursive so we get the LB MAp created
6235 fib_prefix_t pfx_r[N_PFXS];
6236 unsigned int n_pfxs;
6237 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6239 pfx_r[n_pfxs].fp_len = 32;
6240 pfx_r[n_pfxs].fp_proto = FIB_PROTOCOL_IP4;
6241 pfx_r[n_pfxs].fp_addr.ip4.as_u32 =
6242 clib_host_to_net_u32(0x02000000 + n_pfxs);
6244 fei = fib_table_entry_path_add2(0,
6247 FIB_ENTRY_FLAG_NONE,
6250 FIB_TEST(!fib_test_validate_entry(fei,
6251 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6254 "recursive via high preference paths");
6257 * withdraw hig pref resolving entry
6259 fib_table_entry_delete(0,
6263 /* suspend so the update walk kicks int */
6264 vlib_process_suspend(vlib_get_main(), 1e-5);
6266 FIB_TEST(!fib_test_validate_entry(fei,
6267 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6270 "recursive via medium preference paths");
6273 * withdraw medium pref resolving entry
6275 fib_table_entry_delete(0,
6279 /* suspend so the update walk kicks int */
6280 vlib_process_suspend(vlib_get_main(), 1e-5);
6282 FIB_TEST(!fib_test_validate_entry(fei,
6283 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6286 "recursive via low preference paths");
6289 * add back paths for next iteration
6291 fei = fib_table_entry_update(0,
6294 FIB_ENTRY_FLAG_NONE,
6296 fei = fib_table_entry_update(0,
6299 FIB_ENTRY_FLAG_NONE,
6302 /* suspend so the update walk kicks int */
6303 vlib_process_suspend(vlib_get_main(), 1e-5);
6305 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6306 FIB_TEST(!fib_test_validate_entry(fei,
6307 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6310 "recursive via high preference paths");
6314 fib_table_entry_delete(0,
6318 /* suspend so the update walk kicks int */
6319 vlib_process_suspend(vlib_get_main(), 1e-5);
6321 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6323 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6325 FIB_TEST(!fib_test_validate_entry(fei,
6326 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6329 "recursive via medium preference paths");
6331 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6333 fib_table_entry_delete(0,
6341 fib_table_entry_delete(0,
6344 fib_table_entry_delete(0,
6348 dpo_reset(&ip_1_1_1_1);
6349 dpo_reset(&ip_1_1_1_2);
6350 dpo_reset(&ip_1_1_1_3);
6351 adj_unlock(ai_low_2);
6352 adj_unlock(ai_low_1);
6353 adj_unlock(ai_med_2);
6354 adj_unlock(ai_med_1);
6355 adj_unlock(ai_hi_2);
6356 adj_unlock(ai_hi_1);
6362 * Test the recursive route route handling for GRE tunnels
6365 fib_test_label (void)
6367 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;
6368 const u32 fib_index = 0;
6369 int lb_count, ii, res;
6373 lb_count = pool_elts(load_balance_pool);
6377 * add interface routes. We'll assume this works. It's more rigorously
6380 fib_prefix_t local0_pfx = {
6382 .fp_proto = FIB_PROTOCOL_IP4,
6386 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
6391 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6394 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[0]->sw_if_index, fib_index);
6396 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6397 FIB_SOURCE_INTERFACE,
6398 (FIB_ENTRY_FLAG_CONNECTED |
6399 FIB_ENTRY_FLAG_ATTACHED),
6402 tm->hw[0]->sw_if_index,
6406 FIB_ROUTE_PATH_FLAG_NONE);
6407 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6408 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6409 "attached interface route present");
6411 local0_pfx.fp_len = 32;
6412 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6413 FIB_SOURCE_INTERFACE,
6414 (FIB_ENTRY_FLAG_CONNECTED |
6415 FIB_ENTRY_FLAG_LOCAL),
6418 tm->hw[0]->sw_if_index,
6419 ~0, // invalid fib index
6422 FIB_ROUTE_PATH_FLAG_NONE);
6423 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6425 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6426 "local interface route present");
6428 fib_prefix_t local1_pfx = {
6430 .fp_proto = FIB_PROTOCOL_IP4,
6434 .as_u32 = clib_host_to_net_u32(0x0a0a0b0a),
6439 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[1]->sw_if_index, fib_index);
6441 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6442 FIB_SOURCE_INTERFACE,
6443 (FIB_ENTRY_FLAG_CONNECTED |
6444 FIB_ENTRY_FLAG_ATTACHED),
6447 tm->hw[1]->sw_if_index,
6451 FIB_ROUTE_PATH_FLAG_NONE);
6452 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6453 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6454 "attached interface route present");
6456 local1_pfx.fp_len = 32;
6457 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6458 FIB_SOURCE_INTERFACE,
6459 (FIB_ENTRY_FLAG_CONNECTED |
6460 FIB_ENTRY_FLAG_LOCAL),
6463 tm->hw[1]->sw_if_index,
6464 ~0, // invalid fib index
6467 FIB_ROUTE_PATH_FLAG_NONE);
6468 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6470 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6471 "local interface route present");
6473 ip46_address_t nh_10_10_10_1 = {
6475 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
6478 ip46_address_t nh_10_10_11_1 = {
6480 .as_u32 = clib_host_to_net_u32(0x0a0a0b01),
6483 ip46_address_t nh_10_10_11_2 = {
6485 .as_u32 = clib_host_to_net_u32(0x0a0a0b02),
6489 ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6492 tm->hw[1]->sw_if_index);
6493 ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6496 tm->hw[1]->sw_if_index);
6497 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6500 tm->hw[0]->sw_if_index);
6501 ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6504 tm->hw[1]->sw_if_index);
6505 ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6508 tm->hw[1]->sw_if_index);
6511 * Add an etry with one path with a real out-going label
6513 fib_prefix_t pfx_1_1_1_1_s_32 = {
6515 .fp_proto = FIB_PROTOCOL_IP4,
6517 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
6520 fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = {
6521 .type = FT_LB_LABEL_O_ADJ,
6523 .adj = ai_mpls_10_10_10_1,
6528 fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = {
6529 .type = FT_LB_LABEL_O_ADJ,
6531 .adj = ai_mpls_10_10_10_1,
6533 .eos = MPLS_NON_EOS,
6536 fib_mpls_label_t *l99 = NULL, fml99 = {
6539 vec_add1(l99, fml99);
6541 fib_table_entry_update_one_path(fib_index,
6544 FIB_ENTRY_FLAG_NONE,
6547 tm->hw[0]->sw_if_index,
6548 ~0, // invalid fib index
6551 FIB_ROUTE_PATH_FLAG_NONE);
6553 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6554 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created");
6556 FIB_TEST(!fib_test_validate_entry(fei,
6557 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6559 &l99_eos_o_10_10_10_1),
6560 "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1");
6563 * add a path with an implicit NULL label
6565 fib_test_lb_bucket_t a_o_10_10_11_1 = {
6568 .adj = ai_v4_10_10_11_1,
6571 fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = {
6574 .adj = ai_mpls_10_10_11_1,
6577 fib_mpls_label_t *l_imp_null = NULL, fml_imp_null = {
6578 .fml_value = MPLS_IETF_IMPLICIT_NULL_LABEL,
6580 vec_add1(l_imp_null, fml_imp_null);
6582 fei = fib_table_entry_path_add(fib_index,
6585 FIB_ENTRY_FLAG_NONE,
6588 tm->hw[1]->sw_if_index,
6589 ~0, // invalid fib index
6592 FIB_ROUTE_PATH_FLAG_NONE);
6594 FIB_TEST(!fib_test_validate_entry(fei,
6595 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6597 &l99_eos_o_10_10_10_1,
6599 "1.1.1.1/32 LB 2 buckets via: "
6600 "label 99 over 10.10.10.1, "
6601 "adj over 10.10.11.1");
6604 * assign the route a local label
6606 fib_table_entry_local_label_add(fib_index,
6610 fib_prefix_t pfx_24001_eos = {
6611 .fp_proto = FIB_PROTOCOL_MPLS,
6615 fib_prefix_t pfx_24001_neos = {
6616 .fp_proto = FIB_PROTOCOL_MPLS,
6618 .fp_eos = MPLS_NON_EOS,
6620 fib_test_lb_bucket_t disp_o_10_10_11_1 = {
6621 .type = FT_LB_MPLS_DISP_PIPE_O_ADJ,
6623 .adj = ai_v4_10_10_11_1,
6628 * The EOS entry should link to both the paths,
6629 * and use an ip adj for the imp-null
6630 * The NON-EOS entry should link to both the paths,
6631 * and use an mpls adj for the imp-null
6633 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6635 FIB_TEST(!fib_test_validate_entry(fei,
6636 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6638 &l99_eos_o_10_10_10_1,
6639 &disp_o_10_10_11_1),
6640 "24001/eos LB 2 buckets via: "
6641 "label 99 over 10.10.10.1, "
6642 "mpls disp adj over 10.10.11.1");
6645 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6647 FIB_TEST(!fib_test_validate_entry(fei,
6648 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6650 &l99_neos_o_10_10_10_1,
6651 &a_mpls_o_10_10_11_1),
6652 "24001/neos LB 1 bucket via: "
6653 "label 99 over 10.10.10.1 ",
6654 "mpls-adj via 10.10.11.1");
6657 * add an unlabelled path, this is excluded from the neos chains,
6659 fib_test_lb_bucket_t adj_o_10_10_11_2 = {
6662 .adj = ai_v4_10_10_11_2,
6665 fib_test_lb_bucket_t disp_o_10_10_11_2 = {
6666 .type = FT_LB_MPLS_DISP_PIPE_O_ADJ,
6668 .adj = ai_v4_10_10_11_2,
6673 fei = fib_table_entry_path_add(fib_index,
6676 FIB_ENTRY_FLAG_NONE,
6679 tm->hw[1]->sw_if_index,
6680 ~0, // invalid fib index
6683 FIB_ROUTE_PATH_FLAG_NONE);
6685 FIB_TEST(!fib_test_validate_entry(fei,
6686 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6687 16, // 3 choices spread over 16 buckets
6688 &l99_eos_o_10_10_10_1,
6689 &l99_eos_o_10_10_10_1,
6690 &l99_eos_o_10_10_10_1,
6691 &l99_eos_o_10_10_10_1,
6692 &l99_eos_o_10_10_10_1,
6693 &l99_eos_o_10_10_10_1,
6704 "1.1.1.1/32 LB 16 buckets via: "
6705 "label 99 over 10.10.10.1, "
6706 "adj over 10.10.11.1",
6707 "adj over 10.10.11.2");
6710 * get and lock a reference to the non-eos of the via entry 1.1.1.1/32
6712 dpo_id_t non_eos_1_1_1_1 = DPO_INVALID;
6713 fib_entry_contribute_forwarding(fei,
6714 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6718 * n-eos has only the 2 labelled paths
6720 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6723 FIB_TEST(!fib_test_validate_entry(fei,
6724 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6726 &l99_neos_o_10_10_10_1,
6727 &a_mpls_o_10_10_11_1),
6728 "24001/neos LB 2 buckets via: "
6729 "label 99 over 10.10.10.1, "
6730 "adj-mpls over 10.10.11.2");
6733 * A labelled recursive
6735 fib_prefix_t pfx_2_2_2_2_s_32 = {
6737 .fp_proto = FIB_PROTOCOL_IP4,
6739 .ip4.as_u32 = clib_host_to_net_u32(0x02020202),
6742 fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = {
6743 .type = FT_LB_LABEL_O_LB,
6745 .lb = non_eos_1_1_1_1.dpoi_index,
6748 .mode = FIB_MPLS_LSP_MODE_UNIFORM,
6751 fib_mpls_label_t *l1600 = NULL, fml1600 = {
6753 .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM,
6755 vec_add1(l1600, fml1600);
6757 fei = fib_table_entry_update_one_path(fib_index,
6760 FIB_ENTRY_FLAG_NONE,
6762 &pfx_1_1_1_1_s_32.fp_addr,
6767 FIB_ROUTE_PATH_FLAG_NONE);
6769 FIB_TEST(!fib_test_validate_entry(fei,
6770 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6772 &l1600_eos_o_1_1_1_1),
6773 "2.2.2.2.2/32 LB 1 buckets via: "
6774 "label 1600 over 1.1.1.1");
6776 dpo_id_t dpo_44 = DPO_INVALID;
6779 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
6780 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
6782 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
6783 "uRPF check for 2.2.2.2/32 on %d OK",
6784 tm->hw[0]->sw_if_index);
6785 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
6786 "uRPF check for 2.2.2.2/32 on %d OK",
6787 tm->hw[1]->sw_if_index);
6788 FIB_TEST(!fib_urpf_check(urpfi, 99),
6789 "uRPF check for 2.2.2.2/32 on 99 not-OK",
6792 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44);
6793 FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index),
6794 "Shared uRPF on IP and non-EOS chain");
6799 * we are holding a lock on the non-eos LB of the via-entry.
6800 * do a PIC-core failover by shutting the link of the via-entry.
6802 * shut down the link with the valid label
6804 vnet_sw_interface_set_flags(vnet_get_main(),
6805 tm->hw[0]->sw_if_index,
6808 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6809 FIB_TEST(!fib_test_validate_entry(fei,
6810 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6814 "1.1.1.1/32 LB 2 buckets via: "
6815 "adj over 10.10.11.1, ",
6816 "adj-v4 over 10.10.11.2");
6818 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6820 FIB_TEST(!fib_test_validate_entry(fei,
6821 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6824 &disp_o_10_10_11_2),
6825 "24001/eos LB 2 buckets via: "
6826 "mpls-disp adj over 10.10.11.1, ",
6827 "mpls-disp adj-v4 over 10.10.11.2");
6829 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6831 FIB_TEST(!fib_test_validate_entry(fei,
6832 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6834 &a_mpls_o_10_10_11_1),
6835 "24001/neos LB 1 buckets via: "
6836 "adj-mpls over 10.10.11.2");
6839 * test that the pre-failover load-balance has been in-place
6842 dpo_id_t current = DPO_INVALID;
6843 fib_entry_contribute_forwarding(fei,
6844 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6847 FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1,
6849 "PIC-core LB inplace modified %U %U",
6850 format_dpo_id, &non_eos_1_1_1_1, 0,
6851 format_dpo_id, ¤t, 0);
6853 dpo_reset(&non_eos_1_1_1_1);
6854 dpo_reset(¤t);
6857 * no-shut the link with the valid label
6859 vnet_sw_interface_set_flags(vnet_get_main(),
6860 tm->hw[0]->sw_if_index,
6861 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6863 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6864 FIB_TEST(!fib_test_validate_entry(fei,
6865 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6866 16, // 3 choices spread over 16 buckets
6867 &l99_eos_o_10_10_10_1,
6868 &l99_eos_o_10_10_10_1,
6869 &l99_eos_o_10_10_10_1,
6870 &l99_eos_o_10_10_10_1,
6871 &l99_eos_o_10_10_10_1,
6872 &l99_eos_o_10_10_10_1,
6883 "1.1.1.1/32 LB 16 buckets via: "
6884 "label 99 over 10.10.10.1, "
6885 "adj over 10.10.11.1",
6886 "adj-v4 over 10.10.11.2");
6889 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6891 FIB_TEST(!fib_test_validate_entry(fei,
6892 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6893 16, // 3 choices spread over 16 buckets
6894 &l99_eos_o_10_10_10_1,
6895 &l99_eos_o_10_10_10_1,
6896 &l99_eos_o_10_10_10_1,
6897 &l99_eos_o_10_10_10_1,
6898 &l99_eos_o_10_10_10_1,
6899 &l99_eos_o_10_10_10_1,
6909 &disp_o_10_10_11_2),
6910 "24001/eos LB 16 buckets via: "
6911 "label 99 over 10.10.10.1, "
6912 "MPLS disp adj over 10.10.11.1",
6913 "MPLS disp adj-v4 over 10.10.11.2");
6915 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6917 FIB_TEST(!fib_test_validate_entry(fei,
6918 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6920 &l99_neos_o_10_10_10_1,
6921 &a_mpls_o_10_10_11_1),
6922 "24001/neos LB 2 buckets via: "
6923 "label 99 over 10.10.10.1, "
6924 "adj-mpls over 10.10.11.2");
6927 * remove the first path with the valid label
6929 fib_table_entry_path_remove(fib_index,
6934 tm->hw[0]->sw_if_index,
6935 ~0, // invalid fib index
6937 FIB_ROUTE_PATH_FLAG_NONE);
6939 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6940 FIB_TEST(!fib_test_validate_entry(fei,
6941 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6945 "1.1.1.1/32 LB 2 buckets via: "
6946 "adj over 10.10.11.1, "
6947 "adj-v4 over 10.10.11.2");
6949 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6951 FIB_TEST(!fib_test_validate_entry(fei,
6952 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6955 &disp_o_10_10_11_2),
6956 "24001/eos LB 2 buckets via: "
6957 "MPLS disp adj over 10.10.11.1, "
6958 "MPLS disp adj-v4 over 10.10.11.2");
6960 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6963 FIB_TEST(!fib_test_validate_entry(fei,
6964 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6966 &a_mpls_o_10_10_11_1),
6967 "24001/neos LB 1 buckets via: "
6968 "adj-mpls over 10.10.11.2");
6971 * remove the other path with a valid label
6973 fib_test_lb_bucket_t bucket_drop = {
6976 fib_test_lb_bucket_t mpls_bucket_drop = {
6979 .adj = DPO_PROTO_MPLS,
6983 fib_table_entry_path_remove(fib_index,
6988 tm->hw[1]->sw_if_index,
6989 ~0, // invalid fib index
6991 FIB_ROUTE_PATH_FLAG_NONE);
6993 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6994 FIB_TEST(!fib_test_validate_entry(fei,
6995 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6998 "1.1.1.1/32 LB 1 buckets via: "
6999 "adj over 10.10.11.2");
7001 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7003 FIB_TEST(!fib_test_validate_entry(fei,
7004 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7006 &disp_o_10_10_11_2),
7007 "24001/eos LB 1 buckets via: "
7008 "MPLS disp adj over 10.10.11.2");
7010 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7012 FIB_TEST(!fib_test_validate_entry(fei,
7013 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7016 "24001/neos LB 1 buckets via: DROP");
7019 * add back the path with the valid label
7022 vec_add1(l99, fml99);
7024 fib_table_entry_path_add(fib_index,
7027 FIB_ENTRY_FLAG_NONE,
7030 tm->hw[0]->sw_if_index,
7031 ~0, // invalid fib index
7034 FIB_ROUTE_PATH_FLAG_NONE);
7036 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
7037 FIB_TEST(!fib_test_validate_entry(fei,
7038 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7040 &l99_eos_o_10_10_10_1,
7042 "1.1.1.1/32 LB 2 buckets via: "
7043 "label 99 over 10.10.10.1, "
7044 "adj over 10.10.11.2");
7046 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7048 FIB_TEST(!fib_test_validate_entry(fei,
7049 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7051 &l99_eos_o_10_10_10_1,
7052 &disp_o_10_10_11_2),
7053 "24001/eos LB 2 buckets via: "
7054 "label 99 over 10.10.10.1, "
7055 "MPLS disp adj over 10.10.11.2");
7057 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7059 FIB_TEST(!fib_test_validate_entry(fei,
7060 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7062 &l99_neos_o_10_10_10_1),
7063 "24001/neos LB 1 buckets via: "
7064 "label 99 over 10.10.10.1");
7067 * change the local label
7069 fib_table_entry_local_label_add(fib_index,
7073 fib_prefix_t pfx_25005_eos = {
7074 .fp_proto = FIB_PROTOCOL_MPLS,
7078 fib_prefix_t pfx_25005_neos = {
7079 .fp_proto = FIB_PROTOCOL_MPLS,
7081 .fp_eos = MPLS_NON_EOS,
7084 FIB_TEST((FIB_NODE_INDEX_INVALID ==
7085 fib_table_lookup(fib_index, &pfx_24001_eos)),
7086 "24001/eos removed after label change");
7087 FIB_TEST((FIB_NODE_INDEX_INVALID ==
7088 fib_table_lookup(fib_index, &pfx_24001_neos)),
7089 "24001/eos removed after label change");
7091 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7093 FIB_TEST(!fib_test_validate_entry(fei,
7094 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7096 &l99_eos_o_10_10_10_1,
7097 &disp_o_10_10_11_2),
7098 "25005/eos LB 2 buckets via: "
7099 "label 99 over 10.10.10.1, "
7100 "MPLS disp adj over 10.10.11.2");
7102 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7104 FIB_TEST(!fib_test_validate_entry(fei,
7105 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7107 &l99_neos_o_10_10_10_1),
7108 "25005/neos LB 1 buckets via: "
7109 "label 99 over 10.10.10.1");
7112 * remove the local label.
7113 * the check that the MPLS entries are gone is done by the fact the
7114 * MPLS table is no longer present.
7116 fib_table_entry_local_label_remove(fib_index,
7120 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
7121 FIB_TEST(!fib_test_validate_entry(fei,
7122 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7124 &l99_eos_o_10_10_10_1,
7126 "24001/eos LB 2 buckets via: "
7127 "label 99 over 10.10.10.1, "
7128 "adj over 10.10.11.2");
7130 FIB_TEST((FIB_NODE_INDEX_INVALID ==
7131 mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)),
7132 "No more MPLS FIB entries => table removed");
7135 * add another via-entry for the recursive
7137 fib_prefix_t pfx_1_1_1_2_s_32 = {
7139 .fp_proto = FIB_PROTOCOL_IP4,
7141 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
7144 fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = {
7145 .type = FT_LB_LABEL_O_ADJ,
7147 .adj = ai_mpls_10_10_10_1,
7152 fib_mpls_label_t *l101 = NULL, fml101 = {
7155 vec_add1(l101, fml101);
7157 fei = fib_table_entry_update_one_path(fib_index,
7160 FIB_ENTRY_FLAG_NONE,
7163 tm->hw[0]->sw_if_index,
7164 ~0, // invalid fib index
7167 FIB_ROUTE_PATH_FLAG_NONE);
7169 FIB_TEST(!fib_test_validate_entry(fei,
7170 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7172 &l101_eos_o_10_10_10_1),
7173 "1.1.1.2/32 LB 1 buckets via: "
7174 "label 101 over 10.10.10.1");
7176 dpo_id_t non_eos_1_1_1_2 = DPO_INVALID;
7177 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7179 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7181 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7183 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7186 fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = {
7187 .type = FT_LB_LABEL_O_LB,
7189 .lb = non_eos_1_1_1_2.dpoi_index,
7194 fib_mpls_label_t *l1601 = NULL, fml1601 = {
7197 vec_add1(l1601, fml1601);
7199 l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index;
7201 fei = fib_table_entry_path_add(fib_index,
7204 FIB_ENTRY_FLAG_NONE,
7206 &pfx_1_1_1_2_s_32.fp_addr,
7211 FIB_ROUTE_PATH_FLAG_NONE);
7213 FIB_TEST(!fib_test_validate_entry(fei,
7214 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7216 &l1600_eos_o_1_1_1_1,
7217 &l1601_eos_o_1_1_1_2),
7218 "2.2.2.2/32 LB 2 buckets via: "
7219 "label 1600 via 1.1,1.1, "
7220 "label 16001 via 1.1.1.2");
7223 * update the via-entry so it no longer has an imp-null path.
7224 * the LB for the recursive can use an imp-null
7227 vec_add1(l_imp_null, fml_imp_null);
7229 fei = fib_table_entry_update_one_path(fib_index,
7232 FIB_ENTRY_FLAG_NONE,
7235 tm->hw[1]->sw_if_index,
7236 ~0, // invalid fib index
7239 FIB_ROUTE_PATH_FLAG_NONE);
7241 FIB_TEST(!fib_test_validate_entry(fei,
7242 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7245 "1.1.1.2/32 LB 1 buckets via: "
7248 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7249 FIB_TEST(!fib_test_validate_entry(fei,
7250 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7252 &l1600_eos_o_1_1_1_1,
7253 &l1601_eos_o_1_1_1_2),
7254 "2.2.2.2/32 LB 2 buckets via: "
7255 "label 1600 via 1.1,1.1, "
7256 "label 16001 via 1.1.1.2");
7259 * update the via-entry so it no longer has labelled paths.
7260 * the LB for the recursive should exclue this via form its LB
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 "2.2.2.2/32 LB 1 buckets via: "
7287 "label 1600 via 1.1,1.1");
7289 dpo_reset(&non_eos_1_1_1_1);
7290 dpo_reset(&non_eos_1_1_1_2);
7293 * Add a recursive with no out-labels. We expect to use the IP of the via
7295 fib_prefix_t pfx_2_2_2_3_s_32 = {
7297 .fp_proto = FIB_PROTOCOL_IP4,
7299 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
7302 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
7304 fib_table_entry_update_one_path(fib_index,
7307 FIB_ENTRY_FLAG_NONE,
7309 &pfx_1_1_1_1_s_32.fp_addr,
7314 FIB_ROUTE_PATH_FLAG_NONE);
7316 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7318 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7321 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
7324 .lb = ip_1_1_1_1.dpoi_index,
7328 fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
7329 FIB_TEST(!fib_test_validate_entry(fei,
7330 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7333 "2.2.2.2.3/32 LB 1 buckets via: "
7337 * Add a recursive with an imp-null out-label.
7338 * We expect to use the IP of the via
7340 fib_prefix_t pfx_2_2_2_4_s_32 = {
7342 .fp_proto = FIB_PROTOCOL_IP4,
7344 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
7348 fib_table_entry_update_one_path(fib_index,
7351 FIB_ENTRY_FLAG_NONE,
7353 &pfx_1_1_1_1_s_32.fp_addr,
7358 FIB_ROUTE_PATH_FLAG_NONE);
7360 fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
7361 FIB_TEST(!fib_test_validate_entry(fei,
7362 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7365 "2.2.2.2.4/32 LB 1 buckets via: "
7368 dpo_reset(&ip_1_1_1_1);
7371 * Create an entry with a deep label stack
7373 fib_prefix_t pfx_2_2_5_5_s_32 = {
7375 .fp_proto = FIB_PROTOCOL_IP4,
7377 .ip4.as_u32 = clib_host_to_net_u32(0x02020505),
7380 fib_test_lb_bucket_t ls_eos_o_10_10_10_1 = {
7381 .type = FT_LB_LABEL_STACK_O_ADJ,
7382 .label_stack_o_adj = {
7383 .adj = ai_mpls_10_10_11_1,
7384 .label_stack_size = 8,
7386 200, 201, 202, 203, 204, 205, 206, 207
7391 fib_mpls_label_t *label_stack = NULL;
7392 vec_validate(label_stack, 7);
7393 for (ii = 0; ii < 8; ii++)
7395 label_stack[ii].fml_value = ii + 200;
7398 fei = fib_table_entry_update_one_path(fib_index,
7401 FIB_ENTRY_FLAG_NONE,
7404 tm->hw[1]->sw_if_index,
7405 ~0, // invalid fib index
7408 FIB_ROUTE_PATH_FLAG_NONE);
7410 FIB_TEST(!fib_test_validate_entry(fei,
7411 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7413 &ls_eos_o_10_10_10_1),
7414 "2.2.5.5/32 LB 1 buckets via: "
7416 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
7419 * A prefix with outgoing labels. We'll RR source a /32 it covers
7420 * and test that the RR source picks up the out-going labels
7422 fib_prefix_t pfx_100_s_8 = {
7424 .fp_proto = FIB_PROTOCOL_IP4,
7426 .ip4.as_u32 = clib_host_to_net_u32(0x64000000),
7429 fib_test_lb_bucket_t l_100_eos_o_10_10_10_1 = {
7430 .type = FT_LB_LABEL_O_ADJ,
7432 .adj = ai_mpls_10_10_11_1,
7437 fib_mpls_label_t *l1602 = NULL, fml1602 = {
7440 vec_add1(l1602, fml1602);
7441 fei = fib_table_entry_update_one_path(fib_index,
7444 FIB_ENTRY_FLAG_NONE,
7447 tm->hw[1]->sw_if_index,
7448 ~0, // invalid fib index
7451 FIB_ROUTE_PATH_FLAG_NONE);
7453 FIB_TEST(!fib_test_validate_entry(fei,
7454 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7456 &l_100_eos_o_10_10_10_1),
7457 "100.0.0.0/8 LB 1 buckets via: lbl 101 "
7460 fib_prefix_t pfx_100_1_1_1_s_32 = {
7462 .fp_proto = FIB_PROTOCOL_IP4,
7464 .ip4.as_u32 = clib_host_to_net_u32(0x64010101),
7468 fei = fib_table_entry_special_add(fib_index,
7469 &pfx_100_1_1_1_s_32,
7471 FIB_ENTRY_FLAG_NONE);
7473 FIB_TEST(!fib_test_validate_entry(fei,
7474 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7476 &l_100_eos_o_10_10_10_1),
7477 "100.1.1.1/32 LB 1 buckets via: "
7480 fib_table_entry_delete(fib_index,
7483 fib_table_entry_delete_index(fei, FIB_SOURCE_RR);
7488 fib_table_entry_delete(fib_index,
7492 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7493 FIB_TEST(!fib_test_validate_entry(fei,
7494 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7496 &l1600_eos_o_1_1_1_1),
7497 "2.2.2.2/32 LB 1 buckets via: "
7498 "label 1600 via 1.1,1.1");
7500 fib_table_entry_delete(fib_index,
7504 FIB_TEST(!fib_test_validate_entry(fei,
7505 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7508 "2.2.2.2/32 LB 1 buckets via: DROP");
7510 fib_table_entry_delete(fib_index,
7513 fib_table_entry_delete(fib_index,
7516 fib_table_entry_delete(fib_index,
7520 adj_unlock(ai_mpls_10_10_10_1);
7521 adj_unlock(ai_mpls_10_10_11_2);
7522 adj_unlock(ai_v4_10_10_11_1);
7523 adj_unlock(ai_v4_10_10_11_2);
7524 adj_unlock(ai_mpls_10_10_11_1);
7526 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
7529 local0_pfx.fp_len = 32;
7530 fib_table_entry_delete(fib_index,
7532 FIB_SOURCE_INTERFACE);
7533 local0_pfx.fp_len = 24;
7534 fib_table_entry_delete(fib_index,
7536 FIB_SOURCE_INTERFACE);
7537 local1_pfx.fp_len = 32;
7538 fib_table_entry_delete(fib_index,
7540 FIB_SOURCE_INTERFACE);
7541 local1_pfx.fp_len = 24;
7542 fib_table_entry_delete(fib_index,
7544 FIB_SOURCE_INTERFACE);
7547 * +1 for the drop LB in the MPLS tables.
7549 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
7550 "Load-balance resources freed %d of %d",
7551 lb_count+1, pool_elts(load_balance_pool));
7556 #define N_TEST_CHILDREN 4
7557 #define PARENT_INDEX 0
7559 typedef struct fib_node_test_t_
7564 fib_node_back_walk_ctx_t *ctxs;
7568 static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1];
7570 #define PARENT() (&fib_test_nodes[PARENT_INDEX].node)
7572 #define FOR_EACH_TEST_CHILD(_tc) \
7573 for (ii = 1, (_tc) = &fib_test_nodes[1]; \
7574 ii < N_TEST_CHILDREN+1; \
7575 ii++, (_tc) = &fib_test_nodes[ii])
7578 fib_test_child_get_node (fib_node_index_t index)
7580 return (&fib_test_nodes[index].node);
7583 static int fib_test_walk_spawns_walks;
7585 static fib_node_back_walk_rc_t
7586 fib_test_child_back_walk_notify (fib_node_t *node,
7587 fib_node_back_walk_ctx_t *ctx)
7589 fib_node_test_t *tc = (fib_node_test_t*) node;
7591 vec_add1(tc->ctxs, *ctx);
7593 if (1 == fib_test_walk_spawns_walks)
7594 fib_walk_sync(FIB_NODE_TYPE_TEST, tc->index, ctx);
7595 if (2 == fib_test_walk_spawns_walks)
7596 fib_walk_async(FIB_NODE_TYPE_TEST, tc->index,
7597 FIB_WALK_PRIORITY_HIGH, ctx);
7599 return (FIB_NODE_BACK_WALK_CONTINUE);
7603 fib_test_child_last_lock_gone (fib_node_t *node)
7605 fib_node_test_t *tc = (fib_node_test_t *)node;
7611 * The FIB walk's graph node virtual function table
7613 static const fib_node_vft_t fib_test_child_vft = {
7614 .fnv_get = fib_test_child_get_node,
7615 .fnv_last_lock = fib_test_child_last_lock_gone,
7616 .fnv_back_walk = fib_test_child_back_walk_notify,
7620 * the function (that should have been static but isn't so I can do this)
7621 * that processes the walk from the async queue,
7623 f64 fib_walk_process_queues(vlib_main_t * vm,
7625 u32 fib_walk_queue_get_size(fib_walk_priority_t prio);
7628 fib_test_walk (void)
7630 fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {};
7631 fib_node_test_t *tc;
7636 vm = vlib_get_main();
7637 fib_node_register_type(FIB_NODE_TYPE_TEST, &fib_test_child_vft);
7640 * init a fake node on which we will add children
7642 fib_node_init(&fib_test_nodes[PARENT_INDEX].node,
7643 FIB_NODE_TYPE_TEST);
7645 FOR_EACH_TEST_CHILD(tc)
7647 fib_node_init(&tc->node, FIB_NODE_TYPE_TEST);
7648 fib_node_lock(&tc->node);
7651 tc->sibling = fib_node_child_add(FIB_NODE_TYPE_TEST,
7653 FIB_NODE_TYPE_TEST, ii);
7657 * enqueue a walk across the parents children.
7659 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7661 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7662 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7663 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7664 "Parent has %d children pre-walk",
7665 fib_node_list_get_size(PARENT()->fn_children));
7668 * give the walk a large amount of time so it gets to the end
7670 fib_walk_process_queues(vm, 1);
7672 FOR_EACH_TEST_CHILD(tc)
7674 FIB_TEST(1 == vec_len(tc->ctxs),
7675 "%d child visitsed %d times",
7676 ii, vec_len(tc->ctxs));
7679 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7680 "Queue is empty post walk");
7681 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7682 "Parent has %d children post walk",
7683 fib_node_list_get_size(PARENT()->fn_children));
7686 * walk again. should be no increase in the number of visits, since
7687 * the walk will have terminated.
7689 fib_walk_process_queues(vm, 1);
7691 FOR_EACH_TEST_CHILD(tc)
7693 FIB_TEST(0 == vec_len(tc->ctxs),
7694 "%d child visitsed %d times",
7695 ii, vec_len(tc->ctxs));
7699 * schedule a low and hig priority walk. expect the high to be performed
7701 * schedule the high prio walk first so that it is further from the head
7702 * of the dependency list. that way it won't merge with the low one.
7704 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7705 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7707 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7708 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7709 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7710 FIB_WALK_PRIORITY_LOW, &low_ctx);
7712 fib_walk_process_queues(vm, 1);
7714 FOR_EACH_TEST_CHILD(tc)
7716 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7717 "%d child visitsed by high prio walk", ii);
7718 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7719 "%d child visitsed by low prio walk", ii);
7722 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7723 "Queue is empty post prio walk");
7724 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7725 "Parent has %d children post prio walk",
7726 fib_node_list_get_size(PARENT()->fn_children));
7729 * schedule 2 walks of the same priority that can be megred.
7730 * expect that each child is thus visited only once.
7732 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7733 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7735 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7736 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7737 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7738 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7740 fib_walk_process_queues(vm, 1);
7742 FOR_EACH_TEST_CHILD(tc)
7744 FIB_TEST(1 == vec_len(tc->ctxs),
7745 "%d child visitsed %d times during merge walk",
7746 ii, vec_len(tc->ctxs));
7749 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7750 "Queue is empty post merge walk");
7751 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7752 "Parent has %d children post merge walk",
7753 fib_node_list_get_size(PARENT()->fn_children));
7756 * schedule 2 walks of the same priority that cannot be megred.
7757 * expect that each child is thus visited twice and in the order
7758 * in which the walks were scheduled.
7760 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7761 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7763 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7764 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7765 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7766 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7768 fib_walk_process_queues(vm, 1);
7770 FOR_EACH_TEST_CHILD(tc)
7772 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7773 "%d child visitsed by high prio walk", ii);
7774 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7775 "%d child visitsed by low prio walk", ii);
7778 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7779 "Queue is empty post no-merge walk");
7780 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7781 "Parent has %d children post no-merge walk",
7782 fib_node_list_get_size(PARENT()->fn_children));
7785 * schedule a walk that makes one one child progress.
7786 * we do this by giving the queue draining process zero
7787 * time quanta. it's a do..while loop, so it does something.
7789 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7791 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7792 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7793 fib_walk_process_queues(vm, 0);
7795 FOR_EACH_TEST_CHILD(tc)
7797 if (ii == N_TEST_CHILDREN)
7799 FIB_TEST(1 == vec_len(tc->ctxs),
7800 "%d child visitsed %d times in zero quanta walk",
7801 ii, vec_len(tc->ctxs));
7805 FIB_TEST(0 == vec_len(tc->ctxs),
7806 "%d child visitsed %d times in 0 quanta walk",
7807 ii, vec_len(tc->ctxs));
7810 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7811 "Queue is not empty post zero quanta walk");
7812 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7813 "Parent has %d children post zero qunta walk",
7814 fib_node_list_get_size(PARENT()->fn_children));
7819 fib_walk_process_queues(vm, 0);
7821 FOR_EACH_TEST_CHILD(tc)
7823 if (ii >= N_TEST_CHILDREN-1)
7825 FIB_TEST(1 == vec_len(tc->ctxs),
7826 "%d child visitsed %d times in 2nd zero quanta walk",
7827 ii, vec_len(tc->ctxs));
7831 FIB_TEST(0 == vec_len(tc->ctxs),
7832 "%d child visitsed %d times in 2nd 0 quanta walk",
7833 ii, vec_len(tc->ctxs));
7836 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7837 "Queue is not empty post zero quanta walk");
7838 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7839 "Parent has %d children post zero qunta walk",
7840 fib_node_list_get_size(PARENT()->fn_children));
7843 * schedule another walk that will catch-up and merge.
7845 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7846 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7847 fib_walk_process_queues(vm, 1);
7849 FOR_EACH_TEST_CHILD(tc)
7851 if (ii >= N_TEST_CHILDREN-1)
7853 FIB_TEST(2 == vec_len(tc->ctxs),
7854 "%d child visitsed %d times in 2nd zero quanta merge walk",
7855 ii, vec_len(tc->ctxs));
7860 FIB_TEST(1 == vec_len(tc->ctxs),
7861 "%d child visitsed %d times in 2nd 0 quanta merge walk",
7862 ii, vec_len(tc->ctxs));
7866 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7867 "Queue is not empty post 2nd zero quanta merge walk");
7868 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7869 "Parent has %d children post 2nd zero qunta merge walk",
7870 fib_node_list_get_size(PARENT()->fn_children));
7873 * park a async walk in the middle of the list, then have an sync walk catch
7874 * it. same expectations as async catches async.
7876 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7878 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7879 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7881 fib_walk_process_queues(vm, 0);
7882 fib_walk_process_queues(vm, 0);
7884 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7886 FOR_EACH_TEST_CHILD(tc)
7888 if (ii >= N_TEST_CHILDREN-1)
7890 FIB_TEST(2 == vec_len(tc->ctxs),
7891 "%d child visitsed %d times in sync catches async walk",
7892 ii, vec_len(tc->ctxs));
7897 FIB_TEST(1 == vec_len(tc->ctxs),
7898 "%d child visitsed %d times in sync catches async walk",
7899 ii, vec_len(tc->ctxs));
7903 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7904 "Queue is not empty post 2nd zero quanta merge walk");
7905 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7906 "Parent has %d children post 2nd zero qunta merge walk",
7907 fib_node_list_get_size(PARENT()->fn_children));
7910 * make the parent a child of one of its children, thus inducing a routing loop.
7912 fib_test_nodes[PARENT_INDEX].sibling =
7913 fib_node_child_add(FIB_NODE_TYPE_TEST,
7914 1, // the first child
7919 * execute a sync walk from the parent. each child visited spawns more sync
7920 * walks. we expect the walk to terminate.
7922 fib_test_walk_spawns_walks = 1;
7924 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7926 FOR_EACH_TEST_CHILD(tc)
7929 * child 1 - which is last in the list - has the loop.
7930 * the other children a re thus visitsed first. the we meet
7931 * child 1. we go round the loop again, visting the other children.
7932 * then we meet the walk in the dep list and bail. child 1 is not visitsed
7937 FIB_TEST(1 == vec_len(tc->ctxs),
7938 "child %d visitsed %d times during looped sync walk",
7939 ii, vec_len(tc->ctxs));
7943 FIB_TEST(2 == vec_len(tc->ctxs),
7944 "child %d visitsed %d times during looped sync walk",
7945 ii, vec_len(tc->ctxs));
7949 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7950 "Parent has %d children post sync loop walk",
7951 fib_node_list_get_size(PARENT()->fn_children));
7954 * the walk doesn't reach the max depth because the infra knows that sync
7955 * meets sync implies a loop and bails early.
7957 FIB_TEST(high_ctx.fnbw_depth == 9,
7958 "Walk context depth %d post sync loop walk",
7959 high_ctx.fnbw_depth);
7962 * execute an async walk of the graph loop, with each child spawns sync walks
7964 high_ctx.fnbw_depth = 0;
7965 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7966 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7968 fib_walk_process_queues(vm, 1);
7970 FOR_EACH_TEST_CHILD(tc)
7973 * we don't really care how many times the children are visited, as long as
7974 * it is more than once.
7976 FIB_TEST(1 <= vec_len(tc->ctxs),
7977 "child %d visitsed %d times during looped aync spawns sync walk",
7978 ii, vec_len(tc->ctxs));
7983 * execute an async walk of the graph loop, with each child spawns async walks
7985 fib_test_walk_spawns_walks = 2;
7986 high_ctx.fnbw_depth = 0;
7987 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7988 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7990 fib_walk_process_queues(vm, 1);
7992 FOR_EACH_TEST_CHILD(tc)
7995 * we don't really care how many times the children are visited, as long as
7996 * it is more than once.
7998 FIB_TEST(1 <= vec_len(tc->ctxs),
7999 "child %d visitsed %d times during looped async spawns async walk",
8000 ii, vec_len(tc->ctxs));
8005 fib_node_child_remove(FIB_NODE_TYPE_TEST,
8006 1, // the first child
8007 fib_test_nodes[PARENT_INDEX].sibling);
8012 FOR_EACH_TEST_CHILD(tc)
8014 fib_node_child_remove(FIB_NODE_TYPE_TEST, PARENT_INDEX,
8016 fib_node_deinit(&tc->node);
8017 fib_node_unlock(&tc->node);
8019 fib_node_deinit(PARENT());
8022 * The parent will be destroyed when the last lock on it goes.
8023 * this test ensures all the walk objects are unlocking it.
8025 FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed),
8026 "Parent was destroyed");
8032 * declaration of the otherwise static callback functions
8034 void fib_bfd_notify (bfd_listen_event_e event,
8035 const bfd_session_t *session);
8036 void adj_bfd_notify (bfd_listen_event_e event,
8037 const bfd_session_t *session);
8040 * Test BFD session interaction with FIB
8045 fib_node_index_t fei;
8050 /* via 10.10.10.1 */
8051 ip46_address_t nh_10_10_10_1 = {
8052 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
8054 /* via 10.10.10.2 */
8055 ip46_address_t nh_10_10_10_2 = {
8056 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
8058 /* via 10.10.10.10 */
8059 ip46_address_t nh_10_10_10_10 = {
8060 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
8062 n_feis = fib_entry_pool_size();
8067 * add interface routes. we'll assume this works. it's tested elsewhere
8069 fib_prefix_t pfx_10_10_10_10_s_24 = {
8071 .fp_proto = FIB_PROTOCOL_IP4,
8072 .fp_addr = nh_10_10_10_10,
8075 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_24,
8076 FIB_SOURCE_INTERFACE,
8077 (FIB_ENTRY_FLAG_CONNECTED |
8078 FIB_ENTRY_FLAG_ATTACHED),
8081 tm->hw[0]->sw_if_index,
8082 ~0, // invalid fib index
8085 FIB_ROUTE_PATH_FLAG_NONE);
8087 fib_prefix_t pfx_10_10_10_10_s_32 = {
8089 .fp_proto = FIB_PROTOCOL_IP4,
8090 .fp_addr = nh_10_10_10_10,
8092 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_32,
8093 FIB_SOURCE_INTERFACE,
8094 (FIB_ENTRY_FLAG_CONNECTED |
8095 FIB_ENTRY_FLAG_LOCAL),
8098 tm->hw[0]->sw_if_index,
8099 ~0, // invalid fib index
8102 FIB_ROUTE_PATH_FLAG_NONE);
8105 * A BFD session via a neighbour we do not yet know
8107 bfd_session_t bfd_10_10_10_1 = {
8111 .peer_addr = nh_10_10_10_1,
8114 .hop_type = BFD_HOP_TYPE_MULTI,
8115 .local_state = BFD_STATE_init,
8118 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8121 * A new entry will be created that forwards via the adj
8123 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8126 tm->hw[0]->sw_if_index);
8127 fib_prefix_t pfx_10_10_10_1_s_32 = {
8128 .fp_addr = nh_10_10_10_1,
8130 .fp_proto = FIB_PROTOCOL_IP4,
8132 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
8135 .adj = ai_10_10_10_1,
8139 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
8140 FIB_TEST(!fib_test_validate_entry(fei,
8141 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8144 "BFD sourced %U via %U",
8145 format_fib_prefix, &pfx_10_10_10_1_s_32,
8146 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
8149 * Delete the BFD session. Expect the fib_entry to be removed
8151 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8153 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
8154 FIB_TEST(FIB_NODE_INDEX_INVALID == fei,
8155 "BFD sourced %U removed",
8156 format_fib_prefix, &pfx_10_10_10_1_s_32);
8159 * Add the BFD source back
8161 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8164 * source the entry via the ADJ fib
8166 fei = fib_table_entry_path_add(0,
8167 &pfx_10_10_10_1_s_32,
8169 FIB_ENTRY_FLAG_ATTACHED,
8172 tm->hw[0]->sw_if_index,
8173 ~0, // invalid fib index
8176 FIB_ROUTE_PATH_FLAG_NONE);
8179 * Delete the BFD session. Expect the fib_entry to remain
8181 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8183 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
8184 FIB_TEST(!fib_test_validate_entry(fei,
8185 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8188 "BFD sourced %U remains via %U",
8189 format_fib_prefix, &pfx_10_10_10_1_s_32,
8190 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
8193 * Add the BFD source back
8195 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8198 * Create another ADJ FIB
8200 fib_prefix_t pfx_10_10_10_2_s_32 = {
8201 .fp_addr = nh_10_10_10_2,
8203 .fp_proto = FIB_PROTOCOL_IP4,
8205 fib_table_entry_path_add(0,
8206 &pfx_10_10_10_2_s_32,
8208 FIB_ENTRY_FLAG_ATTACHED,
8211 tm->hw[0]->sw_if_index,
8212 ~0, // invalid fib index
8215 FIB_ROUTE_PATH_FLAG_NONE);
8217 * A BFD session for the new ADJ FIB
8219 bfd_session_t bfd_10_10_10_2 = {
8223 .peer_addr = nh_10_10_10_2,
8226 .hop_type = BFD_HOP_TYPE_MULTI,
8227 .local_state = BFD_STATE_init,
8230 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_2);
8233 * remove the adj-fib source whilst the session is present
8236 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
8237 fib_table_entry_path_add(0,
8238 &pfx_10_10_10_2_s_32,
8240 FIB_ENTRY_FLAG_ATTACHED,
8243 tm->hw[0]->sw_if_index,
8244 ~0, // invalid fib index
8247 FIB_ROUTE_PATH_FLAG_NONE);
8250 * Before adding a recursive via the BFD tracked ADJ-FIBs,
8251 * bring one of the sessions UP, leave the other down
8253 bfd_10_10_10_1.local_state = BFD_STATE_up;
8254 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8255 bfd_10_10_10_2.local_state = BFD_STATE_down;
8256 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8259 * A recursive prefix via both of the ADJ FIBs
8261 fib_prefix_t pfx_200_0_0_0_s_24 = {
8262 .fp_proto = FIB_PROTOCOL_IP4,
8265 .ip4.as_u32 = clib_host_to_net_u32(0xc8000000),
8268 const dpo_id_t *dpo_10_10_10_1, *dpo_10_10_10_2;
8271 fib_entry_contribute_ip_forwarding(
8272 fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32));
8274 fib_entry_contribute_ip_forwarding(
8275 fib_table_lookup_exact_match(0, &pfx_10_10_10_2_s_32));
8277 fib_test_lb_bucket_t lb_o_10_10_10_1 = {
8280 .lb = dpo_10_10_10_1->dpoi_index,
8283 fib_test_lb_bucket_t lb_o_10_10_10_2 = {
8286 .lb = dpo_10_10_10_2->dpoi_index,
8291 * A prefix via the adj-fib that is BFD down => DROP
8293 fei = fib_table_entry_path_add(0,
8294 &pfx_200_0_0_0_s_24,
8296 FIB_ENTRY_FLAG_NONE,
8300 0, // default fib index
8303 FIB_ROUTE_PATH_FLAG_NONE);
8304 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8305 "%U resolves via drop",
8306 format_fib_prefix, &pfx_200_0_0_0_s_24);
8309 * add a path via the UP BFD adj-fib.
8310 * we expect that the DOWN BFD ADJ FIB is not used.
8312 fei = fib_table_entry_path_add(0,
8313 &pfx_200_0_0_0_s_24,
8315 FIB_ENTRY_FLAG_NONE,
8319 0, // default fib index
8322 FIB_ROUTE_PATH_FLAG_NONE);
8324 FIB_TEST(!fib_test_validate_entry(fei,
8325 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8328 "Recursive %U only UP BFD adj-fibs",
8329 format_fib_prefix, &pfx_200_0_0_0_s_24);
8332 * Send a BFD state change to UP - both sessions are now up
8333 * the recursive prefix should LB over both
8335 bfd_10_10_10_2.local_state = BFD_STATE_up;
8336 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8339 FIB_TEST(!fib_test_validate_entry(fei,
8340 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8344 "Recursive %U via both UP BFD adj-fibs",
8345 format_fib_prefix, &pfx_200_0_0_0_s_24);
8348 * Send a BFD state change to DOWN
8349 * the recursive prefix should exclude the down
8351 bfd_10_10_10_2.local_state = BFD_STATE_down;
8352 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8355 FIB_TEST(!fib_test_validate_entry(fei,
8356 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8359 "Recursive %U via only UP",
8360 format_fib_prefix, &pfx_200_0_0_0_s_24);
8363 * Delete the BFD session while it is in the DOWN state.
8364 * FIB should consider the entry's state as back up
8366 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_2);
8368 FIB_TEST(!fib_test_validate_entry(fei,
8369 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8373 "Recursive %U via both UP BFD adj-fibs post down session delete",
8374 format_fib_prefix, &pfx_200_0_0_0_s_24);
8377 * Delete the BFD other session while it is in the UP state.
8379 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8381 FIB_TEST(!fib_test_validate_entry(fei,
8382 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8386 "Recursive %U via both UP BFD adj-fibs post up session delete",
8387 format_fib_prefix, &pfx_200_0_0_0_s_24);
8392 fib_table_entry_delete(0, &pfx_200_0_0_0_s_24, FIB_SOURCE_API);
8393 fib_table_entry_delete(0, &pfx_10_10_10_1_s_32, FIB_SOURCE_ADJ);
8394 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
8396 fib_table_entry_delete(0, &pfx_10_10_10_10_s_32, FIB_SOURCE_INTERFACE);
8397 fib_table_entry_delete(0, &pfx_10_10_10_10_s_24, FIB_SOURCE_INTERFACE);
8399 adj_unlock(ai_10_10_10_1);
8401 * test no-one left behind
8403 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8404 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8407 * Single-hop BFD tests
8409 bfd_10_10_10_1.hop_type = BFD_HOP_TYPE_SINGLE;
8410 bfd_10_10_10_1.udp.key.sw_if_index = tm->hw[0]->sw_if_index;
8412 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8414 ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8417 tm->hw[0]->sw_if_index);
8419 * whilst the BFD session is not signalled, the adj is up
8421 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on uninit session");
8424 * bring the BFD session up
8426 bfd_10_10_10_1.local_state = BFD_STATE_up;
8427 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8428 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on UP session");
8431 * bring the BFD session down
8433 bfd_10_10_10_1.local_state = BFD_STATE_down;
8434 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8435 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on DOWN session");
8438 * add an attached next hop FIB entry via the down adj
8440 fib_prefix_t pfx_5_5_5_5_s_32 = {
8443 .as_u32 = clib_host_to_net_u32(0x05050505),
8447 .fp_proto = FIB_PROTOCOL_IP4,
8450 fei = fib_table_entry_path_add(0,
8453 FIB_ENTRY_FLAG_NONE,
8456 tm->hw[0]->sw_if_index,
8457 ~0, // invalid fib index
8460 FIB_ROUTE_PATH_FLAG_NONE);
8461 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8462 "%U resolves via drop",
8463 format_fib_prefix, &pfx_5_5_5_5_s_32);
8466 * Add a path via an ADJ that is up
8468 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8471 tm->hw[0]->sw_if_index);
8473 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
8476 .adj = ai_10_10_10_2,
8479 adj_o_10_10_10_1.adj.adj = ai_10_10_10_1;
8481 fei = fib_table_entry_path_add(0,
8484 FIB_ENTRY_FLAG_NONE,
8487 tm->hw[0]->sw_if_index,
8488 ~0, // invalid fib index
8491 FIB_ROUTE_PATH_FLAG_NONE);
8493 FIB_TEST(!fib_test_validate_entry(fei,
8494 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8497 "BFD sourced %U via %U",
8498 format_fib_prefix, &pfx_5_5_5_5_s_32,
8499 format_ip_adjacency, ai_10_10_10_2, FORMAT_IP_ADJACENCY_NONE);
8502 * Bring up the down session - should now LB
8504 bfd_10_10_10_1.local_state = BFD_STATE_up;
8505 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8506 FIB_TEST(!fib_test_validate_entry(fei,
8507 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8511 "BFD sourced %U via noth adjs",
8512 format_fib_prefix, &pfx_5_5_5_5_s_32);
8515 * remove the BFD session state from the adj
8517 adj_bfd_notify(BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8522 fib_table_entry_delete(0, &pfx_5_5_5_5_s_32, FIB_SOURCE_CLI);
8523 adj_unlock(ai_10_10_10_1);
8524 adj_unlock(ai_10_10_10_2);
8527 * test no-one left behind
8529 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8530 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8538 const mpls_label_t deag_label = 50;
8539 adj_index_t ai_mpls_10_10_10_1;
8540 dpo_id_t dpo = DPO_INVALID;
8541 const u32 lfib_index = 0;
8542 const u32 fib_index = 0;
8543 const dpo_id_t *dpo1;
8544 fib_node_index_t lfe;
8551 lb_count = pool_elts(load_balance_pool);
8553 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
8557 * MPLS enable an interface so we get the MPLS table created
8559 mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL);
8560 mpls_sw_interface_enable_disable(&mpls_main,
8561 tm->hw[0]->sw_if_index,
8564 ip46_address_t nh_10_10_10_1 = {
8565 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
8567 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8570 tm->hw[0]->sw_if_index);
8573 * Test the specials stack properly.
8575 fib_prefix_t exp_null_v6_pfx = {
8576 .fp_proto = FIB_PROTOCOL_MPLS,
8578 .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8579 .fp_payload_proto = DPO_PROTO_IP6,
8581 lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx);
8582 FIB_TEST((FIB_NODE_INDEX_INVALID != lfe),
8584 format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8585 format_mpls_eos_bit, MPLS_EOS);
8586 fib_entry_contribute_forwarding(lfe,
8587 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8589 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8590 lkd = lookup_dpo_get(dpo1->dpoi_index);
8592 FIB_TEST((fib_index == lkd->lkd_fib_index),
8593 "%U/%U is deag in %d %U",
8594 format_mpls_unicast_label, deag_label,
8595 format_mpls_eos_bit, MPLS_EOS,
8597 format_dpo_id, &dpo, 0);
8598 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8599 "%U/%U is dst deag",
8600 format_mpls_unicast_label, deag_label,
8601 format_mpls_eos_bit, MPLS_EOS);
8602 FIB_TEST((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table),
8603 "%U/%U is lookup in interface's table",
8604 format_mpls_unicast_label, deag_label,
8605 format_mpls_eos_bit, MPLS_EOS);
8606 FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto),
8607 "%U/%U is %U dst deag",
8608 format_mpls_unicast_label, deag_label,
8609 format_mpls_eos_bit, MPLS_EOS,
8610 format_dpo_proto, lkd->lkd_proto);
8613 * A route deag route for EOS
8615 fib_prefix_t pfx = {
8616 .fp_proto = FIB_PROTOCOL_MPLS,
8618 .fp_label = deag_label,
8619 .fp_payload_proto = DPO_PROTO_IP4,
8621 mpls_disp_dpo_t *mdd;
8622 lfe = fib_table_entry_path_add(lfib_index,
8625 FIB_ENTRY_FLAG_NONE,
8632 FIB_ROUTE_PATH_FLAG_NONE);
8634 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8636 format_mpls_unicast_label, deag_label,
8637 format_mpls_eos_bit, MPLS_EOS);
8639 fib_entry_contribute_forwarding(lfe,
8640 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8642 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8643 mdd = mpls_disp_dpo_get(dpo1->dpoi_index);
8645 FIB_TEST((FIB_MPLS_LSP_MODE_PIPE == mdd->mdd_mode),
8646 "%U/%U disp is pipe mode",
8647 format_mpls_unicast_label, deag_label,
8648 format_mpls_eos_bit, MPLS_EOS);
8650 lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index);
8652 FIB_TEST((fib_index == lkd->lkd_fib_index),
8653 "%U/%U is deag in %d %U",
8654 format_mpls_unicast_label, deag_label,
8655 format_mpls_eos_bit, MPLS_EOS,
8657 format_dpo_id, &dpo, 0);
8658 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8659 "%U/%U is dst deag",
8660 format_mpls_unicast_label, deag_label,
8661 format_mpls_eos_bit, MPLS_EOS);
8662 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8663 "%U/%U is %U dst deag",
8664 format_mpls_unicast_label, deag_label,
8665 format_mpls_eos_bit, MPLS_EOS,
8666 format_dpo_proto, lkd->lkd_proto);
8668 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8670 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8672 "%U/%U not present",
8673 format_mpls_unicast_label, deag_label,
8674 format_mpls_eos_bit, MPLS_EOS);
8678 * A route deag route for EOS with LSP mode uniform
8680 fib_mpls_label_t *l_pops = NULL, l_pop = {
8681 .fml_value = MPLS_LABEL_POP,
8682 .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM,
8684 vec_add1(l_pops, l_pop);
8685 lfe = fib_table_entry_path_add(lfib_index,
8688 FIB_ENTRY_FLAG_NONE,
8695 FIB_ROUTE_PATH_FLAG_NONE);
8697 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8699 format_mpls_unicast_label, deag_label,
8700 format_mpls_eos_bit, MPLS_EOS);
8702 fib_entry_contribute_forwarding(lfe,
8703 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8705 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8706 mdd = mpls_disp_dpo_get(dpo1->dpoi_index);
8708 FIB_TEST((FIB_MPLS_LSP_MODE_UNIFORM == mdd->mdd_mode),
8709 "%U/%U disp is uniform mode",
8710 format_mpls_unicast_label, deag_label,
8711 format_mpls_eos_bit, MPLS_EOS);
8713 lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index);
8715 FIB_TEST((fib_index == lkd->lkd_fib_index),
8716 "%U/%U is deag in %d %U",
8717 format_mpls_unicast_label, deag_label,
8718 format_mpls_eos_bit, MPLS_EOS,
8720 format_dpo_id, &dpo, 0);
8721 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8722 "%U/%U is dst deag",
8723 format_mpls_unicast_label, deag_label,
8724 format_mpls_eos_bit, MPLS_EOS);
8725 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8726 "%U/%U is %U dst deag",
8727 format_mpls_unicast_label, deag_label,
8728 format_mpls_eos_bit, MPLS_EOS,
8729 format_dpo_proto, lkd->lkd_proto);
8731 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8733 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8735 "%U/%U not present",
8736 format_mpls_unicast_label, deag_label,
8737 format_mpls_eos_bit, MPLS_EOS);
8741 * A route deag route for non-EOS
8743 pfx.fp_eos = MPLS_NON_EOS;
8744 lfe = fib_table_entry_path_add(lfib_index,
8747 FIB_ENTRY_FLAG_NONE,
8754 FIB_ROUTE_PATH_FLAG_NONE);
8756 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8758 format_mpls_unicast_label, deag_label,
8759 format_mpls_eos_bit, MPLS_NON_EOS);
8761 fib_entry_contribute_forwarding(lfe,
8762 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8764 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8765 lkd = lookup_dpo_get(dpo1->dpoi_index);
8767 FIB_TEST((fib_index == lkd->lkd_fib_index),
8768 "%U/%U is deag in %d %U",
8769 format_mpls_unicast_label, deag_label,
8770 format_mpls_eos_bit, MPLS_NON_EOS,
8772 format_dpo_id, &dpo, 0);
8773 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8774 "%U/%U is dst deag",
8775 format_mpls_unicast_label, deag_label,
8776 format_mpls_eos_bit, MPLS_NON_EOS);
8778 FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto),
8779 "%U/%U is %U dst deag",
8780 format_mpls_unicast_label, deag_label,
8781 format_mpls_eos_bit, MPLS_NON_EOS,
8782 format_dpo_proto, lkd->lkd_proto);
8784 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8786 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8788 "%U/%U not present",
8789 format_mpls_unicast_label, deag_label,
8790 format_mpls_eos_bit, MPLS_EOS);
8797 fib_prefix_t pfx_1200 = {
8799 .fp_proto = FIB_PROTOCOL_MPLS,
8801 .fp_eos = MPLS_NON_EOS,
8803 fib_test_lb_bucket_t neos_o_10_10_10_1 = {
8804 .type = FT_LB_LABEL_STACK_O_ADJ,
8805 .label_stack_o_adj = {
8806 .adj = ai_mpls_10_10_10_1,
8807 .label_stack_size = 4,
8811 .eos = MPLS_NON_EOS,
8814 dpo_id_t neos_1200 = DPO_INVALID;
8815 dpo_id_t ip_1200 = DPO_INVALID;
8816 fib_mpls_label_t *l200 = NULL;
8818 for (ii = 0; ii < 4; ii++)
8820 fib_mpls_label_t fml = {
8821 .fml_value = 200 + (ii * 100),
8823 vec_add1(l200, fml);
8826 lfe = fib_table_entry_update_one_path(fib_index,
8829 FIB_ENTRY_FLAG_NONE,
8832 tm->hw[0]->sw_if_index,
8833 ~0, // invalid fib index
8836 FIB_ROUTE_PATH_FLAG_NONE);
8838 FIB_TEST(!fib_test_validate_entry(lfe,
8839 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8841 &neos_o_10_10_10_1),
8842 "1200/0 LB 1 buckets via: "
8846 * A recursive route via the MPLS x-connect
8848 fib_prefix_t pfx_2_2_2_3_s_32 = {
8850 .fp_proto = FIB_PROTOCOL_IP4,
8852 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
8855 fib_route_path_t *rpaths = NULL, rpath = {
8856 .frp_proto = DPO_PROTO_MPLS,
8857 .frp_local_label = 1200,
8858 .frp_eos = MPLS_NON_EOS,
8859 .frp_sw_if_index = ~0, // recurive
8860 .frp_fib_index = 0, // Default MPLS fib
8862 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
8863 .frp_label_stack = NULL,
8865 vec_add1(rpaths, rpath);
8867 fib_table_entry_path_add2(fib_index,
8870 FIB_ENTRY_FLAG_NONE,
8874 * A labelled recursive route via the MPLS x-connect
8876 fib_prefix_t pfx_2_2_2_4_s_32 = {
8878 .fp_proto = FIB_PROTOCOL_IP4,
8880 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
8883 fib_mpls_label_t *l999 = NULL, fml_999 = {
8886 vec_add1(l999, fml_999);
8887 rpaths[0].frp_label_stack = l999,
8889 fib_table_entry_path_add2(fib_index,
8892 FIB_ENTRY_FLAG_NONE,
8895 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8896 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8898 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8899 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8902 fib_test_lb_bucket_t ip_o_1200 = {
8905 .lb = ip_1200.dpoi_index,
8908 fib_test_lb_bucket_t mpls_o_1200 = {
8909 .type = FT_LB_LABEL_O_LB,
8911 .lb = neos_1200.dpoi_index,
8917 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
8918 FIB_TEST(!fib_test_validate_entry(lfe,
8919 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8922 "2.2.2.2.3/32 LB 1 buckets via: label 1200 EOS");
8923 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
8924 FIB_TEST(!fib_test_validate_entry(lfe,
8925 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8928 "2.2.2.2.4/32 LB 1 buckets via: label 1200 non-EOS");
8930 fib_table_entry_delete(fib_index, &pfx_1200, FIB_SOURCE_API);
8931 fib_table_entry_delete(fib_index, &pfx_2_2_2_3_s_32, FIB_SOURCE_API);
8932 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8934 dpo_reset(&neos_1200);
8935 dpo_reset(&ip_1200);
8938 * A recursive via a label that does not exist
8940 fib_test_lb_bucket_t bucket_drop = {
8943 .adj = DPO_PROTO_IP4,
8946 fib_test_lb_bucket_t mpls_bucket_drop = {
8949 .adj = DPO_PROTO_MPLS,
8953 rpaths[0].frp_label_stack = NULL;
8954 lfe = fib_table_entry_path_add2(fib_index,
8957 FIB_ENTRY_FLAG_NONE,
8960 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8961 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8963 ip_o_1200.lb.lb = ip_1200.dpoi_index;
8965 FIB_TEST(!fib_test_validate_entry(lfe,
8966 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8969 "2.2.2.2.4/32 LB 1 buckets via: drop");
8970 lfe = fib_table_lookup(fib_index, &pfx_1200);
8971 FIB_TEST(!fib_test_validate_entry(lfe,
8972 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8975 "1200/neos LB 1 buckets via: ip4-DROP");
8976 FIB_TEST(!fib_test_validate_entry(lfe,
8977 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8980 "1200/neos LB 1 buckets via: mpls-DROP");
8982 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8984 dpo_reset(&ip_1200);
8987 * An rx-interface route.
8988 * like the tail of an mcast LSP
8990 dpo_id_t idpo = DPO_INVALID;
8992 interface_rx_dpo_add_or_lock(DPO_PROTO_IP4,
8993 tm->hw[0]->sw_if_index,
8996 fib_prefix_t pfx_2500 = {
8998 .fp_proto = FIB_PROTOCOL_MPLS,
9001 .fp_payload_proto = DPO_PROTO_IP4,
9003 fib_test_lb_bucket_t rx_intf_0 = {
9006 .adj = idpo.dpoi_index,
9010 lfe = fib_table_entry_update_one_path(fib_index,
9013 FIB_ENTRY_FLAG_NONE,
9016 tm->hw[0]->sw_if_index,
9017 ~0, // invalid fib index
9020 FIB_ROUTE_PATH_INTF_RX);
9021 FIB_TEST(!fib_test_validate_entry(lfe,
9022 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9025 "2500 rx-interface 0");
9026 fib_table_entry_delete(fib_index, &pfx_2500, FIB_SOURCE_API);
9029 * An MPLS mulicast entry
9031 fib_prefix_t pfx_3500 = {
9033 .fp_proto = FIB_PROTOCOL_MPLS,
9036 .fp_payload_proto = DPO_PROTO_IP4,
9038 fib_test_rep_bucket_t mc_0 = {
9039 .type = FT_REP_LABEL_O_ADJ,
9041 .adj = ai_mpls_10_10_10_1,
9046 fib_test_rep_bucket_t mc_intf_0 = {
9047 .type = FT_REP_INTF,
9049 .adj = idpo.dpoi_index,
9052 fib_mpls_label_t *l3300 = NULL, fml_3300 = {
9055 vec_add1(l3300, fml_3300);
9057 lfe = fib_table_entry_update_one_path(lfib_index,
9060 FIB_ENTRY_FLAG_MULTICAST,
9063 tm->hw[0]->sw_if_index,
9064 ~0, // invalid fib index
9067 FIB_ROUTE_PATH_FLAG_NONE);
9068 FIB_TEST(!fib_test_validate_entry(lfe,
9069 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9072 "3500 via replicate over 10.10.10.1");
9075 * MPLS Bud-node. Add a replication via an interface-receieve path
9077 lfe = fib_table_entry_path_add(lfib_index,
9080 FIB_ENTRY_FLAG_MULTICAST,
9083 tm->hw[0]->sw_if_index,
9084 ~0, // invalid fib index
9087 FIB_ROUTE_PATH_INTF_RX);
9088 FIB_TEST(!fib_test_validate_entry(lfe,
9089 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9093 "3500 via replicate over 10.10.10.1 and interface-rx");
9096 * Add a replication via an interface-free for-us path
9098 fib_test_rep_bucket_t mc_disp = {
9099 .type = FT_REP_DISP_MFIB_LOOKUP,
9101 .adj = idpo.dpoi_index,
9104 lfe = fib_table_entry_path_add(lfib_index,
9107 FIB_ENTRY_FLAG_MULTICAST,
9114 FIB_ROUTE_PATH_RPF_ID);
9115 FIB_TEST(!fib_test_validate_entry(lfe,
9116 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
9121 "3500 via replicate over 10.10.10.1 and interface-rx");
9125 fib_table_entry_delete(fib_index, &pfx_3500, FIB_SOURCE_API);
9131 mpls_sw_interface_enable_disable(&mpls_main,
9132 tm->hw[0]->sw_if_index,
9134 mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
9136 FIB_TEST(0 == pool_elts(mpls_disp_dpo_pool),
9137 "mpls_disp_dpo resources freed %d of %d",
9138 0, pool_elts(mpls_disp_dpo_pool));
9139 FIB_TEST(lb_count == pool_elts(load_balance_pool),
9140 "Load-balance resources freed %d of %d",
9141 lb_count, pool_elts(load_balance_pool));
9142 FIB_TEST(0 == pool_elts(interface_rx_dpo_pool),
9143 "interface_rx_dpo resources freed %d of %d",
9144 0, pool_elts(interface_rx_dpo_pool));
9150 fib_test_inherit (void)
9152 fib_node_index_t fei;
9159 for (i = 0; i <= 2; i++)
9161 fib_table_bind (FIB_PROTOCOL_IP4, tm->hw[i]->sw_if_index, 0);
9162 fib_table_bind (FIB_PROTOCOL_IP6, tm->hw[i]->sw_if_index, 0);
9164 n_feis = fib_entry_pool_size();
9166 const ip46_address_t nh_10_10_10_1 = {
9167 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
9169 const ip46_address_t nh_10_10_10_2 = {
9170 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
9172 const ip46_address_t nh_10_10_10_3 = {
9173 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
9175 const ip46_address_t nh_10_10_10_16 = {
9176 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a10),
9178 const ip46_address_t nh_10_10_10_20 = {
9179 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a14),
9181 const ip46_address_t nh_10_10_10_21 = {
9182 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a15),
9184 const ip46_address_t nh_10_10_10_22 = {
9185 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a16),
9187 const ip46_address_t nh_10_10_10_255 = {
9188 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0aff),
9190 const ip46_address_t nh_10_10_10_0 = {
9191 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a00),
9193 const ip46_address_t nh_10_10_0_0 = {
9194 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0000),
9196 const ip46_address_t nh_11_11_11_11 = {
9197 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
9199 const ip46_address_t nh_11_11_11_0 = {
9200 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b00),
9204 * prefixes at the base of a sub-tree
9206 const fib_prefix_t pfx_10_10_10_21_s_32 = {
9208 .fp_proto = FIB_PROTOCOL_IP4,
9209 .fp_addr = nh_10_10_10_21,
9211 const fib_prefix_t pfx_10_10_10_22_s_32 = {
9213 .fp_proto = FIB_PROTOCOL_IP4,
9214 .fp_addr = nh_10_10_10_22,
9216 const fib_prefix_t pfx_10_10_10_255_s_32 = {
9218 .fp_proto = FIB_PROTOCOL_IP4,
9219 .fp_addr = nh_10_10_10_255,
9221 const u32 N_PLS = fib_path_list_pool_size();
9223 fib_table_entry_special_add(0,
9224 &pfx_10_10_10_21_s_32,
9226 FIB_ENTRY_FLAG_DROP);
9227 fib_table_entry_special_add(0,
9228 &pfx_10_10_10_22_s_32,
9230 FIB_ENTRY_FLAG_DROP);
9231 fib_table_entry_special_add(0,
9232 &pfx_10_10_10_255_s_32,
9234 FIB_ENTRY_FLAG_DROP);
9237 * source an entry that pushes its state down the sub-tree
9239 const fib_prefix_t pfx_10_10_10_16_s_28 = {
9241 .fp_proto = FIB_PROTOCOL_IP4,
9242 .fp_addr = nh_10_10_10_16,
9244 fib_table_entry_update_one_path(0,
9245 &pfx_10_10_10_16_s_28,
9247 FIB_ENTRY_FLAG_COVERED_INHERIT,
9250 tm->hw[0]->sw_if_index,
9254 FIB_ROUTE_PATH_FLAG_NONE);
9257 * this covering entry and all those below it should have
9258 * the same forwarding information.
9260 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9263 tm->hw[0]->sw_if_index);
9264 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
9267 .adj = ai_10_10_10_1,
9271 fei = fib_table_lookup(0, &pfx_10_10_10_16_s_28);
9272 FIB_TEST(!fib_test_validate_entry(fei,
9273 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9276 "%U via 10.10.10.1",
9277 format_fib_prefix, &pfx_10_10_10_16_s_28);
9278 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9279 FIB_TEST(!fib_test_validate_entry(fei,
9280 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9283 "%U via 10.10.10.1",
9284 format_fib_prefix, &pfx_10_10_10_21_s_32);
9285 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9286 FIB_TEST(!fib_test_validate_entry(fei,
9287 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9290 "%U via 10.10.10.1",
9291 format_fib_prefix, &pfx_10_10_10_22_s_32);
9292 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9293 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9294 "%U resolves via drop",
9295 format_fib_prefix, &pfx_10_10_10_255_s_32);
9298 * remove the inherting cover - covereds go back to drop
9300 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_API);
9302 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9303 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9304 "%U resolves via drop",
9305 format_fib_prefix, &pfx_10_10_10_21_s_32);
9308 * source an entry that pushes its state down the sub-tree
9310 const fib_prefix_t pfx_10_10_10_0_s_24 = {
9312 .fp_proto = FIB_PROTOCOL_IP4,
9313 .fp_addr = nh_10_10_10_0,
9315 fib_table_entry_update_one_path(0,
9316 &pfx_10_10_10_0_s_24,
9318 FIB_ENTRY_FLAG_COVERED_INHERIT,
9321 tm->hw[0]->sw_if_index,
9325 FIB_ROUTE_PATH_FLAG_NONE);
9328 * whole sub-tree now covered
9330 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9331 FIB_TEST(!fib_test_validate_entry(fei,
9332 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9335 "%U via 10.10.10.1",
9336 format_fib_prefix, &pfx_10_10_10_0_s_24);
9337 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9338 FIB_TEST(!fib_test_validate_entry(fei,
9339 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9342 "%U via 10.10.10.1",
9343 format_fib_prefix, &pfx_10_10_10_21_s_32);
9344 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9345 FIB_TEST(!fib_test_validate_entry(fei,
9346 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9349 "%U via 10.10.10.1",
9350 format_fib_prefix, &pfx_10_10_10_22_s_32);
9351 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9352 FIB_TEST(!fib_test_validate_entry(fei,
9353 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9356 "%U via 10.10.10.1",
9357 format_fib_prefix, &pfx_10_10_10_255_s_32);
9360 * insert a more specific into the sub-tree - expect inheritance
9361 * this one is directly covered by the root
9363 fib_table_entry_special_add(0,
9364 &pfx_10_10_10_16_s_28,
9366 FIB_ENTRY_FLAG_DROP);
9367 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9368 FIB_TEST(!fib_test_validate_entry(fei,
9369 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9372 "%U via 10.10.10.1",
9373 format_fib_prefix, &pfx_10_10_10_16_s_28);
9376 * insert a more specific into the sub-tree - expect inheritance
9377 * this one is indirectly covered by the root
9379 const fib_prefix_t pfx_10_10_10_20_s_30 = {
9381 .fp_proto = FIB_PROTOCOL_IP4,
9382 .fp_addr = nh_10_10_10_20,
9384 fib_table_entry_special_add(0,
9385 &pfx_10_10_10_20_s_30,
9387 FIB_ENTRY_FLAG_DROP);
9388 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_20_s_30);
9389 FIB_TEST(!fib_test_validate_entry(fei,
9390 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9393 "%U via 10.10.10.1",
9394 format_fib_prefix, &pfx_10_10_10_20_s_30);
9397 * remove the prefix from the middle of the sub-tree
9398 * the inherited source will be the only one remaining - expect
9399 * it to be withdrawn and hence the prefix is removed.
9401 fib_table_entry_special_remove(0,
9402 &pfx_10_10_10_20_s_30,
9404 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_20_s_30);
9405 FIB_TEST((FIB_NODE_INDEX_INVALID == fei),
9407 format_fib_prefix, &pfx_10_10_10_20_s_30);
9410 * inheriting source is modifed - expect the modification to be present
9411 * throughout the sub-tree
9413 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9416 tm->hw[0]->sw_if_index);
9417 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
9420 .adj = ai_10_10_10_2,
9424 fib_table_entry_update_one_path(0,
9425 &pfx_10_10_10_0_s_24,
9427 FIB_ENTRY_FLAG_COVERED_INHERIT,
9430 tm->hw[0]->sw_if_index,
9434 FIB_ROUTE_PATH_FLAG_NONE);
9435 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9436 FIB_TEST(!fib_test_validate_entry(fei,
9437 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9440 "%U via 10.10.10.2",
9441 format_fib_prefix, &pfx_10_10_10_21_s_32);
9442 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9443 FIB_TEST(!fib_test_validate_entry(fei,
9444 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9447 "%U via 10.10.10.2",
9448 format_fib_prefix, &pfx_10_10_10_22_s_32);
9449 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9450 FIB_TEST(!fib_test_validate_entry(fei,
9451 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9454 "%U via 10.10.10.2",
9455 format_fib_prefix, &pfx_10_10_10_255_s_32);
9456 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9457 FIB_TEST(!fib_test_validate_entry(fei,
9458 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9461 "%U via 10.10.10.2",
9462 format_fib_prefix, &pfx_10_10_10_0_s_24);
9464 fib_source_t hi_src = fib_source_allocate("test", 0x50,
9465 FIB_SOURCE_BH_SIMPLE);
9468 * add the source that replaces inherited state.
9469 * inheriting source is not the best, so it doesn't push state.
9471 fib_table_entry_update_one_path(0,
9472 &pfx_10_10_10_0_s_24,
9474 FIB_ENTRY_FLAG_NONE,
9477 tm->hw[0]->sw_if_index,
9481 FIB_ROUTE_PATH_FLAG_NONE);
9482 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9483 FIB_TEST(!fib_test_validate_entry(fei,
9484 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9487 "%U via 10.10.10.1",
9488 format_fib_prefix, &pfx_10_10_10_0_s_24);
9490 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9491 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9492 "%U resolves via drop",
9493 format_fib_prefix, &pfx_10_10_10_21_s_32);
9494 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9495 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9496 "%U resolves via drop",
9497 format_fib_prefix, &pfx_10_10_10_22_s_32);
9498 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9499 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9500 "%U resolves via drop",
9501 format_fib_prefix, &pfx_10_10_10_255_s_32);
9502 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9503 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9504 "%U resolves via drop",
9505 format_fib_prefix, &pfx_10_10_10_16_s_28);
9508 * withdraw the higher priority source and expect the inherited to return
9509 * throughout the sub-tree
9511 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, hi_src);
9513 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9514 FIB_TEST(!fib_test_validate_entry(fei,
9515 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9518 "%U via 10.10.10.2",
9519 format_fib_prefix, &pfx_10_10_10_21_s_32);
9520 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9521 FIB_TEST(!fib_test_validate_entry(fei,
9522 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9525 "%U via 10.10.10.2",
9526 format_fib_prefix, &pfx_10_10_10_22_s_32);
9527 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9528 FIB_TEST(!fib_test_validate_entry(fei,
9529 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9532 "%U via 10.10.10.2",
9533 format_fib_prefix, &pfx_10_10_10_255_s_32);
9534 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9535 FIB_TEST(!fib_test_validate_entry(fei,
9536 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9539 "%U via 10.10.10.2",
9540 format_fib_prefix, &pfx_10_10_10_0_s_24);
9541 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9542 FIB_TEST(!fib_test_validate_entry(fei,
9543 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9546 "%U via 10.10.10.2",
9547 format_fib_prefix, &pfx_10_10_10_16_s_28);
9550 * source a covered entry in the sub-tree with the same inherting source
9551 * - expect that it now owns the sub-tree and thus over-rides its cover
9553 fib_table_entry_update_one_path(0,
9554 &pfx_10_10_10_16_s_28,
9556 FIB_ENTRY_FLAG_COVERED_INHERIT,
9559 tm->hw[0]->sw_if_index,
9563 FIB_ROUTE_PATH_FLAG_NONE);
9564 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9565 FIB_TEST(!fib_test_validate_entry(fei,
9566 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9569 "%U via 10.10.10.1",
9570 format_fib_prefix, &pfx_10_10_10_16_s_28);
9571 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9572 FIB_TEST(!fib_test_validate_entry(fei,
9573 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9576 "%U via 10.10.10.2",
9577 format_fib_prefix, &pfx_10_10_10_22_s_32);
9578 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9579 FIB_TEST(!fib_test_validate_entry(fei,
9580 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9583 "%U via 10.10.10.2",
9584 format_fib_prefix, &pfx_10_10_10_21_s_32);
9586 /* these two unaffected by the sub-tree change */
9587 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9588 FIB_TEST(!fib_test_validate_entry(fei,
9589 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9592 "%U via 10.10.10.2",
9593 format_fib_prefix, &pfx_10_10_10_255_s_32);
9594 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9595 FIB_TEST(!fib_test_validate_entry(fei,
9596 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9599 "%U via 10.10.10.2",
9600 format_fib_prefix, &pfx_10_10_10_0_s_24);
9603 * removes the more specific, expect the /24 to now re-owns the sub-tree
9605 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_API);
9607 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_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_16_s_28);
9614 FIB_TEST(!fib_test_validate_entry(fei,
9615 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9618 "%U via 10.10.10.2",
9619 format_fib_prefix, &pfx_10_10_10_21_s_32);
9620 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9621 FIB_TEST(!fib_test_validate_entry(fei,
9622 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9625 "%U via 10.10.10.2",
9626 format_fib_prefix, &pfx_10_10_10_22_s_32);
9627 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9628 FIB_TEST(!fib_test_validate_entry(fei,
9629 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9632 "%U via 10.10.10.2",
9633 format_fib_prefix, &pfx_10_10_10_255_s_32);
9634 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9635 FIB_TEST(!fib_test_validate_entry(fei,
9636 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9639 "%U via 10.10.10.2",
9640 format_fib_prefix, &pfx_10_10_10_0_s_24);
9642 * modify the /24. expect the new forwarding to be pushed down
9644 fib_table_entry_update_one_path(0,
9645 &pfx_10_10_10_0_s_24,
9647 FIB_ENTRY_FLAG_COVERED_INHERIT,
9650 tm->hw[0]->sw_if_index,
9654 FIB_ROUTE_PATH_FLAG_NONE);
9655 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9656 FIB_TEST(!fib_test_validate_entry(fei,
9657 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9660 "%U via 10.10.10.1",
9661 format_fib_prefix, &pfx_10_10_10_16_s_28);
9662 FIB_TEST(!fib_test_validate_entry(fei,
9663 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9666 "%U via 10.10.10.1",
9667 format_fib_prefix, &pfx_10_10_10_21_s_32);
9668 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9669 FIB_TEST(!fib_test_validate_entry(fei,
9670 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9673 "%U via 10.10.10.1",
9674 format_fib_prefix, &pfx_10_10_10_22_s_32);
9675 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9676 FIB_TEST(!fib_test_validate_entry(fei,
9677 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9680 "%U via 10.10.10.1",
9681 format_fib_prefix, &pfx_10_10_10_255_s_32);
9682 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9683 FIB_TEST(!fib_test_validate_entry(fei,
9684 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9687 "%U via 10.10.10.1",
9688 format_fib_prefix, &pfx_10_10_10_0_s_24);
9691 * add an entry less specific to /24. it should not own the /24's tree
9693 const fib_prefix_t pfx_10_10_0_0_s_16 = {
9695 .fp_proto = FIB_PROTOCOL_IP4,
9696 .fp_addr = nh_10_10_0_0,
9698 fib_table_entry_update_one_path(0,
9699 &pfx_10_10_0_0_s_16,
9701 FIB_ENTRY_FLAG_COVERED_INHERIT,
9704 tm->hw[0]->sw_if_index,
9708 FIB_ROUTE_PATH_FLAG_NONE);
9709 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9710 FIB_TEST(!fib_test_validate_entry(fei,
9711 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9714 "%U via 10.10.10.1",
9715 format_fib_prefix, &pfx_10_10_10_16_s_28);
9716 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9717 FIB_TEST(!fib_test_validate_entry(fei,
9718 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9721 "%U via 10.10.10.1",
9722 format_fib_prefix, &pfx_10_10_10_22_s_32);
9723 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9724 FIB_TEST(!fib_test_validate_entry(fei,
9725 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9728 "%U via 10.10.10.1",
9729 format_fib_prefix, &pfx_10_10_10_255_s_32);
9730 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9731 FIB_TEST(!fib_test_validate_entry(fei,
9732 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9735 "%U via 10.10.10.1",
9736 format_fib_prefix, &pfx_10_10_10_0_s_24);
9737 fei = fib_table_lookup_exact_match(0, &pfx_10_10_0_0_s_16);
9738 FIB_TEST(!fib_test_validate_entry(fei,
9739 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9742 "%U via 10.10.10.2",
9743 format_fib_prefix, &pfx_10_10_0_0_s_16);
9746 * Add/remove an interposer source to a new /32
9748 const fib_prefix_t pfx_11_11_11_11_s_32 = {
9750 .fp_proto = FIB_PROTOCOL_IP4,
9751 .fp_addr = nh_11_11_11_11,
9754 fib_table_entry_update_one_path(0,
9755 &pfx_11_11_11_11_s_32,
9757 FIB_ENTRY_FLAG_NONE,
9760 tm->hw[0]->sw_if_index,
9764 FIB_ROUTE_PATH_FLAG_NONE);
9766 dpo_id_t interposer = DPO_INVALID;
9767 fib_mpls_label_t *l99 = NULL, fml_99 = {
9770 vec_add1(l99, fml_99);
9772 mpls_label_dpo_create(l99,
9775 MPLS_LABEL_DPO_FLAG_NONE,
9776 punt_dpo_get(DPO_PROTO_MPLS),
9779 adj_index_t ai_10_10_10_3 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9782 tm->hw[0]->sw_if_index);
9783 fib_test_lb_bucket_t adj_o_10_10_10_3 = {
9786 .adj = ai_10_10_10_3,
9789 fib_test_lb_bucket_t l99_o_10_10_10_3 = {
9790 .type = FT_LB_LABEL_O_ADJ,
9792 .adj = ai_10_10_10_3,
9798 fei = fib_table_entry_special_dpo_add(0,
9799 &pfx_11_11_11_11_s_32,
9801 FIB_ENTRY_FLAG_INTERPOSE,
9803 FIB_TEST(!fib_test_validate_entry(fei,
9804 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9807 "%U via interposer adj",
9808 format_fib_prefix,&pfx_11_11_11_11_s_32);
9810 fib_table_entry_special_remove(0,
9811 &pfx_11_11_11_11_s_32,
9812 FIB_SOURCE_SPECIAL);
9813 FIB_TEST(!fib_test_validate_entry(fei,
9814 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9817 "%U via 10.10.10.1",
9818 format_fib_prefix, &pfx_11_11_11_11_s_32);
9819 dpo_reset(&interposer);
9820 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
9823 * add an interposer to a source with path-extensions
9825 fib_mpls_label_t *l3300 = NULL, fml_3300 = {
9828 vec_add1(l3300, fml_3300);
9829 fib_table_entry_update_one_path(0,
9830 &pfx_11_11_11_11_s_32,
9832 FIB_ENTRY_FLAG_NONE,
9835 tm->hw[0]->sw_if_index,
9839 FIB_ROUTE_PATH_FLAG_NONE);
9841 mpls_label_dpo_create(l99,
9844 MPLS_LABEL_DPO_FLAG_NONE,
9845 punt_dpo_get(DPO_PROTO_MPLS),
9848 adj_index_t ai_mpls_10_10_10_3 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9851 tm->hw[0]->sw_if_index);
9852 fib_test_lb_bucket_t l3300_o_10_10_10_3 = {
9853 .type = FT_LB_LABEL_O_ADJ,
9855 .adj = ai_mpls_10_10_10_3,
9860 fib_test_lb_bucket_t lchain_o_10_10_10_3 = {
9861 .type = FT_LB_LABEL_CHAIN_O_ADJ,
9862 .label_chain_o_adj = {
9863 .adj = ai_mpls_10_10_10_3,
9864 .label_chain_size = 2,
9872 fei = fib_table_entry_special_dpo_add(0,
9873 &pfx_11_11_11_11_s_32,
9875 FIB_ENTRY_FLAG_INTERPOSE,
9878 FIB_TEST(!fib_test_validate_entry(fei,
9879 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9881 &lchain_o_10_10_10_3),
9882 "%U via interposer & mpls on adj",
9883 format_fib_prefix, &pfx_11_11_11_11_s_32);
9885 fib_table_entry_special_remove(0,
9886 &pfx_11_11_11_11_s_32,
9887 FIB_SOURCE_SPECIAL);
9888 FIB_TEST(!fib_test_validate_entry(fei,
9889 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9891 &l3300_o_10_10_10_3),
9892 "%U via 10.10.10.1",
9893 format_fib_prefix, &pfx_11_11_11_11_s_32);
9894 adj_unlock(ai_mpls_10_10_10_3);
9897 * remove and re-add the second best API source while the interpose
9900 fei = fib_table_entry_special_dpo_add(0,
9901 &pfx_11_11_11_11_s_32,
9903 FIB_ENTRY_FLAG_INTERPOSE,
9905 FIB_TEST(!fib_test_validate_entry(fei,
9906 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9908 &lchain_o_10_10_10_3),
9909 "%U via interposer adj",
9910 format_fib_prefix,&pfx_11_11_11_11_s_32);
9912 FIB_TEST(3 == pool_elts(mpls_label_dpo_pool),
9913 "MPLS label pool: %d",
9914 pool_elts(mpls_label_dpo_pool));
9916 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
9919 * the interpose does not get stacked when there are not valid paths
9921 fib_test_lb_bucket_t bucket_drop = {
9924 .adj = DPO_PROTO_IP4,
9927 FIB_TEST(!fib_test_validate_entry(fei,
9928 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9932 format_fib_prefix,&pfx_11_11_11_11_s_32);
9934 fib_table_entry_update_one_path(0,
9935 &pfx_11_11_11_11_s_32,
9937 FIB_ENTRY_FLAG_NONE,
9940 tm->hw[0]->sw_if_index,
9944 FIB_ROUTE_PATH_FLAG_NONE);
9945 FIB_TEST(!fib_test_validate_entry(fei,
9946 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9949 "%U via interposer adj",
9950 format_fib_prefix,&pfx_11_11_11_11_s_32);
9951 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
9954 * add a cover for the interposed entry, so that we test it selects
9955 * the covers forwarding.
9957 const fib_prefix_t pfx_11_11_11_0_s_24 = {
9959 .fp_proto = FIB_PROTOCOL_IP4,
9960 .fp_addr = nh_11_11_11_0,
9962 fib_table_entry_update_one_path(0,
9963 &pfx_11_11_11_0_s_24,
9965 FIB_ENTRY_FLAG_NONE,
9968 tm->hw[0]->sw_if_index,
9972 FIB_ROUTE_PATH_FLAG_NONE);
9973 FIB_TEST(!fib_test_validate_entry(fei,
9974 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9977 "%U via interposer adj",
9978 format_fib_prefix,&pfx_11_11_11_11_s_32);
9981 * multiple interpose sources on the same entry. Only the high
9982 * priority source gets to add the interpose.
9984 fib_table_entry_update_one_path(0,
9985 &pfx_11_11_11_11_s_32,
9987 FIB_ENTRY_FLAG_NONE,
9990 tm->hw[0]->sw_if_index,
9994 FIB_ROUTE_PATH_FLAG_NONE);
9996 dpo_id_t interposer2 = DPO_INVALID;
9997 fib_mpls_label_t *l100 = NULL, fml_100 = {
10000 vec_add1(l100, fml_100);
10002 mpls_label_dpo_create(l100,
10005 MPLS_LABEL_DPO_FLAG_NONE,
10006 punt_dpo_get(DPO_PROTO_MPLS),
10009 fei = fib_table_entry_special_dpo_add(0,
10010 &pfx_11_11_11_11_s_32,
10011 FIB_SOURCE_CLASSIFY,
10012 FIB_ENTRY_FLAG_INTERPOSE,
10015 fib_test_lb_bucket_t lc100_o_10_10_10_3 = {
10016 .type = FT_LB_LABEL_CHAIN_O_ADJ,
10017 .label_chain_o_adj = {
10018 .adj = ai_10_10_10_3,
10019 .label_chain_size = 2,
10027 FIB_TEST(!fib_test_validate_entry(fei,
10028 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10030 &lc100_o_10_10_10_3),
10031 "%U via interposer label 99",
10032 format_fib_prefix,&pfx_11_11_11_11_s_32);
10034 fib_test_lb_bucket_t l100_o_10_10_10_3 = {
10035 .type = FT_LB_LABEL_O_ADJ,
10037 .adj = ai_10_10_10_3,
10043 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_SPECIAL);
10045 FIB_TEST(!fib_test_validate_entry(fei,
10046 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10048 &l100_o_10_10_10_3),
10049 "%U via interposer label 99",
10050 format_fib_prefix,&pfx_11_11_11_11_s_32);
10052 fib_table_entry_delete(0, &pfx_11_11_11_0_s_24, FIB_SOURCE_API);
10053 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
10054 FIB_TEST(!fib_test_validate_entry(fei,
10055 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10059 format_fib_prefix,&pfx_11_11_11_11_s_32);
10060 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_CLASSIFY);
10063 * update a source to/from interpose.
10065 /* fib_table_entry_update_one_path(0, */
10066 /* &pfx_11_11_11_0_s_24, */
10067 /* FIB_SOURCE_API, */
10068 /* FIB_ENTRY_FLAG_NONE, */
10069 /* DPO_PROTO_IP4, */
10070 /* &nh_10_10_10_3, */
10071 /* tm->hw[0]->sw_if_index, */
10075 /* FIB_ROUTE_PATH_FLAG_NONE); */
10076 /* fei = fib_table_entry_special_dpo_add(0, */
10077 /* &pfx_11_11_11_11_s_32, */
10078 /* FIB_SOURCE_API, */
10079 /* FIB_ENTRY_FLAG_INTERPOSE, */
10080 /* &interposer); */
10081 /* FIB_TEST(!fib_test_validate_entry(fei, */
10082 /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */
10084 /* &l99_o_10_10_10_3), */
10085 /* "%U via interposer label 99", */
10086 /* format_fib_prefix,&pfx_11_11_11_11_s_32); */
10088 /* FIB_TEST(3 == pool_elts(mpls_label_dpo_pool), */
10089 /* "MPLS label pool: %d", */
10090 /* pool_elts(mpls_label_dpo_pool)); */
10091 /* FIB_TEST((2 == mpls_label_dpo_get(interposer.dpoi_index)->mld_locks), */
10092 /* "Interposer %d locks", */
10093 /* mpls_label_dpo_get(interposer.dpoi_index)->mld_locks); */
10095 /* fib_table_entry_update_one_path(0, */
10096 /* &pfx_11_11_11_11_s_32, */
10097 /* FIB_SOURCE_API, */
10098 /* FIB_ENTRY_FLAG_NONE, */
10099 /* DPO_PROTO_IP4, */
10100 /* &nh_10_10_10_2, */
10101 /* tm->hw[0]->sw_if_index, */
10105 /* FIB_ROUTE_PATH_FLAG_NONE); */
10106 /* FIB_TEST(!fib_test_validate_entry(fei, */
10107 /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */
10109 /* &adj_o_10_10_10_2), */
10110 /* "%U via 10.10.10.2", */
10111 /* format_fib_prefix,&pfx_11_11_11_11_s_32); */
10113 /* FIB_TEST((1 == mpls_label_dpo_get(interposer.dpoi_index)->mld_locks), */
10114 /* "Interposer %d locks", */
10115 /* mpls_label_dpo_get(interposer.dpoi_index)->mld_locks); */
10116 /* FIB_TEST(2 == pool_elts(mpls_label_dpo_pool), */
10117 /* "MPLS label pool: %d", */
10118 /* pool_elts(mpls_label_dpo_pool)); */
10120 /* fei = fib_table_entry_special_dpo_add(0, */
10121 /* &pfx_11_11_11_11_s_32, */
10122 /* FIB_SOURCE_API, */
10123 /* FIB_ENTRY_FLAG_INTERPOSE, */
10124 /* &interposer); */
10125 /* FIB_TEST(!fib_test_validate_entry(fei, */
10126 /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */
10128 /* &l99_o_10_10_10_3), */
10129 /* "%U via interposer label 99", */
10130 /* format_fib_prefix,&pfx_11_11_11_11_s_32); */
10132 /* fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API); */
10135 * Add/remove an interposer source from the top of the subtrie. The
10136 * interposer source is not inherited.
10138 fib_table_entry_update_one_path(0,
10139 &pfx_10_10_10_0_s_24,
10141 FIB_ENTRY_FLAG_COVERED_INHERIT,
10144 tm->hw[0]->sw_if_index,
10148 FIB_ROUTE_PATH_FLAG_NONE);
10149 fei = fib_table_entry_special_dpo_add(0,
10150 &pfx_10_10_10_0_s_24,
10151 FIB_SOURCE_SPECIAL,
10152 FIB_ENTRY_FLAG_INTERPOSE,
10154 FIB_TEST(!fib_test_validate_entry(fei,
10155 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10157 &l99_o_10_10_10_3),
10158 "%U via interposer label",
10159 format_fib_prefix,&pfx_10_10_10_0_s_24);
10160 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
10161 FIB_TEST(!fib_test_validate_entry(fei,
10162 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10166 format_fib_prefix, &pfx_10_10_10_21_s_32);
10168 fib_table_entry_special_remove(0,
10169 &pfx_10_10_10_0_s_24,
10170 FIB_SOURCE_SPECIAL);
10171 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
10172 FIB_TEST(!fib_test_validate_entry(fei,
10173 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10175 &adj_o_10_10_10_3),
10176 "%U via 10.10.10.1",
10177 format_fib_prefix, &pfx_10_10_10_0_s_24);
10178 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
10179 FIB_TEST(!fib_test_validate_entry(fei,
10180 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10182 &adj_o_10_10_10_3),
10183 "%U via via 10.10.10.1",
10184 format_fib_prefix, &pfx_10_10_10_21_s_32);
10187 * Add/remove an interposer source from the top of the subtrie. The
10188 * interposer source is inherited.
10190 fei = fib_table_entry_special_dpo_add(0,
10191 &pfx_10_10_10_0_s_24,
10192 FIB_SOURCE_SPECIAL,
10193 (FIB_ENTRY_FLAG_COVERED_INHERIT |
10194 FIB_ENTRY_FLAG_INTERPOSE),
10196 FIB_TEST(!fib_test_validate_entry(fei,
10197 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10199 &l99_o_10_10_10_3),
10200 "%U via interposer label",
10201 format_fib_prefix,&pfx_10_10_10_0_s_24);
10203 /* interposer gets forwarding from the drop cli source */
10204 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
10205 FIB_TEST(!fib_test_validate_entry(fei,
10206 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10210 format_fib_prefix,&pfx_10_10_10_21_s_32);
10212 fib_table_entry_update_one_path(0,
10213 &pfx_10_10_10_21_s_32,
10215 FIB_ENTRY_FLAG_NONE,
10218 tm->hw[0]->sw_if_index,
10222 FIB_ROUTE_PATH_FLAG_NONE);
10223 fib_table_entry_delete(0, &pfx_10_10_10_21_s_32, FIB_SOURCE_CLI);
10224 /* interposer gets forwarding from the API source */
10225 FIB_TEST(!fib_test_validate_entry(fei,
10226 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10228 &l99_o_10_10_10_3),
10229 "%U via interposer label",
10230 format_fib_prefix,&pfx_10_10_10_21_s_32);
10235 fib_table_entry_delete(0, &pfx_10_10_10_22_s_32, FIB_SOURCE_CLI);
10236 fib_table_entry_delete(0, &pfx_10_10_10_21_s_32, FIB_SOURCE_API);
10237 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_CLI);
10238 fib_table_entry_delete(0, &pfx_10_10_10_255_s_32, FIB_SOURCE_CLI);
10239 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, FIB_SOURCE_API);
10240 fib_table_entry_delete(0, &pfx_10_10_0_0_s_16, FIB_SOURCE_API);
10241 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, FIB_SOURCE_SPECIAL);
10242 adj_unlock(ai_10_10_10_1);
10243 adj_unlock(ai_10_10_10_2);
10244 adj_unlock(ai_10_10_10_3);
10245 dpo_reset(&interposer);
10246 dpo_reset(&interposer2);
10247 FIB_TEST(0 == pool_elts(mpls_label_dpo_pool),
10248 "MPLS label pool empty: %d",
10249 pool_elts(mpls_label_dpo_pool));
10250 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
10251 FIB_TEST(N_PLS == fib_path_list_pool_size(),
10252 "number of path-lists: %d = %d",
10253 N_PLS, fib_path_list_pool_size());
10256 * test the v6 tree walk.
10257 * a /64 that covers everything. a /96 that covers one /128
10258 * a second /128 covered only by the /64.
10260 const fib_prefix_t pfx_2001_s_64 = {
10262 .fp_proto = FIB_PROTOCOL_IP6,
10266 [0] = clib_host_to_net_u64(0x2001000000000000),
10267 [1] = clib_host_to_net_u64(0x0000000000000000),
10272 const fib_prefix_t pfx_2001_1_s_96 = {
10274 .fp_proto = FIB_PROTOCOL_IP6,
10278 [0] = clib_host_to_net_u64(0x2001000000000000),
10279 [1] = clib_host_to_net_u64(0x1000000000000000),
10284 const fib_prefix_t pfx_2001_1_1_s_128 = {
10286 .fp_proto = FIB_PROTOCOL_IP6,
10290 [0] = clib_host_to_net_u64(0x2001000000000000),
10291 [1] = clib_host_to_net_u64(0x1000000000000001),
10296 const fib_prefix_t pfx_2001_0_1_s_128 = {
10298 .fp_proto = FIB_PROTOCOL_IP6,
10302 [0] = clib_host_to_net_u64(0x2001000000000000),
10303 [1] = clib_host_to_net_u64(0x0000000000000001),
10308 const ip46_address_t nh_3000_1 = {
10311 [0] = clib_host_to_net_u64(0x3000000000000000),
10312 [1] = clib_host_to_net_u64(0x0000000000000001),
10316 const ip46_address_t nh_3000_2 = {
10319 [0] = clib_host_to_net_u64(0x3000000000000000),
10320 [1] = clib_host_to_net_u64(0x0000000000000002),
10324 adj_index_t ai_3000_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
10327 tm->hw[0]->sw_if_index);
10328 adj_index_t ai_3000_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
10331 tm->hw[0]->sw_if_index);
10332 fib_test_lb_bucket_t adj_o_3000_1 = {
10338 fib_test_lb_bucket_t adj_o_3000_2 = {
10345 fib_table_entry_special_add(0,
10346 &pfx_2001_0_1_s_128,
10348 FIB_ENTRY_FLAG_DROP);
10349 fib_table_entry_special_add(0,
10350 &pfx_2001_1_1_s_128,
10352 FIB_ENTRY_FLAG_DROP);
10355 * /96 has inherited forwarding pushed down to its covered /128
10357 fib_table_entry_update_one_path(0,
10360 FIB_ENTRY_FLAG_COVERED_INHERIT,
10363 tm->hw[0]->sw_if_index,
10367 FIB_ROUTE_PATH_FLAG_NONE);
10368 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_s_96);
10369 FIB_TEST(!fib_test_validate_entry(fei,
10370 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10374 format_fib_prefix, &pfx_2001_1_s_96);
10375 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_1_s_128);
10376 FIB_TEST(!fib_test_validate_entry(fei,
10377 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10381 format_fib_prefix, &pfx_2001_1_1_s_128);
10382 fei = fib_table_lookup_exact_match(0, &pfx_2001_0_1_s_128);
10383 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
10384 "%U resolves via drop",
10385 format_fib_prefix, &pfx_2001_0_1_s_128);
10388 * /64 has inherited forwarding pushed down to all, but the /96
10389 * and its sub-tree remain unaffected.
10391 fib_table_entry_update_one_path(0,
10394 FIB_ENTRY_FLAG_COVERED_INHERIT,
10397 tm->hw[0]->sw_if_index,
10401 FIB_ROUTE_PATH_FLAG_NONE);
10403 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
10404 FIB_TEST(!fib_test_validate_entry(fei,
10405 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10409 format_fib_prefix, &pfx_2001_s_64);
10410 fei = fib_table_lookup_exact_match(0, &pfx_2001_0_1_s_128);
10411 FIB_TEST(!fib_test_validate_entry(fei,
10412 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10416 format_fib_prefix, &pfx_2001_0_1_s_128);
10418 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_s_96);
10419 FIB_TEST(!fib_test_validate_entry(fei,
10420 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10424 format_fib_prefix, &pfx_2001_1_s_96);
10425 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_1_s_128);
10426 FIB_TEST(!fib_test_validate_entry(fei,
10427 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10431 format_fib_prefix, &pfx_2001_1_1_s_128);
10436 fib_table_entry_delete(0, &pfx_2001_0_1_s_128, FIB_SOURCE_CLI);
10437 fib_table_entry_delete(0, &pfx_2001_1_1_s_128, FIB_SOURCE_CLI);
10438 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
10439 fib_table_entry_delete(0, &pfx_2001_1_s_96, FIB_SOURCE_API);
10440 adj_unlock(ai_3000_1);
10441 adj_unlock(ai_3000_2);
10444 * test no-one left behind
10446 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
10447 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
10453 fib_test_sticky (void)
10455 fib_route_path_t *r_paths = NULL;
10456 test_main_t *tm = &test_main;
10457 u32 ii, lb_count, pl_count;
10458 dpo_id_t dpo = DPO_INVALID;
10459 fib_node_index_t pl_index;
10463 fib_test_lb_bucket_t buckets[N_PATHS];
10464 bfd_session_t bfds[N_PATHS] = {{0}};
10466 lb_count = pool_elts(load_balance_pool);
10467 pl_count = fib_path_list_pool_size();
10469 for (ii = 0; ii < N_PATHS; ii++)
10471 ip46_address_t nh = {
10472 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
10476 ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
10478 &nh, tm->hw[0]->sw_if_index);
10480 buckets[ii].type = FT_LB_ADJ;
10481 buckets[ii].adj.adj = ai;
10483 bfds[ii].udp.key.peer_addr = nh;
10484 bfds[ii].udp.key.sw_if_index = tm->hw[0]->sw_if_index;
10485 bfds[ii].hop_type = BFD_HOP_TYPE_SINGLE;
10486 bfds[ii].local_state = BFD_STATE_init;
10487 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfds[ii]);
10488 bfds[ii].local_state = BFD_STATE_up;
10489 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[ii]);
10492 for (ii = 0; ii < N_PATHS; ii++)
10494 fib_route_path_t r_path = {
10495 .frp_proto = DPO_PROTO_IP4,
10497 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
10499 .frp_sw_if_index = tm->hw[0]->sw_if_index,
10501 .frp_fib_index = ~0,
10503 vec_add1(r_paths, r_path);
10506 pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths);
10507 fib_path_list_lock(pl_index);
10509 fib_path_list_contribute_forwarding(pl_index,
10510 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10511 FIB_PATH_LIST_FWD_FLAG_STICKY,
10514 FIB_TEST(!fib_test_validate_lb(&dpo,
10534 /* take down paths */
10535 bfds[0].local_state = BFD_STATE_down;
10536 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[0]);
10538 fib_path_list_contribute_forwarding(pl_index,
10539 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10540 FIB_PATH_LIST_FWD_FLAG_STICKY,
10543 FIB_TEST(!fib_test_validate_lb(&dpo,
10561 "Failed at shut-down path 0");
10563 bfds[7].local_state = BFD_STATE_down;
10564 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[7]);
10566 fib_path_list_contribute_forwarding(pl_index,
10567 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10568 FIB_PATH_LIST_FWD_FLAG_STICKY,
10571 FIB_TEST(!fib_test_validate_lb(&dpo,
10589 "Failed at shut-down path 7");
10591 /* paths back up */
10592 bfds[0].local_state = BFD_STATE_up;
10593 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[0]);
10594 bfds[7].local_state = BFD_STATE_up;
10595 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[7]);
10597 fib_path_list_contribute_forwarding(pl_index,
10598 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10599 FIB_PATH_LIST_FWD_FLAG_STICKY,
10602 FIB_TEST(!fib_test_validate_lb(&dpo,
10622 fib_path_list_unlock(pl_index);
10625 * non-power of 2 number of buckets
10627 fib_route_path_t *r_paths2 = NULL;
10629 r_paths2 = vec_dup(r_paths);
10630 _vec_len(r_paths2) = 3;
10632 pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths2);
10633 fib_path_list_lock(pl_index);
10635 fib_path_list_contribute_forwarding(pl_index,
10636 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10637 FIB_PATH_LIST_FWD_FLAG_STICKY,
10640 FIB_TEST(!fib_test_validate_lb(&dpo,
10660 bfds[1].local_state = BFD_STATE_down;
10661 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10663 fib_path_list_contribute_forwarding(pl_index,
10664 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10665 FIB_PATH_LIST_FWD_FLAG_STICKY,
10669 * path 1's buckets alternate between path 0 and 2
10671 FIB_TEST(!fib_test_validate_lb(&dpo,
10690 bfds[1].local_state = BFD_STATE_up;
10691 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10693 fib_path_list_unlock(pl_index);
10698 fib_route_path_t *r_paths3 = NULL;
10700 r_paths3 = vec_dup(r_paths);
10701 _vec_len(r_paths3) = 3;
10703 r_paths3[0].frp_weight = 3;
10705 pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths3);
10706 fib_path_list_lock(pl_index);
10708 fib_path_list_contribute_forwarding(pl_index,
10709 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10710 FIB_PATH_LIST_FWD_FLAG_STICKY,
10713 FIB_TEST(!fib_test_validate_lb(&dpo,
10733 bfds[1].local_state = BFD_STATE_down;
10734 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10736 fib_path_list_contribute_forwarding(pl_index,
10737 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10738 FIB_PATH_LIST_FWD_FLAG_STICKY,
10740 /* No attempt to Un-equal distribute the down path's buckets */
10741 FIB_TEST(!fib_test_validate_lb(&dpo,
10760 bfds[1].local_state = BFD_STATE_up;
10761 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10764 fib_path_list_unlock(pl_index);
10767 vec_free(r_paths2);
10768 vec_free(r_paths3);
10770 FIB_TEST(lb_count == pool_elts(load_balance_pool), "no leaked LBs");
10771 FIB_TEST(pl_count == fib_path_list_pool_size(), "no leaked PLs");
10776 static clib_error_t *
10777 fib_test (vlib_main_t * vm,
10778 unformat_input_t * input,
10779 vlib_cli_command_t * cmd_arg)
10785 fib_test_mk_intf(4);
10787 if (unformat (input, "debug"))
10789 fib_test_do_debug = 1;
10792 if (unformat (input, "ip4"))
10794 res += fib_test_v4();
10796 else if (unformat (input, "ip6"))
10798 res += fib_test_v6();
10800 else if (unformat (input, "ip"))
10802 res += fib_test_v4();
10803 res += fib_test_v6();
10805 else if (unformat (input, "label"))
10807 res += fib_test_label();
10809 else if (unformat (input, "ae"))
10811 res += fib_test_ae();
10813 else if (unformat (input, "pref"))
10815 res += fib_test_pref();
10817 else if (unformat (input, "lfib"))
10819 res += lfib_test();
10821 else if (unformat (input, "walk"))
10823 res += fib_test_walk();
10825 else if (unformat (input, "bfd"))
10827 res += fib_test_bfd();
10829 else if (unformat (input, "inherit"))
10831 res += fib_test_inherit();
10833 else if (unformat (input, "sticky"))
10835 res += fib_test_sticky();
10839 res += fib_test_v4();
10840 res += fib_test_v6();
10841 res += fib_test_ae();
10842 res += fib_test_bfd();
10843 res += fib_test_pref();
10844 res += fib_test_label();
10845 res += fib_test_inherit();
10846 res += lfib_test();
10849 * fib-walk process must be disabled in order for the walk tests to work
10851 fib_walk_process_disable();
10852 res += fib_test_walk();
10853 fib_walk_process_enable();
10859 return clib_error_return(0, "FIB Unit Test Failed");
10867 VLIB_CLI_COMMAND (test_fib_command, static) = {
10868 .path = "test fib",
10869 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
10870 .function = fib_test,
10874 fib_test_init (vlib_main_t *vm)
10879 VLIB_INIT_FUNCTION (fib_test_init);