summaryrefslogtreecommitdiff
path: root/zebra/zebra_rib.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_rib.c')
-rw-r--r--zebra/zebra_rib.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index b531eb7c23..ad6bcc356c 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -428,18 +428,29 @@ int route_entry_update_nhe(struct route_entry *re,
done:
/* Detach / deref previous nhg */
- if (old_nhg)
+
+ if (old_nhg) {
+ /*
+ * Return true if we are deleting the previous NHE
+ * Note: we dont check the return value of the function anywhere
+ * except at rib_handle_nhg_replace().
+ */
+ if (old_nhg->refcnt == 1)
+ ret = 1;
+
zebra_nhg_decrement_ref(old_nhg);
+ }
return ret;
}
-void rib_handle_nhg_replace(struct nhg_hash_entry *old_entry,
- struct nhg_hash_entry *new_entry)
+int rib_handle_nhg_replace(struct nhg_hash_entry *old_entry,
+ struct nhg_hash_entry *new_entry)
{
struct zebra_router_table *zrt;
struct route_node *rn;
struct route_entry *re, *next;
+ int ret = 0;
if (IS_ZEBRA_DEBUG_RIB_DETAILED || IS_ZEBRA_DEBUG_NHG_DETAIL)
zlog_debug("%s: replacing routes nhe (%u) OLD %p NEW %p",
@@ -451,10 +462,17 @@ void rib_handle_nhg_replace(struct nhg_hash_entry *old_entry,
rn = srcdest_route_next(rn)) {
RNODE_FOREACH_RE_SAFE (rn, re, next) {
if (re->nhe && re->nhe == old_entry)
- route_entry_update_nhe(re, new_entry);
+ ret += route_entry_update_nhe(re,
+ new_entry);
}
}
}
+
+ /*
+ * if ret > 0, some previous re->nhe has freed the address to which
+ * old_entry is pointing.
+ */
+ return ret;
}
struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,