diff options
Diffstat (limited to 'zebra')
60 files changed, 1060 insertions, 329 deletions
diff --git a/zebra/connected.c b/zebra/connected.c index 128f397552..7114a3286b 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -272,7 +272,7 @@ void connected_up(struct interface *ifp, struct connected *ifc) ifp->vrf_id, ifp->name, prefix2str(&p, buf, sizeof(buf))); } - mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id)); + mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id), &p); } } @@ -437,7 +437,7 @@ void connected_down(struct interface *ifp, struct connected *ifc) ifp->vrf_id, ifp->name, prefix2str(&p, buf, sizeof(buf))); } - mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id)); + mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id), &p); } } @@ -471,7 +471,7 @@ static void connected_delete_helper(struct connected *ifc, struct prefix *p) ifp->vrf_id, ifp->name, prefix2str(p, buf, sizeof(buf))); } - mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id)); + mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id), p); } } diff --git a/zebra/connected.h b/zebra/connected.h index faba30b0d5..7672bec006 100644 --- a/zebra/connected.h +++ b/zebra/connected.h @@ -28,6 +28,10 @@ #include "lib/if.h" #include "lib/prefix.h" +#ifdef __cplusplus +extern "C" { +#endif + extern struct connected *connected_check(struct interface *ifp, union prefixconstptr p); extern struct connected *connected_check_ptp(struct interface *ifp, @@ -58,4 +62,7 @@ extern void connected_delete_ipv6(struct interface *ifp, extern int connected_is_unnumbered(struct interface *); +#ifdef __cplusplus +} +#endif #endif /*_ZEBRA_CONNECTED_H */ diff --git a/zebra/debug.c b/zebra/debug.c index 87999a1bbc..8e5fb0ea10 100644 --- a/zebra/debug.c +++ b/zebra/debug.c @@ -87,7 +87,9 @@ DEFUN_NOSH (show_debugging_zebra, if (IS_ZEBRA_DEBUG_FPM) vty_out(vty, " Zebra FPM debugging is on\n"); - if (IS_ZEBRA_DEBUG_NHT) + if (IS_ZEBRA_DEBUG_NHT_DETAILED) + vty_out(vty, " Zebra detailed next-hop tracking debugging is on\n"); + else if (IS_ZEBRA_DEBUG_NHT) vty_out(vty, " Zebra next-hop tracking debugging is on\n"); if (IS_ZEBRA_DEBUG_MPLS) vty_out(vty, " Zebra MPLS debugging is on\n"); @@ -119,12 +121,19 @@ DEFUN (debug_zebra_events, DEFUN (debug_zebra_nht, debug_zebra_nht_cmd, - "debug zebra nht", + "debug zebra nht [detailed]", DEBUG_STR "Zebra configuration\n" - "Debug option set for zebra next hop tracking\n") + "Debug option set for zebra next hop tracking\n" + "Debug option set for detailed info\n") { + int idx = 0; + zebra_debug_nht = ZEBRA_DEBUG_NHT; + + if (argv_find(argv, argc, "detailed", &idx)) + zebra_debug_nht |= ZEBRA_DEBUG_NHT_DETAILED; + return CMD_SUCCESS; } @@ -320,11 +329,12 @@ DEFUN (no_debug_zebra_events, DEFUN (no_debug_zebra_nht, no_debug_zebra_nht_cmd, - "no debug zebra nht", + "no debug zebra nht [detailed]", NO_STR DEBUG_STR "Zebra configuration\n" - "Debug option set for zebra next hop tracking\n") + "Debug option set for zebra next hop tracking\n" + "Debug option set for detailed info\n") { zebra_debug_nht = 0; return CMD_SUCCESS; @@ -490,10 +500,15 @@ static int config_write_debug(struct vty *vty) vty_out(vty, "debug zebra fpm\n"); write++; } - if (IS_ZEBRA_DEBUG_NHT) { + + if (IS_ZEBRA_DEBUG_NHT_DETAILED) { + vty_out(vty, "debug zebra nht detailed\n"); + write++; + } else if (IS_ZEBRA_DEBUG_NHT) { vty_out(vty, "debug zebra nht\n"); write++; } + if (IS_ZEBRA_DEBUG_MPLS) { vty_out(vty, "debug zebra mpls\n"); write++; @@ -530,6 +545,7 @@ void zebra_debug_init(void) zebra_debug_pw = 0; zebra_debug_dplane = 0; zebra_debug_mlag = 0; + zebra_debug_nht = 0; install_node(&debug_node, config_write_debug); diff --git a/zebra/debug.h b/zebra/debug.h index c79cd96c21..176226f7ae 100644 --- a/zebra/debug.h +++ b/zebra/debug.h @@ -24,6 +24,10 @@ #include "lib/vty.h" +#ifdef __cplusplus +extern "C" { +#endif + /* Debug flags. */ #define ZEBRA_DEBUG_EVENT 0x01 @@ -40,7 +44,9 @@ #define ZEBRA_DEBUG_RIB_DETAILED 0x02 #define ZEBRA_DEBUG_FPM 0x01 -#define ZEBRA_DEBUG_NHT 0x01 + +#define ZEBRA_DEBUG_NHT 0x01 +#define ZEBRA_DEBUG_NHT_DETAILED 0x02 #define ZEBRA_DEBUG_MPLS 0x01 @@ -72,7 +78,10 @@ #define IS_ZEBRA_DEBUG_RIB_DETAILED (zebra_debug_rib & ZEBRA_DEBUG_RIB_DETAILED) #define IS_ZEBRA_DEBUG_FPM (zebra_debug_fpm & ZEBRA_DEBUG_FPM) + #define IS_ZEBRA_DEBUG_NHT (zebra_debug_nht & ZEBRA_DEBUG_NHT) +#define IS_ZEBRA_DEBUG_NHT_DETAILED (zebra_debug_nht & ZEBRA_DEBUG_NHT_DETAILED) + #define IS_ZEBRA_DEBUG_MPLS (zebra_debug_mpls & ZEBRA_DEBUG_MPLS) #define IS_ZEBRA_DEBUG_VXLAN (zebra_debug_vxlan & ZEBRA_DEBUG_VXLAN) #define IS_ZEBRA_DEBUG_PW (zebra_debug_pw & ZEBRA_DEBUG_PW) @@ -99,4 +108,8 @@ extern void zebra_debug_init(void); DECLARE_HOOK(zebra_debug_show_debugging, (struct vty *vty), (vty)); +#ifdef __cplusplus +} +#endif + #endif /* _ZEBRA_DEBUG_H */ diff --git a/zebra/if_netlink.h b/zebra/if_netlink.h index 65a266a519..710fd52558 100644 --- a/zebra/if_netlink.h +++ b/zebra/if_netlink.h @@ -23,11 +23,19 @@ #ifdef HAVE_NETLINK +#ifdef __cplusplus +extern "C" { +#endif + extern int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup); extern int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup); extern int interface_lookup_netlink(struct zebra_ns *zns); +#ifdef __cplusplus +} +#endif + #endif /* HAVE_NETLINK */ #endif /* _ZEBRA_IF_NETLINK_H */ diff --git a/zebra/interface.h b/zebra/interface.h index 1dbcf33fad..ce404e8253 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -28,6 +28,10 @@ #include "zebra/zebra_l2.h" +#ifdef __cplusplus +extern "C" { +#endif + /* For interface multicast configuration. */ #define IF_ZEBRA_MULTICAST_UNSPEC 0 #define IF_ZEBRA_MULTICAST_ON 1 @@ -432,4 +436,8 @@ extern int interface_list_proc(void); extern int ifaddr_proc_ipv6(void); #endif /* HAVE_PROC_NET_IF_INET6 */ +#ifdef __cplusplus +} +#endif + #endif /* _ZEBRA_INTERFACE_H */ diff --git a/zebra/ioctl.h b/zebra/ioctl.h index 2a8ea77909..67ffd45a08 100644 --- a/zebra/ioctl.h +++ b/zebra/ioctl.h @@ -22,6 +22,10 @@ #ifndef _ZEBRA_IOCTL_H #define _ZEBRA_IOCTL_H +#ifdef __cplusplus +extern "C" { +#endif + /* Prototypes. */ extern void ifreq_set_name(struct ifreq *, struct interface *); extern int if_ioctl(unsigned long, caddr_t); @@ -53,4 +57,8 @@ extern struct connected *if_lookup_linklocal(struct interface *); #endif /* SOLARIS_IPV6 */ +#ifdef __cplusplus +} +#endif + #endif /* _ZEBRA_IOCTL_H */ diff --git a/zebra/ioctl_solaris.h b/zebra/ioctl_solaris.h index 3507e563cd..363f382896 100644 --- a/zebra/ioctl_solaris.h +++ b/zebra/ioctl_solaris.h @@ -22,7 +22,15 @@ #ifndef _ZEBRA_IF_IOCTL_SOLARIS_H #define _ZEBRA_IF_IOCTL_SOLARIS_H +#ifdef __cplusplus +extern "C" { +#endif + void lifreq_set_name(struct lifreq *, const char *); int if_get_flags_direct(const char *, uint64_t *, unsigned int af); +#ifdef __cplusplus +} +#endif + #endif /* _ZEBRA_IF_IOCTL_SOLARIS_H */ diff --git a/zebra/ipforward.h b/zebra/ipforward.h index fe9f2db911..9884678c7a 100644 --- a/zebra/ipforward.h +++ b/zebra/ipforward.h @@ -21,6 +21,10 @@ #ifndef _ZEBRA_IPFORWARD_H #define _ZEBRA_IPFORWARD_H +#ifdef __cplusplus +extern "C" { +#endif + extern int ipforward(void); extern int ipforward_on(void); extern int ipforward_off(void); @@ -29,4 +33,8 @@ extern int ipforward_ipv6(void); extern int ipforward_ipv6_on(void); extern int ipforward_ipv6_off(void); +#ifdef __cplusplus +} +#endif + #endif /* _ZEBRA_IPFORWARD_H */ diff --git a/zebra/irdp.h b/zebra/irdp.h index 4800e75be3..3f4fa93460 100644 --- a/zebra/irdp.h +++ b/zebra/irdp.h @@ -28,6 +28,10 @@ #include "lib/vty.h" +#ifdef __cplusplus +extern "C" { +#endif + #define TRUE 1 #define FALSE 0 @@ -150,5 +154,8 @@ extern int irdp_read_raw(struct thread *r); extern void send_packet(struct interface *ifp, struct stream *s, uint32_t dst, struct prefix *p, uint32_t ttl); +#ifdef __cplusplus +} +#endif #endif /* _IRDP_H */ diff --git a/zebra/irdp_main.c b/zebra/irdp_main.c index a9734056bc..38d241eaa5 100644 --- a/zebra/irdp_main.c +++ b/zebra/irdp_main.c @@ -241,7 +241,7 @@ int irdp_send_thread(struct thread *t_advert) timer = MAX_INITIAL_ADVERT_INTERVAL; if (irdp->flags & IF_DEBUG_MISC) - zlog_debug("IRDP: New timer for %s set to %u\n", ifp->name, + zlog_debug("IRDP: New timer for %s set to %u", ifp->name, timer); irdp->t_advertise = NULL; diff --git a/zebra/irdp_packet.c b/zebra/irdp_packet.c index 774d84d66d..2804787620 100644 --- a/zebra/irdp_packet.c +++ b/zebra/irdp_packet.c @@ -166,7 +166,7 @@ static void parse_irdp_packet(char *p, int len, struct interface *ifp) case ICMP_ROUTERSOLICIT: if (irdp->flags & IF_DEBUG_MESSAGES) - zlog_debug("IRDP: RX Solicit on %s from %s\n", + zlog_debug("IRDP: RX Solicit on %s from %s", ifp->name, inet_ntoa(src)); process_solicit(ifp); @@ -253,7 +253,7 @@ int irdp_read_raw(struct thread *r) if (!(irdp->flags & IF_ACTIVE)) { if (irdp->flags & IF_DEBUG_MISC) - zlog_debug("IRDP: RX ICMP for disabled interface %s\n", + zlog_debug("IRDP: RX ICMP for disabled interface %s", ifp->name); return 0; } diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 2f850c6338..fe37a33358 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -606,53 +606,59 @@ const char *nl_rttype_to_str(uint8_t rttype) return lookup_msg(rttype_str, rttype, ""); } -#define NL_OK(nla, len) \ +#define NLA_OK(nla, len) \ ((len) >= (int)sizeof(struct nlattr) \ && (nla)->nla_len >= sizeof(struct nlattr) \ && (nla)->nla_len <= (len)) -#define NL_NEXT(nla, attrlen) \ - ((attrlen) -= RTA_ALIGN((nla)->nla_len), \ - (struct nlattr *)(((char *)(nla)) + RTA_ALIGN((nla)->nla_len))) -#define NL_RTA(r) \ - ((struct nlattr *)(((char *)(r)) \ - + NLMSG_ALIGN(sizeof(struct nlmsgerr)))) +#define NLA_NEXT(nla, attrlen) \ + ((attrlen) -= NLA_ALIGN((nla)->nla_len), \ + (struct nlattr *)(((char *)(nla)) + NLA_ALIGN((nla)->nla_len))) +#define NLA_LENGTH(len) (NLA_ALIGN(sizeof(struct nlattr)) + (len)) +#define NLA_DATA(nla) ((struct nlattr *)(((char *)(nla)) + NLA_LENGTH(0))) + +#define ERR_NLA(err, inner_len) \ + ((struct nlattr *)(((char *)(err)) \ + + NLMSG_ALIGN(sizeof(struct nlmsgerr)) \ + + NLMSG_ALIGN((inner_len)))) static void netlink_parse_nlattr(struct nlattr **tb, int max, struct nlattr *nla, int len) { - while (NL_OK(nla, len)) { + while (NLA_OK(nla, len)) { if (nla->nla_type <= max) tb[nla->nla_type] = nla; - nla = NL_NEXT(nla, len); + nla = NLA_NEXT(nla, len); } } static void netlink_parse_extended_ack(struct nlmsghdr *h) { - struct nlattr *tb[NLMSGERR_ATTR_MAX + 1]; - const struct nlmsgerr *err = - (const struct nlmsgerr *)((uint8_t *)h - + NLMSG_ALIGN( - sizeof(struct nlmsghdr))); + struct nlattr *tb[NLMSGERR_ATTR_MAX + 1] = {}; + const struct nlmsgerr *err = (const struct nlmsgerr *)NLMSG_DATA(h); const struct nlmsghdr *err_nlh = NULL; - uint32_t hlen = sizeof(*err); + /* Length not including nlmsghdr */ + uint32_t len = 0; + /* Inner error netlink message length */ + uint32_t inner_len = 0; const char *msg = NULL; uint32_t off = 0; if (!(h->nlmsg_flags & NLM_F_CAPPED)) - hlen += h->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr)); + inner_len = (uint32_t)NLMSG_PAYLOAD(&err->msg, 0); + + len = (uint32_t)(NLMSG_PAYLOAD(h, sizeof(struct nlmsgerr)) - inner_len); - memset(tb, 0, sizeof(tb)); - netlink_parse_nlattr(tb, NLMSGERR_ATTR_MAX, NL_RTA(h), hlen); + netlink_parse_nlattr(tb, NLMSGERR_ATTR_MAX, ERR_NLA(err, inner_len), + len); if (tb[NLMSGERR_ATTR_MSG]) - msg = (const char *)RTA_DATA(tb[NLMSGERR_ATTR_MSG]); + msg = (const char *)NLA_DATA(tb[NLMSGERR_ATTR_MSG]); if (tb[NLMSGERR_ATTR_OFFS]) { - off = *(uint32_t *)RTA_DATA(tb[NLMSGERR_ATTR_OFFS]); + off = *(uint32_t *)NLA_DATA(tb[NLMSGERR_ATTR_OFFS]); if (off > h->nlmsg_len) { - zlog_err("Invalid offset for NLMSGERR_ATTR_OFFS\n"); + zlog_err("Invalid offset for NLMSGERR_ATTR_OFFS"); } else if (!(h->nlmsg_flags & NLM_F_CAPPED)) { /* * Header of failed message diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h index 9918729eb6..076ca5c5c7 100644 --- a/zebra/kernel_netlink.h +++ b/zebra/kernel_netlink.h @@ -21,6 +21,10 @@ #ifndef _ZEBRA_KERNEL_NETLINK_H #define _ZEBRA_KERNEL_NETLINK_H +#ifdef __cplusplus +extern "C" { +#endif + #ifdef HAVE_NETLINK #define NL_RCV_PKT_BUF_SIZE 32768 @@ -68,4 +72,8 @@ extern int netlink_request(struct nlsock *nl, struct nlmsghdr *n); #endif /* HAVE_NETLINK */ +#ifdef __cplusplus +} +#endif + #endif /* _ZEBRA_KERNEL_NETLINK_H */ diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 792756efeb..1bbb98ad19 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -148,7 +148,9 @@ const struct message rtm_type_str[] = {{RTM_ADD, "RTM_ADD"}, #ifdef RTM_OLDDEL {RTM_OLDDEL, "RTM_OLDDEL"}, #endif /* RTM_OLDDEL */ +#ifdef RTM_RESOLVE {RTM_RESOLVE, "RTM_RESOLVE"}, +#endif /* RTM_RESOLVE */ {RTM_NEWADDR, "RTM_NEWADDR"}, {RTM_DELADDR, "RTM_DELADDR"}, {RTM_IFINFO, "RTM_IFINFO"}, @@ -622,7 +624,7 @@ int ifm_read(struct if_msghdr *ifm) * RTA_IFP) is required. */ if (!ifnlen) { - zlog_debug("Interface index %d (new) missing ifname\n", + zlog_debug("Interface index %d (new) missing ifname", ifm->ifm_index); return -1; } diff --git a/zebra/kernel_socket.h b/zebra/kernel_socket.h index 096a21f782..15079d796d 100644 --- a/zebra/kernel_socket.h +++ b/zebra/kernel_socket.h @@ -22,6 +22,10 @@ #ifndef __ZEBRA_KERNEL_SOCKET_H #define __ZEBRA_KERNEL_SOCKET_H +#ifdef __cplusplus +extern "C" { +#endif + /* Error codes of zebra. */ #define ZEBRA_ERR_NOERROR 0 #define ZEBRA_ERR_RTEXIST -1 @@ -38,4 +42,8 @@ extern int rtm_write(int, union sockunion *, union sockunion *, enum blackhole_type, int); extern const struct message rtm_type_str[]; +#ifdef __cplusplus +} +#endif + #endif /* __ZEBRA_KERNEL_SOCKET_H */ diff --git a/zebra/label_manager.h b/zebra/label_manager.h index 3e3def5f98..3ea89fbfc3 100644 --- a/zebra/label_manager.h +++ b/zebra/label_manager.h @@ -31,6 +31,10 @@ #include "zebra/zserv.h" +#ifdef __cplusplus +extern "C" { +#endif + #define NO_PROTO 0 /* @@ -74,4 +78,8 @@ int release_label_chunk(uint8_t proto, unsigned short instance, uint32_t start, int release_daemon_label_chunks(struct zserv *client); void label_manager_close(void); +#ifdef __cplusplus +} +#endif + #endif /* _LABEL_MANAGER_H */ diff --git a/zebra/main.c b/zebra/main.c index c605050c57..184e798bd0 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -153,7 +153,9 @@ static void sigint(void) for (ALL_LIST_ELEMENTS(zrouter.client_list, ln, nn, client)) zserv_close_client(client); + zserv_close(); list_delete_all_node(zrouter.client_list); + zebra_ptm_finish(); if (retain_mode) diff --git a/zebra/redistribute.h b/zebra/redistribute.h index f0dc79574c..74a593b240 100644 --- a/zebra/redistribute.h +++ b/zebra/redistribute.h @@ -29,6 +29,10 @@ #include "zebra/zserv.h" #include "zebra/rib.h" +#ifdef __cplusplus +extern "C" { +#endif + /* ZAPI command handlers */ extern void zebra_redistribute_add(ZAPI_HANDLER_ARGS); extern void zebra_redistribute_delete(ZAPI_HANDLER_ARGS); @@ -73,4 +77,9 @@ extern int is_zebra_import_table_enabled(afi_t, uint32_t table_id); extern int zebra_import_table_config(struct vty *); extern void zebra_import_table_rm_update(const char *rmap); + +#ifdef __cplusplus +} +#endif + #endif /* _ZEBRA_REDISTRIBUTE_H */ diff --git a/zebra/rib.h b/zebra/rib.h index a478fffddb..e26831e1a6 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -35,6 +35,10 @@ #include "mpls.h" #include "srcdest_table.h" +#ifdef __cplusplus +extern "C" { +#endif + #define DISTANCE_INFINITY 255 #define ZEBRA_KERNEL_TABLE_MAX 252 /* support for no more than this rt tables */ @@ -141,6 +145,15 @@ typedef struct rib_dest_t_ { uint32_t flags; /* + * The list of nht prefixes that have ended up + * depending on this route node. + * After route processing is returned from + * the data plane we will run evaluate_rnh + * on these prefixes. + */ + struct list *nht; + + /* * Linkage to put dest on the FPM processing queue. */ TAILQ_ENTRY(rib_dest_t_) fpm_q_entries; @@ -168,6 +181,8 @@ typedef struct rib_dest_t_ { */ #define RIB_DEST_UPDATE_FPM (1 << (ZEBRA_MAX_QINDEX + 2)) +#define RIB_DEST_UPDATE_LSPS (1 << (ZEBRA_MAX_QINDEX + 3)) + /* * Macro to iterate over each route for a destination (prefix). */ @@ -355,6 +370,8 @@ extern struct route_table *rib_tables_iter_next(rib_tables_iter_t *iter); extern uint8_t route_distance(int type); +extern void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq); + /* * Inline functions. */ @@ -427,6 +444,11 @@ static inline struct zebra_vrf *rib_dest_vrf(rib_dest_t *dest) } /* + * Create the rib_dest_t and attach it to the specified node + */ +extern rib_dest_t *zebra_rib_create_dest(struct route_node *rn); + +/* * rib_tables_iter_init */ static inline void rib_tables_iter_init(rib_tables_iter_t *iter) @@ -464,4 +486,9 @@ extern void zebra_vty_init(void); extern pid_t pid; extern bool v6_rr_semantics; + +#ifdef __cplusplus +} +#endif + #endif /*_ZEBRA_RIB_H */ diff --git a/zebra/router-id.h b/zebra/router-id.h index 6b15159fdb..f7d16853f1 100644 --- a/zebra/router-id.h +++ b/zebra/router-id.h @@ -30,6 +30,10 @@ #include "zclient.h" #include "if.h" +#ifdef __cplusplus +extern "C" { +#endif + extern void router_id_add_address(struct connected *); extern void router_id_del_address(struct connected *); extern void router_id_init(struct zebra_vrf *); @@ -37,4 +41,8 @@ extern void router_id_cmd_init(void); extern void router_id_write(struct vty *); extern void router_id_get(struct prefix *, vrf_id_t); +#ifdef __cplusplus +} +#endif + #endif diff --git a/zebra/rt.h b/zebra/rt.h index 4080b0ccb2..2c77af2aad 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -31,6 +31,13 @@ #include "zebra/zebra_mpls.h" #include "zebra/zebra_dplane.h" +#ifdef __cplusplus +extern "C" { +#endif + +#define RSYSTEM_ROUTE(type) \ + ((type) == ZEBRA_ROUTE_KERNEL || (type) == ZEBRA_ROUTE_CONNECT) + /* * Update or delete a route, LSP, or pseudowire from the kernel, * using info from a dataplane context. @@ -91,4 +98,8 @@ extern void neigh_read_specific_ip(struct ipaddr *ip, struct interface *vlan_if); extern void route_read(struct zebra_ns *zns); +#ifdef __cplusplus +} +#endif + #endif /* _ZEBRA_RT_H */ diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index c56e2f316d..289ed5a15b 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -835,7 +835,7 @@ int netlink_route_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) { /* If this is not route add/delete message print warning. */ - zlog_debug("Kernel message: %s NS %u\n", + zlog_debug("Kernel message: %s NS %u", nl_msg_type_to_str(h->nlmsg_type), ns_id); return 0; } @@ -1836,7 +1836,9 @@ enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx) * of the route delete. If that happens yeah we're * screwed. */ - (void)netlink_route_multipath(RTM_DELROUTE, ctx); + if (!RSYSTEM_ROUTE(dplane_ctx_get_old_type(ctx))) + (void)netlink_route_multipath(RTM_DELROUTE, + ctx); cmd = RTM_NEWROUTE; } @@ -1844,7 +1846,10 @@ enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx) return ZEBRA_DPLANE_REQUEST_FAILURE; } - ret = netlink_route_multipath(cmd, ctx); + if (!RSYSTEM_ROUTE(dplane_ctx_get_type(ctx))) + ret = netlink_route_multipath(cmd, ctx); + else + ret = 0; if ((cmd == RTM_NEWROUTE) && (ret == 0)) { /* Update installed nexthops to signal which have been * installed. diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index 473ad98a3f..29e0152bb2 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -26,6 +26,10 @@ #include "zebra/zebra_mpls.h" #include "zebra/zebra_dplane.h" +#ifdef __cplusplus +extern "C" { +#endif + #define NL_DEFAULT_ROUTE_METRIC 20 /* @@ -79,6 +83,10 @@ extern int netlink_macfdb_read_specific_mac(struct zebra_ns *zns, extern int netlink_neigh_read_specific_ip(struct ipaddr *ip, struct interface *vlan_if); +#ifdef __cplusplus +} +#endif + #endif /* HAVE_NETLINK */ #endif /* _ZEBRA_RT_NETLINK_H */ diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index f25259f300..8d8bdd0a6d 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -304,33 +304,41 @@ static int kernel_rtm(int cmd, const struct prefix *p, enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx) { enum zebra_dplane_result res = ZEBRA_DPLANE_REQUEST_SUCCESS; + uint32_t type, old_type; if (dplane_ctx_get_src(ctx) != NULL) { zlog_err("route add: IPv6 sourcedest routes unsupported!"); return ZEBRA_DPLANE_REQUEST_FAILURE; } + type = dplane_ctx_get_type(ctx); + old_type = dplane_ctx_get_old_type(ctx); + frr_elevate_privs(&zserv_privs) { - if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_DELETE) - kernel_rtm(RTM_DELETE, dplane_ctx_get_dest(ctx), - dplane_ctx_get_ng(ctx), - dplane_ctx_get_metric(ctx)); - else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_INSTALL) - kernel_rtm(RTM_ADD, dplane_ctx_get_dest(ctx), - dplane_ctx_get_ng(ctx), - dplane_ctx_get_metric(ctx)); - else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_UPDATE) { + if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_DELETE) { + if (!RSYSTEM_ROUTE(type)) + kernel_rtm(RTM_DELETE, dplane_ctx_get_dest(ctx), + dplane_ctx_get_ng(ctx), + dplane_ctx_get_metric(ctx)); + } else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_INSTALL) { + if (!RSYSTEM_ROUTE(type)) + kernel_rtm(RTM_ADD, dplane_ctx_get_dest(ctx), + dplane_ctx_get_ng(ctx), + dplane_ctx_get_metric(ctx)); + } else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_UPDATE) { /* Must do delete and add separately - * no update available */ - kernel_rtm(RTM_DELETE, dplane_ctx_get_dest(ctx), - dplane_ctx_get_old_ng(ctx), - dplane_ctx_get_old_metric(ctx)); - - kernel_rtm(RTM_ADD, dplane_ctx_get_dest(ctx), - dplane_ctx_get_ng(ctx), - dplane_ctx_get_metric(ctx)); + if (!RSYSTEM_ROUTE(old_type)) + kernel_rtm(RTM_DELETE, dplane_ctx_get_dest(ctx), + dplane_ctx_get_old_ng(ctx), + dplane_ctx_get_old_metric(ctx)); + + if (!RSYSTEM_ROUTE(type)) + kernel_rtm(RTM_ADD, dplane_ctx_get_dest(ctx), + dplane_ctx_get_ng(ctx), + dplane_ctx_get_metric(ctx)); } else { zlog_err("Invalid routing socket update op %s (%u)", dplane_op2str(dplane_ctx_get_op(ctx)), @@ -339,6 +347,20 @@ enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx) } } /* Elevated privs */ + if (RSYSTEM_ROUTE(type) + && dplane_ctx_get_op(ctx) != DPLANE_OP_ROUTE_DELETE) { + struct nexthop *nexthop; + + for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) { + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + continue; + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) { + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + } + } + } + return res; } diff --git a/zebra/rtadv.h b/zebra/rtadv.h index f7c27ebcb3..53c497fc09 100644 --- a/zebra/rtadv.h +++ b/zebra/rtadv.h @@ -25,6 +25,10 @@ #include "vty.h" #include "zebra/interface.h" +#ifdef __cplusplus +extern "C" { +#endif + /* NB: RTADV is defined in zebra/interface.h above */ #if defined(HAVE_RTADV) @@ -137,5 +141,8 @@ extern void rtadv_cmd_init(void); extern void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS); extern void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS); +#ifdef __cplusplus +} +#endif #endif /* _ZEBRA_RTADV_H */ diff --git a/zebra/rule_netlink.h b/zebra/rule_netlink.h index 4547a1bb3b..8c4741dc06 100644 --- a/zebra/rule_netlink.h +++ b/zebra/rule_netlink.h @@ -26,6 +26,10 @@ #ifdef HAVE_NETLINK +#ifdef __cplusplus +extern "C" { +#endif + /* * Handle netlink notification informing a rule add or delete. */ @@ -36,6 +40,10 @@ extern int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup); */ extern int netlink_rules_read(struct zebra_ns *zns); +#ifdef __cplusplus +} +#endif + #endif /* HAVE_NETLINK */ #endif /* _ZEBRA_RULE_NETLINK_H */ diff --git a/zebra/table_manager.h b/zebra/table_manager.h index 5196162c4c..4f78f5097e 100644 --- a/zebra/table_manager.h +++ b/zebra/table_manager.h @@ -27,6 +27,10 @@ #include "zebra/zserv.h" +#ifdef __cplusplus +extern "C" { +#endif + /* * Table chunk struct * Client daemon which the chunk belongs to can be identified by either @@ -63,4 +67,8 @@ int release_table_chunk(uint8_t proto, uint16_t instance, uint32_t start, int release_daemon_table_chunks(struct zserv *client); void table_manager_disable(ns_id_t ns_id); +#ifdef __cplusplus +} +#endif + #endif /* _TABLE_MANAGER_H */ diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 9f2bbcf426..2eeb1f2788 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1036,6 +1036,8 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) uint8_t flags = 0; uint16_t type = cmd2type[hdr->command]; bool exist; + bool flag_changed = false; + uint8_t orig_flags; if (IS_ZEBRA_DEBUG_NHT) zlog_debug( @@ -1084,6 +1086,7 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) if (!rnh) return; + orig_flags = rnh->flags; if (type == RNH_NEXTHOP_TYPE) { if (flags && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) @@ -1101,9 +1104,12 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); } + if (orig_flags != rnh->flags) + flag_changed = true; + zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf)); /* Anything not AF_INET/INET6 has been filtered out above */ - if (!exist) + if (!exist || flag_changed) zebra_evaluate_rnh(zvrf, family2afi(p.family), 1, type, &p); } @@ -1456,8 +1462,8 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) &(api_nh->gate.ipv4), sizeof(struct in_addr)); zebra_vxlan_evpn_vrf_route_add( - vrf_id, &api_nh->rmac, &vtep_ip, - &api.prefix); + api_nh->vrf_id, &api_nh->rmac, + &vtep_ip, &api.prefix); } break; case NEXTHOP_TYPE_IPV6: @@ -1479,8 +1485,8 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) memcpy(&vtep_ip.ipaddr_v6, &(api_nh->gate.ipv6), sizeof(struct in6_addr)); zebra_vxlan_evpn_vrf_route_add( - vrf_id, &api_nh->rmac, &vtep_ip, - &api.prefix); + api_nh->vrf_id, &api_nh->rmac, + &vtep_ip, &api.prefix); } break; case NEXTHOP_TYPE_BLACKHOLE: diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h index b770b8e881..d30fa2d0ef 100644 --- a/zebra/zapi_msg.h +++ b/zebra/zapi_msg.h @@ -30,6 +30,10 @@ #include "zebra/zebra_pbr.h" #include "zebra/zebra_errors.h" +#ifdef __cplusplus +extern "C" { +#endif + /* * This is called to process inbound ZAPI messages. * @@ -86,3 +90,7 @@ extern void zserv_nexthop_num_warn(const char *caller, const struct prefix *p, const unsigned int nexthop_num); extern void zsend_capabilities_all_clients(void); + +#ifdef __cplusplus +} +#endif diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 149ff8dc60..1246fcc8ec 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -30,6 +30,10 @@ #include "zebra/zserv.h" #include "zebra/zebra_mpls.h" +#ifdef __cplusplus +extern "C" { +#endif + /* Key netlink info from zebra ns */ struct zebra_dplane_info { ns_id_t ns_id; @@ -394,4 +398,8 @@ void zebra_dplane_pre_finish(void); void zebra_dplane_finish(void); void zebra_dplane_shutdown(void); +#ifdef __cplusplus +} +#endif + #endif /* _ZEBRA_DPLANE_H */ diff --git a/zebra/zebra_errors.h b/zebra/zebra_errors.h index 0af5f8a551..2b7831a408 100644 --- a/zebra/zebra_errors.h +++ b/zebra/zebra_errors.h @@ -23,6 +23,10 @@ #include "lib/ferr.h" +#ifdef __cplusplus +extern "C" { +#endif + enum zebra_log_refs { EC_ZEBRA_LM_RESPONSE = ZEBRA_FERR_START, EC_ZEBRA_LM_NO_SUCH_CLIENT, @@ -126,4 +130,8 @@ enum zebra_log_refs { void zebra_error_init(void); +#ifdef __cplusplus +} +#endif + #endif /* __EC_ZEBRAORS_H__ */ diff --git a/zebra/zebra_fpm_private.h b/zebra/zebra_fpm_private.h index 969ab6cfee..943aad9864 100644 --- a/zebra/zebra_fpm_private.h +++ b/zebra/zebra_fpm_private.h @@ -26,6 +26,10 @@ #include "zebra/debug.h" +#ifdef __cplusplus +extern "C" { +#endif + #if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L #define zfpm_debug(...) \ @@ -61,4 +65,9 @@ extern int zfpm_protobuf_encode_route(rib_dest_t *dest, struct route_entry *re, uint8_t *in_buf, size_t in_buf_len); extern struct route_entry *zfpm_route_for_update(rib_dest_t *dest); + +#ifdef __cplusplus +} +#endif + #endif /* _ZEBRA_FPM_PRIVATE_H */ diff --git a/zebra/zebra_l2.h b/zebra/zebra_l2.h index 68c9d4a7a1..2e3e5b4a85 100644 --- a/zebra/zebra_l2.h +++ b/zebra/zebra_l2.h @@ -29,6 +29,10 @@ #include "vlan.h" #include "vxlan.h" +#ifdef __cplusplus +extern "C" { +#endif + /* zebra L2 interface information - bridge slave (linkage to bridge) */ struct zebra_l2info_brslave { ifindex_t bridge_ifindex; /* Bridge Master */ @@ -96,4 +100,9 @@ extern void zebra_l2if_update_bridge_slave(struct interface *ifp, extern void zebra_l2if_update_bond_slave(struct interface *ifp, ifindex_t bond_ifindex); + +#ifdef __cplusplus +} +#endif + #endif /* _ZEBRA_L2_H */ diff --git a/zebra/zebra_memory.h b/zebra/zebra_memory.h index de55478de2..667c73b227 100644 --- a/zebra/zebra_memory.h +++ b/zebra/zebra_memory.h @@ -24,6 +24,10 @@ #include "memory.h" +#ifdef __cplusplus +extern "C" { +#endif + DECLARE_MGROUP(ZEBRA) DECLARE_MTYPE(RTADV_PREFIX) DECLARE_MTYPE(ZEBRA_NS) @@ -37,4 +41,8 @@ DECLARE_MTYPE(RNH) DECLARE_MTYPE(DP_CTX) DECLARE_MTYPE(DP_PROV) +#ifdef __cplusplus +} +#endif + #endif /* _QUAGGA_ZEBRA_MEMORY_H */ diff --git a/zebra/zebra_mlag.h b/zebra/zebra_mlag.h index c5c147c833..90a5a41fa4 100644 --- a/zebra/zebra_mlag.h +++ b/zebra/zebra_mlag.h @@ -24,8 +24,17 @@ #include "mlag.h" +#ifdef __cplusplus +extern "C" { +#endif + void zebra_mlag_init(void); void zebra_mlag_terminate(void); enum mlag_role zebra_mlag_get_role(void); + +#ifdef __cplusplus +} +#endif + #endif diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h index 39f084ad2f..3a131e1aaf 100644 --- a/zebra/zebra_mpls.h +++ b/zebra/zebra_mpls.h @@ -34,6 +34,9 @@ #include "zebra/zserv.h" #include "zebra/zebra_vrf.h" +#ifdef __cplusplus +extern "C" { +#endif /* Definitions and macros. */ @@ -507,31 +510,48 @@ static inline const char *nhlfe_type2str(enum lsp_types_t lsp_type) return "Unknown"; } -static inline void mpls_mark_lsps_for_processing(struct zebra_vrf *zvrf) +static inline void mpls_mark_lsps_for_processing(struct zebra_vrf *zvrf, + struct prefix *p) { + struct route_table *table; + struct route_node *rn; + rib_dest_t *dest; + if (!zvrf) return; - zvrf->mpls_flags |= MPLS_FLAG_SCHEDULE_LSPS; + table = zvrf->table[family2afi(p->family)][SAFI_UNICAST]; + if (!table) + return; + + rn = route_node_match(table, p); + if (!rn) + return; + + + dest = rib_dest_from_rnode(rn); + SET_FLAG(dest->flags, RIB_DEST_UPDATE_LSPS); } -static inline void mpls_unmark_lsps_for_processing(struct zebra_vrf *zvrf) +static inline void mpls_unmark_lsps_for_processing(struct route_node *rn) { - if (!zvrf) - return; + rib_dest_t *dest = rib_dest_from_rnode(rn); - zvrf->mpls_flags &= ~MPLS_FLAG_SCHEDULE_LSPS; + UNSET_FLAG(dest->flags, RIB_DEST_UPDATE_LSPS); } -static inline int mpls_should_lsps_be_processed(struct zebra_vrf *zvrf) +static inline int mpls_should_lsps_be_processed(struct route_node *rn) { - if (!zvrf) - return 0; + rib_dest_t *dest = rib_dest_from_rnode(rn); - return ((zvrf->mpls_flags & MPLS_FLAG_SCHEDULE_LSPS) ? 1 : 0); + return !!CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_LSPS); } /* Global variables. */ extern int mpls_enabled; +#ifdef __cplusplus +} +#endif + #endif /*_ZEBRA_MPLS_H */ diff --git a/zebra/zebra_mroute.h b/zebra/zebra_mroute.h index 3385153600..3c12b82da3 100644 --- a/zebra/zebra_mroute.h +++ b/zebra/zebra_mroute.h @@ -24,6 +24,10 @@ #include "zebra/zserv.h" +#ifdef __cplusplus +extern "C" { +#endif + struct mcast_route_data { struct prefix_sg sg; unsigned int ifindex; @@ -32,4 +36,8 @@ struct mcast_route_data { void zebra_ipmr_route_stats(ZAPI_HANDLER_ARGS); +#ifdef __cplusplus +} +#endif + #endif diff --git a/zebra/zebra_netns_id.h b/zebra/zebra_netns_id.h index d6530e6694..7a5f6851f4 100644 --- a/zebra/zebra_netns_id.h +++ b/zebra/zebra_netns_id.h @@ -20,7 +20,15 @@ #include "zebra.h" #include "ns.h" +#ifdef __cplusplus +extern "C" { +#endif + extern ns_id_t zebra_ns_id_get(const char *netnspath); extern ns_id_t zebra_ns_id_get_default(void); +#ifdef __cplusplus +} +#endif + #endif /* __ZEBRA_NS_ID_H__ */ diff --git a/zebra/zebra_netns_notify.h b/zebra/zebra_netns_notify.h index 0ced749ae8..18939283a7 100644 --- a/zebra/zebra_netns_notify.h +++ b/zebra/zebra_netns_notify.h @@ -20,10 +20,18 @@ #ifndef _NETNS_NOTIFY_H #define _NETNS_NOTIFY_H +#ifdef __cplusplus +extern "C" { +#endif + extern void zebra_ns_notify_init(void); extern void zebra_ns_notify_parse(void); extern void zebra_ns_notify_close(void); extern struct zebra_privs_t zserv_privs; +#ifdef __cplusplus +} +#endif + #endif /* NETNS_NOTIFY_H */ diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h index 01af64c17b..dc79a83db0 100644 --- a/zebra/zebra_ns.h +++ b/zebra/zebra_ns.h @@ -28,6 +28,10 @@ #include "zebra/rib.h" #include "zebra/zebra_vrf.h" +#ifdef __cplusplus +extern "C" { +#endif + #ifdef HAVE_NETLINK /* Socket interface to kernel */ struct nlsock { @@ -68,4 +72,8 @@ int zebra_ns_final_shutdown(struct ns *ns); int zebra_ns_config_write(struct vty *vty, struct ns *ns); +#ifdef __cplusplus +} +#endif + #endif diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h index 5b6c23896c..0d55491107 100644 --- a/zebra/zebra_pbr.h +++ b/zebra/zebra_pbr.h @@ -32,6 +32,10 @@ #include "rt.h" #include "pbr.h" +#ifdef __cplusplus +extern "C" { +#endif + struct zebra_pbr_rule { int sock; @@ -252,4 +256,8 @@ DECLARE_HOOK(zebra_pbr_ipset_entry_update, DECLARE_HOOK(zebra_pbr_ipset_update, (int cmd, struct zebra_pbr_ipset *ipset), (cmd, ipset)); +#ifdef __cplusplus +} +#endif + #endif /* _ZEBRA_PBR_H */ diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index cc5e38e690..bb352dc2ff 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -328,7 +328,7 @@ DEFUN (zebra_ptm_enable_if, if (!old_ptm_enable && ptm_cb.ptm_enable) { if (!if_is_operative(ifp) && send_linkdown) { if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s: Bringing down interface %s\n", + zlog_debug("%s: Bringing down interface %s", __func__, ifp->name); if_down(ifp); } @@ -354,7 +354,7 @@ DEFUN (no_zebra_ptm_enable_if, ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; if (if_is_no_ptm_operative(ifp) && send_linkup) { if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s: Bringing up interface %s\n", + zlog_debug("%s: Bringing up interface %s", __func__, ifp->name); if_up(ifp); } diff --git a/zebra/zebra_ptm.h b/zebra/zebra_ptm.h index d0cdaf0bce..e578a02a94 100644 --- a/zebra/zebra_ptm.h +++ b/zebra/zebra_ptm.h @@ -31,6 +31,10 @@ extern const char ZEBRA_PTM_SOCK_NAME[]; #include "zebra/zserv.h" #include "zebra/interface.h" +#ifdef __cplusplus +extern "C" { +#endif + /* Zebra ptm context block */ struct zebra_ptm_cb { int ptm_sock; /* ptm file descriptor. */ @@ -87,4 +91,9 @@ void zebra_ptm_if_init(struct zebra_if *zebra_ifp); void zebra_ptm_if_set_ptm_state(struct interface *ifp, struct zebra_if *zebra_ifp); void zebra_ptm_if_write(struct vty *vty, struct zebra_if *zebra_ifp); + +#ifdef __cplusplus +} +#endif + #endif diff --git a/zebra/zebra_ptm_redistribute.h b/zebra/zebra_ptm_redistribute.h index c1b12bd0d1..4daf405825 100644 --- a/zebra/zebra_ptm_redistribute.h +++ b/zebra/zebra_ptm_redistribute.h @@ -21,7 +21,17 @@ #ifndef _ZEBRA_PTM_REDISTRIBUTE_H #define _ZEBRA_PTM_REDISTRIBUTE_H + +#ifdef __cplusplus +extern "C" { +#endif + extern void zebra_interface_bfd_update(struct interface *, struct prefix *, struct prefix *, int, vrf_id_t); extern void zebra_bfd_peer_replay_req(void); + +#ifdef __cplusplus +} +#endif + #endif /* _ZEBRA_PTM_REDISTRIBUTE_H */ diff --git a/zebra/zebra_pw.h b/zebra/zebra_pw.h index 9692fb4d40..bbb3776725 100644 --- a/zebra/zebra_pw.h +++ b/zebra/zebra_pw.h @@ -29,6 +29,10 @@ #include "zebra/zebra_vrf.h" +#ifdef __cplusplus +extern "C" { +#endif + #define PW_INSTALL_RETRY_INTERVAL 30 struct zebra_pw { @@ -74,4 +78,8 @@ void zebra_pw_init(struct zebra_vrf *); void zebra_pw_exit(struct zebra_vrf *); void zebra_pw_vty_init(void); +#ifdef __cplusplus +} +#endif + #endif /* ZEBRA_PW_H_ */ diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 2014aa3bed..557e6876e2 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1175,10 +1175,7 @@ static void rib_uninstall(struct route_node *rn, struct route_entry *re) if (zebra_rib_labeled_unicast(re)) zebra_mpls_lsp_uninstall(info->zvrf, rn, re); - if (!RIB_SYSTEM_ROUTE(re)) - rib_uninstall_kernel(rn, re); - else - UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED); + rib_uninstall_kernel(rn, re); dest->selected_fib = NULL; @@ -1208,6 +1205,16 @@ static int rib_can_delete_dest(rib_dest_t *dest) } /* + * Unresolved rnh's are stored on the default route's list + * + * dest->rnode can also be the source prefix node in an + * ipv6 sourcedest table. Fortunately the prefix of a + * source prefix node can never be the default prefix. + */ + if (is_default_prefix(&dest->rnode->p)) + return 0; + + /* * Don't delete the dest if we have to update the FPM about this * prefix. */ @@ -1218,6 +1225,88 @@ static int rib_can_delete_dest(rib_dest_t *dest) return 1; } +void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq) +{ + rib_dest_t *dest = rib_dest_from_rnode(rn); + struct listnode *node, *nnode; + struct rnh *rnh; + + /* + * We are storing the rnh's associated withb + * the tracked nexthop as a list of the rn's. + * Unresolved rnh's are placed at the top + * of the tree list.( 0.0.0.0/0 for v4 and 0::0/0 for v6 ) + * As such for each rn we need to walk up the tree + * and see if any rnh's need to see if they + * would match a more specific route + */ + while (rn) { + if (IS_ZEBRA_DEBUG_NHT_DETAILED) { + char buf[PREFIX_STRLEN]; + + zlog_debug("%s: %s Being examined for Nexthop Tracking", + __PRETTY_FUNCTION__, + srcdest_rnode2str(rn, buf, sizeof(buf))); + } + if (!dest) { + rn = rn->parent; + if (rn) + dest = rib_dest_from_rnode(rn); + continue; + } + /* + * If we have any rnh's stored in the nht list + * then we know that this route node was used for + * nht resolution and as such we need to call the + * nexthop tracking evaluation code + */ + for (ALL_LIST_ELEMENTS(dest->nht, node, nnode, rnh)) { + struct zebra_vrf *zvrf = + zebra_vrf_lookup_by_id(rnh->vrf_id); + struct prefix *p = &rnh->node->p; + + if (IS_ZEBRA_DEBUG_NHT_DETAILED) { + char buf1[PREFIX_STRLEN]; + char buf2[PREFIX_STRLEN]; + + zlog_debug("%u:%s has Nexthop(%s) depending on it, evaluating %u:%u", + zvrf->vrf->vrf_id, + srcdest_rnode2str(rn, buf1, + sizeof(buf1)), + prefix2str(p, buf2, sizeof(buf2)), + seq, rnh->seqno); + } + + /* + * If we have evaluated this node on this pass + * already, due to following the tree up + * then we know that we can move onto the next + * rnh to process. + * + * Additionally we call zebra_evaluate_rnh + * when we gc the dest. In this case we know + * that there must be no other re's where + * we were originally as such we know that + * that sequence number is ok to respect. + */ + if (rnh->seqno == seq) { + if (IS_ZEBRA_DEBUG_NHT_DETAILED) + zlog_debug( + "\tNode processed and moved already"); + continue; + } + + rnh->seqno = seq; + zebra_evaluate_rnh(zvrf, family2afi(p->family), 0, + rnh->type, p); + } + + rn = rn->parent; + if (rn) + dest = rib_dest_from_rnode(rn); + } +} + /* * rib_gc_dest * @@ -1244,7 +1333,10 @@ int rib_gc_dest(struct route_node *rn) rnode_debug(rn, zvrf_id(zvrf), "removing dest from table"); } + zebra_rib_evaluate_rn_nexthops(rn, zebra_router_get_next_sequence()); + dest->rnode = NULL; + list_delete(&dest->nht); XFREE(MTYPE_RIB_DEST, dest); rn->info = NULL; @@ -1258,8 +1350,6 @@ int rib_gc_dest(struct route_node *rn) static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, struct route_entry *new) { - rib_dest_t *dest = rib_dest_from_rnode(rn); - hook_call(rib_update, rn, "new route selected"); /* Update real nexthop. This may actually determine if nexthop is active @@ -1281,10 +1371,7 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, if (zebra_rib_labeled_unicast(new)) zebra_mpls_lsp_install(zvrf, rn, new); - if (!RIB_SYSTEM_ROUTE(new)) - rib_install_kernel(rn, new, NULL); - else - dest->selected_fib = new; + rib_install_kernel(rn, new, NULL); UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED); } @@ -1292,7 +1379,6 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn, struct route_entry *old) { - rib_dest_t *dest = rib_dest_from_rnode(rn); hook_call(rib_update, rn, "removing existing route"); /* Uninstall from kernel. */ @@ -1308,20 +1394,7 @@ static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn, if (zebra_rib_labeled_unicast(old)) zebra_mpls_lsp_uninstall(zvrf, rn, old); - if (!RIB_SYSTEM_ROUTE(old)) - rib_uninstall_kernel(rn, old); - else { - UNSET_FLAG(old->status, ROUTE_ENTRY_INSTALLED); - /* - * 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; - } + rib_uninstall_kernel(rn, old); /* Update nexthop for route, reset changed flag. */ /* Note: this code also handles the Linux case when an interface goes @@ -1340,9 +1413,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf, struct route_entry *old, struct route_entry *new) { - struct nexthop *nexthop = NULL; int nh_active = 0; - rib_dest_t *dest = rib_dest_from_rnode(rn); /* * We have to install or update if a new route has been selected or @@ -1384,48 +1455,15 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf, if (zebra_rib_labeled_unicast(old)) zebra_mpls_lsp_uninstall(zvrf, rn, old); - /* Non-system route should be installed. */ - if (!RIB_SYSTEM_ROUTE(new)) { - /* If labeled-unicast route, install transit - * LSP. */ - if (zebra_rib_labeled_unicast(new)) - zebra_mpls_lsp_install(zvrf, rn, new); + /* + * Non-system route should be installed. + * If labeled-unicast route, install transit + * LSP. + */ + if (zebra_rib_labeled_unicast(new)) + zebra_mpls_lsp_install(zvrf, rn, new); - rib_install_kernel(rn, new, old); - } else { - UNSET_FLAG(new->status, ROUTE_ENTRY_INSTALLED); - /* - * 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 (new != old) { - if (RIB_SYSTEM_ROUTE(new)) { - if (!RIB_SYSTEM_ROUTE(old)) - rib_uninstall_kernel(rn, old); - else - UNSET_FLAG( - old->status, - ROUTE_ENTRY_INSTALLED); - } else { - UNSET_FLAG(old->status, - ROUTE_ENTRY_INSTALLED); - for (nexthop = old->ng.nexthop; nexthop; - nexthop = nexthop->next) - UNSET_FLAG(nexthop->flags, - NEXTHOP_FLAG_FIB); - } - } + rib_install_kernel(rn, new, old); } /* @@ -1455,25 +1493,18 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf, if (zebra_rib_labeled_unicast(old)) zebra_mpls_lsp_uninstall(zvrf, rn, old); - if (!RIB_SYSTEM_ROUTE(old)) - rib_uninstall_kernel(rn, old); - else { - UNSET_FLAG(old->status, ROUTE_ENTRY_INSTALLED); - dest->selected_fib = NULL; - } + rib_uninstall_kernel(rn, old); } } else { /* * Same route selected; check if in the FIB and if not, - * re-install. This - * is housekeeping code to deal with race conditions in kernel - * with linux - * netlink reporting interface up before IPv4 or IPv6 protocol - * is ready + * re-install. This is housekeeping code to deal with + * race conditions in kernel with linux netlink reporting + * interface up before IPv4 or IPv6 protocol is ready * to add routes. */ - if (!RIB_SYSTEM_ROUTE(new) - && !CHECK_FLAG(new->status, ROUTE_ENTRY_INSTALLED)) + if (!CHECK_FLAG(new->status, ROUTE_ENTRY_INSTALLED) || + RIB_SYSTEM_ROUTE(new)) rib_install_kernel(rn, new, NULL); } @@ -1725,18 +1756,9 @@ static void rib_process(struct route_node *rn) UNSET_FLAG(new_selected->status, ROUTE_ENTRY_CHANGED); } - if (new_selected) { + if (new_selected) SET_FLAG(new_selected->flags, ZEBRA_FLAG_SELECTED); - /* Special case: new route is system route, so - * dataplane update will not be done - ensure we - * redistribute the route. - */ - if (RIB_SYSTEM_ROUTE(new_selected)) - redistribute_update(p, src_p, new_selected, - old_selected); - } - if (old_selected) { if (!new_selected) redistribute_delete(p, src_p, old_selected); @@ -1763,6 +1785,24 @@ static void rib_process(struct route_node *rn) rib_gc_dest(rn); } +static void zebra_rib_evaluate_mpls(struct route_node *rn) +{ + rib_dest_t *dest = rib_dest_from_rnode(rn); + struct zebra_vrf *zvrf = vrf_info_lookup(VRF_DEFAULT); + + if (!dest) + return; + + if (CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_LSPS)) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug( + "%u: Scheduling all LSPs upon RIB completion", + zvrf_id(zvrf)); + zebra_mpls_lsp_schedule(zvrf); + mpls_unmark_lsps_for_processing(rn); + } +} + /* * Utility to match route with dplane context data */ @@ -1821,6 +1861,30 @@ done: return (result); } +static void zebra_rib_fixup_system(struct route_node *rn) +{ + struct route_entry *re; + + RNODE_FOREACH_RE(rn, re) { + struct nexthop *nhop; + + if (!RIB_SYSTEM_ROUTE(re)) + continue; + + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + + SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED); + + for (ALL_NEXTHOPS(re->ng, nhop)) { + if (CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_RECURSIVE)) + continue; + + SET_FLAG(nhop->flags, NEXTHOP_FLAG_FIB); + } + } +} + /* * Route-update results processing after async dataplane update. */ @@ -1836,6 +1900,7 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) enum dplane_op_e op; enum zebra_dplane_result status; const struct prefix *dest_pfx, *src_pfx; + uint32_t seq; /* Locate rn and re(s) from ctx */ @@ -1912,11 +1977,13 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) break; } + seq = dplane_ctx_get_seq(ctx); + /* * Check sequence number(s) to detect stale results before continuing */ if (re) { - if (re->dplane_sequence != dplane_ctx_get_seq(ctx)) { + if (re->dplane_sequence != seq) { if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) zlog_debug("%u:%s Stale dplane result for re %p", dplane_ctx_get_vrf(ctx), @@ -1932,7 +1999,7 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) dplane_ctx_get_vrf(ctx), dest_str, old_re); } else - UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED); + UNSET_FLAG(old_re->status, ROUTE_ENTRY_QUEUED); } switch (op) { @@ -1987,6 +2054,17 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) NEXTHOP_FLAG_FIB); } + /* + * System routes are weird in that they + * allow multiple to be installed that match + * to the same prefix, so after we get the + * result we need to clean them up so that + * we can actually use them. + */ + if ((re && RIB_SYSTEM_ROUTE(re)) || + (old_re && RIB_SYSTEM_ROUTE(old_re))) + zebra_rib_fixup_system(rn); + if (zvrf) { zvrf->installs++; /* Set flag for nexthop tracking processing */ @@ -2010,9 +2088,10 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_INSTALLED); } else { - if (re) + if (re) { SET_FLAG(re->status, ROUTE_ENTRY_FAILED); - if (old_re) + UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED); + } if (old_re) SET_FLAG(old_re->status, ROUTE_ENTRY_FAILED); if (re) zsend_route_notify_owner(re, dest_pfx, @@ -2052,10 +2131,24 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) prefix2str(dest_pfx, dest_str, sizeof(dest_str))); } + + /* + * System routes are weird in that they + * allow multiple to be installed that match + * to the same prefix, so after we get the + * result we need to clean them up so that + * we can actually use them. + */ + if ((re && RIB_SYSTEM_ROUTE(re)) || + (old_re && RIB_SYSTEM_ROUTE(old_re))) + zebra_rib_fixup_system(rn); break; default: break; } + + zebra_rib_evaluate_rn_nexthops(rn, seq); + zebra_rib_evaluate_mpls(rn); done: if (rn) @@ -2110,47 +2203,12 @@ static unsigned int process_subq(struct list *subq, uint8_t qindex) return 1; } + /* * Perform next-hop tracking processing after RIB updates. */ static void do_nht_processing(void) { - struct vrf *vrf; - struct zebra_vrf *zvrf; - - /* Evaluate nexthops for those VRFs which underwent route processing. - * This - * should limit the evaluation to the necessary VRFs in most common - * situations. - */ - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { - zvrf = vrf->info; - if (zvrf == NULL || !(zvrf->flags & ZEBRA_VRF_RIB_SCHEDULED)) - continue; - - if (IS_ZEBRA_DEBUG_RIB_DETAILED || IS_ZEBRA_DEBUG_NHT) - zlog_debug("NHT processing check for zvrf %s", - zvrf_name(zvrf)); - - zvrf->flags &= ~ZEBRA_VRF_RIB_SCHEDULED; - zebra_evaluate_rnh(zvrf, AFI_IP, 0, RNH_NEXTHOP_TYPE, NULL); - zebra_evaluate_rnh(zvrf, AFI_IP, 0, RNH_IMPORT_CHECK_TYPE, - NULL); - zebra_evaluate_rnh(zvrf, AFI_IP6, 0, RNH_NEXTHOP_TYPE, NULL); - zebra_evaluate_rnh(zvrf, AFI_IP6, 0, RNH_IMPORT_CHECK_TYPE, - NULL); - } - - /* Schedule LSPs for processing, if needed. */ - zvrf = vrf_info_lookup(VRF_DEFAULT); - if (mpls_should_lsps_be_processed(zvrf)) { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug( - "%u: Scheduling all LSPs upon RIB completion", - zvrf_id(zvrf)); - zebra_mpls_lsp_schedule(zvrf); - mpls_unmark_lsps_for_processing(zvrf); - } } /* Dispatch the meta queue by picking, processing and unlocking the next RN from @@ -2340,6 +2398,19 @@ static void rib_queue_init(void) return; } +rib_dest_t *zebra_rib_create_dest(struct route_node *rn) +{ + rib_dest_t *dest; + + dest = XCALLOC(MTYPE_RIB_DEST, sizeof(rib_dest_t)); + dest->nht = list_new(); + route_lock_node(rn); /* rn route table reference */ + rn->info = dest; + dest->rnode = rn; + + return dest; +} + /* RIB updates are processed via a queue of pointers to route_nodes. * * The queue length is bounded by the maximal size of the routing table, @@ -2392,10 +2463,7 @@ static void rib_link(struct route_node *rn, struct route_entry *re, int process) if (IS_ZEBRA_DEBUG_RIB_DETAILED) rnode_debug(rn, re->vrf_id, "rn %p adding dest", rn); - dest = XCALLOC(MTYPE_RIB_DEST, sizeof(rib_dest_t)); - route_lock_node(rn); /* rn route table reference */ - rn->info = dest; - dest->rnode = rn; + dest = zebra_rib_create_dest(rn); } head = dest->routes; @@ -2654,7 +2722,7 @@ void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id) * revalidation * of the rest of the RE. */ - if (dest->selected_fib && !RIB_SYSTEM_ROUTE(dest->selected_fib)) { + if (dest->selected_fib) { changed = 1; if (IS_ZEBRA_DEBUG_RIB) { char buf[PREFIX_STRLEN]; @@ -2676,7 +2744,6 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, struct route_table *table; struct route_node *rn; struct route_entry *same = NULL; - struct nexthop *nexthop; int ret = 0; if (!re) @@ -2740,13 +2807,6 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, break; } - /* If this route is kernel route, set FIB flag to the route. */ - if (RIB_SYSTEM_ROUTE(re)) { - SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED); - for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next) - SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); - } - /* Link new re to node.*/ if (IS_ZEBRA_DEBUG_RIB) { rnode_debug(rn, re->vrf_id, @@ -3222,10 +3282,8 @@ void rib_close_table(struct route_table *table) if (info->safi == SAFI_UNICAST) hook_call(rib_update, rn, NULL); - if (!RIB_SYSTEM_ROUTE(dest->selected_fib)) { - rib_uninstall_kernel(rn, dest->selected_fib); - dest->selected_fib = NULL; - } + rib_uninstall_kernel(rn, dest->selected_fib); + dest->selected_fib = NULL; } } } diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 52637c6062..a1519e45cd 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -94,6 +94,61 @@ char *rnh_str(struct rnh *rnh, char *buf, int size) return buf; } +static void zebra_rnh_remove_from_routing_table(struct rnh *rnh) +{ + struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(rnh->vrf_id); + struct route_table *table = zvrf->table[rnh->afi][SAFI_UNICAST]; + struct route_node *rn; + rib_dest_t *dest; + + if (!table) + return; + + rn = route_node_match(table, &rnh->resolved_route); + if (!rn) + return; + + if (IS_ZEBRA_DEBUG_NHT_DETAILED) { + char buf[PREFIX_STRLEN]; + char buf1[PREFIX_STRLEN]; + + zlog_debug("%s: %u:%s removed from tracking on %s", + __PRETTY_FUNCTION__, rnh->vrf_id, + prefix2str(&rnh->node->p, buf, sizeof(buf)), + srcdest_rnode2str(rn, buf1, sizeof(buf))); + } + + dest = rib_dest_from_rnode(rn); + listnode_delete(dest->nht, rnh); + route_unlock_node(rn); +} + +static void zebra_rnh_store_in_routing_table(struct rnh *rnh) +{ + struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(rnh->vrf_id); + struct route_table *table = zvrf->table[rnh->afi][SAFI_UNICAST]; + struct route_node *rn; + rib_dest_t *dest; + + rn = route_node_match(table, &rnh->resolved_route); + if (!rn) + return; + + if (IS_ZEBRA_DEBUG_NHT_DETAILED) { + char buf[PREFIX_STRLEN]; + char buf1[PREFIX_STRLEN]; + + zlog_debug("%s: %u:%s added for tracking on %s", + __PRETTY_FUNCTION__, rnh->vrf_id, + prefix2str(&rnh->node->p, buf, sizeof(buf)), + srcdest_rnode2str(rn, buf1, sizeof(buf))); + } + + dest = rib_dest_from_rnode(rn); + listnode_add(dest->nht, rnh); + route_unlock_node(rn); +} + struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type, bool *exists) { @@ -101,12 +156,13 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type, struct route_node *rn; struct rnh *rnh = NULL; char buf[PREFIX2STR_BUFFER]; + afi_t afi = family2afi(p->family); if (IS_ZEBRA_DEBUG_NHT) { prefix2str(p, buf, sizeof(buf)); zlog_debug("%u: Add RNH %s type %d", vrfid, buf, type); } - table = get_rnh_table(vrfid, family2afi(PREFIX_FAMILY(p)), type); + table = get_rnh_table(vrfid, afi, type); if (!table) { prefix2str(p, buf, sizeof(buf)); flog_warn(EC_ZEBRA_RNH_NO_TABLE, @@ -124,13 +180,26 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type, if (!rn->info) { rnh = XCALLOC(MTYPE_RNH, sizeof(struct rnh)); + + /* + * The resolved route is already 0.0.0.0/0 or + * 0::0/0 due to the calloc right above, but + * we should set the family so that future + * comparisons can just be done + */ + rnh->resolved_route.family = p->family; rnh->client_list = list_new(); rnh->vrf_id = vrfid; + rnh->type = type; + rnh->seqno = 0; + rnh->afi = afi; rnh->zebra_pseudowire_list = list_new(); route_lock_node(rn); rn->info = rnh; rnh->node = rn; *exists = false; + + zebra_rnh_store_in_routing_table(rnh); } else *exists = true; @@ -161,9 +230,30 @@ struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type) void zebra_free_rnh(struct rnh *rnh) { + struct zebra_vrf *zvrf; + struct route_table *table; + + zebra_rnh_remove_from_routing_table(rnh); rnh->flags |= ZEBRA_NHT_DELETED; list_delete(&rnh->client_list); list_delete(&rnh->zebra_pseudowire_list); + + zvrf = zebra_vrf_lookup_by_id(rnh->vrf_id); + table = zvrf->table[family2afi(rnh->resolved_route.family)][SAFI_UNICAST]; + + if (table) { + struct route_node *rern; + + rern = route_node_match(table, &rnh->resolved_route); + if (rern) { + rib_dest_t *dest; + + route_unlock_node(rern); + + dest = rib_dest_from_rnode(rern); + listnode_delete(dest->nht, rnh); + } + } free_state(rnh->vrf_id, rnh->state, rnh->node); XFREE(MTYPE_RNH, rnh); } @@ -344,6 +434,16 @@ zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, afi_t afi, && !prefix_same(&nrn->p, &rn->p)) return NULL; + if (IS_ZEBRA_DEBUG_NHT_DETAILED) { + char buf[PREFIX_STRLEN]; + char buf1[PREFIX_STRLEN]; + + zlog_debug("%s: %u:%s Resolved Import Entry to %s", + __PRETTY_FUNCTION__, rnh->vrf_id, + prefix2str(&rnh->node->p, buf, sizeof(buf)), + srcdest_rnode2str(rn, buf1, sizeof(buf))); + } + /* Identify appropriate route entry. */ RNODE_FOREACH_RE (rn, re) { if (!CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED) @@ -354,6 +454,10 @@ zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, afi_t afi, if (re) *prn = rn; + + if (!re && IS_ZEBRA_DEBUG_NHT_DETAILED) + zlog_debug("\tRejected due to removed or is a bgp route"); + return re; } @@ -361,9 +465,10 @@ zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, afi_t afi, * See if a tracked route entry for import (by BGP) has undergone any * change, and if so, notify the client. */ -static void zebra_rnh_eval_import_check_entry(vrf_id_t vrfid, afi_t afi, +static void zebra_rnh_eval_import_check_entry(struct zebra_vrf *zvrf, afi_t afi, int force, struct route_node *nrn, struct rnh *rnh, + struct route_node *prn, struct route_entry *re) { int state_changed = 0; @@ -371,25 +476,40 @@ static void zebra_rnh_eval_import_check_entry(vrf_id_t vrfid, afi_t afi, char bufn[INET6_ADDRSTRLEN]; struct listnode *node; + zebra_rnh_remove_from_routing_table(rnh); + if (prn) { + prefix_copy(&rnh->resolved_route, &prn->p); + } else { + int family = rnh->resolved_route.family; + + memset(&rnh->resolved_route.family, 0, sizeof(struct prefix)); + rnh->resolved_route.family = family; + } + zebra_rnh_store_in_routing_table(rnh); + if (re && (rnh->state == NULL)) { if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) state_changed = 1; } else if (!re && (rnh->state != NULL)) state_changed = 1; - if (compare_state(re, rnh->state)) + if (compare_state(re, rnh->state)) { copy_state(rnh, re, nrn); + state_changed = 1; + } if (state_changed || force) { if (IS_ZEBRA_DEBUG_NHT) { prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); - zlog_debug("%u:%s: Route import check %s %s\n", vrfid, + zlog_debug("%u:%s: Route import check %s %s", + zvrf->vrf->vrf_id, bufn, rnh->state ? "passed" : "failed", state_changed ? "(state changed)" : ""); } /* state changed, notify clients */ for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) { - send_client(rnh, client, RNH_IMPORT_CHECK_TYPE, vrfid); + send_client(rnh, client, + RNH_IMPORT_CHECK_TYPE, zvrf->vrf->vrf_id); } } } @@ -412,7 +532,7 @@ static void zebra_rnh_notify_protocol_clients(struct zebra_vrf *zvrf, afi_t afi, if (IS_ZEBRA_DEBUG_NHT) { prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); if (prn && re) { - prefix2str(&prn->p, bufp, INET6_ADDRSTRLEN); + srcdest_rnode2str(prn, bufp, INET6_ADDRSTRLEN); zlog_debug("%u:%s: NH resolved over route %s", zvrf->vrf->vrf_id, bufn, bufp); } else @@ -545,19 +665,43 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi, * most-specific match. Do similar logic as in zebra_rib.c */ while (rn) { + if (IS_ZEBRA_DEBUG_NHT_DETAILED) { + char buf[PREFIX_STRLEN]; + char buf1[PREFIX_STRLEN]; + + zlog_debug("%s: %u:%s Possible Match to %s", + __PRETTY_FUNCTION__, rnh->vrf_id, + prefix2str(&rnh->node->p, buf, sizeof(buf)), + srcdest_rnode2str(rn, buf1, sizeof(buf))); + } + /* Do not resolve over default route unless allowed && * match route to be exact if so specified */ if (is_default_prefix(&rn->p) - && !rnh_resolve_via_default(rn->p.family)) + && !rnh_resolve_via_default(rn->p.family)) { + if (IS_ZEBRA_DEBUG_NHT_DETAILED) + zlog_debug( + "\tNot allowed to resolve through default prefix"); return NULL; + } /* Identify appropriate route entry. */ RNODE_FOREACH_RE (rn, re) { - if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) { + if (IS_ZEBRA_DEBUG_NHT_DETAILED) + zlog_debug( + "\tRoute Entry %s removed", + zebra_route_string(re->type)); continue; - if (!CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) + } + if (!CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) { + if (IS_ZEBRA_DEBUG_NHT_DETAILED) + zlog_debug( + "\tRoute Entry %s !selected", + zebra_route_string(re->type)); continue; + } /* Just being SELECTED isn't quite enough - must * have an installed nexthop to be useful. @@ -567,8 +711,13 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi, break; } - if (nexthop == NULL) + if (nexthop == NULL) { + if (IS_ZEBRA_DEBUG_NHT_DETAILED) + zlog_debug( + "\tRoute Entry %s no nexthops", + zebra_route_string(re->type)); continue; + } if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) { if ((re->type == ZEBRA_ROUTE_CONNECT) @@ -594,10 +743,14 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi, return re; } - if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) + if (!CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) rn = rn->parent; - else + else { + if (IS_ZEBRA_DEBUG_NHT_DETAILED) + zlog_debug( + "\tNexthop must be connected, cannot recurse up"); return NULL; + } } return NULL; @@ -629,11 +782,20 @@ static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi, * the resolving route has some change (e.g., metric), there is a state * change. */ - if (!prefix_same(&rnh->resolved_route, &prn->p)) { + zebra_rnh_remove_from_routing_table(rnh); + if (!prefix_same(&rnh->resolved_route, prn ? NULL : &prn->p)) { if (prn) prefix_copy(&rnh->resolved_route, &prn->p); - else + else { + /* + * Just quickly store the family of the resolved + * route so that we can reset it in a second here + */ + int family = rnh->resolved_route.family; + memset(&rnh->resolved_route, 0, sizeof(struct prefix)); + rnh->resolved_route.family = family; + } copy_state(rnh, re, nrn); state_changed = 1; @@ -641,6 +803,7 @@ static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi, copy_state(rnh, re, nrn); state_changed = 1; } + zebra_rnh_store_in_routing_table(rnh); if (state_changed || force) { /* NOTE: Use the "copy" of resolving route stored in 'rnh' i.e., @@ -689,8 +852,8 @@ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, afi_t afi, /* Process based on type of entry. */ if (type == RNH_IMPORT_CHECK_TYPE) - zebra_rnh_eval_import_check_entry(zvrf->vrf->vrf_id, afi, force, - nrn, rnh, re); + zebra_rnh_eval_import_check_entry(zvrf, afi, force, nrn, rnh, + prn, re); else zebra_rnh_eval_nexthop_entry(zvrf, afi, force, nrn, rnh, prn, re); @@ -775,7 +938,7 @@ void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty, table = get_rnh_table(vrfid, afi, type); if (!table) { - zlog_debug("print_rnhs: rnh table not found\n"); + zlog_debug("print_rnhs: rnh table not found"); return; } @@ -790,7 +953,6 @@ void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty, static void free_state(vrf_id_t vrf_id, struct route_entry *re, struct route_node *rn) { - if (!re) return; @@ -1025,7 +1187,7 @@ static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi, ntable = get_rnh_table(vrf_id, afi, type); if (!ntable) { - zlog_debug("cleanup_rnh_client: rnh table not found\n"); + zlog_debug("cleanup_rnh_client: rnh table not found"); return -1; } diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h index 00ee60dc1a..7d823c7acc 100644 --- a/zebra/zebra_rnh.h +++ b/zebra/zebra_rnh.h @@ -25,6 +25,12 @@ #include "prefix.h" #include "vty.h" +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { RNH_NEXTHOP_TYPE, RNH_IMPORT_CHECK_TYPE } rnh_type_t; + /* Nexthop structure. */ struct rnh { uint8_t flags; @@ -36,6 +42,12 @@ struct rnh { /* VRF identifier. */ vrf_id_t vrf_id; + afi_t afi; + + rnh_type_t type; + + uint32_t seqno; + struct route_entry *state; struct prefix resolved_route; struct list *client_list; @@ -51,8 +63,6 @@ struct rnh { int filtered[ZEBRA_ROUTE_MAX]; }; -typedef enum { RNH_NEXTHOP_TYPE, RNH_IMPORT_CHECK_TYPE } rnh_type_t; - extern int zebra_rnh_ip_default_route; extern int zebra_rnh_ipv6_default_route; @@ -83,4 +93,9 @@ extern void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force, extern void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty, rnh_type_t); extern char *rnh_str(struct rnh *rnh, char *buf, int size); + +#ifdef __cplusplus +} +#endif + #endif /*_ZEBRA_RNH_H */ diff --git a/zebra/zebra_routemap.h b/zebra/zebra_routemap.h index abd2ad78f7..6a630e1ac0 100644 --- a/zebra/zebra_routemap.h +++ b/zebra/zebra_routemap.h @@ -24,6 +24,10 @@ #include "lib/routemap.h" +#ifdef __cplusplus +extern "C" { +#endif + extern void zebra_route_map_init(void); extern void zebra_routemap_config_write_protocol(struct vty *vty, struct zebra_vrf *vrf); @@ -48,4 +52,8 @@ zebra_nht_route_map_check(afi_t afi, int client_proto, const struct prefix *p, struct zebra_vrf *zvrf, struct route_entry *, struct nexthop *nexthop); +#ifdef __cplusplus +} +#endif + #endif diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c index cabc8be8dd..9e09cbca3f 100644 --- a/zebra/zebra_router.c +++ b/zebra/zebra_router.c @@ -164,8 +164,6 @@ static void zebra_router_free_table(struct zebra_router_table *zrt) { void *table_info; - rib_close_table(zrt->table); - table_info = route_table_get_info(zrt->table); route_table_finish(zrt->table); RB_REMOVE(zebra_router_table_head, &zrouter.tables, zrt); diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h index e5043f38ae..72b5e9b9b1 100644 --- a/zebra/zebra_router.h +++ b/zebra/zebra_router.h @@ -26,6 +26,10 @@ #include "zebra/zebra_ns.h" +#ifdef __cplusplus +extern "C" { +#endif + /* * This header file contains the idea of a router and as such * owns data that is associated with a router from zebra's @@ -104,6 +108,11 @@ struct zebra_router { /* Mlag information for the router */ struct zebra_mlag_info mlag_info; + + /* + * The EVPN instance, if any + */ + struct zebra_vrf *evpn_vrf; }; extern struct zebra_router zrouter; @@ -129,4 +138,19 @@ extern void zebra_router_sweep_route(void); extern void zebra_router_show_table_summary(struct vty *vty); extern uint32_t zebra_router_get_next_sequence(void); + +static inline vrf_id_t zebra_vrf_get_evpn_id(void) +{ + return zrouter.evpn_vrf ? zvrf_id(zrouter.evpn_vrf) : VRF_DEFAULT; +} +static inline struct zebra_vrf *zebra_vrf_get_evpn(void) +{ + return zrouter.evpn_vrf ? zrouter.evpn_vrf + : zebra_vrf_lookup_by_id(VRF_DEFAULT); +} + +#ifdef __cplusplus +} +#endif + #endif diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 1300ca24f3..2d721ec8a1 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -167,6 +167,11 @@ static int zebra_vrf_disable(struct vrf *vrf) /* Remove all routes. */ for (afi = AFI_IP; afi <= AFI_IP6; afi++) { + route_table_finish(zvrf->rnh_table[afi]); + zvrf->rnh_table[afi] = NULL; + route_table_finish(zvrf->import_check_table[afi]); + zvrf->import_check_table[afi] = NULL; + for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) rib_close_table(zvrf->table[afi][safi]); } @@ -213,11 +218,6 @@ static int zebra_vrf_disable(struct vrf *vrf) safi); zvrf->table[afi][safi] = NULL; } - - route_table_finish(zvrf->rnh_table[afi]); - zvrf->rnh_table[afi] = NULL; - route_table_finish(zvrf->import_check_table[afi]); - zvrf->import_check_table[afi] = NULL; } return 0; @@ -268,8 +268,10 @@ static int zebra_vrf_delete(struct vrf *vrf) } } - route_table_finish(zvrf->rnh_table[afi]); - route_table_finish(zvrf->import_check_table[afi]); + if (zvrf->rnh_table[afi]) + route_table_finish(zvrf->rnh_table[afi]); + if (zvrf->import_check_table[afi]) + route_table_finish(zvrf->import_check_table[afi]); } /* Cleanup EVPN states for vrf */ @@ -352,7 +354,12 @@ void zebra_rtable_node_cleanup(struct route_table *table, rib_unlink(node, re); } - XFREE(MTYPE_RIB_DEST, node->info); + if (node->info) { + rib_dest_t *dest = node->info; + + list_delete(&dest->nht); + XFREE(MTYPE_RIB_DEST, node->info); + } } static void zebra_rnhtable_node_cleanup(struct route_table *table, @@ -368,10 +375,19 @@ static void zebra_rnhtable_node_cleanup(struct route_table *table, static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi, safi_t safi) { + struct route_node *rn; + struct prefix p; + assert(!zvrf->table[afi][safi]); zvrf->table[afi][safi] = zebra_router_get_table(zvrf, zvrf->table_id, afi, safi); + + memset(&p, 0, sizeof(p)); + p.family = afi2family(afi); + + rn = srcdest_rnode_get(zvrf->table[afi][safi], &p, NULL); + zebra_rib_create_dest(rn); } /* Allocate new zebra VRF. */ diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index e35101d833..524c175b79 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -28,6 +28,10 @@ #include <zebra/zebra_pw.h> #include <lib/vxlan.h> +#ifdef __cplusplus +extern "C" { +#endif + /* MPLS (Segment Routing) global block */ typedef struct mpls_srgb_t_ { uint32_t start_label; @@ -107,18 +111,18 @@ struct zebra_vrf { #define MPLS_FLAG_SCHEDULE_LSPS (1 << 0) /* - * VNI hash table (for EVPN). Only in default instance. + * VNI hash table (for EVPN). Only in the EVPN instance. */ struct hash *vni_table; /* - * Whether EVPN is enabled or not. Only in default instance. + * Whether EVPN is enabled or not. Only in the EVPN instance. */ int advertise_all_vni; /* * Whether we are advertising g/w macip in EVPN or not. - * Only in default instance. + * Only in the EVPN instance. */ int advertise_gw_macip; @@ -203,4 +207,9 @@ extern void zebra_vrf_init(void); extern void zebra_rtable_node_cleanup(struct route_table *table, struct route_node *node); + +#ifdef __cplusplus +} +#endif + #endif /* ZEBRA_VRF_H */ diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index b0884f22cf..ad61842005 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -425,12 +425,6 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED)) json_object_boolean_true_add(json_route, "queued"); - if (re->type != ZEBRA_ROUTE_CONNECT) { - json_object_int_add(json_route, "distance", - re->distance); - json_object_int_add(json_route, "metric", re->metric); - } - if (re->tag) json_object_int_add(json_route, "tag", re->tag); @@ -1375,7 +1369,7 @@ static void vty_show_ip_route_summary(struct vty *vty, else rib_cnt[re->type]++; - if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) { fib_cnt[ZEBRA_ROUTE_TOTAL]++; if (is_ibgp) @@ -1614,7 +1608,7 @@ DEFUN (show_vrf, return CMD_SUCCESS; } -DEFUN_HIDDEN (default_vrf_vni_mapping, +DEFUN (default_vrf_vni_mapping, default_vrf_vni_mapping_cmd, "vni " CMD_VNI_RANGE "[prefix-routes-only]", "VNI corresponding to the DEFAULT VRF\n" @@ -1644,7 +1638,7 @@ DEFUN_HIDDEN (default_vrf_vni_mapping, return CMD_SUCCESS; } -DEFUN_HIDDEN (no_default_vrf_vni_mapping, +DEFUN (no_default_vrf_vni_mapping, no_default_vrf_vni_mapping_cmd, "no vni " CMD_VNI_RANGE, NO_STR @@ -1802,7 +1796,7 @@ DEFUN (show_evpn_vni, struct zebra_vrf *zvrf; bool uj = use_json(argc, argv); - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); zebra_vxlan_print_vnis(vty, zvrf, uj); return CMD_SUCCESS; } @@ -1818,7 +1812,7 @@ DEFUN (show_evpn_vni_detail, show_evpn_vni_detail_cmd, struct zebra_vrf *zvrf; bool uj = use_json(argc, argv); - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); zebra_vxlan_print_vnis_detail(vty, zvrf, uj); return CMD_SUCCESS; } @@ -1837,7 +1831,7 @@ DEFUN (show_evpn_vni_vni, bool uj = use_json(argc, argv); vni = strtoul(argv[3]->arg, NULL, 10); - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); zebra_vxlan_print_vni(vty, zvrf, vni, uj); return CMD_SUCCESS; } @@ -1981,7 +1975,7 @@ DEFUN (show_evpn_mac_vni, bool uj = use_json(argc, argv); vni = strtoul(argv[4]->arg, NULL, 10); - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); zebra_vxlan_print_macs_vni(vty, zvrf, vni, uj); return CMD_SUCCESS; } @@ -1999,7 +1993,7 @@ DEFUN (show_evpn_mac_vni_all, struct zebra_vrf *zvrf; bool uj = use_json(argc, argv); - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); zebra_vxlan_print_macs_all_vni(vty, zvrf, false, uj); return CMD_SUCCESS; } @@ -2017,7 +2011,7 @@ DEFUN (show_evpn_mac_vni_all_detail, show_evpn_mac_vni_all_detail_cmd, struct zebra_vrf *zvrf; bool uj = use_json(argc, argv); - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); zebra_vxlan_print_macs_all_vni_detail(vty, zvrf, false, uj); return CMD_SUCCESS; } @@ -2043,7 +2037,7 @@ DEFUN (show_evpn_mac_vni_all_vtep, vty_out(vty, "%% Malformed VTEP IP address\n"); return CMD_WARNING; } - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip, uj); return CMD_SUCCESS; @@ -2073,7 +2067,7 @@ DEFUN (show_evpn_mac_vni_mac, vty_out(vty, "%% Malformed MAC address"); return CMD_WARNING; } - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac, uj); return CMD_SUCCESS; } @@ -2102,7 +2096,7 @@ DEFUN (show_evpn_mac_vni_vtep, return CMD_WARNING; } - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip, uj); return CMD_SUCCESS; } @@ -2121,7 +2115,7 @@ DEFPY (show_evpn_mac_vni_all_dad, struct zebra_vrf *zvrf; bool uj = use_json(argc, argv); - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); zebra_vxlan_print_macs_all_vni(vty, zvrf, true, uj); return CMD_SUCCESS; } @@ -2143,7 +2137,7 @@ DEFPY (show_evpn_mac_vni_dad, bool uj = use_json(argc, argv); vni = strtoul(argv[4]->arg, NULL, 10); - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); zebra_vxlan_print_macs_vni_dad(vty, zvrf, vni, uj); @@ -2166,7 +2160,7 @@ DEFPY (show_evpn_neigh_vni_dad, bool uj = use_json(argc, argv); vni = strtoul(argv[4]->arg, NULL, 10); - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); zebra_vxlan_print_neigh_vni_dad(vty, zvrf, vni, uj); return CMD_SUCCESS; } @@ -2185,7 +2179,7 @@ DEFPY (show_evpn_neigh_vni_all_dad, struct zebra_vrf *zvrf; bool uj = use_json(argc, argv); - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); zebra_vxlan_print_neigh_all_vni(vty, zvrf, true, uj); return CMD_SUCCESS; } @@ -2206,7 +2200,7 @@ DEFUN (show_evpn_neigh_vni, bool uj = use_json(argc, argv); vni = strtoul(argv[4]->arg, NULL, 10); - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); zebra_vxlan_print_neigh_vni(vty, zvrf, vni, uj); return CMD_SUCCESS; } @@ -2224,7 +2218,7 @@ DEFUN (show_evpn_neigh_vni_all, struct zebra_vrf *zvrf; bool uj = use_json(argc, argv); - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); zebra_vxlan_print_neigh_all_vni(vty, zvrf, false, uj); return CMD_SUCCESS; } @@ -2241,7 +2235,7 @@ DEFUN (show_evpn_neigh_vni_all_detail, show_evpn_neigh_vni_all_detail_cmd, struct zebra_vrf *zvrf; bool uj = use_json(argc, argv); - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); zebra_vxlan_print_neigh_all_vni_detail(vty, zvrf, false, uj); return CMD_SUCCESS; } @@ -2269,7 +2263,7 @@ DEFUN (show_evpn_neigh_vni_neigh, vty_out(vty, "%% Malformed Neighbor address\n"); return CMD_WARNING; } - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip, uj); return CMD_SUCCESS; } @@ -2298,7 +2292,7 @@ DEFUN (show_evpn_neigh_vni_vtep, return CMD_WARNING; } - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip, uj); return CMD_SUCCESS; } @@ -2363,7 +2357,7 @@ DEFPY (clear_evpn_dup_addr, struct ethaddr mac_addr; int ret = CMD_SUCCESS; - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); if (vni_val) { vni = strtoul(vni_val, NULL, 10); diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 00fc230851..3a8426e772 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -324,7 +324,7 @@ static int advertise_gw_macip_enabled(zebra_vni_t *zvni) { struct zebra_vrf *zvrf; - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); if (zvrf && zvrf->advertise_gw_macip) return 1; @@ -338,7 +338,7 @@ static int advertise_svi_macip_enabled(zebra_vni_t *zvni) { struct zebra_vrf *zvrf; - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); if (zvrf && zvrf->advertise_svi_macip) return 1; @@ -382,6 +382,9 @@ static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf, SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE); /* Capture Duplicate detection time */ nbr->dad_dup_detect_time = monotime(NULL); + /* Mark neigh inactive */ + ZEBRA_NEIGH_SET_INACTIVE(nbr); + return 1; } else if (is_old_mac_dup && !is_new_mac_dup) { UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE); @@ -704,11 +707,10 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json) struct zebra_vrf *zvrf = NULL; struct timeval detect_start_time = {0, 0}; - zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); if (!zvrf) return; - zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT); ipaddr2str(&n->ip, buf2, sizeof(buf2)); prefix_mac2str(&n->emac, buf1, sizeof(buf1)); type_str = CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) ? @@ -1152,7 +1154,9 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json) struct zebra_vrf *zvrf; struct timeval detect_start_time = {0, 0}; - zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); + if (!zvrf) + return; vty = (struct vty *)ctxt; prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1)); @@ -2076,7 +2080,7 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr, s = stream_new(ZEBRA_MAX_PACKET_SIZ); - zclient_create_header(s, cmd, VRF_DEFAULT); + zclient_create_header(s, cmd, zebra_vrf_get_evpn_id()); stream_putl(s, vni); stream_put(s, macaddr->octet, ETH_ALEN); if (ip) { @@ -2190,6 +2194,8 @@ static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip, memcpy(&n->emac, mac, ETH_ALEN); n->state = ZEBRA_NEIGH_INACTIVE; + n->zvni = zvni; + n->dad_ip_auto_recovery_timer = NULL; /* Associate the neigh to mac */ zmac = zvni_mac_lookup(zvni, mac); @@ -2211,6 +2217,9 @@ static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n) if (zmac) listnode_delete(zmac->neigh_list, n); + /* Cancel auto recovery */ + THREAD_OFF(n->dad_ip_auto_recovery_timer); + /* Free the VNI hash entry and allocated memory. */ tmp_n = hash_release(zvni->neigh_table, n); XFREE(MTYPE_NEIGH, tmp_n); @@ -3191,13 +3200,14 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, return 0; } - ZEBRA_NEIGH_SET_ACTIVE(n); n->loc_seq = zmac->loc_seq; - if (!neigh_on_hold) + if (!neigh_on_hold) { + ZEBRA_NEIGH_SET_ACTIVE(n); + return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, n->flags, n->loc_seq); - else { + } else { if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug("\tNeighbor on hold not sending"); } @@ -3307,6 +3317,9 @@ static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr) mac = hash_get(zvni->mac_table, &tmp_mac, zvni_mac_alloc); assert(mac); + mac->zvni = zvni; + mac->dad_mac_auto_recovery_timer = NULL; + mac->neigh_list = list_new(); mac->neigh_list->cmp = neigh_list_cmp; @@ -3320,6 +3333,9 @@ static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac) { zebra_mac_t *tmp_mac; + /* Cancel auto recovery */ + THREAD_OFF(mac->dad_mac_auto_recovery_timer); + list_delete(&mac->neigh_list); /* Free the VNI hash entry and allocated memory. */ @@ -3817,7 +3833,7 @@ static zebra_vni_t *zvni_lookup(vni_t vni) zebra_vni_t tmp_vni; zebra_vni_t *zvni = NULL; - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); assert(zvrf); memset(&tmp_vni, 0, sizeof(zebra_vni_t)); tmp_vni.vni = vni; @@ -3835,7 +3851,7 @@ static zebra_vni_t *zvni_add(vni_t vni) zebra_vni_t tmp_zvni; zebra_vni_t *zvni = NULL; - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); assert(zvrf); memset(&tmp_zvni, 0, sizeof(zebra_vni_t)); tmp_zvni.vni = vni; @@ -3861,7 +3877,7 @@ static int zvni_del(zebra_vni_t *zvni) struct zebra_vrf *zvrf; zebra_vni_t *tmp_zvni; - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); assert(zvrf); zvni->vxlan_if = NULL; @@ -3896,7 +3912,7 @@ static int zvni_send_add_to_client(zebra_vni_t *zvni) s = stream_new(ZEBRA_MAX_PACKET_SIZ); - zclient_create_header(s, ZEBRA_VNI_ADD, VRF_DEFAULT); + zclient_create_header(s, ZEBRA_VNI_ADD, zebra_vrf_get_evpn_id()); 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 */ @@ -3930,7 +3946,7 @@ static int zvni_send_del_to_client(vni_t vni) s = stream_new(ZEBRA_MAX_PACKET_SIZ); stream_reset(s); - zclient_create_header(s, ZEBRA_VNI_DEL, VRF_DEFAULT); + zclient_create_header(s, ZEBRA_VNI_DEL, zebra_vrf_get_evpn_id()); stream_putl(s, vni); /* Write packet size. */ @@ -6940,7 +6956,7 @@ void zebra_vxlan_print_evpn(struct vty *vty, bool uj) if (!is_evpn_enabled()) return; - zvrf = vrf_info_lookup(VRF_DEFAULT); + zvrf = zebra_vrf_get_evpn(); if (!zvrf) return; @@ -7782,9 +7798,9 @@ void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS) return; } - if (zvrf_id(zvrf) != VRF_DEFAULT) { - zlog_debug("Recv MACIP DEL for non-default VRF %u", - zvrf_id(zvrf)); + if (!EVPN_ENABLED(zvrf)) { + zlog_debug("Recv MACIP DEL for non-EVPN VRF %u", + zvrf_id(zvrf)); return; } @@ -7866,9 +7882,9 @@ void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS) return; } - if (zvrf_id(zvrf) != VRF_DEFAULT) { - zlog_debug("Recv MACIP ADD for non-default VRF %u", - zvrf_id(zvrf)); + if (!EVPN_ENABLED(zvrf)) { + zlog_debug("Recv MACIP ADD for non-EVPN VRF %u", + zvrf_id(zvrf)); return; } @@ -8602,10 +8618,10 @@ int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni, int add) { zebra_l3vni_t *zl3vni = NULL; - struct zebra_vrf *zvrf_default = NULL; + struct zebra_vrf *zvrf_evpn = NULL; - zvrf_default = zebra_vrf_lookup_by_id(VRF_DEFAULT); - if (!zvrf_default) + zvrf_evpn = zebra_vrf_get_evpn(); + if (!zvrf_evpn) return -1; if (IS_ZEBRA_DEBUG_VXLAN) @@ -8659,7 +8675,7 @@ int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni, zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni); /* formulate l2vni list */ - hash_iterate(zvrf_default->vni_table, zvni_add_to_l3vni_list, + hash_iterate(zvrf_evpn->vni_table, zvni_add_to_l3vni_list, zl3vni); if (is_l3vni_oper_up(zl3vni)) @@ -8754,8 +8770,8 @@ void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS) struct stream *s; enum vxlan_flood_control flood_ctrl; - if (zvrf_id(zvrf) != VRF_DEFAULT) { - zlog_err("EVPN flood control for non-default VRF %u", + if (!EVPN_ENABLED(zvrf)) { + zlog_err("EVPN flood control for non-EVPN VRF %u", zvrf_id(zvrf)); return; } @@ -8794,9 +8810,9 @@ void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS) zebra_vni_t *zvni = NULL; struct interface *ifp = NULL; - if (zvrf_id(zvrf) != VRF_DEFAULT) { - zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u", - zvrf_id(zvrf)); + if (!EVPN_ENABLED(zvrf)) { + zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u", + zvrf_id(zvrf)); return; } @@ -8893,9 +8909,9 @@ void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS) struct zebra_l2info_vxlan zl2_info; struct interface *vlan_if = NULL; - if (zvrf_id(zvrf) != VRF_DEFAULT) { - zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u", - zvrf_id(zvrf)); + if (!EVPN_ENABLED(zvrf)) { + zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u", + zvrf_id(zvrf)); return; } @@ -8956,8 +8972,8 @@ void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS) zebra_vni_t *zvni = NULL; struct interface *ifp = NULL; - if (zvrf_id(zvrf) != VRF_DEFAULT) { - zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u", + if (!EVPN_ENABLED(zvrf)) { + zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u", zvrf_id(zvrf)); return; } @@ -9063,18 +9079,18 @@ void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS) int advertise = 0; enum vxlan_flood_control flood_ctrl; - if (zvrf_id(zvrf) != VRF_DEFAULT) { - zlog_debug("EVPN VNI Adv for non-default VRF %u", - zvrf_id(zvrf)); + /* Mismatch between EVPN VRF and current VRF (should be prevented by + * bgpd's cli) */ + if (is_evpn_enabled() && !EVPN_ENABLED(zvrf)) return; - } s = msg; STREAM_GETC(s, advertise); STREAM_GETC(s, flood_ctrl); if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("EVPN VNI Adv %s, currently %s, flood control %u", + zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u", + zvrf_name(zvrf), zvrf_id(zvrf), advertise ? "enabled" : "disabled", is_evpn_enabled() ? "enabled" : "disabled", flood_ctrl); @@ -9083,7 +9099,9 @@ void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS) return; zvrf->advertise_all_vni = advertise; - if (is_evpn_enabled()) { + if (EVPN_ENABLED(zvrf)) { + zrouter.evpn_vrf = zvrf; + /* Note BUM handling */ zvrf->vxlan_flood_ctrl = flood_ctrl; @@ -9107,6 +9125,9 @@ void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS) /* cleanup all l3vnis */ hash_iterate(zrouter.l3vni_table, zl3vni_cleanup_all, NULL); + + /* Mark as "no EVPN VRF" */ + zrouter.evpn_vrf = NULL; } stream_failure: @@ -9147,6 +9168,7 @@ void zebra_vxlan_init(void) { zrouter.l3vni_table = hash_create(l3vni_hash_keymake, l3vni_hash_cmp, "Zebra VRF L3 VNI table"); + zrouter.evpn_vrf = NULL; } /* free l3vni table */ @@ -9193,8 +9215,8 @@ static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread *t) if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired", __PRETTY_FUNCTION__, - prefix_mac2str(&nbr->emac, buf1, sizeof(buf1)), - ipaddr2str(&nbr->ip, buf2, sizeof(buf2)), + prefix_mac2str(&nbr->emac, buf2, sizeof(buf2)), + ipaddr2str(&nbr->ip, buf1, sizeof(buf1)), nbr->flags, nbr->dad_count, zvni->vni); @@ -9204,6 +9226,7 @@ static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread *t) nbr->detect_start_time.tv_usec = 0; nbr->dad_dup_detect_time = 0; nbr->dad_ip_auto_recovery_timer = NULL; + ZEBRA_NEIGH_SET_ACTIVE(nbr); /* Send to BGP */ if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) { diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h index 2cf21ff90b..2ff92970d7 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -25,6 +25,7 @@ #define _ZEBRA_VXLAN_H #include <zebra.h> +#include <zebra/zebra_router.h> #include "linklist.h" #include "if.h" @@ -35,19 +36,23 @@ #include "zebra/zebra_vrf.h" #include "zebra/zserv.h" +#ifdef __cplusplus +extern "C" { +#endif + /* Is EVPN enabled? */ #define EVPN_ENABLED(zvrf) (zvrf)->advertise_all_vni static inline int is_evpn_enabled(void) { struct zebra_vrf *zvrf = NULL; - zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT); - return zvrf ? zvrf->advertise_all_vni : 0; + zvrf = zebra_vrf_get_evpn(); + return zvrf ? EVPN_ENABLED(zvrf) : 0; } static inline int is_vxlan_flooding_head_end(void) { - struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT); + struct zebra_vrf *zvrf = zebra_vrf_get_evpn(); if (!zvrf) return 0; @@ -206,4 +211,8 @@ extern int zebra_vxlan_clear_dup_detect_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni); +#ifdef __cplusplus +} +#endif + #endif /* _ZEBRA_VXLAN_H */ diff --git a/zebra/zebra_vxlan_private.h b/zebra/zebra_vxlan_private.h index c36d156359..5081c08d19 100644 --- a/zebra/zebra_vxlan_private.h +++ b/zebra/zebra_vxlan_private.h @@ -26,12 +26,14 @@ #include <zebra.h> -#include <zebra.h> - #include "if.h" #include "linklist.h" #include "zebra_vxlan.h" +#ifdef __cplusplus +extern "C" { +#endif + #define ERR_STR_SZ 256 /* definitions */ @@ -421,4 +423,8 @@ struct nh_walk_ctx { struct json_object *json; }; +#ifdef __cplusplus +} +#endif + #endif /* _ZEBRA_VXLAN_PRIVATE_H */ diff --git a/zebra/zserv.c b/zebra/zserv.c index 6532491cef..f5bb3aabb7 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -773,6 +773,18 @@ static int zserv_accept(struct thread *thread) return 0; } +void zserv_close(void) +{ + /* + * On shutdown, let's close the socket down + * so that long running processes of killing the + * routing table doesn't leave us in a bad + * state where a client tries to reconnect + */ + close(zsock); + zsock = -1; +} + void zserv_start(char *path) { int ret; diff --git a/zebra/zserv.h b/zebra/zserv.h index ac016e65f3..86863d961c 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -40,6 +40,10 @@ #include "zebra/zebra_vrf.h" /* for zebra_vrf */ /* clang-format on */ +#ifdef __cplusplus +extern "C" { +#endif + /* Default port information. */ #define ZEBRA_VTY_PORT 2601 @@ -180,6 +184,13 @@ extern unsigned int multipath_num; extern void zserv_init(void); /* + * Stop the Zebra API server. + * + * closes the socket + */ +extern void zserv_close(void); + +/* * Start Zebra API server. * * Allocates resources, creates the server socket and begins listening on the @@ -234,4 +245,8 @@ extern void zserv_read_file(char *input); /* TODO */ int zebra_finalize(struct thread *event); +#ifdef __cplusplus +} +#endif + #endif /* _ZEBRA_ZEBRA_H */ |
