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++)
126 vnet_eth_interface_registration_t eir = {};
127 vnet_main_t *vnm = vnet_get_main ();
131 eir.dev_class_index = test_interface_device_class.index;
132 eir.dev_instance = i;
133 eir.address = hw_address;
134 tm->hw_if_indicies[i] = vnet_eth_register_interface (vnm, &eir);
137 vnet_hw_interface_set_flags (vnet_get_main (), tm->hw_if_indicies[i],
138 VNET_HW_INTERFACE_FLAG_LINK_UP);
140 vnet_get_hw_interface (vnet_get_main (), tm->hw_if_indicies[i]);
141 ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
142 ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
144 ip4_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
145 ip6_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
148 vnet_sw_interface_set_flags (vnet_get_main (), tm->hw[i]->sw_if_index,
149 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
150 MFIB_TEST ((NULL == error), "UP interface %d", i);
153 * re-eval after the inevitable realloc
155 for (i = 0; i < ninterfaces; i++)
157 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
158 tm->hw_if_indicies[i]);
164 #define MFIB_TEST_REP(_cond, _comment, _args...) \
166 if (MFIB_TEST_I(_cond, _comment, ##_args)) { \
172 mfib_test_validate_rep_v (const replicate_t *rep,
183 MFIB_TEST_REP((n_buckets == rep->rep_n_buckets),
184 "n_buckets = %d", rep->rep_n_buckets);
186 for (bucket = 0; bucket < n_buckets; bucket++)
188 dt = va_arg(*ap, int); // type promotion
189 ai = va_arg(*ap, adj_index_t);
190 dpo = replicate_get_bucket_i(rep, bucket);
192 MFIB_TEST_REP((dt == dpo->dpoi_type),
193 "bucket %d stacks on %U",
195 format_dpo_type, dpo->dpoi_type);
197 if (DPO_RECEIVE != dt)
199 MFIB_TEST_REP((ai == dpo->dpoi_index),
200 "bucket %d [exp:%d] stacks on %U",
202 format_dpo_id, dpo, 0);
209 mfib_test_entry (fib_node_index_t fei,
210 mfib_entry_flags_t eflags,
214 const mfib_prefix_t *pfx;
215 const mfib_entry_t *mfe;
216 const replicate_t *rep;
222 mfe = mfib_entry_get(fei);
223 pfx = mfib_entry_get_prefix(fei);
225 MFIB_TEST_REP((eflags == mfe->mfe_flags),
226 "%U has %U expect %U",
227 format_mfib_prefix, pfx,
228 format_mfib_entry_flags, mfe->mfe_flags,
229 format_mfib_entry_flags, eflags);
233 MFIB_TEST_REP((DPO_DROP == mfe->mfe_rep.dpoi_type),
235 format_mfib_prefix, pfx,
236 format_dpo_id, &mfe->mfe_rep, 0);
240 dpo_id_t tmp = DPO_INVALID;
242 mfib_entry_contribute_forwarding(
244 mfib_forw_chain_type_from_fib_proto(pfx->fp_proto),
245 MFIB_ENTRY_FWD_FLAG_NONE,
247 rep = replicate_get(tmp.dpoi_index);
249 MFIB_TEST_REP((DPO_REPLICATE == tmp.dpoi_type),
251 format_mfib_prefix, pfx,
252 format_dpo_type, tmp.dpoi_type);
254 va_start(ap, n_buckets);
255 res = mfib_test_validate_rep_v(rep, n_buckets, &ap);
266 mfib_test_entry_itf (fib_node_index_t fei,
268 mfib_itf_flags_t flags)
270 const mfib_prefix_t *pfx;
271 const mfib_entry_t *mfe;
272 const mfib_itf_t *mfi;
276 mfe = mfib_entry_get(fei);
277 mfi = mfib_entry_get_itf(mfe, sw_if_index);
278 pfx = mfib_entry_get_prefix(fei);
280 MFIB_TEST_REP((NULL != mfi),
281 "%U has interface %d",
282 format_mfib_prefix, pfx, sw_if_index);
284 MFIB_TEST_REP((flags == mfi->mfi_flags),
285 "%U interface %d has flags %U expect %U",
286 format_mfib_prefix, pfx, sw_if_index,
287 format_mfib_itf_flags, flags,
288 format_mfib_itf_flags, mfi->mfi_flags);
294 mfib_test_entry_no_itf (fib_node_index_t fei,
297 const mfib_prefix_t *pfx;
298 const mfib_entry_t *mfe;
299 const mfib_itf_t *mfi;
303 mfe = mfib_entry_get(fei);
304 mfi = mfib_entry_get_itf(mfe, sw_if_index);
305 pfx = mfib_entry_get_prefix(fei);
307 MFIB_TEST_REP((NULL == mfi),
308 "%U has no interface %d",
309 format_mfib_prefix, pfx, sw_if_index);
315 mfib_test_i (fib_protocol_t PROTO,
317 const mfib_prefix_t *pfx_no_forward,
318 const mfib_prefix_t *pfx_s_g,
319 const mfib_prefix_t *pfx_star_g_1,
320 const mfib_prefix_t *pfx_star_g_2,
321 const mfib_prefix_t *pfx_star_g_3,
322 const mfib_prefix_t *pfx_star_g_slash_m,
323 const fib_prefix_t *pfx_itf,
324 const ip46_address_t *addr_nbr1,
325 const ip46_address_t *addr_nbr2)
327 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;
328 u32 fib_index, n_entries, n_itfs, n_reps, n_pls;
329 fib_node_index_t ai_1, ai_2, ai_3, ai_nbr1, ai_nbr2;
333 mfib_prefix_t all_1s;
334 clib_memset(&all_1s, 0xfd, sizeof(all_1s));
337 n_entries = pool_elts(mfib_entry_pool);
338 n_itfs = pool_elts(mfib_itf_pool);
339 n_reps = pool_elts(replicate_pool);
340 n_pls = fib_path_list_pool_size();
343 ai_1 = adj_mcast_add_or_lock(PROTO,
345 tm->hw[1]->sw_if_index);
346 ai_2 = adj_mcast_add_or_lock(PROTO,
348 tm->hw[2]->sw_if_index);
349 ai_3 = adj_mcast_add_or_lock(PROTO,
351 tm->hw[3]->sw_if_index);
352 ai_nbr1 = adj_nbr_add_or_lock(PROTO,
355 tm->hw[0]->sw_if_index);
356 ai_nbr2 = adj_nbr_add_or_lock(PROTO,
359 tm->hw[0]->sw_if_index);
361 MFIB_TEST(3 == adj_mcast_db_size(), "3 MCAST adjs");
363 /* Find or create FIB table 11 */
364 fib_index = mfib_table_find_or_create_and_lock(PROTO, 11, MFIB_SOURCE_API);
366 fib_table_entry_update_one_path(0,
368 FIB_SOURCE_INTERFACE,
369 (FIB_ENTRY_FLAG_CONNECTED |
370 FIB_ENTRY_FLAG_ATTACHED),
373 tm->hw[0]->sw_if_index,
374 ~0, // invalid fib index
377 FIB_ROUTE_PATH_FLAG_NONE);
379 mfib_prefix_t pfx_dft = {
383 mfei_dflt = mfib_table_lookup_exact_match(fib_index, &pfx_dft);
384 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
385 MFIB_TEST(!mfib_test_entry(mfei_dflt,
386 MFIB_ENTRY_FLAG_DROP,
388 "(*,*) no replcaitions");
390 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
391 MFIB_TEST(!mfib_test_entry(mfei_dflt,
392 MFIB_ENTRY_FLAG_DROP,
394 "(*,*) no replcaitions");
397 fib_route_path_t path_via_if0 = {
398 .frp_proto = fib_proto_to_dpo(PROTO),
399 .frp_addr = zero_addr,
400 .frp_sw_if_index = tm->hw[0]->sw_if_index,
404 .frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT,
407 mfib_table_entry_path_update (fib_index, pfx_no_forward, MFIB_SOURCE_API,
408 MFIB_ENTRY_FLAG_NONE, &path_via_if0);
410 mfei_no_f = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
411 MFIB_TEST(!mfib_test_entry(mfei_no_f,
412 MFIB_ENTRY_FLAG_NONE,
414 "%U no replcaitions",
415 format_mfib_prefix, pfx_no_forward);
416 MFIB_TEST(!mfib_test_entry_itf(mfei_no_f, tm->hw[0]->sw_if_index,
417 MFIB_ITF_FLAG_ACCEPT),
418 "%U interface not accepting",
419 format_mfib_prefix, pfx_no_forward);
421 fib_route_path_t path_via_if1 = {
422 .frp_proto = fib_proto_to_dpo(PROTO),
423 .frp_addr = zero_addr,
424 .frp_sw_if_index = tm->hw[1]->sw_if_index,
428 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
430 fib_route_path_t path_via_if2 = {
431 .frp_proto = fib_proto_to_dpo(PROTO),
432 .frp_addr = zero_addr,
433 .frp_sw_if_index = tm->hw[2]->sw_if_index,
437 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
439 fib_route_path_t path_via_if3 = {
440 .frp_proto = fib_proto_to_dpo(PROTO),
441 .frp_addr = zero_addr,
442 .frp_sw_if_index = tm->hw[3]->sw_if_index,
446 .frp_mitf_flags = (MFIB_ITF_FLAG_FORWARD |
447 MFIB_ITF_FLAG_NEGATE_SIGNAL),
449 fib_route_path_t *two_paths = NULL;
450 vec_add1(two_paths, path_via_if2);
451 vec_add1(two_paths, path_via_if3);
454 * An (S,G) with 1 accepting and 3 forwarding paths
456 mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
457 MFIB_ENTRY_FLAG_NONE, &path_via_if0);
458 mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
459 MFIB_ENTRY_FLAG_NONE, &path_via_if1);
460 mfib_table_entry_paths_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
461 MFIB_ENTRY_FLAG_NONE, two_paths);
463 mfei_s_g = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
465 MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_s_g,
467 format_mfib_prefix, pfx_s_g);
468 MFIB_TEST(!mfib_test_entry(mfei_s_g,
469 MFIB_ENTRY_FLAG_NONE,
471 DPO_ADJACENCY_MCAST, ai_1,
472 DPO_ADJACENCY_MCAST, ai_2,
473 DPO_ADJACENCY_MCAST, ai_3),
475 format_mfib_prefix, pfx_s_g);
476 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[0]->sw_if_index,
477 MFIB_ITF_FLAG_ACCEPT));
478 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[1]->sw_if_index,
479 MFIB_ITF_FLAG_FORWARD));
480 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[2]->sw_if_index,
481 MFIB_ITF_FLAG_FORWARD));
482 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[3]->sw_if_index,
483 (MFIB_ITF_FLAG_FORWARD |
484 MFIB_ITF_FLAG_NEGATE_SIGNAL)));
487 * A (*,G), which the same G as the (S,G).
488 * different paths. test our LPM.
491 mfib_table_entry_path_update (fib_index, pfx_star_g_1, MFIB_SOURCE_API,
492 MFIB_ENTRY_FLAG_NONE, &path_via_if0);
493 mfib_table_entry_path_update (fib_index, pfx_star_g_1, MFIB_SOURCE_API,
494 MFIB_ENTRY_FLAG_NONE, &path_via_if1);
497 * test we find the *,G and S,G via LPM and exact matches
499 mfei = mfib_table_lookup_exact_match(fib_index,
501 MFIB_TEST(mfei == mfei_g_1,
502 "%U found via exact match",
503 format_mfib_prefix, pfx_star_g_1);
504 MFIB_TEST(!mfib_test_entry(mfei,
505 MFIB_ENTRY_FLAG_NONE,
507 DPO_ADJACENCY_MCAST, ai_1),
509 format_mfib_prefix, pfx_star_g_1);
511 mfei = mfib_table_lookup(fib_index,
513 MFIB_TEST(mfei == mfei_g_1,
514 "[e:%d a:%d] %U found via LP match",
516 format_mfib_prefix, pfx_star_g_1);
518 MFIB_TEST(!mfib_test_entry(mfei,
519 MFIB_ENTRY_FLAG_NONE,
521 DPO_ADJACENCY_MCAST, ai_1),
523 format_mfib_prefix, pfx_star_g_1);
525 mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
526 MFIB_TEST(mfei == mfei_s_g,
527 "%U found via exact match",
528 format_mfib_prefix, pfx_s_g);
530 MFIB_TEST(!mfib_test_entry(mfei,
531 MFIB_ENTRY_FLAG_NONE,
533 DPO_ADJACENCY_MCAST, ai_1,
534 DPO_ADJACENCY_MCAST, ai_2,
535 DPO_ADJACENCY_MCAST, ai_3),
537 format_mfib_prefix, pfx_s_g);
538 mfei = mfib_table_lookup(fib_index, pfx_s_g);
539 MFIB_TEST(mfei == mfei_s_g,
540 "%U found via LP match",
541 format_mfib_prefix, pfx_s_g);
543 MFIB_TEST(!mfib_test_entry(mfei,
544 MFIB_ENTRY_FLAG_NONE,
546 DPO_ADJACENCY_MCAST, ai_1,
547 DPO_ADJACENCY_MCAST, ai_2,
548 DPO_ADJACENCY_MCAST, ai_3),
550 format_mfib_prefix, pfx_s_g);
553 * A (*,G/m), which the same root G as the (*,G).
554 * different paths. test our LPM.
556 path_via_if2.frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT;
557 mfei_g_m = mfib_table_entry_path_update (
558 fib_index, pfx_star_g_slash_m, MFIB_SOURCE_API, MFIB_ENTRY_FLAG_NONE,
560 mfib_table_entry_path_update (fib_index, pfx_star_g_slash_m,
561 MFIB_SOURCE_API, MFIB_ENTRY_FLAG_NONE,
565 * test we find the (*,G/m), (*,G) and (S,G) via LPM and exact matches
567 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
568 MFIB_TEST((mfei_g_1 == mfei),
569 "%U found via DP LPM: %d",
570 format_mfib_prefix, pfx_star_g_1, mfei);
572 MFIB_TEST(!mfib_test_entry(mfei,
573 MFIB_ENTRY_FLAG_NONE,
575 DPO_ADJACENCY_MCAST, ai_1),
577 format_mfib_prefix, pfx_star_g_1);
579 mfei = mfib_table_lookup(fib_index, pfx_star_g_1);
581 MFIB_TEST(!mfib_test_entry(mfei,
582 MFIB_ENTRY_FLAG_NONE,
584 DPO_ADJACENCY_MCAST, ai_1),
586 format_mfib_prefix, pfx_star_g_1);
588 mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
590 MFIB_TEST(!mfib_test_entry(mfei,
591 MFIB_ENTRY_FLAG_NONE,
593 DPO_ADJACENCY_MCAST, ai_1,
594 DPO_ADJACENCY_MCAST, ai_2,
595 DPO_ADJACENCY_MCAST, ai_3),
597 format_mfib_prefix, pfx_s_g);
598 mfei = mfib_table_lookup(fib_index, pfx_s_g);
600 MFIB_TEST(!mfib_test_entry(mfei,
601 MFIB_ENTRY_FLAG_NONE,
603 DPO_ADJACENCY_MCAST, ai_1,
604 DPO_ADJACENCY_MCAST, ai_2,
605 DPO_ADJACENCY_MCAST, ai_3),
607 format_mfib_prefix, pfx_s_g);
609 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
610 MFIB_TEST(mfei = mfei_g_m,
611 "%U Found via exact match",
612 format_mfib_prefix, pfx_star_g_slash_m);
613 MFIB_TEST(!mfib_test_entry(mfei,
614 MFIB_ENTRY_FLAG_NONE,
616 DPO_ADJACENCY_MCAST, ai_3),
618 format_mfib_prefix, pfx_star_g_slash_m);
619 MFIB_TEST(mfei_g_m == mfib_table_lookup(fib_index, pfx_star_g_slash_m),
621 format_mfib_prefix, pfx_star_g_slash_m);
626 fib_route_path_t path_for_us = {
627 .frp_proto = fib_proto_to_dpo(PROTO),
628 .frp_addr = zero_addr,
629 .frp_sw_if_index = 0xffffffff,
632 .frp_flags = FIB_ROUTE_PATH_LOCAL,
633 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
636 mfei = mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
637 MFIB_ENTRY_FLAG_NONE, &path_for_us);
639 MFIB_TEST(!mfib_test_entry(mfei,
640 MFIB_ENTRY_FLAG_NONE,
642 DPO_ADJACENCY_MCAST, ai_1,
643 DPO_ADJACENCY_MCAST, ai_2,
644 DPO_ADJACENCY_MCAST, ai_3,
647 format_mfib_prefix, pfx_s_g);
650 * remove a for-us path
652 mfib_table_entry_path_remove(fib_index,
657 MFIB_TEST(!mfib_test_entry(mfei,
658 MFIB_ENTRY_FLAG_NONE,
660 DPO_ADJACENCY_MCAST, ai_1,
661 DPO_ADJACENCY_MCAST, ai_2,
662 DPO_ADJACENCY_MCAST, ai_3),
664 format_mfib_prefix, pfx_s_g);
667 * update an existing forwarding path to be only accepting
668 * - expect it to be removed from the replication set.
670 path_via_if3.frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT;
671 mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
672 MFIB_ENTRY_FLAG_NONE, &path_via_if3);
674 MFIB_TEST(!mfib_test_entry(mfei,
675 MFIB_ENTRY_FLAG_NONE,
677 DPO_ADJACENCY_MCAST, ai_1,
678 DPO_ADJACENCY_MCAST, ai_2),
680 format_mfib_prefix, pfx_s_g);
681 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
682 MFIB_ITF_FLAG_ACCEPT));
683 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
684 MFIB_ITF_FLAG_FORWARD));
685 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
686 MFIB_ITF_FLAG_FORWARD));
687 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
688 MFIB_ITF_FLAG_ACCEPT));
690 * Make the path forwarding again
691 * - expect it to be added back to the replication set
693 path_via_if3.frp_mitf_flags = (MFIB_ITF_FLAG_FORWARD |
694 MFIB_ITF_FLAG_ACCEPT |
695 MFIB_ITF_FLAG_NEGATE_SIGNAL);
696 mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
697 MFIB_ENTRY_FLAG_NONE, &path_via_if3);
699 mfei = mfib_table_lookup_exact_match(fib_index,
702 MFIB_TEST(!mfib_test_entry(mfei,
703 MFIB_ENTRY_FLAG_NONE,
705 DPO_ADJACENCY_MCAST, ai_1,
706 DPO_ADJACENCY_MCAST, ai_2,
707 DPO_ADJACENCY_MCAST, ai_3),
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_FORWARD |
718 MFIB_ITF_FLAG_ACCEPT |
719 MFIB_ITF_FLAG_NEGATE_SIGNAL)));
722 * update flags on the entry
724 mfib_table_entry_update(fib_index,
728 MFIB_ENTRY_FLAG_SIGNAL);
729 MFIB_TEST(!mfib_test_entry(mfei,
730 MFIB_ENTRY_FLAG_SIGNAL,
732 DPO_ADJACENCY_MCAST, ai_1,
733 DPO_ADJACENCY_MCAST, ai_2,
734 DPO_ADJACENCY_MCAST, ai_3),
736 format_mfib_prefix, pfx_s_g);
741 mfib_table_entry_path_remove(fib_index,
746 MFIB_TEST(!mfib_test_entry(mfei,
747 MFIB_ENTRY_FLAG_SIGNAL,
749 DPO_ADJACENCY_MCAST, ai_1,
750 DPO_ADJACENCY_MCAST, ai_2),
752 format_mfib_prefix, pfx_s_g);
753 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
754 MFIB_ITF_FLAG_ACCEPT));
755 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
756 MFIB_ITF_FLAG_FORWARD));
757 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
758 MFIB_ITF_FLAG_FORWARD));
759 MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
761 mfib_table_entry_path_remove(fib_index,
766 MFIB_TEST(!mfib_test_entry(mfei,
767 MFIB_ENTRY_FLAG_SIGNAL,
769 DPO_ADJACENCY_MCAST, ai_2),
771 format_mfib_prefix, pfx_s_g);
772 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
773 MFIB_ITF_FLAG_ACCEPT));
774 MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
775 MFIB_ITF_FLAG_FORWARD));
776 MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
781 /* mfib_table_entry_path_remove(fib_index, */
783 /* MFIB_SOURCE_API, */
784 /* &path_via_if0); */
786 /* MFIB_TEST(!mfib_test_entry(mfei, */
787 /* MFIB_ENTRY_FLAG_SIGNAL, */
789 /* DPO_ADJACENCY_MCAST, ai_2), */
790 /* "%U replicate OK", */
791 /* format_mfib_prefix, pfx_s_g); */
792 /* MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index, */
793 /* MFIB_ITF_FLAG_FORWARD)); */
794 /* MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[0]->sw_if_index)); */
795 /* MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[1]->sw_if_index)); */
796 /* MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index)); */
799 * remove the last path and the accepting only interface,
800 * the entry still has flags so it remains
802 vec_reset_length(two_paths);
803 vec_add1(two_paths, path_via_if0);
804 vec_add1(two_paths, path_via_if2);
806 mfib_table_entry_paths_remove(fib_index,
811 MFIB_TEST(!mfib_test_entry(mfei,
812 MFIB_ENTRY_FLAG_SIGNAL,
814 "%U no replications",
815 format_mfib_prefix, pfx_s_g);
818 * update flags on the entry
820 mfib_table_entry_update(fib_index,
824 (MFIB_ENTRY_FLAG_SIGNAL |
825 MFIB_ENTRY_FLAG_CONNECTED));
826 MFIB_TEST(!mfib_test_entry(mfei,
827 (MFIB_ENTRY_FLAG_SIGNAL |
828 MFIB_ENTRY_FLAG_CONNECTED),
830 "%U no replications",
831 format_mfib_prefix, pfx_s_g);
834 * An entry with a NS interface
836 path_via_if0.frp_mitf_flags = (MFIB_ITF_FLAG_ACCEPT |
837 MFIB_ITF_FLAG_NEGATE_SIGNAL);
839 mfib_table_entry_path_update (fib_index, pfx_star_g_2, MFIB_SOURCE_API,
840 MFIB_ENTRY_FLAG_NONE, &path_via_if0);
841 MFIB_TEST(!mfib_test_entry(mfei_g_2,
842 MFIB_ENTRY_FLAG_NONE,
844 "%U No replications",
845 format_mfib_prefix, pfx_star_g_2);
848 * Simulate a signal from the data-plane
854 mfe = mfib_entry_get(mfei_g_2);
855 mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
857 mfib_signal_push(mfe, mfi, NULL);
861 * An entry with a NS interface
863 path_via_if0.frp_mitf_flags = (MFIB_ITF_FLAG_ACCEPT |
864 MFIB_ITF_FLAG_NEGATE_SIGNAL);
866 mfib_table_entry_path_update (fib_index, pfx_star_g_3, MFIB_SOURCE_API,
867 MFIB_ENTRY_FLAG_NONE, &path_via_if0);
868 MFIB_TEST(!mfib_test_entry(mfei_g_3,
869 MFIB_ENTRY_FLAG_NONE,
871 "%U No replications",
872 format_mfib_prefix, pfx_star_g_3);
875 * Simulate a signal from the data-plane
881 mfe = mfib_entry_get(mfei_g_3);
882 mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
884 mfib_signal_push(mfe, mfi, NULL);
887 if (FIB_PROTOCOL_IP6 == PROTO)
890 * All the entries are present. let's ensure we can find them all
891 * via exact and longest prefix matches.
894 * A source address we will never match
896 ip6_address_t src = {
897 .as_u64[0] = clib_host_to_net_u64(0x3001000000000000),
898 .as_u64[1] = clib_host_to_net_u64(0xffffffffffffffff),
904 MFIB_TEST((mfei_g_m == ip6_mfib_table_fwd_lookup(
905 ip6_mfib_get(fib_index),
907 &pfx_star_g_slash_m->fp_grp_addr.ip6)),
908 "%U found via DP LPM grp=%U",
909 format_mfib_prefix, pfx_star_g_slash_m,
910 format_ip6_address, &pfx_star_g_slash_m->fp_grp_addr.ip6);
912 ip6_address_t tmp = pfx_star_g_slash_m->fp_grp_addr.ip6;
913 tmp.as_u8[15] = 0xff;
915 MFIB_TEST((mfei_g_m == ip6_mfib_table_fwd_lookup(
916 ip6_mfib_get(fib_index),
917 &pfx_s_g->fp_src_addr.ip6,
919 "%U found via DP LPM grp=%U",
920 format_mfib_prefix, pfx_star_g_slash_m,
921 format_ip6_address, &tmp);
926 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
927 &pfx_s_g->fp_src_addr.ip6,
928 &pfx_s_g->fp_grp_addr.ip6);
929 MFIB_TEST((mfei_s_g == mfei),
930 "%U found via DP LPM: %d",
931 format_mfib_prefix, pfx_s_g, mfei);
936 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
938 &pfx_star_g_1->fp_grp_addr.ip6);
939 MFIB_TEST((mfei_g_1 == mfei),
940 "%U found via DP LPM: %d",
941 format_mfib_prefix, pfx_star_g_1, mfei);
942 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
944 &pfx_star_g_2->fp_grp_addr.ip6);
945 MFIB_TEST((mfei_g_2 == mfei),
946 "%U found via DP LPM: %d",
947 format_mfib_prefix, pfx_star_g_2, mfei);
948 mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
950 &pfx_star_g_3->fp_grp_addr.ip6);
951 MFIB_TEST((mfei_g_3 == mfei),
952 "%U found via DP LPM: %d",
953 format_mfib_prefix, pfx_star_g_3, mfei);
957 * remove flags on the entry. This is the last of the
958 * state associated with the entry, so now it goes.
960 mfib_table_entry_update(fib_index,
964 MFIB_ENTRY_FLAG_NONE);
965 mfei = mfib_table_lookup_exact_match(fib_index,
967 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
969 format_mfib_prefix, pfx_s_g);
972 * remove the last path on the no forward entry - the last entry
974 mfib_table_entry_path_remove(fib_index,
979 mfei = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
980 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
982 format_mfib_prefix, pfx_no_forward);
985 * hard delete the (*,232.1.1.1)
987 mfib_table_entry_delete(fib_index,
991 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
992 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
994 format_mfib_prefix, pfx_star_g_1);
996 * remove the entry whilst the signal is pending
998 mfib_table_entry_delete(fib_index,
1002 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_2);
1003 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1005 format_mfib_prefix, pfx_star_g_2);
1006 mfib_table_entry_delete(fib_index,
1010 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_3);
1011 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1013 format_mfib_prefix, pfx_star_g_3);
1015 mfib_table_entry_delete(fib_index,
1019 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
1020 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1022 format_mfib_prefix, pfx_star_g_slash_m);
1025 * Entries with paths via unicast next-hops
1027 fib_route_path_t path_via_nbr1 = {
1028 .frp_proto = fib_proto_to_dpo(PROTO),
1029 .frp_addr = *addr_nbr1,
1030 .frp_sw_if_index = tm->hw[0]->sw_if_index,
1031 .frp_fib_index = ~0,
1034 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1036 fib_route_path_t path_via_nbr2 = {
1037 .frp_proto = fib_proto_to_dpo(PROTO),
1038 .frp_addr = *addr_nbr2,
1039 .frp_sw_if_index = tm->hw[0]->sw_if_index,
1040 .frp_fib_index = ~0,
1043 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1047 mfib_table_entry_path_update (fib_index, pfx_star_g_1, MFIB_SOURCE_API,
1048 MFIB_ENTRY_FLAG_NONE, &path_via_nbr1);
1050 mfib_table_entry_path_update (fib_index, pfx_star_g_1, MFIB_SOURCE_API,
1051 MFIB_ENTRY_FLAG_NONE, &path_via_nbr2);
1052 MFIB_TEST(!mfib_test_entry(mfei_g_1,
1053 MFIB_ENTRY_FLAG_NONE,
1055 DPO_ADJACENCY_INCOMPLETE, ai_nbr1,
1056 DPO_ADJACENCY_INCOMPLETE, ai_nbr2),
1058 format_mfib_prefix, pfx_star_g_1);
1059 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_g_1, tm->hw[0]->sw_if_index,
1060 MFIB_ITF_FLAG_FORWARD));
1062 mfib_table_entry_path_remove(fib_index,
1067 MFIB_TEST(!mfib_test_entry(mfei_g_1,
1068 MFIB_ENTRY_FLAG_NONE,
1070 DPO_ADJACENCY_INCOMPLETE, ai_nbr2),
1072 format_mfib_prefix, pfx_star_g_1);
1073 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_g_1, tm->hw[0]->sw_if_index,
1074 MFIB_ITF_FLAG_FORWARD));
1076 mfib_table_entry_path_remove(fib_index,
1080 mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
1081 MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1083 format_mfib_prefix, pfx_star_g_1);
1086 * Add a prefix as a special/exclusive route
1088 dpo_id_t td = DPO_INVALID;
1089 index_t repi = replicate_create(1, fib_proto_to_dpo(PROTO));
1091 dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_2);
1092 replicate_set_bucket(repi, 0, &td);
1094 mfei = mfib_table_entry_special_add(fib_index,
1097 MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF,
1099 MFIB_TEST(!mfib_test_entry(mfei,
1100 (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
1101 MFIB_ENTRY_FLAG_EXCLUSIVE),
1103 DPO_ADJACENCY_MCAST, ai_2),
1104 "%U exclusive replicate OK",
1105 format_mfib_prefix, pfx_star_g_3);
1108 * update a special/exclusive route
1110 index_t repi2 = replicate_create(1, fib_proto_to_dpo(PROTO));
1112 dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_1);
1113 replicate_set_bucket(repi2, 0, &td);
1115 mfib_entry_update(mfei,
1117 (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
1118 MFIB_ENTRY_FLAG_EXCLUSIVE),
1121 MFIB_TEST(!mfib_test_entry(mfei,
1122 (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
1123 MFIB_ENTRY_FLAG_EXCLUSIVE),
1125 DPO_ADJACENCY_MCAST, ai_1),
1126 "%U exclusive update replicate OK",
1127 format_mfib_prefix, pfx_star_g_3);
1129 mfib_table_entry_delete(fib_index,
1135 * A Multicast LSP. This a mLDP head-end
1137 fib_node_index_t ai_mpls_10_10_10_1, lfei;
1138 ip46_address_t nh_10_10_10_1 = {
1140 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
1143 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
1146 tm->hw[0]->sw_if_index);
1148 fib_prefix_t pfx_3500 = {
1150 .fp_proto = FIB_PROTOCOL_MPLS,
1153 .fp_payload_proto = DPO_PROTO_IP4,
1155 fib_test_rep_bucket_t mc_0 = {
1156 .type = FT_REP_LABEL_O_ADJ,
1158 .adj = ai_mpls_10_10_10_1,
1163 fib_mpls_label_t *l3300 = NULL, fml3300 = {
1166 vec_add1(l3300, fml3300);
1169 * MPLS enable an interface so we get the MPLS table created
1171 mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL);
1172 mpls_sw_interface_enable_disable (&mpls_main, tm->hw[0]->sw_if_index, 1);
1174 lfei = fib_table_entry_update_one_path(0, // default MPLS Table
1177 FIB_ENTRY_FLAG_MULTICAST,
1180 tm->hw[0]->sw_if_index,
1181 ~0, // invalid fib index
1184 FIB_ROUTE_PATH_FLAG_NONE);
1185 MFIB_TEST(!fib_test_validate_entry(lfei,
1186 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
1189 "3500 via replicate over 10.10.10.1");
1192 * An (S,G) that resolves via the mLDP head-end
1194 fib_route_path_t path_via_mldp = {
1195 .frp_proto = DPO_PROTO_MPLS,
1196 .frp_local_label = pfx_3500.fp_label,
1197 .frp_eos = MPLS_EOS,
1198 .frp_sw_if_index = 0xffffffff,
1201 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
1202 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1204 dpo_id_t mldp_dpo = DPO_INVALID;
1206 fib_entry_contribute_forwarding(lfei,
1207 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
1210 mfei = mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
1211 MFIB_ENTRY_FLAG_NONE, &path_via_mldp);
1213 MFIB_TEST(!mfib_test_entry(mfei,
1214 MFIB_ENTRY_FLAG_NONE,
1216 DPO_REPLICATE, mldp_dpo.dpoi_index),
1217 "%U over-mLDP replicate OK",
1218 format_mfib_prefix, pfx_s_g);
1221 * add a for-us path. this tests two types of non-attached paths on one entry
1223 mfei = mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
1224 MFIB_ENTRY_FLAG_NONE, &path_for_us);
1225 MFIB_TEST(!mfib_test_entry(mfei,
1226 MFIB_ENTRY_FLAG_NONE,
1228 DPO_REPLICATE, mldp_dpo.dpoi_index,
1230 "%U mLDP+for-us replicate OK",
1231 format_mfib_prefix, pfx_s_g);
1233 mfib_table_entry_delete(fib_index,
1236 fib_table_entry_delete(0,
1239 dpo_reset(&mldp_dpo);
1242 * Unlock the table - it's the last lock so should be gone thereafter
1244 MFIB_TEST(((PROTO == FIB_PROTOCOL_IP4 ? 3 : 5) ==
1245 mfib_table_get_n_routes(fib_index, PROTO)),
1246 "1 = %d route left in the FIB",
1247 mfib_table_get_n_routes(fib_index, PROTO));
1249 mfib_table_unlock(fib_index, PROTO, MFIB_SOURCE_API);
1251 MFIB_TEST((FIB_NODE_INDEX_INVALID ==
1252 mfib_table_find(PROTO, fib_index)),
1253 "MFIB table %d gone", fib_index);
1258 adj_unlock(ai_nbr1);
1259 adj_unlock(ai_nbr2);
1262 * MPLS disable the interface
1264 mpls_sw_interface_enable_disable (&mpls_main, tm->hw[0]->sw_if_index, 0);
1265 mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
1268 * remove the connected
1270 fib_table_entry_delete(0, pfx_itf, FIB_SOURCE_INTERFACE);
1273 * test we've leaked no resources
1275 MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
1276 MFIB_TEST(n_pls == fib_path_list_pool_size(), "%d=%d path-lists",
1277 n_pls, fib_path_list_pool_size());
1278 MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
1279 n_reps, pool_elts(replicate_pool));
1280 MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
1281 " No more entries %d!=%d",
1282 n_entries, pool_elts(mfib_entry_pool));
1283 MFIB_TEST(n_itfs == pool_elts(mfib_itf_pool),
1284 " No more Interfaces %d!=%d",
1285 n_itfs, pool_elts(mfib_itf_pool));
1286 vec_free(two_paths);
1294 const mfib_prefix_t pfx_224_s_8 = {
1296 .fp_proto = FIB_PROTOCOL_IP4,
1298 .ip4.as_u32 = clib_host_to_net_u32(0xe0000000),
1301 const mfib_prefix_t pfx_1_1_1_1_c_239_1_1_1 = {
1303 .fp_proto = FIB_PROTOCOL_IP4,
1305 .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1308 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1311 const mfib_prefix_t pfx_239_1_1_1 = {
1313 .fp_proto = FIB_PROTOCOL_IP4,
1315 .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1321 const mfib_prefix_t pfx_239_1_1_2 = {
1323 .fp_proto = FIB_PROTOCOL_IP4,
1325 .ip4.as_u32 = clib_host_to_net_u32(0xef010102),
1331 const mfib_prefix_t pfx_239_1_1_3 = {
1333 .fp_proto = FIB_PROTOCOL_IP4,
1335 .ip4.as_u32 = clib_host_to_net_u32(0xef010103),
1341 const mfib_prefix_t pfx_239 = {
1343 .fp_proto = FIB_PROTOCOL_IP4,
1345 .ip4.as_u32 = clib_host_to_net_u32(0xef000000),
1351 const fib_prefix_t pfx_itf = {
1353 .fp_proto = FIB_PROTOCOL_IP4,
1355 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
1358 const ip46_address_t nbr1 = {
1359 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0b),
1361 const ip46_address_t nbr2 = {
1362 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0c),
1364 return (mfib_test_i(FIB_PROTOCOL_IP4,
1367 &pfx_1_1_1_1_c_239_1_1_1,
1380 const mfib_prefix_t pfx_ffd_s_12 = {
1382 .fp_proto = FIB_PROTOCOL_IP6,
1384 .ip6.as_u64[0] = clib_host_to_net_u64(0xffd0000000000000),
1387 const mfib_prefix_t pfx_2001_1_c_ff_1 = {
1389 .fp_proto = FIB_PROTOCOL_IP6,
1391 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1392 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1395 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1396 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1399 const mfib_prefix_t pfx_ff_1 = {
1401 .fp_proto = FIB_PROTOCOL_IP6,
1403 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1404 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1407 const mfib_prefix_t pfx_ff_2 = {
1409 .fp_proto = FIB_PROTOCOL_IP6,
1411 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1412 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1415 const mfib_prefix_t pfx_ff_3 = {
1417 * this is the ALL DHCP routers address
1420 .fp_proto = FIB_PROTOCOL_IP6,
1422 .ip6.as_u64[0] = clib_host_to_net_u64(0xff02000100000000),
1423 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1426 const mfib_prefix_t pfx_ff = {
1428 .fp_proto = FIB_PROTOCOL_IP6,
1430 .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1431 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000000),
1434 const fib_prefix_t pfx_itf = {
1436 .fp_proto = FIB_PROTOCOL_IP6,
1438 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1439 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1442 const ip46_address_t nbr1 = {
1443 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1444 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1446 const ip46_address_t nbr2 = {
1447 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1448 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000003),
1451 return (mfib_test_i(FIB_PROTOCOL_IP6,
1465 mfib_test_rr_i (fib_protocol_t FPROTO,
1468 const mfib_prefix_t *pfx_cover,
1469 const mfib_prefix_t *pfx_host1,
1470 const mfib_prefix_t *pfx_host2)
1472 fib_node_index_t mfei_cover, mfei_host1, mfei_host2, ai_1, ai_2;
1473 u32 fib_index, n_entries, n_itfs, n_reps, n_pls;
1478 n_entries = pool_elts(mfib_entry_pool);
1479 n_itfs = pool_elts(mfib_itf_pool);
1480 n_reps = pool_elts(replicate_pool);
1481 n_pls = fib_path_list_pool_size();
1485 ai_1 = adj_mcast_add_or_lock(FPROTO,
1487 tm->hw[1]->sw_if_index);
1488 ai_2 = adj_mcast_add_or_lock(FPROTO,
1490 tm->hw[2]->sw_if_index);
1492 fib_route_path_t path_via_if0 = {
1493 .frp_proto = DPROTO,
1494 .frp_addr = zero_addr,
1495 .frp_sw_if_index = tm->hw[0]->sw_if_index,
1496 .frp_fib_index = ~0,
1499 .frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT,
1501 fib_route_path_t path_via_if1 = {
1502 .frp_proto = DPROTO,
1503 .frp_addr = zero_addr,
1504 .frp_sw_if_index = tm->hw[1]->sw_if_index,
1505 .frp_fib_index = ~0,
1508 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1510 fib_route_path_t path_via_if2 = {
1511 .frp_proto = DPROTO,
1512 .frp_addr = zero_addr,
1513 .frp_sw_if_index = tm->hw[2]->sw_if_index,
1514 .frp_fib_index = ~0,
1517 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1519 fib_route_path_t path_for_us = {
1520 .frp_proto = DPROTO,
1521 .frp_addr = zero_addr,
1522 .frp_sw_if_index = 0xffffffff,
1523 .frp_fib_index = ~0,
1525 .frp_flags = FIB_ROUTE_PATH_LOCAL,
1526 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
1530 * with only the default in place, recusre thru the /32
1532 mfei_host1 = mfib_table_entry_special_add(fib_index, pfx_host1,
1534 MFIB_ENTRY_FLAG_NONE,
1537 * expect its forwarding to match the cover's
1539 MFIB_TEST(!mfib_test_entry(mfei_host1,
1540 MFIB_ENTRY_FLAG_DROP,
1542 "%U no replications OK",
1543 format_mfib_prefix, pfx_host1);
1546 * Insert the less specific /28
1548 mfib_table_entry_path_update (fib_index, pfx_cover, MFIB_SOURCE_API,
1549 MFIB_ENTRY_FLAG_NONE, &path_via_if1);
1551 mfei_cover = mfib_table_lookup_exact_match(fib_index, pfx_cover);
1553 MFIB_TEST(!mfib_test_entry(mfei_cover,
1554 MFIB_ENTRY_FLAG_NONE,
1556 DPO_ADJACENCY_MCAST, ai_1),
1558 format_mfib_prefix, pfx_cover);
1561 * expect the /32 forwarding to match the new cover's
1563 MFIB_TEST(!mfib_test_entry(mfei_host1,
1564 MFIB_ENTRY_FLAG_NONE,
1566 DPO_ADJACENCY_MCAST, ai_1),
1568 format_mfib_prefix, pfx_host1);
1571 * add another path to the cover
1573 mfib_table_entry_path_update (fib_index, pfx_cover, MFIB_SOURCE_API,
1574 MFIB_ENTRY_FLAG_NONE, &path_via_if2);
1577 * expect the /32 and /28 to be via both boths
1579 MFIB_TEST(!mfib_test_entry(mfei_cover,
1580 MFIB_ENTRY_FLAG_NONE,
1582 DPO_ADJACENCY_MCAST, ai_1,
1583 DPO_ADJACENCY_MCAST, ai_2),
1585 format_mfib_prefix, pfx_cover);
1586 MFIB_TEST(!mfib_test_entry(mfei_host1,
1587 MFIB_ENTRY_FLAG_NONE,
1589 DPO_ADJACENCY_MCAST, ai_1,
1590 DPO_ADJACENCY_MCAST, ai_2),
1592 format_mfib_prefix, pfx_host1);
1595 * and the other host whilst all is ready
1597 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1599 MFIB_ENTRY_FLAG_NONE,
1601 MFIB_TEST(!mfib_test_entry(mfei_host2,
1602 MFIB_ENTRY_FLAG_NONE,
1604 DPO_ADJACENCY_MCAST, ai_1,
1605 DPO_ADJACENCY_MCAST, ai_2),
1607 format_mfib_prefix, pfx_host2);
1610 * repaet multiple time to simulate multiple recursve children
1612 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1614 MFIB_ENTRY_FLAG_NONE,
1616 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1618 MFIB_ENTRY_FLAG_NONE,
1620 mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
1622 MFIB_ENTRY_FLAG_NONE,
1626 * add an accepting path to the cover
1628 mfib_table_entry_path_update (fib_index, pfx_cover, MFIB_SOURCE_API,
1629 MFIB_ENTRY_FLAG_NONE, &path_via_if0);
1632 * expect the /32 and /28 to be via both boths
1634 MFIB_TEST(!mfib_test_entry(mfei_cover,
1635 MFIB_ENTRY_FLAG_NONE,
1637 DPO_ADJACENCY_MCAST, ai_1,
1638 DPO_ADJACENCY_MCAST, ai_2),
1640 format_mfib_prefix, pfx_cover);
1641 MFIB_TEST(!mfib_test_entry(mfei_host1,
1642 MFIB_ENTRY_FLAG_NONE,
1644 DPO_ADJACENCY_MCAST, ai_1,
1645 DPO_ADJACENCY_MCAST, ai_2),
1647 format_mfib_prefix, pfx_cover);
1648 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[0]->sw_if_index,
1649 MFIB_ITF_FLAG_ACCEPT));
1650 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[0]->sw_if_index,
1651 MFIB_ITF_FLAG_ACCEPT));
1652 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[1]->sw_if_index,
1653 MFIB_ITF_FLAG_FORWARD));
1654 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[1]->sw_if_index,
1655 MFIB_ITF_FLAG_FORWARD));
1656 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[2]->sw_if_index,
1657 MFIB_ITF_FLAG_FORWARD));
1658 MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[2]->sw_if_index,
1659 MFIB_ITF_FLAG_FORWARD));
1662 * add a for-us path to the cover
1664 mfib_table_entry_path_update (fib_index, pfx_cover, MFIB_SOURCE_API,
1665 MFIB_ENTRY_FLAG_NONE, &path_for_us);
1668 * expect the /32 and /28 to be via all three paths
1670 MFIB_TEST(!mfib_test_entry(mfei_cover,
1671 MFIB_ENTRY_FLAG_NONE,
1673 DPO_ADJACENCY_MCAST, ai_1,
1674 DPO_ADJACENCY_MCAST, ai_2,
1677 format_mfib_prefix, pfx_cover);
1678 MFIB_TEST(!mfib_test_entry(mfei_host1,
1679 MFIB_ENTRY_FLAG_NONE,
1681 DPO_ADJACENCY_MCAST, ai_1,
1682 DPO_ADJACENCY_MCAST, ai_2,
1685 format_mfib_prefix, pfx_cover);
1688 * get the forwarding chain from the RR prefix
1691 dpo_id_t dpo = DPO_INVALID;
1693 mfib_entry_contribute_forwarding(
1695 mfib_forw_chain_type_from_dpo_proto(DPROTO),
1696 MFIB_ENTRY_FWD_FLAG_NONE,
1699 rep = replicate_get(dpo.dpoi_index);
1700 MFIB_TEST((3 == rep->rep_n_buckets),
1701 "%U replicate 3 buckets",
1702 format_mfib_prefix, pfx_host1);
1705 * get the forwarding chain from the RR prefix without local paths
1707 mfib_entry_contribute_forwarding(
1709 mfib_forw_chain_type_from_dpo_proto(DPROTO),
1710 MFIB_ENTRY_FWD_FLAG_NO_LOCAL,
1713 rep = replicate_get(dpo.dpoi_index);
1714 MFIB_TEST((2 == rep->rep_n_buckets),
1715 "%U no-local replicate 2 buckets",
1716 format_mfib_prefix, pfx_host1);
1721 * delete the cover, expect the /32 to be via the default
1723 mfib_table_entry_delete(fib_index, pfx_cover, MFIB_SOURCE_API);
1724 MFIB_TEST(!mfib_test_entry(mfei_host1,
1725 MFIB_ENTRY_FLAG_DROP,
1727 "%U no replications OK",
1728 format_mfib_prefix, pfx_host1);
1731 * source the /32 with its own path
1734 mfib_table_entry_path_update (fib_index, pfx_host1, MFIB_SOURCE_API,
1735 MFIB_ENTRY_FLAG_NONE, &path_via_if2);
1736 MFIB_TEST(!mfib_test_entry(mfei_host1,
1737 MFIB_ENTRY_FLAG_NONE,
1739 DPO_ADJACENCY_MCAST, ai_2),
1741 format_mfib_prefix, pfx_host1);
1744 * remove host2 - as many times as it was added
1746 mfib_table_entry_delete(fib_index, pfx_host2,
1748 mfib_table_entry_delete(fib_index, pfx_host2,
1750 mfib_table_entry_delete(fib_index, pfx_host2,
1752 mfib_table_entry_delete(fib_index, pfx_host2,
1757 * remove the RR source with paths present
1759 mfib_table_entry_delete(fib_index, pfx_host1,
1763 * add the RR back then remove the path and RR
1766 mfib_table_entry_path_update (fib_index, pfx_host1, MFIB_SOURCE_API,
1767 MFIB_ENTRY_FLAG_NONE, &path_via_if2);
1768 MFIB_TEST(!mfib_test_entry(mfei_host1,
1769 MFIB_ENTRY_FLAG_NONE,
1771 DPO_ADJACENCY_MCAST, ai_2),
1773 format_mfib_prefix, pfx_host1);
1775 mfib_table_entry_delete(fib_index, pfx_host1,
1777 mfib_table_entry_delete(fib_index, pfx_host1,
1781 * test we've leaked no resources
1785 MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
1786 MFIB_TEST(n_pls == fib_path_list_pool_size(), "%d=%d path-lists",
1787 n_pls, fib_path_list_pool_size());
1788 MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
1789 n_reps, pool_elts(replicate_pool));
1790 MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
1791 " No more entries %d!=%d",
1792 n_entries, pool_elts(mfib_entry_pool));
1793 MFIB_TEST(n_itfs == pool_elts(mfib_itf_pool),
1794 " No more Interfaces %d!=%d",
1795 n_itfs, pool_elts(mfib_itf_pool));
1800 mfib_test_rr_v4 (void)
1803 * 2 length of prefix to play with
1805 const mfib_prefix_t pfx_host1 = {
1807 .fp_proto = FIB_PROTOCOL_IP4,
1809 .ip4.as_u32 = clib_host_to_net_u32(0xe0001011),
1812 const mfib_prefix_t pfx_host2 = {
1814 .fp_proto = FIB_PROTOCOL_IP4,
1816 .ip4.as_u32 = clib_host_to_net_u32(0xe0001011),
1819 .ip4.as_u32 = clib_host_to_net_u32(0x10101010),
1822 const mfib_prefix_t pfx_cover = {
1824 .fp_proto = FIB_PROTOCOL_IP4,
1826 .ip4.as_u32 = clib_host_to_net_u32(0xe0001010),
1830 return (mfib_test_rr_i(FIB_PROTOCOL_IP4,
1839 mfib_test_rr_v6 (void)
1842 * 2 length of prefix to play with
1844 const mfib_prefix_t pfx_host1 = {
1846 .fp_proto = FIB_PROTOCOL_IP6,
1848 .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
1849 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1852 const mfib_prefix_t pfx_host2 = {
1854 .fp_proto = FIB_PROTOCOL_IP6,
1856 .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
1857 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1860 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1861 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1864 const mfib_prefix_t pfx_cover = {
1866 .fp_proto = FIB_PROTOCOL_IP6,
1868 .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
1869 .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000000),
1873 return (mfib_test_rr_i(FIB_PROTOCOL_IP6,
1881 static clib_error_t *
1882 mfib_test (vlib_main_t * vm,
1883 unformat_input_t * input,
1884 vlib_cli_command_t * cmd_arg)
1888 res += mfib_test_mk_intf(4);
1889 res += mfib_test_rr_v4();
1893 return clib_error_return(0, "MFIB RR V4 Unit Test Failed");
1896 res += mfib_test_rr_v6();
1900 return clib_error_return(0, "MFIB RR V6 Unit Test Failed");
1903 res += mfib_test_v4();
1907 return clib_error_return(0, "MFIB V4 Unit Test Failed");
1910 res += mfib_test_v6();
1914 return clib_error_return(0, "MFIB V6 Unit Test Failed");
1920 VLIB_CLI_COMMAND (test_fib_command, static) = {
1921 .path = "test mfib",
1922 .short_help = "mfib unit tests - DO NOT RUN ON A LIVE SYSTEM",
1923 .function = mfib_test,
1927 mfib_test_init (vlib_main_t *vm)
1932 VLIB_INIT_FUNCTION (mfib_test_init);