diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2011-05-09 12:24:42 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2011-05-09 12:24:42 +0000 |
commit | 08c8c3142242232ca8fa5aeb3352c133eb14d443 (patch) | |
tree | 88209eef012cc4e7dbf723b6382b64855fd095e9 | |
parent | 08721b49de139b3b1cfb3053c615667213e3f774 (diff) |
First bits to support opaque LSA. Type-9, 10 and 11 are LSA that can
hold about any data you like and is used for things like greaceful
reload. Implement the basic redistribute logic and LSDB handling but
the data sent is currently not looked at.
Tested and OK sthen@
-rw-r--r-- | usr.sbin/ospfd/control.c | 3 | ||||
-rw-r--r-- | usr.sbin/ospfd/database.c | 12 | ||||
-rw-r--r-- | usr.sbin/ospfd/interface.c | 3 | ||||
-rw-r--r-- | usr.sbin/ospfd/neighbor.c | 7 | ||||
-rw-r--r-- | usr.sbin/ospfd/ospf.h | 20 | ||||
-rw-r--r-- | usr.sbin/ospfd/ospfd.h | 6 | ||||
-rw-r--r-- | usr.sbin/ospfd/ospfe.c | 11 | ||||
-rw-r--r-- | usr.sbin/ospfd/ospfe.h | 3 | ||||
-rw-r--r-- | usr.sbin/ospfd/rde.c | 68 | ||||
-rw-r--r-- | usr.sbin/ospfd/rde.h | 13 | ||||
-rw-r--r-- | usr.sbin/ospfd/rde_lsdb.c | 131 | ||||
-rw-r--r-- | usr.sbin/ospfd/rde_spf.c | 12 |
12 files changed, 213 insertions, 76 deletions
diff --git a/usr.sbin/ospfd/control.c b/usr.sbin/ospfd/control.c index 0012c9ebd40..44157b5f659 100644 --- a/usr.sbin/ospfd/control.c +++ b/usr.sbin/ospfd/control.c @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.34 2010/09/02 14:03:22 sobrado Exp $ */ +/* $OpenBSD: control.c,v 1.35 2011/05/09 12:24:41 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -253,6 +253,7 @@ control_dispatch_imsg(int fd, short event, void *bula) case IMSG_CTL_SHOW_DB_SELF: case IMSG_CTL_SHOW_DB_SUM: case IMSG_CTL_SHOW_DB_ASBR: + case IMSG_CTL_SHOW_DB_OPAQ: case IMSG_CTL_SHOW_RIB: case IMSG_CTL_SHOW_SUM: c->iev.ibuf.pid = imsg.hdr.pid; diff --git a/usr.sbin/ospfd/database.c b/usr.sbin/ospfd/database.c index f3641c31f6d..80f5e0cede0 100644 --- a/usr.sbin/ospfd/database.c +++ b/usr.sbin/ospfd/database.c @@ -1,4 +1,4 @@ -/* $OpenBSD: database.c,v 1.28 2011/03/04 09:24:46 claudio Exp $ */ +/* $OpenBSD: database.c,v 1.29 2011/05/09 12:24:41 claudio Exp $ */ /* * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> @@ -138,7 +138,8 @@ send_db_description(struct nbr *nbr) fatalx("send_db_description: unknown interface type"); } - dd_hdr.opts = area_ospf_options(nbr->iface->area); + /* XXX button or not for opaque LSA? */ + dd_hdr.opts = area_ospf_options(nbr->iface->area) | OSPF_OPTION_O; dd_hdr.bits = bits; dd_hdr.dd_seq_num = htonl(nbr->dd_seq_num); @@ -211,6 +212,13 @@ recv_db_description(struct nbr *nbr, char *buf, u_int16_t len) case NBR_STA_XSTRT: if (dupe) return; + nbr->capa_options = dd_hdr.opts; + if ((nbr->capa_options & nbr->options) != nbr->options) { + log_warnx("recv_db_description: neighbor ID %s " + "sent inconsistent options %x vs. %x", + inet_ntoa(nbr->id), nbr->capa_options, + nbr->options); + } /* * check bits: either I,M,MS or only M */ diff --git a/usr.sbin/ospfd/interface.c b/usr.sbin/ospfd/interface.c index 6ab3c94be36..a7e30359751 100644 --- a/usr.sbin/ospfd/interface.c +++ b/usr.sbin/ospfd/interface.c @@ -1,4 +1,4 @@ -/* $OpenBSD: interface.c,v 1.71 2011/05/06 13:50:37 claudio Exp $ */ +/* $OpenBSD: interface.c,v 1.72 2011/05/09 12:24:41 claudio Exp $ */ /* * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> @@ -167,6 +167,7 @@ if_new(struct kif *kif, struct kif_addr *ka) LIST_INIT(&iface->nbr_list); TAILQ_INIT(&iface->ls_ack_list); TAILQ_INIT(&iface->auth_md_list); + RB_INIT(&iface->lsa_tree); iface->crypt_seq_num = arc4random() & 0x0fffffff; diff --git a/usr.sbin/ospfd/neighbor.c b/usr.sbin/ospfd/neighbor.c index 6ff76c2b1f6..2a6d7b9a558 100644 --- a/usr.sbin/ospfd/neighbor.c +++ b/usr.sbin/ospfd/neighbor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: neighbor.c,v 1.42 2011/03/24 08:35:59 claudio Exp $ */ +/* $OpenBSD: neighbor.c,v 1.43 2011/05/09 12:24:41 claudio Exp $ */ /* * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> @@ -313,6 +313,7 @@ nbr_new(u_int32_t nbr_id, struct iface *iface, int self) bzero(&rn, sizeof(rn)); rn.id.s_addr = nbr->id.s_addr; rn.area_id.s_addr = nbr->iface->area->id.s_addr; + rn.ifindex = nbr->iface->ifindex; rn.state = nbr->state; rn.self = self; ospfe_imsg_compose_rde(IMSG_NEIGHBOR_UP, nbr->peerid, 0, &rn, @@ -519,6 +520,8 @@ nbr_act_snapshot(struct nbr *nbr) { stop_db_tx_timer(nbr); + ospfe_imsg_compose_rde(IMSG_NEIGHBOR_CAPA, nbr->peerid, 0, + &nbr->capa_options, sizeof(nbr->capa_options)); ospfe_imsg_compose_rde(IMSG_DB_SNAPSHOT, nbr->peerid, 0, NULL, 0); return (0); @@ -677,7 +680,7 @@ nbr_to_ctl(struct nbr *nbr) nctl.state_chng_cnt = nbr->stats.sta_chng; nctl.priority = nbr->priority; - nctl.options = nbr->options; + nctl.options = nbr->options | nbr->capa_options; gettimeofday(&now, NULL); if (evtimer_pending(&nbr->inactivity_timer, &tv)) { diff --git a/usr.sbin/ospfd/ospf.h b/usr.sbin/ospfd/ospf.h index 7d2d6b1be61..fe0a8998ffc 100644 --- a/usr.sbin/ospfd/ospf.h +++ b/usr.sbin/ospfd/ospf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ospf.h,v 1.20 2011/03/25 08:52:21 claudio Exp $ */ +/* $OpenBSD: ospf.h,v 1.21 2011/05/09 12:24:41 claudio Exp $ */ /* * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> @@ -81,11 +81,14 @@ #define MAX_SIMPLE_AUTH_LEN 8 /* OSPF compatibility flags */ +#define OSPF_OPTION_MT 0x01 #define OSPF_OPTION_E 0x02 #define OSPF_OPTION_MC 0x04 #define OSPF_OPTION_NP 0x08 #define OSPF_OPTION_EA 0x10 #define OSPF_OPTION_DC 0x20 +#define OSPF_OPTION_O 0x40 /* only on DD options */ +#define OSPF_OPTION_DN 0x80 /* only on LSA options */ /* OSPF packet types */ #define PACKET_TYPE_HELLO 1 @@ -177,6 +180,9 @@ struct ls_upd_hdr { #define LSA_TYPE_SUM_NETWORK 3 #define LSA_TYPE_SUM_ROUTER 4 #define LSA_TYPE_EXTERNAL 5 +#define LSA_TYPE_LINK_OPAQ 9 +#define LSA_TYPE_AREA_OPAQ 10 +#define LSA_TYPE_AS_OPAQ 11 #define LINK_TYPE_POINTTOPOINT 1 #define LINK_TYPE_TRANSIT_NET 2 @@ -187,6 +193,18 @@ struct ls_upd_hdr { #define LSA_METRIC_MASK 0x00ffffff /* only for sum & as-ext */ #define LSA_ASEXT_E_FLAG 0x80000000 +/* for some reason they thought 24bit types are fun, make them less a hazard */ +#define LSA_24_MASK 0xffffff +#define LSA_24_GETHI(x) \ + ((x) >> 24) +#define LSA_24_GETLO(x) \ + ((x) & LSA_24_MASK) +#define LSA_24_SETHI(x, y) \ + ((x) = ((x) & LSA_24_MASK) | (((y) & 0xff) << 24)) +#define LSA_24_SETLO(x, y) \ + ((x) = ((y) & LSA_24_MASK) | ((x) & ~LSA_24_MASK)) + + #define OSPF_RTR_B 0x01 #define OSPF_RTR_E 0x02 #define OSPF_RTR_V 0x04 diff --git a/usr.sbin/ospfd/ospfd.h b/usr.sbin/ospfd/ospfd.h index 6660f2962c5..1cc0145fbdb 100644 --- a/usr.sbin/ospfd/ospfd.h +++ b/usr.sbin/ospfd/ospfd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ospfd.h,v 1.89 2011/01/12 15:07:46 claudio Exp $ */ +/* $OpenBSD: ospfd.h,v 1.90 2011/05/09 12:24:41 claudio Exp $ */ /* * Copyright (c) 2004 Esben Norby <norby@openbsd.org> @@ -80,6 +80,7 @@ enum imsg_type { IMSG_CTL_SHOW_DB_SELF, IMSG_CTL_SHOW_DB_SUM, IMSG_CTL_SHOW_DB_ASBR, + IMSG_CTL_SHOW_DB_OPAQ, IMSG_CTL_SHOW_NBR, IMSG_CTL_SHOW_RIB, IMSG_CTL_SHOW_SUM, @@ -88,6 +89,7 @@ enum imsg_type { IMSG_CTL_FIB_DECOUPLE, IMSG_CTL_FIB_RELOAD, IMSG_CTL_AREA, + IMSG_CTL_IFACE, IMSG_CTL_KROUTE, IMSG_CTL_KROUTE_ADDR, IMSG_CTL_IFINFO, @@ -99,6 +101,7 @@ enum imsg_type { IMSG_NEIGHBOR_UP, IMSG_NEIGHBOR_DOWN, IMSG_NEIGHBOR_CHANGE, + IMSG_NEIGHBOR_CAPA, IMSG_NETWORK_ADD, IMSG_NETWORK_DEL, IMSG_DD, @@ -310,6 +313,7 @@ struct iface { LIST_HEAD(, nbr) nbr_list; struct auth_md_head auth_md_list; struct lsa_head ls_ack_list; + struct lsa_tree lsa_tree; char name[IF_NAMESIZE]; char demote_group[IFNAMSIZ]; diff --git a/usr.sbin/ospfd/ospfe.c b/usr.sbin/ospfd/ospfe.c index ceef94e855a..969c1b0e967 100644 --- a/usr.sbin/ospfd/ospfe.c +++ b/usr.sbin/ospfd/ospfe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ospfe.c,v 1.81 2011/05/02 09:22:23 claudio Exp $ */ +/* $OpenBSD: ospfe.c,v 1.82 2011/05/09 12:24:41 claudio Exp $ */ /* * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> @@ -375,6 +375,7 @@ ospfe_dispatch_main(int fd, short event, void *bula) LIST_INIT(&niface->nbr_list); TAILQ_INIT(&niface->ls_ack_list); TAILQ_INIT(&niface->auth_md_list); + RB_INIT(&niface->lsa_tree); niface->area = narea; LIST_INSERT_HEAD(&narea->iface_list, niface, entry); @@ -544,6 +545,12 @@ ospfe_dispatch_rde(int fd, short event, void *bula) &lsa_hdr, imsg.data); } } + } else if (lsa_hdr.type == LSA_TYPE_LINK_OPAQ) { + /* + * Flood on interface only + */ + noack += lsa_flood(nbr->iface, nbr, + &lsa_hdr, imsg.data); } else { /* * Flood on all area interfaces. For @@ -676,6 +683,7 @@ ospfe_dispatch_rde(int fd, short event, void *bula) } break; case IMSG_CTL_AREA: + case IMSG_CTL_IFACE: case IMSG_CTL_END: case IMSG_CTL_SHOW_DATABASE: case IMSG_CTL_SHOW_DB_EXT: @@ -684,6 +692,7 @@ ospfe_dispatch_rde(int fd, short event, void *bula) case IMSG_CTL_SHOW_DB_SELF: case IMSG_CTL_SHOW_DB_SUM: case IMSG_CTL_SHOW_DB_ASBR: + case IMSG_CTL_SHOW_DB_OPAQ: case IMSG_CTL_SHOW_RIB: case IMSG_CTL_SHOW_SUM: case IMSG_CTL_SHOW_SUM_AREA: diff --git a/usr.sbin/ospfd/ospfe.h b/usr.sbin/ospfd/ospfe.h index fadd896869c..03fdef5e303 100644 --- a/usr.sbin/ospfd/ospfe.h +++ b/usr.sbin/ospfd/ospfe.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ospfe.h,v 1.43 2011/03/25 08:52:21 claudio Exp $ */ +/* $OpenBSD: ospfe.h,v 1.44 2011/05/09 12:24:41 claudio Exp $ */ /* * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> @@ -88,6 +88,7 @@ struct nbr { int state; u_int8_t priority; u_int8_t options; + u_int8_t capa_options; u_int8_t last_rx_options; u_int8_t last_rx_bits; u_int8_t dd_master; diff --git a/usr.sbin/ospfd/rde.c b/usr.sbin/ospfd/rde.c index e4e0e06592e..0155e1cd813 100644 --- a/usr.sbin/ospfd/rde.c +++ b/usr.sbin/ospfd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.93 2011/05/02 11:17:03 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.94 2011/05/09 12:24:41 claudio Exp $ */ /* * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org> @@ -42,6 +42,7 @@ void rde_sig_handler(int sig, short, void *); void rde_shutdown(void); void rde_dispatch_imsg(int, short, void *); void rde_dispatch_parent(int, short, void *); +void rde_dump_area(struct area *, int, pid_t); void rde_send_summary(pid_t); void rde_send_summary_area(struct area *, pid_t); @@ -61,7 +62,6 @@ void rde_asext_get(struct kroute *); void rde_asext_put(struct kroute *); void rde_asext_free(void); struct lsa *orig_asext_lsa(struct kroute *, u_int32_t, u_int16_t); - struct lsa *orig_sum_lsa(struct rt_node *, struct area *, u_int8_t, int); struct ospfd_conf *rdeconf = NULL, *nconf = NULL; @@ -305,12 +305,20 @@ rde_dispatch_imsg(int fd, short event, void *bula) if (nbr->state & NBR_STA_FULL) rde_req_list_free(nbr); break; + case IMSG_NEIGHBOR_CAPA: + if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(u_int8_t)) + fatalx("invalid size of OE request"); + nbr = rde_nbr_find(imsg.hdr.peerid); + if (nbr == NULL) + break; + nbr->capa_options = *(u_int8_t *)imsg.data; + break; case IMSG_DB_SNAPSHOT: nbr = rde_nbr_find(imsg.hdr.peerid); if (nbr == NULL) break; - lsa_snap(nbr->area, imsg.hdr.peerid); + lsa_snap(nbr); imsg_compose_event(iev_ospfe, IMSG_DB_END, imsg.hdr.peerid, 0, -1, NULL, 0); @@ -332,7 +340,7 @@ rde_dispatch_imsg(int fd, short event, void *bula) error = 1; break; } - v = lsa_find(nbr->area, lsa_hdr.type, + v = lsa_find(nbr->iface, lsa_hdr.type, lsa_hdr.ls_id, lsa_hdr.adv_rtr); if (v == NULL) db_hdr = NULL; @@ -373,7 +381,7 @@ rde_dispatch_imsg(int fd, short event, void *bula) memcpy(&req_hdr, buf, sizeof(req_hdr)); buf += sizeof(req_hdr); - if ((v = lsa_find(nbr->area, + if ((v = lsa_find(nbr->iface, ntohl(req_hdr.type), req_hdr.ls_id, req_hdr.adv_rtr)) == NULL) { log_debug("rde_dispatch_imsg: " @@ -408,7 +416,7 @@ rde_dispatch_imsg(int fd, short event, void *bula) break; } - v = lsa_find(nbr->area, lsa->hdr.type, lsa->hdr.ls_id, + v = lsa_find(nbr->iface, lsa->hdr.type, lsa->hdr.ls_id, lsa->hdr.adv_rtr); if (v == NULL) db_hdr = NULL; @@ -504,7 +512,7 @@ rde_dispatch_imsg(int fd, short event, void *bula) if (rde_nbr_loading(nbr->area)) break; - v = lsa_find(nbr->area, lsa_hdr.type, lsa_hdr.ls_id, + v = lsa_find(nbr->iface, lsa_hdr.type, lsa_hdr.ls_id, lsa_hdr.adv_rtr); if (v == NULL) db_hdr = NULL; @@ -524,6 +532,7 @@ rde_dispatch_imsg(int fd, short event, void *bula) case IMSG_CTL_SHOW_DB_SELF: case IMSG_CTL_SHOW_DB_SUM: case IMSG_CTL_SHOW_DB_ASBR: + case IMSG_CTL_SHOW_DB_OPAQ: if (imsg.hdr.len != IMSG_HEADER_SIZE && imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(aid)) { log_warnx("rde_dispatch_imsg: wrong imsg len"); @@ -531,10 +540,7 @@ rde_dispatch_imsg(int fd, short event, void *bula) } if (imsg.hdr.len == IMSG_HEADER_SIZE) { LIST_FOREACH(area, &rdeconf->area_list, entry) { - imsg_compose_event(iev_ospfe, - IMSG_CTL_AREA, 0, imsg.hdr.pid, -1, - area, sizeof(*area)); - lsa_dump(&area->lsa_tree, imsg.hdr.type, + rde_dump_area(area, imsg.hdr.type, imsg.hdr.pid); } lsa_dump(&asext_tree, imsg.hdr.type, @@ -542,10 +548,7 @@ rde_dispatch_imsg(int fd, short event, void *bula) } else { memcpy(&aid, imsg.data, sizeof(aid)); if ((area = area_find(rdeconf, aid)) != NULL) { - imsg_compose_event(iev_ospfe, - IMSG_CTL_AREA, 0, imsg.hdr.pid, -1, - area, sizeof(*area)); - lsa_dump(&area->lsa_tree, imsg.hdr.type, + rde_dump_area(area, imsg.hdr.type, imsg.hdr.pid); if (!area->stub) lsa_dump(&asext_tree, @@ -686,6 +689,7 @@ rde_dispatch_parent(int fd, short event, void *bula) LIST_INIT(&niface->nbr_list); TAILQ_INIT(&niface->ls_ack_list); TAILQ_INIT(&niface->auth_md_list); + RB_INIT(&niface->lsa_tree); niface->area = narea; LIST_INSERT_HEAD(&narea->iface_list, niface, entry); @@ -711,6 +715,26 @@ rde_dispatch_parent(int fd, short event, void *bula) } } +void +rde_dump_area(struct area *area, int imsg_type, pid_t pid) +{ + struct iface *iface; + + /* dump header */ + imsg_compose_event(iev_ospfe, IMSG_CTL_AREA, 0, pid, -1, + area, sizeof(*area)); + + /* dump link local lsa */ + LIST_FOREACH(iface, &area->iface_list, entry) { + imsg_compose_event(iev_ospfe, IMSG_CTL_IFACE, + 0, pid, -1, iface, sizeof(*iface)); + lsa_dump(&iface->lsa_tree, imsg_type, pid); + } + + /* dump area lsa */ + lsa_dump(&area->lsa_tree, imsg_type, pid); +} + u_int32_t rde_router_id(void) { @@ -903,18 +927,27 @@ rde_nbr_new(u_int32_t peerid, struct rde_nbr *new) struct rde_nbr_head *head; struct rde_nbr *nbr; struct area *area; + struct iface *iface; if (rde_nbr_find(peerid)) return (NULL); if ((area = area_find(rdeconf, new->area_id)) == NULL) fatalx("rde_nbr_new: unknown area"); + LIST_FOREACH(iface, &area->iface_list, entry) { + if (iface->ifindex == new->ifindex) + break; + } + if (iface == NULL) + fatalx("rde_nbr_new: unknown interface"); + if ((nbr = calloc(1, sizeof(*nbr))) == NULL) fatal("rde_nbr_new"); memcpy(nbr, new, sizeof(*nbr)); nbr->peerid = peerid; nbr->area = area; + nbr->iface = iface; TAILQ_INIT(&nbr->req_list); @@ -1335,12 +1368,13 @@ rde_summary_update(struct rt_node *rte, struct area *area) fatalx("rde_summary_update: unknown route type"); /* update lsa but only if it was changed */ - v = lsa_find(area, type, rte->prefix.s_addr, rde_router_id()); + v = lsa_find_area(area, type, rte->prefix.s_addr, rde_router_id()); lsa = orig_sum_lsa(rte, area, type, rte->invalid); lsa_merge(rde_nbr_self(area), lsa, v); if (v == NULL) - v = lsa_find(area, type, rte->prefix.s_addr, rde_router_id()); + v = lsa_find_area(area, type, rte->prefix.s_addr, + rde_router_id()); /* suppressed/deleted routes are not found in the second lsa_find */ if (v) diff --git a/usr.sbin/ospfd/rde.h b/usr.sbin/ospfd/rde.h index 384f60fb3ce..4492f5b40ba 100644 --- a/usr.sbin/ospfd/rde.h +++ b/usr.sbin/ospfd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.37 2011/05/02 11:45:55 claudio Exp $ */ +/* $OpenBSD: rde.h,v 1.38 2011/05/09 12:24:41 claudio Exp $ */ /* * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> @@ -41,6 +41,7 @@ struct vertex { struct event ev; struct area *area; struct lsa *lsa; + struct lsa_tree *lsa_tree; time_t changed; time_t stamp; u_int32_t cost; @@ -67,9 +68,12 @@ struct rde_nbr { struct in_addr area_id; TAILQ_HEAD(, rde_req_entry) req_list; struct area *area; + struct iface *iface; u_int32_t peerid; /* unique ID in DB */ int state; - int self; + unsigned int ifindex; + u_int8_t self; + u_int8_t capa_options; }; struct rt_nexthop { @@ -133,10 +137,11 @@ int lsa_self(struct rde_nbr *, struct lsa *, struct vertex *); int lsa_add(struct rde_nbr *, struct lsa *); void lsa_del(struct rde_nbr *, struct lsa_hdr *); void lsa_age(struct vertex *); -struct vertex *lsa_find(struct area *, u_int8_t, u_int32_t, u_int32_t); +struct vertex *lsa_find(struct iface *, u_int8_t, u_int32_t, u_int32_t); +struct vertex *lsa_find_area(struct area *, u_int8_t, u_int32_t, u_int32_t); struct vertex *lsa_find_net(struct area *area, u_int32_t); u_int16_t lsa_num_links(struct vertex *); -void lsa_snap(struct area *, u_int32_t); +void lsa_snap(struct rde_nbr *); void lsa_dump(struct lsa_tree *, int, pid_t); void lsa_merge(struct rde_nbr *, struct lsa *, struct vertex *); void lsa_remove_invalid_sums(struct area *); diff --git a/usr.sbin/ospfd/rde_lsdb.c b/usr.sbin/ospfd/rde_lsdb.c index 4cc79c52fb6..053666cf49e 100644 --- a/usr.sbin/ospfd/rde_lsdb.c +++ b/usr.sbin/ospfd/rde_lsdb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_lsdb.c,v 1.46 2011/05/02 11:45:55 claudio Exp $ */ +/* $OpenBSD: rde_lsdb.c,v 1.47 2011/05/09 12:24:41 claudio Exp $ */ /* * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org> @@ -27,9 +27,11 @@ #include "rde.h" #include "log.h" -struct vertex *vertex_get(struct lsa *, struct rde_nbr *); +struct vertex *vertex_get(struct lsa *, struct rde_nbr *, struct lsa_tree *); int lsa_router_check(struct lsa *, u_int16_t); +struct vertex *lsa_find_tree(struct lsa_tree *, u_int16_t, u_int32_t, + u_int32_t); void lsa_timeout(int, short, void *); void lsa_refresh(struct vertex *); int lsa_equal(struct lsa *, struct lsa *); @@ -49,20 +51,20 @@ lsa_compare(struct vertex *a, struct vertex *b) return (-1); if (a->type > b->type) return (1); - if (a->ls_id < b->ls_id) - return (-1); - if (a->ls_id > b->ls_id) - return (1); if (a->adv_rtr < b->adv_rtr) return (-1); if (a->adv_rtr > b->adv_rtr) return (1); + if (a->ls_id < b->ls_id) + return (-1); + if (a->ls_id > b->ls_id) + return (1); return (0); } struct vertex * -vertex_get(struct lsa *lsa, struct rde_nbr *nbr) +vertex_get(struct lsa *lsa, struct rde_nbr *nbr, struct lsa_tree *tree) { struct vertex *v; struct timespec tp; @@ -79,6 +81,7 @@ vertex_get(struct lsa *lsa, struct rde_nbr *nbr) v->ls_id = ntohl(lsa->hdr.ls_id); v->adv_rtr = ntohl(lsa->hdr.adv_rtr); v->type = lsa->hdr.type; + v->lsa_tree = tree; if (!nbr->self) v->flooded = 1; /* XXX fix me */ @@ -92,10 +95,7 @@ vertex_get(struct lsa *lsa, struct rde_nbr *nbr) void vertex_free(struct vertex *v) { - if (v->type == LSA_TYPE_EXTERNAL) - RB_REMOVE(lsa_tree, &asext_tree, v); - else - RB_REMOVE(lsa_tree, &v->area->lsa_tree, v); + RB_REMOVE(lsa_tree, v->lsa_tree, v); (void)evtimer_del(&v->ev); vertex_nexthop_clear(v); @@ -255,13 +255,24 @@ lsa_check(struct rde_nbr *nbr, struct lsa *lsa, u_int16_t len) if (area->stub) return (0); break; + case LSA_TYPE_LINK_OPAQ: + case LSA_TYPE_AREA_OPAQ: + case LSA_TYPE_AS_OPAQ: + if (len % sizeof(u_int32_t)) { + log_warnx("lsa_check: bad opaque LSA packet"); + return (0); + } + /* Type-11 Opaque-LSA are silently discarded in stub areas */ + if (lsa->hdr.type == LSA_TYPE_AS_OPAQ && area->stub) + return (0); + break; default: log_warnx("lsa_check: unknown type %u", lsa->hdr.type); return (0); } /* MaxAge handling */ - if (lsa->hdr.age == htons(MAX_AGE) && !nbr->self && lsa_find(area, + if (lsa->hdr.age == htons(MAX_AGE) && !nbr->self && lsa_find(nbr->iface, lsa->hdr.type, lsa->hdr.ls_id, lsa->hdr.adv_rtr) == NULL && !rde_nbr_loading(area)) { /* @@ -372,12 +383,15 @@ lsa_add(struct rde_nbr *nbr, struct lsa *lsa) struct vertex *new, *old; struct timeval tv, now, res; - if (lsa->hdr.type == LSA_TYPE_EXTERNAL) + if (lsa->hdr.type == LSA_TYPE_EXTERNAL || + lsa->hdr.type == LSA_TYPE_AS_OPAQ) tree = &asext_tree; + else if (lsa->hdr.type == LSA_TYPE_LINK_OPAQ) + tree = &nbr->iface->lsa_tree; else tree = &nbr->area->lsa_tree; - new = vertex_get(lsa, nbr); + new = vertex_get(lsa, nbr, tree); old = RB_INSERT(lsa_tree, tree, new); if (old != NULL) { @@ -396,14 +410,16 @@ lsa_add(struct rde_nbr *nbr, struct lsa *lsa) return (1); } if (!lsa_equal(new->lsa, old->lsa)) { - if (lsa->hdr.type != LSA_TYPE_EXTERNAL) + if (lsa->hdr.type != LSA_TYPE_EXTERNAL && + lsa->hdr.type != LSA_TYPE_AS_OPAQ) nbr->area->dirty = 1; start_spf_timer(); } vertex_free(old); RB_INSERT(lsa_tree, tree, new); } else { - if (lsa->hdr.type != LSA_TYPE_EXTERNAL) + if (lsa->hdr.type != LSA_TYPE_EXTERNAL && + lsa->hdr.type != LSA_TYPE_AS_OPAQ) nbr->area->dirty = 1; start_spf_timer(); } @@ -427,7 +443,7 @@ lsa_del(struct rde_nbr *nbr, struct lsa_hdr *lsa) struct vertex *v; struct timeval tv; - v = lsa_find(nbr->area, lsa->type, lsa->ls_id, lsa->adv_rtr); + v = lsa_find(nbr->iface, lsa->type, lsa->ls_id, lsa->adv_rtr); if (v == NULL) return; @@ -469,21 +485,39 @@ lsa_age(struct vertex *v) } struct vertex * -lsa_find(struct area *area, u_int8_t type, u_int32_t ls_id, u_int32_t adv_rtr) +lsa_find(struct iface *iface, u_int8_t type, u_int32_t ls_id, u_int32_t adv_rtr) +{ + struct lsa_tree *tree; + + if (type == LSA_TYPE_EXTERNAL || + type == LSA_TYPE_AS_OPAQ) + tree = &asext_tree; + else if (type == LSA_TYPE_LINK_OPAQ) + tree = &iface->lsa_tree; + else + tree = &iface->area->lsa_tree; + + return lsa_find_tree(tree, type, ls_id, adv_rtr); +} + +struct vertex * +lsa_find_area(struct area *area, u_int8_t type, u_int32_t ls_id, + u_int32_t adv_rtr) +{ + return lsa_find_tree(&area->lsa_tree, type, ls_id, adv_rtr); +} + +struct vertex * +lsa_find_tree(struct lsa_tree *tree, u_int16_t type, u_int32_t ls_id, + u_int32_t adv_rtr) { struct vertex key; struct vertex *v; - struct lsa_tree *tree; key.ls_id = ntohl(ls_id); key.adv_rtr = ntohl(adv_rtr); key.type = type; - if (type == LSA_TYPE_EXTERNAL) - tree = &asext_tree; - else - tree = &area->lsa_tree; - v = RB_FIND(lsa_tree, tree, &key); /* LSA that are deleted are not findable */ @@ -532,26 +566,40 @@ lsa_num_links(struct vertex *v) } void -lsa_snap(struct area *area, u_int32_t peerid) +lsa_snap(struct rde_nbr *nbr) { - struct lsa_tree *tree = &area->lsa_tree; + struct lsa_tree *tree = &nbr->area->lsa_tree; struct vertex *v; do { RB_FOREACH(v, lsa_tree, tree) { if (v->deleted) continue; + switch (v->type) { + case LSA_TYPE_LINK_OPAQ: + case LSA_TYPE_AREA_OPAQ: + case LSA_TYPE_AS_OPAQ: + if (nbr->capa_options & OSPF_OPTION_O) + break; + continue; + } lsa_age(v); if (ntohs(v->lsa->hdr.age) >= MAX_AGE) - rde_imsg_compose_ospfe(IMSG_LS_UPD, peerid, + rde_imsg_compose_ospfe(IMSG_LS_UPD, nbr->peerid, 0, &v->lsa->hdr, ntohs(v->lsa->hdr.len)); else - rde_imsg_compose_ospfe(IMSG_DB_SNAPSHOT, peerid, - 0, &v->lsa->hdr, sizeof(struct lsa_hdr)); + rde_imsg_compose_ospfe(IMSG_DB_SNAPSHOT, + nbr->peerid, 0, &v->lsa->hdr, + sizeof(struct lsa_hdr)); } - if (tree != &area->lsa_tree || area->stub) + if (tree == &asext_tree) break; - tree = &asext_tree; + if (tree == &nbr->area->lsa_tree) + tree = &nbr->iface->lsa_tree; + else if (nbr->area->stub) + break; + else + tree = &asext_tree; } while (1); } @@ -566,9 +614,7 @@ lsa_dump(struct lsa_tree *tree, int imsg_type, pid_t pid) lsa_age(v); switch (imsg_type) { case IMSG_CTL_SHOW_DATABASE: - rde_imsg_compose_ospfe(IMSG_CTL_SHOW_DATABASE, 0, pid, - &v->lsa->hdr, ntohs(v->lsa->hdr.len)); - continue; + break; case IMSG_CTL_SHOW_DB_SELF: if (v->lsa->hdr.adv_rtr == rde_router_id()) break; @@ -593,6 +639,12 @@ lsa_dump(struct lsa_tree *tree, int imsg_type, pid_t pid) if (v->type == LSA_TYPE_SUM_ROUTER) break; continue; + case IMSG_CTL_SHOW_DB_OPAQ: + if (v->type == LSA_TYPE_LINK_OPAQ || + v->type == LSA_TYPE_AREA_OPAQ || + v->type == LSA_TYPE_AS_OPAQ) + break; + continue; default: log_warnx("lsa_dump: unknown imsg type"); return; @@ -618,7 +670,8 @@ lsa_timeout(int fd, short event, void *bula) v->deleted = 0; /* schedule recalculation of the RIB */ - if (v->lsa->hdr.type != LSA_TYPE_EXTERNAL) + if (v->type != LSA_TYPE_EXTERNAL && + v->type != LSA_TYPE_AS_OPAQ) v->area->dirty = 1; start_spf_timer(); @@ -713,7 +766,8 @@ lsa_merge(struct rde_nbr *nbr, struct lsa *lsa, struct vertex *v) free(v->lsa); v->lsa = lsa; start_spf_timer(); - if (v->type != LSA_TYPE_EXTERNAL) + if (v->type != LSA_TYPE_EXTERNAL && + v->type != LSA_TYPE_AS_OPAQ) nbr->area->dirty = 1; /* set correct timeout for reflooding the LSA */ @@ -774,13 +828,13 @@ lsa_generate_stub_sums(struct area *area) rn.cost = r->metric & LSA_METRIC_MASK; /* update lsa but only if it was changed */ - v = lsa_find(area, LSA_TYPE_SUM_NETWORK, + v = lsa_find_area(area, LSA_TYPE_SUM_NETWORK, rn.prefix.s_addr, rde_router_id()); lsa = orig_sum_lsa(&rn, area, LSA_TYPE_SUM_NETWORK, 0); lsa_merge(rde_nbr_self(area), lsa, v); if (v == NULL) - v = lsa_find(area, LSA_TYPE_SUM_NETWORK, + v = lsa_find_area(area, LSA_TYPE_SUM_NETWORK, rn.prefix.s_addr, rde_router_id()); /* @@ -817,4 +871,3 @@ lsa_equal(struct lsa *a, struct lsa *b) return (1); } - diff --git a/usr.sbin/ospfd/rde_spf.c b/usr.sbin/ospfd/rde_spf.c index c93d6a25b83..996e9fcaf26 100644 --- a/usr.sbin/ospfd/rde_spf.c +++ b/usr.sbin/ospfd/rde_spf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_spf.c,v 1.71 2011/05/02 11:45:55 claudio Exp $ */ +/* $OpenBSD: rde_spf.c,v 1.72 2011/05/09 12:24:41 claudio Exp $ */ /* * Copyright (c) 2005 Esben Norby <norby@openbsd.org> @@ -63,8 +63,8 @@ spf_calc(struct area *area) cand_list_clr(); /* initialize SPF tree */ - if ((v = spf_root = lsa_find(area, LSA_TYPE_ROUTER, rde_router_id(), - rde_router_id())) == NULL) + if ((v = spf_root = lsa_find_area(area, LSA_TYPE_ROUTER, + rde_router_id(), rde_router_id())) == NULL) /* empty area because no interface is active */ return; @@ -86,7 +86,7 @@ spf_calc(struct area *area) case LINK_TYPE_POINTTOPOINT: case LINK_TYPE_VIRTUAL: /* find router LSA */ - w = lsa_find(area, LSA_TYPE_ROUTER, + w = lsa_find_area(area, LSA_TYPE_ROUTER, rtr_link->id, rtr_link->id); break; case LINK_TYPE_TRANSIT_NET: @@ -100,7 +100,7 @@ spf_calc(struct area *area) case LSA_TYPE_NETWORK: net_link = get_net_link(v, i); /* find router LSA */ - w = lsa_find(area, LSA_TYPE_ROUTER, + w = lsa_find_area(area, LSA_TYPE_ROUTER, net_link->att_rtr, net_link->att_rtr); break; default: @@ -231,7 +231,7 @@ rt_calc(struct vertex *v, struct area *area, struct ospfd_conf *conf) /* TODO type 3 area address range check */ - if ((w = lsa_find(area, LSA_TYPE_ROUTER, + if ((w = lsa_find_area(area, LSA_TYPE_ROUTER, htonl(v->adv_rtr), htonl(v->adv_rtr))) == NULL) return; |