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", \
38 fformat(stderr, "PASS:%d: " _comment "\n", \
43 #define MFIB_TEST(_cond, _comment, _args...) \
45 if (MFIB_TEST_I(_cond, _comment, ##_args)) { \
47 ASSERT(!("FAIL: " _comment)); \
50 #define MFIB_TEST_NS(_cond) \
52 if (MFIB_TEST_I(_cond, "")) { \
54 ASSERT(!("FAIL: ")); \
59 * A 'i'm not fussed is this is not efficient' store of test data
61 typedef struct test_main_t_ {
65 u32 hw_if_indicies[4];
69 vnet_hw_interface_t * hw[4];
72 static test_main_t test_main;
74 /* fake ethernet device class, distinct from "fake-ethX" */
75 static u8 * format_test_interface_name (u8 * s, va_list * args)
77 u32 dev_instance = va_arg (*args, u32);
78 return format (s, "test-eth%d", dev_instance);
81 static uword dummy_interface_tx (vlib_main_t * vm,
82 vlib_node_runtime_t * node,
85 clib_warning ("you shouldn't be here, leaking buffers...");
86 return frame->n_vectors;
90 test_interface_admin_up_down (vnet_main_t * vnm,
94 u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
95 VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
96 vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
100 VNET_DEVICE_CLASS (test_interface_device_class,static) = {
101 .name = "Test interface",
102 .format_device_name = format_test_interface_name,
103 .tx_function = dummy_interface_tx,
104 .admin_up_down_function = test_interface_admin_up_down,
107 static u8 *hw_address;
110 mfib_test_mk_intf (u32 ninterfaces)
112 clib_error_t * error = NULL;
113 test_main_t *tm = &test_main;
119 ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
124 vec_add1(hw_address, byte);
127 for (i = 0; i < ninterfaces; i++)
131 error = ethernet_register_interface(vnet_get_main(),
132 test_interface_device_class.index,
135 &tm->hw_if_indicies[i],
136 /* flag change */ 0);
138 MFIB_TEST((NULL == error), "ADD interface %d", i);
140 error = vnet_hw_interface_set_flags(vnet_get_main(),
141 tm->hw_if_indicies[i],
142 VNET_HW_INTERFACE_FLAG_LINK_UP);
143 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
144 tm->hw_if_indicies[i]);
145 vec_validate (ip4_main.fib_index_by_sw_if_index,
146 tm->hw[i]->sw_if_index);
147 vec_validate (ip6_main.fib_index_by_sw_if_index,
148 tm->hw[i]->sw_if_index);
149 ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
150 ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
152 vec_validate (ip4_main.mfib_index_by_sw_if_index,
153 tm->hw[i]->sw_if_index);
154 vec_validate (ip6_main.mfib_index_by_sw_if_index,
155 tm->hw[i]->sw_if_index);
156 ip4_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
157 ip6_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
159 error = vnet_sw_interface_set_flags(vnet_get_main(),
160 tm->hw[i]->sw_if_index,
161 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
162 MFIB_TEST((NULL == error), "UP interface %d", i);
165 * re-eval after the inevitable realloc
167 for (i = 0; i < ninterfaces; i++)
169 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
170 tm->hw_if_indicies[i]);
176 #define MFIB_TEST_REP(_cond, _comment, _args...) \
178 if (MFIB_TEST_I(_cond, _comment, ##_args)) { \
184 mfib_test_validate_rep_v (const replicate_t *rep,
195 MFIB_TEST_REP((n_buckets == rep->rep_n_buckets),
196 "n_buckets = %d", rep->rep_n_buckets);
198 for (bucket = 0; bucket < n_buckets; bucket++)
200 dt = va_arg(*ap, int); // type promotion
201 ai = va_arg(*ap, adj_index_t);
202 dpo = replicate_get_bucket_i(rep, bucket);
204 MFIB_TEST_REP((dt == dpo->dpoi_type),
205 "bucket %d stacks on %U",
207 format_dpo_type, dpo->dpoi_type);
209 if (DPO_RECEIVE != dt)
211 MFIB_TEST_REP((ai == dpo->dpoi_index),
212 "bucket %d [exp:%d] stacks on %U",
214 format_dpo_id, dpo, 0);
221 mfib_test_entry (fib_node_index_t fei,
222 mfib_entry_flags_t eflags,
226 const mfib_entry_t *mfe;
227 const replicate_t *rep;
234 mfe = mfib_entry_get(fei);
235 mfib_entry_get_prefix(fei, &pfx);
237 MFIB_TEST_REP((eflags == mfe->mfe_flags),
238 "%U has %U expect %U",
239 format_mfib_prefix, &pfx,
240 format_mfib_entry_flags, mfe->mfe_flags,
241 format_mfib_entry_flags, eflags);
245 MFIB_TEST_REP((DPO_DROP == mfe->mfe_rep.dpoi_type),
247 format_mfib_prefix, &pfx,
248 format_dpo_id, &mfe->mfe_rep, 0);
252 dpo_id_t tmp = DPO_INVALID;
254 mfib_entry_contribute_forwarding(
256 fib_forw_chain_type_from_fib_proto(pfx.fp_proto),
258 rep = replicate_get(tmp.dpoi_index);
260 MFIB_TEST_REP((DPO_REPLICATE == tmp.dpoi_type),
262 format_mfib_prefix, &pfx,
263 format_dpo_type, tmp.dpoi_type);
265 va_start(ap, n_buckets);
266 res = mfib_test_validate_rep_v(rep, n_buckets, &ap);
277 mfib_test_entry_itf (fib_node_index_t fei,
279 mfib_itf_flags_t flags)
281 const mfib_entry_t *mfe;
282 const mfib_itf_t *mfi;
287 mfe = mfib_entry_get(fei);
288 mfi = mfib_entry_get_itf(mfe, sw_if_index);
289 mfib_entry_get_prefix(fei, &pfx);
291 MFIB_TEST_REP((NULL != mfi),
292 "%U has interface %d",
293 format_mfib_prefix, &pfx, sw_if_index);
295 MFIB_TEST_REP((flags == mfi->mfi_flags),
296 "%U interface %d has flags %U expect %U",
297 format_mfib_prefix, &pfx, sw_if_index,
298 format_mfib_itf_flags, flags,
299 format_mfib_itf_flags, mfi->mfi_flags);
305 mfib_test_entry_no_itf (fib_node_index_t fei,
308 const mfib_entry_t *mfe;
309 const mfib_itf_t *mfi;
314 mfe = mfib_entry_get(fei);
315 mfi = mfib_entry_get_itf(mfe, sw_if_index);
316 mfib_entry_get_prefix(fei, &pfx);
318 MFIB_TEST_REP((NULL == mfi),
319 "%U has no interface %d",
320 format_mfib_prefix, &pfx, sw_if_index);
326 mfib_test_i (fib_protocol_t PROTO,
328 const mfib_prefix_t *pfx_no_forward,
329 const mfib_prefix_t *pfx_s_g,
330 const mfib_prefix_t *pfx_star_g_1,
331 const mfib_prefix_t *pfx_star_g_2,
332 const mfib_prefix_t *pfx_star_g_3,
333 const mfib_prefix_t *pfx_star_g_slash_m,
334 const fib_prefix_t *pfx_itf,
335 const ip46_address_t *addr_nbr1,
336 const ip46_address_t *addr_nbr2)
338 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;
339 u32 fib_index, n_entries, n_itfs, n_reps, n_pls;
340 fib_node_index_t ai_1, ai_2, ai_3, ai_nbr1, ai_nbr2;
344 mfib_prefix_t all_1s;
345 clib_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);
363 ai_nbr1 = adj_nbr_add_or_lock(PROTO,
366 tm->hw[0]->sw_if_index);
367 ai_nbr2 = adj_nbr_add_or_lock(PROTO,
370 tm->hw[0]->sw_if_index);
372 MFIB_TEST(3 == adj_mcast_db_size(), "3 MCAST adjs");
374 /* Find or create FIB table 11 */
375 fib_index = mfib_table_find_or_create_and_lock(PROTO, 11, MFIB_SOURCE_API);
377 fib_table_entry_update_one_path(0,
379 FIB_SOURCE_INTERFACE,
380 (FIB_ENTRY_FLAG_CONNECTED |
381 FIB_ENTRY_FLAG_ATTACHED),
384 tm->hw[0]->sw_if_index,
385 ~0, // invalid fib index
388 FIB_ROUTE_PATH_FLAG_NONE);
390 mfib_prefix_t pfx_dft = {
394 mfei_dflt = mfib_table_lookup_exact_match(fib_index, &pfx_dft);
395 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
396 MFIB_TEST(!mfib_test_entry(mfei_dflt,
397 MFIB_ENTRY_FLAG_DROP,
399 "(*,*) no replcaitions");
401 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
402 MFIB_TEST(!mfib_test_entry(mfei_dflt,
403 MFIB_ENTRY_FLAG_DROP,
405 "(*,*) no replcaitions");
408 fib_route_path_t path_via_if0 = {
409 .frp_proto = fib_proto_to_dpo(PROTO),
410 .frp_addr = zero_addr,
411 .frp_sw_if_index = tm->hw[0]->sw_if_index,
417 mfib_table_entry_path_update(fib_index,
421 MFIB_ITF_FLAG_ACCEPT);
423 mfei_no_f = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
424 MFIB_TEST(!mfib_test_entry(mfei_no_f,
425 MFIB_ENTRY_FLAG_NONE,
427 "%U no replcaitions",
428 format_mfib_prefix, pfx_no_forward);
429 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_no_f, tm->hw[0]->sw_if_index,
430 MFIB_ITF_FLAG_ACCEPT));
432 fib_route_path_t path_via_if1 = {
433 .frp_proto = fib_proto_to_dpo(PROTO),
434 .frp_addr = zero_addr,
435 .frp_sw_if_index = tm->hw[1]->sw_if_index,
440 fib_route_path_t path_via_if2 = {
441 .frp_proto = fib_proto_to_dpo(PROTO),
442 .frp_addr = zero_addr,
443 .frp_sw_if_index = tm->hw[2]->sw_if_index,
448 fib_route_path_t path_via_if3 = {
449 .frp_proto = fib_proto_to_dpo(PROTO),
450 .frp_addr = zero_addr,
451 .frp_sw_if_index = tm->hw[3]->sw_if_index,
456 fib_route_path_t path_for_us = {
457 .frp_proto = fib_proto_to_dpo(PROTO),
458 .frp_addr = zero_addr,
459 .frp_sw_if_index = 0xffffffff,
462 .frp_flags = FIB_ROUTE_PATH_LOCAL,
466 * An (S,G) with 1 accepting and 3 forwarding paths
468 mfib_table_entry_path_update(fib_index,
472 MFIB_ITF_FLAG_ACCEPT);
473 mfib_table_entry_path_update(fib_index,
477 MFIB_ITF_FLAG_FORWARD);
478 mfib_table_entry_path_update(fib_index,
482 MFIB_ITF_FLAG_FORWARD);
483 mfib_table_entry_path_update(fib_index,
487 (MFIB_ITF_FLAG_FORWARD |
488 MFIB_ITF_FLAG_NEGATE_SIGNAL));
490 mfei_s_g = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
492 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_s_g,
494 format_mfib_prefix, pfx_s_g);
495 MFIB_TEST(!mfib_test_entry(mfei_s_g,
496 MFIB_ENTRY_FLAG_NONE,
498 DPO_ADJACENCY_MCAST, ai_1,
499 DPO_ADJACENCY_MCAST, ai_2,
500 DPO_ADJACENCY_MCAST, ai_3),
502 format_mfib_prefix, pfx_s_g);
503 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[0]->sw_if_index,
504 MFIB_ITF_FLAG_ACCEPT));
505 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[1]->sw_if_index,
506 MFIB_ITF_FLAG_FORWARD));
507 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[2]->sw_if_index,
508 MFIB_ITF_FLAG_FORWARD));
509 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[3]->sw_if_index,
510 (MFIB_ITF_FLAG_FORWARD |
511 MFIB_ITF_FLAG_NEGATE_SIGNAL)));
514 * A (*,G), which the same G as the (S,G).
515 * different paths. test our LPM.
517 mfei_g_1 = mfib_table_entry_path_update(fib_index,
521 MFIB_ITF_FLAG_ACCEPT);
522 mfib_table_entry_path_update(fib_index,
526 MFIB_ITF_FLAG_FORWARD);
529 * test we find the *,G and S,G via LPM and exact matches
531 mfei = mfib_table_lookup_exact_match(fib_index,
533 MFIB_TEST(mfei == mfei_g_1,
534 "%U found via exact match",
535 format_mfib_prefix, pfx_star_g_1);
536 MFIB_TEST(!mfib_test_entry(mfei,
537 MFIB_ENTRY_FLAG_NONE,
539 DPO_ADJACENCY_MCAST, ai_1),
541 format_mfib_prefix, pfx_star_g_1);
543 mfei = mfib_table_lookup(fib_index,
545 MFIB_TEST(mfei == mfei_g_1,
546 "%U found via LP match",
547 format_mfib_prefix, pfx_star_g_1);
549 MFIB_TEST(!mfib_test_entry(mfei,
550 MFIB_ENTRY_FLAG_NONE,
552 DPO_ADJACENCY_MCAST, ai_1),
554 format_mfib_prefix, pfx_star_g_1);
556 mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
557 MFIB_TEST(mfei == mfei_s_g,
558 "%U found via exact match",
559 format_mfib_prefix, pfx_s_g);
561 MFIB_TEST(!mfib_test_entry(mfei,
562 MFIB_ENTRY_FLAG_NONE,
564 DPO_ADJACENCY_MCAST, ai_1,
565 DPO_ADJACENCY_MCAST, ai_2,
566 DPO_ADJACENCY_MCAST, ai_3),
568 format_mfib_prefix, pfx_s_g);
569 mfei = mfib_table_lookup(fib_index, pfx_s_g);
570 MFIB_TEST(mfei == mfei_s_g,
571 "%U found via LP match",
572 format_mfib_prefix, pfx_s_g);
574 MFIB_TEST(!mfib_test_entry(mfei,
575 MFIB_ENTRY_FLAG_NONE,
577 DPO_ADJACENCY_MCAST, ai_1,
578 DPO_ADJACENCY_MCAST, ai_2,
579 DPO_ADJACENCY_MCAST, ai_3),
581 format_mfib_prefix, pfx_s_g);
584 * A (*,G/m), which the same root G as the (*,G).
585 * different paths. test our LPM.
587 mfei_g_m = mfib_table_entry_path_update(fib_index,
591 MFIB_ITF_FLAG_ACCEPT);
592 mfib_table_entry_path_update(fib_index,
596 MFIB_ITF_FLAG_FORWARD);
599 * test we find the (*,G/m), (*,G) and (S,G) via LPM and exact matches
601 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
602 MFIB_TEST((mfei_g_1 == mfei),
603 "%U found via DP LPM: %d",
604 format_mfib_prefix, pfx_star_g_1, mfei);
606 MFIB_TEST(!mfib_test_entry(mfei,
607 MFIB_ENTRY_FLAG_NONE,
609 DPO_ADJACENCY_MCAST, ai_1),
611 format_mfib_prefix, pfx_star_g_1);
613 mfei = mfib_table_lookup(fib_index, pfx_star_g_1);
615 MFIB_TEST(!mfib_test_entry(mfei,
616 MFIB_ENTRY_FLAG_NONE,
618 DPO_ADJACENCY_MCAST, ai_1),
620 format_mfib_prefix, pfx_star_g_1);
622 mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
624 MFIB_TEST(!mfib_test_entry(mfei,
625 MFIB_ENTRY_FLAG_NONE,
627 DPO_ADJACENCY_MCAST, ai_1,
628 DPO_ADJACENCY_MCAST, ai_2,
629 DPO_ADJACENCY_MCAST, ai_3),
631 format_mfib_prefix, pfx_s_g);
632 mfei = mfib_table_lookup(fib_index, pfx_s_g);
634 MFIB_TEST(!mfib_test_entry(mfei,
635 MFIB_ENTRY_FLAG_NONE,
637 DPO_ADJACENCY_MCAST, ai_1,
638 DPO_ADJACENCY_MCAST, ai_2,
639 DPO_ADJACENCY_MCAST, ai_3),
641 format_mfib_prefix, pfx_s_g);
643 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
644 MFIB_TEST(mfei = mfei_g_m,
645 "%U Found via exact match",
646 format_mfib_prefix, pfx_star_g_slash_m);
647 MFIB_TEST(!mfib_test_entry(mfei,
648 MFIB_ENTRY_FLAG_NONE,
650 DPO_ADJACENCY_MCAST, ai_3),
652 format_mfib_prefix, pfx_star_g_slash_m);
653 MFIB_TEST(mfei_g_m == mfib_table_lookup(fib_index, pfx_star_g_slash_m),
655 format_mfib_prefix, pfx_star_g_slash_m);
660 mfei = mfib_table_entry_path_update(fib_index,
664 MFIB_ITF_FLAG_FORWARD);
666 MFIB_TEST(!mfib_test_entry(mfei,
667 MFIB_ENTRY_FLAG_NONE,
669 DPO_ADJACENCY_MCAST, ai_1,
670 DPO_ADJACENCY_MCAST, ai_2,
671 DPO_ADJACENCY_MCAST, ai_3,
674 format_mfib_prefix, pfx_s_g);
677 * remove a for-us path
679 mfib_table_entry_path_remove(fib_index,
684 MFIB_TEST(!mfib_test_entry(mfei,
685 MFIB_ENTRY_FLAG_NONE,
687 DPO_ADJACENCY_MCAST, ai_1,
688 DPO_ADJACENCY_MCAST, ai_2,
689 DPO_ADJACENCY_MCAST, ai_3),
691 format_mfib_prefix, pfx_s_g);
694 * update an existing forwarding path to be only accepting
695 * - expect it to be removed from the replication set.
697 mfib_table_entry_path_update(fib_index,
701 MFIB_ITF_FLAG_ACCEPT);
703 MFIB_TEST(!mfib_test_entry(mfei,
704 MFIB_ENTRY_FLAG_NONE,
706 DPO_ADJACENCY_MCAST, ai_1,
707 DPO_ADJACENCY_MCAST, ai_2),
709 format_mfib_prefix, pfx_s_g);
710 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
711 MFIB_ITF_FLAG_ACCEPT));
712 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
713 MFIB_ITF_FLAG_FORWARD));
714 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
715 MFIB_ITF_FLAG_FORWARD));
716 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
717 MFIB_ITF_FLAG_ACCEPT));
719 * Make the path forwarding again
720 * - expect it to be added back to the replication set
722 mfib_table_entry_path_update(fib_index,
726 (MFIB_ITF_FLAG_FORWARD |
727 MFIB_ITF_FLAG_ACCEPT |
728 MFIB_ITF_FLAG_NEGATE_SIGNAL));
730 mfei = mfib_table_lookup_exact_match(fib_index,
733 MFIB_TEST(!mfib_test_entry(mfei,
734 MFIB_ENTRY_FLAG_NONE,
736 DPO_ADJACENCY_MCAST, ai_1,
737 DPO_ADJACENCY_MCAST, ai_2,
738 DPO_ADJACENCY_MCAST, ai_3),
740 format_mfib_prefix, pfx_s_g);
741 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
742 MFIB_ITF_FLAG_ACCEPT));
743 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
744 MFIB_ITF_FLAG_FORWARD));
745 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
746 MFIB_ITF_FLAG_FORWARD));
747 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
748 (MFIB_ITF_FLAG_FORWARD |
749 MFIB_ITF_FLAG_ACCEPT |
750 MFIB_ITF_FLAG_NEGATE_SIGNAL)));
753 * update flags on the entry
755 mfib_table_entry_update(fib_index,
759 MFIB_ENTRY_FLAG_SIGNAL);
760 MFIB_TEST(!mfib_test_entry(mfei,
761 MFIB_ENTRY_FLAG_SIGNAL,
763 DPO_ADJACENCY_MCAST, ai_1,
764 DPO_ADJACENCY_MCAST, ai_2,
765 DPO_ADJACENCY_MCAST, ai_3),
767 format_mfib_prefix, pfx_s_g);
772 mfib_table_entry_path_remove(fib_index,
777 MFIB_TEST(!mfib_test_entry(mfei,
778 MFIB_ENTRY_FLAG_SIGNAL,
780 DPO_ADJACENCY_MCAST, ai_1,
781 DPO_ADJACENCY_MCAST, ai_2),
783 format_mfib_prefix, pfx_s_g);
784 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
785 MFIB_ITF_FLAG_ACCEPT));
786 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
787 MFIB_ITF_FLAG_FORWARD));
788 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
789 MFIB_ITF_FLAG_FORWARD));
790 MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
792 mfib_table_entry_path_remove(fib_index,
797 MFIB_TEST(!mfib_test_entry(mfei,
798 MFIB_ENTRY_FLAG_SIGNAL,
800 DPO_ADJACENCY_MCAST, ai_2),
802 format_mfib_prefix, pfx_s_g);
803 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
804 MFIB_ITF_FLAG_ACCEPT));
805 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
806 MFIB_ITF_FLAG_FORWARD));
807 MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
810 * remove the accpeting only interface
812 mfib_table_entry_path_remove(fib_index,
817 MFIB_TEST(!mfib_test_entry(mfei,
818 MFIB_ENTRY_FLAG_SIGNAL,
820 DPO_ADJACENCY_MCAST, ai_2),
822 format_mfib_prefix, pfx_s_g);
823 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
824 MFIB_ITF_FLAG_FORWARD));
825 MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[0]->sw_if_index));
826 MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[1]->sw_if_index));
827 MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
830 * remove the last path, the entry still has flags so it remains
832 mfib_table_entry_path_remove(fib_index,
837 MFIB_TEST(!mfib_test_entry(mfei,
838 MFIB_ENTRY_FLAG_SIGNAL,
840 "%U no replications",
841 format_mfib_prefix, pfx_s_g);
844 * update flags on the entry
846 mfib_table_entry_update(fib_index,
850 (MFIB_ENTRY_FLAG_SIGNAL |
851 MFIB_ENTRY_FLAG_CONNECTED));
852 MFIB_TEST(!mfib_test_entry(mfei,
853 (MFIB_ENTRY_FLAG_SIGNAL |
854 MFIB_ENTRY_FLAG_CONNECTED),
856 "%U no replications",
857 format_mfib_prefix, pfx_s_g);
860 * An entry with a NS interface
862 mfei_g_2 = mfib_table_entry_path_update(fib_index,
866 (MFIB_ITF_FLAG_ACCEPT |
867 MFIB_ITF_FLAG_NEGATE_SIGNAL));
868 MFIB_TEST(!mfib_test_entry(mfei_g_2,
869 MFIB_ENTRY_FLAG_NONE,
871 "%U No replications",
872 format_mfib_prefix, pfx_star_g_2);
875 * Simulate a signal from the data-plane
881 mfe = mfib_entry_get(mfei_g_2);
882 mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
884 mfib_signal_push(mfe, mfi, NULL);
888 * An entry with a NS interface
890 mfei_g_3 = mfib_table_entry_path_update(fib_index,
894 (MFIB_ITF_FLAG_ACCEPT |
895 MFIB_ITF_NEGATE_SIGNAL));
896 MFIB_TEST(!mfib_test_entry(mfei_g_3,
897 MFIB_ENTRY_FLAG_NONE,
899 "%U No replications",
900 format_mfib_prefix, pfx_star_g_3);
903 * Simulate a signal from the data-plane
909 mfe = mfib_entry_get(mfei_g_3);
910 mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
912 mfib_signal_push(mfe, mfi, NULL);
915 if (FIB_PROTOCOL_IP6 == PROTO)
918 * All the entries are present. let's ensure we can find them all
919 * via exact and longest prefix matches.
922 * A source address we will never match
924 ip6_address_t src = {
925 .as_u64[0] = clib_host_to_net_u64(0x3001000000000000),
926 .as_u64[1] = clib_host_to_net_u64(0xffffffffffffffff),
932 MFIB_TEST((mfei_g_m == ip6_mfib_table_lookup2(
933 ip6_mfib_get(fib_index),
935 &pfx_star_g_slash_m->fp_grp_addr.ip6)),
936 "%U found via DP LPM grp=%U",
937 format_mfib_prefix, pfx_star_g_slash_m,
938 format_ip6_address, &pfx_star_g_slash_m->fp_grp_addr.ip6);
940 ip6_address_t tmp = pfx_star_g_slash_m->fp_grp_addr.ip6;
941 tmp.as_u8[15] = 0xff;
943 MFIB_TEST((mfei_g_m == ip6_mfib_table_lookup2(
944 ip6_mfib_get(fib_index),
945 &pfx_s_g->fp_src_addr.ip6,
947 "%U found via DP LPM grp=%U",
948 format_mfib_prefix, pfx_star_g_slash_m,
949 format_ip6_address, &tmp);
954 mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
955 &pfx_s_g->fp_src_addr.ip6,
956 &pfx_s_g->fp_grp_addr.ip6);
957 MFIB_TEST((mfei_s_g == mfei),
958 "%U found via DP LPM: %d",
959 format_mfib_prefix, pfx_s_g, mfei);
964 mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
966 &pfx_star_g_1->fp_grp_addr.ip6);
967 MFIB_TEST((mfei_g_1 == mfei),
968 "%U found via DP LPM: %d",
969 format_mfib_prefix, pfx_star_g_1, mfei);
970 mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
972 &pfx_star_g_2->fp_grp_addr.ip6);
973 MFIB_TEST((mfei_g_2 == mfei),
974 "%U found via DP LPM: %d",
975 format_mfib_prefix, pfx_star_g_2, mfei);
976 mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
978 &pfx_star_g_3->fp_grp_addr.ip6);
979 MFIB_TEST((mfei_g_3 == mfei),
980 "%U found via DP LPM: %d",
981 format_mfib_prefix, pfx_star_g_3, mfei);
985 * remove flags on the entry. This is the last of the
986 * state associated with the entry, so now it goes.
988 mfib_table_entry_update(fib_index,
992 MFIB_ENTRY_FLAG_NONE);
993 mfei = mfib_table_lookup_exact_match(fib_index,
995 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
997 format_mfib_prefix, pfx_s_g);
1000 * remove the last path on the no forward entry - the last entry
1002 mfib_table_entry_path_remove(fib_index,
1007 mfei = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
1008 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1010 format_mfib_prefix, pfx_no_forward);
1013 * hard delete the (*,232.1.1.1)
1015 mfib_table_entry_delete(fib_index,
1019 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
1020 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1022 format_mfib_prefix, pfx_star_g_1);
1024 * remove the entry whilst the signal is pending
1026 mfib_table_entry_delete(fib_index,
1030 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_2);
1031 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1033 format_mfib_prefix, pfx_star_g_2);
1034 mfib_table_entry_delete(fib_index,
1038 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_3);
1039 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1041 format_mfib_prefix, pfx_star_g_3);
1043 mfib_table_entry_delete(fib_index,
1047 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
1048 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1050 format_mfib_prefix, pfx_star_g_slash_m);
1053 * Entries with paths via unicast next-hops
1055 fib_route_path_t path_via_nbr1 = {
1056 .frp_proto = fib_proto_to_dpo(PROTO),
1057 .frp_addr = *addr_nbr1,
1058 .frp_sw_if_index = tm->hw[0]->sw_if_index,
1059 .frp_fib_index = ~0,
1063 fib_route_path_t path_via_nbr2 = {
1064 .frp_proto = fib_proto_to_dpo(PROTO),
1065 .frp_addr = *addr_nbr2,
1066 .frp_sw_if_index = tm->hw[0]->sw_if_index,
1067 .frp_fib_index = ~0,
1072 mfei_g_1 = mfib_table_entry_path_update(fib_index,
1076 (MFIB_ITF_FLAG_FORWARD));
1077 mfei_g_1 = mfib_table_entry_path_update(fib_index,
1081 (MFIB_ITF_FLAG_FORWARD));
1082 MFIB_TEST(!mfib_test_entry(mfei_g_1,
1083 MFIB_ENTRY_FLAG_NONE,
1085 DPO_ADJACENCY_INCOMPLETE, ai_nbr1,
1086 DPO_ADJACENCY_INCOMPLETE, ai_nbr2),
1088 format_mfib_prefix, pfx_star_g_1);
1089 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_g_1, tm->hw[0]->sw_if_index,
1090 MFIB_ITF_FLAG_FORWARD));
1092 mfib_table_entry_path_remove(fib_index,
1097 MFIB_TEST(!mfib_test_entry(mfei_g_1,
1098 MFIB_ENTRY_FLAG_NONE,
1100 DPO_ADJACENCY_INCOMPLETE, ai_nbr2),
1102 format_mfib_prefix, pfx_star_g_1);
1103 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_g_1, tm->hw[0]->sw_if_index,
1104 MFIB_ITF_FLAG_FORWARD));
1106 mfib_table_entry_path_remove(fib_index,
1110 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
1111 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1113 format_mfib_prefix, pfx_star_g_1);
1116 * Add a prefix as a special/exclusive route
1118 dpo_id_t td = DPO_INVALID;
1119 index_t repi = replicate_create(1, fib_proto_to_dpo(PROTO));
1121 dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_2);
1122 replicate_set_bucket(repi, 0, &td);
1124 mfei = mfib_table_entry_special_add(fib_index,
1127 MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF,
1129 MFIB_TEST(!mfib_test_entry(mfei,
1130 (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
1131 MFIB_ENTRY_FLAG_EXCLUSIVE),
1133 DPO_ADJACENCY_MCAST, ai_2),
1134 "%U exclusive replicate OK",
1135 format_mfib_prefix, pfx_star_g_3);
1138 * update a special/exclusive route
1140 index_t repi2 = replicate_create(1, fib_proto_to_dpo(PROTO));
1142 dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_1);
1143 replicate_set_bucket(repi2, 0, &td);
1145 mfei = mfib_table_entry_special_add(fib_index,
1148 MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF,
1150 MFIB_TEST(!mfib_test_entry(mfei,
1151 (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
1152 MFIB_ENTRY_FLAG_EXCLUSIVE),
1154 DPO_ADJACENCY_MCAST, ai_1),
1155 "%U exclusive update replicate OK",
1156 format_mfib_prefix, pfx_star_g_3);
1158 mfib_table_entry_delete(fib_index,
1164 * A Multicast LSP. This a mLDP head-end
1166 fib_node_index_t ai_mpls_10_10_10_1, lfei;
1167 ip46_address_t nh_10_10_10_1 = {
1169 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
1172 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1175 tm->hw[0]->sw_if_index);
1177 fib_prefix_t pfx_3500 = {
1179 .fp_proto = FIB_PROTOCOL_MPLS,
1182 .fp_payload_proto = DPO_PROTO_IP4,
1184 fib_test_rep_bucket_t mc_0 = {
1185 .type = FT_REP_LABEL_O_ADJ,
1187 .adj = ai_mpls_10_10_10_1,
1192 fib_mpls_label_t *l3300 = NULL, fml3300 = {
1195 vec_add1(l3300, fml3300);
1198 * MPLS enable an interface so we get the MPLS table created
1200 mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL);
1201 mpls_sw_interface_enable_disable(&mpls_main,
1202 tm->hw[0]->sw_if_index,
1205 lfei = fib_table_entry_update_one_path(0, // default MPLS Table
1208 FIB_ENTRY_FLAG_MULTICAST,
1211 tm->hw[0]->sw_if_index,
1212 ~0, // invalid fib index
1215 FIB_ROUTE_PATH_FLAG_NONE);
1216 MFIB_TEST(!fib_test_validate_entry(lfei,
1217 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
1220 "3500 via replicate over 10.10.10.1");
1223 * An (S,G) that resolves via the mLDP head-end
1225 fib_route_path_t path_via_mldp = {
1226 .frp_proto = DPO_PROTO_MPLS,
1227 .frp_local_label = pfx_3500.fp_label,
1228 .frp_eos = MPLS_EOS,
1229 .frp_sw_if_index = 0xffffffff,
1232 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
1234 dpo_id_t mldp_dpo = DPO_INVALID;
1236 fib_entry_contribute_forwarding(lfei,
1237 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
1240 mfei = mfib_table_entry_path_update(fib_index,
1244 MFIB_ITF_FLAG_FORWARD);
1246 MFIB_TEST(!mfib_test_entry(mfei,
1247 MFIB_ENTRY_FLAG_NONE,
1249 DPO_REPLICATE, mldp_dpo.dpoi_index),
1250 "%U over-mLDP replicate OK",
1251 format_mfib_prefix, pfx_s_g);
1254 * add a for-us path. this tests two types of non-attached paths on one entry
1256 mfei = mfib_table_entry_path_update(fib_index,
1260 MFIB_ITF_FLAG_FORWARD);
1261 MFIB_TEST(!mfib_test_entry(mfei,
1262 MFIB_ENTRY_FLAG_NONE,
1264 DPO_REPLICATE, mldp_dpo.dpoi_index,
1266 "%U mLDP+for-us replicate OK",
1267 format_mfib_prefix, pfx_s_g);
1269 mfib_table_entry_delete(fib_index,
1272 fib_table_entry_delete(0,
1275 dpo_reset(&mldp_dpo);
1278 * Unlock the table - it's the last lock so should be gone thereafter
1280 mfib_table_unlock(fib_index, PROTO, MFIB_SOURCE_API);
1282 MFIB_TEST((FIB_NODE_INDEX_INVALID ==
1283 mfib_table_find(PROTO, fib_index)),
1284 "MFIB table %d gone", fib_index);
1289 adj_unlock(ai_nbr1);
1290 adj_unlock(ai_nbr2);
1293 * MPLS disable the interface
1295 mpls_sw_interface_enable_disable(&mpls_main,
1296 tm->hw[0]->sw_if_index,
1298 mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
1301 * remove the connected
1303 fib_table_entry_delete(0, pfx_itf, FIB_SOURCE_INTERFACE);
1306 * test we've leaked no resources
1308 MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
1309 MFIB_TEST(n_pls == fib_path_list_pool_size(), "%d=%d path-lists",
1310 n_pls, fib_path_list_pool_size());
1311 MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
1312 n_reps, pool_elts(replicate_pool));
1313 MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
1314 " No more entries %d!=%d",
1315 n_entries, pool_elts(mfib_entry_pool));
1316 MFIB_TEST(n_itfs == pool_elts(mfib_itf_pool),
1317 " No more Interfaces %d!=%d",
1318 n_itfs, pool_elts(mfib_itf_pool));
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,
1496 static clib_error_t *
1497 mfib_test (vlib_main_t * vm,
1498 unformat_input_t * input,
1499 vlib_cli_command_t * cmd_arg)
1503 res += mfib_test_mk_intf(4);
1504 res += mfib_test_v4();
1508 return clib_error_return(0, "MFIB Unit Test Failed");
1511 res += mfib_test_v6();
1515 return clib_error_return(0, "MFIB Unit Test Failed");
1523 VLIB_CLI_COMMAND (test_fib_command, static) = {
1524 .path = "test mfib",
1525 .short_help = "mfib unit tests - DO NOT RUN ON A LIVE SYSTEM",
1526 .function = mfib_test,
1530 mfib_test_init (vlib_main_t *vm)
1535 VLIB_INIT_FUNCTION (mfib_test_init);