summaryrefslogtreecommitdiff
path: root/ldpd/lde_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldpd/lde_lib.c')
-rw-r--r--ldpd/lde_lib.c55
1 files changed, 37 insertions, 18 deletions
diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c
index db2682a173..37a670bc8c 100644
--- a/ldpd/lde_lib.c
+++ b/ldpd/lde_lib.c
@@ -383,20 +383,23 @@ lde_kernel_update(struct fec *fec)
if (LIST_EMPTY(&fn->nexthops)) {
RB_FOREACH(ln, nbr_tree, &lde_nbrs)
lde_send_labelwithdraw(ln, fn, NULL, NULL);
- fn->local_label = NO_LABEL;
fn->data = NULL;
- } else {
- uint32_t previous_label;
- previous_label = fn->local_label;
+ /*
+ * Do not deallocate the local label now, do that only in the
+ * LIB garbage collector. This will prevent ldpd from changing
+ * the input label of some prefixes too often when running on
+ * an unstable network. Also, restart the garbage collector
+ * timer so that labels are deallocated only when the network
+ * is stabilized.
+ */
+ lde_gc_start_timer();
+ } else {
fn->local_label = lde_update_label(fn);
-
- if (fn->local_label != NO_LABEL &&
- fn->local_label != previous_label) {
+ if (fn->local_label != NO_LABEL && RB_EMPTY(&fn->upstream))
/* FEC.1: perform lsr label distribution procedure */
RB_FOREACH(ln, nbr_tree, &lde_nbrs)
lde_send_labelmapping(ln, fn, 1);
- }
}
LIST_FOREACH(fnh, &fn->nexthops, entry) {
@@ -659,6 +662,7 @@ lde_check_release(struct map *map, struct lde_nbr *ln)
struct fec_node *fn;
struct lde_wdraw *lw;
struct lde_map *me;
+ struct fec *pending_map;
/* wildcard label release */
if (map->type == MAP_TYPE_WILDCARD ||
@@ -674,17 +678,24 @@ lde_check_release(struct map *map, struct lde_nbr *ln)
if (fn == NULL)
return;
+ /* LRl.6: check sent map list and remove it if available */
+ me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec);
+ if (me && (map->label == NO_LABEL || map->label == me->map.label))
+ lde_map_del(ln, me, 1);
+
/* LRl.3: first check if we have a pending withdraw running */
lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec);
if (lw && (map->label == NO_LABEL || map->label == lw->label)) {
/* LRl.4: delete record of outstanding label withdraw */
lde_wdraw_del(ln, lw);
- }
- /* LRl.6: check sent map list and remove it if available */
- me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec);
- if (me && (map->label == NO_LABEL || map->label == me->map.label))
- lde_map_del(ln, me, 1);
+ /* send pending label mapping if any */
+ pending_map = fec_find(&ln->sent_map_pending, &fn->fec);
+ if (pending_map) {
+ lde_send_labelmapping(ln, fn, 1);
+ lde_map_pending_del(ln, pending_map);
+ }
+ }
/*
* LRl.11 - 13 are unnecessary since we remove the label from
@@ -699,6 +710,7 @@ lde_check_release_wcard(struct map *map, struct lde_nbr *ln)
struct fec_node *fn;
struct lde_wdraw *lw;
struct lde_map *me;
+ struct fec *pending_map;
RB_FOREACH(f, fec_tree, &ft) {
fn = (struct fec_node *)f;
@@ -708,17 +720,24 @@ lde_check_release_wcard(struct map *map, struct lde_nbr *ln)
if (lde_wildcard_apply(map, &fn->fec, me) == 0)
continue;
+ /* LRl.6: check sent map list and remove it if available */
+ if (me &&
+ (map->label == NO_LABEL || map->label == me->map.label))
+ lde_map_del(ln, me, 1);
+
/* LRl.3: first check if we have a pending withdraw running */
lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec);
if (lw && (map->label == NO_LABEL || map->label == lw->label)) {
/* LRl.4: delete record of outstanding lbl withdraw */
lde_wdraw_del(ln, lw);
- }
- /* LRl.6: check sent map list and remove it if available */
- if (me &&
- (map->label == NO_LABEL || map->label == me->map.label))
- lde_map_del(ln, me, 1);
+ /* send pending label mapping if any */
+ pending_map = fec_find(&ln->sent_map_pending, &fn->fec);
+ if (pending_map) {
+ lde_send_labelmapping(ln, fn, 1);
+ lde_map_pending_del(ln, pending_map);
+ }
+ }
/*
* LRl.11 - 13 are unnecessary since we remove the label from