diff options
Diffstat (limited to 'zebra')
| -rw-r--r-- | zebra/dplane_fpm_nl.c | 8 | ||||
| -rw-r--r-- | zebra/kernel_netlink.c | 13 | ||||
| -rw-r--r-- | zebra/kernel_netlink.h | 3 | ||||
| -rw-r--r-- | zebra/rib.h | 3 | ||||
| -rw-r--r-- | zebra/rt_netlink.c | 55 | ||||
| -rw-r--r-- | zebra/sample_plugin.c | 1 | ||||
| -rw-r--r-- | zebra/subdir.am | 11 | ||||
| -rw-r--r-- | zebra/zebra_dplane.c | 26 | ||||
| -rw-r--r-- | zebra/zebra_evpn_mac.c | 311 | ||||
| -rw-r--r-- | zebra/zebra_evpn_mac.h | 1 | ||||
| -rw-r--r-- | zebra/zebra_fpm.c | 22 | ||||
| -rw-r--r-- | zebra/zebra_fpm_netlink.c | 10 | ||||
| -rw-r--r-- | zebra/zebra_nhg.c | 6 | ||||
| -rw-r--r-- | zebra/zebra_rib.c | 145 | ||||
| -rw-r--r-- | zebra/zebra_routemap.c | 63 |
15 files changed, 474 insertions, 204 deletions
diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c index 51ce59c477..bf733e38f7 100644 --- a/zebra/dplane_fpm_nl.c +++ b/zebra/dplane_fpm_nl.c @@ -1236,7 +1236,13 @@ static int fpm_process_queue(struct thread *t) if (ctx == NULL) break; - fpm_nl_enqueue(fnc, ctx); + /* + * Intentionally ignoring the return value + * as that we are ensuring that we can write to + * the output data in the STREAM_WRITEABLE + * check above, so we can ignore the return + */ + (void)fpm_nl_enqueue(fnc, ctx); /* Account the processed entries. */ processed_contexts++; diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 5d64f57b3e..bbe2fccc60 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -489,6 +489,19 @@ static void netlink_install_filter(int sock, __u32 pid, __u32 dplane_pid) safe_strerror(errno)); } +void netlink_parse_rtattr_flags(struct rtattr **tb, int max, + struct rtattr *rta, int len, unsigned short flags) +{ + unsigned short type; + + while (RTA_OK(rta, len)) { + type = rta->rta_type & ~flags; + if ((type <= max) && (!tb[type])) + tb[type] = rta; + rta = RTA_NEXT(rta, len); + } +} + void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len) { diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h index 696f9be4f6..a7b152b31b 100644 --- a/zebra/kernel_netlink.h +++ b/zebra/kernel_netlink.h @@ -79,6 +79,9 @@ extern void nl_attr_rtnh_end(struct nlmsghdr *n, struct rtnexthop *rtnh); extern void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len); +extern void netlink_parse_rtattr_flags(struct rtattr **tb, int max, + struct rtattr *rta, int len, + unsigned short flags); extern void netlink_parse_rtattr_nested(struct rtattr **tb, int max, struct rtattr *rta); extern const char *nl_msg_type_to_str(uint16_t msg_type); diff --git a/zebra/rib.h b/zebra/rib.h index d653425f0d..86766b8175 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -406,9 +406,8 @@ extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id); extern void rib_update(enum rib_update_event event); -extern void rib_update_vrf(vrf_id_t vrf_id, enum rib_update_event event); extern void rib_update_table(struct route_table *table, - enum rib_update_event event); + enum rib_update_event event, int rtype); extern int rib_sweep_route(struct thread *t); extern void rib_sweep_table(struct route_table *table); extern void rib_close_table(struct route_table *table); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 547700d0c5..d96d77e77c 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -77,16 +77,7 @@ /* Re-defining as I am unable to include <linux/if_bridge.h> which has the * UAPI for MAC sync. */ #ifndef _UAPI_LINUX_IF_BRIDGE_H -/* FDB notification bits for NDA_NOTIFY: - * - BR_FDB_NFY_STATIC - notify on activity/expire even for a static entry - * - BR_FDB_NFY_INACTIVE - mark as inactive to avoid double notification, - * used with BR_FDB_NFY_STATIC (kernel controlled) - */ -enum { - BR_FDB_NFY_STATIC, - BR_FDB_NFY_INACTIVE, - BR_FDB_NFY_MAX -}; +#define BR_SPH_LIST_SIZE 10 #endif static vlanid_t filter_vlan = 0; @@ -2766,11 +2757,23 @@ static ssize_t netlink_neigh_update_msg_encode( } if (nfy) { - if (!nl_attr_put(&req->n, datalen, NDA_NOTIFY, - &nfy_flags, sizeof(nfy_flags))) + struct rtattr *nest; + + nest = nl_attr_nest(&req->n, datalen, + NDA_FDB_EXT_ATTRS | NLA_F_NESTED); + if (!nest) + return 0; + + if (!nl_attr_put(&req->n, datalen, NFEA_ACTIVITY_NOTIFY, + &nfy_flags, sizeof(nfy_flags))) + return 0; + if (!nl_attr_put(&req->n, datalen, NFEA_DONT_REFRESH, NULL, 0)) return 0; + + nl_attr_nest_end(&req->n, nest); } + if (ext) { if (!nl_attr_put(&req->n, datalen, NDA_EXT_FLAGS, &ext_flags, sizeof(ext_flags))) @@ -2855,7 +2858,8 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id) * validation of the fields. */ memset(tb, 0, sizeof tb); - netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len); + netlink_parse_rtattr_flags(tb, NDA_MAX, NDA_RTA(ndm), len, + NLA_F_NESTED); if (!tb[NDA_LLADDR]) { if (IS_ZEBRA_DEBUG_KERNEL) @@ -2897,14 +2901,21 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id) if (ndm->ndm_state & NUD_STALE) local_inactive = true; - if (tb[NDA_NOTIFY]) { - uint8_t nfy_flags; + if (tb[NDA_FDB_EXT_ATTRS]) { + struct rtattr *attr = tb[NDA_FDB_EXT_ATTRS]; + struct rtattr *nfea_tb[NFEA_MAX + 1] = {0}; - dp_static = true; - nfy_flags = *(uint8_t *)RTA_DATA(tb[NDA_NOTIFY]); - /* local activity has not been detected on the entry */ - if (nfy_flags & (1 << BR_FDB_NFY_INACTIVE)) - local_inactive = true; + netlink_parse_rtattr_nested(nfea_tb, NFEA_MAX, attr); + if (nfea_tb[NFEA_ACTIVITY_NOTIFY]) { + uint8_t nfy_flags; + + nfy_flags = *(uint8_t *)RTA_DATA( + nfea_tb[NFEA_ACTIVITY_NOTIFY]); + if (nfy_flags & FDB_NOTIFY_BIT) + dp_static = true; + if (nfy_flags & FDB_NOTIFY_INACTIVE_BIT) + local_inactive = true; + } } if (IS_ZEBRA_DEBUG_KERNEL) @@ -3206,12 +3217,12 @@ ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, void *data, } else { /* local mac */ if (update_flags & DPLANE_MAC_SET_STATIC) { - nfy_flags |= (1 << BR_FDB_NFY_STATIC); + nfy_flags |= FDB_NOTIFY_BIT; state |= NUD_NOARP; } if (update_flags & DPLANE_MAC_SET_INACTIVE) - nfy_flags |= (1 << BR_FDB_NFY_INACTIVE); + nfy_flags |= FDB_NOTIFY_INACTIVE_BIT; nfy = true; } diff --git a/zebra/sample_plugin.c b/zebra/sample_plugin.c index c96a86cc73..464205f2f3 100644 --- a/zebra/sample_plugin.c +++ b/zebra/sample_plugin.c @@ -92,7 +92,6 @@ static int sample_process(struct zebra_dplane_provider *prov) static int init_sample_plugin(struct thread_master *tm) { int ret; - struct zebra_dplane_provider *prov = NULL; /* Note that we don't use or store the thread_master 'tm'. We * don't use the zebra main pthread: our plugin code will run in diff --git a/zebra/subdir.am b/zebra/subdir.am index cdacabc102..f842a8c0f3 100644 --- a/zebra/subdir.am +++ b/zebra/subdir.am @@ -40,6 +40,11 @@ if LINUX module_LTLIBRARIES += zebra/zebra_cumulus_mlag.la endif +# Dataplane sample plugin +if DEV_BUILD +module_LTLIBRARIES += zebra/dplane_sample_plugin.la +endif + man8 += $(MANBUILD)/frr-zebra.8 ## endif ZEBRA endif @@ -206,6 +211,12 @@ zebra/zebra_fpm_dt.lo: fpm/fpm.pb-c.h qpb/qpb.pb-c.h endif endif +# Sample dataplane plugin +if DEV_BUILD +zebra_dplane_sample_plugin_la_SOURCES = zebra/sample_plugin.c +zebra_dplane_sample_plugin_la_LDFLAGS = -module -shared -avoid-version -export-dynamic +endif + nodist_zebra_zebra_SOURCES = \ yang/frr-zebra.yang.c \ # end diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index da7f4cf64e..db2b9e002e 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -3684,7 +3684,7 @@ int dplane_show_helper(struct vty *vty, bool detailed) int dplane_show_provs_helper(struct vty *vty, bool detailed) { struct zebra_dplane_provider *prov; - uint64_t in, in_max, out, out_max; + uint64_t in, in_q, in_max, out, out_q, out_max; vty_out(vty, "Zebra dataplane providers:\n"); @@ -3697,17 +3697,20 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed) in = atomic_load_explicit(&prov->dp_in_counter, memory_order_relaxed); + in_q = atomic_load_explicit(&prov->dp_in_queued, + memory_order_relaxed); in_max = atomic_load_explicit(&prov->dp_in_max, memory_order_relaxed); out = atomic_load_explicit(&prov->dp_out_counter, memory_order_relaxed); + out_q = atomic_load_explicit(&prov->dp_out_queued, + memory_order_relaxed); out_max = atomic_load_explicit(&prov->dp_out_max, memory_order_relaxed); - vty_out(vty, - "%s (%u): in: %" PRIu64 ", q_max: %" PRIu64 - ", out: %" PRIu64 ", q_max: %" PRIu64 "\n", - prov->dp_name, prov->dp_id, in, in_max, out, out_max); + vty_out(vty, "%s (%u): in: %"PRIu64", q: %"PRIu64", q_max: %"PRIu64", out: %"PRIu64", q: %"PRIu64", q_max: %"PRIu64"\n", + prov->dp_name, prov->dp_id, in, in_q, in_max, + out, out_q, out_max); DPLANE_LOCK(); prov = TAILQ_NEXT(prov, dp_prov_link); @@ -3912,11 +3915,24 @@ uint32_t dplane_provider_out_ctx_queue_len(struct zebra_dplane_provider *prov) void dplane_provider_enqueue_out_ctx(struct zebra_dplane_provider *prov, struct zebra_dplane_ctx *ctx) { + uint64_t curr, high; + dplane_provider_lock(prov); TAILQ_INSERT_TAIL(&(prov->dp_ctx_out_q), ctx, zd_q_entries); + /* Maintain out-queue counters */ + atomic_fetch_add_explicit(&(prov->dp_out_queued), 1, + memory_order_relaxed); + curr = atomic_load_explicit(&prov->dp_out_queued, + memory_order_relaxed); + high = atomic_load_explicit(&prov->dp_out_max, + memory_order_relaxed); + if (curr > high) + atomic_store_explicit(&prov->dp_out_max, curr, + memory_order_relaxed); + dplane_provider_unlock(prov); atomic_fetch_add_explicit(&(prov->dp_out_counter), 1, diff --git a/zebra/zebra_evpn_mac.c b/zebra/zebra_evpn_mac.c index 376721f83a..6753bf520c 100644 --- a/zebra/zebra_evpn_mac.c +++ b/zebra/zebra_evpn_mac.c @@ -29,6 +29,7 @@ #include "prefix.h" #include "vlan.h" #include "json.h" +#include "printfrr.h" #include "zebra/zserv.h" #include "zebra/debug.h" @@ -254,6 +255,37 @@ static void zebra_evpn_mac_get_access_info(zebra_mac_t *mac, } } +#define MAC_BUF_SIZE 256 +static char *zebra_evpn_zebra_mac_flag_dump(struct zebra_mac_t_ *mac, char *buf, + size_t len) +{ + if (mac->flags == 0) { + snprintfrr(buf, len, "None "); + return buf; + } + + snprintfrr( + buf, len, "%s%s%s%s%s%s%s%s%s%s%s%s", + CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) ? "LOC " : "", + CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) ? "REM " : "", + CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO) ? "AUTO " : "", + CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? "STICKY " : "", + CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_RMAC) ? "REM Router " + : "", + CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW) ? "Default GW " : "", + CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) ? "REM DEF GW " + : "", + CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE) ? "DUP " : "", + CHECK_FLAG(mac->flags, ZEBRA_MAC_FPM_SENT) ? "FPM " : "", + CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE) ? "LOC Active " + : "", + CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY) ? "PROXY " : "", + CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE) + ? "LOC Inactive " + : ""); + return buf; +} + static int zebra_evpn_dad_mac_auto_recovery_exp(struct thread *t) { struct zebra_vrf *zvrf = NULL; @@ -278,12 +310,17 @@ static int zebra_evpn_dad_mac_auto_recovery_exp(struct thread *t) if (!mac) return 0; - if (IS_ZEBRA_DEBUG_VXLAN) + if (IS_ZEBRA_DEBUG_VXLAN) { + char mac_buf[MAC_BUF_SIZE]; + zlog_debug( - "%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired", + "%s: duplicate addr mac %s flags %slearn count %u host count %u auto recovery expired", __func__, prefix_mac2str(&mac->macaddr, buf, sizeof(buf)), - mac->flags, mac->dad_count, listcount(mac->neigh_list)); + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, + sizeof(mac_buf)), + mac->dad_count, listcount(mac->neigh_list)); + } /* Remove all IPs as duplicate associcated with this MAC */ for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) { @@ -350,14 +387,17 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf, * Remote MAC event -> hold on installing it. */ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) { - if (IS_ZEBRA_DEBUG_VXLAN) + if (IS_ZEBRA_DEBUG_VXLAN) { + char mac_buf[MAC_BUF_SIZE]; + zlog_debug( - "%s: duplicate addr MAC %s flags 0x%x skip update to client, learn count %u recover time %u", + "%s: duplicate addr MAC %s flags %sskip update to client, learn count %u recover time %u", __func__, prefix_mac2str(&mac->macaddr, buf, sizeof(buf)), - mac->flags, mac->dad_count, - zvrf->dad_freeze_time); - + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, + sizeof(mac_buf)), + mac->dad_count, zvrf->dad_freeze_time); + } /* For duplicate MAC do not update * client but update neigh due to * this MAC update. @@ -385,12 +425,17 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf, } if (reset_params) { - if (IS_ZEBRA_DEBUG_VXLAN) + if (IS_ZEBRA_DEBUG_VXLAN) { + char mac_buf[MAC_BUF_SIZE]; + zlog_debug( - "%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u", + "%s: duplicate addr MAC %s flags %sdetection time passed, reset learn count %u", __func__, prefix_mac2str(&mac->macaddr, buf, sizeof(buf)), - mac->flags, mac->dad_count); + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, + sizeof(mac_buf)), + mac->dad_count); + } mac->dad_count = 0; /* Start dup. addr detection (DAD) start time, @@ -452,13 +497,18 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf, /* Start auto recovery timer for this MAC */ THREAD_OFF(mac->dad_mac_auto_recovery_timer); if (zvrf->dad_freeze && zvrf->dad_freeze_time) { - if (IS_ZEBRA_DEBUG_VXLAN) + if (IS_ZEBRA_DEBUG_VXLAN) { + char mac_buf[MAC_BUF_SIZE]; + zlog_debug( - "%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start", + "%s: duplicate addr MAC %s flags %sauto recovery time %u start", __func__, prefix_mac2str(&mac->macaddr, buf, sizeof(buf)), - mac->flags, zvrf->dad_freeze_time); + zebra_evpn_zebra_mac_flag_dump( + mac, mac_buf, sizeof(mac_buf)), + zvrf->dad_freeze_time); + } thread_add_timer(zrouter.master, zebra_evpn_dad_mac_auto_recovery_exp, @@ -694,7 +744,7 @@ void zebra_evpn_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json) } static char *zebra_evpn_print_mac_flags(zebra_mac_t *mac, char *flags_buf, - uint32_t flags_buf_sz) + size_t flags_buf_sz) { snprintf(flags_buf, flags_buf_sz, "%s%s%s%s", mac->sync_neigh_cnt ? @@ -903,14 +953,19 @@ int zebra_evpn_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr, /* Write packet size. */ stream_putw_at(s, 0, stream_get_endp(s)); - if (IS_ZEBRA_DEBUG_VXLAN) + if (IS_ZEBRA_DEBUG_VXLAN) { + char flag_buf[MACIP_BUF_SIZE]; + zlog_debug( - "Send MACIP %s f 0x%x MAC %s IP %s seq %u L2-VNI %u ESI %s to %s", - (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del", flags, + "Send MACIP %s f %s MAC %s IP %s seq %u L2-VNI %u ESI %s to %s", + (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del", + zclient_evpn_dump_macip_flags(flags, flag_buf, + sizeof(flag_buf)), prefix_mac2str(macaddr, buf, sizeof(buf)), ipaddr2str(ip, buf2, sizeof(buf2)), seq, vni, es ? es->esi_str : "-", zebra_route_string(client->proto)); + } if (cmd == ZEBRA_MACIP_ADD) client->macipadd_cnt++; @@ -982,10 +1037,12 @@ zebra_mac_t *zebra_evpn_mac_add(zebra_evpn_t *zevpn, struct ethaddr *macaddr) mac->uptime = monotime(NULL); if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) { char buf[ETHER_ADDR_STRLEN]; + char mac_buf[MAC_BUF_SIZE]; - zlog_debug("%s: MAC %s flags 0x%x", __func__, + zlog_debug("%s: MAC %s flags %s", __func__, prefix_mac2str(&mac->macaddr, buf, sizeof(buf)), - mac->flags); + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, + sizeof(mac_buf))); } return mac; } @@ -999,10 +1056,12 @@ int zebra_evpn_mac_del(zebra_evpn_t *zevpn, zebra_mac_t *mac) if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) { char buf[ETHER_ADDR_STRLEN]; + char mac_buf[MAC_BUF_SIZE]; - zlog_debug("%s: MAC %s flags 0x%x", __func__, + zlog_debug("%s: MAC %s flags %s", __func__, prefix_mac2str(&mac->macaddr, buf, sizeof(buf)), - mac->flags); + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, + sizeof(mac_buf))); } /* If the MAC is freed before the neigh we will end up @@ -1047,11 +1106,13 @@ static bool zebra_evpn_check_mac_del_from_db(struct mac_walk_ctx *wctx, && !listcount(mac->neigh_list)) { if (IS_ZEBRA_DEBUG_VXLAN) { char buf[ETHER_ADDR_STRLEN]; + char mac_buf[MAC_BUF_SIZE]; zlog_debug( - "%s: Del MAC %s flags 0x%x", __func__, + "%s: Del MAC %s flags %s", __func__, prefix_mac2str(&mac->macaddr, buf, sizeof(buf)), - mac->flags); + zebra_evpn_zebra_mac_flag_dump( + mac, mac_buf, sizeof(mac_buf))); } wctx->uninstall = 0; @@ -1204,24 +1265,34 @@ int zebra_evpn_sync_mac_dp_install(zebra_mac_t *mac, bool set_inactive, zebra_evpn_mac_get_access_info(mac, &ifp, &vid); if (!ifp) { - if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) + if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) { + char mac_buf[MAC_BUF_SIZE]; + zlog_debug( - "%s: dp-install sync-mac vni %u mac %pEA es %s 0x%x %sskipped, no access-port", + "%s: dp-install sync-mac vni %u mac %pEA es %s %s%sskipped, no access-port", caller, zevpn->vni, &mac->macaddr, - mac->es ? mac->es->esi_str : "-", mac->flags, + mac->es ? mac->es->esi_str : "-", + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, + sizeof(mac_buf)), set_inactive ? "inactive " : ""); + } return -1; } zif = ifp->info; br_ifp = zif->brslave_info.br_if; if (!br_ifp) { - if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) + if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) { + char mac_buf[MAC_BUF_SIZE]; + zlog_debug( - "%s: dp-install sync-mac vni %u mac %pEA es %s 0x%x %sskipped, no br", + "%s: dp-install sync-mac vni %u mac %pEA es %s %s%sskipped, no br", caller, zevpn->vni, &mac->macaddr, - mac->es ? mac->es->esi_str : "-", mac->flags, + mac->es ? mac->es->esi_str : "-", + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, + sizeof(mac_buf)), set_inactive ? "inactive " : ""); + } return -1; } @@ -1236,13 +1307,18 @@ int zebra_evpn_sync_mac_dp_install(zebra_mac_t *mac, bool set_inactive, * supported and if the local ES is oper-down. */ if (mac->es && zebra_evpn_es_local_mac_via_network_port(mac->es)) { - if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) + if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) { + char mac_buf[MAC_BUF_SIZE]; + zlog_debug( - "dp-%s sync-nw-mac vni %u mac %pEA es %s 0x%x %s", + "dp-%s sync-nw-mac vni %u mac %pEA es %s %s%s", set_static ? "install" : "uninstall", zevpn->vni, &mac->macaddr, - mac->es ? mac->es->esi_str : "-", mac->flags, + mac->es ? mac->es->esi_str : "-", + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, + sizeof(mac_buf)), set_inactive ? "inactive " : ""); + } if (set_static) /* XXX - old_static needs to be computed more * accurately @@ -1256,13 +1332,17 @@ int zebra_evpn_sync_mac_dp_install(zebra_mac_t *mac, bool set_inactive, return 0; } - if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) - zlog_debug( - "dp-install sync-mac vni %u mac %pEA es %s 0x%x %s%s", - zevpn->vni, &mac->macaddr, - mac->es ? mac->es->esi_str : "-", mac->flags, - set_static ? "static " : "", - set_inactive ? "inactive " : ""); + if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) { + char mac_buf[MAC_BUF_SIZE]; + + zlog_debug("dp-install sync-mac vni %u mac %pEA es %s %s%s%s", + zevpn->vni, &mac->macaddr, + mac->es ? mac->es->esi_str : "-", + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, + sizeof(mac_buf)), + set_static ? "static " : "", + set_inactive ? "inactive " : ""); + } dplane_local_mac_add(ifp, br_ifp, vid, &mac->macaddr, sticky, set_static, set_inactive); @@ -1310,12 +1390,17 @@ static int zebra_evpn_mac_hold_exp_cb(struct thread *t) new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags); new_static = zebra_evpn_mac_is_static(mac); - if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) + if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) { + char mac_buf[MAC_BUF_SIZE]; + zlog_debug( - "sync-mac vni %u mac %s es %s 0x%x hold expired", + "sync-mac vni %u mac %s es %s %shold expired", mac->zevpn->vni, prefix_mac2str(&mac->macaddr, macbuf, sizeof(macbuf)), - mac->es ? mac->es->esi_str : "-", mac->flags); + mac->es ? mac->es->esi_str : "-", + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, + sizeof(mac_buf))); + } /* re-program the local mac in the dataplane if the mac is no * longer static @@ -1340,12 +1425,17 @@ static inline void zebra_evpn_mac_start_hold_timer(zebra_mac_t *mac) if (mac->hold_timer) return; - if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) + if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) { + char mac_buf[MAC_BUF_SIZE]; + zlog_debug( - "sync-mac vni %u mac %s es %s 0x%x hold started", + "sync-mac vni %u mac %s es %s %shold started", mac->zevpn->vni, prefix_mac2str(&mac->macaddr, macbuf, sizeof(macbuf)), - mac->es ? mac->es->esi_str : "-", mac->flags); + mac->es ? mac->es->esi_str : "-", + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, + sizeof(mac_buf))); + } thread_add_timer(zrouter.master, zebra_evpn_mac_hold_exp_cb, mac, zmh_info->mac_hold_time, &mac->hold_timer); } @@ -1357,12 +1447,18 @@ void zebra_evpn_mac_stop_hold_timer(zebra_mac_t *mac) if (!mac->hold_timer) return; - if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) + if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) { + char mac_buf[MAC_BUF_SIZE]; + zlog_debug( - "sync-mac vni %u mac %s es %s 0x%x hold stopped", + "sync-mac vni %u mac %s es %s %shold stopped", mac->zevpn->vni, prefix_mac2str(&mac->macaddr, macbuf, sizeof(macbuf)), - mac->es ? mac->es->esi_str : "-", mac->flags); + mac->es ? mac->es->esi_str : "-", + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, + sizeof(mac_buf))); + } + THREAD_OFF(mac->hold_timer); } @@ -1372,13 +1468,18 @@ void zebra_evpn_sync_mac_del(zebra_mac_t *mac) bool old_static; bool new_static; - if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) + if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) { + char mac_buf[MAC_BUF_SIZE]; + zlog_debug( - "sync-mac del vni %u mac %s es %s seq %d f 0x%x", + "sync-mac del vni %u mac %s es %s seq %d f %s", mac->zevpn->vni, prefix_mac2str(&mac->macaddr, macbuf, sizeof(macbuf)), mac->es ? mac->es->esi_str : "-", mac->loc_seq, - mac->flags); + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, + sizeof(mac_buf))); + } + old_static = zebra_evpn_mac_is_static(mac); UNSET_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY); if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE)) @@ -1418,9 +1519,12 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(zebra_evpn_t *zevpn, */ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) && !zebra_evpn_mac_is_ready_for_bgp(mac->flags)) { - if (IS_ZEBRA_DEBUG_EVPN_MH_MAC || IS_ZEBRA_DEBUG_VXLAN) + if (IS_ZEBRA_DEBUG_EVPN_MH_MAC + || IS_ZEBRA_DEBUG_VXLAN) { + char mac_buf[MAC_BUF_SIZE]; + zlog_debug( - "%s-macip accept vni %u %s-mac %s%s%s lower seq %u f 0x%x", + "%s-macip accept vni %u %s-mac %s%s%s lower seq %u f %s", sync ? "sync" : "rem", zevpn->vni, n_type, prefix_mac2str(&mac->macaddr, macbuf, @@ -1429,13 +1533,19 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(zebra_evpn_t *zevpn, ipa_len ? ipaddr2str(ipaddr, ipbuf, sizeof(ipbuf)) : "", - tmp_seq, mac->flags); + tmp_seq, + zebra_evpn_zebra_mac_flag_dump( + mac, mac_buf, sizeof(mac_buf))); + } + return true; } - if (IS_ZEBRA_DEBUG_EVPN_MH_MAC || IS_ZEBRA_DEBUG_VXLAN) + if (IS_ZEBRA_DEBUG_EVPN_MH_MAC || IS_ZEBRA_DEBUG_VXLAN) { + char mac_buf[MAC_BUF_SIZE]; + zlog_debug( - "%s-macip ignore vni %u %s-mac %s%s%s as existing has higher seq %u f 0x%x", + "%s-macip ignore vni %u %s-mac %s%s%s as existing has higher seq %u f %s", sync ? "sync" : "rem", zevpn->vni, n_type, prefix_mac2str(&mac->macaddr, macbuf, sizeof(macbuf)), @@ -1443,7 +1553,10 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(zebra_evpn_t *zevpn, ipa_len ? ipaddr2str(ipaddr, ipbuf, sizeof(ipbuf)) : "", - tmp_seq, mac->flags); + tmp_seq, + zebra_evpn_zebra_mac_flag_dump( + mac, mac_buf, sizeof(mac_buf))); + } return false; } @@ -1574,12 +1687,20 @@ zebra_evpn_proc_sync_mac_update(zebra_evpn_t *zevpn, struct ethaddr *macaddr, memset(&mac->fwd_info, 0, sizeof(mac->fwd_info)); mac->flags = new_flags; - if (IS_ZEBRA_DEBUG_EVPN_MH_MAC && (old_flags != new_flags)) + if (IS_ZEBRA_DEBUG_EVPN_MH_MAC && (old_flags != new_flags)) { + char mac_buf[MAC_BUF_SIZE], omac_buf[MAC_BUF_SIZE]; + struct zebra_mac_t_ omac; + + omac.flags = old_flags; zlog_debug( - "sync-mac vni %u mac %s old_f 0x%x new_f 0x%x", + "sync-mac vni %u mac %s old_f %snew_f %s", zevpn->vni, prefix_mac2str(macaddr, macbuf, sizeof(macbuf)), - old_flags, mac->flags); + zebra_evpn_zebra_mac_flag_dump( + &omac, omac_buf, sizeof(omac_buf)), + zebra_evpn_zebra_mac_flag_dump( + mac, mac_buf, sizeof(mac_buf))); + } /* update es */ es_change = zebra_evpn_es_mac_ref(mac, esi); @@ -1613,13 +1734,18 @@ zebra_evpn_proc_sync_mac_update(zebra_evpn_t *zevpn, struct ethaddr *macaddr, inform_bgp = true; } - if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) - zlog_debug("sync-mac %s vni %u mac %s es %s seq %d f 0x%x%s%s", + if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) { + char mac_buf[MAC_BUF_SIZE]; + + zlog_debug("sync-mac %s vni %u mac %s es %s seq %d f %s%s%s", ctx->mac_created ? "created" : "updated", zevpn->vni, prefix_mac2str(macaddr, macbuf, sizeof(macbuf)), mac->es ? mac->es->esi_str : "-", mac->loc_seq, - mac->flags, inform_bgp ? " inform_bgp" : "", + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, + sizeof(mac_buf)), + inform_bgp ? "inform_bgp" : "", inform_dataplane ? " inform_dp" : ""); + } if (inform_bgp) zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, @@ -1869,14 +1995,20 @@ int process_mac_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf, if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { /* force drop the sync flags */ old_static = zebra_evpn_mac_is_static(mac); - if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) + if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) { + char mac_buf[MAC_BUF_SIZE]; + zlog_debug( - "sync-mac->remote vni %u mac %s es %s seq %d f 0x%x", + "sync-mac->remote vni %u mac %s es %s seq %d f %s", zevpn->vni, prefix_mac2str(macaddr, buf, sizeof(buf)), mac->es ? mac->es->esi_str : "-", - mac->loc_seq, mac->flags); + mac->loc_seq, + zebra_evpn_zebra_mac_flag_dump( + mac, mac_buf, sizeof(mac_buf))); + } + zebra_evpn_mac_clear_sync_info(mac); zebra_evpn_mac_send_del_to_client(zevpn->vni, macaddr, mac->flags, @@ -1970,14 +2102,18 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn, SET_FLAG(mac->flags, ZEBRA_MAC_STICKY); inform_client = true; } else { - if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) + if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) { + char mac_buf[MAC_BUF_SIZE]; + zlog_debug( - "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u %scurFlags 0x%x", + "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u %scurFlags %s", sticky ? "sticky " : "", prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, ifp->ifindex, vid, zevpn->vni, local_inactive ? "local-inactive " : "", - mac->flags); + zebra_evpn_zebra_mac_flag_dump( + mac, mac_buf, sizeof(mac_buf))); + } if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { struct interface *old_ifp; @@ -2125,14 +2261,19 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn, */ if ((old_local_inactive != local_inactive) || (new_bgp_ready != old_bgp_ready)) { - if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) + if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) { + char mac_buf[MAC_BUF_SIZE]; + zlog_debug( - "local mac vni %u mac %s es %s seq %d f 0x%x%s", + "local mac vni %u mac %s es %s seq %d f %s%s", zevpn->vni, prefix_mac2str(macaddr, buf, sizeof(buf)), mac->es ? mac->es->esi_str : "", mac->loc_seq, - mac->flags, - local_inactive ? " local-inactive" : ""); + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, + sizeof(mac_buf)), + local_inactive ? "local-inactive" : ""); + } + if (!is_dup_detect) inform_client = true; } @@ -2177,12 +2318,18 @@ int zebra_evpn_del_local_mac(zebra_evpn_t *zevpn, struct ethaddr *macaddr, if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) return 0; - if (IS_ZEBRA_DEBUG_VXLAN) + if (IS_ZEBRA_DEBUG_VXLAN) { + char mac_buf[MAC_BUF_SIZE]; + zlog_debug( - "DEL MAC %s intf %s(%u) VID %u -> VNI %u seq %u flags 0x%x nbr count %u", + "DEL MAC %s intf %s(%u) VID %u -> VNI %u seq %u flags %snbr count %u", prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, ifp->ifindex, mac->fwd_info.local.vid, zevpn->vni, - mac->loc_seq, mac->flags, listcount(mac->neigh_list)); + mac->loc_seq, + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, + sizeof(mac_buf)), + listcount(mac->neigh_list)); + } old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags); if (zebra_evpn_mac_is_static(mac)) { @@ -2191,13 +2338,17 @@ int zebra_evpn_del_local_mac(zebra_evpn_t *zevpn, struct ethaddr *macaddr, */ memset(&mac->fwd_info, 0, sizeof(mac->fwd_info)); - if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) + if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) { + char mac_buf[MAC_BUF_SIZE]; + zlog_debug( - "re-add sync-mac vni %u mac %s es %s seq %d f 0x%x", + "re-add sync-mac vni %u mac %s es %s seq %d f %s", zevpn->vni, prefix_mac2str(macaddr, buf, sizeof(buf)), mac->es ? mac->es->esi_str : "-", mac->loc_seq, - mac->flags); + zebra_evpn_zebra_mac_flag_dump( + mac, mac_buf, sizeof(mac_buf))); + } /* inform-bgp about change in local-activity if any */ if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE)) { diff --git a/zebra/zebra_evpn_mac.h b/zebra/zebra_evpn_mac.h index 1730991f1e..e21b610501 100644 --- a/zebra/zebra_evpn_mac.h +++ b/zebra/zebra_evpn_mac.h @@ -56,6 +56,7 @@ struct zebra_mac_t_ { /* MAC address. */ struct ethaddr macaddr; + /* When modifying flags please fixup zebra_evpn_zebra_mac_flag_dump */ uint32_t flags; #define ZEBRA_MAC_LOCAL 0x01 #define ZEBRA_MAC_REMOTE 0x02 diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c index 2bf48c6277..18ccbb79fb 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -273,6 +273,11 @@ struct zfpm_glob { * If non-zero, the last time when statistics were cleared. */ time_t last_stats_clear_time; + + /* + * Flag to track the MAC dump status to FPM + */ + bool fpm_mac_dump_done; }; static struct zfpm_glob zfpm_glob_space; @@ -517,8 +522,6 @@ static int zfpm_conn_up_thread_cb(struct thread *thread) struct zfpm_rnodes_iter *iter; rib_dest_t *dest; - zfpm_g->t_conn_up = NULL; - iter = &zfpm_g->t_conn_up_state.iter; if (zfpm_g->state != ZFPM_STATE_ESTABLISHED) { @@ -528,8 +531,13 @@ static int zfpm_conn_up_thread_cb(struct thread *thread) goto done; } - /* Enqueue FPM updates for all the RMAC entries */ - hash_iterate(zrouter.l3vni_table, zfpm_iterate_rmac_table, NULL); + if (!zfpm_g->fpm_mac_dump_done) { + /* Enqueue FPM updates for all the RMAC entries */ + hash_iterate(zrouter.l3vni_table, zfpm_iterate_rmac_table, + NULL); + /* mark dump done so that its not repeated after yield */ + zfpm_g->fpm_mac_dump_done = true; + } while ((rnode = zfpm_rnodes_iter_next(iter))) { dest = rib_dest_from_rnode(rnode); @@ -547,7 +555,6 @@ static int zfpm_conn_up_thread_cb(struct thread *thread) zfpm_g->stats.t_conn_up_yields++; zfpm_rnodes_iter_pause(iter); - zfpm_g->t_conn_up = NULL; thread_add_timer_msec(zfpm_g->master, zfpm_conn_up_thread_cb, NULL, 0, &zfpm_g->t_conn_up); return 0; @@ -575,12 +582,13 @@ static void zfpm_connection_up(const char *detail) /* * Start thread to push existing routes to the FPM. */ - assert(!zfpm_g->t_conn_up); + thread_cancel(&zfpm_g->t_conn_up); zfpm_rnodes_iter_init(&zfpm_g->t_conn_up_state.iter); + zfpm_g->fpm_mac_dump_done = false; zfpm_debug("Starting conn_up thread"); - zfpm_g->t_conn_up = NULL; + thread_add_timer_msec(zfpm_g->master, zfpm_conn_up_thread_cb, NULL, 0, &zfpm_g->t_conn_up); zfpm_g->stats.t_conn_up_starts++; diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c index 44f574073c..f7c5da5dec 100644 --- a/zebra/zebra_fpm_netlink.c +++ b/zebra/zebra_fpm_netlink.c @@ -133,6 +133,7 @@ struct netlink_nh_info { * A structure for holding information for a netlink route message. */ struct netlink_route_info { + uint32_t nlmsg_pid; uint16_t nlmsg_type; uint8_t rtm_type; uint32_t rtm_table; @@ -244,14 +245,20 @@ static int netlink_route_info_fill(struct netlink_route_info *ri, int cmd, rib_dest_t *dest, struct route_entry *re) { struct nexthop *nexthop; + struct rib_table_info *table_info = + rib_table_info(rib_dest_table(dest)); + struct zebra_vrf *zvrf = table_info->zvrf; memset(ri, 0, sizeof(*ri)); ri->prefix = rib_dest_prefix(dest); ri->af = rib_dest_af(dest); + if (zvrf && zvrf->zns) + ri->nlmsg_pid = zvrf->zns->netlink_dplane.snl.nl_pid; + ri->nlmsg_type = cmd; - ri->rtm_table = rib_table_info(rib_dest_table(dest))->table_id; + ri->rtm_table = table_info->table_id; ri->rtm_protocol = RTPROT_UNSPEC; /* @@ -357,6 +364,7 @@ static int netlink_route_info_encode(struct netlink_route_info *ri, req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; + req->n.nlmsg_pid = ri->nlmsg_pid; req->n.nlmsg_type = ri->nlmsg_type; req->r.rtm_family = ri->af; diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 375be45df0..0a692feb35 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -2120,7 +2120,6 @@ static unsigned nexthop_active_check(struct route_node *rn, struct interface *ifp; route_map_result_t ret = RMAP_PERMITMATCH; int family; - char buf[SRCDEST2STR_BUFFER]; const struct prefix *p, *src_p; struct zebra_vrf *zvrf; @@ -2230,10 +2229,9 @@ static unsigned nexthop_active_check(struct route_node *rn, zvrf, re->tag); if (ret == RMAP_DENYMATCH) { if (IS_ZEBRA_DEBUG_RIB) { - srcdest_rnode2str(rn, buf, sizeof(buf)); zlog_debug( - "%u:%s: Filtering out with NH out %s due to route map", - re->vrf_id, buf, + "%u:%pRN: Filtering out with NH out %s due to route map", + re->vrf_id, rn, ifindex2ifname(nexthop->ifindex, nexthop->vrf_id)); } diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 1f92c43a69..8914f9c59c 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -38,6 +38,7 @@ #include "workqueue.h" #include "nexthop_group_private.h" #include "frr_pthread.h" +#include "printfrr.h" #include "zebra/zebra_router.h" #include "zebra/connected.h" @@ -148,6 +149,30 @@ _rnode_zlog(const char *_func, vrf_id_t vrf_id, struct route_node *rn, zlog(priority, "%s: (%u:%u):%s: %s", _func, vrf_id, table, buf, msgbuf); } +static char *_dump_re_status(const struct route_entry *re, char *buf, + size_t len) +{ + if (re->status == 0) { + snprintfrr(buf, len, "None "); + return buf; + } + + snprintfrr( + buf, len, "%s%s%s%s%s%s%s", + CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED) ? "Removed " : "", + CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED) ? "Changed " : "", + CHECK_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED) + ? "Label Changed " + : "", + CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED) ? "Queued " : "", + CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED) ? "Installed " + : "", + CHECK_FLAG(re->status, ROUTE_ENTRY_FAILED) ? "Failed " : "", + CHECK_FLAG(re->status, ROUTE_ENTRY_USE_FIB_NHG) ? "Fib NHG " + : ""); + return buf; +} + #define rnode_debug(node, vrf_id, ...) \ _rnode_zlog(__func__, vrf_id, node, LOG_DEBUG, __VA_ARGS__) #define rnode_info(node, ...) \ @@ -1080,12 +1105,20 @@ static void rib_process(struct route_node *rn) } RNODE_FOREACH_RE_SAFE (rn, re, next) { - if (IS_ZEBRA_DEBUG_RIB_DETAILED) + if (IS_ZEBRA_DEBUG_RIB_DETAILED) { + char flags_buf[128]; + char status_buf[128]; + zlog_debug( - "%s(%u:%u):%s: Examine re %p (%s) status %x flags %x dist %d metric %d", + "%s(%u:%u):%s: Examine re %p (%s) status: %sflags: %sdist %d metric %d", VRF_LOGNAME(vrf), vrf_id, re->table, buf, re, - zebra_route_string(re->type), re->status, - re->flags, re->distance, re->metric); + zebra_route_string(re->type), + _dump_re_status(re, status_buf, + sizeof(status_buf)), + zclient_dump_route_flags(re->flags, flags_buf, + sizeof(flags_buf)), + re->distance, re->metric); + } /* Currently selected re. */ if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) { @@ -1107,6 +1140,9 @@ static void rib_process(struct route_node *rn) */ if (CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED)) { if (!nexthop_active_update(rn, re)) { + const struct prefix *p; + struct rib_table_info *info; + if (re->type == ZEBRA_ROUTE_TABLE) { /* XXX: HERE BE DRAGONS!!!!! * In all honesty, I have not yet @@ -1136,6 +1172,11 @@ static void rib_process(struct route_node *rn) ROUTE_ENTRY_REMOVED); } + info = srcdest_rnode_table_info(rn); + srcdest_rnode_prefixes(rn, &p, NULL); + zsend_route_notify_owner(re, p, + ZAPI_ROUTE_FAIL_INSTALL, + info->afi, info->safi); continue; } } else { @@ -2791,6 +2832,8 @@ void _route_entry_dump(const char *func, union prefixconstptr pp, bool is_srcdst = src_p && src_p->prefixlen; char straddr[PREFIX_STRLEN]; char srcaddr[PREFIX_STRLEN]; + char flags_buf[128]; + char status_buf[128]; struct nexthop *nexthop; struct vrf *vrf = vrf_lookup_by_id(re->vrf_id); struct nexthop_group *nhg; @@ -2804,9 +2847,12 @@ void _route_entry_dump(const char *func, union prefixconstptr pp, zlog_debug("%s: uptime == %lu, type == %u, instance == %d, table == %d", straddr, (unsigned long)re->uptime, re->type, re->instance, re->table); - zlog_debug("%s: metric == %u, mtu == %u, distance == %u, flags == %u, status == %u", - straddr, re->metric, re->mtu, re->distance, re->flags, - re->status); + zlog_debug( + "%s: metric == %u, mtu == %u, distance == %u, flags == %sstatus == %s", + straddr, re->metric, re->mtu, re->distance, + zclient_dump_route_flags(re->flags, flags_buf, + sizeof(flags_buf)), + _dump_re_status(re, status_buf, sizeof(status_buf))); zlog_debug("%s: nexthop_num == %u, nexthop_active_num == %u", straddr, nexthop_group_nexthop_num(&(re->nhe->nhg)), nexthop_group_active_nexthop_num(&(re->nhe->nhg))); @@ -2941,8 +2987,10 @@ int rib_add_multipath_nhe(afi_t afi, safi_t safi, struct prefix *p, struct nhg_hash_entry *nhe = NULL; struct route_table *table; struct route_node *rn; - struct route_entry *same = NULL; + struct route_entry *same = NULL, *first_same = NULL; int ret = 0; + int same_count = 0; + rib_dest_t *dest; if (!re || !re_nhe) return -1; @@ -3010,14 +3058,22 @@ int rib_add_multipath_nhe(afi_t afi, safi_t safi, struct prefix *p, * for the install don't do a route replace. */ RNODE_FOREACH_RE (rn, same) { - if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED)) + if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED)) { + same_count++; continue; + } /* Compare various route_entry properties */ - if (rib_compare_routes(re, same)) - break; + if (rib_compare_routes(re, same)) { + same_count++; + + if (first_same == NULL) + first_same = same; + } } + same = first_same; + /* If this route is kernel/connected route, notify the dataplane. */ if (RIB_SYSTEM_ROUTE(re)) { /* Notify dataplane */ @@ -3027,8 +3083,9 @@ int rib_add_multipath_nhe(afi_t afi, safi_t safi, struct prefix *p, /* Link new re to node.*/ if (IS_ZEBRA_DEBUG_RIB) { rnode_debug(rn, re->vrf_id, - "Inserting route rn %p, re %p (%s) existing %p", - rn, re, zebra_route_string(re->type), same); + "Inserting route rn %p, re %p (%s) existing %p, same_count %d", + rn, re, zebra_route_string(re->type), same, + same_count); if (IS_ZEBRA_DEBUG_RIB_DETAILED) route_entry_dump(p, src_p, re); @@ -3042,6 +3099,24 @@ int rib_add_multipath_nhe(afi_t afi, safi_t safi, struct prefix *p, if (same) rib_delnode(rn, same); + /* See if we can remove some RE entries that are queued for + * removal, but won't be considered in rib processing. + */ + dest = rib_dest_from_rnode(rn); + RNODE_FOREACH_RE_SAFE (rn, re, same) { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) { + /* If the route was used earlier, must retain it. */ + if (dest && re == dest->selected_fib) + continue; + + if (IS_ZEBRA_DEBUG_RIB) + rnode_debug(rn, re->vrf_id, "rn %p, removing unneeded re %p", + rn, re); + + rib_unlink(rn, re); + } + } + route_unlock_node(rn); return ret; } @@ -3378,7 +3453,8 @@ static void rib_update_route_node(struct route_node *rn, int type) } /* Schedule routes of a particular table (address-family) based on event. */ -void rib_update_table(struct route_table *table, enum rib_update_event event) +void rib_update_table(struct route_table *table, enum rib_update_event event, + int rtype) { struct route_node *rn; @@ -3391,12 +3467,12 @@ void rib_update_table(struct route_table *table, enum rib_update_event event) : NULL; vrf = zvrf ? zvrf->vrf : NULL; - zlog_debug("%s: %s VRF %s Table %u event %s", __func__, + zlog_debug("%s: %s VRF %s Table %u event %s Route type: %s", __func__, table->info ? afi2str( ((struct rib_table_info *)table->info)->afi) : "Unknown", VRF_LOGNAME(vrf), zvrf ? zvrf->table_id : 0, - rib_update_event2str(event)); + rib_update_event2str(event), zebra_route_string(rtype)); } /* Walk all routes and queue for processing, if appropriate for @@ -3419,7 +3495,7 @@ void rib_update_table(struct route_table *table, enum rib_update_event event) break; case RIB_UPDATE_RMAP_CHANGE: case RIB_UPDATE_OTHER: - rib_update_route_node(rn, ZEBRA_ROUTE_ALL); + rib_update_route_node(rn, rtype); break; default: break; @@ -3427,7 +3503,8 @@ void rib_update_table(struct route_table *table, enum rib_update_event event) } } -static void rib_update_handle_vrf(vrf_id_t vrf_id, enum rib_update_event event) +static void rib_update_handle_vrf(vrf_id_t vrf_id, enum rib_update_event event, + int rtype) { struct route_table *table; @@ -3438,14 +3515,14 @@ static void rib_update_handle_vrf(vrf_id_t vrf_id, enum rib_update_event event) /* Process routes of interested address-families. */ table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); if (table) - rib_update_table(table, event); + rib_update_table(table, event, rtype); table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id); if (table) - rib_update_table(table, event); + rib_update_table(table, event, rtype); } -static void rib_update_handle_vrf_all(enum rib_update_event event) +static void rib_update_handle_vrf_all(enum rib_update_event event, int rtype) { struct zebra_router_table *zrt; @@ -3455,7 +3532,7 @@ static void rib_update_handle_vrf_all(enum rib_update_event event) /* Just iterate over all the route tables, rather than vrf lookups */ RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables) - rib_update_table(zrt->table, event); + rib_update_table(zrt->table, event, rtype); } struct rib_update_ctx { @@ -3489,9 +3566,9 @@ static int rib_update_handler(struct thread *thread) ctx = THREAD_ARG(thread); if (ctx->vrf_all) - rib_update_handle_vrf_all(ctx->event); + rib_update_handle_vrf_all(ctx->event, ZEBRA_ROUTE_ALL); else - rib_update_handle_vrf(ctx->vrf_id, ctx->event); + rib_update_handle_vrf(ctx->vrf_id, ctx->event, ZEBRA_ROUTE_ALL); rib_update_ctx_fini(&ctx); @@ -3504,26 +3581,6 @@ static int rib_update_handler(struct thread *thread) */ static struct thread *t_rib_update_threads[RIB_UPDATE_MAX]; -/* Schedule a RIB update event for specific vrf */ -void rib_update_vrf(vrf_id_t vrf_id, enum rib_update_event event) -{ - struct rib_update_ctx *ctx; - - ctx = rib_update_ctx_init(vrf_id, event); - - /* Don't worry about making sure multiple rib updates for specific vrf - * are scheduled at once for now. If it becomes a problem, we can use a - * lookup of some sort to keep track of running threads via t_vrf_id - * like how we are doing it in t_rib_update_threads[]. - */ - thread_add_event(zrouter.master, rib_update_handler, ctx, 0, NULL); - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s: Scheduled VRF %s, event %s", __func__, - vrf_id_to_name(ctx->vrf_id), - rib_update_event2str(event)); -} - /* Schedule a RIB update event for all vrfs */ void rib_update(enum rib_update_event event) { diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index bbc8b6f19d..229b705ec9 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -267,7 +267,8 @@ static int ip_protocol_rm_add(struct zebra_vrf *zvrf, const char *rmap, /* Process routes of interested address-families. */ table = zebra_vrf_table(afi, safi, zvrf->vrf->vrf_id); if (table) - rib_update_table(table, RIB_UPDATE_RMAP_CHANGE); + rib_update_table(table, RIB_UPDATE_RMAP_CHANGE, + rtype); } return CMD_SUCCESS; @@ -294,7 +295,8 @@ static int ip_protocol_rm_del(struct zebra_vrf *zvrf, const char *rmap, /* Process routes of interested address-families. */ table = zebra_vrf_table(afi, safi, zvrf->vrf->vrf_id); if (table) - rib_update_table(table, RIB_UPDATE_RMAP_CHANGE); + rib_update_table(table, RIB_UPDATE_RMAP_CHANGE, + rtype); } XFREE(MTYPE_ROUTE_MAP_NAME, PROTO_RM_NAME(zvrf, afi, rtype)); } @@ -576,7 +578,7 @@ DEFUN (zebra_route_map_timer, ZEBRA_STR "Set route-map parameters\n" "Time to wait before route-map updates are processed\n" - "0 means event-driven updates are disabled\n") + "0 means route-map changes are run immediately instead of delaying\n") { int idx_number = 3; uint32_t rmap_delay_timer; @@ -594,7 +596,7 @@ DEFUN (no_zebra_route_map_timer, ZEBRA_STR "Set route-map parameters\n" "Reset delay-timer to default value, 30 secs\n" - "0 means event-driven updates are disabled\n") + "0 means route-map changes are run immediately instead of delaying\n") { zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER); @@ -1454,8 +1456,6 @@ static void zebra_rib_table_rm_update(const char *rmap) struct vrf *vrf = NULL; struct zebra_vrf *zvrf = NULL; char *rmap_name; - char afi_ip = 0; - char afi_ipv6 = 0; struct route_map *old = NULL; RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { @@ -1486,16 +1486,12 @@ static void zebra_rib_table_rm_update(const char *rmap) PROTO_RM_MAP(zvrf, AFI_IP, i)); /* There is single rib table for all protocols */ - if (afi_ip == 0) { - table = zvrf->table[AFI_IP] - [SAFI_UNICAST]; - if (table) { - - afi_ip = 1; - rib_update_table( - table, - RIB_UPDATE_RMAP_CHANGE); - } + table = zvrf->table[AFI_IP][SAFI_UNICAST]; + if (table) { + rib_update_table( + table, + RIB_UPDATE_RMAP_CHANGE, + i); } } rmap_name = PROTO_RM_NAME(zvrf, AFI_IP6, i); @@ -1515,16 +1511,12 @@ static void zebra_rib_table_rm_update(const char *rmap) PROTO_RM_MAP(zvrf, AFI_IP6, i)); /* There is single rib table for all protocols */ - if (afi_ipv6 == 0) { - table = zvrf->table[AFI_IP6] - [SAFI_UNICAST]; - if (table) { - - afi_ipv6 = 1; - rib_update_table( - table, - RIB_UPDATE_RMAP_CHANGE); - } + table = zvrf->table[AFI_IP6][SAFI_UNICAST]; + if (table) { + rib_update_table( + table, + RIB_UPDATE_RMAP_CHANGE, + i); } } } @@ -1628,8 +1620,6 @@ static void zebra_route_map_process_update_cb(char *rmap_name) static int zebra_route_map_update_timer(struct thread *thread) { - zebra_t_rmap_update = NULL; - if (IS_ZEBRA_DEBUG_EVENT) zlog_debug("Event driven route-map update triggered"); @@ -1654,8 +1644,8 @@ static void zebra_route_map_set_delay_timer(uint32_t value) if (!value && zebra_t_rmap_update) { /* Event driven route map updates is being disabled */ /* But there's a pending timer. Fire it off now */ - thread_cancel(&zebra_t_rmap_update); - zebra_route_map_update_timer(zebra_t_rmap_update); + THREAD_OFF(zebra_t_rmap_update); + zebra_route_map_update_timer(NULL); } } @@ -1664,7 +1654,7 @@ void zebra_routemap_finish(void) /* Set zebra_rmap_update_timer to 0 so that it wont schedule again */ zebra_rmap_update_timer = 0; /* Thread off if any scheduled already */ - thread_cancel(&zebra_t_rmap_update); + THREAD_OFF(zebra_t_rmap_update); route_map_finish(); } @@ -1780,12 +1770,11 @@ route_map_result_t zebra_nht_route_map_check(afi_t afi, int client_proto, static void zebra_route_map_mark_update(const char *rmap_name) { /* rmap_update_timer of 0 means don't do route updates */ - if (zebra_rmap_update_timer && !zebra_t_rmap_update) { - zebra_t_rmap_update = NULL; - thread_add_timer(zrouter.master, zebra_route_map_update_timer, - NULL, zebra_rmap_update_timer, - &zebra_t_rmap_update); - } + if (zebra_rmap_update_timer) + THREAD_OFF(zebra_t_rmap_update); + + thread_add_timer(zrouter.master, zebra_route_map_update_timer, + NULL, zebra_rmap_update_timer, &zebra_t_rmap_update); } static void zebra_route_map_add(const char *rmap_name) |
