Common form of fib-path reproting in dumps

Change-Id: I8f6fdbbeef2ac7e9fe5d87490ae5cba6e9a0b294
Signed-off-by: Neale Ranns <nranns@cisco.com>
diff --git a/src/vnet.am b/src/vnet.am
index 9548509..a9d984b 100644
--- a/src/vnet.am
+++ b/src/vnet.am
@@ -1076,6 +1076,7 @@
   vnet/fib/fib_path_ext.c			\
   vnet/fib/fib_urpf_list.c			\
   vnet/fib/fib_attached_export.c		\
+  vnet/fib/fib_api.c				\
   vnet/fib/fib_bfd.c
 
 nobase_include_HEADERS +=			\
diff --git a/src/vnet/bier/bier_api.c b/src/vnet/bier/bier_api.c
index 77b2cab..8f168c4 100644
--- a/src/vnet/bier/bier_api.c
+++ b/src/vnet/bier/bier_api.c
@@ -307,11 +307,7 @@
     fp = mp->br_paths;
     vec_foreach (api_rpath, api_rpaths)
     {
-        fp->weight = api_rpath->rpath.frp_weight;
-        fp->preference = api_rpath->rpath.frp_preference;
-        fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
-        fp->n_labels = 0;
-        copy_fib_next_hop (api_rpath, fp);
+        fib_api_path_encode(api_rpath, fp);
         fp++;
     }
 
@@ -672,11 +668,7 @@
             fp = mp->bde_paths;
             vec_foreach (api_rpath, api_rpaths)
             {
-                fp->weight = api_rpath->rpath.frp_weight;
-                fp->preference = api_rpath->rpath.frp_preference;
-                fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
-                fp->n_labels = 0;
-                copy_fib_next_hop (api_rpath, fp);
+                fib_api_path_encode(api_rpath, fp);
                 fp++;
             }
 
diff --git a/src/vnet/fib/fib_api.c b/src/vnet/fib/fib_api.c
new file mode 100644
index 0000000..a2f7e79
--- /dev/null
+++ b/src/vnet/fib/fib_api.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vnet/vnet.h>
+#include <vlibmemory/api.h>
+#include <vnet/fib/fib_api.h>
+#include <vnet/fib/fib_table.h>
+#include <vnet/bier/bier_disp_table.h>
+#include <vnet/dpo/ip_null_dpo.h>
+
+#include <vnet/vnet_msg_enum.h>
+
+#define vl_typedefs		/* define message structures */
+#include <vnet/vnet_all_api_h.h>
+#undef vl_typedefs
+
+#define vl_endianfun		/* define message structures */
+#include <vnet/vnet_all_api_h.h>
+#undef vl_endianfun
+
+/* instantiate all the print functions we know about */
+#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
+#define vl_printfun
+#include <vnet/vnet_all_api_h.h>
+#undef vl_printfun
+
+#include <vlibapi/api_helper_macros.h>
+
+int
+fib_path_api_parse (const vl_api_fib_path_t *in,
+                    fib_route_path_t *out)
+{
+    fib_route_path_flags_t path_flags;
+    mpls_label_t next_hop_via_label;
+    int rv = 0, n_labels;
+    u8 ii;
+
+    path_flags = FIB_ROUTE_PATH_FLAG_NONE;
+    next_hop_via_label = ntohl (in->via_label);
+    memset(out, 0, sizeof(*out));
+    out->frp_sw_if_index = ~0;
+
+    out->frp_proto = in->afi;
+    // .frp_addr = (NULL == next_hop ? zero_addr : *next_hop),
+    out->frp_sw_if_index = ntohl(in->sw_if_index);
+    out->frp_fib_index = ntohl(in->table_id);
+    out->frp_weight = in->weight;
+    out->frp_preference = in->preference;
+
+    /*
+     * the special INVALID label meams we are not recursing via a
+     * label. Exp-null value is never a valid via-label so that
+     * also means it's not a via-label and means clients that set
+     * it to 0 by default get the expected behaviour
+     */
+    if ((MPLS_LABEL_INVALID != next_hop_via_label) &&
+        (0 != next_hop_via_label))
+    {
+        out->frp_proto = DPO_PROTO_MPLS;
+        out->frp_local_label = next_hop_via_label;
+        out->frp_eos = MPLS_NON_EOS;
+    }
+
+    n_labels = in->n_labels;
+    if (n_labels == 0)
+        ;
+    else
+    {
+        vec_validate (out->frp_label_stack, n_labels - 1);
+        for (ii = 0; ii < n_labels; ii++)
+        {
+            out->frp_label_stack[ii].fml_value =
+                ntohl(in->label_stack[ii].label);
+            out->frp_label_stack[ii].fml_ttl =
+                in->label_stack[ii].ttl;
+            out->frp_label_stack[ii].fml_exp =
+                in->label_stack[ii].exp;
+            out->frp_label_stack[ii].fml_mode =
+                (in->label_stack[ii].is_uniform ?
+                 FIB_MPLS_LSP_MODE_UNIFORM :
+                 FIB_MPLS_LSP_MODE_PIPE);
+        }
+    }
+
+    if (in->is_dvr)
+        path_flags |= FIB_ROUTE_PATH_DVR;
+    if (in->is_resolve_host)
+        path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST;
+    if (in->is_resolve_attached)
+        path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED;
+    /* if (in->is_interface_rx) */
+    /*     path_flags |= FIB_ROUTE_PATH_INTF_RX; */
+    /* if (in->is_rpf_id) */
+    /*     path_flags |= FIB_ROUTE_PATH_RPF_ID; */
+    if (in->is_source_lookup)
+        path_flags |= FIB_ROUTE_PATH_SOURCE_LOOKUP;
+
+    if (in->is_udp_encap)
+    {
+        path_flags |= FIB_ROUTE_PATH_UDP_ENCAP;
+        out->frp_udp_encap_id = ntohl(in->next_hop_id);
+    }
+    else
+    {
+        if (DPO_PROTO_IP4 == in->afi)
+        {
+            clib_memcpy (&out->frp_addr.ip4,
+                         in->next_hop,
+                         sizeof (out->frp_addr.ip4));
+        }
+        else if (DPO_PROTO_IP6 == in->afi)
+        {
+            clib_memcpy (&out->frp_addr.ip6,
+                         in->next_hop,
+                         sizeof (out->frp_addr.ip6));
+        }
+
+        if (ip46_address_is_zero(&out->frp_addr))
+        {
+            if (DPO_PROTO_BIER == in->afi)
+            {
+                index_t bdti;
+
+                bdti = bier_disp_table_find(ntohl(in->table_id));
+
+                if (INDEX_INVALID != bdti)
+                {
+                    out->frp_fib_index = bdti;
+                    out->frp_proto = DPO_PROTO_BIER;
+                }
+                else
+                {
+                    rv = VNET_API_ERROR_NO_SUCH_FIB;
+                }
+            }
+            else if (out->frp_sw_if_index == ~0 &&
+                     out->frp_fib_index != ~0)
+            {
+                path_flags |= FIB_ROUTE_PATH_DEAG;
+            }
+        }
+    }
+
+    out->frp_flags = path_flags;
+
+    return (rv);
+}
+
+void
+fib_prefix_to_api (const fib_prefix_t *pfx,
+                   u8 address[16],
+                   u8 *length,
+                   u8 *is_ip6)
+{
+    *length = pfx->fp_len;
+    *is_ip6 = (FIB_PROTOCOL_IP6 == pfx->fp_proto ? 1 : 0);
+
+    if (FIB_PROTOCOL_IP6 == pfx->fp_proto)
+    {
+        memcpy (address, &pfx->fp_addr.ip6, sizeof (pfx->fp_addr.ip6));
+    }
+    else
+    {
+        memcpy (address, &pfx->fp_addr.ip4, sizeof (pfx->fp_addr.ip4));
+    }
+}
+
+static void
+fib_api_path_copy_next_hop (const fib_route_path_encode_t * api_rpath, void *fp_arg)
+{
+  int is_ip4;
+  vl_api_fib_path_t *fp = (vl_api_fib_path_t *) fp_arg;
+
+  if (api_rpath->rpath.frp_proto == DPO_PROTO_IP4)
+    fp->afi = IP46_TYPE_IP4;
+  else if (api_rpath->rpath.frp_proto == DPO_PROTO_IP6)
+    fp->afi = IP46_TYPE_IP6;
+  else
+    {
+      is_ip4 = ip46_address_is_ip4 (&api_rpath->rpath.frp_addr);
+      if (is_ip4)
+	fp->afi = IP46_TYPE_IP4;
+      else
+	fp->afi = IP46_TYPE_IP6;
+    }
+  if (fp->afi == IP46_TYPE_IP4)
+    memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip4,
+	    sizeof (api_rpath->rpath.frp_addr.ip4));
+  else
+    memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip6,
+	    sizeof (api_rpath->rpath.frp_addr.ip6));
+}
+
+void
+fib_api_path_encode (const fib_route_path_encode_t * api_rpath,
+                     vl_api_fib_path_t *out)
+{
+    memset (out, 0, sizeof (*out));
+    switch (api_rpath->dpo.dpoi_type)
+    {
+    case DPO_RECEIVE:
+        out->is_local = true;
+        break;
+    case DPO_DROP:
+        out->is_drop = true;
+        break;
+    case DPO_IP_NULL:
+        switch (api_rpath->dpo.dpoi_index)
+        {
+        case IP_NULL_ACTION_NONE:
+            out->is_drop = true;
+            break;
+        case IP_NULL_ACTION_SEND_ICMP_UNREACH:
+            out->is_unreach = true;
+            break;
+        case IP_NULL_ACTION_SEND_ICMP_PROHIBIT:
+            out->is_prohibit = true;
+            break;
+        default:
+            break;
+        }
+        break;
+    default:
+        break;
+    }
+    out->weight = api_rpath->rpath.frp_weight;
+    out->preference = api_rpath->rpath.frp_preference;
+    out->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
+    out->afi = api_rpath->rpath.frp_proto;
+    fib_api_path_copy_next_hop (api_rpath, out);
+
+    if (~0 == api_rpath->rpath.frp_sw_if_index &&
+        !ip46_address_is_zero(&api_rpath->rpath.frp_addr))
+    {
+        if ((DPO_PROTO_IP6 == api_rpath->rpath.frp_proto) ||
+            (DPO_PROTO_IP6 == api_rpath->rpath.frp_proto))
+        {
+            fib_table_t *fib;
+
+            fib = fib_table_get (api_rpath->rpath.frp_fib_index,
+                                 dpo_proto_to_fib(api_rpath->rpath.frp_proto));
+
+            out->table_id = htonl (fib->ft_table_id);
+        }
+    }
+
+    if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_DVR)
+    {
+        out->is_dvr = 1;
+    }
+    if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_UDP_ENCAP)
+    {
+        out->is_udp_encap = 1;
+        out->next_hop_id = api_rpath->rpath.frp_udp_encap_id;
+    }
+}
diff --git a/src/vnet/fib/fib_api.h b/src/vnet/fib/fib_api.h
index d10ba00..c8b782a 100644
--- a/src/vnet/fib/fib_api.h
+++ b/src/vnet/fib/fib_api.h
@@ -16,6 +16,7 @@
 #ifndef __FIB_API_H__
 #define __FIB_API_H__
 
+#include <vnet/fib/fib_types.h>
 
 int
 add_del_route_check (fib_protocol_t table_proto,
@@ -55,8 +56,9 @@
 			 mpls_label_t next_hop_via_label,
 			 fib_mpls_label_t * next_hop_out_label_stack);
 
-void
-copy_fib_next_hop (fib_route_path_encode_t * api_rpath,
-		   void * fp_arg);
+struct _vl_api_fib_path;
+
+extern void fib_api_path_encode (const fib_route_path_encode_t * api_rpath,
+                                 struct _vl_api_fib_path *out);
 
 #endif /* __FIB_API_H__ */
diff --git a/src/vnet/fib/fib_entry.h b/src/vnet/fib/fib_entry.h
index 3fde97a..4e88314 100644
--- a/src/vnet/fib/fib_entry.h
+++ b/src/vnet/fib/fib_entry.h
@@ -161,6 +161,7 @@
     [FIB_SOURCE_MPLS] = "mpls",           	        \
     [FIB_SOURCE_URPF_EXEMPT] = "urpf-exempt",	        \
     [FIB_SOURCE_DEFAULT_ROUTE] = "default-route",	\
+    [FIB_SOURCE_PLUGIN_HI] = "plugin-hi",               \
 }
 
 #define FOR_EACH_FIB_SOURCE(_item) \
diff --git a/src/vnet/fib/fib_path.c b/src/vnet/fib/fib_path.c
index a859390..8cfe86a 100644
--- a/src/vnet/fib/fib_path.c
+++ b/src/vnet/fib/fib_path.c
@@ -80,7 +80,7 @@
      */
     FIB_PATH_TYPE_INTF_RX,
     /**
-     * interface receive.
+     * Path resolves via a UDP encap object.
      */
     FIB_PATH_TYPE_UDP_ENCAP,
     /**
@@ -2619,6 +2619,14 @@
       case FIB_PATH_TYPE_RECURSIVE:
         api_rpath->rpath.frp_addr = path->recursive.fp_nh.fp_ip;
         break;
+      case FIB_PATH_TYPE_DVR:
+          api_rpath->rpath.frp_sw_if_index = path->dvr.fp_interface;
+          api_rpath->rpath.frp_flags |= FIB_ROUTE_PATH_DVR;
+          break;
+      case FIB_PATH_TYPE_UDP_ENCAP:
+          api_rpath->rpath.frp_udp_encap_id = path->udp_encap.fp_udp_encap_id;
+          api_rpath->rpath.frp_flags |= FIB_ROUTE_PATH_UDP_ENCAP;
+          break;
       default:
         break;
       }
diff --git a/src/vnet/fib/fib_types.api b/src/vnet/fib/fib_types.api
index fde2c33..89f87c0 100644
--- a/src/vnet/fib/fib_types.api
+++ b/src/vnet/fib/fib_types.api
@@ -33,6 +33,10 @@
     @param is_unreach - Drop the packet and rate limit send ICMP unreachable
     @param is_prohibit - Drop the packet and rate limit send ICMP prohibited
     @param is_udp_encap - The path describes a UDP-o-IP encapsulation.
+    @param is_dvr - Does the route resolve via a DVR interface.
+    @param is_source_lookup - The the path is a deaggregate path (i.e. a lookup
+    	   		      in another table) is the lookup on the packet's
+			      source address or destination.
     @param afi - the afi of the next hop, IP46_TYPE_IP4=1, IP46_TYPE_IP6=2
     @param next_hop[16] - the next hop address
     @param next_hop_id - Used when the path resolves via an object
@@ -50,10 +54,15 @@
   u8 is_udp_encap;
   u8 is_unreach;
   u8 is_prohibit;
+  u8 is_resolve_host;
+  u8 is_resolve_attached;
+  u8 is_dvr;
+  u8 is_source_lookup;
   u8 afi;
   u8 next_hop[16];
   u32 next_hop_id;
   u32 rpf_id;
+  u32 via_label;
   u8 n_labels;
   vl_api_fib_mpls_label_t label_stack[16];
 };
diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c
index 726d24c..9cd6257 100644
--- a/src/vnet/ip/ip_api.c
+++ b/src/vnet/ip/ip_api.c
@@ -177,33 +177,6 @@
     }
 }
 
-
-void
-copy_fib_next_hop (fib_route_path_encode_t * api_rpath, void *fp_arg)
-{
-  int is_ip4;
-  vl_api_fib_path_t *fp = (vl_api_fib_path_t *) fp_arg;
-
-  if (api_rpath->rpath.frp_proto == DPO_PROTO_IP4)
-    fp->afi = IP46_TYPE_IP4;
-  else if (api_rpath->rpath.frp_proto == DPO_PROTO_IP6)
-    fp->afi = IP46_TYPE_IP6;
-  else
-    {
-      is_ip4 = ip46_address_is_ip4 (&api_rpath->rpath.frp_addr);
-      if (is_ip4)
-	fp->afi = IP46_TYPE_IP4;
-      else
-	fp->afi = IP46_TYPE_IP6;
-    }
-  if (fp->afi == IP46_TYPE_IP4)
-    memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip4,
-	    sizeof (api_rpath->rpath.frp_addr.ip4));
-  else
-    memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip6,
-	    sizeof (api_rpath->rpath.frp_addr.ip6));
-}
-
 static void
 send_ip_fib_details (vpe_api_main_t * am,
 		     vl_api_registration_t * reg,
@@ -234,38 +207,7 @@
   fp = mp->path;
   vec_foreach (api_rpath, api_rpaths)
   {
-    memset (fp, 0, sizeof (*fp));
-    switch (api_rpath->dpo.dpoi_type)
-      {
-      case DPO_RECEIVE:
-	fp->is_local = true;
-	break;
-      case DPO_DROP:
-	fp->is_drop = true;
-	break;
-      case DPO_IP_NULL:
-	switch (api_rpath->dpo.dpoi_index)
-	  {
-	  case IP_NULL_ACTION_NONE:
-	    fp->is_drop = true;
-	    break;
-	  case IP_NULL_ACTION_SEND_ICMP_UNREACH:
-	    fp->is_unreach = true;
-	    break;
-	  case IP_NULL_ACTION_SEND_ICMP_PROHIBIT:
-	    fp->is_prohibit = true;
-	    break;
-	  default:
-	    break;
-	  }
-	break;
-      default:
-	break;
-      }
-    fp->weight = api_rpath->rpath.frp_weight;
-    fp->preference = api_rpath->rpath.frp_preference;
-    fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
-    copy_fib_next_hop (api_rpath, fp);
+    fib_api_path_encode (api_rpath, fp);
     fp++;
   }
 
@@ -362,38 +304,7 @@
   fp = mp->path;
   vec_foreach (api_rpath, api_rpaths)
   {
-    memset (fp, 0, sizeof (*fp));
-    switch (api_rpath->dpo.dpoi_type)
-      {
-      case DPO_RECEIVE:
-	fp->is_local = true;
-	break;
-      case DPO_DROP:
-	fp->is_drop = true;
-	break;
-      case DPO_IP_NULL:
-	switch (api_rpath->dpo.dpoi_index)
-	  {
-	  case IP_NULL_DPO_ACTION_NUM + IP_NULL_ACTION_NONE:
-	    fp->is_drop = true;
-	    break;
-	  case IP_NULL_DPO_ACTION_NUM + IP_NULL_ACTION_SEND_ICMP_UNREACH:
-	    fp->is_unreach = true;
-	    break;
-	  case IP_NULL_DPO_ACTION_NUM + IP_NULL_ACTION_SEND_ICMP_PROHIBIT:
-	    fp->is_prohibit = true;
-	    break;
-	  default:
-	    break;
-	  }
-	break;
-      default:
-	break;
-      }
-    fp->weight = api_rpath->rpath.frp_weight;
-    fp->preference = api_rpath->rpath.frp_preference;
-    fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
-    copy_fib_next_hop (api_rpath, fp);
+    fib_api_path_encode (api_rpath, fp);
     fp++;
   }
 
@@ -464,6 +375,10 @@
   /* *INDENT-OFF* */
   pool_foreach (fib_table, im6->fibs,
   ({
+    /* don't send link locals */
+    if (fib_table->ft_flags & FIB_TABLE_FLAG_IP6_LL)
+      continue;
+
     api_ip6_fib_table_get_all(reg, mp, fib_table);
   }));
   /* *INDENT-ON* */
@@ -505,11 +420,7 @@
   fp = mp->path;
   vec_foreach (api_rpath, api_rpaths)
   {
-    memset (fp, 0, sizeof (*fp));
-
-    fp->weight = 0;
-    fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
-    copy_fib_next_hop (api_rpath, fp);
+    fib_api_path_encode (api_rpath, fp);
     fp++;
   }
   vec_free (api_rpaths);
@@ -601,11 +512,7 @@
   fp = mp->path;
   vec_foreach (api_rpath, api_rpaths)
   {
-    memset (fp, 0, sizeof (*fp));
-
-    fp->weight = 0;
-    fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
-    copy_fib_next_hop (api_rpath, fp);
+    fib_api_path_encode (api_rpath, fp);
     fp++;
   }
 
diff --git a/src/vnet/mpls/mpls_api.c b/src/vnet/mpls/mpls_api.c
index 169ee40..9f5100a 100644
--- a/src/vnet/mpls/mpls_api.c
+++ b/src/vnet/mpls/mpls_api.c
@@ -427,12 +427,7 @@
   fp = mp->mt_paths;
   vec_foreach (api_rpath, api_rpaths)
   {
-    memset (fp, 0, sizeof (*fp));
-
-    fp->weight = api_rpath->rpath.frp_weight;
-    fp->preference = api_rpath->rpath.frp_preference;
-    fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
-    copy_fib_next_hop (api_rpath, fp);
+    fib_api_path_encode (api_rpath, fp);
     fp++;
   }
 
@@ -491,11 +486,7 @@
   fp = mp->path;
   vec_foreach (api_rpath, api_rpaths)
   {
-    memset (fp, 0, sizeof (*fp));
-    fp->weight = api_rpath->rpath.frp_weight;
-    fp->preference = api_rpath->rpath.frp_preference;
-    fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
-    copy_fib_next_hop (api_rpath, fp);
+    fib_api_path_encode (api_rpath, fp);
     fp++;
   }
 
diff --git a/src/vpp-api/vom/route.cpp b/src/vpp-api/vom/route.cpp
index 780881e..fa6e5d4 100644
--- a/src/vpp-api/vom/route.cpp
+++ b/src/vpp-api/vom/route.cpp
@@ -427,8 +427,14 @@
         boost::asio::ip::address address = from_bytes(0, p.next_hop);
         std::shared_ptr<interface> itf = interface::find(p.sw_if_index);
         if (itf) {
-          path path_v4(address, *itf, p.weight, p.preference);
-          ip_r.add(path_v4);
+          if (p.is_dvr) {
+            path path_v4(*itf, nh_proto_t::IPV4, route::path::flags_t::DVR,
+                         p.weight, p.preference);
+            ip_r.add(path_v4);
+          } else {
+            path path_v4(address, *itf, p.weight, p.preference);
+            ip_r.add(path_v4);
+          }
         } else {
           path path_v4(rd_temp, address, p.weight, p.preference);
           ip_r.add(path_v4);
@@ -474,8 +480,14 @@
         std::shared_ptr<interface> itf = interface::find(p.sw_if_index);
         boost::asio::ip::address address = from_bytes(1, p.next_hop);
         if (itf) {
-          path path_v6(address, *itf, p.weight, p.preference);
-          ip_r.add(path_v6);
+          if (p.is_dvr) {
+            path path_v6(*itf, nh_proto_t::IPV6, route::path::flags_t::DVR,
+                         p.weight, p.preference);
+            ip_r.add(path_v6);
+          } else {
+            path path_v6(address, *itf, p.weight, p.preference);
+            ip_r.add(path_v6);
+          }
         } else {
           path path_v6(rd_temp, address, p.weight, p.preference);
           ip_r.add(path_v6);