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 placeholder_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 = placeholder_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 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 ip4_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
146 ip6_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
148 error = vnet_sw_interface_set_flags(vnet_get_main(),
149 tm->hw[i]->sw_if_index,
150 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
151 MFIB_TEST((NULL == error), "UP interface %d", i);
154 * re-eval after the inevitable realloc
156 for (i = 0; i < ninterfaces; i++)
158 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
159 tm->hw_if_indicies[i]);
165 #define MFIB_TEST_REP(_cond, _comment, _args...) \
167 if (MFIB_TEST_I(_cond, _comment, ##_args)) { \
173 mfib_test_validate_rep_v (const replicate_t *rep,
184 MFIB_TEST_REP((n_buckets == rep->rep_n_buckets),
185 "n_buckets = %d", rep->rep_n_buckets);
187 for (bucket = 0; bucket < n_buckets; bucket++)
189 dt = va_arg(*ap, int); // type promotion
190 ai = va_arg(*ap, adj_index_t);
191 dpo = replicate_get_bucket_i(rep, bucket);
193 MFIB_TEST_REP((dt == dpo->dpoi_type),
194 "bucket %d stacks on %U",
196 format_dpo_type, dpo->dpoi_type);
198 if (DPO_RECEIVE != dt)
200 MFIB_TEST_REP((ai == dpo->dpoi_index),
201 "bucket %d [exp:%d] stacks on %U",
203 format_dpo_id, dpo, 0);
210 mfib_test_entry (fib_node_index_t fei,
211 mfib_entry_flags_t eflags,
215 const mfib_prefix_t *pfx;
216 const mfib_entry_t *mfe;
217 const replicate_t *rep;
223 mfe = mfib_entry_get(fei);
224 pfx = mfib_entry_get_prefix(fei);
226 MFIB_TEST_REP((eflags == mfe->mfe_flags),
227 "%U has %U expect %U",
228 format_mfib_prefix, pfx,
229 format_mfib_entry_flags, mfe->mfe_flags,
230 format_mfib_entry_flags, eflags);
234 MFIB_TEST_REP((DPO_DROP == mfe->mfe_rep.dpoi_type),
236 format_mfib_prefix, pfx,
237 format_dpo_id, &mfe->mfe_rep, 0);
241 dpo_id_t tmp = DPO_INVALID;
243 mfib_entry_contribute_forwarding(
245 mfib_forw_chain_type_from_fib_proto(pfx->fp_proto),
246 MFIB_ENTRY_FWD_FLAG_NONE,
248 rep = replicate_get(tmp.dpoi_index);
250 MFIB_TEST_REP((DPO_REPLICATE == tmp.dpoi_type),
252 format_mfib_prefix, pfx,
253 format_dpo_type, tmp.dpoi_type);
255 va_start(ap, n_buckets);
256 res = mfib_test_validate_rep_v(rep, n_buckets, &ap);
267 mfib_test_entry_itf (fib_node_index_t fei,
269 mfib_itf_flags_t flags)
271 const mfib_prefix_t *pfx;
272 const mfib_entry_t *mfe;
273 const mfib_itf_t *mfi;
277 mfe = mfib_entry_get(fei);
278 mfi = mfib_entry_get_itf(mfe, sw_if_index);
279 pfx = mfib_entry_get_prefix(fei);
281 MFIB_TEST_REP((NULL != mfi),
282 "%U has interface %d",
283 format_mfib_prefix, pfx, sw_if_index);
285 MFIB_TEST_REP((flags == mfi->mfi_flags),
286 "%U interface %d has flags %U expect %U",
287 format_mfib_prefix, pfx, sw_if_index,
288 format_mfib_itf_flags, flags,
289 format_mfib_itf_flags, mfi->mfi_flags);
295 mfib_test_entry_no_itf (fib_node_index_t fei,
298 const mfib_prefix_t *pfx;
299 const mfib_entry_t *mfe;
300 const mfib_itf_t *mfi;
304 mfe = mfib_entry_get(fei);
305 mfi = mfib_entry_get_itf(mfe, sw_if_index);
306 pfx = mfib_entry_get_prefix(fei);
308 MFIB_TEST_REP((NULL == mfi),
309 "%U has no interface %d",
310 format_mfib_prefix, pfx, sw_if_index);
316 mfib_test_i (fib_protocol_t PROTO,
318 const mfib_prefix_t *pfx_no_forward,
319 const mfib_prefix_t *pfx_s_g,
320 const mfib_prefix_t *pfx_star_g_1,
321 const mfib_prefix_t *pfx_star_g_2,
322 const mfib_prefix_t *pfx_star_g_3,
323 const mfib_prefix_t *pfx_star_g_slash_m,
324 const fib_prefix_t *pfx_itf,
325 const ip46_address_t *addr_nbr1,
326 const ip46_address_t *addr_nbr2)
328 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;
329 u32 fib_index, n_entries, n_itfs, n_reps, n_pls;
330 fib_node_index_t ai_1, ai_2, ai_3, ai_nbr1, ai_nbr2;
334 mfib_prefix_t all_1s;
335 clib_memset(&all_1s, 0xfd, sizeof(all_1s));
338 n_entries = pool_elts(mfib_entry_pool);
339 n_itfs = pool_elts(mfib_itf_pool);
340 n_reps = pool_elts(replicate_pool);
341 n_pls = fib_path_list_pool_size();
344 ai_1 = adj_mcast_add_or_lock(PROTO,
346 tm->hw[1]->sw_if_index);
347 ai_2 = adj_mcast_add_or_lock(PROTO,
349 tm->hw[2]->sw_if_index);
350 ai_3 = adj_mcast_add_or_lock(PROTO,
352 tm->hw[3]->sw_if_index);
353 ai_nbr1 = adj_nbr_add_or_lock(PROTO,
356 tm->hw[0]->sw_if_index);
357 ai_nbr2 = adj_nbr_add_or_lock(PROTO,
360 tm->hw[0]->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, MFIB_SOURCE_API);
367 fib_table_entry_update_one_path(0,
369 FIB_SOURCE_INTERFACE,
370 (FIB_ENTRY_FLAG_CONNECTED |
371 FIB_ENTRY_FLAG_ATTACHED),
374 tm->hw[0]->sw_if_index,
375 ~0, // invalid fib index
378 FIB_ROUTE_PATH_FLAG_NONE);
380 mfib_prefix_t pfx_dft = {
384 mfei_dflt = mfib_table_lookup_exact_match(fib_index, &pfx_dft);
385 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
386 MFIB_TEST(!mfib_test_entry(mfei_dflt,
387 MFIB_ENTRY_FLAG_DROP,
389 "(*,*) no replcaitions");
391 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
392 MFIB_TEST(!mfib_test_entry(mfei_dflt,
393 MFIB_ENTRY_FLAG_DROP,
395 "(*,*) no replcaitions");
398 fib_route_path_t path_via_if0 = {
399 .frp_proto = fib_proto_to_dpo(PROTO),
400 .frp_addr = zero_addr,
401 .frp_sw_if_index = tm->hw[0]->sw_if_index,
405 .frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT,
408 mfib_table_entry_path_update (fib_index, pfx_no_forward, MFIB_SOURCE_API,
409 MFIB_ENTRY_FLAG_NONE, &path_via_if0);
411 mfei_no_f = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
412 MFIB_TEST(!mfib_test_entry(mfei_no_f,
413 MFIB_ENTRY_FLAG_NONE,
415 "%U no replcaitions",
416 format_mfib_prefix, pfx_no_forward);
417 MFIB_TEST(!mfib_test_entry_itf(mfei_no_f, tm->hw[0]->sw_if_index,
418 MFIB_ITF_FLAG_ACCEPT),
419 "%U interface not accepting",
420 format_mfib_prefix, pfx_no_forward);
422 fib_route_path_t path_via_if1 = {
423 .frp_proto = fib_proto_to_dpo(PROTO),
424 .frp_addr = zero_addr,
425 .frp_sw_if_index = tm->hw[1]->sw_if_index,
429 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
431 fib_route_path_t path_via_if2 = {
432 .frp_proto = fib_proto_to_dpo(PROTO),
433 .frp_addr = zero_addr,
434 .frp_sw_if_index = tm->hw[2]->sw_if_index,
438 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
440 fib_route_path_t path_via_if3 = {
441 .frp_proto = fib_proto_to_dpo(PROTO),
442 .frp_addr = zero_addr,
443 .frp_sw_if_index = tm->hw[3]->sw_if_index,
447 .frp_mitf_flags = (MFIB_ITF_FLAG_FORWARD |
448 MFIB_ITF_FLAG_NEGATE_SIGNAL),
450 fib_route_path_t *two_paths = NULL;
451 vec_add1(two_paths, path_via_if2);
452 vec_add1(two_paths, path_via_if3);
455 * An (S,G) with 1 accepting and 3 forwarding paths
457 mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
458 MFIB_ENTRY_FLAG_NONE, &path_via_if0);
459 mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
460 MFIB_ENTRY_FLAG_NONE, &path_via_if1);
461 mfib_table_entry_paths_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
462 MFIB_ENTRY_FLAG_NONE, two_paths);
464 mfei_s_g = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
466 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_s_g,
468 format_mfib_prefix, pfx_s_g);
469 MFIB_TEST(!mfib_test_entry(mfei_s_g,
470 MFIB_ENTRY_FLAG_NONE,
472 DPO_ADJACENCY_MCAST, ai_1,
473 DPO_ADJACENCY_MCAST, ai_2,
474 DPO_ADJACENCY_MCAST, ai_3),
476 format_mfib_prefix, pfx_s_g);
477 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[0]->sw_if_index,
478 MFIB_ITF_FLAG_ACCEPT));
479 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[1]->sw_if_index,
480 MFIB_ITF_FLAG_FORWARD));
481 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[2]->sw_if_index,
482 MFIB_ITF_FLAG_FORWARD));
483 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[3]->sw_if_index,
484 (MFIB_ITF_FLAG_FORWARD |
485 MFIB_ITF_FLAG_NEGATE_SIGNAL)));
488 * A (*,G), which the same G as the (S,G).
489 * different paths. test our LPM.
492 mfib_table_entry_path_update (fib_index, pfx_star_g_1, MFIB_SOURCE_API,
493 MFIB_ENTRY_FLAG_NONE, &path_via_if0);
494 mfib_table_entry_path_update (fib_index, pfx_star_g_1, MFIB_SOURCE_API,
495 MFIB_ENTRY_FLAG_NONE, &path_via_if1);
498 * test we find the *,G and S,G via LPM and exact matches
500 mfei = mfib_table_lookup_exact_match(fib_index,
502 MFIB_TEST(mfei == mfei_g_1,
503 "%U found via exact match",
504 format_mfib_prefix, pfx_star_g_1);
505 MFIB_TEST(!mfib_test_entry(mfei,
506 MFIB_ENTRY_FLAG_NONE,
508 DPO_ADJACENCY_MCAST, ai_1),
510 format_mfib_prefix, pfx_star_g_1);
512 mfei = mfib_table_lookup(fib_index,
514 MFIB_TEST(mfei == mfei_g_1,
515 "[e:%d a:%d] %U found via LP match",
517 format_mfib_prefix, pfx_star_g_1);
519 MFIB_TEST(!mfib_test_entry(mfei,
520 MFIB_ENTRY_FLAG_NONE,
522 DPO_ADJACENCY_MCAST, ai_1),
524 format_mfib_prefix, pfx_star_g_1);
526 mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
527 MFIB_TEST(mfei == mfei_s_g,
528 "%U found via exact match",
529 format_mfib_prefix, pfx_s_g);
531 MFIB_TEST(!mfib_test_entry(mfei,
532 MFIB_ENTRY_FLAG_NONE,
534 DPO_ADJACENCY_MCAST, ai_1,
535 DPO_ADJACENCY_MCAST, ai_2,
536 DPO_ADJACENCY_MCAST, ai_3),
538 format_mfib_prefix, pfx_s_g);
539 mfei = mfib_table_lookup(fib_index, pfx_s_g);
540 MFIB_TEST(mfei == mfei_s_g,
541 "%U found via LP match",
542 format_mfib_prefix, pfx_s_g);
544 MFIB_TEST(!mfib_test_entry(mfei,
545 MFIB_ENTRY_FLAG_NONE,
547 DPO_ADJACENCY_MCAST, ai_1,
548 DPO_ADJACENCY_MCAST, ai_2,
549 DPO_ADJACENCY_MCAST, ai_3),
551 format_mfib_prefix, pfx_s_g);
554 * A (*,G/m), which the same root G as the (*,G).
555 * different paths. test our LPM.
557 path_via_if2.frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT;
558 mfei_g_m = mfib_table_entry_path_update (
559 fib_index, pfx_star_g_slash_m, MFIB_SOURCE_API, MFIB_ENTRY_FLAG_NONE,
561 mfib_table_entry_path_update (fib_index, pfx_star_g_slash_m,
562 MFIB_SOURCE_API, MFIB_ENTRY_FLAG_NONE,
566 * test we find the (*,G/m), (*,G) and (S,G) via LPM and exact matches
568 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
569 MFIB_TEST((mfei_g_1 == mfei),
570 "%U found via DP LPM: %d",
571 format_mfib_prefix, pfx_star_g_1, mfei);
573 MFIB_TEST(!mfib_test_entry(mfei,
574 MFIB_ENTRY_FLAG_NONE,
576 DPO_ADJACENCY_MCAST, ai_1),
578 format_mfib_prefix, pfx_star_g_1);
580 mfei = mfib_table_lookup(fib_index, pfx_star_g_1);
582 MFIB_TEST(!mfib_test_entry(mfei,
583 MFIB_ENTRY_FLAG_NONE,
585 DPO_ADJACENCY_MCAST, ai_1),
587 format_mfib_prefix, pfx_star_g_1);
589 mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
591 MFIB_TEST(!mfib_test_entry(mfei,
592 MFIB_ENTRY_FLAG_NONE,
594 DPO_ADJACENCY_MCAST, ai_1,
595 DPO_ADJACENCY_MCAST, ai_2,
596 DPO_ADJACENCY_MCAST, ai_3),
598 format_mfib_prefix, pfx_s_g);
599 mfei = mfib_table_lookup(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);
610 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
611 MFIB_TEST(mfei = mfei_g_m,
612 "%U Found via exact match",
613 format_mfib_prefix, pfx_star_g_slash_m);
614 MFIB_TEST(!mfib_test_entry(mfei,
615 MFIB_ENTRY_FLAG_NONE,
617 DPO_ADJACENCY_MCAST, ai_3),
619 format_mfib_prefix, pfx_star_g_slash_m);
620 MFIB_TEST(mfei_g_m == mfib_table_lookup(fib_index, pfx_star_g_slash_m),
622 format_mfib_prefix, pfx_star_g_slash_m);
627 fib_route_path_t path_for_us = {
628 .frp_proto = fib_proto_to_dpo(PROTO),
629 .frp_addr = zero_addr,
630 .frp_sw_if_index = 0xffffffff,
633 .frp_flags = FIB_ROUTE_PATH_LOCAL,
634 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
637 mfei = mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
638 MFIB_ENTRY_FLAG_NONE, &path_for_us);
640 MFIB_TEST(!mfib_test_entry(mfei,
641 MFIB_ENTRY_FLAG_NONE,
643 DPO_ADJACENCY_MCAST, ai_1,
644 DPO_ADJACENCY_MCAST, ai_2,
645 DPO_ADJACENCY_MCAST, ai_3,
648 format_mfib_prefix, pfx_s_g);
651 * remove a for-us path
653 mfib_table_entry_path_remove(fib_index,
658 MFIB_TEST(!mfib_test_entry(mfei,
659 MFIB_ENTRY_FLAG_NONE,
661 DPO_ADJACENCY_MCAST, ai_1,
662 DPO_ADJACENCY_MCAST, ai_2,
663 DPO_ADJACENCY_MCAST, ai_3),
665 format_mfib_prefix, pfx_s_g);
668 * update an existing forwarding path to be only accepting
669 * - expect it to be removed from the replication set.
671 path_via_if3.frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT;
672 mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
673 MFIB_ENTRY_FLAG_NONE, &path_via_if3);
675 MFIB_TEST(!mfib_test_entry(mfei,
676 MFIB_ENTRY_FLAG_NONE,
678 DPO_ADJACENCY_MCAST, ai_1,
679 DPO_ADJACENCY_MCAST, ai_2),
681 format_mfib_prefix, pfx_s_g);
682 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
683 MFIB_ITF_FLAG_ACCEPT));
684 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
685 MFIB_ITF_FLAG_FORWARD));
686 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
687 MFIB_ITF_FLAG_FORWARD));
688 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
689 MFIB_ITF_FLAG_ACCEPT));
691 * Make the path forwarding again
692 * - expect it to be added back to the replication set
694 path_via_if3.frp_mitf_flags = (MFIB_ITF_FLAG_FORWARD |
695 MFIB_ITF_FLAG_ACCEPT |
696 MFIB_ITF_FLAG_NEGATE_SIGNAL);
697 mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
698 MFIB_ENTRY_FLAG_NONE, &path_via_if3);
700 mfei = mfib_table_lookup_exact_match(fib_index,
703 MFIB_TEST(!mfib_test_entry(mfei,
704 MFIB_ENTRY_FLAG_NONE,
706 DPO_ADJACENCY_MCAST, ai_1,
707 DPO_ADJACENCY_MCAST, ai_2,
708 DPO_ADJACENCY_MCAST, ai_3),
710 format_mfib_prefix, pfx_s_g);
711 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
712 MFIB_ITF_FLAG_ACCEPT));
713 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
714 MFIB_ITF_FLAG_FORWARD));
715 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
716 MFIB_ITF_FLAG_FORWARD));
717 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
718 (MFIB_ITF_FLAG_FORWARD |
719 MFIB_ITF_FLAG_ACCEPT |
720 MFIB_ITF_FLAG_NEGATE_SIGNAL)));
723 * update flags on the entry
725 mfib_table_entry_update(fib_index,
729 MFIB_ENTRY_FLAG_SIGNAL);
730 MFIB_TEST(!mfib_test_entry(mfei,
731 MFIB_ENTRY_FLAG_SIGNAL,
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);
742 mfib_table_entry_path_remove(fib_index,
747 MFIB_TEST(!mfib_test_entry(mfei,
748 MFIB_ENTRY_FLAG_SIGNAL,
750 DPO_ADJACENCY_MCAST, ai_1,
751 DPO_ADJACENCY_MCAST, ai_2),
753 format_mfib_prefix, pfx_s_g);
754 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
755 MFIB_ITF_FLAG_ACCEPT));
756 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
757 MFIB_ITF_FLAG_FORWARD));
758 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
759 MFIB_ITF_FLAG_FORWARD));
760 MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
762 mfib_table_entry_path_remove(fib_index,
767 MFIB_TEST(!mfib_test_entry(mfei,
768 MFIB_ENTRY_FLAG_SIGNAL,
770 DPO_ADJACENCY_MCAST, ai_2),
772 format_mfib_prefix, pfx_s_g);
773 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
774 MFIB_ITF_FLAG_ACCEPT));
775 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
776 MFIB_ITF_FLAG_FORWARD));
777 MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
782 /* mfib_table_entry_path_remove(fib_index, */
784 /* MFIB_SOURCE_API, */
785 /* &path_via_if0); */
787 /* MFIB_TEST(!mfib_test_entry(mfei, */
788 /* MFIB_ENTRY_FLAG_SIGNAL, */
790 /* DPO_ADJACENCY_MCAST, ai_2), */
791 /* "%U replicate OK", */
792 /* format_mfib_prefix, pfx_s_g); */
793 /* MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index, */
794 /* MFIB_ITF_FLAG_FORWARD)); */
795 /* MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[0]->sw_if_index)); */
796 /* MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[1]->sw_if_index)); */
797 /* MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index)); */
800 * remove the last path and the accepting only interface,
801 * the entry still has flags so it remains
803 vec_reset_length(two_paths);
804 vec_add1(two_paths, path_via_if0);
805 vec_add1(two_paths, path_via_if2);
807 mfib_table_entry_paths_remove(fib_index,
812 MFIB_TEST(!mfib_test_entry(mfei,
813 MFIB_ENTRY_FLAG_SIGNAL,
815 "%U no replications",
816 format_mfib_prefix, pfx_s_g);
819 * update flags on the entry
821 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 path_via_if0.frp_mitf_flags = (MFIB_ITF_FLAG_ACCEPT |
838 MFIB_ITF_FLAG_NEGATE_SIGNAL);
840 mfib_table_entry_path_update (fib_index, pfx_star_g_2, MFIB_SOURCE_API,
841 MFIB_ENTRY_FLAG_NONE, &path_via_if0);
842 MFIB_TEST(!mfib_test_entry(mfei_g_2,
843 MFIB_ENTRY_FLAG_NONE,
845 "%U No replications",
846 format_mfib_prefix, pfx_star_g_2);
849 * Simulate a signal from the data-plane
855 mfe = mfib_entry_get(mfei_g_2);
856 mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
858 mfib_signal_push(mfe, mfi, NULL);
862 * An entry with a NS interface
864 path_via_if0.frp_mitf_flags = (MFIB_ITF_FLAG_ACCEPT |
865 MFIB_ITF_FLAG_NEGATE_SIGNAL);
867 mfib_table_entry_path_update (fib_index, pfx_star_g_3, MFIB_SOURCE_API,
868 MFIB_ENTRY_FLAG_NONE, &path_via_if0);
869 MFIB_TEST(!mfib_test_entry(mfei_g_3,
870 MFIB_ENTRY_FLAG_NONE,
872 "%U No replications",
873 format_mfib_prefix, pfx_star_g_3);
876 * Simulate a signal from the data-plane
882 mfe = mfib_entry_get(mfei_g_3);
883 mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
885 mfib_signal_push(mfe, mfi, NULL);
888 if (FIB_PROTOCOL_IP6 == PROTO)
891 * All the entries are present. let's ensure we can find them all
892 * via exact and longest prefix matches.
895 * A source address we will never match
897 ip6_address_t src = {
898 .as_u64[0] = clib_host_to_net_u64(0x3001000000000000),
899 .as_u64[1] = clib_host_to_net_u64(0xffffffffffffffff),
905 MFIB_TEST((mfei_g_m == ip6_mfib_table_fwd_lookup(
906 ip6_mfib_get(fib_index),
908 &pfx_star_g_slash_m->fp_grp_addr.ip6)),
909 "%U found via DP LPM grp=%U",
910 format_mfib_prefix, pfx_star_g_slash_m,
911 format_ip6_address, &pfx_star_g_slash_m->fp_grp_addr.ip6);
913 ip6_address_t tmp = pfx_star_g_slash_m->fp_grp_addr.ip6;
914 tmp.as_u8[15] = 0xff;
916 MFIB_TEST((mfei_g_m == ip6_mfib_table_fwd_lookup(
917 ip6_mfib_get(fib_index),
918 &pfx_s_g->fp_src_addr.ip6,
920 "%U found via DP LPM grp=%U",
921 format_mfib_prefix, pfx_star_g_slash_m,
922 format_ip6_address, &tmp);
927 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
928 &pfx_s_g->fp_src_addr.ip6,
929 &pfx_s_g->fp_grp_addr.ip6);
930 MFIB_TEST((mfei_s_g == mfei),
931 "%U found via DP LPM: %d",
932 format_mfib_prefix, pfx_s_g, mfei);
937 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
939 &pfx_star_g_1->fp_grp_addr.ip6);
940 MFIB_TEST((mfei_g_1 == mfei),
941 "%U found via DP LPM: %d",
942 format_mfib_prefix, pfx_star_g_1, mfei);
943 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
945 &pfx_star_g_2->fp_grp_addr.ip6);
946 MFIB_TEST((mfei_g_2 == mfei),
947 "%U found via DP LPM: %d",
948 format_mfib_prefix, pfx_star_g_2, mfei);
949 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
951 &pfx_star_g_3->fp_grp_addr.ip6);
952 MFIB_TEST((mfei_g_3 == mfei),
953 "%U found via DP LPM: %d",
954 format_mfib_prefix, pfx_star_g_3, mfei);
958 * remove flags on the entry. This is the last of the
959 * state associated with the entry, so now it goes.
961 mfib_table_entry_update(fib_index,
965 MFIB_ENTRY_FLAG_NONE);
966 mfei = mfib_table_lookup_exact_match(fib_index,
968 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
970 format_mfib_prefix, pfx_s_g);
973 * remove the last path on the no forward entry - the last entry
975 mfib_table_entry_path_remove(fib_index,
980 mfei = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
981 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
983 format_mfib_prefix, pfx_no_forward);
986 * hard delete the (*,232.1.1.1)
988 mfib_table_entry_delete(fib_index,
992 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
993 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
995 format_mfib_prefix, pfx_star_g_1);
997 * remove the entry whilst the signal is pending
999 mfib_table_entry_delete(fib_index,
1003 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_2);
1004 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1006 format_mfib_prefix, pfx_star_g_2);
1007 mfib_table_entry_delete(fib_index,
1011 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_3);
1012 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1014 format_mfib_prefix, pfx_star_g_3);
1016 mfib_table_entry_delete(fib_index,
1020 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
1021 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1023 format_mfib_prefix, pfx_star_g_slash_m);
1026 * Entries with paths via unicast next-hops
1028 fib_route_path_t path_via_nbr1 = {
1029 .frp_proto = fib_proto_to_dpo(PROTO),
1030 .frp_addr = *addr_nbr1,
1031 .frp_sw_if_index = tm->hw[0]->sw_if_index,
1032 .frp_fib_index = ~0,
1035 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1037 fib_route_path_t path_via_nbr2 = {
1038 .frp_proto = fib_proto_to_dpo(PROTO),
1039 .frp_addr = *addr_nbr2,
1040 .frp_sw_if_index = tm->hw[0]->sw_if_index,
1041 .frp_fib_index = ~0,
1044 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1048 mfib_table_entry_path_update (fib_index, pfx_star_g_1, MFIB_SOURCE_API,
1049 MFIB_ENTRY_FLAG_NONE, &path_via_nbr1);
1051 mfib_table_entry_path_update (fib_index, pfx_star_g_1, MFIB_SOURCE_API,
1052 MFIB_ENTRY_FLAG_NONE, &path_via_nbr2);
1053 MFIB_TEST(!mfib_test_entry(mfei_g_1,
1054 MFIB_ENTRY_FLAG_NONE,
1056 DPO_ADJACENCY_INCOMPLETE, ai_nbr1,
1057 DPO_ADJACENCY_INCOMPLETE, ai_nbr2),
1059 format_mfib_prefix, pfx_star_g_1);
1060 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_g_1, tm->hw[0]->sw_if_index,
1061 MFIB_ITF_FLAG_FORWARD));
1063 mfib_table_entry_path_remove(fib_index,
1068 MFIB_TEST(!mfib_test_entry(mfei_g_1,
1069 MFIB_ENTRY_FLAG_NONE,
1071 DPO_ADJACENCY_INCOMPLETE, ai_nbr2),
1073 format_mfib_prefix, pfx_star_g_1);
1074 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_g_1, tm->hw[0]->sw_if_index,
1075 MFIB_ITF_FLAG_FORWARD));
1077 mfib_table_entry_path_remove(fib_index,
1081 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
1082 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1084 format_mfib_prefix, pfx_star_g_1);
1087 * Add a prefix as a special/exclusive route
1089 dpo_id_t td = DPO_INVALID;
1090 index_t repi = replicate_create(1, fib_proto_to_dpo(PROTO));
1092 dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_2);
1093 replicate_set_bucket(repi, 0, &td);
1095 mfei = mfib_table_entry_special_add(fib_index,
1098 MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF,
1100 MFIB_TEST(!mfib_test_entry(mfei,
1101 (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
1102 MFIB_ENTRY_FLAG_EXCLUSIVE),
1104 DPO_ADJACENCY_MCAST, ai_2),
1105 "%U exclusive replicate OK",
1106 format_mfib_prefix, pfx_star_g_3);
1109 * update a special/exclusive route
1111 index_t repi2 = replicate_create(1, fib_proto_to_dpo(PROTO));
1113 dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_1);
1114 replicate_set_bucket(repi2, 0, &td);
1116 mfib_entry_update(mfei,
1118 (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
1119 MFIB_ENTRY_FLAG_EXCLUSIVE),
1122 MFIB_TEST(!mfib_test_entry(mfei,
1123 (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
1124 MFIB_ENTRY_FLAG_EXCLUSIVE),
1126 DPO_ADJACENCY_MCAST, ai_1),
1127 "%U exclusive update replicate OK",
1128 format_mfib_prefix, pfx_star_g_3);
1130 mfib_table_entry_delete(fib_index,
1136 * A Multicast LSP. This a mLDP head-end
1138 fib_node_index_t ai_mpls_10_10_10_1, lfei;
1139 ip46_address_t nh_10_10_10_1 = {
1141 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
1144 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1147 tm->hw[0]->sw_if_index);
1149 fib_prefix_t pfx_3500 = {
1151 .fp_proto = FIB_PROTOCOL_MPLS,
1154 .fp_payload_proto = DPO_PROTO_IP4,
1156 fib_test_rep_bucket_t mc_0 = {
1157 .type = FT_REP_LABEL_O_ADJ,
1159 .adj = ai_mpls_10_10_10_1,
1164 fib_mpls_label_t *l3300 = NULL, fml3300 = {
1167 vec_add1(l3300, fml3300);
1170 * MPLS enable an interface so we get the MPLS table created
1172 mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL);
1173 mpls_sw_interface_enable_disable (&mpls_main, tm->hw[0]->sw_if_index, 1);
1175 lfei = fib_table_entry_update_one_path(0, // default MPLS Table
1178 FIB_ENTRY_FLAG_MULTICAST,
1181 tm->hw[0]->sw_if_index,
1182 ~0, // invalid fib index
1185 FIB_ROUTE_PATH_FLAG_NONE);
1186 MFIB_TEST(!fib_test_validate_entry(lfei,
1187 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
1190 "3500 via replicate over 10.10.10.1");
1193 * An (S,G) that resolves via the mLDP head-end
1195 fib_route_path_t path_via_mldp = {
1196 .frp_proto = DPO_PROTO_MPLS,
1197 .frp_local_label = pfx_3500.fp_label,
1198 .frp_eos = MPLS_EOS,
1199 .frp_sw_if_index = 0xffffffff,
1202 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
1203 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1205 dpo_id_t mldp_dpo = DPO_INVALID;
1207 fib_entry_contribute_forwarding(lfei,
1208 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
1211 mfei = mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
1212 MFIB_ENTRY_FLAG_NONE, &path_via_mldp);
1214 MFIB_TEST(!mfib_test_entry(mfei,
1215 MFIB_ENTRY_FLAG_NONE,
1217 DPO_REPLICATE, mldp_dpo.dpoi_index),
1218 "%U over-mLDP replicate OK",
1219 format_mfib_prefix, pfx_s_g);
1222 * add a for-us path. this tests two types of non-attached paths on one entry
1224 mfei = mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
1225 MFIB_ENTRY_FLAG_NONE, &path_for_us);
1226 MFIB_TEST(!mfib_test_entry(mfei,
1227 MFIB_ENTRY_FLAG_NONE,
1229 DPO_REPLICATE, mldp_dpo.dpoi_index,
1231 "%U mLDP+for-us replicate OK",
1232 format_mfib_prefix, pfx_s_g);
1234 mfib_table_entry_delete(fib_index,
1237 fib_table_entry_delete(0,
1240 dpo_reset(&mldp_dpo);
1243 * Unlock the table - it's the last lock so should be gone thereafter
1245 MFIB_TEST(((PROTO == FIB_PROTOCOL_IP4 ? 3 : 5) ==
1246 mfib_table_get_n_routes(fib_index, PROTO)),
1247 "1 = %d route left in the FIB",
1248 mfib_table_get_n_routes(fib_index, PROTO));
1250 mfib_table_unlock(fib_index, PROTO, MFIB_SOURCE_API);
1252 MFIB_TEST((FIB_NODE_INDEX_INVALID ==
1253 mfib_table_find(PROTO, fib_index)),
1254 "MFIB table %d gone", fib_index);
1259 adj_unlock(ai_nbr1);
1260 adj_unlock(ai_nbr2);
1263 * MPLS disable the interface
1265 mpls_sw_interface_enable_disable (&mpls_main, tm->hw[0]->sw_if_index, 0);
1266 mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
1269 * remove the connected
1271 fib_table_entry_delete(0, pfx_itf, FIB_SOURCE_INTERFACE);
1274 * test we've leaked no resources
1276 MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
1277 MFIB_TEST(n_pls == fib_path_list_pool_size(), "%d=%d path-lists",
1278 n_pls, fib_path_list_pool_size());
1279 MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
1280 n_reps, pool_elts(replicate_pool));
1281 MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
1282 " No more entries %d!=%d",
1283 n_entries, pool_elts(mfib_entry_pool));
1284 MFIB_TEST(n_itfs == pool_elts(mfib_itf_pool),
1285 " No more Interfaces %d!=%d",
1286 n_itfs, pool_elts(mfib_itf_pool));
1287 vec_free(two_paths);
1295 const mfib_prefix_t pfx_224_s_8 = {
1297 .fp_proto = FIB_PROTOCOL_IP4,
1299 .ip4.as_u32 = clib_host_to_net_u32(0xe0000000),
1302 const mfib_prefix_t pfx_1_1_1_1_c_239_1_1_1 = {
1304 .fp_proto = FIB_PROTOCOL_IP4,
1306 .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1309 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1312 const mfib_prefix_t pfx_239_1_1_1 = {
1314 .fp_proto = FIB_PROTOCOL_IP4,
1316 .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1322 const mfib_prefix_t pfx_239_1_1_2 = {
1324 .fp_proto = FIB_PROTOCOL_IP4,
1326 .ip4.as_u32 = clib_host_to_net_u32(0xef010102),
1332 const mfib_prefix_t pfx_239_1_1_3 = {
1334 .fp_proto = FIB_PROTOCOL_IP4,
1336 .ip4.as_u32 = clib_host_to_net_u32(0xef010103),
1342 const mfib_prefix_t pfx_239 = {
1344 .fp_proto = FIB_PROTOCOL_IP4,
1346 .ip4.as_u32 = clib_host_to_net_u32(0xef000000),
1352 const fib_prefix_t pfx_itf = {
1354 .fp_proto = FIB_PROTOCOL_IP4,
1356 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
1359 const ip46_address_t nbr1 = {
1360 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0b),
1362 const ip46_address_t nbr2 = {
1363 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0c),
1365 return (mfib_test_i(FIB_PROTOCOL_IP4,
1368 &pfx_1_1_1_1_c_239_1_1_1,
1381 const mfib_prefix_t pfx_ffd_s_12 = {
1383 .fp_proto = FIB_PROTOCOL_IP6,
1385 .ip6.as_u64[0] = clib_host_to_net_u64(0xffd0000000000000),
1388 const mfib_prefix_t pfx_2001_1_c_ff_1 = {
1390 .fp_proto = FIB_PROTOCOL_IP6,
1392 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1393 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1396 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1397 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1400 const mfib_prefix_t pfx_ff_1 = {
1402 .fp_proto = FIB_PROTOCOL_IP6,
1404 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1405 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1408 const mfib_prefix_t pfx_ff_2 = {
1410 .fp_proto = FIB_PROTOCOL_IP6,
1412 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1413 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1416 const mfib_prefix_t pfx_ff_3 = {
1418 * this is the ALL DHCP routers address
1421 .fp_proto = FIB_PROTOCOL_IP6,
1423 .ip6.as_u64[0] = clib_host_to_net_u64(0xff02000100000000),
1424 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1427 const mfib_prefix_t pfx_ff = {
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(0x0000000000000000),
1435 const fib_prefix_t pfx_itf = {
1437 .fp_proto = FIB_PROTOCOL_IP6,
1439 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1440 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1443 const ip46_address_t nbr1 = {
1444 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1445 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1447 const ip46_address_t nbr2 = {
1448 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1449 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000003),
1452 return (mfib_test_i(FIB_PROTOCOL_IP6,
1466 mfib_test_rr_i (fib_protocol_t FPROTO,
1469 const mfib_prefix_t *pfx_cover,
1470 const mfib_prefix_t *pfx_host1,
1471 const mfib_prefix_t *pfx_host2)
1473 fib_node_index_t mfei_cover, mfei_host1, mfei_host2, ai_1, ai_2;
1474 u32 fib_index, n_entries, n_itfs, n_reps, n_pls;
1479 n_entries = pool_elts(mfib_entry_pool);
1480 n_itfs = pool_elts(mfib_itf_pool);
1481 n_reps = pool_elts(replicate_pool);
1482 n_pls = fib_path_list_pool_size();
1486 ai_1 = adj_mcast_add_or_lock(FPROTO,
1488 tm->hw[1]->sw_if_index);
1489 ai_2 = adj_mcast_add_or_lock(FPROTO,
1491 tm->hw[2]->sw_if_index);
1493 fib_route_path_t path_via_if0 = {
1494 .frp_proto = DPROTO,
1495 .frp_addr = zero_addr,
1496 .frp_sw_if_index = tm->hw[0]->sw_if_index,
1497 .frp_fib_index = ~0,
1500 .frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT,
1502 fib_route_path_t path_via_if1 = {
1503 .frp_proto = DPROTO,
1504 .frp_addr = zero_addr,
1505 .frp_sw_if_index = tm->hw[1]->sw_if_index,
1506 .frp_fib_index = ~0,
1509 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1511 fib_route_path_t path_via_if2 = {
1512 .frp_proto = DPROTO,
1513 .frp_addr = zero_addr,
1514 .frp_sw_if_index = tm->hw[2]->sw_if_index,
1515 .frp_fib_index = ~0,
1518 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1520 fib_route_path_t path_for_us = {
1521 .frp_proto = DPROTO,
1522 .frp_addr = zero_addr,
1523 .frp_sw_if_index = 0xffffffff,
1524 .frp_fib_index = ~0,
1526 .frp_flags = FIB_ROUTE_PATH_LOCAL,
1527 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1531 * with only the default in place, recusre thru the /32
1533 mfei_host1 = mfib_table_entry_special_add(fib_index, pfx_host1,
1535 MFIB_ENTRY_FLAG_NONE,
1538 * expect its forwarding to match the cover's
1540 MFIB_TEST(!mfib_test_entry(mfei_host1,
1541 MFIB_ENTRY_FLAG_DROP,
1543 "%U no replications OK",
1544 format_mfib_prefix, pfx_host1);
1547 * Insert the less specific /28
1549 mfib_table_entry_path_update (fib_index, pfx_cover, MFIB_SOURCE_API,
1550 MFIB_ENTRY_FLAG_NONE, &path_via_if1);
1552 mfei_cover = mfib_table_lookup_exact_match(fib_index, pfx_cover);
1554 MFIB_TEST(!mfib_test_entry(mfei_cover,
1555 MFIB_ENTRY_FLAG_NONE,
1557 DPO_ADJACENCY_MCAST, ai_1),
1559 format_mfib_prefix, pfx_cover);
1562 * expect the /32 forwarding to match the new cover's
1564 MFIB_TEST(!mfib_test_entry(mfei_host1,
1565 MFIB_ENTRY_FLAG_NONE,
1567 DPO_ADJACENCY_MCAST, ai_1),
1569 format_mfib_prefix, pfx_host1);
1572 * add another path to the cover
1574 mfib_table_entry_path_update (fib_index, pfx_cover, MFIB_SOURCE_API,
1575 MFIB_ENTRY_FLAG_NONE, &path_via_if2);
1578 * expect the /32 and /28 to be via both boths
1580 MFIB_TEST(!mfib_test_entry(mfei_cover,
1581 MFIB_ENTRY_FLAG_NONE,
1583 DPO_ADJACENCY_MCAST, ai_1,
1584 DPO_ADJACENCY_MCAST, ai_2),
1586 format_mfib_prefix, pfx_cover);
1587 MFIB_TEST(!mfib_test_entry(mfei_host1,
1588 MFIB_ENTRY_FLAG_NONE,
1590 DPO_ADJACENCY_MCAST, ai_1,
1591 DPO_ADJACENCY_MCAST, ai_2),
1593 format_mfib_prefix, pfx_host1);
1596 * and the other host whilst all is ready
1598 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1600 MFIB_ENTRY_FLAG_NONE,
1602 MFIB_TEST(!mfib_test_entry(mfei_host2,
1603 MFIB_ENTRY_FLAG_NONE,
1605 DPO_ADJACENCY_MCAST, ai_1,
1606 DPO_ADJACENCY_MCAST, ai_2),
1608 format_mfib_prefix, pfx_host2);
1611 * repaet multiple time to simulate multiple recursve children
1613 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1615 MFIB_ENTRY_FLAG_NONE,
1617 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1619 MFIB_ENTRY_FLAG_NONE,
1621 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1623 MFIB_ENTRY_FLAG_NONE,
1627 * add an accepting path to the cover
1629 mfib_table_entry_path_update (fib_index, pfx_cover, MFIB_SOURCE_API,
1630 MFIB_ENTRY_FLAG_NONE, &path_via_if0);
1633 * expect the /32 and /28 to be via both boths
1635 MFIB_TEST(!mfib_test_entry(mfei_cover,
1636 MFIB_ENTRY_FLAG_NONE,
1638 DPO_ADJACENCY_MCAST, ai_1,
1639 DPO_ADJACENCY_MCAST, ai_2),
1641 format_mfib_prefix, pfx_cover);
1642 MFIB_TEST(!mfib_test_entry(mfei_host1,
1643 MFIB_ENTRY_FLAG_NONE,
1645 DPO_ADJACENCY_MCAST, ai_1,
1646 DPO_ADJACENCY_MCAST, ai_2),
1648 format_mfib_prefix, pfx_cover);
1649 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[0]->sw_if_index,
1650 MFIB_ITF_FLAG_ACCEPT));
1651 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[0]->sw_if_index,
1652 MFIB_ITF_FLAG_ACCEPT));
1653 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[1]->sw_if_index,
1654 MFIB_ITF_FLAG_FORWARD));
1655 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[1]->sw_if_index,
1656 MFIB_ITF_FLAG_FORWARD));
1657 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[2]->sw_if_index,
1658 MFIB_ITF_FLAG_FORWARD));
1659 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[2]->sw_if_index,
1660 MFIB_ITF_FLAG_FORWARD));
1663 * add a for-us path to the cover
1665 mfib_table_entry_path_update (fib_index, pfx_cover, MFIB_SOURCE_API,
1666 MFIB_ENTRY_FLAG_NONE, &path_for_us);
1669 * expect the /32 and /28 to be via all three paths
1671 MFIB_TEST(!mfib_test_entry(mfei_cover,
1672 MFIB_ENTRY_FLAG_NONE,
1674 DPO_ADJACENCY_MCAST, ai_1,
1675 DPO_ADJACENCY_MCAST, ai_2,
1678 format_mfib_prefix, pfx_cover);
1679 MFIB_TEST(!mfib_test_entry(mfei_host1,
1680 MFIB_ENTRY_FLAG_NONE,
1682 DPO_ADJACENCY_MCAST, ai_1,
1683 DPO_ADJACENCY_MCAST, ai_2,
1686 format_mfib_prefix, pfx_cover);
1689 * get the forwarding chain from the RR prefix
1692 dpo_id_t dpo = DPO_INVALID;
1694 mfib_entry_contribute_forwarding(
1696 mfib_forw_chain_type_from_dpo_proto(DPROTO),
1697 MFIB_ENTRY_FWD_FLAG_NONE,
1700 rep = replicate_get(dpo.dpoi_index);
1701 MFIB_TEST((3 == rep->rep_n_buckets),
1702 "%U replicate 3 buckets",
1703 format_mfib_prefix, pfx_host1);
1706 * get the forwarding chain from the RR prefix without local paths
1708 mfib_entry_contribute_forwarding(
1710 mfib_forw_chain_type_from_dpo_proto(DPROTO),
1711 MFIB_ENTRY_FWD_FLAG_NO_LOCAL,
1714 rep = replicate_get(dpo.dpoi_index);
1715 MFIB_TEST((2 == rep->rep_n_buckets),
1716 "%U no-local replicate 2 buckets",
1717 format_mfib_prefix, pfx_host1);
1722 * delete the cover, expect the /32 to be via the default
1724 mfib_table_entry_delete(fib_index, pfx_cover, MFIB_SOURCE_API);
1725 MFIB_TEST(!mfib_test_entry(mfei_host1,
1726 MFIB_ENTRY_FLAG_DROP,
1728 "%U no replications OK",
1729 format_mfib_prefix, pfx_host1);
1732 * source the /32 with its own path
1735 mfib_table_entry_path_update (fib_index, pfx_host1, MFIB_SOURCE_API,
1736 MFIB_ENTRY_FLAG_NONE, &path_via_if2);
1737 MFIB_TEST(!mfib_test_entry(mfei_host1,
1738 MFIB_ENTRY_FLAG_NONE,
1740 DPO_ADJACENCY_MCAST, ai_2),
1742 format_mfib_prefix, pfx_host1);
1745 * remove host2 - as many times as it was added
1747 mfib_table_entry_delete(fib_index, pfx_host2,
1749 mfib_table_entry_delete(fib_index, pfx_host2,
1751 mfib_table_entry_delete(fib_index, pfx_host2,
1753 mfib_table_entry_delete(fib_index, pfx_host2,
1758 * remove the RR source with paths present
1760 mfib_table_entry_delete(fib_index, pfx_host1,
1764 * add the RR back then remove the path and RR
1767 mfib_table_entry_path_update (fib_index, pfx_host1, MFIB_SOURCE_API,
1768 MFIB_ENTRY_FLAG_NONE, &path_via_if2);
1769 MFIB_TEST(!mfib_test_entry(mfei_host1,
1770 MFIB_ENTRY_FLAG_NONE,
1772 DPO_ADJACENCY_MCAST, ai_2),
1774 format_mfib_prefix, pfx_host1);
1776 mfib_table_entry_delete(fib_index, pfx_host1,
1778 mfib_table_entry_delete(fib_index, pfx_host1,
1782 * test we've leaked no resources
1786 MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
1787 MFIB_TEST(n_pls == fib_path_list_pool_size(), "%d=%d path-lists",
1788 n_pls, fib_path_list_pool_size());
1789 MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
1790 n_reps, pool_elts(replicate_pool));
1791 MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
1792 " No more entries %d!=%d",
1793 n_entries, pool_elts(mfib_entry_pool));
1794 MFIB_TEST(n_itfs == pool_elts(mfib_itf_pool),
1795 " No more Interfaces %d!=%d",
1796 n_itfs, pool_elts(mfib_itf_pool));
1801 mfib_test_rr_v4 (void)
1804 * 2 length of prefix to play with
1806 const mfib_prefix_t pfx_host1 = {
1808 .fp_proto = FIB_PROTOCOL_IP4,
1810 .ip4.as_u32 = clib_host_to_net_u32(0xe0001011),
1813 const mfib_prefix_t pfx_host2 = {
1815 .fp_proto = FIB_PROTOCOL_IP4,
1817 .ip4.as_u32 = clib_host_to_net_u32(0xe0001011),
1820 .ip4.as_u32 = clib_host_to_net_u32(0x10101010),
1823 const mfib_prefix_t pfx_cover = {
1825 .fp_proto = FIB_PROTOCOL_IP4,
1827 .ip4.as_u32 = clib_host_to_net_u32(0xe0001010),
1831 return (mfib_test_rr_i(FIB_PROTOCOL_IP4,
1840 mfib_test_rr_v6 (void)
1843 * 2 length of prefix to play with
1845 const mfib_prefix_t pfx_host1 = {
1847 .fp_proto = FIB_PROTOCOL_IP6,
1849 .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
1850 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1853 const mfib_prefix_t pfx_host2 = {
1855 .fp_proto = FIB_PROTOCOL_IP6,
1857 .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
1858 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1861 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1862 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1865 const mfib_prefix_t pfx_cover = {
1867 .fp_proto = FIB_PROTOCOL_IP6,
1869 .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
1870 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000000),
1874 return (mfib_test_rr_i(FIB_PROTOCOL_IP6,
1882 static clib_error_t *
1883 mfib_test (vlib_main_t * vm,
1884 unformat_input_t * input,
1885 vlib_cli_command_t * cmd_arg)
1889 res += mfib_test_mk_intf(4);
1890 res += mfib_test_rr_v4();
1894 return clib_error_return(0, "MFIB RR V4 Unit Test Failed");
1897 res += mfib_test_rr_v6();
1901 return clib_error_return(0, "MFIB RR V6 Unit Test Failed");
1904 res += mfib_test_v4();
1908 return clib_error_return(0, "MFIB V4 Unit Test Failed");
1911 res += mfib_test_v6();
1915 return clib_error_return(0, "MFIB V6 Unit Test Failed");
1921 VLIB_CLI_COMMAND (test_fib_command, static) = {
1922 .path = "test mfib",
1923 .short_help = "mfib unit tests - DO NOT RUN ON A LIVE SYSTEM",
1924 .function = mfib_test,
1928 mfib_test_init (vlib_main_t *vm)
1933 VLIB_INIT_FUNCTION (mfib_test_init);