LCOV - code coverage report
Current view: top level - plugins/unittest - mfib_test.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 492 496 99.2 %
Date: 2023-07-05 22:20:52 Functions: 22 22 100.0 %

          Line data    Source code
       1             : /*
       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:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       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.
      14             :  */
      15             : 
      16             : #include <vnet/mpls/mpls_types.h>
      17             : 
      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>
      26             : 
      27             : #include <vnet/dpo/replicate_dpo.h>
      28             : #include <vnet/adj/adj_mcast.h>
      29             : 
      30             : #define MFIB_TEST_I(_cond, _comment, _args...)                  \
      31             : ({                                                              \
      32             :     int _evald = (_cond);                                       \
      33             :     if (!(_evald)) {                                            \
      34             :         fformat(stderr, "FAIL:%d: " _comment "\n",          \
      35             :                 __LINE__, ##_args);                             \
      36             :         res = 1;                                                \
      37             :     }                                                           \
      38             :     res;                                                        \
      39             : })
      40             : #define MFIB_TEST(_cond, _comment, _args...)                    \
      41             : {                                                               \
      42             :     if (MFIB_TEST_I(_cond, _comment, ##_args)) {                \
      43             :         return 1;                                               \
      44             :         ASSERT(!("FAIL: " _comment));                         \
      45             :     }                                                           \
      46             : }
      47             : #define MFIB_TEST_NS(_cond)                                     \
      48             : {                                                               \
      49             :     if (MFIB_TEST_I(_cond, "")) {                               \
      50             :         return 1;                                               \
      51             :         ASSERT(!("FAIL: "));                                    \
      52             :     }                                                           \
      53             : }
      54             : 
      55             : /**
      56             :  * A 'i'm not fussed is this is not efficient' store of test data
      57             :  */
      58             : typedef struct test_main_t_ {
      59             :     /**
      60             :      * HW if indicies
      61             :      */
      62             :     u32 hw_if_indicies[4];
      63             :     /**
      64             :      * HW interfaces
      65             :      */
      66             :     vnet_hw_interface_t * hw[4];
      67             : 
      68             : } test_main_t;
      69             : static test_main_t test_main;
      70             : 
      71             : /* fake ethernet device class, distinct from "fake-ethX" */
      72           8 : static u8 * format_test_interface_name (u8 * s, va_list * args)
      73             : {
      74           8 :   u32 dev_instance = va_arg (*args, u32);
      75           8 :   return format (s, "test-eth%d", dev_instance);
      76             : }
      77             : 
      78           1 : static uword placeholder_interface_tx (vlib_main_t * vm,
      79             :                                  vlib_node_runtime_t * node,
      80             :                                  vlib_frame_t * frame)
      81             : {
      82           1 :   clib_warning ("you shouldn't be here, leaking buffers...");
      83           1 :   return frame->n_vectors;
      84             : }
      85             : 
      86             : static clib_error_t *
      87           4 : test_interface_admin_up_down (vnet_main_t * vnm,
      88             :                               u32 hw_if_index,
      89             :                               u32 flags)
      90             : {
      91           4 :   u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
      92             :     VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
      93           4 :   vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
      94           4 :   return 0;
      95             : }
      96             : 
      97        2799 : 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,
     102             : };
     103             : 
     104             : static u8 *hw_address;
     105             : 
     106             : static int
     107           1 : mfib_test_mk_intf (u32 ninterfaces)
     108             : {
     109           1 :     clib_error_t * error = NULL;
     110           1 :     test_main_t *tm = &test_main;
     111             :     u8 byte;
     112             :     int res;
     113             :     u32 i;
     114             : 
     115           1 :     res = 0;
     116           1 :     ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
     117             : 
     118           7 :     for (i=0; i<6; i++)
     119             :     {
     120           6 :         byte = 0xd0+i;
     121           6 :         vec_add1(hw_address, byte);
     122             :     }
     123             : 
     124           5 :     for (i = 0; i < ninterfaces; i++)
     125             :     {
     126           4 :       vnet_eth_interface_registration_t eir = {};
     127           4 :       vnet_main_t *vnm = vnet_get_main ();
     128             : 
     129           4 :       hw_address[5] = i;
     130             : 
     131           4 :       eir.dev_class_index = test_interface_device_class.index;
     132           4 :       eir.dev_instance = i;
     133           4 :       eir.address = hw_address;
     134           4 :       tm->hw_if_indicies[i] = vnet_eth_register_interface (vnm, &eir);
     135             : 
     136             :       error =
     137           4 :         vnet_hw_interface_set_flags (vnet_get_main (), tm->hw_if_indicies[i],
     138             :                                      VNET_HW_INTERFACE_FLAG_LINK_UP);
     139           4 :       tm->hw[i] =
     140           4 :         vnet_get_hw_interface (vnet_get_main (), tm->hw_if_indicies[i]);
     141           4 :       ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
     142           4 :       ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
     143             : 
     144           4 :       ip4_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
     145           4 :       ip6_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
     146             : 
     147             :       error =
     148           4 :         vnet_sw_interface_set_flags (vnet_get_main (), tm->hw[i]->sw_if_index,
     149             :                                      VNET_SW_INTERFACE_FLAG_ADMIN_UP);
     150           4 :       MFIB_TEST ((NULL == error), "UP interface %d", i);
     151             :     }
     152             :     /*
     153             :      * re-eval after the inevitable realloc
     154             :      */
     155           5 :     for (i = 0; i < ninterfaces; i++)
     156             :     {
     157           4 :         tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
     158             :                                           tm->hw_if_indicies[i]);
     159             :     }
     160             : 
     161           1 :     return (res);
     162             : }
     163             : 
     164             : #define MFIB_TEST_REP(_cond, _comment, _args...)                \
     165             : {                                                               \
     166             :     if (MFIB_TEST_I(_cond, _comment, ##_args)) {                \
     167             :         return (1);                                             \
     168             :     }                                                           \
     169             : }
     170             : 
     171             : static int
     172          68 : mfib_test_validate_rep_v (const replicate_t *rep,
     173             :                           u16 n_buckets,
     174             :                           va_list *ap)
     175             : {
     176             :     const dpo_id_t *dpo;
     177             :     adj_index_t ai;
     178             :     dpo_type_t dt;
     179             :     int bucket;
     180             :     int res;
     181             : 
     182          68 :     res = 0;
     183          68 :     MFIB_TEST_REP((n_buckets == rep->rep_n_buckets),
     184             :                   "n_buckets = %d", rep->rep_n_buckets);
     185             : 
     186         200 :     for (bucket = 0; bucket < n_buckets; bucket++)
     187             :     {
     188         132 :         dt = va_arg(*ap, int);  // type promotion
     189         132 :         ai = va_arg(*ap, adj_index_t);
     190         132 :         dpo = replicate_get_bucket_i(rep, bucket);
     191             : 
     192         132 :         MFIB_TEST_REP((dt == dpo->dpoi_type),
     193             :                       "bucket %d stacks on %U",
     194             :                       bucket,
     195             :                       format_dpo_type, dpo->dpoi_type);
     196             : 
     197         132 :         if (DPO_RECEIVE != dt)
     198             :         {
     199         124 :             MFIB_TEST_REP((ai == dpo->dpoi_index),
     200             :                           "bucket %d [exp:%d] stacks on %U",
     201             :                           bucket, ai,
     202             :                           format_dpo_id, dpo, 0);
     203             :         }
     204             :     }
     205          68 :     return (res);
     206             : }
     207             : 
     208             : static int
     209          86 : mfib_test_entry (fib_node_index_t fei,
     210             :                  mfib_entry_flags_t eflags,
     211             :                  int n_buckets,
     212             :                  ...)
     213             : {
     214             :     const mfib_prefix_t *pfx;
     215             :     const mfib_entry_t *mfe;
     216             :     const replicate_t *rep;
     217             :     va_list ap;
     218             :     int res;
     219             : 
     220             : 
     221          86 :     res = 0;
     222          86 :     mfe = mfib_entry_get(fei);
     223          86 :     pfx = mfib_entry_get_prefix(fei);
     224             : 
     225          86 :     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);
     230             : 
     231          86 :     if (0 == n_buckets)
     232             :     {
     233          18 :         MFIB_TEST_REP((DPO_DROP == mfe->mfe_rep.dpoi_type),
     234             :                       "%U links to %U",
     235             :                       format_mfib_prefix, pfx,
     236             :                       format_dpo_id, &mfe->mfe_rep, 0);
     237             :     }
     238             :     else
     239             :     {
     240          68 :         dpo_id_t tmp = DPO_INVALID;
     241             : 
     242          68 :         mfib_entry_contribute_forwarding(
     243             :             fei,
     244          68 :             mfib_forw_chain_type_from_fib_proto(pfx->fp_proto),
     245             :             MFIB_ENTRY_FWD_FLAG_NONE,
     246             :             &tmp);
     247          68 :         rep = replicate_get(tmp.dpoi_index);
     248             : 
     249          68 :         MFIB_TEST_REP((DPO_REPLICATE == tmp.dpoi_type),
     250             :                       "%U links to %U",
     251             :                       format_mfib_prefix, pfx,
     252             :                       format_dpo_type, tmp.dpoi_type);
     253             : 
     254          68 :         va_start(ap, n_buckets);
     255          68 :         res = mfib_test_validate_rep_v(rep, n_buckets, &ap);
     256          68 :         va_end(ap);
     257             : 
     258          68 :         dpo_reset(&tmp);
     259             :     }
     260             : 
     261             : 
     262          86 :     return (res);
     263             : }
     264             : 
     265             : static int
     266          52 : mfib_test_entry_itf (fib_node_index_t fei,
     267             :                      u32 sw_if_index,
     268             :                      mfib_itf_flags_t flags)
     269             : {
     270             :     const mfib_prefix_t *pfx;
     271             :     const mfib_entry_t *mfe;
     272             :     const mfib_itf_t *mfi;
     273             :     int res;
     274             : 
     275          52 :     res = 0;
     276          52 :     mfe = mfib_entry_get(fei);
     277          52 :     mfi = mfib_entry_get_itf(mfe, sw_if_index);
     278          52 :     pfx = mfib_entry_get_prefix(fei);
     279             : 
     280          52 :     MFIB_TEST_REP((NULL != mfi),
     281             :                   "%U has interface %d",
     282             :                   format_mfib_prefix, pfx, sw_if_index);
     283             : 
     284          52 :     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);
     289             : 
     290          52 :     return (res);
     291             : }
     292             : 
     293             : static int
     294           4 : mfib_test_entry_no_itf (fib_node_index_t fei,
     295             :                         u32 sw_if_index)
     296             : {
     297             :     const mfib_prefix_t *pfx;
     298             :     const mfib_entry_t *mfe;
     299             :     const mfib_itf_t *mfi;
     300             :     int res;
     301             : 
     302           4 :     res = 0;
     303           4 :     mfe = mfib_entry_get(fei);
     304           4 :     mfi = mfib_entry_get_itf(mfe, sw_if_index);
     305           4 :     pfx = mfib_entry_get_prefix(fei);
     306             : 
     307           4 :     MFIB_TEST_REP((NULL == mfi),
     308             :                   "%U has no interface %d",
     309             :                   format_mfib_prefix, pfx, sw_if_index);
     310             : 
     311           4 :     return (res);
     312             : }
     313             : 
     314             : static int
     315           2 : mfib_test_i (fib_protocol_t PROTO,
     316             :              vnet_link_t LINKT,
     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)
     326             : {
     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;
     330             :     test_main_t *tm;
     331             :     int res;
     332             : 
     333             :     mfib_prefix_t all_1s;
     334           2 :     clib_memset(&all_1s, 0xfd, sizeof(all_1s));
     335             : 
     336           2 :     res = 0;
     337           2 :     n_entries = pool_elts(mfib_entry_pool);
     338           2 :     n_itfs = pool_elts(mfib_itf_pool);
     339           2 :     n_reps = pool_elts(replicate_pool);
     340           2 :     n_pls = fib_path_list_pool_size();
     341           2 :     tm = &test_main;
     342             : 
     343           2 :     ai_1 = adj_mcast_add_or_lock(PROTO,
     344             :                                  LINKT,
     345           2 :                                  tm->hw[1]->sw_if_index);
     346           2 :     ai_2 = adj_mcast_add_or_lock(PROTO,
     347             :                                  LINKT,
     348           2 :                                  tm->hw[2]->sw_if_index);
     349           2 :     ai_3 = adj_mcast_add_or_lock(PROTO,
     350             :                                  LINKT,
     351           2 :                                  tm->hw[3]->sw_if_index);
     352           2 :     ai_nbr1 = adj_nbr_add_or_lock(PROTO,
     353             :                                   LINKT,
     354             :                                   addr_nbr1,
     355           2 :                                   tm->hw[0]->sw_if_index);
     356           2 :     ai_nbr2 = adj_nbr_add_or_lock(PROTO,
     357             :                                   LINKT,
     358             :                                   addr_nbr2,
     359           2 :                                   tm->hw[0]->sw_if_index);
     360             : 
     361           2 :     MFIB_TEST(3 == adj_mcast_db_size(), "3 MCAST adjs");
     362             : 
     363             :     /* Find or create FIB table 11 */
     364           2 :     fib_index = mfib_table_find_or_create_and_lock(PROTO, 11, MFIB_SOURCE_API);
     365             : 
     366           2 :     fib_table_entry_update_one_path(0,
     367             :                                     pfx_itf,
     368             :                                     FIB_SOURCE_INTERFACE,
     369             :                                     (FIB_ENTRY_FLAG_CONNECTED |
     370             :                                      FIB_ENTRY_FLAG_ATTACHED),
     371             :                                     DPO_PROTO_IP4,
     372             :                                     NULL,
     373           2 :                                     tm->hw[0]->sw_if_index,
     374             :                                     ~0, // invalid fib index
     375             :                                     1, // weight
     376             :                                     NULL,
     377             :                                     FIB_ROUTE_PATH_FLAG_NONE);
     378             : 
     379           2 :     mfib_prefix_t pfx_dft = {
     380             :         .fp_len = 0,
     381             :         .fp_proto = PROTO,
     382             :     };
     383           2 :     mfei_dflt = mfib_table_lookup_exact_match(fib_index, &pfx_dft);
     384           2 :     MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
     385           2 :     MFIB_TEST(!mfib_test_entry(mfei_dflt,
     386             :                                MFIB_ENTRY_FLAG_DROP,
     387             :                                0),
     388             :               "(*,*) no replcaitions");
     389             : 
     390           2 :     MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
     391           2 :     MFIB_TEST(!mfib_test_entry(mfei_dflt,
     392             :                                MFIB_ENTRY_FLAG_DROP,
     393             :                                0),
     394             :               "(*,*) no replcaitions");
     395             : 
     396             : 
     397           4 :     fib_route_path_t path_via_if0 = {
     398           2 :         .frp_proto = fib_proto_to_dpo(PROTO),
     399             :         .frp_addr = zero_addr,
     400           2 :         .frp_sw_if_index = tm->hw[0]->sw_if_index,
     401             :         .frp_fib_index = ~0,
     402             :         .frp_weight = 1,
     403             :         .frp_flags = 0,
     404             :         .frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT,
     405             :     };
     406             : 
     407           2 :     mfib_table_entry_path_update (fib_index, pfx_no_forward, MFIB_SOURCE_API,
     408             :                                   MFIB_ENTRY_FLAG_NONE, &path_via_if0);
     409             : 
     410           2 :     mfei_no_f = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
     411           2 :     MFIB_TEST(!mfib_test_entry(mfei_no_f,
     412             :                                MFIB_ENTRY_FLAG_NONE,
     413             :                                0),
     414             :               "%U no replcaitions",
     415             :               format_mfib_prefix, pfx_no_forward);
     416           2 :     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);
     420             : 
     421           4 :     fib_route_path_t path_via_if1 = {
     422           2 :         .frp_proto = fib_proto_to_dpo(PROTO),
     423             :         .frp_addr = zero_addr,
     424           2 :         .frp_sw_if_index = tm->hw[1]->sw_if_index,
     425             :         .frp_fib_index = ~0,
     426             :         .frp_weight = 1,
     427             :         .frp_flags = 0,
     428             :         .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
     429             :     };
     430           4 :     fib_route_path_t path_via_if2 = {
     431           2 :         .frp_proto = fib_proto_to_dpo(PROTO),
     432             :         .frp_addr = zero_addr,
     433           2 :         .frp_sw_if_index = tm->hw[2]->sw_if_index,
     434             :         .frp_fib_index = ~0,
     435             :         .frp_weight = 1,
     436             :         .frp_flags = 0,
     437             :         .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
     438             :     };
     439           4 :     fib_route_path_t path_via_if3 = {
     440           2 :         .frp_proto = fib_proto_to_dpo(PROTO),
     441             :         .frp_addr = zero_addr,
     442           2 :         .frp_sw_if_index = tm->hw[3]->sw_if_index,
     443             :         .frp_fib_index = ~0,
     444             :         .frp_weight = 1,
     445             :         .frp_flags = 0,
     446             :         .frp_mitf_flags = (MFIB_ITF_FLAG_FORWARD |
     447             :                            MFIB_ITF_FLAG_NEGATE_SIGNAL),
     448             :     };
     449           2 :     fib_route_path_t *two_paths = NULL;
     450           2 :     vec_add1(two_paths, path_via_if2);
     451           2 :     vec_add1(two_paths, path_via_if3);
     452             : 
     453             :     /*
     454             :      * An (S,G) with 1 accepting and 3 forwarding paths
     455             :      */
     456           2 :     mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
     457             :                                   MFIB_ENTRY_FLAG_NONE, &path_via_if0);
     458           2 :     mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
     459             :                                   MFIB_ENTRY_FLAG_NONE, &path_via_if1);
     460           2 :     mfib_table_entry_paths_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
     461             :                                    MFIB_ENTRY_FLAG_NONE, two_paths);
     462             : 
     463           2 :     mfei_s_g = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
     464             : 
     465           2 :     MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_s_g,
     466             :               "%U present",
     467             :               format_mfib_prefix, pfx_s_g);
     468           2 :     MFIB_TEST(!mfib_test_entry(mfei_s_g,
     469             :                                MFIB_ENTRY_FLAG_NONE,
     470             :                                3,
     471             :                                DPO_ADJACENCY_MCAST, ai_1,
     472             :                                DPO_ADJACENCY_MCAST, ai_2,
     473             :                                DPO_ADJACENCY_MCAST, ai_3),
     474             :               "%U replicate ok",
     475             :               format_mfib_prefix, pfx_s_g);
     476           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[0]->sw_if_index,
     477             :                                       MFIB_ITF_FLAG_ACCEPT));
     478           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[1]->sw_if_index,
     479             :                                       MFIB_ITF_FLAG_FORWARD));
     480           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[2]->sw_if_index,
     481             :                                       MFIB_ITF_FLAG_FORWARD));
     482           2 :     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)));
     485             : 
     486             :     /*
     487             :      * A (*,G), which the same G as the (S,G).
     488             :      * different paths. test our LPM.
     489             :      */
     490             :     mfei_g_1 =
     491           2 :       mfib_table_entry_path_update (fib_index, pfx_star_g_1, MFIB_SOURCE_API,
     492             :                                     MFIB_ENTRY_FLAG_NONE, &path_via_if0);
     493           2 :     mfib_table_entry_path_update (fib_index, pfx_star_g_1, MFIB_SOURCE_API,
     494             :                                   MFIB_ENTRY_FLAG_NONE, &path_via_if1);
     495             : 
     496             :     /*
     497             :      * test we find the *,G and S,G via LPM and exact matches
     498             :      */
     499           2 :     mfei = mfib_table_lookup_exact_match(fib_index,
     500             :                                          pfx_star_g_1);
     501           2 :     MFIB_TEST(mfei == mfei_g_1,
     502             :               "%U found via exact match",
     503             :               format_mfib_prefix, pfx_star_g_1);
     504           2 :     MFIB_TEST(!mfib_test_entry(mfei,
     505             :                                MFIB_ENTRY_FLAG_NONE,
     506             :                                1,
     507             :                                DPO_ADJACENCY_MCAST, ai_1),
     508             :               "%U replicate ok",
     509             :               format_mfib_prefix, pfx_star_g_1);
     510             : 
     511           2 :     mfei = mfib_table_lookup(fib_index,
     512             :                              pfx_star_g_1);
     513           2 :     MFIB_TEST(mfei == mfei_g_1,
     514             :               "[e:%d a:%d] %U found via LP match",
     515             :               mfei, mfei_g_1,
     516             :               format_mfib_prefix, pfx_star_g_1);
     517             : 
     518           2 :     MFIB_TEST(!mfib_test_entry(mfei,
     519             :                                MFIB_ENTRY_FLAG_NONE,
     520             :                                1,
     521             :                                DPO_ADJACENCY_MCAST, ai_1),
     522             :               "%U replicate ok",
     523             :               format_mfib_prefix, pfx_star_g_1);
     524             : 
     525           2 :     mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
     526           2 :     MFIB_TEST(mfei == mfei_s_g,
     527             :               "%U found via exact match",
     528             :               format_mfib_prefix, pfx_s_g);
     529             : 
     530           2 :     MFIB_TEST(!mfib_test_entry(mfei,
     531             :                                MFIB_ENTRY_FLAG_NONE,
     532             :                                3,
     533             :                                DPO_ADJACENCY_MCAST, ai_1,
     534             :                                DPO_ADJACENCY_MCAST, ai_2,
     535             :                                DPO_ADJACENCY_MCAST, ai_3),
     536             :               "%U replicate OK",
     537             :               format_mfib_prefix, pfx_s_g);
     538           2 :     mfei = mfib_table_lookup(fib_index, pfx_s_g);
     539           2 :     MFIB_TEST(mfei == mfei_s_g,
     540             :               "%U found via LP match",
     541             :               format_mfib_prefix, pfx_s_g);
     542             : 
     543           2 :     MFIB_TEST(!mfib_test_entry(mfei,
     544             :                                MFIB_ENTRY_FLAG_NONE,
     545             :                                3,
     546             :                                DPO_ADJACENCY_MCAST, ai_1,
     547             :                                DPO_ADJACENCY_MCAST, ai_2,
     548             :                                DPO_ADJACENCY_MCAST, ai_3),
     549             :               "%U replicate OK",
     550             :               format_mfib_prefix, pfx_s_g);
     551             : 
     552             :     /*
     553             :      * A (*,G/m), which the same root G as the (*,G).
     554             :      * different paths. test our LPM.
     555             :      */
     556           2 :     path_via_if2.frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT;
     557           2 :     mfei_g_m = mfib_table_entry_path_update (
     558             :       fib_index, pfx_star_g_slash_m, MFIB_SOURCE_API, MFIB_ENTRY_FLAG_NONE,
     559             :       &path_via_if2);
     560           2 :     mfib_table_entry_path_update (fib_index, pfx_star_g_slash_m,
     561             :                                   MFIB_SOURCE_API, MFIB_ENTRY_FLAG_NONE,
     562             :                                   &path_via_if3);
     563             : 
     564             :     /*
     565             :      * test we find the (*,G/m), (*,G) and (S,G) via LPM and exact matches
     566             :      */
     567           2 :     mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
     568           2 :     MFIB_TEST((mfei_g_1 == mfei),
     569             :               "%U found via DP LPM: %d",
     570             :               format_mfib_prefix, pfx_star_g_1, mfei);
     571             : 
     572           2 :     MFIB_TEST(!mfib_test_entry(mfei,
     573             :                                MFIB_ENTRY_FLAG_NONE,
     574             :                                1,
     575             :                                DPO_ADJACENCY_MCAST, ai_1),
     576             :               "%U replicate ok",
     577             :               format_mfib_prefix, pfx_star_g_1);
     578             : 
     579           2 :     mfei = mfib_table_lookup(fib_index, pfx_star_g_1);
     580             : 
     581           2 :     MFIB_TEST(!mfib_test_entry(mfei,
     582             :                                MFIB_ENTRY_FLAG_NONE,
     583             :                                1,
     584             :                                DPO_ADJACENCY_MCAST, ai_1),
     585             :               "%U replicate ok",
     586             :               format_mfib_prefix, pfx_star_g_1);
     587             : 
     588           2 :     mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
     589             : 
     590           2 :     MFIB_TEST(!mfib_test_entry(mfei,
     591             :                                MFIB_ENTRY_FLAG_NONE,
     592             :                                3,
     593             :                                DPO_ADJACENCY_MCAST, ai_1,
     594             :                                DPO_ADJACENCY_MCAST, ai_2,
     595             :                                DPO_ADJACENCY_MCAST, ai_3),
     596             :               "%U replicate OK",
     597             :               format_mfib_prefix, pfx_s_g);
     598           2 :     mfei = mfib_table_lookup(fib_index, pfx_s_g);
     599             : 
     600           2 :     MFIB_TEST(!mfib_test_entry(mfei,
     601             :                                MFIB_ENTRY_FLAG_NONE,
     602             :                                3,
     603             :                                DPO_ADJACENCY_MCAST, ai_1,
     604             :                                DPO_ADJACENCY_MCAST, ai_2,
     605             :                                DPO_ADJACENCY_MCAST, ai_3),
     606             :               "%U replicate OK",
     607             :               format_mfib_prefix, pfx_s_g);
     608             : 
     609           2 :     mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
     610           2 :     MFIB_TEST(mfei = mfei_g_m,
     611             :               "%U Found via exact match",
     612             :               format_mfib_prefix, pfx_star_g_slash_m);
     613           2 :     MFIB_TEST(!mfib_test_entry(mfei,
     614             :                                MFIB_ENTRY_FLAG_NONE,
     615             :                                1,
     616             :                                DPO_ADJACENCY_MCAST, ai_3),
     617             :               "%U replicate OK",
     618             :               format_mfib_prefix, pfx_star_g_slash_m);
     619           2 :     MFIB_TEST(mfei_g_m == mfib_table_lookup(fib_index, pfx_star_g_slash_m),
     620             :               "%U found via LPM",
     621             :               format_mfib_prefix, pfx_star_g_slash_m);
     622             : 
     623             :     /*
     624             :      * Add a for-us path
     625             :      */
     626           4 :     fib_route_path_t path_for_us = {
     627           2 :         .frp_proto = fib_proto_to_dpo(PROTO),
     628             :         .frp_addr = zero_addr,
     629             :         .frp_sw_if_index = 0xffffffff,
     630             :         .frp_fib_index = ~0,
     631             :         .frp_weight = 1,
     632             :         .frp_flags = FIB_ROUTE_PATH_LOCAL,
     633             :         .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
     634             :     };
     635             : 
     636           2 :     mfei = mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
     637             :                                          MFIB_ENTRY_FLAG_NONE, &path_for_us);
     638             : 
     639           2 :     MFIB_TEST(!mfib_test_entry(mfei,
     640             :                                MFIB_ENTRY_FLAG_NONE,
     641             :                                4,
     642             :                                DPO_ADJACENCY_MCAST, ai_1,
     643             :                                DPO_ADJACENCY_MCAST, ai_2,
     644             :                                DPO_ADJACENCY_MCAST, ai_3,
     645             :                                DPO_RECEIVE, 0),
     646             :               "%U replicate OK",
     647             :               format_mfib_prefix, pfx_s_g);
     648             : 
     649             :     /*
     650             :      * remove a for-us path
     651             :      */
     652           2 :     mfib_table_entry_path_remove(fib_index,
     653             :                                  pfx_s_g,
     654             :                                  MFIB_SOURCE_API,
     655             :                                  &path_for_us);
     656             : 
     657           2 :     MFIB_TEST(!mfib_test_entry(mfei,
     658             :                                MFIB_ENTRY_FLAG_NONE,
     659             :                                3,
     660             :                                DPO_ADJACENCY_MCAST, ai_1,
     661             :                                DPO_ADJACENCY_MCAST, ai_2,
     662             :                                DPO_ADJACENCY_MCAST, ai_3),
     663             :               "%U replicate OK",
     664             :               format_mfib_prefix, pfx_s_g);
     665             : 
     666             :     /*
     667             :      * update an existing forwarding path to be only accepting
     668             :      *   - expect it to be removed from the replication set.
     669             :      */
     670           2 :     path_via_if3.frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT;
     671           2 :     mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
     672             :                                   MFIB_ENTRY_FLAG_NONE, &path_via_if3);
     673             : 
     674           2 :     MFIB_TEST(!mfib_test_entry(mfei,
     675             :                                MFIB_ENTRY_FLAG_NONE,
     676             :                                2,
     677             :                                DPO_ADJACENCY_MCAST, ai_1,
     678             :                                DPO_ADJACENCY_MCAST, ai_2),
     679             :               "%U replicate OK",
     680             :               format_mfib_prefix, pfx_s_g);
     681           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
     682             :                                       MFIB_ITF_FLAG_ACCEPT));
     683           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
     684             :                                       MFIB_ITF_FLAG_FORWARD));
     685           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
     686             :                                       MFIB_ITF_FLAG_FORWARD));
     687           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
     688             :                                       MFIB_ITF_FLAG_ACCEPT));
     689             :     /*
     690             :      * Make the path forwarding again
     691             :      *  - expect it to be added back to the replication set
     692             :      */
     693           2 :     path_via_if3.frp_mitf_flags = (MFIB_ITF_FLAG_FORWARD |
     694             :                               MFIB_ITF_FLAG_ACCEPT |
     695             :                               MFIB_ITF_FLAG_NEGATE_SIGNAL);
     696           2 :     mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
     697             :                                   MFIB_ENTRY_FLAG_NONE, &path_via_if3);
     698             : 
     699           2 :     mfei = mfib_table_lookup_exact_match(fib_index,
     700             :                                          pfx_s_g);
     701             : 
     702           2 :     MFIB_TEST(!mfib_test_entry(mfei,
     703             :                                MFIB_ENTRY_FLAG_NONE,
     704             :                                3,
     705             :                                DPO_ADJACENCY_MCAST, ai_1,
     706             :                                DPO_ADJACENCY_MCAST, ai_2,
     707             :                                DPO_ADJACENCY_MCAST, ai_3),
     708             :               "%U replicate OK",
     709             :               format_mfib_prefix, pfx_s_g);
     710           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
     711             :                                       MFIB_ITF_FLAG_ACCEPT));
     712           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
     713             :                                       MFIB_ITF_FLAG_FORWARD));
     714           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
     715             :                                       MFIB_ITF_FLAG_FORWARD));
     716           2 :     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)));
     720             : 
     721             :     /*
     722             :      * update flags on the entry
     723             :      */
     724           2 :     mfib_table_entry_update(fib_index,
     725             :                             pfx_s_g,
     726             :                             MFIB_SOURCE_API,
     727             :                             MFIB_RPF_ID_NONE,
     728             :                             MFIB_ENTRY_FLAG_SIGNAL);
     729           2 :     MFIB_TEST(!mfib_test_entry(mfei,
     730             :                                MFIB_ENTRY_FLAG_SIGNAL,
     731             :                                3,
     732             :                                DPO_ADJACENCY_MCAST, ai_1,
     733             :                                DPO_ADJACENCY_MCAST, ai_2,
     734             :                                DPO_ADJACENCY_MCAST, ai_3),
     735             :               "%U replicate OK",
     736             :               format_mfib_prefix, pfx_s_g);
     737             : 
     738             :     /*
     739             :      * remove paths
     740             :      */
     741           2 :     mfib_table_entry_path_remove(fib_index,
     742             :                                  pfx_s_g,
     743             :                                  MFIB_SOURCE_API,
     744             :                                  &path_via_if3);
     745             : 
     746           2 :     MFIB_TEST(!mfib_test_entry(mfei,
     747             :                                MFIB_ENTRY_FLAG_SIGNAL,
     748             :                                2,
     749             :                                DPO_ADJACENCY_MCAST, ai_1,
     750             :                                DPO_ADJACENCY_MCAST, ai_2),
     751             :               "%U replicate OK",
     752             :               format_mfib_prefix, pfx_s_g);
     753           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
     754             :                                       MFIB_ITF_FLAG_ACCEPT));
     755           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
     756             :                                       MFIB_ITF_FLAG_FORWARD));
     757           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
     758             :                                       MFIB_ITF_FLAG_FORWARD));
     759           2 :     MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
     760             : 
     761           2 :     mfib_table_entry_path_remove(fib_index,
     762             :                                  pfx_s_g,
     763             :                                  MFIB_SOURCE_API,
     764             :                                  &path_via_if1);
     765             : 
     766           2 :     MFIB_TEST(!mfib_test_entry(mfei,
     767             :                                MFIB_ENTRY_FLAG_SIGNAL,
     768             :                                1,
     769             :                                DPO_ADJACENCY_MCAST, ai_2),
     770             :               "%U replicate OK",
     771             :               format_mfib_prefix, pfx_s_g);
     772           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
     773             :                                       MFIB_ITF_FLAG_ACCEPT));
     774           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
     775             :                                       MFIB_ITF_FLAG_FORWARD));
     776           2 :     MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
     777             : 
     778             :     /*
     779             :      * remove
     780             :      */
     781             :     /* mfib_table_entry_path_remove(fib_index, */
     782             :     /*                              pfx_s_g, */
     783             :     /*                              MFIB_SOURCE_API, */
     784             :     /*                              &path_via_if0); */
     785             : 
     786             :     /* MFIB_TEST(!mfib_test_entry(mfei, */
     787             :     /*                            MFIB_ENTRY_FLAG_SIGNAL, */
     788             :     /*                            1, */
     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)); */
     797             : 
     798             :     /*
     799             :      * remove the last path and the accepting only interface,
     800             :      * the entry still has flags so it remains
     801             :      */
     802           2 :     vec_reset_length(two_paths);
     803           2 :     vec_add1(two_paths, path_via_if0);
     804           2 :     vec_add1(two_paths, path_via_if2);
     805             : 
     806           2 :     mfib_table_entry_paths_remove(fib_index,
     807             :                                   pfx_s_g,
     808             :                                   MFIB_SOURCE_API,
     809             :                                   two_paths);
     810             : 
     811           2 :     MFIB_TEST(!mfib_test_entry(mfei,
     812             :                                MFIB_ENTRY_FLAG_SIGNAL,
     813             :                                0),
     814             :               "%U no replications",
     815             :               format_mfib_prefix, pfx_s_g);
     816             : 
     817             :     /*
     818             :      * update flags on the entry
     819             :      */
     820           2 :     mfib_table_entry_update(fib_index,
     821             :                             pfx_s_g,
     822             :                             MFIB_SOURCE_API,
     823             :                             MFIB_RPF_ID_NONE,
     824             :                             (MFIB_ENTRY_FLAG_SIGNAL |
     825             :                              MFIB_ENTRY_FLAG_CONNECTED));
     826           2 :     MFIB_TEST(!mfib_test_entry(mfei,
     827             :                                (MFIB_ENTRY_FLAG_SIGNAL |
     828             :                                 MFIB_ENTRY_FLAG_CONNECTED),
     829             :                                0),
     830             :               "%U no replications",
     831             :               format_mfib_prefix, pfx_s_g);
     832             : 
     833             :     /*
     834             :      * An entry with a NS interface
     835             :      */
     836           2 :     path_via_if0.frp_mitf_flags = (MFIB_ITF_FLAG_ACCEPT |
     837             :                               MFIB_ITF_FLAG_NEGATE_SIGNAL);
     838             :     mfei_g_2 =
     839           2 :       mfib_table_entry_path_update (fib_index, pfx_star_g_2, MFIB_SOURCE_API,
     840             :                                     MFIB_ENTRY_FLAG_NONE, &path_via_if0);
     841           2 :     MFIB_TEST(!mfib_test_entry(mfei_g_2,
     842             :                                MFIB_ENTRY_FLAG_NONE,
     843             :                                0),
     844             :               "%U No replications",
     845             :               format_mfib_prefix, pfx_star_g_2);
     846             : 
     847             :     /*
     848             :      * Simulate a signal from the data-plane
     849             :      */
     850             :     {
     851             :         mfib_entry_t *mfe;
     852             :         mfib_itf_t *mfi;
     853             : 
     854           2 :         mfe = mfib_entry_get(mfei_g_2);
     855           2 :         mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
     856             : 
     857           2 :         mfib_signal_push(mfe, mfi, NULL);
     858             :     }
     859             : 
     860             :     /*
     861             :      * An entry with a NS interface
     862             :      */
     863           2 :     path_via_if0.frp_mitf_flags = (MFIB_ITF_FLAG_ACCEPT |
     864             :                               MFIB_ITF_FLAG_NEGATE_SIGNAL);
     865             :     mfei_g_3 =
     866           2 :       mfib_table_entry_path_update (fib_index, pfx_star_g_3, MFIB_SOURCE_API,
     867             :                                     MFIB_ENTRY_FLAG_NONE, &path_via_if0);
     868           2 :     MFIB_TEST(!mfib_test_entry(mfei_g_3,
     869             :                                MFIB_ENTRY_FLAG_NONE,
     870             :                                0),
     871             :               "%U No replications",
     872             :               format_mfib_prefix, pfx_star_g_3);
     873             : 
     874             :     /*
     875             :      * Simulate a signal from the data-plane
     876             :      */
     877             :     {
     878             :         mfib_entry_t *mfe;
     879             :         mfib_itf_t *mfi;
     880             : 
     881           2 :         mfe = mfib_entry_get(mfei_g_3);
     882           2 :         mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
     883             : 
     884           2 :         mfib_signal_push(mfe, mfi, NULL);
     885             :     }
     886             : 
     887           2 :     if (FIB_PROTOCOL_IP6 == PROTO)
     888             :     {
     889             :         /*
     890             :          * All the entries are present. let's ensure we can find them all
     891             :          * via exact and longest prefix matches.
     892             :          */
     893             :         /*
     894             :          * A source address we will never match
     895             :          */
     896           2 :         ip6_address_t src = {
     897           1 :             .as_u64[0] = clib_host_to_net_u64(0x3001000000000000),
     898           1 :             .as_u64[1] = clib_host_to_net_u64(0xffffffffffffffff),
     899             :         };
     900             : 
     901             :         /*
     902             :          * Find the (*,G/m)
     903             :          */
     904           1 :         MFIB_TEST((mfei_g_m == ip6_mfib_table_fwd_lookup(
     905             :                        ip6_mfib_get(fib_index),
     906             :                        &src,
     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);
     911             : 
     912           1 :         ip6_address_t tmp = pfx_star_g_slash_m->fp_grp_addr.ip6;
     913           1 :         tmp.as_u8[15] = 0xff;
     914             : 
     915           1 :         MFIB_TEST((mfei_g_m == ip6_mfib_table_fwd_lookup(
     916             :                        ip6_mfib_get(fib_index),
     917             :                        &pfx_s_g->fp_src_addr.ip6,
     918             :                        &tmp)),
     919             :                   "%U found via DP LPM grp=%U",
     920             :                   format_mfib_prefix, pfx_star_g_slash_m,
     921             :                   format_ip6_address, &tmp);
     922             : 
     923             :         /*
     924             :          * Find the (S,G).
     925             :          */
     926           1 :         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           1 :         MFIB_TEST((mfei_s_g == mfei),
     930             :                   "%U found via DP LPM: %d",
     931             :                   format_mfib_prefix, pfx_s_g, mfei);
     932             : 
     933             :         /*
     934             :          * Find the 3 (*,G) s
     935             :          */
     936           1 :         mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
     937             :                                          &src,
     938             :                                          &pfx_star_g_1->fp_grp_addr.ip6);
     939           1 :         MFIB_TEST((mfei_g_1 == mfei),
     940             :                   "%U found via DP LPM: %d",
     941             :                   format_mfib_prefix, pfx_star_g_1, mfei);
     942           1 :         mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
     943             :                                          &src,
     944             :                                          &pfx_star_g_2->fp_grp_addr.ip6);
     945           1 :         MFIB_TEST((mfei_g_2 == mfei),
     946             :                   "%U found via DP LPM: %d",
     947             :                   format_mfib_prefix, pfx_star_g_2, mfei);
     948           1 :         mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
     949             :                                          &src,
     950             :                                          &pfx_star_g_3->fp_grp_addr.ip6);
     951           1 :         MFIB_TEST((mfei_g_3 == mfei),
     952             :                   "%U found via DP LPM: %d",
     953             :                   format_mfib_prefix, pfx_star_g_3, mfei);
     954             :     }
     955             : 
     956             :     /*
     957             :      * remove flags on the entry. This is the last of the
     958             :      * state associated with the entry, so now it goes.
     959             :      */
     960           2 :     mfib_table_entry_update(fib_index,
     961             :                             pfx_s_g,
     962             :                             MFIB_SOURCE_API,
     963             :                             MFIB_RPF_ID_NONE,
     964             :                             MFIB_ENTRY_FLAG_NONE);
     965           2 :     mfei = mfib_table_lookup_exact_match(fib_index,
     966             :                                          pfx_s_g);
     967           2 :     MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
     968             :               "%U gone",
     969             :               format_mfib_prefix, pfx_s_g);
     970             : 
     971             :     /*
     972             :      * remove the last path on the no forward entry - the last entry
     973             :      */
     974           2 :     mfib_table_entry_path_remove(fib_index,
     975             :                                  pfx_no_forward,
     976             :                                  MFIB_SOURCE_API,
     977             :                                  &path_via_if0);
     978             : 
     979           2 :     mfei = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
     980           2 :     MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
     981             :               "%U gone",
     982             :               format_mfib_prefix, pfx_no_forward);
     983             : 
     984             :     /*
     985             :      * hard delete the (*,232.1.1.1)
     986             :      */
     987           2 :     mfib_table_entry_delete(fib_index,
     988             :                             pfx_star_g_1,
     989             :                             MFIB_SOURCE_API);
     990             : 
     991           2 :     mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
     992           2 :     MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
     993             :               "%U gone",
     994             :               format_mfib_prefix, pfx_star_g_1);
     995             :     /*
     996             :      * remove the entry whilst the signal is pending
     997             :      */
     998           2 :     mfib_table_entry_delete(fib_index,
     999             :                             pfx_star_g_2,
    1000             :                             MFIB_SOURCE_API);
    1001             : 
    1002           2 :     mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_2);
    1003           2 :     MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
    1004             :               "%U Gone",
    1005             :               format_mfib_prefix, pfx_star_g_2);
    1006           2 :     mfib_table_entry_delete(fib_index,
    1007             :                             pfx_star_g_3,
    1008             :                             MFIB_SOURCE_API);
    1009             : 
    1010           2 :     mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_3);
    1011           2 :     MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
    1012             :               "%U Gone",
    1013             :               format_mfib_prefix, pfx_star_g_3);
    1014             : 
    1015           2 :     mfib_table_entry_delete(fib_index,
    1016             :                             pfx_star_g_slash_m,
    1017             :                             MFIB_SOURCE_API);
    1018             : 
    1019           2 :     mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
    1020           2 :     MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
    1021             :               "%U Gone",
    1022             :               format_mfib_prefix, pfx_star_g_slash_m);
    1023             : 
    1024             :     /*
    1025             :      * Entries with paths via unicast next-hops
    1026             :      */
    1027           4 :     fib_route_path_t path_via_nbr1 = {
    1028           2 :         .frp_proto = fib_proto_to_dpo(PROTO),
    1029             :         .frp_addr = *addr_nbr1,
    1030           2 :         .frp_sw_if_index = tm->hw[0]->sw_if_index,
    1031             :         .frp_fib_index = ~0,
    1032             :         .frp_weight = 1,
    1033             :         .frp_flags = 0,
    1034             :         .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
    1035             :     };
    1036           4 :     fib_route_path_t path_via_nbr2 = {
    1037           2 :         .frp_proto = fib_proto_to_dpo(PROTO),
    1038             :         .frp_addr = *addr_nbr2,
    1039           2 :         .frp_sw_if_index = tm->hw[0]->sw_if_index,
    1040             :         .frp_fib_index = ~0,
    1041             :         .frp_weight = 1,
    1042             :         .frp_flags = 0,
    1043             :         .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
    1044             :     };
    1045             : 
    1046             :     mfei_g_1 =
    1047           2 :       mfib_table_entry_path_update (fib_index, pfx_star_g_1, MFIB_SOURCE_API,
    1048             :                                     MFIB_ENTRY_FLAG_NONE, &path_via_nbr1);
    1049             :     mfei_g_1 =
    1050           2 :       mfib_table_entry_path_update (fib_index, pfx_star_g_1, MFIB_SOURCE_API,
    1051             :                                     MFIB_ENTRY_FLAG_NONE, &path_via_nbr2);
    1052           2 :     MFIB_TEST(!mfib_test_entry(mfei_g_1,
    1053             :                                MFIB_ENTRY_FLAG_NONE,
    1054             :                                2,
    1055             :                                DPO_ADJACENCY_INCOMPLETE, ai_nbr1,
    1056             :                                DPO_ADJACENCY_INCOMPLETE, ai_nbr2),
    1057             :               "%U replicate OK",
    1058             :               format_mfib_prefix, pfx_star_g_1);
    1059           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei_g_1, tm->hw[0]->sw_if_index,
    1060             :                                       MFIB_ITF_FLAG_FORWARD));
    1061             : 
    1062           2 :     mfib_table_entry_path_remove(fib_index,
    1063             :                                  pfx_star_g_1,
    1064             :                                  MFIB_SOURCE_API,
    1065             :                                  &path_via_nbr1);
    1066             : 
    1067           2 :     MFIB_TEST(!mfib_test_entry(mfei_g_1,
    1068             :                                MFIB_ENTRY_FLAG_NONE,
    1069             :                                1,
    1070             :                                DPO_ADJACENCY_INCOMPLETE, ai_nbr2),
    1071             :               "%U replicate OK",
    1072             :               format_mfib_prefix, pfx_star_g_1);
    1073           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei_g_1, tm->hw[0]->sw_if_index,
    1074             :                                       MFIB_ITF_FLAG_FORWARD));
    1075             : 
    1076           2 :     mfib_table_entry_path_remove(fib_index,
    1077             :                                  pfx_star_g_1,
    1078             :                                  MFIB_SOURCE_API,
    1079             :                                  &path_via_nbr2);
    1080           2 :     mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
    1081           2 :     MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
    1082             :               "%U Gone",
    1083             :               format_mfib_prefix, pfx_star_g_1);
    1084             : 
    1085             :     /*
    1086             :      * Add a prefix as a special/exclusive route
    1087             :      */
    1088           2 :     dpo_id_t td = DPO_INVALID;
    1089           2 :     index_t repi = replicate_create(1, fib_proto_to_dpo(PROTO));
    1090             : 
    1091           2 :     dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_2);
    1092           2 :     replicate_set_bucket(repi, 0, &td);
    1093             : 
    1094           2 :     mfei = mfib_table_entry_special_add(fib_index,
    1095             :                                         pfx_star_g_3,
    1096             :                                         MFIB_SOURCE_SRv6,
    1097             :                                         MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF,
    1098             :                                         repi);
    1099           2 :     MFIB_TEST(!mfib_test_entry(mfei,
    1100             :                                (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
    1101             :                                 MFIB_ENTRY_FLAG_EXCLUSIVE),
    1102             :                                1,
    1103             :                                DPO_ADJACENCY_MCAST, ai_2),
    1104             :               "%U exclusive replicate OK",
    1105             :               format_mfib_prefix, pfx_star_g_3);
    1106             : 
    1107             :     /*
    1108             :      * update a special/exclusive route
    1109             :      */
    1110           2 :     index_t repi2 = replicate_create(1, fib_proto_to_dpo(PROTO));
    1111             : 
    1112           2 :     dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_1);
    1113           2 :     replicate_set_bucket(repi2, 0, &td);
    1114             : 
    1115           2 :     mfib_entry_update(mfei,
    1116             :                       MFIB_SOURCE_SRv6,
    1117             :                       (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
    1118             :                        MFIB_ENTRY_FLAG_EXCLUSIVE),
    1119             :                       MFIB_RPF_ID_NONE,
    1120             :                       repi2);
    1121           2 :     MFIB_TEST(!mfib_test_entry(mfei,
    1122             :                                (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
    1123             :                                 MFIB_ENTRY_FLAG_EXCLUSIVE),
    1124             :                                1,
    1125             :                                DPO_ADJACENCY_MCAST, ai_1),
    1126             :               "%U exclusive update replicate OK",
    1127             :               format_mfib_prefix, pfx_star_g_3);
    1128             : 
    1129           2 :     mfib_table_entry_delete(fib_index,
    1130             :                             pfx_star_g_3,
    1131             :                             MFIB_SOURCE_SRv6);
    1132           2 :     dpo_reset(&td);
    1133             : 
    1134             :     /*
    1135             :      * A Multicast LSP. This a mLDP head-end
    1136             :      */
    1137             :     fib_node_index_t ai_mpls_10_10_10_1, lfei;
    1138           4 :     ip46_address_t nh_10_10_10_1 = {
    1139             :         .ip4 = {
    1140           2 :             .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
    1141             :         },
    1142             :     };
    1143           2 :     ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
    1144             :                                              VNET_LINK_MPLS,
    1145             :                                              &nh_10_10_10_1,
    1146           2 :                                              tm->hw[0]->sw_if_index);
    1147             : 
    1148           2 :     fib_prefix_t pfx_3500 = {
    1149             :         .fp_len = 21,
    1150             :         .fp_proto = FIB_PROTOCOL_MPLS,
    1151             :         .fp_label = 3500,
    1152             :         .fp_eos = MPLS_EOS,
    1153             :         .fp_payload_proto = DPO_PROTO_IP4,
    1154             :     };
    1155           2 :     fib_test_rep_bucket_t mc_0 = {
    1156             :         .type = FT_REP_LABEL_O_ADJ,
    1157             :         .label_o_adj = {
    1158             :             .adj = ai_mpls_10_10_10_1,
    1159             :             .label = 3300,
    1160             :             .eos = MPLS_EOS,
    1161             :         },
    1162             :     };
    1163           2 :     fib_mpls_label_t *l3300 = NULL, fml3300 = {
    1164             :         .fml_value = 3300,
    1165             :     };
    1166           2 :     vec_add1(l3300, fml3300);
    1167             : 
    1168             :     /*
    1169             :      * MPLS enable an interface so we get the MPLS table created
    1170             :      */
    1171           2 :     mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL);
    1172           2 :     mpls_sw_interface_enable_disable (&mpls_main, tm->hw[0]->sw_if_index, 1);
    1173             : 
    1174           2 :     lfei = fib_table_entry_update_one_path(0, // default MPLS Table
    1175             :                                            &pfx_3500,
    1176             :                                            FIB_SOURCE_API,
    1177             :                                            FIB_ENTRY_FLAG_MULTICAST,
    1178             :                                            DPO_PROTO_IP4,
    1179             :                                            &nh_10_10_10_1,
    1180           2 :                                            tm->hw[0]->sw_if_index,
    1181             :                                            ~0, // invalid fib index
    1182             :                                            1,
    1183             :                                            l3300,
    1184             :                                            FIB_ROUTE_PATH_FLAG_NONE);
    1185           2 :     MFIB_TEST(!fib_test_validate_entry(lfei,
    1186             :                                        FIB_FORW_CHAIN_TYPE_MPLS_EOS,
    1187             :                                        1,
    1188             :                                        &mc_0),
    1189             :               "3500 via replicate over 10.10.10.1");
    1190             : 
    1191             :     /*
    1192             :      * An (S,G) that resolves via the mLDP head-end
    1193             :      */
    1194           2 :     fib_route_path_t path_via_mldp = {
    1195             :         .frp_proto = DPO_PROTO_MPLS,
    1196           2 :         .frp_local_label = pfx_3500.fp_label,
    1197             :         .frp_eos = MPLS_EOS,
    1198             :         .frp_sw_if_index = 0xffffffff,
    1199             :         .frp_fib_index = 0,
    1200             :         .frp_weight = 1,
    1201             :         .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
    1202             :         .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
    1203             :     };
    1204           2 :     dpo_id_t mldp_dpo = DPO_INVALID;
    1205             : 
    1206           2 :     fib_entry_contribute_forwarding(lfei,
    1207             :                                     FIB_FORW_CHAIN_TYPE_MPLS_EOS,
    1208             :                                     &mldp_dpo);
    1209             : 
    1210           2 :     mfei = mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
    1211             :                                          MFIB_ENTRY_FLAG_NONE, &path_via_mldp);
    1212             : 
    1213           2 :     MFIB_TEST(!mfib_test_entry(mfei,
    1214             :                                MFIB_ENTRY_FLAG_NONE,
    1215             :                                1,
    1216             :                                DPO_REPLICATE, mldp_dpo.dpoi_index),
    1217             :               "%U over-mLDP replicate OK",
    1218             :               format_mfib_prefix, pfx_s_g);
    1219             : 
    1220             :     /*
    1221             :      * add a for-us path. this tests two types of non-attached paths on one entry
    1222             :      */
    1223           2 :     mfei = mfib_table_entry_path_update (fib_index, pfx_s_g, MFIB_SOURCE_API,
    1224             :                                          MFIB_ENTRY_FLAG_NONE, &path_for_us);
    1225           2 :     MFIB_TEST(!mfib_test_entry(mfei,
    1226             :                                MFIB_ENTRY_FLAG_NONE,
    1227             :                                2,
    1228             :                                DPO_REPLICATE, mldp_dpo.dpoi_index,
    1229             :                                DPO_RECEIVE, 0),
    1230             :               "%U mLDP+for-us replicate OK",
    1231             :               format_mfib_prefix, pfx_s_g);
    1232             : 
    1233           2 :     mfib_table_entry_delete(fib_index,
    1234             :                             pfx_s_g,
    1235             :                             MFIB_SOURCE_API);
    1236           2 :     fib_table_entry_delete(0,
    1237             :                            &pfx_3500,
    1238             :                            FIB_SOURCE_API);
    1239           2 :     dpo_reset(&mldp_dpo);
    1240             : 
    1241             :     /*
    1242             :      * Unlock the table - it's the last lock so should be gone thereafter
    1243             :      */
    1244           2 :     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));
    1248             : 
    1249           2 :     mfib_table_unlock(fib_index, PROTO, MFIB_SOURCE_API);
    1250             : 
    1251           2 :     MFIB_TEST((FIB_NODE_INDEX_INVALID ==
    1252             :                mfib_table_find(PROTO, fib_index)),
    1253             :               "MFIB table %d gone", fib_index);
    1254             : 
    1255           2 :     adj_unlock(ai_1);
    1256           2 :     adj_unlock(ai_2);
    1257           2 :     adj_unlock(ai_3);
    1258           2 :     adj_unlock(ai_nbr1);
    1259           2 :     adj_unlock(ai_nbr2);
    1260             : 
    1261             :     /*
    1262             :      * MPLS disable the interface
    1263             :      */
    1264           2 :     mpls_sw_interface_enable_disable (&mpls_main, tm->hw[0]->sw_if_index, 0);
    1265           2 :     mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
    1266             : 
    1267             :     /*
    1268             :      * remove the connected
    1269             :      */
    1270           2 :     fib_table_entry_delete(0, pfx_itf, FIB_SOURCE_INTERFACE);
    1271             : 
    1272             :     /*
    1273             :      * test we've leaked no resources
    1274             :      */
    1275           2 :     MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
    1276           2 :     MFIB_TEST(n_pls == fib_path_list_pool_size(), "%d=%d path-lists",
    1277             :               n_pls, fib_path_list_pool_size());
    1278           2 :     MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
    1279             :               n_reps, pool_elts(replicate_pool));
    1280           2 :     MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
    1281             :               " No more entries %d!=%d",
    1282             :               n_entries, pool_elts(mfib_entry_pool));
    1283           2 :     MFIB_TEST(n_itfs == pool_elts(mfib_itf_pool),
    1284             :               " No more Interfaces %d!=%d",
    1285             :               n_itfs, pool_elts(mfib_itf_pool));
    1286           2 :     vec_free(two_paths);
    1287             : 
    1288           2 :     return (res);
    1289             : }
    1290             : 
    1291             : static int
    1292           1 : mfib_test_v4 (void)
    1293             : {
    1294           2 :     const mfib_prefix_t pfx_224_s_8 = {
    1295             :         .fp_len = 8,
    1296             :         .fp_proto = FIB_PROTOCOL_IP4,
    1297             :         .fp_grp_addr = {
    1298           1 :             .ip4.as_u32 = clib_host_to_net_u32(0xe0000000),
    1299             :         }
    1300             :     };
    1301           3 :     const mfib_prefix_t pfx_1_1_1_1_c_239_1_1_1 = {
    1302             :         .fp_len = 64,
    1303             :         .fp_proto = FIB_PROTOCOL_IP4,
    1304             :         .fp_grp_addr = {
    1305           1 :             .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
    1306             :         },
    1307             :         .fp_src_addr = {
    1308           1 :             .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
    1309             :         },
    1310             :     };
    1311           2 :     const mfib_prefix_t pfx_239_1_1_1 = {
    1312             :         .fp_len = 32,
    1313             :         .fp_proto = FIB_PROTOCOL_IP4,
    1314             :         .fp_grp_addr = {
    1315           1 :             .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
    1316             :         },
    1317             :         .fp_src_addr = {
    1318             :             .ip4.as_u32 = 0,
    1319             :         },
    1320             :     };
    1321           2 :     const mfib_prefix_t pfx_239_1_1_2 = {
    1322             :         .fp_len = 32,
    1323             :         .fp_proto = FIB_PROTOCOL_IP4,
    1324             :         .fp_grp_addr = {
    1325           1 :             .ip4.as_u32 = clib_host_to_net_u32(0xef010102),
    1326             :         },
    1327             :         .fp_src_addr = {
    1328             :             .ip4.as_u32 = 0,
    1329             :         },
    1330             :     };
    1331           2 :     const mfib_prefix_t pfx_239_1_1_3 = {
    1332             :         .fp_len = 32,
    1333             :         .fp_proto = FIB_PROTOCOL_IP4,
    1334             :         .fp_grp_addr = {
    1335           1 :             .ip4.as_u32 = clib_host_to_net_u32(0xef010103),
    1336             :         },
    1337             :         .fp_src_addr = {
    1338             :             .ip4.as_u32 = 0,
    1339             :         },
    1340             :     };
    1341           2 :     const mfib_prefix_t pfx_239 = {
    1342             :         .fp_len = 8,
    1343             :         .fp_proto = FIB_PROTOCOL_IP4,
    1344             :         .fp_grp_addr = {
    1345           1 :             .ip4.as_u32 = clib_host_to_net_u32(0xef000000),
    1346             :         },
    1347             :         .fp_src_addr = {
    1348             :             .ip4.as_u32 = 0,
    1349             :         },
    1350             :     };
    1351           2 :     const fib_prefix_t pfx_itf = {
    1352             :         .fp_len = 24,
    1353             :         .fp_proto = FIB_PROTOCOL_IP4,
    1354             :         .fp_addr = {
    1355           1 :             .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
    1356             :         },
    1357             :     };
    1358           2 :     const ip46_address_t nbr1 = {
    1359           1 :         .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0b),
    1360             :     };
    1361           2 :     const ip46_address_t nbr2 = {
    1362           1 :         .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0c),
    1363             :     };
    1364           1 :     return (mfib_test_i(FIB_PROTOCOL_IP4,
    1365             :                         VNET_LINK_IP4,
    1366             :                         &pfx_224_s_8,
    1367             :                         &pfx_1_1_1_1_c_239_1_1_1,
    1368             :                         &pfx_239_1_1_1,
    1369             :                         &pfx_239_1_1_2,
    1370             :                         &pfx_239_1_1_3,
    1371             :                         &pfx_239,
    1372             :                         &pfx_itf,
    1373             :                         &nbr1,
    1374             :                         &nbr2));
    1375             : }
    1376             : 
    1377             : static int
    1378           1 : mfib_test_v6 (void)
    1379             : {
    1380           2 :     const mfib_prefix_t pfx_ffd_s_12 = {
    1381             :         .fp_len = 12,
    1382             :         .fp_proto = FIB_PROTOCOL_IP6,
    1383             :         .fp_grp_addr = {
    1384           1 :             .ip6.as_u64[0] = clib_host_to_net_u64(0xffd0000000000000),
    1385             :         }
    1386             :     };
    1387           5 :     const mfib_prefix_t pfx_2001_1_c_ff_1 = {
    1388             :         .fp_len = 256,
    1389             :         .fp_proto = FIB_PROTOCOL_IP6,
    1390             :         .fp_grp_addr = {
    1391           1 :             .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
    1392           1 :             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
    1393             :         },
    1394             :         .fp_src_addr = {
    1395           1 :             .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
    1396           1 :             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
    1397             :         },
    1398             :     };
    1399           3 :     const mfib_prefix_t pfx_ff_1 = {
    1400             :         .fp_len = 128,
    1401             :         .fp_proto = FIB_PROTOCOL_IP6,
    1402             :         .fp_grp_addr = {
    1403           1 :             .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
    1404           1 :             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
    1405             :         },
    1406             :     };
    1407           3 :     const mfib_prefix_t pfx_ff_2 = {
    1408             :         .fp_len = 128,
    1409             :         .fp_proto = FIB_PROTOCOL_IP6,
    1410             :         .fp_grp_addr = {
    1411           1 :             .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
    1412           1 :             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
    1413             :         },
    1414             :     };
    1415           3 :     const mfib_prefix_t pfx_ff_3 = {
    1416             :         /*
    1417             :          * this is the ALL DHCP routers address
    1418             :          */
    1419             :         .fp_len = 128,
    1420             :         .fp_proto = FIB_PROTOCOL_IP6,
    1421             :         .fp_grp_addr = {
    1422           1 :             .ip6.as_u64[0] = clib_host_to_net_u64(0xff02000100000000),
    1423           1 :             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
    1424             :         },
    1425             :     };
    1426           3 :     const mfib_prefix_t pfx_ff = {
    1427             :         .fp_len = 16,
    1428             :         .fp_proto = FIB_PROTOCOL_IP6,
    1429             :         .fp_grp_addr = {
    1430           1 :             .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
    1431           1 :             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000000),
    1432             :         },
    1433             :     };
    1434           3 :     const fib_prefix_t pfx_itf = {
    1435             :         .fp_len = 64,
    1436             :         .fp_proto = FIB_PROTOCOL_IP6,
    1437             :         .fp_addr = {
    1438           1 :             .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
    1439           1 :             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
    1440             :         },
    1441             :     };
    1442           2 :     const ip46_address_t nbr1 = {
    1443           1 :             .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
    1444           1 :             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
    1445             :     };
    1446           2 :     const ip46_address_t nbr2 = {
    1447           1 :             .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
    1448           1 :             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000003),
    1449             :     };
    1450             : 
    1451           1 :     return (mfib_test_i(FIB_PROTOCOL_IP6,
    1452             :                         VNET_LINK_IP6,
    1453             :                         &pfx_ffd_s_12,
    1454             :                         &pfx_2001_1_c_ff_1,
    1455             :                         &pfx_ff_1,
    1456             :                         &pfx_ff_2,
    1457             :                         &pfx_ff_3,
    1458             :                         &pfx_ff,
    1459             :                         &pfx_itf,
    1460             :                         &nbr1,
    1461             :                         &nbr2));
    1462             : }
    1463             : 
    1464             : static int
    1465           2 : mfib_test_rr_i (fib_protocol_t FPROTO,
    1466             :                 dpo_proto_t DPROTO,
    1467             :                 vnet_link_t LINKT,
    1468             :                 const mfib_prefix_t *pfx_cover,
    1469             :                 const mfib_prefix_t *pfx_host1,
    1470             :                 const mfib_prefix_t *pfx_host2)
    1471             : {
    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;
    1474             :     test_main_t *tm;
    1475             :     int res;
    1476             : 
    1477           2 :     res = 0;
    1478           2 :     n_entries = pool_elts(mfib_entry_pool);
    1479           2 :     n_itfs = pool_elts(mfib_itf_pool);
    1480           2 :     n_reps = pool_elts(replicate_pool);
    1481           2 :     n_pls = fib_path_list_pool_size();
    1482           2 :     tm = &test_main;
    1483             : 
    1484           2 :     fib_index = 0;
    1485           2 :     ai_1 = adj_mcast_add_or_lock(FPROTO,
    1486             :                                  LINKT,
    1487           2 :                                  tm->hw[1]->sw_if_index);
    1488           2 :     ai_2 = adj_mcast_add_or_lock(FPROTO,
    1489             :                                  LINKT,
    1490           2 :                                  tm->hw[2]->sw_if_index);
    1491             : 
    1492           2 :     fib_route_path_t path_via_if0 = {
    1493             :         .frp_proto = DPROTO,
    1494             :         .frp_addr = zero_addr,
    1495           2 :         .frp_sw_if_index = tm->hw[0]->sw_if_index,
    1496             :         .frp_fib_index = ~0,
    1497             :         .frp_weight = 1,
    1498             :         .frp_flags = 0,
    1499             :         .frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT,
    1500             :     };
    1501           2 :     fib_route_path_t path_via_if1 = {
    1502             :         .frp_proto = DPROTO,
    1503             :         .frp_addr = zero_addr,
    1504           2 :         .frp_sw_if_index = tm->hw[1]->sw_if_index,
    1505             :         .frp_fib_index = ~0,
    1506             :         .frp_weight = 1,
    1507             :         .frp_flags = 0,
    1508             :         .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
    1509             :     };
    1510           2 :     fib_route_path_t path_via_if2 = {
    1511             :         .frp_proto = DPROTO,
    1512             :         .frp_addr = zero_addr,
    1513           2 :         .frp_sw_if_index = tm->hw[2]->sw_if_index,
    1514             :         .frp_fib_index = ~0,
    1515             :         .frp_weight = 1,
    1516             :         .frp_flags = 0,
    1517             :         .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
    1518             :     };
    1519           2 :     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,
    1524             :         .frp_weight = 1,
    1525             :         .frp_flags = FIB_ROUTE_PATH_LOCAL,
    1526             :         .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
    1527             :     };
    1528             : 
    1529             :     /*
    1530             :      * with only the default in place, recusre thru the /32
    1531             :      */
    1532           2 :     mfei_host1 = mfib_table_entry_special_add(fib_index, pfx_host1,
    1533             :                                               MFIB_SOURCE_RR,
    1534             :                                               MFIB_ENTRY_FLAG_NONE,
    1535             :                                               INDEX_INVALID);
    1536             :     /*
    1537             :      * expect its forwarding to match the cover's
    1538             :      */
    1539           2 :     MFIB_TEST(!mfib_test_entry(mfei_host1,
    1540             :                                MFIB_ENTRY_FLAG_DROP,
    1541             :                                0),
    1542             :               "%U no replications OK",
    1543             :               format_mfib_prefix, pfx_host1);
    1544             : 
    1545             :     /*
    1546             :      * Insert the less specific /28
    1547             :      */
    1548           2 :     mfib_table_entry_path_update (fib_index, pfx_cover, MFIB_SOURCE_API,
    1549             :                                   MFIB_ENTRY_FLAG_NONE, &path_via_if1);
    1550             : 
    1551           2 :     mfei_cover = mfib_table_lookup_exact_match(fib_index, pfx_cover);
    1552             : 
    1553           2 :     MFIB_TEST(!mfib_test_entry(mfei_cover,
    1554             :                                MFIB_ENTRY_FLAG_NONE,
    1555             :                                1,
    1556             :                                DPO_ADJACENCY_MCAST, ai_1),
    1557             :               "%U replicate OK",
    1558             :               format_mfib_prefix, pfx_cover);
    1559             : 
    1560             :     /*
    1561             :      * expect the /32 forwarding to match the new cover's
    1562             :      */
    1563           2 :     MFIB_TEST(!mfib_test_entry(mfei_host1,
    1564             :                                MFIB_ENTRY_FLAG_NONE,
    1565             :                                1,
    1566             :                                DPO_ADJACENCY_MCAST, ai_1),
    1567             :               "%U replicate OK",
    1568             :               format_mfib_prefix, pfx_host1);
    1569             : 
    1570             :     /*
    1571             :      * add another path to the cover
    1572             :      */
    1573           2 :     mfib_table_entry_path_update (fib_index, pfx_cover, MFIB_SOURCE_API,
    1574             :                                   MFIB_ENTRY_FLAG_NONE, &path_via_if2);
    1575             : 
    1576             :     /*
    1577             :      * expect the /32 and /28 to be via both boths
    1578             :      */
    1579           2 :     MFIB_TEST(!mfib_test_entry(mfei_cover,
    1580             :                                MFIB_ENTRY_FLAG_NONE,
    1581             :                                2,
    1582             :                                DPO_ADJACENCY_MCAST, ai_1,
    1583             :                                DPO_ADJACENCY_MCAST, ai_2),
    1584             :               "%U replicate OK",
    1585             :               format_mfib_prefix, pfx_cover);
    1586           2 :     MFIB_TEST(!mfib_test_entry(mfei_host1,
    1587             :                                MFIB_ENTRY_FLAG_NONE,
    1588             :                                2,
    1589             :                                DPO_ADJACENCY_MCAST, ai_1,
    1590             :                                DPO_ADJACENCY_MCAST, ai_2),
    1591             :               "%U replicate OK",
    1592             :               format_mfib_prefix, pfx_host1);
    1593             : 
    1594             :     /*
    1595             :      * and the other host whilst all is ready
    1596             :      */
    1597           2 :     mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
    1598             :                                               MFIB_SOURCE_RR,
    1599             :                                               MFIB_ENTRY_FLAG_NONE,
    1600             :                                               INDEX_INVALID);
    1601           2 :     MFIB_TEST(!mfib_test_entry(mfei_host2,
    1602             :                                MFIB_ENTRY_FLAG_NONE,
    1603             :                                2,
    1604             :                                DPO_ADJACENCY_MCAST, ai_1,
    1605             :                                DPO_ADJACENCY_MCAST, ai_2),
    1606             :               "%U replicate OK",
    1607             :               format_mfib_prefix, pfx_host2);
    1608             : 
    1609             :     /*
    1610             :      * repaet multiple time to simulate multiple recursve children
    1611             :      */
    1612           2 :     mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
    1613             :                                               MFIB_SOURCE_RR,
    1614             :                                               MFIB_ENTRY_FLAG_NONE,
    1615             :                                               INDEX_INVALID);
    1616           2 :     mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
    1617             :                                               MFIB_SOURCE_RR,
    1618             :                                               MFIB_ENTRY_FLAG_NONE,
    1619             :                                               INDEX_INVALID);
    1620           2 :     mfei_host2 = mfib_table_entry_special_add(fib_index, pfx_host2,
    1621             :                                               MFIB_SOURCE_RR,
    1622             :                                               MFIB_ENTRY_FLAG_NONE,
    1623             :                                               INDEX_INVALID);
    1624             : 
    1625             :     /*
    1626             :      * add an accepting path to the cover
    1627             :      */
    1628           2 :     mfib_table_entry_path_update (fib_index, pfx_cover, MFIB_SOURCE_API,
    1629             :                                   MFIB_ENTRY_FLAG_NONE, &path_via_if0);
    1630             : 
    1631             :     /*
    1632             :      * expect the /32 and /28 to be via both boths
    1633             :      */
    1634           2 :     MFIB_TEST(!mfib_test_entry(mfei_cover,
    1635             :                                MFIB_ENTRY_FLAG_NONE,
    1636             :                                2,
    1637             :                                DPO_ADJACENCY_MCAST, ai_1,
    1638             :                                DPO_ADJACENCY_MCAST, ai_2),
    1639             :               "%U replicate OK",
    1640             :               format_mfib_prefix, pfx_cover);
    1641           2 :     MFIB_TEST(!mfib_test_entry(mfei_host1,
    1642             :                                MFIB_ENTRY_FLAG_NONE,
    1643             :                                2,
    1644             :                                DPO_ADJACENCY_MCAST, ai_1,
    1645             :                                DPO_ADJACENCY_MCAST, ai_2),
    1646             :               "%U replicate OK",
    1647             :               format_mfib_prefix, pfx_cover);
    1648           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[0]->sw_if_index,
    1649             :                                       MFIB_ITF_FLAG_ACCEPT));
    1650           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[0]->sw_if_index,
    1651             :                                       MFIB_ITF_FLAG_ACCEPT));
    1652           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[1]->sw_if_index,
    1653             :                                       MFIB_ITF_FLAG_FORWARD));
    1654           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[1]->sw_if_index,
    1655             :                                       MFIB_ITF_FLAG_FORWARD));
    1656           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei_host1, tm->hw[2]->sw_if_index,
    1657             :                                       MFIB_ITF_FLAG_FORWARD));
    1658           2 :     MFIB_TEST_NS(!mfib_test_entry_itf(mfei_cover, tm->hw[2]->sw_if_index,
    1659             :                                       MFIB_ITF_FLAG_FORWARD));
    1660             : 
    1661             :     /*
    1662             :      * add a for-us path to the cover
    1663             :      */
    1664           2 :     mfib_table_entry_path_update (fib_index, pfx_cover, MFIB_SOURCE_API,
    1665             :                                   MFIB_ENTRY_FLAG_NONE, &path_for_us);
    1666             : 
    1667             :     /*
    1668             :      * expect the /32 and /28 to be via all three paths
    1669             :      */
    1670           2 :     MFIB_TEST(!mfib_test_entry(mfei_cover,
    1671             :                                MFIB_ENTRY_FLAG_NONE,
    1672             :                                3,
    1673             :                                DPO_ADJACENCY_MCAST, ai_1,
    1674             :                                DPO_ADJACENCY_MCAST, ai_2,
    1675             :                                DPO_RECEIVE, 0),
    1676             :               "%U replicate OK",
    1677             :               format_mfib_prefix, pfx_cover);
    1678           2 :     MFIB_TEST(!mfib_test_entry(mfei_host1,
    1679             :                                MFIB_ENTRY_FLAG_NONE,
    1680             :                                3,
    1681             :                                DPO_ADJACENCY_MCAST, ai_1,
    1682             :                                DPO_ADJACENCY_MCAST, ai_2,
    1683             :                                DPO_RECEIVE, 0),
    1684             :               "%U replicate OK",
    1685             :               format_mfib_prefix, pfx_cover);
    1686             : 
    1687             :     /*
    1688             :      * get the forwarding chain from the RR prefix
    1689             :      */
    1690             :     replicate_t *rep;
    1691           2 :     dpo_id_t dpo = DPO_INVALID;
    1692             : 
    1693           2 :     mfib_entry_contribute_forwarding(
    1694             :         mfei_host1,
    1695           2 :         mfib_forw_chain_type_from_dpo_proto(DPROTO),
    1696             :         MFIB_ENTRY_FWD_FLAG_NONE,
    1697             :         &dpo);
    1698             : 
    1699           2 :     rep = replicate_get(dpo.dpoi_index);
    1700           2 :     MFIB_TEST((3 == rep->rep_n_buckets),
    1701             :               "%U replicate 3 buckets",
    1702             :               format_mfib_prefix, pfx_host1);
    1703             : 
    1704             :     /*
    1705             :      * get the forwarding chain from the RR prefix without local paths
    1706             :      */
    1707           2 :     mfib_entry_contribute_forwarding(
    1708             :         mfei_host1,
    1709           2 :         mfib_forw_chain_type_from_dpo_proto(DPROTO),
    1710             :         MFIB_ENTRY_FWD_FLAG_NO_LOCAL,
    1711             :         &dpo);
    1712             : 
    1713           2 :     rep = replicate_get(dpo.dpoi_index);
    1714           2 :     MFIB_TEST((2 == rep->rep_n_buckets),
    1715             :               "%U no-local replicate 2 buckets",
    1716             :               format_mfib_prefix, pfx_host1);
    1717             : 
    1718           2 :     dpo_reset(&dpo);
    1719             : 
    1720             :     /*
    1721             :      * delete the cover, expect the /32 to be via the default
    1722             :      */
    1723           2 :     mfib_table_entry_delete(fib_index, pfx_cover, MFIB_SOURCE_API);
    1724           2 :     MFIB_TEST(!mfib_test_entry(mfei_host1,
    1725             :                                MFIB_ENTRY_FLAG_DROP,
    1726             :                                0),
    1727             :               "%U no replications OK",
    1728             :               format_mfib_prefix, pfx_host1);
    1729             : 
    1730             :     /*
    1731             :      * source the /32 with its own path
    1732             :      */
    1733             :     mfei_host1 =
    1734           2 :       mfib_table_entry_path_update (fib_index, pfx_host1, MFIB_SOURCE_API,
    1735             :                                     MFIB_ENTRY_FLAG_NONE, &path_via_if2);
    1736           2 :     MFIB_TEST(!mfib_test_entry(mfei_host1,
    1737             :                                MFIB_ENTRY_FLAG_NONE,
    1738             :                                1,
    1739             :                                DPO_ADJACENCY_MCAST, ai_2),
    1740             :               "%U replicate OK",
    1741             :               format_mfib_prefix, pfx_host1);
    1742             : 
    1743             :     /*
    1744             :      * remove host2 - as many times as it was added
    1745             :      */
    1746           2 :     mfib_table_entry_delete(fib_index, pfx_host2,
    1747             :                             MFIB_SOURCE_RR);
    1748           2 :     mfib_table_entry_delete(fib_index, pfx_host2,
    1749             :                             MFIB_SOURCE_RR);
    1750           2 :     mfib_table_entry_delete(fib_index, pfx_host2,
    1751             :                             MFIB_SOURCE_RR);
    1752           2 :     mfib_table_entry_delete(fib_index, pfx_host2,
    1753             :                             MFIB_SOURCE_RR);
    1754             : 
    1755             : 
    1756             :     /*
    1757             :      * remove the RR source with paths present
    1758             :      */
    1759           2 :     mfib_table_entry_delete(fib_index, pfx_host1,
    1760             :                             MFIB_SOURCE_RR);
    1761             : 
    1762             :     /*
    1763             :      * add the RR back then remove the path and RR
    1764             :      */
    1765             :     mfei_host1 =
    1766           2 :       mfib_table_entry_path_update (fib_index, pfx_host1, MFIB_SOURCE_API,
    1767             :                                     MFIB_ENTRY_FLAG_NONE, &path_via_if2);
    1768           2 :     MFIB_TEST(!mfib_test_entry(mfei_host1,
    1769             :                                MFIB_ENTRY_FLAG_NONE,
    1770             :                                1,
    1771             :                                DPO_ADJACENCY_MCAST, ai_2),
    1772             :               "%U replicate OK",
    1773             :               format_mfib_prefix, pfx_host1);
    1774             : 
    1775           2 :     mfib_table_entry_delete(fib_index, pfx_host1,
    1776             :                             MFIB_SOURCE_API);
    1777           2 :     mfib_table_entry_delete(fib_index, pfx_host1,
    1778             :                             MFIB_SOURCE_RR);
    1779             : 
    1780             :     /*
    1781             :      * test we've leaked no resources
    1782             :      */
    1783           2 :     adj_unlock(ai_1);
    1784           2 :     adj_unlock(ai_2);
    1785           2 :     MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
    1786           2 :     MFIB_TEST(n_pls == fib_path_list_pool_size(), "%d=%d path-lists",
    1787             :               n_pls, fib_path_list_pool_size());
    1788           2 :     MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
    1789             :               n_reps, pool_elts(replicate_pool));
    1790           2 :     MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
    1791             :               " No more entries %d!=%d",
    1792             :               n_entries, pool_elts(mfib_entry_pool));
    1793           2 :     MFIB_TEST(n_itfs == pool_elts(mfib_itf_pool),
    1794             :               " No more Interfaces %d!=%d",
    1795             :               n_itfs, pool_elts(mfib_itf_pool));
    1796           2 :     return (res);
    1797             : }
    1798             : 
    1799             : static int
    1800           1 : mfib_test_rr_v4 (void)
    1801             : {
    1802             :     /*
    1803             :      * 2 length of prefix to play with
    1804             :      */
    1805           2 :     const mfib_prefix_t pfx_host1 = {
    1806             :         .fp_len = 32,
    1807             :         .fp_proto = FIB_PROTOCOL_IP4,
    1808             :         .fp_grp_addr = {
    1809           1 :             .ip4.as_u32 = clib_host_to_net_u32(0xe0001011),
    1810             :         },
    1811             :     };
    1812           3 :     const mfib_prefix_t pfx_host2 = {
    1813             :         .fp_len = 64,
    1814             :         .fp_proto = FIB_PROTOCOL_IP4,
    1815             :         .fp_grp_addr = {
    1816           1 :             .ip4.as_u32 = clib_host_to_net_u32(0xe0001011),
    1817             :         },
    1818             :         .fp_src_addr = {
    1819           1 :             .ip4.as_u32 = clib_host_to_net_u32(0x10101010),
    1820             :         },
    1821             :     };
    1822           2 :     const mfib_prefix_t pfx_cover = {
    1823             :         .fp_len = 28,
    1824             :         .fp_proto = FIB_PROTOCOL_IP4,
    1825             :         .fp_grp_addr = {
    1826           1 :             .ip4.as_u32 = clib_host_to_net_u32(0xe0001010),
    1827             :         },
    1828             :     };
    1829             : 
    1830           1 :     return (mfib_test_rr_i(FIB_PROTOCOL_IP4,
    1831             :                            DPO_PROTO_IP4,
    1832             :                            VNET_LINK_IP4,
    1833             :                            &pfx_cover,
    1834             :                            &pfx_host1,
    1835             :                            &pfx_host2));
    1836             : }
    1837             : 
    1838             : static int
    1839           1 : mfib_test_rr_v6 (void)
    1840             : {
    1841             :     /*
    1842             :      * 2 length of prefix to play with
    1843             :      */
    1844           3 :     const mfib_prefix_t pfx_host1 = {
    1845             :         .fp_len = 128,
    1846             :         .fp_proto = FIB_PROTOCOL_IP6,
    1847             :         .fp_grp_addr = {
    1848           1 :             .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
    1849           1 :             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
    1850             :         },
    1851             :     };
    1852           5 :     const mfib_prefix_t pfx_host2 = {
    1853             :         .fp_len = 256,
    1854             :         .fp_proto = FIB_PROTOCOL_IP6,
    1855             :         .fp_grp_addr = {
    1856           1 :             .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
    1857           1 :             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
    1858             :         },
    1859             :         .fp_src_addr = {
    1860           1 :             .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
    1861           1 :             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
    1862             :         },
    1863             :     };
    1864           3 :     const mfib_prefix_t pfx_cover = {
    1865             :         .fp_len = 64,
    1866             :         .fp_proto = FIB_PROTOCOL_IP6,
    1867             :         .fp_grp_addr = {
    1868           1 :             .ip6.as_u64[0] = clib_host_to_net_u64(0xff03000000000000),
    1869           1 :             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000000),
    1870             :         },
    1871             :     };
    1872             : 
    1873           1 :     return (mfib_test_rr_i(FIB_PROTOCOL_IP6,
    1874             :                            DPO_PROTO_IP6,
    1875             :                            VNET_LINK_IP6,
    1876             :                            &pfx_cover,
    1877             :                            &pfx_host1,
    1878             :                            &pfx_host2));
    1879             : }
    1880             : 
    1881             : static clib_error_t *
    1882           1 : mfib_test (vlib_main_t * vm,
    1883             :            unformat_input_t * input,
    1884             :            vlib_cli_command_t * cmd_arg)
    1885             : {
    1886           1 :     int res = 0;
    1887             : 
    1888           1 :     res += mfib_test_mk_intf(4);
    1889           1 :     res += mfib_test_rr_v4();
    1890             : 
    1891           1 :     if (res)
    1892             :     {
    1893           0 :         return clib_error_return(0, "MFIB RR V4 Unit Test Failed");
    1894             :     }
    1895             : 
    1896           1 :     res += mfib_test_rr_v6();
    1897             : 
    1898           1 :     if (res)
    1899             :     {
    1900           0 :         return clib_error_return(0, "MFIB RR V6 Unit Test Failed");
    1901             :     }
    1902             : 
    1903           1 :     res += mfib_test_v4();
    1904             : 
    1905           1 :     if (res)
    1906             :     {
    1907           0 :         return clib_error_return(0, "MFIB V4 Unit Test Failed");
    1908             :     }
    1909             : 
    1910           1 :     res += mfib_test_v6();
    1911             : 
    1912           1 :     if (res)
    1913             :     {
    1914           0 :         return clib_error_return(0, "MFIB V6 Unit Test Failed");
    1915             :     }
    1916             : 
    1917           1 :     return (NULL);
    1918             : }
    1919             : 
    1920       16239 : 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,
    1924             : };
    1925             : 
    1926             : clib_error_t *
    1927         559 : mfib_test_init (vlib_main_t *vm)
    1928             : {
    1929         559 :     return 0;
    1930             : }
    1931             : 
    1932        4479 : VLIB_INIT_FUNCTION (mfib_test_init);

Generated by: LCOV version 1.14