From 0cb76b9d8dd1925d34fe84f1c24c2a7890444e97 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 8 Jan 2018 08:57:44 -0500 Subject: [PATCH 01/18] lib: Add notice of when we can remove some deprecated code. The zapi_ipv4_route, zapi_ipv6_route and zapi_ipv4_route_ipv6_nexthop functions are deprecated. Add notice of when we can remove the deprecated code from the system. Signed-off-by: Donald Sharp --- lib/zclient.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/zclient.h b/lib/zclient.h index cc34fd9d2c..869b9b7d68 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -420,6 +420,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)); From 14fcc65cbbcd3d1684b879a10a0d8564c238e0e6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 5 Jan 2018 09:21:55 -0500 Subject: [PATCH 02/18] lib: Allow interface lookup by VRF_UNKNOWN Modify if_lookup_by_index to accept a VRF_UNKNOWN as a vrf_id. This will cause it to look in all vrf's for the interface pointer. Subsequently all if_XXXX functions that call this function will also get this behavior. VRF_UNKNOWN *should* not be used for interface creation as that this will break some core assumptions. This work is part of allowing vrf route leaking. Currently it is possible to create a route in the linux kernel that has a nexthop across vrf boundaries. Signed-off-by: Donald Sharp --- lib/if.c | 12 ++++++++++++ lib/if.h | 7 +++++++ 2 files changed, 19 insertions(+) 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); From 8f43b4d8868b340a7c61e55372b01f070abfb491 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 12 Jan 2018 09:20:30 -0500 Subject: [PATCH 03/18] zebra: Add nh_vrf_id to 'struct route_entry` With VRF route-leaking we need to know what vrf the nexthops are in compared to this vrf. This code adds the nh_vrf_id to the route entry and sets it up correctly for the non-route-leaking case. The assumption here is that future commits will make the nh_vrf_id *different* than the vrf_id. Signed-off-by: Donald Sharp --- zebra/rib.h | 1 + zebra/rt_netlink.c | 1 + zebra/zebra_rib.c | 1 + zebra/zebra_rnh.c | 2 ++ zebra/zebra_static.c | 1 + zebra/zserv.c | 5 +++++ 6 files changed, 11 insertions(+) diff --git a/zebra/rib.h b/zebra/rib.h index c7e83480ca..c92f540771 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; diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index a77814668d..cb3f598eb9 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -453,6 +453,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); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 41e14459b1..8caa39427b 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2514,6 +2514,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 = 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 33d0b3a641..3fc496ebb7 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_static.c b/zebra/zebra_static.c index 751ea08a38..7fdc4908b4 100644 --- a/zebra/zebra_static.c +++ b/zebra/zebra_static.c @@ -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->vrf_id; re->table = si->vrf_id ? (zebra_vrf_lookup_by_id(si->vrf_id))->table_id diff --git a/zebra/zserv.c b/zebra/zserv.c index 7eded89f6d..6c453516bd 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1146,6 +1146,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 = vrf_id; re->table = zvrf->table_id; if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { @@ -1372,6 +1373,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)) { @@ -1581,6 +1583,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 @@ -1866,6 +1869,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); From 99b9d9609f57d283d79c72c89848d7ac5f000f0b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 8 Jan 2018 09:56:08 -0500 Subject: [PATCH 04/18] zebra: Use the correct vrf id to lookup the ifp pointer Use the nexthop vrf_id to properly lookup the ifp pointer for display purposes. Signed-off-by: Donald Sharp --- zebra/zebra_rib.c | 3 ++- zebra/zebra_vty.c | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 8caa39427b..6f9b855908 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -911,7 +911,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); } diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 82b0157ad3..a0d2930c89 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -539,7 +539,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 +549,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"); @@ -715,7 +715,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 +734,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 +747,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, @@ -881,7 +881,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 +891,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"); From 8795f90448e45e674ea60da83c2ad571ff2f9fec Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 8 Jan 2018 10:21:09 -0500 Subject: [PATCH 05/18] zebra: Add nh_vrf_id to rib_add Add to the rib_add function the ability to pass in the nexthops vrf. Additionally when we decode the netlink message from the linux kernel, properly figure out the nexthops vrf_id. Signed-off-by: Donald Sharp --- zebra/connected.c | 6 ++++-- zebra/kernel_socket.c | 4 ++-- zebra/rib.h | 4 ++-- zebra/rt_netlink.c | 24 +++++++++++++++++++++++- zebra/rtread_getmsg.c | 5 +++-- zebra/zebra_rib.c | 9 +++++---- 6 files changed, 39 insertions(+), 13 deletions(-) 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/rib.h b/zebra/rib.h index c92f540771..6e3a85c1d1 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -294,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); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index cb3f598eb9..384656a573 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 { @@ -465,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)); 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 6f9b855908..b1f0f70093 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2497,9 +2497,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; @@ -2515,7 +2516,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 = vrf_id; + re->nh_vrf_id = nh_vrf_id; re->nexthop_num = 0; re->uptime = time(NULL); re->tag = tag; From 007dbee65cef24561da54cfbf5c4d24052db002a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 8 Jan 2018 10:34:48 -0500 Subject: [PATCH 06/18] zebra: When handling nexthops use the correct vrf When we are handling nexthops in zebra, use the appropriate vrf to figure out if the nexthops are active or not. Signed-off-by: Donald Sharp --- zebra/zebra_rib.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index b1f0f70093..fd1b273c8e 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) @@ -416,7 +416,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; @@ -444,7 +444,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; @@ -832,7 +832,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 @@ -860,7 +860,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 From 2793a0980dc02ba3179c5af4468943d9d6879b62 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 8 Jan 2018 10:43:07 -0500 Subject: [PATCH 07/18] zebra: When displaying nexthop information show correct vrf If the vrf for the nexthop is different than the vrf the route is in, display the nexthops vrf. Signed-off-by: Donald Sharp --- zebra/zebra_vty.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index a0d2930c89..c56df82053 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -576,6 +576,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)"); @@ -774,6 +782,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"); @@ -918,6 +934,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"); From d5b2119cb418c47a70eb931a4ccdb6e6f078619f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 8 Jan 2018 11:17:02 -0500 Subject: [PATCH 08/18] *: Send/receive the nexthop vrf_id Modify the code to send and receive to/from zebra the nexthops vrf_id. Signed-off-by: Donald Sharp --- babeld/kernel.c | 1 + bgpd/bgp_zebra.c | 2 ++ bgpd/rfapi/vnc_zebra.c | 1 + eigrpd/eigrp_zebra.c | 2 ++ isisd/isis_zebra.c | 2 ++ lib/zclient.c | 5 +++++ lib/zclient.h | 1 + nhrpd/nhrp_route.c | 2 ++ ospf6d/ospf6_zebra.c | 3 +++ ospfd/ospf_zebra.c | 4 ++++ ripd/rip_zebra.c | 1 + ripngd/ripng_zebra.c | 1 + sharpd/sharp_zebra.c | 2 ++ zebra/zserv.c | 3 ++- 14 files changed, 29 insertions(+), 1 deletion(-) 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 f8b38468f5..cba611a774 100644 --- a/bgpd/rfapi/vnc_zebra.c +++ b/bgpd/rfapi/vnc_zebra.c @@ -394,6 +394,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/zclient.c b/lib/zclient.c index 4177ce1a71..8f9536f5a2 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 869b9b7d68..083372a9d2 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; }; 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/zserv.c b/zebra/zserv.c index 6c453516bd..1520fc883a 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -602,6 +602,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; @@ -1146,7 +1147,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 = vrf_id; + re->nh_vrf_id = api.nh_vrf_id; re->table = zvrf->table_id; if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { From 9ceac4c7cf902ac80d422bc5dcebf15305770eb6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 8 Jan 2018 16:09:07 -0500 Subject: [PATCH 09/18] lib: Increment zapi version number Signed-off-by: Donald Sharp --- lib/zclient.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/zclient.h b/lib/zclient.h index 083372a9d2..72e71631d2 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -227,7 +227,7 @@ struct zserv_header { * always set to 255 in new zserv. */ uint8_t version; -#define ZSERV_VERSION 4 +#define ZSERV_VERSION 5 vrf_id_t vrf_id; uint16_t command; }; From f84fc2c9553621648bbaa0c0938cd1b60608e14b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 9 Jan 2018 14:47:11 -0500 Subject: [PATCH 10/18] zebra: Move NS/VRF initialization earlier Move the NS/VRF initialization code for zebra to an earlier point in startup. In the future we will have code that will want to install_element into a VRF_NODE from zebra_vty.c Signed-off-by: Donald Sharp --- zebra/main.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) 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); From 2f03bc8f72de03461b2be732162521fd6b837d49 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 9 Jan 2018 16:25:45 -0500 Subject: [PATCH 11/18] zebra: Add zebra_static_route_leak function Add a function to handle the route leaking of a static route. Signed-off-by: Donald Sharp --- zebra/zebra_vty.c | 51 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index c56df82053..45e204dcc9 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) { @@ -247,6 +241,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, From cbb0dbf6bd49df140ae838b8013c15513d976b4d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 8 Jan 2018 19:11:17 -0500 Subject: [PATCH 12/18] zebra: Add the zvrf pointer to the 'struct static_route' Signed-off-by: Donald Sharp --- zebra/zebra_static.c | 7 +++++-- zebra/zebra_static.h | 2 ++ zebra/zebra_vty.c | 3 ++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c index 7fdc4908b4..3423518bba 100644 --- a/zebra/zebra_static.c +++ b/zebra/zebra_static.c @@ -155,7 +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->vrf_id; + re->nh_vrf_id = si->nh_vrf_id; re->table = si->vrf_id ? (zebra_vrf_lookup_by_id(si->vrf_id))->table_id @@ -379,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; @@ -440,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; @@ -494,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_vty.c b/zebra/zebra_vty.c index 45e204dcc9..ece4428c43 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -233,7 +233,8 @@ static int zebra_static_route_leak(struct vty *vty, 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); From ab32921c8a6a531cc51cbc659ec5abce43d9420a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 10 Jan 2018 09:32:16 -0500 Subject: [PATCH 13/18] zebra: Cleanup vrf_config_write Optimize vrf_config_write a tiny bit to be a bit more efficient. Signed-off-by: Donald Sharp --- zebra/zebra_vrf.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 1ae9eac61f..ae8cb3450e 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -476,12 +476,13 @@ static int vrf_config_write(struct vty *vty) if (!zvrf) continue; - if (strcmp(zvrf_name(zvrf), VRF_DEFAULT_NAME)) { - vty_out(vty, "vrf %s\n", zvrf_name(zvrf)); - if (zvrf->l3vni) - vty_out(vty, " vni %u\n", zvrf->l3vni); - vty_out(vty, "!\n"); - } + if (vrf->vrf_id == VRF_DEFAULT) + continue; + + vty_out(vty, "vrf %s\n", zvrf_name(zvrf)); + if (zvrf->l3vni) + vty_out(vty, " vni %u\n", zvrf->l3vni); + vty_out(vty, "!\n"); } return 0; } From b2ffa06b4f648f193e53fdde9c3e9dd55d8e494d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 10 Jan 2018 10:21:16 -0500 Subject: [PATCH 14/18] zebra: Add vrf level 'ip route ...' commands Add the ability to accept 'ip route ...' commands from within a vrf context. Signed-off-by: Donald Sharp --- zebra/zebra_vty.c | 248 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index ece4428c43..a9f95c1028 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -407,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\ + \ + $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\ @@ -443,6 +474,55 @@ DEFPY(ip_route_address_interface, tag_str, distance_str, vrf, label); } +DEFPY(ip_route_address_interface_vrf, + ip_route_address_interface_vrf_cmd, + "[no] ip route\ + \ + 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, ip_route_cmd, "[no] ip route\ @@ -477,6 +557,53 @@ DEFPY(ip_route, tag_str, distance_str, vrf, label); } +DEFPY(ip_route_vrf, + ip_route_vrf_cmd, + "[no] ip route\ + \ + \ + [{ \ + 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. */ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn, int mcast) @@ -1772,6 +1899,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] \ + $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] \ @@ -1802,6 +1961,48 @@ DEFPY(ipv6_route_address_interface, tag_str, distance_str, vrf, 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, ipv6_route_cmd, "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \ @@ -1831,6 +2032,47 @@ DEFPY(ipv6_route, tag_str, distance_str, vrf, label); } +DEFPY(ipv6_route_vrf, + ipv6_route_vrf_cmd, + "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \ + \ + [{ \ + 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); +} + /* * Show IPv6 mroute command.Used to dump * the Multicast routing table. @@ -2904,8 +3146,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); @@ -2927,8 +3172,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); From 37728041b634b2ef96fe5ff120964fe3ba0b8114 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 10 Jan 2018 09:48:54 -0500 Subject: [PATCH 15/18] zebra: Move `ip route ...` generation to vrf control Move the code that generates the 'show run' output for 'ip route' to be controlled by the vrf config generation code. Since it really belongs there. Signed-off-by: Donald Sharp --- zebra/rib.h | 2 + zebra/zebra_vrf.c | 15 +++-- zebra/zebra_vty.c | 160 +++++++++++++++++++++++----------------------- 3 files changed, 91 insertions(+), 86 deletions(-) diff --git a/zebra/rib.h b/zebra/rib.h index 6e3a85c1d1..664afd01b8 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -440,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/zebra_vrf.c b/zebra/zebra_vrf.c index ae8cb3450e..95426683a8 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -476,13 +476,18 @@ static int vrf_config_write(struct vty *vty) if (!zvrf) continue; - if (vrf->vrf_id == VRF_DEFAULT) - continue; + if (vrf->vrf_id != VRF_DEFAULT) + vty_out(vty, "vrf %s\n", zvrf_name(zvrf)); - vty_out(vty, "vrf %s\n", zvrf_name(zvrf)); - if (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); - vty_out(vty, "!\n"); + + 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 a9f95c1028..bace9314d5 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -1775,97 +1775,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)); + 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_IPV6_GATEWAY: - vty_out(vty, " %s", - inet_ntop(AF_INET6, - &si->addr.ipv6, buf, - sizeof buf)); + case STATIC_BLACKHOLE_NULL: + vty_out(vty, " Null0"); 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; - } - 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); + case STATIC_BLACKHOLE_REJECT: + vty_out(vty, " reject"); break; } - - 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->vrf_id != VRF_DEFAULT) - vty_out(vty, " vrf %s", - zvrf_name(zvrf)); - - /* 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)); - - vty_out(vty, "\n"); - - write = 1; + 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->distance + != ZEBRA_STATIC_DISTANCE_DEFAULT) + vty_out(vty, " %d", si->distance); + + if (si->nh_vrf_id != si->vrf_id) { + struct vrf *vrf; + + vrf = vrf_lookup_by_id(si->nh_vrf_id); + vty_out(vty, " nexthop-vrf %s", + (vrf) ? vrf->name : "Unknown"); + } + + /* 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)); + + vty_out(vty, "\n"); + + write = 1; + } return write; } @@ -2706,11 +2707,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; } From 5e2105220428ca5ba9e80d9810a5ba32c4b18466 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 11 Jan 2018 11:47:04 -0500 Subject: [PATCH 16/18] zebra: Encode the ifindex over netlink In order for routes to be leaked the ifindex must be sent down into the kernel over the netlink protocol. So send it( we always figure it out ) when we add the route. Signed-off-by: Donald Sharp --- zebra/rt_netlink.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 384656a573..1092327fe9 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -963,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, @@ -984,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, @@ -1164,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) @@ -1180,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): " From 5bdd34db693867fbfd80d2fe3fc4bc056cc02b0f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 11 Jan 2018 11:51:46 -0500 Subject: [PATCH 17/18] zebra: Allow static non interface based routes to leak Allow this to work: vrf DONNA ip route 4.3.2.1/32 192.168.1.5 nexthop-vrf EVA The static route code was not properly telling the nexthop resolution code what vrf to use. Signed-off-by: Donald Sharp --- zebra/zebra_rib.c | 4 ++-- zebra/zebra_routemap.c | 2 +- zebra/zebra_static.c | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index fd1b273c8e..16dafa6b89 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -397,7 +397,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; @@ -904,7 +904,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) { 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 3423518bba..fa5f0d9c48 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); @@ -170,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( @@ -190,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( @@ -222,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); From 61408536df768ec97b235b463453b64f4e813369 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 11 Jan 2018 12:20:50 -0500 Subject: [PATCH 18/18] zebra: Add ability for default vrf to route-leak Allow the end user to specify static routes that leak across vrf's in the default vrf. Signed-off-by: Donald Sharp --- zebra/zebra_vty.c | 114 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 98 insertions(+), 16 deletions(-) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index bace9314d5..5df846354e 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -449,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" @@ -462,16 +463,36 @@ 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, @@ -533,6 +554,7 @@ DEFPY(ip_route, |(1-255)$distance \ |vrf NAME \ |label WORD \ + |nexthop-vrf NAME \ }]", NO_STR IP_STR "Establish static routes\n" @@ -545,16 +567,36 @@ 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, @@ -1942,6 +1984,7 @@ DEFPY(ipv6_route_address_interface, |(1-255)$distance \ |vrf NAME \ |label WORD \ + |nexthop-vrf NAME \ }]", NO_STR IPV6_STR @@ -1955,11 +1998,30 @@ 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, @@ -2013,6 +2075,7 @@ DEFPY(ipv6_route, |(1-255)$distance \ |vrf NAME \ |label WORD \ + |nexthop-vrf NAME \ }]", NO_STR IPV6_STR @@ -2026,11 +2089,30 @@ 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,