]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/zebra_nhg.c
zebra: nexthop groups vrf's are only a function of namespaces
[mirror_frr.git] / zebra / zebra_nhg.c
index 74303073206b6ac213ddd1dc60156b6bcf00cd75..732349a570621f96c7e95e4bd480a5e0fb40c5b6 100644 (file)
@@ -99,31 +99,60 @@ nhg_connected_tree_root(struct nhg_connected_tree_head *head)
        return nhg_connected_tree_first(head);
 }
 
-void nhg_connected_tree_del_nhe(struct nhg_connected_tree_head *head,
-                               struct nhg_hash_entry *depend)
+struct nhg_hash_entry *
+nhg_connected_tree_del_nhe(struct nhg_connected_tree_head *head,
+                          struct nhg_hash_entry *depend)
 {
        struct nhg_connected lookup = {};
        struct nhg_connected *remove = NULL;
+       struct nhg_hash_entry *removed_nhe;
 
        lookup.nhe = depend;
 
        /* Lookup to find the element, then remove it */
        remove = nhg_connected_tree_find(head, &lookup);
-       remove = nhg_connected_tree_del(head, remove);
-
        if (remove)
+               /* Re-returning here just in case this API changes..
+                * the _del list api's are a bit undefined at the moment.
+                *
+                * So hopefully returning here will make it fail if the api
+                * changes to something different than currently expected.
+                */
+               remove = nhg_connected_tree_del(head, remove);
+
+       /* If the entry was sucessfully removed, free the 'connected` struct */
+       if (remove) {
+               removed_nhe = remove->nhe;
                nhg_connected_free(remove);
+               return removed_nhe;
+       }
+
+       return NULL;
 }
 
-void nhg_connected_tree_add_nhe(struct nhg_connected_tree_head *head,
-                               struct nhg_hash_entry *depend)
+/* Assuming UNIQUE RB tree. If this changes, assumptions here about
+ * insertion need to change.
+ */
+struct nhg_hash_entry *
+nhg_connected_tree_add_nhe(struct nhg_connected_tree_head *head,
+                          struct nhg_hash_entry *depend)
 {
        struct nhg_connected *new = NULL;
 
        new = nhg_connected_new(depend);
 
-       if (new)
-               nhg_connected_tree_add(head, new);
+       /* On success, NULL will be returned from the
+        * RB code.
+        */
+       if (new && (nhg_connected_tree_add(head, new) == NULL))
+               return NULL;
+
+       /* If it wasn't successful, it must be a duplicate. We enforce the
+        * unique property for the `nhg_connected` tree.
+        */
+       nhg_connected_free(new);
+
+       return depend;
 }
 
 static void
@@ -288,15 +317,15 @@ zebra_nhg_connect_depends(struct nhg_hash_entry *nhe,
                struct interface *ifp = NULL;
 
                ifp = if_lookup_by_index(nhe->nhg->nexthop->ifindex,
-                                        nhe->vrf_id);
+                                        nhe->nhg->nexthop->vrf_id);
                if (ifp)
                        zebra_nhg_set_if(nhe, ifp);
                else
                        flog_err(
                                EC_ZEBRA_IF_LOOKUP_FAILED,
                                "Zebra failed to lookup an interface with ifindex=%d in vrf=%u for NHE id=%u",
-                               nhe->nhg->nexthop->ifindex, nhe->vrf_id,
-                               nhe->id);
+                               nhe->nhg->nexthop->ifindex,
+                               nhe->nhg->nexthop->vrf_id, nhe->id);
        }
 }
 
@@ -481,7 +510,9 @@ static void handle_recursive_depend(struct nhg_connected_tree_head *nhg_depends,
        resolved_ng.nexthop = nh;
 
        depend = zebra_nhg_rib_find(0, &resolved_ng, afi);
-       depends_add(nhg_depends, depend);
+
+       if (depend)
+               depends_add(nhg_depends, depend);
 }
 
 static bool zebra_nhg_find(struct nhg_hash_entry **nhe, uint32_t id,
@@ -504,10 +535,10 @@ static bool zebra_nhg_find(struct nhg_hash_entry **nhe, uint32_t id,
        lookup.type = type ? type : ZEBRA_ROUTE_NHG;
        lookup.nhg = nhg;
 
+       lookup.vrf_id = vrf_id;
        if (lookup.nhg->nexthop->next) {
                /* Groups can have all vrfs and AF's in them */
                lookup.afi = AFI_UNSPEC;
-               lookup.vrf_id = VRF_DEFAULT;
        } else {
                switch (lookup.nhg->nexthop->type) {
                case (NEXTHOP_TYPE_IFINDEX):
@@ -531,8 +562,6 @@ static bool zebra_nhg_find(struct nhg_hash_entry **nhe, uint32_t id,
                        lookup.afi = AFI_IP6;
                        break;
                }
-
-               lookup.vrf_id = vrf_id;
        }
 
        if (id)
@@ -591,10 +620,11 @@ zebra_nhg_find_nexthop(uint32_t id, struct nexthop *nh, afi_t afi, int type)
 {
        struct nhg_hash_entry *nhe = NULL;
        struct nexthop_group nhg = {};
+       vrf_id_t vrf_id = !vrf_is_backend_netns() ? VRF_DEFAULT : nh->vrf_id;
 
        nexthop_group_add_sorted(&nhg, nh);
 
-       zebra_nhg_find(&nhe, id, &nhg, NULL, nh->vrf_id, afi, type);
+       zebra_nhg_find(&nhe, id, &nhg, NULL, vrf_id, afi, type);
 
        return nhe;
 }
@@ -1031,11 +1061,11 @@ int zebra_nhg_kernel_find(uint32_t id, struct nexthop *nh, struct nh_grp *grp,
 }
 
 /* Kernel-side, received delete message */
-int zebra_nhg_kernel_del(uint32_t id)
+int zebra_nhg_kernel_del(uint32_t id, vrf_id_t vrf_id)
 {
        struct nhg_ctx *ctx = NULL;
 
-       ctx = nhg_ctx_init(id, NULL, NULL, 0, 0, 0, 0);
+       ctx = nhg_ctx_init(id, NULL, NULL, vrf_id, 0, 0, 0);
 
        nhg_ctx_set_op(ctx, NHG_CTX_OP_DEL);
 
@@ -1104,8 +1134,14 @@ done:
 static void depends_add(struct nhg_connected_tree_head *head,
                        struct nhg_hash_entry *depend)
 {
-       nhg_connected_tree_add_nhe(head, depend);
-       zebra_nhg_increment_ref(depend);
+       /* If NULL is returned, it was successfully added and
+        * needs to have its refcnt incremented.
+        *
+        * Else the NHE is already present in the tree and doesn't
+        * need to increment the refcnt.
+        */
+       if (nhg_connected_tree_add_nhe(head, depend) == NULL)
+               zebra_nhg_increment_ref(depend);
 }
 
 static struct nhg_hash_entry *
@@ -1146,6 +1182,14 @@ struct nhg_hash_entry *
 zebra_nhg_rib_find(uint32_t id, struct nexthop_group *nhg, afi_t rt_afi)
 {
        struct nhg_hash_entry *nhe = NULL;
+       vrf_id_t vrf_id;
+
+       /*
+        * CLANG SA is complaining that nexthop may be NULL
+        * Make it happy but this is ridonc
+        */
+       assert(nhg->nexthop);
+       vrf_id = !vrf_is_backend_netns() ? VRF_DEFAULT : nhg->nexthop->vrf_id;
 
        if (!(nhg && nhg->nexthop)) {
                flog_err(EC_ZEBRA_TABLE_LOOKUP_FAILED,
@@ -1153,7 +1197,7 @@ zebra_nhg_rib_find(uint32_t id, struct nexthop_group *nhg, afi_t rt_afi)
                return NULL;
        }
 
-       zebra_nhg_find(&nhe, id, nhg, NULL, nhg->nexthop->vrf_id, rt_afi, 0);
+       zebra_nhg_find(&nhe, id, nhg, NULL, vrf_id, rt_afi, 0);
 
        return nhe;
 }