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