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>
47 * Add debugs for passing tests
49 static int fib_test_do_debug;
51 #define FIB_TEST_I(_cond, _comment, _args...) \
53 int _evald = (_cond); \
55 fformat(stderr, "FAIL:%d: " _comment "\n", \
59 if (fib_test_do_debug) \
60 fformat(stderr, "PASS:%d: " _comment "\n", \
65 #define FIB_TEST(_cond, _comment, _args...) \
67 if (FIB_TEST_I(_cond, _comment, ##_args)) { \
69 ASSERT(!("FAIL: " _comment)); \
74 * A 'i'm not fussed is this is not efficient' store of test data
76 typedef struct test_main_t_ {
80 u32 hw_if_indicies[4];
84 vnet_hw_interface_t * hw[4];
87 static test_main_t test_main;
89 /* fake ethernet device class, distinct from "fake-ethX" */
90 static u8 * format_test_interface_name (u8 * s, va_list * args)
92 u32 dev_instance = va_arg (*args, u32);
93 return format (s, "test-eth%d", dev_instance);
96 static uword placeholder_interface_tx (vlib_main_t * vm,
97 vlib_node_runtime_t * node,
100 clib_warning ("you shouldn't be here, leaking buffers...");
101 return frame->n_vectors;
104 static clib_error_t *
105 test_interface_admin_up_down (vnet_main_t * vnm,
109 u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
110 VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
111 vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
115 VNET_DEVICE_CLASS (test_interface_device_class,static) = {
116 .name = "Test interface",
117 .format_device_name = format_test_interface_name,
118 .tx_function = placeholder_interface_tx,
119 .admin_up_down_function = test_interface_admin_up_down,
122 static u8 *hw_address;
125 fib_test_mk_intf (u32 ninterfaces)
127 clib_error_t * error = NULL;
128 test_main_t *tm = &test_main;
133 ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
138 vec_add1(hw_address, byte);
141 for (i = 0; i < ninterfaces; i++)
145 error = ethernet_register_interface(vnet_get_main(),
146 test_interface_device_class.index,
149 &tm->hw_if_indicies[i],
150 /* flag change */ 0);
152 FIB_TEST((NULL == error), "ADD interface %d", i);
154 error = vnet_hw_interface_set_flags(vnet_get_main(),
155 tm->hw_if_indicies[i],
156 VNET_HW_INTERFACE_FLAG_LINK_UP);
157 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
158 tm->hw_if_indicies[i]);
159 vec_validate (ip4_main.fib_index_by_sw_if_index,
160 tm->hw[i]->sw_if_index);
161 vec_validate (ip6_main.fib_index_by_sw_if_index,
162 tm->hw[i]->sw_if_index);
163 ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
164 ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
166 error = vnet_sw_interface_set_flags(vnet_get_main(),
167 tm->hw[i]->sw_if_index,
168 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
169 FIB_TEST((NULL == error), "UP interface %d", i);
172 * re-eval after the inevitable realloc
174 for (i = 0; i < ninterfaces; i++)
176 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
177 tm->hw_if_indicies[i]);
183 #define FIB_TEST_REC_FORW(_rec_prefix, _via_prefix, _bucket) \
185 const dpo_id_t *_rec_dpo = fib_entry_contribute_ip_forwarding( \
186 fib_table_lookup_exact_match(fib_index, (_rec_prefix))); \
187 const dpo_id_t *_via_dpo = fib_entry_contribute_ip_forwarding( \
188 fib_table_lookup(fib_index, (_via_prefix))); \
189 FIB_TEST(!dpo_cmp(_via_dpo, \
190 load_balance_get_bucket(_rec_dpo->dpoi_index, \
192 "%U is recursive via %U", \
193 format_fib_prefix, (_rec_prefix), \
194 format_fib_prefix, _via_prefix); \
197 #define FIB_TEST_LB_BUCKET_VIA_ADJ(_prefix, _bucket, _ai) \
199 const dpo_id_t *_dpo = fib_entry_contribute_ip_forwarding( \
200 fib_table_lookup_exact_match(fib_index, (_prefix))); \
201 const dpo_id_t *_dpo1 = \
202 load_balance_get_bucket(_dpo->dpoi_index, _bucket); \
203 FIB_TEST(DPO_ADJACENCY == _dpo1->dpoi_type, "type is %U", \
204 format_dpo_type, _dpo1->dpoi_type); \
205 FIB_TEST((_ai == _dpo1->dpoi_index), \
206 "%U bucket %d resolves via %U", \
207 format_fib_prefix, (_prefix), \
209 format_dpo_id, _dpo1, 0); \
212 #define FIB_TEST_RPF(_cond, _comment, _args...) \
214 if (FIB_TEST_I(_cond, _comment, ##_args)) { \
221 fib_test_urpf_is_equal (fib_node_index_t fei,
222 fib_forward_chain_type_t fct,
225 dpo_id_t dpo = DPO_INVALID;
226 fib_urpf_list_t *urpf;
234 fib_entry_contribute_forwarding(fei, fct, &dpo);
235 ui = load_balance_get_urpf(dpo.dpoi_index);
237 urpf = fib_urpf_list_get(ui);
239 FIB_TEST_RPF(num == vec_len(urpf->furpf_itfs),
240 "RPF:%U len %d == %d",
241 format_fib_urpf_list, ui,
242 num, vec_len(urpf->furpf_itfs));
243 FIB_TEST_RPF(num == fib_urpf_check_size(ui),
244 "RPF:%U check-size %d == %d",
245 format_fib_urpf_list, ui,
246 num, vec_len(urpf->furpf_itfs));
248 for (ii = 0; ii < num; ii++)
250 adj_index_t ai = va_arg(ap, adj_index_t);
252 FIB_TEST_RPF(ai == urpf->furpf_itfs[ii],
253 "RPF:%d item:%d - %d == %d",
254 ui, ii, ai, urpf->furpf_itfs[ii]);
255 FIB_TEST_RPF(fib_urpf_check(ui, ai),
269 fib_test_build_rewrite (u8 *eth_addr)
273 vec_validate(rewrite, 13);
275 memcpy(rewrite, eth_addr, 6);
276 memcpy(rewrite+6, eth_addr, 6);
281 #define FIB_TEST_LB(_cond, _comment, _args...) \
283 if (FIB_TEST_I(_cond, _comment, ##_args)) { \
289 fib_test_validate_rep_v (const replicate_t *rep,
293 const fib_test_rep_bucket_t *exp;
298 FIB_TEST_LB((n_buckets == rep->rep_n_buckets),
299 "n_buckets = %d", rep->rep_n_buckets);
301 for (bucket = 0; bucket < n_buckets; bucket++)
303 exp = va_arg(*ap, fib_test_rep_bucket_t*);
305 dpo = replicate_get_bucket_i(rep, bucket);
309 case FT_REP_LABEL_O_ADJ:
311 const mpls_label_dpo_t *mld;
314 FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE)
316 "bucket %d stacks on %U",
318 format_dpo_type, dpo->dpoi_type);
320 mld = mpls_label_dpo_get(dpo->dpoi_index);
321 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
323 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
324 exp->label_o_adj.label),
325 "bucket %d stacks on label %d",
327 exp->label_o_adj.label);
329 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
330 exp->label_o_adj.eos),
331 "bucket %d stacks on label %d %U",
333 exp->label_o_adj.label,
334 format_mpls_eos_bit, exp->label_o_adj.eos);
336 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
337 "bucket %d label stacks on %U",
339 format_dpo_type, mld->mld_dpo.dpoi_type);
341 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
342 "bucket %d label stacks on adj %d",
344 exp->label_o_adj.adj);
348 FIB_TEST_LB((DPO_INTERFACE_RX == dpo->dpoi_type),
349 "bucket %d stacks on %U",
351 format_dpo_type, dpo->dpoi_type);
353 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
354 "bucket %d stacks on adj %d",
358 case FT_REP_DISP_MFIB_LOOKUP:
368 fib_test_validate_lb_v (const load_balance_t *lb,
376 FIB_TEST_LB((n_buckets == lb->lb_n_buckets), "n_buckets = %d", lb->lb_n_buckets);
378 for (bucket = 0; bucket < n_buckets; bucket++)
380 const fib_test_lb_bucket_t *exp;
382 exp = va_arg(*ap, fib_test_lb_bucket_t*);
383 dpo = load_balance_get_bucket_i(lb, bucket);
387 case FT_LB_LABEL_STACK_O_ADJ:
389 const mpls_label_dpo_t *mld;
390 mpls_label_dpo_flags_t mf;
394 mf = ((exp->label_stack_o_adj.mode ==
395 FIB_MPLS_LSP_MODE_UNIFORM) ?
396 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
397 MPLS_LABEL_DPO_FLAG_NONE);
398 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
399 "bucket %d stacks on %U",
401 format_dpo_type, dpo->dpoi_type);
403 mld = mpls_label_dpo_get(dpo->dpoi_index);
405 FIB_TEST_LB(exp->label_stack_o_adj.label_stack_size == mld->mld_n_labels,
409 for (ii = 0; ii < mld->mld_n_labels; ii++)
411 hdr = clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
412 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
413 exp->label_stack_o_adj.label_stack[ii]),
414 "bucket %d stacks on label %d",
416 exp->label_stack_o_adj.label_stack[ii]);
418 if (ii == mld->mld_n_labels-1)
420 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
421 exp->label_o_adj.eos),
422 "bucket %d stacks on label %d %U!=%U",
424 exp->label_stack_o_adj.label_stack[ii],
425 format_mpls_eos_bit, exp->label_o_adj.eos,
426 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
430 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) == MPLS_NON_EOS),
431 "bucket %d stacks on label %d %U",
433 exp->label_stack_o_adj.label_stack[ii],
434 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
438 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
439 "bucket %d label stacks on %U",
441 format_dpo_type, mld->mld_dpo.dpoi_type);
443 FIB_TEST_LB((exp->label_stack_o_adj.adj == mld->mld_dpo.dpoi_index),
444 "bucket %d label stacks on adj %d",
446 exp->label_stack_o_adj.adj);
449 case FT_LB_LABEL_O_ADJ:
451 const mpls_label_dpo_t *mld;
453 FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE)
455 "bucket %d stacks on %U",
457 format_dpo_type, dpo->dpoi_type);
459 mld = mpls_label_dpo_get(dpo->dpoi_index);
460 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
462 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
463 exp->label_o_adj.label),
464 "bucket %d stacks on label %d",
466 exp->label_o_adj.label);
468 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
469 exp->label_o_adj.eos),
470 "bucket %d stacks on label %d %U",
472 exp->label_o_adj.label,
473 format_mpls_eos_bit, exp->label_o_adj.eos);
475 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
476 "bucket %d label stacks on %U",
478 format_dpo_type, mld->mld_dpo.dpoi_type);
480 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
481 "bucket %d label stacks on adj %d",
483 exp->label_o_adj.adj);
486 case FT_LB_LABEL_O_LB:
488 const mpls_label_dpo_t *mld;
489 mpls_label_dpo_flags_t mf;
492 mf = ((exp->label_o_lb.mode ==
493 FIB_MPLS_LSP_MODE_UNIFORM) ?
494 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE :
495 MPLS_LABEL_DPO_FLAG_NONE);
496 FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type),
497 "bucket %d stacks on %U",
499 format_dpo_type, dpo->dpoi_type);
501 mld = mpls_label_dpo_get(dpo->dpoi_index);
502 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
504 FIB_TEST_LB(1 == mld->mld_n_labels, "label stack size",
506 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
507 exp->label_o_lb.label),
508 "bucket %d stacks on label %d",
510 exp->label_o_lb.label);
512 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
513 exp->label_o_lb.eos),
514 "bucket %d stacks on label %d %U",
516 exp->label_o_lb.label,
517 format_mpls_eos_bit, exp->label_o_lb.eos);
519 FIB_TEST_LB((DPO_LOAD_BALANCE == mld->mld_dpo.dpoi_type),
520 "bucket %d label stacks on %U",
522 format_dpo_type, mld->mld_dpo.dpoi_type);
524 FIB_TEST_LB((exp->label_o_lb.lb == mld->mld_dpo.dpoi_index),
525 "bucket %d label stacks on LB %d",
531 res = FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
532 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
533 "bucket %d stacks on %U",
535 format_dpo_type, dpo->dpoi_type);
536 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
537 "bucket %d stacks on adj %d",
541 case FT_LB_MPLS_DISP_PIPE_O_ADJ:
543 const mpls_disp_dpo_t *mdd;
545 res = FIB_TEST_I((DPO_MPLS_DISPOSITION_PIPE == dpo->dpoi_type),
546 "bucket %d stacks on %U",
548 format_dpo_type, dpo->dpoi_type);
550 mdd = mpls_disp_dpo_get(dpo->dpoi_index);
554 res = FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
555 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
556 "bucket %d stacks on %U",
558 format_dpo_type, dpo->dpoi_type);
559 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
560 "bucket %d stacks on adj %d",
566 res = FIB_TEST_I((DPO_INTERFACE_RX == dpo->dpoi_type),
567 "bucket %d stacks on %U",
569 format_dpo_type, dpo->dpoi_type);
570 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
571 "bucket %d stacks on adj %d",
576 res = FIB_TEST_I((DPO_DVR == dpo->dpoi_type),
577 "bucket %d stacks on %U",
579 format_dpo_type, dpo->dpoi_type);
580 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
581 "bucket %d stacks on adj %d",
586 res = FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
587 "bucket %d stacks on %U",
589 format_dpo_type, dpo->dpoi_type);
590 FIB_TEST_LB((exp->lb.lb == dpo->dpoi_index),
591 "bucket %d stacks on lb %d not %d",
596 case FT_LB_BIER_TABLE:
597 FIB_TEST_LB((DPO_BIER_TABLE == dpo->dpoi_type),
598 "bucket %d stacks on %U",
600 format_dpo_type, dpo->dpoi_type);
601 FIB_TEST_LB((exp->bier.table == dpo->dpoi_index),
602 "bucket %d stacks on lb %d",
606 case FT_LB_BIER_FMASK:
607 FIB_TEST_LB((DPO_BIER_FMASK == dpo->dpoi_type),
608 "bucket %d stacks on %U",
610 format_dpo_type, dpo->dpoi_type);
611 FIB_TEST_LB((exp->bier.fmask == dpo->dpoi_index),
612 "bucket %d stacks on lb %d",
617 FIB_TEST_LB((DPO_DROP == dpo->dpoi_type),
618 "bucket %d stacks on %U",
620 format_dpo_type, dpo->dpoi_type);
623 FIB_TEST_LB((DPO_PUNT == dpo->dpoi_type),
624 "bucket %d stacks on %U",
626 format_dpo_type, dpo->dpoi_type);
634 fib_test_validate_lb (const dpo_id_t *dpo,
638 const load_balance_t *lb;
643 va_start(ap, n_buckets);
645 if (!FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
647 format_dpo_type, dpo->dpoi_type))
649 lb = load_balance_get(dpo->dpoi_index);
651 res = fib_test_validate_lb_v(lb, n_buckets, &ap);
664 fib_test_validate_entry (fib_node_index_t fei,
665 fib_forward_chain_type_t fct,
669 dpo_id_t dpo = DPO_INVALID;
670 const fib_prefix_t *pfx;
678 pfx = fib_entry_get_prefix(fei);
679 fib_index = fib_entry_get_fib_index(fei);
680 fib_entry_contribute_forwarding(fei, fct, &dpo);
682 if (DPO_REPLICATE == dpo.dpoi_type)
684 const replicate_t *rep;
686 va_start(ap, n_buckets);
687 rep = replicate_get(dpo.dpoi_index);
688 res = fib_test_validate_rep_v(rep, n_buckets, &ap);
693 const load_balance_t *lb;
695 FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type),
696 "%U Entry links to %U",
697 format_fib_prefix, pfx,
698 format_dpo_type, dpo.dpoi_type);
700 va_start(ap, n_buckets);
701 lb = load_balance_get(dpo.dpoi_index);
702 res = fib_test_validate_lb_v(lb, n_buckets, &ap);
706 * ensure that the LB contributed by the entry is the
707 * same as the LB in the forwarding tables
709 if (fct == fib_entry_get_default_chain_type(fib_entry_get(fei)))
711 switch (pfx->fp_proto)
713 case FIB_PROTOCOL_IP4:
714 fw_lbi = ip4_fib_forwarding_lookup(fib_index, &pfx->fp_addr.ip4);
716 case FIB_PROTOCOL_IP6:
717 fw_lbi = ip6_fib_table_fwding_lookup(fib_index, &pfx->fp_addr.ip6);
719 case FIB_PROTOCOL_MPLS:
721 mpls_unicast_header_t hdr = {
722 .label_exp_s_ttl = 0,
725 vnet_mpls_uc_set_label(&hdr.label_exp_s_ttl, pfx->fp_label);
726 vnet_mpls_uc_set_s(&hdr.label_exp_s_ttl, pfx->fp_eos);
727 hdr.label_exp_s_ttl = clib_host_to_net_u32(hdr.label_exp_s_ttl);
729 fw_lbi = mpls_fib_table_forwarding_lookup(fib_index, &hdr);
735 FIB_TEST_LB((fw_lbi == dpo.dpoi_index),
736 "Contributed LB = FW LB:\n fwd:%U\n cont:%U",
737 format_load_balance, fw_lbi, 0,
738 format_load_balance, dpo.dpoi_index, 0);
751 * In the default table check for the presence and correct forwarding
752 * of the special entries
754 fib_node_index_t dfrt, fei, ai, ai2, locked_ai, ai_01, ai_02, ai_03;
755 const dpo_id_t *dpo, *dpo1, *dpo2, *dpo_drop;
756 const ip_adjacency_t *adj;
757 const load_balance_t *lb;
765 ip46_address_t nh_10_10_10_1 = {
766 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
769 ip46_address_t nh_10_10_10_2 = {
770 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
773 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
774 pool_elts(load_balance_map_pool));
778 /* record the nubmer of load-balances in use before we start */
779 lb_count = pool_elts(load_balance_pool);
781 /* Find or create FIB table 11 */
782 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11,
785 for (ii = 0; ii < 4; ii++)
787 ip4_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
790 fib_prefix_t pfx_0_0_0_0_s_0 = {
792 .fp_proto = FIB_PROTOCOL_IP4,
802 .fp_proto = FIB_PROTOCOL_IP4,
810 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
812 dfrt = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
813 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
814 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
815 "Default route is DROP");
818 fei = fib_table_lookup(fib_index, &pfx);
819 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all zeros route present");
820 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
821 "all 0s route is DROP");
823 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xffffffff);
825 fei = fib_table_lookup(fib_index, &pfx);
826 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all ones route present");
827 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
828 "all 1s route is DROP");
830 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xe0000000);
832 fei = fib_table_lookup(fib_index, &pfx);
833 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all-mcast route present");
834 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
835 "all-mcast route is DROP");
837 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xf0000000);
839 fei = fib_table_lookup(fib_index, &pfx);
840 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "class-e route present");
841 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
842 "class-e route is DROP");
845 * at this stage there are 5 entries in the test FIB (plus 5 in the default),
846 * all of which are special sourced and so none of which share path-lists.
847 * There are also 2 entries, and 2 non-shared path-lists, in the v6 default
848 * table, and 4 path-lists in the v6 MFIB table and 2 in v4.
852 u32 PNBR = 5+5+2+4+2;
855 * if the IGMP plugin is loaded this adds two more entries to the v4 MFIB
857 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
858 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
859 fib_path_list_pool_size());
860 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
861 fib_entry_pool_size());
864 * add interface routes.
865 * validate presence of /24 attached and /32 recieve.
866 * test for the presence of the receive address in the glean and local adj
868 fib_prefix_t local_pfx = {
870 .fp_proto = FIB_PROTOCOL_IP4,
873 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
878 fib_table_entry_update_one_path(fib_index, &local_pfx,
879 FIB_SOURCE_INTERFACE,
880 (FIB_ENTRY_FLAG_CONNECTED |
881 FIB_ENTRY_FLAG_ATTACHED),
884 tm->hw[0]->sw_if_index,
885 ~0, // invalid fib index
888 FIB_ROUTE_PATH_FLAG_NONE);
889 fei = fib_table_lookup(fib_index, &local_pfx);
890 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
891 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
892 fib_entry_get_flags(fei)),
893 "Flags set on attached interface");
895 ai = fib_entry_get_adj(fei);
896 FIB_TEST((FIB_NODE_INDEX_INVALID != ai),
897 "attached interface route adj present %d", ai);
899 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
900 "attached interface adj is glean");
902 local_pfx.fp_len = 32;
903 fib_table_entry_update_one_path(fib_index, &local_pfx,
904 FIB_SOURCE_INTERFACE,
905 (FIB_ENTRY_FLAG_CONNECTED |
906 FIB_ENTRY_FLAG_LOCAL),
909 tm->hw[0]->sw_if_index,
910 ~0, // invalid fib index
913 FIB_ROUTE_PATH_FLAG_NONE);
914 fei = fib_table_lookup(fib_index, &local_pfx);
915 FIB_TEST(((FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_CONNECTED) ==
916 fib_entry_get_flags(fei)),
917 "Flags set on local interface");
919 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
921 dpo = fib_entry_contribute_ip_forwarding(fei);
922 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
923 "RPF list for local length 0");
924 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
925 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
926 "local interface adj is local");
927 receive_dpo_t *rd = receive_dpo_get(dpo->dpoi_index);
929 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
931 "local interface adj is receive ok");
933 FIB_TEST((2 == fib_table_get_num_entries(fib_index,
935 FIB_SOURCE_INTERFACE)),
936 "2 Interface Source'd prefixes");
937 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
938 &adj->sub_type.glean.rx_pfx.fp_addr)),
939 "attached interface adj is receive ok");
942 * +2 interface routes +2 non-shared path-lists
944 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
945 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
946 fib_path_list_pool_size());
947 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
948 fib_entry_pool_size());
951 * Modify the default route to be via an adj not yet known.
952 * this sources the defalut route with the API source, which is
953 * a higher preference to the DEFAULT_ROUTE source
955 pfx.fp_addr.ip4.as_u32 = 0;
957 fib_table_entry_path_add(fib_index, &pfx,
962 tm->hw[0]->sw_if_index,
963 ~0, // invalid fib index
966 FIB_ROUTE_PATH_FLAG_NONE);
967 fei = fib_table_lookup(fib_index, &pfx);
968 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
969 "Flags set on API route");
971 FIB_TEST((fei == dfrt), "default route same index");
972 ai = fib_entry_get_adj(fei);
973 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
975 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
976 "adj is incomplete");
977 FIB_TEST((0 == ip46_address_cmp(&nh_10_10_10_1, &adj->sub_type.nbr.next_hop)),
978 "adj nbr next-hop ok");
979 FIB_TEST((1 == fib_table_get_num_entries(fib_index,
982 "1 API Source'd prefixes");
985 * find the adj in the shared db
987 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
990 tm->hw[0]->sw_if_index);
991 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
992 adj_unlock(locked_ai);
995 * +1 shared path-list
997 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
998 fib_path_list_db_size());
999 FIB_TEST((PNBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
1000 fib_path_list_pool_size());
1001 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
1002 fib_entry_pool_size());
1005 * remove the API source from the default route. We expected
1006 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
1008 pfx.fp_addr.ip4.as_u32 = 0;
1010 fib_table_entry_path_remove(fib_index, &pfx,
1014 tm->hw[0]->sw_if_index,
1015 ~0, // non-recursive path, so no FIB index
1017 FIB_ROUTE_PATH_FLAG_NONE);
1019 fei = fib_table_lookup(fib_index, &pfx);
1021 FIB_TEST((fei == dfrt), "default route same index");
1022 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
1023 "Default route is DROP");
1026 * -1 shared-path-list
1028 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
1029 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
1030 fib_path_list_pool_size());
1031 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
1032 fib_entry_pool_size());
1035 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
1037 fib_prefix_t pfx_10_10_10_1_s_32 = {
1039 .fp_proto = FIB_PROTOCOL_IP4,
1042 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
1045 fib_prefix_t pfx_10_10_10_2_s_32 = {
1047 .fp_proto = FIB_PROTOCOL_IP4,
1050 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
1053 fib_prefix_t pfx_11_11_11_11_s_32 = {
1055 .fp_proto = FIB_PROTOCOL_IP4,
1058 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
1062 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
1065 ip46_address_t nh_12_12_12_12 = {
1066 .ip4.as_u32 = clib_host_to_net_u32(0x0c0c0c0c),
1068 adj_index_t ai_12_12_12_12;
1071 * Add a route via an incomplete ADJ. then complete the ADJ
1072 * Expect the route LB is updated to use complete adj type.
1074 fei = fib_table_entry_update_one_path(fib_index,
1075 &pfx_11_11_11_11_s_32,
1077 FIB_ENTRY_FLAG_ATTACHED,
1079 &pfx_10_10_10_1_s_32.fp_addr,
1080 tm->hw[0]->sw_if_index,
1081 ~0, // invalid fib index
1084 FIB_ROUTE_PATH_FLAG_NONE);
1086 dpo = fib_entry_contribute_ip_forwarding(fei);
1087 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1088 FIB_TEST(DPO_ADJACENCY_INCOMPLETE == dpo1->dpoi_type,
1089 "11.11.11.11/32 via incomplete adj");
1091 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1093 &pfx_10_10_10_1_s_32.fp_addr,
1094 tm->hw[0]->sw_if_index);
1095 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
1096 adj = adj_get(ai_01);
1097 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1098 "adj is incomplete");
1099 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1100 &adj->sub_type.nbr.next_hop)),
1101 "adj nbr next-hop ok");
1103 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1104 fib_test_build_rewrite(eth_addr));
1105 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1107 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1108 &adj->sub_type.nbr.next_hop)),
1109 "adj nbr next-hop ok");
1110 ai = fib_entry_get_adj(fei);
1111 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
1113 dpo = fib_entry_contribute_ip_forwarding(fei);
1114 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1115 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type,
1116 "11.11.11.11/32 via complete adj");
1117 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1118 tm->hw[0]->sw_if_index),
1119 "RPF list for adj-fib contains adj");
1121 ai_12_12_12_12 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1124 tm->hw[1]->sw_if_index);
1125 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_12_12_12_12), "adj created");
1126 adj = adj_get(ai_12_12_12_12);
1127 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1128 "adj is incomplete");
1129 FIB_TEST((0 == ip46_address_cmp(&nh_12_12_12_12,
1130 &adj->sub_type.nbr.next_hop)),
1131 "adj nbr next-hop ok");
1132 adj_nbr_update_rewrite(ai_12_12_12_12, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1133 fib_test_build_rewrite(eth_addr));
1134 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1140 fei = fib_table_entry_path_add(fib_index,
1141 &pfx_10_10_10_1_s_32,
1143 FIB_ENTRY_FLAG_ATTACHED,
1145 &pfx_10_10_10_1_s_32.fp_addr,
1146 tm->hw[0]->sw_if_index,
1147 ~0, // invalid fib index
1150 FIB_ROUTE_PATH_FLAG_NONE);
1151 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
1152 "Flags set on adj-fib");
1153 ai = fib_entry_get_adj(fei);
1154 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj, %d", ai);
1156 fib_table_entry_path_remove(fib_index,
1157 &pfx_11_11_11_11_s_32,
1160 &pfx_10_10_10_1_s_32.fp_addr,
1161 tm->hw[0]->sw_if_index,
1162 ~0, // invalid fib index
1164 FIB_ROUTE_PATH_FLAG_NONE);
1168 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1170 &pfx_10_10_10_2_s_32.fp_addr,
1171 tm->hw[0]->sw_if_index);
1172 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
1173 adj = adj_get(ai_02);
1174 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1175 "adj is incomplete");
1176 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1177 &adj->sub_type.nbr.next_hop)),
1178 "adj nbr next-hop ok");
1180 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1181 fib_test_build_rewrite(eth_addr));
1182 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1184 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1185 &adj->sub_type.nbr.next_hop)),
1186 "adj nbr next-hop ok");
1187 FIB_TEST((ai_01 != ai_02), "ADJs are different");
1189 fib_table_entry_path_add(fib_index,
1190 &pfx_10_10_10_2_s_32,
1192 FIB_ENTRY_FLAG_ATTACHED,
1194 &pfx_10_10_10_2_s_32.fp_addr,
1195 tm->hw[0]->sw_if_index,
1196 ~0, // invalid fib index
1199 FIB_ROUTE_PATH_FLAG_NONE);
1201 fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32);
1202 ai = fib_entry_get_adj(fei);
1203 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
1206 * +2 adj-fibs, and their non-shared path-lists
1208 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
1209 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
1210 fib_path_list_pool_size());
1211 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
1212 fib_entry_pool_size());
1215 * Add 2 routes via the first ADJ. ensure path-list sharing
1217 fib_prefix_t pfx_1_1_1_1_s_32 = {
1219 .fp_proto = FIB_PROTOCOL_IP4,
1222 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1226 fib_table_entry_path_add(fib_index,
1229 FIB_ENTRY_FLAG_NONE,
1232 tm->hw[0]->sw_if_index,
1233 ~0, // invalid fib index
1236 FIB_ROUTE_PATH_FLAG_NONE);
1237 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
1238 ai = fib_entry_get_adj(fei);
1239 FIB_TEST((ai_01 == ai), "1.1.1.1 resolves via 10.10.10.1");
1242 * +1 entry and a shared path-list
1244 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
1245 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1246 fib_path_list_pool_size());
1247 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
1248 fib_entry_pool_size());
1251 fib_prefix_t pfx_1_1_2_0_s_24 = {
1253 .fp_proto = FIB_PROTOCOL_IP4,
1255 .ip4.as_u32 = clib_host_to_net_u32(0x01010200),
1259 fib_table_entry_path_add(fib_index,
1262 FIB_ENTRY_FLAG_NONE,
1265 tm->hw[0]->sw_if_index,
1266 ~0, // invalid fib index
1269 FIB_ROUTE_PATH_FLAG_NONE);
1270 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1271 ai = fib_entry_get_adj(fei);
1272 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1277 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
1278 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1279 fib_path_list_pool_size());
1280 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1281 fib_entry_pool_size());
1284 * modify 1.1.2.0/24 to use multipath.
1286 fib_table_entry_path_add(fib_index,
1289 FIB_ENTRY_FLAG_NONE,
1292 tm->hw[0]->sw_if_index,
1293 ~0, // invalid fib index
1296 FIB_ROUTE_PATH_FLAG_NONE);
1297 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1298 dpo = fib_entry_contribute_ip_forwarding(fei);
1299 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1300 1, tm->hw[0]->sw_if_index),
1301 "RPF list for 1.1.2.0/24 contains both adjs");
1303 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1304 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1305 FIB_TEST((ai_01 == dpo1->dpoi_index),
1306 "1.1.2.0/24 bucket 0 resolves via 10.10.10.1 (%d=%d)",
1307 ai_01, dpo1->dpoi_index);
1309 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 1);
1310 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1311 FIB_TEST((ai_02 == dpo1->dpoi_index),
1312 "1.1.2.0/24 bucket 1 resolves via 10.10.10.2");
1315 * +1 shared-pathlist
1317 FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty");
1318 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1319 fib_path_list_pool_size());
1320 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1321 fib_entry_pool_size());
1326 fib_table_entry_path_remove(fib_index,
1331 tm->hw[0]->sw_if_index,
1334 FIB_ROUTE_PATH_FLAG_NONE);
1335 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1336 dpo = fib_entry_contribute_ip_forwarding(fei);
1337 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1338 1, tm->hw[0]->sw_if_index),
1339 "RPF list for 1.1.2.0/24 contains one adj");
1341 ai = fib_entry_get_adj(fei);
1342 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1345 * +1 shared-pathlist
1347 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d",
1348 fib_path_list_db_size());
1349 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1350 fib_path_list_pool_size());
1351 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1352 fib_entry_pool_size());
1355 * Add 2 recursive routes:
1356 * 100.100.100.100/32 via 1.1.1.1/32 => the via entry is installed.
1357 * 100.100.100.101/32 via 1.1.1.1/32 => the via entry is installed.
1359 fib_prefix_t bgp_100_pfx = {
1361 .fp_proto = FIB_PROTOCOL_IP4,
1363 /* 100.100.100.100/32 */
1364 .ip4.as_u32 = clib_host_to_net_u32(0x64646464),
1368 ip46_address_t nh_1_1_1_1 = {
1369 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1372 fei = fib_table_entry_path_add(fib_index,
1375 FIB_ENTRY_FLAG_NONE,
1378 ~0, // no index provided.
1379 fib_index, // nexthop in same fib as route
1382 FIB_ROUTE_PATH_FLAG_NONE);
1384 FIB_TEST_REC_FORW(&bgp_100_pfx, &pfx_1_1_1_1_s_32, 0);
1385 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1386 tm->hw[0]->sw_if_index),
1387 "RPF list for adj-fib contains adj");
1390 * +1 entry and +1 shared-path-list
1392 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1393 fib_path_list_db_size());
1394 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1395 fib_path_list_pool_size());
1396 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
1397 fib_entry_pool_size());
1399 fib_prefix_t bgp_101_pfx = {
1401 .fp_proto = FIB_PROTOCOL_IP4,
1403 /* 100.100.100.101/32 */
1404 .ip4.as_u32 = clib_host_to_net_u32(0x64646465),
1408 fib_table_entry_path_add(fib_index,
1411 FIB_ENTRY_FLAG_NONE,
1414 ~0, // no index provided.
1415 fib_index, // nexthop in same fib as route
1418 FIB_ROUTE_PATH_FLAG_NONE);
1420 FIB_TEST_REC_FORW(&bgp_101_pfx, &pfx_1_1_1_1_s_32, 0);
1421 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1422 tm->hw[0]->sw_if_index),
1423 "RPF list for adj-fib contains adj");
1426 * +1 entry, but the recursive path-list is shared.
1428 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1429 fib_path_list_db_size());
1430 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1431 fib_path_list_pool_size());
1432 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
1433 fib_entry_pool_size());
1436 * An special route; one where the user (me) provides the
1437 * adjacency through which the route will resovle by setting the flags
1439 fib_prefix_t ex_pfx = {
1441 .fp_proto = FIB_PROTOCOL_IP4,
1444 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
1448 fib_table_entry_special_add(fib_index,
1451 FIB_ENTRY_FLAG_LOCAL);
1452 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1453 dpo = fib_entry_contribute_ip_forwarding(fei);
1454 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
1455 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
1456 "local interface adj is local");
1458 fib_table_entry_special_remove(fib_index,
1460 FIB_SOURCE_SPECIAL);
1461 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1462 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1463 "Exclusive reoute removed");
1466 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1467 * adjacency through which the route will resovle
1469 dpo_id_t ex_dpo = DPO_INVALID;
1471 lookup_dpo_add_or_lock_w_fib_index(fib_index,
1474 LOOKUP_INPUT_DST_ADDR,
1475 LOOKUP_TABLE_FROM_CONFIG,
1478 fib_table_entry_special_dpo_add(fib_index,
1481 FIB_ENTRY_FLAG_EXCLUSIVE,
1483 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1484 dpo = fib_entry_contribute_ip_forwarding(fei);
1485 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1486 "exclusive remote uses lookup DPO");
1489 * update the exclusive to use a different DPO
1491 ip_null_dpo_add_and_lock(DPO_PROTO_IP4,
1492 IP_NULL_ACTION_SEND_ICMP_UNREACH,
1494 fib_table_entry_special_dpo_update(fib_index,
1497 FIB_ENTRY_FLAG_EXCLUSIVE,
1499 dpo = fib_entry_contribute_ip_forwarding(fei);
1500 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1501 "exclusive remote uses now uses NULL DPO");
1503 fib_table_entry_special_remove(fib_index,
1505 FIB_SOURCE_SPECIAL);
1506 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1507 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1508 "Exclusive reoute removed");
1512 * Add a recursive route:
1513 * 200.200.200.200/32 via 1.1.1.2/32 => the via entry is NOT installed.
1515 fib_prefix_t bgp_200_pfx = {
1517 .fp_proto = FIB_PROTOCOL_IP4,
1519 /* 200.200.200.200/32 */
1520 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c8),
1524 fib_prefix_t pfx_1_1_1_2_s_32 = {
1526 .fp_proto = FIB_PROTOCOL_IP4,
1528 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
1532 fei = fib_table_entry_path_add(fib_index,
1535 FIB_ENTRY_FLAG_NONE,
1537 &pfx_1_1_1_2_s_32.fp_addr,
1538 ~0, // no index provided.
1539 fib_index, // nexthop in same fib as route
1542 FIB_ROUTE_PATH_FLAG_NONE);
1544 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
1545 "Recursive via unresolved is drop");
1548 * the adj should be recursive via drop, since the route resolves via
1549 * the default route, which is itself a DROP
1551 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
1552 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1553 FIB_TEST(load_balance_is_drop(dpo1), "1.1.1.2/32 is drop");
1554 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1555 "RPF list for 1.1.1.2/32 contains 0 adjs");
1558 * +2 entry and +1 shared-path-list
1560 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
1561 fib_path_list_db_size());
1562 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
1563 fib_path_list_pool_size());
1564 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
1565 fib_entry_pool_size());
1568 * Unequal Cost load-balance. 3:1 ratio. fits in a 4 bucket LB
1569 * The paths are sort by NH first. in this case the the path with greater
1570 * weight is first in the set. This ordering is to test the RPF sort|uniq logic
1572 fib_prefix_t pfx_1_2_3_4_s_32 = {
1574 .fp_proto = FIB_PROTOCOL_IP4,
1576 .ip4.as_u32 = clib_host_to_net_u32(0x01020304),
1579 fib_table_entry_path_add(fib_index,
1582 FIB_ENTRY_FLAG_NONE,
1585 tm->hw[0]->sw_if_index,
1589 FIB_ROUTE_PATH_FLAG_NONE);
1590 fei = fib_table_entry_path_add(fib_index,
1593 FIB_ENTRY_FLAG_NONE,
1596 tm->hw[1]->sw_if_index,
1600 FIB_ROUTE_PATH_FLAG_NONE);
1602 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.4/32 presnet");
1603 dpo = fib_entry_contribute_ip_forwarding(fei);
1604 lb = load_balance_get(dpo->dpoi_index);
1605 FIB_TEST((lb->lb_n_buckets == 4),
1606 "1.2.3.4/32 LB has %d bucket",
1609 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 0, ai_12_12_12_12);
1610 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 1, ai_12_12_12_12);
1611 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 2, ai_12_12_12_12);
1612 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 3, ai_01);
1614 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1615 tm->hw[0]->sw_if_index,
1616 tm->hw[1]->sw_if_index),
1617 "RPF list for 1.2.3.4/32 contains both adjs");
1621 * Unequal Cost load-balance. 4:1 ratio.
1622 * fits in a 16 bucket LB with ratio 13:3
1624 fib_prefix_t pfx_1_2_3_5_s_32 = {
1626 .fp_proto = FIB_PROTOCOL_IP4,
1628 .ip4.as_u32 = clib_host_to_net_u32(0x01020305),
1631 fib_table_entry_path_add(fib_index,
1634 FIB_ENTRY_FLAG_NONE,
1637 tm->hw[1]->sw_if_index,
1641 FIB_ROUTE_PATH_FLAG_NONE);
1642 fei = fib_table_entry_path_add(fib_index,
1645 FIB_ENTRY_FLAG_NONE,
1648 tm->hw[0]->sw_if_index,
1652 FIB_ROUTE_PATH_FLAG_NONE);
1654 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.5/32 presnet");
1655 dpo = fib_entry_contribute_ip_forwarding(fei);
1656 lb = load_balance_get(dpo->dpoi_index);
1657 FIB_TEST((lb->lb_n_buckets == 16),
1658 "1.2.3.5/32 LB has %d bucket",
1661 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 0, ai_01);
1662 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 1, ai_01);
1663 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 2, ai_01);
1664 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 3, ai_01);
1665 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 4, ai_01);
1666 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 5, ai_01);
1667 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 6, ai_01);
1668 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 7, ai_01);
1669 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 8, ai_01);
1670 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 9, ai_01);
1671 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 10, ai_01);
1672 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 11, ai_01);
1673 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 12, ai_01);
1674 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 13, ai_12_12_12_12);
1675 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 14, ai_12_12_12_12);
1676 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 15, ai_12_12_12_12);
1678 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1679 tm->hw[0]->sw_if_index,
1680 tm->hw[1]->sw_if_index),
1681 "RPF list for 1.2.3.4/32 contains both adjs");
1684 * Test UCMP with a large weight skew - this produces load-balance objects with large
1685 * numbers of buckets to accommodate the skew. By updating said load-balances we are
1686 * laso testing the LB in placce modify code when number of buckets is large.
1688 fib_prefix_t pfx_6_6_6_6_s_32 = {
1690 .fp_proto = FIB_PROTOCOL_IP4,
1693 .ip4.as_u32 = clib_host_to_net_u32(0x06060606),
1696 fib_test_lb_bucket_t ip_o_10_10_10_1 = {
1702 fib_test_lb_bucket_t ip_o_10_10_10_2 = {
1708 fib_test_lb_bucket_t ip_6_6_6_6_o_12_12_12_12 = {
1711 .adj = ai_12_12_12_12,
1714 fib_table_entry_update_one_path(fib_index,
1717 FIB_ENTRY_FLAG_NONE,
1720 tm->hw[0]->sw_if_index,
1721 ~0, // invalid fib index
1724 FIB_ROUTE_PATH_FLAG_NONE);
1726 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1727 FIB_TEST(!fib_test_validate_entry(fei,
1728 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1731 "6.6.6.6/32 via 10.10.10.1");
1733 fib_table_entry_path_add(fib_index,
1736 FIB_ENTRY_FLAG_NONE,
1739 tm->hw[0]->sw_if_index,
1740 ~0, // invalid fib index
1743 FIB_ROUTE_PATH_FLAG_NONE);
1745 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1746 FIB_TEST(!fib_test_validate_entry(fei,
1747 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1813 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1815 fib_table_entry_path_add(fib_index,
1818 FIB_ENTRY_FLAG_NONE,
1821 tm->hw[1]->sw_if_index,
1822 ~0, // invalid fib index
1825 FIB_ROUTE_PATH_FLAG_NONE);
1827 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1828 FIB_TEST(!fib_test_validate_entry(fei,
1829 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1896 &ip_6_6_6_6_o_12_12_12_12,
1897 &ip_6_6_6_6_o_12_12_12_12,
1898 &ip_6_6_6_6_o_12_12_12_12,
1899 &ip_6_6_6_6_o_12_12_12_12,
1900 &ip_6_6_6_6_o_12_12_12_12,
1901 &ip_6_6_6_6_o_12_12_12_12,
1902 &ip_6_6_6_6_o_12_12_12_12,
1903 &ip_6_6_6_6_o_12_12_12_12,
1904 &ip_6_6_6_6_o_12_12_12_12,
1905 &ip_6_6_6_6_o_12_12_12_12,
1906 &ip_6_6_6_6_o_12_12_12_12,
1907 &ip_6_6_6_6_o_12_12_12_12,
1908 &ip_6_6_6_6_o_12_12_12_12,
1909 &ip_6_6_6_6_o_12_12_12_12,
1910 &ip_6_6_6_6_o_12_12_12_12,
1911 &ip_6_6_6_6_o_12_12_12_12,
1912 &ip_6_6_6_6_o_12_12_12_12,
1913 &ip_6_6_6_6_o_12_12_12_12,
1914 &ip_6_6_6_6_o_12_12_12_12,
1915 &ip_6_6_6_6_o_12_12_12_12,
1916 &ip_6_6_6_6_o_12_12_12_12,
1917 &ip_6_6_6_6_o_12_12_12_12,
1918 &ip_6_6_6_6_o_12_12_12_12,
1919 &ip_6_6_6_6_o_12_12_12_12,
1920 &ip_6_6_6_6_o_12_12_12_12,
1921 &ip_6_6_6_6_o_12_12_12_12,
1922 &ip_6_6_6_6_o_12_12_12_12,
1923 &ip_6_6_6_6_o_12_12_12_12,
1924 &ip_6_6_6_6_o_12_12_12_12,
1925 &ip_6_6_6_6_o_12_12_12_12,
1926 &ip_6_6_6_6_o_12_12_12_12,
1927 &ip_6_6_6_6_o_12_12_12_12,
1928 &ip_6_6_6_6_o_12_12_12_12,
1929 &ip_6_6_6_6_o_12_12_12_12,
1930 &ip_6_6_6_6_o_12_12_12_12,
1931 &ip_6_6_6_6_o_12_12_12_12,
1932 &ip_6_6_6_6_o_12_12_12_12,
1933 &ip_6_6_6_6_o_12_12_12_12,
1934 &ip_6_6_6_6_o_12_12_12_12,
1935 &ip_6_6_6_6_o_12_12_12_12,
1936 &ip_6_6_6_6_o_12_12_12_12,
1937 &ip_6_6_6_6_o_12_12_12_12,
1938 &ip_6_6_6_6_o_12_12_12_12,
1939 &ip_6_6_6_6_o_12_12_12_12,
1940 &ip_6_6_6_6_o_12_12_12_12,
1941 &ip_6_6_6_6_o_12_12_12_12,
1942 &ip_6_6_6_6_o_12_12_12_12,
1943 &ip_6_6_6_6_o_12_12_12_12,
1944 &ip_6_6_6_6_o_12_12_12_12,
1945 &ip_6_6_6_6_o_12_12_12_12,
1946 &ip_6_6_6_6_o_12_12_12_12,
1947 &ip_6_6_6_6_o_12_12_12_12,
1948 &ip_6_6_6_6_o_12_12_12_12,
1949 &ip_6_6_6_6_o_12_12_12_12,
1950 &ip_6_6_6_6_o_12_12_12_12,
1951 &ip_6_6_6_6_o_12_12_12_12,
1952 &ip_6_6_6_6_o_12_12_12_12,
1953 &ip_6_6_6_6_o_12_12_12_12,
1954 &ip_6_6_6_6_o_12_12_12_12,
1955 &ip_6_6_6_6_o_12_12_12_12,
1956 &ip_6_6_6_6_o_12_12_12_12,
1957 &ip_6_6_6_6_o_12_12_12_12,
1958 &ip_6_6_6_6_o_12_12_12_12),
1959 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1961 fib_table_entry_path_remove(fib_index,
1966 tm->hw[1]->sw_if_index,
1967 ~0, // invalid fib index
1969 FIB_ROUTE_PATH_FLAG_NONE);
1971 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1972 FIB_TEST(!fib_test_validate_entry(fei,
1973 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2039 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
2041 fib_table_entry_path_remove(fib_index,
2046 tm->hw[0]->sw_if_index,
2047 ~0, // invalid fib index
2049 FIB_ROUTE_PATH_FLAG_NONE);
2051 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
2052 FIB_TEST(!fib_test_validate_entry(fei,
2053 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2056 "6.6.6.6/32 via 10.10.10.1");
2058 fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API);
2061 * A recursive via the two unequal cost entries
2063 fib_prefix_t bgp_44_s_32 = {
2065 .fp_proto = FIB_PROTOCOL_IP4,
2067 /* 200.200.200.201/32 */
2068 .ip4.as_u32 = clib_host_to_net_u32(0x44444444),
2071 fei = fib_table_entry_path_add(fib_index,
2074 FIB_ENTRY_FLAG_NONE,
2076 &pfx_1_2_3_4_s_32.fp_addr,
2081 FIB_ROUTE_PATH_FLAG_NONE);
2082 fei = fib_table_entry_path_add(fib_index,
2085 FIB_ENTRY_FLAG_NONE,
2087 &pfx_1_2_3_5_s_32.fp_addr,
2092 FIB_ROUTE_PATH_FLAG_NONE);
2094 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_4_s_32, 0);
2095 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_5_s_32, 1);
2096 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
2097 tm->hw[0]->sw_if_index,
2098 tm->hw[1]->sw_if_index),
2099 "RPF list for 1.2.3.4/32 contains both adjs");
2102 * test the uRPF check functions
2104 dpo_id_t dpo_44 = DPO_INVALID;
2107 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
2108 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
2110 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
2111 "uRPF check for 68.68.68.68/32 on %d OK",
2112 tm->hw[0]->sw_if_index);
2113 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
2114 "uRPF check for 68.68.68.68/32 on %d OK",
2115 tm->hw[1]->sw_if_index);
2116 FIB_TEST(!fib_urpf_check(urpfi, 99),
2117 "uRPF check for 68.68.68.68/32 on 99 not-OK",
2121 fib_table_entry_delete(fib_index,
2124 fib_table_entry_delete(fib_index,
2127 fib_table_entry_delete(fib_index,
2132 * Add a recursive route:
2133 * 200.200.200.201/32 via 1.1.1.200/32 => the via entry is NOT installed.
2135 fib_prefix_t bgp_201_pfx = {
2137 .fp_proto = FIB_PROTOCOL_IP4,
2139 /* 200.200.200.201/32 */
2140 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c9),
2144 fib_prefix_t pfx_1_1_1_200_s_32 = {
2146 .fp_proto = FIB_PROTOCOL_IP4,
2148 .ip4.as_u32 = clib_host_to_net_u32(0x010101c8),
2152 fei = fib_table_entry_path_add(fib_index,
2155 FIB_ENTRY_FLAG_NONE,
2157 &pfx_1_1_1_200_s_32.fp_addr,
2158 ~0, // no index provided.
2159 fib_index, // nexthop in same fib as route
2162 FIB_ROUTE_PATH_FLAG_NONE);
2164 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2165 "Recursive via unresolved is drop");
2167 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2168 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
2169 "Flags set on RR via non-attached");
2170 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
2171 "RPF list for BGP route empty");
2174 * +2 entry (BGP & RR) and +1 shared-path-list
2176 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2177 fib_path_list_db_size());
2178 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2179 fib_path_list_pool_size());
2180 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2181 fib_entry_pool_size());
2184 * insert a route that covers the missing 1.1.1.2/32. we epxect
2185 * 200.200.200.200/32 and 200.200.200.201/32 to resolve through it.
2187 fib_prefix_t pfx_1_1_1_0_s_24 = {
2189 .fp_proto = FIB_PROTOCOL_IP4,
2192 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2196 fib_table_entry_path_add(fib_index,
2199 FIB_ENTRY_FLAG_NONE,
2202 tm->hw[0]->sw_if_index,
2203 ~0, // invalid fib index
2206 FIB_ROUTE_PATH_FLAG_NONE);
2207 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24);
2208 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2209 ai = fib_entry_get_adj(fei);
2210 FIB_TEST((ai_01 == ai), "1.1.1.0/24 resolves via 10.10.10.1");
2211 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2212 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2213 ai = fib_entry_get_adj(fei);
2214 FIB_TEST((ai_01 == ai), "1.1.1.2/32 resolves via 10.10.10.1");
2215 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2216 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2217 ai = fib_entry_get_adj(fei);
2218 FIB_TEST((ai_01 == ai), "1.1.1.200/24 resolves via 10.10.10.1");
2221 * +1 entry. 1.1.1.1/32 already uses 10.10.10.1 so no new pah-list
2223 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2224 fib_path_list_db_size());
2225 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2226 fib_path_list_pool_size());
2227 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
2228 fib_entry_pool_size());
2231 * the recursive adj for 200.200.200.200 should be updated.
2233 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2234 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2235 fei = fib_table_lookup(fib_index, &bgp_200_pfx);
2236 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
2237 tm->hw[0]->sw_if_index),
2238 "RPF list for BGP route has itf index 0");
2241 * insert a more specific route than 1.1.1.0/24 that also covers the
2242 * missing 1.1.1.2/32, but not 1.1.1.200/32. we expect
2243 * 200.200.200.200 to resolve through it.
2245 fib_prefix_t pfx_1_1_1_0_s_28 = {
2247 .fp_proto = FIB_PROTOCOL_IP4,
2250 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2254 fib_table_entry_path_add(fib_index,
2257 FIB_ENTRY_FLAG_NONE,
2260 tm->hw[0]->sw_if_index,
2261 ~0, // invalid fib index
2264 FIB_ROUTE_PATH_FLAG_NONE);
2265 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28);
2266 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2267 ai = fib_entry_get_adj(fei);
2268 FIB_TEST((ai_02 == ai), "1.1.1.0/24 resolves via 10.10.10.2");
2271 * +1 entry. +1 shared path-list
2273 FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d",
2274 fib_path_list_db_size());
2275 FIB_TEST((PNBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
2276 fib_path_list_pool_size());
2277 FIB_TEST((ENBR+14 == fib_entry_pool_size()), "entry pool size is %d",
2278 fib_entry_pool_size());
2281 * the recursive adj for 200.200.200.200 should be updated.
2282 * 200.200.200.201 remains unchanged.
2284 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2285 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2288 * remove this /28. 200.200.200.200/32 should revert back to via 1.1.1.0/24
2290 fib_table_entry_path_remove(fib_index,
2295 tm->hw[0]->sw_if_index,
2298 FIB_ROUTE_PATH_FLAG_NONE);
2299 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28) ==
2300 FIB_NODE_INDEX_INVALID),
2301 "1.1.1.0/28 removed");
2302 FIB_TEST((fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28) ==
2303 fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24)),
2304 "1.1.1.0/28 lookup via /24");
2305 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2306 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2309 * -1 entry. -1 shared path-list
2311 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2312 fib_path_list_db_size());
2313 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2314 fib_path_list_pool_size());
2315 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
2316 fib_entry_pool_size());
2319 * remove 1.1.1.0/24. 200.200.200.200/32 should revert back to via 0.0.0.0/0
2321 fib_table_entry_path_remove(fib_index,
2326 tm->hw[0]->sw_if_index,
2329 FIB_ROUTE_PATH_FLAG_NONE);
2330 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_24) ==
2331 FIB_NODE_INDEX_INVALID),
2332 "1.1.1.0/24 removed");
2334 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2335 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2336 "1.1.1.2/32 route is DROP");
2337 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2338 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2339 "1.1.1.200/32 route is DROP");
2341 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2342 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2344 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2345 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2351 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2352 fib_path_list_db_size());
2353 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2354 fib_path_list_pool_size());
2355 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2356 fib_entry_pool_size());
2359 * insert the missing 1.1.1.2/32
2361 fei = fib_table_entry_path_add(fib_index,
2364 FIB_ENTRY_FLAG_NONE,
2367 tm->hw[0]->sw_if_index,
2368 ~0, // invalid fib index
2371 FIB_ROUTE_PATH_FLAG_NONE);
2372 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2373 ai = fib_entry_get_adj(fei);
2374 FIB_TEST((ai = ai_01), "1.1.1.2/32 resolves via 10.10.10.1");
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 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2382 * no change. 1.1.1.2/32 was already there RR sourced.
2384 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2385 fib_path_list_db_size());
2386 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2387 fib_path_list_pool_size());
2388 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2389 fib_entry_pool_size());
2392 * give 201 a resolved path.
2393 * it now has the unresolved 1.1.1.200 and the resolved 1.1.1.2,
2394 * only the latter contributes forwarding.
2396 fei = fib_table_entry_path_add(fib_index,
2399 FIB_ENTRY_FLAG_NONE,
2401 &pfx_1_1_1_2_s_32.fp_addr,
2406 FIB_ROUTE_PATH_FLAG_NONE);
2407 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_2_s_32, 0);
2408 fib_table_entry_path_remove(fib_index,
2412 &pfx_1_1_1_2_s_32.fp_addr,
2416 FIB_ROUTE_PATH_FLAG_NONE);
2419 * remove 200.200.200.201/32 which does not have a valid via FIB
2421 fib_table_entry_path_remove(fib_index,
2425 &pfx_1_1_1_200_s_32.fp_addr,
2426 ~0, // no index provided.
2429 FIB_ROUTE_PATH_FLAG_NONE);
2432 * -2 entries (BGP and RR). -1 shared path-list;
2434 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2435 FIB_NODE_INDEX_INVALID),
2436 "200.200.200.201/32 removed");
2437 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32) ==
2438 FIB_NODE_INDEX_INVALID),
2439 "1.1.1.200/32 removed");
2441 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2442 fib_path_list_db_size());
2443 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
2444 fib_path_list_pool_size());
2445 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2446 fib_entry_pool_size());
2449 * remove 200.200.200.200/32 which does have a valid via FIB
2451 fib_table_entry_path_remove(fib_index,
2455 &pfx_1_1_1_2_s_32.fp_addr,
2456 ~0, // no index provided.
2459 FIB_ROUTE_PATH_FLAG_NONE);
2461 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2462 FIB_NODE_INDEX_INVALID),
2463 "200.200.200.200/32 removed");
2464 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32) !=
2465 FIB_NODE_INDEX_INVALID),
2466 "1.1.1.2/32 still present");
2469 * -1 entry (BGP, the RR source is also API sourced). -1 shared path-list;
2471 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2472 fib_path_list_db_size());
2473 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2474 fib_path_list_pool_size());
2475 FIB_TEST((ENBR+9 == fib_entry_pool_size()), "entry pool size is %d",
2476 fib_entry_pool_size());
2479 * A recursive prefix that has a 2 path load-balance.
2480 * It also shares a next-hop with other BGP prefixes and hence
2481 * test the ref counting of RR sourced prefixes and 2 level LB.
2483 const fib_prefix_t bgp_102 = {
2485 .fp_proto = FIB_PROTOCOL_IP4,
2487 /* 100.100.100.101/32 */
2488 .ip4.as_u32 = clib_host_to_net_u32(0x64646466),
2491 fib_table_entry_path_add(fib_index,
2494 FIB_ENTRY_FLAG_NONE,
2496 &pfx_1_1_1_1_s_32.fp_addr,
2497 ~0, // no index provided.
2498 fib_index, // same as route
2501 FIB_ROUTE_PATH_FLAG_NONE);
2502 fib_table_entry_path_add(fib_index,
2505 FIB_ENTRY_FLAG_NONE,
2507 &pfx_1_1_1_2_s_32.fp_addr,
2508 ~0, // no index provided.
2509 fib_index, // same as route's FIB
2512 FIB_ROUTE_PATH_FLAG_NONE);
2513 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2514 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "100.100.100.102/32 presnet");
2515 dpo = fib_entry_contribute_ip_forwarding(fei);
2517 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2518 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2519 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32);
2520 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2522 lb = load_balance_get(dpo->dpoi_index);
2523 FIB_TEST((lb->lb_n_buckets == 2), "Recursive LB has %d bucket", lb->lb_n_buckets);
2524 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2525 "First via 10.10.10.1");
2526 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 1)),
2527 "Second via 10.10.10.1");
2529 fib_table_entry_path_remove(fib_index,
2533 &pfx_1_1_1_1_s_32.fp_addr,
2534 ~0, // no index provided.
2535 fib_index, // same as route's FIB
2537 FIB_ROUTE_PATH_FLAG_NONE);
2538 fib_table_entry_path_remove(fib_index,
2542 &pfx_1_1_1_2_s_32.fp_addr,
2543 ~0, // no index provided.
2544 fib_index, // same as route's FIB
2546 FIB_ROUTE_PATH_FLAG_NONE);
2547 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2548 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "100.100.100.102/32 removed");
2551 * remove the remaining recursives
2553 fib_table_entry_path_remove(fib_index,
2557 &pfx_1_1_1_1_s_32.fp_addr,
2558 ~0, // no index provided.
2559 fib_index, // same as route's FIB
2561 FIB_ROUTE_PATH_FLAG_NONE);
2562 fib_table_entry_path_remove(fib_index,
2566 &pfx_1_1_1_1_s_32.fp_addr,
2567 ~0, // no index provided.
2568 fib_index, // same as route's FIB
2570 FIB_ROUTE_PATH_FLAG_NONE);
2571 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_100_pfx) ==
2572 FIB_NODE_INDEX_INVALID),
2573 "100.100.100.100/32 removed");
2574 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_101_pfx) ==
2575 FIB_NODE_INDEX_INVALID),
2576 "100.100.100.101/32 removed");
2579 * -2 entry (2*BGP, the RR source is also API sourced). -1 shared path-list;
2581 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2582 fib_path_list_db_size());
2583 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2584 fib_path_list_pool_size());
2585 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2586 fib_entry_pool_size());
2589 * Add a recursive route via a connected cover, using an adj-fib that does exist
2591 fib_table_entry_path_add(fib_index,
2594 FIB_ENTRY_FLAG_NONE,
2597 ~0, // no index provided.
2598 fib_index, // Same as route's FIB
2601 FIB_ROUTE_PATH_FLAG_NONE);
2604 * +1 entry. +1 shared path-list (recursive via 10.10.10.1)
2606 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2607 fib_path_list_db_size());
2608 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2609 fib_path_list_pool_size());
2610 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
2611 fib_entry_pool_size());
2613 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2614 dpo = fib_entry_contribute_ip_forwarding(fei);
2616 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
2617 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2619 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2620 "200.200.200.200/32 is recursive via adj for 10.10.10.1");
2622 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
2623 "Flags set on RR via existing attached");
2626 * Add a recursive route via a connected cover, using and adj-fib that does
2629 ip46_address_t nh_10_10_10_3 = {
2630 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
2632 fib_prefix_t pfx_10_10_10_3 = {
2634 .fp_proto = FIB_PROTOCOL_IP4,
2635 .fp_addr = nh_10_10_10_3,
2638 fib_table_entry_path_add(fib_index,
2641 FIB_ENTRY_FLAG_NONE,
2644 ~0, // no index provided.
2648 FIB_ROUTE_PATH_FLAG_NONE);
2651 * +2 entries (BGP and RR). +1 shared path-list (recursive via 10.10.10.3) and
2652 * one unshared non-recursive via 10.10.10.3
2654 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2655 fib_path_list_db_size());
2656 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2657 fib_path_list_pool_size());
2658 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2659 fib_entry_pool_size());
2661 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
2664 tm->hw[0]->sw_if_index);
2666 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2667 dpo = fib_entry_contribute_ip_forwarding(fei);
2668 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3);
2669 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2671 ai = fib_entry_get_adj(fei);
2672 FIB_TEST((ai == ai_03), "adj for 10.10.10.3/32 is via adj for 10.10.10.3");
2673 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
2674 fib_entry_get_flags(fei)),
2675 "Flags set on RR via non-existing attached");
2677 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2678 "adj for 200.200.200.200/32 is recursive via adj for 10.10.10.3");
2683 * remove the recursives
2685 fib_table_entry_path_remove(fib_index,
2690 ~0, // no index provided.
2691 fib_index, // same as route's FIB
2693 FIB_ROUTE_PATH_FLAG_NONE);
2694 fib_table_entry_path_remove(fib_index,
2699 ~0, // no index provided.
2700 fib_index, // same as route's FIB
2702 FIB_ROUTE_PATH_FLAG_NONE);
2704 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2705 FIB_NODE_INDEX_INVALID),
2706 "200.200.200.201/32 removed");
2707 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2708 FIB_NODE_INDEX_INVALID),
2709 "200.200.200.200/32 removed");
2710 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3) ==
2711 FIB_NODE_INDEX_INVALID),
2712 "10.10.10.3/32 removed");
2715 * -3 entries (2*BGP and RR). -2 shared path-list (recursive via 10.10.10.3 &
2716 * 10.10.10.1) and one unshared non-recursive via 10.10.10.3
2718 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2719 fib_path_list_db_size());
2720 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2721 fib_path_list_pool_size());
2722 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2723 fib_entry_pool_size());
2728 * Add 5.5.5.5/32 -> 5.5.5.6/32 -> 5.5.5.7/32 -> 5.5.5.5/32
2730 fib_prefix_t pfx_5_5_5_5_s_32 = {
2732 .fp_proto = FIB_PROTOCOL_IP4,
2734 .ip4.as_u32 = clib_host_to_net_u32(0x05050505),
2737 fib_prefix_t pfx_5_5_5_6_s_32 = {
2739 .fp_proto = FIB_PROTOCOL_IP4,
2741 .ip4.as_u32 = clib_host_to_net_u32(0x05050506),
2744 fib_prefix_t pfx_5_5_5_7_s_32 = {
2746 .fp_proto = FIB_PROTOCOL_IP4,
2748 .ip4.as_u32 = clib_host_to_net_u32(0x05050507),
2752 fib_table_entry_path_add(fib_index,
2755 FIB_ENTRY_FLAG_NONE,
2757 &pfx_5_5_5_6_s_32.fp_addr,
2758 ~0, // no index provided.
2762 FIB_ROUTE_PATH_FLAG_NONE);
2763 fib_table_entry_path_add(fib_index,
2766 FIB_ENTRY_FLAG_NONE,
2768 &pfx_5_5_5_7_s_32.fp_addr,
2769 ~0, // no index provided.
2773 FIB_ROUTE_PATH_FLAG_NONE);
2774 fib_table_entry_path_add(fib_index,
2777 FIB_ENTRY_FLAG_NONE,
2779 &pfx_5_5_5_5_s_32.fp_addr,
2780 ~0, // no index provided.
2784 FIB_ROUTE_PATH_FLAG_NONE);
2786 * +3 entries, +3 shared path-list
2788 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2789 fib_path_list_db_size());
2790 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2791 fib_path_list_pool_size());
2792 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2793 fib_entry_pool_size());
2796 * All the entries have only looped paths, so they are all drop
2798 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2799 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2800 "LB for 5.5.5.7/32 is via adj for DROP");
2801 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2802 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2803 "LB for 5.5.5.5/32 is via adj for DROP");
2804 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2805 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2806 "LB for 5.5.5.6/32 is via adj for DROP");
2809 * provide 5.5.5.6/32 with alternate path.
2810 * this will allow only 5.5.5.6/32 to forward with this path, the others
2811 * are still drop since the loop is still present.
2813 fib_table_entry_path_add(fib_index,
2816 FIB_ENTRY_FLAG_NONE,
2819 tm->hw[0]->sw_if_index,
2823 FIB_ROUTE_PATH_FLAG_NONE);
2825 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2826 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2828 lb = load_balance_get(dpo1->dpoi_index);
2829 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.6 LB has %d bucket", lb->lb_n_buckets);
2831 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2832 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2833 FIB_TEST((ai_01 == dpo2->dpoi_index),
2834 "5.5.5.6 bucket 0 resolves via 10.10.10.2");
2836 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2837 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2838 "LB for 5.5.5.7/32 is via adj for DROP");
2839 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2840 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2841 "LB for 5.5.5.5/32 is via adj for DROP");
2844 * remove the alternate path for 5.5.5.6/32
2847 fib_table_entry_path_remove(fib_index,
2852 tm->hw[0]->sw_if_index,
2855 FIB_ROUTE_PATH_FLAG_NONE);
2857 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2858 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2859 "LB for 5.5.5.7/32 is via adj for DROP");
2860 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2861 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2862 "LB for 5.5.5.5/32 is via adj for DROP");
2863 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2864 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2865 "LB for 5.5.5.6/32 is via adj for DROP");
2868 * break the loop by giving 5.5.5.5/32 a new set of paths
2869 * expect all to forward via this new path.
2871 fib_table_entry_update_one_path(fib_index,
2874 FIB_ENTRY_FLAG_NONE,
2877 tm->hw[0]->sw_if_index,
2878 ~0, // invalid fib index
2881 FIB_ROUTE_PATH_FLAG_NONE);
2883 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2884 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2885 lb = load_balance_get(dpo1->dpoi_index);
2886 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.5 LB has %d bucket", lb->lb_n_buckets);
2888 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2889 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2890 FIB_TEST((ai_01 == dpo2->dpoi_index),
2891 "5.5.5.5 bucket 0 resolves via 10.10.10.2");
2893 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_7_s_32);
2894 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2896 lb = load_balance_get(dpo2->dpoi_index);
2897 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2898 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo2->dpoi_index, 0)),
2899 "5.5.5.5.7 via 5.5.5.5");
2901 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32);
2902 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2904 lb = load_balance_get(dpo1->dpoi_index);
2905 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2906 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2907 "5.5.5.5.6 via 5.5.5.7");
2910 * revert back to the loop. so we can remove the prefixes with
2913 fib_table_entry_update_one_path(fib_index,
2916 FIB_ENTRY_FLAG_NONE,
2918 &pfx_5_5_5_6_s_32.fp_addr,
2919 ~0, // no index provided.
2923 FIB_ROUTE_PATH_FLAG_NONE);
2925 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2926 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2927 "LB for 5.5.5.7/32 is via adj for DROP");
2928 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2929 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2930 "LB for 5.5.5.5/32 is via adj for DROP");
2931 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2932 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2933 "LB for 5.5.5.6/32 is via adj for DROP");
2936 * remove all the 5.5.5.x/32 prefixes
2938 fib_table_entry_path_remove(fib_index,
2942 &pfx_5_5_5_6_s_32.fp_addr,
2943 ~0, // no index provided.
2944 fib_index, // same as route's FIB
2946 FIB_ROUTE_PATH_FLAG_NONE);
2947 fib_table_entry_path_remove(fib_index,
2951 &pfx_5_5_5_7_s_32.fp_addr,
2952 ~0, // no index provided.
2953 fib_index, // same as route's FIB
2955 FIB_ROUTE_PATH_FLAG_NONE);
2956 fib_table_entry_path_remove(fib_index,
2960 &pfx_5_5_5_5_s_32.fp_addr,
2961 ~0, // no index provided.
2962 fib_index, // same as route's FIB
2964 FIB_ROUTE_PATH_FLAG_NONE);
2965 fib_table_entry_path_remove(fib_index,
2970 ~0, // no index provided.
2971 fib_index, // same as route's FIB
2973 FIB_ROUTE_PATH_FLAG_NONE);
2976 * -3 entries, -3 shared path-list
2978 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2979 fib_path_list_db_size());
2980 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2981 fib_path_list_pool_size());
2982 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2983 fib_entry_pool_size());
2986 * Single level loop 5.5.5.5/32 via 5.5.5.5/32
2988 fib_table_entry_path_add(fib_index,
2991 FIB_ENTRY_FLAG_NONE,
2993 &pfx_5_5_5_6_s_32.fp_addr,
2994 ~0, // no index provided.
2998 FIB_ROUTE_PATH_FLAG_NONE);
2999 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
3000 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
3001 "1-level 5.5.5.6/32 loop is via adj for DROP");
3003 fib_table_entry_path_remove(fib_index,
3007 &pfx_5_5_5_6_s_32.fp_addr,
3008 ~0, // no index provided.
3009 fib_index, // same as route's FIB
3011 FIB_ROUTE_PATH_FLAG_NONE);
3012 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3013 fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32),
3014 "1-level 5.5.5.6/32 loop is removed");
3017 * A recursive route whose next-hop is covered by the prefix.
3018 * This would mean the via-fib, which inherits forwarding from its
3019 * cover, thus picks up forwarding from the prfix, which is via the
3020 * via-fib, and we have a loop.
3022 fib_prefix_t pfx_23_23_23_0_s_24 = {
3024 .fp_proto = FIB_PROTOCOL_IP4,
3026 .ip4.as_u32 = clib_host_to_net_u32(0x17171700),
3029 fib_prefix_t pfx_23_23_23_23_s_32 = {
3031 .fp_proto = FIB_PROTOCOL_IP4,
3033 .ip4.as_u32 = clib_host_to_net_u32(0x17171717),
3036 fei = fib_table_entry_path_add(fib_index,
3037 &pfx_23_23_23_0_s_24,
3039 FIB_ENTRY_FLAG_NONE,
3041 &pfx_23_23_23_23_s_32.fp_addr,
3046 FIB_ROUTE_PATH_FLAG_NONE);
3047 dpo = fib_entry_contribute_ip_forwarding(fei);
3048 FIB_TEST(load_balance_is_drop(dpo),
3049 "23.23.23.0/24 via covered is DROP");
3050 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3053 * add-remove test. no change.
3055 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3056 fib_path_list_db_size());
3057 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3058 fib_path_list_pool_size());
3059 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3060 fib_entry_pool_size());
3063 * Make the default route recursive via a unknown next-hop. Thus the
3064 * next hop's cover would be the default route
3066 fei = fib_table_entry_path_add(fib_index,
3069 FIB_ENTRY_FLAG_NONE,
3071 &pfx_23_23_23_23_s_32.fp_addr,
3076 FIB_ROUTE_PATH_FLAG_NONE);
3077 dpo = fib_entry_contribute_ip_forwarding(fei);
3078 FIB_TEST(load_balance_is_drop(dpo),
3079 "0.0.0.0.0/0 via is DROP");
3080 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3081 "no resolving interface for looped 0.0.0.0/0");
3083 fei = fib_table_lookup_exact_match(fib_index, &pfx_23_23_23_23_s_32);
3084 dpo = fib_entry_contribute_ip_forwarding(fei);
3085 FIB_TEST(load_balance_is_drop(dpo),
3086 "23.23.23.23/32 via is DROP");
3087 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3088 "no resolving interface for looped 23.23.23.23/32");
3090 fib_table_entry_delete(fib_index, &pfx_0_0_0_0_s_0, FIB_SOURCE_API);
3093 * A recursive route with recursion constraints.
3094 * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained
3096 fib_table_entry_path_add(fib_index,
3099 FIB_ENTRY_FLAG_NONE,
3106 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3108 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3109 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3111 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3112 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3114 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3115 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3118 * save the load-balance. we expect it to be inplace modified
3120 lb = load_balance_get(dpo1->dpoi_index);
3123 * add a covering prefix for the via fib that would otherwise serve
3124 * as the resolving route when the host is removed
3126 fib_table_entry_path_add(fib_index,
3129 FIB_ENTRY_FLAG_NONE,
3132 tm->hw[0]->sw_if_index,
3133 ~0, // invalid fib index
3136 FIB_ROUTE_PATH_FLAG_NONE);
3137 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28);
3138 ai = fib_entry_get_adj(fei);
3139 FIB_TEST((ai == ai_01),
3140 "adj for 1.1.1.0/28 is via adj for 1.1.1.1");
3143 * remove the host via FIB - expect the BGP prefix to be drop
3145 fib_table_entry_path_remove(fib_index,
3150 tm->hw[0]->sw_if_index,
3151 ~0, // invalid fib index
3153 FIB_ROUTE_PATH_FLAG_NONE);
3155 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3156 "adj for 200.200.200.200/32 is recursive via adj for DROP");
3159 * add the via-entry host reoute back. expect to resolve again
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 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3173 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3176 * add another path for the recursive. it will then have 2.
3178 fib_prefix_t pfx_1_1_1_3_s_32 = {
3180 .fp_proto = FIB_PROTOCOL_IP4,
3182 .ip4.as_u32 = clib_host_to_net_u32(0x01010103),
3185 fib_table_entry_path_add(fib_index,
3188 FIB_ENTRY_FLAG_NONE,
3191 tm->hw[0]->sw_if_index,
3192 ~0, // invalid fib index
3195 FIB_ROUTE_PATH_FLAG_NONE);
3197 fib_table_entry_path_add(fib_index,
3200 FIB_ENTRY_FLAG_NONE,
3202 &pfx_1_1_1_3_s_32.fp_addr,
3207 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3210 * add a bunch load more entries using this path combo so that we get
3211 * an LB-map created.
3214 fib_prefix_t bgp_78s[N_P];
3215 for (ii = 0; ii < N_P; ii++)
3217 bgp_78s[ii].fp_len = 32;
3218 bgp_78s[ii].fp_proto = FIB_PROTOCOL_IP4;
3219 bgp_78s[ii].fp_addr.ip4.as_u32 = clib_host_to_net_u32(0x4e000000+ii);
3222 fib_table_entry_path_add(fib_index,
3225 FIB_ENTRY_FLAG_NONE,
3227 &pfx_1_1_1_3_s_32.fp_addr,
3232 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3233 fib_table_entry_path_add(fib_index,
3236 FIB_ENTRY_FLAG_NONE,
3243 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3246 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3247 dpo = fib_entry_contribute_ip_forwarding(fei);
3249 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3250 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3251 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)),
3252 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3253 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32);
3254 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3255 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)),
3256 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3");
3259 * expect the lb-map used by the recursive's load-balance is using both buckets
3261 load_balance_map_t *lbm;
3264 lb = load_balance_get(dpo->dpoi_index);
3266 load_balance_map_lock(lbmi);
3267 lbm = load_balance_map_get(lbmi);
3269 FIB_TEST(lbm->lbm_buckets[0] == 0,
3270 "LB maps's bucket 0 is %d",
3271 lbm->lbm_buckets[0]);
3272 FIB_TEST(lbm->lbm_buckets[1] == 1,
3273 "LB maps's bucket 1 is %d",
3274 lbm->lbm_buckets[1]);
3277 * withdraw one of the /32 via-entrys.
3278 * that ECMP path will be unresolved and forwarding should continue on the
3279 * other available path. this is an iBGP PIC edge failover.
3280 * Test the forwarding changes without re-fetching the adj from the
3281 * recursive entry. this ensures its the same one that is updated; i.e. an
3284 fib_table_entry_path_remove(fib_index,
3289 tm->hw[0]->sw_if_index,
3290 ~0, // invalid fib index
3292 FIB_ROUTE_PATH_FLAG_NONE);
3294 /* suspend so the update walk kicks int */
3295 vlib_process_suspend(vlib_get_main(), 1e-5);
3297 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3298 FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)),
3299 "post PIC 200.200.200.200/32 was inplace modified");
3301 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)),
3302 "post PIC adj for 200.200.200.200/32 is recursive"
3303 " via adj for 1.1.1.3");
3306 * the LB maps that was locked above should have been modified to remove
3307 * the path that was down, and thus its bucket points to a path that is
3310 FIB_TEST(lbm->lbm_buckets[0] == 1,
3311 "LB maps's bucket 0 is %d",
3312 lbm->lbm_buckets[0]);
3313 FIB_TEST(lbm->lbm_buckets[1] == 1,
3314 "LB maps's bucket 1 is %d",
3315 lbm->lbm_buckets[1]);
3317 load_balance_map_unlock(lbmi);
3320 * add it back. again
3322 fib_table_entry_path_add(fib_index,
3325 FIB_ENTRY_FLAG_NONE,
3328 tm->hw[0]->sw_if_index,
3329 ~0, // invalid fib index
3332 FIB_ROUTE_PATH_FLAG_NONE);
3334 /* suspend so the update walk kicks in */
3335 vlib_process_suspend(vlib_get_main(), 1e-5);
3337 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)),
3338 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3339 "via adj for 1.1.1.1");
3340 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)),
3341 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3342 "via adj for 1.1.1.3");
3344 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3345 dpo = fib_entry_contribute_ip_forwarding(fei);
3346 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3347 "post PIC 200.200.200.200/32 was inplace modified");
3350 * add a 3rd path. this makes the LB 16 buckets.
3352 fib_table_entry_path_add(fib_index,
3355 FIB_ENTRY_FLAG_NONE,
3357 &pfx_1_1_1_2_s_32.fp_addr,
3362 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3363 for (ii = 0; ii < N_P; ii++)
3365 fib_table_entry_path_add(fib_index,
3368 FIB_ENTRY_FLAG_NONE,
3370 &pfx_1_1_1_2_s_32.fp_addr,
3375 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3378 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3379 dpo = fib_entry_contribute_ip_forwarding(fei);
3380 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3381 "200.200.200.200/32 was inplace modified for 3rd path");
3382 FIB_TEST(16 == lb->lb_n_buckets,
3383 "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets");
3386 load_balance_map_lock(lbmi);
3387 lbm = load_balance_map_get(lbmi);
3389 for (ii = 0; ii < 16; ii++)
3391 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3392 "LB Map for 200.200.200.200/32 at %d is %d",
3393 ii, lbm->lbm_buckets[ii]);
3397 * trigger PIC by removing the first via-entry
3398 * the first 6 buckets of the map should map to the next 6
3400 fib_table_entry_path_remove(fib_index,
3405 tm->hw[0]->sw_if_index,
3408 FIB_ROUTE_PATH_FLAG_NONE);
3409 /* suspend so the update walk kicks int */
3410 vlib_process_suspend(vlib_get_main(), 1e-5);
3412 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3413 dpo = fib_entry_contribute_ip_forwarding(fei);
3414 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3415 "200.200.200.200/32 was inplace modified for 3rd path");
3416 FIB_TEST(2 == lb->lb_n_buckets,
3417 "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets");
3419 for (ii = 0; ii < 6; ii++)
3421 FIB_TEST(lbm->lbm_buckets[ii] == ii+6,
3422 "LB Map for 200.200.200.200/32 at %d is %d",
3423 ii, lbm->lbm_buckets[ii]);
3425 for (ii = 6; ii < 16; ii++)
3427 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3428 "LB Map for 200.200.200.200/32 at %d is %d",
3429 ii, lbm->lbm_buckets[ii]);
3431 load_balance_map_unlock(lbmi);
3436 fib_table_entry_path_add(fib_index,
3439 FIB_ENTRY_FLAG_NONE,
3442 tm->hw[0]->sw_if_index,
3446 FIB_ROUTE_PATH_FLAG_NONE);
3448 for (ii = 0; ii < N_P; ii++)
3450 fib_table_entry_delete(fib_index,
3453 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3454 fib_table_lookup_exact_match(fib_index, &bgp_78s[ii])),
3456 format_fib_prefix, &bgp_78s[ii]);
3458 fib_table_entry_path_remove(fib_index,
3462 &pfx_1_1_1_2_s_32.fp_addr,
3466 MPLS_LABEL_INVALID);
3467 fib_table_entry_path_remove(fib_index,
3475 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3476 fib_table_entry_path_remove(fib_index,
3480 &pfx_1_1_1_3_s_32.fp_addr,
3484 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3485 fib_table_entry_delete(fib_index,
3488 fib_table_entry_delete(fib_index,
3491 /* suspend so the update walk kicks int */
3492 vlib_process_suspend(vlib_get_main(), 1e-5);
3493 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3494 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)),
3495 "1.1.1.1/28 removed");
3496 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3497 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)),
3498 "1.1.1.3/32 removed");
3499 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3500 fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)),
3501 "200.200.200.200/32 removed");
3504 * add-remove test. no change.
3506 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3507 fib_path_list_db_size());
3508 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3509 fib_path_list_pool_size());
3510 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3511 fib_entry_pool_size());
3514 * A route whose paths are built up iteratively and then removed
3517 fib_prefix_t pfx_4_4_4_4_s_32 = {
3519 .fp_proto = FIB_PROTOCOL_IP4,
3522 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
3526 fib_table_entry_path_add(fib_index,
3529 FIB_ENTRY_FLAG_NONE,
3532 tm->hw[0]->sw_if_index,
3536 FIB_ROUTE_PATH_FLAG_NONE);
3537 fib_table_entry_path_add(fib_index,
3540 FIB_ENTRY_FLAG_NONE,
3543 tm->hw[0]->sw_if_index,
3547 FIB_ROUTE_PATH_FLAG_NONE);
3548 fib_table_entry_path_add(fib_index,
3551 FIB_ENTRY_FLAG_NONE,
3554 tm->hw[0]->sw_if_index,
3558 FIB_ROUTE_PATH_FLAG_NONE);
3559 FIB_TEST(FIB_NODE_INDEX_INVALID !=
3560 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3561 "4.4.4.4/32 present");
3563 fib_table_entry_delete(fib_index,
3566 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3567 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3568 "4.4.4.4/32 removed");
3571 * add-remove test. no change.
3573 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3574 fib_path_list_db_size());
3575 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3576 fib_path_list_pool_size());
3577 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3578 fib_entry_pool_size());
3581 * A route with multiple paths at once
3583 fib_route_path_t *r_paths = NULL;
3585 for (ii = 0; ii < 4; ii++)
3587 fib_route_path_t r_path = {
3588 .frp_proto = DPO_PROTO_IP4,
3590 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
3592 .frp_sw_if_index = tm->hw[0]->sw_if_index,
3594 .frp_fib_index = ~0,
3596 vec_add1(r_paths, r_path);
3599 fib_table_entry_update(fib_index,
3602 FIB_ENTRY_FLAG_NONE,
3605 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3606 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3607 dpo = fib_entry_contribute_ip_forwarding(fei);
3609 lb = load_balance_get(dpo->dpoi_index);
3610 FIB_TEST((lb->lb_n_buckets == 4), "4.4.4.4/32 lb over %d paths", lb->lb_n_buckets);
3612 fib_table_entry_delete(fib_index,
3615 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3616 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3617 "4.4.4.4/32 removed");
3621 * add-remove test. no change.
3623 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3624 fib_path_list_db_size());
3625 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3626 fib_path_list_pool_size());
3627 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3628 fib_entry_pool_size());
3631 * A route deag route
3633 fib_table_entry_path_add(fib_index,
3636 FIB_ENTRY_FLAG_NONE,
3643 FIB_ROUTE_PATH_FLAG_NONE);
3645 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3646 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3648 dpo = fib_entry_contribute_ip_forwarding(fei);
3649 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3650 lookup_dpo_t *lkd = lookup_dpo_get(dpo->dpoi_index);
3652 FIB_TEST((fib_index == lkd->lkd_fib_index),
3653 "4.4.4.4/32 is deag in %d %U",
3655 format_dpo_id, dpo, 0);
3656 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
3657 "4.4.4.4/32 is source deag in %d %U",
3659 format_dpo_id, dpo, 0);
3661 fib_table_entry_delete(fib_index,
3664 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3665 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3666 "4.4.4.4/32 removed");
3670 * A route deag route in a source lookup table
3672 fib_table_entry_path_add(fib_index,
3675 FIB_ENTRY_FLAG_NONE,
3682 FIB_ROUTE_PATH_SOURCE_LOOKUP);
3684 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3685 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3687 dpo = fib_entry_contribute_ip_forwarding(fei);
3688 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3689 lkd = lookup_dpo_get(dpo->dpoi_index);
3691 FIB_TEST((fib_index == lkd->lkd_fib_index),
3692 "4.4.4.4/32 is deag in %d %U",
3694 format_dpo_id, dpo, 0);
3695 FIB_TEST((LOOKUP_INPUT_SRC_ADDR == lkd->lkd_input),
3696 "4.4.4.4/32 is source deag in %d %U",
3698 format_dpo_id, dpo, 0);
3700 fib_table_entry_delete(fib_index,
3703 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3704 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3705 "4.4.4.4/32 removed");
3709 * add-remove test. no change.
3711 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3712 fib_path_list_db_size());
3713 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3714 fib_path_list_pool_size());
3715 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3716 fib_entry_pool_size());
3720 * add a recursive with duplicate paths. Expect the duplicate to be ignored.
3722 fib_prefix_t pfx_34_1_1_1_s_32 = {
3724 .fp_proto = FIB_PROTOCOL_IP4,
3726 .ip4.as_u32 = clib_host_to_net_u32(0x22010101),
3729 fib_prefix_t pfx_34_34_1_1_s_32 = {
3731 .fp_proto = FIB_PROTOCOL_IP4,
3733 .ip4.as_u32 = clib_host_to_net_u32(0x22220101),
3736 fei = fib_table_entry_path_add(fib_index,
3737 &pfx_34_34_1_1_s_32,
3739 FIB_ENTRY_FLAG_NONE,
3742 tm->hw[0]->sw_if_index,
3746 FIB_ROUTE_PATH_FLAG_NONE);
3747 fei = fib_table_entry_path_add(fib_index,
3750 FIB_ENTRY_FLAG_NONE,
3752 &pfx_34_34_1_1_s_32.fp_addr,
3757 FIB_ROUTE_PATH_FLAG_NONE);
3758 fei = fib_table_entry_path_add(fib_index,
3761 FIB_ENTRY_FLAG_NONE,
3763 &pfx_34_34_1_1_s_32.fp_addr,
3768 FIB_ROUTE_PATH_FLAG_NONE);
3769 FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0);
3770 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3771 fib_table_entry_delete(fib_index,
3772 &pfx_34_34_1_1_s_32,
3777 * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32
3778 * all of which are via 10.10.10.1, Itf1
3780 fib_table_entry_path_remove(fib_index,
3785 tm->hw[0]->sw_if_index,
3788 FIB_ROUTE_PATH_FLAG_NONE);
3789 fib_table_entry_path_remove(fib_index,
3794 tm->hw[0]->sw_if_index,
3797 FIB_ROUTE_PATH_FLAG_NONE);
3798 fib_table_entry_path_remove(fib_index,
3803 tm->hw[0]->sw_if_index,
3806 FIB_ROUTE_PATH_FLAG_NONE);
3808 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3809 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32),
3810 "1.1.1.1/32 removed");
3811 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3812 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32),
3813 "1.1.1.2/32 removed");
3814 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3815 fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24),
3816 "1.1.2.0/24 removed");
3819 * -3 entries and -1 shared path-list
3821 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3822 fib_path_list_db_size());
3823 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3824 fib_path_list_pool_size());
3825 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3826 fib_entry_pool_size());
3829 * An attached-host route. Expect to link to the incomplete adj
3831 fib_prefix_t pfx_4_1_1_1_s_32 = {
3833 .fp_proto = FIB_PROTOCOL_IP4,
3836 .ip4.as_u32 = clib_host_to_net_u32(0x04010101),
3839 fib_table_entry_path_add(fib_index,
3842 FIB_ENTRY_FLAG_NONE,
3845 tm->hw[0]->sw_if_index,
3849 FIB_ROUTE_PATH_FLAG_NONE);
3851 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32);
3852 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present");
3853 ai = fib_entry_get_adj(fei);
3855 ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
3857 &pfx_4_1_1_1_s_32.fp_addr,
3858 tm->hw[0]->sw_if_index);
3859 FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ");
3863 * +1 entry and +1 shared path-list
3865 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3866 fib_path_list_db_size());
3867 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3868 fib_path_list_pool_size());
3869 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
3870 fib_entry_pool_size());
3872 fib_table_entry_delete(fib_index,
3876 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3877 fib_path_list_db_size());
3878 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3879 fib_path_list_pool_size());
3880 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3881 fib_entry_pool_size());
3884 * add a v6 prefix via v4 next-hops
3886 fib_prefix_t pfx_2001_s_64 = {
3888 .fp_proto = FIB_PROTOCOL_IP6,
3890 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
3893 fei = fib_table_entry_path_add(0, //default v6 table
3896 FIB_ENTRY_FLAG_NONE,
3899 tm->hw[0]->sw_if_index,
3903 FIB_ROUTE_PATH_FLAG_NONE);
3905 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
3906 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present");
3907 ai = fib_entry_get_adj(fei);
3909 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
3910 "2001::/64 via ARP-adj");
3911 FIB_TEST((adj->ia_link == VNET_LINK_IP6),
3912 "2001::/64 is link type v6");
3913 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4),
3914 "2001::/64 ADJ-adj is NH proto v4");
3915 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
3918 * add a uRPF exempt prefix:
3920 * - it's forwarding is drop
3921 * - it's uRPF list is not empty
3922 * - the uRPF list for the default route (it's cover) is empty
3924 fei = fib_table_entry_special_add(fib_index,
3926 FIB_SOURCE_URPF_EXEMPT,
3927 FIB_ENTRY_FLAG_DROP);
3928 dpo = fib_entry_contribute_ip_forwarding(fei);
3929 FIB_TEST(load_balance_is_drop(dpo),
3930 "uRPF exempt 4.1.1.1/32 DROP");
3931 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0),
3932 "uRPF list for exempt prefix has itf index 0");
3933 fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0);
3934 FIB_TEST(!fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
3935 "uRPF list for 0.0.0.0/0 empty");
3937 fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
3940 * An adj-fib that fails the refinement criteria - no connected cover
3942 fib_prefix_t pfx_12_10_10_2_s_32 = {
3944 .fp_proto = FIB_PROTOCOL_IP4,
3947 .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02),
3951 fib_table_entry_path_add(fib_index,
3952 &pfx_12_10_10_2_s_32,
3954 FIB_ENTRY_FLAG_ATTACHED,
3956 &pfx_12_10_10_2_s_32.fp_addr,
3957 tm->hw[0]->sw_if_index,
3958 ~0, // invalid fib index
3961 FIB_ROUTE_PATH_FLAG_NONE);
3963 fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32);
3964 dpo = fib_entry_contribute_ip_forwarding(fei);
3965 FIB_TEST(dpo_is_drop(dpo),
3966 "no connected cover adj-fib fails refinement: %U",
3967 format_dpo_id, dpo, 0);
3969 fib_table_entry_delete(fib_index,
3970 &pfx_12_10_10_2_s_32,
3974 * An adj-fib that fails the refinement criteria - cover is connected
3975 * but on a different interface
3977 fib_prefix_t pfx_10_10_10_127_s_32 = {
3979 .fp_proto = FIB_PROTOCOL_IP4,
3982 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f),
3986 fib_table_entry_path_add(fib_index,
3987 &pfx_10_10_10_127_s_32,
3989 FIB_ENTRY_FLAG_ATTACHED,
3991 &pfx_10_10_10_127_s_32.fp_addr,
3992 tm->hw[1]->sw_if_index,
3993 ~0, // invalid fib index
3996 FIB_ROUTE_PATH_FLAG_NONE);
3998 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32);
3999 dpo = fib_entry_contribute_ip_forwarding(fei);
4000 FIB_TEST(dpo_is_drop(dpo),
4001 "wrong interface adj-fib fails refinement");
4003 fib_table_entry_delete(fib_index,
4004 &pfx_10_10_10_127_s_32,
4008 * add a second path to an adj-fib
4009 * this is a sumiluation of another ARP entry created
4010 * on an interface on which the connected prefix does not exist.
4011 * The second path fails refinement. Expect to forward through the
4014 fib_prefix_t pfx_10_10_10_3_s_32 = {
4016 .fp_proto = FIB_PROTOCOL_IP4,
4019 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
4023 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
4026 tm->hw[0]->sw_if_index);
4028 fib_test_lb_bucket_t ip_o_10_10_10_3 = {
4034 fei = fib_table_entry_path_add(fib_index,
4035 &pfx_10_10_10_3_s_32,
4037 FIB_ENTRY_FLAG_NONE,
4040 tm->hw[0]->sw_if_index,
4044 FIB_ROUTE_PATH_FLAG_NONE);
4045 fei = fib_table_entry_path_add(fib_index,
4046 &pfx_10_10_10_3_s_32,
4048 FIB_ENTRY_FLAG_NONE,
4051 tm->hw[1]->sw_if_index,
4055 FIB_ROUTE_PATH_FLAG_NONE);
4056 FIB_TEST(!fib_test_validate_entry(fei,
4057 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4060 "10.10.10.3 via 10.10.10.3/Eth0 only");
4063 * remove the path that refines the cover, should go unresolved
4065 fib_table_entry_path_remove(fib_index,
4066 &pfx_10_10_10_3_s_32,
4070 tm->hw[0]->sw_if_index,
4073 FIB_ROUTE_PATH_FLAG_NONE);
4074 dpo = fib_entry_contribute_ip_forwarding(fei);
4075 FIB_TEST(dpo_is_drop(dpo),
4076 "wrong interface adj-fib fails refinement");
4079 * add back the path that refines the cover
4081 fei = fib_table_entry_path_add(fib_index,
4082 &pfx_10_10_10_3_s_32,
4084 FIB_ENTRY_FLAG_NONE,
4087 tm->hw[0]->sw_if_index,
4091 FIB_ROUTE_PATH_FLAG_NONE);
4092 FIB_TEST(!fib_test_validate_entry(fei,
4093 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4096 "10.10.10.3 via 10.10.10.3/Eth0 only");
4099 * remove the path that does not refine the cover
4101 fib_table_entry_path_remove(fib_index,
4102 &pfx_10_10_10_3_s_32,
4106 tm->hw[1]->sw_if_index,
4109 FIB_ROUTE_PATH_FLAG_NONE);
4110 FIB_TEST(!fib_test_validate_entry(fei,
4111 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4114 "10.10.10.3 via 10.10.10.3/Eth0 only");
4117 * remove the path that does refine, it's the last path, so
4118 * the entry should be gone
4120 fib_table_entry_path_remove(fib_index,
4121 &pfx_10_10_10_3_s_32,
4125 tm->hw[0]->sw_if_index,
4128 FIB_ROUTE_PATH_FLAG_NONE);
4129 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
4130 FIB_TEST((fei == FIB_NODE_INDEX_INVALID), "10.10.10.3 gone");
4135 * change the table's flow-hash config - expect the update to propagete to
4136 * the entries' load-balance objects
4138 flow_hash_config_t old_hash_config, new_hash_config;
4140 old_hash_config = fib_table_get_flow_hash_config(fib_index,
4142 new_hash_config = (IP_FLOW_HASH_SRC_ADDR |
4143 IP_FLOW_HASH_DST_ADDR);
4145 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
4146 dpo = fib_entry_contribute_ip_forwarding(fei);
4147 lb = load_balance_get(dpo->dpoi_index);
4148 FIB_TEST((lb->lb_hash_config == old_hash_config),
4149 "Table and LB hash config match: %U",
4150 format_ip_flow_hash_config, lb->lb_hash_config);
4152 fib_table_set_flow_hash_config(fib_index, FIB_PROTOCOL_IP4, new_hash_config);
4154 FIB_TEST((lb->lb_hash_config == new_hash_config),
4155 "Table and LB newhash config match: %U",
4156 format_ip_flow_hash_config, lb->lb_hash_config);
4159 * A route via DVR DPO
4161 fei = fib_table_entry_path_add(fib_index,
4162 &pfx_10_10_10_3_s_32,
4164 FIB_ENTRY_FLAG_NONE,
4167 tm->hw[0]->sw_if_index,
4171 FIB_ROUTE_PATH_DVR);
4172 dpo_id_t dvr_dpo = DPO_INVALID;
4173 dvr_dpo_add_or_lock(tm->hw[0]->sw_if_index, DPO_PROTO_IP4, &dvr_dpo);
4174 fib_test_lb_bucket_t ip_o_l2 = {
4177 .adj = dvr_dpo.dpoi_index,
4181 FIB_TEST(!fib_test_validate_entry(fei,
4182 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4185 "10.10.10.3 via L2 on Eth0");
4186 fib_table_entry_path_remove(fib_index,
4187 &pfx_10_10_10_3_s_32,
4191 tm->hw[0]->sw_if_index,
4194 FIB_ROUTE_PATH_DVR);
4195 dpo_reset(&dvr_dpo);
4198 * add the default route via a next-hop that will form a loop
4200 fib_prefix_t pfx_conn = {
4202 .fp_proto = FIB_PROTOCOL_IP4,
4205 .ip4.as_u32 = clib_host_to_net_u32(0x1e1e1e1e),
4209 dfrt = fib_table_entry_path_add(fib_index,
4212 FIB_ENTRY_FLAG_NONE,
4219 FIB_ROUTE_PATH_FLAG_NONE);
4221 * the default route is a drop, since it's looped
4223 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4224 "Default route is DROP");
4227 * add a connected cover for the next-hop, this breaks the recursion loop
4228 * for the default route
4230 fib_table_entry_path_add(fib_index,
4233 (FIB_ENTRY_FLAG_CONNECTED |
4234 FIB_ENTRY_FLAG_ATTACHED),
4237 tm->hw[0]->sw_if_index,
4241 FIB_ROUTE_PATH_FLAG_NONE);
4242 pfx_conn.fp_len = 32;
4243 fei = fib_table_lookup_exact_match(fib_index, &pfx_conn);
4245 u32 ai_30 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
4248 tm->hw[0]->sw_if_index);
4250 fib_test_lb_bucket_t ip_o_30_30_30_30 = {
4256 FIB_TEST(!fib_test_validate_entry(fei,
4257 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4260 "30.30.30.30 via adj");
4261 FIB_TEST_REC_FORW(&pfx_0_0_0_0_s_0, &pfx_conn, 0);
4263 pfx_conn.fp_len = 24;
4264 fib_table_entry_delete(fib_index,
4267 fib_table_entry_delete(fib_index,
4276 fib_table_entry_delete(fib_index,
4277 &pfx_10_10_10_1_s_32,
4279 fib_table_entry_delete(fib_index,
4280 &pfx_10_10_10_2_s_32,
4282 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4283 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32),
4284 "10.10.10.1/32 adj-fib removed");
4285 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4286 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32),
4287 "10.10.10.2/32 adj-fib removed");
4290 * -2 entries and -2 non-shared path-list
4292 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4293 fib_path_list_db_size());
4294 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
4295 fib_path_list_pool_size());
4296 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
4297 fib_entry_pool_size());
4300 * unlock the adjacencies for which this test provided a rewrite.
4301 * These are the last locks on these adjs. they should thus go away.
4305 adj_unlock(ai_12_12_12_12);
4307 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4312 * remove the interface prefixes
4314 local_pfx.fp_len = 32;
4315 fib_table_entry_special_remove(fib_index, &local_pfx,
4316 FIB_SOURCE_INTERFACE);
4317 fei = fib_table_lookup(fib_index, &local_pfx);
4319 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4320 fib_table_lookup_exact_match(fib_index, &local_pfx),
4321 "10.10.10.10/32 adj-fib removed");
4323 local_pfx.fp_len = 24;
4324 fib_table_entry_delete(fib_index, &local_pfx,
4325 FIB_SOURCE_INTERFACE);
4327 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4328 fib_table_lookup_exact_match(fib_index, &local_pfx),
4329 "10.10.10.10/24 adj-fib removed");
4332 * -2 entries and -2 non-shared path-list
4334 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4335 fib_path_list_db_size());
4336 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
4337 fib_path_list_pool_size());
4338 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
4339 fib_entry_pool_size());
4342 * Last but not least, remove the VRF
4344 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4347 "NO API Source'd prefixes");
4348 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4351 "NO RR Source'd prefixes");
4352 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4354 FIB_SOURCE_INTERFACE)),
4355 "NO INterface Source'd prefixes");
4357 fib_table_unlock(fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
4359 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4360 fib_path_list_db_size());
4361 FIB_TEST((PNBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
4362 fib_path_list_pool_size());
4363 FIB_TEST((ENBR-5 == fib_entry_pool_size()), "entry pool size is %d",
4364 fib_entry_pool_size());
4365 FIB_TEST((ENBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
4366 pool_elts(fib_urpf_list_pool));
4367 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
4368 pool_elts(load_balance_map_pool));
4369 FIB_TEST((lb_count == pool_elts(load_balance_pool)), "LB pool size is %d",
4370 pool_elts(load_balance_pool));
4371 FIB_TEST((0 == pool_elts(dvr_dpo_pool)), "L2 DPO pool size is %d",
4372 pool_elts(dvr_dpo_pool));
4381 * In the default table check for the presence and correct forwarding
4382 * of the special entries
4384 fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02;
4385 const dpo_id_t *dpo, *dpo_drop;
4386 const ip_adjacency_t *adj;
4387 const receive_dpo_t *rd;
4393 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4396 /* via 2001:0:0:1::2 */
4397 ip46_address_t nh_2001_2 = {
4400 [0] = clib_host_to_net_u64(0x2001000000000001),
4401 [1] = clib_host_to_net_u64(0x0000000000000002),
4408 dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
4410 /* Find or create FIB table 11 */
4411 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11,
4414 for (ii = 0; ii < 4; ii++)
4416 ip6_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
4419 fib_prefix_t pfx_0_0 = {
4421 .fp_proto = FIB_PROTOCOL_IP6,
4429 dfrt = fib_table_lookup(fib_index, &pfx_0_0);
4430 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
4431 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4432 "Default route is DROP");
4434 dpo = fib_entry_contribute_ip_forwarding(dfrt);
4435 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4437 &pfx_0_0.fp_addr.ip6)),
4438 "default-route; fwd and non-fwd tables match");
4440 // FIXME - check specials.
4443 * At this stage there is one v4 FIB with 5 routes and two v6 FIBs
4444 * each with 2 entries and a v6 mfib with 4 path-lists and v4 mfib with 2.
4445 * All entries are special so no path-list sharing.
4448 u32 PNPS = (5+4+4+2);
4450 * if the IGMP plugin is loaded this adds two more entries to the v4 MFIB
4452 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
4453 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is %d",
4454 fib_path_list_pool_size());
4455 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
4456 fib_entry_pool_size());
4459 * add interface routes.
4460 * validate presence of /64 attached and /128 recieve.
4461 * test for the presence of the receive address in the glean and local adj
4463 * receive on 2001:0:0:1::1/128
4465 fib_prefix_t local_pfx = {
4467 .fp_proto = FIB_PROTOCOL_IP6,
4471 [0] = clib_host_to_net_u64(0x2001000000000001),
4472 [1] = clib_host_to_net_u64(0x0000000000000001),
4478 fib_table_entry_update_one_path(fib_index, &local_pfx,
4479 FIB_SOURCE_INTERFACE,
4480 (FIB_ENTRY_FLAG_CONNECTED |
4481 FIB_ENTRY_FLAG_ATTACHED),
4484 tm->hw[0]->sw_if_index,
4488 FIB_ROUTE_PATH_FLAG_NONE);
4489 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4491 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4493 ai = fib_entry_get_adj(fei);
4494 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
4496 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4497 "attached interface adj is glean");
4498 dpo = fib_entry_contribute_ip_forwarding(fei);
4499 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4501 &local_pfx.fp_addr.ip6)),
4502 "attached-route; fwd and non-fwd tables match");
4504 local_pfx.fp_len = 128;
4505 fib_table_entry_update_one_path(fib_index, &local_pfx,
4506 FIB_SOURCE_INTERFACE,
4507 (FIB_ENTRY_FLAG_CONNECTED |
4508 FIB_ENTRY_FLAG_LOCAL),
4511 tm->hw[0]->sw_if_index,
4512 ~0, // invalid fib index
4515 FIB_ROUTE_PATH_FLAG_NONE);
4516 fei = fib_table_lookup(fib_index, &local_pfx);
4518 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4520 dpo = fib_entry_contribute_ip_forwarding(fei);
4521 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4522 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4523 "local interface adj is local");
4524 rd = receive_dpo_get(dpo->dpoi_index);
4526 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4528 "local interface adj is receive ok");
4530 dpo = fib_entry_contribute_ip_forwarding(fei);
4531 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4533 &local_pfx.fp_addr.ip6)),
4534 "local-route; fwd and non-fwd tables match");
4535 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4536 &adj->sub_type.glean.rx_pfx.fp_addr)),
4537 "attached interface adj is receive ok");
4540 * +2 entries. +2 unshared path-lists
4542 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
4543 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
4544 fib_path_list_pool_size());
4545 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4546 fib_entry_pool_size());
4549 * Modify the default route to be via an adj not yet known.
4550 * this sources the defalut route with the API source, which is
4551 * a higher preference to the DEFAULT_ROUTE source
4553 fib_table_entry_path_add(fib_index, &pfx_0_0,
4555 FIB_ENTRY_FLAG_NONE,
4558 tm->hw[0]->sw_if_index,
4562 FIB_ROUTE_PATH_FLAG_NONE);
4563 fei = fib_table_lookup(fib_index, &pfx_0_0);
4565 FIB_TEST((fei == dfrt), "default route same index");
4566 ai = fib_entry_get_adj(fei);
4567 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
4569 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4570 "adj is incomplete");
4571 FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)),
4572 "adj nbr next-hop ok");
4575 * find the adj in the shared db
4577 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4580 tm->hw[0]->sw_if_index);
4581 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
4582 adj_unlock(locked_ai);
4585 * no more entries. +1 shared path-list
4587 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4588 fib_path_list_db_size());
4589 FIB_TEST((PNPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
4590 fib_path_list_pool_size());
4591 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4592 fib_entry_pool_size());
4595 * remove the API source from the default route. We expected
4596 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
4598 fib_table_entry_path_remove(fib_index, &pfx_0_0,
4602 tm->hw[0]->sw_if_index,
4605 FIB_ROUTE_PATH_FLAG_NONE);
4606 fei = fib_table_lookup(fib_index, &pfx_0_0);
4608 FIB_TEST((fei == dfrt), "default route same index");
4609 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4610 "Default route is DROP");
4613 * no more entries. -1 shared path-list
4615 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4616 fib_path_list_db_size());
4617 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
4618 fib_path_list_pool_size());
4619 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
4620 fib_entry_pool_size());
4623 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4625 fib_prefix_t pfx_2001_1_2_s_128 = {
4627 .fp_proto = FIB_PROTOCOL_IP6,
4631 [0] = clib_host_to_net_u64(0x2001000000000001),
4632 [1] = clib_host_to_net_u64(0x0000000000000002),
4637 fib_prefix_t pfx_2001_1_3_s_128 = {
4639 .fp_proto = FIB_PROTOCOL_IP6,
4643 [0] = clib_host_to_net_u64(0x2001000000000001),
4644 [1] = clib_host_to_net_u64(0x0000000000000003),
4650 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
4653 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4655 &pfx_2001_1_2_s_128.fp_addr,
4656 tm->hw[0]->sw_if_index);
4657 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
4658 adj = adj_get(ai_01);
4659 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4660 "adj is incomplete");
4661 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4662 &adj->sub_type.nbr.next_hop)),
4663 "adj nbr next-hop ok");
4665 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4666 fib_test_build_rewrite(eth_addr));
4667 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4669 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4670 &adj->sub_type.nbr.next_hop)),
4671 "adj nbr next-hop ok");
4673 fib_table_entry_path_add(fib_index,
4674 &pfx_2001_1_2_s_128,
4676 FIB_ENTRY_FLAG_ATTACHED,
4678 &pfx_2001_1_2_s_128.fp_addr,
4679 tm->hw[0]->sw_if_index,
4683 FIB_ROUTE_PATH_FLAG_NONE);
4685 fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
4686 ai = fib_entry_get_adj(fei);
4687 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4691 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
4693 &pfx_2001_1_3_s_128.fp_addr,
4694 tm->hw[0]->sw_if_index);
4695 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
4696 adj = adj_get(ai_02);
4697 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4698 "adj is incomplete");
4699 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4700 &adj->sub_type.nbr.next_hop)),
4701 "adj nbr next-hop ok");
4703 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4704 fib_test_build_rewrite(eth_addr));
4705 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4707 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4708 &adj->sub_type.nbr.next_hop)),
4709 "adj nbr next-hop ok");
4710 FIB_TEST((ai_01 != ai_02), "ADJs are different");
4712 fib_table_entry_path_add(fib_index,
4713 &pfx_2001_1_3_s_128,
4715 FIB_ENTRY_FLAG_ATTACHED,
4717 &pfx_2001_1_3_s_128.fp_addr,
4718 tm->hw[0]->sw_if_index,
4722 FIB_ROUTE_PATH_FLAG_NONE);
4724 fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
4725 ai = fib_entry_get_adj(fei);
4726 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4729 * +2 entries, +2 unshread path-lists.
4731 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4732 fib_path_list_db_size());
4733 FIB_TEST((PNPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
4734 fib_path_list_pool_size());
4735 FIB_TEST((ENPS+4 == fib_entry_pool_size()), "entry pool size is %d",
4736 fib_entry_pool_size());
4739 * Add a 2 routes via the first ADJ. ensure path-list sharing
4741 fib_prefix_t pfx_2001_a_s_64 = {
4743 .fp_proto = FIB_PROTOCOL_IP6,
4747 [0] = clib_host_to_net_u64(0x200100000000000a),
4748 [1] = clib_host_to_net_u64(0x0000000000000000),
4753 fib_prefix_t pfx_2001_b_s_64 = {
4755 .fp_proto = FIB_PROTOCOL_IP6,
4759 [0] = clib_host_to_net_u64(0x200100000000000b),
4760 [1] = clib_host_to_net_u64(0x0000000000000000),
4766 fib_table_entry_path_add(fib_index,
4769 FIB_ENTRY_FLAG_NONE,
4772 tm->hw[0]->sw_if_index,
4776 FIB_ROUTE_PATH_FLAG_NONE);
4777 fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64);
4778 ai = fib_entry_get_adj(fei);
4779 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4780 fib_table_entry_path_add(fib_index,
4783 FIB_ENTRY_FLAG_NONE,
4786 tm->hw[0]->sw_if_index,
4790 FIB_ROUTE_PATH_FLAG_NONE);
4791 fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64);
4792 ai = fib_entry_get_adj(fei);
4793 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4796 * +2 entries, +1 shared path-list.
4798 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4799 fib_path_list_db_size());
4800 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4801 fib_path_list_pool_size());
4802 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
4803 fib_entry_pool_size());
4806 * add a v4 prefix via a v6 next-hop
4808 fib_prefix_t pfx_1_1_1_1_s_32 = {
4810 .fp_proto = FIB_PROTOCOL_IP4,
4812 .ip4.as_u32 = 0x01010101,
4815 fei = fib_table_entry_path_add(0, // default table
4818 FIB_ENTRY_FLAG_NONE,
4821 tm->hw[0]->sw_if_index,
4825 FIB_ROUTE_PATH_FLAG_NONE);
4826 FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32),
4827 "1.1.1.1/32 o v6 route present");
4828 ai = fib_entry_get_adj(fei);
4830 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
4831 "1.1.1.1/32 via ARP-adj");
4832 FIB_TEST((adj->ia_link == VNET_LINK_IP4),
4833 "1.1.1.1/32 ADJ-adj is link type v4");
4834 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6),
4835 "1.1.1.1/32 ADJ-adj is NH proto v6");
4836 fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API);
4841 fib_prefix_t pfx_2001_c_s_64 = {
4843 .fp_proto = FIB_PROTOCOL_IP6,
4847 [0] = clib_host_to_net_u64(0x200100000000000c),
4848 [1] = clib_host_to_net_u64(0x0000000000000000),
4853 fib_table_entry_path_add(fib_index,
4856 FIB_ENTRY_FLAG_ATTACHED,
4859 tm->hw[0]->sw_if_index,
4863 FIB_ROUTE_PATH_FLAG_NONE);
4864 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4865 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present");
4866 ai = fib_entry_get_adj(fei);
4868 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN),
4869 "2001:0:0:c/64 attached resolves via glean");
4871 fib_table_entry_path_remove(fib_index,
4876 tm->hw[0]->sw_if_index,
4879 FIB_ROUTE_PATH_FLAG_NONE);
4880 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4881 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached route removed");
4884 * Shutdown the interface on which we have a connected and through
4885 * which the routes are reachable.
4886 * This will result in the connected, adj-fibs, and routes linking to drop
4887 * The local/for-us prefix continues to receive.
4889 clib_error_t * error;
4891 error = vnet_sw_interface_set_flags(vnet_get_main(),
4892 tm->hw[0]->sw_if_index,
4893 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4894 FIB_TEST((NULL == error), "Interface shutdown OK");
4896 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4897 dpo = fib_entry_contribute_ip_forwarding(fei);
4898 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4899 "2001::b/64 resolves via drop");
4901 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4902 dpo = fib_entry_contribute_ip_forwarding(fei);
4903 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4904 "2001::a/64 resolves via drop");
4905 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4906 dpo = fib_entry_contribute_ip_forwarding(fei);
4907 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4908 "2001:0:0:1::3/64 resolves via drop");
4909 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4910 dpo = fib_entry_contribute_ip_forwarding(fei);
4911 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4912 "2001:0:0:1::2/64 resolves via drop");
4913 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4914 dpo = fib_entry_contribute_ip_forwarding(fei);
4915 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4916 "2001:0:0:1::1/128 not drop");
4917 local_pfx.fp_len = 64;
4918 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4919 dpo = fib_entry_contribute_ip_forwarding(fei);
4920 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4921 "2001:0:0:1/64 resolves via drop");
4926 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4927 fib_path_list_db_size());
4928 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4929 fib_path_list_pool_size());
4930 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
4931 fib_entry_pool_size());
4934 * shutdown one of the other interfaces, then add a connected.
4935 * and swap one of the routes to it.
4937 error = vnet_sw_interface_set_flags(vnet_get_main(),
4938 tm->hw[1]->sw_if_index,
4939 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4940 FIB_TEST((NULL == error), "Interface 1 shutdown OK");
4942 fib_prefix_t connected_pfx = {
4944 .fp_proto = FIB_PROTOCOL_IP6,
4947 /* 2001:0:0:2::1/64 */
4949 [0] = clib_host_to_net_u64(0x2001000000000002),
4950 [1] = clib_host_to_net_u64(0x0000000000000001),
4955 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4956 FIB_SOURCE_INTERFACE,
4957 (FIB_ENTRY_FLAG_CONNECTED |
4958 FIB_ENTRY_FLAG_ATTACHED),
4961 tm->hw[1]->sw_if_index,
4965 FIB_ROUTE_PATH_FLAG_NONE);
4966 fei = fib_table_lookup_exact_match(fib_index, &connected_pfx);
4967 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4968 dpo = fib_entry_contribute_ip_forwarding(fei);
4969 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4970 FIB_TEST(!dpo_cmp(dpo, dpo_drop),
4971 "2001:0:0:2/64 not resolves via drop");
4973 connected_pfx.fp_len = 128;
4974 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4975 FIB_SOURCE_INTERFACE,
4976 (FIB_ENTRY_FLAG_CONNECTED |
4977 FIB_ENTRY_FLAG_LOCAL),
4980 tm->hw[0]->sw_if_index,
4981 ~0, // invalid fib index
4984 FIB_ROUTE_PATH_FLAG_NONE);
4985 fei = fib_table_lookup(fib_index, &connected_pfx);
4987 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4988 dpo = fib_entry_contribute_ip_forwarding(fei);
4989 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4990 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4991 "local interface adj is local");
4992 rd = receive_dpo_get(dpo->dpoi_index);
4993 FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr,
4995 "local interface adj is receive ok");
4998 * +2 entries, +2 unshared path-lists
5000 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
5001 fib_path_list_db_size());
5002 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
5003 fib_path_list_pool_size());
5004 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
5005 fib_entry_pool_size());
5009 * bring the interface back up. we expected the routes to return
5010 * to normal forwarding.
5012 error = vnet_sw_interface_set_flags(vnet_get_main(),
5013 tm->hw[0]->sw_if_index,
5014 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5015 FIB_TEST((NULL == error), "Interface bring-up OK");
5016 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5017 ai = fib_entry_get_adj(fei);
5018 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
5019 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5020 ai = fib_entry_get_adj(fei);
5021 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
5022 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5023 ai = fib_entry_get_adj(fei);
5024 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
5025 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5026 ai = fib_entry_get_adj(fei);
5027 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
5028 local_pfx.fp_len = 64;
5029 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5030 ai = fib_entry_get_adj(fei);
5032 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
5033 "attached interface adj is glean");
5036 * Same test as above, but this time the HW interface goes down
5038 error = vnet_hw_interface_set_flags(vnet_get_main(),
5039 tm->hw_if_indicies[0],
5040 ~VNET_HW_INTERFACE_FLAG_LINK_UP);
5041 FIB_TEST((NULL == error), "Interface shutdown OK");
5043 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5044 dpo = fib_entry_contribute_ip_forwarding(fei);
5045 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5046 "2001::b/64 resolves via drop");
5047 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5048 dpo = fib_entry_contribute_ip_forwarding(fei);
5049 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5050 "2001::a/64 resolves via drop");
5051 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5052 dpo = fib_entry_contribute_ip_forwarding(fei);
5053 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5054 "2001:0:0:1::3/128 resolves via drop");
5055 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5056 dpo = fib_entry_contribute_ip_forwarding(fei);
5057 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5058 "2001:0:0:1::2/128 resolves via drop");
5059 local_pfx.fp_len = 128;
5060 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5061 dpo = fib_entry_contribute_ip_forwarding(fei);
5062 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5063 "2001:0:0:1::1/128 not drop");
5064 local_pfx.fp_len = 64;
5065 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5066 dpo = fib_entry_contribute_ip_forwarding(fei);
5067 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5068 "2001:0:0:1/64 resolves via drop");
5070 error = vnet_hw_interface_set_flags(vnet_get_main(),
5071 tm->hw_if_indicies[0],
5072 VNET_HW_INTERFACE_FLAG_LINK_UP);
5073 FIB_TEST((NULL == error), "Interface bring-up OK");
5074 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5075 ai = fib_entry_get_adj(fei);
5076 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
5077 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5078 ai = fib_entry_get_adj(fei);
5079 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
5080 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5081 ai = fib_entry_get_adj(fei);
5082 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
5083 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5084 ai = fib_entry_get_adj(fei);
5085 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
5086 local_pfx.fp_len = 64;
5087 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5088 ai = fib_entry_get_adj(fei);
5090 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
5091 "attached interface adj is glean");
5094 * Delete the interface that the routes reolve through.
5095 * Again no routes are removed. They all point to drop.
5097 * This is considered an error case. The control plane should
5098 * not remove interfaces through which routes resolve, but
5099 * such things can happen. ALL affected routes will drop.
5101 vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]);
5103 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5104 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5105 "2001::b/64 resolves via drop");
5106 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5107 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5108 "2001::b/64 resolves via drop");
5109 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5110 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5111 "2001:0:0:1::3/64 resolves via drop");
5112 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5113 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5114 "2001:0:0:1::2/64 resolves via drop");
5115 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5116 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5117 "2001:0:0:1::1/128 is drop");
5118 local_pfx.fp_len = 64;
5119 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5120 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5121 "2001:0:0:1/64 resolves via drop");
5126 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
5127 fib_path_list_db_size());
5128 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
5129 fib_path_list_pool_size());
5130 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
5131 fib_entry_pool_size());
5134 * Add the interface back. routes stay unresolved.
5136 error = ethernet_register_interface(vnet_get_main(),
5137 test_interface_device_class.index,
5140 &tm->hw_if_indicies[0],
5141 /* flag change */ 0);
5143 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
5144 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5145 "2001::b/64 resolves via drop");
5146 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5147 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5148 "2001::b/64 resolves via drop");
5149 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5150 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5151 "2001:0:0:1::3/64 resolves via drop");
5152 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5153 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5154 "2001:0:0:1::2/64 resolves via drop");
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::1/128 is drop");
5158 local_pfx.fp_len = 64;
5159 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5160 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5161 "2001:0:0:1/64 resolves via drop");
5164 * CLEANUP ALL the routes
5166 fib_table_entry_delete(fib_index,
5169 fib_table_entry_delete(fib_index,
5172 fib_table_entry_delete(fib_index,
5175 fib_table_entry_delete(fib_index,
5176 &pfx_2001_1_3_s_128,
5178 fib_table_entry_delete(fib_index,
5179 &pfx_2001_1_2_s_128,
5181 local_pfx.fp_len = 64;
5182 fib_table_entry_delete(fib_index, &local_pfx,
5183 FIB_SOURCE_INTERFACE);
5184 local_pfx.fp_len = 128;
5185 fib_table_entry_special_remove(fib_index, &local_pfx,
5186 FIB_SOURCE_INTERFACE);
5187 connected_pfx.fp_len = 64;
5188 fib_table_entry_delete(fib_index, &connected_pfx,
5189 FIB_SOURCE_INTERFACE);
5190 connected_pfx.fp_len = 128;
5191 fib_table_entry_special_remove(fib_index, &connected_pfx,
5192 FIB_SOURCE_INTERFACE);
5194 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5195 fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)),
5196 "2001::a/64 removed");
5197 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5198 fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)),
5199 "2001::b/64 removed");
5200 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5201 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)),
5202 "2001:0:0:1::3/128 removed");
5203 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5204 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)),
5205 "2001:0:0:1::3/128 removed");
5206 local_pfx.fp_len = 64;
5207 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5208 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5209 "2001:0:0:1/64 removed");
5210 local_pfx.fp_len = 128;
5211 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5212 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5213 "2001:0:0:1::1/128 removed");
5214 connected_pfx.fp_len = 64;
5215 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5216 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5217 "2001:0:0:2/64 removed");
5218 connected_pfx.fp_len = 128;
5219 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5220 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5221 "2001:0:0:2::1/128 removed");
5224 * -8 entries. -7 path-lists (1 was shared).
5226 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5227 fib_path_list_db_size());
5228 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is%d",
5229 fib_path_list_pool_size());
5230 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
5231 fib_entry_pool_size());
5234 * now remove the VRF
5236 fib_table_unlock(fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
5238 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5239 fib_path_list_db_size());
5240 FIB_TEST((PNPS-2 == fib_path_list_pool_size()), "path list pool size is%d",
5241 fib_path_list_pool_size());
5242 FIB_TEST((ENPS-2 == fib_entry_pool_size()), "entry pool size is %d",
5243 fib_entry_pool_size());
5249 * return the interfaces to up state
5251 error = vnet_sw_interface_set_flags(vnet_get_main(),
5252 tm->hw[0]->sw_if_index,
5253 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5254 error = vnet_sw_interface_set_flags(vnet_get_main(),
5255 tm->hw[1]->sw_if_index,
5256 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5258 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5260 FIB_TEST((0 == adj_glean_db_size()), "ADJ DB size is %d",
5261 adj_glean_db_size());
5267 * Test Attached Exports
5272 const dpo_id_t *dpo, *dpo_drop;
5273 const u32 fib_index = 0;
5274 fib_node_index_t fei;
5283 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5287 * add interface routes. We'll assume this works. It's more rigorously
5290 fib_prefix_t local_pfx = {
5292 .fp_proto = FIB_PROTOCOL_IP4,
5296 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5301 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
5302 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
5304 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
5306 fib_table_entry_update_one_path(fib_index, &local_pfx,
5307 FIB_SOURCE_INTERFACE,
5308 (FIB_ENTRY_FLAG_CONNECTED |
5309 FIB_ENTRY_FLAG_ATTACHED),
5312 tm->hw[0]->sw_if_index,
5316 FIB_ROUTE_PATH_FLAG_NONE);
5317 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5318 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5319 "attached interface route present");
5321 local_pfx.fp_len = 32;
5322 fib_table_entry_update_one_path(fib_index, &local_pfx,
5323 FIB_SOURCE_INTERFACE,
5324 (FIB_ENTRY_FLAG_CONNECTED |
5325 FIB_ENTRY_FLAG_LOCAL),
5328 tm->hw[0]->sw_if_index,
5329 ~0, // invalid fib index
5332 FIB_ROUTE_PATH_FLAG_NONE);
5333 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5335 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5336 "local interface route present");
5339 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
5341 fib_prefix_t pfx_10_10_10_1_s_32 = {
5343 .fp_proto = FIB_PROTOCOL_IP4,
5346 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5349 fib_node_index_t ai;
5351 fib_table_entry_path_add(fib_index,
5352 &pfx_10_10_10_1_s_32,
5354 FIB_ENTRY_FLAG_ATTACHED,
5356 &pfx_10_10_10_1_s_32.fp_addr,
5357 tm->hw[0]->sw_if_index,
5358 ~0, // invalid fib index
5361 FIB_ROUTE_PATH_FLAG_NONE);
5363 fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
5364 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
5365 ai = fib_entry_get_adj(fei);
5368 * create another FIB table into which routes will be imported
5370 u32 import_fib_index1;
5372 import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4,
5377 * Add an attached route in the import FIB
5379 local_pfx.fp_len = 24;
5380 fib_table_entry_update_one_path(import_fib_index1,
5383 FIB_ENTRY_FLAG_NONE,
5386 tm->hw[0]->sw_if_index,
5387 ~0, // invalid fib index
5390 FIB_ROUTE_PATH_FLAG_NONE);
5391 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5392 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5395 * check for the presence of the adj-fibs in the import table
5397 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5398 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5399 FIB_TEST((ai == fib_entry_get_adj(fei)),
5400 "adj-fib1 Import uses same adj as export");
5403 * check for the presence of the local in the import table
5405 local_pfx.fp_len = 32;
5406 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5407 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5410 * Add another adj-fin in the export table. Expect this
5411 * to get magically exported;
5413 fib_prefix_t pfx_10_10_10_2_s_32 = {
5415 .fp_proto = FIB_PROTOCOL_IP4,
5418 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5422 fib_table_entry_path_add(fib_index,
5423 &pfx_10_10_10_2_s_32,
5425 FIB_ENTRY_FLAG_ATTACHED,
5427 &pfx_10_10_10_2_s_32.fp_addr,
5428 tm->hw[0]->sw_if_index,
5429 ~0, // invalid fib index
5432 FIB_ROUTE_PATH_FLAG_NONE);
5433 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5434 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
5435 ai = fib_entry_get_adj(fei);
5437 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5438 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5439 FIB_TEST((ai == fib_entry_get_adj(fei)),
5440 "Import uses same adj as export");
5441 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(fei)),
5442 "ADJ-fib2 imported flags %d",
5443 fib_entry_get_flags(fei));
5446 * create a 2nd FIB table into which routes will be imported
5448 u32 import_fib_index2;
5450 import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12,
5454 * Add an attached route in the import FIB
5456 local_pfx.fp_len = 24;
5457 fib_table_entry_update_one_path(import_fib_index2,
5460 FIB_ENTRY_FLAG_NONE,
5463 tm->hw[0]->sw_if_index,
5464 ~0, // invalid fib index
5467 FIB_ROUTE_PATH_FLAG_NONE);
5468 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5469 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5472 * check for the presence of all the adj-fibs and local in the import table
5474 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5475 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5476 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5477 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5478 local_pfx.fp_len = 32;
5479 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5480 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5483 * add a 3rd adj-fib. expect it to be exported to both tables.
5485 fib_prefix_t pfx_10_10_10_3_s_32 = {
5487 .fp_proto = FIB_PROTOCOL_IP4,
5490 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
5494 fib_table_entry_path_add(fib_index,
5495 &pfx_10_10_10_3_s_32,
5497 FIB_ENTRY_FLAG_ATTACHED,
5499 &pfx_10_10_10_3_s_32.fp_addr,
5500 tm->hw[0]->sw_if_index,
5501 ~0, // invalid fib index
5504 FIB_ROUTE_PATH_FLAG_NONE);
5505 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5506 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
5507 ai = fib_entry_get_adj(fei);
5509 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5510 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1");
5511 FIB_TEST((ai == fib_entry_get_adj(fei)),
5512 "Import uses same adj as export");
5513 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5514 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2");
5515 FIB_TEST((ai == fib_entry_get_adj(fei)),
5516 "Import uses same adj as export");
5519 * remove the 3rd adj fib. we expect it to be removed from both FIBs
5521 fib_table_entry_delete(fib_index,
5522 &pfx_10_10_10_3_s_32,
5525 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5526 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved");
5528 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5529 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1");
5531 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5532 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2");
5535 * remove the attached route from the 2nd FIB. expect the imported
5536 * entries to be removed
5538 local_pfx.fp_len = 24;
5539 fib_table_entry_delete(import_fib_index2,
5542 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5543 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed");
5545 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5546 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2");
5547 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5548 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2");
5549 local_pfx.fp_len = 32;
5550 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5551 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2");
5553 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5554 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1");
5555 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5556 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1");
5557 local_pfx.fp_len = 32;
5558 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5559 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1");
5562 * modify the route in FIB1 so it is no longer attached. expect the imported
5563 * entries to be removed
5565 local_pfx.fp_len = 24;
5566 fib_table_entry_update_one_path(import_fib_index1,
5569 FIB_ENTRY_FLAG_NONE,
5571 &pfx_10_10_10_2_s_32.fp_addr,
5572 tm->hw[0]->sw_if_index,
5573 ~0, // invalid fib index
5576 FIB_ROUTE_PATH_FLAG_NONE);
5577 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5578 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5579 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5580 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5581 local_pfx.fp_len = 32;
5582 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5583 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5586 * modify it back to attached. expect the adj-fibs back
5588 local_pfx.fp_len = 24;
5589 fib_table_entry_update_one_path(import_fib_index1,
5592 FIB_ENTRY_FLAG_NONE,
5595 tm->hw[0]->sw_if_index,
5596 ~0, // invalid fib index
5599 FIB_ROUTE_PATH_FLAG_NONE);
5600 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5601 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1");
5602 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5603 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1");
5604 local_pfx.fp_len = 32;
5605 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5606 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1");
5609 * add a covering attached next-hop for the interface address, so we have
5610 * a valid adj to find when we check the forwarding tables
5612 fib_prefix_t pfx_10_0_0_0_s_8 = {
5614 .fp_proto = FIB_PROTOCOL_IP4,
5617 .ip4.as_u32 = clib_host_to_net_u32(0x0a000000),
5621 fei = fib_table_entry_update_one_path(fib_index,
5624 FIB_ENTRY_FLAG_NONE,
5626 &pfx_10_10_10_3_s_32.fp_addr,
5627 tm->hw[0]->sw_if_index,
5628 ~0, // invalid fib index
5631 FIB_ROUTE_PATH_FLAG_NONE);
5632 dpo = fib_entry_contribute_ip_forwarding(fei);
5635 * remove the route in the export fib. expect the adj-fibs to be removed
5637 local_pfx.fp_len = 24;
5638 fib_table_entry_delete(fib_index,
5640 FIB_SOURCE_INTERFACE);
5642 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5643 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1");
5644 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5645 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5646 local_pfx.fp_len = 32;
5647 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5648 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5651 * the adj-fibs in the export VRF are present in the FIB table,
5652 * but not installed in forwarding, since they have no attached cover.
5653 * Consequently a lookup in the MTRIE gives the adj for the covering
5656 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5657 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5660 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5661 FIB_TEST(lbi == dpo->dpoi_index,
5662 "10.10.10.1 forwards on \n%U not \n%U",
5663 format_load_balance, lbi, 0,
5664 format_dpo_id, dpo, 0);
5665 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5666 FIB_TEST(lbi == dpo->dpoi_index,
5667 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5668 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4);
5669 FIB_TEST(lbi == dpo->dpoi_index,
5670 "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0);
5673 * add the export prefix back, but not as attached.
5674 * No adj-fibs in export nor import tables
5676 local_pfx.fp_len = 24;
5677 fei = fib_table_entry_update_one_path(fib_index,
5680 FIB_ENTRY_FLAG_NONE,
5682 &pfx_10_10_10_1_s_32.fp_addr,
5683 tm->hw[0]->sw_if_index,
5684 ~0, // invalid fib index
5687 FIB_ROUTE_PATH_FLAG_NONE);
5688 dpo = fib_entry_contribute_ip_forwarding(fei);
5690 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5691 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export");
5692 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5693 FIB_TEST(lbi == dpo->dpoi_index,
5694 "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0);
5695 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5696 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5697 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5698 FIB_TEST(lbi == dpo->dpoi_index,
5699 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5701 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5702 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5703 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5704 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5705 local_pfx.fp_len = 32;
5706 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5707 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5710 * modify the export prefix so it is attached. expect all covereds to return
5712 local_pfx.fp_len = 24;
5713 fib_table_entry_update_one_path(fib_index,
5716 FIB_ENTRY_FLAG_NONE,
5719 tm->hw[0]->sw_if_index,
5720 ~0, // invalid fib index
5723 FIB_ROUTE_PATH_FLAG_NONE);
5725 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5726 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5727 dpo = fib_entry_contribute_ip_forwarding(fei);
5728 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5729 "Adj-fib1 is not drop in export");
5730 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5731 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5732 local_pfx.fp_len = 32;
5733 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5734 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5735 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5736 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5737 dpo = fib_entry_contribute_ip_forwarding(fei);
5738 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5739 "Adj-fib1 is not drop in export: %U %U",
5740 format_dpo_id, dpo, 0,
5741 format_dpo_id, load_balance_get_bucket(dpo->dpoi_index, 0), 0);
5742 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5743 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5744 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5745 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5746 local_pfx.fp_len = 32;
5747 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5748 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5751 * modify the export prefix so connected. no change.
5753 local_pfx.fp_len = 24;
5754 fib_table_entry_update_one_path(fib_index, &local_pfx,
5755 FIB_SOURCE_INTERFACE,
5756 (FIB_ENTRY_FLAG_CONNECTED |
5757 FIB_ENTRY_FLAG_ATTACHED),
5760 tm->hw[0]->sw_if_index,
5764 FIB_ROUTE_PATH_FLAG_NONE);
5766 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5767 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5768 dpo = fib_entry_contribute_ip_forwarding(fei);
5769 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5770 "Adj-fib1 is not drop in export");
5771 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5772 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5773 local_pfx.fp_len = 32;
5774 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5775 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
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), "attached in export: ADJ-fib1 imported");
5778 dpo = fib_entry_contribute_ip_forwarding(fei);
5779 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5780 "Adj-fib1 is not drop in export");
5781 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5782 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5783 local_pfx.fp_len = 32;
5784 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5785 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5790 fib_table_entry_delete(fib_index,
5793 fib_table_entry_delete(fib_index,
5794 &pfx_10_10_10_1_s_32,
5796 fib_table_entry_delete(fib_index,
5797 &pfx_10_10_10_2_s_32,
5799 local_pfx.fp_len = 32;
5800 fib_table_entry_delete(fib_index,
5802 FIB_SOURCE_INTERFACE);
5803 local_pfx.fp_len = 24;
5804 fib_table_entry_delete(fib_index,
5807 fib_table_entry_delete(fib_index,
5809 FIB_SOURCE_INTERFACE);
5810 local_pfx.fp_len = 24;
5811 fib_table_entry_delete(import_fib_index1,
5815 fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
5816 fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
5818 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5825 * Test Path Preference
5828 fib_test_pref (void)
5830 test_main_t *tm = &test_main;
5834 const fib_prefix_t pfx_1_1_1_1_s_32 = {
5836 .fp_proto = FIB_PROTOCOL_IP4,
5839 .as_u32 = clib_host_to_net_u32(0x01010101),
5845 * 2 high, 2 medium and 2 low preference non-recursive paths
5847 fib_route_path_t nr_path_hi_1 = {
5848 .frp_proto = DPO_PROTO_IP4,
5849 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5850 .frp_fib_index = ~0,
5852 .frp_preference = 0,
5853 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5855 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5858 fib_route_path_t nr_path_hi_2 = {
5859 .frp_proto = DPO_PROTO_IP4,
5860 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5861 .frp_fib_index = ~0,
5863 .frp_preference = 0,
5864 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5866 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5869 fib_route_path_t nr_path_med_1 = {
5870 .frp_proto = DPO_PROTO_IP4,
5871 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5872 .frp_fib_index = ~0,
5874 .frp_preference = 1,
5875 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5877 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5880 fib_route_path_t nr_path_med_2 = {
5881 .frp_proto = DPO_PROTO_IP4,
5882 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5883 .frp_fib_index = ~0,
5885 .frp_preference = 1,
5886 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5888 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5891 fib_route_path_t nr_path_low_1 = {
5892 .frp_proto = DPO_PROTO_IP4,
5893 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5894 .frp_fib_index = ~0,
5896 .frp_preference = 2,
5897 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5899 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b01),
5902 fib_route_path_t nr_path_low_2 = {
5903 .frp_proto = DPO_PROTO_IP4,
5904 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5905 .frp_fib_index = ~0,
5907 .frp_preference = 2,
5908 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5910 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b02),
5913 fib_route_path_t *nr_paths = NULL;
5915 vec_add1(nr_paths, nr_path_hi_1);
5916 vec_add1(nr_paths, nr_path_hi_2);
5917 vec_add1(nr_paths, nr_path_med_1);
5918 vec_add1(nr_paths, nr_path_med_2);
5919 vec_add1(nr_paths, nr_path_low_1);
5920 vec_add1(nr_paths, nr_path_low_2);
5922 adj_index_t ai_hi_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5924 &nr_path_hi_1.frp_addr,
5925 nr_path_hi_1.frp_sw_if_index);
5926 adj_index_t ai_hi_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5928 &nr_path_hi_2.frp_addr,
5929 nr_path_hi_2.frp_sw_if_index);
5930 adj_index_t ai_med_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5932 &nr_path_med_1.frp_addr,
5933 nr_path_med_1.frp_sw_if_index);
5934 adj_index_t ai_med_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5936 &nr_path_med_2.frp_addr,
5937 nr_path_med_2.frp_sw_if_index);
5938 adj_index_t ai_low_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5940 &nr_path_low_1.frp_addr,
5941 nr_path_low_1.frp_sw_if_index);
5942 adj_index_t ai_low_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5944 &nr_path_low_2.frp_addr,
5945 nr_path_low_2.frp_sw_if_index);
5947 fib_test_lb_bucket_t ip_hi_1 = {
5953 fib_test_lb_bucket_t ip_hi_2 = {
5959 fib_test_lb_bucket_t ip_med_1 = {
5965 fib_test_lb_bucket_t ip_med_2 = {
5971 fib_test_lb_bucket_t ip_low_1 = {
5977 fib_test_lb_bucket_t ip_low_2 = {
5984 fib_node_index_t fei;
5986 fei = fib_table_entry_path_add2(0,
5989 FIB_ENTRY_FLAG_NONE,
5992 FIB_TEST(!fib_test_validate_entry(fei,
5993 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5997 "1.1.1.1/32 via high preference paths");
6000 * bring down the interface on which the high preference path lie
6002 vnet_sw_interface_set_flags(vnet_get_main(),
6003 tm->hw[0]->sw_if_index,
6006 FIB_TEST(!fib_test_validate_entry(fei,
6007 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6011 "1.1.1.1/32 via medium preference paths");
6014 * bring down the interface on which the medium preference path lie
6016 vnet_sw_interface_set_flags(vnet_get_main(),
6017 tm->hw[1]->sw_if_index,
6020 FIB_TEST(!fib_test_validate_entry(fei,
6021 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6025 "1.1.1.1/32 via low preference paths");
6028 * bring up the interface on which the high preference path lie
6030 vnet_sw_interface_set_flags(vnet_get_main(),
6031 tm->hw[0]->sw_if_index,
6032 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6034 FIB_TEST(!fib_test_validate_entry(fei,
6035 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6039 "1.1.1.1/32 via high preference paths");
6042 * bring up the interface on which the medium preference path lie
6044 vnet_sw_interface_set_flags(vnet_get_main(),
6045 tm->hw[1]->sw_if_index,
6046 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6048 FIB_TEST(!fib_test_validate_entry(fei,
6049 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6053 "1.1.1.1/32 via high preference paths");
6055 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
6056 fib_entry_contribute_forwarding(fei,
6057 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6061 * 3 recursive paths of different preference
6063 const fib_prefix_t pfx_1_1_1_2_s_32 = {
6065 .fp_proto = FIB_PROTOCOL_IP4,
6068 .as_u32 = clib_host_to_net_u32(0x01010102),
6072 const fib_prefix_t pfx_1_1_1_3_s_32 = {
6074 .fp_proto = FIB_PROTOCOL_IP4,
6077 .as_u32 = clib_host_to_net_u32(0x01010103),
6081 fei = fib_table_entry_path_add2(0,
6084 FIB_ENTRY_FLAG_NONE,
6086 dpo_id_t ip_1_1_1_2 = DPO_INVALID;
6087 fib_entry_contribute_forwarding(fei,
6088 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6090 fei = fib_table_entry_path_add2(0,
6093 FIB_ENTRY_FLAG_NONE,
6095 dpo_id_t ip_1_1_1_3 = DPO_INVALID;
6096 fib_entry_contribute_forwarding(fei,
6097 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6100 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
6103 .lb = ip_1_1_1_1.dpoi_index,
6106 fib_test_lb_bucket_t ip_o_1_1_1_2 = {
6109 .lb = ip_1_1_1_2.dpoi_index,
6112 fib_test_lb_bucket_t ip_o_1_1_1_3 = {
6115 .lb = ip_1_1_1_3.dpoi_index,
6118 fib_route_path_t r_path_hi = {
6119 .frp_proto = DPO_PROTO_IP4,
6120 .frp_sw_if_index = ~0,
6123 .frp_preference = 0,
6124 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
6125 .frp_addr = pfx_1_1_1_1_s_32.fp_addr,
6127 fib_route_path_t r_path_med = {
6128 .frp_proto = DPO_PROTO_IP4,
6129 .frp_sw_if_index = ~0,
6132 .frp_preference = 10,
6133 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
6134 .frp_addr = pfx_1_1_1_2_s_32.fp_addr,
6136 fib_route_path_t r_path_low = {
6137 .frp_proto = DPO_PROTO_IP4,
6138 .frp_sw_if_index = ~0,
6141 .frp_preference = 255,
6142 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
6143 .frp_addr = pfx_1_1_1_3_s_32.fp_addr,
6145 fib_route_path_t *r_paths = NULL;
6147 vec_add1(r_paths, r_path_hi);
6148 vec_add1(r_paths, r_path_low);
6149 vec_add1(r_paths, r_path_med);
6152 * add many recursive so we get the LB MAp created
6155 fib_prefix_t pfx_r[N_PFXS];
6156 unsigned int n_pfxs;
6157 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6159 pfx_r[n_pfxs].fp_len = 32;
6160 pfx_r[n_pfxs].fp_proto = FIB_PROTOCOL_IP4;
6161 pfx_r[n_pfxs].fp_addr.ip4.as_u32 =
6162 clib_host_to_net_u32(0x02000000 + n_pfxs);
6164 fei = fib_table_entry_path_add2(0,
6167 FIB_ENTRY_FLAG_NONE,
6170 FIB_TEST(!fib_test_validate_entry(fei,
6171 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6174 "recursive via high preference paths");
6177 * withdraw hig pref resolving entry
6179 fib_table_entry_delete(0,
6183 /* suspend so the update walk kicks int */
6184 vlib_process_suspend(vlib_get_main(), 1e-5);
6186 FIB_TEST(!fib_test_validate_entry(fei,
6187 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6190 "recursive via medium preference paths");
6193 * withdraw medium pref resolving entry
6195 fib_table_entry_delete(0,
6199 /* suspend so the update walk kicks int */
6200 vlib_process_suspend(vlib_get_main(), 1e-5);
6202 FIB_TEST(!fib_test_validate_entry(fei,
6203 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6206 "recursive via low preference paths");
6209 * add back paths for next iteration
6211 fei = fib_table_entry_update(0,
6214 FIB_ENTRY_FLAG_NONE,
6216 fei = fib_table_entry_update(0,
6219 FIB_ENTRY_FLAG_NONE,
6222 /* suspend so the update walk kicks int */
6223 vlib_process_suspend(vlib_get_main(), 1e-5);
6225 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6226 FIB_TEST(!fib_test_validate_entry(fei,
6227 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6230 "recursive via high preference paths");
6234 fib_table_entry_delete(0,
6238 /* suspend so the update walk kicks int */
6239 vlib_process_suspend(vlib_get_main(), 1e-5);
6241 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6243 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6245 FIB_TEST(!fib_test_validate_entry(fei,
6246 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6249 "recursive via medium preference paths");
6251 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6253 fib_table_entry_delete(0,
6261 fib_table_entry_delete(0,
6264 fib_table_entry_delete(0,
6268 dpo_reset(&ip_1_1_1_1);
6269 dpo_reset(&ip_1_1_1_2);
6270 dpo_reset(&ip_1_1_1_3);
6271 adj_unlock(ai_low_2);
6272 adj_unlock(ai_low_1);
6273 adj_unlock(ai_med_2);
6274 adj_unlock(ai_med_1);
6275 adj_unlock(ai_hi_2);
6276 adj_unlock(ai_hi_1);
6282 * Test the recursive route route handling for GRE tunnels
6285 fib_test_label (void)
6287 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;
6288 const u32 fib_index = 0;
6289 int lb_count, ii, res;
6294 lb_count = pool_elts(load_balance_pool);
6299 * add interface routes. We'll assume this works. It's more rigorously
6302 fib_prefix_t local0_pfx = {
6304 .fp_proto = FIB_PROTOCOL_IP4,
6308 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
6313 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6316 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
6317 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
6319 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6320 FIB_SOURCE_INTERFACE,
6321 (FIB_ENTRY_FLAG_CONNECTED |
6322 FIB_ENTRY_FLAG_ATTACHED),
6325 tm->hw[0]->sw_if_index,
6329 FIB_ROUTE_PATH_FLAG_NONE);
6330 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6331 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6332 "attached interface route present");
6334 local0_pfx.fp_len = 32;
6335 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6336 FIB_SOURCE_INTERFACE,
6337 (FIB_ENTRY_FLAG_CONNECTED |
6338 FIB_ENTRY_FLAG_LOCAL),
6341 tm->hw[0]->sw_if_index,
6342 ~0, // invalid fib index
6345 FIB_ROUTE_PATH_FLAG_NONE);
6346 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6348 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6349 "local interface route present");
6351 fib_prefix_t local1_pfx = {
6353 .fp_proto = FIB_PROTOCOL_IP4,
6357 .as_u32 = clib_host_to_net_u32(0x0a0a0b0a),
6362 vec_validate(im->fib_index_by_sw_if_index, tm->hw[1]->sw_if_index);
6363 im->fib_index_by_sw_if_index[tm->hw[1]->sw_if_index] = fib_index;
6365 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6366 FIB_SOURCE_INTERFACE,
6367 (FIB_ENTRY_FLAG_CONNECTED |
6368 FIB_ENTRY_FLAG_ATTACHED),
6371 tm->hw[1]->sw_if_index,
6375 FIB_ROUTE_PATH_FLAG_NONE);
6376 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6377 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6378 "attached interface route present");
6380 local1_pfx.fp_len = 32;
6381 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6382 FIB_SOURCE_INTERFACE,
6383 (FIB_ENTRY_FLAG_CONNECTED |
6384 FIB_ENTRY_FLAG_LOCAL),
6387 tm->hw[1]->sw_if_index,
6388 ~0, // invalid fib index
6391 FIB_ROUTE_PATH_FLAG_NONE);
6392 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6394 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6395 "local interface route present");
6397 ip46_address_t nh_10_10_10_1 = {
6399 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
6402 ip46_address_t nh_10_10_11_1 = {
6404 .as_u32 = clib_host_to_net_u32(0x0a0a0b01),
6407 ip46_address_t nh_10_10_11_2 = {
6409 .as_u32 = clib_host_to_net_u32(0x0a0a0b02),
6413 ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6416 tm->hw[1]->sw_if_index);
6417 ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6420 tm->hw[1]->sw_if_index);
6421 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6424 tm->hw[0]->sw_if_index);
6425 ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6428 tm->hw[1]->sw_if_index);
6429 ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6432 tm->hw[1]->sw_if_index);
6435 * Add an etry with one path with a real out-going label
6437 fib_prefix_t pfx_1_1_1_1_s_32 = {
6439 .fp_proto = FIB_PROTOCOL_IP4,
6441 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
6444 fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = {
6445 .type = FT_LB_LABEL_O_ADJ,
6447 .adj = ai_mpls_10_10_10_1,
6452 fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = {
6453 .type = FT_LB_LABEL_O_ADJ,
6455 .adj = ai_mpls_10_10_10_1,
6457 .eos = MPLS_NON_EOS,
6460 fib_mpls_label_t *l99 = NULL, fml99 = {
6463 vec_add1(l99, fml99);
6465 fib_table_entry_update_one_path(fib_index,
6468 FIB_ENTRY_FLAG_NONE,
6471 tm->hw[0]->sw_if_index,
6472 ~0, // invalid fib index
6475 FIB_ROUTE_PATH_FLAG_NONE);
6477 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6478 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created");
6480 FIB_TEST(!fib_test_validate_entry(fei,
6481 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6483 &l99_eos_o_10_10_10_1),
6484 "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1");
6487 * add a path with an implicit NULL label
6489 fib_test_lb_bucket_t a_o_10_10_11_1 = {
6492 .adj = ai_v4_10_10_11_1,
6495 fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = {
6498 .adj = ai_mpls_10_10_11_1,
6501 fib_mpls_label_t *l_imp_null = NULL, fml_imp_null = {
6502 .fml_value = MPLS_IETF_IMPLICIT_NULL_LABEL,
6504 vec_add1(l_imp_null, fml_imp_null);
6506 fei = fib_table_entry_path_add(fib_index,
6509 FIB_ENTRY_FLAG_NONE,
6512 tm->hw[1]->sw_if_index,
6513 ~0, // invalid fib index
6516 FIB_ROUTE_PATH_FLAG_NONE);
6518 FIB_TEST(!fib_test_validate_entry(fei,
6519 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6521 &l99_eos_o_10_10_10_1,
6523 "1.1.1.1/32 LB 2 buckets via: "
6524 "label 99 over 10.10.10.1, "
6525 "adj over 10.10.11.1");
6528 * assign the route a local label
6530 fib_table_entry_local_label_add(fib_index,
6534 fib_prefix_t pfx_24001_eos = {
6535 .fp_proto = FIB_PROTOCOL_MPLS,
6539 fib_prefix_t pfx_24001_neos = {
6540 .fp_proto = FIB_PROTOCOL_MPLS,
6542 .fp_eos = MPLS_NON_EOS,
6544 fib_test_lb_bucket_t disp_o_10_10_11_1 = {
6545 .type = FT_LB_MPLS_DISP_PIPE_O_ADJ,
6547 .adj = ai_v4_10_10_11_1,
6552 * The EOS entry should link to both the paths,
6553 * and use an ip adj for the imp-null
6554 * The NON-EOS entry should link to both the paths,
6555 * and use an mpls adj for the imp-null
6557 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6559 FIB_TEST(!fib_test_validate_entry(fei,
6560 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6562 &l99_eos_o_10_10_10_1,
6563 &disp_o_10_10_11_1),
6564 "24001/eos LB 2 buckets via: "
6565 "label 99 over 10.10.10.1, "
6566 "mpls disp adj over 10.10.11.1");
6569 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6571 FIB_TEST(!fib_test_validate_entry(fei,
6572 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6574 &l99_neos_o_10_10_10_1,
6575 &a_mpls_o_10_10_11_1),
6576 "24001/neos LB 1 bucket via: "
6577 "label 99 over 10.10.10.1 ",
6578 "mpls-adj via 10.10.11.1");
6581 * add an unlabelled path, this is excluded from the neos chains,
6583 fib_test_lb_bucket_t adj_o_10_10_11_2 = {
6586 .adj = ai_v4_10_10_11_2,
6589 fib_test_lb_bucket_t disp_o_10_10_11_2 = {
6590 .type = FT_LB_MPLS_DISP_PIPE_O_ADJ,
6592 .adj = ai_v4_10_10_11_2,
6597 fei = fib_table_entry_path_add(fib_index,
6600 FIB_ENTRY_FLAG_NONE,
6603 tm->hw[1]->sw_if_index,
6604 ~0, // invalid fib index
6607 FIB_ROUTE_PATH_FLAG_NONE);
6609 FIB_TEST(!fib_test_validate_entry(fei,
6610 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6611 16, // 3 choices spread over 16 buckets
6612 &l99_eos_o_10_10_10_1,
6613 &l99_eos_o_10_10_10_1,
6614 &l99_eos_o_10_10_10_1,
6615 &l99_eos_o_10_10_10_1,
6616 &l99_eos_o_10_10_10_1,
6617 &l99_eos_o_10_10_10_1,
6628 "1.1.1.1/32 LB 16 buckets via: "
6629 "label 99 over 10.10.10.1, "
6630 "adj over 10.10.11.1",
6631 "adj over 10.10.11.2");
6634 * get and lock a reference to the non-eos of the via entry 1.1.1.1/32
6636 dpo_id_t non_eos_1_1_1_1 = DPO_INVALID;
6637 fib_entry_contribute_forwarding(fei,
6638 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6642 * n-eos has only the 2 labelled paths
6644 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 2 buckets via: "
6653 "label 99 over 10.10.10.1, "
6654 "adj-mpls over 10.10.11.2");
6657 * A labelled recursive
6659 fib_prefix_t pfx_2_2_2_2_s_32 = {
6661 .fp_proto = FIB_PROTOCOL_IP4,
6663 .ip4.as_u32 = clib_host_to_net_u32(0x02020202),
6666 fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = {
6667 .type = FT_LB_LABEL_O_LB,
6669 .lb = non_eos_1_1_1_1.dpoi_index,
6672 .mode = FIB_MPLS_LSP_MODE_UNIFORM,
6675 fib_mpls_label_t *l1600 = NULL, fml1600 = {
6677 .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM,
6679 vec_add1(l1600, fml1600);
6681 fei = fib_table_entry_update_one_path(fib_index,
6684 FIB_ENTRY_FLAG_NONE,
6686 &pfx_1_1_1_1_s_32.fp_addr,
6691 FIB_ROUTE_PATH_FLAG_NONE);
6693 FIB_TEST(!fib_test_validate_entry(fei,
6694 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6696 &l1600_eos_o_1_1_1_1),
6697 "2.2.2.2.2/32 LB 1 buckets via: "
6698 "label 1600 over 1.1.1.1");
6700 dpo_id_t dpo_44 = DPO_INVALID;
6703 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
6704 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
6706 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
6707 "uRPF check for 2.2.2.2/32 on %d OK",
6708 tm->hw[0]->sw_if_index);
6709 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
6710 "uRPF check for 2.2.2.2/32 on %d OK",
6711 tm->hw[1]->sw_if_index);
6712 FIB_TEST(!fib_urpf_check(urpfi, 99),
6713 "uRPF check for 2.2.2.2/32 on 99 not-OK",
6716 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44);
6717 FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index),
6718 "Shared uRPF on IP and non-EOS chain");
6723 * we are holding a lock on the non-eos LB of the via-entry.
6724 * do a PIC-core failover by shutting the link of the via-entry.
6726 * shut down the link with the valid label
6728 vnet_sw_interface_set_flags(vnet_get_main(),
6729 tm->hw[0]->sw_if_index,
6732 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6733 FIB_TEST(!fib_test_validate_entry(fei,
6734 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6738 "1.1.1.1/32 LB 2 buckets via: "
6739 "adj over 10.10.11.1, ",
6740 "adj-v4 over 10.10.11.2");
6742 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6744 FIB_TEST(!fib_test_validate_entry(fei,
6745 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6748 &disp_o_10_10_11_2),
6749 "24001/eos LB 2 buckets via: "
6750 "mpls-disp adj over 10.10.11.1, ",
6751 "mpls-disp adj-v4 over 10.10.11.2");
6753 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6755 FIB_TEST(!fib_test_validate_entry(fei,
6756 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6758 &a_mpls_o_10_10_11_1),
6759 "24001/neos LB 1 buckets via: "
6760 "adj-mpls over 10.10.11.2");
6763 * test that the pre-failover load-balance has been in-place
6766 dpo_id_t current = DPO_INVALID;
6767 fib_entry_contribute_forwarding(fei,
6768 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6771 FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1,
6773 "PIC-core LB inplace modified %U %U",
6774 format_dpo_id, &non_eos_1_1_1_1, 0,
6775 format_dpo_id, ¤t, 0);
6777 dpo_reset(&non_eos_1_1_1_1);
6778 dpo_reset(¤t);
6781 * no-shut the link with the valid label
6783 vnet_sw_interface_set_flags(vnet_get_main(),
6784 tm->hw[0]->sw_if_index,
6785 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6787 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6788 FIB_TEST(!fib_test_validate_entry(fei,
6789 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6790 16, // 3 choices spread over 16 buckets
6791 &l99_eos_o_10_10_10_1,
6792 &l99_eos_o_10_10_10_1,
6793 &l99_eos_o_10_10_10_1,
6794 &l99_eos_o_10_10_10_1,
6795 &l99_eos_o_10_10_10_1,
6796 &l99_eos_o_10_10_10_1,
6807 "1.1.1.1/32 LB 16 buckets via: "
6808 "label 99 over 10.10.10.1, "
6809 "adj over 10.10.11.1",
6810 "adj-v4 over 10.10.11.2");
6813 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6815 FIB_TEST(!fib_test_validate_entry(fei,
6816 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6817 16, // 3 choices spread over 16 buckets
6818 &l99_eos_o_10_10_10_1,
6819 &l99_eos_o_10_10_10_1,
6820 &l99_eos_o_10_10_10_1,
6821 &l99_eos_o_10_10_10_1,
6822 &l99_eos_o_10_10_10_1,
6823 &l99_eos_o_10_10_10_1,
6833 &disp_o_10_10_11_2),
6834 "24001/eos LB 16 buckets via: "
6835 "label 99 over 10.10.10.1, "
6836 "MPLS disp adj over 10.10.11.1",
6837 "MPLS disp adj-v4 over 10.10.11.2");
6839 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6841 FIB_TEST(!fib_test_validate_entry(fei,
6842 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6844 &l99_neos_o_10_10_10_1,
6845 &a_mpls_o_10_10_11_1),
6846 "24001/neos LB 2 buckets via: "
6847 "label 99 over 10.10.10.1, "
6848 "adj-mpls over 10.10.11.2");
6851 * remove the first path with the valid label
6853 fib_table_entry_path_remove(fib_index,
6858 tm->hw[0]->sw_if_index,
6859 ~0, // invalid fib index
6861 FIB_ROUTE_PATH_FLAG_NONE);
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,
6869 "1.1.1.1/32 LB 2 buckets via: "
6870 "adj over 10.10.11.1, "
6871 "adj-v4 over 10.10.11.2");
6873 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6875 FIB_TEST(!fib_test_validate_entry(fei,
6876 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6879 &disp_o_10_10_11_2),
6880 "24001/eos LB 2 buckets via: "
6881 "MPLS disp adj over 10.10.11.1, "
6882 "MPLS disp adj-v4 over 10.10.11.2");
6884 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6887 FIB_TEST(!fib_test_validate_entry(fei,
6888 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6890 &a_mpls_o_10_10_11_1),
6891 "24001/neos LB 1 buckets via: "
6892 "adj-mpls over 10.10.11.2");
6895 * remove the other path with a valid label
6897 fib_test_lb_bucket_t bucket_drop = {
6900 fib_test_lb_bucket_t mpls_bucket_drop = {
6903 .adj = DPO_PROTO_MPLS,
6907 fib_table_entry_path_remove(fib_index,
6912 tm->hw[1]->sw_if_index,
6913 ~0, // invalid fib index
6915 FIB_ROUTE_PATH_FLAG_NONE);
6917 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6918 FIB_TEST(!fib_test_validate_entry(fei,
6919 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6922 "1.1.1.1/32 LB 1 buckets via: "
6923 "adj over 10.10.11.2");
6925 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6927 FIB_TEST(!fib_test_validate_entry(fei,
6928 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6930 &disp_o_10_10_11_2),
6931 "24001/eos LB 1 buckets via: "
6932 "MPLS disp adj over 10.10.11.2");
6934 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6936 FIB_TEST(!fib_test_validate_entry(fei,
6937 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6940 "24001/neos LB 1 buckets via: DROP");
6943 * add back the path with the valid label
6946 vec_add1(l99, fml99);
6948 fib_table_entry_path_add(fib_index,
6951 FIB_ENTRY_FLAG_NONE,
6954 tm->hw[0]->sw_if_index,
6955 ~0, // invalid fib index
6958 FIB_ROUTE_PATH_FLAG_NONE);
6960 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6961 FIB_TEST(!fib_test_validate_entry(fei,
6962 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6964 &l99_eos_o_10_10_10_1,
6966 "1.1.1.1/32 LB 2 buckets via: "
6967 "label 99 over 10.10.10.1, "
6968 "adj over 10.10.11.2");
6970 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6972 FIB_TEST(!fib_test_validate_entry(fei,
6973 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6975 &l99_eos_o_10_10_10_1,
6976 &disp_o_10_10_11_2),
6977 "24001/eos LB 2 buckets via: "
6978 "label 99 over 10.10.10.1, "
6979 "MPLS disp adj over 10.10.11.2");
6981 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6983 FIB_TEST(!fib_test_validate_entry(fei,
6984 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6986 &l99_neos_o_10_10_10_1),
6987 "24001/neos LB 1 buckets via: "
6988 "label 99 over 10.10.10.1");
6991 * change the local label
6993 fib_table_entry_local_label_add(fib_index,
6997 fib_prefix_t pfx_25005_eos = {
6998 .fp_proto = FIB_PROTOCOL_MPLS,
7002 fib_prefix_t pfx_25005_neos = {
7003 .fp_proto = FIB_PROTOCOL_MPLS,
7005 .fp_eos = MPLS_NON_EOS,
7008 FIB_TEST((FIB_NODE_INDEX_INVALID ==
7009 fib_table_lookup(fib_index, &pfx_24001_eos)),
7010 "24001/eos removed after label change");
7011 FIB_TEST((FIB_NODE_INDEX_INVALID ==
7012 fib_table_lookup(fib_index, &pfx_24001_neos)),
7013 "24001/eos removed after label change");
7015 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7017 FIB_TEST(!fib_test_validate_entry(fei,
7018 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7020 &l99_eos_o_10_10_10_1,
7021 &disp_o_10_10_11_2),
7022 "25005/eos LB 2 buckets via: "
7023 "label 99 over 10.10.10.1, "
7024 "MPLS disp adj over 10.10.11.2");
7026 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
7028 FIB_TEST(!fib_test_validate_entry(fei,
7029 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7031 &l99_neos_o_10_10_10_1),
7032 "25005/neos LB 1 buckets via: "
7033 "label 99 over 10.10.10.1");
7036 * remove the local label.
7037 * the check that the MPLS entries are gone is done by the fact the
7038 * MPLS table is no longer present.
7040 fib_table_entry_local_label_remove(fib_index,
7044 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
7045 FIB_TEST(!fib_test_validate_entry(fei,
7046 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7048 &l99_eos_o_10_10_10_1,
7050 "24001/eos LB 2 buckets via: "
7051 "label 99 over 10.10.10.1, "
7052 "adj over 10.10.11.2");
7054 FIB_TEST((FIB_NODE_INDEX_INVALID ==
7055 mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)),
7056 "No more MPLS FIB entries => table removed");
7059 * add another via-entry for the recursive
7061 fib_prefix_t pfx_1_1_1_2_s_32 = {
7063 .fp_proto = FIB_PROTOCOL_IP4,
7065 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
7068 fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = {
7069 .type = FT_LB_LABEL_O_ADJ,
7071 .adj = ai_mpls_10_10_10_1,
7076 fib_mpls_label_t *l101 = NULL, fml101 = {
7079 vec_add1(l101, fml101);
7081 fei = fib_table_entry_update_one_path(fib_index,
7084 FIB_ENTRY_FLAG_NONE,
7087 tm->hw[0]->sw_if_index,
7088 ~0, // invalid fib index
7091 FIB_ROUTE_PATH_FLAG_NONE);
7093 FIB_TEST(!fib_test_validate_entry(fei,
7094 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7096 &l101_eos_o_10_10_10_1),
7097 "1.1.1.2/32 LB 1 buckets via: "
7098 "label 101 over 10.10.10.1");
7100 dpo_id_t non_eos_1_1_1_2 = DPO_INVALID;
7101 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7103 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7105 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7107 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7110 fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = {
7111 .type = FT_LB_LABEL_O_LB,
7113 .lb = non_eos_1_1_1_2.dpoi_index,
7118 fib_mpls_label_t *l1601 = NULL, fml1601 = {
7121 vec_add1(l1601, fml1601);
7123 l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index;
7125 fei = fib_table_entry_path_add(fib_index,
7128 FIB_ENTRY_FLAG_NONE,
7130 &pfx_1_1_1_2_s_32.fp_addr,
7135 FIB_ROUTE_PATH_FLAG_NONE);
7137 FIB_TEST(!fib_test_validate_entry(fei,
7138 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7140 &l1600_eos_o_1_1_1_1,
7141 &l1601_eos_o_1_1_1_2),
7142 "2.2.2.2/32 LB 2 buckets via: "
7143 "label 1600 via 1.1,1.1, "
7144 "label 16001 via 1.1.1.2");
7147 * update the via-entry so it no longer has an imp-null path.
7148 * the LB for the recursive can use an imp-null
7151 vec_add1(l_imp_null, fml_imp_null);
7153 fei = fib_table_entry_update_one_path(fib_index,
7156 FIB_ENTRY_FLAG_NONE,
7159 tm->hw[1]->sw_if_index,
7160 ~0, // invalid fib index
7163 FIB_ROUTE_PATH_FLAG_NONE);
7165 FIB_TEST(!fib_test_validate_entry(fei,
7166 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7169 "1.1.1.2/32 LB 1 buckets via: "
7172 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7173 FIB_TEST(!fib_test_validate_entry(fei,
7174 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7176 &l1600_eos_o_1_1_1_1,
7177 &l1601_eos_o_1_1_1_2),
7178 "2.2.2.2/32 LB 2 buckets via: "
7179 "label 1600 via 1.1,1.1, "
7180 "label 16001 via 1.1.1.2");
7183 * update the via-entry so it no longer has labelled paths.
7184 * the LB for the recursive should exclue this via form its LB
7186 fei = fib_table_entry_update_one_path(fib_index,
7189 FIB_ENTRY_FLAG_NONE,
7192 tm->hw[1]->sw_if_index,
7193 ~0, // invalid fib index
7196 FIB_ROUTE_PATH_FLAG_NONE);
7198 FIB_TEST(!fib_test_validate_entry(fei,
7199 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7202 "1.1.1.2/32 LB 1 buckets via: "
7205 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7206 FIB_TEST(!fib_test_validate_entry(fei,
7207 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7209 &l1600_eos_o_1_1_1_1),
7210 "2.2.2.2/32 LB 1 buckets via: "
7211 "label 1600 via 1.1,1.1");
7213 dpo_reset(&non_eos_1_1_1_1);
7214 dpo_reset(&non_eos_1_1_1_2);
7217 * Add a recursive with no out-labels. We expect to use the IP of the via
7219 fib_prefix_t pfx_2_2_2_3_s_32 = {
7221 .fp_proto = FIB_PROTOCOL_IP4,
7223 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
7226 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
7228 fib_table_entry_update_one_path(fib_index,
7231 FIB_ENTRY_FLAG_NONE,
7233 &pfx_1_1_1_1_s_32.fp_addr,
7238 FIB_ROUTE_PATH_FLAG_NONE);
7240 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7242 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7245 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
7248 .lb = ip_1_1_1_1.dpoi_index,
7252 fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
7253 FIB_TEST(!fib_test_validate_entry(fei,
7254 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7257 "2.2.2.2.3/32 LB 1 buckets via: "
7261 * Add a recursive with an imp-null out-label.
7262 * We expect to use the IP of the via
7264 fib_prefix_t pfx_2_2_2_4_s_32 = {
7266 .fp_proto = FIB_PROTOCOL_IP4,
7268 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
7272 fib_table_entry_update_one_path(fib_index,
7275 FIB_ENTRY_FLAG_NONE,
7277 &pfx_1_1_1_1_s_32.fp_addr,
7282 FIB_ROUTE_PATH_FLAG_NONE);
7284 fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
7285 FIB_TEST(!fib_test_validate_entry(fei,
7286 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7289 "2.2.2.2.4/32 LB 1 buckets via: "
7292 dpo_reset(&ip_1_1_1_1);
7295 * Create an entry with a deep label stack
7297 fib_prefix_t pfx_2_2_5_5_s_32 = {
7299 .fp_proto = FIB_PROTOCOL_IP4,
7301 .ip4.as_u32 = clib_host_to_net_u32(0x02020505),
7304 fib_test_lb_bucket_t ls_eos_o_10_10_10_1 = {
7305 .type = FT_LB_LABEL_STACK_O_ADJ,
7306 .label_stack_o_adj = {
7307 .adj = ai_mpls_10_10_11_1,
7308 .label_stack_size = 8,
7310 200, 201, 202, 203, 204, 205, 206, 207
7315 fib_mpls_label_t *label_stack = NULL;
7316 vec_validate(label_stack, 7);
7317 for (ii = 0; ii < 8; ii++)
7319 label_stack[ii].fml_value = ii + 200;
7322 fei = fib_table_entry_update_one_path(fib_index,
7325 FIB_ENTRY_FLAG_NONE,
7328 tm->hw[1]->sw_if_index,
7329 ~0, // invalid fib index
7332 FIB_ROUTE_PATH_FLAG_NONE);
7334 FIB_TEST(!fib_test_validate_entry(fei,
7335 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7337 &ls_eos_o_10_10_10_1),
7338 "2.2.5.5/32 LB 1 buckets via: "
7340 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
7345 fib_table_entry_delete(fib_index,
7349 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7350 FIB_TEST(!fib_test_validate_entry(fei,
7351 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7353 &l1600_eos_o_1_1_1_1),
7354 "2.2.2.2/32 LB 1 buckets via: "
7355 "label 1600 via 1.1,1.1");
7357 fib_table_entry_delete(fib_index,
7361 FIB_TEST(!fib_test_validate_entry(fei,
7362 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7365 "2.2.2.2/32 LB 1 buckets via: DROP");
7367 fib_table_entry_delete(fib_index,
7370 fib_table_entry_delete(fib_index,
7373 fib_table_entry_delete(fib_index,
7377 adj_unlock(ai_mpls_10_10_10_1);
7378 adj_unlock(ai_mpls_10_10_11_2);
7379 adj_unlock(ai_v4_10_10_11_1);
7380 adj_unlock(ai_v4_10_10_11_2);
7381 adj_unlock(ai_mpls_10_10_11_1);
7383 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
7386 local0_pfx.fp_len = 32;
7387 fib_table_entry_delete(fib_index,
7389 FIB_SOURCE_INTERFACE);
7390 local0_pfx.fp_len = 24;
7391 fib_table_entry_delete(fib_index,
7393 FIB_SOURCE_INTERFACE);
7394 local1_pfx.fp_len = 32;
7395 fib_table_entry_delete(fib_index,
7397 FIB_SOURCE_INTERFACE);
7398 local1_pfx.fp_len = 24;
7399 fib_table_entry_delete(fib_index,
7401 FIB_SOURCE_INTERFACE);
7404 * +1 for the drop LB in the MPLS tables.
7406 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
7407 "Load-balance resources freed %d of %d",
7408 lb_count+1, pool_elts(load_balance_pool));
7413 #define N_TEST_CHILDREN 4
7414 #define PARENT_INDEX 0
7416 typedef struct fib_node_test_t_
7421 fib_node_back_walk_ctx_t *ctxs;
7425 static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1];
7427 #define PARENT() (&fib_test_nodes[PARENT_INDEX].node)
7429 #define FOR_EACH_TEST_CHILD(_tc) \
7430 for (ii = 1, (_tc) = &fib_test_nodes[1]; \
7431 ii < N_TEST_CHILDREN+1; \
7432 ii++, (_tc) = &fib_test_nodes[ii])
7435 fib_test_child_get_node (fib_node_index_t index)
7437 return (&fib_test_nodes[index].node);
7440 static int fib_test_walk_spawns_walks;
7442 static fib_node_back_walk_rc_t
7443 fib_test_child_back_walk_notify (fib_node_t *node,
7444 fib_node_back_walk_ctx_t *ctx)
7446 fib_node_test_t *tc = (fib_node_test_t*) node;
7448 vec_add1(tc->ctxs, *ctx);
7450 if (1 == fib_test_walk_spawns_walks)
7451 fib_walk_sync(FIB_NODE_TYPE_TEST, tc->index, ctx);
7452 if (2 == fib_test_walk_spawns_walks)
7453 fib_walk_async(FIB_NODE_TYPE_TEST, tc->index,
7454 FIB_WALK_PRIORITY_HIGH, ctx);
7456 return (FIB_NODE_BACK_WALK_CONTINUE);
7460 fib_test_child_last_lock_gone (fib_node_t *node)
7462 fib_node_test_t *tc = (fib_node_test_t *)node;
7468 * The FIB walk's graph node virtual function table
7470 static const fib_node_vft_t fib_test_child_vft = {
7471 .fnv_get = fib_test_child_get_node,
7472 .fnv_last_lock = fib_test_child_last_lock_gone,
7473 .fnv_back_walk = fib_test_child_back_walk_notify,
7477 * the function (that should have been static but isn't so I can do this)
7478 * that processes the walk from the async queue,
7480 f64 fib_walk_process_queues(vlib_main_t * vm,
7482 u32 fib_walk_queue_get_size(fib_walk_priority_t prio);
7485 fib_test_walk (void)
7487 fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {};
7488 fib_node_test_t *tc;
7493 vm = vlib_get_main();
7494 fib_node_register_type(FIB_NODE_TYPE_TEST, &fib_test_child_vft);
7497 * init a fake node on which we will add children
7499 fib_node_init(&fib_test_nodes[PARENT_INDEX].node,
7500 FIB_NODE_TYPE_TEST);
7502 FOR_EACH_TEST_CHILD(tc)
7504 fib_node_init(&tc->node, FIB_NODE_TYPE_TEST);
7505 fib_node_lock(&tc->node);
7508 tc->sibling = fib_node_child_add(FIB_NODE_TYPE_TEST,
7510 FIB_NODE_TYPE_TEST, ii);
7514 * enqueue a walk across the parents children.
7516 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7518 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7519 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7520 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7521 "Parent has %d children pre-walk",
7522 fib_node_list_get_size(PARENT()->fn_children));
7525 * give the walk a large amount of time so it gets to the end
7527 fib_walk_process_queues(vm, 1);
7529 FOR_EACH_TEST_CHILD(tc)
7531 FIB_TEST(1 == vec_len(tc->ctxs),
7532 "%d child visitsed %d times",
7533 ii, vec_len(tc->ctxs));
7536 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7537 "Queue is empty post walk");
7538 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7539 "Parent has %d children post walk",
7540 fib_node_list_get_size(PARENT()->fn_children));
7543 * walk again. should be no increase in the number of visits, since
7544 * the walk will have terminated.
7546 fib_walk_process_queues(vm, 1);
7548 FOR_EACH_TEST_CHILD(tc)
7550 FIB_TEST(0 == vec_len(tc->ctxs),
7551 "%d child visitsed %d times",
7552 ii, vec_len(tc->ctxs));
7556 * schedule a low and hig priority walk. expect the high to be performed
7558 * schedule the high prio walk first so that it is further from the head
7559 * of the dependency list. that way it won't merge with the low one.
7561 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7562 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7564 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7565 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7566 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7567 FIB_WALK_PRIORITY_LOW, &low_ctx);
7569 fib_walk_process_queues(vm, 1);
7571 FOR_EACH_TEST_CHILD(tc)
7573 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7574 "%d child visitsed by high prio walk", ii);
7575 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7576 "%d child visitsed by low prio walk", ii);
7579 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7580 "Queue is empty post prio walk");
7581 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7582 "Parent has %d children post prio walk",
7583 fib_node_list_get_size(PARENT()->fn_children));
7586 * schedule 2 walks of the same priority that can be megred.
7587 * expect that each child is thus visited only once.
7589 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7590 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7592 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7593 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7594 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7595 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7597 fib_walk_process_queues(vm, 1);
7599 FOR_EACH_TEST_CHILD(tc)
7601 FIB_TEST(1 == vec_len(tc->ctxs),
7602 "%d child visitsed %d times during merge walk",
7603 ii, vec_len(tc->ctxs));
7606 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7607 "Queue is empty post merge walk");
7608 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7609 "Parent has %d children post merge walk",
7610 fib_node_list_get_size(PARENT()->fn_children));
7613 * schedule 2 walks of the same priority that cannot be megred.
7614 * expect that each child is thus visited twice and in the order
7615 * in which the walks were scheduled.
7617 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7618 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7620 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7621 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7622 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7623 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7625 fib_walk_process_queues(vm, 1);
7627 FOR_EACH_TEST_CHILD(tc)
7629 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7630 "%d child visitsed by high prio walk", ii);
7631 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7632 "%d child visitsed by low prio walk", ii);
7635 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7636 "Queue is empty post no-merge walk");
7637 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7638 "Parent has %d children post no-merge walk",
7639 fib_node_list_get_size(PARENT()->fn_children));
7642 * schedule a walk that makes one one child progress.
7643 * we do this by giving the queue draining process zero
7644 * time quanta. it's a do..while loop, so it does something.
7646 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7648 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7649 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7650 fib_walk_process_queues(vm, 0);
7652 FOR_EACH_TEST_CHILD(tc)
7654 if (ii == N_TEST_CHILDREN)
7656 FIB_TEST(1 == vec_len(tc->ctxs),
7657 "%d child visitsed %d times in zero quanta walk",
7658 ii, vec_len(tc->ctxs));
7662 FIB_TEST(0 == vec_len(tc->ctxs),
7663 "%d child visitsed %d times in 0 quanta walk",
7664 ii, vec_len(tc->ctxs));
7667 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7668 "Queue is not empty post zero quanta walk");
7669 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7670 "Parent has %d children post zero qunta walk",
7671 fib_node_list_get_size(PARENT()->fn_children));
7676 fib_walk_process_queues(vm, 0);
7678 FOR_EACH_TEST_CHILD(tc)
7680 if (ii >= N_TEST_CHILDREN-1)
7682 FIB_TEST(1 == vec_len(tc->ctxs),
7683 "%d child visitsed %d times in 2nd zero quanta walk",
7684 ii, vec_len(tc->ctxs));
7688 FIB_TEST(0 == vec_len(tc->ctxs),
7689 "%d child visitsed %d times in 2nd 0 quanta walk",
7690 ii, vec_len(tc->ctxs));
7693 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7694 "Queue is not empty post zero quanta walk");
7695 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7696 "Parent has %d children post zero qunta walk",
7697 fib_node_list_get_size(PARENT()->fn_children));
7700 * schedule another walk that will catch-up and merge.
7702 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7703 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7704 fib_walk_process_queues(vm, 1);
7706 FOR_EACH_TEST_CHILD(tc)
7708 if (ii >= N_TEST_CHILDREN-1)
7710 FIB_TEST(2 == vec_len(tc->ctxs),
7711 "%d child visitsed %d times in 2nd zero quanta merge walk",
7712 ii, vec_len(tc->ctxs));
7717 FIB_TEST(1 == vec_len(tc->ctxs),
7718 "%d child visitsed %d times in 2nd 0 quanta merge walk",
7719 ii, vec_len(tc->ctxs));
7723 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7724 "Queue is not empty post 2nd zero quanta merge walk");
7725 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7726 "Parent has %d children post 2nd zero qunta merge walk",
7727 fib_node_list_get_size(PARENT()->fn_children));
7730 * park a async walk in the middle of the list, then have an sync walk catch
7731 * it. same expectations as async catches async.
7733 high_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);
7738 fib_walk_process_queues(vm, 0);
7739 fib_walk_process_queues(vm, 0);
7741 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7743 FOR_EACH_TEST_CHILD(tc)
7745 if (ii >= N_TEST_CHILDREN-1)
7747 FIB_TEST(2 == vec_len(tc->ctxs),
7748 "%d child visitsed %d times in sync catches async walk",
7749 ii, vec_len(tc->ctxs));
7754 FIB_TEST(1 == vec_len(tc->ctxs),
7755 "%d child visitsed %d times in sync catches async walk",
7756 ii, vec_len(tc->ctxs));
7760 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7761 "Queue is not empty post 2nd zero quanta merge walk");
7762 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7763 "Parent has %d children post 2nd zero qunta merge walk",
7764 fib_node_list_get_size(PARENT()->fn_children));
7767 * make the parent a child of one of its children, thus inducing a routing loop.
7769 fib_test_nodes[PARENT_INDEX].sibling =
7770 fib_node_child_add(FIB_NODE_TYPE_TEST,
7771 1, // the first child
7776 * execute a sync walk from the parent. each child visited spawns more sync
7777 * walks. we expect the walk to terminate.
7779 fib_test_walk_spawns_walks = 1;
7781 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7783 FOR_EACH_TEST_CHILD(tc)
7786 * child 1 - which is last in the list - has the loop.
7787 * the other children a re thus visitsed first. the we meet
7788 * child 1. we go round the loop again, visting the other children.
7789 * then we meet the walk in the dep list and bail. child 1 is not visitsed
7794 FIB_TEST(1 == vec_len(tc->ctxs),
7795 "child %d visitsed %d times during looped sync walk",
7796 ii, vec_len(tc->ctxs));
7800 FIB_TEST(2 == vec_len(tc->ctxs),
7801 "child %d visitsed %d times during looped sync walk",
7802 ii, vec_len(tc->ctxs));
7806 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7807 "Parent has %d children post sync loop walk",
7808 fib_node_list_get_size(PARENT()->fn_children));
7811 * the walk doesn't reach the max depth because the infra knows that sync
7812 * meets sync implies a loop and bails early.
7814 FIB_TEST(high_ctx.fnbw_depth == 9,
7815 "Walk context depth %d post sync loop walk",
7816 high_ctx.fnbw_depth);
7819 * execute an async walk of the graph loop, with each child spawns sync walks
7821 high_ctx.fnbw_depth = 0;
7822 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7823 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7825 fib_walk_process_queues(vm, 1);
7827 FOR_EACH_TEST_CHILD(tc)
7830 * we don't really care how many times the children are visited, as long as
7831 * it is more than once.
7833 FIB_TEST(1 <= vec_len(tc->ctxs),
7834 "child %d visitsed %d times during looped aync spawns sync walk",
7835 ii, vec_len(tc->ctxs));
7840 * execute an async walk of the graph loop, with each child spawns async walks
7842 fib_test_walk_spawns_walks = 2;
7843 high_ctx.fnbw_depth = 0;
7844 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7845 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7847 fib_walk_process_queues(vm, 1);
7849 FOR_EACH_TEST_CHILD(tc)
7852 * we don't really care how many times the children are visited, as long as
7853 * it is more than once.
7855 FIB_TEST(1 <= vec_len(tc->ctxs),
7856 "child %d visitsed %d times during looped async spawns async walk",
7857 ii, vec_len(tc->ctxs));
7862 fib_node_child_remove(FIB_NODE_TYPE_TEST,
7863 1, // the first child
7864 fib_test_nodes[PARENT_INDEX].sibling);
7869 FOR_EACH_TEST_CHILD(tc)
7871 fib_node_child_remove(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7873 fib_node_deinit(&tc->node);
7874 fib_node_unlock(&tc->node);
7876 fib_node_deinit(PARENT());
7879 * The parent will be destroyed when the last lock on it goes.
7880 * this test ensures all the walk objects are unlocking it.
7882 FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed),
7883 "Parent was destroyed");
7889 * declaration of the otherwise static callback functions
7891 void fib_bfd_notify (bfd_listen_event_e event,
7892 const bfd_session_t *session);
7893 void adj_bfd_notify (bfd_listen_event_e event,
7894 const bfd_session_t *session);
7897 * Test BFD session interaction with FIB
7902 fib_node_index_t fei;
7907 /* via 10.10.10.1 */
7908 ip46_address_t nh_10_10_10_1 = {
7909 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
7911 /* via 10.10.10.2 */
7912 ip46_address_t nh_10_10_10_2 = {
7913 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
7915 /* via 10.10.10.10 */
7916 ip46_address_t nh_10_10_10_10 = {
7917 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
7919 n_feis = fib_entry_pool_size();
7924 * add interface routes. we'll assume this works. it's tested elsewhere
7926 fib_prefix_t pfx_10_10_10_10_s_24 = {
7928 .fp_proto = FIB_PROTOCOL_IP4,
7929 .fp_addr = nh_10_10_10_10,
7932 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_24,
7933 FIB_SOURCE_INTERFACE,
7934 (FIB_ENTRY_FLAG_CONNECTED |
7935 FIB_ENTRY_FLAG_ATTACHED),
7938 tm->hw[0]->sw_if_index,
7939 ~0, // invalid fib index
7942 FIB_ROUTE_PATH_FLAG_NONE);
7944 fib_prefix_t pfx_10_10_10_10_s_32 = {
7946 .fp_proto = FIB_PROTOCOL_IP4,
7947 .fp_addr = nh_10_10_10_10,
7949 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_32,
7950 FIB_SOURCE_INTERFACE,
7951 (FIB_ENTRY_FLAG_CONNECTED |
7952 FIB_ENTRY_FLAG_LOCAL),
7955 tm->hw[0]->sw_if_index,
7956 ~0, // invalid fib index
7959 FIB_ROUTE_PATH_FLAG_NONE);
7962 * A BFD session via a neighbour we do not yet know
7964 bfd_session_t bfd_10_10_10_1 = {
7968 .peer_addr = nh_10_10_10_1,
7971 .hop_type = BFD_HOP_TYPE_MULTI,
7972 .local_state = BFD_STATE_init,
7975 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7978 * A new entry will be created that forwards via the adj
7980 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
7983 tm->hw[0]->sw_if_index);
7984 fib_prefix_t pfx_10_10_10_1_s_32 = {
7985 .fp_addr = nh_10_10_10_1,
7987 .fp_proto = FIB_PROTOCOL_IP4,
7989 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
7992 .adj = ai_10_10_10_1,
7996 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7997 FIB_TEST(!fib_test_validate_entry(fei,
7998 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8001 "BFD sourced %U via %U",
8002 format_fib_prefix, &pfx_10_10_10_1_s_32,
8003 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
8006 * Delete the BFD session. Expect the fib_entry to be removed
8008 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8010 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
8011 FIB_TEST(FIB_NODE_INDEX_INVALID == fei,
8012 "BFD sourced %U removed",
8013 format_fib_prefix, &pfx_10_10_10_1_s_32);
8016 * Add the BFD source back
8018 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8021 * source the entry via the ADJ fib
8023 fei = fib_table_entry_path_add(0,
8024 &pfx_10_10_10_1_s_32,
8026 FIB_ENTRY_FLAG_ATTACHED,
8029 tm->hw[0]->sw_if_index,
8030 ~0, // invalid fib index
8033 FIB_ROUTE_PATH_FLAG_NONE);
8036 * Delete the BFD session. Expect the fib_entry to remain
8038 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8040 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
8041 FIB_TEST(!fib_test_validate_entry(fei,
8042 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8045 "BFD sourced %U remains via %U",
8046 format_fib_prefix, &pfx_10_10_10_1_s_32,
8047 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
8050 * Add the BFD source back
8052 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8055 * Create another ADJ FIB
8057 fib_prefix_t pfx_10_10_10_2_s_32 = {
8058 .fp_addr = nh_10_10_10_2,
8060 .fp_proto = FIB_PROTOCOL_IP4,
8062 fib_table_entry_path_add(0,
8063 &pfx_10_10_10_2_s_32,
8065 FIB_ENTRY_FLAG_ATTACHED,
8068 tm->hw[0]->sw_if_index,
8069 ~0, // invalid fib index
8072 FIB_ROUTE_PATH_FLAG_NONE);
8074 * A BFD session for the new ADJ FIB
8076 bfd_session_t bfd_10_10_10_2 = {
8080 .peer_addr = nh_10_10_10_2,
8083 .hop_type = BFD_HOP_TYPE_MULTI,
8084 .local_state = BFD_STATE_init,
8087 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_2);
8090 * remove the adj-fib source whilst the session is present
8093 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
8094 fib_table_entry_path_add(0,
8095 &pfx_10_10_10_2_s_32,
8097 FIB_ENTRY_FLAG_ATTACHED,
8100 tm->hw[0]->sw_if_index,
8101 ~0, // invalid fib index
8104 FIB_ROUTE_PATH_FLAG_NONE);
8107 * Before adding a recursive via the BFD tracked ADJ-FIBs,
8108 * bring one of the sessions UP, leave the other down
8110 bfd_10_10_10_1.local_state = BFD_STATE_up;
8111 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8112 bfd_10_10_10_2.local_state = BFD_STATE_down;
8113 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8116 * A recursive prefix via both of the ADJ FIBs
8118 fib_prefix_t pfx_200_0_0_0_s_24 = {
8119 .fp_proto = FIB_PROTOCOL_IP4,
8122 .ip4.as_u32 = clib_host_to_net_u32(0xc8000000),
8125 const dpo_id_t *dpo_10_10_10_1, *dpo_10_10_10_2;
8128 fib_entry_contribute_ip_forwarding(
8129 fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32));
8131 fib_entry_contribute_ip_forwarding(
8132 fib_table_lookup_exact_match(0, &pfx_10_10_10_2_s_32));
8134 fib_test_lb_bucket_t lb_o_10_10_10_1 = {
8137 .lb = dpo_10_10_10_1->dpoi_index,
8140 fib_test_lb_bucket_t lb_o_10_10_10_2 = {
8143 .lb = dpo_10_10_10_2->dpoi_index,
8148 * A prefix via the adj-fib that is BFD down => DROP
8150 fei = fib_table_entry_path_add(0,
8151 &pfx_200_0_0_0_s_24,
8153 FIB_ENTRY_FLAG_NONE,
8157 0, // default fib index
8160 FIB_ROUTE_PATH_FLAG_NONE);
8161 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8162 "%U resolves via drop",
8163 format_fib_prefix, &pfx_200_0_0_0_s_24);
8166 * add a path via the UP BFD adj-fib.
8167 * we expect that the DOWN BFD ADJ FIB is not used.
8169 fei = fib_table_entry_path_add(0,
8170 &pfx_200_0_0_0_s_24,
8172 FIB_ENTRY_FLAG_NONE,
8176 0, // default fib index
8179 FIB_ROUTE_PATH_FLAG_NONE);
8181 FIB_TEST(!fib_test_validate_entry(fei,
8182 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8185 "Recursive %U only UP BFD adj-fibs",
8186 format_fib_prefix, &pfx_200_0_0_0_s_24);
8189 * Send a BFD state change to UP - both sessions are now up
8190 * the recursive prefix should LB over both
8192 bfd_10_10_10_2.local_state = BFD_STATE_up;
8193 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8196 FIB_TEST(!fib_test_validate_entry(fei,
8197 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8201 "Recursive %U via both UP BFD adj-fibs",
8202 format_fib_prefix, &pfx_200_0_0_0_s_24);
8205 * Send a BFD state change to DOWN
8206 * the recursive prefix should exclude the down
8208 bfd_10_10_10_2.local_state = BFD_STATE_down;
8209 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8212 FIB_TEST(!fib_test_validate_entry(fei,
8213 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8216 "Recursive %U via only UP",
8217 format_fib_prefix, &pfx_200_0_0_0_s_24);
8220 * Delete the BFD session while it is in the DOWN state.
8221 * FIB should consider the entry's state as back up
8223 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_2);
8225 FIB_TEST(!fib_test_validate_entry(fei,
8226 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8230 "Recursive %U via both UP BFD adj-fibs post down session delete",
8231 format_fib_prefix, &pfx_200_0_0_0_s_24);
8234 * Delete the BFD other session while it is in the UP state.
8236 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8238 FIB_TEST(!fib_test_validate_entry(fei,
8239 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8243 "Recursive %U via both UP BFD adj-fibs post up session delete",
8244 format_fib_prefix, &pfx_200_0_0_0_s_24);
8249 fib_table_entry_delete(0, &pfx_200_0_0_0_s_24, FIB_SOURCE_API);
8250 fib_table_entry_delete(0, &pfx_10_10_10_1_s_32, FIB_SOURCE_ADJ);
8251 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
8253 fib_table_entry_delete(0, &pfx_10_10_10_10_s_32, FIB_SOURCE_INTERFACE);
8254 fib_table_entry_delete(0, &pfx_10_10_10_10_s_24, FIB_SOURCE_INTERFACE);
8256 adj_unlock(ai_10_10_10_1);
8258 * test no-one left behind
8260 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8261 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8264 * Single-hop BFD tests
8266 bfd_10_10_10_1.hop_type = BFD_HOP_TYPE_SINGLE;
8267 bfd_10_10_10_1.udp.key.sw_if_index = tm->hw[0]->sw_if_index;
8269 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8271 ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8274 tm->hw[0]->sw_if_index);
8276 * whilst the BFD session is not signalled, the adj is up
8278 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on uninit session");
8281 * bring the BFD session up
8283 bfd_10_10_10_1.local_state = BFD_STATE_up;
8284 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8285 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on UP session");
8288 * bring the BFD session down
8290 bfd_10_10_10_1.local_state = BFD_STATE_down;
8291 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8292 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on DOWN session");
8295 * add an attached next hop FIB entry via the down adj
8297 fib_prefix_t pfx_5_5_5_5_s_32 = {
8300 .as_u32 = clib_host_to_net_u32(0x05050505),
8304 .fp_proto = FIB_PROTOCOL_IP4,
8307 fei = fib_table_entry_path_add(0,
8310 FIB_ENTRY_FLAG_NONE,
8313 tm->hw[0]->sw_if_index,
8314 ~0, // invalid fib index
8317 FIB_ROUTE_PATH_FLAG_NONE);
8318 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8319 "%U resolves via drop",
8320 format_fib_prefix, &pfx_5_5_5_5_s_32);
8323 * Add a path via an ADJ that is up
8325 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8328 tm->hw[0]->sw_if_index);
8330 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
8333 .adj = ai_10_10_10_2,
8336 adj_o_10_10_10_1.adj.adj = ai_10_10_10_1;
8338 fei = fib_table_entry_path_add(0,
8341 FIB_ENTRY_FLAG_NONE,
8344 tm->hw[0]->sw_if_index,
8345 ~0, // invalid fib index
8348 FIB_ROUTE_PATH_FLAG_NONE);
8350 FIB_TEST(!fib_test_validate_entry(fei,
8351 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8354 "BFD sourced %U via %U",
8355 format_fib_prefix, &pfx_5_5_5_5_s_32,
8356 format_ip_adjacency, ai_10_10_10_2, FORMAT_IP_ADJACENCY_NONE);
8359 * Bring up the down session - should now LB
8361 bfd_10_10_10_1.local_state = BFD_STATE_up;
8362 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8363 FIB_TEST(!fib_test_validate_entry(fei,
8364 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8368 "BFD sourced %U via noth adjs",
8369 format_fib_prefix, &pfx_5_5_5_5_s_32);
8372 * remove the BFD session state from the adj
8374 adj_bfd_notify(BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8379 fib_table_entry_delete(0, &pfx_5_5_5_5_s_32, FIB_SOURCE_CLI);
8380 adj_unlock(ai_10_10_10_1);
8381 adj_unlock(ai_10_10_10_2);
8384 * test no-one left behind
8386 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8387 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8395 const mpls_label_t deag_label = 50;
8396 adj_index_t ai_mpls_10_10_10_1;
8397 dpo_id_t dpo = DPO_INVALID;
8398 const u32 lfib_index = 0;
8399 const u32 fib_index = 0;
8400 const dpo_id_t *dpo1;
8401 fib_node_index_t lfe;
8408 lb_count = pool_elts(load_balance_pool);
8410 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
8414 * MPLS enable an interface so we get the MPLS table created
8416 mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL);
8417 mpls_sw_interface_enable_disable(&mpls_main,
8418 tm->hw[0]->sw_if_index,
8421 ip46_address_t nh_10_10_10_1 = {
8422 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
8424 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8427 tm->hw[0]->sw_if_index);
8430 * Test the specials stack properly.
8432 fib_prefix_t exp_null_v6_pfx = {
8433 .fp_proto = FIB_PROTOCOL_MPLS,
8435 .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8436 .fp_payload_proto = DPO_PROTO_IP6,
8438 lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx);
8439 FIB_TEST((FIB_NODE_INDEX_INVALID != lfe),
8441 format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8442 format_mpls_eos_bit, MPLS_EOS);
8443 fib_entry_contribute_forwarding(lfe,
8444 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8446 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8447 lkd = lookup_dpo_get(dpo1->dpoi_index);
8449 FIB_TEST((fib_index == lkd->lkd_fib_index),
8450 "%U/%U is deag in %d %U",
8451 format_mpls_unicast_label, deag_label,
8452 format_mpls_eos_bit, MPLS_EOS,
8454 format_dpo_id, &dpo, 0);
8455 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8456 "%U/%U is dst deag",
8457 format_mpls_unicast_label, deag_label,
8458 format_mpls_eos_bit, MPLS_EOS);
8459 FIB_TEST((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table),
8460 "%U/%U is lookup in interface's table",
8461 format_mpls_unicast_label, deag_label,
8462 format_mpls_eos_bit, MPLS_EOS);
8463 FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto),
8464 "%U/%U is %U dst deag",
8465 format_mpls_unicast_label, deag_label,
8466 format_mpls_eos_bit, MPLS_EOS,
8467 format_dpo_proto, lkd->lkd_proto);
8470 * A route deag route for EOS
8472 fib_prefix_t pfx = {
8473 .fp_proto = FIB_PROTOCOL_MPLS,
8475 .fp_label = deag_label,
8476 .fp_payload_proto = DPO_PROTO_IP4,
8478 mpls_disp_dpo_t *mdd;
8479 lfe = fib_table_entry_path_add(lfib_index,
8482 FIB_ENTRY_FLAG_NONE,
8489 FIB_ROUTE_PATH_FLAG_NONE);
8491 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8493 format_mpls_unicast_label, deag_label,
8494 format_mpls_eos_bit, MPLS_EOS);
8496 fib_entry_contribute_forwarding(lfe,
8497 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8499 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8500 mdd = mpls_disp_dpo_get(dpo1->dpoi_index);
8502 FIB_TEST((FIB_MPLS_LSP_MODE_PIPE == mdd->mdd_mode),
8503 "%U/%U disp is pipe mode",
8504 format_mpls_unicast_label, deag_label,
8505 format_mpls_eos_bit, MPLS_EOS);
8507 lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index);
8509 FIB_TEST((fib_index == lkd->lkd_fib_index),
8510 "%U/%U is deag in %d %U",
8511 format_mpls_unicast_label, deag_label,
8512 format_mpls_eos_bit, MPLS_EOS,
8514 format_dpo_id, &dpo, 0);
8515 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8516 "%U/%U is dst deag",
8517 format_mpls_unicast_label, deag_label,
8518 format_mpls_eos_bit, MPLS_EOS);
8519 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8520 "%U/%U is %U dst deag",
8521 format_mpls_unicast_label, deag_label,
8522 format_mpls_eos_bit, MPLS_EOS,
8523 format_dpo_proto, lkd->lkd_proto);
8525 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8527 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8529 "%U/%U not present",
8530 format_mpls_unicast_label, deag_label,
8531 format_mpls_eos_bit, MPLS_EOS);
8535 * A route deag route for EOS with LSP mode uniform
8537 fib_mpls_label_t *l_pops = NULL, l_pop = {
8538 .fml_value = MPLS_LABEL_POP,
8539 .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM,
8541 vec_add1(l_pops, l_pop);
8542 lfe = fib_table_entry_path_add(lfib_index,
8545 FIB_ENTRY_FLAG_NONE,
8552 FIB_ROUTE_PATH_FLAG_NONE);
8554 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8556 format_mpls_unicast_label, deag_label,
8557 format_mpls_eos_bit, MPLS_EOS);
8559 fib_entry_contribute_forwarding(lfe,
8560 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8562 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8563 mdd = mpls_disp_dpo_get(dpo1->dpoi_index);
8565 FIB_TEST((FIB_MPLS_LSP_MODE_UNIFORM == mdd->mdd_mode),
8566 "%U/%U disp is uniform mode",
8567 format_mpls_unicast_label, deag_label,
8568 format_mpls_eos_bit, MPLS_EOS);
8570 lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index);
8572 FIB_TEST((fib_index == lkd->lkd_fib_index),
8573 "%U/%U is deag in %d %U",
8574 format_mpls_unicast_label, deag_label,
8575 format_mpls_eos_bit, MPLS_EOS,
8577 format_dpo_id, &dpo, 0);
8578 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8579 "%U/%U is dst deag",
8580 format_mpls_unicast_label, deag_label,
8581 format_mpls_eos_bit, MPLS_EOS);
8582 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8583 "%U/%U is %U dst deag",
8584 format_mpls_unicast_label, deag_label,
8585 format_mpls_eos_bit, MPLS_EOS,
8586 format_dpo_proto, lkd->lkd_proto);
8588 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8590 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8592 "%U/%U not present",
8593 format_mpls_unicast_label, deag_label,
8594 format_mpls_eos_bit, MPLS_EOS);
8598 * A route deag route for non-EOS
8600 pfx.fp_eos = MPLS_NON_EOS;
8601 lfe = fib_table_entry_path_add(lfib_index,
8604 FIB_ENTRY_FLAG_NONE,
8611 FIB_ROUTE_PATH_FLAG_NONE);
8613 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8615 format_mpls_unicast_label, deag_label,
8616 format_mpls_eos_bit, MPLS_NON_EOS);
8618 fib_entry_contribute_forwarding(lfe,
8619 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8621 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8622 lkd = lookup_dpo_get(dpo1->dpoi_index);
8624 FIB_TEST((fib_index == lkd->lkd_fib_index),
8625 "%U/%U is deag in %d %U",
8626 format_mpls_unicast_label, deag_label,
8627 format_mpls_eos_bit, MPLS_NON_EOS,
8629 format_dpo_id, &dpo, 0);
8630 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8631 "%U/%U is dst deag",
8632 format_mpls_unicast_label, deag_label,
8633 format_mpls_eos_bit, MPLS_NON_EOS);
8635 FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto),
8636 "%U/%U is %U dst deag",
8637 format_mpls_unicast_label, deag_label,
8638 format_mpls_eos_bit, MPLS_NON_EOS,
8639 format_dpo_proto, lkd->lkd_proto);
8641 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8643 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8645 "%U/%U not present",
8646 format_mpls_unicast_label, deag_label,
8647 format_mpls_eos_bit, MPLS_EOS);
8654 fib_prefix_t pfx_1200 = {
8656 .fp_proto = FIB_PROTOCOL_MPLS,
8658 .fp_eos = MPLS_NON_EOS,
8660 fib_test_lb_bucket_t neos_o_10_10_10_1 = {
8661 .type = FT_LB_LABEL_STACK_O_ADJ,
8662 .label_stack_o_adj = {
8663 .adj = ai_mpls_10_10_10_1,
8664 .label_stack_size = 4,
8668 .eos = MPLS_NON_EOS,
8671 dpo_id_t neos_1200 = DPO_INVALID;
8672 dpo_id_t ip_1200 = DPO_INVALID;
8673 fib_mpls_label_t *l200 = NULL;
8675 for (ii = 0; ii < 4; ii++)
8677 fib_mpls_label_t fml = {
8678 .fml_value = 200 + (ii * 100),
8680 vec_add1(l200, fml);
8683 lfe = fib_table_entry_update_one_path(fib_index,
8686 FIB_ENTRY_FLAG_NONE,
8689 tm->hw[0]->sw_if_index,
8690 ~0, // invalid fib index
8693 FIB_ROUTE_PATH_FLAG_NONE);
8695 FIB_TEST(!fib_test_validate_entry(lfe,
8696 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8698 &neos_o_10_10_10_1),
8699 "1200/0 LB 1 buckets via: "
8703 * A recursive route via the MPLS x-connect
8705 fib_prefix_t pfx_2_2_2_3_s_32 = {
8707 .fp_proto = FIB_PROTOCOL_IP4,
8709 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
8712 fib_route_path_t *rpaths = NULL, rpath = {
8713 .frp_proto = DPO_PROTO_MPLS,
8714 .frp_local_label = 1200,
8715 .frp_eos = MPLS_NON_EOS,
8716 .frp_sw_if_index = ~0, // recurive
8717 .frp_fib_index = 0, // Default MPLS fib
8719 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
8720 .frp_label_stack = NULL,
8722 vec_add1(rpaths, rpath);
8724 fib_table_entry_path_add2(fib_index,
8727 FIB_ENTRY_FLAG_NONE,
8731 * A labelled recursive route via the MPLS x-connect
8733 fib_prefix_t pfx_2_2_2_4_s_32 = {
8735 .fp_proto = FIB_PROTOCOL_IP4,
8737 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
8740 fib_mpls_label_t *l999 = NULL, fml_999 = {
8743 vec_add1(l999, fml_999);
8744 rpaths[0].frp_label_stack = l999,
8746 fib_table_entry_path_add2(fib_index,
8749 FIB_ENTRY_FLAG_NONE,
8752 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8753 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8755 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8756 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8759 fib_test_lb_bucket_t ip_o_1200 = {
8762 .lb = ip_1200.dpoi_index,
8765 fib_test_lb_bucket_t mpls_o_1200 = {
8766 .type = FT_LB_LABEL_O_LB,
8768 .lb = neos_1200.dpoi_index,
8774 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
8775 FIB_TEST(!fib_test_validate_entry(lfe,
8776 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8779 "2.2.2.2.3/32 LB 1 buckets via: label 1200 EOS");
8780 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
8781 FIB_TEST(!fib_test_validate_entry(lfe,
8782 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8785 "2.2.2.2.4/32 LB 1 buckets via: label 1200 non-EOS");
8787 fib_table_entry_delete(fib_index, &pfx_1200, FIB_SOURCE_API);
8788 fib_table_entry_delete(fib_index, &pfx_2_2_2_3_s_32, FIB_SOURCE_API);
8789 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8791 dpo_reset(&neos_1200);
8792 dpo_reset(&ip_1200);
8795 * A recursive via a label that does not exist
8797 fib_test_lb_bucket_t bucket_drop = {
8800 .adj = DPO_PROTO_IP4,
8803 fib_test_lb_bucket_t mpls_bucket_drop = {
8806 .adj = DPO_PROTO_MPLS,
8810 rpaths[0].frp_label_stack = NULL;
8811 lfe = fib_table_entry_path_add2(fib_index,
8814 FIB_ENTRY_FLAG_NONE,
8817 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8818 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8820 ip_o_1200.lb.lb = ip_1200.dpoi_index;
8822 FIB_TEST(!fib_test_validate_entry(lfe,
8823 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8826 "2.2.2.2.4/32 LB 1 buckets via: drop");
8827 lfe = fib_table_lookup(fib_index, &pfx_1200);
8828 FIB_TEST(!fib_test_validate_entry(lfe,
8829 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8832 "1200/neos LB 1 buckets via: ip4-DROP");
8833 FIB_TEST(!fib_test_validate_entry(lfe,
8834 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8837 "1200/neos LB 1 buckets via: mpls-DROP");
8839 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8841 dpo_reset(&ip_1200);
8844 * An rx-interface route.
8845 * like the tail of an mcast LSP
8847 dpo_id_t idpo = DPO_INVALID;
8849 interface_rx_dpo_add_or_lock(DPO_PROTO_IP4,
8850 tm->hw[0]->sw_if_index,
8853 fib_prefix_t pfx_2500 = {
8855 .fp_proto = FIB_PROTOCOL_MPLS,
8858 .fp_payload_proto = DPO_PROTO_IP4,
8860 fib_test_lb_bucket_t rx_intf_0 = {
8863 .adj = idpo.dpoi_index,
8867 lfe = fib_table_entry_update_one_path(fib_index,
8870 FIB_ENTRY_FLAG_NONE,
8873 tm->hw[0]->sw_if_index,
8874 ~0, // invalid fib index
8877 FIB_ROUTE_PATH_INTF_RX);
8878 FIB_TEST(!fib_test_validate_entry(lfe,
8879 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8882 "2500 rx-interface 0");
8883 fib_table_entry_delete(fib_index, &pfx_2500, FIB_SOURCE_API);
8886 * An MPLS mulicast entry
8888 fib_prefix_t pfx_3500 = {
8890 .fp_proto = FIB_PROTOCOL_MPLS,
8893 .fp_payload_proto = DPO_PROTO_IP4,
8895 fib_test_rep_bucket_t mc_0 = {
8896 .type = FT_REP_LABEL_O_ADJ,
8898 .adj = ai_mpls_10_10_10_1,
8903 fib_test_rep_bucket_t mc_intf_0 = {
8904 .type = FT_REP_INTF,
8906 .adj = idpo.dpoi_index,
8909 fib_mpls_label_t *l3300 = NULL, fml_3300 = {
8912 vec_add1(l3300, fml_3300);
8914 lfe = fib_table_entry_update_one_path(lfib_index,
8917 FIB_ENTRY_FLAG_MULTICAST,
8920 tm->hw[0]->sw_if_index,
8921 ~0, // invalid fib index
8924 FIB_ROUTE_PATH_FLAG_NONE);
8925 FIB_TEST(!fib_test_validate_entry(lfe,
8926 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8929 "3500 via replicate over 10.10.10.1");
8932 * MPLS Bud-node. Add a replication via an interface-receieve path
8934 lfe = fib_table_entry_path_add(lfib_index,
8937 FIB_ENTRY_FLAG_MULTICAST,
8940 tm->hw[0]->sw_if_index,
8941 ~0, // invalid fib index
8944 FIB_ROUTE_PATH_INTF_RX);
8945 FIB_TEST(!fib_test_validate_entry(lfe,
8946 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8950 "3500 via replicate over 10.10.10.1 and interface-rx");
8953 * Add a replication via an interface-free for-us path
8955 fib_test_rep_bucket_t mc_disp = {
8956 .type = FT_REP_DISP_MFIB_LOOKUP,
8958 .adj = idpo.dpoi_index,
8961 lfe = fib_table_entry_path_add(lfib_index,
8964 FIB_ENTRY_FLAG_MULTICAST,
8971 FIB_ROUTE_PATH_RPF_ID);
8972 FIB_TEST(!fib_test_validate_entry(lfe,
8973 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8978 "3500 via replicate over 10.10.10.1 and interface-rx");
8982 fib_table_entry_delete(fib_index, &pfx_3500, FIB_SOURCE_API);
8988 mpls_sw_interface_enable_disable(&mpls_main,
8989 tm->hw[0]->sw_if_index,
8991 mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
8993 FIB_TEST(0 == pool_elts(mpls_disp_dpo_pool),
8994 "mpls_disp_dpo resources freed %d of %d",
8995 0, pool_elts(mpls_disp_dpo_pool));
8996 FIB_TEST(lb_count == pool_elts(load_balance_pool),
8997 "Load-balance resources freed %d of %d",
8998 lb_count, pool_elts(load_balance_pool));
8999 FIB_TEST(0 == pool_elts(interface_rx_dpo_pool),
9000 "interface_rx_dpo resources freed %d of %d",
9001 0, pool_elts(interface_rx_dpo_pool));
9007 fib_test_inherit (void)
9009 fib_node_index_t fei;
9014 n_feis = fib_entry_pool_size();
9017 const ip46_address_t nh_10_10_10_1 = {
9018 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
9020 const ip46_address_t nh_10_10_10_2 = {
9021 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
9023 const ip46_address_t nh_10_10_10_3 = {
9024 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
9026 const ip46_address_t nh_10_10_10_16 = {
9027 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a10),
9029 const ip46_address_t nh_10_10_10_20 = {
9030 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a14),
9032 const ip46_address_t nh_10_10_10_21 = {
9033 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a15),
9035 const ip46_address_t nh_10_10_10_22 = {
9036 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a16),
9038 const ip46_address_t nh_10_10_10_255 = {
9039 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0aff),
9041 const ip46_address_t nh_10_10_10_0 = {
9042 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a00),
9044 const ip46_address_t nh_10_10_0_0 = {
9045 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0000),
9047 const ip46_address_t nh_11_11_11_11 = {
9048 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
9050 const ip46_address_t nh_11_11_11_0 = {
9051 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b00),
9055 * prefixes at the base of a sub-tree
9057 const fib_prefix_t pfx_10_10_10_21_s_32 = {
9059 .fp_proto = FIB_PROTOCOL_IP4,
9060 .fp_addr = nh_10_10_10_21,
9062 const fib_prefix_t pfx_10_10_10_22_s_32 = {
9064 .fp_proto = FIB_PROTOCOL_IP4,
9065 .fp_addr = nh_10_10_10_22,
9067 const fib_prefix_t pfx_10_10_10_255_s_32 = {
9069 .fp_proto = FIB_PROTOCOL_IP4,
9070 .fp_addr = nh_10_10_10_255,
9072 const u32 N_PLS = fib_path_list_pool_size();
9074 fib_table_entry_special_add(0,
9075 &pfx_10_10_10_21_s_32,
9077 FIB_ENTRY_FLAG_DROP);
9078 fib_table_entry_special_add(0,
9079 &pfx_10_10_10_22_s_32,
9081 FIB_ENTRY_FLAG_DROP);
9082 fib_table_entry_special_add(0,
9083 &pfx_10_10_10_255_s_32,
9085 FIB_ENTRY_FLAG_DROP);
9088 * source an entry that pushes its state down the sub-tree
9090 const fib_prefix_t pfx_10_10_10_16_s_28 = {
9092 .fp_proto = FIB_PROTOCOL_IP4,
9093 .fp_addr = nh_10_10_10_16,
9095 fib_table_entry_update_one_path(0,
9096 &pfx_10_10_10_16_s_28,
9098 FIB_ENTRY_FLAG_COVERED_INHERIT,
9101 tm->hw[0]->sw_if_index,
9105 FIB_ROUTE_PATH_FLAG_NONE);
9108 * this covering entry and all those below it should have
9109 * the same forwarding information.
9111 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9114 tm->hw[0]->sw_if_index);
9115 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
9118 .adj = ai_10_10_10_1,
9122 fei = fib_table_lookup(0, &pfx_10_10_10_16_s_28);
9123 FIB_TEST(!fib_test_validate_entry(fei,
9124 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9127 "%U via 10.10.10.1",
9128 format_fib_prefix, &pfx_10_10_10_16_s_28);
9129 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9130 FIB_TEST(!fib_test_validate_entry(fei,
9131 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9134 "%U via 10.10.10.1",
9135 format_fib_prefix, &pfx_10_10_10_21_s_32);
9136 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9137 FIB_TEST(!fib_test_validate_entry(fei,
9138 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9141 "%U via 10.10.10.1",
9142 format_fib_prefix, &pfx_10_10_10_22_s_32);
9143 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9144 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9145 "%U resolves via drop",
9146 format_fib_prefix, &pfx_10_10_10_255_s_32);
9149 * remove the inherting cover - covereds go back to drop
9151 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_API);
9153 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9154 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9155 "%U resolves via drop",
9156 format_fib_prefix, &pfx_10_10_10_21_s_32);
9159 * source an entry that pushes its state down the sub-tree
9161 const fib_prefix_t pfx_10_10_10_0_s_24 = {
9163 .fp_proto = FIB_PROTOCOL_IP4,
9164 .fp_addr = nh_10_10_10_0,
9166 fib_table_entry_update_one_path(0,
9167 &pfx_10_10_10_0_s_24,
9169 FIB_ENTRY_FLAG_COVERED_INHERIT,
9172 tm->hw[0]->sw_if_index,
9176 FIB_ROUTE_PATH_FLAG_NONE);
9179 * whole sub-tree now covered
9181 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9182 FIB_TEST(!fib_test_validate_entry(fei,
9183 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9186 "%U via 10.10.10.1",
9187 format_fib_prefix, &pfx_10_10_10_0_s_24);
9188 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9189 FIB_TEST(!fib_test_validate_entry(fei,
9190 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9193 "%U via 10.10.10.1",
9194 format_fib_prefix, &pfx_10_10_10_21_s_32);
9195 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9196 FIB_TEST(!fib_test_validate_entry(fei,
9197 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9200 "%U via 10.10.10.1",
9201 format_fib_prefix, &pfx_10_10_10_22_s_32);
9202 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9203 FIB_TEST(!fib_test_validate_entry(fei,
9204 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9207 "%U via 10.10.10.1",
9208 format_fib_prefix, &pfx_10_10_10_255_s_32);
9211 * insert a more specific into the sub-tree - expect inheritance
9212 * this one is directly covered by the root
9214 fib_table_entry_special_add(0,
9215 &pfx_10_10_10_16_s_28,
9217 FIB_ENTRY_FLAG_DROP);
9218 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9219 FIB_TEST(!fib_test_validate_entry(fei,
9220 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9223 "%U via 10.10.10.1",
9224 format_fib_prefix, &pfx_10_10_10_16_s_28);
9227 * insert a more specific into the sub-tree - expect inheritance
9228 * this one is indirectly covered by the root
9230 const fib_prefix_t pfx_10_10_10_20_s_30 = {
9232 .fp_proto = FIB_PROTOCOL_IP4,
9233 .fp_addr = nh_10_10_10_20,
9235 fib_table_entry_special_add(0,
9236 &pfx_10_10_10_20_s_30,
9238 FIB_ENTRY_FLAG_DROP);
9239 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_20_s_30);
9240 FIB_TEST(!fib_test_validate_entry(fei,
9241 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9244 "%U via 10.10.10.1",
9245 format_fib_prefix, &pfx_10_10_10_20_s_30);
9248 * remove the prefix from the middle of the sub-tree
9249 * the inherited source will be the only one remaining - expect
9250 * it to be withdrawn and hence the prefix is removed.
9252 fib_table_entry_special_remove(0,
9253 &pfx_10_10_10_20_s_30,
9255 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_20_s_30);
9256 FIB_TEST((FIB_NODE_INDEX_INVALID == fei),
9258 format_fib_prefix, &pfx_10_10_10_20_s_30);
9261 * inheriting source is modifed - expect the modification to be present
9262 * throughout the sub-tree
9264 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9267 tm->hw[0]->sw_if_index);
9268 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
9271 .adj = ai_10_10_10_2,
9275 fib_table_entry_update_one_path(0,
9276 &pfx_10_10_10_0_s_24,
9278 FIB_ENTRY_FLAG_COVERED_INHERIT,
9281 tm->hw[0]->sw_if_index,
9285 FIB_ROUTE_PATH_FLAG_NONE);
9286 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9287 FIB_TEST(!fib_test_validate_entry(fei,
9288 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9291 "%U via 10.10.10.2",
9292 format_fib_prefix, &pfx_10_10_10_21_s_32);
9293 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9294 FIB_TEST(!fib_test_validate_entry(fei,
9295 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9298 "%U via 10.10.10.2",
9299 format_fib_prefix, &pfx_10_10_10_22_s_32);
9300 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9301 FIB_TEST(!fib_test_validate_entry(fei,
9302 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9305 "%U via 10.10.10.2",
9306 format_fib_prefix, &pfx_10_10_10_255_s_32);
9307 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9308 FIB_TEST(!fib_test_validate_entry(fei,
9309 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9312 "%U via 10.10.10.2",
9313 format_fib_prefix, &pfx_10_10_10_0_s_24);
9315 fib_source_t hi_src = fib_source_allocate("test", 0x50,
9316 FIB_SOURCE_BH_SIMPLE);
9319 * add the source that replaces inherited state.
9320 * inheriting source is not the best, so it doesn't push state.
9322 fib_table_entry_update_one_path(0,
9323 &pfx_10_10_10_0_s_24,
9325 FIB_ENTRY_FLAG_NONE,
9328 tm->hw[0]->sw_if_index,
9332 FIB_ROUTE_PATH_FLAG_NONE);
9333 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9334 FIB_TEST(!fib_test_validate_entry(fei,
9335 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9338 "%U via 10.10.10.1",
9339 format_fib_prefix, &pfx_10_10_10_0_s_24);
9341 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9342 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9343 "%U resolves via drop",
9344 format_fib_prefix, &pfx_10_10_10_21_s_32);
9345 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9346 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9347 "%U resolves via drop",
9348 format_fib_prefix, &pfx_10_10_10_22_s_32);
9349 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9350 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9351 "%U resolves via drop",
9352 format_fib_prefix, &pfx_10_10_10_255_s_32);
9353 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9354 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
9355 "%U resolves via drop",
9356 format_fib_prefix, &pfx_10_10_10_16_s_28);
9359 * withdraw the higher priority source and expect the inherited to return
9360 * throughout the sub-tree
9362 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, hi_src);
9364 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9365 FIB_TEST(!fib_test_validate_entry(fei,
9366 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9369 "%U via 10.10.10.2",
9370 format_fib_prefix, &pfx_10_10_10_21_s_32);
9371 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9372 FIB_TEST(!fib_test_validate_entry(fei,
9373 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9376 "%U via 10.10.10.2",
9377 format_fib_prefix, &pfx_10_10_10_22_s_32);
9378 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9379 FIB_TEST(!fib_test_validate_entry(fei,
9380 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9383 "%U via 10.10.10.2",
9384 format_fib_prefix, &pfx_10_10_10_255_s_32);
9385 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9386 FIB_TEST(!fib_test_validate_entry(fei,
9387 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9390 "%U via 10.10.10.2",
9391 format_fib_prefix, &pfx_10_10_10_0_s_24);
9392 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9393 FIB_TEST(!fib_test_validate_entry(fei,
9394 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9397 "%U via 10.10.10.2",
9398 format_fib_prefix, &pfx_10_10_10_16_s_28);
9401 * source a covered entry in the sub-tree with the same inherting source
9402 * - expect that it now owns the sub-tree and thus over-rides its cover
9404 fib_table_entry_update_one_path(0,
9405 &pfx_10_10_10_16_s_28,
9407 FIB_ENTRY_FLAG_COVERED_INHERIT,
9410 tm->hw[0]->sw_if_index,
9414 FIB_ROUTE_PATH_FLAG_NONE);
9415 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_16_s_28);
9416 FIB_TEST(!fib_test_validate_entry(fei,
9417 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9420 "%U via 10.10.10.1",
9421 format_fib_prefix, &pfx_10_10_10_16_s_28);
9422 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9423 FIB_TEST(!fib_test_validate_entry(fei,
9424 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9427 "%U via 10.10.10.2",
9428 format_fib_prefix, &pfx_10_10_10_22_s_32);
9429 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9430 FIB_TEST(!fib_test_validate_entry(fei,
9431 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9434 "%U via 10.10.10.2",
9435 format_fib_prefix, &pfx_10_10_10_21_s_32);
9437 /* these two unaffected by the sub-tree change */
9438 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9439 FIB_TEST(!fib_test_validate_entry(fei,
9440 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9443 "%U via 10.10.10.2",
9444 format_fib_prefix, &pfx_10_10_10_255_s_32);
9445 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9446 FIB_TEST(!fib_test_validate_entry(fei,
9447 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9450 "%U via 10.10.10.2",
9451 format_fib_prefix, &pfx_10_10_10_0_s_24);
9454 * removes the more specific, expect the /24 to now re-owns the sub-tree
9456 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_API);
9458 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9459 FIB_TEST(!fib_test_validate_entry(fei,
9460 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9463 "%U via 10.10.10.2",
9464 format_fib_prefix, &pfx_10_10_10_16_s_28);
9465 FIB_TEST(!fib_test_validate_entry(fei,
9466 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9469 "%U via 10.10.10.2",
9470 format_fib_prefix, &pfx_10_10_10_21_s_32);
9471 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9472 FIB_TEST(!fib_test_validate_entry(fei,
9473 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9476 "%U via 10.10.10.2",
9477 format_fib_prefix, &pfx_10_10_10_22_s_32);
9478 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9479 FIB_TEST(!fib_test_validate_entry(fei,
9480 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9483 "%U via 10.10.10.2",
9484 format_fib_prefix, &pfx_10_10_10_255_s_32);
9485 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9486 FIB_TEST(!fib_test_validate_entry(fei,
9487 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9490 "%U via 10.10.10.2",
9491 format_fib_prefix, &pfx_10_10_10_0_s_24);
9493 * modify the /24. expect the new forwarding to be pushed down
9495 fib_table_entry_update_one_path(0,
9496 &pfx_10_10_10_0_s_24,
9498 FIB_ENTRY_FLAG_COVERED_INHERIT,
9501 tm->hw[0]->sw_if_index,
9505 FIB_ROUTE_PATH_FLAG_NONE);
9506 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9507 FIB_TEST(!fib_test_validate_entry(fei,
9508 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9511 "%U via 10.10.10.1",
9512 format_fib_prefix, &pfx_10_10_10_16_s_28);
9513 FIB_TEST(!fib_test_validate_entry(fei,
9514 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9517 "%U via 10.10.10.1",
9518 format_fib_prefix, &pfx_10_10_10_21_s_32);
9519 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9520 FIB_TEST(!fib_test_validate_entry(fei,
9521 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9524 "%U via 10.10.10.1",
9525 format_fib_prefix, &pfx_10_10_10_22_s_32);
9526 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9527 FIB_TEST(!fib_test_validate_entry(fei,
9528 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9531 "%U via 10.10.10.1",
9532 format_fib_prefix, &pfx_10_10_10_255_s_32);
9533 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9534 FIB_TEST(!fib_test_validate_entry(fei,
9535 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9538 "%U via 10.10.10.1",
9539 format_fib_prefix, &pfx_10_10_10_0_s_24);
9542 * add an entry less specific to /24. it should not own the /24's tree
9544 const fib_prefix_t pfx_10_10_0_0_s_16 = {
9546 .fp_proto = FIB_PROTOCOL_IP4,
9547 .fp_addr = nh_10_10_0_0,
9549 fib_table_entry_update_one_path(0,
9550 &pfx_10_10_0_0_s_16,
9552 FIB_ENTRY_FLAG_COVERED_INHERIT,
9555 tm->hw[0]->sw_if_index,
9559 FIB_ROUTE_PATH_FLAG_NONE);
9560 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9561 FIB_TEST(!fib_test_validate_entry(fei,
9562 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9565 "%U via 10.10.10.1",
9566 format_fib_prefix, &pfx_10_10_10_16_s_28);
9567 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_22_s_32);
9568 FIB_TEST(!fib_test_validate_entry(fei,
9569 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9572 "%U via 10.10.10.1",
9573 format_fib_prefix, &pfx_10_10_10_22_s_32);
9574 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_255_s_32);
9575 FIB_TEST(!fib_test_validate_entry(fei,
9576 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9579 "%U via 10.10.10.1",
9580 format_fib_prefix, &pfx_10_10_10_255_s_32);
9581 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9582 FIB_TEST(!fib_test_validate_entry(fei,
9583 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9586 "%U via 10.10.10.1",
9587 format_fib_prefix, &pfx_10_10_10_0_s_24);
9588 fei = fib_table_lookup_exact_match(0, &pfx_10_10_0_0_s_16);
9589 FIB_TEST(!fib_test_validate_entry(fei,
9590 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9593 "%U via 10.10.10.2",
9594 format_fib_prefix, &pfx_10_10_0_0_s_16);
9597 * Add/remove an interposer source to a new /32
9599 const fib_prefix_t pfx_11_11_11_11_s_32 = {
9601 .fp_proto = FIB_PROTOCOL_IP4,
9602 .fp_addr = nh_11_11_11_11,
9605 fib_table_entry_update_one_path(0,
9606 &pfx_11_11_11_11_s_32,
9608 FIB_ENTRY_FLAG_NONE,
9611 tm->hw[0]->sw_if_index,
9615 FIB_ROUTE_PATH_FLAG_NONE);
9617 dpo_id_t interposer = DPO_INVALID;
9618 fib_mpls_label_t *l99 = NULL, fml_99 = {
9621 vec_add1(l99, fml_99);
9623 mpls_label_dpo_create(l99,
9626 MPLS_LABEL_DPO_FLAG_NONE,
9627 punt_dpo_get(DPO_PROTO_MPLS),
9630 adj_index_t ai_10_10_10_3 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
9633 tm->hw[0]->sw_if_index);
9634 fib_test_lb_bucket_t adj_o_10_10_10_3 = {
9637 .adj = ai_10_10_10_3,
9640 fib_test_lb_bucket_t l99_o_10_10_10_3 = {
9641 .type = FT_LB_LABEL_O_ADJ,
9643 .adj = ai_10_10_10_3,
9649 fei = fib_table_entry_special_dpo_add(0,
9650 &pfx_11_11_11_11_s_32,
9652 FIB_ENTRY_FLAG_INTERPOSE,
9654 FIB_TEST(!fib_test_validate_entry(fei,
9655 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9658 "%U via interposer adj",
9659 format_fib_prefix,&pfx_11_11_11_11_s_32);
9661 fib_table_entry_special_remove(0,
9662 &pfx_11_11_11_11_s_32,
9663 FIB_SOURCE_SPECIAL);
9664 FIB_TEST(!fib_test_validate_entry(fei,
9665 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9668 "%U via 10.10.10.1",
9669 format_fib_prefix, &pfx_11_11_11_11_s_32);
9672 * remove and re-add the second best API source while the interpose
9675 fei = fib_table_entry_special_dpo_add(0,
9676 &pfx_11_11_11_11_s_32,
9678 FIB_ENTRY_FLAG_INTERPOSE,
9680 FIB_TEST(!fib_test_validate_entry(fei,
9681 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9684 "%U via interposer adj",
9685 format_fib_prefix,&pfx_11_11_11_11_s_32);
9687 FIB_TEST(2 == pool_elts(mpls_label_dpo_pool),
9688 "MPLS label pool: %d",
9689 pool_elts(mpls_label_dpo_pool));
9691 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
9694 * the interpose does not get stacked when there are not valid paths
9696 fib_test_lb_bucket_t bucket_drop = {
9699 .adj = DPO_PROTO_IP4,
9702 FIB_TEST(!fib_test_validate_entry(fei,
9703 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9707 format_fib_prefix,&pfx_11_11_11_11_s_32);
9709 fib_table_entry_update_one_path(0,
9710 &pfx_11_11_11_11_s_32,
9712 FIB_ENTRY_FLAG_NONE,
9715 tm->hw[0]->sw_if_index,
9719 FIB_ROUTE_PATH_FLAG_NONE);
9720 FIB_TEST(!fib_test_validate_entry(fei,
9721 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9724 "%U via interposer adj",
9725 format_fib_prefix,&pfx_11_11_11_11_s_32);
9726 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API);
9729 * add a cover for the interposed entry, so that we test it selects
9730 * the covers forwarding.
9732 const fib_prefix_t pfx_11_11_11_0_s_24 = {
9734 .fp_proto = FIB_PROTOCOL_IP4,
9735 .fp_addr = nh_11_11_11_0,
9737 fib_table_entry_update_one_path(0,
9738 &pfx_11_11_11_0_s_24,
9740 FIB_ENTRY_FLAG_NONE,
9743 tm->hw[0]->sw_if_index,
9747 FIB_ROUTE_PATH_FLAG_NONE);
9748 FIB_TEST(!fib_test_validate_entry(fei,
9749 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9752 "%U via interposer adj",
9753 format_fib_prefix,&pfx_11_11_11_11_s_32);
9756 * multiple interpose sources on the same entry. Only the high
9757 * priority source gets to add the interpose.
9759 dpo_id_t interposer2 = DPO_INVALID;
9760 fib_mpls_label_t *l100 = NULL, fml_100 = {
9763 vec_add1(l100, fml_100);
9765 mpls_label_dpo_create(l100,
9768 MPLS_LABEL_DPO_FLAG_NONE,
9769 punt_dpo_get(DPO_PROTO_MPLS),
9772 fei = fib_table_entry_special_dpo_add(0,
9773 &pfx_11_11_11_11_s_32,
9774 FIB_SOURCE_CLASSIFY,
9775 FIB_ENTRY_FLAG_INTERPOSE,
9777 FIB_TEST(!fib_test_validate_entry(fei,
9778 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9781 "%U via interposer label 99",
9782 format_fib_prefix,&pfx_11_11_11_11_s_32);
9784 fib_test_lb_bucket_t l100_o_10_10_10_3 = {
9785 .type = FT_LB_LABEL_O_ADJ,
9787 .adj = ai_10_10_10_3,
9793 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_SPECIAL);
9795 FIB_TEST(!fib_test_validate_entry(fei,
9796 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9798 &l100_o_10_10_10_3),
9799 "%U via interposer label 99",
9800 format_fib_prefix,&pfx_11_11_11_11_s_32);
9802 fib_table_entry_delete(0, &pfx_11_11_11_0_s_24, FIB_SOURCE_API);
9803 FIB_TEST(!fib_test_validate_entry(fei,
9804 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9808 format_fib_prefix,&pfx_11_11_11_11_s_32);
9809 fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_CLASSIFY);
9812 * update a source to/from interpose.
9814 /* fib_table_entry_update_one_path(0, */
9815 /* &pfx_11_11_11_0_s_24, */
9816 /* FIB_SOURCE_API, */
9817 /* FIB_ENTRY_FLAG_NONE, */
9818 /* DPO_PROTO_IP4, */
9819 /* &nh_10_10_10_3, */
9820 /* tm->hw[0]->sw_if_index, */
9824 /* FIB_ROUTE_PATH_FLAG_NONE); */
9825 /* fei = fib_table_entry_special_dpo_add(0, */
9826 /* &pfx_11_11_11_11_s_32, */
9827 /* FIB_SOURCE_API, */
9828 /* FIB_ENTRY_FLAG_INTERPOSE, */
9830 /* FIB_TEST(!fib_test_validate_entry(fei, */
9831 /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */
9833 /* &l99_o_10_10_10_3), */
9834 /* "%U via interposer label 99", */
9835 /* format_fib_prefix,&pfx_11_11_11_11_s_32); */
9837 /* FIB_TEST(3 == pool_elts(mpls_label_dpo_pool), */
9838 /* "MPLS label pool: %d", */
9839 /* pool_elts(mpls_label_dpo_pool)); */
9840 /* FIB_TEST((2 == mpls_label_dpo_get(interposer.dpoi_index)->mld_locks), */
9841 /* "Interposer %d locks", */
9842 /* mpls_label_dpo_get(interposer.dpoi_index)->mld_locks); */
9844 /* fib_table_entry_update_one_path(0, */
9845 /* &pfx_11_11_11_11_s_32, */
9846 /* FIB_SOURCE_API, */
9847 /* FIB_ENTRY_FLAG_NONE, */
9848 /* DPO_PROTO_IP4, */
9849 /* &nh_10_10_10_2, */
9850 /* tm->hw[0]->sw_if_index, */
9854 /* FIB_ROUTE_PATH_FLAG_NONE); */
9855 /* FIB_TEST(!fib_test_validate_entry(fei, */
9856 /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */
9858 /* &adj_o_10_10_10_2), */
9859 /* "%U via 10.10.10.2", */
9860 /* format_fib_prefix,&pfx_11_11_11_11_s_32); */
9862 /* FIB_TEST((1 == mpls_label_dpo_get(interposer.dpoi_index)->mld_locks), */
9863 /* "Interposer %d locks", */
9864 /* mpls_label_dpo_get(interposer.dpoi_index)->mld_locks); */
9865 /* FIB_TEST(2 == pool_elts(mpls_label_dpo_pool), */
9866 /* "MPLS label pool: %d", */
9867 /* pool_elts(mpls_label_dpo_pool)); */
9869 /* fei = fib_table_entry_special_dpo_add(0, */
9870 /* &pfx_11_11_11_11_s_32, */
9871 /* FIB_SOURCE_API, */
9872 /* FIB_ENTRY_FLAG_INTERPOSE, */
9874 /* FIB_TEST(!fib_test_validate_entry(fei, */
9875 /* FIB_FORW_CHAIN_TYPE_UNICAST_IP4, */
9877 /* &l99_o_10_10_10_3), */
9878 /* "%U via interposer label 99", */
9879 /* format_fib_prefix,&pfx_11_11_11_11_s_32); */
9881 /* fib_table_entry_delete(0, &pfx_11_11_11_11_s_32, FIB_SOURCE_API); */
9884 * Add/remove an interposer source from the top of the subtrie. The
9885 * interposer source is not inherited.
9887 fib_table_entry_update_one_path(0,
9888 &pfx_10_10_10_0_s_24,
9890 FIB_ENTRY_FLAG_COVERED_INHERIT,
9893 tm->hw[0]->sw_if_index,
9897 FIB_ROUTE_PATH_FLAG_NONE);
9898 fei = fib_table_entry_special_dpo_add(0,
9899 &pfx_10_10_10_0_s_24,
9901 FIB_ENTRY_FLAG_INTERPOSE,
9903 FIB_TEST(!fib_test_validate_entry(fei,
9904 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9907 "%U via interposer label",
9908 format_fib_prefix,&pfx_10_10_10_0_s_24);
9909 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9910 FIB_TEST(!fib_test_validate_entry(fei,
9911 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9915 format_fib_prefix, &pfx_10_10_10_21_s_32);
9917 fib_table_entry_special_remove(0,
9918 &pfx_10_10_10_0_s_24,
9919 FIB_SOURCE_SPECIAL);
9920 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_0_s_24);
9921 FIB_TEST(!fib_test_validate_entry(fei,
9922 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9925 "%U via 10.10.10.1",
9926 format_fib_prefix, &pfx_10_10_10_0_s_24);
9927 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9928 FIB_TEST(!fib_test_validate_entry(fei,
9929 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9932 "%U via via 10.10.10.1",
9933 format_fib_prefix, &pfx_10_10_10_21_s_32);
9936 * Add/remove an interposer source from the top of the subtrie. The
9937 * interposer source is inherited.
9939 fei = fib_table_entry_special_dpo_add(0,
9940 &pfx_10_10_10_0_s_24,
9942 (FIB_ENTRY_FLAG_COVERED_INHERIT |
9943 FIB_ENTRY_FLAG_INTERPOSE),
9945 FIB_TEST(!fib_test_validate_entry(fei,
9946 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9949 "%U via interposer label",
9950 format_fib_prefix,&pfx_10_10_10_0_s_24);
9952 /* interposer gets forwarding from the drop cli source */
9953 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_21_s_32);
9954 FIB_TEST(!fib_test_validate_entry(fei,
9955 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9959 format_fib_prefix,&pfx_10_10_10_21_s_32);
9961 fib_table_entry_update_one_path(0,
9962 &pfx_10_10_10_21_s_32,
9964 FIB_ENTRY_FLAG_NONE,
9967 tm->hw[0]->sw_if_index,
9971 FIB_ROUTE_PATH_FLAG_NONE);
9972 fib_table_entry_delete(0, &pfx_10_10_10_21_s_32, FIB_SOURCE_CLI);
9973 /* interposer gets forwarding from the API source */
9974 FIB_TEST(!fib_test_validate_entry(fei,
9975 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
9978 "%U via interposer label",
9979 format_fib_prefix,&pfx_10_10_10_21_s_32);
9984 fib_table_entry_delete(0, &pfx_10_10_10_22_s_32, FIB_SOURCE_CLI);
9985 fib_table_entry_delete(0, &pfx_10_10_10_21_s_32, FIB_SOURCE_API);
9986 fib_table_entry_delete(0, &pfx_10_10_10_16_s_28, FIB_SOURCE_CLI);
9987 fib_table_entry_delete(0, &pfx_10_10_10_255_s_32, FIB_SOURCE_CLI);
9988 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, FIB_SOURCE_API);
9989 fib_table_entry_delete(0, &pfx_10_10_0_0_s_16, FIB_SOURCE_API);
9990 fib_table_entry_delete(0, &pfx_10_10_10_0_s_24, FIB_SOURCE_SPECIAL);
9991 adj_unlock(ai_10_10_10_1);
9992 adj_unlock(ai_10_10_10_2);
9993 adj_unlock(ai_10_10_10_3);
9994 dpo_reset(&interposer);
9995 dpo_reset(&interposer2);
9996 FIB_TEST(0 == pool_elts(mpls_label_dpo_pool),
9997 "MPLS label pool empty: %d",
9998 pool_elts(mpls_label_dpo_pool));
9999 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
10000 FIB_TEST(N_PLS == fib_path_list_pool_size(),
10001 "number of path-lists: %d = %d",
10002 N_PLS, fib_path_list_pool_size());
10005 * test the v6 tree walk.
10006 * a /64 that covers everything. a /96 that covers one /128
10007 * a second /128 covered only by the /64.
10009 const fib_prefix_t pfx_2001_s_64 = {
10011 .fp_proto = FIB_PROTOCOL_IP6,
10015 [0] = clib_host_to_net_u64(0x2001000000000000),
10016 [1] = clib_host_to_net_u64(0x0000000000000000),
10021 const fib_prefix_t pfx_2001_1_s_96 = {
10023 .fp_proto = FIB_PROTOCOL_IP6,
10027 [0] = clib_host_to_net_u64(0x2001000000000000),
10028 [1] = clib_host_to_net_u64(0x1000000000000000),
10033 const fib_prefix_t pfx_2001_1_1_s_128 = {
10035 .fp_proto = FIB_PROTOCOL_IP6,
10039 [0] = clib_host_to_net_u64(0x2001000000000000),
10040 [1] = clib_host_to_net_u64(0x1000000000000001),
10045 const fib_prefix_t pfx_2001_0_1_s_128 = {
10047 .fp_proto = FIB_PROTOCOL_IP6,
10051 [0] = clib_host_to_net_u64(0x2001000000000000),
10052 [1] = clib_host_to_net_u64(0x0000000000000001),
10057 const ip46_address_t nh_3000_1 = {
10060 [0] = clib_host_to_net_u64(0x3000000000000000),
10061 [1] = clib_host_to_net_u64(0x0000000000000001),
10065 const ip46_address_t nh_3000_2 = {
10068 [0] = clib_host_to_net_u64(0x3000000000000000),
10069 [1] = clib_host_to_net_u64(0x0000000000000002),
10073 adj_index_t ai_3000_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
10076 tm->hw[0]->sw_if_index);
10077 adj_index_t ai_3000_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
10080 tm->hw[0]->sw_if_index);
10081 fib_test_lb_bucket_t adj_o_3000_1 = {
10087 fib_test_lb_bucket_t adj_o_3000_2 = {
10094 fib_table_entry_special_add(0,
10095 &pfx_2001_0_1_s_128,
10097 FIB_ENTRY_FLAG_DROP);
10098 fib_table_entry_special_add(0,
10099 &pfx_2001_1_1_s_128,
10101 FIB_ENTRY_FLAG_DROP);
10104 * /96 has inherited forwarding pushed down to its covered /128
10106 fib_table_entry_update_one_path(0,
10109 FIB_ENTRY_FLAG_COVERED_INHERIT,
10112 tm->hw[0]->sw_if_index,
10116 FIB_ROUTE_PATH_FLAG_NONE);
10117 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_s_96);
10118 FIB_TEST(!fib_test_validate_entry(fei,
10119 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10123 format_fib_prefix, &pfx_2001_1_s_96);
10124 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_1_s_128);
10125 FIB_TEST(!fib_test_validate_entry(fei,
10126 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10130 format_fib_prefix, &pfx_2001_1_1_s_128);
10131 fei = fib_table_lookup_exact_match(0, &pfx_2001_0_1_s_128);
10132 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
10133 "%U resolves via drop",
10134 format_fib_prefix, &pfx_2001_0_1_s_128);
10137 * /64 has inherited forwarding pushed down to all, but the /96
10138 * and its sub-tree remain unaffected.
10140 fib_table_entry_update_one_path(0,
10143 FIB_ENTRY_FLAG_COVERED_INHERIT,
10146 tm->hw[0]->sw_if_index,
10150 FIB_ROUTE_PATH_FLAG_NONE);
10152 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
10153 FIB_TEST(!fib_test_validate_entry(fei,
10154 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10158 format_fib_prefix, &pfx_2001_s_64);
10159 fei = fib_table_lookup_exact_match(0, &pfx_2001_0_1_s_128);
10160 FIB_TEST(!fib_test_validate_entry(fei,
10161 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10165 format_fib_prefix, &pfx_2001_0_1_s_128);
10167 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_s_96);
10168 FIB_TEST(!fib_test_validate_entry(fei,
10169 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10173 format_fib_prefix, &pfx_2001_1_s_96);
10174 fei = fib_table_lookup_exact_match(0, &pfx_2001_1_1_s_128);
10175 FIB_TEST(!fib_test_validate_entry(fei,
10176 FIB_FORW_CHAIN_TYPE_UNICAST_IP6,
10180 format_fib_prefix, &pfx_2001_1_1_s_128);
10185 fib_table_entry_delete(0, &pfx_2001_0_1_s_128, FIB_SOURCE_CLI);
10186 fib_table_entry_delete(0, &pfx_2001_1_1_s_128, FIB_SOURCE_CLI);
10187 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
10188 fib_table_entry_delete(0, &pfx_2001_1_s_96, FIB_SOURCE_API);
10189 adj_unlock(ai_3000_1);
10190 adj_unlock(ai_3000_2);
10193 * test no-one left behind
10195 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
10196 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
10202 fib_test_sticky (void)
10204 fib_route_path_t *r_paths = NULL;
10205 test_main_t *tm = &test_main;
10206 u32 ii, lb_count, pl_count;
10207 dpo_id_t dpo = DPO_INVALID;
10208 fib_node_index_t pl_index;
10212 fib_test_lb_bucket_t buckets[N_PATHS];
10213 bfd_session_t bfds[N_PATHS] = {{0}};
10215 lb_count = pool_elts(load_balance_pool);
10216 pl_count = fib_path_list_pool_size();
10218 for (ii = 0; ii < N_PATHS; ii++)
10220 ip46_address_t nh = {
10221 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
10225 ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
10227 &nh, tm->hw[0]->sw_if_index);
10229 buckets[ii].type = FT_LB_ADJ;
10230 buckets[ii].adj.adj = ai;
10232 bfds[ii].udp.key.peer_addr = nh;
10233 bfds[ii].udp.key.sw_if_index = tm->hw[0]->sw_if_index;
10234 bfds[ii].hop_type = BFD_HOP_TYPE_SINGLE;
10235 bfds[ii].local_state = BFD_STATE_init;
10236 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfds[ii]);
10237 bfds[ii].local_state = BFD_STATE_up;
10238 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[ii]);
10241 for (ii = 0; ii < N_PATHS; ii++)
10243 fib_route_path_t r_path = {
10244 .frp_proto = DPO_PROTO_IP4,
10246 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
10248 .frp_sw_if_index = tm->hw[0]->sw_if_index,
10250 .frp_fib_index = ~0,
10252 vec_add1(r_paths, r_path);
10255 pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths);
10256 fib_path_list_lock(pl_index);
10258 fib_path_list_contribute_forwarding(pl_index,
10259 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10260 FIB_PATH_LIST_FWD_FLAG_STICKY,
10263 FIB_TEST(!fib_test_validate_lb(&dpo,
10283 /* take down paths */
10284 bfds[0].local_state = BFD_STATE_down;
10285 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[0]);
10287 fib_path_list_contribute_forwarding(pl_index,
10288 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10289 FIB_PATH_LIST_FWD_FLAG_STICKY,
10292 FIB_TEST(!fib_test_validate_lb(&dpo,
10310 "Failed at shut-down path 0");
10312 bfds[7].local_state = BFD_STATE_down;
10313 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[7]);
10315 fib_path_list_contribute_forwarding(pl_index,
10316 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10317 FIB_PATH_LIST_FWD_FLAG_STICKY,
10320 FIB_TEST(!fib_test_validate_lb(&dpo,
10338 "Failed at shut-down path 7");
10340 /* paths back up */
10341 bfds[0].local_state = BFD_STATE_up;
10342 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[0]);
10343 bfds[7].local_state = BFD_STATE_up;
10344 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[7]);
10346 fib_path_list_contribute_forwarding(pl_index,
10347 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10348 FIB_PATH_LIST_FWD_FLAG_STICKY,
10351 FIB_TEST(!fib_test_validate_lb(&dpo,
10371 fib_path_list_unlock(pl_index);
10374 * non-power of 2 number of buckets
10376 fib_route_path_t *r_paths2 = NULL;
10378 r_paths2 = vec_dup(r_paths);
10379 _vec_len(r_paths2) = 3;
10381 pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths2);
10382 fib_path_list_lock(pl_index);
10384 fib_path_list_contribute_forwarding(pl_index,
10385 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10386 FIB_PATH_LIST_FWD_FLAG_STICKY,
10389 FIB_TEST(!fib_test_validate_lb(&dpo,
10409 bfds[1].local_state = BFD_STATE_down;
10410 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10412 fib_path_list_contribute_forwarding(pl_index,
10413 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10414 FIB_PATH_LIST_FWD_FLAG_STICKY,
10418 * path 1's buckets alternate between path 0 and 2
10420 FIB_TEST(!fib_test_validate_lb(&dpo,
10439 bfds[1].local_state = BFD_STATE_up;
10440 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10442 fib_path_list_unlock(pl_index);
10447 fib_route_path_t *r_paths3 = NULL;
10449 r_paths3 = vec_dup(r_paths);
10450 _vec_len(r_paths3) = 3;
10452 r_paths3[0].frp_weight = 3;
10454 pl_index = fib_path_list_create(FIB_PATH_LIST_FLAG_SHARED, r_paths3);
10455 fib_path_list_lock(pl_index);
10457 fib_path_list_contribute_forwarding(pl_index,
10458 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10459 FIB_PATH_LIST_FWD_FLAG_STICKY,
10462 FIB_TEST(!fib_test_validate_lb(&dpo,
10482 bfds[1].local_state = BFD_STATE_down;
10483 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10485 fib_path_list_contribute_forwarding(pl_index,
10486 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
10487 FIB_PATH_LIST_FWD_FLAG_STICKY,
10489 /* No attempt to Un-equal distribute the down path's buckets */
10490 FIB_TEST(!fib_test_validate_lb(&dpo,
10509 bfds[1].local_state = BFD_STATE_up;
10510 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfds[1]);
10513 fib_path_list_unlock(pl_index);
10516 vec_free(r_paths2);
10517 vec_free(r_paths3);
10519 FIB_TEST(lb_count == pool_elts(load_balance_pool), "no leaked LBs");
10520 FIB_TEST(pl_count == fib_path_list_pool_size(), "no leaked PLs");
10525 static clib_error_t *
10526 fib_test (vlib_main_t * vm,
10527 unformat_input_t * input,
10528 vlib_cli_command_t * cmd_arg)
10534 fib_test_mk_intf(4);
10536 if (unformat (input, "debug"))
10538 fib_test_do_debug = 1;
10541 if (unformat (input, "ip4"))
10543 res += fib_test_v4();
10545 else if (unformat (input, "ip6"))
10547 res += fib_test_v6();
10549 else if (unformat (input, "ip"))
10551 res += fib_test_v4();
10552 res += fib_test_v6();
10554 else if (unformat (input, "label"))
10556 res += fib_test_label();
10558 else if (unformat (input, "ae"))
10560 res += fib_test_ae();
10562 else if (unformat (input, "pref"))
10564 res += fib_test_pref();
10566 else if (unformat (input, "lfib"))
10568 res += lfib_test();
10570 else if (unformat (input, "walk"))
10572 res += fib_test_walk();
10574 else if (unformat (input, "bfd"))
10576 res += fib_test_bfd();
10578 else if (unformat (input, "inherit"))
10580 res += fib_test_inherit();
10582 else if (unformat (input, "sticky"))
10584 res += fib_test_sticky();
10588 res += fib_test_v4();
10589 res += fib_test_v6();
10590 res += fib_test_ae();
10591 res += fib_test_bfd();
10592 res += fib_test_pref();
10593 res += fib_test_label();
10594 res += fib_test_inherit();
10595 res += lfib_test();
10598 * fib-walk process must be disabled in order for the walk tests to work
10600 fib_walk_process_disable();
10601 res += fib_test_walk();
10602 fib_walk_process_enable();
10608 return clib_error_return(0, "FIB Unit Test Failed");
10616 VLIB_CLI_COMMAND (test_fib_command, static) = {
10617 .path = "test fib",
10618 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
10619 .function = fib_test,
10623 fib_test_init (vlib_main_t *vm)
10628 VLIB_INIT_FUNCTION (fib_test_init);