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/mpls/mpls_types.h>
18 #include <vnet/mfib/mfib_table.h>
19 #include <vnet/mfib/mfib_entry.h>
20 #include <vnet/mfib/mfib_signal.h>
21 #include <vnet/mfib/ip6_mfib.h>
22 #include <vnet/fib/fib_path_list.h>
23 #include <vnet/fib/fib_test.h>
24 #include <vnet/fib/fib_table.h>
25 #include <vnet/fib/mpls_fib.h>
27 #include <vnet/dpo/replicate_dpo.h>
28 #include <vnet/adj/adj_mcast.h>
30 #define MFIB_TEST_I(_cond, _comment, _args...) \
32 int _evald = (_cond); \
34 fformat(stderr, "FAIL:%d: " _comment "\n", \
40 #define MFIB_TEST(_cond, _comment, _args...) \
42 if (MFIB_TEST_I(_cond, _comment, ##_args)) { \
44 ASSERT(!("FAIL: " _comment)); \
47 #define MFIB_TEST_NS(_cond) \
49 if (MFIB_TEST_I(_cond, "")) { \
51 ASSERT(!("FAIL: ")); \
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 mfib_test_mk_intf (u32 ninterfaces)
109 clib_error_t * error = NULL;
110 test_main_t *tm = &test_main;
116 ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
121 vec_add1(hw_address, byte);
124 for (i = 0; i < ninterfaces; i++)
128 error = ethernet_register_interface(vnet_get_main(),
129 test_interface_device_class.index,
132 &tm->hw_if_indicies[i],
133 /* flag change */ 0);
135 MFIB_TEST((NULL == error), "ADD interface %d", i);
137 error = vnet_hw_interface_set_flags(vnet_get_main(),
138 tm->hw_if_indicies[i],
139 VNET_HW_INTERFACE_FLAG_LINK_UP);
140 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
141 tm->hw_if_indicies[i]);
142 vec_validate (ip4_main.fib_index_by_sw_if_index,
143 tm->hw[i]->sw_if_index);
144 vec_validate (ip6_main.fib_index_by_sw_if_index,
145 tm->hw[i]->sw_if_index);
146 ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
147 ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
149 vec_validate (ip4_main.mfib_index_by_sw_if_index,
150 tm->hw[i]->sw_if_index);
151 vec_validate (ip6_main.mfib_index_by_sw_if_index,
152 tm->hw[i]->sw_if_index);
153 ip4_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
154 ip6_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
156 error = vnet_sw_interface_set_flags(vnet_get_main(),
157 tm->hw[i]->sw_if_index,
158 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
159 MFIB_TEST((NULL == error), "UP interface %d", i);
162 * re-eval after the inevitable realloc
164 for (i = 0; i < ninterfaces; i++)
166 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
167 tm->hw_if_indicies[i]);
173 #define MFIB_TEST_REP(_cond, _comment, _args...) \
175 if (MFIB_TEST_I(_cond, _comment, ##_args)) { \
181 mfib_test_validate_rep_v (const replicate_t *rep,
192 MFIB_TEST_REP((n_buckets == rep->rep_n_buckets),
193 "n_buckets = %d", rep->rep_n_buckets);
195 for (bucket = 0; bucket < n_buckets; bucket++)
197 dt = va_arg(*ap, int); // type promotion
198 ai = va_arg(*ap, adj_index_t);
199 dpo = replicate_get_bucket_i(rep, bucket);
201 MFIB_TEST_REP((dt == dpo->dpoi_type),
202 "bucket %d stacks on %U",
204 format_dpo_type, dpo->dpoi_type);
206 if (DPO_RECEIVE != dt)
208 MFIB_TEST_REP((ai == dpo->dpoi_index),
209 "bucket %d [exp:%d] stacks on %U",
211 format_dpo_id, dpo, 0);
218 mfib_test_entry (fib_node_index_t fei,
219 mfib_entry_flags_t eflags,
223 const mfib_prefix_t *pfx;
224 const mfib_entry_t *mfe;
225 const replicate_t *rep;
231 mfe = mfib_entry_get(fei);
232 pfx = mfib_entry_get_prefix(fei);
234 MFIB_TEST_REP((eflags == mfe->mfe_flags),
235 "%U has %U expect %U",
236 format_mfib_prefix, &pfx,
237 format_mfib_entry_flags, mfe->mfe_flags,
238 format_mfib_entry_flags, eflags);
242 MFIB_TEST_REP((DPO_DROP == mfe->mfe_rep.dpoi_type),
244 format_mfib_prefix, &pfx,
245 format_dpo_id, &mfe->mfe_rep, 0);
249 dpo_id_t tmp = DPO_INVALID;
251 mfib_entry_contribute_forwarding(
253 mfib_forw_chain_type_from_fib_proto(pfx->fp_proto),
254 MFIB_ENTRY_FWD_FLAG_NONE,
256 rep = replicate_get(tmp.dpoi_index);
258 MFIB_TEST_REP((DPO_REPLICATE == tmp.dpoi_type),
260 format_mfib_prefix, &pfx,
261 format_dpo_type, tmp.dpoi_type);
263 va_start(ap, n_buckets);
264 res = mfib_test_validate_rep_v(rep, n_buckets, &ap);
275 mfib_test_entry_itf (fib_node_index_t fei,
277 mfib_itf_flags_t flags)
279 const mfib_prefix_t *pfx;
280 const mfib_entry_t *mfe;
281 const mfib_itf_t *mfi;
285 mfe = mfib_entry_get(fei);
286 mfi = mfib_entry_get_itf(mfe, sw_if_index);
287 pfx = mfib_entry_get_prefix(fei);
289 MFIB_TEST_REP((NULL != mfi),
290 "%U has interface %d",
291 format_mfib_prefix, &pfx, sw_if_index);
293 MFIB_TEST_REP((flags == mfi->mfi_flags),
294 "%U interface %d has flags %U expect %U",
295 format_mfib_prefix, &pfx, sw_if_index,
296 format_mfib_itf_flags, flags,
297 format_mfib_itf_flags, mfi->mfi_flags);
303 mfib_test_entry_no_itf (fib_node_index_t fei,
306 const mfib_prefix_t *pfx;
307 const mfib_entry_t *mfe;
308 const mfib_itf_t *mfi;
312 mfe = mfib_entry_get(fei);
313 mfi = mfib_entry_get_itf(mfe, sw_if_index);
314 pfx = mfib_entry_get_prefix(fei);
316 MFIB_TEST_REP((NULL == mfi),
317 "%U has no interface %d",
318 format_mfib_prefix, pfx, sw_if_index);
324 mfib_test_i (fib_protocol_t PROTO,
326 const mfib_prefix_t *pfx_no_forward,
327 const mfib_prefix_t *pfx_s_g,
328 const mfib_prefix_t *pfx_star_g_1,
329 const mfib_prefix_t *pfx_star_g_2,
330 const mfib_prefix_t *pfx_star_g_3,
331 const mfib_prefix_t *pfx_star_g_slash_m,
332 const fib_prefix_t *pfx_itf,
333 const ip46_address_t *addr_nbr1,
334 const ip46_address_t *addr_nbr2)
336 fib_node_index_t mfei, mfei_dflt, mfei_no_f, mfei_s_g, mfei_g_1, mfei_g_2, mfei_g_3, mfei_g_m;
337 u32 fib_index, n_entries, n_itfs, n_reps, n_pls;
338 fib_node_index_t ai_1, ai_2, ai_3, ai_nbr1, ai_nbr2;
342 mfib_prefix_t all_1s;
343 clib_memset(&all_1s, 0xfd, sizeof(all_1s));
346 n_entries = pool_elts(mfib_entry_pool);
347 n_itfs = pool_elts(mfib_itf_pool);
348 n_reps = pool_elts(replicate_pool);
349 n_pls = fib_path_list_pool_size();
352 ai_1 = adj_mcast_add_or_lock(PROTO,
354 tm->hw[1]->sw_if_index);
355 ai_2 = adj_mcast_add_or_lock(PROTO,
357 tm->hw[2]->sw_if_index);
358 ai_3 = adj_mcast_add_or_lock(PROTO,
360 tm->hw[3]->sw_if_index);
361 ai_nbr1 = adj_nbr_add_or_lock(PROTO,
364 tm->hw[0]->sw_if_index);
365 ai_nbr2 = adj_nbr_add_or_lock(PROTO,
368 tm->hw[0]->sw_if_index);
370 MFIB_TEST(3 == adj_mcast_db_size(), "3 MCAST adjs");
372 /* Find or create FIB table 11 */
373 fib_index = mfib_table_find_or_create_and_lock(PROTO, 11, MFIB_SOURCE_API);
375 fib_table_entry_update_one_path(0,
377 FIB_SOURCE_INTERFACE,
378 (FIB_ENTRY_FLAG_CONNECTED |
379 FIB_ENTRY_FLAG_ATTACHED),
382 tm->hw[0]->sw_if_index,
383 ~0, // invalid fib index
386 FIB_ROUTE_PATH_FLAG_NONE);
388 mfib_prefix_t pfx_dft = {
392 mfei_dflt = mfib_table_lookup_exact_match(fib_index, &pfx_dft);
393 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
394 MFIB_TEST(!mfib_test_entry(mfei_dflt,
395 MFIB_ENTRY_FLAG_DROP,
397 "(*,*) no replcaitions");
399 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
400 MFIB_TEST(!mfib_test_entry(mfei_dflt,
401 MFIB_ENTRY_FLAG_DROP,
403 "(*,*) no replcaitions");
406 fib_route_path_t path_via_if0 = {
407 .frp_proto = fib_proto_to_dpo(PROTO),
408 .frp_addr = zero_addr,
409 .frp_sw_if_index = tm->hw[0]->sw_if_index,
415 mfib_table_entry_path_update(fib_index,
419 MFIB_ITF_FLAG_ACCEPT);
421 mfei_no_f = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
422 MFIB_TEST(!mfib_test_entry(mfei_no_f,
423 MFIB_ENTRY_FLAG_NONE,
425 "%U no replcaitions",
426 format_mfib_prefix, pfx_no_forward);
427 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_no_f, tm->hw[0]->sw_if_index,
428 MFIB_ITF_FLAG_ACCEPT));
430 fib_route_path_t path_via_if1 = {
431 .frp_proto = fib_proto_to_dpo(PROTO),
432 .frp_addr = zero_addr,
433 .frp_sw_if_index = tm->hw[1]->sw_if_index,
438 fib_route_path_t path_via_if2 = {
439 .frp_proto = fib_proto_to_dpo(PROTO),
440 .frp_addr = zero_addr,
441 .frp_sw_if_index = tm->hw[2]->sw_if_index,
446 fib_route_path_t path_via_if3 = {
447 .frp_proto = fib_proto_to_dpo(PROTO),
448 .frp_addr = zero_addr,
449 .frp_sw_if_index = tm->hw[3]->sw_if_index,
454 fib_route_path_t path_for_us = {
455 .frp_proto = fib_proto_to_dpo(PROTO),
456 .frp_addr = zero_addr,
457 .frp_sw_if_index = 0xffffffff,
460 .frp_flags = FIB_ROUTE_PATH_LOCAL,
464 * An (S,G) with 1 accepting and 3 forwarding paths
466 mfib_table_entry_path_update(fib_index,
470 MFIB_ITF_FLAG_ACCEPT);
471 mfib_table_entry_path_update(fib_index,
475 MFIB_ITF_FLAG_FORWARD);
476 mfib_table_entry_path_update(fib_index,
480 MFIB_ITF_FLAG_FORWARD);
481 mfib_table_entry_path_update(fib_index,
485 (MFIB_ITF_FLAG_FORWARD |
486 MFIB_ITF_FLAG_NEGATE_SIGNAL));
488 mfei_s_g = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
490 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_s_g,
492 format_mfib_prefix, pfx_s_g);
493 MFIB_TEST(!mfib_test_entry(mfei_s_g,
494 MFIB_ENTRY_FLAG_NONE,
496 DPO_ADJACENCY_MCAST, ai_1,
497 DPO_ADJACENCY_MCAST, ai_2,
498 DPO_ADJACENCY_MCAST, ai_3),
500 format_mfib_prefix, pfx_s_g);
501 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[0]->sw_if_index,
502 MFIB_ITF_FLAG_ACCEPT));
503 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[1]->sw_if_index,
504 MFIB_ITF_FLAG_FORWARD));
505 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[2]->sw_if_index,
506 MFIB_ITF_FLAG_FORWARD));
507 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[3]->sw_if_index,
508 (MFIB_ITF_FLAG_FORWARD |
509 MFIB_ITF_FLAG_NEGATE_SIGNAL)));
512 * A (*,G), which the same G as the (S,G).
513 * different paths. test our LPM.
515 mfei_g_1 = mfib_table_entry_path_update(fib_index,
519 MFIB_ITF_FLAG_ACCEPT);
520 mfib_table_entry_path_update(fib_index,
524 MFIB_ITF_FLAG_FORWARD);
527 * test we find the *,G and S,G via LPM and exact matches
529 mfei = mfib_table_lookup_exact_match(fib_index,
531 MFIB_TEST(mfei == mfei_g_1,
532 "%U found via exact match",
533 format_mfib_prefix, pfx_star_g_1);
534 MFIB_TEST(!mfib_test_entry(mfei,
535 MFIB_ENTRY_FLAG_NONE,
537 DPO_ADJACENCY_MCAST, ai_1),
539 format_mfib_prefix, pfx_star_g_1);
541 mfei = mfib_table_lookup(fib_index,
543 MFIB_TEST(mfei == mfei_g_1,
544 "[e:%d a:%d] %U found via LP match",
546 format_mfib_prefix, pfx_star_g_1);
548 MFIB_TEST(!mfib_test_entry(mfei,
549 MFIB_ENTRY_FLAG_NONE,
551 DPO_ADJACENCY_MCAST, ai_1),
553 format_mfib_prefix, pfx_star_g_1);
555 mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
556 MFIB_TEST(mfei == mfei_s_g,
557 "%U found via exact match",
558 format_mfib_prefix, pfx_s_g);
560 MFIB_TEST(!mfib_test_entry(mfei,
561 MFIB_ENTRY_FLAG_NONE,
563 DPO_ADJACENCY_MCAST, ai_1,
564 DPO_ADJACENCY_MCAST, ai_2,
565 DPO_ADJACENCY_MCAST, ai_3),
567 format_mfib_prefix, pfx_s_g);
568 mfei = mfib_table_lookup(fib_index, pfx_s_g);
569 MFIB_TEST(mfei == mfei_s_g,
570 "%U found via LP match",
571 format_mfib_prefix, pfx_s_g);
573 MFIB_TEST(!mfib_test_entry(mfei,
574 MFIB_ENTRY_FLAG_NONE,
576 DPO_ADJACENCY_MCAST, ai_1,
577 DPO_ADJACENCY_MCAST, ai_2,
578 DPO_ADJACENCY_MCAST, ai_3),
580 format_mfib_prefix, pfx_s_g);
583 * A (*,G/m), which the same root G as the (*,G).
584 * different paths. test our LPM.
586 mfei_g_m = mfib_table_entry_path_update(fib_index,
590 MFIB_ITF_FLAG_ACCEPT);
591 mfib_table_entry_path_update(fib_index,
595 MFIB_ITF_FLAG_FORWARD);
598 * test we find the (*,G/m), (*,G) and (S,G) via LPM and exact matches
600 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
601 MFIB_TEST((mfei_g_1 == mfei),
602 "%U found via DP LPM: %d",
603 format_mfib_prefix, pfx_star_g_1, mfei);
605 MFIB_TEST(!mfib_test_entry(mfei,
606 MFIB_ENTRY_FLAG_NONE,
608 DPO_ADJACENCY_MCAST, ai_1),
610 format_mfib_prefix, pfx_star_g_1);
612 mfei = mfib_table_lookup(fib_index, pfx_star_g_1);
614 MFIB_TEST(!mfib_test_entry(mfei,
615 MFIB_ENTRY_FLAG_NONE,
617 DPO_ADJACENCY_MCAST, ai_1),
619 format_mfib_prefix, pfx_star_g_1);
621 mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
623 MFIB_TEST(!mfib_test_entry(mfei,
624 MFIB_ENTRY_FLAG_NONE,
626 DPO_ADJACENCY_MCAST, ai_1,
627 DPO_ADJACENCY_MCAST, ai_2,
628 DPO_ADJACENCY_MCAST, ai_3),
630 format_mfib_prefix, pfx_s_g);
631 mfei = mfib_table_lookup(fib_index, pfx_s_g);
633 MFIB_TEST(!mfib_test_entry(mfei,
634 MFIB_ENTRY_FLAG_NONE,
636 DPO_ADJACENCY_MCAST, ai_1,
637 DPO_ADJACENCY_MCAST, ai_2,
638 DPO_ADJACENCY_MCAST, ai_3),
640 format_mfib_prefix, pfx_s_g);
642 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
643 MFIB_TEST(mfei = mfei_g_m,
644 "%U Found via exact match",
645 format_mfib_prefix, pfx_star_g_slash_m);
646 MFIB_TEST(!mfib_test_entry(mfei,
647 MFIB_ENTRY_FLAG_NONE,
649 DPO_ADJACENCY_MCAST, ai_3),
651 format_mfib_prefix, pfx_star_g_slash_m);
652 MFIB_TEST(mfei_g_m == mfib_table_lookup(fib_index, pfx_star_g_slash_m),
654 format_mfib_prefix, pfx_star_g_slash_m);
659 mfei = mfib_table_entry_path_update(fib_index,
663 MFIB_ITF_FLAG_FORWARD);
665 MFIB_TEST(!mfib_test_entry(mfei,
666 MFIB_ENTRY_FLAG_NONE,
668 DPO_ADJACENCY_MCAST, ai_1,
669 DPO_ADJACENCY_MCAST, ai_2,
670 DPO_ADJACENCY_MCAST, ai_3,
673 format_mfib_prefix, pfx_s_g);
676 * remove a for-us path
678 mfib_table_entry_path_remove(fib_index,
683 MFIB_TEST(!mfib_test_entry(mfei,
684 MFIB_ENTRY_FLAG_NONE,
686 DPO_ADJACENCY_MCAST, ai_1,
687 DPO_ADJACENCY_MCAST, ai_2,
688 DPO_ADJACENCY_MCAST, ai_3),
690 format_mfib_prefix, pfx_s_g);
693 * update an existing forwarding path to be only accepting
694 * - expect it to be removed from the replication set.
696 mfib_table_entry_path_update(fib_index,
700 MFIB_ITF_FLAG_ACCEPT);
702 MFIB_TEST(!mfib_test_entry(mfei,
703 MFIB_ENTRY_FLAG_NONE,
705 DPO_ADJACENCY_MCAST, ai_1,
706 DPO_ADJACENCY_MCAST, ai_2),
708 format_mfib_prefix, pfx_s_g);
709 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
710 MFIB_ITF_FLAG_ACCEPT));
711 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
712 MFIB_ITF_FLAG_FORWARD));
713 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
714 MFIB_ITF_FLAG_FORWARD));
715 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
716 MFIB_ITF_FLAG_ACCEPT));
718 * Make the path forwarding again
719 * - expect it to be added back to the replication set
721 mfib_table_entry_path_update(fib_index,
725 (MFIB_ITF_FLAG_FORWARD |
726 MFIB_ITF_FLAG_ACCEPT |
727 MFIB_ITF_FLAG_NEGATE_SIGNAL));
729 mfei = mfib_table_lookup_exact_match(fib_index,
732 MFIB_TEST(!mfib_test_entry(mfei,
733 MFIB_ENTRY_FLAG_NONE,
735 DPO_ADJACENCY_MCAST, ai_1,
736 DPO_ADJACENCY_MCAST, ai_2,
737 DPO_ADJACENCY_MCAST, ai_3),
739 format_mfib_prefix, pfx_s_g);
740 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
741 MFIB_ITF_FLAG_ACCEPT));
742 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
743 MFIB_ITF_FLAG_FORWARD));
744 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
745 MFIB_ITF_FLAG_FORWARD));
746 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
747 (MFIB_ITF_FLAG_FORWARD |
748 MFIB_ITF_FLAG_ACCEPT |
749 MFIB_ITF_FLAG_NEGATE_SIGNAL)));
752 * update flags on the entry
754 mfib_table_entry_update(fib_index,
758 MFIB_ENTRY_FLAG_SIGNAL);
759 MFIB_TEST(!mfib_test_entry(mfei,
760 MFIB_ENTRY_FLAG_SIGNAL,
762 DPO_ADJACENCY_MCAST, ai_1,
763 DPO_ADJACENCY_MCAST, ai_2,
764 DPO_ADJACENCY_MCAST, ai_3),
766 format_mfib_prefix, pfx_s_g);
771 mfib_table_entry_path_remove(fib_index,
776 MFIB_TEST(!mfib_test_entry(mfei,
777 MFIB_ENTRY_FLAG_SIGNAL,
779 DPO_ADJACENCY_MCAST, ai_1,
780 DPO_ADJACENCY_MCAST, ai_2),
782 format_mfib_prefix, pfx_s_g);
783 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
784 MFIB_ITF_FLAG_ACCEPT));
785 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
786 MFIB_ITF_FLAG_FORWARD));
787 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
788 MFIB_ITF_FLAG_FORWARD));
789 MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
791 mfib_table_entry_path_remove(fib_index,
796 MFIB_TEST(!mfib_test_entry(mfei,
797 MFIB_ENTRY_FLAG_SIGNAL,
799 DPO_ADJACENCY_MCAST, ai_2),
801 format_mfib_prefix, pfx_s_g);
802 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
803 MFIB_ITF_FLAG_ACCEPT));
804 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
805 MFIB_ITF_FLAG_FORWARD));
806 MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
809 * remove the accpeting only interface
811 mfib_table_entry_path_remove(fib_index,
816 MFIB_TEST(!mfib_test_entry(mfei,
817 MFIB_ENTRY_FLAG_SIGNAL,
819 DPO_ADJACENCY_MCAST, ai_2),
821 format_mfib_prefix, pfx_s_g);
822 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
823 MFIB_ITF_FLAG_FORWARD));
824 MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[0]->sw_if_index));
825 MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[1]->sw_if_index));
826 MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
829 * remove the last path, the entry still has flags so it remains
831 mfib_table_entry_path_remove(fib_index,
836 MFIB_TEST(!mfib_test_entry(mfei,
837 MFIB_ENTRY_FLAG_SIGNAL,
839 "%U no replications",
840 format_mfib_prefix, pfx_s_g);
843 * update flags on the entry
845 mfib_table_entry_update(fib_index,
849 (MFIB_ENTRY_FLAG_SIGNAL |
850 MFIB_ENTRY_FLAG_CONNECTED));
851 MFIB_TEST(!mfib_test_entry(mfei,
852 (MFIB_ENTRY_FLAG_SIGNAL |
853 MFIB_ENTRY_FLAG_CONNECTED),
855 "%U no replications",
856 format_mfib_prefix, pfx_s_g);
859 * An entry with a NS interface
861 mfei_g_2 = mfib_table_entry_path_update(fib_index,
865 (MFIB_ITF_FLAG_ACCEPT |
866 MFIB_ITF_FLAG_NEGATE_SIGNAL));
867 MFIB_TEST(!mfib_test_entry(mfei_g_2,
868 MFIB_ENTRY_FLAG_NONE,
870 "%U No replications",
871 format_mfib_prefix, pfx_star_g_2);
874 * Simulate a signal from the data-plane
880 mfe = mfib_entry_get(mfei_g_2);
881 mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
883 mfib_signal_push(mfe, mfi, NULL);
887 * An entry with a NS interface
889 mfei_g_3 = mfib_table_entry_path_update(fib_index,
893 (MFIB_ITF_FLAG_ACCEPT |
894 MFIB_ITF_NEGATE_SIGNAL));
895 MFIB_TEST(!mfib_test_entry(mfei_g_3,
896 MFIB_ENTRY_FLAG_NONE,
898 "%U No replications",
899 format_mfib_prefix, pfx_star_g_3);
902 * Simulate a signal from the data-plane
908 mfe = mfib_entry_get(mfei_g_3);
909 mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
911 mfib_signal_push(mfe, mfi, NULL);
914 if (FIB_PROTOCOL_IP6 == PROTO)
917 * All the entries are present. let's ensure we can find them all
918 * via exact and longest prefix matches.
921 * A source address we will never match
923 ip6_address_t src = {
924 .as_u64[0] = clib_host_to_net_u64(0x3001000000000000),
925 .as_u64[1] = clib_host_to_net_u64(0xffffffffffffffff),
931 MFIB_TEST((mfei_g_m == ip6_mfib_table_fwd_lookup(
932 ip6_mfib_get(fib_index),
934 &pfx_star_g_slash_m->fp_grp_addr.ip6)),
935 "%U found via DP LPM grp=%U",
936 format_mfib_prefix, pfx_star_g_slash_m,
937 format_ip6_address, &pfx_star_g_slash_m->fp_grp_addr.ip6);
939 ip6_address_t tmp = pfx_star_g_slash_m->fp_grp_addr.ip6;
940 tmp.as_u8[15] = 0xff;
942 MFIB_TEST((mfei_g_m == ip6_mfib_table_fwd_lookup(
943 ip6_mfib_get(fib_index),
944 &pfx_s_g->fp_src_addr.ip6,
946 "%U found via DP LPM grp=%U",
947 format_mfib_prefix, pfx_star_g_slash_m,
948 format_ip6_address, &tmp);
953 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
954 &pfx_s_g->fp_src_addr.ip6,
955 &pfx_s_g->fp_grp_addr.ip6);
956 MFIB_TEST((mfei_s_g == mfei),
957 "%U found via DP LPM: %d",
958 format_mfib_prefix, pfx_s_g, mfei);
963 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
965 &pfx_star_g_1->fp_grp_addr.ip6);
966 MFIB_TEST((mfei_g_1 == mfei),
967 "%U found via DP LPM: %d",
968 format_mfib_prefix, pfx_star_g_1, mfei);
969 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
971 &pfx_star_g_2->fp_grp_addr.ip6);
972 MFIB_TEST((mfei_g_2 == mfei),
973 "%U found via DP LPM: %d",
974 format_mfib_prefix, pfx_star_g_2, mfei);
975 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
977 &pfx_star_g_3->fp_grp_addr.ip6);
978 MFIB_TEST((mfei_g_3 == mfei),
979 "%U found via DP LPM: %d",
980 format_mfib_prefix, pfx_star_g_3, mfei);
984 * remove flags on the entry. This is the last of the
985 * state associated with the entry, so now it goes.
987 mfib_table_entry_update(fib_index,
991 MFIB_ENTRY_FLAG_NONE);
992 mfei = mfib_table_lookup_exact_match(fib_index,
994 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
996 format_mfib_prefix, pfx_s_g);
999 * remove the last path on the no forward entry - the last entry
1001 mfib_table_entry_path_remove(fib_index,
1006 mfei = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
1007 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1009 format_mfib_prefix, pfx_no_forward);
1012 * hard delete the (*,232.1.1.1)
1014 mfib_table_entry_delete(fib_index,
1018 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
1019 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1021 format_mfib_prefix, pfx_star_g_1);
1023 * remove the entry whilst the signal is pending
1025 mfib_table_entry_delete(fib_index,
1029 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_2);
1030 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1032 format_mfib_prefix, pfx_star_g_2);
1033 mfib_table_entry_delete(fib_index,
1037 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_3);
1038 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1040 format_mfib_prefix, pfx_star_g_3);
1042 mfib_table_entry_delete(fib_index,
1046 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
1047 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1049 format_mfib_prefix, pfx_star_g_slash_m);
1052 * Entries with paths via unicast next-hops
1054 fib_route_path_t path_via_nbr1 = {
1055 .frp_proto = fib_proto_to_dpo(PROTO),
1056 .frp_addr = *addr_nbr1,
1057 .frp_sw_if_index = tm->hw[0]->sw_if_index,
1058 .frp_fib_index = ~0,
1062 fib_route_path_t path_via_nbr2 = {
1063 .frp_proto = fib_proto_to_dpo(PROTO),
1064 .frp_addr = *addr_nbr2,
1065 .frp_sw_if_index = tm->hw[0]->sw_if_index,
1066 .frp_fib_index = ~0,
1071 mfei_g_1 = mfib_table_entry_path_update(fib_index,
1075 (MFIB_ITF_FLAG_FORWARD));
1076 mfei_g_1 = mfib_table_entry_path_update(fib_index,
1080 (MFIB_ITF_FLAG_FORWARD));
1081 MFIB_TEST(!mfib_test_entry(mfei_g_1,
1082 MFIB_ENTRY_FLAG_NONE,
1084 DPO_ADJACENCY_INCOMPLETE, ai_nbr1,
1085 DPO_ADJACENCY_INCOMPLETE, ai_nbr2),
1087 format_mfib_prefix, pfx_star_g_1);
1088 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_g_1, tm->hw[0]->sw_if_index,
1089 MFIB_ITF_FLAG_FORWARD));
1091 mfib_table_entry_path_remove(fib_index,
1096 MFIB_TEST(!mfib_test_entry(mfei_g_1,
1097 MFIB_ENTRY_FLAG_NONE,
1099 DPO_ADJACENCY_INCOMPLETE, ai_nbr2),
1101 format_mfib_prefix, pfx_star_g_1);
1102 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_g_1, tm->hw[0]->sw_if_index,
1103 MFIB_ITF_FLAG_FORWARD));
1105 mfib_table_entry_path_remove(fib_index,
1109 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
1110 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1112 format_mfib_prefix, pfx_star_g_1);
1115 * Add a prefix as a special/exclusive route
1117 dpo_id_t td = DPO_INVALID;
1118 index_t repi = replicate_create(1, fib_proto_to_dpo(PROTO));
1120 dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_2);
1121 replicate_set_bucket(repi, 0, &td);
1123 mfei = mfib_table_entry_special_add(fib_index,
1126 MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF,
1128 MFIB_TEST(!mfib_test_entry(mfei,
1129 (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
1130 MFIB_ENTRY_FLAG_EXCLUSIVE),
1132 DPO_ADJACENCY_MCAST, ai_2),
1133 "%U exclusive replicate OK",
1134 format_mfib_prefix, pfx_star_g_3);
1137 * update a special/exclusive route
1139 index_t repi2 = replicate_create(1, fib_proto_to_dpo(PROTO));
1141 dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_1);
1142 replicate_set_bucket(repi2, 0, &td);
1144 mfib_entry_update(mfei,
1146 (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
1147 MFIB_ENTRY_FLAG_EXCLUSIVE),
1150 MFIB_TEST(!mfib_test_entry(mfei,
1151 (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
1152 MFIB_ENTRY_FLAG_EXCLUSIVE),
1154 DPO_ADJACENCY_MCAST, ai_1),
1155 "%U exclusive update replicate OK",
1156 format_mfib_prefix, pfx_star_g_3);
1158 mfib_table_entry_delete(fib_index,
1164 * A Multicast LSP. This a mLDP head-end
1166 fib_node_index_t ai_mpls_10_10_10_1, lfei;
1167 ip46_address_t nh_10_10_10_1 = {
1169 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
1172 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1175 tm->hw[0]->sw_if_index);
1177 fib_prefix_t pfx_3500 = {
1179 .fp_proto = FIB_PROTOCOL_MPLS,
1182 .fp_payload_proto = DPO_PROTO_IP4,
1184 fib_test_rep_bucket_t mc_0 = {
1185 .type = FT_REP_LABEL_O_ADJ,
1187 .adj = ai_mpls_10_10_10_1,
1192 fib_mpls_label_t *l3300 = NULL, fml3300 = {
1195 vec_add1(l3300, fml3300);
1198 * MPLS enable an interface so we get the MPLS table created
1200 mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL);
1201 mpls_sw_interface_enable_disable(&mpls_main,
1202 tm->hw[0]->sw_if_index,
1205 lfei = fib_table_entry_update_one_path(0, // default MPLS Table
1208 FIB_ENTRY_FLAG_MULTICAST,
1211 tm->hw[0]->sw_if_index,
1212 ~0, // invalid fib index
1215 FIB_ROUTE_PATH_FLAG_NONE);
1216 MFIB_TEST(!fib_test_validate_entry(lfei,
1217 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
1220 "3500 via replicate over 10.10.10.1");
1223 * An (S,G) that resolves via the mLDP head-end
1225 fib_route_path_t path_via_mldp = {
1226 .frp_proto = DPO_PROTO_MPLS,
1227 .frp_local_label = pfx_3500.fp_label,
1228 .frp_eos = MPLS_EOS,
1229 .frp_sw_if_index = 0xffffffff,
1232 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
1234 dpo_id_t mldp_dpo = DPO_INVALID;
1236 fib_entry_contribute_forwarding(lfei,
1237 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
1240 mfei = mfib_table_entry_path_update(fib_index,
1244 MFIB_ITF_FLAG_FORWARD);
1246 MFIB_TEST(!mfib_test_entry(mfei,
1247 MFIB_ENTRY_FLAG_NONE,
1249 DPO_REPLICATE, mldp_dpo.dpoi_index),
1250 "%U over-mLDP replicate OK",
1251 format_mfib_prefix, pfx_s_g);
1254 * add a for-us path. this tests two types of non-attached paths on one entry
1256 mfei = mfib_table_entry_path_update(fib_index,
1260 MFIB_ITF_FLAG_FORWARD);
1261 MFIB_TEST(!mfib_test_entry(mfei,
1262 MFIB_ENTRY_FLAG_NONE,
1264 DPO_REPLICATE, mldp_dpo.dpoi_index,
1266 "%U mLDP+for-us replicate OK",
1267 format_mfib_prefix, pfx_s_g);
1269 mfib_table_entry_delete(fib_index,
1272 fib_table_entry_delete(0,
1275 dpo_reset(&mldp_dpo);
1278 * Unlock the table - it's the last lock so should be gone thereafter
1280 MFIB_TEST(((PROTO == FIB_PROTOCOL_IP4 ? 1 : 5) ==
1281 mfib_table_get_n_routes(fib_index, PROTO)),
1282 "1 = %d route left in the FIB",
1283 mfib_table_get_n_routes(fib_index, PROTO));
1285 mfib_table_unlock(fib_index, PROTO, MFIB_SOURCE_API);
1287 MFIB_TEST((FIB_NODE_INDEX_INVALID ==
1288 mfib_table_find(PROTO, fib_index)),
1289 "MFIB table %d gone", fib_index);
1294 adj_unlock(ai_nbr1);
1295 adj_unlock(ai_nbr2);
1298 * MPLS disable the interface
1300 mpls_sw_interface_enable_disable(&mpls_main,
1301 tm->hw[0]->sw_if_index,
1303 mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
1306 * remove the connected
1308 fib_table_entry_delete(0, pfx_itf, FIB_SOURCE_INTERFACE);
1311 * test we've leaked no resources
1313 MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
1314 MFIB_TEST(n_pls == fib_path_list_pool_size(), "%d=%d path-lists",
1315 n_pls, fib_path_list_pool_size());
1316 MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
1317 n_reps, pool_elts(replicate_pool));
1318 MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
1319 " No more entries %d!=%d",
1320 n_entries, pool_elts(mfib_entry_pool));
1321 MFIB_TEST(n_itfs == pool_elts(mfib_itf_pool),
1322 " No more Interfaces %d!=%d",
1323 n_itfs, pool_elts(mfib_itf_pool));
1331 const mfib_prefix_t pfx_224_s_8 = {
1333 .fp_proto = FIB_PROTOCOL_IP4,
1335 .ip4.as_u32 = clib_host_to_net_u32(0xe0000000),
1338 const mfib_prefix_t pfx_1_1_1_1_c_239_1_1_1 = {
1340 .fp_proto = FIB_PROTOCOL_IP4,
1342 .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1345 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1348 const mfib_prefix_t pfx_239_1_1_1 = {
1350 .fp_proto = FIB_PROTOCOL_IP4,
1352 .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1358 const mfib_prefix_t pfx_239_1_1_2 = {
1360 .fp_proto = FIB_PROTOCOL_IP4,
1362 .ip4.as_u32 = clib_host_to_net_u32(0xef010102),
1368 const mfib_prefix_t pfx_239_1_1_3 = {
1370 .fp_proto = FIB_PROTOCOL_IP4,
1372 .ip4.as_u32 = clib_host_to_net_u32(0xef010103),
1378 const mfib_prefix_t pfx_239 = {
1380 .fp_proto = FIB_PROTOCOL_IP4,
1382 .ip4.as_u32 = clib_host_to_net_u32(0xef000000),
1388 const fib_prefix_t pfx_itf = {
1390 .fp_proto = FIB_PROTOCOL_IP4,
1392 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
1395 const ip46_address_t nbr1 = {
1396 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0b),
1398 const ip46_address_t nbr2 = {
1399 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0c),
1401 return (mfib_test_i(FIB_PROTOCOL_IP4,
1404 &pfx_1_1_1_1_c_239_1_1_1,
1417 const mfib_prefix_t pfx_ffd_s_12 = {
1419 .fp_proto = FIB_PROTOCOL_IP6,
1421 .ip6.as_u64[0] = clib_host_to_net_u64(0xffd0000000000000),
1424 const mfib_prefix_t pfx_2001_1_c_ff_1 = {
1426 .fp_proto = FIB_PROTOCOL_IP6,
1428 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1429 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1432 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1433 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1436 const mfib_prefix_t pfx_ff_1 = {
1438 .fp_proto = FIB_PROTOCOL_IP6,
1440 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1441 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1444 const mfib_prefix_t pfx_ff_2 = {
1446 .fp_proto = FIB_PROTOCOL_IP6,
1448 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1449 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1452 const mfib_prefix_t pfx_ff_3 = {
1454 * this is the ALL DHCP routers address
1457 .fp_proto = FIB_PROTOCOL_IP6,
1459 .ip6.as_u64[0] = clib_host_to_net_u64(0xff02000100000000),
1460 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1463 const mfib_prefix_t pfx_ff = {
1465 .fp_proto = FIB_PROTOCOL_IP6,
1467 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1468 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000000),
1471 const fib_prefix_t pfx_itf = {
1473 .fp_proto = FIB_PROTOCOL_IP6,
1475 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1476 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1479 const ip46_address_t nbr1 = {
1480 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1481 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1483 const ip46_address_t nbr2 = {
1484 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1485 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000003),
1488 return (mfib_test_i(FIB_PROTOCOL_IP6,
1502 mfib_test_rr_i (fib_protocol_t FPROTO,
1505 const mfib_prefix_t *pfx_cover,
1506 const mfib_prefix_t *pfx_host1,
1507 const mfib_prefix_t *pfx_host2)
1509 fib_node_index_t mfei_cover, mfei_host1, mfei_host2, ai_1, ai_2;
1510 u32 fib_index, n_entries, n_itfs, n_reps, n_pls;
1515 n_entries = pool_elts(mfib_entry_pool);
1516 n_itfs = pool_elts(mfib_itf_pool);
1517 n_reps = pool_elts(replicate_pool);
1518 n_pls = fib_path_list_pool_size();
1522 ai_1 = adj_mcast_add_or_lock(FPROTO,
1524 tm->hw[1]->sw_if_index);
1525 ai_2 = adj_mcast_add_or_lock(FPROTO,
1527 tm->hw[2]->sw_if_index);
1529 fib_route_path_t path_via_if0 = {
1530 .frp_proto = DPROTO,
1531 .frp_addr = zero_addr,
1532 .frp_sw_if_index = tm->hw[0]->sw_if_index,
1533 .frp_fib_index = ~0,
1537 fib_route_path_t path_via_if1 = {
1538 .frp_proto = DPROTO,
1539 .frp_addr = zero_addr,
1540 .frp_sw_if_index = tm->hw[1]->sw_if_index,
1541 .frp_fib_index = ~0,
1545 fib_route_path_t path_via_if2 = {
1546 .frp_proto = DPROTO,
1547 .frp_addr = zero_addr,
1548 .frp_sw_if_index = tm->hw[2]->sw_if_index,
1549 .frp_fib_index = ~0,
1553 fib_route_path_t path_for_us = {
1554 .frp_proto = DPROTO,
1555 .frp_addr = zero_addr,
1556 .frp_sw_if_index = 0xffffffff,
1557 .frp_fib_index = ~0,
1559 .frp_flags = FIB_ROUTE_PATH_LOCAL,
1563 * with only the default in place, recusre thru the /32
1565 mfei_host1 = mfib_table_entry_special_add(fib_index, pfx_host1,
1567 MFIB_ENTRY_FLAG_NONE,
1570 * expect its forwarding to match the cover's
1572 MFIB_TEST(!mfib_test_entry(mfei_host1,
1573 MFIB_ENTRY_FLAG_DROP,
1575 "%U no replications OK",
1576 format_mfib_prefix, pfx_host1);
1579 * Insert the less specific /28
1581 mfib_table_entry_path_update(fib_index,
1585 MFIB_ITF_FLAG_FORWARD);
1587 mfei_cover = mfib_table_lookup_exact_match(fib_index, pfx_cover);
1589 MFIB_TEST(!mfib_test_entry(mfei_cover,
1590 MFIB_ENTRY_FLAG_NONE,
1592 DPO_ADJACENCY_MCAST, ai_1),
1594 format_mfib_prefix, pfx_cover);
1597 * expect the /32 forwarding to match the new cover's
1599 MFIB_TEST(!mfib_test_entry(mfei_host1,
1600 MFIB_ENTRY_FLAG_NONE,
1602 DPO_ADJACENCY_MCAST, ai_1),
1604 format_mfib_prefix, pfx_host1);
1607 * add another path to the cover
1609 mfib_table_entry_path_update(fib_index,
1613 MFIB_ITF_FLAG_FORWARD);
1616 * expect the /32 and /28 to be via both boths
1618 MFIB_TEST(!mfib_test_entry(mfei_cover,
1619 MFIB_ENTRY_FLAG_NONE,
1621 DPO_ADJACENCY_MCAST, ai_1,
1622 DPO_ADJACENCY_MCAST, ai_2),
1624 format_mfib_prefix, pfx_cover);
1625 MFIB_TEST(!mfib_test_entry(mfei_host1,
1626 MFIB_ENTRY_FLAG_NONE,
1628 DPO_ADJACENCY_MCAST, ai_1,
1629 DPO_ADJACENCY_MCAST, ai_2),
1631 format_mfib_prefix, pfx_host1);
1634 * and the other host whilst all is ready
1636 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1638 MFIB_ENTRY_FLAG_NONE,
1640 MFIB_TEST(!mfib_test_entry(mfei_host2,
1641 MFIB_ENTRY_FLAG_NONE,
1643 DPO_ADJACENCY_MCAST, ai_1,
1644 DPO_ADJACENCY_MCAST, ai_2),
1646 format_mfib_prefix, pfx_host2);
1649 * repaet multiple time to simulate multiple recursve children
1651 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1653 MFIB_ENTRY_FLAG_NONE,
1655 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1657 MFIB_ENTRY_FLAG_NONE,
1659 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1661 MFIB_ENTRY_FLAG_NONE,
1665 * add an accepting path to the cover
1667 mfib_table_entry_path_update(fib_index,
1671 MFIB_ITF_FLAG_ACCEPT);
1674 * expect the /32 and /28 to be via both boths
1676 MFIB_TEST(!mfib_test_entry(mfei_cover,
1677 MFIB_ENTRY_FLAG_NONE,
1679 DPO_ADJACENCY_MCAST, ai_1,
1680 DPO_ADJACENCY_MCAST, ai_2),
1682 format_mfib_prefix, pfx_cover);
1683 MFIB_TEST(!mfib_test_entry(mfei_host1,
1684 MFIB_ENTRY_FLAG_NONE,
1686 DPO_ADJACENCY_MCAST, ai_1,
1687 DPO_ADJACENCY_MCAST, ai_2),
1689 format_mfib_prefix, pfx_cover);
1690 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[0]->sw_if_index,
1691 MFIB_ITF_FLAG_ACCEPT));
1692 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[0]->sw_if_index,
1693 MFIB_ITF_FLAG_ACCEPT));
1694 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[1]->sw_if_index,
1695 MFIB_ITF_FLAG_FORWARD));
1696 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[1]->sw_if_index,
1697 MFIB_ITF_FLAG_FORWARD));
1698 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[2]->sw_if_index,
1699 MFIB_ITF_FLAG_FORWARD));
1700 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[2]->sw_if_index,
1701 MFIB_ITF_FLAG_FORWARD));
1704 * add a for-us path to the cover
1706 mfib_table_entry_path_update(fib_index,
1710 MFIB_ITF_FLAG_FORWARD);
1713 * expect the /32 and /28 to be via all three paths
1715 MFIB_TEST(!mfib_test_entry(mfei_cover,
1716 MFIB_ENTRY_FLAG_NONE,
1718 DPO_ADJACENCY_MCAST, ai_1,
1719 DPO_ADJACENCY_MCAST, ai_2,
1722 format_mfib_prefix, pfx_cover);
1723 MFIB_TEST(!mfib_test_entry(mfei_host1,
1724 MFIB_ENTRY_FLAG_NONE,
1726 DPO_ADJACENCY_MCAST, ai_1,
1727 DPO_ADJACENCY_MCAST, ai_2,
1730 format_mfib_prefix, pfx_cover);
1733 * get the forwarding chain from the RR prefix
1736 dpo_id_t dpo = DPO_INVALID;
1738 mfib_entry_contribute_forwarding(
1740 mfib_forw_chain_type_from_dpo_proto(DPROTO),
1741 MFIB_ENTRY_FWD_FLAG_NONE,
1744 rep = replicate_get(dpo.dpoi_index);
1745 MFIB_TEST((3 == rep->rep_n_buckets),
1746 "%U replicate 3 buckets",
1747 format_mfib_prefix, pfx_host1);
1750 * get the forwarding chain from the RR prefix without local paths
1752 mfib_entry_contribute_forwarding(
1754 mfib_forw_chain_type_from_dpo_proto(DPROTO),
1755 MFIB_ENTRY_FWD_FLAG_NO_LOCAL,
1758 rep = replicate_get(dpo.dpoi_index);
1759 MFIB_TEST((2 == rep->rep_n_buckets),
1760 "%U no-local replicate 2 buckets",
1761 format_mfib_prefix, pfx_host1);
1766 * delete the cover, expect the /32 to be via the default
1768 mfib_table_entry_delete(fib_index, pfx_cover, MFIB_SOURCE_API);
1769 MFIB_TEST(!mfib_test_entry(mfei_host1,
1770 MFIB_ENTRY_FLAG_DROP,
1772 "%U no replications OK",
1773 format_mfib_prefix, pfx_host1);
1776 * source the /32 with its own path
1778 mfib_table_entry_path_update(fib_index,
1782 MFIB_ITF_FLAG_FORWARD);
1783 MFIB_TEST(!mfib_test_entry(mfei_host1,
1784 MFIB_ENTRY_FLAG_NONE,
1786 DPO_ADJACENCY_MCAST, ai_2),
1788 format_mfib_prefix, pfx_host1);
1791 * remove host2 - as many times as it was added
1793 mfib_table_entry_delete(fib_index, pfx_host2,
1795 mfib_table_entry_delete(fib_index, pfx_host2,
1797 mfib_table_entry_delete(fib_index, pfx_host2,
1799 mfib_table_entry_delete(fib_index, pfx_host2,
1804 * remove the RR source with paths present
1806 mfib_table_entry_delete(fib_index, pfx_host1,
1810 * add the RR back then remove the path and RR
1812 mfib_table_entry_path_update(fib_index,
1816 MFIB_ITF_FLAG_FORWARD);
1817 MFIB_TEST(!mfib_test_entry(mfei_host1,
1818 MFIB_ENTRY_FLAG_NONE,
1820 DPO_ADJACENCY_MCAST, ai_2),
1822 format_mfib_prefix, pfx_cover);
1824 mfib_table_entry_delete(fib_index, pfx_host1,
1826 mfib_table_entry_delete(fib_index, pfx_host1,
1830 * test we've leaked no resources
1834 MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
1835 MFIB_TEST(n_pls == fib_path_list_pool_size(), "%d=%d path-lists",
1836 n_pls, fib_path_list_pool_size());
1837 MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
1838 n_reps, pool_elts(replicate_pool));
1839 MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
1840 " No more entries %d!=%d",
1841 n_entries, pool_elts(mfib_entry_pool));
1842 MFIB_TEST(n_itfs == pool_elts(mfib_itf_pool),
1843 " No more Interfaces %d!=%d",
1844 n_itfs, pool_elts(mfib_itf_pool));
1849 mfib_test_rr_v4 (void)
1852 * 2 length of prefix to play with
1854 const mfib_prefix_t pfx_host1 = {
1856 .fp_proto = FIB_PROTOCOL_IP4,
1858 .ip4.as_u32 = clib_host_to_net_u32(0xe0001011),
1861 const mfib_prefix_t pfx_host2 = {
1863 .fp_proto = FIB_PROTOCOL_IP4,
1865 .ip4.as_u32 = clib_host_to_net_u32(0xe0001011),
1868 .ip4.as_u32 = clib_host_to_net_u32(0x10101010),
1871 const mfib_prefix_t pfx_cover = {
1873 .fp_proto = FIB_PROTOCOL_IP4,
1875 .ip4.as_u32 = clib_host_to_net_u32(0xe0001010),
1879 return (mfib_test_rr_i(FIB_PROTOCOL_IP4,
1888 mfib_test_rr_v6 (void)
1891 * 2 length of prefix to play with
1893 const mfib_prefix_t pfx_host1 = {
1895 .fp_proto = FIB_PROTOCOL_IP6,
1897 .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
1898 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1901 const mfib_prefix_t pfx_host2 = {
1903 .fp_proto = FIB_PROTOCOL_IP6,
1905 .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
1906 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1909 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1910 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1913 const mfib_prefix_t pfx_cover = {
1915 .fp_proto = FIB_PROTOCOL_IP6,
1917 .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
1918 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000000),
1922 return (mfib_test_rr_i(FIB_PROTOCOL_IP6,
1930 static clib_error_t *
1931 mfib_test (vlib_main_t * vm,
1932 unformat_input_t * input,
1933 vlib_cli_command_t * cmd_arg)
1937 res += mfib_test_mk_intf(4);
1938 res += mfib_test_rr_v4();
1942 return clib_error_return(0, "MFIB RR V4 Unit Test Failed");
1945 res += mfib_test_rr_v6();
1949 return clib_error_return(0, "MFIB RR V6 Unit Test Failed");
1952 res += mfib_test_v4();
1956 return clib_error_return(0, "MFIB V4 Unit Test Failed");
1959 res += mfib_test_v6();
1963 return clib_error_return(0, "MFIB V6 Unit Test Failed");
1969 VLIB_CLI_COMMAND (test_fib_command, static) = {
1970 .path = "test mfib",
1971 .short_help = "mfib unit tests - DO NOT RUN ON A LIVE SYSTEM",
1972 .function = mfib_test,
1976 mfib_test_init (vlib_main_t *vm)
1981 VLIB_INIT_FUNCTION (mfib_test_init);