diff options
Diffstat (limited to 'zebra/zebra_rib.c')
| -rw-r--r-- | zebra/zebra_rib.c | 101 |
1 files changed, 88 insertions, 13 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 1f92c43a69..7c86735545 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; } |
