GRE: fix 4o6 and 6o4 adj stacking
[vpp.git] / src / vnet / mfib / mfib_test.c
index 8082a6b..4d519cd 100644 (file)
 #include <vnet/mfib/mfib_entry.h>
 #include <vnet/mfib/mfib_signal.h>
 #include <vnet/mfib/ip6_mfib.h>
+#include <vnet/fib/fib_path_list.h>
+#include <vnet/fib/fib_test.h>
+#include <vnet/fib/fib_table.h>
+#include <vnet/fib/mpls_fib.h>
 
 #include <vnet/dpo/replicate_dpo.h>
 #include <vnet/adj/adj_mcast.h>
     if (!(_evald)) {                                           \
         fformat(stderr, "FAIL:%d: " _comment "\n",             \
                 __LINE__, ##_args);                            \
+        res = 1;                                                \
     } else {                                                   \
         fformat(stderr, "PASS:%d: " _comment "\n",             \
                 __LINE__, ##_args);                            \
     }                                                          \
-    _evald;                                                    \
+    res;                                                       \
 })
 #define MFIB_TEST(_cond, _comment, _args...)                   \
 {                                                              \
-    if (!MFIB_TEST_I(_cond, _comment, ##_args)) {              \
-        return 1;\
+    if (MFIB_TEST_I(_cond, _comment, ##_args)) {               \
+        return 1;                                               \
         ASSERT(!("FAIL: " _comment));                          \
     }                                                          \
 }
 #define MFIB_TEST_NS(_cond)                                     \
 {                                                              \
-    if (!MFIB_TEST_I(_cond, "")) {                              \
-        return 1;\
+    if (MFIB_TEST_I(_cond, "")) {                               \
+        return 1;                                               \
         ASSERT(!("FAIL: "));                                    \
     }                                                          \
 }
@@ -107,8 +112,10 @@ mfib_test_mk_intf (u32 ninterfaces)
     clib_error_t * error = NULL;
     test_main_t *tm = &test_main;
     u8 byte;
+    int res;
     u32 i;
 
+    res = 0;
     ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
 
     for (i=0; i<6; i++)
@@ -163,33 +170,35 @@ mfib_test_mk_intf (u32 ninterfaces)
                                           tm->hw_if_indicies[i]);
     }
 
-    return (0);
+    return (res);
 }
 
 #define MFIB_TEST_REP(_cond, _comment, _args...)               \
 {                                                              \
-    if (!MFIB_TEST_I(_cond, _comment, ##_args)) {              \
-        return (0);                                            \
+    if (MFIB_TEST_I(_cond, _comment, ##_args)) {               \
+        return (1);                                            \
     }                                                          \
 }
 
 static int
 mfib_test_validate_rep_v (const replicate_t *rep,
                           u16 n_buckets,
-                          va_list ap)
+                          va_list *ap)
 {
     const dpo_id_t *dpo;
     adj_index_t ai;
     dpo_type_t dt;
     int bucket;
+    int res;
 
+    res = 0;
     MFIB_TEST_REP((n_buckets == rep->rep_n_buckets),
                   "n_buckets = %d", rep->rep_n_buckets);
 
     for (bucket = 0; bucket < n_buckets; bucket++)
     {
-        dt = va_arg(ap, int);  // type promotion
-        ai = va_arg(ap, adj_index_t);
+        dt = va_arg(*ap, int);  // type promotion
+        ai = va_arg(*ap, adj_index_t);
         dpo = replicate_get_bucket_i(rep, bucket);
 
         MFIB_TEST_REP((dt == dpo->dpoi_type),
@@ -200,35 +209,18 @@ mfib_test_validate_rep_v (const replicate_t *rep,
         if (DPO_RECEIVE != dt)
         {
             MFIB_TEST_REP((ai == dpo->dpoi_index),
-                          "bucket %d stacks on %U",
-                          bucket,
+                          "bucket %d [exp:%d] stacks on %U",
+                          bucket, ai,
                           format_dpo_id, dpo, 0);
         }
     }
-    return (!0);
-}
-
-static fib_forward_chain_type_t
-fib_forw_chain_type_from_fib_proto (fib_protocol_t proto)
-{
-    switch (proto)
-    {
-    case FIB_PROTOCOL_IP4:
-        return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
-    case FIB_PROTOCOL_IP6:
-        return (FIB_FORW_CHAIN_TYPE_UNICAST_IP6);
-    default:
-        break;
-    }
-    ASSERT(0);
-    return (0);
+    return (res);
 }
 
-
 static int
 mfib_test_entry (fib_node_index_t fei,
                  mfib_entry_flags_t eflags,
-                 u16 n_buckets,
+                 int n_buckets,
                  ...)
 {
     const mfib_entry_t *mfe;
@@ -239,6 +231,7 @@ mfib_test_entry (fib_node_index_t fei,
 
     va_start(ap, n_buckets);
 
+    res = 0;
     mfe = mfib_entry_get(fei);
     mfib_entry_get_prefix(fei, &pfx);
 
@@ -254,7 +247,6 @@ mfib_test_entry (fib_node_index_t fei,
                       "%U links to %U",
                       format_mfib_prefix, &pfx,
                       format_dpo_id, &mfe->mfe_rep, 0);
-        res = !0;
     }
     else
     {
@@ -271,7 +263,7 @@ mfib_test_entry (fib_node_index_t fei,
                       format_mfib_prefix, &pfx,
                       format_dpo_type, tmp.dpoi_type);
 
-        res = mfib_test_validate_rep_v(rep, n_buckets, ap);
+        res = mfib_test_validate_rep_v(rep, n_buckets, &ap);
 
         dpo_reset(&tmp);
     }
@@ -289,7 +281,9 @@ mfib_test_entry_itf (fib_node_index_t fei,
     const mfib_entry_t *mfe;
     const mfib_itf_t *mfi;
     mfib_prefix_t pfx;
+    int res;
 
+    res = 0;
     mfe = mfib_entry_get(fei);
     mfi = mfib_entry_get_itf(mfe, sw_if_index);
     mfib_entry_get_prefix(fei, &pfx);
@@ -304,7 +298,7 @@ mfib_test_entry_itf (fib_node_index_t fei,
                   format_mfib_itf_flags, flags,
                   format_mfib_itf_flags, mfi->mfi_flags);
 
-    return (!0);
+    return (res);
 }
 
 static int
@@ -314,7 +308,9 @@ mfib_test_entry_no_itf (fib_node_index_t fei,
     const mfib_entry_t *mfe;
     const mfib_itf_t *mfi;
     mfib_prefix_t pfx;
+    int res;
 
+    res = 0;
     mfe = mfib_entry_get(fei);
     mfi = mfib_entry_get_itf(mfe, sw_if_index);
     mfib_entry_get_prefix(fei, &pfx);
@@ -323,7 +319,7 @@ mfib_test_entry_no_itf (fib_node_index_t fei,
                   "%U has no interface %d",
                   format_mfib_prefix, &pfx, sw_if_index);
 
-    return (!0);
+    return (res);
 }
 
 static int
@@ -334,19 +330,25 @@ mfib_test_i (fib_protocol_t PROTO,
              const mfib_prefix_t *pfx_star_g_1,
              const mfib_prefix_t *pfx_star_g_2,
              const mfib_prefix_t *pfx_star_g_3,
-             const mfib_prefix_t *pfx_star_g_slash_m)
+             const mfib_prefix_t *pfx_star_g_slash_m,
+             const fib_prefix_t *pfx_itf,
+             const ip46_address_t *addr_nbr1,
+             const ip46_address_t *addr_nbr2)
 {
     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;
-    u32 fib_index, n_entries, n_itfs, n_reps;
-    fib_node_index_t ai_1, ai_2, ai_3;
+    u32 fib_index, n_entries, n_itfs, n_reps, n_pls;
+    fib_node_index_t ai_1, ai_2, ai_3, ai_nbr1, ai_nbr2;
     test_main_t *tm;
+    int res;
 
     mfib_prefix_t all_1s;
     memset(&all_1s, 0xfd, sizeof(all_1s));
 
+    res = 0;
     n_entries = pool_elts(mfib_entry_pool);
     n_itfs = pool_elts(mfib_itf_pool);
     n_reps = pool_elts(replicate_pool);
+    n_pls = fib_path_list_pool_size();
     tm = &test_main;
 
     ai_1 = adj_mcast_add_or_lock(PROTO,
@@ -358,11 +360,32 @@ mfib_test_i (fib_protocol_t PROTO,
     ai_3 = adj_mcast_add_or_lock(PROTO,
                                  LINKT,
                                  tm->hw[3]->sw_if_index);
+    ai_nbr1 = adj_nbr_add_or_lock(PROTO,
+                                  LINKT,
+                                  addr_nbr1,
+                                  tm->hw[0]->sw_if_index);
+    ai_nbr2 = adj_nbr_add_or_lock(PROTO,
+                                  LINKT,
+                                  addr_nbr2,
+                                  tm->hw[0]->sw_if_index);
 
     MFIB_TEST(3 == adj_mcast_db_size(), "3 MCAST adjs");
 
     /* Find or create FIB table 11 */
-    fib_index = mfib_table_find_or_create_and_lock(PROTO, 11);
+    fib_index = mfib_table_find_or_create_and_lock(PROTO, 11, MFIB_SOURCE_API);
+
+    fib_table_entry_update_one_path(0,
+                                    pfx_itf,
+                                   FIB_SOURCE_INTERFACE,
+                                   (FIB_ENTRY_FLAG_CONNECTED |
+                                    FIB_ENTRY_FLAG_ATTACHED),
+                                   DPO_PROTO_IP4,
+                                   NULL,
+                                   tm->hw[0]->sw_if_index,
+                                   ~0, // invalid fib index
+                                   1, // weight
+                                   NULL,
+                                   FIB_ROUTE_PATH_FLAG_NONE);
 
     mfib_prefix_t pfx_dft = {
         .fp_len = 0,
@@ -370,20 +393,20 @@ mfib_test_i (fib_protocol_t PROTO,
     };
     mfei_dflt = mfib_table_lookup_exact_match(fib_index, &pfx_dft);
     MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
-    MFIB_TEST(mfib_test_entry(mfei_dflt,
-                              MFIB_ENTRY_FLAG_DROP,
-                              0),
+    MFIB_TEST(!mfib_test_entry(mfei_dflt,
+                               MFIB_ENTRY_FLAG_DROP,
+                               0),
               "(*,*) no replcaitions");
 
     MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_dflt, "(*,*) presnet");
-    MFIB_TEST(mfib_test_entry(mfei_dflt,
-                              MFIB_ENTRY_FLAG_DROP,
-                              0),
+    MFIB_TEST(!mfib_test_entry(mfei_dflt,
+                               MFIB_ENTRY_FLAG_DROP,
+                               0),
               "(*,*) no replcaitions");
 
 
     fib_route_path_t path_via_if0 = {
-        .frp_proto = PROTO,
+        .frp_proto = fib_proto_to_dpo(PROTO),
         .frp_addr = zero_addr,
         .frp_sw_if_index = tm->hw[0]->sw_if_index,
         .frp_fib_index = ~0,
@@ -398,16 +421,16 @@ mfib_test_i (fib_protocol_t PROTO,
                                  MFIB_ITF_FLAG_ACCEPT);
 
     mfei_no_f = mfib_table_lookup_exact_match(fib_index, pfx_no_forward);
-    MFIB_TEST(mfib_test_entry(mfei_no_f,
-                              MFIB_ENTRY_FLAG_NONE,
-                              0),
+    MFIB_TEST(!mfib_test_entry(mfei_no_f,
+                               MFIB_ENTRY_FLAG_NONE,
+                               0),
               "%U no replcaitions",
               format_mfib_prefix, pfx_no_forward);
-    MFIB_TEST_NS(mfib_test_entry_itf(mfei_no_f, tm->hw[0]->sw_if_index,
-                                     MFIB_ITF_FLAG_ACCEPT));
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei_no_f, tm->hw[0]->sw_if_index,
+                                      MFIB_ITF_FLAG_ACCEPT));
 
     fib_route_path_t path_via_if1 = {
-        .frp_proto = PROTO,
+        .frp_proto = fib_proto_to_dpo(PROTO),
         .frp_addr = zero_addr,
         .frp_sw_if_index = tm->hw[1]->sw_if_index,
         .frp_fib_index = ~0,
@@ -415,7 +438,7 @@ mfib_test_i (fib_protocol_t PROTO,
         .frp_flags = 0,
     };
     fib_route_path_t path_via_if2 = {
-        .frp_proto = PROTO,
+        .frp_proto = fib_proto_to_dpo(PROTO),
         .frp_addr = zero_addr,
         .frp_sw_if_index = tm->hw[2]->sw_if_index,
         .frp_fib_index = ~0,
@@ -423,7 +446,7 @@ mfib_test_i (fib_protocol_t PROTO,
         .frp_flags = 0,
     };
     fib_route_path_t path_via_if3 = {
-        .frp_proto = PROTO,
+        .frp_proto = fib_proto_to_dpo(PROTO),
         .frp_addr = zero_addr,
         .frp_sw_if_index = tm->hw[3]->sw_if_index,
         .frp_fib_index = ~0,
@@ -431,7 +454,7 @@ mfib_test_i (fib_protocol_t PROTO,
         .frp_flags = 0,
     };
     fib_route_path_t path_for_us = {
-        .frp_proto = PROTO,
+        .frp_proto = fib_proto_to_dpo(PROTO),
         .frp_addr = zero_addr,
         .frp_sw_if_index = 0xffffffff,
         .frp_fib_index = ~0,
@@ -469,23 +492,23 @@ mfib_test_i (fib_protocol_t PROTO,
     MFIB_TEST(FIB_NODE_INDEX_INVALID != mfei_s_g,
               "%U present",
               format_mfib_prefix, pfx_s_g);
-    MFIB_TEST(mfib_test_entry(mfei_s_g,
-                              MFIB_ENTRY_FLAG_NONE,
-                              3,
-                              DPO_ADJACENCY_MCAST, ai_1,
-                              DPO_ADJACENCY_MCAST, ai_2,
-                              DPO_ADJACENCY_MCAST, ai_3),
+    MFIB_TEST(!mfib_test_entry(mfei_s_g,
+                               MFIB_ENTRY_FLAG_NONE,
+                               3,
+                               DPO_ADJACENCY_MCAST, ai_1,
+                               DPO_ADJACENCY_MCAST, ai_2,
+                               DPO_ADJACENCY_MCAST, ai_3),
               "%U replicate ok",
               format_mfib_prefix, pfx_s_g);
-    MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[0]->sw_if_index,
-                                     MFIB_ITF_FLAG_ACCEPT));
-    MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[1]->sw_if_index,
-                                     MFIB_ITF_FLAG_FORWARD));
-    MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[2]->sw_if_index,
-                                     MFIB_ITF_FLAG_FORWARD));
-    MFIB_TEST_NS(mfib_test_entry_itf(mfei_s_g, tm->hw[3]->sw_if_index,
-                                     (MFIB_ITF_FLAG_FORWARD |
-                                      MFIB_ITF_FLAG_NEGATE_SIGNAL)));
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[0]->sw_if_index,
+                                      MFIB_ITF_FLAG_ACCEPT));
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[1]->sw_if_index,
+                                      MFIB_ITF_FLAG_FORWARD));
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[2]->sw_if_index,
+                                      MFIB_ITF_FLAG_FORWARD));
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei_s_g, tm->hw[3]->sw_if_index,
+                                      (MFIB_ITF_FLAG_FORWARD |
+                                       MFIB_ITF_FLAG_NEGATE_SIGNAL)));
 
     /*
      * A (*,G), which the same G as the (S,G).
@@ -510,10 +533,10 @@ mfib_test_i (fib_protocol_t PROTO,
     MFIB_TEST(mfei == mfei_g_1,
               "%U found via exact match",
               format_mfib_prefix, pfx_star_g_1);
-    MFIB_TEST(mfib_test_entry(mfei,
-                              MFIB_ENTRY_FLAG_NONE,
-                              1,
-                              DPO_ADJACENCY_MCAST, ai_1),
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_NONE,
+                               1,
+                               DPO_ADJACENCY_MCAST, ai_1),
               "%U replicate ok",
               format_mfib_prefix, pfx_star_g_1);
 
@@ -523,10 +546,10 @@ mfib_test_i (fib_protocol_t PROTO,
               "%U found via LP match",
               format_mfib_prefix, pfx_star_g_1);
 
-    MFIB_TEST(mfib_test_entry(mfei,
-                              MFIB_ENTRY_FLAG_NONE,
-                              1,
-                              DPO_ADJACENCY_MCAST, ai_1),
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_NONE,
+                               1,
+                               DPO_ADJACENCY_MCAST, ai_1),
               "%U replicate ok",
               format_mfib_prefix, pfx_star_g_1);
 
@@ -535,12 +558,12 @@ mfib_test_i (fib_protocol_t PROTO,
               "%U found via exact match",
               format_mfib_prefix, pfx_s_g);
 
-    MFIB_TEST(mfib_test_entry(mfei,
-                              MFIB_ENTRY_FLAG_NONE,
-                              3,
-                              DPO_ADJACENCY_MCAST, ai_1,
-                              DPO_ADJACENCY_MCAST, ai_2,
-                              DPO_ADJACENCY_MCAST, ai_3),
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_NONE,
+                               3,
+                               DPO_ADJACENCY_MCAST, ai_1,
+                               DPO_ADJACENCY_MCAST, ai_2,
+                               DPO_ADJACENCY_MCAST, ai_3),
               "%U replicate OK",
               format_mfib_prefix, pfx_s_g);
     mfei = mfib_table_lookup(fib_index, pfx_s_g);
@@ -548,12 +571,12 @@ mfib_test_i (fib_protocol_t PROTO,
               "%U found via LP match",
               format_mfib_prefix, pfx_s_g);
 
-    MFIB_TEST(mfib_test_entry(mfei,
-                              MFIB_ENTRY_FLAG_NONE,
-                              3,
-                              DPO_ADJACENCY_MCAST, ai_1,
-                              DPO_ADJACENCY_MCAST, ai_2,
-                              DPO_ADJACENCY_MCAST, ai_3),
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_NONE,
+                               3,
+                               DPO_ADJACENCY_MCAST, ai_1,
+                               DPO_ADJACENCY_MCAST, ai_2,
+                               DPO_ADJACENCY_MCAST, ai_3),
               "%U replicate OK",
               format_mfib_prefix, pfx_s_g);
 
@@ -580,40 +603,40 @@ mfib_test_i (fib_protocol_t PROTO,
               "%U found via DP LPM: %d",
               format_mfib_prefix, pfx_star_g_1, mfei);
 
-    MFIB_TEST(mfib_test_entry(mfei,
-                              MFIB_ENTRY_FLAG_NONE,
-                              1,
-                              DPO_ADJACENCY_MCAST, ai_1),
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_NONE,
+                               1,
+                               DPO_ADJACENCY_MCAST, ai_1),
               "%U replicate ok",
               format_mfib_prefix, pfx_star_g_1);
 
     mfei = mfib_table_lookup(fib_index, pfx_star_g_1);
 
-    MFIB_TEST(mfib_test_entry(mfei,
-                              MFIB_ENTRY_FLAG_NONE,
-                              1,
-                              DPO_ADJACENCY_MCAST, ai_1),
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_NONE,
+                               1,
+                               DPO_ADJACENCY_MCAST, ai_1),
               "%U replicate ok",
               format_mfib_prefix, pfx_star_g_1);
 
     mfei = mfib_table_lookup_exact_match(fib_index, pfx_s_g);
 
-    MFIB_TEST(mfib_test_entry(mfei,
-                              MFIB_ENTRY_FLAG_NONE,
-                              3,
-                              DPO_ADJACENCY_MCAST, ai_1,
-                              DPO_ADJACENCY_MCAST, ai_2,
-                              DPO_ADJACENCY_MCAST, ai_3),
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_NONE,
+                               3,
+                               DPO_ADJACENCY_MCAST, ai_1,
+                               DPO_ADJACENCY_MCAST, ai_2,
+                               DPO_ADJACENCY_MCAST, ai_3),
               "%U replicate OK",
               format_mfib_prefix, pfx_s_g);
     mfei = mfib_table_lookup(fib_index, pfx_s_g);
 
-    MFIB_TEST(mfib_test_entry(mfei,
-                              MFIB_ENTRY_FLAG_NONE,
-                              3,
-                              DPO_ADJACENCY_MCAST, ai_1,
-                              DPO_ADJACENCY_MCAST, ai_2,
-                              DPO_ADJACENCY_MCAST, ai_3),
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_NONE,
+                               3,
+                               DPO_ADJACENCY_MCAST, ai_1,
+                               DPO_ADJACENCY_MCAST, ai_2,
+                               DPO_ADJACENCY_MCAST, ai_3),
               "%U replicate OK",
               format_mfib_prefix, pfx_s_g);
 
@@ -621,10 +644,10 @@ mfib_test_i (fib_protocol_t PROTO,
     MFIB_TEST(mfei = mfei_g_m,
               "%U Found via exact match",
               format_mfib_prefix, pfx_star_g_slash_m);
-    MFIB_TEST(mfib_test_entry(mfei,
-                              MFIB_ENTRY_FLAG_NONE,
-                              1,
-                              DPO_ADJACENCY_MCAST, ai_3),
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_NONE,
+                               1,
+                               DPO_ADJACENCY_MCAST, ai_3),
               "%U replicate OK",
               format_mfib_prefix, pfx_star_g_slash_m);
     MFIB_TEST(mfei_g_m == mfib_table_lookup(fib_index, pfx_star_g_slash_m),
@@ -640,13 +663,13 @@ mfib_test_i (fib_protocol_t PROTO,
                                         &path_for_us,
                                         MFIB_ITF_FLAG_FORWARD);
 
-    MFIB_TEST(mfib_test_entry(mfei,
-                              MFIB_ENTRY_FLAG_NONE,
-                              4,
-                              DPO_ADJACENCY_MCAST, ai_1,
-                              DPO_ADJACENCY_MCAST, ai_2,
-                              DPO_ADJACENCY_MCAST, ai_3,
-                              DPO_RECEIVE, 0),
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_NONE,
+                               4,
+                               DPO_ADJACENCY_MCAST, ai_1,
+                               DPO_ADJACENCY_MCAST, ai_2,
+                               DPO_ADJACENCY_MCAST, ai_3,
+                               DPO_RECEIVE, 0),
               "%U replicate OK",
               format_mfib_prefix, pfx_s_g);
 
@@ -658,12 +681,12 @@ mfib_test_i (fib_protocol_t PROTO,
                                  MFIB_SOURCE_API,
                                  &path_for_us);
 
-    MFIB_TEST(mfib_test_entry(mfei,
-                              MFIB_ENTRY_FLAG_NONE,
-                              3,
-                              DPO_ADJACENCY_MCAST, ai_1,
-                              DPO_ADJACENCY_MCAST, ai_2,
-                              DPO_ADJACENCY_MCAST, ai_3),
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_NONE,
+                               3,
+                               DPO_ADJACENCY_MCAST, ai_1,
+                               DPO_ADJACENCY_MCAST, ai_2,
+                               DPO_ADJACENCY_MCAST, ai_3),
               "%U replicate OK",
               format_mfib_prefix, pfx_s_g);
 
@@ -677,21 +700,21 @@ mfib_test_i (fib_protocol_t PROTO,
                                  &path_via_if3,
                                  MFIB_ITF_FLAG_ACCEPT);
 
-    MFIB_TEST(mfib_test_entry(mfei,
-                              MFIB_ENTRY_FLAG_NONE,
-                              2,
-                              DPO_ADJACENCY_MCAST, ai_1,
-                              DPO_ADJACENCY_MCAST, ai_2),
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_NONE,
+                               2,
+                               DPO_ADJACENCY_MCAST, ai_1,
+                               DPO_ADJACENCY_MCAST, ai_2),
               "%U replicate OK",
               format_mfib_prefix, pfx_s_g);
-    MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
-                                     MFIB_ITF_FLAG_ACCEPT));
-    MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
-                                     MFIB_ITF_FLAG_FORWARD));
-    MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
-                                     MFIB_ITF_FLAG_FORWARD));
-    MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
-                                     MFIB_ITF_FLAG_ACCEPT));
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
+                                      MFIB_ITF_FLAG_ACCEPT));
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
+                                      MFIB_ITF_FLAG_FORWARD));
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
+                                      MFIB_ITF_FLAG_FORWARD));
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
+                                      MFIB_ITF_FLAG_ACCEPT));
     /*
      * Make the path forwarding again
      *  - expect it to be added back to the replication set
@@ -707,24 +730,24 @@ mfib_test_i (fib_protocol_t PROTO,
     mfei = mfib_table_lookup_exact_match(fib_index,
                                          pfx_s_g);
 
-    MFIB_TEST(mfib_test_entry(mfei,
-                              MFIB_ENTRY_FLAG_NONE,
-                              3,
-                              DPO_ADJACENCY_MCAST, ai_1,
-                              DPO_ADJACENCY_MCAST, ai_2,
-                              DPO_ADJACENCY_MCAST, ai_3),
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_NONE,
+                               3,
+                               DPO_ADJACENCY_MCAST, ai_1,
+                               DPO_ADJACENCY_MCAST, ai_2,
+                               DPO_ADJACENCY_MCAST, ai_3),
               "%U replicate OK",
               format_mfib_prefix, pfx_s_g);
-    MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
-                                     MFIB_ITF_FLAG_ACCEPT));
-     MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
-                                     MFIB_ITF_FLAG_FORWARD));
-    MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
-                                     MFIB_ITF_FLAG_FORWARD));
-    MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
-                                     (MFIB_ITF_FLAG_FORWARD |
-                                      MFIB_ITF_FLAG_ACCEPT |
-                                      MFIB_ITF_FLAG_NEGATE_SIGNAL)));
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
+                                      MFIB_ITF_FLAG_ACCEPT));
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
+                                      MFIB_ITF_FLAG_FORWARD));
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
+                                      MFIB_ITF_FLAG_FORWARD));
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[3]->sw_if_index,
+                                      (MFIB_ITF_FLAG_FORWARD |
+                                       MFIB_ITF_FLAG_ACCEPT |
+                                       MFIB_ITF_FLAG_NEGATE_SIGNAL)));
 
     /*
      * update flags on the entry
@@ -732,13 +755,14 @@ mfib_test_i (fib_protocol_t PROTO,
     mfib_table_entry_update(fib_index,
                             pfx_s_g,
                             MFIB_SOURCE_API,
+                            MFIB_RPF_ID_NONE,
                             MFIB_ENTRY_FLAG_SIGNAL);
-    MFIB_TEST(mfib_test_entry(mfei,
-                              MFIB_ENTRY_FLAG_SIGNAL,
-                              3,
-                              DPO_ADJACENCY_MCAST, ai_1,
-                              DPO_ADJACENCY_MCAST, ai_2,
-                              DPO_ADJACENCY_MCAST, ai_3),
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_SIGNAL,
+                               3,
+                               DPO_ADJACENCY_MCAST, ai_1,
+                               DPO_ADJACENCY_MCAST, ai_2,
+                               DPO_ADJACENCY_MCAST, ai_3),
               "%U replicate OK",
               format_mfib_prefix, pfx_s_g);
 
@@ -750,37 +774,37 @@ mfib_test_i (fib_protocol_t PROTO,
                                  MFIB_SOURCE_API,
                                  &path_via_if3);
 
-    MFIB_TEST(mfib_test_entry(mfei,
-                              MFIB_ENTRY_FLAG_SIGNAL,
-                              2,
-                              DPO_ADJACENCY_MCAST, ai_1,
-                              DPO_ADJACENCY_MCAST, ai_2),
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_SIGNAL,
+                               2,
+                               DPO_ADJACENCY_MCAST, ai_1,
+                               DPO_ADJACENCY_MCAST, ai_2),
               "%U replicate OK",
               format_mfib_prefix, pfx_s_g);
-    MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
-                                     MFIB_ITF_FLAG_ACCEPT));
-    MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
-                                     MFIB_ITF_FLAG_FORWARD));
-    MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
-                                     MFIB_ITF_FLAG_FORWARD));
-    MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
+                                      MFIB_ITF_FLAG_ACCEPT));
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[1]->sw_if_index,
+                                      MFIB_ITF_FLAG_FORWARD));
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
+                                      MFIB_ITF_FLAG_FORWARD));
+    MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
 
     mfib_table_entry_path_remove(fib_index,
                                  pfx_s_g,
                                  MFIB_SOURCE_API,
                                  &path_via_if1);
 
-    MFIB_TEST(mfib_test_entry(mfei,
-                              MFIB_ENTRY_FLAG_SIGNAL,
-                              1,
-                              DPO_ADJACENCY_MCAST, ai_2),
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_SIGNAL,
+                               1,
+                               DPO_ADJACENCY_MCAST, ai_2),
               "%U replicate OK",
               format_mfib_prefix, pfx_s_g);
-    MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
-                                     MFIB_ITF_FLAG_ACCEPT));
-    MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
-                                     MFIB_ITF_FLAG_FORWARD));
-    MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[0]->sw_if_index,
+                                      MFIB_ITF_FLAG_ACCEPT));
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
+                                      MFIB_ITF_FLAG_FORWARD));
+    MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
 
     /*
      * remove the accpeting only interface
@@ -790,17 +814,17 @@ mfib_test_i (fib_protocol_t PROTO,
                                  MFIB_SOURCE_API,
                                  &path_via_if0);
 
-    MFIB_TEST(mfib_test_entry(mfei,
-                              MFIB_ENTRY_FLAG_SIGNAL,
-                              1,
-                              DPO_ADJACENCY_MCAST, ai_2),
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_SIGNAL,
+                               1,
+                               DPO_ADJACENCY_MCAST, ai_2),
               "%U replicate OK",
               format_mfib_prefix, pfx_s_g);
-    MFIB_TEST_NS(mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
-                                     MFIB_ITF_FLAG_FORWARD));
-    MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[0]->sw_if_index));
-    MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[1]->sw_if_index));
-    MFIB_TEST_NS(mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei, tm->hw[2]->sw_if_index,
+                                      MFIB_ITF_FLAG_FORWARD));
+    MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[0]->sw_if_index));
+    MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[1]->sw_if_index));
+    MFIB_TEST_NS(!mfib_test_entry_no_itf(mfei, tm->hw[3]->sw_if_index));
 
     /*
      * remove the last path, the entry still has flags so it remains
@@ -810,9 +834,9 @@ mfib_test_i (fib_protocol_t PROTO,
                                  MFIB_SOURCE_API,
                                  &path_via_if2);
 
-    MFIB_TEST(mfib_test_entry(mfei,
-                              MFIB_ENTRY_FLAG_SIGNAL,
-                              0),
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_SIGNAL,
+                               0),
               "%U no replications",
               format_mfib_prefix, pfx_s_g);
 
@@ -822,12 +846,13 @@ mfib_test_i (fib_protocol_t PROTO,
     mfib_table_entry_update(fib_index,
                             pfx_s_g,
                             MFIB_SOURCE_API,
+                            MFIB_RPF_ID_NONE,
                             (MFIB_ENTRY_FLAG_SIGNAL |
                              MFIB_ENTRY_FLAG_CONNECTED));
-    MFIB_TEST(mfib_test_entry(mfei,
-                              (MFIB_ENTRY_FLAG_SIGNAL |
-                               MFIB_ENTRY_FLAG_CONNECTED),
-                              0),
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               (MFIB_ENTRY_FLAG_SIGNAL |
+                                MFIB_ENTRY_FLAG_CONNECTED),
+                               0),
               "%U no replications",
               format_mfib_prefix, pfx_s_g);
 
@@ -840,9 +865,9 @@ mfib_test_i (fib_protocol_t PROTO,
                                             &path_via_if0,
                                             (MFIB_ITF_FLAG_ACCEPT |
                                              MFIB_ITF_FLAG_NEGATE_SIGNAL));
-    MFIB_TEST(mfib_test_entry(mfei_g_2,
-                              MFIB_ENTRY_FLAG_NONE,
-                              0),
+    MFIB_TEST(!mfib_test_entry(mfei_g_2,
+                               MFIB_ENTRY_FLAG_NONE,
+                               0),
               "%U No replications",
               format_mfib_prefix, pfx_star_g_2);
 
@@ -868,9 +893,9 @@ mfib_test_i (fib_protocol_t PROTO,
                                             &path_via_if0,
                                             (MFIB_ITF_FLAG_ACCEPT |
                                              MFIB_ITF_NEGATE_SIGNAL));
-    MFIB_TEST(mfib_test_entry(mfei_g_3,
-                              MFIB_ENTRY_FLAG_NONE,
-                              0),
+    MFIB_TEST(!mfib_test_entry(mfei_g_3,
+                               MFIB_ENTRY_FLAG_NONE,
+                               0),
               "%U No replications",
               format_mfib_prefix, pfx_star_g_3);
 
@@ -905,9 +930,9 @@ mfib_test_i (fib_protocol_t PROTO,
          * Find the (*,G/m)
          */
         MFIB_TEST((mfei_g_m == ip6_mfib_table_lookup2(
-                                   ip6_mfib_get(fib_index),
-                                   &src,
-                                   &pfx_star_g_slash_m->fp_grp_addr.ip6)),
+                       ip6_mfib_get(fib_index),
+                       &src,
+                       &pfx_star_g_slash_m->fp_grp_addr.ip6)),
                   "%U found via DP LPM grp=%U",
                   format_mfib_prefix, pfx_star_g_slash_m,
                   format_ip6_address, &pfx_star_g_slash_m->fp_grp_addr.ip6);
@@ -916,9 +941,9 @@ mfib_test_i (fib_protocol_t PROTO,
         tmp.as_u8[15] = 0xff;
 
         MFIB_TEST((mfei_g_m == ip6_mfib_table_lookup2(
-                                   ip6_mfib_get(fib_index),
-                                   &pfx_s_g->fp_src_addr.ip6,
-                                   &tmp)),
+                       ip6_mfib_get(fib_index),
+                       &pfx_s_g->fp_src_addr.ip6,
+                       &tmp)),
                   "%U found via DP LPM grp=%U",
                   format_mfib_prefix, pfx_star_g_slash_m,
                   format_ip6_address, &tmp);
@@ -963,6 +988,7 @@ mfib_test_i (fib_protocol_t PROTO,
     mfib_table_entry_update(fib_index,
                             pfx_s_g,
                             MFIB_SOURCE_API,
+                            MFIB_RPF_ID_NONE,
                             MFIB_ENTRY_FLAG_NONE);
     mfei = mfib_table_lookup_exact_match(fib_index,
                                          pfx_s_g);
@@ -1023,10 +1049,235 @@ mfib_test_i (fib_protocol_t PROTO,
               "%U Gone",
               format_mfib_prefix, pfx_star_g_slash_m);
 
+    /*
+     * Entries with paths via unicast next-hops
+     */
+    fib_route_path_t path_via_nbr1 = {
+        .frp_proto = fib_proto_to_dpo(PROTO),
+        .frp_addr = *addr_nbr1,
+        .frp_sw_if_index = tm->hw[0]->sw_if_index,
+        .frp_fib_index = ~0,
+        .frp_weight = 0,
+        .frp_flags = 0,
+    };
+    fib_route_path_t path_via_nbr2 = {
+        .frp_proto = fib_proto_to_dpo(PROTO),
+        .frp_addr = *addr_nbr2,
+        .frp_sw_if_index = tm->hw[0]->sw_if_index,
+        .frp_fib_index = ~0,
+        .frp_weight = 0,
+        .frp_flags = 0,
+    };
+
+    mfei_g_1 = mfib_table_entry_path_update(fib_index,
+                                            pfx_star_g_1,
+                                            MFIB_SOURCE_API,
+                                            &path_via_nbr1,
+                                            (MFIB_ITF_FLAG_FORWARD));
+    mfei_g_1 = mfib_table_entry_path_update(fib_index,
+                                            pfx_star_g_1,
+                                            MFIB_SOURCE_API,
+                                            &path_via_nbr2,
+                                            (MFIB_ITF_FLAG_FORWARD));
+    MFIB_TEST(!mfib_test_entry(mfei_g_1,
+                               MFIB_ENTRY_FLAG_NONE,
+                               2,
+                               DPO_ADJACENCY_INCOMPLETE, ai_nbr1,
+                               DPO_ADJACENCY_INCOMPLETE, ai_nbr2),
+              "%U replicate OK",
+              format_mfib_prefix, pfx_star_g_1);
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei_g_1, tm->hw[0]->sw_if_index,
+                                      MFIB_ITF_FLAG_FORWARD));
+
+    mfib_table_entry_path_remove(fib_index,
+                                 pfx_star_g_1,
+                                 MFIB_SOURCE_API,
+                                 &path_via_nbr1);
+
+    MFIB_TEST(!mfib_test_entry(mfei_g_1,
+                               MFIB_ENTRY_FLAG_NONE,
+                               1,
+                               DPO_ADJACENCY_INCOMPLETE, ai_nbr2),
+              "%U replicate OK",
+              format_mfib_prefix, pfx_star_g_1);
+    MFIB_TEST_NS(!mfib_test_entry_itf(mfei_g_1, tm->hw[0]->sw_if_index,
+                                      MFIB_ITF_FLAG_FORWARD));
+
+    mfib_table_entry_path_remove(fib_index,
+                                 pfx_star_g_1,
+                                 MFIB_SOURCE_API,
+                                 &path_via_nbr2);
+    mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
+    MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
+              "%U Gone",
+              format_mfib_prefix, pfx_star_g_1);
+
+    /*
+     * Add a prefix as a special/exclusive route
+     */
+    dpo_id_t td = DPO_INVALID;
+    index_t repi = replicate_create(1, fib_proto_to_dpo(PROTO));
+
+    dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_2);
+    replicate_set_bucket(repi, 0, &td);
+
+    mfei = mfib_table_entry_special_add(fib_index,
+                                        pfx_star_g_3,
+                                        MFIB_SOURCE_SRv6,
+                                        MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF,
+                                        repi);
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
+                                MFIB_ENTRY_FLAG_EXCLUSIVE),
+                               1,
+                               DPO_ADJACENCY_MCAST, ai_2),
+              "%U exclusive replicate OK",
+              format_mfib_prefix, pfx_star_g_3);
+
+    /*
+     * update a special/exclusive route
+     */
+    index_t repi2 = replicate_create(1, fib_proto_to_dpo(PROTO));
+
+    dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_1);
+    replicate_set_bucket(repi2, 0, &td);
+
+    mfei = mfib_table_entry_special_add(fib_index,
+                                        pfx_star_g_3,
+                                        MFIB_SOURCE_SRv6,
+                                        MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF,
+                                        repi2);
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF |
+                                MFIB_ENTRY_FLAG_EXCLUSIVE),
+                               1,
+                               DPO_ADJACENCY_MCAST, ai_1),
+              "%U exclusive update replicate OK",
+              format_mfib_prefix, pfx_star_g_3);
+
+    mfib_table_entry_delete(fib_index,
+                            pfx_star_g_3,
+                            MFIB_SOURCE_SRv6);
+    dpo_reset(&td);
+
+    /*
+     * A Multicast LSP. This a mLDP head-end
+     */
+    fib_node_index_t ai_mpls_10_10_10_1, lfei;
+    ip46_address_t nh_10_10_10_1 = {
+       .ip4 = {
+           .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
+       },
+    };
+    ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
+                                             VNET_LINK_MPLS,
+                                             &nh_10_10_10_1,
+                                             tm->hw[0]->sw_if_index);
+
+    fib_prefix_t pfx_3500 = {
+       .fp_len = 21,
+       .fp_proto = FIB_PROTOCOL_MPLS,
+       .fp_label = 3500,
+       .fp_eos = MPLS_EOS,
+       .fp_payload_proto = DPO_PROTO_IP4,
+    };
+    fib_test_rep_bucket_t mc_0 = {
+        .type = FT_REP_LABEL_O_ADJ,
+       .label_o_adj = {
+           .adj = ai_mpls_10_10_10_1,
+           .label = 3300,
+           .eos = MPLS_EOS,
+       },
+    };
+    fib_mpls_label_t *l3300 = NULL, fml3300 = {
+        .fml_value = 3300,
+    };
+    vec_add1(l3300, fml3300);
+
+    /*
+     * MPLS enable an interface so we get the MPLS table created
+     */
+    mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL);
+    mpls_sw_interface_enable_disable(&mpls_main,
+                                     tm->hw[0]->sw_if_index,
+                                     1, 0);
+
+    lfei = fib_table_entry_update_one_path(0, // default MPLS Table
+                                           &pfx_3500,
+                                           FIB_SOURCE_API,
+                                           FIB_ENTRY_FLAG_MULTICAST,
+                                           DPO_PROTO_IP4,
+                                           &nh_10_10_10_1,
+                                           tm->hw[0]->sw_if_index,
+                                           ~0, // invalid fib index
+                                           1,
+                                           l3300,
+                                           FIB_ROUTE_PATH_FLAG_NONE);
+    MFIB_TEST(!fib_test_validate_entry(lfei,
+                                       FIB_FORW_CHAIN_TYPE_MPLS_EOS,
+                                       1,
+                                       &mc_0),
+              "3500 via replicate over 10.10.10.1");
+
+    /*
+     * An (S,G) that resolves via the mLDP head-end
+     */
+    fib_route_path_t path_via_mldp = {
+        .frp_proto = DPO_PROTO_MPLS,
+        .frp_local_label = pfx_3500.fp_label,
+        .frp_eos = MPLS_EOS,
+        .frp_sw_if_index = 0xffffffff,
+        .frp_fib_index = 0,
+        .frp_weight = 1,
+        .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
+    };
+    dpo_id_t mldp_dpo = DPO_INVALID;
+
+    fib_entry_contribute_forwarding(lfei,
+                                    FIB_FORW_CHAIN_TYPE_MPLS_EOS,
+                                    &mldp_dpo);
+
+    mfei = mfib_table_entry_path_update(fib_index,
+                                        pfx_s_g,
+                                        MFIB_SOURCE_API,
+                                        &path_via_mldp,
+                                        MFIB_ITF_FLAG_FORWARD);
+
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_NONE,
+                               1,
+                               DPO_REPLICATE, mldp_dpo.dpoi_index),
+              "%U over-mLDP replicate OK",
+              format_mfib_prefix, pfx_s_g);
+
+    /*
+     * add a for-us path. this tests two types of non-attached paths on one entry
+     */
+    mfei = mfib_table_entry_path_update(fib_index,
+                                        pfx_s_g,
+                                        MFIB_SOURCE_API,
+                                        &path_for_us,
+                                        MFIB_ITF_FLAG_FORWARD);
+    MFIB_TEST(!mfib_test_entry(mfei,
+                               MFIB_ENTRY_FLAG_NONE,
+                               2,
+                               DPO_REPLICATE, mldp_dpo.dpoi_index,
+                               DPO_RECEIVE, 0),
+              "%U mLDP+for-us replicate OK",
+              format_mfib_prefix, pfx_s_g);
+
+    mfib_table_entry_delete(fib_index,
+                            pfx_s_g,
+                            MFIB_SOURCE_API);
+    fib_table_entry_delete(0,
+                           &pfx_3500,
+                           FIB_SOURCE_API);
+    dpo_reset(&mldp_dpo);
+
     /*
      * Unlock the table - it's the last lock so should be gone thereafter
      */
-    mfib_table_unlock(fib_index, PROTO);
+    mfib_table_unlock(fib_index, PROTO, MFIB_SOURCE_API);
 
     MFIB_TEST((FIB_NODE_INDEX_INVALID ==
                mfib_table_find(PROTO, fib_index)),
@@ -1035,11 +1286,28 @@ mfib_test_i (fib_protocol_t PROTO,
     adj_unlock(ai_1);
     adj_unlock(ai_2);
     adj_unlock(ai_3);
+    adj_unlock(ai_nbr1);
+    adj_unlock(ai_nbr2);
+
+    /*
+     * MPLS disable the interface
+     */
+    mpls_sw_interface_enable_disable(&mpls_main,
+                                     tm->hw[0]->sw_if_index,
+                                     0, 0);
+    mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
+
+    /*
+     * remove the connected
+     */
+    fib_table_entry_delete(0, pfx_itf, FIB_SOURCE_INTERFACE);
 
     /*
      * test we've leaked no resources
      */
     MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size());
+    MFIB_TEST(n_pls == fib_path_list_pool_size(), "%d=%d path-lists",
+              n_pls, fib_path_list_pool_size());
     MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates",
               n_reps, pool_elts(replicate_pool));
     MFIB_TEST(n_entries == pool_elts(mfib_entry_pool),
@@ -1049,7 +1317,7 @@ mfib_test_i (fib_protocol_t PROTO,
               " No more Interfaces %d!=%d",
               n_itfs, pool_elts(mfib_itf_pool));
 
-    return (0);
+    return (res);
 }
 
 static int
@@ -1112,7 +1380,19 @@ mfib_test_v4 (void)
             .ip4.as_u32 = 0,
         },
     };
-
+    const fib_prefix_t pfx_itf = {
+        .fp_len = 24,
+        .fp_proto = FIB_PROTOCOL_IP4,
+        .fp_addr = {
+            .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
+        },
+    };
+    const ip46_address_t nbr1 = {
+        .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0b),
+    };
+    const ip46_address_t nbr2 = {
+        .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0c),
+    };
     return (mfib_test_i(FIB_PROTOCOL_IP4,
                         VNET_LINK_IP4,
                         &pfx_224_s_8,
@@ -1120,7 +1400,10 @@ mfib_test_v4 (void)
                         &pfx_239_1_1_1,
                         &pfx_239_1_1_2,
                         &pfx_239_1_1_3,
-                        &pfx_239));
+                        &pfx_239,
+                        &pfx_itf,
+                        &nbr1,
+                        &nbr2));
 }
 
 static int
@@ -1180,6 +1463,22 @@ mfib_test_v6 (void)
             .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000000),
         },
     };
+    const fib_prefix_t pfx_itf = {
+        .fp_len = 64,
+        .fp_proto = FIB_PROTOCOL_IP6,
+        .fp_addr = {
+            .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
+            .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
+        },
+    };
+    const ip46_address_t nbr1 = {
+            .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
+            .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
+    };
+    const ip46_address_t nbr2 = {
+            .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
+            .ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000003),
+    };
 
     return (mfib_test_i(FIB_PROTOCOL_IP6,
                         VNET_LINK_IP6,
@@ -1188,7 +1487,10 @@ mfib_test_v6 (void)
                         &pfx_ff_1,
                         &pfx_ff_2,
                         &pfx_ff_3,
-                        &pfx_ff));
+                        &pfx_ff,
+                        &pfx_itf,
+                        &nbr1,
+                        &nbr2));
 }
 
 static clib_error_t *
@@ -1200,6 +1502,12 @@ mfib_test (vlib_main_t * vm,
 
     res += mfib_test_mk_intf(4);
     res += mfib_test_v4();
+
+    if (res)
+    {
+        return clib_error_return(0, "MFIB Unit Test Failed");
+    }
+
     res += mfib_test_v6();
 
     if (res)
@@ -1214,7 +1522,7 @@ mfib_test (vlib_main_t * vm,
 
 VLIB_CLI_COMMAND (test_fib_command, static) = {
     .path = "test mfib",
-    .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
+    .short_help = "mfib unit tests - DO NOT RUN ON A LIVE SYSTEM",
     .function = mfib_test,
 };