summaryrefslogtreecommitdiff
path: root/usr.sbin/ldpd
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2010-06-30 22:15:03 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2010-06-30 22:15:03 +0000
commit34931cd02c9f2f36b1c40b7669d8c87152fea6be (patch)
tree6b2302a9030ce6632bbe048678a4c6e2c9008a60 /usr.sbin/ldpd
parent43d133ff81055647efc440fd43eb7896003b5d2d (diff)
Make it possible to store multiple LSP to a FEC. This is another step to
handle multipath routes in MPLS. Looks good to michele@
Diffstat (limited to 'usr.sbin/ldpd')
-rw-r--r--usr.sbin/ldpd/lde.c64
-rw-r--r--usr.sbin/ldpd/lde.h18
-rw-r--r--usr.sbin/ldpd/lde_lib.c350
3 files changed, 247 insertions, 185 deletions
diff --git a/usr.sbin/ldpd/lde.c b/usr.sbin/ldpd/lde.c
index 0a87fafa813..58935519ca8 100644
--- a/usr.sbin/ldpd/lde.c
+++ b/usr.sbin/ldpd/lde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lde.c,v 1.19 2010/06/30 05:21:38 claudio Exp $ */
+/* $OpenBSD: lde.c,v 1.20 2010/06/30 22:15:02 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -431,29 +431,34 @@ lde_assign_label(void)
}
void
-lde_send_change_klabel(struct rt_node *r)
+lde_send_change_klabel(struct rt_node *rr, struct rt_lsp *rl)
{
struct kroute kr;
bzero(&kr, sizeof(kr));
- kr.prefix.s_addr = r->fec.prefix.s_addr;
- kr.prefixlen = r->fec.prefixlen;
- kr.nexthop.s_addr = r->nexthop.s_addr;
- kr.local_label = r->local_label;
- kr.remote_label = r->remote_label;
+ kr.prefix.s_addr = rr->fec.prefix.s_addr;
+ kr.prefixlen = rr->fec.prefixlen;
+ kr.local_label = rr->local_label;
+
+ kr.nexthop.s_addr = rl->nexthop.s_addr;
+ kr.remote_label = rl->remote_label;
imsg_compose_event(iev_main, IMSG_KLABEL_CHANGE, 0, 0, -1,
&kr, sizeof(kr));
}
void
-lde_send_delete_klabel(struct rt_node *r)
+lde_send_delete_klabel(struct rt_node *rr, struct rt_lsp *rl)
{
struct kroute kr;
bzero(&kr, sizeof(kr));
- kr.prefix.s_addr = r->fec.prefix.s_addr;
- kr.prefixlen = r->fec.prefixlen;
+ kr.prefix.s_addr = rr->fec.prefix.s_addr;
+ kr.prefixlen = rr->fec.prefixlen;
+ kr.local_label = rr->local_label;
+
+ kr.nexthop.s_addr = rl->nexthop.s_addr;
+ kr.remote_label = rl->remote_label;
imsg_compose_event(iev_main, IMSG_KLABEL_DELETE, 0, 0, -1,
&kr, sizeof(kr));
@@ -585,10 +590,11 @@ lde_nbr_clear(void)
void
lde_nbr_do_mappings(struct rt_node *rn)
{
+ struct map map;
struct lde_nbr *ln;
struct lde_map *lm;
struct lde_req *lr;
- struct map map;
+ struct rt_lsp *rl;
map.label = rn->local_label;
map.prefix = rn->fec.prefix;
@@ -610,9 +616,12 @@ lde_nbr_do_mappings(struct rt_node *rn)
if (ldeconf->mode & MODE_DIST_ORDERED) {
/* ordered mode needs the downstream path to be
* ready before we can send the mapping upstream */
- if (rn->nexthop.s_addr != INADDR_ANY &&
- rn->remote_label == NO_LABEL)
- /* not local FEC but no remote-label, skip */
+ LIST_FOREACH(rl, &rn->lsp, entry) {
+ /* no remote-label, skip */
+ if (rl->remote_label == NO_LABEL)
+ continue;
+ }
+ if (rl == NULL)
continue;
}
@@ -642,6 +651,33 @@ lde_nbr_do_mappings(struct rt_node *rn)
}
}
+struct lde_map *
+lde_map_add(struct lde_nbr *ln, struct rt_node *rn, int sent)
+{
+ struct lde_map *me;
+
+ me = calloc(1, sizeof(*me));
+ if (me == NULL)
+ fatal("lde_map_add");
+
+ me->fec = rn->fec;
+ me->nexthop = ln;
+
+ if (sent) {
+ LIST_INSERT_HEAD(&rn->upstream, me, entry);
+ if (fec_insert(&ln->sent_map, &me->fec))
+ log_warnx("failed to add %s/%u to sent map",
+ inet_ntoa(me->fec.prefix), me->fec.prefixlen);
+ } else {
+ LIST_INSERT_HEAD(&rn->downstream, me, entry);
+ if (fec_insert(&ln->recv_map, &me->fec))
+ log_warnx("failed to add %s/%u to recv map",
+ inet_ntoa(me->fec.prefix), me->fec.prefixlen);
+ }
+
+ return (me);
+}
+
void
lde_map_free(void *ptr)
{
diff --git a/usr.sbin/ldpd/lde.h b/usr.sbin/ldpd/lde.h
index 16a09be974c..8bc08c29895 100644
--- a/usr.sbin/ldpd/lde.h
+++ b/usr.sbin/ldpd/lde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: lde.h,v 1.14 2010/06/30 05:21:38 claudio Exp $ */
+/* $OpenBSD: lde.h,v 1.15 2010/06/30 22:15:02 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -77,26 +77,31 @@ struct lde_nbr {
u_int16_t lspace;
};
+struct rt_lsp {
+ LIST_ENTRY(rt_lsp) entry;
+
+ struct in_addr nexthop;
+ u_int32_t remote_label;
+};
+
struct rt_node {
struct fec fec;
- struct in_addr nexthop;
+ LIST_HEAD(, rt_lsp) lsp; /* label switching pathes */
LIST_HEAD(, lde_map) downstream; /* recv mappings */
LIST_HEAD(, lde_map) upstream; /* sent mappings */
u_int32_t local_label;
- u_int32_t remote_label;
u_int16_t lspace;
u_int8_t flags;
- u_int8_t present; /* Is it present in fib? */
};
/* lde.c */
pid_t lde(struct ldpd_conf *, int [2], int [2], int [2]);
int lde_imsg_compose_ldpe(int, u_int32_t, pid_t, void *, u_int16_t);
u_int32_t lde_assign_label(void);
-void lde_send_change_klabel(struct rt_node *);
-void lde_send_delete_klabel(struct rt_node *);
+void lde_send_change_klabel(struct rt_node *, struct rt_lsp *);
+void lde_send_delete_klabel(struct rt_node *, struct rt_lsp *);
void lde_send_labelmapping(u_int32_t, struct map *);
void lde_send_labelrequest(u_int32_t, struct map *);
void lde_send_labelrelease(u_int32_t, struct map *);
@@ -105,6 +110,7 @@ void lde_send_notification(u_int32_t, u_int32_t, u_int32_t,
void lde_nbr_del(struct lde_nbr *);
void lde_nbr_do_mappings(struct rt_node *);
+struct lde_map *lde_map_add(struct lde_nbr *, struct rt_node *, int);
struct lde_nbr *lde_find_address(struct in_addr);
diff --git a/usr.sbin/ldpd/lde_lib.c b/usr.sbin/ldpd/lde_lib.c
index 3b4051a39fe..cc4be767118 100644
--- a/usr.sbin/ldpd/lde_lib.c
+++ b/usr.sbin/ldpd/lde_lib.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lde_lib.c,v 1.23 2010/06/30 05:21:38 claudio Exp $ */
+/* $OpenBSD: lde_lib.c,v 1.24 2010/06/30 22:15:02 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -40,6 +40,12 @@
static int fec_compare(struct fec *, struct fec *);
+void rt_free(void *);
+struct rt_node *rt_add(struct in_addr, u_int8_t);
+struct rt_lsp *rt_lsp_find(struct rt_node *, struct in_addr);
+struct rt_lsp *rt_lsp_add(struct rt_node *, struct in_addr);
+void rt_lsp_del(struct rt_lsp *);
+
RB_PROTOTYPE(fec_tree, fec, entry, fec_compare)
RB_GENERATE(fec_tree, fec, entry, fec_compare)
@@ -118,34 +124,48 @@ fec_clear(struct fec_tree *fh, void (*free_cb)(void *))
}
+/* routing table functions */
void
rt_dump(pid_t pid)
{
struct fec *f;
- struct rt_node *r;
+ struct rt_node *rr;
+ struct rt_lsp *rl;
+ struct lde_map *me;
static struct ctl_rt rtctl;
RB_FOREACH(f, fec_tree, &rt) {
- r = (struct rt_node *)f;
- rtctl.prefix.s_addr = r->fec.prefix.s_addr;
- rtctl.prefixlen = r->fec.prefixlen;
- rtctl.nexthop.s_addr = r->nexthop.s_addr;
- rtctl.flags = r->flags;
- rtctl.local_label = r->local_label;
- rtctl.remote_label = r->remote_label;
-
- if (!r->present)
- rtctl.in_use = 0;
- else
+ rr = (struct rt_node *)f;
+ rtctl.prefix = rr->fec.prefix;
+ rtctl.prefixlen = rr->fec.prefixlen;
+ rtctl.flags = rr->flags;
+ rtctl.local_label = rr->local_label;
+
+ LIST_FOREACH(rl, &rr->lsp, entry) {
+ rtctl.nexthop = rl->nexthop;
+ rtctl.remote_label = rl->remote_label;
rtctl.in_use = 1;
- if (rtctl.nexthop.s_addr == htonl(INADDR_LOOPBACK))
- rtctl.connected = 1;
- else
- rtctl.connected = 0;
+ if (rtctl.nexthop.s_addr == htonl(INADDR_ANY))
+ rtctl.connected = 1;
+ else
+ rtctl.connected = 0;
- lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB, 0, pid, &rtctl,
- sizeof(rtctl));
+ lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB, 0, pid,
+ &rtctl, sizeof(rtctl));
+ }
+ if (LIST_EMPTY(&rr->lsp)) {
+ LIST_FOREACH(me, &rr->downstream, entry) {
+ rtctl.in_use = 0;
+ rtctl.connected = 0;
+ /* we don't know the nexthop use id instead */
+ rtctl.nexthop = me->nexthop->id;
+ rtctl.remote_label = me->label;
+
+ lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB, 0, pid,
+ &rtctl, sizeof(rtctl));
+ }
+ }
}
}
@@ -169,15 +189,94 @@ rt_snap(u_int32_t peerid)
}
void
+rt_free(void *arg)
+{
+ struct rt_node *rr = arg;
+ struct rt_lsp *rl;
+
+ while ((rl = LIST_FIRST(&rr->lsp))) {
+ LIST_REMOVE(rl, entry);
+ free(rl);
+ }
+
+ if (!LIST_EMPTY(&rr->downstream))
+ log_warnx("rt_free: fec %s/%u downstream list not empty",
+ inet_ntoa(rr->fec.prefix), rr->fec.prefixlen);
+ if (!LIST_EMPTY(&rr->upstream))
+ log_warnx("rt_free: fec %s/%u upstream list not empty",
+ inet_ntoa(rr->fec.prefix), rr->fec.prefixlen);
+
+ free(rl);
+}
+
+void
rt_clear(void)
{
- fec_clear(&rt, free);
+ fec_clear(&rt, rt_free);
+}
+
+struct rt_node *
+rt_add(struct in_addr prefix, u_int8_t prefixlen)
+{
+ struct rt_node *rn;
+
+ rn = calloc(1, sizeof(*rn));
+ if (rn == NULL)
+ fatal("rt_add");
+
+ rn->fec.prefix.s_addr = prefix.s_addr;
+ rn->fec.prefixlen = prefixlen;
+ rn->local_label = NO_LABEL;
+ LIST_INIT(&rn->upstream);
+ LIST_INIT(&rn->downstream);
+ LIST_INIT(&rn->lsp);
+
+ if (fec_insert(&rt, &rn->fec))
+ log_warnx("failed to add %s/%u to rt tree",
+ inet_ntoa(rn->fec.prefix), rn->fec.prefixlen);
+
+ return (rn);
+}
+
+struct rt_lsp *
+rt_lsp_find(struct rt_node *rn, struct in_addr nexthop)
+{
+ struct rt_lsp *rl;
+
+ LIST_FOREACH(rl, &rn->lsp, entry)
+ if (rl->nexthop.s_addr == nexthop.s_addr)
+ return (rl);
+ return (NULL);
+}
+
+struct rt_lsp *
+rt_lsp_add(struct rt_node *rn, struct in_addr nexthop)
+{
+ struct rt_lsp *rl;
+
+ rl = calloc(1, sizeof(*rl));
+ if (rl == NULL)
+ fatal("rt_lsp_add");
+
+ rl->nexthop.s_addr = nexthop.s_addr;
+ rl->remote_label = NO_LABEL;
+ LIST_INSERT_HEAD(&rn->lsp, rl, entry);
+
+ return (rl);
+}
+
+void
+rt_lsp_del(struct rt_lsp *rl)
+{
+ LIST_REMOVE(rl, entry);
+ free(rl);
}
void
lde_kernel_insert(struct kroute *kr)
{
struct rt_node *rn;
+ struct rt_lsp *rl;
struct lde_nbr_address *addr;
struct lde_map *map;
@@ -186,56 +285,12 @@ lde_kernel_insert(struct kroute *kr)
rn = (struct rt_node *)fec_find_prefix(&rt, kr->prefix.s_addr,
kr->prefixlen);
- if (rn == NULL) {
- rn = calloc(1, sizeof(*rn));
- if (rn == NULL)
- fatal("lde_insert");
-
- rn->fec.prefix.s_addr = kr->prefix.s_addr;
- rn->fec.prefixlen = kr->prefixlen;
- rn->remote_label = NO_LABEL;
- rn->local_label = NO_LABEL;
- LIST_INIT(&rn->upstream);
- LIST_INIT(&rn->downstream);
-
- if (fec_insert(&rt, &rn->fec))
- log_warnx("failed to add %s/%u to rt tree",
- inet_ntoa(rn->fec.prefix), rn->fec.prefixlen);
- }
-
- if (rn->present) {
- if (kr->nexthop.s_addr == rn->nexthop.s_addr)
- return;
-
- /* The nexthop has changed, change also the label associated
- with prefix */
- rn->remote_label = NO_LABEL;
- rn->nexthop.s_addr = kr->nexthop.s_addr;
-
- if ((ldeconf->mode & MODE_RET_LIBERAL) == 0) {
- /* XXX: we support just liberal retention for now */
- log_warnx("lde_kernel_insert: missing mode");
- return;
- }
-
- LIST_FOREACH(map, &rn->downstream, entry) {
- addr = lde_address_find(map->nexthop, &rn->nexthop);
- if (addr != NULL) {
- rn->remote_label = map->label;
- break;
- }
- }
-
- log_debug("lde_kernel_insert: prefix %s%u, "
- "changing label to %u", inet_ntoa(rn->fec.prefix),
- rn->fec.prefixlen, map ? map->label : 0);
-
- lde_send_change_klabel(rn);
- return;
- }
+ if (rn == NULL)
+ rn = rt_add(kr->prefix, kr->prefixlen);
- rn->present = 1;
- rn->nexthop.s_addr = kr->nexthop.s_addr;
+ rl = rt_lsp_find(rn, kr->nexthop);
+ if (rl == NULL)
+ rl = rt_lsp_add(rn, kr->nexthop);
/* There is static assigned label for this route, record it in lib */
if (kr->local_label != NO_LABEL) {
@@ -243,24 +298,23 @@ lde_kernel_insert(struct kroute *kr)
return;
}
+ if (rn->local_label == NO_LABEL) {
+ if (kr->nexthop.s_addr == INADDR_ANY)
+ /* Directly connected route */
+ rn->local_label = MPLS_LABEL_IMPLNULL;
+ else
+ rn->local_label = lde_assign_label();
+ }
+
LIST_FOREACH(map, &rn->downstream, entry) {
- addr = lde_address_find(map->nexthop, &rn->nexthop);
+ addr = lde_address_find(map->nexthop, &rl->nexthop);
if (addr != NULL) {
- rn->remote_label = map->label;
+ rl->remote_label = map->label;
break;
}
}
- if (rn->local_label == NO_LABEL) {
- /* Directly connected route */
- if (kr->nexthop.s_addr == INADDR_ANY) {
- rn->local_label = MPLS_LABEL_IMPLNULL;
- rn->nexthop.s_addr = htonl(INADDR_LOOPBACK);
- } else
- rn->local_label = lde_assign_label();
- }
-
- lde_send_change_klabel(rn);
+ lde_send_change_klabel(rn, rl);
/* Redistribute the current mapping to every nbr */
lde_nbr_do_mappings(rn);
@@ -270,8 +324,7 @@ void
lde_kernel_remove(struct kroute *kr)
{
struct rt_node *rn;
- struct lde_map *map;
- struct lde_nbr *ln;
+ struct rt_lsp *rl;
log_debug("kernel remove route %s/%u", inet_ntoa(kr->prefix),
kr->prefixlen);
@@ -279,36 +332,27 @@ lde_kernel_remove(struct kroute *kr)
rn = (struct rt_node *)fec_find_prefix(&rt, kr->prefix.s_addr,
kr->prefixlen);
if (rn == NULL)
+ /* route lost */
return;
- if (ldeconf->mode & MODE_RET_LIBERAL) {
- ln = lde_find_address(rn->nexthop);
- if (ln) {
- map = calloc(1, sizeof(*map));
- if (map == NULL)
- fatal("lde_kernel_remove");
-
- map->label = rn->remote_label;
- map->fec = rn->fec;
- map->nexthop = ln;
- LIST_INSERT_HEAD(&rn->downstream, map, entry);
- if (fec_insert(&ln->recv_map, &map->fec))
- log_warnx("failed to add %s/%u to recv map (1)",
- inet_ntoa(map->fec.prefix),
- map->fec.prefixlen);
- }
- }
+ rl = rt_lsp_find(rn, kr->nexthop);
+ if (rl == NULL)
+ /* nexthop lost */
- rn->remote_label = NO_LABEL;
- rn->nexthop.s_addr = INADDR_ANY;
- rn->present = 0;
+ rt_lsp_del(rl);
+
+ /* XXX handling of total loss of route, withdraw mappings, etc */
+
+ /* Redistribute the current mapping to every nbr */
+ lde_nbr_do_mappings(rn);
}
void
lde_check_mapping(struct map *map, struct lde_nbr *ln)
{
struct rt_node *rn;
- struct lde_nbr_address *addr;
+ struct rt_lsp *rl;
+ struct lde_nbr_address *addr = NULL;
struct lde_map *me;
log_debug("label mapping from nbr %s, FEC %s/%u, label %u",
@@ -322,22 +366,8 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln)
if (ldeconf->mode & MODE_RET_CONSERVATIVE)
return;
- rn = calloc(1, sizeof(*rn));
- if (rn == NULL)
- fatal("lde_check_mapping");
-
- rn->fec.prefix = map->prefix;
- rn->fec.prefixlen = map->prefixlen;
+ rn = rt_add(map->prefix, map->prefixlen);
rn->local_label = lde_assign_label();
- rn->remote_label = NO_LABEL;
- rn->present = 0;
-
- LIST_INIT(&rn->upstream);
- LIST_INIT(&rn->downstream);
-
- if (fec_insert(&rt, &rn->fec))
- log_warnx("failed to add %s/%u to rt tree",
- inet_ntoa(rn->fec.prefix), rn->fec.prefixlen);
}
LIST_FOREACH(me, &rn->downstream, entry) {
@@ -355,54 +385,34 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln)
}
}
- addr = lde_address_find(ln, &rn->nexthop);
- if (addr == NULL || !rn->present) {
+ LIST_FOREACH(rl, &rn->lsp, entry) {
+ addr = lde_address_find(ln, &rl->nexthop);
+ if (addr)
+ break;
+ }
+
+ if (addr == NULL) {
/* route not yet available */
if (ldeconf->mode & MODE_RET_CONSERVATIVE) {
lde_send_labelrelease(ln->peerid, map);
return;
}
/* in liberal mode just note the mapping */
- if (me == NULL) {
- me = calloc(1, sizeof(*me));
- if (me == NULL)
- fatal("lde_check_mapping");
- me->fec = rn->fec;
- me->nexthop = ln;
-
- LIST_INSERT_HEAD(&rn->downstream, me, entry);
- if (fec_insert(&ln->recv_map, &me->fec))
- log_warnx("failed to add %s/%u to recv map (2)",
- inet_ntoa(me->fec.prefix),
- me->fec.prefixlen);
- }
+ if (me == NULL)
+ me = lde_map_add(ln, rn, 0);
me->label = map->label;
return;
}
- rn->remote_label = map->label;
-
- /* If we are ingress for this LSP install the label */
- if (rn->nexthop.s_addr == INADDR_ANY)
- lde_send_change_klabel(rn);
+ rl->remote_label = map->label;
/* Record the mapping from this peer */
- if (me == NULL) {
- me = calloc(1, sizeof(*me));
- if (me == NULL)
- fatal("lde_check_mapping");
-
- me->fec = rn->fec;
- me->nexthop = ln;
- LIST_INSERT_HEAD(&rn->downstream, me, entry);
- if (fec_insert(&ln->recv_map, &me->fec))
- log_warnx("failed to add %s/%u to recv map (3)",
- inet_ntoa(me->fec.prefix), me->fec.prefixlen);
- }
+ if (me == NULL)
+ me = lde_map_add(ln, rn, 0);
me->label = map->label;
- lde_send_change_klabel(rn);
+ lde_send_change_klabel(rn, rl);
/* Redistribute the current mapping to every nbr */
lde_nbr_do_mappings(rn);
@@ -413,6 +423,7 @@ lde_check_request(struct map *map, struct lde_nbr *ln)
{
struct lde_req *lre;
struct rt_node *rn;
+ struct rt_lsp *rl;
struct lde_nbr *lnn;
struct map localmap;
@@ -421,35 +432,44 @@ lde_check_request(struct map *map, struct lde_nbr *ln)
rn = (struct rt_node *)fec_find_prefix(&rt, map->prefix.s_addr,
map->prefixlen);
- if (rn == NULL || rn->remote_label == NO_LABEL) {
+ if (rn == NULL) {
lde_send_notification(ln->peerid, S_NO_ROUTE, map->messageid,
MSG_TYPE_LABELREQUEST);
return;
}
- if (lde_address_find(ln, &rn->nexthop)) {
- lde_send_notification(ln->peerid, S_LOOP_DETECTED,
- map->messageid, MSG_TYPE_LABELREQUEST);
- return;
- }
-
+ /* first check if we have a pending request running */
lre = (struct lde_req *)fec_find(&ln->recv_req, &rn->fec);
if (lre != NULL)
return;
- if (rn->nexthop.s_addr == INADDR_ANY ||
- rn->remote_label != NO_LABEL) {
+ LIST_FOREACH(rl, &rn->lsp, entry) {
+ if (lde_address_find(ln, &rl->nexthop)) {
+ lde_send_notification(ln->peerid, S_LOOP_DETECTED,
+ map->messageid, MSG_TYPE_LABELREQUEST);
+ return;
+ }
+
+ if (rl->remote_label != NO_LABEL)
+ break;
+ }
+
+ /* there is a valid mapping available */
+ if (rl != NULL) {
bzero(&localmap, sizeof(localmap));
localmap.prefix = map->prefix;
localmap.prefixlen = map->prefixlen;
localmap.label = rn->local_label;
lde_send_labelmapping(ln->peerid, &localmap);
- } else {
- lnn = lde_find_address(rn->nexthop);
+ return;
+ }
+
+ /* no mapping available, try to request */
+ LIST_FOREACH(rl, &rn->lsp, entry) {
+ lnn = lde_find_address(rl->nexthop);
if (lnn == NULL)
- /* XXX this feels wrong.... */
- return;
+ continue;
lde_send_labelrequest(lnn->peerid, map);