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 accpeting 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,
1197 tm->hw[0]->sw_if_index,
1200 lfei = fib_table_entry_update_one_path(0, // default MPLS Table
1203 FIB_ENTRY_FLAG_MULTICAST,
1206 tm->hw[0]->sw_if_index,
1207 ~0, // invalid fib index
1210 FIB_ROUTE_PATH_FLAG_NONE);
1211 MFIB_TEST(!fib_test_validate_entry(lfei,
1212 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
1215 "3500 via replicate over 10.10.10.1");
1218 * An (S,G) that resolves via the mLDP head-end
1220 fib_route_path_t path_via_mldp = {
1221 .frp_proto = DPO_PROTO_MPLS,
1222 .frp_local_label = pfx_3500.fp_label,
1223 .frp_eos = MPLS_EOS,
1224 .frp_sw_if_index = 0xffffffff,
1227 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
1228 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1230 dpo_id_t mldp_dpo = DPO_INVALID;
1232 fib_entry_contribute_forwarding(lfei,
1233 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
1236 mfei = mfib_table_entry_path_update(fib_index,
1241 MFIB_TEST(!mfib_test_entry(mfei,
1242 MFIB_ENTRY_FLAG_NONE,
1244 DPO_REPLICATE, mldp_dpo.dpoi_index),
1245 "%U over-mLDP replicate OK",
1246 format_mfib_prefix, pfx_s_g);
1249 * add a for-us path. this tests two types of non-attached paths on one entry
1251 mfei = mfib_table_entry_path_update(fib_index,
1255 MFIB_TEST(!mfib_test_entry(mfei,
1256 MFIB_ENTRY_FLAG_NONE,
1258 DPO_REPLICATE, mldp_dpo.dpoi_index,
1260 "%U mLDP+for-us replicate OK",
1261 format_mfib_prefix, pfx_s_g);
1263 mfib_table_entry_delete(fib_index,
1266 fib_table_entry_delete(0,
1269 dpo_reset(&mldp_dpo);
1272 * Unlock the table - it's the last lock so should be gone thereafter
1274 MFIB_TEST(((PROTO == FIB_PROTOCOL_IP4 ? 3 : 5) ==
1275 mfib_table_get_n_routes(fib_index, PROTO)),
1276 "1 = %d route left in the FIB",
1277 mfib_table_get_n_routes(fib_index, PROTO));
1279 mfib_table_unlock(fib_index, PROTO, MFIB_SOURCE_API);
1281 MFIB_TEST((FIB_NODE_INDEX_INVALID ==
1282 mfib_table_find(PROTO, fib_index)),
1283 "MFIB table %d gone", fib_index);
1288 adj_unlock(ai_nbr1);
1289 adj_unlock(ai_nbr2);
1292 * MPLS disable the interface
1294 mpls_sw_interface_enable_disable(&mpls_main,
1295 tm->hw[0]->sw_if_index,
1297 mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
1300 * remove the connected
1302 fib_table_entry_delete(0, pfx_itf, FIB_SOURCE_INTERFACE);
1305 * test we've leaked no resources
1307 MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
1308 MFIB_TEST(n_pls == fib_path_list_pool_size(), "%d=%d path-lists",
1309 n_pls, fib_path_list_pool_size());
1310 MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
1311 n_reps, pool_elts(replicate_pool));
1312 MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
1313 " No more entries %d!=%d",
1314 n_entries, pool_elts(mfib_entry_pool));
1315 MFIB_TEST(n_itfs == pool_elts(mfib_itf_pool),
1316 " No more Interfaces %d!=%d",
1317 n_itfs, pool_elts(mfib_itf_pool));
1318 vec_free(two_paths);
1326 const mfib_prefix_t pfx_224_s_8 = {
1328 .fp_proto = FIB_PROTOCOL_IP4,
1330 .ip4.as_u32 = clib_host_to_net_u32(0xe0000000),
1333 const mfib_prefix_t pfx_1_1_1_1_c_239_1_1_1 = {
1335 .fp_proto = FIB_PROTOCOL_IP4,
1337 .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1340 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1343 const mfib_prefix_t pfx_239_1_1_1 = {
1345 .fp_proto = FIB_PROTOCOL_IP4,
1347 .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1353 const mfib_prefix_t pfx_239_1_1_2 = {
1355 .fp_proto = FIB_PROTOCOL_IP4,
1357 .ip4.as_u32 = clib_host_to_net_u32(0xef010102),
1363 const mfib_prefix_t pfx_239_1_1_3 = {
1365 .fp_proto = FIB_PROTOCOL_IP4,
1367 .ip4.as_u32 = clib_host_to_net_u32(0xef010103),
1373 const mfib_prefix_t pfx_239 = {
1375 .fp_proto = FIB_PROTOCOL_IP4,
1377 .ip4.as_u32 = clib_host_to_net_u32(0xef000000),
1383 const fib_prefix_t pfx_itf = {
1385 .fp_proto = FIB_PROTOCOL_IP4,
1387 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
1390 const ip46_address_t nbr1 = {
1391 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0b),
1393 const ip46_address_t nbr2 = {
1394 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0c),
1396 return (mfib_test_i(FIB_PROTOCOL_IP4,
1399 &pfx_1_1_1_1_c_239_1_1_1,
1412 const mfib_prefix_t pfx_ffd_s_12 = {
1414 .fp_proto = FIB_PROTOCOL_IP6,
1416 .ip6.as_u64[0] = clib_host_to_net_u64(0xffd0000000000000),
1419 const mfib_prefix_t pfx_2001_1_c_ff_1 = {
1421 .fp_proto = FIB_PROTOCOL_IP6,
1423 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1424 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1427 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1428 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1431 const mfib_prefix_t pfx_ff_1 = {
1433 .fp_proto = FIB_PROTOCOL_IP6,
1435 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1436 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1439 const mfib_prefix_t pfx_ff_2 = {
1441 .fp_proto = FIB_PROTOCOL_IP6,
1443 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1444 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1447 const mfib_prefix_t pfx_ff_3 = {
1449 * this is the ALL DHCP routers address
1452 .fp_proto = FIB_PROTOCOL_IP6,
1454 .ip6.as_u64[0] = clib_host_to_net_u64(0xff02000100000000),
1455 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1458 const mfib_prefix_t pfx_ff = {
1460 .fp_proto = FIB_PROTOCOL_IP6,
1462 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1463 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000000),
1466 const fib_prefix_t pfx_itf = {
1468 .fp_proto = FIB_PROTOCOL_IP6,
1470 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1471 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1474 const ip46_address_t nbr1 = {
1475 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1476 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1478 const ip46_address_t nbr2 = {
1479 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1480 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000003),
1483 return (mfib_test_i(FIB_PROTOCOL_IP6,
1497 mfib_test_rr_i (fib_protocol_t FPROTO,
1500 const mfib_prefix_t *pfx_cover,
1501 const mfib_prefix_t *pfx_host1,
1502 const mfib_prefix_t *pfx_host2)
1504 fib_node_index_t mfei_cover, mfei_host1, mfei_host2, ai_1, ai_2;
1505 u32 fib_index, n_entries, n_itfs, n_reps, n_pls;
1510 n_entries = pool_elts(mfib_entry_pool);
1511 n_itfs = pool_elts(mfib_itf_pool);
1512 n_reps = pool_elts(replicate_pool);
1513 n_pls = fib_path_list_pool_size();
1517 ai_1 = adj_mcast_add_or_lock(FPROTO,
1519 tm->hw[1]->sw_if_index);
1520 ai_2 = adj_mcast_add_or_lock(FPROTO,
1522 tm->hw[2]->sw_if_index);
1524 fib_route_path_t path_via_if0 = {
1525 .frp_proto = DPROTO,
1526 .frp_addr = zero_addr,
1527 .frp_sw_if_index = tm->hw[0]->sw_if_index,
1528 .frp_fib_index = ~0,
1531 .frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT,
1533 fib_route_path_t path_via_if1 = {
1534 .frp_proto = DPROTO,
1535 .frp_addr = zero_addr,
1536 .frp_sw_if_index = tm->hw[1]->sw_if_index,
1537 .frp_fib_index = ~0,
1540 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1542 fib_route_path_t path_via_if2 = {
1543 .frp_proto = DPROTO,
1544 .frp_addr = zero_addr,
1545 .frp_sw_if_index = tm->hw[2]->sw_if_index,
1546 .frp_fib_index = ~0,
1549 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1551 fib_route_path_t path_for_us = {
1552 .frp_proto = DPROTO,
1553 .frp_addr = zero_addr,
1554 .frp_sw_if_index = 0xffffffff,
1555 .frp_fib_index = ~0,
1557 .frp_flags = FIB_ROUTE_PATH_LOCAL,
1558 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1562 * with only the default in place, recusre thru the /32
1564 mfei_host1 = mfib_table_entry_special_add(fib_index, pfx_host1,
1566 MFIB_ENTRY_FLAG_NONE,
1569 * expect its forwarding to match the cover's
1571 MFIB_TEST(!mfib_test_entry(mfei_host1,
1572 MFIB_ENTRY_FLAG_DROP,
1574 "%U no replications OK",
1575 format_mfib_prefix, pfx_host1);
1578 * Insert the less specific /28
1580 mfib_table_entry_path_update(fib_index,
1585 mfei_cover = mfib_table_lookup_exact_match(fib_index, pfx_cover);
1587 MFIB_TEST(!mfib_test_entry(mfei_cover,
1588 MFIB_ENTRY_FLAG_NONE,
1590 DPO_ADJACENCY_MCAST, ai_1),
1592 format_mfib_prefix, pfx_cover);
1595 * expect the /32 forwarding to match the new cover's
1597 MFIB_TEST(!mfib_test_entry(mfei_host1,
1598 MFIB_ENTRY_FLAG_NONE,
1600 DPO_ADJACENCY_MCAST, ai_1),
1602 format_mfib_prefix, pfx_host1);
1605 * add another path to the cover
1607 mfib_table_entry_path_update(fib_index,
1613 * expect the /32 and /28 to be via both boths
1615 MFIB_TEST(!mfib_test_entry(mfei_cover,
1616 MFIB_ENTRY_FLAG_NONE,
1618 DPO_ADJACENCY_MCAST, ai_1,
1619 DPO_ADJACENCY_MCAST, ai_2),
1621 format_mfib_prefix, pfx_cover);
1622 MFIB_TEST(!mfib_test_entry(mfei_host1,
1623 MFIB_ENTRY_FLAG_NONE,
1625 DPO_ADJACENCY_MCAST, ai_1,
1626 DPO_ADJACENCY_MCAST, ai_2),
1628 format_mfib_prefix, pfx_host1);
1631 * and the other host whilst all is ready
1633 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1635 MFIB_ENTRY_FLAG_NONE,
1637 MFIB_TEST(!mfib_test_entry(mfei_host2,
1638 MFIB_ENTRY_FLAG_NONE,
1640 DPO_ADJACENCY_MCAST, ai_1,
1641 DPO_ADJACENCY_MCAST, ai_2),
1643 format_mfib_prefix, pfx_host2);
1646 * repaet multiple time to simulate multiple recursve children
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,
1656 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1658 MFIB_ENTRY_FLAG_NONE,
1662 * add an accepting path to the cover
1664 mfib_table_entry_path_update(fib_index,
1670 * expect the /32 and /28 to be via both boths
1672 MFIB_TEST(!mfib_test_entry(mfei_cover,
1673 MFIB_ENTRY_FLAG_NONE,
1675 DPO_ADJACENCY_MCAST, ai_1,
1676 DPO_ADJACENCY_MCAST, ai_2),
1678 format_mfib_prefix, pfx_cover);
1679 MFIB_TEST(!mfib_test_entry(mfei_host1,
1680 MFIB_ENTRY_FLAG_NONE,
1682 DPO_ADJACENCY_MCAST, ai_1,
1683 DPO_ADJACENCY_MCAST, ai_2),
1685 format_mfib_prefix, pfx_cover);
1686 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[0]->sw_if_index,
1687 MFIB_ITF_FLAG_ACCEPT));
1688 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[0]->sw_if_index,
1689 MFIB_ITF_FLAG_ACCEPT));
1690 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[1]->sw_if_index,
1691 MFIB_ITF_FLAG_FORWARD));
1692 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[1]->sw_if_index,
1693 MFIB_ITF_FLAG_FORWARD));
1694 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[2]->sw_if_index,
1695 MFIB_ITF_FLAG_FORWARD));
1696 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[2]->sw_if_index,
1697 MFIB_ITF_FLAG_FORWARD));
1700 * add a for-us path to the cover
1702 mfib_table_entry_path_update(fib_index,
1708 * expect the /32 and /28 to be via all three paths
1710 MFIB_TEST(!mfib_test_entry(mfei_cover,
1711 MFIB_ENTRY_FLAG_NONE,
1713 DPO_ADJACENCY_MCAST, ai_1,
1714 DPO_ADJACENCY_MCAST, ai_2,
1717 format_mfib_prefix, pfx_cover);
1718 MFIB_TEST(!mfib_test_entry(mfei_host1,
1719 MFIB_ENTRY_FLAG_NONE,
1721 DPO_ADJACENCY_MCAST, ai_1,
1722 DPO_ADJACENCY_MCAST, ai_2,
1725 format_mfib_prefix, pfx_cover);
1728 * get the forwarding chain from the RR prefix
1731 dpo_id_t dpo = DPO_INVALID;
1733 mfib_entry_contribute_forwarding(
1735 mfib_forw_chain_type_from_dpo_proto(DPROTO),
1736 MFIB_ENTRY_FWD_FLAG_NONE,
1739 rep = replicate_get(dpo.dpoi_index);
1740 MFIB_TEST((3 == rep->rep_n_buckets),
1741 "%U replicate 3 buckets",
1742 format_mfib_prefix, pfx_host1);
1745 * get the forwarding chain from the RR prefix without local paths
1747 mfib_entry_contribute_forwarding(
1749 mfib_forw_chain_type_from_dpo_proto(DPROTO),
1750 MFIB_ENTRY_FWD_FLAG_NO_LOCAL,
1753 rep = replicate_get(dpo.dpoi_index);
1754 MFIB_TEST((2 == rep->rep_n_buckets),
1755 "%U no-local replicate 2 buckets",
1756 format_mfib_prefix, pfx_host1);
1761 * delete the cover, expect the /32 to be via the default
1763 mfib_table_entry_delete(fib_index, pfx_cover, MFIB_SOURCE_API);
1764 MFIB_TEST(!mfib_test_entry(mfei_host1,
1765 MFIB_ENTRY_FLAG_DROP,
1767 "%U no replications OK",
1768 format_mfib_prefix, pfx_host1);
1771 * source the /32 with its own path
1773 mfei_host1 = mfib_table_entry_path_update(fib_index,
1777 MFIB_TEST(!mfib_test_entry(mfei_host1,
1778 MFIB_ENTRY_FLAG_NONE,
1780 DPO_ADJACENCY_MCAST, ai_2),
1782 format_mfib_prefix, pfx_host1);
1785 * remove host2 - as many times as it was added
1787 mfib_table_entry_delete(fib_index, pfx_host2,
1789 mfib_table_entry_delete(fib_index, pfx_host2,
1791 mfib_table_entry_delete(fib_index, pfx_host2,
1793 mfib_table_entry_delete(fib_index, pfx_host2,
1798 * remove the RR source with paths present
1800 mfib_table_entry_delete(fib_index, pfx_host1,
1804 * add the RR back then remove the path and RR
1806 mfei_host1 = mfib_table_entry_path_update(fib_index,
1810 MFIB_TEST(!mfib_test_entry(mfei_host1,
1811 MFIB_ENTRY_FLAG_NONE,
1813 DPO_ADJACENCY_MCAST, ai_2),
1815 format_mfib_prefix, pfx_host1);
1817 mfib_table_entry_delete(fib_index, pfx_host1,
1819 mfib_table_entry_delete(fib_index, pfx_host1,
1823 * test we've leaked no resources
1827 MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
1828 MFIB_TEST(n_pls == fib_path_list_pool_size(), "%d=%d path-lists",
1829 n_pls, fib_path_list_pool_size());
1830 MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
1831 n_reps, pool_elts(replicate_pool));
1832 MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
1833 " No more entries %d!=%d",
1834 n_entries, pool_elts(mfib_entry_pool));
1835 MFIB_TEST(n_itfs == pool_elts(mfib_itf_pool),
1836 " No more Interfaces %d!=%d",
1837 n_itfs, pool_elts(mfib_itf_pool));
1842 mfib_test_rr_v4 (void)
1845 * 2 length of prefix to play with
1847 const mfib_prefix_t pfx_host1 = {
1849 .fp_proto = FIB_PROTOCOL_IP4,
1851 .ip4.as_u32 = clib_host_to_net_u32(0xe0001011),
1854 const mfib_prefix_t pfx_host2 = {
1856 .fp_proto = FIB_PROTOCOL_IP4,
1858 .ip4.as_u32 = clib_host_to_net_u32(0xe0001011),
1861 .ip4.as_u32 = clib_host_to_net_u32(0x10101010),
1864 const mfib_prefix_t pfx_cover = {
1866 .fp_proto = FIB_PROTOCOL_IP4,
1868 .ip4.as_u32 = clib_host_to_net_u32(0xe0001010),
1872 return (mfib_test_rr_i(FIB_PROTOCOL_IP4,
1881 mfib_test_rr_v6 (void)
1884 * 2 length of prefix to play with
1886 const mfib_prefix_t pfx_host1 = {
1888 .fp_proto = FIB_PROTOCOL_IP6,
1890 .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
1891 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1894 const mfib_prefix_t pfx_host2 = {
1896 .fp_proto = FIB_PROTOCOL_IP6,
1898 .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
1899 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1902 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1903 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1906 const mfib_prefix_t pfx_cover = {
1908 .fp_proto = FIB_PROTOCOL_IP6,
1910 .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
1911 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000000),
1915 return (mfib_test_rr_i(FIB_PROTOCOL_IP6,
1923 static clib_error_t *
1924 mfib_test (vlib_main_t * vm,
1925 unformat_input_t * input,
1926 vlib_cli_command_t * cmd_arg)
1930 res += mfib_test_mk_intf(4);
1931 res += mfib_test_rr_v4();
1935 return clib_error_return(0, "MFIB RR V4 Unit Test Failed");
1938 res += mfib_test_rr_v6();
1942 return clib_error_return(0, "MFIB RR V6 Unit Test Failed");
1945 res += mfib_test_v4();
1949 return clib_error_return(0, "MFIB V4 Unit Test Failed");
1952 res += mfib_test_v6();
1956 return clib_error_return(0, "MFIB V6 Unit Test Failed");
1962 VLIB_CLI_COMMAND (test_fib_command, static) = {
1963 .path = "test mfib",
1964 .short_help = "mfib unit tests - DO NOT RUN ON A LIVE SYSTEM",
1965 .function = mfib_test,
1969 mfib_test_init (vlib_main_t *vm)
1974 VLIB_INIT_FUNCTION (mfib_test_init);