]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/zebra_rib.c
zebra: Releasing/uninstalling re-work with groups
[mirror_frr.git] / zebra / zebra_rib.c
index 3b3bf921bc80f1784e5b45778a83adc113ddb295..3155570df5e3d2f937833629b99d712456ac82d6 100644 (file)
@@ -2396,7 +2396,7 @@ static void rib_addnode(struct route_node *rn,
 void rib_unlink(struct route_node *rn, struct route_entry *re)
 {
        rib_dest_t *dest;
-       rib_table_info_t *info;
+       struct nhg_hash_entry *nhe = NULL;
 
        assert(rn && re);
 
@@ -2411,11 +2411,10 @@ void rib_unlink(struct route_node *rn, struct route_entry *re)
        if (dest->selected_fib == re)
                dest->selected_fib = NULL;
 
-       zebra_nhg_decrement_ref(re->nhe);
+       nhe = zebra_nhg_lookup_id(re->nhe_id);
+       if (nhe)
+               zebra_nhg_decrement_ref(nhe);
 
-       // TODO: We need to hold on nh's until refcnt is 0 right?
-       nexthops_free(re->ng->nexthop);
-       nexthop_group_delete(&re->ng);
        nexthops_free(re->fib_ng.nexthop);
 
        XFREE(MTYPE_RE, re);
@@ -2638,6 +2637,10 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
        struct route_table *table;
        struct route_node *rn;
        struct route_entry *same = NULL;
+       struct nhg_hash_entry *nhe = NULL;
+       struct list *nhg_depends = NULL;
+       /* Default to route afi */
+       afi_t nhg_afi = afi;
        int ret = 0;
 
        if (!re)
@@ -2648,8 +2651,7 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
        /* Lookup table.  */
        table = zebra_vrf_table_with_table_id(afi, safi, re->vrf_id, re->table);
        if (!table) {
-               nexthops_free(re->ng->nexthop);
-               nexthop_group_delete(&re->ng);
+               zebra_nhg_free_group_depends(re->ng, nhg_depends);
                XFREE(MTYPE_RE, re);
                return 0;
        }
@@ -2659,8 +2661,45 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
        if (src_p)
                apply_mask_ipv6(src_p);
 
-       re->nhe = zebra_nhg_find(re->ng, re->vrf_id, 0);
-       re->nhe->refcnt++;
+       /* If its a group, create a dependency list */
+       if (re->ng && re->ng->nexthop->next) {
+               struct nexthop *nh = NULL;
+               struct nexthop lookup = {0};
+               struct nhg_hash_entry *depend = NULL;
+
+               nhg_depends = nhg_depend_new_list();
+
+               for (ALL_NEXTHOPS_PTR(re->ng, nh)) {
+                       lookup = *nh;
+                       /* Clear it, since its a group */
+                       lookup.next = NULL;
+                       /* Use the route afi here, since a single nh */
+                       depend = zebra_nhg_find_nexthop(&lookup, afi);
+                       nhg_depend_add(nhg_depends, depend);
+               }
+
+               /* change the afi for group */
+               if (listcount(nhg_depends))
+                       nhg_afi = AFI_UNSPEC;
+       }
+
+       nhe = zebra_nhg_find(re->ng, re->vrf_id, nhg_afi, re->nhe_id,
+                            nhg_depends, false);
+
+       if (nhe) {
+               // TODO: Add interface pointer
+               zebra_nhg_free_group_depends(re->ng, nhg_depends);
+               re->ng = nhe->nhg;
+               re->nhe_id = nhe->id;
+               zebra_nhg_increment_ref(nhe);
+       } else {
+               flog_err(
+                       EC_ZEBRA_TABLE_LOOKUP_FAILED,
+                       "Zebra failed to find or create a nexthop hash entry for id=%u in a route entry",
+                       re->nhe_id);
+       }
+
+
        /* Set default distance by route type. */
        if (re->distance == 0)
                re->distance = route_distance(re->type);
@@ -2941,11 +2980,11 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
 int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
            unsigned short instance, int flags, struct prefix *p,
            struct prefix_ipv6 *src_p, const struct nexthop *nh,
-           uint32_t table_id, uint32_t metric, uint32_t mtu, uint8_t distance,
-           route_tag_t tag)
+           uint32_t nhe_id, uint32_t table_id, uint32_t metric, uint32_t mtu,
+           uint8_t distance, route_tag_t tag)
 {
-       struct route_entry *re;
-       struct nexthop *nexthop;
+       struct route_entry *re = NULL;
+       struct nexthop *nexthop = NULL;
 
        /* Allocate new route_entry structure. */
        re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
@@ -2959,6 +2998,8 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
        re->vrf_id = vrf_id;
        re->uptime = monotime(NULL);
        re->tag = tag;
+       re->nhe_id = nhe_id;
+
        re->ng = nexthop_group_new();
 
        /* Add nexthop. */
@@ -3418,6 +3459,12 @@ static int rib_process_dplane_results(struct thread *thread)
                                rib_process_dplane_notify(ctx);
                                break;
 
+                       case DPLANE_OP_NH_INSTALL:
+                       case DPLANE_OP_NH_UPDATE:
+                       case DPLANE_OP_NH_DELETE:
+                               zebra_nhg_dplane_result(ctx);
+                               break;
+
                        case DPLANE_OP_LSP_INSTALL:
                        case DPLANE_OP_LSP_UPDATE:
                        case DPLANE_OP_LSP_DELETE: