]> git.proxmox.com Git - mirror_frr.git/commitdiff
ldpd: Fix to release MPLS label if its not used anymore
authorBinu Abraham <binu_abraham@looptelecom.com>
Wed, 10 Jul 2019 07:13:08 +0000 (15:13 +0800)
committerBinu Abraham <binu_abraham@looptelecom.com>
Mon, 15 Jul 2019 06:05:51 +0000 (14:05 +0800)
LDP should release labels allocated from zebra if its not getting used.

Signed-off-by: Binu <binu_abraham@looptelecom.com>
ldpd/lde.c
ldpd/lde.h
ldpd/lde_lib.c

index 0ddf4f07d99ef386aff2cdfce4f05ab0be7f9c0e..ac680b47a93230b1a7d88fffc2195a2c12dbe7ec 100644 (file)
@@ -1653,6 +1653,19 @@ lde_del_label_chunk(void *val)
        free(val);
 }
 
+static int
+lde_release_label_chunk(uint32_t start, uint32_t end)
+{
+       int             ret;
+
+       ret = lm_release_label_chunk(zclient_sync, start, end);
+       if (ret < 0) {
+               log_warnx("Error releasing label chunk!");
+               return (-1);
+       }
+       return (0);
+}
+
 static int
 lde_get_label_chunk(void)
 {
@@ -1709,6 +1722,32 @@ on_get_label_chunk_response(uint32_t start, uint32_t end)
                current_label_chunk = listtail(label_chunk_list);
 }
 
+void
+lde_free_label(uint32_t label)
+{
+       struct listnode *node;
+       struct label_chunk      *label_chunk;
+       uint64_t                pos;
+
+       for (ALL_LIST_ELEMENTS_RO(label_chunk_list, node, label_chunk)) {
+               if (label <= label_chunk->end && label >= label_chunk->start) {
+                       pos = 1ULL << (label - label_chunk->start);
+                       label_chunk->used_mask &= ~pos;
+                       /* if nobody is using this chunk and it's not current_label_chunk, then free it */
+                       if (!label_chunk->used_mask && (current_label_chunk != node)) {
+                               if (lde_release_label_chunk(label_chunk->start, label_chunk->end) != 0)
+                                       log_warnx("%s: Error releasing label chunk!", __func__);
+                               else {
+                                       listnode_delete(label_chunk_list, label_chunk);
+                                       lde_del_label_chunk(label_chunk);
+                               }
+                       }
+                       break;
+               }
+       }
+       return;
+}
+
 static uint32_t
 lde_get_next_label(void)
 {
index 94077d16316be8b948d2a2881e4ab3fab01c0638..0a7d0a58fe4a1b62f1ac7f886bf75f198e70db00 100644 (file)
@@ -147,6 +147,7 @@ void                 lde_imsg_compose_parent_sync(int, pid_t, void *, uint16_t);
 int             lde_imsg_compose_ldpe(int, uint32_t, pid_t, void *, uint16_t);
 int             lde_acl_check(char *, int, union ldpd_addr *, uint8_t);
 uint32_t        lde_update_label(struct fec_node *);
+void            lde_free_label(uint32_t label);
 void            lde_send_change_klabel(struct fec_node *, struct fec_nh *);
 void            lde_send_delete_klabel(struct fec_node *, struct fec_nh *);
 void            lde_fec2map(struct fec *, struct map *);
index 28e455c7a58fc7009c64e6b96a0d9f76ed4d872d..0957a5455e3dfc99db93c59eba0c48a9154c1de9 100644 (file)
@@ -919,6 +919,9 @@ lde_gc_timer(struct thread *thread)
                    !RB_EMPTY(lde_map_head, &fn->upstream))
                        continue;
 
+               if (fn->local_label != NO_LABEL)
+                       lde_free_label(fn->local_label);
+
                fec_remove(&ft, &fn->fec);
                free(fn);
                count++;