summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2018-01-23 08:25:01 +0100
committerGitHub <noreply@github.com>2018-01-23 08:25:01 +0100
commitd6fed381094ba34c04166b08cd16af01f6c263ea (patch)
tree84eef98e9afe3c57dc9dff2e28a117c79511b936
parent5c6580957d18884f12dd8cdab9945b6f6bafd0ce (diff)
parent61408536df768ec97b235b463453b64f4e813369 (diff)
Merge pull request #1618 from donaldsharp/zebra_startup_ordering
zebra route-leaking for static routes
-rw-r--r--babeld/kernel.c1
-rw-r--r--bgpd/bgp_zebra.c2
-rw-r--r--bgpd/rfapi/vnc_zebra.c1
-rw-r--r--eigrpd/eigrp_zebra.c2
-rw-r--r--isisd/isis_zebra.c2
-rw-r--r--lib/if.c12
-rw-r--r--lib/if.h7
-rw-r--r--lib/zclient.c5
-rw-r--r--lib/zclient.h6
-rw-r--r--nhrpd/nhrp_route.c2
-rw-r--r--ospf6d/ospf6_zebra.c3
-rw-r--r--ospfd/ospf_zebra.c4
-rw-r--r--ripd/rip_zebra.c1
-rw-r--r--ripngd/ripng_zebra.c1
-rw-r--r--sharpd/sharp_zebra.c2
-rw-r--r--zebra/connected.c6
-rw-r--r--zebra/kernel_socket.c4
-rw-r--r--zebra/main.c17
-rw-r--r--zebra/rib.h7
-rw-r--r--zebra/rt_netlink.c51
-rw-r--r--zebra/rtread_getmsg.c5
-rw-r--r--zebra/zebra_rib.c26
-rw-r--r--zebra/zebra_rnh.c2
-rw-r--r--zebra/zebra_routemap.c2
-rw-r--r--zebra/zebra_static.c18
-rw-r--r--zebra/zebra_static.h2
-rw-r--r--zebra/zebra_vrf.c14
-rw-r--r--zebra/zebra_vty.c609
-rw-r--r--zebra/zserv.c6
29 files changed, 652 insertions, 168 deletions
diff --git a/babeld/kernel.c b/babeld/kernel.c
index 8c4fc953e7..6b673c487c 100644
--- a/babeld/kernel.c
+++ b/babeld/kernel.c
@@ -166,6 +166,7 @@ zebra_route(int add, int family, const unsigned char *pref, unsigned short plen,
api.type = ZEBRA_ROUTE_BABEL;
api.safi = SAFI_UNICAST;
api.vrf_id = VRF_DEFAULT;
+ api.nh_vrf_id = VRF_DEFAULT;
api.prefix = quagga_prefix;
if(metric >= KERNEL_INFINITY) {
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 30e3c6f31d..de170fdd01 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -1001,6 +1001,7 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
memset(&api, 0, sizeof(api));
memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
api.vrf_id = bgp->vrf_id;
+ api.nh_vrf_id = bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP;
api.safi = safi;
api.prefix = *p;
@@ -1253,6 +1254,7 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi)
memset(&api, 0, sizeof(api));
memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
api.vrf_id = peer->bgp->vrf_id;
+ api.nh_vrf_id = peer->bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP;
api.safi = safi;
api.prefix = *p;
diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c
index e0e58e9559..92d7e6fc76 100644
--- a/bgpd/rfapi/vnc_zebra.c
+++ b/bgpd/rfapi/vnc_zebra.c
@@ -396,6 +396,7 @@ static void vnc_zebra_route_msg(struct prefix *p, unsigned int nhp_count,
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
+ api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_VNC;
api.safi = SAFI_UNICAST;
api.prefix = *p;
diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c
index 00438f2f47..f18d39d575 100644
--- a/eigrpd/eigrp_zebra.c
+++ b/eigrpd/eigrp_zebra.c
@@ -366,6 +366,7 @@ void eigrp_zebra_route_add(struct prefix *p, struct list *successors)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
+ api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_EIGRP;
api.safi = SAFI_UNICAST;
memcpy(&api.prefix, p, sizeof(*p));
@@ -407,6 +408,7 @@ void eigrp_zebra_route_delete(struct prefix *p)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
+ api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_EIGRP;
api.safi = SAFI_UNICAST;
memcpy(&api.prefix, p, sizeof(*p));
diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c
index 573b81591c..0512a18a2a 100644
--- a/isisd/isis_zebra.c
+++ b/isisd/isis_zebra.c
@@ -261,6 +261,7 @@ static void isis_zebra_route_add_route(struct prefix *prefix,
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
+ api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_ISIS;
api.safi = SAFI_UNICAST;
api.prefix = *prefix;
@@ -329,6 +330,7 @@ static void isis_zebra_route_del_route(struct prefix *prefix,
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
+ api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_ISIS;
api.safi = SAFI_UNICAST;
api.prefix = *prefix;
diff --git a/lib/if.c b/lib/if.c
index 8e6a9a6968..fdcd563a5d 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -219,6 +219,18 @@ struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id)
struct vrf *vrf;
struct interface if_tmp;
+ if (vrf_id == VRF_UNKNOWN) {
+ struct interface *ifp;
+
+ RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) {
+ ifp = if_lookup_by_index(ifindex, vrf->vrf_id);
+ if (ifp)
+ return ifp;
+ }
+
+ return NULL;
+ }
+
vrf = vrf_lookup_by_id(vrf_id);
if (!vrf)
return NULL;
diff --git a/lib/if.h b/lib/if.h
index eb8af2041b..79f96a7c45 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -452,6 +452,13 @@ struct nbr_connected {
/* Prototypes. */
extern int if_cmp_name_func(char *, char *);
+/*
+ * Passing in VRF_UNKNOWN is a valid thing to do, unless we
+ * are creating a new interface.
+ *
+ * This is useful for vrf route-leaking. So more than anything
+ * else think before you use VRF_UNKNOWN
+ */
extern void if_update_to_new_vrf(struct interface *, vrf_id_t vrf_id);
extern struct interface *if_create(const char *name, vrf_id_t vrf_id);
extern struct interface *if_lookup_by_index(ifindex_t, vrf_id_t vrf_id);
diff --git a/lib/zclient.c b/lib/zclient.c
index d4a7b45b97..a4bd2bda32 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -942,6 +942,8 @@ int zapi_route_encode(u_char cmd, struct stream *s, struct zapi_route *api)
}
stream_putw(s, api->nexthop_num);
+ if (api->nexthop_num)
+ stream_putw(s, api->nh_vrf_id);
for (i = 0; i < api->nexthop_num; i++) {
api_nh = &api->nexthops[i];
@@ -1091,6 +1093,9 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
return -1;
}
+ if (api->nexthop_num)
+ STREAM_GETW(s, api->nh_vrf_id);
+
for (i = 0; i < api->nexthop_num; i++) {
api_nh = &api->nexthops[i];
diff --git a/lib/zclient.h b/lib/zclient.h
index 00ad692718..c24f2b2a4e 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -281,6 +281,7 @@ struct zapi_route {
u_int32_t mtu;
vrf_id_t vrf_id;
+ vrf_id_t nh_vrf_id;
struct ethaddr rmac;
};
@@ -420,6 +421,11 @@ extern struct interface *zebra_interface_vrf_update_read(struct stream *s,
vrf_id_t *new_vrf_id);
extern void zebra_interface_if_set_value(struct stream *, struct interface *);
extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid);
+
+#if CONFDATE > 20180823
+CPP_NOTICE("zapi_ipv4_route, zapi_ipv6_route, zapi_ipv4_route_ipv6_nexthop as well as the zapi_ipv4 and zapi_ipv6 data structures should be removed now");
+#endif
+
extern int zapi_ipv4_route(u_char, struct zclient *, struct prefix_ipv4 *,
struct zapi_ipv4 *) __attribute__((deprecated));
diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c
index 2612d8e045..2f084f8422 100644
--- a/nhrpd/nhrp_route.c
+++ b/nhrpd/nhrp_route.c
@@ -95,6 +95,8 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix
memset(&api, 0, sizeof(api));
api.type = ZEBRA_ROUTE_NHRP;
api.safi = SAFI_UNICAST;
+ api.vrf_id = VRF_DEFAULT;
+ api.nh_vrf_id = VRF_DEFAULT;
api.prefix = *p;
switch (type) {
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index cc87c499ee..2a419ddfc6 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -337,6 +337,7 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
+ api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_OSPF6;
api.safi = SAFI_UNICAST;
api.prefix = *dest;
@@ -387,6 +388,7 @@ void ospf6_zebra_add_discard(struct ospf6_route *request)
if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
+ api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_OSPF6;
api.safi = SAFI_UNICAST;
api.prefix = *dest;
@@ -420,6 +422,7 @@ void ospf6_zebra_delete_discard(struct ospf6_route *request)
if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
+ api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_OSPF6;
api.safi = SAFI_UNICAST;
api.prefix = *dest;
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 66be29dbb4..58e8a921d5 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -389,6 +389,7 @@ void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p,
memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id;
+ api.nh_vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF;
api.instance = ospf->instance;
api.safi = SAFI_UNICAST;
@@ -466,6 +467,7 @@ void ospf_zebra_delete(struct ospf *ospf, struct prefix_ipv4 *p,
memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id;
+ api.nh_vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF;
api.instance = ospf->instance;
api.safi = SAFI_UNICAST;
@@ -487,6 +489,7 @@ void ospf_zebra_add_discard(struct ospf *ospf, struct prefix_ipv4 *p)
memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id;
+ api.nh_vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF;
api.instance = ospf->instance;
api.safi = SAFI_UNICAST;
@@ -506,6 +509,7 @@ void ospf_zebra_delete_discard(struct ospf *ospf, struct prefix_ipv4 *p)
memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id;
+ api.nh_vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF;
api.instance = ospf->instance;
api.safi = SAFI_UNICAST;
diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c
index 041635e153..52a5d93c4f 100644
--- a/ripd/rip_zebra.c
+++ b/ripd/rip_zebra.c
@@ -48,6 +48,7 @@ static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
+ api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_RIP;
api.safi = SAFI_UNICAST;
diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c
index 18a8d14f09..ea069d877f 100644
--- a/ripngd/ripng_zebra.c
+++ b/ripngd/ripng_zebra.c
@@ -48,6 +48,7 @@ static void ripng_zebra_ipv6_send(struct route_node *rp, u_char cmd)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
+ api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_RIPNG;
api.safi = SAFI_UNICAST;
api.prefix = rp->p;
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index 4a5ae13c43..25bb512a8b 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -159,6 +159,7 @@ void route_add(struct prefix *p, struct nexthop *nh)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
+ api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_SHARP;
api.safi = SAFI_UNICAST;
memcpy(&api.prefix, p, sizeof(*p));
@@ -180,6 +181,7 @@ void route_delete(struct prefix *p)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
+ api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_SHARP;
api.safi = SAFI_UNICAST;
memcpy(&api.prefix, p, sizeof(*p));
diff --git a/zebra/connected.c b/zebra/connected.c
index 7b949c5041..d34fd9021a 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -238,10 +238,12 @@ void connected_up(struct interface *ifp, struct connected *ifc)
break;
}
- rib_add(afi, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
+ rib_add(afi, SAFI_UNICAST, ifp->vrf_id, ifp->vrf_id,
+ ZEBRA_ROUTE_CONNECT, 0, 0,
&p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
- rib_add(afi, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
+ rib_add(afi, SAFI_MULTICAST, ifp->vrf_id, ifp->vrf_id,
+ ZEBRA_ROUTE_CONNECT, 0, 0,
&p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index 9fd7bb1c24..ba028ed09c 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -1048,7 +1048,7 @@ void rtm_read(struct rt_msghdr *rtm)
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|| rtm->rtm_type == RTM_CHANGE)
- rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
+ rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, VRF_DEFAULT,
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
&nh, 0, 0, 0, 0, 0);
else
@@ -1096,7 +1096,7 @@ void rtm_read(struct rt_msghdr *rtm)
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|| rtm->rtm_type == RTM_CHANGE)
- rib_add(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
+ rib_add(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, VRF_DEFAULT,
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
&nh, 0, 0, 0, 0, 0);
else
diff --git a/zebra/main.c b/zebra/main.c
index e26c8e3d69..19b16936d9 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -300,6 +300,13 @@ int main(int argc, char **argv)
zebra_if_init();
zebra_debug_init();
router_id_cmd_init();
+
+ /*
+ * Initialize NS( and implicitly the VRF module), and make kernel
+ * routing socket. */
+ zebra_ns_init();
+
+ zebra_vty_init();
access_list_init();
prefix_list_init();
#if defined(HAVE_RTADV)
@@ -317,16 +324,6 @@ int main(int argc, char **argv)
/* For debug purpose. */
/* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */
- /* Initialize NS( and implicitly the VRF module), and make kernel
- * routing socket. */
- zebra_ns_init();
-
- /*
- * Initialize show/config command after the vrf initialization is
- * complete
- */
- zebra_vty_init();
-
#if defined(HANDLE_ZAPI_FUZZING)
if (fuzzing) {
zserv_read_file(fuzzing);
diff --git a/zebra/rib.h b/zebra/rib.h
index c7e83480ca..664afd01b8 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -59,6 +59,7 @@ struct route_entry {
/* VRF identifier. */
vrf_id_t vrf_id;
+ vrf_id_t nh_vrf_id;
/* Which routing table */
uint32_t table;
@@ -293,8 +294,8 @@ extern void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re);
/* NOTE:
* All rib_add function will not just add prefix into RIB, but
* also implicitly withdraw equal prefix of same type. */
-extern int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
- u_short instance, int flags, struct prefix *p,
+extern int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, vrf_id_t nh_vrf_id,
+ int type, u_short instance, int flags, struct prefix *p,
struct prefix_ipv6 *src_p, const struct nexthop *nh,
u_int32_t table_id, u_int32_t metric, u_int32_t mtu,
uint8_t distance, route_tag_t tag);
@@ -439,6 +440,8 @@ DECLARE_HOOK(rib_update, (struct route_node * rn, const char *reason),
extern void zebra_vty_init(void);
+extern int static_config(struct vty *vty, struct zebra_vrf *zvrf,
+ afi_t afi, safi_t safi, const char *cmd);
extern pid_t pid;
#endif /*_ZEBRA_RIB_H */
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 2dc3771b25..0221162a30 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -403,6 +403,9 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
afi = AFI_IP6;
if (h->nlmsg_type == RTM_NEWROUTE) {
+ struct interface *ifp;
+ vrf_id_t nh_vrf_id = vrf_id;
+
if (!tb[RTA_MULTIPATH]) {
struct nexthop nh;
size_t sz = (afi == AFI_IP) ? 4 : 16;
@@ -434,7 +437,14 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
if (gate)
memcpy(&nh.gate, gate, sz);
- rib_add(afi, SAFI_UNICAST, vrf_id, proto,
+ if (index) {
+ ifp = if_lookup_by_index(index,
+ VRF_UNKNOWN);
+ if (ifp)
+ nh_vrf_id = ifp->vrf_id;
+ }
+
+ rib_add(afi, SAFI_UNICAST, vrf_id, nh_vrf_id, proto,
0, flags, &p, NULL, &nh, table, metric,
mtu, distance, tag);
} else {
@@ -453,6 +463,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
re->metric = metric;
re->mtu = mtu;
re->vrf_id = vrf_id;
+ re->nh_vrf_id = vrf_id;
re->table = table;
re->nexthop_num = 0;
re->uptime = time(NULL);
@@ -464,6 +475,18 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
break;
index = rtnh->rtnh_ifindex;
+ if (index) {
+ /*
+ * Yes we are looking this up
+ * for every nexthop and just
+ * using the last one looked
+ * up right now
+ */
+ ifp = if_lookup_by_index(index,
+ VRF_UNKNOWN);
+ if (ifp)
+ re->nh_vrf_id = ifp->vrf_id;
+ }
gate = 0;
if (rtnh->rtnh_len > sizeof(*rtnh)) {
memset(tb, 0, sizeof(tb));
@@ -940,10 +963,17 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
routedesc, inet6_ntoa(nexthop->gate.ipv6),
label_buf, nexthop->ifindex);
}
- if (nexthop->type == NEXTHOP_TYPE_IFINDEX
- || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
+
+ /*
+ * We have the ifindex so we should always send it
+ * This is especially useful if we are doing route
+ * leaking.
+ */
+ if (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)
addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
+ if (nexthop->type == NEXTHOP_TYPE_IFINDEX
+ || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
if (cmd == RTM_NEWROUTE) {
if (nexthop->rmap_src.ipv4.s_addr)
addattr_l(nlmsg, req_size, RTA_PREFSRC,
@@ -961,8 +991,6 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
}
if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
- addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
-
if (cmd == RTM_NEWROUTE) {
if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
addattr_l(nlmsg, req_size, RTA_PREFSRC,
@@ -1141,11 +1169,18 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
routedesc, inet6_ntoa(nexthop->gate.ipv6),
label_buf, nexthop->ifindex);
}
+
+ /*
+ * We have figured out the ifindex so we should always send it
+ * This is especially useful if we are doing route
+ * leaking.
+ */
+ if (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)
+ rtnh->rtnh_ifindex = nexthop->ifindex;
+
/* ifindex */
if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
|| nexthop->type == NEXTHOP_TYPE_IFINDEX) {
- rtnh->rtnh_ifindex = nexthop->ifindex;
-
if (nexthop->rmap_src.ipv4.s_addr)
*src = &nexthop->rmap_src;
else if (nexthop->src.ipv4.s_addr)
@@ -1157,8 +1192,6 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
"nexthop via if %u",
routedesc, nexthop->ifindex);
} else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
- rtnh->rtnh_ifindex = nexthop->ifindex;
-
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
"netlink_route_multipath() (%s): "
diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c
index 69e45f9a6c..ba45f54ad2 100644
--- a/zebra/rtread_getmsg.c
+++ b/zebra/rtread_getmsg.c
@@ -97,8 +97,9 @@ static void handle_route_entry(mib2_ipRouteEntry_t *routeEntry)
nh.type = NEXTHOP_TYPE_IPV4;
nh.gate.ipv4.s_addr = routeEntry->ipRouteNextHop;
- rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0,
- zebra_flags, &prefix, NULL, &nh, 0, 0, 0, 0, 0);
+ rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, VRF_DEFAULT,
+ ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &prefix, NULL,
+ &nh, 0, 0, 0, 0, 0);
}
void route_read(struct zebra_ns *zns)
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index f7f05ba68a..78077a4b3d 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -256,7 +256,7 @@ struct nexthop *route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re,
if (src)
nexthop->src.ipv4 = *src;
nexthop->ifindex = ifindex;
- ifp = if_lookup_by_index(nexthop->ifindex, re->vrf_id);
+ ifp = if_lookup_by_index(nexthop->ifindex, re->nh_vrf_id);
/*Pending: need to think if null ifp here is ok during bootup?
There was a crash because ifp here was coming to be NULL */
if (ifp)
@@ -403,7 +403,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
if (set) {
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
- zebra_deregister_rnh_static_nexthops(re->vrf_id,
+ zebra_deregister_rnh_static_nexthops(re->nh_vrf_id,
nexthop->resolved, top);
nexthops_free(nexthop->resolved);
nexthop->resolved = NULL;
@@ -422,7 +422,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
* address in the routing table.
*/
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) {
- ifp = if_lookup_by_index(nexthop->ifindex, re->vrf_id);
+ ifp = if_lookup_by_index(nexthop->ifindex, re->nh_vrf_id);
if (ifp && connected_is_unnumbered(ifp)) {
if (if_is_operative(ifp))
return 1;
@@ -450,7 +450,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
break;
}
/* Lookup table. */
- table = zebra_vrf_table(afi, SAFI_UNICAST, re->vrf_id);
+ table = zebra_vrf_table(afi, SAFI_UNICAST, re->nh_vrf_id);
if (!table)
return 0;
@@ -838,7 +838,7 @@ static unsigned nexthop_active_check(struct route_node *rn,
family = 0;
switch (nexthop->type) {
case NEXTHOP_TYPE_IFINDEX:
- ifp = if_lookup_by_index(nexthop->ifindex, re->vrf_id);
+ ifp = if_lookup_by_index(nexthop->ifindex, re->nh_vrf_id);
if (ifp && if_is_operative(ifp))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
else
@@ -866,7 +866,8 @@ static unsigned nexthop_active_check(struct route_node *rn,
if (rn->p.family != AF_INET)
family = AFI_IP6;
if (IN6_IS_ADDR_LINKLOCAL(&nexthop->gate.ipv6)) {
- ifp = if_lookup_by_index(nexthop->ifindex, re->vrf_id);
+ ifp = if_lookup_by_index(nexthop->ifindex,
+ re->nh_vrf_id);
if (ifp && if_is_operative(ifp))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
else
@@ -909,7 +910,7 @@ static unsigned nexthop_active_check(struct route_node *rn,
memset(&nexthop->rmap_src.ipv6, 0, sizeof(union g_addr));
/* It'll get set if required inside */
- ret = zebra_route_map_check(family, re->type, p, nexthop, re->vrf_id,
+ ret = zebra_route_map_check(family, re->type, p, nexthop, re->nh_vrf_id,
re->tag);
if (ret == RMAP_DENYMATCH) {
if (IS_ZEBRA_DEBUG_RIB) {
@@ -917,7 +918,8 @@ static unsigned nexthop_active_check(struct route_node *rn,
zlog_debug(
"%u:%s: Filtering out with NH out %s due to route map",
re->vrf_id, buf,
- ifindex2ifname(nexthop->ifindex, re->vrf_id));
+ ifindex2ifname(nexthop->ifindex,
+ re->nh_vrf_id));
}
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
}
@@ -2502,9 +2504,10 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
}
-int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
- int flags, struct prefix *p, struct prefix_ipv6 *src_p,
- const struct nexthop *nh, u_int32_t table_id, u_int32_t metric,
+int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, vrf_id_t nh_vrf_id,
+ int type, u_short instance, int flags, struct prefix *p,
+ struct prefix_ipv6 *src_p, const struct nexthop *nh,
+ u_int32_t table_id, u_int32_t metric,
u_int32_t mtu, uint8_t distance, route_tag_t tag)
{
struct route_entry *re;
@@ -2520,6 +2523,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
re->mtu = mtu;
re->table = table_id;
re->vrf_id = vrf_id;
+ re->nh_vrf_id = nh_vrf_id;
re->nexthop_num = 0;
re->uptime = time(NULL);
re->tag = tag;
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index 825dea21bb..8983bdee09 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -951,6 +951,8 @@ static void copy_state(struct rnh *rnh, struct route_entry *re,
state->type = re->type;
state->distance = re->distance;
state->metric = re->metric;
+ state->vrf_id = re->vrf_id;
+ state->nh_vrf_id = re->vrf_id;
route_entry_copy_nexthops(state, re->nexthop);
rnh->state = state;
diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c
index 61af60b5da..89cb2fc488 100644
--- a/zebra/zebra_routemap.c
+++ b/zebra/zebra_routemap.c
@@ -1329,7 +1329,7 @@ route_map_result_t zebra_nht_route_map_check(int family, int client_proto,
struct nh_rmap_obj nh_obj;
nh_obj.nexthop = nexthop;
- nh_obj.vrf_id = re->vrf_id;
+ nh_obj.vrf_id = re->nh_vrf_id;
nh_obj.source_protocol = re->type;
nh_obj.metric = re->metric;
nh_obj.tag = re->tag;
diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c
index 3dd5378f22..2e8ab11b04 100644
--- a/zebra/zebra_static.c
+++ b/zebra/zebra_static.c
@@ -91,7 +91,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
nh_p.family = AF_INET;
nh_p.prefixlen = IPV4_MAX_BITLEN;
nh_p.u.prefix4 = si->addr.ipv4;
- zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
+ zebra_register_rnh_static_nh(si->nh_vrf_id, &nh_p, rn);
break;
case STATIC_IPV4_GATEWAY_IFNAME:
nexthop = route_entry_nexthop_ipv4_ifindex_add(
@@ -111,7 +111,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
nh_p.family = AF_INET6;
nh_p.prefixlen = IPV6_MAX_BITLEN;
nh_p.u.prefix6 = si->addr.ipv6;
- zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
+ zebra_register_rnh_static_nh(si->nh_vrf_id, &nh_p, rn);
break;
case STATIC_IPV6_GATEWAY_IFNAME:
nexthop = route_entry_nexthop_ipv6_ifindex_add(
@@ -141,7 +141,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
*/
if (si->type == STATIC_IPV4_GATEWAY
|| si->type == STATIC_IPV6_GATEWAY)
- zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1,
+ zebra_evaluate_rnh(si->nh_vrf_id, nh_p.family, 1,
RNH_NEXTHOP_TYPE, &nh_p);
else
rib_queue_add(rn);
@@ -155,6 +155,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
re->metric = 0;
re->mtu = 0;
re->vrf_id = si->vrf_id;
+ re->nh_vrf_id = si->nh_vrf_id;
re->table =
(si->vrf_id != VRF_DEFAULT)
? (zebra_vrf_lookup_by_id(si->vrf_id))->table_id
@@ -169,7 +170,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
nh_p.family = AF_INET;
nh_p.prefixlen = IPV4_MAX_BITLEN;
nh_p.u.prefix4 = si->addr.ipv4;
- zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
+ zebra_register_rnh_static_nh(si->nh_vrf_id, &nh_p, rn);
break;
case STATIC_IPV4_GATEWAY_IFNAME:
nexthop = route_entry_nexthop_ipv4_ifindex_add(
@@ -189,7 +190,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
nh_p.family = AF_INET6;
nh_p.prefixlen = IPV6_MAX_BITLEN;
nh_p.u.prefix6 = si->addr.ipv6;
- zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
+ zebra_register_rnh_static_nh(si->nh_vrf_id, &nh_p, rn);
break;
case STATIC_IPV6_GATEWAY_IFNAME:
nexthop = route_entry_nexthop_ipv6_ifindex_add(
@@ -221,7 +222,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
if (si->type == STATIC_IPV4_GATEWAY
|| si->type == STATIC_IPV6_GATEWAY) {
rib_addnode(rn, re, 0);
- zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1,
+ zebra_evaluate_rnh(si->nh_vrf_id, nh_p.family, 1,
RNH_NEXTHOP_TYPE, &nh_p);
} else
rib_addnode(rn, re, 1);
@@ -378,6 +379,7 @@ int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
struct prefix_ipv6 *src_p, union g_addr *gate,
const char *ifname, enum static_blackhole_type bh_type,
route_tag_t tag, u_char distance, struct zebra_vrf *zvrf,
+ struct zebra_vrf *nh_zvrf,
struct static_nh_label *snh_label)
{
struct route_node *rn;
@@ -439,6 +441,8 @@ int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
si->bh_type = bh_type;
si->tag = tag;
si->vrf_id = zvrf_id(zvrf);
+ si->nh_vrf_id = zvrf_id(nh_zvrf);
+
if (ifname)
strlcpy(si->ifname, ifname, sizeof(si->ifname));
si->ifindex = IFINDEX_INTERNAL;
@@ -493,7 +497,7 @@ int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
else {
struct interface *ifp;
- ifp = if_lookup_by_name(ifname, zvrf_id(zvrf));
+ ifp = if_lookup_by_name(ifname, zvrf_id(nh_zvrf));
if (ifp && ifp->ifindex != IFINDEX_INTERNAL) {
si->ifindex = ifp->ifindex;
static_install_route(afi, safi, p, src_p, si);
diff --git a/zebra/zebra_static.h b/zebra/zebra_static.h
index 68fe73b0a3..234e3e4036 100644
--- a/zebra/zebra_static.h
+++ b/zebra/zebra_static.h
@@ -54,6 +54,7 @@ struct static_route {
/* VRF identifier. */
vrf_id_t vrf_id;
+ vrf_id_t nh_vrf_id;
/* Administrative distance. */
u_char distance;
@@ -89,6 +90,7 @@ extern int static_add_route(afi_t, safi_t safi, u_char type, struct prefix *p,
const char *ifname,
enum static_blackhole_type bh_type, route_tag_t tag,
u_char distance, struct zebra_vrf *zvrf,
+ struct zebra_vrf *nh_zvrf,
struct static_nh_label *snh_label);
extern int static_delete_route(afi_t, safi_t safi, u_char type,
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index 1ae9eac61f..95426683a8 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -476,12 +476,18 @@ static int vrf_config_write(struct vty *vty)
if (!zvrf)
continue;
- if (strcmp(zvrf_name(zvrf), VRF_DEFAULT_NAME)) {
+ if (vrf->vrf_id != VRF_DEFAULT)
vty_out(vty, "vrf %s\n", zvrf_name(zvrf));
- if (zvrf->l3vni)
- vty_out(vty, " vni %u\n", zvrf->l3vni);
+
+ static_config(vty, zvrf, AFI_IP, SAFI_UNICAST, "ip route");
+ static_config(vty, zvrf, AFI_IP, SAFI_MULTICAST, "ip mroute");
+ static_config(vty, zvrf, AFI_IP6, SAFI_UNICAST, "ipv6 route");
+
+ if (vrf->vrf_id != VRF_DEFAULT && zvrf->l3vni)
+ vty_out(vty, " vni %u\n", zvrf->l3vni);
+
+ if (vrf->vrf_id != VRF_DEFAULT)
vty_out(vty, "!\n");
- }
}
return 0;
}
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index df461ab10c..92e1076b2e 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -78,13 +78,16 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty,
#define CMD_VNI_RANGE "(1-16777215)"
/* General function for static route. */
-static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
- const char *negate, const char *dest_str,
- const char *mask_str, const char *src_str,
- const char *gate_str, const char *ifname,
- const char *flag_str, const char *tag_str,
- const char *distance_str, const char *vrf_id_str,
- const char *label_str)
+static int zebra_static_route_leak(struct vty *vty,
+ struct zebra_vrf *zvrf,
+ struct zebra_vrf *nh_zvrf,
+ afi_t afi, safi_t safi,
+ const char *negate, const char *dest_str,
+ const char *mask_str, const char *src_str,
+ const char *gate_str, const char *ifname,
+ const char *flag_str, const char *tag_str,
+ const char *distance_str,
+ const char *label_str)
{
int ret;
u_char distance;
@@ -95,7 +98,6 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
struct in_addr mask;
enum static_blackhole_type bh_type = 0;
route_tag_t tag = 0;
- struct zebra_vrf *zvrf;
u_char type;
struct static_nh_label snh_label;
@@ -145,14 +147,6 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
if (tag_str)
tag = strtoul(tag_str, NULL, 10);
- /* VRF id */
- zvrf = zebra_vrf_lookup_by_name(vrf_id_str);
-
- if (!zvrf) {
- vty_out(vty, "%% vrf %s is not defined\n", vrf_id_str);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
/* Labels */
memset(&snh_label, 0, sizeof(struct static_nh_label));
if (label_str) {
@@ -239,7 +233,8 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
if (!negate)
static_add_route(afi, safi, type, &p, src_p, gatep, ifname,
- bh_type, tag, distance, zvrf, &snh_label);
+ bh_type, tag, distance, zvrf, nh_zvrf,
+ &snh_label);
else
static_delete_route(afi, safi, type, &p, src_p, gatep, ifname,
tag, distance, zvrf, &snh_label);
@@ -247,6 +242,31 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
return CMD_SUCCESS;
}
+static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
+ const char *negate, const char *dest_str,
+ const char *mask_str, const char *src_str,
+ const char *gate_str, const char *ifname,
+ const char *flag_str, const char *tag_str,
+ const char *distance_str, const char *vrf_id_str,
+ const char *label_str)
+{
+ struct zebra_vrf *zvrf;
+
+ /* VRF id */
+ zvrf = zebra_vrf_lookup_by_name(vrf_id_str);
+
+ if (!zvrf) {
+ vty_out(vty, "%% vrf %s is not defined\n", vrf_id_str);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return zebra_static_route_leak(vty, zvrf, zvrf, afi, safi,
+ negate, dest_str, mask_str, src_str,
+ gate_str, ifname, flag_str, tag_str,
+ distance_str, label_str);
+}
+
+
/* Static unicast routes for multicast RPF lookup. */
DEFPY (ip_mroute_dist,
ip_mroute_dist_cmd,
@@ -387,6 +407,37 @@ DEFPY(ip_route_blackhole,
tag_str, distance_str, vrf, label);
}
+DEFPY(ip_route_blackhole_vrf,
+ ip_route_blackhole_vrf_cmd,
+ "[no] ip route\
+ <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
+ <reject|blackhole>$flag \
+ [{ \
+ tag (1-4294967295) \
+ |(1-255)$distance \
+ |label WORD \
+ }]",
+ NO_STR IP_STR
+ "Establish static routes\n"
+ "IP destination prefix (e.g. 10.0.0.0/8)\n"
+ "IP destination prefix\n"
+ "IP destination prefix mask\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n"
+ "Set tag for this route\n"
+ "Tag value\n"
+ "Distance value for this route\n"
+ MPLS_LABEL_HELPSTR)
+{
+ VTY_DECLVAR_CONTEXT(vrf, vrf);
+ struct zebra_vrf *zvrf = vrf->info;
+
+ return zebra_static_route_leak(vty, zvrf, zvrf,
+ AFI_IP, SAFI_UNICAST, no, prefix,
+ mask_str, NULL, NULL, NULL, flag,
+ tag_str, distance_str, label);
+}
+
DEFPY(ip_route_address_interface,
ip_route_address_interface_cmd,
"[no] ip route\
@@ -398,6 +449,7 @@ DEFPY(ip_route_address_interface,
|(1-255)$distance \
|vrf NAME \
|label WORD \
+ |nexthop-vrf NAME \
}]",
NO_STR IP_STR
"Establish static routes\n"
@@ -411,16 +463,85 @@ DEFPY(ip_route_address_interface,
"Tag value\n"
"Distance value for this route\n"
VRF_CMD_HELP_STR
- MPLS_LABEL_HELPSTR)
+ MPLS_LABEL_HELPSTR
+ VRF_CMD_HELP_STR)
{
+ struct zebra_vrf *zvrf;
+ struct zebra_vrf *nh_zvrf;
+
const char *flag = NULL;
if (ifname && !strncasecmp(ifname, "Null0", 5)) {
flag = "Null0";
ifname = NULL;
}
- return zebra_static_route(vty, AFI_IP, SAFI_UNICAST, no, prefix,
- mask_str, NULL, gate_str, ifname, flag,
- tag_str, distance_str, vrf, label);
+
+ nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ nexthop_vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ zvrf = zebra_vrf_lookup_by_name(vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return zebra_static_route_leak(vty, zvrf, nh_zvrf,
+ AFI_IP, SAFI_UNICAST, no, prefix,
+ mask_str, NULL, gate_str, ifname, flag,
+ tag_str, distance_str, label);
+}
+
+DEFPY(ip_route_address_interface_vrf,
+ ip_route_address_interface_vrf_cmd,
+ "[no] ip route\
+ <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
+ A.B.C.D$gate \
+ INTERFACE$ifname \
+ [{ \
+ tag (1-4294967295) \
+ |(1-255)$distance \
+ |label WORD \
+ |nexthop-vrf NAME \
+ }]",
+ NO_STR IP_STR
+ "Establish static routes\n"
+ "IP destination prefix (e.g. 10.0.0.0/8)\n"
+ "IP destination prefix\n"
+ "IP destination prefix mask\n"
+ "IP gateway address\n"
+ "IP gateway interface name. Specify 'Null0' (case-insensitive) for a \
+ null route.\n"
+ "Set tag for this route\n"
+ "Tag value\n"
+ "Distance value for this route\n"
+ MPLS_LABEL_HELPSTR
+ VRF_CMD_HELP_STR)
+{
+ VTY_DECLVAR_CONTEXT(vrf, vrf);
+ const char *flag = NULL;
+ struct zebra_vrf *zvrf = vrf->info;
+ struct zebra_vrf *nh_zvrf;
+
+ if (ifname && !strncasecmp(ifname, "Null0", 5)) {
+ flag = "Null0";
+ ifname = NULL;
+ }
+
+ nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ nexthop_vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return zebra_static_route_leak(vty, zvrf, nh_zvrf,
+ AFI_IP, SAFI_UNICAST, no, prefix,
+ mask_str, NULL, gate_str, ifname, flag,
+ tag_str, distance_str, label);
}
DEFPY(ip_route,
@@ -433,6 +554,7 @@ DEFPY(ip_route,
|(1-255)$distance \
|vrf NAME \
|label WORD \
+ |nexthop-vrf NAME \
}]",
NO_STR IP_STR
"Establish static routes\n"
@@ -445,16 +567,83 @@ DEFPY(ip_route,
"Tag value\n"
"Distance value for this route\n"
VRF_CMD_HELP_STR
- MPLS_LABEL_HELPSTR)
+ MPLS_LABEL_HELPSTR
+ VRF_CMD_HELP_STR)
{
+ struct zebra_vrf *zvrf;
+ struct zebra_vrf *nh_zvrf;
const char *flag = NULL;
+
if (ifname && !strncasecmp(ifname, "Null0", 5)) {
flag = "Null0";
ifname = NULL;
}
- return zebra_static_route(vty, AFI_IP, SAFI_UNICAST, no, prefix,
- mask_str, NULL, gate_str, ifname, flag,
- tag_str, distance_str, vrf, label);
+
+ nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ nexthop_vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ zvrf = zebra_vrf_lookup_by_name(vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return zebra_static_route_leak(vty, zvrf, nh_zvrf,
+ AFI_IP, SAFI_UNICAST, no, prefix,
+ mask_str, NULL, gate_str, ifname, flag,
+ tag_str, distance_str, label);
+}
+
+DEFPY(ip_route_vrf,
+ ip_route_vrf_cmd,
+ "[no] ip route\
+ <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
+ <A.B.C.D$gate|INTERFACE$ifname> \
+ [{ \
+ tag (1-4294967295) \
+ |(1-255)$distance \
+ |label WORD \
+ |nexthop-vrf NAME \
+ }]",
+ NO_STR IP_STR
+ "Establish static routes\n"
+ "IP destination prefix (e.g. 10.0.0.0/8)\n"
+ "IP destination prefix\n"
+ "IP destination prefix mask\n"
+ "IP gateway address\n"
+ "IP gateway interface name\n"
+ "Set tag for this route\n"
+ "Tag value\n"
+ "Distance value for this route\n"
+ MPLS_LABEL_HELPSTR
+ VRF_CMD_HELP_STR)
+{
+ VTY_DECLVAR_CONTEXT(vrf, vrf);
+ struct zebra_vrf *zvrf = vrf->info;
+ struct zebra_vrf *nh_zvrf;
+
+ const char *flag = NULL;
+ if (ifname && !strncasecmp(ifname, "Null0", 5)) {
+ flag = "Null0";
+ ifname = NULL;
+ }
+
+ nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ nexthop_vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return zebra_static_route_leak(vty, zvrf, nh_zvrf,
+ AFI_IP, SAFI_UNICAST, no, prefix,
+ mask_str, NULL, gate_str, ifname, flag,
+ tag_str, distance_str, label);
}
/* New RIB. Detailed information for IPv4 route. */
@@ -539,7 +728,7 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
if (nexthop->ifindex)
vty_out(vty, ", via %s",
ifindex2ifname(nexthop->ifindex,
- re->vrf_id));
+ re->nh_vrf_id));
break;
case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
@@ -549,12 +738,12 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
if (nexthop->ifindex)
vty_out(vty, ", via %s",
ifindex2ifname(nexthop->ifindex,
- re->vrf_id));
+ re->nh_vrf_id));
break;
case NEXTHOP_TYPE_IFINDEX:
vty_out(vty, " directly connected, %s",
ifindex2ifname(nexthop->ifindex,
- re->vrf_id));
+ re->nh_vrf_id));
break;
case NEXTHOP_TYPE_BLACKHOLE:
vty_out(vty, " unreachable");
@@ -576,6 +765,14 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
default:
break;
}
+
+ if (re->vrf_id != re->nh_vrf_id) {
+ struct vrf *vrf =
+ vrf_lookup_by_id(re->nh_vrf_id);
+
+ vty_out(vty, "(vrf %s)", vrf->name);
+ }
+
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
vty_out(vty, " (duplicate nexthop removed)");
@@ -715,7 +912,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object_string_add(
json_nexthop, "interfaceName",
ifindex2ifname(nexthop->ifindex,
- re->vrf_id));
+ re->nh_vrf_id));
}
break;
case NEXTHOP_TYPE_IPV6:
@@ -734,7 +931,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object_string_add(
json_nexthop, "interfaceName",
ifindex2ifname(nexthop->ifindex,
- re->vrf_id));
+ re->nh_vrf_id));
}
break;
@@ -747,7 +944,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object_string_add(
json_nexthop, "interfaceName",
ifindex2ifname(nexthop->ifindex,
- re->vrf_id));
+ re->nh_vrf_id));
break;
case NEXTHOP_TYPE_BLACKHOLE:
json_object_boolean_true_add(json_nexthop,
@@ -774,6 +971,14 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
break;
}
+ if (re->nh_vrf_id != re->vrf_id) {
+ struct vrf *vrf =
+ vrf_lookup_by_id(re->nh_vrf_id);
+
+ json_object_string_add(json_nexthop,
+ "vrf",
+ vrf->name);
+ }
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
json_object_boolean_true_add(json_nexthop,
"duplicate");
@@ -881,7 +1086,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
if (nexthop->ifindex)
vty_out(vty, ", %s",
ifindex2ifname(nexthop->ifindex,
- re->vrf_id));
+ re->nh_vrf_id));
break;
case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
@@ -891,12 +1096,13 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
if (nexthop->ifindex)
vty_out(vty, ", %s",
ifindex2ifname(nexthop->ifindex,
- re->vrf_id));
+ re->nh_vrf_id));
break;
case NEXTHOP_TYPE_IFINDEX:
vty_out(vty, " is directly connected, %s",
- ifindex2ifname(nexthop->ifindex, re->vrf_id));
+ ifindex2ifname(nexthop->ifindex,
+ re->nh_vrf_id));
break;
case NEXTHOP_TYPE_BLACKHOLE:
vty_out(vty, " unreachable");
@@ -917,6 +1123,14 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
default:
break;
}
+
+ if (re->nh_vrf_id != re->vrf_id) {
+ struct vrf *vrf =
+ vrf_lookup_by_id(re->nh_vrf_id);
+
+ vty_out(vty, "(vrf %s)", vrf->name);
+ }
+
if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
vty_out(vty, " inactive");
@@ -1603,97 +1817,98 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty,
}
/* Write static route configuration. */
-static int static_config(struct vty *vty, afi_t afi, safi_t safi,
- const char *cmd)
+int static_config(struct vty *vty, struct zebra_vrf *zvrf,
+ afi_t afi, safi_t safi, const char *cmd)
{
+ char spacing[100];
struct route_node *rn;
struct static_route *si;
struct route_table *stable;
- struct vrf *vrf;
- struct zebra_vrf *zvrf;
char buf[SRCDEST2STR_BUFFER];
int write = 0;
- RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
- if (!(zvrf = vrf->info))
- continue;
- if ((stable = zvrf->stable[afi][safi]) == NULL)
- continue;
+ if ((stable = zvrf->stable[afi][safi]) == NULL)
+ return write;
- for (rn = route_top(stable); rn; rn = srcdest_route_next(rn))
- for (si = rn->info; si; si = si->next) {
- vty_out(vty, "%s %s", cmd,
- srcdest_rnode2str(rn, buf, sizeof buf));
+ sprintf(spacing, "%s%s",
+ (zvrf->vrf->vrf_id == VRF_DEFAULT) ? "" : " ",
+ cmd);
- switch (si->type) {
- case STATIC_IPV4_GATEWAY:
- vty_out(vty, " %s",
- inet_ntoa(si->addr.ipv4));
- break;
- case STATIC_IPV6_GATEWAY:
- vty_out(vty, " %s",
- inet_ntop(AF_INET6,
- &si->addr.ipv6, buf,
- sizeof buf));
- break;
- case STATIC_IFNAME:
- vty_out(vty, " %s", si->ifname);
- break;
- case STATIC_BLACKHOLE:
- switch (si->bh_type) {
- case STATIC_BLACKHOLE_DROP:
- vty_out(vty, " blackhole");
- break;
- case STATIC_BLACKHOLE_NULL:
- vty_out(vty, " Null0");
- break;
- case STATIC_BLACKHOLE_REJECT:
- vty_out(vty, " reject");
- break;
- }
+ for (rn = route_top(stable); rn; rn = srcdest_route_next(rn))
+ for (si = rn->info; si; si = si->next) {
+ vty_out(vty, "%s %s", spacing,
+ srcdest_rnode2str(rn, buf, sizeof buf));
+
+ switch (si->type) {
+ case STATIC_IPV4_GATEWAY:
+ vty_out(vty, " %s",
+ inet_ntoa(si->addr.ipv4));
+ break;
+ case STATIC_IPV6_GATEWAY:
+ vty_out(vty, " %s",
+ inet_ntop(AF_INET6,
+ &si->addr.ipv6, buf,
+ sizeof buf));
+ break;
+ case STATIC_IFNAME:
+ vty_out(vty, " %s", si->ifname);
+ break;
+ case STATIC_BLACKHOLE:
+ switch (si->bh_type) {
+ case STATIC_BLACKHOLE_DROP:
+ vty_out(vty, " blackhole");
break;
- case STATIC_IPV4_GATEWAY_IFNAME:
- vty_out(vty, " %s %s",
- inet_ntop(AF_INET,
- &si->addr.ipv4, buf,
- sizeof buf),
- si->ifname);
+ case STATIC_BLACKHOLE_NULL:
+ vty_out(vty, " Null0");
break;
- case STATIC_IPV6_GATEWAY_IFNAME:
- vty_out(vty, " %s %s",
- inet_ntop(AF_INET6,
- &si->addr.ipv6, buf,
- sizeof buf),
- si->ifname);
+ case STATIC_BLACKHOLE_REJECT:
+ vty_out(vty, " reject");
break;
}
+ break;
+ case STATIC_IPV4_GATEWAY_IFNAME:
+ vty_out(vty, " %s %s",
+ inet_ntop(AF_INET,
+ &si->addr.ipv4, buf,
+ sizeof buf),
+ si->ifname);
+ break;
+ case STATIC_IPV6_GATEWAY_IFNAME:
+ vty_out(vty, " %s %s",
+ inet_ntop(AF_INET6,
+ &si->addr.ipv6, buf,
+ sizeof buf),
+ si->ifname);
+ break;
+ }
- if (si->tag)
- vty_out(vty, " tag %" ROUTE_TAG_PRI,
- si->tag);
+ if (si->tag)
+ vty_out(vty, " tag %" ROUTE_TAG_PRI,
+ si->tag);
- if (si->distance
- != ZEBRA_STATIC_DISTANCE_DEFAULT)
- vty_out(vty, " %d", si->distance);
+ if (si->distance
+ != ZEBRA_STATIC_DISTANCE_DEFAULT)
+ vty_out(vty, " %d", si->distance);
- if (si->vrf_id != VRF_DEFAULT)
- vty_out(vty, " vrf %s",
- zvrf_name(zvrf));
+ if (si->nh_vrf_id != si->vrf_id) {
+ struct vrf *vrf;
- /* Label information */
- if (si->snh_label.num_labels)
- vty_out(vty, " label %s",
- mpls_label2str(
- si->snh_label
- .num_labels,
- si->snh_label.label,
- buf, sizeof buf, 0));
+ vrf = vrf_lookup_by_id(si->nh_vrf_id);
+ vty_out(vty, " nexthop-vrf %s",
+ (vrf) ? vrf->name : "Unknown");
+ }
- vty_out(vty, "\n");
+ /* Label information */
+ if (si->snh_label.num_labels)
+ vty_out(vty, " label %s",
+ mpls_label2str(si->snh_label.num_labels,
+ si->snh_label.label,
+ buf, sizeof buf, 0));
- write = 1;
- }
- }
+ vty_out(vty, "\n");
+
+ write = 1;
+ }
return write;
}
@@ -1727,6 +1942,38 @@ DEFPY(ipv6_route_blackhole,
tag_str, distance_str, vrf, label);
}
+DEFPY(ipv6_route_blackhole_vrf,
+ ipv6_route_blackhole_vrf_cmd,
+ "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
+ <Null0|reject|blackhole>$flag \
+ [{ \
+ tag (1-4294967295) \
+ |(1-255)$distance \
+ |label WORD \
+ }]",
+ NO_STR
+ IPV6_STR
+ "Establish static routes\n"
+ "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+ "IPv6 source-dest route\n"
+ "IPv6 source prefix\n"
+ "Null interface\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n"
+ "Set tag for this route\n"
+ "Tag value\n"
+ "Distance value for this prefix\n"
+ MPLS_LABEL_HELPSTR)
+{
+ VTY_DECLVAR_CONTEXT(vrf, vrf);
+ struct zebra_vrf *zvrf = vrf->info;
+
+ return zebra_static_route_leak(vty, zvrf, zvrf,
+ AFI_IP6, SAFI_UNICAST, no, prefix_str,
+ NULL, from_str, NULL, NULL, flag,
+ tag_str, distance_str, label);
+}
+
DEFPY(ipv6_route_address_interface,
ipv6_route_address_interface_cmd,
"[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
@@ -1737,6 +1984,7 @@ DEFPY(ipv6_route_address_interface,
|(1-255)$distance \
|vrf NAME \
|label WORD \
+ |nexthop-vrf NAME \
}]",
NO_STR
IPV6_STR
@@ -1750,11 +1998,72 @@ DEFPY(ipv6_route_address_interface,
"Tag value\n"
"Distance value for this prefix\n"
VRF_CMD_HELP_STR
- MPLS_LABEL_HELPSTR)
+ MPLS_LABEL_HELPSTR
+ VRF_CMD_HELP_STR)
{
- return zebra_static_route(vty, AFI_IP6, SAFI_UNICAST, no, prefix_str,
- NULL, from_str, gate_str, ifname, NULL,
- tag_str, distance_str, vrf, label);
+ struct zebra_vrf *zvrf;
+ struct zebra_vrf *nh_zvrf;
+
+ nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ nexthop_vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ zvrf = zebra_vrf_lookup_by_name(vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return zebra_static_route_leak(vty, zvrf, nh_zvrf,
+ AFI_IP6, SAFI_UNICAST, no, prefix_str,
+ NULL, from_str, gate_str, ifname, NULL,
+ tag_str, distance_str, label);
+}
+
+DEFPY(ipv6_route_address_interface_vrf,
+ ipv6_route_address_interface_vrf_cmd,
+ "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
+ X:X::X:X$gate \
+ INTERFACE$ifname \
+ [{ \
+ tag (1-4294967295) \
+ |(1-255)$distance \
+ |label WORD \
+ |nexthop-vrf NAME \
+ }]",
+ NO_STR
+ IPV6_STR
+ "Establish static routes\n"
+ "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+ "IPv6 source-dest route\n"
+ "IPv6 source prefix\n"
+ "IPv6 gateway address\n"
+ "IPv6 gateway interface name\n"
+ "Set tag for this route\n"
+ "Tag value\n"
+ "Distance value for this prefix\n"
+ MPLS_LABEL_HELPSTR
+ VRF_CMD_HELP_STR)
+{
+ VTY_DECLVAR_CONTEXT(vrf, vrf);
+ struct zebra_vrf *zvrf = vrf->info;
+ struct zebra_vrf *nh_zvrf;
+
+ nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ nexthop_vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return zebra_static_route_leak(vty, zvrf, nh_zvrf,
+ AFI_IP6, SAFI_UNICAST, no, prefix_str,
+ NULL, from_str, gate_str, ifname, NULL,
+ tag_str, distance_str, label);
}
DEFPY(ipv6_route,
@@ -1766,6 +2075,7 @@ DEFPY(ipv6_route,
|(1-255)$distance \
|vrf NAME \
|label WORD \
+ |nexthop-vrf NAME \
}]",
NO_STR
IPV6_STR
@@ -1779,11 +2089,71 @@ DEFPY(ipv6_route,
"Tag value\n"
"Distance value for this prefix\n"
VRF_CMD_HELP_STR
- MPLS_LABEL_HELPSTR)
+ MPLS_LABEL_HELPSTR
+ VRF_CMD_HELP_STR)
{
- return zebra_static_route(vty, AFI_IP6, SAFI_UNICAST, no, prefix_str,
- NULL, from_str, gate_str, ifname, NULL,
- tag_str, distance_str, vrf, label);
+ struct zebra_vrf *zvrf;
+ struct zebra_vrf *nh_zvrf;
+
+ nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ nexthop_vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ zvrf = zebra_vrf_lookup_by_name(vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return zebra_static_route_leak(vty, zvrf, nh_zvrf,
+ AFI_IP6, SAFI_UNICAST, no, prefix_str,
+ NULL, from_str, gate_str, ifname, NULL,
+ tag_str, distance_str, label);
+}
+
+DEFPY(ipv6_route_vrf,
+ ipv6_route_vrf_cmd,
+ "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
+ <X:X::X:X$gate|INTERFACE$ifname> \
+ [{ \
+ tag (1-4294967295) \
+ |(1-255)$distance \
+ |label WORD \
+ |nexthop-vrf NAME \
+ }]",
+ NO_STR
+ IPV6_STR
+ "Establish static routes\n"
+ "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+ "IPv6 source-dest route\n"
+ "IPv6 source prefix\n"
+ "IPv6 gateway address\n"
+ "IPv6 gateway interface name\n"
+ "Set tag for this route\n"
+ "Tag value\n"
+ "Distance value for this prefix\n"
+ MPLS_LABEL_HELPSTR
+ VRF_CMD_HELP_STR)
+{
+ VTY_DECLVAR_CONTEXT(vrf, vrf);
+ struct zebra_vrf *zvrf = vrf->info;
+ struct zebra_vrf *nh_zvrf;
+
+ nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ nexthop_vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return zebra_static_route_leak(vty, zvrf, nh_zvrf,
+ AFI_IP6, SAFI_UNICAST, no, prefix_str,
+ NULL, from_str, gate_str, ifname, NULL,
+ tag_str, distance_str, label);
}
/*
@@ -2419,11 +2789,8 @@ static int zebra_ip_config(struct vty *vty)
{
int write = 0;
- write += static_config(vty, AFI_IP, SAFI_UNICAST, "ip route");
- write += static_config(vty, AFI_IP, SAFI_MULTICAST, "ip mroute");
- write += static_config(vty, AFI_IP6, SAFI_UNICAST, "ipv6 route");
-
write += zebra_import_table_config(vty);
+
return write;
}
@@ -2859,8 +3226,11 @@ void zebra_vty_init(void)
install_element(CONFIG_NODE, &ip_multicast_mode_cmd);
install_element(CONFIG_NODE, &no_ip_multicast_mode_cmd);
install_element(CONFIG_NODE, &ip_route_blackhole_cmd);
+ install_element(VRF_NODE, &ip_route_blackhole_vrf_cmd);
install_element(CONFIG_NODE, &ip_route_address_interface_cmd);
+ install_element(VRF_NODE, &ip_route_address_interface_vrf_cmd);
install_element(CONFIG_NODE, &ip_route_cmd);
+ install_element(VRF_NODE, &ip_route_vrf_cmd);
install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd);
install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd);
install_element(CONFIG_NODE, &zebra_workqueue_timer_cmd);
@@ -2882,8 +3252,11 @@ void zebra_vty_init(void)
install_element(VIEW_NODE, &show_ip_rpf_addr_cmd);
install_element(CONFIG_NODE, &ipv6_route_blackhole_cmd);
+ install_element(VRF_NODE, &ipv6_route_blackhole_vrf_cmd);
install_element(CONFIG_NODE, &ipv6_route_address_interface_cmd);
+ install_element(VRF_NODE, &ipv6_route_address_interface_vrf_cmd);
install_element(CONFIG_NODE, &ipv6_route_cmd);
+ install_element(VRF_NODE, &ipv6_route_vrf_cmd);
install_element(CONFIG_NODE, &ip_nht_default_route_cmd);
install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd);
install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd);
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 604054f2ab..3ee2bb59ec 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -592,6 +592,7 @@ int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p,
memset(&api, 0, sizeof(api));
api.vrf_id = re->vrf_id;
+ api.nh_vrf_id = re->nh_vrf_id;
api.type = re->type;
api.instance = re->instance;
api.flags = re->flags;
@@ -1136,6 +1137,7 @@ static int zread_route_add(struct zserv *client, u_short length,
re->flags = api.flags;
re->uptime = time(NULL);
re->vrf_id = vrf_id;
+ re->nh_vrf_id = api.nh_vrf_id;
re->table = zvrf->table_id;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
@@ -1362,6 +1364,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
/* VRF ID */
re->vrf_id = zvrf_id(zvrf);
+ re->nh_vrf_id = zvrf_id(zvrf);
/* Nexthop parse. */
if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) {
@@ -1571,6 +1574,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
/* VRF ID */
re->vrf_id = zvrf_id(zvrf);
+ re->nh_vrf_id = zvrf_id(zvrf);
/* We need to give nh-addr, nh-ifindex with the same next-hop object
* to the re to ensure that IPv6 multipathing works; need to coalesce
@@ -1856,6 +1860,8 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
/* VRF ID */
re->vrf_id = zvrf_id(zvrf);
+ re->nh_vrf_id = zvrf_id(zvrf);
+
re->table = zvrf->table_id;
ret = rib_add_multipath(AFI_IP6, safi, &p, src_pp, re);