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>
23 #include <vnet/dpo/replicate_dpo.h>
24 #include <vnet/adj/adj_mcast.h>
26 #define MFIB_TEST_I(_cond, _comment, _args...) \
28 int _evald = (_cond); \
30 fformat(stderr, "FAIL:%d: " _comment "\n", \
33 fformat(stderr, "PASS:%d: " _comment "\n", \
38 #define MFIB_TEST(_cond, _comment, _args...) \
40 if (!MFIB_TEST_I(_cond, _comment, ##_args)) { \
42 ASSERT(!("FAIL: " _comment)); \
45 #define MFIB_TEST_NS(_cond) \
47 if (!MFIB_TEST_I(_cond, "")) { \
49 ASSERT(!("FAIL: ")); \
54 * A 'i'm not fussed is this is not efficient' store of test data
56 typedef struct test_main_t_ {
60 u32 hw_if_indicies[4];
64 vnet_hw_interface_t * hw[4];
67 static test_main_t test_main;
69 /* fake ethernet device class, distinct from "fake-ethX" */
70 static u8 * format_test_interface_name (u8 * s, va_list * args)
72 u32 dev_instance = va_arg (*args, u32);
73 return format (s, "test-eth%d", dev_instance);
76 static uword dummy_interface_tx (vlib_main_t * vm,
77 vlib_node_runtime_t * node,
80 clib_warning ("you shouldn't be here, leaking buffers...");
81 return frame->n_vectors;
85 test_interface_admin_up_down (vnet_main_t * vnm,
89 u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
90 VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
91 vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
95 VNET_DEVICE_CLASS (test_interface_device_class,static) = {
96 .name = "Test interface",
97 .format_device_name = format_test_interface_name,
98 .tx_function = dummy_interface_tx,
99 .admin_up_down_function = test_interface_admin_up_down,
102 static u8 *hw_address;
105 mfib_test_mk_intf (u32 ninterfaces)
107 clib_error_t * error = NULL;
108 test_main_t *tm = &test_main;
112 ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
117 vec_add1(hw_address, byte);
120 for (i = 0; i < ninterfaces; i++)
124 error = ethernet_register_interface(vnet_get_main(),
125 test_interface_device_class.index,
128 &tm->hw_if_indicies[i],
129 /* flag change */ 0);
131 MFIB_TEST((NULL == error), "ADD interface %d", i);
133 error = vnet_hw_interface_set_flags(vnet_get_main(),
134 tm->hw_if_indicies[i],
135 VNET_HW_INTERFACE_FLAG_LINK_UP);
136 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
137 tm->hw_if_indicies[i]);
138 vec_validate (ip4_main.fib_index_by_sw_if_index,
139 tm->hw[i]->sw_if_index);
140 vec_validate (ip6_main.fib_index_by_sw_if_index,
141 tm->hw[i]->sw_if_index);
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 vec_validate (ip4_main.mfib_index_by_sw_if_index,
146 tm->hw[i]->sw_if_index);
147 vec_validate (ip6_main.mfib_index_by_sw_if_index,
148 tm->hw[i]->sw_if_index);
149 ip4_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
150 ip6_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
152 error = vnet_sw_interface_set_flags(vnet_get_main(),
153 tm->hw[i]->sw_if_index,
154 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
155 MFIB_TEST((NULL == error), "UP interface %d", i);
158 * re-eval after the inevitable realloc
160 for (i = 0; i < ninterfaces; i++)
162 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
163 tm->hw_if_indicies[i]);
169 #define MFIB_TEST_REP(_cond, _comment, _args...) \
171 if (!MFIB_TEST_I(_cond, _comment, ##_args)) { \
177 mfib_test_validate_rep_v (const replicate_t *rep,
186 MFIB_TEST_REP((n_buckets == rep->rep_n_buckets),
187 "n_buckets = %d", rep->rep_n_buckets);
189 for (bucket = 0; bucket < n_buckets; bucket++)
191 dt = va_arg(ap, int); // type promotion
192 ai = va_arg(ap, adj_index_t);
193 dpo = replicate_get_bucket_i(rep, bucket);
195 MFIB_TEST_REP((dt == dpo->dpoi_type),
196 "bucket %d stacks on %U",
198 format_dpo_type, dpo->dpoi_type);
200 if (DPO_RECEIVE != dt)
202 MFIB_TEST_REP((ai == dpo->dpoi_index),
203 "bucket %d stacks on %U",
205 format_dpo_id, dpo, 0);
211 static fib_forward_chain_type_t
212 fib_forw_chain_type_from_fib_proto (fib_protocol_t proto)
216 case FIB_PROTOCOL_IP4:
217 return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
218 case FIB_PROTOCOL_IP6:
219 return (FIB_FORW_CHAIN_TYPE_UNICAST_IP6);
229 mfib_test_entry (fib_node_index_t fei,
230 mfib_entry_flags_t eflags,
234 const mfib_entry_t *mfe;
235 const replicate_t *rep;
239 va_start(ap, n_buckets);
241 mfe = mfib_entry_get(fei);
242 mfib_entry_get_prefix(fei, &pfx);
244 MFIB_TEST_REP((eflags == mfe->mfe_flags),
245 "%U has %U expect %U",
246 format_mfib_prefix, &pfx,
247 format_mfib_entry_flags, mfe->mfe_flags,
248 format_mfib_entry_flags, eflags);
252 MFIB_TEST_REP((DPO_DROP == mfe->mfe_rep.dpoi_type),
254 format_mfib_prefix, &pfx,
255 format_dpo_id, &mfe->mfe_rep, 0);
260 dpo_id_t tmp = DPO_INVALID;
263 mfib_entry_contribute_forwarding(
265 fib_forw_chain_type_from_fib_proto(pfx.fp_proto),
267 rep = replicate_get(tmp.dpoi_index);
269 MFIB_TEST_REP((DPO_REPLICATE == tmp.dpoi_type),
271 format_mfib_prefix, &pfx,
272 format_dpo_type, tmp.dpoi_type);
274 res = mfib_test_validate_rep_v(rep, n_buckets, ap);
283 mfib_test_entry_itf (fib_node_index_t fei,
285 mfib_itf_flags_t flags)
287 const mfib_entry_t *mfe;
288 const mfib_itf_t *mfi;
291 mfe = mfib_entry_get(fei);
292 mfi = mfib_entry_get_itf(mfe, sw_if_index);
293 mfib_entry_get_prefix(fei, &pfx);
295 MFIB_TEST_REP((NULL != mfi),
296 "%U has interface %d",
297 format_mfib_prefix, &pfx, sw_if_index);
299 MFIB_TEST_REP((flags == mfi->mfi_flags),
300 "%U interface %d has flags %U expect %U",
301 format_mfib_prefix, &pfx, sw_if_index,
302 format_mfib_itf_flags, flags,
303 format_mfib_itf_flags, mfi->mfi_flags);
309 mfib_test_entry_no_itf (fib_node_index_t fei,
312 const mfib_entry_t *mfe;
313 const mfib_itf_t *mfi;
316 mfe = mfib_entry_get(fei);
317 mfi = mfib_entry_get_itf(mfe, sw_if_index);
318 mfib_entry_get_prefix(fei, &pfx);
320 MFIB_TEST_REP((NULL == mfi),
321 "%U has no interface %d",
322 format_mfib_prefix, &pfx, sw_if_index);
328 mfib_test_i (fib_protocol_t PROTO,
330 const mfib_prefix_t *pfx_no_forward,
331 const mfib_prefix_t *pfx_s_g,
332 const mfib_prefix_t *pfx_star_g_1,
333 const mfib_prefix_t *pfx_star_g_2,
334 const mfib_prefix_t *pfx_star_g_3,
335 const mfib_prefix_t *pfx_star_g_slash_m)
337 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;
338 u32 fib_index, n_entries, n_itfs, n_reps;
339 fib_node_index_t ai_1, ai_2, ai_3;
342 mfib_prefix_t all_1s;
343 memset(&all_1s, 0xfd, sizeof(all_1s));
345 n_entries = pool_elts(mfib_entry_pool);
346 n_itfs = pool_elts(mfib_itf_pool);
347 n_reps = pool_elts(replicate_pool);
350 ai_1 = adj_mcast_add_or_lock(PROTO,
352 tm->hw[1]->sw_if_index);
353 ai_2 = adj_mcast_add_or_lock(PROTO,
355 tm->hw[2]->sw_if_index);
356 ai_3 = adj_mcast_add_or_lock(PROTO,
358 tm->hw[3]->sw_if_index);
360 MFIB_TEST(3 == adj_mcast_db_size(), "3 MCAST adjs");
362 /* Find or create FIB table 11 */
363 fib_index = mfib_table_find_or_create_and_lock(PROTO, 11);
365 mfib_prefix_t pfx_dft = {
369 mfei_dflt = mfib_table_lookup_exact_match(fib_index, &pfx_dft);
370 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
371 MFIB_TEST(mfib_test_entry(mfei_dflt,
372 MFIB_ENTRY_FLAG_DROP,
374 "(*,*) no replcaitions");
376 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
377 MFIB_TEST(mfib_test_entry(mfei_dflt,
378 MFIB_ENTRY_FLAG_DROP,
380 "(*,*) no replcaitions");
383 fib_route_path_t path_via_if0 = {
385 .frp_addr = zero_addr,
386 .frp_sw_if_index = tm->hw[0]->sw_if_index,
392 mfib_table_entry_path_update(fib_index,
396 MFIB_ITF_FLAG_ACCEPT);
398 mfei_no_f = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
399 MFIB_TEST(mfib_test_entry(mfei_no_f,
400 MFIB_ENTRY_FLAG_NONE,
402 "%U no replcaitions",
403 format_mfib_prefix, pfx_no_forward);
404 MFIB_TEST_NS(mfib_test_entry_itf(mfei_no_f, tm->hw[0]->sw_if_index,
405 MFIB_ITF_FLAG_ACCEPT));
407 fib_route_path_t path_via_if1 = {
409 .frp_addr = zero_addr,
410 .frp_sw_if_index = tm->hw[1]->sw_if_index,
415 fib_route_path_t path_via_if2 = {
417 .frp_addr = zero_addr,
418 .frp_sw_if_index = tm->hw[2]->sw_if_index,
423 fib_route_path_t path_via_if3 = {
425 .frp_addr = zero_addr,
426 .frp_sw_if_index = tm->hw[3]->sw_if_index,
431 fib_route_path_t path_for_us = {
433 .frp_addr = zero_addr,
434 .frp_sw_if_index = 0xffffffff,
437 .frp_flags = FIB_ROUTE_PATH_LOCAL,
441 * An (S,G) with 1 accepting and 3 forwarding paths
443 mfib_table_entry_path_update(fib_index,
447 MFIB_ITF_FLAG_ACCEPT);
448 mfib_table_entry_path_update(fib_index,
452 MFIB_ITF_FLAG_FORWARD);
453 mfib_table_entry_path_update(fib_index,
457 MFIB_ITF_FLAG_FORWARD);
458 mfib_table_entry_path_update(fib_index,
462 (MFIB_ITF_FLAG_FORWARD |
463 MFIB_ITF_FLAG_NEGATE_SIGNAL));
465 mfei_s_g = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
467 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_s_g,
469 format_mfib_prefix, pfx_s_g);
470 MFIB_TEST(mfib_test_entry(mfei_s_g,
471 MFIB_ENTRY_FLAG_NONE,
473 DPO_ADJACENCY_MCAST, ai_1,
474 DPO_ADJACENCY_MCAST, ai_2,
475 DPO_ADJACENCY_MCAST, ai_3),
477 format_mfib_prefix, pfx_s_g);
478 MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[0]->sw_if_index,
479 MFIB_ITF_FLAG_ACCEPT));
480 MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[1]->sw_if_index,
481 MFIB_ITF_FLAG_FORWARD));
482 MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[2]->sw_if_index,
483 MFIB_ITF_FLAG_FORWARD));
484 MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[3]->sw_if_index,
485 (MFIB_ITF_FLAG_FORWARD |
486 MFIB_ITF_FLAG_NEGATE_SIGNAL)));
489 * A (*,G), which the same G as the (S,G).
490 * different paths. test our LPM.
492 mfei_g_1 = mfib_table_entry_path_update(fib_index,
496 MFIB_ITF_FLAG_ACCEPT);
497 mfib_table_entry_path_update(fib_index,
501 MFIB_ITF_FLAG_FORWARD);
504 * test we find the *,G and S,G via LPM and exact matches
506 mfei = mfib_table_lookup_exact_match(fib_index,
508 MFIB_TEST(mfei == mfei_g_1,
509 "%U found via exact match",
510 format_mfib_prefix, pfx_star_g_1);
511 MFIB_TEST(mfib_test_entry(mfei,
512 MFIB_ENTRY_FLAG_NONE,
514 DPO_ADJACENCY_MCAST, ai_1),
516 format_mfib_prefix, pfx_star_g_1);
518 mfei = mfib_table_lookup(fib_index,
520 MFIB_TEST(mfei == mfei_g_1,
521 "%U found via LP match",
522 format_mfib_prefix, pfx_star_g_1);
524 MFIB_TEST(mfib_test_entry(mfei,
525 MFIB_ENTRY_FLAG_NONE,
527 DPO_ADJACENCY_MCAST, ai_1),
529 format_mfib_prefix, pfx_star_g_1);
531 mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
532 MFIB_TEST(mfei == mfei_s_g,
533 "%U found via exact match",
534 format_mfib_prefix, pfx_s_g);
536 MFIB_TEST(mfib_test_entry(mfei,
537 MFIB_ENTRY_FLAG_NONE,
539 DPO_ADJACENCY_MCAST, ai_1,
540 DPO_ADJACENCY_MCAST, ai_2,
541 DPO_ADJACENCY_MCAST, ai_3),
543 format_mfib_prefix, pfx_s_g);
544 mfei = mfib_table_lookup(fib_index, pfx_s_g);
545 MFIB_TEST(mfei == mfei_s_g,
546 "%U found via LP match",
547 format_mfib_prefix, pfx_s_g);
549 MFIB_TEST(mfib_test_entry(mfei,
550 MFIB_ENTRY_FLAG_NONE,
552 DPO_ADJACENCY_MCAST, ai_1,
553 DPO_ADJACENCY_MCAST, ai_2,
554 DPO_ADJACENCY_MCAST, ai_3),
556 format_mfib_prefix, pfx_s_g);
559 * A (*,G/m), which the same root G as the (*,G).
560 * different paths. test our LPM.
562 mfei_g_m = mfib_table_entry_path_update(fib_index,
566 MFIB_ITF_FLAG_ACCEPT);
567 mfib_table_entry_path_update(fib_index,
571 MFIB_ITF_FLAG_FORWARD);
574 * test we find the (*,G/m), (*,G) and (S,G) via LPM and exact matches
576 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
577 MFIB_TEST((mfei_g_1 == mfei),
578 "%U found via DP LPM: %d",
579 format_mfib_prefix, pfx_star_g_1, mfei);
581 MFIB_TEST(mfib_test_entry(mfei,
582 MFIB_ENTRY_FLAG_NONE,
584 DPO_ADJACENCY_MCAST, ai_1),
586 format_mfib_prefix, pfx_star_g_1);
588 mfei = mfib_table_lookup(fib_index, pfx_star_g_1);
590 MFIB_TEST(mfib_test_entry(mfei,
591 MFIB_ENTRY_FLAG_NONE,
593 DPO_ADJACENCY_MCAST, ai_1),
595 format_mfib_prefix, pfx_star_g_1);
597 mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
599 MFIB_TEST(mfib_test_entry(mfei,
600 MFIB_ENTRY_FLAG_NONE,
602 DPO_ADJACENCY_MCAST, ai_1,
603 DPO_ADJACENCY_MCAST, ai_2,
604 DPO_ADJACENCY_MCAST, ai_3),
606 format_mfib_prefix, pfx_s_g);
607 mfei = mfib_table_lookup(fib_index, pfx_s_g);
609 MFIB_TEST(mfib_test_entry(mfei,
610 MFIB_ENTRY_FLAG_NONE,
612 DPO_ADJACENCY_MCAST, ai_1,
613 DPO_ADJACENCY_MCAST, ai_2,
614 DPO_ADJACENCY_MCAST, ai_3),
616 format_mfib_prefix, pfx_s_g);
618 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
619 MFIB_TEST(mfei = mfei_g_m,
620 "%U Found via exact match",
621 format_mfib_prefix, pfx_star_g_slash_m);
622 MFIB_TEST(mfib_test_entry(mfei,
623 MFIB_ENTRY_FLAG_NONE,
625 DPO_ADJACENCY_MCAST, ai_3),
627 format_mfib_prefix, pfx_star_g_slash_m);
628 MFIB_TEST(mfei_g_m == mfib_table_lookup(fib_index, pfx_star_g_slash_m),
630 format_mfib_prefix, pfx_star_g_slash_m);
635 mfei = mfib_table_entry_path_update(fib_index,
639 MFIB_ITF_FLAG_FORWARD);
641 MFIB_TEST(mfib_test_entry(mfei,
642 MFIB_ENTRY_FLAG_NONE,
644 DPO_ADJACENCY_MCAST, ai_1,
645 DPO_ADJACENCY_MCAST, ai_2,
646 DPO_ADJACENCY_MCAST, ai_3,
649 format_mfib_prefix, pfx_s_g);
652 * remove a for-us path
654 mfib_table_entry_path_remove(fib_index,
659 MFIB_TEST(mfib_test_entry(mfei,
660 MFIB_ENTRY_FLAG_NONE,
662 DPO_ADJACENCY_MCAST, ai_1,
663 DPO_ADJACENCY_MCAST, ai_2,
664 DPO_ADJACENCY_MCAST, ai_3),
666 format_mfib_prefix, pfx_s_g);
669 * update an existing forwarding path to be only accepting
670 * - expect it to be removed from the replication set.
672 mfib_table_entry_path_update(fib_index,
676 MFIB_ITF_FLAG_ACCEPT);
678 MFIB_TEST(mfib_test_entry(mfei,
679 MFIB_ENTRY_FLAG_NONE,
681 DPO_ADJACENCY_MCAST, ai_1,
682 DPO_ADJACENCY_MCAST, ai_2),
684 format_mfib_prefix, pfx_s_g);
685 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
686 MFIB_ITF_FLAG_ACCEPT));
687 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
688 MFIB_ITF_FLAG_FORWARD));
689 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
690 MFIB_ITF_FLAG_FORWARD));
691 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
692 MFIB_ITF_FLAG_ACCEPT));
694 * Make the path forwarding again
695 * - expect it to be added back to the replication set
697 mfib_table_entry_path_update(fib_index,
701 (MFIB_ITF_FLAG_FORWARD |
702 MFIB_ITF_FLAG_ACCEPT |
703 MFIB_ITF_FLAG_NEGATE_SIGNAL));
705 mfei = mfib_table_lookup_exact_match(fib_index,
708 MFIB_TEST(mfib_test_entry(mfei,
709 MFIB_ENTRY_FLAG_NONE,
711 DPO_ADJACENCY_MCAST, ai_1,
712 DPO_ADJACENCY_MCAST, ai_2,
713 DPO_ADJACENCY_MCAST, ai_3),
715 format_mfib_prefix, pfx_s_g);
716 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
717 MFIB_ITF_FLAG_ACCEPT));
718 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
719 MFIB_ITF_FLAG_FORWARD));
720 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
721 MFIB_ITF_FLAG_FORWARD));
722 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
723 (MFIB_ITF_FLAG_FORWARD |
724 MFIB_ITF_FLAG_ACCEPT |
725 MFIB_ITF_FLAG_NEGATE_SIGNAL)));
728 * update flags on the entry
730 mfib_table_entry_update(fib_index,
733 MFIB_ENTRY_FLAG_SIGNAL);
734 MFIB_TEST(mfib_test_entry(mfei,
735 MFIB_ENTRY_FLAG_SIGNAL,
737 DPO_ADJACENCY_MCAST, ai_1,
738 DPO_ADJACENCY_MCAST, ai_2,
739 DPO_ADJACENCY_MCAST, ai_3),
741 format_mfib_prefix, pfx_s_g);
746 mfib_table_entry_path_remove(fib_index,
751 MFIB_TEST(mfib_test_entry(mfei,
752 MFIB_ENTRY_FLAG_SIGNAL,
754 DPO_ADJACENCY_MCAST, ai_1,
755 DPO_ADJACENCY_MCAST, ai_2),
757 format_mfib_prefix, pfx_s_g);
758 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
759 MFIB_ITF_FLAG_ACCEPT));
760 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
761 MFIB_ITF_FLAG_FORWARD));
762 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
763 MFIB_ITF_FLAG_FORWARD));
764 MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
766 mfib_table_entry_path_remove(fib_index,
771 MFIB_TEST(mfib_test_entry(mfei,
772 MFIB_ENTRY_FLAG_SIGNAL,
774 DPO_ADJACENCY_MCAST, ai_2),
776 format_mfib_prefix, pfx_s_g);
777 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
778 MFIB_ITF_FLAG_ACCEPT));
779 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
780 MFIB_ITF_FLAG_FORWARD));
781 MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
784 * remove the accpeting only interface
786 mfib_table_entry_path_remove(fib_index,
791 MFIB_TEST(mfib_test_entry(mfei,
792 MFIB_ENTRY_FLAG_SIGNAL,
794 DPO_ADJACENCY_MCAST, ai_2),
796 format_mfib_prefix, pfx_s_g);
797 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
798 MFIB_ITF_FLAG_FORWARD));
799 MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[0]->sw_if_index));
800 MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[1]->sw_if_index));
801 MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
804 * remove the last path, the entry still has flags so it remains
806 mfib_table_entry_path_remove(fib_index,
811 MFIB_TEST(mfib_test_entry(mfei,
812 MFIB_ENTRY_FLAG_SIGNAL,
814 "%U no replications",
815 format_mfib_prefix, pfx_s_g);
818 * update flags on the entry
820 mfib_table_entry_update(fib_index,
823 (MFIB_ENTRY_FLAG_SIGNAL |
824 MFIB_ENTRY_FLAG_CONNECTED));
825 MFIB_TEST(mfib_test_entry(mfei,
826 (MFIB_ENTRY_FLAG_SIGNAL |
827 MFIB_ENTRY_FLAG_CONNECTED),
829 "%U no replications",
830 format_mfib_prefix, pfx_s_g);
833 * An entry with a NS interface
835 mfei_g_2 = mfib_table_entry_path_update(fib_index,
839 (MFIB_ITF_FLAG_ACCEPT |
840 MFIB_ITF_FLAG_NEGATE_SIGNAL));
841 MFIB_TEST(mfib_test_entry(mfei_g_2,
842 MFIB_ENTRY_FLAG_NONE,
844 "%U No replications",
845 format_mfib_prefix, pfx_star_g_2);
848 * Simulate a signal from the data-plane
854 mfe = mfib_entry_get(mfei_g_2);
855 mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
857 mfib_signal_push(mfe, mfi, NULL);
861 * An entry with a NS interface
863 mfei_g_3 = mfib_table_entry_path_update(fib_index,
867 (MFIB_ITF_FLAG_ACCEPT |
868 MFIB_ITF_NEGATE_SIGNAL));
869 MFIB_TEST(mfib_test_entry(mfei_g_3,
870 MFIB_ENTRY_FLAG_NONE,
872 "%U No replications",
873 format_mfib_prefix, pfx_star_g_3);
876 * Simulate a signal from the data-plane
882 mfe = mfib_entry_get(mfei_g_3);
883 mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
885 mfib_signal_push(mfe, mfi, NULL);
888 if (FIB_PROTOCOL_IP6 == PROTO)
891 * All the entries are present. let's ensure we can find them all
892 * via exact and longest prefix matches.
895 * A source address we will never match
897 ip6_address_t src = {
898 .as_u64[0] = clib_host_to_net_u64(0x3001000000000000),
899 .as_u64[1] = clib_host_to_net_u64(0xffffffffffffffff),
905 MFIB_TEST((mfei_g_m == ip6_mfib_table_lookup2(
906 ip6_mfib_get(fib_index),
908 &pfx_star_g_slash_m->fp_grp_addr.ip6)),
909 "%U found via DP LPM grp=%U",
910 format_mfib_prefix, pfx_star_g_slash_m,
911 format_ip6_address, &pfx_star_g_slash_m->fp_grp_addr.ip6);
913 ip6_address_t tmp = pfx_star_g_slash_m->fp_grp_addr.ip6;
914 tmp.as_u8[15] = 0xff;
916 MFIB_TEST((mfei_g_m == ip6_mfib_table_lookup2(
917 ip6_mfib_get(fib_index),
918 &pfx_s_g->fp_src_addr.ip6,
920 "%U found via DP LPM grp=%U",
921 format_mfib_prefix, pfx_star_g_slash_m,
922 format_ip6_address, &tmp);
927 mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
928 &pfx_s_g->fp_src_addr.ip6,
929 &pfx_s_g->fp_grp_addr.ip6);
930 MFIB_TEST((mfei_s_g == mfei),
931 "%U found via DP LPM: %d",
932 format_mfib_prefix, pfx_s_g, mfei);
937 mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
939 &pfx_star_g_1->fp_grp_addr.ip6);
940 MFIB_TEST((mfei_g_1 == mfei),
941 "%U found via DP LPM: %d",
942 format_mfib_prefix, pfx_star_g_1, mfei);
943 mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
945 &pfx_star_g_2->fp_grp_addr.ip6);
946 MFIB_TEST((mfei_g_2 == mfei),
947 "%U found via DP LPM: %d",
948 format_mfib_prefix, pfx_star_g_2, mfei);
949 mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
951 &pfx_star_g_3->fp_grp_addr.ip6);
952 MFIB_TEST((mfei_g_3 == mfei),
953 "%U found via DP LPM: %d",
954 format_mfib_prefix, pfx_star_g_3, mfei);
958 * remove flags on the entry. This is the last of the
959 * state associated with the entry, so now it goes.
961 mfib_table_entry_update(fib_index,
964 MFIB_ENTRY_FLAG_NONE);
965 mfei = mfib_table_lookup_exact_match(fib_index,
967 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
969 format_mfib_prefix, pfx_s_g);
972 * remove the last path on the no forward entry - the last entry
974 mfib_table_entry_path_remove(fib_index,
979 mfei = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
980 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
982 format_mfib_prefix, pfx_no_forward);
985 * hard delete the (*,232.1.1.1)
987 mfib_table_entry_delete(fib_index,
991 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
992 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
994 format_mfib_prefix, pfx_star_g_1);
996 * remove the entry whilst the signal is pending
998 mfib_table_entry_delete(fib_index,
1002 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_2);
1003 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1005 format_mfib_prefix, pfx_star_g_2);
1006 mfib_table_entry_delete(fib_index,
1010 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_3);
1011 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1013 format_mfib_prefix, pfx_star_g_3);
1015 mfib_table_entry_delete(fib_index,
1019 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
1020 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1022 format_mfib_prefix, pfx_star_g_slash_m);
1025 * Unlock the table - it's the last lock so should be gone thereafter
1027 mfib_table_unlock(fib_index, PROTO);
1029 MFIB_TEST((FIB_NODE_INDEX_INVALID ==
1030 mfib_table_find(PROTO, fib_index)),
1031 "MFIB table %d gone", fib_index);
1038 * test we've leaked no resources
1040 MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
1041 MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
1042 n_reps, pool_elts(replicate_pool));
1043 MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
1044 " No more entries %d!=%d",
1045 n_entries, pool_elts(mfib_entry_pool));
1046 MFIB_TEST(n_itfs == pool_elts(mfib_itf_pool),
1047 " No more Interfaces %d!=%d",
1048 n_itfs, pool_elts(mfib_itf_pool));
1056 const mfib_prefix_t pfx_224_s_8 = {
1058 .fp_proto = FIB_PROTOCOL_IP4,
1060 .ip4.as_u32 = clib_host_to_net_u32(0xe0000000),
1063 const mfib_prefix_t pfx_1_1_1_1_c_239_1_1_1 = {
1065 .fp_proto = FIB_PROTOCOL_IP4,
1067 .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1070 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1073 const mfib_prefix_t pfx_239_1_1_1 = {
1075 .fp_proto = FIB_PROTOCOL_IP4,
1077 .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1083 const mfib_prefix_t pfx_239_1_1_2 = {
1085 .fp_proto = FIB_PROTOCOL_IP4,
1087 .ip4.as_u32 = clib_host_to_net_u32(0xef010102),
1093 const mfib_prefix_t pfx_239_1_1_3 = {
1095 .fp_proto = FIB_PROTOCOL_IP4,
1097 .ip4.as_u32 = clib_host_to_net_u32(0xef010103),
1103 const mfib_prefix_t pfx_239 = {
1105 .fp_proto = FIB_PROTOCOL_IP4,
1107 .ip4.as_u32 = clib_host_to_net_u32(0xef000000),
1114 return (mfib_test_i(FIB_PROTOCOL_IP4,
1117 &pfx_1_1_1_1_c_239_1_1_1,
1127 const mfib_prefix_t pfx_ffd_s_12 = {
1129 .fp_proto = FIB_PROTOCOL_IP6,
1131 .ip6.as_u64[0] = clib_host_to_net_u64(0xffd0000000000000),
1134 const mfib_prefix_t pfx_2001_1_c_ff_1 = {
1136 .fp_proto = FIB_PROTOCOL_IP6,
1138 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1139 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1142 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1143 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1146 const mfib_prefix_t pfx_ff_1 = {
1148 .fp_proto = FIB_PROTOCOL_IP6,
1150 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1151 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1154 const mfib_prefix_t pfx_ff_2 = {
1156 .fp_proto = FIB_PROTOCOL_IP6,
1158 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1159 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1162 const mfib_prefix_t pfx_ff_3 = {
1164 * this is the ALL DHCP routers address
1167 .fp_proto = FIB_PROTOCOL_IP6,
1169 .ip6.as_u64[0] = clib_host_to_net_u64(0xff02000100000000),
1170 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1173 const mfib_prefix_t pfx_ff = {
1175 .fp_proto = FIB_PROTOCOL_IP6,
1177 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1178 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000000),
1182 return (mfib_test_i(FIB_PROTOCOL_IP6,
1192 static clib_error_t *
1193 mfib_test (vlib_main_t * vm,
1194 unformat_input_t * input,
1195 vlib_cli_command_t * cmd_arg)
1199 res += mfib_test_mk_intf(4);
1200 res += mfib_test_v4();
1201 res += mfib_test_v6();
1205 return clib_error_return(0, "MFIB Unit Test Failed");
1213 VLIB_CLI_COMMAND (test_fib_command, static) = {
1214 .path = "test mfib",
1215 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
1216 .function = mfib_test,
1220 mfib_test_init (vlib_main_t *vm)
1225 VLIB_INIT_FUNCTION (mfib_test_init);