diff options
author | Michele Marchetto <michele@cvs.openbsd.org> | 2008-12-02 13:42:45 +0000 |
---|---|---|
committer | Michele Marchetto <michele@cvs.openbsd.org> | 2008-12-02 13:42:45 +0000 |
commit | eb623989fbafae8f3d155313d2eeb80dacc8341b (patch) | |
tree | 355f00c02f98436a935d418b15a0832d7415ed16 | |
parent | 4914f64e7a7e2b8113b5852684c7213e356cef80 (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.h | 4 | ||||
-rw-r--r-- | usr.sbin/dvmrpd/neighbor.c | 10 | ||||
-rw-r--r-- | usr.sbin/dvmrpd/rde.c | 117 | ||||
-rw-r--r-- | usr.sbin/dvmrpd/rde.h | 13 | ||||
-rw-r--r-- | usr.sbin/dvmrpd/rde_srt.c | 20 |
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; |