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/ip6_fib.h>
17 #include <vnet/fib/ip4_fib.h>
18 #include <vnet/fib/mpls_fib.h>
19 #include <vnet/adj/adj.h>
20 #include <vnet/dpo/load_balance.h>
21 #include <vnet/dpo/load_balance_map.h>
22 #include <vnet/dpo/mpls_label_dpo.h>
23 #include <vnet/dpo/lookup_dpo.h>
24 #include <vnet/dpo/drop_dpo.h>
25 #include <vnet/dpo/receive_dpo.h>
26 #include <vnet/dpo/ip_null_dpo.h>
28 #include <vnet/mpls/mpls.h>
30 #include <vnet/fib/fib_path_list.h>
31 #include <vnet/fib/fib_walk.h>
32 #include <vnet/fib/fib_node_list.h>
33 #include <vnet/fib/fib_urpf_list.h>
35 #define FIB_TEST_I(_cond, _comment, _args...) \
37 int _evald = (_cond); \
39 fformat(stderr, "FAIL:%d: " _comment "\n", \
42 fformat(stderr, "PASS:%d: " _comment "\n", \
47 #define FIB_TEST(_cond, _comment, _args...) \
49 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
51 ASSERT(!("FAIL: " _comment)); \
56 * A 'i'm not fussed is this is not efficient' store of test data
58 typedef struct test_main_t_ {
62 u32 hw_if_indicies[4];
66 vnet_hw_interface_t * hw[4];
69 static test_main_t test_main;
71 /* fake ethernet device class, distinct from "fake-ethX" */
72 static u8 * format_test_interface_name (u8 * s, va_list * args)
74 u32 dev_instance = va_arg (*args, u32);
75 return format (s, "test-eth%d", dev_instance);
78 static uword dummy_interface_tx (vlib_main_t * vm,
79 vlib_node_runtime_t * node,
82 clib_warning ("you shouldn't be here, leaking buffers...");
83 return frame->n_vectors;
87 test_interface_admin_up_down (vnet_main_t * vnm,
91 u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
92 VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
93 vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
97 VNET_DEVICE_CLASS (test_interface_device_class,static) = {
98 .name = "Test interface",
99 .format_device_name = format_test_interface_name,
100 .tx_function = dummy_interface_tx,
101 .admin_up_down_function = test_interface_admin_up_down,
104 static u8 *hw_address;
107 fib_test_mk_intf (u32 ninterfaces)
109 clib_error_t * error = NULL;
110 test_main_t *tm = &test_main;
114 ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
119 vec_add1(hw_address, byte);
122 for (i = 0; i < ninterfaces; i++)
126 error = ethernet_register_interface(vnet_get_main(),
127 test_interface_device_class.index,
130 &tm->hw_if_indicies[i],
131 /* flag change */ 0);
133 FIB_TEST((NULL == error), "ADD interface %d", i);
135 error = vnet_hw_interface_set_flags(vnet_get_main(),
136 tm->hw_if_indicies[i],
137 VNET_HW_INTERFACE_FLAG_LINK_UP);
138 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
139 tm->hw_if_indicies[i]);
140 vec_validate (ip4_main.fib_index_by_sw_if_index,
141 tm->hw[i]->sw_if_index);
142 vec_validate (ip6_main.fib_index_by_sw_if_index,
143 tm->hw[i]->sw_if_index);
144 ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
145 ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
147 error = vnet_sw_interface_set_flags(vnet_get_main(),
148 tm->hw[i]->sw_if_index,
149 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
150 FIB_TEST((NULL == error), "UP interface %d", i);
153 * re-eval after the inevitable realloc
155 for (i = 0; i < ninterfaces; i++)
157 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
158 tm->hw_if_indicies[i]);
162 #define FIB_TEST_REC_FORW(_rec_prefix, _via_prefix, _bucket) \
164 const dpo_id_t *_rec_dpo = fib_entry_contribute_ip_forwarding( \
165 fib_table_lookup_exact_match(fib_index, (_rec_prefix))); \
166 const dpo_id_t *_via_dpo = fib_entry_contribute_ip_forwarding( \
167 fib_table_lookup(fib_index, (_via_prefix))); \
168 FIB_TEST(!dpo_cmp(_via_dpo, \
169 load_balance_get_bucket(_rec_dpo->dpoi_index, \
171 "%U is recursive via %U", \
172 format_fib_prefix, (_rec_prefix), \
173 format_fib_prefix, _via_prefix); \
176 #define FIB_TEST_LB_BUCKET_VIA_ADJ(_prefix, _bucket, _ai) \
178 const dpo_id_t *_dpo = fib_entry_contribute_ip_forwarding( \
179 fib_table_lookup_exact_match(fib_index, (_prefix))); \
180 const dpo_id_t *_dpo1 = \
181 load_balance_get_bucket(_dpo->dpoi_index, _bucket); \
182 FIB_TEST(DPO_ADJACENCY == _dpo1->dpoi_type, "type is %U", \
183 format_dpo_type, _dpo1->dpoi_type); \
184 FIB_TEST((_ai == _dpo1->dpoi_index), \
185 "%U bucket %d resolves via %U", \
186 format_fib_prefix, (_prefix), \
188 format_dpo_id, _dpo1, 0); \
191 #define FIB_TEST_RPF(_cond, _comment, _args...) \
193 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
199 fib_test_urpf_is_equal (fib_node_index_t fei,
200 fib_forward_chain_type_t fct,
203 dpo_id_t dpo = DPO_INVALID;
204 fib_urpf_list_t *urpf;
211 fib_entry_contribute_forwarding(fei, fct, &dpo);
212 ui = load_balance_get_urpf(dpo.dpoi_index);
214 urpf = fib_urpf_list_get(ui);
216 FIB_TEST_RPF(num == vec_len(urpf->furpf_itfs),
217 "RPF:%U len %d == %d",
218 format_fib_urpf_list, ui,
219 num, vec_len(urpf->furpf_itfs));
220 FIB_TEST_RPF(num == fib_urpf_check_size(ui),
221 "RPF:%U check-size %d == %d",
222 format_fib_urpf_list, ui,
223 num, vec_len(urpf->furpf_itfs));
225 for (ii = 0; ii < num; ii++)
227 adj_index_t ai = va_arg(ap, adj_index_t);
229 FIB_TEST_RPF(ai == urpf->furpf_itfs[ii],
230 "RPF:%d item:%d - %d == %d",
231 ui, ii, ai, urpf->furpf_itfs[ii]);
232 FIB_TEST_RPF(fib_urpf_check(ui, ai),
245 fib_test_build_rewrite (u8 *eth_addr)
249 vec_validate(rewrite, 13);
251 memcpy(rewrite, eth_addr, 6);
252 memcpy(rewrite+6, eth_addr, 6);
257 typedef enum fib_test_lb_bucket_type_t_ {
263 } fib_test_lb_bucket_type_t;
265 typedef struct fib_test_lb_bucket_t_ {
266 fib_test_lb_bucket_type_t type;
297 } fib_test_lb_bucket_t;
299 #define FIB_TEST_LB(_cond, _comment, _args...) \
301 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
307 fib_test_validate_lb_v (const load_balance_t *lb,
314 FIB_TEST_LB((n_buckets == lb->lb_n_buckets), "n_buckets = %d", lb->lb_n_buckets);
316 for (bucket = 0; bucket < n_buckets; bucket++)
318 const fib_test_lb_bucket_t *exp;
320 exp = va_arg(ap, fib_test_lb_bucket_t*);
321 dpo = load_balance_get_bucket_i(lb, bucket);
325 case FT_LB_LABEL_O_ADJ:
327 const mpls_label_dpo_t *mld;
329 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
330 "bucket %d stacks on %U",
332 format_dpo_type, dpo->dpoi_type);
334 mld = mpls_label_dpo_get(dpo->dpoi_index);
335 hdr = clib_net_to_host_u32(mld->mld_hdr.label_exp_s_ttl);
337 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
338 exp->label_o_adj.label),
339 "bucket %d stacks on label %d",
341 exp->label_o_adj.label);
343 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
344 exp->label_o_adj.eos),
345 "bucket %d stacks on label %d %U",
347 exp->label_o_adj.label,
348 format_mpls_eos_bit, exp->label_o_adj.eos);
350 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
351 "bucket %d label stacks on %U",
353 format_dpo_type, mld->mld_dpo.dpoi_type);
355 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
356 "bucket %d label stacks on adj %d",
358 exp->label_o_adj.adj);
361 case FT_LB_LABEL_O_LB:
363 const mpls_label_dpo_t *mld;
366 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
367 "bucket %d stacks on %U",
369 format_dpo_type, dpo->dpoi_type);
371 mld = mpls_label_dpo_get(dpo->dpoi_index);
372 hdr = clib_net_to_host_u32(mld->mld_hdr.label_exp_s_ttl);
374 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
375 exp->label_o_lb.label),
376 "bucket %d stacks on label %d",
378 exp->label_o_lb.label);
380 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
381 exp->label_o_lb.eos),
382 "bucket %d stacks on label %d %U",
384 exp->label_o_lb.label,
385 format_mpls_eos_bit, exp->label_o_lb.eos);
387 FIB_TEST_LB((DPO_LOAD_BALANCE == mld->mld_dpo.dpoi_type),
388 "bucket %d label stacks on %U",
390 format_dpo_type, mld->mld_dpo.dpoi_type);
392 FIB_TEST_LB((exp->label_o_lb.lb == mld->mld_dpo.dpoi_index),
393 "bucket %d label stacks on LB %d",
399 FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
400 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
401 "bucket %d stacks on %U",
403 format_dpo_type, dpo->dpoi_type);
404 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
405 "bucket %d stacks on adj %d",
410 FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
411 "bucket %d stacks on %U",
413 format_dpo_type, dpo->dpoi_type);
414 FIB_TEST_LB((exp->lb.lb == dpo->dpoi_index),
415 "bucket %d stacks on lb %d",
420 FIB_TEST_I((DPO_DROP == dpo->dpoi_type),
421 "bucket %d stacks on %U",
423 format_dpo_type, dpo->dpoi_type);
424 FIB_TEST_LB((exp->special.adj == dpo->dpoi_index),
425 "bucket %d stacks on drop %d",
435 fib_test_validate_entry (fib_node_index_t fei,
436 fib_forward_chain_type_t fct,
440 const load_balance_t *lb;
441 dpo_id_t dpo = DPO_INVALID;
448 va_start(ap, n_buckets);
450 fib_entry_get_prefix(fei, &pfx);
451 fib_index = fib_entry_get_fib_index(fei);
452 fib_entry_contribute_forwarding(fei, fct, &dpo);
454 FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type),
456 format_dpo_type, dpo.dpoi_type);
457 lb = load_balance_get(dpo.dpoi_index);
459 res = fib_test_validate_lb_v(lb, n_buckets, ap);
462 * ensure that the LB contributed by the entry is the
463 * same as the LB in the forwarding tables
465 switch (pfx.fp_proto)
467 case FIB_PROTOCOL_IP4:
468 fw_lbi = ip4_fib_forwarding_lookup(fib_index, &pfx.fp_addr.ip4);
470 case FIB_PROTOCOL_IP6:
471 fw_lbi = ip6_fib_table_fwding_lookup(&ip6_main, fib_index, &pfx.fp_addr.ip6);
473 case FIB_PROTOCOL_MPLS:
475 mpls_unicast_header_t hdr = {
476 .label_exp_s_ttl = 0,
479 vnet_mpls_uc_set_label(&hdr.label_exp_s_ttl, pfx.fp_label);
480 vnet_mpls_uc_set_s(&hdr.label_exp_s_ttl, pfx.fp_eos);
481 hdr.label_exp_s_ttl = clib_host_to_net_u32(hdr.label_exp_s_ttl);
483 fw_lbi = mpls_fib_table_forwarding_lookup(fib_index, &hdr);
489 FIB_TEST_LB((fw_lbi == dpo.dpoi_index),
490 "Contributed LB = FW LB: %U\n %U",
491 format_load_balance, fw_lbi, 0,
492 format_load_balance, dpo.dpoi_index, 0);
505 * In the default table check for the presence and correct forwarding
506 * of the special entries
508 fib_node_index_t dfrt, fei, ai, ai2, locked_ai, ai_01, ai_02, ai_03;
509 const dpo_id_t *dpo, *dpo1, *dpo2, *dpo_drop;
510 const ip_adjacency_t *adj;
511 const load_balance_t *lb;
517 ip46_address_t nh_10_10_10_1 = {
518 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
521 ip46_address_t nh_10_10_10_2 = {
522 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
527 /* Find or create FIB table 11 */
528 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11);
530 for (ii = 0; ii < 4; ii++)
532 ip4_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
535 fib_prefix_t pfx_0_0_0_0_s_0 = {
537 .fp_proto = FIB_PROTOCOL_IP4,
547 .fp_proto = FIB_PROTOCOL_IP4,
555 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
557 dfrt = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
558 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
559 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
560 "Default route is DROP");
563 fei = fib_table_lookup(fib_index, &pfx);
564 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all zeros route present");
565 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
566 "all 0s route is DROP");
568 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xffffffff);
570 fei = fib_table_lookup(fib_index, &pfx);
571 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all ones route present");
572 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
573 "all 1s route is DROP");
575 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xe0000000);
577 fei = fib_table_lookup(fib_index, &pfx);
578 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all-mcast route present");
579 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
580 "all-mcast route is DROP");
582 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xf0000000);
584 fei = fib_table_lookup(fib_index, &pfx);
585 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "class-e route present");
586 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
587 "class-e route is DROP");
590 * at this stage there are 5 entries in the test FIB (plus 5 in the default),
591 * all of which are special sourced and so none of which share path-lists.
592 * There are also 6 entries, and 6 non-shared path-lists, in the v6 default
596 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
597 FIB_TEST((NBR == fib_path_list_pool_size()), "path list pool size is %d",
598 fib_path_list_pool_size());
599 FIB_TEST((NBR == fib_entry_pool_size()), "entry pool size is %d",
600 fib_entry_pool_size());
603 * add interface routes.
604 * validate presence of /24 attached and /32 recieve.
605 * test for the presence of the receive address in the glean and local adj
607 fib_prefix_t local_pfx = {
609 .fp_proto = FIB_PROTOCOL_IP4,
612 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
617 fib_table_entry_update_one_path(fib_index, &local_pfx,
618 FIB_SOURCE_INTERFACE,
619 (FIB_ENTRY_FLAG_CONNECTED |
620 FIB_ENTRY_FLAG_ATTACHED),
623 tm->hw[0]->sw_if_index,
624 ~0, // invalid fib index
627 FIB_ROUTE_PATH_FLAG_NONE);
628 fei = fib_table_lookup(fib_index, &local_pfx);
629 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
630 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
631 fib_entry_get_flags(fei)),
632 "Flags set on attached interface");
634 ai = fib_entry_get_adj(fei);
635 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
637 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
638 "attached interface adj is glean");
639 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
640 &adj->sub_type.glean.receive_addr)),
641 "attached interface adj is receive ok");
643 local_pfx.fp_len = 32;
644 fib_table_entry_update_one_path(fib_index, &local_pfx,
645 FIB_SOURCE_INTERFACE,
646 (FIB_ENTRY_FLAG_CONNECTED |
647 FIB_ENTRY_FLAG_LOCAL),
650 tm->hw[0]->sw_if_index,
651 ~0, // invalid fib index
654 FIB_ROUTE_PATH_FLAG_NONE);
655 fei = fib_table_lookup(fib_index, &local_pfx);
656 FIB_TEST(((FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_CONNECTED) ==
657 fib_entry_get_flags(fei)),
658 "Flags set on local interface");
660 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
662 dpo = fib_entry_contribute_ip_forwarding(fei);
663 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
664 "RPF list for local length 0");
665 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
666 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
667 "local interface adj is local");
668 receive_dpo_t *rd = receive_dpo_get(dpo->dpoi_index);
670 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
672 "local interface adj is receive ok");
674 FIB_TEST((2 == fib_table_get_num_entries(fib_index,
676 FIB_SOURCE_INTERFACE)),
677 "2 Interface Source'd prefixes");
680 * +2 interface routes +2 non-shared path-lists
682 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
683 FIB_TEST((NBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
684 fib_path_list_pool_size());
685 FIB_TEST((NBR+2 == fib_entry_pool_size()), "entry pool size is %d",
686 fib_entry_pool_size());
689 * Modify the default route to be via an adj not yet known.
690 * this sources the defalut route with the API source, which is
691 * a higher preference to the DEFAULT_ROUTE source
693 pfx.fp_addr.ip4.as_u32 = 0;
695 fib_table_entry_path_add(fib_index, &pfx,
700 tm->hw[0]->sw_if_index,
701 ~0, // invalid fib index
704 FIB_ROUTE_PATH_FLAG_NONE);
705 fei = fib_table_lookup(fib_index, &pfx);
706 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
707 "Flags set on API route");
709 FIB_TEST((fei == dfrt), "default route same index");
710 ai = fib_entry_get_adj(fei);
711 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
713 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
714 "adj is incomplete");
715 FIB_TEST((0 == ip46_address_cmp(&nh_10_10_10_1, &adj->sub_type.nbr.next_hop)),
716 "adj nbr next-hop ok");
717 FIB_TEST((1 == fib_table_get_num_entries(fib_index,
720 "1 API Source'd prefixes");
723 * find the adj in the shared db
725 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
728 tm->hw[0]->sw_if_index);
729 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
730 adj_unlock(locked_ai);
733 * +1 shared path-list
735 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
736 fib_path_list_db_size());
737 FIB_TEST((NBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
738 fib_path_list_pool_size());
739 FIB_TEST((NBR+2 == fib_entry_pool_size()), "entry pool size is %d",
740 fib_entry_pool_size());
743 * remove the API source from the default route. We expected
744 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
746 pfx.fp_addr.ip4.as_u32 = 0;
748 fib_table_entry_path_remove(fib_index, &pfx,
752 tm->hw[0]->sw_if_index,
753 ~0, // non-recursive path, so no FIB index
755 FIB_ROUTE_PATH_FLAG_NONE);
757 fei = fib_table_lookup(fib_index, &pfx);
759 FIB_TEST((fei == dfrt), "default route same index");
760 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
761 "Default route is DROP");
764 * -1 shared-path-list
766 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
767 FIB_TEST((NBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
768 fib_path_list_pool_size());
769 FIB_TEST((NBR+2 == fib_entry_pool_size()), "entry pool size is %d",
770 fib_entry_pool_size());
773 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
775 fib_prefix_t pfx_10_10_10_1_s_32 = {
777 .fp_proto = FIB_PROTOCOL_IP4,
780 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
783 fib_prefix_t pfx_10_10_10_2_s_32 = {
785 .fp_proto = FIB_PROTOCOL_IP4,
788 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
791 fib_prefix_t pfx_11_11_11_11_s_32 = {
793 .fp_proto = FIB_PROTOCOL_IP4,
796 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
800 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
803 ip46_address_t nh_12_12_12_12 = {
804 .ip4.as_u32 = clib_host_to_net_u32(0x0c0c0c0c),
806 adj_index_t ai_12_12_12_12;
809 * Add a route via an incomplete ADJ. then complete the ADJ
810 * Expect the route LB is updated to use complete adj type.
812 fei = fib_table_entry_update_one_path(fib_index,
813 &pfx_11_11_11_11_s_32,
815 FIB_ENTRY_FLAG_ATTACHED,
817 &pfx_10_10_10_1_s_32.fp_addr,
818 tm->hw[0]->sw_if_index,
819 ~0, // invalid fib index
822 FIB_ROUTE_PATH_FLAG_NONE);
824 dpo = fib_entry_contribute_ip_forwarding(fei);
825 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
826 FIB_TEST(DPO_ADJACENCY_INCOMPLETE == dpo1->dpoi_type,
827 "11.11.11.11/32 via incomplete adj");
829 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
831 &pfx_10_10_10_1_s_32.fp_addr,
832 tm->hw[0]->sw_if_index);
833 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
834 adj = adj_get(ai_01);
835 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
836 "adj is incomplete");
837 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
838 &adj->sub_type.nbr.next_hop)),
839 "adj nbr next-hop ok");
841 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
842 fib_test_build_rewrite(eth_addr));
843 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
845 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
846 &adj->sub_type.nbr.next_hop)),
847 "adj nbr next-hop ok");
848 ai = fib_entry_get_adj(fei);
849 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
851 dpo = fib_entry_contribute_ip_forwarding(fei);
852 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
853 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type,
854 "11.11.11.11/32 via complete adj");
855 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
856 tm->hw[0]->sw_if_index),
857 "RPF list for adj-fib contains adj");
859 ai_12_12_12_12 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
862 tm->hw[1]->sw_if_index);
863 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_12_12_12_12), "adj created");
864 adj = adj_get(ai_12_12_12_12);
865 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
866 "adj is incomplete");
867 FIB_TEST((0 == ip46_address_cmp(&nh_12_12_12_12,
868 &adj->sub_type.nbr.next_hop)),
869 "adj nbr next-hop ok");
870 adj_nbr_update_rewrite(ai_12_12_12_12, ADJ_NBR_REWRITE_FLAG_COMPLETE,
871 fib_test_build_rewrite(eth_addr));
872 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
878 fei = fib_table_entry_update_one_path(fib_index,
879 &pfx_10_10_10_1_s_32,
881 FIB_ENTRY_FLAG_ATTACHED,
883 &pfx_10_10_10_1_s_32.fp_addr,
884 tm->hw[0]->sw_if_index,
885 ~0, // invalid fib index
888 FIB_ROUTE_PATH_FLAG_NONE);
889 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
890 "Flags set on adj-fib");
891 ai = fib_entry_get_adj(fei);
892 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
894 fib_table_entry_path_remove(fib_index,
895 &pfx_11_11_11_11_s_32,
898 &pfx_10_10_10_1_s_32.fp_addr,
899 tm->hw[0]->sw_if_index,
900 ~0, // invalid fib index
902 FIB_ROUTE_PATH_FLAG_NONE);
906 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
908 &pfx_10_10_10_2_s_32.fp_addr,
909 tm->hw[0]->sw_if_index);
910 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
911 adj = adj_get(ai_02);
912 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
913 "adj is incomplete");
914 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
915 &adj->sub_type.nbr.next_hop)),
916 "adj nbr next-hop ok");
918 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
919 fib_test_build_rewrite(eth_addr));
920 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
922 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
923 &adj->sub_type.nbr.next_hop)),
924 "adj nbr next-hop ok");
925 FIB_TEST((ai_01 != ai_02), "ADJs are different");
927 fib_table_entry_update_one_path(fib_index,
928 &pfx_10_10_10_2_s_32,
932 &pfx_10_10_10_2_s_32.fp_addr,
933 tm->hw[0]->sw_if_index,
934 ~0, // invalid fib index
937 FIB_ROUTE_PATH_FLAG_NONE);
939 fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32);
940 ai = fib_entry_get_adj(fei);
941 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
944 * +2 adj-fibs, and their non-shared path-lists
946 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
947 FIB_TEST((NBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
948 fib_path_list_pool_size());
949 FIB_TEST((NBR+4 == fib_entry_pool_size()), "entry pool size is %d",
950 fib_entry_pool_size());
953 * Add 2 routes via the first ADJ. ensure path-list sharing
955 fib_prefix_t pfx_1_1_1_1_s_32 = {
957 .fp_proto = FIB_PROTOCOL_IP4,
960 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
964 fib_table_entry_path_add(fib_index,
970 tm->hw[0]->sw_if_index,
971 ~0, // invalid fib index
974 FIB_ROUTE_PATH_FLAG_NONE);
975 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
976 ai = fib_entry_get_adj(fei);
977 FIB_TEST((ai_01 == ai), "1.1.1.1 resolves via 10.10.10.1");
980 * +1 entry and a shared path-list
982 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
983 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
984 fib_path_list_pool_size());
985 FIB_TEST((NBR+5 == fib_entry_pool_size()), "entry pool size is %d",
986 fib_entry_pool_size());
989 fib_prefix_t pfx_1_1_2_0_s_24 = {
991 .fp_proto = FIB_PROTOCOL_IP4,
993 .ip4.as_u32 = clib_host_to_net_u32(0x01010200),
997 fib_table_entry_path_add(fib_index,
1000 FIB_ENTRY_FLAG_NONE,
1003 tm->hw[0]->sw_if_index,
1004 ~0, // invalid fib index
1007 FIB_ROUTE_PATH_FLAG_NONE);
1008 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1009 ai = fib_entry_get_adj(fei);
1010 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1015 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
1016 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1017 fib_path_list_pool_size());
1018 FIB_TEST((NBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1019 fib_entry_pool_size());
1022 * modify 1.1.2.0/24 to use multipath.
1024 fib_table_entry_path_add(fib_index,
1027 FIB_ENTRY_FLAG_NONE,
1030 tm->hw[0]->sw_if_index,
1031 ~0, // invalid fib index
1034 FIB_ROUTE_PATH_FLAG_NONE);
1035 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1036 dpo = fib_entry_contribute_ip_forwarding(fei);
1037 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1038 1, tm->hw[0]->sw_if_index),
1039 "RPF list for 1.1.2.0/24 contains both adjs");
1041 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1042 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1043 FIB_TEST((ai_01 == dpo1->dpoi_index),
1044 "1.1.2.0/24 bucket 0 resolves via 10.10.10.1 (%d=%d)",
1045 ai_01, dpo1->dpoi_index);
1047 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 1);
1048 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1049 FIB_TEST((ai_02 == dpo1->dpoi_index),
1050 "1.1.2.0/24 bucket 1 resolves via 10.10.10.2");
1053 * +1 shared-pathlist
1055 FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty");
1056 FIB_TEST((NBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1057 fib_path_list_pool_size());
1058 FIB_TEST((NBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1059 fib_entry_pool_size());
1064 fib_table_entry_path_remove(fib_index,
1069 tm->hw[0]->sw_if_index,
1072 FIB_ROUTE_PATH_FLAG_NONE);
1073 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1074 dpo = fib_entry_contribute_ip_forwarding(fei);
1075 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1076 1, tm->hw[0]->sw_if_index),
1077 "RPF list for 1.1.2.0/24 contains one adj");
1079 ai = fib_entry_get_adj(fei);
1080 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1083 * +1 shared-pathlist
1085 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d",
1086 fib_path_list_db_size());
1087 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1088 fib_path_list_pool_size());
1089 FIB_TEST((NBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1090 fib_entry_pool_size());
1093 * Add 2 recursive routes:
1094 * 100.100.100.100/32 via 1.1.1.1/32 => the via entry is installed.
1095 * 100.100.100.101/32 via 1.1.1.1/32 => the via entry is installed.
1097 fib_prefix_t bgp_100_pfx = {
1099 .fp_proto = FIB_PROTOCOL_IP4,
1101 /* 100.100.100.100/32 */
1102 .ip4.as_u32 = clib_host_to_net_u32(0x64646464),
1106 ip46_address_t nh_1_1_1_1 = {
1107 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1110 fei = fib_table_entry_path_add(fib_index,
1113 FIB_ENTRY_FLAG_NONE,
1116 ~0, // no index provided.
1117 fib_index, // nexthop in same fib as route
1120 FIB_ROUTE_PATH_FLAG_NONE);
1122 FIB_TEST_REC_FORW(&bgp_100_pfx, &pfx_1_1_1_1_s_32, 0);
1123 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1124 tm->hw[0]->sw_if_index),
1125 "RPF list for adj-fib contains adj");
1128 * +1 entry and +1 shared-path-list
1130 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1131 fib_path_list_db_size());
1132 FIB_TEST((NBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1133 fib_path_list_pool_size());
1134 FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
1135 fib_entry_pool_size());
1137 fib_prefix_t bgp_101_pfx = {
1139 .fp_proto = FIB_PROTOCOL_IP4,
1141 /* 100.100.100.101/32 */
1142 .ip4.as_u32 = clib_host_to_net_u32(0x64646465),
1146 fib_table_entry_path_add(fib_index,
1149 FIB_ENTRY_FLAG_NONE,
1152 ~0, // no index provided.
1153 fib_index, // nexthop in same fib as route
1156 FIB_ROUTE_PATH_FLAG_NONE);
1158 FIB_TEST_REC_FORW(&bgp_101_pfx, &pfx_1_1_1_1_s_32, 0);
1159 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1160 tm->hw[0]->sw_if_index),
1161 "RPF list for adj-fib contains adj");
1164 * +1 entry, but the recursive path-list is shared.
1166 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1167 fib_path_list_db_size());
1168 FIB_TEST((NBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1169 fib_path_list_pool_size());
1170 FIB_TEST((NBR+8 == fib_entry_pool_size()), "entry pool size is %d",
1171 fib_entry_pool_size());
1174 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1175 * adjacency through which the route will resovle
1177 fib_prefix_t ex_pfx = {
1179 .fp_proto = FIB_PROTOCOL_IP4,
1182 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
1186 fib_table_entry_special_add(fib_index,
1189 FIB_ENTRY_FLAG_EXCLUSIVE,
1191 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1192 FIB_TEST((ai == fib_entry_get_adj(fei)),
1193 "Exclusive route links to user adj");
1195 fib_table_entry_special_remove(fib_index,
1197 FIB_SOURCE_SPECIAL);
1198 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1199 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1200 "Exclusive reoute removed");
1203 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1204 * adjacency through which the route will resovle
1206 dpo_id_t ex_dpo = DPO_INVALID;
1208 lookup_dpo_add_or_lock_w_fib_index(fib_index,
1210 LOOKUP_INPUT_DST_ADDR,
1211 LOOKUP_TABLE_FROM_CONFIG,
1214 fib_table_entry_special_dpo_add(fib_index,
1217 FIB_ENTRY_FLAG_EXCLUSIVE,
1219 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1220 dpo = fib_entry_contribute_ip_forwarding(fei);
1221 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1222 "exclusive remote uses lookup DPO");
1225 * update the exclusive to use a different DPO
1227 ip_null_dpo_add_and_lock(DPO_PROTO_IP4,
1228 IP_NULL_ACTION_SEND_ICMP_UNREACH,
1230 fib_table_entry_special_dpo_update(fib_index,
1233 FIB_ENTRY_FLAG_EXCLUSIVE,
1235 dpo = fib_entry_contribute_ip_forwarding(fei);
1236 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1237 "exclusive remote uses now uses NULL DPO");
1239 fib_table_entry_special_remove(fib_index,
1241 FIB_SOURCE_SPECIAL);
1242 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1243 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1244 "Exclusive reoute removed");
1248 * Add a recursive route:
1249 * 200.200.200.200/32 via 1.1.1.2/32 => the via entry is NOT installed.
1251 fib_prefix_t bgp_200_pfx = {
1253 .fp_proto = FIB_PROTOCOL_IP4,
1255 /* 200.200.200.200/32 */
1256 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c8),
1260 fib_prefix_t pfx_1_1_1_2_s_32 = {
1262 .fp_proto = FIB_PROTOCOL_IP4,
1264 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
1268 fib_table_entry_path_add(fib_index,
1271 FIB_ENTRY_FLAG_NONE,
1273 &pfx_1_1_1_2_s_32.fp_addr,
1274 ~0, // no index provided.
1275 fib_index, // nexthop in same fib as route
1278 FIB_ROUTE_PATH_FLAG_NONE);
1280 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
1283 * the adj should be recursive via drop, since the route resolves via
1284 * the default route, which is itself a DROP
1286 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
1287 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1288 FIB_TEST(load_balance_is_drop(dpo1), "1.1.1.2/32 is drop");
1289 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1290 "RPF list for 1.1.1.2/32 contains 0 adjs");
1293 * +2 entry and +1 shared-path-list
1295 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
1296 fib_path_list_db_size());
1297 FIB_TEST((NBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
1298 fib_path_list_pool_size());
1299 FIB_TEST((NBR+10 == fib_entry_pool_size()), "entry pool size is %d",
1300 fib_entry_pool_size());
1303 * Unequal Cost load-balance. 3:1 ratio. fits in a 4 bucket LB
1304 * The paths are sort by NH first. in this case the the path with greater
1305 * weight is first in the set. This ordering is to test the RPF sort|uniq logic
1307 fib_prefix_t pfx_1_2_3_4_s_32 = {
1309 .fp_proto = FIB_PROTOCOL_IP4,
1311 .ip4.as_u32 = clib_host_to_net_u32(0x01020304),
1314 fib_table_entry_path_add(fib_index,
1317 FIB_ENTRY_FLAG_NONE,
1320 tm->hw[0]->sw_if_index,
1324 FIB_ROUTE_PATH_FLAG_NONE);
1325 fei = fib_table_entry_path_add(fib_index,
1328 FIB_ENTRY_FLAG_NONE,
1331 tm->hw[1]->sw_if_index,
1335 FIB_ROUTE_PATH_FLAG_NONE);
1337 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.4/32 presnet");
1338 dpo = fib_entry_contribute_ip_forwarding(fei);
1339 lb = load_balance_get(dpo->dpoi_index);
1340 FIB_TEST((lb->lb_n_buckets == 4),
1341 "1.2.3.4/32 LB has %d bucket",
1344 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 0, ai_12_12_12_12);
1345 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 1, ai_12_12_12_12);
1346 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 2, ai_12_12_12_12);
1347 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 3, ai_01);
1349 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1350 tm->hw[0]->sw_if_index,
1351 tm->hw[1]->sw_if_index),
1352 "RPF list for 1.2.3.4/32 contains both adjs");
1356 * Unequal Cost load-balance. 4:1 ratio.
1357 * fits in a 16 bucket LB with ratio 13:3
1359 fib_prefix_t pfx_1_2_3_5_s_32 = {
1361 .fp_proto = FIB_PROTOCOL_IP4,
1363 .ip4.as_u32 = clib_host_to_net_u32(0x01020305),
1366 fib_table_entry_path_add(fib_index,
1369 FIB_ENTRY_FLAG_NONE,
1372 tm->hw[1]->sw_if_index,
1376 FIB_ROUTE_PATH_FLAG_NONE);
1377 fei = fib_table_entry_path_add(fib_index,
1380 FIB_ENTRY_FLAG_NONE,
1383 tm->hw[0]->sw_if_index,
1387 FIB_ROUTE_PATH_FLAG_NONE);
1389 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.5/32 presnet");
1390 dpo = fib_entry_contribute_ip_forwarding(fei);
1391 lb = load_balance_get(dpo->dpoi_index);
1392 FIB_TEST((lb->lb_n_buckets == 16),
1393 "1.2.3.5/32 LB has %d bucket",
1396 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 0, ai_01);
1397 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 1, ai_01);
1398 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 2, ai_01);
1399 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 3, ai_01);
1400 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 4, ai_01);
1401 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 5, ai_01);
1402 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 6, ai_01);
1403 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 7, ai_01);
1404 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 8, ai_01);
1405 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 9, ai_01);
1406 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 10, ai_01);
1407 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 11, ai_01);
1408 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 12, ai_01);
1409 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 13, ai_12_12_12_12);
1410 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 14, ai_12_12_12_12);
1411 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 15, ai_12_12_12_12);
1413 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1414 tm->hw[0]->sw_if_index,
1415 tm->hw[1]->sw_if_index),
1416 "RPF list for 1.2.3.4/32 contains both adjs");
1419 * Test UCMP with a large weight skew - this produces load-balance objects with large
1420 * numbers of buckets to accommodate the skew. By updating said load-balances we are
1421 * laso testing the LB in placce modify code when number of buckets is large.
1423 fib_prefix_t pfx_6_6_6_6_s_32 = {
1425 .fp_proto = FIB_PROTOCOL_IP4,
1428 .ip4.as_u32 = clib_host_to_net_u32(0x06060606),
1431 fib_test_lb_bucket_t ip_6_6_6_6_o_10_10_10_1 = {
1437 fib_test_lb_bucket_t ip_6_6_6_6_o_10_10_10_2 = {
1443 fib_test_lb_bucket_t ip_6_6_6_6_o_12_12_12_12 = {
1446 .adj = ai_12_12_12_12,
1449 fib_table_entry_update_one_path(fib_index,
1452 FIB_ENTRY_FLAG_NONE,
1455 tm->hw[0]->sw_if_index,
1456 ~0, // invalid fib index
1459 FIB_ROUTE_PATH_FLAG_NONE);
1461 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1462 FIB_TEST(fib_test_validate_entry(fei,
1463 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1465 &ip_6_6_6_6_o_10_10_10_1),
1466 "6.6.6.6/32 via 10.10.10.1");
1468 fib_table_entry_path_add(fib_index,
1471 FIB_ENTRY_FLAG_NONE,
1474 tm->hw[0]->sw_if_index,
1475 ~0, // invalid fib index
1478 FIB_ROUTE_PATH_FLAG_NONE);
1480 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1481 FIB_TEST(fib_test_validate_entry(fei,
1482 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1484 &ip_6_6_6_6_o_10_10_10_2,
1485 &ip_6_6_6_6_o_10_10_10_2,
1486 &ip_6_6_6_6_o_10_10_10_2,
1487 &ip_6_6_6_6_o_10_10_10_2,
1488 &ip_6_6_6_6_o_10_10_10_2,
1489 &ip_6_6_6_6_o_10_10_10_2,
1490 &ip_6_6_6_6_o_10_10_10_2,
1491 &ip_6_6_6_6_o_10_10_10_2,
1492 &ip_6_6_6_6_o_10_10_10_2,
1493 &ip_6_6_6_6_o_10_10_10_2,
1494 &ip_6_6_6_6_o_10_10_10_2,
1495 &ip_6_6_6_6_o_10_10_10_2,
1496 &ip_6_6_6_6_o_10_10_10_2,
1497 &ip_6_6_6_6_o_10_10_10_2,
1498 &ip_6_6_6_6_o_10_10_10_2,
1499 &ip_6_6_6_6_o_10_10_10_2,
1500 &ip_6_6_6_6_o_10_10_10_2,
1501 &ip_6_6_6_6_o_10_10_10_2,
1502 &ip_6_6_6_6_o_10_10_10_2,
1503 &ip_6_6_6_6_o_10_10_10_2,
1504 &ip_6_6_6_6_o_10_10_10_2,
1505 &ip_6_6_6_6_o_10_10_10_2,
1506 &ip_6_6_6_6_o_10_10_10_2,
1507 &ip_6_6_6_6_o_10_10_10_2,
1508 &ip_6_6_6_6_o_10_10_10_2,
1509 &ip_6_6_6_6_o_10_10_10_2,
1510 &ip_6_6_6_6_o_10_10_10_2,
1511 &ip_6_6_6_6_o_10_10_10_2,
1512 &ip_6_6_6_6_o_10_10_10_2,
1513 &ip_6_6_6_6_o_10_10_10_2,
1514 &ip_6_6_6_6_o_10_10_10_2,
1515 &ip_6_6_6_6_o_10_10_10_2,
1516 &ip_6_6_6_6_o_10_10_10_2,
1517 &ip_6_6_6_6_o_10_10_10_2,
1518 &ip_6_6_6_6_o_10_10_10_2,
1519 &ip_6_6_6_6_o_10_10_10_2,
1520 &ip_6_6_6_6_o_10_10_10_2,
1521 &ip_6_6_6_6_o_10_10_10_2,
1522 &ip_6_6_6_6_o_10_10_10_2,
1523 &ip_6_6_6_6_o_10_10_10_2,
1524 &ip_6_6_6_6_o_10_10_10_2,
1525 &ip_6_6_6_6_o_10_10_10_2,
1526 &ip_6_6_6_6_o_10_10_10_2,
1527 &ip_6_6_6_6_o_10_10_10_2,
1528 &ip_6_6_6_6_o_10_10_10_2,
1529 &ip_6_6_6_6_o_10_10_10_2,
1530 &ip_6_6_6_6_o_10_10_10_2,
1531 &ip_6_6_6_6_o_10_10_10_2,
1532 &ip_6_6_6_6_o_10_10_10_2,
1533 &ip_6_6_6_6_o_10_10_10_2,
1534 &ip_6_6_6_6_o_10_10_10_2,
1535 &ip_6_6_6_6_o_10_10_10_2,
1536 &ip_6_6_6_6_o_10_10_10_2,
1537 &ip_6_6_6_6_o_10_10_10_2,
1538 &ip_6_6_6_6_o_10_10_10_2,
1539 &ip_6_6_6_6_o_10_10_10_2,
1540 &ip_6_6_6_6_o_10_10_10_2,
1541 &ip_6_6_6_6_o_10_10_10_2,
1542 &ip_6_6_6_6_o_10_10_10_2,
1543 &ip_6_6_6_6_o_10_10_10_2,
1544 &ip_6_6_6_6_o_10_10_10_2,
1545 &ip_6_6_6_6_o_10_10_10_2,
1546 &ip_6_6_6_6_o_10_10_10_2,
1547 &ip_6_6_6_6_o_10_10_10_1),
1548 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1550 fib_table_entry_path_add(fib_index,
1553 FIB_ENTRY_FLAG_NONE,
1556 tm->hw[1]->sw_if_index,
1557 ~0, // invalid fib index
1560 FIB_ROUTE_PATH_FLAG_NONE);
1562 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1563 FIB_TEST(fib_test_validate_entry(fei,
1564 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1566 &ip_6_6_6_6_o_10_10_10_1,
1567 &ip_6_6_6_6_o_10_10_10_2,
1568 &ip_6_6_6_6_o_10_10_10_2,
1569 &ip_6_6_6_6_o_10_10_10_2,
1570 &ip_6_6_6_6_o_10_10_10_2,
1571 &ip_6_6_6_6_o_10_10_10_2,
1572 &ip_6_6_6_6_o_10_10_10_2,
1573 &ip_6_6_6_6_o_10_10_10_2,
1574 &ip_6_6_6_6_o_10_10_10_2,
1575 &ip_6_6_6_6_o_10_10_10_2,
1576 &ip_6_6_6_6_o_10_10_10_2,
1577 &ip_6_6_6_6_o_10_10_10_2,
1578 &ip_6_6_6_6_o_10_10_10_2,
1579 &ip_6_6_6_6_o_10_10_10_2,
1580 &ip_6_6_6_6_o_10_10_10_2,
1581 &ip_6_6_6_6_o_10_10_10_2,
1582 &ip_6_6_6_6_o_10_10_10_2,
1583 &ip_6_6_6_6_o_10_10_10_2,
1584 &ip_6_6_6_6_o_10_10_10_2,
1585 &ip_6_6_6_6_o_10_10_10_2,
1586 &ip_6_6_6_6_o_10_10_10_2,
1587 &ip_6_6_6_6_o_10_10_10_2,
1588 &ip_6_6_6_6_o_10_10_10_2,
1589 &ip_6_6_6_6_o_10_10_10_2,
1590 &ip_6_6_6_6_o_10_10_10_2,
1591 &ip_6_6_6_6_o_10_10_10_2,
1592 &ip_6_6_6_6_o_10_10_10_2,
1593 &ip_6_6_6_6_o_10_10_10_2,
1594 &ip_6_6_6_6_o_10_10_10_2,
1595 &ip_6_6_6_6_o_10_10_10_2,
1596 &ip_6_6_6_6_o_10_10_10_2,
1597 &ip_6_6_6_6_o_10_10_10_2,
1598 &ip_6_6_6_6_o_10_10_10_2,
1599 &ip_6_6_6_6_o_10_10_10_2,
1600 &ip_6_6_6_6_o_10_10_10_2,
1601 &ip_6_6_6_6_o_10_10_10_2,
1602 &ip_6_6_6_6_o_10_10_10_2,
1603 &ip_6_6_6_6_o_10_10_10_2,
1604 &ip_6_6_6_6_o_10_10_10_2,
1605 &ip_6_6_6_6_o_10_10_10_2,
1606 &ip_6_6_6_6_o_10_10_10_2,
1607 &ip_6_6_6_6_o_10_10_10_2,
1608 &ip_6_6_6_6_o_10_10_10_2,
1609 &ip_6_6_6_6_o_10_10_10_2,
1610 &ip_6_6_6_6_o_10_10_10_2,
1611 &ip_6_6_6_6_o_10_10_10_2,
1612 &ip_6_6_6_6_o_10_10_10_2,
1613 &ip_6_6_6_6_o_10_10_10_2,
1614 &ip_6_6_6_6_o_10_10_10_2,
1615 &ip_6_6_6_6_o_10_10_10_2,
1616 &ip_6_6_6_6_o_10_10_10_2,
1617 &ip_6_6_6_6_o_10_10_10_2,
1618 &ip_6_6_6_6_o_10_10_10_2,
1619 &ip_6_6_6_6_o_10_10_10_2,
1620 &ip_6_6_6_6_o_10_10_10_2,
1621 &ip_6_6_6_6_o_10_10_10_2,
1622 &ip_6_6_6_6_o_10_10_10_2,
1623 &ip_6_6_6_6_o_10_10_10_2,
1624 &ip_6_6_6_6_o_10_10_10_2,
1625 &ip_6_6_6_6_o_10_10_10_2,
1626 &ip_6_6_6_6_o_10_10_10_2,
1627 &ip_6_6_6_6_o_10_10_10_2,
1628 &ip_6_6_6_6_o_10_10_10_2,
1629 &ip_6_6_6_6_o_10_10_10_2,
1630 &ip_6_6_6_6_o_10_10_10_2,
1631 &ip_6_6_6_6_o_12_12_12_12,
1632 &ip_6_6_6_6_o_12_12_12_12,
1633 &ip_6_6_6_6_o_12_12_12_12,
1634 &ip_6_6_6_6_o_12_12_12_12,
1635 &ip_6_6_6_6_o_12_12_12_12,
1636 &ip_6_6_6_6_o_12_12_12_12,
1637 &ip_6_6_6_6_o_12_12_12_12,
1638 &ip_6_6_6_6_o_12_12_12_12,
1639 &ip_6_6_6_6_o_12_12_12_12,
1640 &ip_6_6_6_6_o_12_12_12_12,
1641 &ip_6_6_6_6_o_12_12_12_12,
1642 &ip_6_6_6_6_o_12_12_12_12,
1643 &ip_6_6_6_6_o_12_12_12_12,
1644 &ip_6_6_6_6_o_12_12_12_12,
1645 &ip_6_6_6_6_o_12_12_12_12,
1646 &ip_6_6_6_6_o_12_12_12_12,
1647 &ip_6_6_6_6_o_12_12_12_12,
1648 &ip_6_6_6_6_o_12_12_12_12,
1649 &ip_6_6_6_6_o_12_12_12_12,
1650 &ip_6_6_6_6_o_12_12_12_12,
1651 &ip_6_6_6_6_o_12_12_12_12,
1652 &ip_6_6_6_6_o_12_12_12_12,
1653 &ip_6_6_6_6_o_12_12_12_12,
1654 &ip_6_6_6_6_o_12_12_12_12,
1655 &ip_6_6_6_6_o_12_12_12_12,
1656 &ip_6_6_6_6_o_12_12_12_12,
1657 &ip_6_6_6_6_o_12_12_12_12,
1658 &ip_6_6_6_6_o_12_12_12_12,
1659 &ip_6_6_6_6_o_12_12_12_12,
1660 &ip_6_6_6_6_o_12_12_12_12,
1661 &ip_6_6_6_6_o_12_12_12_12,
1662 &ip_6_6_6_6_o_12_12_12_12,
1663 &ip_6_6_6_6_o_12_12_12_12,
1664 &ip_6_6_6_6_o_12_12_12_12,
1665 &ip_6_6_6_6_o_12_12_12_12,
1666 &ip_6_6_6_6_o_12_12_12_12,
1667 &ip_6_6_6_6_o_12_12_12_12,
1668 &ip_6_6_6_6_o_12_12_12_12,
1669 &ip_6_6_6_6_o_12_12_12_12,
1670 &ip_6_6_6_6_o_12_12_12_12,
1671 &ip_6_6_6_6_o_12_12_12_12,
1672 &ip_6_6_6_6_o_12_12_12_12,
1673 &ip_6_6_6_6_o_12_12_12_12,
1674 &ip_6_6_6_6_o_12_12_12_12,
1675 &ip_6_6_6_6_o_12_12_12_12,
1676 &ip_6_6_6_6_o_12_12_12_12,
1677 &ip_6_6_6_6_o_12_12_12_12,
1678 &ip_6_6_6_6_o_12_12_12_12,
1679 &ip_6_6_6_6_o_12_12_12_12,
1680 &ip_6_6_6_6_o_12_12_12_12,
1681 &ip_6_6_6_6_o_12_12_12_12,
1682 &ip_6_6_6_6_o_12_12_12_12,
1683 &ip_6_6_6_6_o_12_12_12_12,
1684 &ip_6_6_6_6_o_12_12_12_12,
1685 &ip_6_6_6_6_o_12_12_12_12,
1686 &ip_6_6_6_6_o_12_12_12_12,
1687 &ip_6_6_6_6_o_12_12_12_12,
1688 &ip_6_6_6_6_o_12_12_12_12,
1689 &ip_6_6_6_6_o_12_12_12_12,
1690 &ip_6_6_6_6_o_12_12_12_12,
1691 &ip_6_6_6_6_o_12_12_12_12,
1692 &ip_6_6_6_6_o_12_12_12_12,
1693 &ip_6_6_6_6_o_12_12_12_12),
1694 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1696 fib_table_entry_path_remove(fib_index,
1701 tm->hw[1]->sw_if_index,
1702 ~0, // invalid fib index
1704 FIB_ROUTE_PATH_FLAG_NONE);
1706 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1707 FIB_TEST(fib_test_validate_entry(fei,
1708 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1710 &ip_6_6_6_6_o_10_10_10_2,
1711 &ip_6_6_6_6_o_10_10_10_2,
1712 &ip_6_6_6_6_o_10_10_10_2,
1713 &ip_6_6_6_6_o_10_10_10_2,
1714 &ip_6_6_6_6_o_10_10_10_2,
1715 &ip_6_6_6_6_o_10_10_10_2,
1716 &ip_6_6_6_6_o_10_10_10_2,
1717 &ip_6_6_6_6_o_10_10_10_2,
1718 &ip_6_6_6_6_o_10_10_10_2,
1719 &ip_6_6_6_6_o_10_10_10_2,
1720 &ip_6_6_6_6_o_10_10_10_2,
1721 &ip_6_6_6_6_o_10_10_10_2,
1722 &ip_6_6_6_6_o_10_10_10_2,
1723 &ip_6_6_6_6_o_10_10_10_2,
1724 &ip_6_6_6_6_o_10_10_10_2,
1725 &ip_6_6_6_6_o_10_10_10_2,
1726 &ip_6_6_6_6_o_10_10_10_2,
1727 &ip_6_6_6_6_o_10_10_10_2,
1728 &ip_6_6_6_6_o_10_10_10_2,
1729 &ip_6_6_6_6_o_10_10_10_2,
1730 &ip_6_6_6_6_o_10_10_10_2,
1731 &ip_6_6_6_6_o_10_10_10_2,
1732 &ip_6_6_6_6_o_10_10_10_2,
1733 &ip_6_6_6_6_o_10_10_10_2,
1734 &ip_6_6_6_6_o_10_10_10_2,
1735 &ip_6_6_6_6_o_10_10_10_2,
1736 &ip_6_6_6_6_o_10_10_10_2,
1737 &ip_6_6_6_6_o_10_10_10_2,
1738 &ip_6_6_6_6_o_10_10_10_2,
1739 &ip_6_6_6_6_o_10_10_10_2,
1740 &ip_6_6_6_6_o_10_10_10_2,
1741 &ip_6_6_6_6_o_10_10_10_2,
1742 &ip_6_6_6_6_o_10_10_10_2,
1743 &ip_6_6_6_6_o_10_10_10_2,
1744 &ip_6_6_6_6_o_10_10_10_2,
1745 &ip_6_6_6_6_o_10_10_10_2,
1746 &ip_6_6_6_6_o_10_10_10_2,
1747 &ip_6_6_6_6_o_10_10_10_2,
1748 &ip_6_6_6_6_o_10_10_10_2,
1749 &ip_6_6_6_6_o_10_10_10_2,
1750 &ip_6_6_6_6_o_10_10_10_2,
1751 &ip_6_6_6_6_o_10_10_10_2,
1752 &ip_6_6_6_6_o_10_10_10_2,
1753 &ip_6_6_6_6_o_10_10_10_2,
1754 &ip_6_6_6_6_o_10_10_10_2,
1755 &ip_6_6_6_6_o_10_10_10_2,
1756 &ip_6_6_6_6_o_10_10_10_2,
1757 &ip_6_6_6_6_o_10_10_10_2,
1758 &ip_6_6_6_6_o_10_10_10_2,
1759 &ip_6_6_6_6_o_10_10_10_2,
1760 &ip_6_6_6_6_o_10_10_10_2,
1761 &ip_6_6_6_6_o_10_10_10_2,
1762 &ip_6_6_6_6_o_10_10_10_2,
1763 &ip_6_6_6_6_o_10_10_10_2,
1764 &ip_6_6_6_6_o_10_10_10_2,
1765 &ip_6_6_6_6_o_10_10_10_2,
1766 &ip_6_6_6_6_o_10_10_10_2,
1767 &ip_6_6_6_6_o_10_10_10_2,
1768 &ip_6_6_6_6_o_10_10_10_2,
1769 &ip_6_6_6_6_o_10_10_10_2,
1770 &ip_6_6_6_6_o_10_10_10_2,
1771 &ip_6_6_6_6_o_10_10_10_2,
1772 &ip_6_6_6_6_o_10_10_10_2,
1773 &ip_6_6_6_6_o_10_10_10_1),
1774 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1776 fib_table_entry_path_remove(fib_index,
1781 tm->hw[0]->sw_if_index,
1782 ~0, // invalid fib index
1784 FIB_ROUTE_PATH_FLAG_NONE);
1786 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1787 FIB_TEST(fib_test_validate_entry(fei,
1788 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1790 &ip_6_6_6_6_o_10_10_10_1),
1791 "6.6.6.6/32 via 10.10.10.1");
1793 fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API);
1796 * A recursive via the two unequal cost entries
1798 fib_prefix_t bgp_44_s_32 = {
1800 .fp_proto = FIB_PROTOCOL_IP4,
1802 /* 200.200.200.201/32 */
1803 .ip4.as_u32 = clib_host_to_net_u32(0x44444444),
1806 fei = fib_table_entry_path_add(fib_index,
1809 FIB_ENTRY_FLAG_NONE,
1811 &pfx_1_2_3_4_s_32.fp_addr,
1816 FIB_ROUTE_PATH_FLAG_NONE);
1817 fei = fib_table_entry_path_add(fib_index,
1820 FIB_ENTRY_FLAG_NONE,
1822 &pfx_1_2_3_5_s_32.fp_addr,
1827 FIB_ROUTE_PATH_FLAG_NONE);
1829 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_4_s_32, 0);
1830 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_5_s_32, 1);
1831 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1832 tm->hw[0]->sw_if_index,
1833 tm->hw[1]->sw_if_index),
1834 "RPF list for 1.2.3.4/32 contains both adjs");
1837 * test the uRPF check functions
1839 dpo_id_t dpo_44 = DPO_INVALID;
1842 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
1843 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
1845 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
1846 "uRPF check for 68.68.68.68/32 on %d OK",
1847 tm->hw[0]->sw_if_index);
1848 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
1849 "uRPF check for 68.68.68.68/32 on %d OK",
1850 tm->hw[1]->sw_if_index);
1851 FIB_TEST(!fib_urpf_check(urpfi, 99),
1852 "uRPF check for 68.68.68.68/32 on 99 not-OK",
1856 fib_table_entry_delete(fib_index,
1859 fib_table_entry_delete(fib_index,
1862 fib_table_entry_delete(fib_index,
1867 * Add a recursive route:
1868 * 200.200.200.201/32 via 1.1.1.200/32 => the via entry is NOT installed.
1870 fib_prefix_t bgp_201_pfx = {
1872 .fp_proto = FIB_PROTOCOL_IP4,
1874 /* 200.200.200.201/32 */
1875 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c9),
1879 fib_prefix_t pfx_1_1_1_200_s_32 = {
1881 .fp_proto = FIB_PROTOCOL_IP4,
1883 .ip4.as_u32 = clib_host_to_net_u32(0x010101c8),
1887 fib_table_entry_path_add(fib_index,
1890 FIB_ENTRY_FLAG_NONE,
1892 &pfx_1_1_1_200_s_32.fp_addr,
1893 ~0, // no index provided.
1894 fib_index, // nexthop in same fib as route
1897 FIB_ROUTE_PATH_FLAG_NONE);
1899 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
1901 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
1902 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
1903 "Flags set on RR via non-attached");
1904 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1905 "RPF list for BGP route empty");
1908 * +2 entry (BGP & RR) and +1 shared-path-list
1910 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
1911 fib_path_list_db_size());
1912 FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
1913 fib_path_list_pool_size());
1914 FIB_TEST((NBR+12 == fib_entry_pool_size()), "entry pool size is %d",
1915 fib_entry_pool_size());
1918 * insert a route that covers the missing 1.1.1.2/32. we epxect
1919 * 200.200.200.200/32 and 200.200.200.201/32 to resolve through it.
1921 fib_prefix_t pfx_1_1_1_0_s_24 = {
1923 .fp_proto = FIB_PROTOCOL_IP4,
1926 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
1930 fib_table_entry_path_add(fib_index,
1933 FIB_ENTRY_FLAG_NONE,
1936 tm->hw[0]->sw_if_index,
1937 ~0, // invalid fib index
1940 FIB_ROUTE_PATH_FLAG_NONE);
1941 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24);
1942 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1943 ai = fib_entry_get_adj(fei);
1944 FIB_TEST((ai_01 == ai), "1.1.1.0/24 resolves via 10.10.10.1");
1945 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
1946 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1947 ai = fib_entry_get_adj(fei);
1948 FIB_TEST((ai_01 == ai), "1.1.1.2/32 resolves via 10.10.10.1");
1949 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
1950 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1951 ai = fib_entry_get_adj(fei);
1952 FIB_TEST((ai_01 == ai), "1.1.1.200/24 resolves via 10.10.10.1");
1955 * +1 entry. 1.1.1.1/32 already uses 10.10.10.1 so no new pah-list
1957 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
1958 fib_path_list_db_size());
1959 FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
1960 fib_path_list_pool_size());
1961 FIB_TEST((NBR+13 == fib_entry_pool_size()), "entry pool size is %d",
1962 fib_entry_pool_size());
1965 * the recursive adj for 200.200.200.200 should be updated.
1967 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
1968 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
1969 fei = fib_table_lookup(fib_index, &bgp_200_pfx);
1970 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1971 tm->hw[0]->sw_if_index),
1972 "RPF list for BGP route has itf index 0");
1975 * insert a more specific route than 1.1.1.0/24 that also covers the
1976 * missing 1.1.1.2/32, but not 1.1.1.200/32. we epxect
1977 * 200.200.200.200 to resolve through it.
1979 fib_prefix_t pfx_1_1_1_0_s_28 = {
1981 .fp_proto = FIB_PROTOCOL_IP4,
1984 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
1988 fib_table_entry_path_add(fib_index,
1991 FIB_ENTRY_FLAG_NONE,
1994 tm->hw[0]->sw_if_index,
1995 ~0, // invalid fib index
1998 FIB_ROUTE_PATH_FLAG_NONE);
1999 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28);
2000 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2001 ai = fib_entry_get_adj(fei);
2002 FIB_TEST((ai_02 == ai), "1.1.1.0/24 resolves via 10.10.10.2");
2005 * +1 entry. +1 shared path-list
2007 FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d",
2008 fib_path_list_db_size());
2009 FIB_TEST((NBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
2010 fib_path_list_pool_size());
2011 FIB_TEST((NBR+14 == fib_entry_pool_size()), "entry pool size is %d",
2012 fib_entry_pool_size());
2015 * the recursive adj for 200.200.200.200 should be updated.
2016 * 200.200.200.201 remains unchanged.
2018 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2019 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2022 * remove this /28. 200.200.200.200/32 should revert back to via 1.1.1.0/24
2024 fib_table_entry_path_remove(fib_index,
2029 tm->hw[0]->sw_if_index,
2032 FIB_ROUTE_PATH_FLAG_NONE);
2033 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28) ==
2034 FIB_NODE_INDEX_INVALID),
2035 "1.1.1.0/28 removed");
2036 FIB_TEST((fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28) ==
2037 fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24)),
2038 "1.1.1.0/28 lookup via /24");
2039 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2040 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2043 * -1 entry. -1 shared path-list
2045 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2046 fib_path_list_db_size());
2047 FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2048 fib_path_list_pool_size());
2049 FIB_TEST((NBR+13 == fib_entry_pool_size()), "entry pool size is %d",
2050 fib_entry_pool_size());
2053 * remove 1.1.1.0/24. 200.200.200.200/32 should revert back to via 0.0.0.0/0
2055 fib_table_entry_path_remove(fib_index,
2060 tm->hw[0]->sw_if_index,
2063 FIB_ROUTE_PATH_FLAG_NONE);
2064 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_24) ==
2065 FIB_NODE_INDEX_INVALID),
2066 "1.1.1.0/24 removed");
2068 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2069 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2070 "1.1.1.2/32 route is DROP");
2071 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2072 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2073 "1.1.1.200/32 route is DROP");
2075 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2076 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2081 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2082 fib_path_list_db_size());
2083 FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2084 fib_path_list_pool_size());
2085 FIB_TEST((NBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2086 fib_entry_pool_size());
2089 * insert the missing 1.1.1.2/32
2091 fei = fib_table_entry_path_add(fib_index,
2094 FIB_ENTRY_FLAG_NONE,
2097 tm->hw[0]->sw_if_index,
2098 ~0, // invalid fib index
2101 FIB_ROUTE_PATH_FLAG_NONE);
2102 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2103 ai = fib_entry_get_adj(fei);
2104 FIB_TEST((ai = ai_01), "1.1.1.2/32 resolves via 10.10.10.1");
2106 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2107 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2110 * no change. 1.1.1.2/32 was already there RR sourced.
2112 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2113 fib_path_list_db_size());
2114 FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2115 fib_path_list_pool_size());
2116 FIB_TEST((NBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2117 fib_entry_pool_size());
2120 * remove 200.200.200.201/32 which does not have a valid via FIB
2122 fib_table_entry_path_remove(fib_index,
2126 &pfx_1_1_1_200_s_32.fp_addr,
2127 ~0, // no index provided.
2130 FIB_ROUTE_PATH_FLAG_NONE);
2133 * -2 entries (BGP and RR). -1 shared path-list;
2135 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2136 FIB_NODE_INDEX_INVALID),
2137 "200.200.200.201/32 removed");
2138 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32) ==
2139 FIB_NODE_INDEX_INVALID),
2140 "1.1.1.200/32 removed");
2142 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2143 fib_path_list_db_size());
2144 FIB_TEST((NBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
2145 fib_path_list_pool_size());
2146 FIB_TEST((NBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2147 fib_entry_pool_size());
2150 * remove 200.200.200.200/32 which does have a valid via FIB
2152 fib_table_entry_path_remove(fib_index,
2156 &pfx_1_1_1_2_s_32.fp_addr,
2157 ~0, // no index provided.
2160 FIB_ROUTE_PATH_FLAG_NONE);
2162 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2163 FIB_NODE_INDEX_INVALID),
2164 "200.200.200.200/32 removed");
2165 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32) !=
2166 FIB_NODE_INDEX_INVALID),
2167 "1.1.1.2/32 still present");
2170 * -1 entry (BGP, the RR source is also API sourced). -1 shared path-list;
2172 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2173 fib_path_list_db_size());
2174 FIB_TEST((NBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2175 fib_path_list_pool_size());
2176 FIB_TEST((NBR+9 == fib_entry_pool_size()), "entry pool size is %d",
2177 fib_entry_pool_size());
2180 * A recursive prefix that has a 2 path load-balance.
2181 * It also shares a next-hop with other BGP prefixes and hence
2182 * test the ref counting of RR sourced prefixes and 2 level LB.
2184 const fib_prefix_t bgp_102 = {
2186 .fp_proto = FIB_PROTOCOL_IP4,
2188 /* 100.100.100.101/32 */
2189 .ip4.as_u32 = clib_host_to_net_u32(0x64646466),
2192 fib_table_entry_path_add(fib_index,
2195 FIB_ENTRY_FLAG_NONE,
2197 &pfx_1_1_1_1_s_32.fp_addr,
2198 ~0, // no index provided.
2199 fib_index, // same as route
2202 FIB_ROUTE_PATH_FLAG_NONE);
2203 fib_table_entry_path_add(fib_index,
2206 FIB_ENTRY_FLAG_NONE,
2208 &pfx_1_1_1_2_s_32.fp_addr,
2209 ~0, // no index provided.
2210 fib_index, // same as route's FIB
2213 FIB_ROUTE_PATH_FLAG_NONE);
2214 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2215 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "100.100.100.102/32 presnet");
2216 dpo = fib_entry_contribute_ip_forwarding(fei);
2218 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2219 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2220 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32);
2221 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2223 lb = load_balance_get(dpo->dpoi_index);
2224 FIB_TEST((lb->lb_n_buckets == 2), "Recursive LB has %d bucket", lb->lb_n_buckets);
2225 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2226 "First via 10.10.10.1");
2227 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 1)),
2228 "Second via 10.10.10.1");
2230 fib_table_entry_path_remove(fib_index,
2234 &pfx_1_1_1_1_s_32.fp_addr,
2235 ~0, // no index provided.
2236 fib_index, // same as route's FIB
2238 FIB_ROUTE_PATH_FLAG_NONE);
2239 fib_table_entry_path_remove(fib_index,
2243 &pfx_1_1_1_2_s_32.fp_addr,
2244 ~0, // no index provided.
2245 fib_index, // same as route's FIB
2247 FIB_ROUTE_PATH_FLAG_NONE);
2248 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2249 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "100.100.100.102/32 removed");
2252 * remove the remaining recursives
2254 fib_table_entry_path_remove(fib_index,
2258 &pfx_1_1_1_1_s_32.fp_addr,
2259 ~0, // no index provided.
2260 fib_index, // same as route's FIB
2262 FIB_ROUTE_PATH_FLAG_NONE);
2263 fib_table_entry_path_remove(fib_index,
2267 &pfx_1_1_1_1_s_32.fp_addr,
2268 ~0, // no index provided.
2269 fib_index, // same as route's FIB
2271 FIB_ROUTE_PATH_FLAG_NONE);
2272 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_100_pfx) ==
2273 FIB_NODE_INDEX_INVALID),
2274 "100.100.100.100/32 removed");
2275 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_101_pfx) ==
2276 FIB_NODE_INDEX_INVALID),
2277 "100.100.100.101/32 removed");
2280 * -2 entry (2*BGP, the RR source is also API sourced). -1 shared path-list;
2282 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2283 fib_path_list_db_size());
2284 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2285 fib_path_list_pool_size());
2286 FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2287 fib_entry_pool_size());
2290 * Add a recursive route via a connected cover, using an adj-fib that does exist
2292 fib_table_entry_path_add(fib_index,
2295 FIB_ENTRY_FLAG_NONE,
2298 ~0, // no index provided.
2299 fib_index, // Same as route's FIB
2302 FIB_ROUTE_PATH_FLAG_NONE);
2305 * +1 entry. +1 shared path-list (recursive via 10.10.10.1)
2307 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2308 fib_path_list_db_size());
2309 FIB_TEST((NBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2310 fib_path_list_pool_size());
2311 FIB_TEST((NBR+8 == fib_entry_pool_size()), "entry pool size is %d",
2312 fib_entry_pool_size());
2314 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2315 dpo = fib_entry_contribute_ip_forwarding(fei);
2317 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
2318 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2320 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2321 "200.200.200.200/32 is recursive via adj for 10.10.10.1");
2323 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
2324 "Flags set on RR via existing attached");
2327 * Add a recursive route via a connected cover, using and adj-fib that does
2330 ip46_address_t nh_10_10_10_3 = {
2331 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
2333 fib_prefix_t pfx_10_10_10_3 = {
2335 .fp_proto = FIB_PROTOCOL_IP4,
2336 .fp_addr = nh_10_10_10_3,
2339 fib_table_entry_path_add(fib_index,
2342 FIB_ENTRY_FLAG_NONE,
2345 ~0, // no index provided.
2349 FIB_ROUTE_PATH_FLAG_NONE);
2352 * +2 entries (BGP and RR). +1 shared path-list (recursive via 10.10.10.3) and
2353 * one unshared non-recursive via 10.10.10.3
2355 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2356 fib_path_list_db_size());
2357 FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2358 fib_path_list_pool_size());
2359 FIB_TEST((NBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2360 fib_entry_pool_size());
2362 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
2365 tm->hw[0]->sw_if_index);
2367 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2368 dpo = fib_entry_contribute_ip_forwarding(fei);
2369 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3);
2370 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2372 ai = fib_entry_get_adj(fei);
2373 FIB_TEST((ai == ai_03), "adj for 10.10.10.3/32 is via adj for 10.10.10.3");
2374 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
2375 fib_entry_get_flags(fei)),
2376 "Flags set on RR via non-existing attached");
2378 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2379 "adj for 200.200.200.200/32 is recursive via adj for 10.10.10.3");
2384 * remove the recursives
2386 fib_table_entry_path_remove(fib_index,
2391 ~0, // no index provided.
2392 fib_index, // same as route's FIB
2394 FIB_ROUTE_PATH_FLAG_NONE);
2395 fib_table_entry_path_remove(fib_index,
2400 ~0, // no index provided.
2401 fib_index, // same as route's FIB
2403 FIB_ROUTE_PATH_FLAG_NONE);
2405 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2406 FIB_NODE_INDEX_INVALID),
2407 "200.200.200.201/32 removed");
2408 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2409 FIB_NODE_INDEX_INVALID),
2410 "200.200.200.200/32 removed");
2411 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3) ==
2412 FIB_NODE_INDEX_INVALID),
2413 "10.10.10.3/32 removed");
2416 * -3 entries (2*BGP and RR). -2 shared path-list (recursive via 10.10.10.3 &
2417 * 10.10.10.1) and one unshared non-recursive via 10.10.10.3
2419 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2420 fib_path_list_db_size());
2421 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2422 fib_path_list_pool_size());
2423 FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2424 fib_entry_pool_size());
2429 * Add 5.5.5.5/32 -> 5.5.5.6/32 -> 5.5.5.7/32 -> 5.5.5.5/32
2431 fib_prefix_t pfx_5_5_5_5_s_32 = {
2433 .fp_proto = FIB_PROTOCOL_IP4,
2435 .ip4.as_u32 = clib_host_to_net_u32(0x05050505),
2438 fib_prefix_t pfx_5_5_5_6_s_32 = {
2440 .fp_proto = FIB_PROTOCOL_IP4,
2442 .ip4.as_u32 = clib_host_to_net_u32(0x05050506),
2445 fib_prefix_t pfx_5_5_5_7_s_32 = {
2447 .fp_proto = FIB_PROTOCOL_IP4,
2449 .ip4.as_u32 = clib_host_to_net_u32(0x05050507),
2453 fib_table_entry_path_add(fib_index,
2456 FIB_ENTRY_FLAG_NONE,
2458 &pfx_5_5_5_6_s_32.fp_addr,
2459 ~0, // no index provided.
2463 FIB_ROUTE_PATH_FLAG_NONE);
2464 fib_table_entry_path_add(fib_index,
2467 FIB_ENTRY_FLAG_NONE,
2469 &pfx_5_5_5_7_s_32.fp_addr,
2470 ~0, // no index provided.
2474 FIB_ROUTE_PATH_FLAG_NONE);
2475 fib_table_entry_path_add(fib_index,
2478 FIB_ENTRY_FLAG_NONE,
2480 &pfx_5_5_5_5_s_32.fp_addr,
2481 ~0, // no index provided.
2485 FIB_ROUTE_PATH_FLAG_NONE);
2487 * +3 entries, +3 shared path-list
2489 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2490 fib_path_list_db_size());
2491 FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2492 fib_path_list_pool_size());
2493 FIB_TEST((NBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2494 fib_entry_pool_size());
2497 * All the entries have only looped paths, so they are all drop
2499 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2500 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2501 "LB for 5.5.5.7/32 is via adj for DROP");
2502 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2503 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2504 "LB for 5.5.5.5/32 is via adj for DROP");
2505 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2506 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2507 "LB for 5.5.5.6/32 is via adj for DROP");
2510 * provide 5.5.5.6/32 with alternate path.
2511 * this will allow only 5.5.5.6/32 to forward with this path, the others
2512 * are still drop since the loop is still present.
2514 fib_table_entry_path_add(fib_index,
2517 FIB_ENTRY_FLAG_NONE,
2520 tm->hw[0]->sw_if_index,
2524 FIB_ROUTE_PATH_FLAG_NONE);
2527 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2528 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2530 lb = load_balance_get(dpo1->dpoi_index);
2531 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.6 LB has %d bucket", lb->lb_n_buckets);
2533 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2534 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2535 FIB_TEST((ai_01 == dpo2->dpoi_index),
2536 "5.5.5.6 bucket 0 resolves via 10.10.10.2");
2538 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2539 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2540 "LB for 5.5.5.7/32 is via adj for DROP");
2541 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2542 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2543 "LB for 5.5.5.5/32 is via adj for DROP");
2546 * remove the alternate path for 5.5.5.6/32
2549 fib_table_entry_path_remove(fib_index,
2554 tm->hw[0]->sw_if_index,
2557 FIB_ROUTE_PATH_FLAG_NONE);
2559 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2560 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2561 "LB for 5.5.5.7/32 is via adj for DROP");
2562 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2563 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2564 "LB for 5.5.5.5/32 is via adj for DROP");
2565 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2566 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2567 "LB for 5.5.5.6/32 is via adj for DROP");
2570 * break the loop by giving 5.5.5.5/32 a new set of paths
2571 * expect all to forward via this new path.
2573 fib_table_entry_update_one_path(fib_index,
2576 FIB_ENTRY_FLAG_NONE,
2579 tm->hw[0]->sw_if_index,
2580 ~0, // invalid fib index
2583 FIB_ROUTE_PATH_FLAG_NONE);
2585 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2586 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2587 lb = load_balance_get(dpo1->dpoi_index);
2588 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.5 LB has %d bucket", lb->lb_n_buckets);
2590 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2591 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2592 FIB_TEST((ai_01 == dpo2->dpoi_index),
2593 "5.5.5.5 bucket 0 resolves via 10.10.10.2");
2595 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_7_s_32);
2596 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2598 lb = load_balance_get(dpo2->dpoi_index);
2599 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2600 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo2->dpoi_index, 0)),
2601 "5.5.5.5.7 via 5.5.5.5");
2603 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32);
2604 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2606 lb = load_balance_get(dpo1->dpoi_index);
2607 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2608 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2609 "5.5.5.5.6 via 5.5.5.7");
2612 * revert back to the loop. so we can remove the prefixes with
2615 fib_table_entry_update_one_path(fib_index,
2618 FIB_ENTRY_FLAG_NONE,
2620 &pfx_5_5_5_6_s_32.fp_addr,
2621 ~0, // no index provided.
2625 FIB_ROUTE_PATH_FLAG_NONE);
2627 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2628 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2629 "LB for 5.5.5.7/32 is via adj for DROP");
2630 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2631 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2632 "LB for 5.5.5.5/32 is via adj for DROP");
2633 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2634 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2635 "LB for 5.5.5.6/32 is via adj for DROP");
2638 * remove all the 5.5.5.x/32 prefixes
2640 fib_table_entry_path_remove(fib_index,
2644 &pfx_5_5_5_6_s_32.fp_addr,
2645 ~0, // no index provided.
2646 fib_index, // same as route's FIB
2648 FIB_ROUTE_PATH_FLAG_NONE);
2649 fib_table_entry_path_remove(fib_index,
2653 &pfx_5_5_5_7_s_32.fp_addr,
2654 ~0, // no index provided.
2655 fib_index, // same as route's FIB
2657 FIB_ROUTE_PATH_FLAG_NONE);
2658 fib_table_entry_path_remove(fib_index,
2662 &pfx_5_5_5_5_s_32.fp_addr,
2663 ~0, // no index provided.
2664 fib_index, // same as route's FIB
2666 FIB_ROUTE_PATH_FLAG_NONE);
2667 fib_table_entry_path_remove(fib_index,
2672 ~0, // no index provided.
2673 fib_index, // same as route's FIB
2675 FIB_ROUTE_PATH_FLAG_NONE);
2678 * -3 entries, -3 shared path-list
2680 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2681 fib_path_list_db_size());
2682 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2683 fib_path_list_pool_size());
2684 FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2685 fib_entry_pool_size());
2688 * Single level loop 5.5.5.5/32 via 5.5.5.5/32
2690 fib_table_entry_path_add(fib_index,
2693 FIB_ENTRY_FLAG_NONE,
2695 &pfx_5_5_5_6_s_32.fp_addr,
2696 ~0, // no index provided.
2700 FIB_ROUTE_PATH_FLAG_NONE);
2701 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2702 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2703 "1-level 5.5.5.6/32 loop is via adj for DROP");
2705 fib_table_entry_path_remove(fib_index,
2709 &pfx_5_5_5_6_s_32.fp_addr,
2710 ~0, // no index provided.
2711 fib_index, // same as route's FIB
2713 FIB_ROUTE_PATH_FLAG_NONE);
2714 FIB_TEST(FIB_NODE_INDEX_INVALID ==
2715 fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32),
2716 "1-level 5.5.5.6/32 loop is removed");
2719 * A recursive route whose next-hop is covered by the prefix.
2720 * This would mean the via-fib, which inherits forwarding from its
2721 * cover, thus picks up forwarding from the prfix, which is via the
2722 * via-fib, and we have a loop.
2724 fib_prefix_t pfx_23_23_23_0_s_24 = {
2726 .fp_proto = FIB_PROTOCOL_IP4,
2728 .ip4.as_u32 = clib_host_to_net_u32(0x17171700),
2731 fib_prefix_t pfx_23_23_23_23_s_32 = {
2733 .fp_proto = FIB_PROTOCOL_IP4,
2735 .ip4.as_u32 = clib_host_to_net_u32(0x17171717),
2738 fei = fib_table_entry_path_add(fib_index,
2739 &pfx_23_23_23_0_s_24,
2741 FIB_ENTRY_FLAG_NONE,
2743 &pfx_23_23_23_23_s_32.fp_addr,
2748 FIB_ROUTE_PATH_FLAG_NONE);
2749 dpo = fib_entry_contribute_ip_forwarding(fei);
2750 FIB_TEST(load_balance_is_drop(dpo),
2751 "23.23.23.0/24 via covered is DROP");
2752 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
2755 * add-remove test. no change.
2757 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2758 fib_path_list_db_size());
2759 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2760 fib_path_list_pool_size());
2761 FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2762 fib_entry_pool_size());
2765 * A recursive route with recursion constraints.
2766 * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained
2768 fib_table_entry_path_add(fib_index,
2771 FIB_ENTRY_FLAG_NONE,
2778 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
2780 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2781 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2783 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2784 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2786 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2787 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
2790 * save the load-balance. we expect it to be inplace modified
2792 lb = load_balance_get(dpo1->dpoi_index);
2795 * add a covering prefix for the via fib that would otherwise serve
2796 * as the resolving route when the host is removed
2798 fib_table_entry_path_add(fib_index,
2801 FIB_ENTRY_FLAG_NONE,
2804 tm->hw[0]->sw_if_index,
2805 ~0, // invalid fib index
2808 FIB_ROUTE_PATH_FLAG_NONE);
2809 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28);
2810 ai = fib_entry_get_adj(fei);
2811 FIB_TEST((ai == ai_01),
2812 "adj for 1.1.1.0/28 is via adj for 1.1.1.1");
2815 * remove the host via FIB - expect the BGP prefix to be drop
2817 fib_table_entry_path_remove(fib_index,
2822 tm->hw[0]->sw_if_index,
2823 ~0, // invalid fib index
2825 FIB_ROUTE_PATH_FLAG_NONE);
2827 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2828 "adj for 200.200.200.200/32 is recursive via adj for DROP");
2831 * add the via-entry host reoute back. expect to resolve again
2833 fib_table_entry_path_add(fib_index,
2836 FIB_ENTRY_FLAG_NONE,
2839 tm->hw[0]->sw_if_index,
2840 ~0, // invalid fib index
2843 FIB_ROUTE_PATH_FLAG_NONE);
2844 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2845 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
2848 * add another path for the recursive. it will then have 2.
2850 fib_prefix_t pfx_1_1_1_3_s_32 = {
2852 .fp_proto = FIB_PROTOCOL_IP4,
2854 .ip4.as_u32 = clib_host_to_net_u32(0x01010103),
2857 fib_table_entry_path_add(fib_index,
2860 FIB_ENTRY_FLAG_NONE,
2863 tm->hw[0]->sw_if_index,
2864 ~0, // invalid fib index
2867 FIB_ROUTE_PATH_FLAG_NONE);
2869 fib_table_entry_path_add(fib_index,
2872 FIB_ENTRY_FLAG_NONE,
2874 &pfx_1_1_1_3_s_32.fp_addr,
2879 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
2881 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2882 dpo = fib_entry_contribute_ip_forwarding(fei);
2884 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2885 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2886 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)),
2887 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
2888 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32);
2889 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2890 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)),
2891 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3");
2894 * expect the lb-map used by the recursive's load-balance is using both buckets
2896 load_balance_map_t *lbm;
2899 lb = load_balance_get(dpo->dpoi_index);
2901 load_balance_map_lock(lbmi);
2902 lbm = load_balance_map_get(lbmi);
2904 FIB_TEST(lbm->lbm_buckets[0] == 0,
2905 "LB maps's bucket 0 is %d",
2906 lbm->lbm_buckets[0]);
2907 FIB_TEST(lbm->lbm_buckets[1] == 1,
2908 "LB maps's bucket 1 is %d",
2909 lbm->lbm_buckets[1]);
2912 * withdraw one of the /32 via-entrys.
2913 * that ECMP path will be unresolved and forwarding should continue on the
2914 * other available path. this is an iBGP PIC edge failover.
2915 * Test the forwarding changes without re-fetching the adj from the
2916 * recursive entry. this ensures its the same one that is updated; i.e. an
2919 fib_table_entry_path_remove(fib_index,
2924 tm->hw[0]->sw_if_index,
2925 ~0, // invalid fib index
2927 FIB_ROUTE_PATH_FLAG_NONE);
2929 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2930 FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)),
2931 "post PIC 200.200.200.200/32 was inplace modified");
2933 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)),
2934 "post PIC adj for 200.200.200.200/32 is recursive"
2935 " via adj for 1.1.1.3");
2938 * the LB maps that was locked above should have been modified to remove
2939 * the path that was down, and thus its bucket points to a path that is
2942 FIB_TEST(lbm->lbm_buckets[0] == 1,
2943 "LB maps's bucket 0 is %d",
2944 lbm->lbm_buckets[0]);
2945 FIB_TEST(lbm->lbm_buckets[1] == 1,
2946 "LB maps's bucket 1 is %d",
2947 lbm->lbm_buckets[1]);
2949 load_balance_map_unlock(lb->lb_map);
2952 * add it back. again
2954 fib_table_entry_path_add(fib_index,
2957 FIB_ENTRY_FLAG_NONE,
2960 tm->hw[0]->sw_if_index,
2961 ~0, // invalid fib index
2964 FIB_ROUTE_PATH_FLAG_NONE);
2966 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)),
2967 "post PIC recovery adj for 200.200.200.200/32 is recursive "
2968 "via adj for 1.1.1.1");
2969 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)),
2970 "post PIC recovery adj for 200.200.200.200/32 is recursive "
2971 "via adj for 1.1.1.3");
2973 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2974 dpo = fib_entry_contribute_ip_forwarding(fei);
2975 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
2976 "post PIC 200.200.200.200/32 was inplace modified");
2979 * add a 3rd path. this makes the LB 16 buckets.
2981 fib_table_entry_path_add(fib_index,
2984 FIB_ENTRY_FLAG_NONE,
2986 &pfx_1_1_1_2_s_32.fp_addr,
2991 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
2993 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2994 dpo = fib_entry_contribute_ip_forwarding(fei);
2995 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
2996 "200.200.200.200/32 was inplace modified for 3rd path");
2997 FIB_TEST(16 == lb->lb_n_buckets,
2998 "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets");
3001 load_balance_map_lock(lbmi);
3002 lbm = load_balance_map_get(lbmi);
3004 for (ii = 0; ii < 16; ii++)
3006 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3007 "LB Map for 200.200.200.200/32 at %d is %d",
3008 ii, lbm->lbm_buckets[ii]);
3012 * trigger PIC by removing the first via-entry
3013 * the first 6 buckets of the map should map to the next 6
3015 fib_table_entry_path_remove(fib_index,
3020 tm->hw[0]->sw_if_index,
3023 FIB_ROUTE_PATH_FLAG_NONE);
3025 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3026 dpo = fib_entry_contribute_ip_forwarding(fei);
3027 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3028 "200.200.200.200/32 was inplace modified for 3rd path");
3029 FIB_TEST(2 == lb->lb_n_buckets,
3030 "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets");
3032 for (ii = 0; ii < 6; ii++)
3034 FIB_TEST(lbm->lbm_buckets[ii] == ii+6,
3035 "LB Map for 200.200.200.200/32 at %d is %d",
3036 ii, lbm->lbm_buckets[ii]);
3038 for (ii = 6; ii < 16; ii++)
3040 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3041 "LB Map for 200.200.200.200/32 at %d is %d",
3042 ii, lbm->lbm_buckets[ii]);
3049 fib_table_entry_path_add(fib_index,
3052 FIB_ENTRY_FLAG_NONE,
3055 tm->hw[0]->sw_if_index,
3059 FIB_ROUTE_PATH_FLAG_NONE);
3061 fib_table_entry_path_remove(fib_index,
3065 &pfx_1_1_1_2_s_32.fp_addr,
3069 MPLS_LABEL_INVALID);
3070 fib_table_entry_path_remove(fib_index,
3078 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3079 fib_table_entry_path_remove(fib_index,
3083 &pfx_1_1_1_3_s_32.fp_addr,
3087 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3088 fib_table_entry_delete(fib_index,
3091 fib_table_entry_delete(fib_index,
3094 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3095 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)),
3096 "1.1.1.1/28 removed");
3097 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3098 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)),
3099 "1.1.1.3/32 removed");
3100 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3101 fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)),
3102 "200.200.200.200/32 removed");
3105 * add-remove test. no change.
3107 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3108 fib_path_list_db_size());
3109 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3110 fib_path_list_pool_size());
3111 FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3112 fib_entry_pool_size());
3115 * A route whose paths are built up iteratively and then removed
3118 fib_prefix_t pfx_4_4_4_4_s_32 = {
3120 .fp_proto = FIB_PROTOCOL_IP4,
3123 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
3127 fib_table_entry_path_add(fib_index,
3130 FIB_ENTRY_FLAG_NONE,
3133 tm->hw[0]->sw_if_index,
3137 FIB_ROUTE_PATH_FLAG_NONE);
3138 fib_table_entry_path_add(fib_index,
3141 FIB_ENTRY_FLAG_NONE,
3144 tm->hw[0]->sw_if_index,
3148 FIB_ROUTE_PATH_FLAG_NONE);
3149 fib_table_entry_path_add(fib_index,
3152 FIB_ENTRY_FLAG_NONE,
3155 tm->hw[0]->sw_if_index,
3159 FIB_ROUTE_PATH_FLAG_NONE);
3160 FIB_TEST(FIB_NODE_INDEX_INVALID !=
3161 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3162 "4.4.4.4/32 present");
3164 fib_table_entry_delete(fib_index,
3167 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3168 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3169 "4.4.4.4/32 removed");
3172 * add-remove test. no change.
3174 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3175 fib_path_list_db_size());
3176 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3177 fib_path_list_pool_size());
3178 FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3179 fib_entry_pool_size());
3182 * A route with multiple paths at once
3184 fib_route_path_t *r_paths = NULL;
3186 for (ii = 0; ii < 4; ii++)
3188 fib_route_path_t r_path = {
3189 .frp_proto = FIB_PROTOCOL_IP4,
3191 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
3193 .frp_sw_if_index = tm->hw[0]->sw_if_index,
3195 .frp_fib_index = ~0,
3197 vec_add1(r_paths, r_path);
3200 fib_table_entry_update(fib_index,
3203 FIB_ENTRY_FLAG_NONE,
3206 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3207 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3208 dpo = fib_entry_contribute_ip_forwarding(fei);
3210 lb = load_balance_get(dpo->dpoi_index);
3211 FIB_TEST((lb->lb_n_buckets == 4), "4.4.4.4/32 lb over %d paths", lb->lb_n_buckets);
3213 fib_table_entry_delete(fib_index,
3216 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3217 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3218 "4.4.4.4/32 removed");
3222 * add-remove test. no change.
3224 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3225 fib_path_list_db_size());
3226 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3227 fib_path_list_pool_size());
3228 FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3229 fib_entry_pool_size());
3232 * A route deag route
3234 fib_table_entry_path_add(fib_index,
3237 FIB_ENTRY_FLAG_NONE,
3244 FIB_ROUTE_PATH_FLAG_NONE);
3246 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3247 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3249 dpo = fib_entry_contribute_ip_forwarding(fei);
3250 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3251 lookup_dpo_t *lkd = lookup_dpo_get(dpo->dpoi_index);
3253 FIB_TEST((fib_index == lkd->lkd_fib_index),
3254 "4.4.4.4/32 is deag in %d %U",
3256 format_dpo_id, dpo, 0);
3258 fib_table_entry_delete(fib_index,
3261 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3262 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3263 "4.4.4.4/32 removed");
3267 * add-remove test. no change.
3269 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3270 fib_path_list_db_size());
3271 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3272 fib_path_list_pool_size());
3273 FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3274 fib_entry_pool_size());
3278 * add a recursive with duplicate paths. Expect the duplicate to be ignored.
3280 fib_prefix_t pfx_34_1_1_1_s_32 = {
3282 .fp_proto = FIB_PROTOCOL_IP4,
3284 .ip4.as_u32 = clib_host_to_net_u32(0x22010101),
3287 fib_prefix_t pfx_34_34_1_1_s_32 = {
3289 .fp_proto = FIB_PROTOCOL_IP4,
3291 .ip4.as_u32 = clib_host_to_net_u32(0x22220101),
3294 fei = fib_table_entry_path_add(fib_index,
3297 FIB_ENTRY_FLAG_NONE,
3299 &pfx_34_34_1_1_s_32.fp_addr,
3304 FIB_ROUTE_PATH_FLAG_NONE);
3305 fei = fib_table_entry_path_add(fib_index,
3308 FIB_ENTRY_FLAG_NONE,
3310 &pfx_34_34_1_1_s_32.fp_addr,
3315 FIB_ROUTE_PATH_FLAG_NONE);
3316 FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0);
3317 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3321 * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32
3322 * all of which are via 10.10.10.1, Itf1
3324 fib_table_entry_path_remove(fib_index,
3329 tm->hw[0]->sw_if_index,
3332 FIB_ROUTE_PATH_FLAG_NONE);
3333 fib_table_entry_path_remove(fib_index,
3338 tm->hw[0]->sw_if_index,
3341 FIB_ROUTE_PATH_FLAG_NONE);
3342 fib_table_entry_path_remove(fib_index,
3347 tm->hw[0]->sw_if_index,
3350 FIB_ROUTE_PATH_FLAG_NONE);
3352 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3353 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32),
3354 "1.1.1.1/32 removed");
3355 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3356 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32),
3357 "1.1.1.2/32 removed");
3358 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3359 fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24),
3360 "1.1.2.0/24 removed");
3363 * -3 entries and -1 shared path-list
3365 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3366 fib_path_list_db_size());
3367 FIB_TEST((NBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3368 fib_path_list_pool_size());
3369 FIB_TEST((NBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3370 fib_entry_pool_size());
3373 * An attached-host route. Expect to link to the incomplete adj
3375 fib_prefix_t pfx_4_1_1_1_s_32 = {
3377 .fp_proto = FIB_PROTOCOL_IP4,
3380 .ip4.as_u32 = clib_host_to_net_u32(0x04010101),
3383 fib_table_entry_path_add(fib_index,
3386 FIB_ENTRY_FLAG_NONE,
3389 tm->hw[0]->sw_if_index,
3393 FIB_ROUTE_PATH_FLAG_NONE);
3395 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32);
3396 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present");
3397 ai = fib_entry_get_adj(fei);
3399 ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
3401 &pfx_4_1_1_1_s_32.fp_addr,
3402 tm->hw[0]->sw_if_index);
3403 FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ");
3407 * +1 entry and +1 shared path-list
3409 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3410 fib_path_list_db_size());
3411 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3412 fib_path_list_pool_size());
3413 FIB_TEST((NBR+5 == fib_entry_pool_size()), "entry pool size is %d",
3414 fib_entry_pool_size());
3416 fib_table_entry_delete(fib_index,
3420 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3421 fib_path_list_db_size());
3422 FIB_TEST((NBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3423 fib_path_list_pool_size());
3424 FIB_TEST((NBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3425 fib_entry_pool_size());
3428 * add a v6 prefix via v4 next-hops
3430 fib_prefix_t pfx_2001_s_64 = {
3432 .fp_proto = FIB_PROTOCOL_IP6,
3434 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
3437 fei = fib_table_entry_path_add(0, //default v6 table
3440 FIB_ENTRY_FLAG_NONE,
3443 tm->hw[0]->sw_if_index,
3447 FIB_ROUTE_PATH_FLAG_NONE);
3449 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
3450 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present");
3451 ai = fib_entry_get_adj(fei);
3453 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
3454 "2001::/64 via ARP-adj");
3455 FIB_TEST((adj->ia_link == VNET_LINK_IP6),
3456 "2001::/64 is link type v6");
3457 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4),
3458 "2001::/64 ADJ-adj is NH proto v4");
3459 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
3462 * add a uRPF exempt prefix:
3464 * - it's forwarding is drop
3465 * - it's uRPF list is not empty
3466 * - the uRPF list for the default route (it's cover) is empty
3468 fei = fib_table_entry_special_add(fib_index,
3470 FIB_SOURCE_URPF_EXEMPT,
3471 FIB_ENTRY_FLAG_DROP,
3473 dpo = fib_entry_contribute_ip_forwarding(fei);
3474 FIB_TEST(load_balance_is_drop(dpo),
3475 "uRPF exempt 4.1.1.1/32 DROP");
3476 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0),
3477 "uRPF list for exempt prefix has itf index 0");
3478 fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0);
3479 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
3480 "uRPF list for 0.0.0.0/0 empty");
3482 fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
3488 fib_table_entry_delete(fib_index,
3489 &pfx_10_10_10_1_s_32,
3491 fib_table_entry_delete(fib_index,
3492 &pfx_10_10_10_2_s_32,
3494 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3495 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32),
3496 "10.10.10.1/32 adj-fib removed");
3497 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3498 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32),
3499 "10.10.10.2/32 adj-fib removed");
3502 * -2 entries and -2 non-shared path-list
3504 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3505 fib_path_list_db_size());
3506 FIB_TEST((NBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
3507 fib_path_list_pool_size());
3508 FIB_TEST((NBR+2 == fib_entry_pool_size()), "entry pool size is %d",
3509 fib_entry_pool_size());
3512 * unlock the adjacencies for which this test provided a rewrite.
3513 * These are the last locks on these adjs. they should thus go away.
3517 adj_unlock(ai_12_12_12_12);
3519 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
3524 * remove the interface prefixes
3526 local_pfx.fp_len = 32;
3527 fib_table_entry_special_remove(fib_index, &local_pfx,
3528 FIB_SOURCE_INTERFACE);
3529 fei = fib_table_lookup(fib_index, &local_pfx);
3531 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3532 fib_table_lookup_exact_match(fib_index, &local_pfx),
3533 "10.10.10.10/32 adj-fib removed");
3535 local_pfx.fp_len = 24;
3536 fib_table_entry_delete(fib_index, &local_pfx,
3537 FIB_SOURCE_INTERFACE);
3539 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3540 fib_table_lookup_exact_match(fib_index, &local_pfx),
3541 "10.10.10.10/24 adj-fib removed");
3544 * -2 entries and -2 non-shared path-list
3546 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3547 fib_path_list_db_size());
3548 FIB_TEST((NBR == fib_path_list_pool_size()), "path list pool size is %d",
3549 fib_path_list_pool_size());
3550 FIB_TEST((NBR == fib_entry_pool_size()), "entry pool size is %d",
3551 fib_entry_pool_size());
3554 * Last but not least, remove the VRF
3556 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
3559 "NO API Source'd prefixes");
3560 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
3563 "NO RR Source'd prefixes");
3564 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
3566 FIB_SOURCE_INTERFACE)),
3567 "NO INterface Source'd prefixes");
3569 fib_table_unlock(fib_index, FIB_PROTOCOL_IP4);
3571 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3572 fib_path_list_db_size());
3573 FIB_TEST((NBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
3574 fib_path_list_pool_size());
3575 FIB_TEST((NBR-5 == fib_entry_pool_size()), "entry pool size is %d",
3576 fib_entry_pool_size());
3577 FIB_TEST((NBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
3578 pool_elts(fib_urpf_list_pool));
3587 * In the default table check for the presence and correct forwarding
3588 * of the special entries
3590 fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02;
3591 const dpo_id_t *dpo, *dpo_drop;
3592 const ip_adjacency_t *adj;
3593 const receive_dpo_t *rd;
3598 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
3601 /* via 2001:0:0:1::2 */
3602 ip46_address_t nh_2001_2 = {
3605 [0] = clib_host_to_net_u64(0x2001000000000001),
3606 [1] = clib_host_to_net_u64(0x0000000000000002),
3613 dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
3615 /* Find or create FIB table 11 */
3616 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11);
3618 for (ii = 0; ii < 4; ii++)
3620 ip6_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
3623 fib_prefix_t pfx_0_0 = {
3625 .fp_proto = FIB_PROTOCOL_IP6,
3633 dfrt = fib_table_lookup(fib_index, &pfx_0_0);
3634 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
3635 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
3636 "Default route is DROP");
3638 dpo = fib_entry_contribute_ip_forwarding(dfrt);
3639 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
3642 &pfx_0_0.fp_addr.ip6)),
3643 "default-route; fwd and non-fwd tables match");
3645 // FIXME - check specials.
3648 * At this stage there is one v4 FIB with 5 routes and two v6 FIBs
3649 * each with 6 entries. All entries are special so no path-list sharing.
3652 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
3653 FIB_TEST((NPS == fib_path_list_pool_size()), "path list pool size is %d",
3654 fib_path_list_pool_size());
3655 FIB_TEST((NPS == fib_entry_pool_size()), "entry pool size is %d",
3656 fib_entry_pool_size());
3659 * add interface routes.
3660 * validate presence of /64 attached and /128 recieve.
3661 * test for the presence of the receive address in the glean and local adj
3663 * receive on 2001:0:0:1::1/128
3665 fib_prefix_t local_pfx = {
3667 .fp_proto = FIB_PROTOCOL_IP6,
3671 [0] = clib_host_to_net_u64(0x2001000000000001),
3672 [1] = clib_host_to_net_u64(0x0000000000000001),
3678 fib_table_entry_update_one_path(fib_index, &local_pfx,
3679 FIB_SOURCE_INTERFACE,
3680 (FIB_ENTRY_FLAG_CONNECTED |
3681 FIB_ENTRY_FLAG_ATTACHED),
3684 tm->hw[0]->sw_if_index,
3688 FIB_ROUTE_PATH_FLAG_NONE);
3689 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
3691 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
3693 ai = fib_entry_get_adj(fei);
3694 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
3696 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
3697 "attached interface adj is glean");
3698 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
3699 &adj->sub_type.glean.receive_addr)),
3700 "attached interface adj is receive ok");
3701 dpo = fib_entry_contribute_ip_forwarding(fei);
3702 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
3705 &local_pfx.fp_addr.ip6)),
3706 "attached-route; fwd and non-fwd tables match");
3708 local_pfx.fp_len = 128;
3709 fib_table_entry_update_one_path(fib_index, &local_pfx,
3710 FIB_SOURCE_INTERFACE,
3711 (FIB_ENTRY_FLAG_CONNECTED |
3712 FIB_ENTRY_FLAG_LOCAL),
3715 tm->hw[0]->sw_if_index,
3716 ~0, // invalid fib index
3719 FIB_ROUTE_PATH_FLAG_NONE);
3720 fei = fib_table_lookup(fib_index, &local_pfx);
3722 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
3724 dpo = fib_entry_contribute_ip_forwarding(fei);
3725 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3726 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
3727 "local interface adj is local");
3728 rd = receive_dpo_get(dpo->dpoi_index);
3730 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
3732 "local interface adj is receive ok");
3734 dpo = fib_entry_contribute_ip_forwarding(fei);
3735 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
3738 &local_pfx.fp_addr.ip6)),
3739 "local-route; fwd and non-fwd tables match");
3742 * +2 entries. +2 unshared path-lists
3744 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
3745 FIB_TEST((NPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
3746 fib_path_list_pool_size());
3747 FIB_TEST((NPS+2 == fib_entry_pool_size()), "entry pool size is %d",
3748 fib_entry_pool_size());
3751 * Modify the default route to be via an adj not yet known.
3752 * this sources the defalut route with the API source, which is
3753 * a higher preference to the DEFAULT_ROUTE source
3755 fib_table_entry_path_add(fib_index, &pfx_0_0,
3757 FIB_ENTRY_FLAG_NONE,
3760 tm->hw[0]->sw_if_index,
3764 FIB_ROUTE_PATH_FLAG_NONE);
3765 fei = fib_table_lookup(fib_index, &pfx_0_0);
3767 FIB_TEST((fei == dfrt), "default route same index");
3768 ai = fib_entry_get_adj(fei);
3769 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
3771 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
3772 "adj is incomplete");
3773 FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)),
3774 "adj nbr next-hop ok");
3777 * find the adj in the shared db
3779 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
3782 tm->hw[0]->sw_if_index);
3783 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
3784 adj_unlock(locked_ai);
3787 * no more entires. +1 shared path-list
3789 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3790 fib_path_list_db_size());
3791 FIB_TEST((NPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
3792 fib_path_list_pool_size());
3793 FIB_TEST((NPS+2 == fib_entry_pool_size()), "entry pool size is %d",
3794 fib_entry_pool_size());
3797 * remove the API source from the default route. We expected
3798 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
3800 fib_table_entry_path_remove(fib_index, &pfx_0_0,
3804 tm->hw[0]->sw_if_index,
3807 FIB_ROUTE_PATH_FLAG_NONE);
3808 fei = fib_table_lookup(fib_index, &pfx_0_0);
3810 FIB_TEST((fei == dfrt), "default route same index");
3811 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
3812 "Default route is DROP");
3815 * no more entires. -1 shared path-list
3817 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3818 fib_path_list_db_size());
3819 FIB_TEST((NPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
3820 fib_path_list_pool_size());
3821 FIB_TEST((NPS+2 == fib_entry_pool_size()), "entry pool size is %d",
3822 fib_entry_pool_size());
3825 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
3827 fib_prefix_t pfx_2001_1_2_s_128 = {
3829 .fp_proto = FIB_PROTOCOL_IP6,
3833 [0] = clib_host_to_net_u64(0x2001000000000001),
3834 [1] = clib_host_to_net_u64(0x0000000000000002),
3839 fib_prefix_t pfx_2001_1_3_s_128 = {
3841 .fp_proto = FIB_PROTOCOL_IP6,
3845 [0] = clib_host_to_net_u64(0x2001000000000001),
3846 [1] = clib_host_to_net_u64(0x0000000000000003),
3852 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
3855 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
3857 &pfx_2001_1_2_s_128.fp_addr,
3858 tm->hw[0]->sw_if_index);
3859 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
3860 adj = adj_get(ai_01);
3861 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
3862 "adj is incomplete");
3863 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
3864 &adj->sub_type.nbr.next_hop)),
3865 "adj nbr next-hop ok");
3867 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
3868 fib_test_build_rewrite(eth_addr));
3869 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
3871 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
3872 &adj->sub_type.nbr.next_hop)),
3873 "adj nbr next-hop ok");
3875 fib_table_entry_update_one_path(fib_index,
3876 &pfx_2001_1_2_s_128,
3878 FIB_ENTRY_FLAG_NONE,
3880 &pfx_2001_1_2_s_128.fp_addr,
3881 tm->hw[0]->sw_if_index,
3885 FIB_ROUTE_PATH_FLAG_NONE);
3887 fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
3888 ai = fib_entry_get_adj(fei);
3889 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
3893 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
3895 &pfx_2001_1_3_s_128.fp_addr,
3896 tm->hw[0]->sw_if_index);
3897 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
3898 adj = adj_get(ai_02);
3899 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
3900 "adj is incomplete");
3901 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
3902 &adj->sub_type.nbr.next_hop)),
3903 "adj nbr next-hop ok");
3905 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
3906 fib_test_build_rewrite(eth_addr));
3907 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
3909 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
3910 &adj->sub_type.nbr.next_hop)),
3911 "adj nbr next-hop ok");
3912 FIB_TEST((ai_01 != ai_02), "ADJs are different");
3914 fib_table_entry_update_one_path(fib_index,
3915 &pfx_2001_1_3_s_128,
3917 FIB_ENTRY_FLAG_NONE,
3919 &pfx_2001_1_3_s_128.fp_addr,
3920 tm->hw[0]->sw_if_index,
3924 FIB_ROUTE_PATH_FLAG_NONE);
3926 fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
3927 ai = fib_entry_get_adj(fei);
3928 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
3931 * +2 entries, +2 unshread path-lists.
3933 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3934 fib_path_list_db_size());
3935 FIB_TEST((NPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
3936 fib_path_list_pool_size());
3937 FIB_TEST((NPS+4 == fib_entry_pool_size()), "entry pool size is %d",
3938 fib_entry_pool_size());
3941 * Add a 2 routes via the first ADJ. ensure path-list sharing
3943 fib_prefix_t pfx_2001_a_s_64 = {
3945 .fp_proto = FIB_PROTOCOL_IP6,
3949 [0] = clib_host_to_net_u64(0x200100000000000a),
3950 [1] = clib_host_to_net_u64(0x0000000000000000),
3955 fib_prefix_t pfx_2001_b_s_64 = {
3957 .fp_proto = FIB_PROTOCOL_IP6,
3961 [0] = clib_host_to_net_u64(0x200100000000000b),
3962 [1] = clib_host_to_net_u64(0x0000000000000000),
3968 fib_table_entry_path_add(fib_index,
3971 FIB_ENTRY_FLAG_NONE,
3974 tm->hw[0]->sw_if_index,
3978 FIB_ROUTE_PATH_FLAG_NONE);
3979 fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64);
3980 ai = fib_entry_get_adj(fei);
3981 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
3982 fib_table_entry_path_add(fib_index,
3985 FIB_ENTRY_FLAG_NONE,
3988 tm->hw[0]->sw_if_index,
3992 FIB_ROUTE_PATH_FLAG_NONE);
3993 fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64);
3994 ai = fib_entry_get_adj(fei);
3995 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
3998 * +2 entries, +1 shared path-list.
4000 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4001 fib_path_list_db_size());
4002 FIB_TEST((NPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4003 fib_path_list_pool_size());
4004 FIB_TEST((NPS+6 == fib_entry_pool_size()), "entry pool size is %d",
4005 fib_entry_pool_size());
4008 * add a v4 prefix via a v6 next-hop
4010 fib_prefix_t pfx_1_1_1_1_s_32 = {
4012 .fp_proto = FIB_PROTOCOL_IP4,
4014 .ip4.as_u32 = 0x01010101,
4017 fei = fib_table_entry_path_add(0, // default table
4020 FIB_ENTRY_FLAG_NONE,
4023 tm->hw[0]->sw_if_index,
4027 FIB_ROUTE_PATH_FLAG_NONE);
4028 FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32),
4029 "1.1.1.1/32 o v6 route present");
4030 ai = fib_entry_get_adj(fei);
4032 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
4033 "1.1.1.1/32 via ARP-adj");
4034 FIB_TEST((adj->ia_link == VNET_LINK_IP4),
4035 "1.1.1.1/32 ADJ-adj is link type v4");
4036 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6),
4037 "1.1.1.1/32 ADJ-adj is NH proto v6");
4038 fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API);
4043 fib_prefix_t pfx_2001_c_s_64 = {
4045 .fp_proto = FIB_PROTOCOL_IP6,
4049 [0] = clib_host_to_net_u64(0x200100000000000c),
4050 [1] = clib_host_to_net_u64(0x0000000000000000),
4055 fib_table_entry_path_add(fib_index,
4058 FIB_ENTRY_FLAG_ATTACHED,
4061 tm->hw[0]->sw_if_index,
4065 FIB_ROUTE_PATH_FLAG_NONE);
4066 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4067 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present");
4068 ai = fib_entry_get_adj(fei);
4070 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN),
4071 "2001:0:0:c/64 attached resolves via glean");
4073 fib_table_entry_path_remove(fib_index,
4078 tm->hw[0]->sw_if_index,
4081 FIB_ROUTE_PATH_FLAG_NONE);
4082 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4083 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached route removed");
4086 * Shutdown the interface on which we have a connected and through
4087 * which the routes are reachable.
4088 * This will result in the connected, adj-fibs, and routes linking to drop
4089 * The local/for-us prefix continues to receive.
4091 clib_error_t * error;
4093 error = vnet_sw_interface_set_flags(vnet_get_main(),
4094 tm->hw[0]->sw_if_index,
4095 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4096 FIB_TEST((NULL == error), "Interface shutdown OK");
4098 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4099 dpo = fib_entry_contribute_ip_forwarding(fei);
4100 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4101 "2001::b/64 resolves via drop");
4103 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4104 dpo = fib_entry_contribute_ip_forwarding(fei);
4105 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4106 "2001::a/64 resolves via drop");
4107 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4108 dpo = fib_entry_contribute_ip_forwarding(fei);
4109 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4110 "2001:0:0:1::3/64 resolves via drop");
4111 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4112 dpo = fib_entry_contribute_ip_forwarding(fei);
4113 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4114 "2001:0:0:1::2/64 resolves via drop");
4115 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4116 dpo = fib_entry_contribute_ip_forwarding(fei);
4117 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4118 "2001:0:0:1::1/128 not drop");
4119 local_pfx.fp_len = 64;
4120 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4121 dpo = fib_entry_contribute_ip_forwarding(fei);
4122 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4123 "2001:0:0:1/64 resolves via drop");
4128 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4129 fib_path_list_db_size());
4130 FIB_TEST((NPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4131 fib_path_list_pool_size());
4132 FIB_TEST((NPS+6 == fib_entry_pool_size()), "entry pool size is %d",
4133 fib_entry_pool_size());
4136 * shutdown one of the other interfaces, then add a connected.
4137 * and swap one of the routes to it.
4139 error = vnet_sw_interface_set_flags(vnet_get_main(),
4140 tm->hw[1]->sw_if_index,
4141 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4142 FIB_TEST((NULL == error), "Interface 1 shutdown OK");
4144 fib_prefix_t connected_pfx = {
4146 .fp_proto = FIB_PROTOCOL_IP6,
4149 /* 2001:0:0:2::1/64 */
4151 [0] = clib_host_to_net_u64(0x2001000000000002),
4152 [1] = clib_host_to_net_u64(0x0000000000000001),
4157 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4158 FIB_SOURCE_INTERFACE,
4159 (FIB_ENTRY_FLAG_CONNECTED |
4160 FIB_ENTRY_FLAG_ATTACHED),
4163 tm->hw[1]->sw_if_index,
4167 FIB_ROUTE_PATH_FLAG_NONE);
4168 fei = fib_table_lookup_exact_match(fib_index, &connected_pfx);
4169 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4170 dpo = fib_entry_contribute_ip_forwarding(fei);
4171 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4172 FIB_TEST(!dpo_cmp(dpo, dpo_drop),
4173 "2001:0:0:2/64 not resolves via drop");
4175 connected_pfx.fp_len = 128;
4176 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4177 FIB_SOURCE_INTERFACE,
4178 (FIB_ENTRY_FLAG_CONNECTED |
4179 FIB_ENTRY_FLAG_LOCAL),
4182 tm->hw[0]->sw_if_index,
4183 ~0, // invalid fib index
4186 FIB_ROUTE_PATH_FLAG_NONE);
4187 fei = fib_table_lookup(fib_index, &connected_pfx);
4189 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4190 dpo = fib_entry_contribute_ip_forwarding(fei);
4191 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4192 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4193 "local interface adj is local");
4194 rd = receive_dpo_get(dpo->dpoi_index);
4195 FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr,
4197 "local interface adj is receive ok");
4200 * +2 entries, +2 unshared path-lists
4202 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4203 fib_path_list_db_size());
4204 FIB_TEST((NPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
4205 fib_path_list_pool_size());
4206 FIB_TEST((NPS+8 == fib_entry_pool_size()), "entry pool size is %d",
4207 fib_entry_pool_size());
4211 * bring the interface back up. we expected the routes to return
4212 * to normal forwarding.
4214 error = vnet_sw_interface_set_flags(vnet_get_main(),
4215 tm->hw[0]->sw_if_index,
4216 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4217 FIB_TEST((NULL == error), "Interface bring-up OK");
4218 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4219 ai = fib_entry_get_adj(fei);
4220 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4221 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4222 ai = fib_entry_get_adj(fei);
4223 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4224 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4225 ai = fib_entry_get_adj(fei);
4226 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4227 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4228 ai = fib_entry_get_adj(fei);
4229 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4230 local_pfx.fp_len = 64;
4231 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4232 ai = fib_entry_get_adj(fei);
4234 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4235 "attached interface adj is glean");
4238 * Same test as above, but this time the HW interface goes down
4240 error = vnet_hw_interface_set_flags(vnet_get_main(),
4241 tm->hw_if_indicies[0],
4242 ~VNET_HW_INTERFACE_FLAG_LINK_UP);
4243 FIB_TEST((NULL == error), "Interface shutdown OK");
4245 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4246 dpo = fib_entry_contribute_ip_forwarding(fei);
4247 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4248 "2001::b/64 resolves via drop");
4249 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4250 dpo = fib_entry_contribute_ip_forwarding(fei);
4251 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4252 "2001::a/64 resolves via drop");
4253 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4254 dpo = fib_entry_contribute_ip_forwarding(fei);
4255 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4256 "2001:0:0:1::3/128 resolves via drop");
4257 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4258 dpo = fib_entry_contribute_ip_forwarding(fei);
4259 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4260 "2001:0:0:1::2/128 resolves via drop");
4261 local_pfx.fp_len = 128;
4262 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4263 dpo = fib_entry_contribute_ip_forwarding(fei);
4264 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4265 "2001:0:0:1::1/128 not drop");
4266 local_pfx.fp_len = 64;
4267 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4268 dpo = fib_entry_contribute_ip_forwarding(fei);
4269 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4270 "2001:0:0:1/64 resolves via drop");
4272 error = vnet_hw_interface_set_flags(vnet_get_main(),
4273 tm->hw_if_indicies[0],
4274 VNET_HW_INTERFACE_FLAG_LINK_UP);
4275 FIB_TEST((NULL == error), "Interface bring-up OK");
4276 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4277 ai = fib_entry_get_adj(fei);
4278 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4279 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4280 ai = fib_entry_get_adj(fei);
4281 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4282 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4283 ai = fib_entry_get_adj(fei);
4284 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4285 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4286 ai = fib_entry_get_adj(fei);
4287 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4288 local_pfx.fp_len = 64;
4289 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4290 ai = fib_entry_get_adj(fei);
4292 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4293 "attached interface adj is glean");
4296 * Delete the interface that the routes reolve through.
4297 * Again no routes are removed. They all point to drop.
4299 * This is considered an error case. The control plane should
4300 * not remove interfaces through which routes resolve, but
4301 * such things can happen. ALL affected routes will drop.
4303 vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]);
4305 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4306 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4307 "2001::b/64 resolves via drop");
4308 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4309 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4310 "2001::b/64 resolves via drop");
4311 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4312 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4313 "2001:0:0:1::3/64 resolves via drop");
4314 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4315 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4316 "2001:0:0:1::2/64 resolves via drop");
4317 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4318 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4319 "2001:0:0:1::1/128 is drop");
4320 local_pfx.fp_len = 64;
4321 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4322 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4323 "2001:0:0:1/64 resolves via drop");
4328 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4329 fib_path_list_db_size());
4330 FIB_TEST((NPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
4331 fib_path_list_pool_size());
4332 FIB_TEST((NPS+8 == fib_entry_pool_size()), "entry pool size is %d",
4333 fib_entry_pool_size());
4336 * Add the interface back. routes stay unresolved.
4338 error = ethernet_register_interface(vnet_get_main(),
4339 test_interface_device_class.index,
4342 &tm->hw_if_indicies[0],
4343 /* flag change */ 0);
4345 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4346 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4347 "2001::b/64 resolves via drop");
4348 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4349 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4350 "2001::b/64 resolves via drop");
4351 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4352 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4353 "2001:0:0:1::3/64 resolves via drop");
4354 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4355 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4356 "2001:0:0:1::2/64 resolves via drop");
4357 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4358 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4359 "2001:0:0:1::1/128 is drop");
4360 local_pfx.fp_len = 64;
4361 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4362 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4363 "2001:0:0:1/64 resolves via drop");
4366 * CLEANUP ALL the routes
4368 fib_table_entry_delete(fib_index,
4371 fib_table_entry_delete(fib_index,
4374 fib_table_entry_delete(fib_index,
4377 fib_table_entry_delete(fib_index,
4378 &pfx_2001_1_3_s_128,
4380 fib_table_entry_delete(fib_index,
4381 &pfx_2001_1_2_s_128,
4383 local_pfx.fp_len = 64;
4384 fib_table_entry_delete(fib_index, &local_pfx,
4385 FIB_SOURCE_INTERFACE);
4386 local_pfx.fp_len = 128;
4387 fib_table_entry_special_remove(fib_index, &local_pfx,
4388 FIB_SOURCE_INTERFACE);
4389 connected_pfx.fp_len = 64;
4390 fib_table_entry_delete(fib_index, &connected_pfx,
4391 FIB_SOURCE_INTERFACE);
4392 connected_pfx.fp_len = 128;
4393 fib_table_entry_special_remove(fib_index, &connected_pfx,
4394 FIB_SOURCE_INTERFACE);
4396 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4397 fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)),
4398 "2001::a/64 removed");
4399 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4400 fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)),
4401 "2001::b/64 removed");
4402 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4403 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)),
4404 "2001:0:0:1::3/128 removed");
4405 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4406 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)),
4407 "2001:0:0:1::3/128 removed");
4408 local_pfx.fp_len = 64;
4409 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4410 fib_table_lookup_exact_match(fib_index, &local_pfx)),
4411 "2001:0:0:1/64 removed");
4412 local_pfx.fp_len = 128;
4413 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4414 fib_table_lookup_exact_match(fib_index, &local_pfx)),
4415 "2001:0:0:1::1/128 removed");
4416 connected_pfx.fp_len = 64;
4417 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4418 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
4419 "2001:0:0:2/64 removed");
4420 connected_pfx.fp_len = 128;
4421 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4422 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
4423 "2001:0:0:2::1/128 removed");
4426 * -8 entries. -7 path-lists (1 was shared).
4428 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4429 fib_path_list_db_size());
4430 FIB_TEST((NPS == fib_path_list_pool_size()), "path list pool size is%d",
4431 fib_path_list_pool_size());
4432 FIB_TEST((NPS == fib_entry_pool_size()), "entry pool size is %d",
4433 fib_entry_pool_size());
4436 * now remove the VRF
4438 fib_table_unlock(fib_index, FIB_PROTOCOL_IP6);
4440 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4441 fib_path_list_db_size());
4442 FIB_TEST((NPS-6 == fib_path_list_pool_size()), "path list pool size is%d",
4443 fib_path_list_pool_size());
4444 FIB_TEST((NPS-6 == fib_entry_pool_size()), "entry pool size is %d",
4445 fib_entry_pool_size());
4451 * return the interfaces to up state
4453 error = vnet_sw_interface_set_flags(vnet_get_main(),
4454 tm->hw[0]->sw_if_index,
4455 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4456 error = vnet_sw_interface_set_flags(vnet_get_main(),
4457 tm->hw[1]->sw_if_index,
4458 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4460 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4465 * Test the recursive route route handling for GRE tunnels
4470 /* fib_node_index_t fei; */
4471 /* u32 fib_index = 0; */
4472 /* test_main_t *tm; */
4475 /* tm = &test_main; */
4477 /* for (ii = 0; ii < 4; ii++) */
4479 /* ip4_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = 0; */
4483 /* * add interface routes. We'll assume this works. It's more rigorously */
4484 /* * tested elsewhere. */
4486 /* fib_prefix_t local_pfx = { */
4488 /* .fp_proto = FIB_PROTOCOL_IP4, */
4491 /* /\* 10.10.10.10 *\/ */
4492 /* .as_u32 = clib_host_to_net_u32(0x0a0a0a0a), */
4497 /* fib_table_entry_update_one_path(fib_index, &local_pfx, */
4498 /* FIB_SOURCE_INTERFACE, */
4499 /* (FIB_ENTRY_FLAG_CONNECTED | */
4500 /* FIB_ENTRY_FLAG_ATTACHED), */
4502 /* tm->hw[0]->sw_if_index, */
4505 /* FIB_ROUTE_PATH_FLAG_NONE); */
4506 /* fei = fib_table_lookup_exact_match(fib_index, &local_pfx); */
4507 /* FIB_TEST((FIB_NODE_INDEX_INVALID != fei), */
4508 /* "attached interface route present"); */
4510 /* local_pfx.fp_len = 32; */
4511 /* fib_table_entry_update_one_path(fib_index, &local_pfx, */
4512 /* FIB_SOURCE_INTERFACE, */
4513 /* (FIB_ENTRY_FLAG_CONNECTED | */
4514 /* FIB_ENTRY_FLAG_LOCAL), */
4516 /* tm->hw[0]->sw_if_index, */
4517 /* ~0, // invalid fib index */
4519 /* FIB_ROUTE_PATH_FLAG_NONE); */
4520 /* fei = fib_table_lookup_exact_match(fib_index, &local_pfx); */
4522 /* FIB_TEST((FIB_NODE_INDEX_INVALID != fei), */
4523 /* "local interface route present"); */
4525 /* fib_prefix_t local2_pfx = { */
4527 /* .fp_proto = FIB_PROTOCOL_IP4, */
4530 /* /\* 10.10.11.11 *\/ */
4531 /* .as_u32 = clib_host_to_net_u32(0x0a0a0b0b), */
4536 /* fib_table_entry_update_one_path(fib_index, &local2_pfx, */
4537 /* FIB_SOURCE_INTERFACE, */
4538 /* (FIB_ENTRY_FLAG_CONNECTED | */
4539 /* FIB_ENTRY_FLAG_ATTACHED), */
4541 /* tm->hw[1]->sw_if_index, */
4544 /* FIB_ROUTE_PATH_FLAG_NONE); */
4545 /* fei = fib_table_lookup_exact_match(fib_index, &local2_pfx); */
4546 /* FIB_TEST((FIB_NODE_INDEX_INVALID != fei), */
4547 /* "attached interface route present"); */
4549 /* local2_pfx.fp_len = 32; */
4550 /* fib_table_entry_update_one_path(fib_index, &local2_pfx, */
4551 /* FIB_SOURCE_INTERFACE, */
4552 /* (FIB_ENTRY_FLAG_CONNECTED | */
4553 /* FIB_ENTRY_FLAG_LOCAL), */
4555 /* tm->hw[0]->sw_if_index, */
4556 /* ~0, // invalid fib index */
4558 /* FIB_ROUTE_PATH_FLAG_NONE); */
4559 /* fei = fib_table_lookup_exact_match(fib_index, &local2_pfx); */
4561 /* FIB_TEST((FIB_NODE_INDEX_INVALID != fei), */
4562 /* "local interface route present"); */
4565 /* * Add the route that will be used to resolve the tunnel's destination */
4567 /* fib_prefix_t route_pfx = { */
4569 /* .fp_proto = FIB_PROTOCOL_IP4, */
4572 /* /\* 1.1.1.0/24 *\/ */
4573 /* .as_u32 = clib_host_to_net_u32(0x01010100), */
4577 /* /\* 10.10.10.2 *\/ */
4578 /* ip46_address_t nh_10_10_10_2 = { */
4579 /* .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02), */
4582 /* fib_table_entry_path_add(fib_index, &route_pfx, */
4583 /* FIB_SOURCE_API, */
4584 /* FIB_ENTRY_FLAG_NONE, */
4585 /* &nh_10_10_10_2, */
4586 /* tm->hw[0]->sw_if_index, */
4589 /* FIB_ROUTE_PATH_FLAG_NONE); */
4590 /* FIB_TEST((FIB_NODE_INDEX_INVALID != */
4591 /* fib_table_lookup_exact_match(fib_index, &local_pfx)), */
4592 /* "route present"); */
4595 /* * Add a tunnel */
4597 /* /\* 1.1.1.1 *\/ */
4598 /* fib_prefix_t tun_dst_pfx = { */
4600 /* .fp_proto = FIB_PROTOCOL_IP4, */
4602 /* .ip4.as_u32 = clib_host_to_net_u32(0x01010101), */
4605 /* /\* 10.10.10.10 *\/ */
4606 /* ip4_address_t tun_src = { */
4607 /* .as_u32 = clib_host_to_net_u32(0x0a0a0a0a), */
4609 /* /\* 172.16.0.1 *\/ */
4610 /* ip4_address_t tun_itf = { */
4611 /* .as_u32 = clib_host_to_net_u32(0xac100001), */
4613 /* fib_prefix_t tun_itf_pfx = { */
4615 /* .fp_proto = FIB_PROTOCOL_IP4, */
4617 /* .ip4 = tun_itf, */
4620 /* u32 *encap_labels = NULL; */
4621 /* u32 label = 0xbaba; */
4622 /* u32 encap_index; */
4623 /* u32 tunnel_sw_if_index; */
4628 /* * First we need the MPLS Encap present */
4630 /* * Pretty sure this is broken. the wiki say the 1st aparamter address */
4631 /* * should be the tunnel's interface address, which makes some sense. But */
4632 /* * the code for tunnel creation checks for the tunnel's destination */
4633 /* * address. curious... */
4635 /* vec_add1(encap_labels, label); */
4636 /* rv = vnet_mpls_add_del_encap(&tun_dst_pfx.fp_addr.ip4, */
4637 /* 0, // inner VRF */
4639 /* ~0, // policy_tunnel_index, */
4640 /* 0, // no_dst_hash, */
4643 /* FIB_TEST((0 == rv), "MPLS encap created"); */
4646 /* * now create the tunnel */
4648 /* rv = vnet_mpls_gre_add_del_tunnel(&tun_src, */
4649 /* &tun_dst_pfx.fp_addr.ip4, */
4650 /* &tun_itf_pfx.fp_addr.ip4, */
4651 /* tun_itf_pfx.fp_len, */
4652 /* 0, // inner VRF */
4653 /* 0, // outer VRF */
4654 /* &tunnel_sw_if_index, */
4657 /* FIB_TEST((0 == rv), "Tunnel created"); */
4660 /* * add it again. just for giggles. */
4662 /* rv = vnet_mpls_gre_add_del_tunnel(&tun_src, */
4663 /* &tun_dst_pfx.fp_addr.ip4, */
4664 /* &tun_itf_pfx.fp_addr.ip4, */
4665 /* tun_itf_pfx.fp_len, */
4666 /* 0, // inner VRF */
4667 /* 0, // outer VRF */
4668 /* &tunnel_sw_if_index, */
4671 /* FIB_TEST((0 != rv), "Duplicate Tunnel not created"); */
4674 /* * Find the route added for the tunnel subnet and check that */
4675 /* * it has a midchin adj that is stacked on the adj used to reach the */
4676 /* * tunnel destination */
4678 /* ip_adjacency_t *midchain_adj, *route_adj, *adjfib_adj; */
4679 /* adj_index_t midchain_ai, route_ai, adjfib_ai1, adjfib_ai2; */
4680 /* ip_lookup_main_t *lm; */
4682 /* lm = &ip4_main.lookup_main; */
4684 /* fei = fib_table_lookup_exact_match(fib_index, &tun_itf_pfx); */
4685 /* FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "tun itf route present"); */
4686 /* midchain_ai = fib_entry_contribute_forwarding(fei); */
4687 /* midchain_adj = adj_get(midchain_ai); */
4689 /* FIB_TEST((IP_LOOKUP_NEXT_MIDCHAIN == midchain_adj->lookup_next_index), */
4690 /* "Tunnel interface links to midchain"); */
4692 /* fei = fib_table_lookup_exact_match(fib_index, &route_pfx); */
4693 /* route_ai = fib_entry_contribute_forwarding(fei); */
4694 /* FIB_TEST((midchain_adj->sub_type.midchain.adj_index == route_ai), */
4695 /* "tunnel midchain it stacked on route adj"); */
4698 /* * update the route to the tunnel's destination to load-balance via */
4699 /* * interface 1. */
4701 /* /\* 10.10.11.2 *\/ */
4702 /* ip46_address_t nh_10_10_11_2 = { */
4703 /* .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b02), */
4706 /* fib_table_entry_path_add(fib_index, &route_pfx, */
4707 /* FIB_SOURCE_API, */
4708 /* FIB_ENTRY_FLAG_NONE, */
4709 /* &nh_10_10_11_2, */
4710 /* tm->hw[1]->sw_if_index, */
4713 /* FIB_ROUTE_PATH_FLAG_NONE); */
4716 /* * the tunnels midchain should have re-stacked. This tests that the */
4717 /* * route re-resolution backwalk works to a tunnel interface. */
4719 /* fei = fib_table_lookup_exact_match(fib_index, &route_pfx); */
4720 /* FIB_TEST((route_ai != fib_entry_contribute_forwarding(fei)), "route changed"); */
4721 /* route_ai = fib_entry_contribute_forwarding(fei); */
4723 /* midchain_adj = adj_get(midchain_ai); */
4725 /* FIB_TEST((midchain_adj->sub_type.midchain.adj_index == route_ai), */
4726 /* "tunnel midchain has re-stacked on route adj"); */
4728 /* route_adj = adj_get(route_ai); */
4730 /* FIB_TEST((2 == route_adj->n_adj), "Route adj is multipath"); */
4733 /* * At this stage both nieghbour adjs are incomplete, so the same should */
4734 /* * be true of the multipath adj */
4736 /* FIB_TEST((IP_LOOKUP_NEXT_ARP == route_adj->lookup_next_index), */
4737 /* "Adj0 is ARP: %d", route_adj->lookup_next_index); */
4738 /* FIB_TEST((IP_LOOKUP_NEXT_ARP == (route_adj+1)->lookup_next_index), */
4739 /* "Adj1 is ARP"); */
4742 /* * do the equivalent of creating an ARP entry for 10.10.10.2. */
4743 /* * This will complete the adj, and this */
4744 /* * change should be refelct in the multipath too. */
4746 /* u8* rewrite = NULL, byte = 0xd; */
4747 /* vec_add(rewrite, &byte, 6); */
4749 /* adjfib_ai1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, */
4750 /* VNET_LINK_IP4, */
4751 /* &nh_10_10_10_2, */
4752 /* tm->hw[0]->sw_if_index); */
4753 /* adj_nbr_update_rewrite(FIB_PROTOCOL_IP4, */
4756 /* adjfib_adj = adj_get(adjfib_ai1); */
4757 /* FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adjfib_adj->lookup_next_index), */
4758 /* "Adj-fib10 adj is rewrite"); */
4760 /* adjfib_ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, */
4761 /* VNET_LINK_IP4, */
4762 /* &nh_10_10_11_2, */
4763 /* tm->hw[1]->sw_if_index); */
4764 /* adj_nbr_update_rewrite(FIB_PROTOCOL_IP4, */
4768 /* adjfib_adj = adj_get(adjfib_ai2); */
4770 /* FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adjfib_adj->lookup_next_index), */
4771 /* "Adj-fib11 adj is rewrite"); */
4773 /* fei = fib_table_lookup_exact_match(fib_index, &route_pfx); */
4774 /* FIB_TEST((route_ai != fib_entry_contribute_forwarding(fei)), "route changed"); */
4775 /* route_ai = fib_entry_contribute_forwarding(fei); */
4776 /* route_adj = adj_get(route_ai); */
4777 /* FIB_TEST((IP_LOOKUP_NEXT_REWRITE == route_adj->lookup_next_index), */
4778 /* "Adj0 is rewrite"); */
4779 /* FIB_TEST((IP_LOOKUP_NEXT_REWRITE == (route_adj+1)->lookup_next_index), */
4780 /* "Adj1 is rewrite"); */
4785 /* adj_index_t drop_ai = adj_get_special(FIB_PROTOCOL_IP4, */
4786 /* ADJ_SPECIAL_TYPE_DROP); */
4789 /* * remove the route that the tunnel resovles via. expect */
4790 /* * it to now resolve via the default route, which is drop */
4792 /* fib_table_entry_path_remove(fib_index, &route_pfx, */
4793 /* FIB_SOURCE_API, */
4794 /* &nh_10_10_10_2, */
4795 /* tm->hw[0]->sw_if_index, */
4798 /* FIB_ROUTE_PATH_FLAG_NONE); */
4799 /* fib_table_entry_path_remove(fib_index, &route_pfx, */
4800 /* FIB_SOURCE_API, */
4801 /* &nh_10_10_11_2, */
4802 /* tm->hw[1]->sw_if_index, */
4805 /* FIB_ROUTE_PATH_FLAG_NONE); */
4806 /* FIB_TEST((FIB_NODE_INDEX_INVALID != */
4807 /* fib_table_lookup_exact_match(fib_index, &local_pfx)), */
4808 /* "route present"); */
4809 /* midchain_adj = adj_get(midchain_ai); */
4810 /* FIB_TEST((midchain_adj->sub_type.midchain.adj_index == drop_ai), */
4811 /* "tunnel midchain has re-stacked on drop"); */
4814 /* * remove the tunnel and its MPLS encaps */
4816 /* rv = vnet_mpls_gre_add_del_tunnel(&tun_src, */
4817 /* &tun_dst_pfx.fp_addr.ip4, */
4818 /* &tun_itf_pfx.fp_addr.ip4, */
4819 /* tun_itf_pfx.fp_len, */
4820 /* 0, // inner VRF */
4821 /* 0, // outer VRF */
4822 /* &tunnel_sw_if_index, */
4825 /* FIB_TEST((0 == rv), "Tunnel removed"); */
4826 /* rv = vnet_mpls_gre_add_del_tunnel(&tun_src, */
4827 /* &tun_dst_pfx.fp_addr.ip4, */
4828 /* &tun_itf_pfx.fp_addr.ip4, */
4829 /* tun_itf_pfx.fp_len, */
4830 /* 0, // inner VRF */
4831 /* 0, // outer VRF */
4832 /* &tunnel_sw_if_index, */
4835 /* FIB_TEST((0 != rv), "No existant Tunnel not removed"); */
4837 /* rv = vnet_mpls_add_del_encap(&tun_dst_pfx.fp_addr.ip4, */
4838 /* 0, // inner VRF */
4840 /* ~0, // policy_tunnel_index, */
4841 /* 0, // no_dst_hash, */
4844 /* FIB_TEST((0 == rv), "MPLS encap deleted"); */
4846 /* vec_free(encap_labels); */
4849 /* * no more FIB entries expected */
4851 /* fei = fib_table_lookup_exact_match(fib_index, &tun_itf_pfx); */
4852 /* FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "tun itf route removed"); */
4853 /* fei = fib_table_lookup_exact_match(fib_index, &tun_dst_pfx); */
4854 /* FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "tun dst route removed"); */
4857 /* * CLEANUP the connecteds */
4859 /* local2_pfx.fp_len = 24; */
4860 /* fib_table_entry_delete(fib_index, &local2_pfx, */
4861 /* FIB_SOURCE_INTERFACE); */
4862 /* fei = fib_table_lookup_exact_match(fib_index, &local2_pfx); */
4863 /* FIB_TEST((FIB_NODE_INDEX_INVALID == fei), */
4864 /* "attached interface route remove"); */
4866 /* local2_pfx.fp_len = 32; */
4867 /* fib_table_entry_special_remove(fib_index, &local2_pfx, */
4868 /* FIB_SOURCE_INTERFACE); */
4869 /* fei = fib_table_lookup_exact_match(fib_index, &local2_pfx); */
4870 /* FIB_TEST((FIB_NODE_INDEX_INVALID == fei), */
4871 /* "local interface route removed"); */
4872 /* local_pfx.fp_len = 24; */
4873 /* fib_table_entry_delete(fib_index, &local_pfx, */
4874 /* FIB_SOURCE_INTERFACE); */
4875 /* fei = fib_table_lookup_exact_match(fib_index, &local_pfx); */
4876 /* FIB_TEST((FIB_NODE_INDEX_INVALID == fei), */
4877 /* "attached interface route remove"); */
4879 /* local_pfx.fp_len = 32; */
4880 /* fib_table_entry_special_remove(fib_index, &local_pfx, */
4881 /* FIB_SOURCE_INTERFACE); */
4882 /* fei = fib_table_lookup_exact_match(fib_index, &local_pfx); */
4883 /* FIB_TEST((FIB_NODE_INDEX_INVALID == fei), */
4884 /* "local interface route removed"); */
4888 * Test Attached Exports
4893 const dpo_id_t *dpo, *dpo_drop;
4894 const u32 fib_index = 0;
4895 fib_node_index_t fei;
4902 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4906 * add interface routes. We'll assume this works. It's more rigorously
4909 fib_prefix_t local_pfx = {
4911 .fp_proto = FIB_PROTOCOL_IP4,
4915 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
4920 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
4921 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
4923 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
4925 fib_table_entry_update_one_path(fib_index, &local_pfx,
4926 FIB_SOURCE_INTERFACE,
4927 (FIB_ENTRY_FLAG_CONNECTED |
4928 FIB_ENTRY_FLAG_ATTACHED),
4931 tm->hw[0]->sw_if_index,
4935 FIB_ROUTE_PATH_FLAG_NONE);
4936 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4937 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
4938 "attached interface route present");
4940 local_pfx.fp_len = 32;
4941 fib_table_entry_update_one_path(fib_index, &local_pfx,
4942 FIB_SOURCE_INTERFACE,
4943 (FIB_ENTRY_FLAG_CONNECTED |
4944 FIB_ENTRY_FLAG_LOCAL),
4947 tm->hw[0]->sw_if_index,
4948 ~0, // invalid fib index
4951 FIB_ROUTE_PATH_FLAG_NONE);
4952 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4954 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
4955 "local interface route present");
4958 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4960 fib_prefix_t pfx_10_10_10_1_s_32 = {
4962 .fp_proto = FIB_PROTOCOL_IP4,
4965 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
4968 fib_node_index_t ai;
4970 fib_table_entry_update_one_path(fib_index,
4971 &pfx_10_10_10_1_s_32,
4973 FIB_ENTRY_FLAG_NONE,
4975 &pfx_10_10_10_1_s_32.fp_addr,
4976 tm->hw[0]->sw_if_index,
4977 ~0, // invalid fib index
4980 FIB_ROUTE_PATH_FLAG_NONE);
4982 fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
4983 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
4984 ai = fib_entry_get_adj(fei);
4987 * create another FIB table into which routes will be imported
4989 u32 import_fib_index1;
4991 import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11);
4994 * Add an attached route in the import FIB
4996 local_pfx.fp_len = 24;
4997 fib_table_entry_update_one_path(import_fib_index1,
5000 FIB_ENTRY_FLAG_NONE,
5003 tm->hw[0]->sw_if_index,
5004 ~0, // invalid fib index
5007 FIB_ROUTE_PATH_FLAG_NONE);
5008 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5009 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5012 * check for the presence of the adj-fibs in the import table
5014 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5015 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5016 FIB_TEST((ai == fib_entry_get_adj(fei)),
5017 "adj-fib1 Import uses same adj as export");
5020 * check for the presence of the local in the import table
5022 local_pfx.fp_len = 32;
5023 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5024 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5027 * Add another adj-fin in the export table. Expect this
5028 * to get magically exported;
5030 fib_prefix_t pfx_10_10_10_2_s_32 = {
5032 .fp_proto = FIB_PROTOCOL_IP4,
5035 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5039 fib_table_entry_update_one_path(fib_index,
5040 &pfx_10_10_10_2_s_32,
5042 FIB_ENTRY_FLAG_NONE,
5044 &pfx_10_10_10_2_s_32.fp_addr,
5045 tm->hw[0]->sw_if_index,
5046 ~0, // invalid fib index
5049 FIB_ROUTE_PATH_FLAG_NONE);
5050 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5051 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
5052 ai = fib_entry_get_adj(fei);
5054 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5055 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5056 FIB_TEST((ai == fib_entry_get_adj(fei)),
5057 "Import uses same adj as export");
5060 * create a 2nd FIB table into which routes will be imported
5062 u32 import_fib_index2;
5064 import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12);
5067 * Add an attached route in the import FIB
5069 local_pfx.fp_len = 24;
5070 fib_table_entry_update_one_path(import_fib_index2,
5073 FIB_ENTRY_FLAG_NONE,
5076 tm->hw[0]->sw_if_index,
5077 ~0, // invalid fib index
5080 FIB_ROUTE_PATH_FLAG_NONE);
5081 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5082 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5085 * check for the presence of all the adj-fibs and local in the import table
5087 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5088 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5089 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5090 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5091 local_pfx.fp_len = 32;
5092 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5093 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5096 * add a 3rd adj-fib. expect it to be exported to both tables.
5098 fib_prefix_t pfx_10_10_10_3_s_32 = {
5100 .fp_proto = FIB_PROTOCOL_IP4,
5103 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
5107 fib_table_entry_update_one_path(fib_index,
5108 &pfx_10_10_10_3_s_32,
5110 FIB_ENTRY_FLAG_NONE,
5112 &pfx_10_10_10_3_s_32.fp_addr,
5113 tm->hw[0]->sw_if_index,
5114 ~0, // invalid fib index
5117 FIB_ROUTE_PATH_FLAG_NONE);
5118 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5119 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
5120 ai = fib_entry_get_adj(fei);
5122 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5123 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1");
5124 FIB_TEST((ai == fib_entry_get_adj(fei)),
5125 "Import uses same adj as export");
5126 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5127 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2");
5128 FIB_TEST((ai == fib_entry_get_adj(fei)),
5129 "Import uses same adj as export");
5132 * remove the 3rd adj fib. we expect it to be removed from both FIBs
5134 fib_table_entry_delete(fib_index,
5135 &pfx_10_10_10_3_s_32,
5138 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5139 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved");
5141 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5142 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1");
5144 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5145 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2");
5148 * remove the attached route from the 2nd FIB. expect the imported
5149 * entires to be removed
5151 local_pfx.fp_len = 24;
5152 fib_table_entry_delete(import_fib_index2,
5155 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5156 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed");
5158 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5159 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2");
5160 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5161 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2");
5162 local_pfx.fp_len = 32;
5163 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5164 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2");
5166 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5167 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1");
5168 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5169 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1");
5170 local_pfx.fp_len = 32;
5171 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5172 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1");
5175 * modify the route in FIB1 so it is no longer attached. expect the imported
5176 * entires to be removed
5178 local_pfx.fp_len = 24;
5179 fib_table_entry_update_one_path(import_fib_index1,
5182 FIB_ENTRY_FLAG_NONE,
5184 &pfx_10_10_10_2_s_32.fp_addr,
5185 tm->hw[0]->sw_if_index,
5186 ~0, // invalid fib index
5189 FIB_ROUTE_PATH_FLAG_NONE);
5190 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5191 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5192 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5193 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5194 local_pfx.fp_len = 32;
5195 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5196 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5199 * modify it back to attached. expect the adj-fibs back
5201 local_pfx.fp_len = 24;
5202 fib_table_entry_update_one_path(import_fib_index1,
5205 FIB_ENTRY_FLAG_NONE,
5208 tm->hw[0]->sw_if_index,
5209 ~0, // invalid fib index
5212 FIB_ROUTE_PATH_FLAG_NONE);
5213 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5214 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1");
5215 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5216 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1");
5217 local_pfx.fp_len = 32;
5218 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5219 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1");
5222 * add a covering attached next-hop for the interface address, so we have
5223 * a valid adj to find when we check the forwarding tables
5225 fib_prefix_t pfx_10_0_0_0_s_8 = {
5227 .fp_proto = FIB_PROTOCOL_IP4,
5230 .ip4.as_u32 = clib_host_to_net_u32(0x0a000000),
5234 fei = fib_table_entry_update_one_path(fib_index,
5237 FIB_ENTRY_FLAG_NONE,
5239 &pfx_10_10_10_3_s_32.fp_addr,
5240 tm->hw[0]->sw_if_index,
5241 ~0, // invalid fib index
5244 FIB_ROUTE_PATH_FLAG_NONE);
5245 dpo = fib_entry_contribute_ip_forwarding(fei);
5248 * remove the route in the export fib. expect the adj-fibs to be removed
5250 local_pfx.fp_len = 24;
5251 fib_table_entry_delete(fib_index,
5253 FIB_SOURCE_INTERFACE);
5255 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5256 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1");
5257 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5258 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5259 local_pfx.fp_len = 32;
5260 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5261 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5264 * the adj-fibs in the export VRF are present in the FIB table,
5265 * but not installed in forwarding, since they have no attached cover.
5266 * Consequently a lookup in the MTRIE gives the adj for the covering
5269 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5270 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5273 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5274 FIB_TEST(lbi == dpo->dpoi_index,
5275 "10.10.10.1 forwards on \n%U not \n%U",
5276 format_load_balance, lbi, 0,
5277 format_dpo_id, dpo, 0);
5278 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5279 FIB_TEST(lbi == dpo->dpoi_index,
5280 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5281 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4);
5282 FIB_TEST(lbi == dpo->dpoi_index,
5283 "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0);
5286 * add the export prefix back, but not as attached.
5287 * No adj-fibs in export nor import tables
5289 local_pfx.fp_len = 24;
5290 fei = fib_table_entry_update_one_path(fib_index,
5293 FIB_ENTRY_FLAG_NONE,
5295 &pfx_10_10_10_1_s_32.fp_addr,
5296 tm->hw[0]->sw_if_index,
5297 ~0, // invalid fib index
5300 FIB_ROUTE_PATH_FLAG_NONE);
5301 dpo = fib_entry_contribute_ip_forwarding(fei);
5303 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5304 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export");
5305 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5306 FIB_TEST(lbi == dpo->dpoi_index,
5307 "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0);
5308 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5309 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5310 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5311 FIB_TEST(lbi == dpo->dpoi_index,
5312 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5314 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5315 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5316 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5317 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5318 local_pfx.fp_len = 32;
5319 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5320 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5323 * modify the export prefix so it is attached. expect all covereds to return
5325 local_pfx.fp_len = 24;
5326 fib_table_entry_update_one_path(fib_index,
5329 FIB_ENTRY_FLAG_NONE,
5332 tm->hw[0]->sw_if_index,
5333 ~0, // invalid fib index
5336 FIB_ROUTE_PATH_FLAG_NONE);
5338 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5339 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5340 dpo = fib_entry_contribute_ip_forwarding(fei);
5341 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5342 "Adj-fib1 is not drop in export");
5343 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5344 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5345 local_pfx.fp_len = 32;
5346 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5347 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5348 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5349 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5350 dpo = fib_entry_contribute_ip_forwarding(fei);
5351 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5352 "Adj-fib1 is not drop in export");
5353 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5354 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5355 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5356 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5357 local_pfx.fp_len = 32;
5358 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5359 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5362 * modify the export prefix so connected. no change.
5364 local_pfx.fp_len = 24;
5365 fib_table_entry_update_one_path(fib_index, &local_pfx,
5366 FIB_SOURCE_INTERFACE,
5367 (FIB_ENTRY_FLAG_CONNECTED |
5368 FIB_ENTRY_FLAG_ATTACHED),
5371 tm->hw[0]->sw_if_index,
5375 FIB_ROUTE_PATH_FLAG_NONE);
5377 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5378 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5379 dpo = fib_entry_contribute_ip_forwarding(fei);
5380 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5381 "Adj-fib1 is not drop in export");
5382 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5383 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5384 local_pfx.fp_len = 32;
5385 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5386 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5387 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5388 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5389 dpo = fib_entry_contribute_ip_forwarding(fei);
5390 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5391 "Adj-fib1 is not drop in export");
5392 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5393 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5394 local_pfx.fp_len = 32;
5395 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5396 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5401 fib_table_entry_delete(fib_index,
5404 fib_table_entry_delete(fib_index,
5405 &pfx_10_10_10_1_s_32,
5407 fib_table_entry_delete(fib_index,
5408 &pfx_10_10_10_2_s_32,
5410 local_pfx.fp_len = 32;
5411 fib_table_entry_delete(fib_index,
5413 FIB_SOURCE_INTERFACE);
5414 local_pfx.fp_len = 24;
5415 fib_table_entry_delete(fib_index,
5418 fib_table_entry_delete(fib_index,
5420 FIB_SOURCE_INTERFACE);
5421 local_pfx.fp_len = 24;
5422 fib_table_entry_delete(import_fib_index1,
5426 fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4);
5427 fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4);
5429 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5434 * Test the recursive route route handling for GRE tunnels
5437 fib_test_label (void)
5439 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;
5440 const u32 fib_index = 0;
5445 lb_count = pool_elts(load_balance_pool);
5450 * add interface routes. We'll assume this works. It's more rigorously
5453 fib_prefix_t local0_pfx = {
5455 .fp_proto = FIB_PROTOCOL_IP4,
5459 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5464 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5467 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
5468 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
5470 fib_table_entry_update_one_path(fib_index, &local0_pfx,
5471 FIB_SOURCE_INTERFACE,
5472 (FIB_ENTRY_FLAG_CONNECTED |
5473 FIB_ENTRY_FLAG_ATTACHED),
5476 tm->hw[0]->sw_if_index,
5480 FIB_ROUTE_PATH_FLAG_NONE);
5481 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
5482 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5483 "attached interface route present");
5485 local0_pfx.fp_len = 32;
5486 fib_table_entry_update_one_path(fib_index, &local0_pfx,
5487 FIB_SOURCE_INTERFACE,
5488 (FIB_ENTRY_FLAG_CONNECTED |
5489 FIB_ENTRY_FLAG_LOCAL),
5492 tm->hw[0]->sw_if_index,
5493 ~0, // invalid fib index
5496 FIB_ROUTE_PATH_FLAG_NONE);
5497 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
5499 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5500 "local interface route present");
5502 fib_prefix_t local1_pfx = {
5504 .fp_proto = FIB_PROTOCOL_IP4,
5508 .as_u32 = clib_host_to_net_u32(0x0a0a0b0a),
5513 vec_validate(im->fib_index_by_sw_if_index, tm->hw[1]->sw_if_index);
5514 im->fib_index_by_sw_if_index[tm->hw[1]->sw_if_index] = fib_index;
5516 fib_table_entry_update_one_path(fib_index, &local1_pfx,
5517 FIB_SOURCE_INTERFACE,
5518 (FIB_ENTRY_FLAG_CONNECTED |
5519 FIB_ENTRY_FLAG_ATTACHED),
5522 tm->hw[1]->sw_if_index,
5526 FIB_ROUTE_PATH_FLAG_NONE);
5527 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
5528 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5529 "attached interface route present");
5531 local1_pfx.fp_len = 32;
5532 fib_table_entry_update_one_path(fib_index, &local1_pfx,
5533 FIB_SOURCE_INTERFACE,
5534 (FIB_ENTRY_FLAG_CONNECTED |
5535 FIB_ENTRY_FLAG_LOCAL),
5538 tm->hw[1]->sw_if_index,
5539 ~0, // invalid fib index
5542 FIB_ROUTE_PATH_FLAG_NONE);
5543 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
5545 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5546 "local interface route present");
5548 ip46_address_t nh_10_10_10_1 = {
5550 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5553 ip46_address_t nh_10_10_11_1 = {
5555 .as_u32 = clib_host_to_net_u32(0x0a0a0b01),
5558 ip46_address_t nh_10_10_11_2 = {
5560 .as_u32 = clib_host_to_net_u32(0x0a0a0b02),
5564 ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5567 tm->hw[1]->sw_if_index);
5568 ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5571 tm->hw[1]->sw_if_index);
5572 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5575 tm->hw[0]->sw_if_index);
5576 ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5579 tm->hw[1]->sw_if_index);
5580 ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5583 tm->hw[1]->sw_if_index);
5586 * Add an etry with one path with a real out-going label
5588 fib_prefix_t pfx_1_1_1_1_s_32 = {
5590 .fp_proto = FIB_PROTOCOL_IP4,
5592 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
5595 fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = {
5596 .type = FT_LB_LABEL_O_ADJ,
5598 .adj = ai_mpls_10_10_10_1,
5603 fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = {
5604 .type = FT_LB_LABEL_O_ADJ,
5606 .adj = ai_mpls_10_10_10_1,
5608 .eos = MPLS_NON_EOS,
5611 fib_table_entry_update_one_path(fib_index,
5614 FIB_ENTRY_FLAG_NONE,
5617 tm->hw[0]->sw_if_index,
5618 ~0, // invalid fib index
5621 FIB_ROUTE_PATH_FLAG_NONE);
5623 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5624 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created");
5626 FIB_TEST(fib_test_validate_entry(fei,
5627 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5629 &l99_eos_o_10_10_10_1),
5630 "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1");
5633 * add a path with an implicit NULL label
5635 fib_test_lb_bucket_t a_o_10_10_11_1 = {
5638 .adj = ai_v4_10_10_11_1,
5641 fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = {
5644 .adj = ai_mpls_10_10_11_1,
5648 fei = fib_table_entry_path_add(fib_index,
5651 FIB_ENTRY_FLAG_NONE,
5654 tm->hw[1]->sw_if_index,
5655 ~0, // invalid fib index
5657 MPLS_IETF_IMPLICIT_NULL_LABEL,
5658 FIB_ROUTE_PATH_FLAG_NONE);
5660 FIB_TEST(fib_test_validate_entry(fei,
5661 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5663 &l99_eos_o_10_10_10_1,
5665 "1.1.1.1/32 LB 2 buckets via: "
5666 "label 99 over 10.10.10.1, "
5667 "adj over 10.10.11.1");
5670 * assign the route a local label
5672 fib_table_entry_local_label_add(fib_index,
5676 fib_prefix_t pfx_24001_eos = {
5677 .fp_proto = FIB_PROTOCOL_MPLS,
5681 fib_prefix_t pfx_24001_neos = {
5682 .fp_proto = FIB_PROTOCOL_MPLS,
5684 .fp_eos = MPLS_NON_EOS,
5688 * The EOS entry should link to both the paths,
5689 * and use an ip adj for the imp-null
5690 * The NON-EOS entry should link to both the paths,
5691 * and use an mpls adj for the imp-null
5693 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5695 FIB_TEST(fib_test_validate_entry(fei,
5696 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5698 &l99_eos_o_10_10_10_1,
5700 "24001/eos LB 2 buckets via: "
5701 "label 99 over 10.10.10.1, "
5702 "adj over 10.10.11.1");
5705 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5707 FIB_TEST(fib_test_validate_entry(fei,
5708 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5710 &l99_neos_o_10_10_10_1,
5711 &a_mpls_o_10_10_11_1),
5712 "24001/neos LB 1 bucket via: "
5713 "label 99 over 10.10.10.1 ",
5714 "mpls-adj via 10.10.11.1");
5717 * add an unlabelled path, this is excluded from the neos chains,
5719 fib_test_lb_bucket_t adj_o_10_10_11_2 = {
5722 .adj = ai_v4_10_10_11_2,
5726 fei = fib_table_entry_path_add(fib_index,
5729 FIB_ENTRY_FLAG_NONE,
5732 tm->hw[1]->sw_if_index,
5733 ~0, // invalid fib index
5736 FIB_ROUTE_PATH_FLAG_NONE);
5738 FIB_TEST(fib_test_validate_entry(fei,
5739 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5740 16, // 3 choices spread over 16 buckets
5741 &l99_eos_o_10_10_10_1,
5742 &l99_eos_o_10_10_10_1,
5743 &l99_eos_o_10_10_10_1,
5744 &l99_eos_o_10_10_10_1,
5745 &l99_eos_o_10_10_10_1,
5746 &l99_eos_o_10_10_10_1,
5757 "1.1.1.1/32 LB 16 buckets via: "
5758 "label 99 over 10.10.10.1, "
5759 "adj over 10.10.11.1",
5760 "adj over 10.10.11.2");
5763 * get and lock a reference to the non-eos of the via entry 1.1.1.1/32
5765 dpo_id_t non_eos_1_1_1_1 = DPO_INVALID;
5766 fib_entry_contribute_forwarding(fei,
5767 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5771 * n-eos has only the 2 labelled paths
5773 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5776 FIB_TEST(fib_test_validate_entry(fei,
5777 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5779 &l99_neos_o_10_10_10_1,
5780 &a_mpls_o_10_10_11_1),
5781 "24001/neos LB 2 buckets via: "
5782 "label 99 over 10.10.10.1, "
5783 "adj-mpls over 10.10.11.2");
5786 * A labelled recursive
5788 fib_prefix_t pfx_2_2_2_2_s_32 = {
5790 .fp_proto = FIB_PROTOCOL_IP4,
5792 .ip4.as_u32 = clib_host_to_net_u32(0x02020202),
5795 fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = {
5796 .type = FT_LB_LABEL_O_LB,
5798 .lb = non_eos_1_1_1_1.dpoi_index,
5804 fib_table_entry_update_one_path(fib_index,
5807 FIB_ENTRY_FLAG_NONE,
5809 &pfx_1_1_1_1_s_32.fp_addr,
5814 FIB_ROUTE_PATH_FLAG_NONE);
5816 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
5817 FIB_TEST(fib_test_validate_entry(fei,
5818 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5820 &l1600_eos_o_1_1_1_1),
5821 "2.2.2.2.2/32 LB 1 buckets via: "
5822 "label 1600 over 1.1.1.1");
5824 dpo_id_t dpo_44 = DPO_INVALID;
5827 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
5828 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
5830 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
5831 "uRPF check for 2.2.2.2/32 on %d OK",
5832 tm->hw[0]->sw_if_index);
5833 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
5834 "uRPF check for 2.2.2.2/32 on %d OK",
5835 tm->hw[1]->sw_if_index);
5836 FIB_TEST(!fib_urpf_check(urpfi, 99),
5837 "uRPF check for 2.2.2.2/32 on 99 not-OK",
5840 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44);
5841 FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index),
5842 "Shared uRPF on IP and non-EOS chain");
5847 * we are holding a lock on the non-eos LB of the via-entry.
5848 * do a PIC-core failover by shutting the link of the via-entry.
5850 * shut down the link with the valid label
5852 vnet_sw_interface_set_flags(vnet_get_main(),
5853 tm->hw[0]->sw_if_index,
5856 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5857 FIB_TEST(fib_test_validate_entry(fei,
5858 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5862 "1.1.1.1/32 LB 2 buckets via: "
5863 "adj over 10.10.11.1, ",
5864 "adj-v4 over 10.10.11.2");
5866 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5868 FIB_TEST(fib_test_validate_entry(fei,
5869 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5873 "24001/eos LB 2 buckets via: "
5874 "adj over 10.10.11.1, ",
5875 "adj-v4 over 10.10.11.2");
5877 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5879 FIB_TEST(fib_test_validate_entry(fei,
5880 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5882 &a_mpls_o_10_10_11_1),
5883 "24001/neos LB 1 buckets via: "
5884 "adj-mpls over 10.10.11.2");
5887 * test that the pre-failover load-balance has been in-place
5890 dpo_id_t current = DPO_INVALID;
5891 fib_entry_contribute_forwarding(fei,
5892 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5895 FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1,
5897 "PIC-core LB inplace modified %U %U",
5898 format_dpo_id, &non_eos_1_1_1_1, 0,
5899 format_dpo_id, ¤t, 0);
5901 dpo_reset(&non_eos_1_1_1_1);
5902 dpo_reset(¤t);
5905 * no-shut the link with the valid label
5907 vnet_sw_interface_set_flags(vnet_get_main(),
5908 tm->hw[0]->sw_if_index,
5909 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5911 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5912 FIB_TEST(fib_test_validate_entry(fei,
5913 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5914 16, // 3 choices spread over 16 buckets
5915 &l99_eos_o_10_10_10_1,
5916 &l99_eos_o_10_10_10_1,
5917 &l99_eos_o_10_10_10_1,
5918 &l99_eos_o_10_10_10_1,
5919 &l99_eos_o_10_10_10_1,
5920 &l99_eos_o_10_10_10_1,
5931 "1.1.1.1/32 LB 16 buckets via: "
5932 "label 99 over 10.10.10.1, "
5933 "adj over 10.10.11.1",
5934 "adj-v4 over 10.10.11.2");
5937 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5939 FIB_TEST(fib_test_validate_entry(fei,
5940 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5941 16, // 3 choices spread over 16 buckets
5942 &l99_eos_o_10_10_10_1,
5943 &l99_eos_o_10_10_10_1,
5944 &l99_eos_o_10_10_10_1,
5945 &l99_eos_o_10_10_10_1,
5946 &l99_eos_o_10_10_10_1,
5947 &l99_eos_o_10_10_10_1,
5958 "24001/eos LB 16 buckets via: "
5959 "label 99 over 10.10.10.1, "
5960 "adj over 10.10.11.1",
5961 "adj-v4 over 10.10.11.2");
5963 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5965 FIB_TEST(fib_test_validate_entry(fei,
5966 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5968 &l99_neos_o_10_10_10_1,
5969 &a_mpls_o_10_10_11_1),
5970 "24001/neos LB 2 buckets via: "
5971 "label 99 over 10.10.10.1, "
5972 "adj-mpls over 10.10.11.2");
5975 * remove the first path with the valid label
5977 fib_table_entry_path_remove(fib_index,
5982 tm->hw[0]->sw_if_index,
5983 ~0, // invalid fib index
5985 FIB_ROUTE_PATH_FLAG_NONE);
5987 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5988 FIB_TEST(fib_test_validate_entry(fei,
5989 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5993 "1.1.1.1/32 LB 2 buckets via: "
5994 "adj over 10.10.11.1",
5995 "adj-v4 over 10.10.11.2");
5997 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5999 FIB_TEST(fib_test_validate_entry(fei,
6000 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6004 "24001/eos LB 2 buckets via: "
6005 "adj over 10.10.11.1",
6006 "adj-v4 over 10.10.11.2");
6008 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6011 FIB_TEST(fib_test_validate_entry(fei,
6012 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6014 &a_mpls_o_10_10_11_1),
6015 "24001/neos LB 1 buckets via: "
6016 "adj-mpls over 10.10.11.2");
6019 * remove the other path with a valid label
6021 fib_test_lb_bucket_t bucket_drop = {
6022 .type = FT_LB_SPECIAL,
6024 .adj = DPO_PROTO_IP4,
6028 fib_table_entry_path_remove(fib_index,
6033 tm->hw[1]->sw_if_index,
6034 ~0, // invalid fib index
6036 FIB_ROUTE_PATH_FLAG_NONE);
6038 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6039 FIB_TEST(fib_test_validate_entry(fei,
6040 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6043 "1.1.1.1/32 LB 1 buckets via: "
6044 "adj over 10.10.11.2");
6046 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6048 FIB_TEST(fib_test_validate_entry(fei,
6049 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6052 "24001/eos LB 1 buckets via: "
6053 "adj over 10.10.11.2");
6055 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6057 FIB_TEST(fib_test_validate_entry(fei,
6058 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6061 "24001/eos LB 1 buckets via: DROP");
6064 * add back the path with the valid label
6066 fib_table_entry_path_add(fib_index,
6069 FIB_ENTRY_FLAG_NONE,
6072 tm->hw[0]->sw_if_index,
6073 ~0, // invalid fib index
6076 FIB_ROUTE_PATH_FLAG_NONE);
6078 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6079 FIB_TEST(fib_test_validate_entry(fei,
6080 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6082 &l99_eos_o_10_10_10_1,
6084 "1.1.1.1/32 LB 2 buckets via: "
6085 "label 99 over 10.10.10.1, "
6086 "adj over 10.10.11.2");
6088 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6090 FIB_TEST(fib_test_validate_entry(fei,
6091 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6093 &l99_eos_o_10_10_10_1,
6095 "24001/eos LB 2 buckets via: "
6096 "label 99 over 10.10.10.1, "
6097 "adj over 10.10.11.2");
6099 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6101 FIB_TEST(fib_test_validate_entry(fei,
6102 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6104 &l99_neos_o_10_10_10_1),
6105 "24001/neos LB 1 buckets via: "
6106 "label 99 over 10.10.10.1");
6109 * change the local label
6111 fib_table_entry_local_label_add(fib_index,
6115 fib_prefix_t pfx_25005_eos = {
6116 .fp_proto = FIB_PROTOCOL_MPLS,
6120 fib_prefix_t pfx_25005_neos = {
6121 .fp_proto = FIB_PROTOCOL_MPLS,
6123 .fp_eos = MPLS_NON_EOS,
6126 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6127 fib_table_lookup(fib_index, &pfx_24001_eos)),
6128 "24001/eos removed after label change");
6129 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6130 fib_table_lookup(fib_index, &pfx_24001_neos)),
6131 "24001/eos removed after label change");
6133 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6135 FIB_TEST(fib_test_validate_entry(fei,
6136 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6138 &l99_eos_o_10_10_10_1,
6140 "25005/eos LB 2 buckets via: "
6141 "label 99 over 10.10.10.1, "
6142 "adj over 10.10.11.2");
6144 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6146 FIB_TEST(fib_test_validate_entry(fei,
6147 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6149 &l99_neos_o_10_10_10_1),
6150 "25005/neos LB 1 buckets via: "
6151 "label 99 over 10.10.10.1");
6154 * remove the local label.
6155 * the check that the MPLS entries are gone is done by the fact the
6156 * MPLS table is no longer present.
6158 fib_table_entry_local_label_remove(fib_index,
6162 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6163 FIB_TEST(fib_test_validate_entry(fei,
6164 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6166 &l99_eos_o_10_10_10_1,
6168 "24001/eos LB 2 buckets via: "
6169 "label 99 over 10.10.10.1, "
6170 "adj over 10.10.11.2");
6172 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6173 mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)),
6174 "No more MPLS FIB entries => table removed");
6177 * add another via-entry for the recursive
6179 fib_prefix_t pfx_1_1_1_2_s_32 = {
6181 .fp_proto = FIB_PROTOCOL_IP4,
6183 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
6186 fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = {
6187 .type = FT_LB_LABEL_O_ADJ,
6189 .adj = ai_mpls_10_10_10_1,
6195 fei = fib_table_entry_update_one_path(fib_index,
6198 FIB_ENTRY_FLAG_NONE,
6201 tm->hw[0]->sw_if_index,
6202 ~0, // invalid fib index
6205 FIB_ROUTE_PATH_FLAG_NONE);
6207 FIB_TEST(fib_test_validate_entry(fei,
6208 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6210 &l101_eos_o_10_10_10_1),
6211 "1.1.1.2/32 LB 1 buckets via: "
6212 "label 101 over 10.10.10.1");
6214 dpo_id_t non_eos_1_1_1_2 = DPO_INVALID;
6215 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6217 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6219 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6221 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6224 fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = {
6225 .type = FT_LB_LABEL_O_LB,
6227 .lb = non_eos_1_1_1_2.dpoi_index,
6232 l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index;
6234 fei = fib_table_entry_path_add(fib_index,
6237 FIB_ENTRY_FLAG_NONE,
6239 &pfx_1_1_1_2_s_32.fp_addr,
6244 FIB_ROUTE_PATH_FLAG_NONE);
6246 FIB_TEST(fib_test_validate_entry(fei,
6247 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6249 &l1600_eos_o_1_1_1_1,
6250 &l1601_eos_o_1_1_1_2),
6251 "2.2.2.2/32 LB 2 buckets via: "
6252 "label 1600 via 1.1,1.1, "
6253 "label 16001 via 1.1.1.2");
6256 * update the via-entry so it no longer has an imp-null path.
6257 * the LB for the recursive can use an imp-null
6259 fei = fib_table_entry_update_one_path(fib_index,
6262 FIB_ENTRY_FLAG_NONE,
6265 tm->hw[1]->sw_if_index,
6266 ~0, // invalid fib index
6268 MPLS_IETF_IMPLICIT_NULL_LABEL,
6269 FIB_ROUTE_PATH_FLAG_NONE);
6271 FIB_TEST(fib_test_validate_entry(fei,
6272 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6275 "1.1.1.2/32 LB 1 buckets via: "
6278 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6279 FIB_TEST(fib_test_validate_entry(fei,
6280 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6282 &l1600_eos_o_1_1_1_1,
6283 &l1601_eos_o_1_1_1_2),
6284 "2.2.2.2/32 LB 2 buckets via: "
6285 "label 1600 via 1.1,1.1, "
6286 "label 16001 via 1.1.1.2");
6289 * update the via-entry so it no longer has labelled paths.
6290 * the LB for the recursive should exclue this via form its LB
6292 fei = fib_table_entry_update_one_path(fib_index,
6295 FIB_ENTRY_FLAG_NONE,
6298 tm->hw[1]->sw_if_index,
6299 ~0, // invalid fib index
6302 FIB_ROUTE_PATH_FLAG_NONE);
6304 FIB_TEST(fib_test_validate_entry(fei,
6305 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6308 "1.1.1.2/32 LB 1 buckets via: "
6311 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6312 FIB_TEST(fib_test_validate_entry(fei,
6313 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6315 &l1600_eos_o_1_1_1_1),
6316 "2.2.2.2/32 LB 1 buckets via: "
6317 "label 1600 via 1.1,1.1");
6319 dpo_reset(&non_eos_1_1_1_1);
6320 dpo_reset(&non_eos_1_1_1_2);
6323 * Add a recursive with no out-labels. We expect to use the IP of the via
6325 fib_prefix_t pfx_2_2_2_3_s_32 = {
6327 .fp_proto = FIB_PROTOCOL_IP4,
6329 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
6332 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
6334 fib_table_entry_update_one_path(fib_index,
6337 FIB_ENTRY_FLAG_NONE,
6339 &pfx_1_1_1_1_s_32.fp_addr,
6344 FIB_ROUTE_PATH_FLAG_NONE);
6346 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6348 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6351 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
6354 .lb = ip_1_1_1_1.dpoi_index,
6358 fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
6359 FIB_TEST(fib_test_validate_entry(fei,
6360 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6363 "2.2.2.2.3/32 LB 1 buckets via: "
6367 * Add a recursive with an imp-null out-label.
6368 * We expect to use the IP of the via
6370 fib_prefix_t pfx_2_2_2_4_s_32 = {
6372 .fp_proto = FIB_PROTOCOL_IP4,
6374 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
6378 fib_table_entry_update_one_path(fib_index,
6381 FIB_ENTRY_FLAG_NONE,
6383 &pfx_1_1_1_1_s_32.fp_addr,
6388 FIB_ROUTE_PATH_FLAG_NONE);
6390 fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
6391 FIB_TEST(fib_test_validate_entry(fei,
6392 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6395 "2.2.2.2.4/32 LB 1 buckets via: "
6398 dpo_reset(&ip_1_1_1_1);
6403 fib_table_entry_delete(fib_index,
6407 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6408 FIB_TEST(fib_test_validate_entry(fei,
6409 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6411 &l1600_eos_o_1_1_1_1),
6412 "2.2.2.2/32 LB 1 buckets via: "
6413 "label 1600 via 1.1,1.1");
6415 fib_table_entry_delete(fib_index,
6419 FIB_TEST(fib_test_validate_entry(fei,
6420 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6423 "2.2.2.2/32 LB 1 buckets via: DROP");
6425 fib_table_entry_delete(fib_index,
6428 fib_table_entry_delete(fib_index,
6431 fib_table_entry_delete(fib_index,
6435 adj_unlock(ai_mpls_10_10_10_1);
6436 adj_unlock(ai_mpls_10_10_11_2);
6437 adj_unlock(ai_v4_10_10_11_1);
6438 adj_unlock(ai_v4_10_10_11_2);
6439 adj_unlock(ai_mpls_10_10_11_1);
6441 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6444 local0_pfx.fp_len = 32;
6445 fib_table_entry_delete(fib_index,
6447 FIB_SOURCE_INTERFACE);
6448 local0_pfx.fp_len = 24;
6449 fib_table_entry_delete(fib_index,
6451 FIB_SOURCE_INTERFACE);
6452 local1_pfx.fp_len = 32;
6453 fib_table_entry_delete(fib_index,
6455 FIB_SOURCE_INTERFACE);
6456 local1_pfx.fp_len = 24;
6457 fib_table_entry_delete(fib_index,
6459 FIB_SOURCE_INTERFACE);
6462 * +1 for the drop LB in the MPLS tables.
6464 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
6465 "Load-balance resources freed %d of %d",
6466 lb_count+1, pool_elts(load_balance_pool));
6469 #define N_TEST_CHILDREN 4
6470 #define PARENT_INDEX 0
6472 typedef struct fib_node_test_t_
6477 fib_node_back_walk_ctx_t *ctxs;
6481 static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1];
6483 #define PARENT() (&fib_test_nodes[PARENT_INDEX].node)
6485 #define FOR_EACH_TEST_CHILD(_tc) \
6486 for (ii = 1, (_tc) = &fib_test_nodes[1]; \
6487 ii < N_TEST_CHILDREN+1; \
6488 ii++, (_tc) = &fib_test_nodes[ii])
6491 fib_test_child_get_node (fib_node_index_t index)
6493 return (&fib_test_nodes[index].node);
6496 static int fib_test_walk_spawns_walks;
6498 static fib_node_back_walk_rc_t
6499 fib_test_child_back_walk_notify (fib_node_t *node,
6500 fib_node_back_walk_ctx_t *ctx)
6502 fib_node_test_t *tc = (fib_node_test_t*) node;
6504 vec_add1(tc->ctxs, *ctx);
6506 if (1 == fib_test_walk_spawns_walks)
6507 fib_walk_sync(FIB_NODE_TYPE_TEST, tc->index, ctx);
6508 if (2 == fib_test_walk_spawns_walks)
6509 fib_walk_async(FIB_NODE_TYPE_TEST, tc->index,
6510 FIB_WALK_PRIORITY_HIGH, ctx);
6512 return (FIB_NODE_BACK_WALK_CONTINUE);
6516 fib_test_child_last_lock_gone (fib_node_t *node)
6518 fib_node_test_t *tc = (fib_node_test_t *)node;
6524 * The FIB walk's graph node virtual function table
6526 static const fib_node_vft_t fib_test_child_vft = {
6527 .fnv_get = fib_test_child_get_node,
6528 .fnv_last_lock = fib_test_child_last_lock_gone,
6529 .fnv_back_walk = fib_test_child_back_walk_notify,
6533 * the function (that should have been static but isn't so I can do this)
6534 * that processes the walk from the async queue,
6536 f64 fib_walk_process_queues(vlib_main_t * vm,
6538 u32 fib_walk_queue_get_size(fib_walk_priority_t prio);
6541 fib_test_walk (void)
6543 fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {};
6544 fib_node_test_t *tc;
6548 vm = vlib_get_main();
6549 fib_node_register_type(FIB_NODE_TYPE_TEST, &fib_test_child_vft);
6552 * init a fake node on which we will add children
6554 fib_node_init(&fib_test_nodes[PARENT_INDEX].node,
6555 FIB_NODE_TYPE_TEST);
6557 FOR_EACH_TEST_CHILD(tc)
6559 fib_node_init(&tc->node, FIB_NODE_TYPE_TEST);
6560 fib_node_lock(&tc->node);
6563 tc->sibling = fib_node_child_add(FIB_NODE_TYPE_TEST,
6565 FIB_NODE_TYPE_TEST, ii);
6569 * enqueue a walk across the parents children.
6571 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6573 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6574 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6575 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6576 "Parent has %d children pre-walk",
6577 fib_node_list_get_size(PARENT()->fn_children));
6580 * give the walk a large amount of time so it gets to the end
6582 fib_walk_process_queues(vm, 1);
6584 FOR_EACH_TEST_CHILD(tc)
6586 FIB_TEST(1 == vec_len(tc->ctxs),
6587 "%d child visitsed %d times",
6588 ii, vec_len(tc->ctxs));
6591 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6592 "Queue is empty post walk");
6593 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6594 "Parent has %d children post walk",
6595 fib_node_list_get_size(PARENT()->fn_children));
6598 * walk again. should be no increase in the number of visits, since
6599 * the walk will have terminated.
6601 fib_walk_process_queues(vm, 1);
6603 FOR_EACH_TEST_CHILD(tc)
6605 FIB_TEST(0 == vec_len(tc->ctxs),
6606 "%d child visitsed %d times",
6607 ii, vec_len(tc->ctxs));
6611 * schedule a low and hig priority walk. expect the high to be performed
6613 * schedule the high prio walk first so that it is further from the head
6614 * of the dependency list. that way it won't merge with the low one.
6616 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6617 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
6619 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6620 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6621 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6622 FIB_WALK_PRIORITY_LOW, &low_ctx);
6624 fib_walk_process_queues(vm, 1);
6626 FOR_EACH_TEST_CHILD(tc)
6628 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
6629 "%d child visitsed by high prio walk", ii);
6630 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
6631 "%d child visitsed by low prio walk", ii);
6634 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6635 "Queue is empty post prio walk");
6636 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6637 "Parent has %d children post prio walk",
6638 fib_node_list_get_size(PARENT()->fn_children));
6641 * schedule 2 walks of the same priority that can be megred.
6642 * expect that each child is thus visited only once.
6644 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6645 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6647 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6648 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6649 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6650 FIB_WALK_PRIORITY_HIGH, &low_ctx);
6652 fib_walk_process_queues(vm, 1);
6654 FOR_EACH_TEST_CHILD(tc)
6656 FIB_TEST(1 == vec_len(tc->ctxs),
6657 "%d child visitsed %d times during merge walk",
6658 ii, vec_len(tc->ctxs));
6661 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6662 "Queue is empty post merge walk");
6663 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6664 "Parent has %d children post merge walk",
6665 fib_node_list_get_size(PARENT()->fn_children));
6668 * schedule 2 walks of the same priority that cannot be megred.
6669 * expect that each child is thus visited twice and in the order
6670 * in which the walks were scheduled.
6672 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6673 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
6675 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6676 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6677 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6678 FIB_WALK_PRIORITY_HIGH, &low_ctx);
6680 fib_walk_process_queues(vm, 1);
6682 FOR_EACH_TEST_CHILD(tc)
6684 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
6685 "%d child visitsed by high prio walk", ii);
6686 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
6687 "%d child visitsed by low prio walk", ii);
6690 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6691 "Queue is empty post no-merge walk");
6692 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6693 "Parent has %d children post no-merge walk",
6694 fib_node_list_get_size(PARENT()->fn_children));
6697 * schedule a walk that makes one one child progress.
6698 * we do this by giving the queue draining process zero
6699 * time quanta. it's a do..while loop, so it does something.
6701 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6703 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6704 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6705 fib_walk_process_queues(vm, 0);
6707 FOR_EACH_TEST_CHILD(tc)
6709 if (ii == N_TEST_CHILDREN)
6711 FIB_TEST(1 == vec_len(tc->ctxs),
6712 "%d child visitsed %d times in zero quanta walk",
6713 ii, vec_len(tc->ctxs));
6717 FIB_TEST(0 == vec_len(tc->ctxs),
6718 "%d child visitsed %d times in 0 quanta walk",
6719 ii, vec_len(tc->ctxs));
6722 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6723 "Queue is not empty post zero quanta walk");
6724 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6725 "Parent has %d children post zero qunta walk",
6726 fib_node_list_get_size(PARENT()->fn_children));
6731 fib_walk_process_queues(vm, 0);
6733 FOR_EACH_TEST_CHILD(tc)
6735 if (ii >= N_TEST_CHILDREN-1)
6737 FIB_TEST(1 == vec_len(tc->ctxs),
6738 "%d child visitsed %d times in 2nd zero quanta walk",
6739 ii, vec_len(tc->ctxs));
6743 FIB_TEST(0 == vec_len(tc->ctxs),
6744 "%d child visitsed %d times in 2nd 0 quanta walk",
6745 ii, vec_len(tc->ctxs));
6748 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6749 "Queue is not empty post zero quanta walk");
6750 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6751 "Parent has %d children post zero qunta walk",
6752 fib_node_list_get_size(PARENT()->fn_children));
6755 * schedule another walk that will catch-up and merge.
6757 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6758 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6759 fib_walk_process_queues(vm, 1);
6761 FOR_EACH_TEST_CHILD(tc)
6763 if (ii >= N_TEST_CHILDREN-1)
6765 FIB_TEST(2 == vec_len(tc->ctxs),
6766 "%d child visitsed %d times in 2nd zero quanta merge walk",
6767 ii, vec_len(tc->ctxs));
6772 FIB_TEST(1 == vec_len(tc->ctxs),
6773 "%d child visitsed %d times in 2nd 0 quanta merge walk",
6774 ii, vec_len(tc->ctxs));
6778 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6779 "Queue is not empty post 2nd zero quanta merge walk");
6780 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6781 "Parent has %d children post 2nd zero qunta merge walk",
6782 fib_node_list_get_size(PARENT()->fn_children));
6785 * park a async walk in the middle of the list, then have an sync walk catch
6786 * it. same expectations as async catches async.
6788 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6790 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6791 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6793 fib_walk_process_queues(vm, 0);
6794 fib_walk_process_queues(vm, 0);
6796 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
6798 FOR_EACH_TEST_CHILD(tc)
6800 if (ii >= N_TEST_CHILDREN-1)
6802 FIB_TEST(2 == vec_len(tc->ctxs),
6803 "%d child visitsed %d times in sync catches async walk",
6804 ii, vec_len(tc->ctxs));
6809 FIB_TEST(1 == vec_len(tc->ctxs),
6810 "%d child visitsed %d times in sync catches async walk",
6811 ii, vec_len(tc->ctxs));
6815 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6816 "Queue is not empty post 2nd zero quanta merge walk");
6817 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6818 "Parent has %d children post 2nd zero qunta merge walk",
6819 fib_node_list_get_size(PARENT()->fn_children));
6822 * make the parent a child of one of its children, thus inducing a routing loop.
6824 fib_test_nodes[PARENT_INDEX].sibling =
6825 fib_node_child_add(FIB_NODE_TYPE_TEST,
6826 1, // the first child
6831 * execute a sync walk from the parent. each child visited spawns more sync
6832 * walks. we expect the walk to terminate.
6834 fib_test_walk_spawns_walks = 1;
6836 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
6838 FOR_EACH_TEST_CHILD(tc)
6841 * child 1 - which is last in the list - has the loop.
6842 * the other children a re thus visitsed first. the we meet
6843 * child 1. we go round the loop again, visting the other children.
6844 * then we meet the walk in the dep list and bail. child 1 is not visitsed
6849 FIB_TEST(1 == vec_len(tc->ctxs),
6850 "child %d visitsed %d times during looped sync walk",
6851 ii, vec_len(tc->ctxs));
6855 FIB_TEST(2 == vec_len(tc->ctxs),
6856 "child %d visitsed %d times during looped sync walk",
6857 ii, vec_len(tc->ctxs));
6861 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6862 "Parent has %d children post sync loop walk",
6863 fib_node_list_get_size(PARENT()->fn_children));
6866 * the walk doesn't reach the max depth because the infra knows that sync
6867 * meets sync implies a loop and bails early.
6869 FIB_TEST(high_ctx.fnbw_depth == 9,
6870 "Walk context depth %d post sync loop walk",
6871 high_ctx.fnbw_depth);
6874 * execute an async walk of the graph loop, with each child spawns sync walks
6876 high_ctx.fnbw_depth = 0;
6877 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6878 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6880 fib_walk_process_queues(vm, 1);
6882 FOR_EACH_TEST_CHILD(tc)
6885 * we don't really care how many times the children are visisted, as long as
6886 * it is more than once.
6888 FIB_TEST(1 <= vec_len(tc->ctxs),
6889 "child %d visitsed %d times during looped aync spawns sync walk",
6890 ii, vec_len(tc->ctxs));
6895 * execute an async walk of the graph loop, with each child spawns async walks
6897 fib_test_walk_spawns_walks = 2;
6898 high_ctx.fnbw_depth = 0;
6899 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6900 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6902 fib_walk_process_queues(vm, 1);
6904 FOR_EACH_TEST_CHILD(tc)
6907 * we don't really care how many times the children are visisted, as long as
6908 * it is more than once.
6910 FIB_TEST(1 <= vec_len(tc->ctxs),
6911 "child %d visitsed %d times during looped async spawns async walk",
6912 ii, vec_len(tc->ctxs));
6917 fib_node_child_remove(FIB_NODE_TYPE_TEST,
6918 1, // the first child
6919 fib_test_nodes[PARENT_INDEX].sibling);
6924 FOR_EACH_TEST_CHILD(tc)
6926 fib_node_child_remove(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6928 fib_node_deinit(&tc->node);
6929 fib_node_unlock(&tc->node);
6931 fib_node_deinit(PARENT());
6934 * The parent will be destroyed when the last lock on it goes.
6935 * this test ensures all the walk objects are unlocking it.
6937 FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed),
6938 "Parent was destroyed");
6942 lfib_test_deagg (void)
6944 const mpls_label_t deag_label = 50;
6945 const u32 lfib_index = 0;
6946 const u32 fib_index = 0;
6947 dpo_id_t dpo = DPO_INVALID;
6948 const dpo_id_t *dpo1;
6949 fib_node_index_t lfe;
6955 lb_count = pool_elts(load_balance_pool);
6957 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6961 * MPLS enable an interface so we get the MPLS table created
6963 mpls_sw_interface_enable_disable(&mpls_main,
6964 tm->hw[0]->sw_if_index,
6968 * Test the specials stack properly.
6970 fib_prefix_t exp_null_v6_pfx = {
6971 .fp_proto = FIB_PROTOCOL_MPLS,
6973 .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
6974 .fp_payload_proto = DPO_PROTO_IP6,
6976 lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx);
6977 FIB_TEST((FIB_NODE_INDEX_INVALID != lfe),
6979 format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
6980 format_mpls_eos_bit, MPLS_EOS);
6981 fib_entry_contribute_forwarding(lfe,
6982 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6984 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
6985 lkd = lookup_dpo_get(dpo1->dpoi_index);
6987 FIB_TEST((fib_index == lkd->lkd_fib_index),
6988 "%U/%U is deag in %d %U",
6989 format_mpls_unicast_label, deag_label,
6990 format_mpls_eos_bit, MPLS_EOS,
6992 format_dpo_id, &dpo, 0);
6993 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
6994 "%U/%U is dst deag",
6995 format_mpls_unicast_label, deag_label,
6996 format_mpls_eos_bit, MPLS_EOS);
6997 FIB_TEST((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table),
6998 "%U/%U is lookup in interface's table",
6999 format_mpls_unicast_label, deag_label,
7000 format_mpls_eos_bit, MPLS_EOS);
7001 FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto),
7002 "%U/%U is %U dst deag",
7003 format_mpls_unicast_label, deag_label,
7004 format_mpls_eos_bit, MPLS_EOS,
7005 format_dpo_proto, lkd->lkd_proto);
7009 * A route deag route for EOS
7011 fib_prefix_t pfx = {
7012 .fp_proto = FIB_PROTOCOL_MPLS,
7014 .fp_label = deag_label,
7015 .fp_payload_proto = DPO_PROTO_IP4,
7017 lfe = fib_table_entry_path_add(lfib_index,
7020 FIB_ENTRY_FLAG_NONE,
7027 FIB_ROUTE_PATH_FLAG_NONE);
7029 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
7031 format_mpls_unicast_label, deag_label,
7032 format_mpls_eos_bit, MPLS_EOS);
7034 fib_entry_contribute_forwarding(lfe,
7035 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7037 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
7038 lkd = lookup_dpo_get(dpo1->dpoi_index);
7040 FIB_TEST((fib_index == lkd->lkd_fib_index),
7041 "%U/%U is deag in %d %U",
7042 format_mpls_unicast_label, deag_label,
7043 format_mpls_eos_bit, MPLS_EOS,
7045 format_dpo_id, &dpo, 0);
7046 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
7047 "%U/%U is dst deag",
7048 format_mpls_unicast_label, deag_label,
7049 format_mpls_eos_bit, MPLS_EOS);
7050 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
7051 "%U/%U is %U dst deag",
7052 format_mpls_unicast_label, deag_label,
7053 format_mpls_eos_bit, MPLS_EOS,
7054 format_dpo_proto, lkd->lkd_proto);
7056 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
7058 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
7060 "%U/%U not present",
7061 format_mpls_unicast_label, deag_label,
7062 format_mpls_eos_bit, MPLS_EOS);
7065 * A route deag route for non-EOS
7067 pfx.fp_eos = MPLS_NON_EOS;
7068 lfe = fib_table_entry_path_add(lfib_index,
7071 FIB_ENTRY_FLAG_NONE,
7078 FIB_ROUTE_PATH_FLAG_NONE);
7080 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
7082 format_mpls_unicast_label, deag_label,
7083 format_mpls_eos_bit, MPLS_NON_EOS);
7085 fib_entry_contribute_forwarding(lfe,
7086 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7088 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
7089 lkd = lookup_dpo_get(dpo1->dpoi_index);
7091 FIB_TEST((fib_index == lkd->lkd_fib_index),
7092 "%U/%U is deag in %d %U",
7093 format_mpls_unicast_label, deag_label,
7094 format_mpls_eos_bit, MPLS_NON_EOS,
7096 format_dpo_id, &dpo, 0);
7097 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
7098 "%U/%U is dst deag",
7099 format_mpls_unicast_label, deag_label,
7100 format_mpls_eos_bit, MPLS_NON_EOS);
7102 FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto),
7103 "%U/%U is %U dst deag",
7104 format_mpls_unicast_label, deag_label,
7105 format_mpls_eos_bit, MPLS_NON_EOS,
7106 format_dpo_proto, lkd->lkd_proto);
7108 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
7110 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
7112 "%U/%U not present",
7113 format_mpls_unicast_label, deag_label,
7114 format_mpls_eos_bit, MPLS_EOS);
7117 mpls_sw_interface_enable_disable(&mpls_main,
7118 tm->hw[0]->sw_if_index,
7123 * +1 for the drop LB in the MPLS tables.
7125 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
7126 "Load-balance resources freed %d of %d",
7127 lb_count+1, pool_elts(load_balance_pool));
7130 static clib_error_t *
7131 lfib_test (vlib_main_t * vm,
7132 unformat_input_t * input,
7133 vlib_cli_command_t * cmd_arg)
7135 fib_test_mk_intf(4);
7142 static clib_error_t *
7143 fib_test (vlib_main_t * vm,
7144 unformat_input_t * input,
7145 vlib_cli_command_t * cmd_arg)
7147 fib_test_mk_intf(4);
7149 if (unformat (input, "ip"))
7154 else if (unformat (input, "gre"))
7158 else if (unformat (input, "label"))
7162 else if (unformat (input, "ae"))
7166 else if (unformat (input, "walk"))
7173 * These walk UT aren't run as part of the full suite, since the
7174 * fib-walk process must be disabled in order for the tests to work
7188 VLIB_CLI_COMMAND (test_fib_command, static) = {
7190 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
7191 .function = fib_test,
7194 VLIB_CLI_COMMAND (test_lfib_command, static) = {
7195 .path = "test lfib",
7196 .short_help = "mpls label fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
7197 .function = lfib_test,
7201 fib_test_init (vlib_main_t *vm)
7206 VLIB_INIT_FUNCTION (fib_test_init);