summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/vnet.am1
-rw-r--r--src/vnet/bier/bier_api.c12
-rw-r--r--src/vnet/fib/fib_api.c268
-rw-r--r--src/vnet/fib/fib_api.h8
-rw-r--r--src/vnet/fib/fib_entry.h1
-rw-r--r--src/vnet/fib/fib_path.c10
-rw-r--r--src/vnet/fib/fib_types.api9
-rw-r--r--src/vnet/ip/ip_api.c109
-rw-r--r--src/vnet/mpls/mpls_api.c13
-rw-r--r--src/vpp-api/vom/route.cpp20
-rw-r--r--test/test_dvr.py17
11 files changed, 338 insertions, 130 deletions
diff --git a/src/vnet.am b/src/vnet.am
index 9548509715d..a9d984b3ce7 100644
--- a/src/vnet.am
+++ b/src/vnet.am
@@ -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 += \
diff --git a/src/vnet/bier/bier_api.c b/src/vnet/bier/bier_api.c
index 77b2cabaa44..8f168c46e29 100644
--- a/src/vnet/bier/bier_api.c
+++ b/src/vnet/bier/bier_api.c
@@ -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
index 00000000000..a2f7e79b03c
--- /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 d10ba00913b..c8b782ab156 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 @@ 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__ */
diff --git a/src/vnet/fib/fib_entry.h b/src/vnet/fib/fib_entry.h
index 3fde97add32..4e88314005e 100644
--- a/src/vnet/fib/fib_entry.h
+++ b/src/vnet/fib/fib_entry.h
@@ -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) \
diff --git a/src/vnet/fib/fib_path.c b/src/vnet/fib/fib_path.c
index a8593905438..8cfe86a7a90 100644
--- a/src/vnet/fib/fib_path.c
+++ b/src/vnet/fib/fib_path.c
@@ -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;
}
diff --git a/src/vnet/fib/fib_types.api b/src/vnet/fib/fib_types.api
index fde2c337190..89f87c0f16f 100644
--- a/src/vnet/fib/fib_types.api
+++ b/src/vnet/fib/fib_types.api
@@ -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];
};
diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c
index 726d24ca5a8..9cd625799b6 100644
--- a/src/vnet/ip/ip_api.c
+++ b/src/vnet/ip/ip_api.c
@@ -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++;
}
diff --git a/src/vnet/mpls/mpls_api.c b/src/vnet/mpls/mpls_api.c
index 169ee406a91..9f5100a7f83 100644
--- a/src/vnet/mpls/mpls_api.c
+++ b/src/vnet/mpls/mpls_api.c
@@ -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++;
}
diff --git a/src/vpp-api/vom/route.cpp b/src/vpp-api/vom/route.cpp
index 780881e5805..fa6e5d43b37 100644
--- a/src/vpp-api/vom/route.cpp
+++ b/src/vpp-api/vom/route.cpp
@@ -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);
diff --git a/test/test_dvr.py b/test/test_dvr.py
index e2e960584a6..d508a8d8b1a 100644
--- a/test/test_dvr.py
+++ b/test/test_dvr.py
@@ -215,6 +215,23 @@ class TestDVR(VppTestCase):
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
# because that object type does not use the object registry