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>
24 #include <vnet/dpo/replicate_dpo.h>
25 #include <vnet/adj/adj_mcast.h>
27 #define MFIB_TEST_I(_cond, _comment, _args...) \
29 int _evald = (_cond); \
31 fformat(stderr, "FAIL:%d: " _comment "\n", \
34 fformat(stderr, "PASS:%d: " _comment "\n", \
39 #define MFIB_TEST(_cond, _comment, _args...) \
41 if (!MFIB_TEST_I(_cond, _comment, ##_args)) { \
43 ASSERT(!("FAIL: " _comment)); \
46 #define MFIB_TEST_NS(_cond) \
48 if (!MFIB_TEST_I(_cond, "")) { \
50 ASSERT(!("FAIL: ")); \
55 * A 'i'm not fussed is this is not efficient' store of test data
57 typedef struct test_main_t_ {
61 u32 hw_if_indicies[4];
65 vnet_hw_interface_t * hw[4];
68 static test_main_t test_main;
70 /* fake ethernet device class, distinct from "fake-ethX" */
71 static u8 * format_test_interface_name (u8 * s, va_list * args)
73 u32 dev_instance = va_arg (*args, u32);
74 return format (s, "test-eth%d", dev_instance);
77 static uword dummy_interface_tx (vlib_main_t * vm,
78 vlib_node_runtime_t * node,
81 clib_warning ("you shouldn't be here, leaking buffers...");
82 return frame->n_vectors;
86 test_interface_admin_up_down (vnet_main_t * vnm,
90 u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
91 VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
92 vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
96 VNET_DEVICE_CLASS (test_interface_device_class,static) = {
97 .name = "Test interface",
98 .format_device_name = format_test_interface_name,
99 .tx_function = dummy_interface_tx,
100 .admin_up_down_function = test_interface_admin_up_down,
103 static u8 *hw_address;
106 mfib_test_mk_intf (u32 ninterfaces)
108 clib_error_t * error = NULL;
109 test_main_t *tm = &test_main;
113 ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
118 vec_add1(hw_address, byte);
121 for (i = 0; i < ninterfaces; i++)
125 error = ethernet_register_interface(vnet_get_main(),
126 test_interface_device_class.index,
129 &tm->hw_if_indicies[i],
130 /* flag change */ 0);
132 MFIB_TEST((NULL == error), "ADD interface %d", i);
134 error = vnet_hw_interface_set_flags(vnet_get_main(),
135 tm->hw_if_indicies[i],
136 VNET_HW_INTERFACE_FLAG_LINK_UP);
137 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
138 tm->hw_if_indicies[i]);
139 vec_validate (ip4_main.fib_index_by_sw_if_index,
140 tm->hw[i]->sw_if_index);
141 vec_validate (ip6_main.fib_index_by_sw_if_index,
142 tm->hw[i]->sw_if_index);
143 ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
144 ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
146 vec_validate (ip4_main.mfib_index_by_sw_if_index,
147 tm->hw[i]->sw_if_index);
148 vec_validate (ip6_main.mfib_index_by_sw_if_index,
149 tm->hw[i]->sw_if_index);
150 ip4_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
151 ip6_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
153 error = vnet_sw_interface_set_flags(vnet_get_main(),
154 tm->hw[i]->sw_if_index,
155 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
156 MFIB_TEST((NULL == error), "UP interface %d", i);
159 * re-eval after the inevitable realloc
161 for (i = 0; i < ninterfaces; i++)
163 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
164 tm->hw_if_indicies[i]);
170 #define MFIB_TEST_REP(_cond, _comment, _args...) \
172 if (!MFIB_TEST_I(_cond, _comment, ##_args)) { \
178 mfib_test_validate_rep_v (const replicate_t *rep,
187 MFIB_TEST_REP((n_buckets == rep->rep_n_buckets),
188 "n_buckets = %d", rep->rep_n_buckets);
190 for (bucket = 0; bucket < n_buckets; bucket++)
192 dt = va_arg(ap, int); // type promotion
193 ai = va_arg(ap, adj_index_t);
194 dpo = replicate_get_bucket_i(rep, bucket);
196 MFIB_TEST_REP((dt == dpo->dpoi_type),
197 "bucket %d stacks on %U",
199 format_dpo_type, dpo->dpoi_type);
201 if (DPO_RECEIVE != dt)
203 MFIB_TEST_REP((ai == dpo->dpoi_index),
204 "bucket %d stacks on %U",
206 format_dpo_id, dpo, 0);
212 static fib_forward_chain_type_t
213 fib_forw_chain_type_from_fib_proto (fib_protocol_t proto)
217 case FIB_PROTOCOL_IP4:
218 return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
219 case FIB_PROTOCOL_IP6:
220 return (FIB_FORW_CHAIN_TYPE_UNICAST_IP6);
230 mfib_test_entry (fib_node_index_t fei,
231 mfib_entry_flags_t eflags,
235 const mfib_entry_t *mfe;
236 const replicate_t *rep;
241 va_start(ap, n_buckets);
243 mfe = mfib_entry_get(fei);
244 mfib_entry_get_prefix(fei, &pfx);
246 MFIB_TEST_REP((eflags == mfe->mfe_flags),
247 "%U has %U expect %U",
248 format_mfib_prefix, &pfx,
249 format_mfib_entry_flags, mfe->mfe_flags,
250 format_mfib_entry_flags, eflags);
254 MFIB_TEST_REP((DPO_DROP == mfe->mfe_rep.dpoi_type),
256 format_mfib_prefix, &pfx,
257 format_dpo_id, &mfe->mfe_rep, 0);
262 dpo_id_t tmp = DPO_INVALID;
264 mfib_entry_contribute_forwarding(
266 fib_forw_chain_type_from_fib_proto(pfx.fp_proto),
268 rep = replicate_get(tmp.dpoi_index);
270 MFIB_TEST_REP((DPO_REPLICATE == tmp.dpoi_type),
272 format_mfib_prefix, &pfx,
273 format_dpo_type, tmp.dpoi_type);
275 res = mfib_test_validate_rep_v(rep, n_buckets, ap);
286 mfib_test_entry_itf (fib_node_index_t fei,
288 mfib_itf_flags_t flags)
290 const mfib_entry_t *mfe;
291 const mfib_itf_t *mfi;
294 mfe = mfib_entry_get(fei);
295 mfi = mfib_entry_get_itf(mfe, sw_if_index);
296 mfib_entry_get_prefix(fei, &pfx);
298 MFIB_TEST_REP((NULL != mfi),
299 "%U has interface %d",
300 format_mfib_prefix, &pfx, sw_if_index);
302 MFIB_TEST_REP((flags == mfi->mfi_flags),
303 "%U interface %d has flags %U expect %U",
304 format_mfib_prefix, &pfx, sw_if_index,
305 format_mfib_itf_flags, flags,
306 format_mfib_itf_flags, mfi->mfi_flags);
312 mfib_test_entry_no_itf (fib_node_index_t fei,
315 const mfib_entry_t *mfe;
316 const mfib_itf_t *mfi;
319 mfe = mfib_entry_get(fei);
320 mfi = mfib_entry_get_itf(mfe, sw_if_index);
321 mfib_entry_get_prefix(fei, &pfx);
323 MFIB_TEST_REP((NULL == mfi),
324 "%U has no interface %d",
325 format_mfib_prefix, &pfx, sw_if_index);
331 mfib_test_i (fib_protocol_t PROTO,
333 const mfib_prefix_t *pfx_no_forward,
334 const mfib_prefix_t *pfx_s_g,
335 const mfib_prefix_t *pfx_star_g_1,
336 const mfib_prefix_t *pfx_star_g_2,
337 const mfib_prefix_t *pfx_star_g_3,
338 const mfib_prefix_t *pfx_star_g_slash_m)
340 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;
341 u32 fib_index, n_entries, n_itfs, n_reps, n_pls;
342 fib_node_index_t ai_1, ai_2, ai_3;
345 mfib_prefix_t all_1s;
346 memset(&all_1s, 0xfd, sizeof(all_1s));
348 n_entries = pool_elts(mfib_entry_pool);
349 n_itfs = pool_elts(mfib_itf_pool);
350 n_reps = pool_elts(replicate_pool);
351 n_pls = fib_path_list_pool_size();
354 ai_1 = adj_mcast_add_or_lock(PROTO,
356 tm->hw[1]->sw_if_index);
357 ai_2 = adj_mcast_add_or_lock(PROTO,
359 tm->hw[2]->sw_if_index);
360 ai_3 = adj_mcast_add_or_lock(PROTO,
362 tm->hw[3]->sw_if_index);
364 MFIB_TEST(3 == adj_mcast_db_size(), "3 MCAST adjs");
366 /* Find or create FIB table 11 */
367 fib_index = mfib_table_find_or_create_and_lock(PROTO, 11);
369 mfib_prefix_t pfx_dft = {
373 mfei_dflt = mfib_table_lookup_exact_match(fib_index, &pfx_dft);
374 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
375 MFIB_TEST(mfib_test_entry(mfei_dflt,
376 MFIB_ENTRY_FLAG_DROP,
378 "(*,*) no replcaitions");
380 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
381 MFIB_TEST(mfib_test_entry(mfei_dflt,
382 MFIB_ENTRY_FLAG_DROP,
384 "(*,*) no replcaitions");
387 fib_route_path_t path_via_if0 = {
389 .frp_addr = zero_addr,
390 .frp_sw_if_index = tm->hw[0]->sw_if_index,
396 mfib_table_entry_path_update(fib_index,
400 MFIB_ITF_FLAG_ACCEPT);
402 mfei_no_f = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
403 MFIB_TEST(mfib_test_entry(mfei_no_f,
404 MFIB_ENTRY_FLAG_NONE,
406 "%U no replcaitions",
407 format_mfib_prefix, pfx_no_forward);
408 MFIB_TEST_NS(mfib_test_entry_itf(mfei_no_f, tm->hw[0]->sw_if_index,
409 MFIB_ITF_FLAG_ACCEPT));
411 fib_route_path_t path_via_if1 = {
413 .frp_addr = zero_addr,
414 .frp_sw_if_index = tm->hw[1]->sw_if_index,
419 fib_route_path_t path_via_if2 = {
421 .frp_addr = zero_addr,
422 .frp_sw_if_index = tm->hw[2]->sw_if_index,
427 fib_route_path_t path_via_if3 = {
429 .frp_addr = zero_addr,
430 .frp_sw_if_index = tm->hw[3]->sw_if_index,
435 fib_route_path_t path_for_us = {
437 .frp_addr = zero_addr,
438 .frp_sw_if_index = 0xffffffff,
441 .frp_flags = FIB_ROUTE_PATH_LOCAL,
445 * An (S,G) with 1 accepting and 3 forwarding paths
447 mfib_table_entry_path_update(fib_index,
451 MFIB_ITF_FLAG_ACCEPT);
452 mfib_table_entry_path_update(fib_index,
456 MFIB_ITF_FLAG_FORWARD);
457 mfib_table_entry_path_update(fib_index,
461 MFIB_ITF_FLAG_FORWARD);
462 mfib_table_entry_path_update(fib_index,
466 (MFIB_ITF_FLAG_FORWARD |
467 MFIB_ITF_FLAG_NEGATE_SIGNAL));
469 mfei_s_g = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
471 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_s_g,
473 format_mfib_prefix, pfx_s_g);
474 MFIB_TEST(mfib_test_entry(mfei_s_g,
475 MFIB_ENTRY_FLAG_NONE,
477 DPO_ADJACENCY_MCAST, ai_1,
478 DPO_ADJACENCY_MCAST, ai_2,
479 DPO_ADJACENCY_MCAST, ai_3),
481 format_mfib_prefix, pfx_s_g);
482 MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[0]->sw_if_index,
483 MFIB_ITF_FLAG_ACCEPT));
484 MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[1]->sw_if_index,
485 MFIB_ITF_FLAG_FORWARD));
486 MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[2]->sw_if_index,
487 MFIB_ITF_FLAG_FORWARD));
488 MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[3]->sw_if_index,
489 (MFIB_ITF_FLAG_FORWARD |
490 MFIB_ITF_FLAG_NEGATE_SIGNAL)));
493 * A (*,G), which the same G as the (S,G).
494 * different paths. test our LPM.
496 mfei_g_1 = mfib_table_entry_path_update(fib_index,
500 MFIB_ITF_FLAG_ACCEPT);
501 mfib_table_entry_path_update(fib_index,
505 MFIB_ITF_FLAG_FORWARD);
508 * test we find the *,G and S,G via LPM and exact matches
510 mfei = mfib_table_lookup_exact_match(fib_index,
512 MFIB_TEST(mfei == mfei_g_1,
513 "%U found via exact match",
514 format_mfib_prefix, pfx_star_g_1);
515 MFIB_TEST(mfib_test_entry(mfei,
516 MFIB_ENTRY_FLAG_NONE,
518 DPO_ADJACENCY_MCAST, ai_1),
520 format_mfib_prefix, pfx_star_g_1);
522 mfei = mfib_table_lookup(fib_index,
524 MFIB_TEST(mfei == mfei_g_1,
525 "%U found via LP match",
526 format_mfib_prefix, pfx_star_g_1);
528 MFIB_TEST(mfib_test_entry(mfei,
529 MFIB_ENTRY_FLAG_NONE,
531 DPO_ADJACENCY_MCAST, ai_1),
533 format_mfib_prefix, pfx_star_g_1);
535 mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
536 MFIB_TEST(mfei == mfei_s_g,
537 "%U found via exact match",
538 format_mfib_prefix, pfx_s_g);
540 MFIB_TEST(mfib_test_entry(mfei,
541 MFIB_ENTRY_FLAG_NONE,
543 DPO_ADJACENCY_MCAST, ai_1,
544 DPO_ADJACENCY_MCAST, ai_2,
545 DPO_ADJACENCY_MCAST, ai_3),
547 format_mfib_prefix, pfx_s_g);
548 mfei = mfib_table_lookup(fib_index, pfx_s_g);
549 MFIB_TEST(mfei == mfei_s_g,
550 "%U found via LP match",
551 format_mfib_prefix, pfx_s_g);
553 MFIB_TEST(mfib_test_entry(mfei,
554 MFIB_ENTRY_FLAG_NONE,
556 DPO_ADJACENCY_MCAST, ai_1,
557 DPO_ADJACENCY_MCAST, ai_2,
558 DPO_ADJACENCY_MCAST, ai_3),
560 format_mfib_prefix, pfx_s_g);
563 * A (*,G/m), which the same root G as the (*,G).
564 * different paths. test our LPM.
566 mfei_g_m = mfib_table_entry_path_update(fib_index,
570 MFIB_ITF_FLAG_ACCEPT);
571 mfib_table_entry_path_update(fib_index,
575 MFIB_ITF_FLAG_FORWARD);
578 * test we find the (*,G/m), (*,G) and (S,G) via LPM and exact matches
580 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
581 MFIB_TEST((mfei_g_1 == mfei),
582 "%U found via DP LPM: %d",
583 format_mfib_prefix, pfx_star_g_1, mfei);
585 MFIB_TEST(mfib_test_entry(mfei,
586 MFIB_ENTRY_FLAG_NONE,
588 DPO_ADJACENCY_MCAST, ai_1),
590 format_mfib_prefix, pfx_star_g_1);
592 mfei = mfib_table_lookup(fib_index, pfx_star_g_1);
594 MFIB_TEST(mfib_test_entry(mfei,
595 MFIB_ENTRY_FLAG_NONE,
597 DPO_ADJACENCY_MCAST, ai_1),
599 format_mfib_prefix, pfx_star_g_1);
601 mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
603 MFIB_TEST(mfib_test_entry(mfei,
604 MFIB_ENTRY_FLAG_NONE,
606 DPO_ADJACENCY_MCAST, ai_1,
607 DPO_ADJACENCY_MCAST, ai_2,
608 DPO_ADJACENCY_MCAST, ai_3),
610 format_mfib_prefix, pfx_s_g);
611 mfei = mfib_table_lookup(fib_index, pfx_s_g);
613 MFIB_TEST(mfib_test_entry(mfei,
614 MFIB_ENTRY_FLAG_NONE,
616 DPO_ADJACENCY_MCAST, ai_1,
617 DPO_ADJACENCY_MCAST, ai_2,
618 DPO_ADJACENCY_MCAST, ai_3),
620 format_mfib_prefix, pfx_s_g);
622 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
623 MFIB_TEST(mfei = mfei_g_m,
624 "%U Found via exact match",
625 format_mfib_prefix, pfx_star_g_slash_m);
626 MFIB_TEST(mfib_test_entry(mfei,
627 MFIB_ENTRY_FLAG_NONE,
629 DPO_ADJACENCY_MCAST, ai_3),
631 format_mfib_prefix, pfx_star_g_slash_m);
632 MFIB_TEST(mfei_g_m == mfib_table_lookup(fib_index, pfx_star_g_slash_m),
634 format_mfib_prefix, pfx_star_g_slash_m);
639 mfei = mfib_table_entry_path_update(fib_index,
643 MFIB_ITF_FLAG_FORWARD);
645 MFIB_TEST(mfib_test_entry(mfei,
646 MFIB_ENTRY_FLAG_NONE,
648 DPO_ADJACENCY_MCAST, ai_1,
649 DPO_ADJACENCY_MCAST, ai_2,
650 DPO_ADJACENCY_MCAST, ai_3,
653 format_mfib_prefix, pfx_s_g);
656 * remove a for-us path
658 mfib_table_entry_path_remove(fib_index,
663 MFIB_TEST(mfib_test_entry(mfei,
664 MFIB_ENTRY_FLAG_NONE,
666 DPO_ADJACENCY_MCAST, ai_1,
667 DPO_ADJACENCY_MCAST, ai_2,
668 DPO_ADJACENCY_MCAST, ai_3),
670 format_mfib_prefix, pfx_s_g);
673 * update an existing forwarding path to be only accepting
674 * - expect it to be removed from the replication set.
676 mfib_table_entry_path_update(fib_index,
680 MFIB_ITF_FLAG_ACCEPT);
682 MFIB_TEST(mfib_test_entry(mfei,
683 MFIB_ENTRY_FLAG_NONE,
685 DPO_ADJACENCY_MCAST, ai_1,
686 DPO_ADJACENCY_MCAST, ai_2),
688 format_mfib_prefix, pfx_s_g);
689 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
690 MFIB_ITF_FLAG_ACCEPT));
691 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
692 MFIB_ITF_FLAG_FORWARD));
693 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
694 MFIB_ITF_FLAG_FORWARD));
695 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
696 MFIB_ITF_FLAG_ACCEPT));
698 * Make the path forwarding again
699 * - expect it to be added back to the replication set
701 mfib_table_entry_path_update(fib_index,
705 (MFIB_ITF_FLAG_FORWARD |
706 MFIB_ITF_FLAG_ACCEPT |
707 MFIB_ITF_FLAG_NEGATE_SIGNAL));
709 mfei = mfib_table_lookup_exact_match(fib_index,
712 MFIB_TEST(mfib_test_entry(mfei,
713 MFIB_ENTRY_FLAG_NONE,
715 DPO_ADJACENCY_MCAST, ai_1,
716 DPO_ADJACENCY_MCAST, ai_2,
717 DPO_ADJACENCY_MCAST, ai_3),
719 format_mfib_prefix, pfx_s_g);
720 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
721 MFIB_ITF_FLAG_ACCEPT));
722 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
723 MFIB_ITF_FLAG_FORWARD));
724 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
725 MFIB_ITF_FLAG_FORWARD));
726 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
727 (MFIB_ITF_FLAG_FORWARD |
728 MFIB_ITF_FLAG_ACCEPT |
729 MFIB_ITF_FLAG_NEGATE_SIGNAL)));
732 * update flags on the entry
734 mfib_table_entry_update(fib_index,
737 MFIB_ENTRY_FLAG_SIGNAL);
738 MFIB_TEST(mfib_test_entry(mfei,
739 MFIB_ENTRY_FLAG_SIGNAL,
741 DPO_ADJACENCY_MCAST, ai_1,
742 DPO_ADJACENCY_MCAST, ai_2,
743 DPO_ADJACENCY_MCAST, ai_3),
745 format_mfib_prefix, pfx_s_g);
750 mfib_table_entry_path_remove(fib_index,
755 MFIB_TEST(mfib_test_entry(mfei,
756 MFIB_ENTRY_FLAG_SIGNAL,
758 DPO_ADJACENCY_MCAST, ai_1,
759 DPO_ADJACENCY_MCAST, ai_2),
761 format_mfib_prefix, pfx_s_g);
762 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
763 MFIB_ITF_FLAG_ACCEPT));
764 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
765 MFIB_ITF_FLAG_FORWARD));
766 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
767 MFIB_ITF_FLAG_FORWARD));
768 MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
770 mfib_table_entry_path_remove(fib_index,
775 MFIB_TEST(mfib_test_entry(mfei,
776 MFIB_ENTRY_FLAG_SIGNAL,
778 DPO_ADJACENCY_MCAST, ai_2),
780 format_mfib_prefix, pfx_s_g);
781 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
782 MFIB_ITF_FLAG_ACCEPT));
783 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
784 MFIB_ITF_FLAG_FORWARD));
785 MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
788 * remove the accpeting only interface
790 mfib_table_entry_path_remove(fib_index,
795 MFIB_TEST(mfib_test_entry(mfei,
796 MFIB_ENTRY_FLAG_SIGNAL,
798 DPO_ADJACENCY_MCAST, ai_2),
800 format_mfib_prefix, pfx_s_g);
801 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
802 MFIB_ITF_FLAG_FORWARD));
803 MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[0]->sw_if_index));
804 MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[1]->sw_if_index));
805 MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
808 * remove the last path, the entry still has flags so it remains
810 mfib_table_entry_path_remove(fib_index,
815 MFIB_TEST(mfib_test_entry(mfei,
816 MFIB_ENTRY_FLAG_SIGNAL,
818 "%U no replications",
819 format_mfib_prefix, pfx_s_g);
822 * update flags on the entry
824 mfib_table_entry_update(fib_index,
827 (MFIB_ENTRY_FLAG_SIGNAL |
828 MFIB_ENTRY_FLAG_CONNECTED));
829 MFIB_TEST(mfib_test_entry(mfei,
830 (MFIB_ENTRY_FLAG_SIGNAL |
831 MFIB_ENTRY_FLAG_CONNECTED),
833 "%U no replications",
834 format_mfib_prefix, pfx_s_g);
837 * An entry with a NS interface
839 mfei_g_2 = mfib_table_entry_path_update(fib_index,
843 (MFIB_ITF_FLAG_ACCEPT |
844 MFIB_ITF_FLAG_NEGATE_SIGNAL));
845 MFIB_TEST(mfib_test_entry(mfei_g_2,
846 MFIB_ENTRY_FLAG_NONE,
848 "%U No replications",
849 format_mfib_prefix, pfx_star_g_2);
852 * Simulate a signal from the data-plane
858 mfe = mfib_entry_get(mfei_g_2);
859 mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
861 mfib_signal_push(mfe, mfi, NULL);
865 * An entry with a NS interface
867 mfei_g_3 = mfib_table_entry_path_update(fib_index,
871 (MFIB_ITF_FLAG_ACCEPT |
872 MFIB_ITF_NEGATE_SIGNAL));
873 MFIB_TEST(mfib_test_entry(mfei_g_3,
874 MFIB_ENTRY_FLAG_NONE,
876 "%U No replications",
877 format_mfib_prefix, pfx_star_g_3);
880 * Simulate a signal from the data-plane
886 mfe = mfib_entry_get(mfei_g_3);
887 mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
889 mfib_signal_push(mfe, mfi, NULL);
892 if (FIB_PROTOCOL_IP6 == PROTO)
895 * All the entries are present. let's ensure we can find them all
896 * via exact and longest prefix matches.
899 * A source address we will never match
901 ip6_address_t src = {
902 .as_u64[0] = clib_host_to_net_u64(0x3001000000000000),
903 .as_u64[1] = clib_host_to_net_u64(0xffffffffffffffff),
909 MFIB_TEST((mfei_g_m == ip6_mfib_table_lookup2(
910 ip6_mfib_get(fib_index),
912 &pfx_star_g_slash_m->fp_grp_addr.ip6)),
913 "%U found via DP LPM grp=%U",
914 format_mfib_prefix, pfx_star_g_slash_m,
915 format_ip6_address, &pfx_star_g_slash_m->fp_grp_addr.ip6);
917 ip6_address_t tmp = pfx_star_g_slash_m->fp_grp_addr.ip6;
918 tmp.as_u8[15] = 0xff;
920 MFIB_TEST((mfei_g_m == ip6_mfib_table_lookup2(
921 ip6_mfib_get(fib_index),
922 &pfx_s_g->fp_src_addr.ip6,
924 "%U found via DP LPM grp=%U",
925 format_mfib_prefix, pfx_star_g_slash_m,
926 format_ip6_address, &tmp);
931 mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
932 &pfx_s_g->fp_src_addr.ip6,
933 &pfx_s_g->fp_grp_addr.ip6);
934 MFIB_TEST((mfei_s_g == mfei),
935 "%U found via DP LPM: %d",
936 format_mfib_prefix, pfx_s_g, mfei);
941 mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
943 &pfx_star_g_1->fp_grp_addr.ip6);
944 MFIB_TEST((mfei_g_1 == mfei),
945 "%U found via DP LPM: %d",
946 format_mfib_prefix, pfx_star_g_1, mfei);
947 mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
949 &pfx_star_g_2->fp_grp_addr.ip6);
950 MFIB_TEST((mfei_g_2 == mfei),
951 "%U found via DP LPM: %d",
952 format_mfib_prefix, pfx_star_g_2, mfei);
953 mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
955 &pfx_star_g_3->fp_grp_addr.ip6);
956 MFIB_TEST((mfei_g_3 == mfei),
957 "%U found via DP LPM: %d",
958 format_mfib_prefix, pfx_star_g_3, mfei);
962 * remove flags on the entry. This is the last of the
963 * state associated with the entry, so now it goes.
965 mfib_table_entry_update(fib_index,
968 MFIB_ENTRY_FLAG_NONE);
969 mfei = mfib_table_lookup_exact_match(fib_index,
971 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
973 format_mfib_prefix, pfx_s_g);
976 * remove the last path on the no forward entry - the last entry
978 mfib_table_entry_path_remove(fib_index,
983 mfei = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
984 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
986 format_mfib_prefix, pfx_no_forward);
989 * hard delete the (*,232.1.1.1)
991 mfib_table_entry_delete(fib_index,
995 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
996 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
998 format_mfib_prefix, pfx_star_g_1);
1000 * remove the entry whilst the signal is pending
1002 mfib_table_entry_delete(fib_index,
1006 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_2);
1007 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1009 format_mfib_prefix, pfx_star_g_2);
1010 mfib_table_entry_delete(fib_index,
1014 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_3);
1015 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1017 format_mfib_prefix, pfx_star_g_3);
1019 mfib_table_entry_delete(fib_index,
1023 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
1024 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1026 format_mfib_prefix, pfx_star_g_slash_m);
1029 * Add a prefix as a special/exclusive route
1031 dpo_id_t td = DPO_INVALID;
1032 index_t repi = replicate_create(1, fib_proto_to_dpo(PROTO));
1034 dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_2);
1035 replicate_set_bucket(repi, 0, &td);
1037 mfei = mfib_table_entry_special_add(fib_index,
1040 MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF,
1042 MFIB_TEST(mfib_test_entry(mfei,
1043 (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
1044 MFIB_ENTRY_FLAG_EXCLUSIVE),
1046 DPO_ADJACENCY_MCAST, ai_2),
1047 "%U exclusive replicate OK",
1048 format_mfib_prefix, pfx_star_g_3);
1051 * update a special/exclusive route
1053 index_t repi2 = replicate_create(1, fib_proto_to_dpo(PROTO));
1055 dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_1);
1056 replicate_set_bucket(repi2, 0, &td);
1058 mfei = mfib_table_entry_special_add(fib_index,
1061 MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF,
1063 MFIB_TEST(mfib_test_entry(mfei,
1064 (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
1065 MFIB_ENTRY_FLAG_EXCLUSIVE),
1067 DPO_ADJACENCY_MCAST, ai_1),
1068 "%U exclusive update replicate OK",
1069 format_mfib_prefix, pfx_star_g_3);
1071 mfib_table_entry_delete(fib_index,
1077 * Unlock the table - it's the last lock so should be gone thereafter
1079 mfib_table_unlock(fib_index, PROTO);
1081 MFIB_TEST((FIB_NODE_INDEX_INVALID ==
1082 mfib_table_find(PROTO, fib_index)),
1083 "MFIB table %d gone", fib_index);
1090 * test we've leaked no resources
1092 MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
1093 MFIB_TEST(n_pls == fib_path_list_pool_size(), "%d=%d path-lists",
1094 n_pls, fib_path_list_pool_size());
1095 MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
1096 n_reps, pool_elts(replicate_pool));
1097 MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
1098 " No more entries %d!=%d",
1099 n_entries, pool_elts(mfib_entry_pool));
1100 MFIB_TEST(n_itfs == pool_elts(mfib_itf_pool),
1101 " No more Interfaces %d!=%d",
1102 n_itfs, pool_elts(mfib_itf_pool));
1110 const mfib_prefix_t pfx_224_s_8 = {
1112 .fp_proto = FIB_PROTOCOL_IP4,
1114 .ip4.as_u32 = clib_host_to_net_u32(0xe0000000),
1117 const mfib_prefix_t pfx_1_1_1_1_c_239_1_1_1 = {
1119 .fp_proto = FIB_PROTOCOL_IP4,
1121 .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1124 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1127 const mfib_prefix_t pfx_239_1_1_1 = {
1129 .fp_proto = FIB_PROTOCOL_IP4,
1131 .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1137 const mfib_prefix_t pfx_239_1_1_2 = {
1139 .fp_proto = FIB_PROTOCOL_IP4,
1141 .ip4.as_u32 = clib_host_to_net_u32(0xef010102),
1147 const mfib_prefix_t pfx_239_1_1_3 = {
1149 .fp_proto = FIB_PROTOCOL_IP4,
1151 .ip4.as_u32 = clib_host_to_net_u32(0xef010103),
1157 const mfib_prefix_t pfx_239 = {
1159 .fp_proto = FIB_PROTOCOL_IP4,
1161 .ip4.as_u32 = clib_host_to_net_u32(0xef000000),
1168 return (mfib_test_i(FIB_PROTOCOL_IP4,
1171 &pfx_1_1_1_1_c_239_1_1_1,
1181 const mfib_prefix_t pfx_ffd_s_12 = {
1183 .fp_proto = FIB_PROTOCOL_IP6,
1185 .ip6.as_u64[0] = clib_host_to_net_u64(0xffd0000000000000),
1188 const mfib_prefix_t pfx_2001_1_c_ff_1 = {
1190 .fp_proto = FIB_PROTOCOL_IP6,
1192 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1193 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1196 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1197 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1200 const mfib_prefix_t pfx_ff_1 = {
1202 .fp_proto = FIB_PROTOCOL_IP6,
1204 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1205 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1208 const mfib_prefix_t pfx_ff_2 = {
1210 .fp_proto = FIB_PROTOCOL_IP6,
1212 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1213 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1216 const mfib_prefix_t pfx_ff_3 = {
1218 * this is the ALL DHCP routers address
1221 .fp_proto = FIB_PROTOCOL_IP6,
1223 .ip6.as_u64[0] = clib_host_to_net_u64(0xff02000100000000),
1224 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1227 const mfib_prefix_t pfx_ff = {
1229 .fp_proto = FIB_PROTOCOL_IP6,
1231 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1232 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000000),
1236 return (mfib_test_i(FIB_PROTOCOL_IP6,
1246 static clib_error_t *
1247 mfib_test (vlib_main_t * vm,
1248 unformat_input_t * input,
1249 vlib_cli_command_t * cmd_arg)
1253 res += mfib_test_mk_intf(4);
1254 res += mfib_test_v4();
1255 res += mfib_test_v6();
1259 return clib_error_return(0, "MFIB Unit Test Failed");
1267 VLIB_CLI_COMMAND (test_fib_command, static) = {
1268 .path = "test mfib",
1269 .short_help = "mfib unit tests - DO NOT RUN ON A LIVE SYSTEM",
1270 .function = mfib_test,
1274 mfib_test_init (vlib_main_t *vm)
1279 VLIB_INIT_FUNCTION (mfib_test_init);