2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 #include <vnet/mpls/mpls_types.h>
18 #include <vnet/mfib/mfib_table.h>
19 #include <vnet/mfib/mfib_entry.h>
20 #include <vnet/mfib/mfib_signal.h>
21 #include <vnet/mfib/ip6_mfib.h>
22 #include <vnet/fib/fib_path_list.h>
23 #include <vnet/fib/fib_test.h>
24 #include <vnet/fib/fib_table.h>
25 #include <vnet/fib/mpls_fib.h>
27 #include <vnet/dpo/replicate_dpo.h>
28 #include <vnet/adj/adj_mcast.h>
30 #define MFIB_TEST_I(_cond, _comment, _args...) \
32 int _evald = (_cond); \
34 fformat(stderr, "FAIL:%d: " _comment "\n", \
40 #define MFIB_TEST(_cond, _comment, _args...) \
42 if (MFIB_TEST_I(_cond, _comment, ##_args)) { \
44 ASSERT(!("FAIL: " _comment)); \
47 #define MFIB_TEST_NS(_cond) \
49 if (MFIB_TEST_I(_cond, "")) { \
51 ASSERT(!("FAIL: ")); \
56 * A 'i'm not fussed is this is not efficient' store of test data
58 typedef struct test_main_t_ {
62 u32 hw_if_indicies[4];
66 vnet_hw_interface_t * hw[4];
69 static test_main_t test_main;
71 /* fake ethernet device class, distinct from "fake-ethX" */
72 static u8 * format_test_interface_name (u8 * s, va_list * args)
74 u32 dev_instance = va_arg (*args, u32);
75 return format (s, "test-eth%d", dev_instance);
78 static uword dummy_interface_tx (vlib_main_t * vm,
79 vlib_node_runtime_t * node,
82 clib_warning ("you shouldn't be here, leaking buffers...");
83 return frame->n_vectors;
87 test_interface_admin_up_down (vnet_main_t * vnm,
91 u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
92 VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
93 vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
97 VNET_DEVICE_CLASS (test_interface_device_class,static) = {
98 .name = "Test interface",
99 .format_device_name = format_test_interface_name,
100 .tx_function = dummy_interface_tx,
101 .admin_up_down_function = test_interface_admin_up_down,
104 static u8 *hw_address;
107 mfib_test_mk_intf (u32 ninterfaces)
109 clib_error_t * error = NULL;
110 test_main_t *tm = &test_main;
116 ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
121 vec_add1(hw_address, byte);
124 for (i = 0; i < ninterfaces; i++)
128 error = ethernet_register_interface(vnet_get_main(),
129 test_interface_device_class.index,
132 &tm->hw_if_indicies[i],
133 /* flag change */ 0);
135 MFIB_TEST((NULL == error), "ADD interface %d", i);
137 error = vnet_hw_interface_set_flags(vnet_get_main(),
138 tm->hw_if_indicies[i],
139 VNET_HW_INTERFACE_FLAG_LINK_UP);
140 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
141 tm->hw_if_indicies[i]);
142 vec_validate (ip4_main.fib_index_by_sw_if_index,
143 tm->hw[i]->sw_if_index);
144 vec_validate (ip6_main.fib_index_by_sw_if_index,
145 tm->hw[i]->sw_if_index);
146 ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
147 ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
149 vec_validate (ip4_main.mfib_index_by_sw_if_index,
150 tm->hw[i]->sw_if_index);
151 vec_validate (ip6_main.mfib_index_by_sw_if_index,
152 tm->hw[i]->sw_if_index);
153 ip4_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
154 ip6_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
156 error = vnet_sw_interface_set_flags(vnet_get_main(),
157 tm->hw[i]->sw_if_index,
158 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
159 MFIB_TEST((NULL == error), "UP interface %d", i);
162 * re-eval after the inevitable realloc
164 for (i = 0; i < ninterfaces; i++)
166 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
167 tm->hw_if_indicies[i]);
173 #define MFIB_TEST_REP(_cond, _comment, _args...) \
175 if (MFIB_TEST_I(_cond, _comment, ##_args)) { \
181 mfib_test_validate_rep_v (const replicate_t *rep,
192 MFIB_TEST_REP((n_buckets == rep->rep_n_buckets),
193 "n_buckets = %d", rep->rep_n_buckets);
195 for (bucket = 0; bucket < n_buckets; bucket++)
197 dt = va_arg(*ap, int); // type promotion
198 ai = va_arg(*ap, adj_index_t);
199 dpo = replicate_get_bucket_i(rep, bucket);
201 MFIB_TEST_REP((dt == dpo->dpoi_type),
202 "bucket %d stacks on %U",
204 format_dpo_type, dpo->dpoi_type);
206 if (DPO_RECEIVE != dt)
208 MFIB_TEST_REP((ai == dpo->dpoi_index),
209 "bucket %d [exp:%d] stacks on %U",
211 format_dpo_id, dpo, 0);
218 mfib_test_entry (fib_node_index_t fei,
219 mfib_entry_flags_t eflags,
223 const mfib_prefix_t *pfx;
224 const mfib_entry_t *mfe;
225 const replicate_t *rep;
231 mfe = mfib_entry_get(fei);
232 pfx = mfib_entry_get_prefix(fei);
234 MFIB_TEST_REP((eflags == mfe->mfe_flags),
235 "%U has %U expect %U",
236 format_mfib_prefix, pfx,
237 format_mfib_entry_flags, mfe->mfe_flags,
238 format_mfib_entry_flags, eflags);
242 MFIB_TEST_REP((DPO_DROP == mfe->mfe_rep.dpoi_type),
244 format_mfib_prefix, pfx,
245 format_dpo_id, &mfe->mfe_rep, 0);
249 dpo_id_t tmp = DPO_INVALID;
251 mfib_entry_contribute_forwarding(
253 mfib_forw_chain_type_from_fib_proto(pfx->fp_proto),
254 MFIB_ENTRY_FWD_FLAG_NONE,
256 rep = replicate_get(tmp.dpoi_index);
258 MFIB_TEST_REP((DPO_REPLICATE == tmp.dpoi_type),
260 format_mfib_prefix, pfx,
261 format_dpo_type, tmp.dpoi_type);
263 va_start(ap, n_buckets);
264 res = mfib_test_validate_rep_v(rep, n_buckets, &ap);
275 mfib_test_entry_itf (fib_node_index_t fei,
277 mfib_itf_flags_t flags)
279 const mfib_prefix_t *pfx;
280 const mfib_entry_t *mfe;
281 const mfib_itf_t *mfi;
285 mfe = mfib_entry_get(fei);
286 mfi = mfib_entry_get_itf(mfe, sw_if_index);
287 pfx = mfib_entry_get_prefix(fei);
289 MFIB_TEST_REP((NULL != mfi),
290 "%U has interface %d",
291 format_mfib_prefix, pfx, sw_if_index);
293 MFIB_TEST_REP((flags == mfi->mfi_flags),
294 "%U interface %d has flags %U expect %U",
295 format_mfib_prefix, pfx, sw_if_index,
296 format_mfib_itf_flags, flags,
297 format_mfib_itf_flags, mfi->mfi_flags);
303 mfib_test_entry_no_itf (fib_node_index_t fei,
306 const mfib_prefix_t *pfx;
307 const mfib_entry_t *mfe;
308 const mfib_itf_t *mfi;
312 mfe = mfib_entry_get(fei);
313 mfi = mfib_entry_get_itf(mfe, sw_if_index);
314 pfx = mfib_entry_get_prefix(fei);
316 MFIB_TEST_REP((NULL == mfi),
317 "%U has no interface %d",
318 format_mfib_prefix, pfx, sw_if_index);
324 mfib_test_i (fib_protocol_t PROTO,
326 const mfib_prefix_t *pfx_no_forward,
327 const mfib_prefix_t *pfx_s_g,
328 const mfib_prefix_t *pfx_star_g_1,
329 const mfib_prefix_t *pfx_star_g_2,
330 const mfib_prefix_t *pfx_star_g_3,
331 const mfib_prefix_t *pfx_star_g_slash_m,
332 const fib_prefix_t *pfx_itf,
333 const ip46_address_t *addr_nbr1,
334 const ip46_address_t *addr_nbr2)
336 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;
337 u32 fib_index, n_entries, n_itfs, n_reps, n_pls;
338 fib_node_index_t ai_1, ai_2, ai_3, ai_nbr1, ai_nbr2;
342 mfib_prefix_t all_1s;
343 clib_memset(&all_1s, 0xfd, sizeof(all_1s));
346 n_entries = pool_elts(mfib_entry_pool);
347 n_itfs = pool_elts(mfib_itf_pool);
348 n_reps = pool_elts(replicate_pool);
349 n_pls = fib_path_list_pool_size();
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);
361 ai_nbr1 = adj_nbr_add_or_lock(PROTO,
364 tm->hw[0]->sw_if_index);
365 ai_nbr2 = adj_nbr_add_or_lock(PROTO,
368 tm->hw[0]->sw_if_index);
370 MFIB_TEST(3 == adj_mcast_db_size(), "3 MCAST adjs");
372 /* Find or create FIB table 11 */
373 fib_index = mfib_table_find_or_create_and_lock(PROTO, 11, MFIB_SOURCE_API);
375 fib_table_entry_update_one_path(0,
377 FIB_SOURCE_INTERFACE,
378 (FIB_ENTRY_FLAG_CONNECTED |
379 FIB_ENTRY_FLAG_ATTACHED),
382 tm->hw[0]->sw_if_index,
383 ~0, // invalid fib index
386 FIB_ROUTE_PATH_FLAG_NONE);
388 mfib_prefix_t pfx_dft = {
392 mfei_dflt = mfib_table_lookup_exact_match(fib_index, &pfx_dft);
393 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
394 MFIB_TEST(!mfib_test_entry(mfei_dflt,
395 MFIB_ENTRY_FLAG_DROP,
397 "(*,*) no replcaitions");
399 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
400 MFIB_TEST(!mfib_test_entry(mfei_dflt,
401 MFIB_ENTRY_FLAG_DROP,
403 "(*,*) no replcaitions");
406 fib_route_path_t path_via_if0 = {
407 .frp_proto = fib_proto_to_dpo(PROTO),
408 .frp_addr = zero_addr,
409 .frp_sw_if_index = tm->hw[0]->sw_if_index,
413 .frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT,
416 mfib_table_entry_path_update(fib_index,
421 mfei_no_f = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
422 MFIB_TEST(!mfib_test_entry(mfei_no_f,
423 MFIB_ENTRY_FLAG_NONE,
425 "%U no replcaitions",
426 format_mfib_prefix, pfx_no_forward);
427 MFIB_TEST(!mfib_test_entry_itf(mfei_no_f, tm->hw[0]->sw_if_index,
428 MFIB_ITF_FLAG_ACCEPT),
429 "%U interface not accepting",
430 format_mfib_prefix, pfx_no_forward);
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,
439 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
441 fib_route_path_t path_via_if2 = {
442 .frp_proto = fib_proto_to_dpo(PROTO),
443 .frp_addr = zero_addr,
444 .frp_sw_if_index = tm->hw[2]->sw_if_index,
448 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
450 fib_route_path_t path_via_if3 = {
451 .frp_proto = fib_proto_to_dpo(PROTO),
452 .frp_addr = zero_addr,
453 .frp_sw_if_index = tm->hw[3]->sw_if_index,
457 .frp_mitf_flags = (MFIB_ITF_FLAG_FORWARD |
458 MFIB_ITF_FLAG_NEGATE_SIGNAL),
460 fib_route_path_t *two_paths = NULL;
461 vec_add1(two_paths, path_via_if2);
462 vec_add1(two_paths, path_via_if3);
465 * An (S,G) with 1 accepting and 3 forwarding paths
467 mfib_table_entry_path_update(fib_index,
471 mfib_table_entry_path_update(fib_index,
475 mfib_table_entry_paths_update(fib_index,
480 mfei_s_g = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
482 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_s_g,
484 format_mfib_prefix, pfx_s_g);
485 MFIB_TEST(!mfib_test_entry(mfei_s_g,
486 MFIB_ENTRY_FLAG_NONE,
488 DPO_ADJACENCY_MCAST, ai_1,
489 DPO_ADJACENCY_MCAST, ai_2,
490 DPO_ADJACENCY_MCAST, ai_3),
492 format_mfib_prefix, pfx_s_g);
493 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[0]->sw_if_index,
494 MFIB_ITF_FLAG_ACCEPT));
495 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[1]->sw_if_index,
496 MFIB_ITF_FLAG_FORWARD));
497 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[2]->sw_if_index,
498 MFIB_ITF_FLAG_FORWARD));
499 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[3]->sw_if_index,
500 (MFIB_ITF_FLAG_FORWARD |
501 MFIB_ITF_FLAG_NEGATE_SIGNAL)));
504 * A (*,G), which the same G as the (S,G).
505 * different paths. test our LPM.
507 mfei_g_1 = mfib_table_entry_path_update(fib_index,
511 mfib_table_entry_path_update(fib_index,
517 * test we find the *,G and S,G via LPM and exact matches
519 mfei = mfib_table_lookup_exact_match(fib_index,
521 MFIB_TEST(mfei == mfei_g_1,
522 "%U found via exact match",
523 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(fib_index,
533 MFIB_TEST(mfei == mfei_g_1,
534 "[e:%d a:%d] %U found via LP match",
536 format_mfib_prefix, pfx_star_g_1);
538 MFIB_TEST(!mfib_test_entry(mfei,
539 MFIB_ENTRY_FLAG_NONE,
541 DPO_ADJACENCY_MCAST, ai_1),
543 format_mfib_prefix, pfx_star_g_1);
545 mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
546 MFIB_TEST(mfei == mfei_s_g,
547 "%U found via exact match",
548 format_mfib_prefix, pfx_s_g);
550 MFIB_TEST(!mfib_test_entry(mfei,
551 MFIB_ENTRY_FLAG_NONE,
553 DPO_ADJACENCY_MCAST, ai_1,
554 DPO_ADJACENCY_MCAST, ai_2,
555 DPO_ADJACENCY_MCAST, ai_3),
557 format_mfib_prefix, pfx_s_g);
558 mfei = mfib_table_lookup(fib_index, pfx_s_g);
559 MFIB_TEST(mfei == mfei_s_g,
560 "%U found via LP match",
561 format_mfib_prefix, pfx_s_g);
563 MFIB_TEST(!mfib_test_entry(mfei,
564 MFIB_ENTRY_FLAG_NONE,
566 DPO_ADJACENCY_MCAST, ai_1,
567 DPO_ADJACENCY_MCAST, ai_2,
568 DPO_ADJACENCY_MCAST, ai_3),
570 format_mfib_prefix, pfx_s_g);
573 * A (*,G/m), which the same root G as the (*,G).
574 * different paths. test our LPM.
576 path_via_if2.frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT;
577 mfei_g_m = mfib_table_entry_path_update(fib_index,
581 mfib_table_entry_path_update(fib_index,
587 * test we find the (*,G/m), (*,G) and (S,G) via LPM and exact matches
589 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
590 MFIB_TEST((mfei_g_1 == mfei),
591 "%U found via DP LPM: %d",
592 format_mfib_prefix, pfx_star_g_1, mfei);
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(fib_index, pfx_star_g_1);
603 MFIB_TEST(!mfib_test_entry(mfei,
604 MFIB_ENTRY_FLAG_NONE,
606 DPO_ADJACENCY_MCAST, ai_1),
608 format_mfib_prefix, pfx_star_g_1);
610 mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
612 MFIB_TEST(!mfib_test_entry(mfei,
613 MFIB_ENTRY_FLAG_NONE,
615 DPO_ADJACENCY_MCAST, ai_1,
616 DPO_ADJACENCY_MCAST, ai_2,
617 DPO_ADJACENCY_MCAST, ai_3),
619 format_mfib_prefix, pfx_s_g);
620 mfei = mfib_table_lookup(fib_index, pfx_s_g);
622 MFIB_TEST(!mfib_test_entry(mfei,
623 MFIB_ENTRY_FLAG_NONE,
625 DPO_ADJACENCY_MCAST, ai_1,
626 DPO_ADJACENCY_MCAST, ai_2,
627 DPO_ADJACENCY_MCAST, ai_3),
629 format_mfib_prefix, pfx_s_g);
631 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
632 MFIB_TEST(mfei = mfei_g_m,
633 "%U Found via exact match",
634 format_mfib_prefix, pfx_star_g_slash_m);
635 MFIB_TEST(!mfib_test_entry(mfei,
636 MFIB_ENTRY_FLAG_NONE,
638 DPO_ADJACENCY_MCAST, ai_3),
640 format_mfib_prefix, pfx_star_g_slash_m);
641 MFIB_TEST(mfei_g_m == mfib_table_lookup(fib_index, pfx_star_g_slash_m),
643 format_mfib_prefix, pfx_star_g_slash_m);
648 fib_route_path_t path_for_us = {
649 .frp_proto = fib_proto_to_dpo(PROTO),
650 .frp_addr = zero_addr,
651 .frp_sw_if_index = 0xffffffff,
654 .frp_flags = FIB_ROUTE_PATH_LOCAL,
655 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
658 mfei = mfib_table_entry_path_update(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,
671 format_mfib_prefix, pfx_s_g);
674 * remove a for-us path
676 mfib_table_entry_path_remove(fib_index,
681 MFIB_TEST(!mfib_test_entry(mfei,
682 MFIB_ENTRY_FLAG_NONE,
684 DPO_ADJACENCY_MCAST, ai_1,
685 DPO_ADJACENCY_MCAST, ai_2,
686 DPO_ADJACENCY_MCAST, ai_3),
688 format_mfib_prefix, pfx_s_g);
691 * update an existing forwarding path to be only accepting
692 * - expect it to be removed from the replication set.
694 path_via_if3.frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT;
695 mfib_table_entry_path_update(fib_index,
700 MFIB_TEST(!mfib_test_entry(mfei,
701 MFIB_ENTRY_FLAG_NONE,
703 DPO_ADJACENCY_MCAST, ai_1,
704 DPO_ADJACENCY_MCAST, ai_2),
706 format_mfib_prefix, pfx_s_g);
707 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
708 MFIB_ITF_FLAG_ACCEPT));
709 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
710 MFIB_ITF_FLAG_FORWARD));
711 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
712 MFIB_ITF_FLAG_FORWARD));
713 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
714 MFIB_ITF_FLAG_ACCEPT));
716 * Make the path forwarding again
717 * - expect it to be added back to the replication set
719 path_via_if3.frp_mitf_flags = (MFIB_ITF_FLAG_FORWARD |
720 MFIB_ITF_FLAG_ACCEPT |
721 MFIB_ITF_FLAG_NEGATE_SIGNAL);
722 mfib_table_entry_path_update(fib_index,
727 mfei = mfib_table_lookup_exact_match(fib_index,
730 MFIB_TEST(!mfib_test_entry(mfei,
731 MFIB_ENTRY_FLAG_NONE,
733 DPO_ADJACENCY_MCAST, ai_1,
734 DPO_ADJACENCY_MCAST, ai_2,
735 DPO_ADJACENCY_MCAST, ai_3),
737 format_mfib_prefix, pfx_s_g);
738 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
739 MFIB_ITF_FLAG_ACCEPT));
740 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
741 MFIB_ITF_FLAG_FORWARD));
742 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
743 MFIB_ITF_FLAG_FORWARD));
744 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
745 (MFIB_ITF_FLAG_FORWARD |
746 MFIB_ITF_FLAG_ACCEPT |
747 MFIB_ITF_FLAG_NEGATE_SIGNAL)));
750 * update flags on the entry
752 mfib_table_entry_update(fib_index,
756 MFIB_ENTRY_FLAG_SIGNAL);
757 MFIB_TEST(!mfib_test_entry(mfei,
758 MFIB_ENTRY_FLAG_SIGNAL,
760 DPO_ADJACENCY_MCAST, ai_1,
761 DPO_ADJACENCY_MCAST, ai_2,
762 DPO_ADJACENCY_MCAST, ai_3),
764 format_mfib_prefix, pfx_s_g);
769 mfib_table_entry_path_remove(fib_index,
774 MFIB_TEST(!mfib_test_entry(mfei,
775 MFIB_ENTRY_FLAG_SIGNAL,
777 DPO_ADJACENCY_MCAST, ai_1,
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[1]->sw_if_index,
784 MFIB_ITF_FLAG_FORWARD));
785 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
786 MFIB_ITF_FLAG_FORWARD));
787 MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
789 mfib_table_entry_path_remove(fib_index,
794 MFIB_TEST(!mfib_test_entry(mfei,
795 MFIB_ENTRY_FLAG_SIGNAL,
797 DPO_ADJACENCY_MCAST, ai_2),
799 format_mfib_prefix, pfx_s_g);
800 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
801 MFIB_ITF_FLAG_ACCEPT));
802 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
803 MFIB_ITF_FLAG_FORWARD));
804 MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
809 /* mfib_table_entry_path_remove(fib_index, */
811 /* MFIB_SOURCE_API, */
812 /* &path_via_if0); */
814 /* MFIB_TEST(!mfib_test_entry(mfei, */
815 /* MFIB_ENTRY_FLAG_SIGNAL, */
817 /* DPO_ADJACENCY_MCAST, ai_2), */
818 /* "%U replicate OK", */
819 /* format_mfib_prefix, pfx_s_g); */
820 /* MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index, */
821 /* MFIB_ITF_FLAG_FORWARD)); */
822 /* MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[0]->sw_if_index)); */
823 /* MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[1]->sw_if_index)); */
824 /* MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index)); */
827 * remove the last path and the accpeting only interface,
828 * the entry still has flags so it remains
830 vec_reset_length(two_paths);
831 vec_add1(two_paths, path_via_if0);
832 vec_add1(two_paths, path_via_if2);
834 mfib_table_entry_paths_remove(fib_index,
839 MFIB_TEST(!mfib_test_entry(mfei,
840 MFIB_ENTRY_FLAG_SIGNAL,
842 "%U no replications",
843 format_mfib_prefix, pfx_s_g);
846 * update flags on the entry
848 mfib_table_entry_update(fib_index,
852 (MFIB_ENTRY_FLAG_SIGNAL |
853 MFIB_ENTRY_FLAG_CONNECTED));
854 MFIB_TEST(!mfib_test_entry(mfei,
855 (MFIB_ENTRY_FLAG_SIGNAL |
856 MFIB_ENTRY_FLAG_CONNECTED),
858 "%U no replications",
859 format_mfib_prefix, pfx_s_g);
862 * An entry with a NS interface
864 path_via_if0.frp_mitf_flags = (MFIB_ITF_FLAG_ACCEPT |
865 MFIB_ITF_FLAG_NEGATE_SIGNAL);
866 mfei_g_2 = mfib_table_entry_path_update(fib_index,
870 MFIB_TEST(!mfib_test_entry(mfei_g_2,
871 MFIB_ENTRY_FLAG_NONE,
873 "%U No replications",
874 format_mfib_prefix, pfx_star_g_2);
877 * Simulate a signal from the data-plane
883 mfe = mfib_entry_get(mfei_g_2);
884 mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
886 mfib_signal_push(mfe, mfi, NULL);
890 * An entry with a NS interface
892 path_via_if0.frp_mitf_flags = (MFIB_ITF_FLAG_ACCEPT |
893 MFIB_ITF_FLAG_NEGATE_SIGNAL);
894 mfei_g_3 = mfib_table_entry_path_update(fib_index,
898 MFIB_TEST(!mfib_test_entry(mfei_g_3,
899 MFIB_ENTRY_FLAG_NONE,
901 "%U No replications",
902 format_mfib_prefix, pfx_star_g_3);
905 * Simulate a signal from the data-plane
911 mfe = mfib_entry_get(mfei_g_3);
912 mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
914 mfib_signal_push(mfe, mfi, NULL);
917 if (FIB_PROTOCOL_IP6 == PROTO)
920 * All the entries are present. let's ensure we can find them all
921 * via exact and longest prefix matches.
924 * A source address we will never match
926 ip6_address_t src = {
927 .as_u64[0] = clib_host_to_net_u64(0x3001000000000000),
928 .as_u64[1] = clib_host_to_net_u64(0xffffffffffffffff),
934 MFIB_TEST((mfei_g_m == ip6_mfib_table_fwd_lookup(
935 ip6_mfib_get(fib_index),
937 &pfx_star_g_slash_m->fp_grp_addr.ip6)),
938 "%U found via DP LPM grp=%U",
939 format_mfib_prefix, pfx_star_g_slash_m,
940 format_ip6_address, &pfx_star_g_slash_m->fp_grp_addr.ip6);
942 ip6_address_t tmp = pfx_star_g_slash_m->fp_grp_addr.ip6;
943 tmp.as_u8[15] = 0xff;
945 MFIB_TEST((mfei_g_m == ip6_mfib_table_fwd_lookup(
946 ip6_mfib_get(fib_index),
947 &pfx_s_g->fp_src_addr.ip6,
949 "%U found via DP LPM grp=%U",
950 format_mfib_prefix, pfx_star_g_slash_m,
951 format_ip6_address, &tmp);
956 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
957 &pfx_s_g->fp_src_addr.ip6,
958 &pfx_s_g->fp_grp_addr.ip6);
959 MFIB_TEST((mfei_s_g == mfei),
960 "%U found via DP LPM: %d",
961 format_mfib_prefix, pfx_s_g, mfei);
966 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
968 &pfx_star_g_1->fp_grp_addr.ip6);
969 MFIB_TEST((mfei_g_1 == mfei),
970 "%U found via DP LPM: %d",
971 format_mfib_prefix, pfx_star_g_1, mfei);
972 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
974 &pfx_star_g_2->fp_grp_addr.ip6);
975 MFIB_TEST((mfei_g_2 == mfei),
976 "%U found via DP LPM: %d",
977 format_mfib_prefix, pfx_star_g_2, mfei);
978 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
980 &pfx_star_g_3->fp_grp_addr.ip6);
981 MFIB_TEST((mfei_g_3 == mfei),
982 "%U found via DP LPM: %d",
983 format_mfib_prefix, pfx_star_g_3, mfei);
987 * remove flags on the entry. This is the last of the
988 * state associated with the entry, so now it goes.
990 mfib_table_entry_update(fib_index,
994 MFIB_ENTRY_FLAG_NONE);
995 mfei = mfib_table_lookup_exact_match(fib_index,
997 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
999 format_mfib_prefix, pfx_s_g);
1002 * remove the last path on the no forward entry - the last entry
1004 mfib_table_entry_path_remove(fib_index,
1009 mfei = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
1010 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1012 format_mfib_prefix, pfx_no_forward);
1015 * hard delete the (*,232.1.1.1)
1017 mfib_table_entry_delete(fib_index,
1021 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
1022 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1024 format_mfib_prefix, pfx_star_g_1);
1026 * remove the entry whilst the signal is pending
1028 mfib_table_entry_delete(fib_index,
1032 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_2);
1033 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1035 format_mfib_prefix, pfx_star_g_2);
1036 mfib_table_entry_delete(fib_index,
1040 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_3);
1041 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1043 format_mfib_prefix, pfx_star_g_3);
1045 mfib_table_entry_delete(fib_index,
1049 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
1050 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1052 format_mfib_prefix, pfx_star_g_slash_m);
1055 * Entries with paths via unicast next-hops
1057 fib_route_path_t path_via_nbr1 = {
1058 .frp_proto = fib_proto_to_dpo(PROTO),
1059 .frp_addr = *addr_nbr1,
1060 .frp_sw_if_index = tm->hw[0]->sw_if_index,
1061 .frp_fib_index = ~0,
1064 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1066 fib_route_path_t path_via_nbr2 = {
1067 .frp_proto = fib_proto_to_dpo(PROTO),
1068 .frp_addr = *addr_nbr2,
1069 .frp_sw_if_index = tm->hw[0]->sw_if_index,
1070 .frp_fib_index = ~0,
1073 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1076 mfei_g_1 = mfib_table_entry_path_update(fib_index,
1080 mfei_g_1 = mfib_table_entry_path_update(fib_index,
1084 MFIB_TEST(!mfib_test_entry(mfei_g_1,
1085 MFIB_ENTRY_FLAG_NONE,
1087 DPO_ADJACENCY_INCOMPLETE, ai_nbr1,
1088 DPO_ADJACENCY_INCOMPLETE, ai_nbr2),
1090 format_mfib_prefix, pfx_star_g_1);
1091 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_g_1, tm->hw[0]->sw_if_index,
1092 MFIB_ITF_FLAG_FORWARD));
1094 mfib_table_entry_path_remove(fib_index,
1099 MFIB_TEST(!mfib_test_entry(mfei_g_1,
1100 MFIB_ENTRY_FLAG_NONE,
1102 DPO_ADJACENCY_INCOMPLETE, ai_nbr2),
1104 format_mfib_prefix, pfx_star_g_1);
1105 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_g_1, tm->hw[0]->sw_if_index,
1106 MFIB_ITF_FLAG_FORWARD));
1108 mfib_table_entry_path_remove(fib_index,
1112 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
1113 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1115 format_mfib_prefix, pfx_star_g_1);
1118 * Add a prefix as a special/exclusive route
1120 dpo_id_t td = DPO_INVALID;
1121 index_t repi = replicate_create(1, fib_proto_to_dpo(PROTO));
1123 dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_2);
1124 replicate_set_bucket(repi, 0, &td);
1126 mfei = mfib_table_entry_special_add(fib_index,
1129 MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF,
1131 MFIB_TEST(!mfib_test_entry(mfei,
1132 (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
1133 MFIB_ENTRY_FLAG_EXCLUSIVE),
1135 DPO_ADJACENCY_MCAST, ai_2),
1136 "%U exclusive replicate OK",
1137 format_mfib_prefix, pfx_star_g_3);
1140 * update a special/exclusive route
1142 index_t repi2 = replicate_create(1, fib_proto_to_dpo(PROTO));
1144 dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_1);
1145 replicate_set_bucket(repi2, 0, &td);
1147 mfib_entry_update(mfei,
1149 (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
1150 MFIB_ENTRY_FLAG_EXCLUSIVE),
1153 MFIB_TEST(!mfib_test_entry(mfei,
1154 (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
1155 MFIB_ENTRY_FLAG_EXCLUSIVE),
1157 DPO_ADJACENCY_MCAST, ai_1),
1158 "%U exclusive update replicate OK",
1159 format_mfib_prefix, pfx_star_g_3);
1161 mfib_table_entry_delete(fib_index,
1167 * A Multicast LSP. This a mLDP head-end
1169 fib_node_index_t ai_mpls_10_10_10_1, lfei;
1170 ip46_address_t nh_10_10_10_1 = {
1172 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
1175 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1178 tm->hw[0]->sw_if_index);
1180 fib_prefix_t pfx_3500 = {
1182 .fp_proto = FIB_PROTOCOL_MPLS,
1185 .fp_payload_proto = DPO_PROTO_IP4,
1187 fib_test_rep_bucket_t mc_0 = {
1188 .type = FT_REP_LABEL_O_ADJ,
1190 .adj = ai_mpls_10_10_10_1,
1195 fib_mpls_label_t *l3300 = NULL, fml3300 = {
1198 vec_add1(l3300, fml3300);
1201 * MPLS enable an interface so we get the MPLS table created
1203 mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL);
1204 mpls_sw_interface_enable_disable(&mpls_main,
1205 tm->hw[0]->sw_if_index,
1208 lfei = fib_table_entry_update_one_path(0, // default MPLS Table
1211 FIB_ENTRY_FLAG_MULTICAST,
1214 tm->hw[0]->sw_if_index,
1215 ~0, // invalid fib index
1218 FIB_ROUTE_PATH_FLAG_NONE);
1219 MFIB_TEST(!fib_test_validate_entry(lfei,
1220 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
1223 "3500 via replicate over 10.10.10.1");
1226 * An (S,G) that resolves via the mLDP head-end
1228 fib_route_path_t path_via_mldp = {
1229 .frp_proto = DPO_PROTO_MPLS,
1230 .frp_local_label = pfx_3500.fp_label,
1231 .frp_eos = MPLS_EOS,
1232 .frp_sw_if_index = 0xffffffff,
1235 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
1236 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1238 dpo_id_t mldp_dpo = DPO_INVALID;
1240 fib_entry_contribute_forwarding(lfei,
1241 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
1244 mfei = mfib_table_entry_path_update(fib_index,
1249 MFIB_TEST(!mfib_test_entry(mfei,
1250 MFIB_ENTRY_FLAG_NONE,
1252 DPO_REPLICATE, mldp_dpo.dpoi_index),
1253 "%U over-mLDP replicate OK",
1254 format_mfib_prefix, pfx_s_g);
1257 * add a for-us path. this tests two types of non-attached paths on one entry
1259 mfei = mfib_table_entry_path_update(fib_index,
1263 MFIB_TEST(!mfib_test_entry(mfei,
1264 MFIB_ENTRY_FLAG_NONE,
1266 DPO_REPLICATE, mldp_dpo.dpoi_index,
1268 "%U mLDP+for-us replicate OK",
1269 format_mfib_prefix, pfx_s_g);
1271 mfib_table_entry_delete(fib_index,
1274 fib_table_entry_delete(0,
1277 dpo_reset(&mldp_dpo);
1280 * Unlock the table - it's the last lock so should be gone thereafter
1282 MFIB_TEST(((PROTO == FIB_PROTOCOL_IP4 ? 1 : 5) ==
1283 mfib_table_get_n_routes(fib_index, PROTO)),
1284 "1 = %d route left in the FIB",
1285 mfib_table_get_n_routes(fib_index, PROTO));
1287 mfib_table_unlock(fib_index, PROTO, MFIB_SOURCE_API);
1289 MFIB_TEST((FIB_NODE_INDEX_INVALID ==
1290 mfib_table_find(PROTO, fib_index)),
1291 "MFIB table %d gone", fib_index);
1296 adj_unlock(ai_nbr1);
1297 adj_unlock(ai_nbr2);
1300 * MPLS disable the interface
1302 mpls_sw_interface_enable_disable(&mpls_main,
1303 tm->hw[0]->sw_if_index,
1305 mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
1308 * remove the connected
1310 fib_table_entry_delete(0, pfx_itf, FIB_SOURCE_INTERFACE);
1313 * test we've leaked no resources
1315 MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
1316 MFIB_TEST(n_pls == fib_path_list_pool_size(), "%d=%d path-lists",
1317 n_pls, fib_path_list_pool_size());
1318 MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
1319 n_reps, pool_elts(replicate_pool));
1320 MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
1321 " No more entries %d!=%d",
1322 n_entries, pool_elts(mfib_entry_pool));
1323 MFIB_TEST(n_itfs == pool_elts(mfib_itf_pool),
1324 " No more Interfaces %d!=%d",
1325 n_itfs, pool_elts(mfib_itf_pool));
1326 vec_free(two_paths);
1334 const mfib_prefix_t pfx_224_s_8 = {
1336 .fp_proto = FIB_PROTOCOL_IP4,
1338 .ip4.as_u32 = clib_host_to_net_u32(0xe0000000),
1341 const mfib_prefix_t pfx_1_1_1_1_c_239_1_1_1 = {
1343 .fp_proto = FIB_PROTOCOL_IP4,
1345 .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1348 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1351 const mfib_prefix_t pfx_239_1_1_1 = {
1353 .fp_proto = FIB_PROTOCOL_IP4,
1355 .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1361 const mfib_prefix_t pfx_239_1_1_2 = {
1363 .fp_proto = FIB_PROTOCOL_IP4,
1365 .ip4.as_u32 = clib_host_to_net_u32(0xef010102),
1371 const mfib_prefix_t pfx_239_1_1_3 = {
1373 .fp_proto = FIB_PROTOCOL_IP4,
1375 .ip4.as_u32 = clib_host_to_net_u32(0xef010103),
1381 const mfib_prefix_t pfx_239 = {
1383 .fp_proto = FIB_PROTOCOL_IP4,
1385 .ip4.as_u32 = clib_host_to_net_u32(0xef000000),
1391 const fib_prefix_t pfx_itf = {
1393 .fp_proto = FIB_PROTOCOL_IP4,
1395 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
1398 const ip46_address_t nbr1 = {
1399 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0b),
1401 const ip46_address_t nbr2 = {
1402 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0c),
1404 return (mfib_test_i(FIB_PROTOCOL_IP4,
1407 &pfx_1_1_1_1_c_239_1_1_1,
1420 const mfib_prefix_t pfx_ffd_s_12 = {
1422 .fp_proto = FIB_PROTOCOL_IP6,
1424 .ip6.as_u64[0] = clib_host_to_net_u64(0xffd0000000000000),
1427 const mfib_prefix_t pfx_2001_1_c_ff_1 = {
1429 .fp_proto = FIB_PROTOCOL_IP6,
1431 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1432 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1435 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1436 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1439 const mfib_prefix_t pfx_ff_1 = {
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(0x0000000000000001),
1447 const mfib_prefix_t pfx_ff_2 = {
1449 .fp_proto = FIB_PROTOCOL_IP6,
1451 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1452 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1455 const mfib_prefix_t pfx_ff_3 = {
1457 * this is the ALL DHCP routers address
1460 .fp_proto = FIB_PROTOCOL_IP6,
1462 .ip6.as_u64[0] = clib_host_to_net_u64(0xff02000100000000),
1463 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1466 const mfib_prefix_t pfx_ff = {
1468 .fp_proto = FIB_PROTOCOL_IP6,
1470 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1471 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000000),
1474 const fib_prefix_t pfx_itf = {
1476 .fp_proto = FIB_PROTOCOL_IP6,
1478 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1479 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1482 const ip46_address_t nbr1 = {
1483 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1484 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1486 const ip46_address_t nbr2 = {
1487 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1488 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000003),
1491 return (mfib_test_i(FIB_PROTOCOL_IP6,
1505 mfib_test_rr_i (fib_protocol_t FPROTO,
1508 const mfib_prefix_t *pfx_cover,
1509 const mfib_prefix_t *pfx_host1,
1510 const mfib_prefix_t *pfx_host2)
1512 fib_node_index_t mfei_cover, mfei_host1, mfei_host2, ai_1, ai_2;
1513 u32 fib_index, n_entries, n_itfs, n_reps, n_pls;
1518 n_entries = pool_elts(mfib_entry_pool);
1519 n_itfs = pool_elts(mfib_itf_pool);
1520 n_reps = pool_elts(replicate_pool);
1521 n_pls = fib_path_list_pool_size();
1525 ai_1 = adj_mcast_add_or_lock(FPROTO,
1527 tm->hw[1]->sw_if_index);
1528 ai_2 = adj_mcast_add_or_lock(FPROTO,
1530 tm->hw[2]->sw_if_index);
1532 fib_route_path_t path_via_if0 = {
1533 .frp_proto = DPROTO,
1534 .frp_addr = zero_addr,
1535 .frp_sw_if_index = tm->hw[0]->sw_if_index,
1536 .frp_fib_index = ~0,
1539 .frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT,
1541 fib_route_path_t path_via_if1 = {
1542 .frp_proto = DPROTO,
1543 .frp_addr = zero_addr,
1544 .frp_sw_if_index = tm->hw[1]->sw_if_index,
1545 .frp_fib_index = ~0,
1548 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1550 fib_route_path_t path_via_if2 = {
1551 .frp_proto = DPROTO,
1552 .frp_addr = zero_addr,
1553 .frp_sw_if_index = tm->hw[2]->sw_if_index,
1554 .frp_fib_index = ~0,
1557 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1559 fib_route_path_t path_for_us = {
1560 .frp_proto = DPROTO,
1561 .frp_addr = zero_addr,
1562 .frp_sw_if_index = 0xffffffff,
1563 .frp_fib_index = ~0,
1565 .frp_flags = FIB_ROUTE_PATH_LOCAL,
1566 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1570 * with only the default in place, recusre thru the /32
1572 mfei_host1 = mfib_table_entry_special_add(fib_index, pfx_host1,
1574 MFIB_ENTRY_FLAG_NONE,
1577 * expect its forwarding to match the cover's
1579 MFIB_TEST(!mfib_test_entry(mfei_host1,
1580 MFIB_ENTRY_FLAG_DROP,
1582 "%U no replications OK",
1583 format_mfib_prefix, pfx_host1);
1586 * Insert the less specific /28
1588 mfib_table_entry_path_update(fib_index,
1593 mfei_cover = mfib_table_lookup_exact_match(fib_index, pfx_cover);
1595 MFIB_TEST(!mfib_test_entry(mfei_cover,
1596 MFIB_ENTRY_FLAG_NONE,
1598 DPO_ADJACENCY_MCAST, ai_1),
1600 format_mfib_prefix, pfx_cover);
1603 * expect the /32 forwarding to match the new cover's
1605 MFIB_TEST(!mfib_test_entry(mfei_host1,
1606 MFIB_ENTRY_FLAG_NONE,
1608 DPO_ADJACENCY_MCAST, ai_1),
1610 format_mfib_prefix, pfx_host1);
1613 * add another path to the cover
1615 mfib_table_entry_path_update(fib_index,
1621 * expect the /32 and /28 to be via both boths
1623 MFIB_TEST(!mfib_test_entry(mfei_cover,
1624 MFIB_ENTRY_FLAG_NONE,
1626 DPO_ADJACENCY_MCAST, ai_1,
1627 DPO_ADJACENCY_MCAST, ai_2),
1629 format_mfib_prefix, pfx_cover);
1630 MFIB_TEST(!mfib_test_entry(mfei_host1,
1631 MFIB_ENTRY_FLAG_NONE,
1633 DPO_ADJACENCY_MCAST, ai_1,
1634 DPO_ADJACENCY_MCAST, ai_2),
1636 format_mfib_prefix, pfx_host1);
1639 * and the other host whilst all is ready
1641 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1643 MFIB_ENTRY_FLAG_NONE,
1645 MFIB_TEST(!mfib_test_entry(mfei_host2,
1646 MFIB_ENTRY_FLAG_NONE,
1648 DPO_ADJACENCY_MCAST, ai_1,
1649 DPO_ADJACENCY_MCAST, ai_2),
1651 format_mfib_prefix, pfx_host2);
1654 * repaet multiple time to simulate multiple recursve children
1656 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1658 MFIB_ENTRY_FLAG_NONE,
1660 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1662 MFIB_ENTRY_FLAG_NONE,
1664 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1666 MFIB_ENTRY_FLAG_NONE,
1670 * add an accepting path to the cover
1672 mfib_table_entry_path_update(fib_index,
1678 * expect the /32 and /28 to be via both boths
1680 MFIB_TEST(!mfib_test_entry(mfei_cover,
1681 MFIB_ENTRY_FLAG_NONE,
1683 DPO_ADJACENCY_MCAST, ai_1,
1684 DPO_ADJACENCY_MCAST, ai_2),
1686 format_mfib_prefix, pfx_cover);
1687 MFIB_TEST(!mfib_test_entry(mfei_host1,
1688 MFIB_ENTRY_FLAG_NONE,
1690 DPO_ADJACENCY_MCAST, ai_1,
1691 DPO_ADJACENCY_MCAST, ai_2),
1693 format_mfib_prefix, pfx_cover);
1694 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[0]->sw_if_index,
1695 MFIB_ITF_FLAG_ACCEPT));
1696 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[0]->sw_if_index,
1697 MFIB_ITF_FLAG_ACCEPT));
1698 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[1]->sw_if_index,
1699 MFIB_ITF_FLAG_FORWARD));
1700 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[1]->sw_if_index,
1701 MFIB_ITF_FLAG_FORWARD));
1702 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[2]->sw_if_index,
1703 MFIB_ITF_FLAG_FORWARD));
1704 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[2]->sw_if_index,
1705 MFIB_ITF_FLAG_FORWARD));
1708 * add a for-us path to the cover
1710 mfib_table_entry_path_update(fib_index,
1716 * expect the /32 and /28 to be via all three paths
1718 MFIB_TEST(!mfib_test_entry(mfei_cover,
1719 MFIB_ENTRY_FLAG_NONE,
1721 DPO_ADJACENCY_MCAST, ai_1,
1722 DPO_ADJACENCY_MCAST, ai_2,
1725 format_mfib_prefix, pfx_cover);
1726 MFIB_TEST(!mfib_test_entry(mfei_host1,
1727 MFIB_ENTRY_FLAG_NONE,
1729 DPO_ADJACENCY_MCAST, ai_1,
1730 DPO_ADJACENCY_MCAST, ai_2,
1733 format_mfib_prefix, pfx_cover);
1736 * get the forwarding chain from the RR prefix
1739 dpo_id_t dpo = DPO_INVALID;
1741 mfib_entry_contribute_forwarding(
1743 mfib_forw_chain_type_from_dpo_proto(DPROTO),
1744 MFIB_ENTRY_FWD_FLAG_NONE,
1747 rep = replicate_get(dpo.dpoi_index);
1748 MFIB_TEST((3 == rep->rep_n_buckets),
1749 "%U replicate 3 buckets",
1750 format_mfib_prefix, pfx_host1);
1753 * get the forwarding chain from the RR prefix without local paths
1755 mfib_entry_contribute_forwarding(
1757 mfib_forw_chain_type_from_dpo_proto(DPROTO),
1758 MFIB_ENTRY_FWD_FLAG_NO_LOCAL,
1761 rep = replicate_get(dpo.dpoi_index);
1762 MFIB_TEST((2 == rep->rep_n_buckets),
1763 "%U no-local replicate 2 buckets",
1764 format_mfib_prefix, pfx_host1);
1769 * delete the cover, expect the /32 to be via the default
1771 mfib_table_entry_delete(fib_index, pfx_cover, MFIB_SOURCE_API);
1772 MFIB_TEST(!mfib_test_entry(mfei_host1,
1773 MFIB_ENTRY_FLAG_DROP,
1775 "%U no replications OK",
1776 format_mfib_prefix, pfx_host1);
1779 * source the /32 with its own path
1781 mfei_host1 = mfib_table_entry_path_update(fib_index,
1785 MFIB_TEST(!mfib_test_entry(mfei_host1,
1786 MFIB_ENTRY_FLAG_NONE,
1788 DPO_ADJACENCY_MCAST, ai_2),
1790 format_mfib_prefix, pfx_host1);
1793 * remove host2 - as many times as it was added
1795 mfib_table_entry_delete(fib_index, pfx_host2,
1797 mfib_table_entry_delete(fib_index, pfx_host2,
1799 mfib_table_entry_delete(fib_index, pfx_host2,
1801 mfib_table_entry_delete(fib_index, pfx_host2,
1806 * remove the RR source with paths present
1808 mfib_table_entry_delete(fib_index, pfx_host1,
1812 * add the RR back then remove the path and RR
1814 mfei_host1 = mfib_table_entry_path_update(fib_index,
1818 MFIB_TEST(!mfib_test_entry(mfei_host1,
1819 MFIB_ENTRY_FLAG_NONE,
1821 DPO_ADJACENCY_MCAST, ai_2),
1823 format_mfib_prefix, pfx_host1);
1825 mfib_table_entry_delete(fib_index, pfx_host1,
1827 mfib_table_entry_delete(fib_index, pfx_host1,
1831 * test we've leaked no resources
1835 MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
1836 MFIB_TEST(n_pls == fib_path_list_pool_size(), "%d=%d path-lists",
1837 n_pls, fib_path_list_pool_size());
1838 MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
1839 n_reps, pool_elts(replicate_pool));
1840 MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
1841 " No more entries %d!=%d",
1842 n_entries, pool_elts(mfib_entry_pool));
1843 MFIB_TEST(n_itfs == pool_elts(mfib_itf_pool),
1844 " No more Interfaces %d!=%d",
1845 n_itfs, pool_elts(mfib_itf_pool));
1850 mfib_test_rr_v4 (void)
1853 * 2 length of prefix to play with
1855 const mfib_prefix_t pfx_host1 = {
1857 .fp_proto = FIB_PROTOCOL_IP4,
1859 .ip4.as_u32 = clib_host_to_net_u32(0xe0001011),
1862 const mfib_prefix_t pfx_host2 = {
1864 .fp_proto = FIB_PROTOCOL_IP4,
1866 .ip4.as_u32 = clib_host_to_net_u32(0xe0001011),
1869 .ip4.as_u32 = clib_host_to_net_u32(0x10101010),
1872 const mfib_prefix_t pfx_cover = {
1874 .fp_proto = FIB_PROTOCOL_IP4,
1876 .ip4.as_u32 = clib_host_to_net_u32(0xe0001010),
1880 return (mfib_test_rr_i(FIB_PROTOCOL_IP4,
1889 mfib_test_rr_v6 (void)
1892 * 2 length of prefix to play with
1894 const mfib_prefix_t pfx_host1 = {
1896 .fp_proto = FIB_PROTOCOL_IP6,
1898 .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
1899 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1902 const mfib_prefix_t pfx_host2 = {
1904 .fp_proto = FIB_PROTOCOL_IP6,
1906 .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
1907 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1910 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1911 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1914 const mfib_prefix_t pfx_cover = {
1916 .fp_proto = FIB_PROTOCOL_IP6,
1918 .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
1919 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000000),
1923 return (mfib_test_rr_i(FIB_PROTOCOL_IP6,
1931 static clib_error_t *
1932 mfib_test (vlib_main_t * vm,
1933 unformat_input_t * input,
1934 vlib_cli_command_t * cmd_arg)
1938 res += mfib_test_mk_intf(4);
1939 res += mfib_test_rr_v4();
1943 return clib_error_return(0, "MFIB RR V4 Unit Test Failed");
1946 res += mfib_test_rr_v6();
1950 return clib_error_return(0, "MFIB RR V6 Unit Test Failed");
1953 res += mfib_test_v4();
1957 return clib_error_return(0, "MFIB V4 Unit Test Failed");
1960 res += mfib_test_v6();
1964 return clib_error_return(0, "MFIB V6 Unit Test Failed");
1970 VLIB_CLI_COMMAND (test_fib_command, static) = {
1971 .path = "test mfib",
1972 .short_help = "mfib unit tests - DO NOT RUN ON A LIVE SYSTEM",
1973 .function = mfib_test,
1977 mfib_test_init (vlib_main_t *vm)
1982 VLIB_INIT_FUNCTION (mfib_test_init);