]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: implement NHG proto replace
authorStephen Worley <sworley@cumulusnetworks.com>
Sun, 10 May 2020 20:36:49 +0000 (16:36 -0400)
committerStephen Worley <sworley@cumulusnetworks.com>
Mon, 28 Sep 2020 16:40:59 +0000 (12:40 -0400)
Implement the ability to replace an NHG sent down
from an upper level proto. With proto-owned NHGs, we make the
assumption they are ecmp and always treat them as a group
to make the replace from 1 -> 2 and 2 -> 1 quite a bit
easier.

Signed-off-by: Stephen Worley <sworley@cumulusnetworks.com>
zebra/zebra_nhg.c

index e5fa7b425aa5009f656ae2278fb23fce955e144d..9c45093f21e995662800290782b9392a0544218d 100644 (file)
@@ -730,7 +730,7 @@ static bool zebra_nhe_find(struct nhg_hash_entry **nhe, /* return value */
        if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ACTIVE))
                SET_FLAG(newnhe->flags, NEXTHOP_GROUP_VALID);
 
-       if (nh->next == NULL) {
+       if (nh->next == NULL && newnhe->id < zclient_get_nhg_lower_bound()) {
                if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RECURSIVE)) {
                        /* Single recursive nexthop */
                        handle_recursive_depend(&newnhe->nhg_depends,
@@ -739,6 +739,7 @@ static bool zebra_nhe_find(struct nhg_hash_entry **nhe, /* return value */
                        recursive = true;
                }
        } else {
+               /* Proto-owned are groups by default */
                /* List of nexthops */
                for (nh = newnhe->nhg.nexthop; nh; nh = nh->next) {
                        if (IS_ZEBRA_DEBUG_NHG_DETAIL)
@@ -1024,17 +1025,21 @@ done:
                zebra_nhg_set_invalid(nhe);
 }
 
-
-static void zebra_nhg_release(struct nhg_hash_entry *nhe)
+static void zebra_nhg_release_all_deps(struct nhg_hash_entry *nhe)
 {
-       if (IS_ZEBRA_DEBUG_NHG_DETAIL)
-               zlog_debug("%s: nhe %p (%u)", __func__, nhe, nhe->id);
-
        /* Remove it from any lists it may be on */
        zebra_nhg_depends_release(nhe);
        zebra_nhg_dependents_release(nhe);
        if (nhe->ifp)
                if_nhg_dependents_del(nhe->ifp, nhe);
+}
+
+static void zebra_nhg_release(struct nhg_hash_entry *nhe)
+{
+       if (IS_ZEBRA_DEBUG_NHG_DETAIL)
+               zlog_debug("%s: nhe %p (%u)", __func__, nhe, nhe->id);
+
+       zebra_nhg_release_all_deps(nhe);
 
        /*
         * If its not zebra owned, we didn't store it here and have to be
@@ -2500,7 +2505,8 @@ void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe)
        }
 
        if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID)
-           && !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED)
+           && (!CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED)
+               || nhe->id >= zclient_get_nhg_lower_bound())
            && !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_QUEUED)) {
                /* Change its type to us since we are installing it */
                if (!ZEBRA_NHG_CREATED(nhe))
@@ -2685,7 +2691,7 @@ struct nhg_hash_entry *zebra_nhg_proto_add(uint32_t id, int type,
                                           struct nexthop_group *nhg, afi_t afi)
 {
        struct nhg_hash_entry lookup;
-       struct nhg_hash_entry *new;
+       struct nhg_hash_entry *new, *old;
        struct nhg_connected *rb_node_dep = NULL;
 
        zebra_nhe_init(&lookup, afi, nhg->nexthop);
@@ -2693,8 +2699,23 @@ struct nhg_hash_entry *zebra_nhg_proto_add(uint32_t id, int type,
        lookup.id = id;
        lookup.type = type;
 
+       old = zebra_nhg_lookup_id(id);
+
+       if (old) {
+               /*
+                * This is a replace, just release NHE from ID for now, The
+                * depends/dependents may still be used in the replacement.
+                */
+               hash_release(zrouter.nhgs_id, old);
+       }
+
        new = zebra_nhg_rib_find_nhe(&lookup, afi);
 
+       if (old) {
+               /* Now release depends/dependents in old one */
+               zebra_nhg_release_all_deps(old);
+       }
+
        if (!new)
                return NULL;
 
@@ -2707,9 +2728,9 @@ struct nhg_hash_entry *zebra_nhg_proto_add(uint32_t id, int type,
        }
 
        if (IS_ZEBRA_DEBUG_NHG_DETAIL)
-               zlog_debug("%s: added nhe %p (%u), vrf %d, type %s", __func__,
-                          new, new->id, new->vrf_id,
-                          zebra_route_string(new->type));
+               zlog_debug("%s: %s nhe %p (%u), vrf %d, type %s", __func__,
+                          (old ? "replaced" : "added"), new, new->id,
+                          new->vrf_id, zebra_route_string(new->type));
 
        return new;
 }