summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2010-11-04 09:49:08 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2010-11-04 09:49:08 +0000
commit399e2bd2fdd1d1bfede26dda086423c31e1000bc (patch)
treec8535984e77b1e61693c4aed3cc95421bd7fe67f
parentb3820fad02938cae736bb4066531c3929d307e53 (diff)
Only consider pathes with highest priority when replying to label
requests. Else a priority inversion may happen that would build label switching pathes that use inactive routes. OK michele@
-rw-r--r--usr.sbin/ldpd/lde.h3
-rw-r--r--usr.sbin/ldpd/lde_lib.c52
2 files changed, 42 insertions, 13 deletions
diff --git a/usr.sbin/ldpd/lde.h b/usr.sbin/ldpd/lde.h
index 4ef44e90de1..7dbeceed33a 100644
--- a/usr.sbin/ldpd/lde.h
+++ b/usr.sbin/ldpd/lde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: lde.h,v 1.17 2010/10/26 12:08:14 claudio Exp $ */
+/* $OpenBSD: lde.h,v 1.18 2010/11/04 09:49:07 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -82,6 +82,7 @@ struct rt_lsp {
struct in_addr nexthop;
u_int32_t remote_label;
+ u_int8_t priority;
};
struct rt_node {
diff --git a/usr.sbin/ldpd/lde_lib.c b/usr.sbin/ldpd/lde_lib.c
index da78b53b4e9..c0d153040e6 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.28 2010/10/26 12:08:14 claudio Exp $ */
+/* $OpenBSD: lde_lib.c,v 1.29 2010/11/04 09:49:07 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -42,8 +42,8 @@ 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);
+struct rt_lsp *rt_lsp_find(struct rt_node *, struct in_addr, u_int8_t);
+struct rt_lsp *rt_lsp_add(struct rt_node *, struct in_addr, u_int8_t);
void rt_lsp_del(struct rt_lsp *);
RB_PROTOTYPE(fec_tree, fec, entry, fec_compare)
@@ -243,20 +243,21 @@ rt_add(struct in_addr prefix, u_int8_t prefixlen)
}
struct rt_lsp *
-rt_lsp_find(struct rt_node *rn, struct in_addr nexthop)
+rt_lsp_find(struct rt_node *rn, struct in_addr nexthop, u_int8_t prio)
{
struct rt_lsp *rl;
LIST_FOREACH(rl, &rn->lsp, entry)
- if (rl->nexthop.s_addr == nexthop.s_addr)
+ if (rl->nexthop.s_addr == nexthop.s_addr &&
+ rl->priority == prio)
return (rl);
return (NULL);
}
struct rt_lsp *
-rt_lsp_add(struct rt_node *rn, struct in_addr nexthop)
+rt_lsp_add(struct rt_node *rn, struct in_addr nexthop, u_int8_t prio)
{
- struct rt_lsp *rl;
+ struct rt_lsp *rl, *nrl;
rl = calloc(1, sizeof(*rl));
if (rl == NULL)
@@ -264,8 +265,24 @@ rt_lsp_add(struct rt_node *rn, struct in_addr nexthop)
rl->nexthop.s_addr = nexthop.s_addr;
rl->remote_label = NO_LABEL;
- LIST_INSERT_HEAD(&rn->lsp, rl, entry);
-
+ rl->priority = prio;
+
+ /* keep LSP list sorted by priority because only the best routes
+ * can be used in a LSP. */
+ if (LIST_EMPTY(&rn->lsp))
+ LIST_INSERT_HEAD(&rn->lsp, rl, entry);
+ else {
+ LIST_FOREACH(nrl, &rn->lsp, entry) {
+ if (prio < nrl->priority) {
+ LIST_INSERT_BEFORE(nrl, rl, entry);
+ break;
+ }
+ if (LIST_NEXT(nrl, entry) == NULL) {
+ LIST_INSERT_AFTER(nrl, rl, entry);
+ break;
+ }
+ }
+ }
return (rl);
}
@@ -292,9 +309,9 @@ lde_kernel_insert(struct kroute *kr)
if (rn == NULL)
rn = rt_add(kr->prefix, kr->prefixlen);
- rl = rt_lsp_find(rn, kr->nexthop);
+ rl = rt_lsp_find(rn, kr->nexthop, kr->priority);
if (rl == NULL)
- rl = rt_lsp_add(rn, kr->nexthop);
+ rl = rt_lsp_add(rn, kr->nexthop, kr->priority);
/* There is static assigned label for this route, record it in lib */
if (kr->local_label != NO_LABEL) {
@@ -339,7 +356,7 @@ lde_kernel_remove(struct kroute *kr)
/* route lost */
return;
- rl = rt_lsp_find(rn, kr->nexthop);
+ rl = rt_lsp_find(rn, kr->nexthop, kr->priority);
if (rl != NULL)
rt_lsp_del(rl);
@@ -446,6 +463,7 @@ lde_check_request(struct map *map, struct lde_nbr *ln)
struct rt_node *rn;
struct rt_lsp *rl;
struct lde_nbr *lnn;
+ u_int8_t prio = 0;
log_debug("label request from nbr %s, FEC %s",
inet_ntoa(ln->id), log_fec(map));
@@ -459,6 +477,11 @@ lde_check_request(struct map *map, struct lde_nbr *ln)
}
LIST_FOREACH(rl, &rn->lsp, entry) {
+ /* only consider pathes with highest priority */
+ if (prio == 0)
+ prio = rl->priority;
+ if (prio < rl->priority)
+ break;
if (lde_address_find(ln, &rl->nexthop)) {
lde_send_notification(ln->peerid, S_LOOP_DETECTED,
map->messageid, MSG_TYPE_LABELREQUEST);
@@ -488,6 +511,11 @@ lde_check_request(struct map *map, struct lde_nbr *ln)
/* no mapping available, try to request */
/* XXX depending on the request behaviour we could return here */
LIST_FOREACH(rl, &rn->lsp, entry) {
+ /* only consider pathes with highest priority */
+ if (prio == 0)
+ prio = rl->priority;
+ if (prio < rl->priority)
+ break;
lnn = lde_find_address(rl->nexthop);
if (lnn == NULL)
continue;