diff options
Diffstat (limited to 'zebra')
| -rw-r--r-- | zebra/connected.c | 6 | ||||
| -rw-r--r-- | zebra/if_netlink.c | 5 | ||||
| -rw-r--r-- | zebra/interface.c | 36 | ||||
| -rw-r--r-- | zebra/interface.h | 2 | ||||
| -rw-r--r-- | zebra/kernel_socket.c | 4 | ||||
| -rw-r--r-- | zebra/label_manager.c | 2 | ||||
| -rw-r--r-- | zebra/main.c | 17 | ||||
| -rw-r--r-- | zebra/rib.h | 7 | ||||
| -rw-r--r-- | zebra/rt.h | 9 | ||||
| -rw-r--r-- | zebra/rt_netlink.c | 64 | ||||
| -rw-r--r-- | zebra/rt_socket.c | 16 | ||||
| -rw-r--r-- | zebra/rtread_getmsg.c | 5 | ||||
| -rw-r--r-- | zebra/zebra_fpm.c | 20 | ||||
| -rw-r--r-- | zebra/zebra_mpls.c | 6 | ||||
| -rw-r--r-- | zebra/zebra_mroute.c | 2 | ||||
| -rw-r--r-- | zebra/zebra_ns.c | 2 | ||||
| -rw-r--r-- | zebra/zebra_ns.h | 3 | ||||
| -rw-r--r-- | zebra/zebra_ptm.c | 13 | ||||
| -rw-r--r-- | zebra/zebra_ptm_redistribute.c | 5 | ||||
| -rw-r--r-- | zebra/zebra_rib.c | 117 | ||||
| -rw-r--r-- | zebra/zebra_rnh.c | 4 | ||||
| -rw-r--r-- | zebra/zebra_routemap.c | 4 | ||||
| -rw-r--r-- | zebra/zebra_static.c | 20 | ||||
| -rw-r--r-- | zebra/zebra_static.h | 2 | ||||
| -rw-r--r-- | zebra/zebra_vrf.c | 15 | ||||
| -rw-r--r-- | zebra/zebra_vty.c | 628 | ||||
| -rw-r--r-- | zebra/zebra_vxlan.c | 10 | ||||
| -rw-r--r-- | zebra/zserv.c | 54 | ||||
| -rw-r--r-- | zebra/zserv.h | 2 |
29 files changed, 818 insertions, 262 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/if_netlink.c b/zebra/if_netlink.c index f73506bf91..14905b738b 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -387,6 +387,11 @@ static int get_iflink_speed(const char *ifname) return (ecmd.speed_hi << 16) | ecmd.speed; } +uint32_t kernel_get_speed(struct interface *ifp) +{ + return get_iflink_speed(ifp->name); +} + static int netlink_extract_bridge_info(struct rtattr *link_data, struct zebra_l2info_bridge *bridge_info) { diff --git a/zebra/interface.c b/zebra/interface.c index 18588ee52c..07570e64bf 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -57,8 +57,29 @@ DEFINE_HOOK(zebra_if_extra_info, (struct vty *vty, struct interface *ifp), DEFINE_HOOK(zebra_if_config_wr, (struct vty *vty, struct interface *ifp), (vty, ifp)) + static void if_down_del_nbr_connected(struct interface *ifp); +static int if_zebra_speed_update(struct thread *thread) +{ + struct interface *ifp = THREAD_ARG(thread); + struct zebra_if *zif = ifp->info; + uint32_t new_speed; + + zif->speed_update = NULL; + + new_speed = kernel_get_speed(ifp); + if (new_speed != ifp->speed) { + zlog_info("%s: %s old speed: %u new speed: %u", + __PRETTY_FUNCTION__, ifp->name, + ifp->speed, new_speed); + ifp->speed = new_speed; + if_add_update(ifp); + } + + return 1; +} + static void zebra_if_node_destroy(route_table_delegate_t *delegate, struct route_table *table, struct route_node *node) @@ -119,6 +140,16 @@ static int if_zebra_new_hook(struct interface *ifp) route_table_init_with_delegate(&zebra_if_table_delegate); ifp->info = zebra_if; + + /* + * Some platforms are telling us that the interface is + * up and ready to go. When we check the speed we + * sometimes get the wrong value. Wait a couple + * of seconds and ask again. Hopefully it's all settled + * down upon startup. + */ + thread_add_timer(zebrad.master, if_zebra_speed_update, + ifp, 15, &zebra_if->speed_update); return 0; } @@ -141,6 +172,8 @@ static int if_zebra_delete_hook(struct interface *ifp) list_delete_and_null(&rtadv->AdvPrefixList); #endif /* HAVE_RTADV */ + THREAD_OFF(zebra_if->speed_update); + XFREE(MTYPE_TMP, zebra_if); } @@ -735,7 +768,8 @@ void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id) zebra_interface_vrf_update_add(ifp, old_vrf_id); /* Install connected routes (in new VRF). */ - if_install_connected(ifp); + if (if_is_operative(ifp)) + if_install_connected(ifp); static_ifindex_update(ifp, true); diff --git a/zebra/interface.h b/zebra/interface.h index 61c3359f3b..e13721448c 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -273,6 +273,8 @@ struct zebra_if { /* Link fields - for sub-interfaces. */ ifindex_t link_ifindex; struct interface *link; + + struct thread *speed_update; }; DECLARE_HOOK(zebra_if_extra_info, (struct vty *vty, struct interface *ifp), 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/label_manager.c b/zebra/label_manager.c index f38206d8e1..ace13eda71 100644 --- a/zebra/label_manager.c +++ b/zebra/label_manager.c @@ -121,7 +121,7 @@ static int reply_error(int cmd, struct zserv *zserv, vrf_id_t vrf_id) s = zserv->obuf; stream_reset(s); - zserv_create_header(s, cmd, vrf_id); + zclient_create_header(s, cmd, vrf_id); /* result */ stream_putc(s, 1); 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.h b/zebra/rt.h index 7f5bb4dd34..54d45b889a 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -60,15 +60,17 @@ enum southbound_results { * semantics so we will end up with a delete than * a re-add. */ -extern void kernel_route_rib(struct prefix *p, struct prefix *src_p, - struct route_entry *old, struct route_entry *new); +extern void kernel_route_rib(struct route_node *rn, struct prefix *p, + struct prefix *src_p, struct route_entry *old, + struct route_entry *new); /* * So route install/failure may not be immediately known * so let's separate it out and allow the result to * be passed back up. */ -extern void kernel_route_rib_pass_fail(struct prefix *p, +extern void kernel_route_rib_pass_fail(struct route_node *rn, + struct prefix *p, struct route_entry *re, enum southbound_results res); @@ -98,6 +100,7 @@ extern void kernel_lsp_pass_fail(zebra_lsp_t *lsp, extern int mpls_kernel_init(void); +extern uint32_t kernel_get_speed(struct interface *ifp); extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute); extern int kernel_add_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index a77814668d..20cc292e11 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)); @@ -803,7 +826,7 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen, struct rtmsg *rtmsg, size_t req_size, int cmd) { - struct nexthop_label *nh_label; + struct mpls_label_stack *nh_label; mpls_lse_t out_lse[MPLS_MAX_LABELS]; char label_buf[256]; @@ -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, @@ -1003,7 +1031,7 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen, struct rtmsg *rtmsg, union g_addr **src) { - struct nexthop_label *nh_label; + struct mpls_label_stack *nh_label; mpls_lse_t out_lse[MPLS_MAX_LABELS]; char label_buf[256]; @@ -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): " @@ -1609,8 +1642,9 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in) return suc; } -void kernel_route_rib(struct prefix *p, struct prefix *src_p, - struct route_entry *old, struct route_entry *new) +void kernel_route_rib(struct route_node *rn, struct prefix *p, + struct prefix *src_p, struct route_entry *old, + struct route_entry *new) { int ret = 0; @@ -1639,7 +1673,7 @@ void kernel_route_rib(struct prefix *p, struct prefix *src_p, ret = netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 0); } - kernel_route_rib_pass_fail(p, new, + kernel_route_rib_pass_fail(rn, p, new, (!ret) ? SOUTHBOUND_INSTALL_SUCCESS : SOUTHBOUND_INSTALL_FAILURE); @@ -1649,7 +1683,7 @@ void kernel_route_rib(struct prefix *p, struct prefix *src_p, if (old) { ret = netlink_route_multipath(RTM_DELROUTE, p, src_p, old, 0); - kernel_route_rib_pass_fail(p, old, + kernel_route_rib_pass_fail(rn, p, old, (!ret) ? SOUTHBOUND_DELETE_SUCCESS : SOUTHBOUND_DELETE_FAILURE); diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index 0d1a80e737..6d4af1203c 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -67,7 +67,7 @@ static int sin_masklen(struct in_addr mask) #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ #ifdef __OpenBSD__ -static int kernel_rtm_add_labels(struct nexthop_label *nh_label, +static int kernel_rtm_add_labels(struct mpls_label_stack *nh_label, struct sockaddr_mpls *smpls) { if (nh_label->num_labels > 1) { @@ -387,8 +387,9 @@ static int kernel_rtm(int cmd, struct prefix *p, struct route_entry *re) return 0; } -void kernel_route_rib(struct prefix *p, struct prefix *src_p, - struct route_entry *old, struct route_entry *new) +void kernel_route_rib(struct route_node *rn, struct prefix *p, + struct prefix *src_p, struct route_entry *old, + struct route_entry *new) { int route = 0; @@ -410,12 +411,12 @@ void kernel_route_rib(struct prefix *p, struct prefix *src_p, zlog_err("Can't lower privileges"); if (new) { - kernel_route_rib_pass_fail(p, new, + kernel_route_rib_pass_fail(rn, p, new, (!route) ? SOUTHBOUND_INSTALL_SUCCESS : SOUTHBOUND_INSTALL_FAILURE); } else { - kernel_route_rib_pass_fail(p, old, + kernel_route_rib_pass_fail(rn, p, old, (!route) ? SOUTHBOUND_DELETE_SUCCESS : SOUTHBOUND_DELETE_FAILURE); @@ -473,4 +474,9 @@ extern int kernel_interface_set_master(struct interface *master, return 0; } +uint32_t kernel_get_speed(struct interface *ifp) +{ + return ifp->speed; +} + #endif /* !HAVE_NETLINK */ 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_fpm.c b/zebra/zebra_fpm.c index 0d0a2cb3bf..a6e0882ff8 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -713,7 +713,15 @@ static int zfpm_read_cb(struct thread *thread) nbyte = stream_read_try(ibuf, zfpm_g->sock, FPM_MSG_HDR_LEN - already); if (nbyte == 0 || nbyte == -1) { - zfpm_connection_down("closed socket in read"); + if (nbyte == -1) { + char buffer[1024]; + + sprintf(buffer, "closed socket in read(%d): %s", + errno, safe_strerror(errno)); + zfpm_connection_down(buffer); + } + else + zfpm_connection_down("closed socket in read"); return 0; } @@ -743,7 +751,15 @@ static int zfpm_read_cb(struct thread *thread) nbyte = stream_read_try(ibuf, zfpm_g->sock, msg_len - already); if (nbyte == 0 || nbyte == -1) { - zfpm_connection_down("failed to read message"); + if (nbyte == -1) { + char buffer[1024]; + + sprintf(buffer, "failed to read message(%d) %s", + errno, safe_strerror(errno)); + zfpm_connection_down(buffer); + } + else + zfpm_connection_down("failed to read message"); return 0; } diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 4c6fb002dc..61051ba87e 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -104,7 +104,7 @@ static zebra_nhlfe_t *nhlfe_add(zebra_lsp_t *lsp, enum lsp_types_t lsp_type, ifindex_t ifindex, mpls_label_t out_label); static int nhlfe_del(zebra_nhlfe_t *snhlfe); static void nhlfe_out_label_update(zebra_nhlfe_t *nhlfe, - struct nexthop_label *nh_label); + struct mpls_label_stack *nh_label); static int mpls_lsp_uninstall_all(struct hash *lsp_table, zebra_lsp_t *lsp, enum lsp_types_t type); static int mpls_static_lsp_uninstall_all(struct zebra_vrf *zvrf, @@ -457,7 +457,7 @@ static int fec_send(zebra_fec_t *fec, struct zserv *client) s = client->obuf; stream_reset(s); - zserv_create_header(s, ZEBRA_FEC_UPDATE, VRF_DEFAULT); + zclient_create_header(s, ZEBRA_FEC_UPDATE, VRF_DEFAULT); stream_putw(s, rn->p.family); stream_put_prefix(s, &rn->p); @@ -1217,7 +1217,7 @@ static int nhlfe_del(zebra_nhlfe_t *nhlfe) * Update label for NHLFE entry. */ static void nhlfe_out_label_update(zebra_nhlfe_t *nhlfe, - struct nexthop_label *nh_label) + struct mpls_label_stack *nh_label) { nhlfe->nexthop->nh_label->label[0] = nh_label->label[0]; } diff --git a/zebra/zebra_mroute.c b/zebra/zebra_mroute.c index 519c120a67..e9cd19ebe0 100644 --- a/zebra/zebra_mroute.c +++ b/zebra/zebra_mroute.c @@ -61,7 +61,7 @@ stream_failure: stream_reset(s); - zserv_create_header(s, ZEBRA_IPMR_ROUTE_STATS, zvrf_id(zvrf)); + zclient_create_header(s, ZEBRA_IPMR_ROUTE_STATS, zvrf_id(zvrf)); stream_put_in_addr(s, &mroute.sg.src); stream_put_in_addr(s, &mroute.sg.grp); stream_put(s, &mroute.lastused, sizeof(mroute.lastused)); diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c index 5ede948e0a..b3b9c6d18a 100644 --- a/zebra/zebra_ns.c +++ b/zebra/zebra_ns.c @@ -81,7 +81,7 @@ int zebra_ns_init(void) zebra_vrf_init(); - zebra_ns_enable(0, (void **)&dzns); + zebra_ns_enable(NS_DEFAULT, (void **)&dzns); return 0; } diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h index 0c340d8d59..5d90b9be67 100644 --- a/zebra/zebra_ns.h +++ b/zebra/zebra_ns.h @@ -57,9 +57,6 @@ struct zebra_ns { #endif /* HAVE_RTADV */ }; -#define NS_DEFAULT 0 -#define NS_UNKNOWN UINT16_MAX - struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id); int zebra_ns_init(void); diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index 769d2f5666..7f5fd472f1 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -432,7 +432,7 @@ static void if_bfd_session_update(struct interface *ifp, struct prefix *dp, } else { zlog_debug( "MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d " - "with src %s/%d and vrf %d %s event", + "with src %s/%d and vrf %u %s event", inet_ntop(dp->family, &dp->u.prefix, buf[0], INET6_ADDRSTRLEN), dp->prefixlen, @@ -816,6 +816,8 @@ int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, ptm_cb.out_data); zebra_ptm_send_message(ptm_cb.out_data, data_len); + return 0; + stream_failure: ptm_lib_cleanup_msg(ptm_hdl, out_ctxt); return 0; @@ -946,6 +948,8 @@ int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length, zebra_ptm_send_message(ptm_cb.out_data, data_len); + return 0; + stream_failure: ptm_lib_cleanup_msg(ptm_hdl, out_ctxt); return 0; @@ -957,7 +961,7 @@ int zebra_ptm_bfd_client_register(struct zserv *client, { struct stream *s; unsigned int pid; - void *out_ctxt; + void *out_ctxt = NULL; char tmp_buf[64]; int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; @@ -999,7 +1003,12 @@ int zebra_ptm_bfd_client_register(struct zserv *client, SET_FLAG(ptm_cb.client_flags[client->proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG); + + return 0; + stream_failure: + if (out_ctxt) + ptm_lib_cleanup_msg(ptm_hdl, out_ctxt); return 0; } diff --git a/zebra/zebra_ptm_redistribute.c b/zebra/zebra_ptm_redistribute.c index 1378ea186d..8fddd400cc 100644 --- a/zebra/zebra_ptm_redistribute.c +++ b/zebra/zebra_ptm_redistribute.c @@ -41,7 +41,7 @@ static int zsend_interface_bfd_update(int cmd, struct zserv *client, s = client->obuf; stream_reset(s); - zserv_create_header(s, cmd, vrf_id); + zclient_create_header(s, cmd, vrf_id); if (ifp) stream_putl(s, ifp->ifindex); else @@ -96,8 +96,7 @@ static int zsend_bfd_peer_replay(int cmd, struct zserv *client) s = client->obuf; stream_reset(s); - zserv_create_header( - s, cmd, VRF_DEFAULT); // Pending: adjust when multi-vrf bfd work + zclient_create_header(s, cmd, VRF_DEFAULT); /* Write packet size. */ stream_putw_at(s, 0, stream_get_endp(s)); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 41e14459b1..c200e2dbb3 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) @@ -372,6 +372,12 @@ static void nexthop_set_resolved(afi_t afi, struct nexthop *newhop, break; } + /* Copy labels of the resolved route */ + if (newhop->nh_label) + nexthop_add_labels(resolved_hop, newhop->nh_label_type, + newhop->nh_label->num_labels, + &newhop->nh_label->label[0]); + resolved_hop->rparent = nexthop; nexthop_add(&nexthop->resolved, resolved_hop); } @@ -397,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; @@ -416,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; @@ -444,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; @@ -832,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 @@ -860,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 @@ -903,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) { @@ -911,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); } @@ -990,14 +998,19 @@ int zebra_rib_labeled_unicast(struct route_entry *re) return 1; } -void kernel_route_rib_pass_fail(struct prefix *p, struct route_entry *re, +void kernel_route_rib_pass_fail(struct route_node *rn, struct prefix *p, + struct route_entry *re, enum southbound_results res) { struct nexthop *nexthop; char buf[PREFIX_STRLEN]; + rib_dest_t *dest; + + dest = rib_dest_from_rnode(rn); switch (res) { case SOUTHBOUND_INSTALL_SUCCESS: + dest->selected_fib = re; for (ALL_NEXTHOPS(re->nexthop, nexthop)) { if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) continue; @@ -1011,16 +1024,37 @@ void kernel_route_rib_pass_fail(struct prefix *p, struct route_entry *re, p, ZAPI_ROUTE_INSTALLED); break; case SOUTHBOUND_INSTALL_FAILURE: + /* + * I am not sure this is the right thing to do here + * but the code always set selected_fib before + * this assignment was moved here. + */ + dest->selected_fib = re; + zsend_route_notify_owner(re->type, re->instance, re->vrf_id, p, ZAPI_ROUTE_FAIL_INSTALL); zlog_warn("%u:%s: Route install failed", re->vrf_id, prefix2str(p, buf, sizeof(buf))); break; case SOUTHBOUND_DELETE_SUCCESS: + /* + * The case where selected_fib is not re is + * when we have received a system route + * that is overriding our installed route + * as such we should leave the selected_fib + * pointer alone + */ + if (dest->selected_fib == re) + dest->selected_fib = NULL; for (ALL_NEXTHOPS(re->nexthop, nexthop)) UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); break; case SOUTHBOUND_DELETE_FAILURE: + /* + * Should we set this to NULL if the + * delete fails? + */ + dest->selected_fib = NULL; zlog_warn("%u:%s: Route Deletion failure", re->vrf_id, prefix2str(p, buf, sizeof(buf))); break; @@ -1075,7 +1109,7 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re, * the kernel. */ hook_call(rib_update, rn, "installing in kernel"); - kernel_route_rib(p, src_p, old, re); + kernel_route_rib(rn, p, src_p, old, re); zvrf->installs++; return; @@ -1102,7 +1136,7 @@ void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re) * the kernel. */ hook_call(rib_update, rn, "uninstalling from kernel"); - kernel_route_rib(p, src_p, re, NULL); + kernel_route_rib(rn, p, src_p, re, NULL); zvrf->removals++; return; @@ -1124,8 +1158,6 @@ static void rib_uninstall(struct route_node *rn, struct route_entry *re) /* If labeled-unicast route, uninstall transit LSP. */ if (zebra_rib_labeled_unicast(re)) zebra_mpls_lsp_uninstall(info->zvrf, rn, re); - - dest->selected_fib = NULL; } if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) { @@ -1210,7 +1242,6 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, return; } - dest->selected_fib = new; if (IS_ZEBRA_DEBUG_RIB) { char buf[SRCDEST2STR_BUFFER]; srcdest_rnode2str(rn, buf, sizeof(buf)); @@ -1224,6 +1255,8 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, if (!RIB_SYSTEM_ROUTE(new)) rib_install_kernel(rn, new, NULL); + else + dest->selected_fib = new; UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED); } @@ -1248,8 +1281,17 @@ static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn, if (!RIB_SYSTEM_ROUTE(old)) rib_uninstall_kernel(rn, old); - - dest->selected_fib = NULL; + else { + /* + * We are setting this to NULL here + * because that is what we traditionally + * have been doing. I am not positive + * that this is the right thing to do + * but let's leave the code alone + * for the RIB_SYSTEM_ROUTE case + */ + dest->selected_fib = NULL; + } /* Update nexthop for route, reset changed flag. */ nexthop_active_update(rn, old, 1); @@ -1263,7 +1305,6 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf, { struct nexthop *nexthop = NULL; int nh_active = 0; - int installed = 1; rib_dest_t *dest = rib_dest_from_rnode(rn); /* @@ -1313,11 +1354,23 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf, zebra_mpls_lsp_install(zvrf, rn, new); rib_install_kernel(rn, new, old); + } else { + /* + * We do not need to install the + * selected route because it + * is already isntalled by + * the system( ie not us ) + * so just mark it as winning + * we do need to ensure that + * if we uninstall a route + * from ourselves we don't + * over write this pointer + */ + dest->selected_fib = NULL; } - /* If install succeeded or system route, cleanup flags * for prior route. */ - if (installed && new != old) { + if (new != old) { if (RIB_SYSTEM_ROUTE(new)) { if (!RIB_SYSTEM_ROUTE(old)) rib_uninstall_kernel(rn, old); @@ -1328,10 +1381,6 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf, NEXTHOP_FLAG_FIB); } } - - /* Update for redistribution. */ - if (installed) - dest->selected_fib = new; } /* @@ -1339,7 +1388,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf, * failed, we * may need to uninstall and delete for redistribution. */ - if (!nh_active || !installed) { + if (!nh_active) { if (IS_ZEBRA_DEBUG_RIB) { char buf[SRCDEST2STR_BUFFER]; srcdest_rnode2str(rn, buf, sizeof(buf)); @@ -1366,7 +1415,8 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf, if (!RIB_SYSTEM_ROUTE(old)) rib_uninstall_kernel(rn, old); - dest->selected_fib = NULL; + else + dest->selected_fib = NULL; } } else { /* @@ -1379,12 +1429,12 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf, * to add routes. */ if (!RIB_SYSTEM_ROUTE(new)) { - int in_fib = 0; + bool in_fib = false; for (ALL_NEXTHOPS(new->nexthop, nexthop)) if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) { - in_fib = 1; + in_fib = true; break; } if (!in_fib) @@ -2431,6 +2481,11 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, UNSET_FLAG(rtnh->flags, NEXTHOP_FLAG_FIB); + /* + * This is a non FRR route + * as such we should mark + * it as deleted + */ dest->selected_fib = NULL; } else { /* This means someone else, other than Zebra, @@ -2496,9 +2551,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; @@ -2514,6 +2570,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 33d0b3a641..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; @@ -1000,7 +1002,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, s = client->obuf; stream_reset(s); - zserv_create_header(s, cmd, vrf_id); + zclient_create_header(s, cmd, vrf_id); stream_putw(s, rn->p.family); switch (rn->p.family) { diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index 61af60b5da..4c619e5782 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -1193,7 +1193,7 @@ static void *route_set_src_compile(const char *arg) union g_addr src, *psrc; if ((inet_pton(AF_INET6, arg, &src.ipv6) == 1) - || (src.ipv4.s_addr && (inet_pton(AF_INET, arg, &src.ipv4) == 1))) { + || (inet_pton(AF_INET, arg, &src.ipv4) == 1)) { psrc = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(union g_addr)); *psrc = src; return psrc; @@ -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 751ea08a38..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,8 +155,9 @@ 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 + (si->vrf_id != VRF_DEFAULT) ? (zebra_vrf_lookup_by_id(si->vrf_id))->table_id : zebrad.rtm_table_default; re->nexthop_num = 0; @@ -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..246a7e7e4c 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -456,6 +456,7 @@ struct route_table *zebra_vrf_other_route_table(afi_t afi, u_int32_t table_id, info->afi = afi; info->safi = SAFI_UNICAST; table->info = info; + table->cleanup = zebra_rtable_node_cleanup; zvrf->other_table[afi][table_id] = table; } @@ -476,12 +477,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 82b0157ad3..f0be862221 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,89 @@ 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); + + zvrf = zebra_vrf_lookup_by_name(vrf); + if (!zvrf) { + vty_out(vty, "%% vrf %s is not defined\n", + vrf); + return CMD_WARNING_CONFIG_FAILED; + } + + if (nexthop_vrf) + nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf); + else + nh_zvrf = zvrf; + + 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_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 +558,7 @@ DEFPY(ip_route, |(1-255)$distance \ |vrf NAME \ |label WORD \ + |nexthop-vrf NAME \ }]", NO_STR IP_STR "Establish static routes\n" @@ -445,16 +571,88 @@ 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); + + zvrf = zebra_vrf_lookup_by_name(vrf); + if (!zvrf) { + vty_out(vty, "%% vrf %s is not defined\n", + vrf); + return CMD_WARNING_CONFIG_FAILED; + } + + if (nexthop_vrf) + nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf); + else + nh_zvrf = zvrf; + + 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_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 +737,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 +747,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 +774,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 +921,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 +940,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 +953,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 +980,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 +1095,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 +1105,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 +1132,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"); @@ -1181,7 +1404,7 @@ DEFUN (ip_nht_default_route, return CMD_SUCCESS; zebra_rnh_ip_default_route = 1; - zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(VRF_DEFAULT, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -1197,7 +1420,7 @@ DEFUN (no_ip_nht_default_route, return CMD_SUCCESS; zebra_rnh_ip_default_route = 0; - zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(VRF_DEFAULT, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -1212,7 +1435,7 @@ DEFUN (ipv6_nht_default_route, return CMD_SUCCESS; zebra_rnh_ipv6_default_route = 1; - zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(VRF_DEFAULT, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -1228,7 +1451,7 @@ DEFUN (no_ipv6_nht_default_route, return CMD_SUCCESS; zebra_rnh_ipv6_default_route = 0; - zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(VRF_DEFAULT, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -1603,97 +1826,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; + + 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)); + /* 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"); + vty_out(vty, "\n"); - write = 1; - } - } + write = 1; + } return write; } @@ -1727,6 +1951,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 +1993,7 @@ DEFPY(ipv6_route_address_interface, |(1-255)$distance \ |vrf NAME \ |label WORD \ + |nexthop-vrf NAME \ }]", NO_STR IPV6_STR @@ -1750,11 +2007,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 +2084,7 @@ DEFPY(ipv6_route, |(1-255)$distance \ |vrf NAME \ |label WORD \ + |nexthop-vrf NAME \ }]", NO_STR IPV6_STR @@ -1779,11 +2098,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); } /* @@ -1890,7 +2269,7 @@ DEFUN (show_vrf, RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { if (!(zvrf = vrf->info)) continue; - if (!zvrf_id(zvrf)) + if (zvrf_id(zvrf) == VRF_DEFAULT) continue; vty_out(vty, "vrf %s ", zvrf_name(zvrf)); @@ -2419,11 +2798,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 +3235,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 +3261,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/zebra_vxlan.c b/zebra/zebra_vxlan.c index 0ef1802367..1690079f68 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -1166,7 +1166,7 @@ static int zvni_macip_send_msg_to_client(vni_t vni, s = client->obuf; stream_reset(s); - zserv_create_header(s, cmd, VRF_DEFAULT); + zclient_create_header(s, cmd, VRF_DEFAULT); stream_putl(s, vni); stream_put(s, macaddr->octet, ETH_ALEN); if (ip) { @@ -2531,7 +2531,7 @@ static int zvni_send_add_to_client(zebra_vni_t *zvni) s = client->obuf; stream_reset(s); - zserv_create_header(s, ZEBRA_VNI_ADD, VRF_DEFAULT); + zclient_create_header(s, ZEBRA_VNI_ADD, VRF_DEFAULT); stream_putl(s, zvni->vni); stream_put_in_addr(s, &zvni->local_vtep_ip); stream_put(s, &zvni->vrf_id, sizeof(vrf_id_t)); /* tenant vrf */ @@ -2565,7 +2565,7 @@ static int zvni_send_del_to_client(vni_t vni) s = client->obuf; stream_reset(s); - zserv_create_header(s, ZEBRA_VNI_DEL, VRF_DEFAULT); + zclient_create_header(s, ZEBRA_VNI_DEL, VRF_DEFAULT); stream_putl(s, vni); /* Write packet size. */ @@ -3550,7 +3550,7 @@ static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni) s = client->obuf; stream_reset(s); - zserv_create_header(s, ZEBRA_L3VNI_ADD, + zclient_create_header(s, ZEBRA_L3VNI_ADD, zl3vni_vrf_id(zl3vni)); stream_putl(s, zl3vni->vni); stream_put(s, &rmac, sizeof(struct ethaddr)); @@ -3586,7 +3586,7 @@ static int zl3vni_send_del_to_client(zebra_l3vni_t *zl3vni) s = client->obuf; stream_reset(s); - zserv_create_header(s, ZEBRA_L3VNI_DEL, + zclient_create_header(s, ZEBRA_L3VNI_DEL, zl3vni_vrf_id(zl3vni)); stream_putl(s, zl3vni->vni); diff --git a/zebra/zserv.c b/zebra/zserv.c index 7eded89f6d..3ee2bb59ec 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -149,16 +149,6 @@ int zebra_server_send_message(struct zserv *client) return 0; } -void zserv_create_header(struct stream *s, uint16_t cmd, vrf_id_t vrf_id) -{ - /* length placeholder, caller can update */ - stream_putw(s, ZEBRA_HEADER_SIZE); - stream_putc(s, ZEBRA_HEADER_MARKER); - stream_putc(s, ZSERV_VERSION); - stream_putw(s, vrf_id); - stream_putw(s, cmd); -} - static void zserv_encode_interface(struct stream *s, struct interface *ifp) { /* Interface information. */ @@ -221,7 +211,7 @@ int zsend_interface_add(struct zserv *client, struct interface *ifp) s = client->obuf; stream_reset(s); - zserv_create_header(s, ZEBRA_INTERFACE_ADD, ifp->vrf_id); + zclient_create_header(s, ZEBRA_INTERFACE_ADD, ifp->vrf_id); zserv_encode_interface(s, ifp); client->ifadd_cnt++; @@ -236,7 +226,7 @@ int zsend_interface_delete(struct zserv *client, struct interface *ifp) s = client->obuf; stream_reset(s); - zserv_create_header(s, ZEBRA_INTERFACE_DELETE, ifp->vrf_id); + zclient_create_header(s, ZEBRA_INTERFACE_DELETE, ifp->vrf_id); zserv_encode_interface(s, ifp); client->ifdel_cnt++; @@ -250,7 +240,7 @@ int zsend_vrf_add(struct zserv *client, struct zebra_vrf *zvrf) s = client->obuf; stream_reset(s); - zserv_create_header(s, ZEBRA_VRF_ADD, zvrf_id(zvrf)); + zclient_create_header(s, ZEBRA_VRF_ADD, zvrf_id(zvrf)); zserv_encode_vrf(s, zvrf); client->vrfadd_cnt++; @@ -265,7 +255,7 @@ int zsend_vrf_delete(struct zserv *client, struct zebra_vrf *zvrf) s = client->obuf; stream_reset(s); - zserv_create_header(s, ZEBRA_VRF_DELETE, zvrf_id(zvrf)); + zclient_create_header(s, ZEBRA_VRF_DELETE, zvrf_id(zvrf)); zserv_encode_vrf(s, zvrf); client->vrfdel_cnt++; @@ -285,7 +275,7 @@ int zsend_interface_link_params(struct zserv *client, struct interface *ifp) s = client->obuf; stream_reset(s); - zserv_create_header(s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf_id); + zclient_create_header(s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf_id); /* Add Interface Index */ stream_putl(s, ifp->ifindex); @@ -348,7 +338,7 @@ int zsend_interface_address(int cmd, struct zserv *client, s = client->obuf; stream_reset(s); - zserv_create_header(s, cmd, ifp->vrf_id); + zclient_create_header(s, cmd, ifp->vrf_id); stream_putl(s, ifp->ifindex); /* Interface address flag. */ @@ -393,7 +383,7 @@ static int zsend_interface_nbr_address(int cmd, struct zserv *client, s = client->obuf; stream_reset(s); - zserv_create_header(s, cmd, ifp->vrf_id); + zclient_create_header(s, cmd, ifp->vrf_id); stream_putl(s, ifp->ifindex); /* Prefix information. */ @@ -504,11 +494,11 @@ int zsend_interface_vrf_update(struct zserv *client, struct interface *ifp, s = client->obuf; stream_reset(s); - zserv_create_header(s, ZEBRA_INTERFACE_VRF_UPDATE, ifp->vrf_id); + zclient_create_header(s, ZEBRA_INTERFACE_VRF_UPDATE, ifp->vrf_id); /* Fill in the ifIndex of the interface and its new VRF (id) */ stream_putl(s, ifp->ifindex); - stream_putw(s, vrf_id); + stream_putl(s, vrf_id); /* Write packet size. */ stream_putw_at(s, 0, stream_get_endp(s)); @@ -581,7 +571,7 @@ int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp) s = client->obuf; stream_reset(s); - zserv_create_header(s, cmd, ifp->vrf_id); + zclient_create_header(s, cmd, ifp->vrf_id); zserv_encode_interface(s, ifp); if (cmd == ZEBRA_INTERFACE_UP) @@ -602,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; @@ -957,7 +948,7 @@ static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client, stream_reset(s); /* Fill in result. */ - zserv_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, zvrf_id(zvrf)); + zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, zvrf_id(zvrf)); stream_put_in_addr(s, &addr); if (re) { @@ -1009,7 +1000,7 @@ int zsend_route_notify_owner(u_char proto, u_short instance, s = client->obuf; stream_reset(s); - zserv_create_header(s, ZEBRA_ROUTE_NOTIFY_OWNER, vrf_id); + zclient_create_header(s, ZEBRA_ROUTE_NOTIFY_OWNER, vrf_id); stream_put(s, ¬e, sizeof(note)); @@ -1039,7 +1030,7 @@ int zsend_router_id_update(struct zserv *client, struct prefix *p, stream_reset(s); /* Message type. */ - zserv_create_header(s, ZEBRA_ROUTER_ID_UPDATE, vrf_id); + zclient_create_header(s, ZEBRA_ROUTER_ID_UPDATE, vrf_id); /* Prefix information. */ stream_putc(s, p->family); @@ -1063,7 +1054,7 @@ int zsend_pw_update(struct zserv *client, struct zebra_pw *pw) s = client->obuf; stream_reset(s); - zserv_create_header(s, ZEBRA_PW_STATUS_UPDATE, pw->vrf_id); + zclient_create_header(s, ZEBRA_PW_STATUS_UPDATE, pw->vrf_id); stream_write(s, pw->ifname, IF_NAMESIZE); stream_putl(s, pw->ifindex); stream_putl(s, pw->status); @@ -1146,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)) { @@ -1372,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)) { @@ -1581,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 @@ -1866,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); @@ -2089,7 +2085,7 @@ static int zsend_label_manager_connect_response(struct zserv *client, s = client->obuf; stream_reset(s); - zserv_create_header(s, ZEBRA_LABEL_MANAGER_CONNECT, vrf_id); + zclient_create_header(s, ZEBRA_LABEL_MANAGER_CONNECT, vrf_id); /* result */ stream_putc(s, result); @@ -2151,7 +2147,7 @@ static int zsend_assign_label_chunk_response(struct zserv *client, s = client->obuf; stream_reset(s); - zserv_create_header(s, ZEBRA_GET_LABEL_CHUNK, vrf_id); + zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, vrf_id); if (lmc) { /* keep */ @@ -2472,11 +2468,11 @@ static int zread_interface_set_master(struct zserv *client, int ifindex; vrf_id_t vrf_id; - STREAM_GETW(s, vrf_id); + STREAM_GETL(s, vrf_id); STREAM_GETL(s, ifindex); master = if_lookup_by_index(ifindex, vrf_id); - STREAM_GETW(s, vrf_id); + STREAM_GETL(s, vrf_id); STREAM_GETL(s, ifindex); slave = if_lookup_by_index(ifindex, vrf_id); @@ -2714,7 +2710,7 @@ static int zebra_client_read(struct thread *thread) STREAM_GETW(client->ibuf, length); STREAM_GETC(client->ibuf, marker); STREAM_GETC(client->ibuf, version); - STREAM_GETW(client->ibuf, vrf_id); + STREAM_GETL(client->ibuf, vrf_id); STREAM_GETW(client->ibuf, command); if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) { diff --git a/zebra/zserv.h b/zebra/zserv.h index 63db9d9eb9..4b3b0041b8 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -177,8 +177,6 @@ extern int zsend_route_notify_owner(u_char proto, u_short instance, vrf_id_t vrf_id, struct prefix *p, enum zapi_route_notify_owner note); -extern void zserv_create_header(struct stream *s, uint16_t cmd, - vrf_id_t vrf_id); extern void zserv_nexthop_num_warn(const char *, const struct prefix *, const unsigned int); extern int zebra_server_send_message(struct zserv *client); |
