diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2015-11-22 13:09:11 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2015-11-22 13:09:11 +0000 |
commit | 133a1308b1d2e18611a184d0b42336639cadb06d (patch) | |
tree | 4b3c0b7c15cddafdc92075e137627d95655a1893 /usr.sbin | |
parent | 7ced6c1796420a2a7af7561e238ea2f55322fe69 (diff) |
Improve ABR support especially for self-originated stub networks.
This seems to solve the last issues people reported when using ospfd
in multiple areas. OK sthen@ prodding by deraadt@
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/ospfd/area.c | 29 | ||||
-rw-r--r-- | usr.sbin/ospfd/interface.c | 6 | ||||
-rw-r--r-- | usr.sbin/ospfd/neighbor.c | 3 | ||||
-rw-r--r-- | usr.sbin/ospfd/ospfd.h | 6 | ||||
-rw-r--r-- | usr.sbin/ospfd/ospfe.c | 4 | ||||
-rw-r--r-- | usr.sbin/ospfd/rde.c | 41 | ||||
-rw-r--r-- | usr.sbin/ospfd/rde_lsdb.c | 6 | ||||
-rw-r--r-- | usr.sbin/ospfd/rde_spf.c | 45 |
8 files changed, 84 insertions, 56 deletions
diff --git a/usr.sbin/ospfd/area.c b/usr.sbin/ospfd/area.c index f5f4acf7091..f1def2aaf23 100644 --- a/usr.sbin/ospfd/area.c +++ b/usr.sbin/ospfd/area.c @@ -1,4 +1,4 @@ -/* $OpenBSD: area.c,v 1.9 2009/01/07 21:16:36 claudio Exp $ */ +/* $OpenBSD: area.c,v 1.10 2015/11/22 13:09:10 claudio Exp $ */ /* * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> @@ -94,19 +94,24 @@ area_find(struct ospfd_conf *conf, struct in_addr area_id) } void -area_track(struct area *area, int state) +area_track(struct area *area) { - int old = area->active; - - if (state & NBR_STA_FULL) - area->active++; - else if (area->active == 0) - fatalx("area_track: area already inactive"); - else - area->active--; + int old = area->active; + struct iface *iface; + + area->active = 0; + LIST_FOREACH(iface, &area->iface_list, entry) { + if (iface->state & IF_STA_DOWN) + continue; + area->active = 1; + break; + } - if (area->active == 0 || old == 0) + if (area->active != old) { + ospfe_imsg_compose_rde(IMSG_AREA_CHANGE, area->id.s_addr, 0, + &area->active, sizeof(area->active)); ospfe_demote_area(area, old == 0); + } } int @@ -116,7 +121,7 @@ area_border_router(struct ospfd_conf *conf) int active = 0; LIST_FOREACH(area, &conf->area_list, entry) - if (area->active > 0) + if (area->active) active++; return (active > 1); diff --git a/usr.sbin/ospfd/interface.c b/usr.sbin/ospfd/interface.c index 1c8fca2f388..069da3d5b47 100644 --- a/usr.sbin/ospfd/interface.c +++ b/usr.sbin/ospfd/interface.c @@ -1,4 +1,4 @@ -/* $OpenBSD: interface.c,v 1.79 2015/09/27 17:31:50 stsp Exp $ */ +/* $OpenBSD: interface.c,v 1.80 2015/11/22 13:09:10 claudio Exp $ */ /* * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> @@ -136,8 +136,10 @@ if_fsm(struct iface *iface, enum iface_event event) if (new_state != 0) iface->state = new_state; - if (iface->state != old_state) + if (iface->state != old_state) { + area_track(iface->area); orig_rtr_lsa(iface->area); + } if (old_state & (IF_STA_MULTI | IF_STA_POINTTOPOINT) && (iface->state & (IF_STA_MULTI | IF_STA_POINTTOPOINT)) == 0) diff --git a/usr.sbin/ospfd/neighbor.c b/usr.sbin/ospfd/neighbor.c index 2679dc4a8e2..cb85fdede62 100644 --- a/usr.sbin/ospfd/neighbor.c +++ b/usr.sbin/ospfd/neighbor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: neighbor.c,v 1.46 2013/01/17 10:07:56 markus Exp $ */ +/* $OpenBSD: neighbor.c,v 1.47 2015/11/22 13:09:10 claudio Exp $ */ /* * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> @@ -204,7 +204,6 @@ nbr_fsm(struct nbr *nbr, enum nbr_event event) * neighbor changed from/to FULL * originate new rtr and net LSA */ - area_track(nbr->iface->area, nbr->state); orig_rtr_lsa(nbr->iface->area); if (nbr->iface->state & IF_STA_DR) orig_net_lsa(nbr->iface); diff --git a/usr.sbin/ospfd/ospfd.h b/usr.sbin/ospfd/ospfd.h index 7205a65d731..a225fd6830d 100644 --- a/usr.sbin/ospfd/ospfd.h +++ b/usr.sbin/ospfd/ospfd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ospfd.h,v 1.92 2015/09/27 17:31:50 stsp Exp $ */ +/* $OpenBSD: ospfd.h,v 1.93 2015/11/22 13:09:10 claudio Exp $ */ /* * Copyright (c) 2004 Esben Norby <norby@openbsd.org> @@ -104,6 +104,7 @@ enum imsg_type { IMSG_NEIGHBOR_CAPA, IMSG_NETWORK_ADD, IMSG_NETWORK_DEL, + IMSG_AREA_CHANGE, IMSG_DD, IMSG_DD_END, IMSG_DD_BADLSA, @@ -499,6 +500,7 @@ struct ctl_rt { enum dst_type d_type; u_int8_t flags; u_int8_t prefixlen; + u_int8_t connected; }; struct ctl_sum { @@ -530,7 +532,7 @@ struct demote_msg { struct area *area_new(void); int area_del(struct area *); struct area *area_find(struct ospfd_conf *, struct in_addr); -void area_track(struct area *, int); +void area_track(struct area *); int area_border_router(struct ospfd_conf *); u_int8_t area_ospf_options(struct area *); diff --git a/usr.sbin/ospfd/ospfe.c b/usr.sbin/ospfd/ospfe.c index b3c7ac26c9d..03fc2556f11 100644 --- a/usr.sbin/ospfd/ospfe.c +++ b/usr.sbin/ospfd/ospfe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ospfe.c,v 1.91 2015/09/27 17:31:50 stsp Exp $ */ +/* $OpenBSD: ospfe.c,v 1.92 2015/11/22 13:09:10 claudio Exp $ */ /* * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> @@ -996,9 +996,9 @@ orig_rtr_lsa(struct area *area) oeconf->border = border; orig_rtr_lsa_all(area); } - if (oeconf->border) lsa_rtr.flags |= OSPF_RTR_B; + /* TODO set V flag if a active virtual link ends here and the * area is the transit area for this link. */ if (virtual) diff --git a/usr.sbin/ospfd/rde.c b/usr.sbin/ospfd/rde.c index 844bd5c6542..4c63fcfc230 100644 --- a/usr.sbin/ospfd/rde.c +++ b/usr.sbin/ospfd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.97 2015/03/14 02:22:09 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.98 2015/11/22 13:09:10 claudio Exp $ */ /* * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org> @@ -298,11 +298,6 @@ rde_dispatch_imsg(int fd, short event, void *bula) if (nbr == NULL) break; - if (state != nbr->state && - (nbr->state & NBR_STA_FULL || - state & NBR_STA_FULL)) - area_track(nbr->area, state); - nbr->state = state; if (nbr->state & NBR_STA_FULL) rde_req_list_free(nbr); @@ -315,6 +310,19 @@ rde_dispatch_imsg(int fd, short event, void *bula) break; nbr->capa_options = *(u_int8_t *)imsg.data; break; + case IMSG_AREA_CHANGE: + if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(state)) + fatalx("invalid size of OE request"); + + LIST_FOREACH(area, &rdeconf->area_list, entry) { + if (area->id.s_addr == imsg.hdr.peerid) + break; + } + if (area == NULL) + break; + memcpy(&state, imsg.data, sizeof(state)); + area->active = state; + break; case IMSG_DB_SNAPSHOT: nbr = rde_nbr_find(imsg.hdr.peerid); if (nbr == NULL) @@ -771,6 +779,9 @@ rde_send_change_kroute(struct rt_node *r) TAILQ_FOREACH(rn, &r->nexthop, entry) { if (rn->invalid) continue; + if (rn->connected) + /* skip self-originated routes */ + continue; krcount++; bzero(&kr, sizeof(kr)); @@ -780,8 +791,12 @@ rde_send_change_kroute(struct rt_node *r) kr.ext_tag = r->ext_tag; imsg_add(wbuf, &kr, sizeof(kr)); } - if (krcount == 0) - fatalx("rde_send_change_kroute: no valid nexthop found"); + if (krcount == 0) { + /* no valid nexthop or self originated, so remove */ + ibuf_free(wbuf); + rde_send_delete_kroute(r); + return; + } imsg_close(&iev_main->ibuf, wbuf); imsg_event_add(iev_main); } @@ -1352,6 +1367,9 @@ rde_summary_update(struct rt_node *rte, struct area *area) /* first check if we actually need to announce this route */ if (!(rte->d_type == DT_NET || rte->flags & OSPF_RTR_E)) return; + /* route is invalid, lsa_remove_invalid_sums() will do the cleanup */ + if (rte->cost >= LS_INFINITY) + return; /* never create summaries for as-ext LSA */ if (rte->p_type == PT_TYPE1_EXT || rte->p_type == PT_TYPE2_EXT) return; @@ -1363,16 +1381,17 @@ rde_summary_update(struct rt_node *rte, struct area *area) return; /* nexthop check, nexthop part of area -> no summary */ TAILQ_FOREACH(rn, &rte->nexthop, entry) { + if (rn->invalid) + continue; nr = rt_lookup(DT_NET, rn->nexthop.s_addr); if (nr && nr->area.s_addr == area->id.s_addr) continue; break; } - if (rn == NULL) /* all nexthops belong to this area */ + if (rn == NULL) + /* all nexthops belong to this area or are invalid */ return; - if (rte->cost >= LS_INFINITY) - return; /* TODO AS border router specific checks */ /* TODO inter-area network route stuff */ /* TODO intra-area stuff -- condense LSA ??? */ diff --git a/usr.sbin/ospfd/rde_lsdb.c b/usr.sbin/ospfd/rde_lsdb.c index 115eb44ab93..c64b1d95f71 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.49 2013/08/14 20:16:09 claudio Exp $ */ +/* $OpenBSD: rde_lsdb.c,v 1.50 2015/11/22 13:09:10 claudio Exp $ */ /* * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org> @@ -119,10 +119,6 @@ vertex_nexthop_add(struct vertex *dst, struct vertex *parent, u_int32_t nexthop) { struct v_nexthop *vn; - if (nexthop == 0) - /* invalid nexthop, skip it */ - return; - if ((vn = calloc(1, sizeof(*vn))) == NULL) fatal("vertex_nexthop_add"); diff --git a/usr.sbin/ospfd/rde_spf.c b/usr.sbin/ospfd/rde_spf.c index b79ba30506f..736f2e57577 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.75 2012/09/18 18:58:56 bluhm Exp $ */ +/* $OpenBSD: rde_spf.c,v 1.76 2015/11/22 13:09:10 claudio Exp $ */ /* * Copyright (c) 2005 Esben Norby <norby@openbsd.org> @@ -22,6 +22,7 @@ #include <arpa/inet.h> #include <err.h> #include <stdlib.h> +#include <string.h> #include "ospfd.h" #include "ospf.h" @@ -64,14 +65,19 @@ spf_calc(struct area *area) /* initialize SPF tree */ if ((v = spf_root = lsa_find_area(area, LSA_TYPE_ROUTER, - rde_router_id(), rde_router_id())) == NULL) + rde_router_id(), rde_router_id())) == NULL) { /* empty area because no interface is active */ return; + } area->transit = 0; spf_root->cost = 0; w = NULL; + /* make sure the spf root has a nexthop */ + vertex_nexthop_clear(spf_root); + vertex_nexthop_add(spf_root, spf_root, 0); + /* calculate SPF tree */ do { /* loop links */ @@ -159,8 +165,7 @@ spf_calc(struct area *area) } while (v != NULL); /* spf_dump(area); */ - log_debug("spf_calc: area %s calculated", - inet_ntoa(area->id)); + log_debug("spf_calc: area %s calculated", inet_ntoa(area->id)); area->num_spf_calc++; start_spf_timer(); @@ -182,7 +187,7 @@ rt_calc(struct vertex *v, struct area *area, struct ospfd_conf *conf) switch (v->type) { case LSA_TYPE_ROUTER: /* stub networks */ - if (v->cost >= LS_INFINITY || TAILQ_EMPTY(&v->nexthop)) + if (v->cost >= LS_INFINITY) return; for (i = 0; i < lsa_num_links(v); i++) { @@ -211,7 +216,7 @@ rt_calc(struct vertex *v, struct area *area, struct ospfd_conf *conf) adv_rtr, PT_INTRA_AREA, DT_RTR, v->lsa->data.rtr.flags, 0); break; case LSA_TYPE_NETWORK: - if (v->cost >= LS_INFINITY || TAILQ_EMPTY(&v->nexthop)) + if (v->cost >= LS_INFINITY) return; addr.s_addr = htonl(v->ls_id) & v->lsa->data.net.mask; @@ -245,7 +250,7 @@ rt_calc(struct vertex *v, struct area *area, struct ospfd_conf *conf) v->cost = w->cost + (ntohl(v->lsa->data.sum.metric) & LSA_METRIC_MASK); - if (v->cost >= LS_INFINITY || TAILQ_EMPTY(&v->nexthop)) + if (v->cost >= LS_INFINITY) return; adv_rtr.s_addr = htonl(v->adv_rtr); @@ -751,7 +756,7 @@ rt_nexthop_add(struct rt_node *r, struct v_nexthead *vnh, u_int8_t type, rn->adv_rtr.s_addr = adv_rtr.s_addr; rn->connected = (type == LSA_TYPE_NETWORK && - vn->prev == spf_root); + vn->prev == spf_root) || (vn->nexthop.s_addr == 0); rn->invalid = 0; r->invalid = 0; @@ -768,7 +773,7 @@ rt_nexthop_add(struct rt_node *r, struct v_nexthead *vnh, u_int8_t type, rn->adv_rtr.s_addr = adv_rtr.s_addr; rn->uptime = now.tv_sec; rn->connected = (type == LSA_TYPE_NETWORK && - vn->prev == spf_root); + vn->prev == spf_root) || (vn->nexthop.s_addr == 0); rn->invalid = 0; r->invalid = 0; @@ -823,20 +828,23 @@ rt_dump(struct in_addr area, pid_t pid, u_int8_t r_type) fatalx("rt_dump: invalid RIB type"); } + bzero(&rtctl, sizeof(rtctl)); + rtctl.prefix.s_addr = r->prefix.s_addr; + rtctl.area.s_addr = r->area.s_addr; + rtctl.cost = r->cost; + rtctl.cost2 = r->cost2; + rtctl.p_type = r->p_type; + rtctl.d_type = r->d_type; + rtctl.flags = r->flags; + rtctl.prefixlen = r->prefixlen; + TAILQ_FOREACH(rn, &r->nexthop, entry) { if (rn->invalid) continue; - rtctl.prefix.s_addr = r->prefix.s_addr; + rtctl.connected = rn->connected; rtctl.nexthop.s_addr = rn->nexthop.s_addr; - rtctl.area.s_addr = r->area.s_addr; rtctl.adv_rtr.s_addr = rn->adv_rtr.s_addr; - rtctl.cost = r->cost; - rtctl.cost2 = r->cost2; - rtctl.p_type = r->p_type; - rtctl.d_type = r->d_type; - rtctl.flags = r->flags; - rtctl.prefixlen = r->prefixlen; rtctl.uptime = now.tv_sec - rn->uptime; rde_imsg_compose_ospfe(IMSG_CTL_SHOW_RIB, 0, pid, @@ -855,9 +863,6 @@ rt_update(struct in_addr prefix, u_int8_t prefixlen, struct v_nexthead *vnh, struct rt_nexthop *rn; int better = 0, equal = 0; - if (vnh == NULL || TAILQ_EMPTY(vnh)) /* XXX remove */ - fatalx("rt_update: invalid nexthop"); - if ((rte = rt_find(prefix.s_addr, prefixlen, d_type)) == NULL) { if ((rte = calloc(1, sizeof(struct rt_node))) == NULL) fatal("rt_update"); |