summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorMichele Marchetto <michele@cvs.openbsd.org>2009-06-19 17:10:10 +0000
committerMichele Marchetto <michele@cvs.openbsd.org>2009-06-19 17:10:10 +0000
commitd69ce1d8e713532f6ea57a6e8b85ae5f40e406f3 (patch)
treede2c66ba777d172077d680e00f7d0d6d9b3ffc7d /usr.sbin
parent9e389c97db2994250cf69b5e94b03cff0cf5c0d0 (diff)
When operating in liberal mode, retain labels even if they aren't learnt
from current nexthop. ok laurent@
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/ldpd/lde.h3
-rw-r--r--usr.sbin/ldpd/lde_lib.c77
2 files changed, 63 insertions, 17 deletions
diff --git a/usr.sbin/ldpd/lde.h b/usr.sbin/ldpd/lde.h
index 1f60365965e..8023e6d6a32 100644
--- a/usr.sbin/ldpd/lde.h
+++ b/usr.sbin/ldpd/lde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: lde.h,v 1.2 2009/06/05 22:34:45 michele Exp $ */
+/* $OpenBSD: lde.h,v 1.3 2009/06/19 17:10:09 michele Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -85,6 +85,7 @@ struct rt_node {
u_int8_t flags;
u_int8_t prefixlen;
u_int8_t invalid;
+ u_int8_t present; /* Is it present in fib? */
};
/* lde.c */
diff --git a/usr.sbin/ldpd/lde_lib.c b/usr.sbin/ldpd/lde_lib.c
index ce5388d8326..cc6b4bdfe22 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.2 2009/06/05 22:34:45 michele Exp $ */
+/* $OpenBSD: lde_lib.c,v 1.3 2009/06/19 17:10:09 michele Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -164,20 +164,49 @@ lde_assign_label()
void
lde_insert(struct kroute *kr)
{
- struct rt_node *rn;
+ struct rt_node *rn;
+ struct rt_label *rl;
+ struct lde_nbr_address *addr;
+
+ rn = rt_find(kr->prefix.s_addr, kr->prefixlen);
+ if (rn == NULL) {
+ rn = calloc(1, sizeof(*rn));
+ if (rn == NULL)
+ fatal("lde_insert");
+
+ rn->prefix.s_addr = kr->prefix.s_addr;
+ rn->prefixlen = kr->prefixlen;
+ TAILQ_INIT(&rn->labels_list);
+
+ rt_insert(rn);
+ }
- rn = calloc(1, sizeof(*rn));
- if (rn == NULL)
- fatal("lde_insert");
+ if (rn->present)
+ return;
- rn->prefix.s_addr = kr->prefix.s_addr;
+ rn->present = 1;
rn->nexthop.s_addr = kr->nexthop.s_addr;
- rn->prefixlen = kr->prefixlen;
- TAILQ_INIT(&rn->labels_list);
- rt_insert(rn);
+ /* There is static assigned label for this route, record it in lib */
+ if (kr->local_label) {
+ rn->local_label = (htonl(kr->local_label) << MPLS_LABEL_OFFSET);
+ return;
+ }
- if (kr->local_label == 0) {
+ /* There is already a local mapping, check if there
+ is also a remote one */
+ if (rn->local_label) {
+ TAILQ_FOREACH(rl, &rn->labels_list, entry) {
+ addr = lde_address_find(rl->nexthop, &rn->nexthop);
+ if (addr != NULL) {
+ rn->remote_label =
+ htonl(rl->label << MPLS_LABEL_OFFSET);
+ TAILQ_REMOVE(&rn->labels_list, rl, entry);
+ free(rl);
+ break;
+ }
+ }
+ } else {
/* Directly connected route */
if (kr->nexthop.s_addr == INADDR_ANY) {
rn->local_label =
@@ -185,10 +214,9 @@ lde_insert(struct kroute *kr)
rn->nexthop.s_addr = htonl(INADDR_LOOPBACK);
} else
rn->local_label = lde_assign_label();
+ }
- lde_send_insert_klabel(rn);
- } else
- rn->local_label = (htonl(kr->local_label) << MPLS_LABEL_OFFSET);
+ lde_send_insert_klabel(rn);
}
void
@@ -202,9 +230,26 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln)
struct iface *iface;
struct map localmap;
+ /* The route is not yet in fib. If we are in liberal mode create a
+ route and record the label */
rn = rt_find(map->prefix, map->prefixlen);
- if (rn == NULL)
- return;
+ if (rn == NULL) {
+ if (ldeconf->mode & MODE_RET_CONSERVATIVE)
+ return;
+
+ rn = calloc(1, sizeof(*rn));
+ if (rn == NULL)
+ fatal("lde_check_mapping");
+
+ rn->prefix.s_addr = map->prefix;
+ rn->prefixlen = map->prefixlen;
+ rn->local_label = lde_assign_label();
+ rn->present = 0;
+
+ TAILQ_INIT(&rn->labels_list);
+
+ rt_insert(rn);
+ }
TAILQ_FOREACH(me, &ln->recv_map_list, entry) {
if (me->prefix.s_addr == map->prefix &&
@@ -217,7 +262,7 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln)
}
addr = lde_address_find(ln, &rn->nexthop);
- if (addr == NULL) {
+ if (addr == NULL || !rn->present) {
if (ldeconf->mode & MODE_RET_CONSERVATIVE) {
lde_send_labelrelease(ln->peerid, map);
return;