summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--zebra/interface.c45
-rw-r--r--zebra/zebra_nhg.c92
-rw-r--r--zebra/zebra_nhg.h2
3 files changed, 82 insertions, 57 deletions
diff --git a/zebra/interface.c b/zebra/interface.c
index 76d5d2a246..daa93e36d1 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -189,17 +189,31 @@ static int if_zebra_new_hook(struct interface *ifp)
return 0;
}
-static void if_nhg_dependents_release(struct interface *ifp)
+static void if_nhg_dependents_check_valid(struct nhg_hash_entry *nhe)
{
- if (!if_nhg_dependents_is_empty(ifp)) {
- struct nhg_connected *rb_node_dep = NULL;
- struct zebra_if *zif = (struct zebra_if *)ifp->info;
+ zebra_nhg_check_valid(nhe);
+ if (!CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID))
+ /* Assuming uninstalled as well here */
+ UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
+}
- frr_each(nhg_connected_tree, &zif->nhg_dependents,
- rb_node_dep) {
- rb_node_dep->nhe->ifp = NULL;
- zebra_nhg_set_invalid(rb_node_dep->nhe);
- }
+static void if_down_nhg_dependents(const struct interface *ifp)
+{
+ struct nhg_connected *rb_node_dep = NULL;
+ struct zebra_if *zif = (struct zebra_if *)ifp->info;
+
+ frr_each(nhg_connected_tree, &zif->nhg_dependents, rb_node_dep)
+ if_nhg_dependents_check_valid(rb_node_dep->nhe);
+}
+
+static void if_nhg_dependents_release(const struct interface *ifp)
+{
+ struct nhg_connected *rb_node_dep = NULL;
+ struct zebra_if *zif = (struct zebra_if *)ifp->info;
+
+ frr_each(nhg_connected_tree, &zif->nhg_dependents, rb_node_dep) {
+ rb_node_dep->nhe->ifp = NULL; /* Null it out */
+ if_nhg_dependents_check_valid(rb_node_dep->nhe);
}
}
@@ -998,19 +1012,6 @@ bool if_nhg_dependents_is_empty(const struct interface *ifp)
return false;
}
-static void if_down_nhg_dependents(const struct interface *ifp)
-{
- if (!if_nhg_dependents_is_empty(ifp)) {
- struct nhg_connected *rb_node_dep = NULL;
- struct zebra_if *zif = (struct zebra_if *)ifp->info;
-
- frr_each(nhg_connected_tree, &zif->nhg_dependents,
- rb_node_dep) {
- zebra_nhg_set_invalid(rb_node_dep->nhe);
- }
- }
-}
-
/* Interface is up. */
void if_up(struct interface *ifp)
{
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index 418c1102bd..3ec764c5d3 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -246,13 +246,12 @@ void zebra_nhg_dependents_init(struct nhg_hash_entry *nhe)
/* Release this nhe from anything depending on it */
static void zebra_nhg_dependents_release(struct nhg_hash_entry *nhe)
{
- if (!zebra_nhg_dependents_is_empty(nhe)) {
- struct nhg_connected *rb_node_dep = NULL;
+ struct nhg_connected *rb_node_dep = NULL;
- frr_each_safe(nhg_connected_tree, &nhe->nhg_dependents,
- rb_node_dep) {
- zebra_nhg_depends_del(rb_node_dep->nhe, nhe);
- }
+ frr_each_safe(nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep) {
+ zebra_nhg_depends_del(rb_node_dep->nhe, nhe);
+ /* recheck validity of the dependent */
+ zebra_nhg_check_valid(rb_node_dep->nhe);
}
}
@@ -687,6 +686,48 @@ static void zebra_nhg_set_unhashable(struct nhg_hash_entry *nhe)
nhe->id);
}
+static void zebra_nhg_set_valid(struct nhg_hash_entry *nhe)
+{
+ struct nhg_connected *rb_node_dep;
+
+ SET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID);
+
+ frr_each(nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep)
+ zebra_nhg_set_valid(rb_node_dep->nhe);
+}
+
+static void zebra_nhg_set_invalid(struct nhg_hash_entry *nhe)
+{
+ struct nhg_connected *rb_node_dep;
+
+ UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID);
+
+ /* Update validity of nexthops depending on it */
+ frr_each(nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep)
+ zebra_nhg_check_valid(rb_node_dep->nhe);
+}
+
+void zebra_nhg_check_valid(struct nhg_hash_entry *nhe)
+{
+ struct nhg_connected *rb_node_dep = NULL;
+ bool valid = false;
+
+ /* If anthing else in the group is valid, the group is valid */
+ frr_each(nhg_connected_tree, &nhe->nhg_depends, rb_node_dep) {
+ if (CHECK_FLAG(rb_node_dep->nhe->flags, NEXTHOP_GROUP_VALID)) {
+ valid = true;
+ goto done;
+ }
+ }
+
+done:
+ if (valid)
+ zebra_nhg_set_valid(nhe);
+ else
+ zebra_nhg_set_invalid(nhe);
+}
+
+
static void zebra_nhg_release(struct nhg_hash_entry *nhe)
{
/* Remove it from any lists it may be on */
@@ -711,6 +752,15 @@ static void zebra_nhg_handle_uninstall(struct nhg_hash_entry *nhe)
zebra_nhg_free(nhe);
}
+static void zebra_nhg_handle_install(struct nhg_hash_entry *nhe)
+{
+ /* Update validity of groups depending on it */
+ struct nhg_connected *rb_node_dep;
+
+ frr_each_safe(nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep)
+ zebra_nhg_set_valid(rb_node_dep->nhe);
+}
+
/*
* The kernel/other program has changed the state of a nexthop object we are
* using.
@@ -1083,34 +1133,6 @@ void zebra_nhg_increment_ref(struct nhg_hash_entry *nhe)
nhg_connected_tree_increment_ref(&nhe->nhg_depends);
}
-void zebra_nhg_set_invalid(struct nhg_hash_entry *nhe)
-{
- if (!zebra_nhg_depends_is_empty(nhe)
- && !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_RECURSIVE)) {
- struct nhg_connected *rb_node_dep = NULL;
-
- /* If anthing else in the group is valid, the group is valid */
- frr_each(nhg_connected_tree, &nhe->nhg_depends, rb_node_dep) {
- if (CHECK_FLAG(rb_node_dep->nhe->flags,
- NEXTHOP_GROUP_VALID))
- return;
- }
- }
-
- UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID);
- /* Assuming uninstalled as well here */
- UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
-
- if (!zebra_nhg_dependents_is_empty(nhe)) {
- struct nhg_connected *rb_node_dep = NULL;
-
- frr_each(nhg_connected_tree, &nhe->nhg_dependents,
- rb_node_dep) {
- zebra_nhg_set_invalid(rb_node_dep->nhe);
- }
- }
-}
-
void zebra_nhg_set_if(struct nhg_hash_entry *nhe, struct interface *ifp)
{
nhe->ifp = ifp;
@@ -1799,6 +1821,7 @@ void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe)
break;
case ZEBRA_DPLANE_REQUEST_SUCCESS:
SET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
+ zebra_nhg_handle_install(nhe);
break;
}
}
@@ -1870,6 +1893,7 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
SET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID);
SET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
+ zebra_nhg_handle_install(nhe);
} else
flog_err(
EC_ZEBRA_DP_INSTALL_FAIL,
diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h
index 82f54a3a63..e636c0f2d2 100644
--- a/zebra/zebra_nhg.h
+++ b/zebra/zebra_nhg.h
@@ -249,7 +249,7 @@ void zebra_nhg_free(void *arg);
void zebra_nhg_decrement_ref(struct nhg_hash_entry *nhe);
void zebra_nhg_increment_ref(struct nhg_hash_entry *nhe);
-void zebra_nhg_set_invalid(struct nhg_hash_entry *nhe);
+void zebra_nhg_check_valid(struct nhg_hash_entry *nhe);
void zebra_nhg_set_if(struct nhg_hash_entry *nhe, struct interface *ifp);
extern int nexthop_active_update(struct route_node *rn, struct route_entry *re);