summaryrefslogtreecommitdiffstats
path: root/ldpd
diff options
context:
space:
mode:
authorBinu Abraham <binu_abraham@looptelecom.com>2019-07-10 09:13:08 +0200
committerBinu Abraham <binu_abraham@looptelecom.com>2019-07-15 08:05:51 +0200
commitf4ec681c8151ba75a7951db589ca5dcc6870f887 (patch)
treea5e95ff9ff19675b2e9e3fd6850ca02fbdd70a74 /ldpd
parentMerge pull request #4658 from chiragshah6/ospf_vrf_dev (diff)
downloadfrr-f4ec681c8151ba75a7951db589ca5dcc6870f887.tar.xz
frr-f4ec681c8151ba75a7951db589ca5dcc6870f887.zip
ldpd: Fix to release MPLS label if its not used anymore
LDP should release labels allocated from zebra if its not getting used. Signed-off-by: Binu <binu_abraham@looptelecom.com>
Diffstat (limited to 'ldpd')
-rw-r--r--ldpd/lde.c39
-rw-r--r--ldpd/lde.h1
-rw-r--r--ldpd/lde_lib.c3
3 files changed, 43 insertions, 0 deletions
diff --git a/ldpd/lde.c b/ldpd/lde.c
index 0ddf4f07d..ac680b47a 100644
--- a/ldpd/lde.c
+++ b/ldpd/lde.c
@@ -1654,6 +1654,19 @@ lde_del_label_chunk(void *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)
{
int ret;
@@ -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)
{
diff --git a/ldpd/lde.h b/ldpd/lde.h
index 94077d163..0a7d0a58f 100644
--- a/ldpd/lde.h
+++ b/ldpd/lde.h
@@ -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 *);
diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c
index 28e455c7a..0957a5455 100644
--- a/ldpd/lde_lib.c
+++ b/ldpd/lde_lib.c
@@ -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++;