summaryrefslogtreecommitdiff
path: root/zebra/zebra_nhg.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_nhg.c')
-rw-r--r--zebra/zebra_nhg.c59
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(