Common form of fib-path reproting in dumps 81/11081/4
authorNeale Ranns <nranns@cisco.com>
Mon, 12 Mar 2018 13:59:36 +0000 (06:59 -0700)
committerNeale Ranns <nranns@cisco.com>
Tue, 13 Mar 2018 16:48:23 +0000 (16:48 +0000)
Change-Id: I8f6fdbbeef2ac7e9fe5d87490ae5cba6e9a0b294
Signed-off-by: Neale Ranns <nranns@cisco.com>
src/vnet.am
src/vnet/bier/bier_api.c
src/vnet/fib/fib_api.c [new file with mode: 0644]
src/vnet/fib/fib_api.h
src/vnet/fib/fib_entry.h
src/vnet/fib/fib_path.c
src/vnet/fib/fib_types.api
src/vnet/ip/ip_api.c
src/vnet/mpls/mpls_api.c
src/vpp-api/vom/route.cpp
test/test_dvr.py

index 9548509..a9d984b 100644 (file)
@@ -1076,6 +1076,7 @@ libvnet_la_SOURCES +=                             \
   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 +=                      \
index 77b2cab..8f168c4 100644 (file)
@@ -307,11 +307,7 @@ send_bier_route_details (const bier_table_t *bt,
     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 @@ send_bier_disp_entry_details (const bier_disp_table_t *bdt,
             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 (file)
index 0000000..a2f7e79
--- /dev/null
@@ -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;
+    }
+}
index d10ba00..c8b782a 100644 (file)
@@ -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 @@ add_del_route_t_handler (u8 is_multipath,
                         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__ */
index 3fde97a..4e88314 100644 (file)
@@ -161,6 +161,7 @@ STATIC_ASSERT (sizeof(fib_source_t) == 1,
     [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) \
index a859390..8cfe86a 100644 (file)
@@ -80,7 +80,7 @@ typedef enum fib_path_type_t_ {
      */
     FIB_PATH_TYPE_INTF_RX,
     /**
-     * interface receive.
+     * Path resolves via a UDP encap object.
      */
     FIB_PATH_TYPE_UDP_ENCAP,
     /**
@@ -2619,6 +2619,14 @@ fib_path_encode (fib_node_index_t path_list_index,
       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;
       }
index fde2c33..89f87c0 100644 (file)
@@ -33,6 +33,10 @@ typeonly define fib_mpls_label
     @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 @@ typeonly define fib_path
   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];
 };
index 726d24c..9cd6257 100644 (file)
@@ -177,33 +177,6 @@ vl_api_ip_neighbor_dump_t_handler (vl_api_ip_neighbor_dump_t * mp)
     }
 }
 
-
-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 @@ send_ip_fib_details (vpe_api_main_t * am,
   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 @@ send_ip6_fib_details (vpe_api_main_t * am,
   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 @@ vl_api_ip6_fib_dump_t_handler (vl_api_ip6_fib_dump_t * mp)
   /* *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 @@ send_ip_mfib_details (vl_api_registration_t * reg,
   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 @@ send_ip6_mfib_details (vpe_api_main_t * am,
   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++;
   }
 
index 169ee40..9f5100a 100644 (file)
@@ -427,12 +427,7 @@ send_mpls_tunnel_entry (u32 mti, void *arg)
   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 @@ send_mpls_fib_details (vpe_api_main_t * am,
   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++;
   }
 
index 780881e..fa6e5d4 100644 (file)
@@ -427,8 +427,14 @@ ip_route::event_handler::handle_populate(const client_db::key_t& key)
         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 @@ ip_route::event_handler::handle_populate(const client_db::key_t& key)
         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);
index e2e9605..d508a8d 100644 (file)
@@ -214,6 +214,23 @@ class TestDVR(VppTestCase):
         self.vapi.sw_interface_set_l2_bridge(self.loop0.sw_if_index,
                                              1, bvi=1, enable=0)
 
+        #
+        # Do a FIB dump to make sure the paths are correctly reported as DVR
+        #
+        routes = self.vapi.ip_fib_dump()
+
+        for r in routes:
+            if (inet_pton(AF_INET, ip_tag_bridged) == r.address):
+                print r
+                self.assertEqual(r.path[0].sw_if_index,
+                                 sub_if_on_pg3.sw_if_index)
+                self.assertEqual(r.path[0].is_dvr, 1)
+            if (inet_pton(AF_INET, ip_non_tag_bridged) == r.address):
+                print r
+                self.assertEqual(r.path[0].sw_if_index,
+                                 self.pg1.sw_if_index)
+                self.assertEqual(r.path[0].is_dvr, 1)
+
         #
         # the explicit route delete is require so it happens before
         # the sbu-interface delete. subinterface delete is required