summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichele Marchetto <michele@cvs.openbsd.org>2008-12-02 13:42:45 +0000
committerMichele Marchetto <michele@cvs.openbsd.org>2008-12-02 13:42:45 +0000
commiteb623989fbafae8f3d155313d2eeb80dacc8341b (patch)
tree355f00c02f98436a935d418b15a0832d7415ed16
parent4914f64e7a7e2b8113b5852684c7213e356cef80 (diff)
Initial support for neighbor expiry.
When a nbr goes down delete it from the lists of downstream dependent neighbors. OK norby@
-rw-r--r--usr.sbin/dvmrpd/dvmrpd.h4
-rw-r--r--usr.sbin/dvmrpd/neighbor.c10
-rw-r--r--usr.sbin/dvmrpd/rde.c117
-rw-r--r--usr.sbin/dvmrpd/rde.h13
-rw-r--r--usr.sbin/dvmrpd/rde_srt.c20
5 files changed, 159 insertions, 5 deletions
diff --git a/usr.sbin/dvmrpd/dvmrpd.h b/usr.sbin/dvmrpd/dvmrpd.h
index b271d198112..d8f107b9825 100644
--- a/usr.sbin/dvmrpd/dvmrpd.h
+++ b/usr.sbin/dvmrpd/dvmrpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dvmrpd.h,v 1.9 2008/11/21 10:39:32 michele Exp $ */
+/* $OpenBSD: dvmrpd.h,v 1.10 2008/12/02 13:42:44 michele Exp $ */
/*
* Copyright (c) 2004, 2005, 2006 Esben Norby <norby@openbsd.org>
@@ -109,6 +109,8 @@ enum imsg_type {
IMSG_FULL_ROUTE_REPORT_END,
IMSG_MFC_ADD,
IMSG_MFC_DEL,
+ IMSG_NEIGHBOR_UP,
+ IMSG_NEIGHBOR_DOWN,
IMSG_FLASH_UPDATE,
IMSG_FLASH_UPDATE_DS
};
diff --git a/usr.sbin/dvmrpd/neighbor.c b/usr.sbin/dvmrpd/neighbor.c
index 3f27c507a1b..c92f67c48c7 100644
--- a/usr.sbin/dvmrpd/neighbor.c
+++ b/usr.sbin/dvmrpd/neighbor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: neighbor.c,v 1.3 2006/11/10 11:09:56 michele Exp $ */
+/* $OpenBSD: neighbor.c,v 1.4 2008/12/02 13:42:44 michele Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -189,6 +189,7 @@ nbr_new(u_int32_t nbr_id, struct iface *iface, int self)
{
struct nbr_head *head;
struct nbr *nbr = NULL;
+ struct rde_nbr rn;
if ((nbr = calloc(1, sizeof(*nbr))) == NULL)
fatal("nbr_new");
@@ -212,6 +213,11 @@ nbr_new(u_int32_t nbr_id, struct iface *iface, int self)
/* set event structures */
evtimer_set(&nbr->inactivity_timer, nbr_itimer, nbr);
+ bzero(&rn, sizeof(rn));
+ rn.iface = iface;
+ dvmrpe_imsg_compose_rde(IMSG_NEIGHBOR_UP, nbr->peerid, 0, &rn,
+ sizeof(rn));
+
log_debug("nbr_new: neighbor ID %s, peerid %lu",
inet_ntoa(nbr->id), nbr->peerid);
@@ -224,6 +230,8 @@ nbr_del(struct nbr *nbr)
log_debug("nbr_del: neighbor ID %s, peerid %lu", inet_ntoa(nbr->id),
nbr->peerid);
+ dvmrpe_imsg_compose_rde(IMSG_NEIGHBOR_DOWN, nbr->peerid, 0, NULL, 0);
+
/* clear lists */
rr_list_clr(&nbr->rr_list);
diff --git a/usr.sbin/dvmrpd/rde.c b/usr.sbin/dvmrpd/rde.c
index af3823f9753..b1e3e9071a7 100644
--- a/usr.sbin/dvmrpd/rde.c
+++ b/usr.sbin/dvmrpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.5 2007/03/21 19:33:48 michele Exp $ */
+/* $OpenBSD: rde.c,v 1.6 2008/12/02 13:42:44 michele Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -39,12 +39,19 @@
#include "log.h"
#include "rde.h"
+void rde_nbr_init(u_int32_t);
+void rde_nbr_free(void);
+struct rde_nbr *rde_nbr_find(u_int32_t);
+struct rde_nbr *rde_nbr_new(u_int32_t, struct rde_nbr *);
+void rde_nbr_del(struct rde_nbr *);
+
void rde_sig_handler(int sig, short, void *);
void rde_shutdown(void);
void rde_dispatch_imsg(int, short, void *);
volatile sig_atomic_t rde_quit = 0;
struct dvmrpd_conf *rdeconf = NULL;
+struct rde_nbr *nbrself;
struct imsgbuf *ibuf_dvmrpe;
struct imsgbuf *ibuf_main;
@@ -104,6 +111,7 @@ rde(struct dvmrpd_conf *xconf, int pipe_parent2rde[2], int pipe_dvmrpe2rde[2],
endpwent();
event_init();
+ rde_nbr_init(NBR_HASHSIZE);
/* setup signal handler */
signal_set(&ev_sigint, SIGINT, rde_sig_handler, NULL);
@@ -189,6 +197,7 @@ rde_dispatch_imsg(int fd, short event, void *bula)
struct imsgbuf *ibuf = bula;
struct imsg imsg;
struct route_report rr;
+ struct rde_nbr rn;
int i, n, connected = 0;
struct iface *iface;
@@ -267,6 +276,19 @@ rde_dispatch_imsg(int fd, short event, void *bula)
mfc_delete(&mfc);
#endif
break;
+ case IMSG_NEIGHBOR_UP:
+ if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(rn))
+ fatalx("invalid size of OE request");
+ memcpy(&rn, imsg.data, sizeof(rn));
+
+ if (rde_nbr_find(imsg.hdr.peerid));
+ fatalx("rde_rispatch_imsg: "
+ "neighbor already exists");
+ rde_nbr_new(imsg.hdr.peerid, &rn);
+ break;
+ case IMSG_NEIGHBOR_DOWN:
+ rde_nbr_del(rde_nbr_find(imsg.hdr.peerid));
+ break;
default:
log_debug("rde_dispatch_msg: unexpected imsg %d",
imsg.hdr.type);
@@ -276,3 +298,96 @@ rde_dispatch_imsg(int fd, short event, void *bula)
}
imsg_event_add(ibuf);
}
+
+LIST_HEAD(rde_nbr_head, rde_nbr);
+
+struct nbr_table {
+ struct rde_nbr_head *hashtbl;
+ u_int32_t hashmask;
+} rdenbrtable;
+
+#define RDE_NBR_HASH(x) \
+ &rdenbrtable.hashtbl[(x) & rdenbrtable.hashmask]
+
+void
+rde_nbr_init(u_int32_t hashsize)
+{
+ struct rde_nbr_head *head;
+ u_int32_t hs, i;
+
+ for (hs = 1; hs < hashsize; hs <<= 1)
+ ;
+ rdenbrtable.hashtbl = calloc(hs, sizeof(struct rde_nbr_head));
+ if (rdenbrtable.hashtbl == NULL)
+ fatal("rde_nbr_init");
+
+ for (i = 0; i < hs; i++)
+ LIST_INIT(&rdenbrtable.hashtbl[i]);
+
+ rdenbrtable.hashmask = hs - 1;
+
+ if ((nbrself = calloc(1, sizeof(*nbrself))) == NULL)
+ fatal("rde_nbr_init");
+
+ nbrself->peerid = NBR_IDSELF;
+ head = RDE_NBR_HASH(NBR_IDSELF);
+ LIST_INSERT_HEAD(head, nbrself, hash);
+}
+
+void
+rde_nbr_free(void)
+{
+ free(nbrself);
+ free(rdenbrtable.hashtbl);
+}
+
+struct rde_nbr *
+rde_nbr_find(u_int32_t peerid)
+{
+ struct rde_nbr_head *head;
+ struct rde_nbr *nbr;
+
+ head = RDE_NBR_HASH(peerid);
+
+ LIST_FOREACH(nbr, head, hash) {
+ if (nbr->peerid == peerid)
+ return (nbr);
+ }
+
+ return (NULL);
+}
+
+struct rde_nbr *
+rde_nbr_new(u_int32_t peerid, struct rde_nbr *new)
+{
+ struct rde_nbr_head *head;
+ struct rde_nbr *nbr;
+
+ if (rde_nbr_find(peerid))
+ return (NULL);
+
+ if ((nbr = calloc(1, sizeof(*nbr))) == NULL)
+ fatal("rde_nbr_new");
+
+ memcpy(nbr, new, sizeof(*nbr));
+ nbr->peerid = peerid;
+
+ head = RDE_NBR_HASH(peerid);
+ LIST_INSERT_HEAD(head, nbr, hash);
+
+ return (nbr);
+}
+
+void
+rde_nbr_del(struct rde_nbr *nbr)
+{
+ if (nbr == NULL)
+ return;
+
+ srt_expire_nbr(nbr->addr, nbr->iface);
+
+ LIST_REMOVE(nbr, entry);
+ LIST_REMOVE(nbr, hash);
+
+ free(nbr);
+}
diff --git a/usr.sbin/dvmrpd/rde.h b/usr.sbin/dvmrpd/rde.h
index ca81f395e0d..e47a6d2cc4a 100644
--- a/usr.sbin/dvmrpd/rde.h
+++ b/usr.sbin/dvmrpd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.5 2008/11/24 21:55:52 michele Exp $ */
+/* $OpenBSD: rde.h,v 1.6 2008/12/02 13:42:44 michele Exp $ */
/*
* Copyright (c) 2005, 2006 Esben Norby <norby@openbsd.org>
@@ -53,6 +53,15 @@ struct mfc_node {
time_t uptime;
};
+/* just the infos rde needs */
+struct rde_nbr {
+ LIST_ENTRY(rde_nbr) entry, hash;
+ struct in_addr addr;
+ u_int32_t peerid;
+
+ struct iface *iface;
+};
+
struct ds {
LIST_ENTRY(ds) entry;
struct in_addr addr;
@@ -103,6 +112,8 @@ void rt_dump(pid_t);
int srt_check_route(struct route_report *, int);
int src_compare(struct src_node *, struct src_node *);
+void srt_expire_nbr(struct in_addr, struct iface *);
+
RB_PROTOTYPE(src_head, src_node, entry, src_compare);
#endif /* _RDE_H_ */
diff --git a/usr.sbin/dvmrpd/rde_srt.c b/usr.sbin/dvmrpd/rde_srt.c
index 9ccf3d81517..73ec6483ff1 100644
--- a/usr.sbin/dvmrpd/rde_srt.c
+++ b/usr.sbin/dvmrpd/rde_srt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_srt.c,v 1.10 2008/11/24 21:55:52 michele Exp $ */
+/* $OpenBSD: rde_srt.c,v 1.11 2008/12/02 13:42:44 michele Exp $ */
/*
* Copyright (c) 2005, 2006 Esben Norby <norby@openbsd.org>
@@ -606,6 +606,24 @@ srt_delete_src(struct src_node *src_node)
}
void
+srt_expire_nbr(struct in_addr addr, struct iface *iface)
+{
+ struct src_node *src_node;
+ struct ds *ds;
+ struct rt_node *rn;
+
+ RB_FOREACH(src_node, src_head, &rdeconf->src_list) {
+ rn = rt_find(src_node->origin.s_addr,
+ mask2prefixlen(src_node->mask.s_addr));
+ if (rn == NULL)
+ fatalx("srt_expires_nbr: route not found");
+ ds = srt_find_ds(src_node, addr.s_addr);
+ if (ds)
+ srt_delete_ds(src_node, rn, ds, iface);
+ }
+}
+
+void
flash_update(struct rt_node *rn) {
struct route_report rr;