diff options
Diffstat (limited to 'zebra/zebra_nhg.c')
| -rw-r--r-- | zebra/zebra_nhg.c | 59 |
1 files changed, 45 insertions, 14 deletions
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index a32fc2bb14..f5141c8f23 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -572,8 +572,7 @@ bool zebra_nhg_hash_equal(const void *arg1, const void *arg2) /* Nexthops should be in-order, so we simply compare them in-place */ for (nexthop1 = nhe1->nhg.nexthop, nexthop2 = nhe2->nhg.nexthop; nexthop1 && nexthop2; - nexthop1 = nexthop1->next, nexthop2 = nexthop2->next) { - + nexthop1 = nexthop_next(nexthop1), nexthop2 = nexthop_next(nexthop2)) { if (!nhg_compare_nexthops(nexthop1, nexthop2)) return false; } @@ -608,8 +607,7 @@ bool zebra_nhg_hash_equal(const void *arg1, const void *arg2) for (nexthop1 = nhe1->backup_info->nhe->nhg.nexthop, nexthop2 = nhe2->backup_info->nhe->nhg.nexthop; nexthop1 && nexthop2; - nexthop1 = nexthop1->next, nexthop2 = nexthop2->next) { - + nexthop1 = nexthop_next(nexthop1), nexthop2 = nexthop_next(nexthop2)) { if (!nhg_compare_nexthops(nexthop1, nexthop2)) return false; } @@ -1762,7 +1760,8 @@ void zebra_nhg_decrement_ref(struct nhg_hash_entry *nhe) nhe->refcnt--; if (!zebra_router_in_shutdown() && nhe->refcnt <= 0 && - CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED) && + (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED) || + CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_QUEUED)) && !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_KEEP_AROUND)) { nhe->refcnt = 1; SET_FLAG(nhe->flags, NEXTHOP_GROUP_KEEP_AROUND); @@ -3089,7 +3088,7 @@ static struct nhg_hash_entry *zebra_nhg_rib_compare_old_nhe( int nexthop_active_update(struct route_node *rn, struct route_entry *re, struct route_entry *old_re) { - struct nhg_hash_entry *curr_nhe; + struct nhg_hash_entry *curr_nhe, *remove; uint32_t curr_active = 0, backup_active = 0; if (PROTO_OWNED(re->nhe)) @@ -3143,16 +3142,25 @@ backups_done: new_nhe = zebra_nhg_rib_find_nhe(curr_nhe, rt_afi); - if (old_re && old_re->type == re->type && - old_re->instance == re->instance) + remove = new_nhe; + + if (old_re && old_re->type == re->type && old_re->instance == re->instance && + new_nhe != old_re->nhe) new_nhe = zebra_nhg_rib_compare_old_nhe(rn, re, new_nhe, old_re->nhe); if (IS_ZEBRA_DEBUG_NHG_DETAIL) - zlog_debug( - "%s: re %p CHANGED: nhe %p (%pNG) => new_nhe %p (%pNG)", - __func__, re, re->nhe, re->nhe, new_nhe, - new_nhe); + zlog_debug("%s: re %p CHANGED: nhe %p (%pNG) => new_nhe %p (%pNG) rib_find_nhe returned %p (%pNG) refcnt: %d", + __func__, re, re->nhe, re->nhe, new_nhe, new_nhe, remove, remove, + remove ? remove->refcnt : 0); + + /* + * if the results from zebra_nhg_rib_find_nhe is being + * dropped and it was generated in that function + * (refcnt of 0) then we know we can clean it up + */ + if (remove && remove != new_nhe && remove != re->nhe && remove->refcnt == 0) + zebra_nhg_handle_uninstall(remove); route_entry_update_nhe(re, new_nhe); } @@ -3373,7 +3381,17 @@ void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe, uint8_t type) void zebra_nhg_uninstall_kernel(struct nhg_hash_entry *nhe) { - if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED)) { + /* + * Clearly if the nexthop group is installed we should + * remove it. Additionally If the nexthop is already + * QUEUED for installation, we should also just send + * a deletion down as well. We cannot necessarily pluck + * the installation out of the queue ( since it may have + * already been acted on, but not processed yet in the + * main pthread ). + */ + if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED) || + CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_QUEUED)) { int ret = dplane_nexthop_delete(nhe); switch (ret) { @@ -3445,7 +3463,13 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx) ZAPI_NHG_INSTALLED); break; case ZEBRA_DPLANE_REQUEST_FAILURE: - UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED); + /* + * With a request failure it is unknown what we now know + * this is because Zebra has lost track of whether or not + * any previous versions of this NHG are in the kernel + * or even what those versions were. So at this point + * we cannot unset the INSTALLED flag. + */ /* If daemon nhg, send it an update */ if (PROTO_OWNED(nhe)) zsend_nhg_notify(nhe->type, nhe->zapi_instance, @@ -3909,7 +3933,14 @@ void zebra_interface_nhg_reinstall(struct interface *ifp) __func__, ifp->name); frr_each (nhg_connected_tree, &zif->nhg_dependents, rb_node_dep) { + /* + * The nexthop associated with this was set as !ACTIVE + * so we need to turn it back to active when we get to + * this point again + */ + SET_FLAG(rb_node_dep->nhe->nhg.nexthop->flags, NEXTHOP_FLAG_ACTIVE); nh = rb_node_dep->nhe->nhg.nexthop; + if (zebra_nhg_set_valid_if_active(rb_node_dep->nhe)) { if (IS_ZEBRA_DEBUG_NHG_DETAIL) zlog_debug( |
