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 placeholder_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 = placeholder_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 ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
143 ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
145 ip4_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
146 ip6_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
148 error = vnet_sw_interface_set_flags(vnet_get_main(),
149 tm->hw[i]->sw_if_index,
150 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
151 MFIB_TEST((NULL == error), "UP interface %d", i);
154 * re-eval after the inevitable realloc
156 for (i = 0; i < ninterfaces; i++)
158 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
159 tm->hw_if_indicies[i]);
165 #define MFIB_TEST_REP(_cond, _comment, _args...) \
167 if (MFIB_TEST_I(_cond, _comment, ##_args)) { \
173 mfib_test_validate_rep_v (const replicate_t *rep,
184 MFIB_TEST_REP((n_buckets == rep->rep_n_buckets),
185 "n_buckets = %d", rep->rep_n_buckets);
187 for (bucket = 0; bucket < n_buckets; bucket++)
189 dt = va_arg(*ap, int); // type promotion
190 ai = va_arg(*ap, adj_index_t);
191 dpo = replicate_get_bucket_i(rep, bucket);
193 MFIB_TEST_REP((dt == dpo->dpoi_type),
194 "bucket %d stacks on %U",
196 format_dpo_type, dpo->dpoi_type);
198 if (DPO_RECEIVE != dt)
200 MFIB_TEST_REP((ai == dpo->dpoi_index),
201 "bucket %d [exp:%d] stacks on %U",
203 format_dpo_id, dpo, 0);
210 mfib_test_entry (fib_node_index_t fei,
211 mfib_entry_flags_t eflags,
215 const mfib_prefix_t *pfx;
216 const mfib_entry_t *mfe;
217 const replicate_t *rep;
223 mfe = mfib_entry_get(fei);
224 pfx = mfib_entry_get_prefix(fei);
226 MFIB_TEST_REP((eflags == mfe->mfe_flags),
227 "%U has %U expect %U",
228 format_mfib_prefix, pfx,
229 format_mfib_entry_flags, mfe->mfe_flags,
230 format_mfib_entry_flags, eflags);
234 MFIB_TEST_REP((DPO_DROP == mfe->mfe_rep.dpoi_type),
236 format_mfib_prefix, pfx,
237 format_dpo_id, &mfe->mfe_rep, 0);
241 dpo_id_t tmp = DPO_INVALID;
243 mfib_entry_contribute_forwarding(
245 mfib_forw_chain_type_from_fib_proto(pfx->fp_proto),
246 MFIB_ENTRY_FWD_FLAG_NONE,
248 rep = replicate_get(tmp.dpoi_index);
250 MFIB_TEST_REP((DPO_REPLICATE == tmp.dpoi_type),
252 format_mfib_prefix, pfx,
253 format_dpo_type, tmp.dpoi_type);
255 va_start(ap, n_buckets);
256 res = mfib_test_validate_rep_v(rep, n_buckets, &ap);
267 mfib_test_entry_itf (fib_node_index_t fei,
269 mfib_itf_flags_t flags)
271 const mfib_prefix_t *pfx;
272 const mfib_entry_t *mfe;
273 const mfib_itf_t *mfi;
277 mfe = mfib_entry_get(fei);
278 mfi = mfib_entry_get_itf(mfe, sw_if_index);
279 pfx = mfib_entry_get_prefix(fei);
281 MFIB_TEST_REP((NULL != mfi),
282 "%U has interface %d",
283 format_mfib_prefix, pfx, sw_if_index);
285 MFIB_TEST_REP((flags == mfi->mfi_flags),
286 "%U interface %d has flags %U expect %U",
287 format_mfib_prefix, pfx, sw_if_index,
288 format_mfib_itf_flags, flags,
289 format_mfib_itf_flags, mfi->mfi_flags);
295 mfib_test_entry_no_itf (fib_node_index_t fei,
298 const mfib_prefix_t *pfx;
299 const mfib_entry_t *mfe;
300 const mfib_itf_t *mfi;
304 mfe = mfib_entry_get(fei);
305 mfi = mfib_entry_get_itf(mfe, sw_if_index);
306 pfx = mfib_entry_get_prefix(fei);
308 MFIB_TEST_REP((NULL == mfi),
309 "%U has no interface %d",
310 format_mfib_prefix, pfx, sw_if_index);
316 mfib_test_i (fib_protocol_t PROTO,
318 const mfib_prefix_t *pfx_no_forward,
319 const mfib_prefix_t *pfx_s_g,
320 const mfib_prefix_t *pfx_star_g_1,
321 const mfib_prefix_t *pfx_star_g_2,
322 const mfib_prefix_t *pfx_star_g_3,
323 const mfib_prefix_t *pfx_star_g_slash_m,
324 const fib_prefix_t *pfx_itf,
325 const ip46_address_t *addr_nbr1,
326 const ip46_address_t *addr_nbr2)
328 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;
329 u32 fib_index, n_entries, n_itfs, n_reps, n_pls;
330 fib_node_index_t ai_1, ai_2, ai_3, ai_nbr1, ai_nbr2;
334 mfib_prefix_t all_1s;
335 clib_memset(&all_1s, 0xfd, sizeof(all_1s));
338 n_entries = pool_elts(mfib_entry_pool);
339 n_itfs = pool_elts(mfib_itf_pool);
340 n_reps = pool_elts(replicate_pool);
341 n_pls = fib_path_list_pool_size();
344 ai_1 = adj_mcast_add_or_lock(PROTO,
346 tm->hw[1]->sw_if_index);
347 ai_2 = adj_mcast_add_or_lock(PROTO,
349 tm->hw[2]->sw_if_index);
350 ai_3 = adj_mcast_add_or_lock(PROTO,
352 tm->hw[3]->sw_if_index);
353 ai_nbr1 = adj_nbr_add_or_lock(PROTO,
356 tm->hw[0]->sw_if_index);
357 ai_nbr2 = adj_nbr_add_or_lock(PROTO,
360 tm->hw[0]->sw_if_index);
362 MFIB_TEST(3 == adj_mcast_db_size(), "3 MCAST adjs");
364 /* Find or create FIB table 11 */
365 fib_index = mfib_table_find_or_create_and_lock(PROTO, 11, MFIB_SOURCE_API);
367 fib_table_entry_update_one_path(0,
369 FIB_SOURCE_INTERFACE,
370 (FIB_ENTRY_FLAG_CONNECTED |
371 FIB_ENTRY_FLAG_ATTACHED),
374 tm->hw[0]->sw_if_index,
375 ~0, // invalid fib index
378 FIB_ROUTE_PATH_FLAG_NONE);
380 mfib_prefix_t pfx_dft = {
384 mfei_dflt = mfib_table_lookup_exact_match(fib_index, &pfx_dft);
385 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
386 MFIB_TEST(!mfib_test_entry(mfei_dflt,
387 MFIB_ENTRY_FLAG_DROP,
389 "(*,*) no replcaitions");
391 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
392 MFIB_TEST(!mfib_test_entry(mfei_dflt,
393 MFIB_ENTRY_FLAG_DROP,
395 "(*,*) no replcaitions");
398 fib_route_path_t path_via_if0 = {
399 .frp_proto = fib_proto_to_dpo(PROTO),
400 .frp_addr = zero_addr,
401 .frp_sw_if_index = tm->hw[0]->sw_if_index,
405 .frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT,
408 mfib_table_entry_path_update(fib_index,
413 mfei_no_f = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
414 MFIB_TEST(!mfib_test_entry(mfei_no_f,
415 MFIB_ENTRY_FLAG_NONE,
417 "%U no replcaitions",
418 format_mfib_prefix, pfx_no_forward);
419 MFIB_TEST(!mfib_test_entry_itf(mfei_no_f, tm->hw[0]->sw_if_index,
420 MFIB_ITF_FLAG_ACCEPT),
421 "%U interface not accepting",
422 format_mfib_prefix, pfx_no_forward);
424 fib_route_path_t path_via_if1 = {
425 .frp_proto = fib_proto_to_dpo(PROTO),
426 .frp_addr = zero_addr,
427 .frp_sw_if_index = tm->hw[1]->sw_if_index,
431 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
433 fib_route_path_t path_via_if2 = {
434 .frp_proto = fib_proto_to_dpo(PROTO),
435 .frp_addr = zero_addr,
436 .frp_sw_if_index = tm->hw[2]->sw_if_index,
440 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
442 fib_route_path_t path_via_if3 = {
443 .frp_proto = fib_proto_to_dpo(PROTO),
444 .frp_addr = zero_addr,
445 .frp_sw_if_index = tm->hw[3]->sw_if_index,
449 .frp_mitf_flags = (MFIB_ITF_FLAG_FORWARD |
450 MFIB_ITF_FLAG_NEGATE_SIGNAL),
452 fib_route_path_t *two_paths = NULL;
453 vec_add1(two_paths, path_via_if2);
454 vec_add1(two_paths, path_via_if3);
457 * An (S,G) with 1 accepting and 3 forwarding paths
459 mfib_table_entry_path_update(fib_index,
463 mfib_table_entry_path_update(fib_index,
467 mfib_table_entry_paths_update(fib_index,
472 mfei_s_g = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
474 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_s_g,
476 format_mfib_prefix, pfx_s_g);
477 MFIB_TEST(!mfib_test_entry(mfei_s_g,
478 MFIB_ENTRY_FLAG_NONE,
480 DPO_ADJACENCY_MCAST, ai_1,
481 DPO_ADJACENCY_MCAST, ai_2,
482 DPO_ADJACENCY_MCAST, ai_3),
484 format_mfib_prefix, pfx_s_g);
485 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[0]->sw_if_index,
486 MFIB_ITF_FLAG_ACCEPT));
487 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[1]->sw_if_index,
488 MFIB_ITF_FLAG_FORWARD));
489 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[2]->sw_if_index,
490 MFIB_ITF_FLAG_FORWARD));
491 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[3]->sw_if_index,
492 (MFIB_ITF_FLAG_FORWARD |
493 MFIB_ITF_FLAG_NEGATE_SIGNAL)));
496 * A (*,G), which the same G as the (S,G).
497 * different paths. test our LPM.
499 mfei_g_1 = mfib_table_entry_path_update(fib_index,
503 mfib_table_entry_path_update(fib_index,
509 * test we find the *,G and S,G via LPM and exact matches
511 mfei = mfib_table_lookup_exact_match(fib_index,
513 MFIB_TEST(mfei == mfei_g_1,
514 "%U found via exact match",
515 format_mfib_prefix, pfx_star_g_1);
516 MFIB_TEST(!mfib_test_entry(mfei,
517 MFIB_ENTRY_FLAG_NONE,
519 DPO_ADJACENCY_MCAST, ai_1),
521 format_mfib_prefix, pfx_star_g_1);
523 mfei = mfib_table_lookup(fib_index,
525 MFIB_TEST(mfei == mfei_g_1,
526 "[e:%d a:%d] %U found via LP match",
528 format_mfib_prefix, pfx_star_g_1);
530 MFIB_TEST(!mfib_test_entry(mfei,
531 MFIB_ENTRY_FLAG_NONE,
533 DPO_ADJACENCY_MCAST, ai_1),
535 format_mfib_prefix, pfx_star_g_1);
537 mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
538 MFIB_TEST(mfei == mfei_s_g,
539 "%U found via exact match",
540 format_mfib_prefix, pfx_s_g);
542 MFIB_TEST(!mfib_test_entry(mfei,
543 MFIB_ENTRY_FLAG_NONE,
545 DPO_ADJACENCY_MCAST, ai_1,
546 DPO_ADJACENCY_MCAST, ai_2,
547 DPO_ADJACENCY_MCAST, ai_3),
549 format_mfib_prefix, pfx_s_g);
550 mfei = mfib_table_lookup(fib_index, pfx_s_g);
551 MFIB_TEST(mfei == mfei_s_g,
552 "%U found via LP match",
553 format_mfib_prefix, pfx_s_g);
555 MFIB_TEST(!mfib_test_entry(mfei,
556 MFIB_ENTRY_FLAG_NONE,
558 DPO_ADJACENCY_MCAST, ai_1,
559 DPO_ADJACENCY_MCAST, ai_2,
560 DPO_ADJACENCY_MCAST, ai_3),
562 format_mfib_prefix, pfx_s_g);
565 * A (*,G/m), which the same root G as the (*,G).
566 * different paths. test our LPM.
568 path_via_if2.frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT;
569 mfei_g_m = mfib_table_entry_path_update(fib_index,
573 mfib_table_entry_path_update(fib_index,
579 * test we find the (*,G/m), (*,G) and (S,G) via LPM and exact matches
581 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
582 MFIB_TEST((mfei_g_1 == mfei),
583 "%U found via DP LPM: %d",
584 format_mfib_prefix, pfx_star_g_1, mfei);
586 MFIB_TEST(!mfib_test_entry(mfei,
587 MFIB_ENTRY_FLAG_NONE,
589 DPO_ADJACENCY_MCAST, ai_1),
591 format_mfib_prefix, pfx_star_g_1);
593 mfei = mfib_table_lookup(fib_index, pfx_star_g_1);
595 MFIB_TEST(!mfib_test_entry(mfei,
596 MFIB_ENTRY_FLAG_NONE,
598 DPO_ADJACENCY_MCAST, ai_1),
600 format_mfib_prefix, pfx_star_g_1);
602 mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
604 MFIB_TEST(!mfib_test_entry(mfei,
605 MFIB_ENTRY_FLAG_NONE,
607 DPO_ADJACENCY_MCAST, ai_1,
608 DPO_ADJACENCY_MCAST, ai_2,
609 DPO_ADJACENCY_MCAST, ai_3),
611 format_mfib_prefix, pfx_s_g);
612 mfei = mfib_table_lookup(fib_index, pfx_s_g);
614 MFIB_TEST(!mfib_test_entry(mfei,
615 MFIB_ENTRY_FLAG_NONE,
617 DPO_ADJACENCY_MCAST, ai_1,
618 DPO_ADJACENCY_MCAST, ai_2,
619 DPO_ADJACENCY_MCAST, ai_3),
621 format_mfib_prefix, pfx_s_g);
623 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
624 MFIB_TEST(mfei = mfei_g_m,
625 "%U Found via exact match",
626 format_mfib_prefix, pfx_star_g_slash_m);
627 MFIB_TEST(!mfib_test_entry(mfei,
628 MFIB_ENTRY_FLAG_NONE,
630 DPO_ADJACENCY_MCAST, ai_3),
632 format_mfib_prefix, pfx_star_g_slash_m);
633 MFIB_TEST(mfei_g_m == mfib_table_lookup(fib_index, pfx_star_g_slash_m),
635 format_mfib_prefix, pfx_star_g_slash_m);
640 fib_route_path_t path_for_us = {
641 .frp_proto = fib_proto_to_dpo(PROTO),
642 .frp_addr = zero_addr,
643 .frp_sw_if_index = 0xffffffff,
646 .frp_flags = FIB_ROUTE_PATH_LOCAL,
647 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
650 mfei = mfib_table_entry_path_update(fib_index,
655 MFIB_TEST(!mfib_test_entry(mfei,
656 MFIB_ENTRY_FLAG_NONE,
658 DPO_ADJACENCY_MCAST, ai_1,
659 DPO_ADJACENCY_MCAST, ai_2,
660 DPO_ADJACENCY_MCAST, ai_3,
663 format_mfib_prefix, pfx_s_g);
666 * remove a for-us path
668 mfib_table_entry_path_remove(fib_index,
673 MFIB_TEST(!mfib_test_entry(mfei,
674 MFIB_ENTRY_FLAG_NONE,
676 DPO_ADJACENCY_MCAST, ai_1,
677 DPO_ADJACENCY_MCAST, ai_2,
678 DPO_ADJACENCY_MCAST, ai_3),
680 format_mfib_prefix, pfx_s_g);
683 * update an existing forwarding path to be only accepting
684 * - expect it to be removed from the replication set.
686 path_via_if3.frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT;
687 mfib_table_entry_path_update(fib_index,
692 MFIB_TEST(!mfib_test_entry(mfei,
693 MFIB_ENTRY_FLAG_NONE,
695 DPO_ADJACENCY_MCAST, ai_1,
696 DPO_ADJACENCY_MCAST, ai_2),
698 format_mfib_prefix, pfx_s_g);
699 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
700 MFIB_ITF_FLAG_ACCEPT));
701 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
702 MFIB_ITF_FLAG_FORWARD));
703 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
704 MFIB_ITF_FLAG_FORWARD));
705 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
706 MFIB_ITF_FLAG_ACCEPT));
708 * Make the path forwarding again
709 * - expect it to be added back to the replication set
711 path_via_if3.frp_mitf_flags = (MFIB_ITF_FLAG_FORWARD |
712 MFIB_ITF_FLAG_ACCEPT |
713 MFIB_ITF_FLAG_NEGATE_SIGNAL);
714 mfib_table_entry_path_update(fib_index,
719 mfei = mfib_table_lookup_exact_match(fib_index,
722 MFIB_TEST(!mfib_test_entry(mfei,
723 MFIB_ENTRY_FLAG_NONE,
725 DPO_ADJACENCY_MCAST, ai_1,
726 DPO_ADJACENCY_MCAST, ai_2,
727 DPO_ADJACENCY_MCAST, ai_3),
729 format_mfib_prefix, pfx_s_g);
730 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
731 MFIB_ITF_FLAG_ACCEPT));
732 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
733 MFIB_ITF_FLAG_FORWARD));
734 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
735 MFIB_ITF_FLAG_FORWARD));
736 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
737 (MFIB_ITF_FLAG_FORWARD |
738 MFIB_ITF_FLAG_ACCEPT |
739 MFIB_ITF_FLAG_NEGATE_SIGNAL)));
742 * update flags on the entry
744 mfib_table_entry_update(fib_index,
748 MFIB_ENTRY_FLAG_SIGNAL);
749 MFIB_TEST(!mfib_test_entry(mfei,
750 MFIB_ENTRY_FLAG_SIGNAL,
752 DPO_ADJACENCY_MCAST, ai_1,
753 DPO_ADJACENCY_MCAST, ai_2,
754 DPO_ADJACENCY_MCAST, ai_3),
756 format_mfib_prefix, pfx_s_g);
761 mfib_table_entry_path_remove(fib_index,
766 MFIB_TEST(!mfib_test_entry(mfei,
767 MFIB_ENTRY_FLAG_SIGNAL,
769 DPO_ADJACENCY_MCAST, ai_1,
770 DPO_ADJACENCY_MCAST, ai_2),
772 format_mfib_prefix, pfx_s_g);
773 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
774 MFIB_ITF_FLAG_ACCEPT));
775 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
776 MFIB_ITF_FLAG_FORWARD));
777 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
778 MFIB_ITF_FLAG_FORWARD));
779 MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
781 mfib_table_entry_path_remove(fib_index,
786 MFIB_TEST(!mfib_test_entry(mfei,
787 MFIB_ENTRY_FLAG_SIGNAL,
789 DPO_ADJACENCY_MCAST, ai_2),
791 format_mfib_prefix, pfx_s_g);
792 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
793 MFIB_ITF_FLAG_ACCEPT));
794 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
795 MFIB_ITF_FLAG_FORWARD));
796 MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
801 /* mfib_table_entry_path_remove(fib_index, */
803 /* MFIB_SOURCE_API, */
804 /* &path_via_if0); */
806 /* MFIB_TEST(!mfib_test_entry(mfei, */
807 /* MFIB_ENTRY_FLAG_SIGNAL, */
809 /* DPO_ADJACENCY_MCAST, ai_2), */
810 /* "%U replicate OK", */
811 /* format_mfib_prefix, pfx_s_g); */
812 /* MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index, */
813 /* MFIB_ITF_FLAG_FORWARD)); */
814 /* MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[0]->sw_if_index)); */
815 /* MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[1]->sw_if_index)); */
816 /* MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index)); */
819 * remove the last path and the accepting only interface,
820 * the entry still has flags so it remains
822 vec_reset_length(two_paths);
823 vec_add1(two_paths, path_via_if0);
824 vec_add1(two_paths, path_via_if2);
826 mfib_table_entry_paths_remove(fib_index,
831 MFIB_TEST(!mfib_test_entry(mfei,
832 MFIB_ENTRY_FLAG_SIGNAL,
834 "%U no replications",
835 format_mfib_prefix, pfx_s_g);
838 * update flags on the entry
840 mfib_table_entry_update(fib_index,
844 (MFIB_ENTRY_FLAG_SIGNAL |
845 MFIB_ENTRY_FLAG_CONNECTED));
846 MFIB_TEST(!mfib_test_entry(mfei,
847 (MFIB_ENTRY_FLAG_SIGNAL |
848 MFIB_ENTRY_FLAG_CONNECTED),
850 "%U no replications",
851 format_mfib_prefix, pfx_s_g);
854 * An entry with a NS interface
856 path_via_if0.frp_mitf_flags = (MFIB_ITF_FLAG_ACCEPT |
857 MFIB_ITF_FLAG_NEGATE_SIGNAL);
858 mfei_g_2 = mfib_table_entry_path_update(fib_index,
862 MFIB_TEST(!mfib_test_entry(mfei_g_2,
863 MFIB_ENTRY_FLAG_NONE,
865 "%U No replications",
866 format_mfib_prefix, pfx_star_g_2);
869 * Simulate a signal from the data-plane
875 mfe = mfib_entry_get(mfei_g_2);
876 mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
878 mfib_signal_push(mfe, mfi, NULL);
882 * An entry with a NS interface
884 path_via_if0.frp_mitf_flags = (MFIB_ITF_FLAG_ACCEPT |
885 MFIB_ITF_FLAG_NEGATE_SIGNAL);
886 mfei_g_3 = mfib_table_entry_path_update(fib_index,
890 MFIB_TEST(!mfib_test_entry(mfei_g_3,
891 MFIB_ENTRY_FLAG_NONE,
893 "%U No replications",
894 format_mfib_prefix, pfx_star_g_3);
897 * Simulate a signal from the data-plane
903 mfe = mfib_entry_get(mfei_g_3);
904 mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
906 mfib_signal_push(mfe, mfi, NULL);
909 if (FIB_PROTOCOL_IP6 == PROTO)
912 * All the entries are present. let's ensure we can find them all
913 * via exact and longest prefix matches.
916 * A source address we will never match
918 ip6_address_t src = {
919 .as_u64[0] = clib_host_to_net_u64(0x3001000000000000),
920 .as_u64[1] = clib_host_to_net_u64(0xffffffffffffffff),
926 MFIB_TEST((mfei_g_m == ip6_mfib_table_fwd_lookup(
927 ip6_mfib_get(fib_index),
929 &pfx_star_g_slash_m->fp_grp_addr.ip6)),
930 "%U found via DP LPM grp=%U",
931 format_mfib_prefix, pfx_star_g_slash_m,
932 format_ip6_address, &pfx_star_g_slash_m->fp_grp_addr.ip6);
934 ip6_address_t tmp = pfx_star_g_slash_m->fp_grp_addr.ip6;
935 tmp.as_u8[15] = 0xff;
937 MFIB_TEST((mfei_g_m == ip6_mfib_table_fwd_lookup(
938 ip6_mfib_get(fib_index),
939 &pfx_s_g->fp_src_addr.ip6,
941 "%U found via DP LPM grp=%U",
942 format_mfib_prefix, pfx_star_g_slash_m,
943 format_ip6_address, &tmp);
948 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
949 &pfx_s_g->fp_src_addr.ip6,
950 &pfx_s_g->fp_grp_addr.ip6);
951 MFIB_TEST((mfei_s_g == mfei),
952 "%U found via DP LPM: %d",
953 format_mfib_prefix, pfx_s_g, mfei);
958 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
960 &pfx_star_g_1->fp_grp_addr.ip6);
961 MFIB_TEST((mfei_g_1 == mfei),
962 "%U found via DP LPM: %d",
963 format_mfib_prefix, pfx_star_g_1, mfei);
964 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
966 &pfx_star_g_2->fp_grp_addr.ip6);
967 MFIB_TEST((mfei_g_2 == mfei),
968 "%U found via DP LPM: %d",
969 format_mfib_prefix, pfx_star_g_2, mfei);
970 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
972 &pfx_star_g_3->fp_grp_addr.ip6);
973 MFIB_TEST((mfei_g_3 == mfei),
974 "%U found via DP LPM: %d",
975 format_mfib_prefix, pfx_star_g_3, mfei);
979 * remove flags on the entry. This is the last of the
980 * state associated with the entry, so now it goes.
982 mfib_table_entry_update(fib_index,
986 MFIB_ENTRY_FLAG_NONE);
987 mfei = mfib_table_lookup_exact_match(fib_index,
989 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
991 format_mfib_prefix, pfx_s_g);
994 * remove the last path on the no forward entry - the last entry
996 mfib_table_entry_path_remove(fib_index,
1001 mfei = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
1002 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1004 format_mfib_prefix, pfx_no_forward);
1007 * hard delete the (*,232.1.1.1)
1009 mfib_table_entry_delete(fib_index,
1013 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
1014 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1016 format_mfib_prefix, pfx_star_g_1);
1018 * remove the entry whilst the signal is pending
1020 mfib_table_entry_delete(fib_index,
1024 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_2);
1025 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1027 format_mfib_prefix, pfx_star_g_2);
1028 mfib_table_entry_delete(fib_index,
1032 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_3);
1033 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1035 format_mfib_prefix, pfx_star_g_3);
1037 mfib_table_entry_delete(fib_index,
1041 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
1042 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1044 format_mfib_prefix, pfx_star_g_slash_m);
1047 * Entries with paths via unicast next-hops
1049 fib_route_path_t path_via_nbr1 = {
1050 .frp_proto = fib_proto_to_dpo(PROTO),
1051 .frp_addr = *addr_nbr1,
1052 .frp_sw_if_index = tm->hw[0]->sw_if_index,
1053 .frp_fib_index = ~0,
1056 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1058 fib_route_path_t path_via_nbr2 = {
1059 .frp_proto = fib_proto_to_dpo(PROTO),
1060 .frp_addr = *addr_nbr2,
1061 .frp_sw_if_index = tm->hw[0]->sw_if_index,
1062 .frp_fib_index = ~0,
1065 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1068 mfei_g_1 = mfib_table_entry_path_update(fib_index,
1072 mfei_g_1 = mfib_table_entry_path_update(fib_index,
1076 MFIB_TEST(!mfib_test_entry(mfei_g_1,
1077 MFIB_ENTRY_FLAG_NONE,
1079 DPO_ADJACENCY_INCOMPLETE, ai_nbr1,
1080 DPO_ADJACENCY_INCOMPLETE, ai_nbr2),
1082 format_mfib_prefix, pfx_star_g_1);
1083 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_g_1, tm->hw[0]->sw_if_index,
1084 MFIB_ITF_FLAG_FORWARD));
1086 mfib_table_entry_path_remove(fib_index,
1091 MFIB_TEST(!mfib_test_entry(mfei_g_1,
1092 MFIB_ENTRY_FLAG_NONE,
1094 DPO_ADJACENCY_INCOMPLETE, ai_nbr2),
1096 format_mfib_prefix, pfx_star_g_1);
1097 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_g_1, tm->hw[0]->sw_if_index,
1098 MFIB_ITF_FLAG_FORWARD));
1100 mfib_table_entry_path_remove(fib_index,
1104 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
1105 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1107 format_mfib_prefix, pfx_star_g_1);
1110 * Add a prefix as a special/exclusive route
1112 dpo_id_t td = DPO_INVALID;
1113 index_t repi = replicate_create(1, fib_proto_to_dpo(PROTO));
1115 dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_2);
1116 replicate_set_bucket(repi, 0, &td);
1118 mfei = mfib_table_entry_special_add(fib_index,
1121 MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF,
1123 MFIB_TEST(!mfib_test_entry(mfei,
1124 (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
1125 MFIB_ENTRY_FLAG_EXCLUSIVE),
1127 DPO_ADJACENCY_MCAST, ai_2),
1128 "%U exclusive replicate OK",
1129 format_mfib_prefix, pfx_star_g_3);
1132 * update a special/exclusive route
1134 index_t repi2 = replicate_create(1, fib_proto_to_dpo(PROTO));
1136 dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_1);
1137 replicate_set_bucket(repi2, 0, &td);
1139 mfib_entry_update(mfei,
1141 (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
1142 MFIB_ENTRY_FLAG_EXCLUSIVE),
1145 MFIB_TEST(!mfib_test_entry(mfei,
1146 (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
1147 MFIB_ENTRY_FLAG_EXCLUSIVE),
1149 DPO_ADJACENCY_MCAST, ai_1),
1150 "%U exclusive update replicate OK",
1151 format_mfib_prefix, pfx_star_g_3);
1153 mfib_table_entry_delete(fib_index,
1159 * A Multicast LSP. This a mLDP head-end
1161 fib_node_index_t ai_mpls_10_10_10_1, lfei;
1162 ip46_address_t nh_10_10_10_1 = {
1164 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
1167 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1170 tm->hw[0]->sw_if_index);
1172 fib_prefix_t pfx_3500 = {
1174 .fp_proto = FIB_PROTOCOL_MPLS,
1177 .fp_payload_proto = DPO_PROTO_IP4,
1179 fib_test_rep_bucket_t mc_0 = {
1180 .type = FT_REP_LABEL_O_ADJ,
1182 .adj = ai_mpls_10_10_10_1,
1187 fib_mpls_label_t *l3300 = NULL, fml3300 = {
1190 vec_add1(l3300, fml3300);
1193 * MPLS enable an interface so we get the MPLS table created
1195 mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL);
1196 mpls_sw_interface_enable_disable (&mpls_main, tm->hw[0]->sw_if_index, 1);
1198 lfei = fib_table_entry_update_one_path(0, // default MPLS Table
1201 FIB_ENTRY_FLAG_MULTICAST,
1204 tm->hw[0]->sw_if_index,
1205 ~0, // invalid fib index
1208 FIB_ROUTE_PATH_FLAG_NONE);
1209 MFIB_TEST(!fib_test_validate_entry(lfei,
1210 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
1213 "3500 via replicate over 10.10.10.1");
1216 * An (S,G) that resolves via the mLDP head-end
1218 fib_route_path_t path_via_mldp = {
1219 .frp_proto = DPO_PROTO_MPLS,
1220 .frp_local_label = pfx_3500.fp_label,
1221 .frp_eos = MPLS_EOS,
1222 .frp_sw_if_index = 0xffffffff,
1225 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
1226 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1228 dpo_id_t mldp_dpo = DPO_INVALID;
1230 fib_entry_contribute_forwarding(lfei,
1231 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
1234 mfei = mfib_table_entry_path_update(fib_index,
1239 MFIB_TEST(!mfib_test_entry(mfei,
1240 MFIB_ENTRY_FLAG_NONE,
1242 DPO_REPLICATE, mldp_dpo.dpoi_index),
1243 "%U over-mLDP replicate OK",
1244 format_mfib_prefix, pfx_s_g);
1247 * add a for-us path. this tests two types of non-attached paths on one entry
1249 mfei = mfib_table_entry_path_update(fib_index,
1253 MFIB_TEST(!mfib_test_entry(mfei,
1254 MFIB_ENTRY_FLAG_NONE,
1256 DPO_REPLICATE, mldp_dpo.dpoi_index,
1258 "%U mLDP+for-us replicate OK",
1259 format_mfib_prefix, pfx_s_g);
1261 mfib_table_entry_delete(fib_index,
1264 fib_table_entry_delete(0,
1267 dpo_reset(&mldp_dpo);
1270 * Unlock the table - it's the last lock so should be gone thereafter
1272 MFIB_TEST(((PROTO == FIB_PROTOCOL_IP4 ? 3 : 5) ==
1273 mfib_table_get_n_routes(fib_index, PROTO)),
1274 "1 = %d route left in the FIB",
1275 mfib_table_get_n_routes(fib_index, PROTO));
1277 mfib_table_unlock(fib_index, PROTO, MFIB_SOURCE_API);
1279 MFIB_TEST((FIB_NODE_INDEX_INVALID ==
1280 mfib_table_find(PROTO, fib_index)),
1281 "MFIB table %d gone", fib_index);
1286 adj_unlock(ai_nbr1);
1287 adj_unlock(ai_nbr2);
1290 * MPLS disable the interface
1292 mpls_sw_interface_enable_disable (&mpls_main, tm->hw[0]->sw_if_index, 0);
1293 mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
1296 * remove the connected
1298 fib_table_entry_delete(0, pfx_itf, FIB_SOURCE_INTERFACE);
1301 * test we've leaked no resources
1303 MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
1304 MFIB_TEST(n_pls == fib_path_list_pool_size(), "%d=%d path-lists",
1305 n_pls, fib_path_list_pool_size());
1306 MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
1307 n_reps, pool_elts(replicate_pool));
1308 MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
1309 " No more entries %d!=%d",
1310 n_entries, pool_elts(mfib_entry_pool));
1311 MFIB_TEST(n_itfs == pool_elts(mfib_itf_pool),
1312 " No more Interfaces %d!=%d",
1313 n_itfs, pool_elts(mfib_itf_pool));
1314 vec_free(two_paths);
1322 const mfib_prefix_t pfx_224_s_8 = {
1324 .fp_proto = FIB_PROTOCOL_IP4,
1326 .ip4.as_u32 = clib_host_to_net_u32(0xe0000000),
1329 const mfib_prefix_t pfx_1_1_1_1_c_239_1_1_1 = {
1331 .fp_proto = FIB_PROTOCOL_IP4,
1333 .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1336 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1339 const mfib_prefix_t pfx_239_1_1_1 = {
1341 .fp_proto = FIB_PROTOCOL_IP4,
1343 .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1349 const mfib_prefix_t pfx_239_1_1_2 = {
1351 .fp_proto = FIB_PROTOCOL_IP4,
1353 .ip4.as_u32 = clib_host_to_net_u32(0xef010102),
1359 const mfib_prefix_t pfx_239_1_1_3 = {
1361 .fp_proto = FIB_PROTOCOL_IP4,
1363 .ip4.as_u32 = clib_host_to_net_u32(0xef010103),
1369 const mfib_prefix_t pfx_239 = {
1371 .fp_proto = FIB_PROTOCOL_IP4,
1373 .ip4.as_u32 = clib_host_to_net_u32(0xef000000),
1379 const fib_prefix_t pfx_itf = {
1381 .fp_proto = FIB_PROTOCOL_IP4,
1383 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
1386 const ip46_address_t nbr1 = {
1387 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0b),
1389 const ip46_address_t nbr2 = {
1390 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0c),
1392 return (mfib_test_i(FIB_PROTOCOL_IP4,
1395 &pfx_1_1_1_1_c_239_1_1_1,
1408 const mfib_prefix_t pfx_ffd_s_12 = {
1410 .fp_proto = FIB_PROTOCOL_IP6,
1412 .ip6.as_u64[0] = clib_host_to_net_u64(0xffd0000000000000),
1415 const mfib_prefix_t pfx_2001_1_c_ff_1 = {
1417 .fp_proto = FIB_PROTOCOL_IP6,
1419 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1420 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1423 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1424 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1427 const mfib_prefix_t pfx_ff_1 = {
1429 .fp_proto = FIB_PROTOCOL_IP6,
1431 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1432 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1435 const mfib_prefix_t pfx_ff_2 = {
1437 .fp_proto = FIB_PROTOCOL_IP6,
1439 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1440 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1443 const mfib_prefix_t pfx_ff_3 = {
1445 * this is the ALL DHCP routers address
1448 .fp_proto = FIB_PROTOCOL_IP6,
1450 .ip6.as_u64[0] = clib_host_to_net_u64(0xff02000100000000),
1451 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1454 const mfib_prefix_t pfx_ff = {
1456 .fp_proto = FIB_PROTOCOL_IP6,
1458 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1459 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000000),
1462 const fib_prefix_t pfx_itf = {
1464 .fp_proto = FIB_PROTOCOL_IP6,
1466 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1467 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1470 const ip46_address_t nbr1 = {
1471 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1472 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1474 const ip46_address_t nbr2 = {
1475 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1476 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000003),
1479 return (mfib_test_i(FIB_PROTOCOL_IP6,
1493 mfib_test_rr_i (fib_protocol_t FPROTO,
1496 const mfib_prefix_t *pfx_cover,
1497 const mfib_prefix_t *pfx_host1,
1498 const mfib_prefix_t *pfx_host2)
1500 fib_node_index_t mfei_cover, mfei_host1, mfei_host2, ai_1, ai_2;
1501 u32 fib_index, n_entries, n_itfs, n_reps, n_pls;
1506 n_entries = pool_elts(mfib_entry_pool);
1507 n_itfs = pool_elts(mfib_itf_pool);
1508 n_reps = pool_elts(replicate_pool);
1509 n_pls = fib_path_list_pool_size();
1513 ai_1 = adj_mcast_add_or_lock(FPROTO,
1515 tm->hw[1]->sw_if_index);
1516 ai_2 = adj_mcast_add_or_lock(FPROTO,
1518 tm->hw[2]->sw_if_index);
1520 fib_route_path_t path_via_if0 = {
1521 .frp_proto = DPROTO,
1522 .frp_addr = zero_addr,
1523 .frp_sw_if_index = tm->hw[0]->sw_if_index,
1524 .frp_fib_index = ~0,
1527 .frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT,
1529 fib_route_path_t path_via_if1 = {
1530 .frp_proto = DPROTO,
1531 .frp_addr = zero_addr,
1532 .frp_sw_if_index = tm->hw[1]->sw_if_index,
1533 .frp_fib_index = ~0,
1536 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1538 fib_route_path_t path_via_if2 = {
1539 .frp_proto = DPROTO,
1540 .frp_addr = zero_addr,
1541 .frp_sw_if_index = tm->hw[2]->sw_if_index,
1542 .frp_fib_index = ~0,
1545 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1547 fib_route_path_t path_for_us = {
1548 .frp_proto = DPROTO,
1549 .frp_addr = zero_addr,
1550 .frp_sw_if_index = 0xffffffff,
1551 .frp_fib_index = ~0,
1553 .frp_flags = FIB_ROUTE_PATH_LOCAL,
1554 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1558 * with only the default in place, recusre thru the /32
1560 mfei_host1 = mfib_table_entry_special_add(fib_index, pfx_host1,
1562 MFIB_ENTRY_FLAG_NONE,
1565 * expect its forwarding to match the cover's
1567 MFIB_TEST(!mfib_test_entry(mfei_host1,
1568 MFIB_ENTRY_FLAG_DROP,
1570 "%U no replications OK",
1571 format_mfib_prefix, pfx_host1);
1574 * Insert the less specific /28
1576 mfib_table_entry_path_update(fib_index,
1581 mfei_cover = mfib_table_lookup_exact_match(fib_index, pfx_cover);
1583 MFIB_TEST(!mfib_test_entry(mfei_cover,
1584 MFIB_ENTRY_FLAG_NONE,
1586 DPO_ADJACENCY_MCAST, ai_1),
1588 format_mfib_prefix, pfx_cover);
1591 * expect the /32 forwarding to match the new cover's
1593 MFIB_TEST(!mfib_test_entry(mfei_host1,
1594 MFIB_ENTRY_FLAG_NONE,
1596 DPO_ADJACENCY_MCAST, ai_1),
1598 format_mfib_prefix, pfx_host1);
1601 * add another path to the cover
1603 mfib_table_entry_path_update(fib_index,
1609 * expect the /32 and /28 to be via both boths
1611 MFIB_TEST(!mfib_test_entry(mfei_cover,
1612 MFIB_ENTRY_FLAG_NONE,
1614 DPO_ADJACENCY_MCAST, ai_1,
1615 DPO_ADJACENCY_MCAST, ai_2),
1617 format_mfib_prefix, pfx_cover);
1618 MFIB_TEST(!mfib_test_entry(mfei_host1,
1619 MFIB_ENTRY_FLAG_NONE,
1621 DPO_ADJACENCY_MCAST, ai_1,
1622 DPO_ADJACENCY_MCAST, ai_2),
1624 format_mfib_prefix, pfx_host1);
1627 * and the other host whilst all is ready
1629 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1631 MFIB_ENTRY_FLAG_NONE,
1633 MFIB_TEST(!mfib_test_entry(mfei_host2,
1634 MFIB_ENTRY_FLAG_NONE,
1636 DPO_ADJACENCY_MCAST, ai_1,
1637 DPO_ADJACENCY_MCAST, ai_2),
1639 format_mfib_prefix, pfx_host2);
1642 * repaet multiple time to simulate multiple recursve children
1644 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1646 MFIB_ENTRY_FLAG_NONE,
1648 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1650 MFIB_ENTRY_FLAG_NONE,
1652 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1654 MFIB_ENTRY_FLAG_NONE,
1658 * add an accepting path to the cover
1660 mfib_table_entry_path_update(fib_index,
1666 * expect the /32 and /28 to be via both boths
1668 MFIB_TEST(!mfib_test_entry(mfei_cover,
1669 MFIB_ENTRY_FLAG_NONE,
1671 DPO_ADJACENCY_MCAST, ai_1,
1672 DPO_ADJACENCY_MCAST, ai_2),
1674 format_mfib_prefix, pfx_cover);
1675 MFIB_TEST(!mfib_test_entry(mfei_host1,
1676 MFIB_ENTRY_FLAG_NONE,
1678 DPO_ADJACENCY_MCAST, ai_1,
1679 DPO_ADJACENCY_MCAST, ai_2),
1681 format_mfib_prefix, pfx_cover);
1682 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[0]->sw_if_index,
1683 MFIB_ITF_FLAG_ACCEPT));
1684 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[0]->sw_if_index,
1685 MFIB_ITF_FLAG_ACCEPT));
1686 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[1]->sw_if_index,
1687 MFIB_ITF_FLAG_FORWARD));
1688 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[1]->sw_if_index,
1689 MFIB_ITF_FLAG_FORWARD));
1690 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[2]->sw_if_index,
1691 MFIB_ITF_FLAG_FORWARD));
1692 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[2]->sw_if_index,
1693 MFIB_ITF_FLAG_FORWARD));
1696 * add a for-us path to the cover
1698 mfib_table_entry_path_update(fib_index,
1704 * expect the /32 and /28 to be via all three paths
1706 MFIB_TEST(!mfib_test_entry(mfei_cover,
1707 MFIB_ENTRY_FLAG_NONE,
1709 DPO_ADJACENCY_MCAST, ai_1,
1710 DPO_ADJACENCY_MCAST, ai_2,
1713 format_mfib_prefix, pfx_cover);
1714 MFIB_TEST(!mfib_test_entry(mfei_host1,
1715 MFIB_ENTRY_FLAG_NONE,
1717 DPO_ADJACENCY_MCAST, ai_1,
1718 DPO_ADJACENCY_MCAST, ai_2,
1721 format_mfib_prefix, pfx_cover);
1724 * get the forwarding chain from the RR prefix
1727 dpo_id_t dpo = DPO_INVALID;
1729 mfib_entry_contribute_forwarding(
1731 mfib_forw_chain_type_from_dpo_proto(DPROTO),
1732 MFIB_ENTRY_FWD_FLAG_NONE,
1735 rep = replicate_get(dpo.dpoi_index);
1736 MFIB_TEST((3 == rep->rep_n_buckets),
1737 "%U replicate 3 buckets",
1738 format_mfib_prefix, pfx_host1);
1741 * get the forwarding chain from the RR prefix without local paths
1743 mfib_entry_contribute_forwarding(
1745 mfib_forw_chain_type_from_dpo_proto(DPROTO),
1746 MFIB_ENTRY_FWD_FLAG_NO_LOCAL,
1749 rep = replicate_get(dpo.dpoi_index);
1750 MFIB_TEST((2 == rep->rep_n_buckets),
1751 "%U no-local replicate 2 buckets",
1752 format_mfib_prefix, pfx_host1);
1757 * delete the cover, expect the /32 to be via the default
1759 mfib_table_entry_delete(fib_index, pfx_cover, MFIB_SOURCE_API);
1760 MFIB_TEST(!mfib_test_entry(mfei_host1,
1761 MFIB_ENTRY_FLAG_DROP,
1763 "%U no replications OK",
1764 format_mfib_prefix, pfx_host1);
1767 * source the /32 with its own path
1769 mfei_host1 = mfib_table_entry_path_update(fib_index,
1773 MFIB_TEST(!mfib_test_entry(mfei_host1,
1774 MFIB_ENTRY_FLAG_NONE,
1776 DPO_ADJACENCY_MCAST, ai_2),
1778 format_mfib_prefix, pfx_host1);
1781 * remove host2 - as many times as it was added
1783 mfib_table_entry_delete(fib_index, pfx_host2,
1785 mfib_table_entry_delete(fib_index, pfx_host2,
1787 mfib_table_entry_delete(fib_index, pfx_host2,
1789 mfib_table_entry_delete(fib_index, pfx_host2,
1794 * remove the RR source with paths present
1796 mfib_table_entry_delete(fib_index, pfx_host1,
1800 * add the RR back then remove the path and RR
1802 mfei_host1 = mfib_table_entry_path_update(fib_index,
1806 MFIB_TEST(!mfib_test_entry(mfei_host1,
1807 MFIB_ENTRY_FLAG_NONE,
1809 DPO_ADJACENCY_MCAST, ai_2),
1811 format_mfib_prefix, pfx_host1);
1813 mfib_table_entry_delete(fib_index, pfx_host1,
1815 mfib_table_entry_delete(fib_index, pfx_host1,
1819 * test we've leaked no resources
1823 MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
1824 MFIB_TEST(n_pls == fib_path_list_pool_size(), "%d=%d path-lists",
1825 n_pls, fib_path_list_pool_size());
1826 MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
1827 n_reps, pool_elts(replicate_pool));
1828 MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
1829 " No more entries %d!=%d",
1830 n_entries, pool_elts(mfib_entry_pool));
1831 MFIB_TEST(n_itfs == pool_elts(mfib_itf_pool),
1832 " No more Interfaces %d!=%d",
1833 n_itfs, pool_elts(mfib_itf_pool));
1838 mfib_test_rr_v4 (void)
1841 * 2 length of prefix to play with
1843 const mfib_prefix_t pfx_host1 = {
1845 .fp_proto = FIB_PROTOCOL_IP4,
1847 .ip4.as_u32 = clib_host_to_net_u32(0xe0001011),
1850 const mfib_prefix_t pfx_host2 = {
1852 .fp_proto = FIB_PROTOCOL_IP4,
1854 .ip4.as_u32 = clib_host_to_net_u32(0xe0001011),
1857 .ip4.as_u32 = clib_host_to_net_u32(0x10101010),
1860 const mfib_prefix_t pfx_cover = {
1862 .fp_proto = FIB_PROTOCOL_IP4,
1864 .ip4.as_u32 = clib_host_to_net_u32(0xe0001010),
1868 return (mfib_test_rr_i(FIB_PROTOCOL_IP4,
1877 mfib_test_rr_v6 (void)
1880 * 2 length of prefix to play with
1882 const mfib_prefix_t pfx_host1 = {
1884 .fp_proto = FIB_PROTOCOL_IP6,
1886 .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
1887 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1890 const mfib_prefix_t pfx_host2 = {
1892 .fp_proto = FIB_PROTOCOL_IP6,
1894 .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
1895 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1898 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1899 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1902 const mfib_prefix_t pfx_cover = {
1904 .fp_proto = FIB_PROTOCOL_IP6,
1906 .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
1907 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000000),
1911 return (mfib_test_rr_i(FIB_PROTOCOL_IP6,
1919 static clib_error_t *
1920 mfib_test (vlib_main_t * vm,
1921 unformat_input_t * input,
1922 vlib_cli_command_t * cmd_arg)
1926 res += mfib_test_mk_intf(4);
1927 res += mfib_test_rr_v4();
1931 return clib_error_return(0, "MFIB RR V4 Unit Test Failed");
1934 res += mfib_test_rr_v6();
1938 return clib_error_return(0, "MFIB RR V6 Unit Test Failed");
1941 res += mfib_test_v4();
1945 return clib_error_return(0, "MFIB V4 Unit Test Failed");
1948 res += mfib_test_v6();
1952 return clib_error_return(0, "MFIB V6 Unit Test Failed");
1958 VLIB_CLI_COMMAND (test_fib_command, static) = {
1959 .path = "test mfib",
1960 .short_help = "mfib unit tests - DO NOT RUN ON A LIVE SYSTEM",
1961 .function = mfib_test,
1965 mfib_test_init (vlib_main_t *vm)
1970 VLIB_INIT_FUNCTION (mfib_test_init);