summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/ldpd/lde.c233
-rw-r--r--usr.sbin/ldpd/lde.h85
-rw-r--r--usr.sbin/ldpd/lde_lib.c380
3 files changed, 328 insertions, 370 deletions
diff --git a/usr.sbin/ldpd/lde.c b/usr.sbin/ldpd/lde.c
index 2213fbc66ff..a4780e87ce1 100644
--- a/usr.sbin/ldpd/lde.c
+++ b/usr.sbin/ldpd/lde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lde.c,v 1.14 2010/05/25 13:29:45 claudio Exp $ */
+/* $OpenBSD: lde.c,v 1.15 2010/06/02 11:56:29 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -22,6 +22,7 @@
#include <sys/socket.h>
#include <sys/queue.h>
#include <netinet/in.h>
+#include <netmpls/mpls.h>
#include <arpa/inet.h>
#include <err.h>
#include <errno.h>
@@ -43,15 +44,13 @@ void lde_shutdown(void);
void lde_dispatch_imsg(int, short, void *);
void lde_dispatch_parent(int, short, void *);
-void lde_nbr_init(u_int32_t);
-void lde_nbr_free(void);
struct lde_nbr *lde_nbr_find(u_int32_t);
struct lde_nbr *lde_nbr_new(u_int32_t, struct lde_nbr *);
void lde_nbr_del(struct lde_nbr *);
+void lde_nbr_clear(void);
+void lde_map_free(void *);
void lde_address_list_free(struct lde_nbr *);
-void lde_req_list_free(struct lde_nbr *);
-void lde_map_list_free(struct lde_nbr *);
struct ldpd_conf *ldeconf = NULL, *nconf = NULL;
struct imsgev *iev_ldpe;
@@ -114,7 +113,6 @@ lde(struct ldpd_conf *xconf, int pipe_parent2lde[2], int pipe_ldpe2lde[2],
fatal("can't drop privileges");
event_init();
- lde_nbr_init(NBR_HASHSIZE);
/* setup signal handler */
signal_set(&ev_sigint, SIGINT, lde_sig_handler, NULL);
@@ -149,8 +147,6 @@ lde(struct ldpd_conf *xconf, int pipe_parent2lde[2], int pipe_ldpe2lde[2],
iev_main->handler, iev_main);
event_add(&iev_main->ev, NULL);
- rt_init();
-
gettimeofday(&now, NULL);
ldeconf->uptime = now.tv_sec;
@@ -165,10 +161,9 @@ lde(struct ldpd_conf *xconf, int pipe_parent2lde[2], int pipe_ldpe2lde[2],
void
lde_shutdown(void)
{
+ lde_nbr_clear();
rt_clear();
- lde_nbr_free();
-
msgbuf_clear(&iev_ldpe->ibuf.w);
free(iev_ldpe);
msgbuf_clear(&iev_main->ibuf.w);
@@ -425,9 +420,13 @@ lde_dispatch_parent(int fd, short event, void *bula)
}
u_int32_t
-lde_router_id(void)
+lde_assign_label(void)
{
- return (ldeconf->rtr_id.s_addr);
+ static u_int32_t label = MPLS_LABEL_RESERVED_MAX;
+
+ /* XXX some checks needed */
+ label++;
+ return (htonl(label << MPLS_LABEL_OFFSET));
}
void
@@ -436,11 +435,11 @@ lde_send_insert_klabel(struct rt_node *r)
struct kroute kr;
bzero(&kr, sizeof(kr));
- kr.prefix.s_addr = r->prefix.s_addr;
+ 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.prefixlen = r->prefixlen;
imsg_compose_event(iev_main, IMSG_KLABEL_INSERT, 0, 0, -1,
&kr, sizeof(kr));
@@ -452,11 +451,11 @@ lde_send_change_klabel(struct rt_node *r)
struct kroute kr;
bzero(&kr, sizeof(kr));
- kr.prefix.s_addr = r->prefix.s_addr;
+ 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.prefixlen = r->prefixlen;
imsg_compose_event(iev_main, IMSG_KLABEL_CHANGE, 0, 0, -1,
&kr, sizeof(kr));
@@ -468,8 +467,8 @@ lde_send_delete_klabel(struct rt_node *r)
struct kroute kr;
bzero(&kr, sizeof(kr));
- kr.prefix.s_addr = r->prefix.s_addr;
- kr.prefixlen = r->prefixlen;
+ kr.prefix.s_addr = r->fec.prefix.s_addr;
+ kr.prefixlen = r->fec.prefixlen;
imsg_compose_event(iev_main, IMSG_KLABEL_DELETE, 0, 0, -1,
&kr, sizeof(kr));
@@ -519,61 +518,34 @@ lde_send_notification(u_int32_t peerid, u_int32_t code, u_int32_t msgid,
-1, &nm, sizeof(nm));
}
-LIST_HEAD(lde_nbr_head, lde_nbr);
-
-struct nbr_table {
- struct lde_nbr_head *hashtbl;
- u_int32_t hashmask;
-} ldenbrtable;
-
-#define LDE_NBR_HASH(x) \
- &ldenbrtable.hashtbl[(x) & ldenbrtable.hashmask]
-
-void
-lde_nbr_init(u_int32_t hashsize)
-{
- u_int32_t hs, i;
-
- for (hs = 1; hs < hashsize; hs <<= 1)
- ;
- ldenbrtable.hashtbl = calloc(hs, sizeof(struct lde_nbr_head));
- if (ldenbrtable.hashtbl == NULL)
- fatal("lde_nbr_init");
+static __inline int lde_nbr_compare(struct lde_nbr *, struct lde_nbr *);
- for (i = 0; i < hs; i++)
- LIST_INIT(&ldenbrtable.hashtbl[i]);
+RB_HEAD(nbr_tree, lde_nbr);
+RB_PROTOTYPE(nbr_tree, lde_nbr, entry, lde_nbr_compare)
+RB_GENERATE(nbr_tree, lde_nbr, entry, lde_nbr_compare)
- ldenbrtable.hashmask = hs - 1;
-}
+struct nbr_tree lde_nbrs = RB_INITIALIZER(&lde_nbrs);
-void
-lde_nbr_free(void)
+static __inline int
+lde_nbr_compare(struct lde_nbr *a, struct lde_nbr *b)
{
- free(ldenbrtable.hashtbl);
+ return (a->peerid - b->peerid);
}
struct lde_nbr *
lde_nbr_find(u_int32_t peerid)
{
- struct lde_nbr_head *head;
- struct lde_nbr *nbr;
+ struct lde_nbr n;
- head = LDE_NBR_HASH(peerid);
+ n.peerid = peerid;
- LIST_FOREACH(nbr, head, hash) {
- if (nbr->peerid == peerid)
- return (nbr);
- }
-
- return (NULL);
+ return (RB_FIND(nbr_tree, &lde_nbrs, &n));
}
struct lde_nbr *
lde_nbr_new(u_int32_t peerid, struct lde_nbr *new)
{
- struct lde_nbr_head *head;
- struct lde_nbr *nbr;
- struct iface *iface;
+ struct lde_nbr *nbr;
if (lde_nbr_find(peerid))
return (NULL);
@@ -583,22 +555,16 @@ lde_nbr_new(u_int32_t peerid, struct lde_nbr *new)
memcpy(nbr, new, sizeof(*nbr));
nbr->peerid = peerid;
+ fec_init(&nbr->recv_map);
+ fec_init(&nbr->sent_map);
+ fec_init(&nbr->recv_req);
+ fec_init(&nbr->sent_req);
+ fec_init(&nbr->sent_wdraw);
TAILQ_INIT(&nbr->addr_list);
- TAILQ_INIT(&nbr->req_list);
- TAILQ_INIT(&nbr->sent_map_list);
- TAILQ_INIT(&nbr->recv_map_list);
- TAILQ_INIT(&nbr->labels_list);
- head = LDE_NBR_HASH(peerid);
- LIST_INSERT_HEAD(head, nbr, hash);
-
- LIST_FOREACH(iface, &ldeconf->iface_list, entry) {
- if (iface->ifindex == new->ifindex) {
- LIST_INSERT_HEAD(&iface->lde_nbr_list, nbr, entry);
- break;
- }
- }
+ if (RB_INSERT(nbr_tree, &lde_nbrs, nbr) != NULL)
+ fatalx("lde_nbr_new: RB_INSERT failed");
return (nbr);
}
@@ -609,17 +575,98 @@ lde_nbr_del(struct lde_nbr *nbr)
if (nbr == NULL)
return;
- lde_req_list_free(nbr);
- lde_map_list_free(nbr);
lde_address_list_free(nbr);
- lde_label_list_free(nbr);
- LIST_REMOVE(nbr, hash);
- LIST_REMOVE(nbr, entry);
+ fec_clear(&nbr->recv_map, lde_map_free);
+ fec_clear(&nbr->sent_map, lde_map_free);
+ fec_clear(&nbr->recv_req, free);
+ fec_clear(&nbr->sent_req, free);
+ fec_clear(&nbr->sent_wdraw, free);
+
+ RB_REMOVE(nbr_tree, &lde_nbrs, nbr);
free(nbr);
}
+void
+lde_nbr_clear(void)
+{
+ struct lde_nbr *nbr;
+
+ while ((nbr = RB_ROOT(&lde_nbrs)) != NULL)
+ lde_nbr_del(nbr);
+}
+
+void
+lde_nbr_do_mappings(struct rt_node *rn)
+{
+ struct lde_nbr *ln;
+ struct lde_map *lm;
+ struct lde_req *lr;
+ struct map map;
+
+ map.label = (ntohl(rn->local_label) & MPLS_LABEL_MASK) >>
+ MPLS_LABEL_OFFSET;
+ map.prefix = rn->fec.prefix.s_addr;
+ map.prefixlen = rn->fec.prefixlen;
+
+ RB_FOREACH(ln, nbr_tree, &lde_nbrs) {
+ /* Did we already send a mapping to this peer? */
+ lm = (struct lde_map *)fec_find(&ln->sent_map, &rn->fec);
+ if (lm && lm->label == map.label)
+ /* same mapping already sent, skip */
+ continue;
+
+ /* Is this from a pending request? */
+ lr = (struct lde_req *)fec_find(&ln->recv_req, &rn->fec);
+ if (ldeconf->mode & MODE_ADV_ONDEMAND && lr == NULL)
+ /* adv. on demand but no req pending, skip */
+ continue;
+
+ 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 */
+ continue;
+ }
+
+ if (lr) {
+ /* set label request msg id in the mapping response. */
+ map.requestid = lr->msgid;
+ map.flags = F_MAP_REQ_ID;
+ fec_remove(&ln->sent_req, &lr->fec);
+ }
+
+ if (lm == NULL) {
+ lm = calloc(1, sizeof(*lm));
+ if (lm == NULL)
+ fatal("lde_nbr_do_mappings");
+ lm->fec = rn->fec;
+ lm->nexthop = ln;
+
+ LIST_INSERT_HEAD(&rn->upstream, lm, entry);
+ if (fec_insert(&ln->sent_map, &lm->fec))
+ log_warnx("failed to add %s/%u to sent map",
+ inet_ntoa(lm->fec.prefix),
+ lm->fec.prefixlen);
+ }
+ lm->label = map.label;
+
+ lde_send_labelmapping(ln->peerid, &map);
+ }
+}
+
+void
+lde_map_free(void *ptr)
+{
+ struct lde_map *map = ptr;
+
+ LIST_REMOVE(map, entry);
+ free(map);
+}
+
int
lde_address_add(struct lde_nbr *lr, struct in_addr *addr)
{
@@ -682,44 +729,14 @@ lde_address_list_free(struct lde_nbr *nbr)
}
}
-void
-lde_req_list_free(struct lde_nbr *nbr)
-{
- struct lde_req_entry *req;
-
- while ((req = TAILQ_FIRST(&nbr->req_list)) != NULL) {
- TAILQ_REMOVE(&nbr->req_list, req, entry);
- free(req);
- }
-}
-
-void
-lde_map_list_free(struct lde_nbr *nbr)
-{
- struct lde_map_entry *map;
-
- while ((map = TAILQ_FIRST(&nbr->recv_map_list)) != NULL) {
- TAILQ_REMOVE(&nbr->recv_map_list, map, entry);
- free(map);
- }
-
- while ((map = TAILQ_FIRST(&nbr->sent_map_list)) != NULL) {
- TAILQ_REMOVE(&nbr->sent_map_list, map, entry);
- free(map);
- }
-}
-
struct lde_nbr *
lde_find_address(struct in_addr address)
{
- struct iface *iface;
struct lde_nbr *ln;
- LIST_FOREACH(iface, &ldeconf->iface_list, entry) {
- LIST_FOREACH(ln, &iface->lde_nbr_list, entry) {
- if (lde_address_find(ln, &address) != NULL)
- return (ln);
- }
+ RB_FOREACH(ln, nbr_tree, &lde_nbrs) {
+ if (lde_address_find(ln, &address) != NULL)
+ return (ln);
}
return (NULL);
diff --git a/usr.sbin/ldpd/lde.h b/usr.sbin/ldpd/lde.h
index 331df88872b..aaa15ec4ef8 100644
--- a/usr.sbin/ldpd/lde.h
+++ b/usr.sbin/ldpd/lde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: lde.h,v 1.10 2010/05/25 13:29:45 claudio Exp $ */
+/* $OpenBSD: lde.h,v 1.11 2010/06/02 11:56:29 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -26,19 +26,30 @@
#include <event.h>
#include <limits.h>
-/* Label mapping request pending */
-struct lde_req_entry {
- TAILQ_ENTRY(lde_req_entry) entry;
- struct in_addr prefix;
- u_int8_t prefixlen;
+RB_HEAD(fec_tree, fec);
+
+struct fec {
+ RB_ENTRY(fec) entry;
+ struct in_addr prefix;
+ u_int8_t prefixlen;
};
-/* Label mapping message sent */
-struct lde_map_entry {
- TAILQ_ENTRY(lde_map_entry) entry;
- struct in_addr prefix;
- u_int32_t label;
- u_int8_t prefixlen;
+/*
+ * fec tree of pending label request
+ * Note: currently only one outstanding request per FEC can be tracked but
+ * should not be a problem since ldpd does not support multipath for now.
+ */
+struct lde_req {
+ struct fec fec;
+ u_int32_t msgid;
+};
+
+/* mapping entries */
+struct lde_map {
+ struct fec fec;
+ LIST_ENTRY(lde_map) entry;
+ struct lde_nbr *nexthop;
+ u_int32_t label;
};
/* Addresses belonging to neighbor */
@@ -49,14 +60,15 @@ struct lde_nbr_address {
/* just the info LDE needs */
struct lde_nbr {
- LIST_ENTRY(lde_nbr) hash, entry;
+ RB_ENTRY(lde_nbr) entry;
struct in_addr id;
- TAILQ_HEAD(, lde_req_entry) req_list;
- TAILQ_HEAD(, lde_map_entry) recv_map_list;
- TAILQ_HEAD(, lde_map_entry) sent_map_list;
+ struct fec_tree recv_req;
+ struct fec_tree sent_req;
+ struct fec_tree recv_map;
+ struct fec_tree sent_map;
+ struct fec_tree sent_wdraw;
TAILQ_HEAD(, lde_nbr_address) addr_list;
- TAILQ_HEAD(, rt_label) labels_list;
u_int32_t peerid;
unsigned int ifindex;
@@ -65,27 +77,17 @@ struct lde_nbr {
u_int16_t lspace;
};
-struct rt_node;
-
-struct rt_label {
- TAILQ_ENTRY(rt_label) node_l, nbr_l;
- struct lde_nbr *nexthop;
- struct rt_node *node;
- u_int32_t label;
-};
-
struct rt_node {
- RB_ENTRY(rt_node) entry;
- TAILQ_HEAD(, rt_label) labels_list;
- struct in_addr prefix;
+ struct fec fec;
struct in_addr nexthop;
+ LIST_HEAD(, lde_map) upstream; /* recv mappings */
+ LIST_HEAD(, lde_map) downstream; /* sent mappings */
+
u_int32_t local_label;
u_int32_t remote_label;
-
u_int16_t lspace;
u_int8_t flags;
- u_int8_t prefixlen;
u_int8_t invalid;
u_int8_t present; /* Is it present in fib? */
};
@@ -93,7 +95,7 @@ struct rt_node {
/* 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_router_id(void);
+u_int32_t lde_assign_label(void);
void lde_send_insert_klabel(struct rt_node *);
void lde_send_change_klabel(struct rt_node *);
void lde_send_delete_klabel(struct rt_node *);
@@ -104,6 +106,7 @@ void lde_send_notification(u_int32_t, 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_nbr *lde_find_address(struct in_addr);
@@ -112,17 +115,17 @@ struct lde_nbr_address *lde_address_find(struct lde_nbr *, struct in_addr *);
int lde_address_del(struct lde_nbr *, struct in_addr *);
/* lde_lib.c */
-void rt_init(void);
-int rt_compare(struct rt_node *, struct rt_node *);
-int rt_insert(struct rt_node *);
-int rt_remove(struct rt_node *);
-struct rt_node *rt_find(in_addr_t, u_int8_t);
-void rt_clear(void);
-void route_reset_timers(struct rt_node *);
-int route_start_timeout(struct rt_node *);
-void route_start_garbage(struct rt_node *);
+void fec_init(struct fec_tree *);
+int fec_insert(struct fec_tree *, struct fec *);
+int fec_remove(struct fec_tree *, struct fec *);
+struct fec *fec_find_prefix(struct fec_tree *, in_addr_t, u_int8_t);
+struct fec *fec_find(struct fec_tree *, struct fec *);
+void fec_clear(struct fec_tree *, void (*)(void *));
+
void rt_dump(pid_t);
void rt_snap(u_int32_t);
+void rt_clear(void);
+
void lde_kernel_insert(struct kroute *);
void lde_kernel_remove(struct kroute *);
void lde_check_mapping(struct map *, struct lde_nbr *);
diff --git a/usr.sbin/ldpd/lde_lib.c b/usr.sbin/ldpd/lde_lib.c
index c10d42cf520..032ab63694b 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.18 2010/05/25 09:31:25 claudio Exp $ */
+/* $OpenBSD: lde_lib.c,v 1.19 2010/06/02 11:56:29 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -20,11 +20,11 @@
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
#include <net/if.h>
#include <net/if_types.h>
+#include <netinet/in.h>
#include <netmpls/mpls.h>
+#include <arpa/inet.h>
#include <ctype.h>
#include <err.h>
#include <stdio.h>
@@ -38,22 +38,24 @@
#include "log.h"
#include "lde.h"
+static int fec_compare(struct fec *, struct fec *);
+
+RB_PROTOTYPE(fec_tree, fec, entry, fec_compare)
+RB_GENERATE(fec_tree, fec, entry, fec_compare)
+
extern struct ldpd_conf *ldeconf;
-RB_HEAD(rt_tree, rt_node) rt;
-RB_PROTOTYPE(rt_tree, rt_node, entry, rt_compare)
-RB_GENERATE(rt_tree, rt_node, entry, rt_compare)
-u_int32_t lde_assign_label(void);
+struct fec_tree rt = RB_INITIALIZER(&rt);
-/* route table */
+/* FEC tree fucntions */
void
-rt_init(void)
+fec_init(struct fec_tree *fh)
{
- RB_INIT(&rt);
+ RB_INIT(fh);
}
-int
-rt_compare(struct rt_node *a, struct rt_node *b)
+static int
+fec_compare(struct fec *a, struct fec *b)
{
if (ntohl(a->prefix.s_addr) < ntohl(b->prefix.s_addr))
return (-1);
@@ -67,52 +69,66 @@ rt_compare(struct rt_node *a, struct rt_node *b)
return (0);
}
-struct rt_node *
-rt_find(in_addr_t prefix, u_int8_t prefixlen)
+struct fec *
+fec_find_prefix(struct fec_tree *fh, in_addr_t prefix, u_int8_t prefixlen)
{
- struct rt_node s;
+ struct fec s;
s.prefix.s_addr = prefix;
s.prefixlen = prefixlen;
- return (RB_FIND(rt_tree, &rt, &s));
+ return (fec_find(fh, &s));
}
+struct fec *
+fec_find(struct fec_tree *fh, struct fec *f)
+{
+ return (RB_FIND(fec_tree, fh, f));
+}
+
+
int
-rt_insert(struct rt_node *r)
+fec_insert(struct fec_tree *fh, struct fec *f)
{
- if (RB_INSERT(rt_tree, &rt, r) != NULL) {
- log_warnx("rt_insert failed for %s/%u",
- inet_ntoa(r->prefix), r->prefixlen);
- free(r);
+ if (RB_INSERT(fec_tree, fh, f) != NULL)
return (-1);
- }
-
return (0);
}
int
-rt_remove(struct rt_node *r)
+fec_remove(struct fec_tree *fh, struct fec *f)
{
- if (RB_REMOVE(rt_tree, &rt, r) == NULL) {
- log_warnx("rt_remove failed for %s/%u",
- inet_ntoa(r->prefix), r->prefixlen);
+ if (RB_REMOVE(fec_tree, fh, f) == NULL) {
+ log_warnx("fec_remove failed for %s/%u",
+ inet_ntoa(f->prefix), f->prefixlen);
return (-1);
}
-
- free(r);
return (0);
}
void
+fec_clear(struct fec_tree *fh, void (*free_cb)(void *))
+{
+ struct fec *f;
+
+ while ((f = RB_ROOT(fh)) != NULL) {
+ fec_remove(fh, f);
+ free_cb(f);
+ }
+}
+
+
+void
rt_dump(pid_t pid)
{
+ struct fec *f;
struct rt_node *r;
static struct ctl_rt rtctl;
- RB_FOREACH(r, rt_tree, &rt) {
- rtctl.prefix.s_addr = r->prefix.s_addr;
- rtctl.prefixlen = r->prefixlen;
+ 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;
@@ -136,14 +152,15 @@ rt_dump(pid_t pid)
void
rt_snap(u_int32_t peerid)
{
+ struct fec *f;
struct rt_node *r;
struct map map;
bzero(&map, sizeof(map));
-
- RB_FOREACH(r, rt_tree, &rt) {
- map.prefix = r->prefix.s_addr;
- map.prefixlen = r->prefixlen;
+ RB_FOREACH(f, fec_tree, &rt) {
+ r = (struct rt_node *)f;
+ map.prefix = r->fec.prefix.s_addr;
+ map.prefixlen = r->fec.prefixlen;
map.label = (ntohl(r->local_label) & MPLS_LABEL_MASK) >>
MPLS_LABEL_OFFSET;
@@ -155,45 +172,33 @@ rt_snap(u_int32_t peerid)
void
rt_clear(void)
{
- struct rt_node *r;
-
- while ((r = RB_MIN(rt_tree, &rt)) != NULL)
- rt_remove(r);
-}
-
-u_int32_t
-lde_assign_label()
-{
- static u_int32_t label = MPLS_LABEL_RESERVED_MAX;
-
- /* XXX some checks needed */
- label++;
- return (htonl(label << MPLS_LABEL_OFFSET));
+ fec_clear(&rt, free);
}
void
lde_kernel_insert(struct kroute *kr)
{
struct rt_node *rn;
- struct rt_label *rl;
- struct iface *iface;
- struct lde_nbr *ln;
struct lde_nbr_address *addr;
- struct map localmap;
+ struct lde_map *map;
- rn = rt_find(kr->prefix.s_addr, kr->prefixlen);
+ 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->prefix.s_addr = kr->prefix.s_addr;
- rn->prefixlen = kr->prefixlen;
+ rn->fec.prefix.s_addr = kr->prefix.s_addr;
+ rn->fec.prefixlen = kr->prefixlen;
rn->remote_label = NO_LABEL;
rn->local_label = NO_LABEL;
- TAILQ_INIT(&rn->labels_list);
+ LIST_INIT(&rn->upstream);
+ LIST_INIT(&rn->downstream);
- rt_insert(rn);
+ 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) {
@@ -211,17 +216,18 @@ lde_kernel_insert(struct kroute *kr)
return;
}
- TAILQ_FOREACH(rl, &rn->labels_list, node_l) {
- addr = lde_address_find(rl->nexthop, &rn->nexthop);
+ LIST_FOREACH(map, &rn->downstream, entry) {
+ addr = lde_address_find(map->nexthop, &rn->nexthop);
if (addr != NULL) {
rn->remote_label =
- htonl(rl->label << MPLS_LABEL_OFFSET);
+ htonl(map->label << MPLS_LABEL_OFFSET);
break;
}
}
- log_debug("lde_kernel_insert: prefix %s, changing label to %u",
- inet_ntoa(rn->prefix), rl ? rl->label : 0);
+ 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;
@@ -232,15 +238,15 @@ lde_kernel_insert(struct kroute *kr)
/* There is static assigned label for this route, record it in lib */
if (kr->local_label != NO_LABEL) {
- rn->local_label = (htonl(kr->local_label) << MPLS_LABEL_OFFSET);
+ rn->local_label = htonl(kr->local_label << MPLS_LABEL_OFFSET);
return;
}
- TAILQ_FOREACH(rl, &rn->labels_list, node_l) {
- addr = lde_address_find(rl->nexthop, &rn->nexthop);
+ LIST_FOREACH(map, &rn->downstream, entry) {
+ addr = lde_address_find(map->nexthop, &rn->nexthop);
if (addr != NULL) {
rn->remote_label =
- htonl(rl->label << MPLS_LABEL_OFFSET);
+ htonl(map->label << MPLS_LABEL_OFFSET);
break;
}
}
@@ -258,52 +264,37 @@ lde_kernel_insert(struct kroute *kr)
lde_send_insert_klabel(rn);
/* Redistribute the current mapping to every nbr */
- localmap.label = (ntohl(rn->local_label) & MPLS_LABEL_MASK) >>
- MPLS_LABEL_OFFSET;
- localmap.prefix = rn->prefix.s_addr;
- localmap.prefixlen = rn->prefixlen;
-
- LIST_FOREACH(iface, &ldeconf->iface_list, entry) {
- LIST_FOREACH(ln, &iface->lde_nbr_list, entry) {
- if (ldeconf->mode & MODE_ADV_UNSOLICITED &&
- ldeconf->mode & MODE_DIST_INDEPENDENT)
- lde_send_labelmapping(ln->peerid, &localmap);
-
- if (ldeconf->mode & MODE_ADV_UNSOLICITED &&
- ldeconf->mode & MODE_DIST_ORDERED) {
- /* XXX */
- if (rn->nexthop.s_addr == INADDR_ANY ||
- rn->remote_label != NO_LABEL)
- lde_send_labelmapping(ln->peerid,
- &localmap);
- }
- }
- }
+ lde_nbr_do_mappings(rn);
}
void
lde_kernel_remove(struct kroute *kr)
{
struct rt_node *rn;
- struct rt_label *rl;
+ struct lde_map *map;
struct lde_nbr *ln;
- rn = rt_find(kr->prefix.s_addr, kr->prefixlen);
+ rn = (struct rt_node *)fec_find_prefix(&rt, kr->prefix.s_addr,
+ kr->prefixlen);
if (rn == NULL)
return;
if (ldeconf->mode & MODE_RET_LIBERAL) {
ln = lde_find_address(rn->nexthop);
if (ln) {
- rl = calloc(1, sizeof(*rl));
- if (rl == NULL)
+ map = calloc(1, sizeof(*map));
+ if (map == NULL)
fatal("lde_kernel_remove");
- rl->label = rn->remote_label;
- rl->node = rn;
- rl->nexthop = ln;
- TAILQ_INSERT_TAIL(&rn->labels_list, rl, node_l);
- TAILQ_INSERT_TAIL(&ln->labels_list, rl, nbr_l);
+ map->label = (ntohl(rn->remote_label) &
+ MPLS_LABEL_MASK) >> MPLS_LABEL_OFFSET;
+ 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);
}
}
@@ -316,17 +307,14 @@ void
lde_check_mapping(struct map *map, struct lde_nbr *ln)
{
struct rt_node *rn;
- struct rt_label *rl;
struct lde_nbr_address *addr;
- struct lde_map_entry *me, *menew;
- struct lde_req_entry *req;
- 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);
+ struct lde_map *me;
+
+ rn = (struct rt_node *)fec_find_prefix(&rt, map->prefix,
+ map->prefixlen);
if (rn == NULL) {
+ /* The route is not yet in fib. If we are in liberal mode
+ * create a route and record the label */
if (ldeconf->mode & MODE_RET_CONSERVATIVE)
return;
@@ -334,44 +322,58 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln)
if (rn == NULL)
fatal("lde_check_mapping");
- rn->prefix.s_addr = map->prefix;
- rn->prefixlen = map->prefixlen;
+ rn->fec.prefix.s_addr = map->prefix;
+ rn->fec.prefixlen = map->prefixlen;
rn->local_label = lde_assign_label();
rn->remote_label = NO_LABEL;
rn->present = 0;
- TAILQ_INIT(&rn->labels_list);
+ LIST_INIT(&rn->upstream);
+ LIST_INIT(&rn->downstream);
- rt_insert(rn);
+ if (fec_insert(&rt, &rn->fec))
+ log_warnx("failed to add %s/%u to rt tree",
+ inet_ntoa(rn->fec.prefix), rn->fec.prefixlen);
}
- TAILQ_FOREACH(me, &ln->recv_map_list, entry) {
- if (me->prefix.s_addr == map->prefix &&
- me->prefixlen == map->prefixlen) {
+ LIST_FOREACH(me, &rn->downstream, entry) {
+ if (ln == me->nexthop) {
if (me->label == map->label) {
+ /* Duplicate: RFC says to send back a release,
+ * even though we did not release the actual
+ * mapping. This is confusing.
+ */
lde_send_labelrelease(ln->peerid, map);
return;
}
+ /* old mapping that is now changed */
+ break;
}
}
addr = lde_address_find(ln, &rn->nexthop);
if (addr == NULL || !rn->present) {
+ /* 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);
+ }
+ me->label = map->label;
- rl = calloc(1, sizeof(*rl));
- if (rl == NULL)
- fatal("lde_check_mapping");
-
- rl->label = map->label;
- rl->node = rn;
- rl->nexthop = ln;
-
- TAILQ_INSERT_TAIL(&rn->labels_list, rl, node_l);
- TAILQ_INSERT_TAIL(&ln->labels_list, rl, nbr_l);
return;
}
@@ -382,87 +384,36 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln)
lde_send_change_klabel(rn);
/* Record the mapping from this peer */
- menew = calloc(1, sizeof(*menew));
- if (menew == NULL)
- fatal("lde_check_mapping");
-
- menew->prefix.s_addr = map->prefix;
- menew->prefixlen = map->prefixlen;
- menew->label = map->label;
-
- TAILQ_INSERT_HEAD(&ln->recv_map_list, menew, entry);
-
- /* Redistribute the current mapping to every nbr */
- localmap.label = rn->local_label;
- localmap.prefix = rn->prefix.s_addr;
- localmap.prefixlen = rn->prefixlen;
-
- LIST_FOREACH(iface, &ldeconf->iface_list, entry) {
- LIST_FOREACH(ln, &iface->lde_nbr_list, entry) {
- /* Did we already send a mapping to this peer? */
- TAILQ_FOREACH(me, &ln->sent_map_list, entry) {
- if (me->prefix.s_addr == rn->prefix.s_addr &&
- me->prefixlen == rn->prefixlen)
- break;
- }
- if (me != NULL) {
- /* XXX: check RAttributes */
- continue;
- }
-
- if (ldeconf->mode & MODE_ADV_UNSOLICITED &&
- ldeconf->mode & MODE_DIST_ORDERED) {
- lde_send_labelmapping(ln->peerid, &localmap);
-
- menew = calloc(1, sizeof(*menew));
- if (menew == NULL)
- fatal("lde_check_mapping");
-
- menew->prefix.s_addr = map->prefix;
- menew->prefixlen = map->prefixlen;
- menew->label = map->label;
-
- TAILQ_INSERT_HEAD(&ln->sent_map_list, menew,
- entry);
- }
-
- TAILQ_FOREACH(req, &ln->req_list, entry) {
- if (req->prefix.s_addr == rn->prefix.s_addr &&
- req->prefixlen == rn->prefixlen)
- break;
- }
- if (req != NULL) {
- lde_send_labelmapping(ln->peerid, &localmap);
-
- menew = calloc(1, sizeof(*menew));
- if (menew == NULL)
- fatal("lde_check_mapping");
-
- menew->prefix.s_addr = map->prefix;
- menew->prefixlen = map->prefixlen;
- menew->label = map->label;
-
- TAILQ_INSERT_HEAD(&ln->sent_map_list, menew,
- entry);
+ if (me == NULL) {
+ me = calloc(1, sizeof(*me));
+ if (me == NULL)
+ fatal("lde_check_mapping");
- TAILQ_REMOVE(&ln->req_list, req, entry);
- free(req);
- }
- }
+ 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);
}
+ me->label = map->label;
lde_send_change_klabel(rn);
+
+ /* Redistribute the current mapping to every nbr */
+ lde_nbr_do_mappings(rn);
}
void
lde_check_request(struct map *map, struct lde_nbr *ln)
{
- struct lde_req_entry *lre, *newlre;
- struct rt_node *rn;
- struct lde_nbr *lnn;
- struct map localmap;
+ struct lde_req *lre;
+ struct rt_node *rn;
+ struct lde_nbr *lnn;
+ struct map localmap;
- rn = rt_find(map->prefix, map->prefixlen);
+ rn = (struct rt_node *)fec_find_prefix(&rt, map->prefix,
+ map->prefixlen);
if (rn == NULL || rn->remote_label == NO_LABEL) {
lde_send_notification(ln->peerid, S_NO_ROUTE, map->messageid,
MSG_TYPE_LABELREQUEST);
@@ -475,14 +426,12 @@ lde_check_request(struct map *map, struct lde_nbr *ln)
return;
}
- TAILQ_FOREACH(lre, &ln->req_list, entry) {
- if (lre->prefix.s_addr == map->prefix &&
- lre->prefixlen == map->prefixlen)
- return;
- }
+ lre = (struct lde_req *)fec_find(&ln->recv_req, &rn->fec);
+ if (lre != NULL)
+ return;
- /* XXX: if we are egress ? */
- if (rn->remote_label != NO_LABEL) {
+ if (rn->nexthop.s_addr == INADDR_ANY ||
+ rn->remote_label != NO_LABEL) {
bzero(&localmap, sizeof(localmap));
localmap.prefix = map->prefix;
localmap.prefixlen = map->prefixlen;
@@ -492,18 +441,21 @@ lde_check_request(struct map *map, struct lde_nbr *ln)
} else {
lnn = lde_find_address(rn->nexthop);
if (lnn == NULL)
+ /* XXX this feels wrong.... */
return;
lde_send_labelrequest(lnn->peerid, map);
- newlre = calloc(1, sizeof(*newlre));
- if (newlre == NULL)
+ lre = calloc(1, sizeof(*lre));
+ if (lre == NULL)
fatal("lde_check_request");
- newlre->prefix.s_addr = map->prefix;
- newlre->prefixlen = map->prefixlen;
+ lre->fec = rn->fec;
+ lre->msgid = map->messageid;
- TAILQ_INSERT_HEAD(&ln->req_list, newlre, entry);
+ if (fec_insert(&ln->recv_req, &lre->fec))
+ log_warnx("failed to add %s/%u to recv req",
+ inet_ntoa(lre->fec.prefix), lre->fec.prefixlen);
}
}
@@ -511,17 +463,3 @@ void
lde_check_release(struct map *map, struct lde_nbr *ln)
{
}
-
-void
-lde_label_list_free(struct lde_nbr *nbr)
-{
- struct rt_label *rl;
-
- while ((rl = TAILQ_FIRST(&nbr->labels_list)) != NULL) {
- TAILQ_REMOVE(&nbr->labels_list, rl, nbr_l);
- TAILQ_REMOVE(&nbr->labels_list, rl, node_l);
- if (TAILQ_EMPTY(&rl->node->labels_list))
- rt_remove(rl->node);
- free(rl);
- }
-}