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;
240 va_start(ap, n_buckets);
242 mfe = mfib_entry_get(fei);
243 mfib_entry_get_prefix(fei, &pfx);
245 MFIB_TEST_REP((eflags == mfe->mfe_flags),
246 "%U has %U expect %U",
247 format_mfib_prefix, &pfx,
248 format_mfib_entry_flags, mfe->mfe_flags,
249 format_mfib_entry_flags, eflags);
253 MFIB_TEST_REP((DPO_DROP == mfe->mfe_rep.dpoi_type),
255 format_mfib_prefix, &pfx,
256 format_dpo_id, &mfe->mfe_rep, 0);
261 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);
285 mfib_test_entry_itf (fib_node_index_t fei,
287 mfib_itf_flags_t flags)
289 const mfib_entry_t *mfe;
290 const mfib_itf_t *mfi;
293 mfe = mfib_entry_get(fei);
294 mfi = mfib_entry_get_itf(mfe, sw_if_index);
295 mfib_entry_get_prefix(fei, &pfx);
297 MFIB_TEST_REP((NULL != mfi),
298 "%U has interface %d",
299 format_mfib_prefix, &pfx, sw_if_index);
301 MFIB_TEST_REP((flags == mfi->mfi_flags),
302 "%U interface %d has flags %U expect %U",
303 format_mfib_prefix, &pfx, sw_if_index,
304 format_mfib_itf_flags, flags,
305 format_mfib_itf_flags, mfi->mfi_flags);
311 mfib_test_entry_no_itf (fib_node_index_t fei,
314 const mfib_entry_t *mfe;
315 const mfib_itf_t *mfi;
318 mfe = mfib_entry_get(fei);
319 mfi = mfib_entry_get_itf(mfe, sw_if_index);
320 mfib_entry_get_prefix(fei, &pfx);
322 MFIB_TEST_REP((NULL == mfi),
323 "%U has no interface %d",
324 format_mfib_prefix, &pfx, sw_if_index);
330 mfib_test_i (fib_protocol_t PROTO,
332 const mfib_prefix_t *pfx_no_forward,
333 const mfib_prefix_t *pfx_s_g,
334 const mfib_prefix_t *pfx_star_g_1,
335 const mfib_prefix_t *pfx_star_g_2,
336 const mfib_prefix_t *pfx_star_g_3,
337 const mfib_prefix_t *pfx_star_g_slash_m)
339 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;
340 u32 fib_index, n_entries, n_itfs, n_reps;
341 fib_node_index_t ai_1, ai_2, ai_3;
344 mfib_prefix_t all_1s;
345 memset(&all_1s, 0xfd, sizeof(all_1s));
347 n_entries = pool_elts(mfib_entry_pool);
348 n_itfs = pool_elts(mfib_itf_pool);
349 n_reps = pool_elts(replicate_pool);
352 ai_1 = adj_mcast_add_or_lock(PROTO,
354 tm->hw[1]->sw_if_index);
355 ai_2 = adj_mcast_add_or_lock(PROTO,
357 tm->hw[2]->sw_if_index);
358 ai_3 = adj_mcast_add_or_lock(PROTO,
360 tm->hw[3]->sw_if_index);
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);
367 mfib_prefix_t pfx_dft = {
371 mfei_dflt = mfib_table_lookup_exact_match(fib_index, &pfx_dft);
372 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
373 MFIB_TEST(mfib_test_entry(mfei_dflt,
374 MFIB_ENTRY_FLAG_DROP,
376 "(*,*) no replcaitions");
378 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
379 MFIB_TEST(mfib_test_entry(mfei_dflt,
380 MFIB_ENTRY_FLAG_DROP,
382 "(*,*) no replcaitions");
385 fib_route_path_t path_via_if0 = {
387 .frp_addr = zero_addr,
388 .frp_sw_if_index = tm->hw[0]->sw_if_index,
394 mfib_table_entry_path_update(fib_index,
398 MFIB_ITF_FLAG_ACCEPT);
400 mfei_no_f = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
401 MFIB_TEST(mfib_test_entry(mfei_no_f,
402 MFIB_ENTRY_FLAG_NONE,
404 "%U no replcaitions",
405 format_mfib_prefix, pfx_no_forward);
406 MFIB_TEST_NS(mfib_test_entry_itf(mfei_no_f, tm->hw[0]->sw_if_index,
407 MFIB_ITF_FLAG_ACCEPT));
409 fib_route_path_t path_via_if1 = {
411 .frp_addr = zero_addr,
412 .frp_sw_if_index = tm->hw[1]->sw_if_index,
417 fib_route_path_t path_via_if2 = {
419 .frp_addr = zero_addr,
420 .frp_sw_if_index = tm->hw[2]->sw_if_index,
425 fib_route_path_t path_via_if3 = {
427 .frp_addr = zero_addr,
428 .frp_sw_if_index = tm->hw[3]->sw_if_index,
433 fib_route_path_t path_for_us = {
435 .frp_addr = zero_addr,
436 .frp_sw_if_index = 0xffffffff,
439 .frp_flags = FIB_ROUTE_PATH_LOCAL,
443 * An (S,G) with 1 accepting and 3 forwarding paths
445 mfib_table_entry_path_update(fib_index,
449 MFIB_ITF_FLAG_ACCEPT);
450 mfib_table_entry_path_update(fib_index,
454 MFIB_ITF_FLAG_FORWARD);
455 mfib_table_entry_path_update(fib_index,
459 MFIB_ITF_FLAG_FORWARD);
460 mfib_table_entry_path_update(fib_index,
464 (MFIB_ITF_FLAG_FORWARD |
465 MFIB_ITF_FLAG_NEGATE_SIGNAL));
467 mfei_s_g = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
469 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_s_g,
471 format_mfib_prefix, pfx_s_g);
472 MFIB_TEST(mfib_test_entry(mfei_s_g,
473 MFIB_ENTRY_FLAG_NONE,
475 DPO_ADJACENCY_MCAST, ai_1,
476 DPO_ADJACENCY_MCAST, ai_2,
477 DPO_ADJACENCY_MCAST, ai_3),
479 format_mfib_prefix, pfx_s_g);
480 MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[0]->sw_if_index,
481 MFIB_ITF_FLAG_ACCEPT));
482 MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[1]->sw_if_index,
483 MFIB_ITF_FLAG_FORWARD));
484 MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[2]->sw_if_index,
485 MFIB_ITF_FLAG_FORWARD));
486 MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[3]->sw_if_index,
487 (MFIB_ITF_FLAG_FORWARD |
488 MFIB_ITF_FLAG_NEGATE_SIGNAL)));
491 * A (*,G), which the same G as the (S,G).
492 * different paths. test our LPM.
494 mfei_g_1 = mfib_table_entry_path_update(fib_index,
498 MFIB_ITF_FLAG_ACCEPT);
499 mfib_table_entry_path_update(fib_index,
503 MFIB_ITF_FLAG_FORWARD);
506 * test we find the *,G and S,G via LPM and exact matches
508 mfei = mfib_table_lookup_exact_match(fib_index,
510 MFIB_TEST(mfei == mfei_g_1,
511 "%U found via exact match",
512 format_mfib_prefix, pfx_star_g_1);
513 MFIB_TEST(mfib_test_entry(mfei,
514 MFIB_ENTRY_FLAG_NONE,
516 DPO_ADJACENCY_MCAST, ai_1),
518 format_mfib_prefix, pfx_star_g_1);
520 mfei = mfib_table_lookup(fib_index,
522 MFIB_TEST(mfei == mfei_g_1,
523 "%U found via LP match",
524 format_mfib_prefix, pfx_star_g_1);
526 MFIB_TEST(mfib_test_entry(mfei,
527 MFIB_ENTRY_FLAG_NONE,
529 DPO_ADJACENCY_MCAST, ai_1),
531 format_mfib_prefix, pfx_star_g_1);
533 mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
534 MFIB_TEST(mfei == mfei_s_g,
535 "%U found via exact match",
536 format_mfib_prefix, pfx_s_g);
538 MFIB_TEST(mfib_test_entry(mfei,
539 MFIB_ENTRY_FLAG_NONE,
541 DPO_ADJACENCY_MCAST, ai_1,
542 DPO_ADJACENCY_MCAST, ai_2,
543 DPO_ADJACENCY_MCAST, ai_3),
545 format_mfib_prefix, pfx_s_g);
546 mfei = mfib_table_lookup(fib_index, pfx_s_g);
547 MFIB_TEST(mfei == mfei_s_g,
548 "%U found via LP match",
549 format_mfib_prefix, pfx_s_g);
551 MFIB_TEST(mfib_test_entry(mfei,
552 MFIB_ENTRY_FLAG_NONE,
554 DPO_ADJACENCY_MCAST, ai_1,
555 DPO_ADJACENCY_MCAST, ai_2,
556 DPO_ADJACENCY_MCAST, ai_3),
558 format_mfib_prefix, pfx_s_g);
561 * A (*,G/m), which the same root G as the (*,G).
562 * different paths. test our LPM.
564 mfei_g_m = mfib_table_entry_path_update(fib_index,
568 MFIB_ITF_FLAG_ACCEPT);
569 mfib_table_entry_path_update(fib_index,
573 MFIB_ITF_FLAG_FORWARD);
576 * test we find the (*,G/m), (*,G) and (S,G) via LPM and exact matches
578 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
579 MFIB_TEST((mfei_g_1 == mfei),
580 "%U found via DP LPM: %d",
581 format_mfib_prefix, pfx_star_g_1, mfei);
583 MFIB_TEST(mfib_test_entry(mfei,
584 MFIB_ENTRY_FLAG_NONE,
586 DPO_ADJACENCY_MCAST, ai_1),
588 format_mfib_prefix, pfx_star_g_1);
590 mfei = mfib_table_lookup(fib_index, pfx_star_g_1);
592 MFIB_TEST(mfib_test_entry(mfei,
593 MFIB_ENTRY_FLAG_NONE,
595 DPO_ADJACENCY_MCAST, ai_1),
597 format_mfib_prefix, pfx_star_g_1);
599 mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
601 MFIB_TEST(mfib_test_entry(mfei,
602 MFIB_ENTRY_FLAG_NONE,
604 DPO_ADJACENCY_MCAST, ai_1,
605 DPO_ADJACENCY_MCAST, ai_2,
606 DPO_ADJACENCY_MCAST, ai_3),
608 format_mfib_prefix, pfx_s_g);
609 mfei = mfib_table_lookup(fib_index, pfx_s_g);
611 MFIB_TEST(mfib_test_entry(mfei,
612 MFIB_ENTRY_FLAG_NONE,
614 DPO_ADJACENCY_MCAST, ai_1,
615 DPO_ADJACENCY_MCAST, ai_2,
616 DPO_ADJACENCY_MCAST, ai_3),
618 format_mfib_prefix, pfx_s_g);
620 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
621 MFIB_TEST(mfei = mfei_g_m,
622 "%U Found via exact match",
623 format_mfib_prefix, pfx_star_g_slash_m);
624 MFIB_TEST(mfib_test_entry(mfei,
625 MFIB_ENTRY_FLAG_NONE,
627 DPO_ADJACENCY_MCAST, ai_3),
629 format_mfib_prefix, pfx_star_g_slash_m);
630 MFIB_TEST(mfei_g_m == mfib_table_lookup(fib_index, pfx_star_g_slash_m),
632 format_mfib_prefix, pfx_star_g_slash_m);
637 mfei = mfib_table_entry_path_update(fib_index,
641 MFIB_ITF_FLAG_FORWARD);
643 MFIB_TEST(mfib_test_entry(mfei,
644 MFIB_ENTRY_FLAG_NONE,
646 DPO_ADJACENCY_MCAST, ai_1,
647 DPO_ADJACENCY_MCAST, ai_2,
648 DPO_ADJACENCY_MCAST, ai_3,
651 format_mfib_prefix, pfx_s_g);
654 * remove a for-us path
656 mfib_table_entry_path_remove(fib_index,
661 MFIB_TEST(mfib_test_entry(mfei,
662 MFIB_ENTRY_FLAG_NONE,
664 DPO_ADJACENCY_MCAST, ai_1,
665 DPO_ADJACENCY_MCAST, ai_2,
666 DPO_ADJACENCY_MCAST, ai_3),
668 format_mfib_prefix, pfx_s_g);
671 * update an existing forwarding path to be only accepting
672 * - expect it to be removed from the replication set.
674 mfib_table_entry_path_update(fib_index,
678 MFIB_ITF_FLAG_ACCEPT);
680 MFIB_TEST(mfib_test_entry(mfei,
681 MFIB_ENTRY_FLAG_NONE,
683 DPO_ADJACENCY_MCAST, ai_1,
684 DPO_ADJACENCY_MCAST, ai_2),
686 format_mfib_prefix, pfx_s_g);
687 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
688 MFIB_ITF_FLAG_ACCEPT));
689 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
690 MFIB_ITF_FLAG_FORWARD));
691 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
692 MFIB_ITF_FLAG_FORWARD));
693 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
694 MFIB_ITF_FLAG_ACCEPT));
696 * Make the path forwarding again
697 * - expect it to be added back to the replication set
699 mfib_table_entry_path_update(fib_index,
703 (MFIB_ITF_FLAG_FORWARD |
704 MFIB_ITF_FLAG_ACCEPT |
705 MFIB_ITF_FLAG_NEGATE_SIGNAL));
707 mfei = mfib_table_lookup_exact_match(fib_index,
710 MFIB_TEST(mfib_test_entry(mfei,
711 MFIB_ENTRY_FLAG_NONE,
713 DPO_ADJACENCY_MCAST, ai_1,
714 DPO_ADJACENCY_MCAST, ai_2,
715 DPO_ADJACENCY_MCAST, ai_3),
717 format_mfib_prefix, pfx_s_g);
718 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
719 MFIB_ITF_FLAG_ACCEPT));
720 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
721 MFIB_ITF_FLAG_FORWARD));
722 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
723 MFIB_ITF_FLAG_FORWARD));
724 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
725 (MFIB_ITF_FLAG_FORWARD |
726 MFIB_ITF_FLAG_ACCEPT |
727 MFIB_ITF_FLAG_NEGATE_SIGNAL)));
730 * update flags on the entry
732 mfib_table_entry_update(fib_index,
735 MFIB_ENTRY_FLAG_SIGNAL);
736 MFIB_TEST(mfib_test_entry(mfei,
737 MFIB_ENTRY_FLAG_SIGNAL,
739 DPO_ADJACENCY_MCAST, ai_1,
740 DPO_ADJACENCY_MCAST, ai_2,
741 DPO_ADJACENCY_MCAST, ai_3),
743 format_mfib_prefix, pfx_s_g);
748 mfib_table_entry_path_remove(fib_index,
753 MFIB_TEST(mfib_test_entry(mfei,
754 MFIB_ENTRY_FLAG_SIGNAL,
756 DPO_ADJACENCY_MCAST, ai_1,
757 DPO_ADJACENCY_MCAST, ai_2),
759 format_mfib_prefix, pfx_s_g);
760 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
761 MFIB_ITF_FLAG_ACCEPT));
762 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
763 MFIB_ITF_FLAG_FORWARD));
764 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
765 MFIB_ITF_FLAG_FORWARD));
766 MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
768 mfib_table_entry_path_remove(fib_index,
773 MFIB_TEST(mfib_test_entry(mfei,
774 MFIB_ENTRY_FLAG_SIGNAL,
776 DPO_ADJACENCY_MCAST, ai_2),
778 format_mfib_prefix, pfx_s_g);
779 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
780 MFIB_ITF_FLAG_ACCEPT));
781 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
782 MFIB_ITF_FLAG_FORWARD));
783 MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
786 * remove the accpeting only interface
788 mfib_table_entry_path_remove(fib_index,
793 MFIB_TEST(mfib_test_entry(mfei,
794 MFIB_ENTRY_FLAG_SIGNAL,
796 DPO_ADJACENCY_MCAST, ai_2),
798 format_mfib_prefix, pfx_s_g);
799 MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
800 MFIB_ITF_FLAG_FORWARD));
801 MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[0]->sw_if_index));
802 MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[1]->sw_if_index));
803 MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
806 * remove the last path, the entry still has flags so it remains
808 mfib_table_entry_path_remove(fib_index,
813 MFIB_TEST(mfib_test_entry(mfei,
814 MFIB_ENTRY_FLAG_SIGNAL,
816 "%U no replications",
817 format_mfib_prefix, pfx_s_g);
820 * update flags on the entry
822 mfib_table_entry_update(fib_index,
825 (MFIB_ENTRY_FLAG_SIGNAL |
826 MFIB_ENTRY_FLAG_CONNECTED));
827 MFIB_TEST(mfib_test_entry(mfei,
828 (MFIB_ENTRY_FLAG_SIGNAL |
829 MFIB_ENTRY_FLAG_CONNECTED),
831 "%U no replications",
832 format_mfib_prefix, pfx_s_g);
835 * An entry with a NS interface
837 mfei_g_2 = mfib_table_entry_path_update(fib_index,
841 (MFIB_ITF_FLAG_ACCEPT |
842 MFIB_ITF_FLAG_NEGATE_SIGNAL));
843 MFIB_TEST(mfib_test_entry(mfei_g_2,
844 MFIB_ENTRY_FLAG_NONE,
846 "%U No replications",
847 format_mfib_prefix, pfx_star_g_2);
850 * Simulate a signal from the data-plane
856 mfe = mfib_entry_get(mfei_g_2);
857 mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
859 mfib_signal_push(mfe, mfi, NULL);
863 * An entry with a NS interface
865 mfei_g_3 = mfib_table_entry_path_update(fib_index,
869 (MFIB_ITF_FLAG_ACCEPT |
870 MFIB_ITF_NEGATE_SIGNAL));
871 MFIB_TEST(mfib_test_entry(mfei_g_3,
872 MFIB_ENTRY_FLAG_NONE,
874 "%U No replications",
875 format_mfib_prefix, pfx_star_g_3);
878 * Simulate a signal from the data-plane
884 mfe = mfib_entry_get(mfei_g_3);
885 mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
887 mfib_signal_push(mfe, mfi, NULL);
890 if (FIB_PROTOCOL_IP6 == PROTO)
893 * All the entries are present. let's ensure we can find them all
894 * via exact and longest prefix matches.
897 * A source address we will never match
899 ip6_address_t src = {
900 .as_u64[0] = clib_host_to_net_u64(0x3001000000000000),
901 .as_u64[1] = clib_host_to_net_u64(0xffffffffffffffff),
907 MFIB_TEST((mfei_g_m == ip6_mfib_table_lookup2(
908 ip6_mfib_get(fib_index),
910 &pfx_star_g_slash_m->fp_grp_addr.ip6)),
911 "%U found via DP LPM grp=%U",
912 format_mfib_prefix, pfx_star_g_slash_m,
913 format_ip6_address, &pfx_star_g_slash_m->fp_grp_addr.ip6);
915 ip6_address_t tmp = pfx_star_g_slash_m->fp_grp_addr.ip6;
916 tmp.as_u8[15] = 0xff;
918 MFIB_TEST((mfei_g_m == ip6_mfib_table_lookup2(
919 ip6_mfib_get(fib_index),
920 &pfx_s_g->fp_src_addr.ip6,
922 "%U found via DP LPM grp=%U",
923 format_mfib_prefix, pfx_star_g_slash_m,
924 format_ip6_address, &tmp);
929 mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
930 &pfx_s_g->fp_src_addr.ip6,
931 &pfx_s_g->fp_grp_addr.ip6);
932 MFIB_TEST((mfei_s_g == mfei),
933 "%U found via DP LPM: %d",
934 format_mfib_prefix, pfx_s_g, mfei);
939 mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
941 &pfx_star_g_1->fp_grp_addr.ip6);
942 MFIB_TEST((mfei_g_1 == mfei),
943 "%U found via DP LPM: %d",
944 format_mfib_prefix, pfx_star_g_1, mfei);
945 mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
947 &pfx_star_g_2->fp_grp_addr.ip6);
948 MFIB_TEST((mfei_g_2 == mfei),
949 "%U found via DP LPM: %d",
950 format_mfib_prefix, pfx_star_g_2, mfei);
951 mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
953 &pfx_star_g_3->fp_grp_addr.ip6);
954 MFIB_TEST((mfei_g_3 == mfei),
955 "%U found via DP LPM: %d",
956 format_mfib_prefix, pfx_star_g_3, mfei);
960 * remove flags on the entry. This is the last of the
961 * state associated with the entry, so now it goes.
963 mfib_table_entry_update(fib_index,
966 MFIB_ENTRY_FLAG_NONE);
967 mfei = mfib_table_lookup_exact_match(fib_index,
969 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
971 format_mfib_prefix, pfx_s_g);
974 * remove the last path on the no forward entry - the last entry
976 mfib_table_entry_path_remove(fib_index,
981 mfei = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
982 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
984 format_mfib_prefix, pfx_no_forward);
987 * hard delete the (*,232.1.1.1)
989 mfib_table_entry_delete(fib_index,
993 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
994 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
996 format_mfib_prefix, pfx_star_g_1);
998 * remove the entry whilst the signal is pending
1000 mfib_table_entry_delete(fib_index,
1004 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_2);
1005 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1007 format_mfib_prefix, pfx_star_g_2);
1008 mfib_table_entry_delete(fib_index,
1012 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_3);
1013 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1015 format_mfib_prefix, pfx_star_g_3);
1017 mfib_table_entry_delete(fib_index,
1021 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
1022 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1024 format_mfib_prefix, pfx_star_g_slash_m);
1027 * Unlock the table - it's the last lock so should be gone thereafter
1029 mfib_table_unlock(fib_index, PROTO);
1031 MFIB_TEST((FIB_NODE_INDEX_INVALID ==
1032 mfib_table_find(PROTO, fib_index)),
1033 "MFIB table %d gone", fib_index);
1040 * test we've leaked no resources
1042 MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
1043 MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
1044 n_reps, pool_elts(replicate_pool));
1045 MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
1046 " No more entries %d!=%d",
1047 n_entries, pool_elts(mfib_entry_pool));
1048 MFIB_TEST(n_itfs == pool_elts(mfib_itf_pool),
1049 " No more Interfaces %d!=%d",
1050 n_itfs, pool_elts(mfib_itf_pool));
1058 const mfib_prefix_t pfx_224_s_8 = {
1060 .fp_proto = FIB_PROTOCOL_IP4,
1062 .ip4.as_u32 = clib_host_to_net_u32(0xe0000000),
1065 const mfib_prefix_t pfx_1_1_1_1_c_239_1_1_1 = {
1067 .fp_proto = FIB_PROTOCOL_IP4,
1069 .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1072 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1075 const mfib_prefix_t pfx_239_1_1_1 = {
1077 .fp_proto = FIB_PROTOCOL_IP4,
1079 .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1085 const mfib_prefix_t pfx_239_1_1_2 = {
1087 .fp_proto = FIB_PROTOCOL_IP4,
1089 .ip4.as_u32 = clib_host_to_net_u32(0xef010102),
1095 const mfib_prefix_t pfx_239_1_1_3 = {
1097 .fp_proto = FIB_PROTOCOL_IP4,
1099 .ip4.as_u32 = clib_host_to_net_u32(0xef010103),
1105 const mfib_prefix_t pfx_239 = {
1107 .fp_proto = FIB_PROTOCOL_IP4,
1109 .ip4.as_u32 = clib_host_to_net_u32(0xef000000),
1116 return (mfib_test_i(FIB_PROTOCOL_IP4,
1119 &pfx_1_1_1_1_c_239_1_1_1,
1129 const mfib_prefix_t pfx_ffd_s_12 = {
1131 .fp_proto = FIB_PROTOCOL_IP6,
1133 .ip6.as_u64[0] = clib_host_to_net_u64(0xffd0000000000000),
1136 const mfib_prefix_t pfx_2001_1_c_ff_1 = {
1138 .fp_proto = FIB_PROTOCOL_IP6,
1140 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1141 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1144 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1145 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1148 const mfib_prefix_t pfx_ff_1 = {
1150 .fp_proto = FIB_PROTOCOL_IP6,
1152 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1153 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1156 const mfib_prefix_t pfx_ff_2 = {
1158 .fp_proto = FIB_PROTOCOL_IP6,
1160 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1161 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1164 const mfib_prefix_t pfx_ff_3 = {
1166 * this is the ALL DHCP routers address
1169 .fp_proto = FIB_PROTOCOL_IP6,
1171 .ip6.as_u64[0] = clib_host_to_net_u64(0xff02000100000000),
1172 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1175 const mfib_prefix_t pfx_ff = {
1177 .fp_proto = FIB_PROTOCOL_IP6,
1179 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1180 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000000),
1184 return (mfib_test_i(FIB_PROTOCOL_IP6,
1194 static clib_error_t *
1195 mfib_test (vlib_main_t * vm,
1196 unformat_input_t * input,
1197 vlib_cli_command_t * cmd_arg)
1201 res += mfib_test_mk_intf(4);
1202 res += mfib_test_v4();
1203 res += mfib_test_v6();
1207 return clib_error_return(0, "MFIB Unit Test Failed");
1215 VLIB_CLI_COMMAND (test_fib_command, static) = {
1216 .path = "test mfib",
1217 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
1218 .function = mfib_test,
1222 mfib_test_init (vlib_main_t *vm)
1227 VLIB_INIT_FUNCTION (mfib_test_init);