MFIB Coverity warnings. The lock macro is functionally equivalent but more expressive...
[vpp.git] / src / vnet / mfib / mfib_test.c
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
23 #include <vnet/dpo/replicate_dpo.h>
24 #include <vnet/adj/adj_mcast.h>
25
26 #define MFIB_TEST_I(_cond, _comment, _args...)                  \
27 ({                                                              \
28     int _evald = (_cond);                                       \
29     if (!(_evald)) {                                            \
30         fformat(stderr, "FAIL:%d: " _comment "\n",              \
31                 __LINE__, ##_args);                             \
32     } else {                                                    \
33         fformat(stderr, "PASS:%d: " _comment "\n",              \
34                 __LINE__, ##_args);                             \
35     }                                                           \
36     _evald;                                                     \
37 })
38 #define MFIB_TEST(_cond, _comment, _args...)                    \
39 {                                                               \
40     if (!MFIB_TEST_I(_cond, _comment, ##_args)) {               \
41         return 1;\
42         ASSERT(!("FAIL: " _comment));                           \
43     }                                                           \
44 }
45 #define MFIB_TEST_NS(_cond)                                     \
46 {                                                               \
47     if (!MFIB_TEST_I(_cond, "")) {                              \
48         return 1;\
49         ASSERT(!("FAIL: "));                                    \
50     }                                                           \
51 }
52
53 /**
54  * A 'i'm not fussed is this is not efficient' store of test data
55  */
56 typedef struct test_main_t_ {
57     /**
58      * HW if indicies
59      */
60     u32 hw_if_indicies[4];
61     /**
62      * HW interfaces
63      */
64     vnet_hw_interface_t * hw[4];
65
66 } test_main_t;
67 static test_main_t test_main;
68
69 /* fake ethernet device class, distinct from "fake-ethX" */
70 static u8 * format_test_interface_name (u8 * s, va_list * args)
71 {
72   u32 dev_instance = va_arg (*args, u32);
73   return format (s, "test-eth%d", dev_instance);
74 }
75
76 static uword dummy_interface_tx (vlib_main_t * vm,
77                                  vlib_node_runtime_t * node,
78                                  vlib_frame_t * frame)
79 {
80   clib_warning ("you shouldn't be here, leaking buffers...");
81   return frame->n_vectors;
82 }
83
84 static clib_error_t *
85 test_interface_admin_up_down (vnet_main_t * vnm,
86                               u32 hw_if_index,
87                               u32 flags)
88 {
89   u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
90     VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
91   vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
92   return 0;
93 }
94
95 VNET_DEVICE_CLASS (test_interface_device_class,static) = {
96   .name = "Test interface",
97   .format_device_name = format_test_interface_name,
98   .tx_function = dummy_interface_tx,
99   .admin_up_down_function = test_interface_admin_up_down,
100 };
101
102 static u8 *hw_address;
103
104 static int
105 mfib_test_mk_intf (u32 ninterfaces)
106 {
107     clib_error_t * error = NULL;
108     test_main_t *tm = &test_main;
109     u8 byte;
110     u32 i;
111
112     ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
113
114     for (i=0; i<6; i++)
115     {
116         byte = 0xd0+i;
117         vec_add1(hw_address, byte);
118     }
119
120     for (i = 0; i < ninterfaces; i++)
121     {
122         hw_address[5] = i;
123
124         error = ethernet_register_interface(vnet_get_main(),
125                                             test_interface_device_class.index,
126                                             i /* instance */,
127                                             hw_address,
128                                             &tm->hw_if_indicies[i],
129                                             /* flag change */ 0);
130
131         MFIB_TEST((NULL == error), "ADD interface %d", i);
132
133         error = vnet_hw_interface_set_flags(vnet_get_main(),
134                                             tm->hw_if_indicies[i],
135                                             VNET_HW_INTERFACE_FLAG_LINK_UP);
136         tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
137                                           tm->hw_if_indicies[i]);
138         vec_validate (ip4_main.fib_index_by_sw_if_index,
139                       tm->hw[i]->sw_if_index);
140         vec_validate (ip6_main.fib_index_by_sw_if_index,
141                       tm->hw[i]->sw_if_index);
142         ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
143         ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
144
145         vec_validate (ip4_main.mfib_index_by_sw_if_index,
146                       tm->hw[i]->sw_if_index);
147         vec_validate (ip6_main.mfib_index_by_sw_if_index,
148                       tm->hw[i]->sw_if_index);
149         ip4_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
150         ip6_main.mfib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
151
152         error = vnet_sw_interface_set_flags(vnet_get_main(),
153                                             tm->hw[i]->sw_if_index,
154                                             VNET_SW_INTERFACE_FLAG_ADMIN_UP);
155         MFIB_TEST((NULL == error), "UP interface %d", i);
156     }
157     /*
158      * re-eval after the inevitable realloc
159      */
160     for (i = 0; i < ninterfaces; i++)
161     {
162         tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
163                                           tm->hw_if_indicies[i]);
164     }
165
166     return (0);
167 }
168
169 #define MFIB_TEST_REP(_cond, _comment, _args...)                \
170 {                                                               \
171     if (!MFIB_TEST_I(_cond, _comment, ##_args)) {               \
172         return (0);                                             \
173     }                                                           \
174 }
175
176 static int
177 mfib_test_validate_rep_v (const replicate_t *rep,
178                           u16 n_buckets,
179                           va_list ap)
180 {
181     const dpo_id_t *dpo;
182     adj_index_t ai;
183     dpo_type_t dt;
184     int bucket;
185
186     MFIB_TEST_REP((n_buckets == rep->rep_n_buckets),
187                   "n_buckets = %d", rep->rep_n_buckets);
188
189     for (bucket = 0; bucket < n_buckets; bucket++)
190     {
191         dt = va_arg(ap, int);  // type promotion
192         ai = va_arg(ap, adj_index_t);
193         dpo = replicate_get_bucket_i(rep, bucket);
194
195         MFIB_TEST_REP((dt == dpo->dpoi_type),
196                       "bucket %d stacks on %U",
197                       bucket,
198                       format_dpo_type, dpo->dpoi_type);
199
200         if (DPO_RECEIVE != dt)
201         {
202             MFIB_TEST_REP((ai == dpo->dpoi_index),
203                           "bucket %d stacks on %U",
204                           bucket,
205                           format_dpo_id, dpo, 0);
206         }
207     }
208     return (!0);
209 }
210
211 static fib_forward_chain_type_t
212 fib_forw_chain_type_from_fib_proto (fib_protocol_t proto)
213 {
214     switch (proto)
215     {
216     case FIB_PROTOCOL_IP4:
217         return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
218     case FIB_PROTOCOL_IP6:
219         return (FIB_FORW_CHAIN_TYPE_UNICAST_IP6);
220     default:
221         break;
222     }
223     ASSERT(0);
224     return (0);
225 }
226
227
228 static int
229 mfib_test_entry (fib_node_index_t fei,
230                  mfib_entry_flags_t eflags,
231                  u16 n_buckets,
232                  ...)
233 {
234     const mfib_entry_t *mfe;
235     const replicate_t *rep;
236     mfib_prefix_t pfx;
237     va_list ap;
238     int res;
239
240     va_start(ap, n_buckets);
241
242     mfe = mfib_entry_get(fei);
243     mfib_entry_get_prefix(fei, &pfx);
244
245     MFIB_TEST_REP((eflags == mfe->mfe_flags),
246                   "%U has %U expect %U",
247                   format_mfib_prefix, &pfx,
248                   format_mfib_entry_flags, mfe->mfe_flags,
249                   format_mfib_entry_flags, eflags);
250
251     if (0 == n_buckets)
252     {
253         MFIB_TEST_REP((DPO_DROP == mfe->mfe_rep.dpoi_type),
254                       "%U links to %U",
255                       format_mfib_prefix, &pfx,
256                       format_dpo_id, &mfe->mfe_rep, 0);
257         res = !0;
258     }
259     else
260     {
261         dpo_id_t tmp = DPO_INVALID;
262
263         mfib_entry_contribute_forwarding(
264             fei,
265             fib_forw_chain_type_from_fib_proto(pfx.fp_proto),
266             &tmp);
267         rep = replicate_get(tmp.dpoi_index);
268
269         MFIB_TEST_REP((DPO_REPLICATE == tmp.dpoi_type),
270                       "%U links to %U",
271                       format_mfib_prefix, &pfx,
272                       format_dpo_type, tmp.dpoi_type);
273
274         res = mfib_test_validate_rep_v(rep, n_buckets, ap);
275
276         dpo_reset(&tmp);
277     }
278
279     va_end(ap);
280
281     return (res);
282 }
283
284 static int
285 mfib_test_entry_itf (fib_node_index_t fei,
286                      u32 sw_if_index,
287                      mfib_itf_flags_t flags)
288 {
289     const mfib_entry_t *mfe;
290     const mfib_itf_t *mfi;
291     mfib_prefix_t pfx;
292
293     mfe = mfib_entry_get(fei);
294     mfi = mfib_entry_get_itf(mfe, sw_if_index);
295     mfib_entry_get_prefix(fei, &pfx);
296
297     MFIB_TEST_REP((NULL != mfi),
298                   "%U has interface %d",
299                   format_mfib_prefix, &pfx, sw_if_index);
300
301     MFIB_TEST_REP((flags == mfi->mfi_flags),
302                   "%U interface %d has flags %U expect %U",
303                   format_mfib_prefix, &pfx, sw_if_index,
304                   format_mfib_itf_flags, flags,
305                   format_mfib_itf_flags, mfi->mfi_flags);
306
307     return (!0);
308 }
309
310 static int
311 mfib_test_entry_no_itf (fib_node_index_t fei,
312                         u32 sw_if_index)
313 {
314     const mfib_entry_t *mfe;
315     const mfib_itf_t *mfi;
316     mfib_prefix_t pfx;
317
318     mfe = mfib_entry_get(fei);
319     mfi = mfib_entry_get_itf(mfe, sw_if_index);
320     mfib_entry_get_prefix(fei, &pfx);
321
322     MFIB_TEST_REP((NULL == mfi),
323                   "%U has no interface %d",
324                   format_mfib_prefix, &pfx, sw_if_index);
325
326     return (!0);
327 }
328
329 static int
330 mfib_test_i (fib_protocol_t PROTO,
331              vnet_link_t LINKT,
332              const mfib_prefix_t *pfx_no_forward,
333              const mfib_prefix_t *pfx_s_g,
334              const mfib_prefix_t *pfx_star_g_1,
335              const mfib_prefix_t *pfx_star_g_2,
336              const mfib_prefix_t *pfx_star_g_3,
337              const mfib_prefix_t *pfx_star_g_slash_m)
338 {
339     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;
340     u32 fib_index, n_entries, n_itfs, n_reps;
341     fib_node_index_t ai_1, ai_2, ai_3;
342     test_main_t *tm;
343
344     mfib_prefix_t all_1s;
345     memset(&all_1s, 0xfd, sizeof(all_1s));
346
347     n_entries = pool_elts(mfib_entry_pool);
348     n_itfs = pool_elts(mfib_itf_pool);
349     n_reps = pool_elts(replicate_pool);
350     tm = &test_main;
351
352     ai_1 = adj_mcast_add_or_lock(PROTO,
353                                  LINKT,
354                                  tm->hw[1]->sw_if_index);
355     ai_2 = adj_mcast_add_or_lock(PROTO,
356                                  LINKT,
357                                  tm->hw[2]->sw_if_index);
358     ai_3 = adj_mcast_add_or_lock(PROTO,
359                                  LINKT,
360                                  tm->hw[3]->sw_if_index);
361
362     MFIB_TEST(3 == adj_mcast_db_size(), "3 MCAST adjs");
363
364     /* Find or create FIB table 11 */
365     fib_index = mfib_table_find_or_create_and_lock(PROTO, 11);
366
367     mfib_prefix_t pfx_dft = {
368         .fp_len = 0,
369         .fp_proto = PROTO,
370     };
371     mfei_dflt = mfib_table_lookup_exact_match(fib_index, &pfx_dft);
372     MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
373     MFIB_TEST(mfib_test_entry(mfei_dflt,
374                               MFIB_ENTRY_FLAG_DROP,
375                               0),
376               "(*,*) no replcaitions");
377
378     MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
379     MFIB_TEST(mfib_test_entry(mfei_dflt,
380                               MFIB_ENTRY_FLAG_DROP,
381                               0),
382               "(*,*) no replcaitions");
383
384
385     fib_route_path_t path_via_if0 = {
386         .frp_proto = PROTO,
387         .frp_addr = zero_addr,
388         .frp_sw_if_index = tm->hw[0]->sw_if_index,
389         .frp_fib_index = ~0,
390         .frp_weight = 0,
391         .frp_flags = 0,
392     };
393
394     mfib_table_entry_path_update(fib_index,
395                                  pfx_no_forward,
396                                  MFIB_SOURCE_API,
397                                  &path_via_if0,
398                                  MFIB_ITF_FLAG_ACCEPT);
399
400     mfei_no_f = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
401     MFIB_TEST(mfib_test_entry(mfei_no_f,
402                               MFIB_ENTRY_FLAG_NONE,
403                               0),
404               "%U no replcaitions",
405               format_mfib_prefix, pfx_no_forward);
406     MFIB_TEST_NS(mfib_test_entry_itf(mfei_no_f, tm->hw[0]->sw_if_index,
407                                      MFIB_ITF_FLAG_ACCEPT));
408
409     fib_route_path_t path_via_if1 = {
410         .frp_proto = PROTO,
411         .frp_addr = zero_addr,
412         .frp_sw_if_index = tm->hw[1]->sw_if_index,
413         .frp_fib_index = ~0,
414         .frp_weight = 0,
415         .frp_flags = 0,
416     };
417     fib_route_path_t path_via_if2 = {
418         .frp_proto = PROTO,
419         .frp_addr = zero_addr,
420         .frp_sw_if_index = tm->hw[2]->sw_if_index,
421         .frp_fib_index = ~0,
422         .frp_weight = 0,
423         .frp_flags = 0,
424     };
425     fib_route_path_t path_via_if3 = {
426         .frp_proto = PROTO,
427         .frp_addr = zero_addr,
428         .frp_sw_if_index = tm->hw[3]->sw_if_index,
429         .frp_fib_index = ~0,
430         .frp_weight = 0,
431         .frp_flags = 0,
432     };
433     fib_route_path_t path_for_us = {
434         .frp_proto = PROTO,
435         .frp_addr = zero_addr,
436         .frp_sw_if_index = 0xffffffff,
437         .frp_fib_index = ~0,
438         .frp_weight = 0,
439         .frp_flags = FIB_ROUTE_PATH_LOCAL,
440     };
441
442     /*
443      * An (S,G) with 1 accepting and 3 forwarding paths
444      */
445     mfib_table_entry_path_update(fib_index,
446                                  pfx_s_g,
447                                  MFIB_SOURCE_API,
448                                  &path_via_if0,
449                                  MFIB_ITF_FLAG_ACCEPT);
450     mfib_table_entry_path_update(fib_index,
451                                  pfx_s_g,
452                                  MFIB_SOURCE_API,
453                                  &path_via_if1,
454                                  MFIB_ITF_FLAG_FORWARD);
455     mfib_table_entry_path_update(fib_index,
456                                  pfx_s_g,
457                                  MFIB_SOURCE_API,
458                                  &path_via_if2,
459                                  MFIB_ITF_FLAG_FORWARD);
460     mfib_table_entry_path_update(fib_index,
461                                  pfx_s_g,
462                                  MFIB_SOURCE_API,
463                                  &path_via_if3,
464                                  (MFIB_ITF_FLAG_FORWARD |
465                                   MFIB_ITF_FLAG_NEGATE_SIGNAL));
466
467     mfei_s_g = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
468
469     MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_s_g,
470               "%U present",
471               format_mfib_prefix, pfx_s_g);
472     MFIB_TEST(mfib_test_entry(mfei_s_g,
473                               MFIB_ENTRY_FLAG_NONE,
474                               3,
475                               DPO_ADJACENCY_MCAST, ai_1,
476                               DPO_ADJACENCY_MCAST, ai_2,
477                               DPO_ADJACENCY_MCAST, ai_3),
478               "%U replicate ok",
479               format_mfib_prefix, pfx_s_g);
480     MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[0]->sw_if_index,
481                                      MFIB_ITF_FLAG_ACCEPT));
482     MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[1]->sw_if_index,
483                                      MFIB_ITF_FLAG_FORWARD));
484     MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[2]->sw_if_index,
485                                      MFIB_ITF_FLAG_FORWARD));
486     MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[3]->sw_if_index,
487                                      (MFIB_ITF_FLAG_FORWARD |
488                                       MFIB_ITF_FLAG_NEGATE_SIGNAL)));
489
490     /*
491      * A (*,G), which the same G as the (S,G).
492      * different paths. test our LPM.
493      */
494     mfei_g_1 = mfib_table_entry_path_update(fib_index,
495                                             pfx_star_g_1,
496                                             MFIB_SOURCE_API,
497                                             &path_via_if0,
498                                             MFIB_ITF_FLAG_ACCEPT);
499     mfib_table_entry_path_update(fib_index,
500                                  pfx_star_g_1,
501                                  MFIB_SOURCE_API,
502                                  &path_via_if1,
503                                  MFIB_ITF_FLAG_FORWARD);
504
505     /*
506      * test we find the *,G and S,G via LPM and exact matches
507      */
508     mfei = mfib_table_lookup_exact_match(fib_index,
509                                          pfx_star_g_1);
510     MFIB_TEST(mfei == mfei_g_1,
511               "%U found via exact match",
512               format_mfib_prefix, pfx_star_g_1);
513     MFIB_TEST(mfib_test_entry(mfei,
514                               MFIB_ENTRY_FLAG_NONE,
515                               1,
516                               DPO_ADJACENCY_MCAST, ai_1),
517               "%U replicate ok",
518               format_mfib_prefix, pfx_star_g_1);
519
520     mfei = mfib_table_lookup(fib_index,
521                              pfx_star_g_1);
522     MFIB_TEST(mfei == mfei_g_1,
523               "%U found via LP match",
524               format_mfib_prefix, pfx_star_g_1);
525
526     MFIB_TEST(mfib_test_entry(mfei,
527                               MFIB_ENTRY_FLAG_NONE,
528                               1,
529                               DPO_ADJACENCY_MCAST, ai_1),
530               "%U replicate ok",
531               format_mfib_prefix, pfx_star_g_1);
532
533     mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
534     MFIB_TEST(mfei == mfei_s_g,
535               "%U found via exact match",
536               format_mfib_prefix, pfx_s_g);
537
538     MFIB_TEST(mfib_test_entry(mfei,
539                               MFIB_ENTRY_FLAG_NONE,
540                               3,
541                               DPO_ADJACENCY_MCAST, ai_1,
542                               DPO_ADJACENCY_MCAST, ai_2,
543                               DPO_ADJACENCY_MCAST, ai_3),
544               "%U replicate OK",
545               format_mfib_prefix, pfx_s_g);
546     mfei = mfib_table_lookup(fib_index, pfx_s_g);
547     MFIB_TEST(mfei == mfei_s_g,
548               "%U found via LP match",
549               format_mfib_prefix, pfx_s_g);
550
551     MFIB_TEST(mfib_test_entry(mfei,
552                               MFIB_ENTRY_FLAG_NONE,
553                               3,
554                               DPO_ADJACENCY_MCAST, ai_1,
555                               DPO_ADJACENCY_MCAST, ai_2,
556                               DPO_ADJACENCY_MCAST, ai_3),
557               "%U replicate OK",
558               format_mfib_prefix, pfx_s_g);
559
560     /*
561      * A (*,G/m), which the same root G as the (*,G).
562      * different paths. test our LPM.
563      */
564     mfei_g_m = mfib_table_entry_path_update(fib_index,
565                                             pfx_star_g_slash_m,
566                                             MFIB_SOURCE_API,
567                                             &path_via_if2,
568                                             MFIB_ITF_FLAG_ACCEPT);
569     mfib_table_entry_path_update(fib_index,
570                                  pfx_star_g_slash_m,
571                                  MFIB_SOURCE_API,
572                                  &path_via_if3,
573                                  MFIB_ITF_FLAG_FORWARD);
574
575     /*
576      * test we find the (*,G/m), (*,G) and (S,G) via LPM and exact matches
577      */
578     mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
579     MFIB_TEST((mfei_g_1 == mfei),
580               "%U found via DP LPM: %d",
581               format_mfib_prefix, pfx_star_g_1, mfei);
582
583     MFIB_TEST(mfib_test_entry(mfei,
584                               MFIB_ENTRY_FLAG_NONE,
585                               1,
586                               DPO_ADJACENCY_MCAST, ai_1),
587               "%U replicate ok",
588               format_mfib_prefix, pfx_star_g_1);
589
590     mfei = mfib_table_lookup(fib_index, pfx_star_g_1);
591
592     MFIB_TEST(mfib_test_entry(mfei,
593                               MFIB_ENTRY_FLAG_NONE,
594                               1,
595                               DPO_ADJACENCY_MCAST, ai_1),
596               "%U replicate ok",
597               format_mfib_prefix, pfx_star_g_1);
598
599     mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
600
601     MFIB_TEST(mfib_test_entry(mfei,
602                               MFIB_ENTRY_FLAG_NONE,
603                               3,
604                               DPO_ADJACENCY_MCAST, ai_1,
605                               DPO_ADJACENCY_MCAST, ai_2,
606                               DPO_ADJACENCY_MCAST, ai_3),
607               "%U replicate OK",
608               format_mfib_prefix, pfx_s_g);
609     mfei = mfib_table_lookup(fib_index, pfx_s_g);
610
611     MFIB_TEST(mfib_test_entry(mfei,
612                               MFIB_ENTRY_FLAG_NONE,
613                               3,
614                               DPO_ADJACENCY_MCAST, ai_1,
615                               DPO_ADJACENCY_MCAST, ai_2,
616                               DPO_ADJACENCY_MCAST, ai_3),
617               "%U replicate OK",
618               format_mfib_prefix, pfx_s_g);
619
620     mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
621     MFIB_TEST(mfei = mfei_g_m,
622               "%U Found via exact match",
623               format_mfib_prefix, pfx_star_g_slash_m);
624     MFIB_TEST(mfib_test_entry(mfei,
625                               MFIB_ENTRY_FLAG_NONE,
626                               1,
627                               DPO_ADJACENCY_MCAST, ai_3),
628               "%U replicate OK",
629               format_mfib_prefix, pfx_star_g_slash_m);
630     MFIB_TEST(mfei_g_m == mfib_table_lookup(fib_index, pfx_star_g_slash_m),
631               "%U found via LPM",
632               format_mfib_prefix, pfx_star_g_slash_m);
633
634     /*
635      * Add a for-us path
636      */
637     mfei = mfib_table_entry_path_update(fib_index,
638                                         pfx_s_g,
639                                         MFIB_SOURCE_API,
640                                         &path_for_us,
641                                         MFIB_ITF_FLAG_FORWARD);
642
643     MFIB_TEST(mfib_test_entry(mfei,
644                               MFIB_ENTRY_FLAG_NONE,
645                               4,
646                               DPO_ADJACENCY_MCAST, ai_1,
647                               DPO_ADJACENCY_MCAST, ai_2,
648                               DPO_ADJACENCY_MCAST, ai_3,
649                               DPO_RECEIVE, 0),
650               "%U replicate OK",
651               format_mfib_prefix, pfx_s_g);
652
653     /*
654      * remove a for-us path
655      */
656     mfib_table_entry_path_remove(fib_index,
657                                  pfx_s_g,
658                                  MFIB_SOURCE_API,
659                                  &path_for_us);
660
661     MFIB_TEST(mfib_test_entry(mfei,
662                               MFIB_ENTRY_FLAG_NONE,
663                               3,
664                               DPO_ADJACENCY_MCAST, ai_1,
665                               DPO_ADJACENCY_MCAST, ai_2,
666                               DPO_ADJACENCY_MCAST, ai_3),
667               "%U replicate OK",
668               format_mfib_prefix, pfx_s_g);
669
670     /*
671      * update an existing forwarding path to be only accepting
672      *   - expect it to be removed from the replication set.
673      */
674     mfib_table_entry_path_update(fib_index,
675                                  pfx_s_g,
676                                  MFIB_SOURCE_API,
677                                  &path_via_if3,
678                                  MFIB_ITF_FLAG_ACCEPT);
679
680     MFIB_TEST(mfib_test_entry(mfei,
681                               MFIB_ENTRY_FLAG_NONE,
682                               2,
683                               DPO_ADJACENCY_MCAST, ai_1,
684                               DPO_ADJACENCY_MCAST, ai_2),
685               "%U replicate OK",
686               format_mfib_prefix, pfx_s_g);
687     MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
688                                      MFIB_ITF_FLAG_ACCEPT));
689     MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
690                                      MFIB_ITF_FLAG_FORWARD));
691     MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
692                                      MFIB_ITF_FLAG_FORWARD));
693     MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
694                                      MFIB_ITF_FLAG_ACCEPT));
695     /*
696      * Make the path forwarding again
697      *  - expect it to be added back to the replication set
698      */
699     mfib_table_entry_path_update(fib_index,
700                                  pfx_s_g,
701                                  MFIB_SOURCE_API,
702                                  &path_via_if3,
703                                  (MFIB_ITF_FLAG_FORWARD |
704                                   MFIB_ITF_FLAG_ACCEPT |
705                                   MFIB_ITF_FLAG_NEGATE_SIGNAL));
706
707     mfei = mfib_table_lookup_exact_match(fib_index,
708                                          pfx_s_g);
709
710     MFIB_TEST(mfib_test_entry(mfei,
711                               MFIB_ENTRY_FLAG_NONE,
712                               3,
713                               DPO_ADJACENCY_MCAST, ai_1,
714                               DPO_ADJACENCY_MCAST, ai_2,
715                               DPO_ADJACENCY_MCAST, ai_3),
716               "%U replicate OK",
717               format_mfib_prefix, pfx_s_g);
718     MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
719                                      MFIB_ITF_FLAG_ACCEPT));
720      MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
721                                      MFIB_ITF_FLAG_FORWARD));
722     MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
723                                      MFIB_ITF_FLAG_FORWARD));
724     MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
725                                      (MFIB_ITF_FLAG_FORWARD |
726                                       MFIB_ITF_FLAG_ACCEPT |
727                                       MFIB_ITF_FLAG_NEGATE_SIGNAL)));
728
729     /*
730      * update flags on the entry
731      */
732     mfib_table_entry_update(fib_index,
733                             pfx_s_g,
734                             MFIB_SOURCE_API,
735                             MFIB_ENTRY_FLAG_SIGNAL);
736     MFIB_TEST(mfib_test_entry(mfei,
737                               MFIB_ENTRY_FLAG_SIGNAL,
738                               3,
739                               DPO_ADJACENCY_MCAST, ai_1,
740                               DPO_ADJACENCY_MCAST, ai_2,
741                               DPO_ADJACENCY_MCAST, ai_3),
742               "%U replicate OK",
743               format_mfib_prefix, pfx_s_g);
744
745     /*
746      * remove paths
747      */
748     mfib_table_entry_path_remove(fib_index,
749                                  pfx_s_g,
750                                  MFIB_SOURCE_API,
751                                  &path_via_if3);
752
753     MFIB_TEST(mfib_test_entry(mfei,
754                               MFIB_ENTRY_FLAG_SIGNAL,
755                               2,
756                               DPO_ADJACENCY_MCAST, ai_1,
757                               DPO_ADJACENCY_MCAST, ai_2),
758               "%U replicate OK",
759               format_mfib_prefix, pfx_s_g);
760     MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
761                                      MFIB_ITF_FLAG_ACCEPT));
762     MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
763                                      MFIB_ITF_FLAG_FORWARD));
764     MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
765                                      MFIB_ITF_FLAG_FORWARD));
766     MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
767
768     mfib_table_entry_path_remove(fib_index,
769                                  pfx_s_g,
770                                  MFIB_SOURCE_API,
771                                  &path_via_if1);
772
773     MFIB_TEST(mfib_test_entry(mfei,
774                               MFIB_ENTRY_FLAG_SIGNAL,
775                               1,
776                               DPO_ADJACENCY_MCAST, ai_2),
777               "%U replicate OK",
778               format_mfib_prefix, pfx_s_g);
779     MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
780                                      MFIB_ITF_FLAG_ACCEPT));
781     MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
782                                      MFIB_ITF_FLAG_FORWARD));
783     MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
784
785     /*
786      * remove the accpeting only interface
787      */
788     mfib_table_entry_path_remove(fib_index,
789                                  pfx_s_g,
790                                  MFIB_SOURCE_API,
791                                  &path_via_if0);
792
793     MFIB_TEST(mfib_test_entry(mfei,
794                               MFIB_ENTRY_FLAG_SIGNAL,
795                               1,
796                               DPO_ADJACENCY_MCAST, ai_2),
797               "%U replicate OK",
798               format_mfib_prefix, pfx_s_g);
799     MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
800                                      MFIB_ITF_FLAG_FORWARD));
801     MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[0]->sw_if_index));
802     MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[1]->sw_if_index));
803     MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
804
805     /*
806      * remove the last path, the entry still has flags so it remains
807      */
808     mfib_table_entry_path_remove(fib_index,
809                                  pfx_s_g,
810                                  MFIB_SOURCE_API,
811                                  &path_via_if2);
812
813     MFIB_TEST(mfib_test_entry(mfei,
814                               MFIB_ENTRY_FLAG_SIGNAL,
815                               0),
816               "%U no replications",
817               format_mfib_prefix, pfx_s_g);
818
819     /*
820      * update flags on the entry
821      */
822     mfib_table_entry_update(fib_index,
823                             pfx_s_g,
824                             MFIB_SOURCE_API,
825                             (MFIB_ENTRY_FLAG_SIGNAL |
826                              MFIB_ENTRY_FLAG_CONNECTED));
827     MFIB_TEST(mfib_test_entry(mfei,
828                               (MFIB_ENTRY_FLAG_SIGNAL |
829                                MFIB_ENTRY_FLAG_CONNECTED),
830                               0),
831               "%U no replications",
832               format_mfib_prefix, pfx_s_g);
833
834     /*
835      * An entry with a NS interface
836      */
837     mfei_g_2 = mfib_table_entry_path_update(fib_index,
838                                             pfx_star_g_2,
839                                             MFIB_SOURCE_API,
840                                             &path_via_if0,
841                                             (MFIB_ITF_FLAG_ACCEPT |
842                                              MFIB_ITF_FLAG_NEGATE_SIGNAL));
843     MFIB_TEST(mfib_test_entry(mfei_g_2,
844                               MFIB_ENTRY_FLAG_NONE,
845                               0),
846               "%U No replications",
847               format_mfib_prefix, pfx_star_g_2);
848
849     /*
850      * Simulate a signal from the data-plane
851      */
852     {
853         mfib_entry_t *mfe;
854         mfib_itf_t *mfi;
855
856         mfe = mfib_entry_get(mfei_g_2);
857         mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
858
859         mfib_signal_push(mfe, mfi, NULL);
860     }
861
862     /*
863      * An entry with a NS interface
864      */
865     mfei_g_3 = mfib_table_entry_path_update(fib_index,
866                                             pfx_star_g_3,
867                                             MFIB_SOURCE_API,
868                                             &path_via_if0,
869                                             (MFIB_ITF_FLAG_ACCEPT |
870                                              MFIB_ITF_NEGATE_SIGNAL));
871     MFIB_TEST(mfib_test_entry(mfei_g_3,
872                               MFIB_ENTRY_FLAG_NONE,
873                               0),
874               "%U No replications",
875               format_mfib_prefix, pfx_star_g_3);
876
877     /*
878      * Simulate a signal from the data-plane
879      */
880     {
881         mfib_entry_t *mfe;
882         mfib_itf_t *mfi;
883
884         mfe = mfib_entry_get(mfei_g_3);
885         mfi = mfib_entry_get_itf(mfe, path_via_if0.frp_sw_if_index);
886
887         mfib_signal_push(mfe, mfi, NULL);
888     }
889
890     if (FIB_PROTOCOL_IP6 == PROTO)
891     {
892         /*
893          * All the entries are present. let's ensure we can find them all
894          * via exact and longest prefix matches.
895          */
896         /*
897          * A source address we will never match
898          */
899         ip6_address_t src = {
900             .as_u64[0] = clib_host_to_net_u64(0x3001000000000000),
901             .as_u64[1] = clib_host_to_net_u64(0xffffffffffffffff),
902         };
903
904         /*
905          * Find the (*,G/m)
906          */
907         MFIB_TEST((mfei_g_m == ip6_mfib_table_lookup2(
908                                    ip6_mfib_get(fib_index),
909                                    &src,
910                                    &pfx_star_g_slash_m->fp_grp_addr.ip6)),
911                   "%U found via DP LPM grp=%U",
912                   format_mfib_prefix, pfx_star_g_slash_m,
913                   format_ip6_address, &pfx_star_g_slash_m->fp_grp_addr.ip6);
914
915         ip6_address_t tmp = pfx_star_g_slash_m->fp_grp_addr.ip6;
916         tmp.as_u8[15] = 0xff;
917
918         MFIB_TEST((mfei_g_m == ip6_mfib_table_lookup2(
919                                    ip6_mfib_get(fib_index),
920                                    &pfx_s_g->fp_src_addr.ip6,
921                                    &tmp)),
922                   "%U found via DP LPM grp=%U",
923                   format_mfib_prefix, pfx_star_g_slash_m,
924                   format_ip6_address, &tmp);
925
926         /*
927          * Find the (S,G).
928          */
929         mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
930                                       &pfx_s_g->fp_src_addr.ip6,
931                                       &pfx_s_g->fp_grp_addr.ip6);
932         MFIB_TEST((mfei_s_g == mfei),
933                   "%U found via DP LPM: %d",
934                   format_mfib_prefix, pfx_s_g, mfei);
935
936         /*
937          * Find the 3 (*,G) s
938          */
939         mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
940                                       &src,
941                                       &pfx_star_g_1->fp_grp_addr.ip6);
942         MFIB_TEST((mfei_g_1 == mfei),
943                   "%U found via DP LPM: %d",
944                   format_mfib_prefix, pfx_star_g_1, mfei);
945         mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
946                                       &src,
947                                       &pfx_star_g_2->fp_grp_addr.ip6);
948         MFIB_TEST((mfei_g_2 == mfei),
949                   "%U found via DP LPM: %d",
950                   format_mfib_prefix, pfx_star_g_2, mfei);
951         mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
952                                       &src,
953                                       &pfx_star_g_3->fp_grp_addr.ip6);
954         MFIB_TEST((mfei_g_3 == mfei),
955                   "%U found via DP LPM: %d",
956                   format_mfib_prefix, pfx_star_g_3, mfei);
957     }
958
959     /*
960      * remove flags on the entry. This is the last of the
961      * state associated with the entry, so now it goes.
962      */
963     mfib_table_entry_update(fib_index,
964                             pfx_s_g,
965                             MFIB_SOURCE_API,
966                             MFIB_ENTRY_FLAG_NONE);
967     mfei = mfib_table_lookup_exact_match(fib_index,
968                                          pfx_s_g);
969     MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
970               "%U gone",
971               format_mfib_prefix, pfx_s_g);
972
973     /*
974      * remove the last path on the no forward entry - the last entry
975      */
976     mfib_table_entry_path_remove(fib_index,
977                                  pfx_no_forward,
978                                  MFIB_SOURCE_API,
979                                  &path_via_if0);
980
981     mfei = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
982     MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
983               "%U gone",
984               format_mfib_prefix, pfx_no_forward);
985
986     /*
987      * hard delete the (*,232.1.1.1)
988      */
989     mfib_table_entry_delete(fib_index,
990                             pfx_star_g_1,
991                             MFIB_SOURCE_API);
992
993     mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
994     MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
995               "%U gone",
996               format_mfib_prefix, pfx_star_g_1);
997     /*
998      * remove the entry whilst the signal is pending
999      */
1000     mfib_table_entry_delete(fib_index,
1001                             pfx_star_g_2,
1002                             MFIB_SOURCE_API);
1003
1004     mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_2);
1005     MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1006               "%U Gone",
1007               format_mfib_prefix, pfx_star_g_2);
1008     mfib_table_entry_delete(fib_index,
1009                             pfx_star_g_3,
1010                             MFIB_SOURCE_API);
1011
1012     mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_3);
1013     MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1014               "%U Gone",
1015               format_mfib_prefix, pfx_star_g_3);
1016
1017     mfib_table_entry_delete(fib_index,
1018                             pfx_star_g_slash_m,
1019                             MFIB_SOURCE_API);
1020
1021     mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_slash_m);
1022     MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
1023               "%U Gone",
1024               format_mfib_prefix, pfx_star_g_slash_m);
1025
1026     /*
1027      * Unlock the table - it's the last lock so should be gone thereafter
1028      */
1029     mfib_table_unlock(fib_index, PROTO);
1030
1031     MFIB_TEST((FIB_NODE_INDEX_INVALID ==
1032                mfib_table_find(PROTO, fib_index)),
1033               "MFIB table %d gone", fib_index);
1034
1035     adj_unlock(ai_1);
1036     adj_unlock(ai_2);
1037     adj_unlock(ai_3);
1038
1039     /*
1040      * test we've leaked no resources
1041      */
1042     MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
1043     MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
1044               n_reps, pool_elts(replicate_pool));
1045     MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
1046               " No more entries %d!=%d",
1047               n_entries, pool_elts(mfib_entry_pool));
1048     MFIB_TEST(n_itfs == pool_elts(mfib_itf_pool),
1049               " No more Interfaces %d!=%d",
1050               n_itfs, pool_elts(mfib_itf_pool));
1051
1052     return (0);
1053 }
1054
1055 static int
1056 mfib_test_v4 (void)
1057 {
1058     const mfib_prefix_t pfx_224_s_8 = {
1059         .fp_len = 8,
1060         .fp_proto = FIB_PROTOCOL_IP4,
1061         .fp_grp_addr = {
1062             .ip4.as_u32 = clib_host_to_net_u32(0xe0000000),
1063         }
1064     };
1065     const mfib_prefix_t pfx_1_1_1_1_c_239_1_1_1 = {
1066         .fp_len = 64,
1067         .fp_proto = FIB_PROTOCOL_IP4,
1068         .fp_grp_addr = {
1069             .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1070         },
1071         .fp_src_addr = {
1072             .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1073         },
1074     };
1075     const mfib_prefix_t pfx_239_1_1_1 = {
1076         .fp_len = 32,
1077         .fp_proto = FIB_PROTOCOL_IP4,
1078         .fp_grp_addr = {
1079             .ip4.as_u32 = clib_host_to_net_u32(0xef010101),
1080         },
1081         .fp_src_addr = {
1082             .ip4.as_u32 = 0,
1083         },
1084     };
1085     const mfib_prefix_t pfx_239_1_1_2 = {
1086         .fp_len = 32,
1087         .fp_proto = FIB_PROTOCOL_IP4,
1088         .fp_grp_addr = {
1089             .ip4.as_u32 = clib_host_to_net_u32(0xef010102),
1090         },
1091         .fp_src_addr = {
1092             .ip4.as_u32 = 0,
1093         },
1094     };
1095     const mfib_prefix_t pfx_239_1_1_3 = {
1096         .fp_len = 32,
1097         .fp_proto = FIB_PROTOCOL_IP4,
1098         .fp_grp_addr = {
1099             .ip4.as_u32 = clib_host_to_net_u32(0xef010103),
1100         },
1101         .fp_src_addr = {
1102             .ip4.as_u32 = 0,
1103         },
1104     };
1105     const mfib_prefix_t pfx_239 = {
1106         .fp_len = 8,
1107         .fp_proto = FIB_PROTOCOL_IP4,
1108         .fp_grp_addr = {
1109             .ip4.as_u32 = clib_host_to_net_u32(0xef000000),
1110         },
1111         .fp_src_addr = {
1112             .ip4.as_u32 = 0,
1113         },
1114     };
1115
1116     return (mfib_test_i(FIB_PROTOCOL_IP4,
1117                         VNET_LINK_IP4,
1118                         &pfx_224_s_8,
1119                         &pfx_1_1_1_1_c_239_1_1_1,
1120                         &pfx_239_1_1_1,
1121                         &pfx_239_1_1_2,
1122                         &pfx_239_1_1_3,
1123                         &pfx_239));
1124 }
1125
1126 static int
1127 mfib_test_v6 (void)
1128 {
1129     const mfib_prefix_t pfx_ffd_s_12 = {
1130         .fp_len = 12,
1131         .fp_proto = FIB_PROTOCOL_IP6,
1132         .fp_grp_addr = {
1133             .ip6.as_u64[0] = clib_host_to_net_u64(0xffd0000000000000),
1134         }
1135     };
1136     const mfib_prefix_t pfx_2001_1_c_ff_1 = {
1137         .fp_len = 256,
1138         .fp_proto = FIB_PROTOCOL_IP6,
1139         .fp_grp_addr = {
1140             .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1141             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1142         },
1143         .fp_src_addr = {
1144             .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
1145             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1146         },
1147     };
1148     const mfib_prefix_t pfx_ff_1 = {
1149         .fp_len = 128,
1150         .fp_proto = FIB_PROTOCOL_IP6,
1151         .fp_grp_addr = {
1152             .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1153             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
1154         },
1155     };
1156     const mfib_prefix_t pfx_ff_2 = {
1157         .fp_len = 128,
1158         .fp_proto = FIB_PROTOCOL_IP6,
1159         .fp_grp_addr = {
1160             .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1161             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1162         },
1163     };
1164     const mfib_prefix_t pfx_ff_3 = {
1165         /*
1166          * this is the ALL DHCP routers address
1167          */
1168         .fp_len = 128,
1169         .fp_proto = FIB_PROTOCOL_IP6,
1170         .fp_grp_addr = {
1171             .ip6.as_u64[0] = clib_host_to_net_u64(0xff02000100000000),
1172             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
1173         },
1174     };
1175     const mfib_prefix_t pfx_ff = {
1176         .fp_len = 16,
1177         .fp_proto = FIB_PROTOCOL_IP6,
1178         .fp_grp_addr = {
1179             .ip6.as_u64[0] = clib_host_to_net_u64(0xff01000000000000),
1180             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000000),
1181         },
1182     };
1183
1184     return (mfib_test_i(FIB_PROTOCOL_IP6,
1185                         VNET_LINK_IP6,
1186                         &pfx_ffd_s_12,
1187                         &pfx_2001_1_c_ff_1,
1188                         &pfx_ff_1,
1189                         &pfx_ff_2,
1190                         &pfx_ff_3,
1191                         &pfx_ff));
1192 }
1193
1194 static clib_error_t *
1195 mfib_test (vlib_main_t * vm,
1196            unformat_input_t * input,
1197            vlib_cli_command_t * cmd_arg)
1198 {
1199     int res = 0;
1200
1201     res += mfib_test_mk_intf(4);
1202     res += mfib_test_v4();
1203     res += mfib_test_v6();
1204
1205     if (res)
1206     {
1207         return clib_error_return(0, "MFIB Unit Test Failed");
1208     }
1209     else
1210     {
1211         return (NULL);
1212     }
1213 }
1214
1215 VLIB_CLI_COMMAND (test_fib_command, static) = {
1216     .path = "test mfib",
1217     .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
1218     .function = mfib_test,
1219 };
1220
1221 clib_error_t *
1222 mfib_test_init (vlib_main_t *vm)
1223 {
1224     return 0;
1225 }
1226
1227 VLIB_INIT_FUNCTION (mfib_test_init);