From 86c84d76b706e77ec5977a3c9e300b0fca9f6b10 Mon Sep 17 00:00:00 2001 From: Ondrej Filip Date: Thu, 15 Jul 2004 16:37:52 +0000 Subject: [PATCH] Huge OSPF database redesign. Since now, all LSAs of all areas are in single database. This avoids duplication of external LSAs and fixes bug in external LSA distribution. --- TODO | 1 - proto/ospf/config.Y | 2 - proto/ospf/dbdes.c | 40 +++++++++------- proto/ospf/hello.c | 5 +- proto/ospf/iface.c | 25 ++++------ proto/ospf/lsack.c | 6 +-- proto/ospf/lsalib.c | 38 +++++++-------- proto/ospf/lsalib.h | 4 +- proto/ospf/lsreq.c | 8 ++-- proto/ospf/lsupd.c | 47 ++++++++----------- proto/ospf/neighbor.c | 27 +++++------ proto/ospf/ospf.c | 62 +++++++++++++------------ proto/ospf/ospf.h | 7 ++- proto/ospf/packet.c | 28 ++++-------- proto/ospf/rt.c | 52 +++++++++++---------- proto/ospf/topology.c | 104 +++++++++++++++++++++++------------------- proto/ospf/topology.h | 11 +++-- 17 files changed, 233 insertions(+), 234 deletions(-) diff --git a/TODO b/TODO index b6693366..f0c60b6b 100644 --- a/TODO +++ b/TODO @@ -49,5 +49,4 @@ OSPF - automatic generation of external route tags (RFC1403) - RFC1587 NSSA areas - RFC2370 opaque LSA's - - AS external LSAs are in topology database of every OSPF Area - Limit export rate of external LSAs (like Gated does) diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y index bd3a2e54..4a625498 100644 --- a/proto/ospf/config.Y +++ b/proto/ospf/config.Y @@ -104,7 +104,6 @@ ospf_vlink_item: ospf_vlink_start: VIRTUAL LINK idval { - log("Vlink start"); if (this_area->areaid == 0) cf_error("Virtual link cannot be in backbone"); this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt)); add_tail(&this_area->vlink_list, NODE this_ipatt); @@ -200,7 +199,6 @@ ipa_ne: IPA ELIGIBLE ';' ospf_iface_start: { - log("Iface start"); this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt)); add_tail(&this_area->patt_list, NODE this_ipatt); OSPF_PATT->cost = COST_D; diff --git a/proto/ospf/dbdes.c b/proto/ospf/dbdes.c index 6e84eddf..7f181fb6 100644 --- a/proto/ospf/dbdes.c +++ b/proto/ospf/dbdes.c @@ -25,11 +25,11 @@ ospf_dbdes_send(struct ospf_neighbor *n) struct ospf_packet *op; struct ospf_iface *ifa = n->ifa; struct ospf_area *oa = ifa->oa; - u16 length; - struct proto *p = (struct proto *) (ifa->proto); - u16 i, j; + struct proto_ospf *po = oa->po; + struct proto *p = &po->proto; + u16 length, i, j; - if ((oa->rt == NULL) || (EMPTY_LIST(oa->lsal))) + if ((oa->rt == NULL) || (EMPTY_LIST(po->lsal))) originate_rt_lsa(oa); switch (n->state) @@ -40,7 +40,7 @@ ospf_dbdes_send(struct ospf_neighbor *n) op = (struct ospf_packet *) pkt; ospf_pkt_fill_hdr(ifa, pkt, DBDES_P); pkt->iface_mtu = htons(ifa->iface->mtu); - pkt->options = ifa->oa->opt.byte; + pkt->options = oa->opt.byte; pkt->imms = n->myimms; pkt->ddseq = htonl(n->dds); length = sizeof(struct ospf_dbdes_packet); @@ -64,7 +64,7 @@ ospf_dbdes_send(struct ospf_neighbor *n) ospf_pkt_fill_hdr(ifa, pkt, DBDES_P); pkt->iface_mtu = htons(ifa->iface->mtu); - pkt->options = ifa->oa->opt.byte; + pkt->options = oa->opt.byte; pkt->ddseq = htonl(n->dds); j = i = (ospf_pkt_maxsize(ifa) - sizeof(struct ospf_dbdes_packet)) / sizeof(struct ospf_lsa_header); /* Number of possible lsaheaders to send */ @@ -77,10 +77,17 @@ ospf_dbdes_send(struct ospf_neighbor *n) DBG("Number of LSA: %d\n", j); for (; i > 0; i--) { - struct top_hash_entry *en; - en = (struct top_hash_entry *) sn; + struct top_hash_entry *en= (struct top_hash_entry *) sn; + int send = 1; - if ((n->ifa->type != OSPF_IT_VLINK) || (en->lsa.type != LSA_T_EXT)) + /* Don't send ext LSA into stub areas */ + if (oa->stub && (en->lsa.type == LSA_T_EXT)) send = 0; + /* Don't send ext LSAs through VLINK */ + if ((ifa->type == OSPF_IT_VLINK) && (en->lsa.type == LSA_T_EXT)) send = 0;; + /* Don't send LSA of other areas */ + if ((en->lsa.type != LSA_T_EXT) && (en->oa != oa)) send = 0; + + if (send) { htonlsah(&(en->lsa), lsa); DBG("Working on: %d\n", i); @@ -91,7 +98,7 @@ ospf_dbdes_send(struct ospf_neighbor *n) } else i++; /* No lsa added */ - if (sn == STAIL(n->ifa->oa->lsal)) + if (sn == STAIL(po->lsal)) { i--; break; @@ -100,7 +107,7 @@ ospf_dbdes_send(struct ospf_neighbor *n) sn = sn->next; } - if (sn == STAIL(n->ifa->oa->lsal)) + if (sn == STAIL(po->lsal)) { DBG("Number of LSA NOT sent: %d\n", i); DBG("M bit unset.\n"); @@ -163,7 +170,8 @@ ospf_dbdes_reqladd(struct ospf_dbdes_packet *ps, struct ospf_neighbor *n) { struct ospf_lsa_header *plsa, lsa; struct top_hash_entry *he, *sn; - struct top_graph *gr = n->ifa->oa->gr; + struct ospf_area *oa = n->ifa->oa; + struct top_graph *gr = oa->po->gr; struct ospf_packet *op; int i, j; @@ -177,13 +185,13 @@ ospf_dbdes_reqladd(struct ospf_dbdes_packet *ps, struct ospf_neighbor *n) for (i = 0; i < j; i++) { ntohlsah(plsa + i, &lsa); - if (((he = ospf_hash_find(gr, lsa.id, lsa.rt, lsa.type)) == NULL) || + if (((he = ospf_hash_find(gr, oa->areaid, lsa.id, lsa.rt, lsa.type)) == NULL) || (lsa_comp(&lsa, &(he->lsa)) == 1)) { /* Is this condition necessary? */ - if (ospf_hash_find(n->lsrqh, lsa.id, lsa.rt, lsa.type) == NULL) + if (ospf_hash_find(n->lsrqh, oa->areaid, lsa.id, lsa.rt, lsa.type) == NULL) { - sn = ospf_hash_get(n->lsrqh, lsa.id, lsa.rt, lsa.type); + sn = ospf_hash_get(n->lsrqh, oa, lsa.id, lsa.rt, lsa.type); ntohlsah(plsa + i, &(sn->lsa)); s_add_tail(&(n->lsrql), SNODE sn); } @@ -195,7 +203,7 @@ void ospf_dbdes_receive(struct ospf_dbdes_packet *ps, struct ospf_iface *ifa, struct ospf_neighbor *n) { - struct proto *p = (struct proto *) ifa->proto; + struct proto *p = &ifa->oa->po->proto; u32 myrid = p->cf->global->router_id; unsigned int size = ntohs(ps->ospf_packet.length); diff --git a/proto/ospf/hello.c b/proto/ospf/hello.c index 350bad7c..58d1423a 100644 --- a/proto/ospf/hello.c +++ b/proto/ospf/hello.c @@ -16,7 +16,7 @@ ospf_hello_receive(struct ospf_hello_packet *ps, ip_addr olddr, oldbdr; ip_addr mask; char *beg = "Bad OSPF hello packet from ", *rec = " received: "; - struct proto *p = (struct proto *) ifa->proto; + struct proto *p = (struct proto *) ifa->oa->po; unsigned int size = ntohs(ps->ospf_packet.length), i, twoway, oldpriority, eligible = 0, peers; OSPF_TRACE(D_PACKETS, "Received hello from %I via %s%s", faddr, @@ -172,6 +172,7 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn) u32 *pp; int i, send; struct nbma_node *nb; + if (timer == NULL) ifa = dirn->ifa; else @@ -183,7 +184,7 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn) if (ifa->stub) return; /* Don't send any packet on stub iface */ - p = (struct proto *) (ifa->proto); + p = (struct proto *) (ifa->oa->po); DBG("%s: Hello/Poll timer fired on interface %s.\n", p->name, ifa->iface->name); /* Now we should send a hello packet */ diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c index 5a10cde7..68b6377d 100644 --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@ -35,7 +35,7 @@ static void wait_timer_hook(timer * timer) { struct ospf_iface *ifa = (struct ospf_iface *) timer->data; - struct proto *p = (struct proto *) (ifa->proto); + struct proto *p = &ifa->oa->po->proto; OSPF_TRACE(D_EVENTS, "Wait timer fired on interface %s.", ifa->iface->name); ospf_iface_sm(ifa, ISM_WAITF); @@ -45,9 +45,7 @@ static sock * ospf_open_ip_socket(struct ospf_iface *ifa) { sock *ipsk; - struct proto *p; - - p = (struct proto *) (ifa->proto); + struct proto *p = &ifa->oa->po->proto; ipsk = sk_new(p->pool); ipsk->type = SK_IP; @@ -86,7 +84,7 @@ ospf_open_ip_socket(struct ospf_iface *ifa) void ospf_iface_chstate(struct ospf_iface *ifa, u8 state) { - struct proto_ospf *po = ifa->proto; + struct proto_ospf *po = ifa->oa->po; struct proto *p = &po->proto; u8 oldstate = ifa->state; @@ -149,8 +147,8 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state) { ospf_lsupd_flush_nlsa(ifa->nlsa, ifa->oa); } - if (can_flush_lsa(ifa->oa)) - flush_lsa(ifa->nlsa, ifa->oa); + if (can_flush_lsa(po)) + flush_lsa(ifa->nlsa, po); ifa->nlsa = NULL; } } @@ -162,8 +160,8 @@ static void ospf_iface_down(struct ospf_iface *ifa) { struct ospf_neighbor *n, *nx; - struct proto *p = &ifa->proto->proto; - struct proto_ospf *po = ifa->proto; + struct proto_ospf *po = ifa->oa->po; + struct proto *p = &po->proto; struct ospf_iface *iff; /* First of all kill all the related vlinks */ @@ -287,9 +285,7 @@ static sock * ospf_open_mc_socket(struct ospf_iface *ifa) { sock *mcsk; - struct proto *p; - - p = (struct proto *) (ifa->proto); + struct proto *p = &ifa->oa->po->proto; mcsk = sk_new(p->pool); mcsk->type = SK_IP_MC; @@ -342,9 +338,9 @@ static void ospf_iface_add(struct object_lock *lock) { struct ospf_iface *ifa = lock->data; - struct proto_ospf *po = ifa->proto; - struct iface *iface = lock->iface; + struct proto_ospf *po = ifa->oa->po; struct proto *p = &po->proto; + struct iface *iface = lock->iface; ifa->lock = lock; @@ -387,7 +383,6 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area *oa; ifa = mb_allocz(p->pool, sizeof(struct ospf_iface)); - ifa->proto = po; ifa->iface = iface; ifa->cost = ip->cost; diff --git a/proto/ospf/lsack.c b/proto/ospf/lsack.c index 14832b82..bb1afa0a 100644 --- a/proto/ospf/lsack.c +++ b/proto/ospf/lsack.c @@ -37,7 +37,7 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue) struct ospf_lsa_header *h; struct lsah_n *no; struct ospf_iface *ifa = n->ifa; - struct proto *p = &n->ifa->proto->proto; + struct proto *p = &n->ifa->oa->po->proto; if (EMPTY_LIST(n->ackl[queue])) return; @@ -122,7 +122,7 @@ ospf_lsack_receive(struct ospf_lsack_packet *ps, struct ospf_lsa_header lsa, *plsa; u16 nolsa; struct top_hash_entry *en; - struct proto *p = (struct proto *) ifa->proto; + struct proto *p = &ifa->oa->po->proto; unsigned int size = ntohs(ps->ospf_packet.length), i; OSPF_TRACE(D_PACKETS, "Received LS ack from %I", n->ip); @@ -146,7 +146,7 @@ ospf_lsack_receive(struct ospf_lsack_packet *ps, for (i = 0; i < nolsa; i++) { ntohlsah(plsa + i, &lsa); - if ((en = ospf_hash_find_header(n->lsrth, &lsa)) == NULL) + if ((en = ospf_hash_find_header(n->lsrth, n->ifa->oa->areaid, &lsa)) == NULL) continue; /* pg 155 */ if (lsa_comp(&lsa, &en->lsa) != CMP_SAME) /* pg 156 */ diff --git a/proto/ospf/lsalib.c b/proto/ospf/lsalib.c index b244c3f2..af3f743a 100644 --- a/proto/ospf/lsalib.c +++ b/proto/ospf/lsalib.c @@ -9,9 +9,10 @@ #include "ospf.h" void -flush_lsa(struct top_hash_entry *en, struct ospf_area *oa) +flush_lsa(struct top_hash_entry *en, struct proto_ospf *po) { - struct proto *p = &oa->po->proto; + struct proto *p = &po->proto; + OSPF_TRACE(D_EVENTS, "Going to remove node Type: %u, Id: %I, Rt: %I, Age: %u, SN: 0x%x", en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa.age, en->lsa.sn); @@ -19,14 +20,14 @@ flush_lsa(struct top_hash_entry *en, struct ospf_area *oa) if (en->lsa_body != NULL) mb_free(en->lsa_body); en->lsa_body = NULL; - ospf_hash_delete(oa->gr, en); + ospf_hash_delete(po->gr, en); } /** * ospf_age - * @oa: ospf area + * @po: ospf protocol * - * This function is periodicaly invoked from area_disp(). It computes the new + * This function is periodicaly invoked from ospf_disp(). It computes the new * age of all LSAs and old (@age is higher than %LSA_MAXAGE) LSAs are flushed * whenever possible. If an LSA originated by the router itself is older * than %LSREFRESHTIME a new instance is originated. @@ -38,19 +39,17 @@ flush_lsa(struct top_hash_entry *en, struct ospf_area *oa) * table calculation results. */ void -ospf_age(struct ospf_area *oa) +ospf_age(struct proto_ospf *po) { - struct proto *p = &oa->po->proto; - struct proto_ospf *po = (struct proto_ospf *) p; + struct proto *p = &po->proto; struct top_hash_entry *en, *nxt; - int flush = can_flush_lsa(oa); - int cleanup = (oa->rt && (oa->rt->dist != LSINFINITY)); + int flush = can_flush_lsa(po); - if (cleanup) OSPF_TRACE(D_EVENTS, "Running ospf_age cleanup"); + if (po->cleanup) OSPF_TRACE(D_EVENTS, "Running ospf_age cleanup"); - WALK_SLIST_DELSAFE(en, nxt, oa->lsal) + WALK_SLIST_DELSAFE(en, nxt, po->lsal) { - if (cleanup) + if (po->cleanup) { en->color = OUTSPF; en->dist = LSINFINITY; @@ -63,7 +62,7 @@ ospf_age(struct ospf_area *oa) if (en->lsa.age == LSA_MAXAGE) { if (flush) - flush_lsa(en, oa); + flush_lsa(en, po); continue; } if ((en->lsa.rt == p->cf->global->router_id) &&(en->lsa.age >= @@ -76,20 +75,21 @@ ospf_age(struct ospf_area *oa) en->inst_t = now; en->ini_age = 0; lsasum_calculate(&en->lsa, en->lsa_body); - ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1); + ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, en->oa, 1); continue; } if ((en->lsa.age = (en->ini_age + (now - en->inst_t))) >= LSA_MAXAGE) { if (flush) { - flush_lsa(en, oa); + flush_lsa(en, po); schedule_rtcalc(po); } else en->lsa.age = LSA_MAXAGE; } } + po->cleanup = 0; } void @@ -446,9 +446,9 @@ lsa_install_new(struct ospf_lsa_header *lsa, void *body, struct ospf_area *oa) struct top_hash_entry *en; struct proto_ospf *po = oa->po; - if ((en = ospf_hash_find_header(oa->gr, lsa)) == NULL) + if ((en = ospf_hash_find_header(po->gr, oa->areaid, lsa)) == NULL) { - en = ospf_hash_get_header(oa->gr, lsa); + en = ospf_hash_get_header(po->gr, oa, lsa); change = 1; } else @@ -474,7 +474,7 @@ lsa_install_new(struct ospf_lsa_header *lsa, void *body, struct ospf_area *oa) DBG("Inst lsa: Id: %I, Rt: %I, Type: %u, Age: %u, Sum: %u, Sn: 0x%x\n", lsa->id, lsa->rt, lsa->type, lsa->age, lsa->checksum, lsa->sn); - s_add_tail(&oa->lsal, SNODE en); + s_add_tail(&po->lsal, SNODE en); en->inst_t = now; if (en->lsa_body != NULL) mb_free(en->lsa_body); diff --git a/proto/ospf/lsalib.h b/proto/ospf/lsalib.h index 43f95130..c7f16d51 100644 --- a/proto/ospf/lsalib.h +++ b/proto/ospf/lsalib.h @@ -22,7 +22,7 @@ u16 lsasum_check(struct ospf_lsa_header *h, void *body); int lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2); struct top_hash_entry *lsa_install_new(struct ospf_lsa_header *lsa, void *body, struct ospf_area *oa); -void ospf_age(struct ospf_area *oa); -void flush_lsa(struct top_hash_entry *en, struct ospf_area *oa); +void ospf_age(struct proto_ospf *po); +void flush_lsa(struct top_hash_entry *en, struct proto_ospf *po); #endif /* _BIRD_OSPF_LSALIB_H_ */ diff --git a/proto/ospf/lsreq.c b/proto/ospf/lsreq.c index 64f10827..3c8b7220 100644 --- a/proto/ospf/lsreq.c +++ b/proto/ospf/lsreq.c @@ -18,7 +18,7 @@ ospf_lsreq_send(struct ospf_neighbor *n) struct ospf_lsreq_header *lsh; u16 length; int i, j; - struct proto *p = &n->ifa->proto->proto; + struct proto *p = &n->ifa->oa->po->proto; pk = (struct ospf_lsreq_packet *) n->ifa->ip_sk->tbuf; op = (struct ospf_packet *) n->ifa->ip_sk->tbuf; @@ -73,7 +73,9 @@ ospf_lsreq_receive(struct ospf_lsreq_packet *ps, slab *upslab; unsigned int size = ntohs(ps->ospf_packet.length); int i, lsano; - struct proto *p = (struct proto *) ifa->proto; + struct ospf_area *oa = ifa->oa; + struct proto_ospf *po = oa->po; + struct proto *p = &po->proto; if (n->state < NEIGHBOR_EXCHANGE) return; @@ -96,7 +98,7 @@ ospf_lsreq_receive(struct ospf_lsreq_packet *ps, llsh->lsh.rt = ntohl(lsh->rt); llsh->lsh.type = lsh->type; add_tail(&uplist, NODE llsh); - if (ospf_hash_find(n->ifa->oa->gr, llsh->lsh.id, llsh->lsh.rt, + if (ospf_hash_find(po->gr, oa->areaid, llsh->lsh.id, llsh->lsh.rt, llsh->lsh.type) == NULL) { log(L_WARN diff --git a/proto/ospf/lsupd.c b/proto/ospf/lsupd.c index 51b38afd..c6194424 100644 --- a/proto/ospf/lsupd.c +++ b/proto/ospf/lsupd.c @@ -13,7 +13,6 @@ * @n: neighbor than sent this lsa (or NULL if generated) * @hn: LSA header followed by lsa body in network endianity (may be NULL) * @hh: LSA header in host endianity (must be filled) - * @po: actual instance of OSPF protocol * @iff: interface which received this LSA (or NULL if LSA is generated) * @oa: ospf_area which is the LSA generated for * @rtl: add this LSA into retransmission list @@ -48,16 +47,8 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn, } else { - if (oa->areaid == BACKBONE) - { - if ((ifa->type != OSPF_IT_VLINK) && (ifa->oa != oa)) - continue; - } - else - { - if (ifa->oa != oa) - continue; - } + if (ifa->oa != oa) + continue; } ret = 0; WALK_LIST(NODE nn, ifa->neigh_list) @@ -66,7 +57,7 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn, continue; if (nn->state < NEIGHBOR_FULL) { - if ((en = ospf_hash_find_header(nn->lsrqh, hh)) != NULL) + if ((en = ospf_hash_find_header(nn->lsrqh, nn->ifa->oa->areaid, hh)) != NULL) { switch (lsa_comp(hh, &en->lsa)) { @@ -105,9 +96,9 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn, if (rtl) { - if ((en = ospf_hash_find_header(nn->lsrth, hh)) == NULL) + if ((en = ospf_hash_find_header(nn->lsrth, nn->ifa->oa->areaid, hh)) == NULL) { - en = ospf_hash_get_header(nn->lsrth, hh); + en = ospf_hash_get_header(nn->lsrth, nn->ifa->oa, hh); } else { @@ -120,7 +111,7 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn, } else { - if ((en = ospf_hash_find_header(nn->lsrth, hh)) != NULL) + if ((en = ospf_hash_find_header(nn->lsrth, nn->ifa->oa->areaid, hh)) != NULL) { s_rem_node(SNODE en); if (en->lsa_body != NULL) @@ -177,7 +168,7 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn, htonlsah(hh, lh); help = (u8 *) (lh + 1); - en = ospf_hash_find_header(oa->gr, hh); + en = ospf_hash_find_header(po->gr, oa->areaid, hh); htonlsab(en->lsa_body, help, hh->type, hh->length - sizeof(struct ospf_lsa_header)); } @@ -229,7 +220,9 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l) struct top_hash_entry *en; struct ospf_lsupd_packet *pk; struct ospf_packet *op; - struct proto *p = &n->ifa->oa->po->proto; + struct ospf_area *oa = n->ifa->oa; + struct proto_ospf *po = oa->po; + struct proto *p = &po->proto; void *pktpos; if (EMPTY_LIST(*l)) @@ -247,7 +240,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l) WALK_LIST(llsh, *l) { - if ((en = ospf_hash_find(n->ifa->oa->gr, llsh->lsh.id, llsh->lsh.rt, + if ((en = ospf_hash_find(po->gr, oa->areaid, llsh->lsh.id, llsh->lsh.rt, llsh->lsh.type)) == NULL) continue; /* Probably flushed LSA */ /* FIXME This is a bug! I cannot flush LSA that is in lsrt */ @@ -294,8 +287,8 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps, struct ospf_neighbor *ntmp; struct ospf_lsa_header *lsa; struct ospf_area *oa; - struct proto_ospf *po = ifa->proto; - struct proto *p = (struct proto *) po; + struct proto_ospf *po = ifa->oa->po; + struct proto *p = &po->proto; unsigned int i, sendreq = 1, size = ntohs(ps->ospf_packet.length); if (n->state < NEIGHBOR_EXCHANGE) @@ -372,7 +365,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps, lsatmp.type, lsatmp.id, lsatmp.rt, lsatmp.sn, lsatmp.age, lsatmp.checksum); - lsadb = ospf_hash_find_header(oa->gr, &lsatmp); + lsadb = ospf_hash_find_header(po->gr, oa->areaid, &lsatmp); #ifdef LOCAL_DEBUG if (lsadb) @@ -382,7 +375,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps, #endif /* pg 143 (4) */ - if ((lsatmp.age == LSA_MAXAGE) && (lsadb == NULL) && can_flush_lsa(oa)) + if ((lsatmp.age == LSA_MAXAGE) && (lsadb == NULL) && can_flush_lsa(po)) { ospf_lsack_enqueue(n, lsa, ACKL_DIRECT); continue; @@ -433,7 +426,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps, lsasum_check(lsa, (lsa + 1)); /* It also calculates chsum! */ lsatmp.checksum = ntohs(lsa->checksum); ospf_lsupd_flood(NULL, lsa, &lsatmp, NULL, oa, 0); - if (en = ospf_hash_find_header(oa->gr, &lsatmp)) + if (en = ospf_hash_find_header(po->gr, oa->areaid, &lsatmp)) { ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1); } @@ -468,7 +461,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps, { struct top_hash_entry *en; if (ntmp->state > NEIGHBOR_EXSTART) - if ((en = ospf_hash_find_header(ntmp->lsrth, &lsadb->lsa)) != NULL) + if ((en = ospf_hash_find_header(ntmp->lsrth, ntmp->ifa->oa->areaid, &lsadb->lsa)) != NULL) { s_rem_node(SNODE en); if (en->lsa_body != NULL) @@ -479,9 +472,9 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps, } if ((lsatmp.age == LSA_MAXAGE) && (lsatmp.sn == LSA_MAXSEQNO) - && lsadb && can_flush_lsa(oa)) + && lsadb && can_flush_lsa(po)) { - flush_lsa(lsadb, oa); + flush_lsa(lsadb, po); schedule_rtcalc(po); continue; } /* FIXME lsack? */ @@ -504,7 +497,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps, { struct top_hash_entry *en; DBG("PG145(7) Got the same LSA\n"); - if ((en = ospf_hash_find_header(n->lsrth, &lsadb->lsa)) != NULL) + if ((en = ospf_hash_find_header(n->lsrth, n->ifa->oa->areaid, &lsadb->lsa)) != NULL) { /* pg145 (7a) */ s_rem_node(SNODE en); diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c index 869db2b7..af6b8534 100644 --- a/proto/ospf/neighbor.c +++ b/proto/ospf/neighbor.c @@ -33,7 +33,7 @@ void ackd_timer_hook(timer * t); struct ospf_neighbor * ospf_neighbor_new(struct ospf_iface *ifa) { - struct proto *p = (struct proto *) (ifa->proto); + struct proto *p = (struct proto *) (ifa->oa->po); struct pool *pool = rp_new(p->pool, "OSPF Neighbor"); struct ospf_neighbor *n = mb_allocz(pool, sizeof(struct ospf_neighbor)); @@ -231,7 +231,7 @@ can_do_adj(struct ospf_neighbor *n) int i; ifa = n->ifa; - p = (struct proto *) (ifa->proto); + p = (struct proto *) (ifa->oa->po); i = 0; switch (ifa->type) @@ -289,8 +289,8 @@ can_do_adj(struct ospf_neighbor *n) void ospf_neigh_sm(struct ospf_neighbor *n, int event) { - struct proto_ospf *po = n->ifa->proto; - struct proto *p = (struct proto *) po; + struct proto_ospf *po = n->ifa->oa->po; + struct proto *p = &po->proto; DBG("Neighbor state machine for neighbor %I, event \"%s\".", n->ip, ospf_inm[event]); @@ -322,7 +322,7 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event) if (n->state == NEIGHBOR_EXSTART) { neigh_chstate(n, NEIGHBOR_EXCHANGE); - s_init(&(n->dbsi), &(n->ifa->oa->lsal)); + s_init(&(n->dbsi), &po->lsal); while (!EMPTY_LIST(n->ackl[ACKL_DELAY])) { struct lsah_n *no; @@ -396,7 +396,7 @@ bdr_election(struct ospf_iface *ifa) u32 myid; ip_addr ndrip, nbdrip; int doadj; - struct proto *p = &ifa->proto->proto; + struct proto *p = &ifa->oa->po->proto; DBG("(B)DR election.\n"); @@ -541,13 +541,10 @@ ospf_find_area(struct proto_ospf *po, u32 aid) void neighbor_timer_hook(timer * timer) { - struct ospf_neighbor *n; - struct ospf_iface *ifa; - struct proto *p; + struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data; + struct ospf_iface *ifa = n->ifa; + struct proto *p = &ifa->oa->po->proto; - n = (struct ospf_neighbor *) timer->data; - ifa = n->ifa; - p = (struct proto *) (ifa->proto); OSPF_TRACE(D_EVENTS, "Inactivity timer fired on interface %s for neighbor %I.", ifa->iface->name, n->ip); @@ -557,11 +554,9 @@ neighbor_timer_hook(timer * timer) void ospf_neigh_remove(struct ospf_neighbor *n) { - struct ospf_iface *ifa; - struct proto *p; + struct ospf_iface *ifa = n->ifa; + struct proto *p = &ifa->oa->po->proto; - ifa = n->ifa; - p = (struct proto *) (ifa->proto); neigh_chstate(n, NEIGHBOR_DOWN); rem_node(NODE n); rfree(n->pool); diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index 8f6b2171..e9e45d76 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -41,11 +41,16 @@ * describes the link-state database. It allows fast search, addition * and deletion. Each LSA is kept in two pieces: header and body. Both of them are * kept in the endianity of the CPU. + * + * The heart beat of ospf is ospf_disp(). It is called at regular intervals + * (&proto_ospf->tick). It is responsible for aging and flushing of LSAs in + * the database, for routing table calculaction and it call area_disp() of every + * ospf_area. * - * Every area has its own area_disp() which is - * responsible for late originating of router LSA, calculating - * of the routing table and it also ages and flushes the LSAs. This - * function is called in regular intervals from ospf_disp() + * The function area_disp() is + * responsible for late originating of router LSA and network LSA + * and for cleanup after routing table calculation process in + * the area. * To every &ospf_iface, we connect one or more * &ospf_neighbor's -- a structure containing many timers and queues * for building adjacency and for exchange of routing messages. @@ -122,6 +127,9 @@ ospf_start(struct proto *p) init_list(&(po->area_list)); fib_init(&po->rtf, p->pool, sizeof(ort), 16, ospf_rt_initort); po->areano = 0; + po->gr = ospf_top_new(p->pool); + po->cleanup = 1; + s_init_list(&(po->lsal)); if (EMPTY_LIST(c->area_list)) { log(L_ERR "Cannot start, no OSPF areas configured!"); @@ -135,8 +143,6 @@ ospf_start(struct proto *p) po->areano++; oa->stub = ac->stub; oa->areaid = ac->areaid; - oa->gr = ospf_top_new(p->pool); - s_init_list(&(oa->lsal)); oa->rt = NULL; oa->po = po; add_area_nets(oa, ac); @@ -181,13 +187,9 @@ ospf_dump(struct proto *p) } } - WALK_LIST(NODE oa, po->area_list) - { - OSPF_TRACE(D_EVENTS, "LSA graph dump for area \"%I\" start:", oa->areaid); - ospf_top_dump(oa->gr, p); - OSPF_TRACE(D_EVENTS, "LSA graph dump for area \"%I\" finished", - oa->areaid); - } + OSPF_TRACE(D_EVENTS, "LSA graph dump start:"); + ospf_top_dump(po->gr, p); + OSPF_TRACE(D_EVENTS, "LSA graph dump finished"); neigh_dump_all(); } @@ -293,9 +295,9 @@ schedule_rtcalc(struct proto_ospf *po) } /** - * area_disp - invokes link-state database aging, origination of - * router LSA and routing table calculation - * @timer: it's called every @ospf_area->tick seconds + * area_disp - invokes origination of + * router LSA and routing table cleanup + * @oa: ospf area * * It invokes aging and when @ospf_area->origrt is set to 1, start * function for origination of router LSA and network LSAs. @@ -316,11 +318,13 @@ area_disp(struct ospf_area *oa) if (ifa->orignet && (ifa->oa == oa)) originate_net_lsa(ifa); } - - /* Age LSA DB */ - ospf_age(oa); } +/** + * ospf_disp - invokes routing table calctulation, aging and also area_disp() + * @timer: timer usually called every @proto_ospf->tick second, @timer->data + * point to @proto_ospf + */ void ospf_disp(timer * timer) { @@ -330,10 +334,12 @@ ospf_disp(timer * timer) WALK_LIST(oa, po->area_list) area_disp(oa); + /* Age LSA DB */ + ospf_age(po); + /* Calculate routing table */ if (po->calcrt) ospf_rt_spf (po); - po->calcrt = 0; } @@ -425,19 +431,19 @@ ospf_rt_notify(struct proto *p, net * n, rte * new, rte * old UNUSED, int max = max_ext_lsa(n->n.pxlen); /* Flush old external LSA */ - WALK_LIST(oa, po->area_list) + for (i = 0; i < max; i++, pr++) { - for (i = 0; i < max; i++, pr++) + if (en = ospf_hash_find(po->gr, 0, pr, rtid, LSA_T_EXT)) { - if (en = ospf_hash_find(oa->gr, pr, rtid, LSA_T_EXT)) + ext = en->lsa_body; + if (ipa_compare(ext->netmask, ipa_mkmask(n->n.pxlen)) == 0) { - ext = en->lsa_body; - if (ipa_compare(ext->netmask, ipa_mkmask(n->n.pxlen)) == 0) - { + WALK_LIST(oa, po->area_list) + { ospf_lsupd_flush_nlsa(en, oa); - break; } } + break; } } } @@ -830,6 +836,7 @@ ospf_sh(struct proto *p) cli_msg(-1014, "RFC1583 compatibility: %s", (po->rfc1583 ? "enable" : "disabled")); cli_msg(-1014, "RT scheduler tick: %d", po->tick); cli_msg(-1014, "Number of areas: %u", po->areano); + cli_msg(-1014, "Number of LSAs in DB:\t%u", po->gr->hash_entries); WALK_LIST(oa, po->area_list) { @@ -854,7 +861,6 @@ ospf_sh(struct proto *p) cli_msg(-1014, "\t\tStub:\t%s", oa->stub ? "Yes" : "No"); cli_msg(-1014, "\t\tTransit:\t%s", oa->trcap ? "Yes" : "No"); cli_msg(-1014, "\t\tNumber of interfaces:\t%u", ifano); - cli_msg(-1014, "\t\tNumber of LSAs in DB:\t%u", oa->gr->hash_entries); cli_msg(-1014, "\t\tNumber of neighbors:\t%u", nno); cli_msg(-1014, "\t\tNumber of adjacent neighbors:\t%u", adjno); diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index 40452c2b..8f0b4983 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -125,7 +125,6 @@ union options struct ospf_iface { node n; - struct proto_ospf *proto; struct iface *iface; /* Nest's iface */ struct ospf_area *oa; struct object_lock *lock; @@ -507,10 +506,7 @@ struct ospf_area { node n; u32 areaid; - timer *disp_timer; /* Area's dispatcher hear beat */ int origrt; /* Rt lsa origination scheduled? */ - struct top_graph *gr; /* LSA graph */ - slist lsal; /* List of all LSA's */ struct top_hash_entry *rt; /* My own router LSA */ list cand; /* List of candidates for RT calc. */ struct fib net_fib; /* Networks to advertise or not */ @@ -526,7 +522,10 @@ struct proto_ospf struct proto proto; timer *disp_timer; /* OSPF proto dispatcher */ unsigned tick; + struct top_graph *gr; /* LSA graph */ + slist lsal; /* List of all LSA's */ int calcrt; /* Routing table calculation scheduled? */ + int cleanup; /* Should I cleanup after RT calculation? */ list iface_list; /* Interfaces we really use */ list area_list; int areano; /* Number of area I belong to */ diff --git a/proto/ospf/packet.c b/proto/ospf/packet.c index 92e05226..5b0ad807 100644 --- a/proto/ospf/packet.c +++ b/proto/ospf/packet.c @@ -14,9 +14,7 @@ void ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type) { struct ospf_packet *pkt; - struct proto *p; - - p = (struct proto *) (ifa->proto); + struct proto *p = (struct proto *) (ifa->oa->po); pkt = (struct ospf_packet *) buf; @@ -40,7 +38,7 @@ ospf_pkt_maxsize(struct ospf_iface *ifa) void ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt) { - struct proto_ospf *po = ifa->proto; + struct proto_ospf *po = ifa->oa->po; struct proto *p = &po->proto; struct password_item *passwd = password_find (ifa->passwords); void *tail; @@ -97,7 +95,7 @@ static int ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, int size) { int i; - struct proto_ospf *po = ifa->proto; + struct proto_ospf *po = ifa->oa->po; struct proto *p = &po->proto; struct password_item *pass = NULL, *ptmp; void *tail; @@ -219,8 +217,8 @@ ospf_rx_hook(sock * sk, int size) { struct ospf_packet *ps; struct ospf_iface *ifa = (struct ospf_iface *) (sk->data); - struct proto_ospf *po = ifa->proto; - struct proto *p = (struct proto *) (ifa->proto); + struct proto_ospf *po = ifa->oa->po; + struct proto *p = &po->proto; struct ospf_neighbor *n; int osize; char *mesg = "Bad OSPF packet from "; @@ -356,24 +354,16 @@ ospf_rx_hook(sock * sk, int size) void ospf_tx_hook(sock * sk) { - struct ospf_iface *ifa; - struct proto *p; - - ifa = (struct ospf_iface *) (sk->data); - - p = (struct proto *) (ifa->proto); + struct ospf_iface *ifa= (struct ospf_iface *) (sk->data); + struct proto *p = (struct proto *) (ifa->oa->po); DBG("%s: TX_Hook called on interface %s\n", p->name, sk->iface->name); } void ospf_err_hook(sock * sk, int err UNUSED) { - struct ospf_iface *ifa; - struct proto *p; - - ifa = (struct ospf_iface *) (sk->data); - - p = (struct proto *) (ifa->proto); + struct ospf_iface *ifa= (struct ospf_iface *) (sk->data); + struct proto *p = (struct proto *) (ifa->oa->po); DBG("%s: Err_Hook called on interface %s\n", p->name, sk->iface->name); } diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index ef3d44da..a6db9ca4 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -13,7 +13,7 @@ add_cand(list * l, struct top_hash_entry *en, static void calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par, struct ospf_area *oa); -static void ospf_ext_spfa(struct ospf_area *oa); +static void ospf_ext_spf(struct proto_ospf *po); static void rt_sync(struct proto_ospf *po); static void @@ -231,7 +231,7 @@ ospf_rt_spfa(struct ospf_area *oa) break; case LSART_NET: - tmp = ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_NET); + tmp = ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_NET); if (tmp == NULL) DBG("Not found!\n"); else @@ -241,7 +241,7 @@ ospf_rt_spfa(struct ospf_area *oa) case LSART_VLNK: vlink = 1; case LSART_PTP: - tmp = ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_RT); + tmp = ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_RT); DBG("PTP found.\n"); break; default: @@ -272,7 +272,7 @@ ospf_rt_spfa(struct ospf_area *oa) sizeof(struct ospf_lsa_net)) / sizeof(u32); i++) { DBG(" Working on router %I ", *(rts + i)); - tmp = ospf_hash_find(oa->gr, *(rts + i), *(rts + i), LSA_T_RT); + tmp = ospf_hash_find(po->gr, oa->areaid, *(rts + i), *(rts + i), LSA_T_RT); if (tmp != NULL) DBG("Found :-)\n"); else @@ -288,7 +288,7 @@ ospf_rt_spfa(struct ospf_area *oa) { if ((iface->type == OSPF_IT_VLINK) && (iface->voa == oa)) { - if ((tmp = ospf_hash_find(oa->gr, iface->vid, iface->vid, LSA_T_RT)) && + if ((tmp = ospf_hash_find(po->gr, oa->areaid, iface->vid, iface->vid, LSA_T_RT)) && (!ipa_equal(tmp->lb, IPA_NONE))) { if ((iface->state != OSPF_IS_PTP) || (iface->iface != tmp->nhi) || (!ipa_equal(iface->vip, tmp->lb))) @@ -319,6 +319,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr struct ospf_lsa_net *ln; struct ospf_lsa_rt *rt; struct ospf_lsa_rt_link *rtl, *rr; + struct proto_ospf *po = oa->po; if(!pre) return 0; if(!fol) return 0; @@ -335,7 +336,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr case LSART_STUB: break; case LSART_NET: - if (ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_NET) == pre) + if (ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_NET) == pre) { fol->lb = ipa_from_u32(rtl->data); return 1; @@ -343,7 +344,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr break; case LSART_VLNK: case LSART_PTP: - if (ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_RT) == pre) + if (ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_RT) == pre) { fol->lb = ipa_from_u32(rtl->data); return 1; @@ -361,7 +362,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr for (i = 0; i < (fol->lsa.length - sizeof(struct ospf_lsa_header) - sizeof(struct ospf_lsa_net)) / sizeof(u32); i++) { - if (ospf_hash_find(oa->gr, *(rts + i), *(rts + i), LSA_T_RT) == pre) + if (ospf_hash_find(po->gr, oa->areaid, *(rts + i), *(rts + i), LSA_T_RT) == pre) { return 1; } @@ -388,8 +389,10 @@ ospf_rt_sum_tr(struct ospf_area *oa) if(!bb) return; - WALK_SLIST(en, oa->lsal) + WALK_SLIST(en, po->lsal) { + if (en->oa != oa) + continue; if (en->lsa.age == LSA_MAXAGE) continue; if (en->dist == LSINFINITY) @@ -398,7 +401,7 @@ ospf_rt_sum_tr(struct ospf_area *oa) if (en->lsa.rt == p->cf->global->router_id) continue; - if((en->lsa.type != LSA_T_SUM_RT) && (en->lsa.type != LSA_T_SUM_NET)) + if ((en->lsa.type != LSA_T_SUM_RT) && (en->lsa.type != LSA_T_SUM_NET)) continue; mask = (ip_addr *)en->lsa_body; @@ -457,8 +460,10 @@ ospf_rt_sum(struct ospf_area *oa) OSPF_TRACE(D_EVENTS, "Starting routing table calculation for inter-area routes"); - WALK_SLIST(en, oa->lsal) + WALK_SLIST(en, po->lsal) { + if (en->oa != oa) + continue; /* Page 169 (1) */ if (en->lsa.age == LSA_MAXAGE) continue; @@ -528,6 +533,8 @@ ospf_rt_spf(struct proto_ospf *po) if (po->areano == 0) return; + po->cleanup = 1; + OSPF_TRACE(D_EVENTS, "Starting routing table calculation"); /* Invalidate old routing table */ @@ -580,20 +587,16 @@ ospf_rt_spf(struct proto_ospf *po) } } - WALK_LIST(oa, po->area_list) - { - if (!oa->stub) - { - ospf_ext_spfa(oa); - break; - } - } + ospf_ext_spf(po); + rt_sync(po); + + po->calcrt = 0; } /** - * ospf_ext_spfa - calculate external paths + * ospf_ext_spf - calculate external paths * @po: protocol * * After routing table for any area is calculated, calculation of external @@ -601,9 +604,8 @@ ospf_rt_spf(struct proto_ospf *po) * Inter- and Intra-area paths are always prefered over externals. */ static void -ospf_ext_spfa(struct ospf_area *oa) +ospf_ext_spf(struct proto_ospf *po) { - struct proto_ospf *po = oa->po; ort *nf1, *nf2, *nfh; orta nfa; struct top_hash_entry *en; @@ -621,7 +623,7 @@ ospf_ext_spfa(struct ospf_area *oa) OSPF_TRACE(D_EVENTS, "Starting routing table calculation for ext routes"); - WALK_SLIST(en, oa->lsal) + WALK_SLIST(en, po->lsal) { if (en->lsa.type != LSA_T_EXT) continue; @@ -729,7 +731,7 @@ ospf_ext_spfa(struct ospf_area *oa) nfa.capa = 0; nfa.metric1 = met1; nfa.metric2 = met2; - nfa.oa = oa; + nfa.oa = NULL; nfa.ar = nf1->n.ar; nfa.nh = nh; nfa.ifa = nhi; @@ -941,7 +943,7 @@ again1: { if ((ifa->type == OSPF_IT_VLINK) && ipa_equal(ifa->vip, nf->n.nh)) { - if ((en = ospf_hash_find(ifa->voa->gr, ifa->vid, ifa->vid, LSA_T_RT)) && + if ((en = ospf_hash_find(po->gr, ifa->voa->areaid, ifa->vid, ifa->vid, LSA_T_RT)) && (!ipa_equal(en->nh, IPA_NONE))) { a0.gw = en->nh; diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 48547214..b0c97b33 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -159,7 +159,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length) default: ln--; i--; /* No link added */ - log("Unknown interface type"); + log("Unknown interface type %s", ifa->iface->name); break; } } @@ -217,7 +217,6 @@ originate_rt_lsa(struct ospf_area *oa) lsasum_calculate(&lsa, body); en = lsa_install_new(&lsa, body, oa); oa->rt = en; - en->dist = 0; /* Force area aging */ ospf_lsupd_flood(NULL, NULL, &oa->rt->lsa, NULL, oa, 1); schedule_rtcalc(po); oa->origrt = 0; @@ -264,7 +263,7 @@ originate_net_lsa_body(struct ospf_iface *ifa, u16 * length, void originate_net_lsa(struct ospf_iface *ifa) { - struct proto_ospf *po = ifa->proto; + struct proto_ospf *po = ifa->oa->po; struct ospf_lsa_header lsa; u32 rtid = po->proto.cf->global->router_id; struct proto *p = &po->proto; @@ -291,7 +290,7 @@ originate_net_lsa(struct ospf_iface *ifa) if (ifa->nlsa->lsa_body != NULL) mb_free(ifa->nlsa->lsa_body); ifa->nlsa->lsa_body = NULL; - ospf_hash_delete(ifa->oa->gr, ifa->nlsa); + ospf_hash_delete(po->gr, ifa->nlsa); schedule_rtcalc(po); ifa->nlsa = NULL; return; @@ -411,7 +410,7 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type) for (i = 0; i < max; i++) { lsa.id = ipa_to_u32(fn->prefix) + i; - if ((en = ospf_hash_find_header(oa->gr, &lsa)) != NULL) + if ((en = ospf_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL) { sum = en->lsa_body; if (fn->pxlen == ipa_mklen(sum->netmask)) @@ -421,7 +420,7 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type) lsasum_calculate(&en->lsa, sum); OSPF_TRACE(D_EVENTS, "Flushing summary lsa. (id=%I, type=%d)", en->lsa.id, en->lsa.type); ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1); - if (can_flush_lsa(oa)) flush_lsa(en, oa); + if (can_flush_lsa(po)) flush_lsa(en, po); break; } } @@ -458,7 +457,7 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri for (i = 0; i < max; i++) { lsa.id = ipa_to_u32(fn->prefix) + i; - if ((en = ospf_hash_find_header(oa->gr, &lsa)) == NULL) + if ((en = ospf_hash_find_header(po->gr, oa->areaid, &lsa)) == NULL) { if (!free) free = lsa.id; } @@ -590,11 +589,9 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po, ext1 = body; max = max_ext_lsa(n->n.pxlen); - oa = HEAD(po->area_list); - for (i = 0; i < max; i++) { - if ((en = ospf_hash_find_header(oa->gr, &lsa)) != NULL) + if ((en = ospf_hash_find_header(po->gr, 0 , &lsa)) != NULL) { ext2 = en->lsa_body; if (ipa_compare(ext1->netmask, ext2->netmask) != 0) @@ -672,16 +669,16 @@ ospf_top_hash_u32(u32 a) } static inline unsigned -ospf_top_hash(struct top_graph *f, u32 lsaid, u32 rtrid, u32 type) +ospf_top_hash(struct top_graph *f, u32 areaid, u32 lsaid, u32 rtrid, u32 type) { #if 1 /* Dirty patch to make rt table calculation work. */ return (ospf_top_hash_u32(lsaid) + ospf_top_hash_u32((type == - LSA_T_NET) ? lsaid : rtrid) + - type) & f->hash_mask; + LSA_T_NET) ? lsaid : rtrid) + type + + (type == LSA_T_EXT ? 0 : areaid)) & f->hash_mask; #else return (ospf_top_hash_u32(lsaid) + ospf_top_hash_u32(rtrid) + - type) & f->hash_mask; + type + areaid) & f->hash_mask; #endif } @@ -735,7 +732,7 @@ ospf_top_rehash(struct top_graph *f, int step) while (e) { x = e->next; - n = newt + ospf_top_hash(f, e->lsa.id, e->lsa.rt, e->lsa.type); + n = newt + ospf_top_hash(f, e->oa->areaid, e->lsa.id, e->lsa.rt, e->lsa.type); e->next = *n; *n = e; e = x; @@ -745,49 +742,65 @@ ospf_top_rehash(struct top_graph *f, int step) } struct top_hash_entry * -ospf_hash_find_header(struct top_graph *f, struct ospf_lsa_header *h) +ospf_hash_find_header(struct top_graph *f, u32 areaid, struct ospf_lsa_header *h) { - return ospf_hash_find(f, h->id, h->rt, h->type); + return ospf_hash_find(f, areaid, h->id, h->rt, h->type); } struct top_hash_entry * -ospf_hash_get_header(struct top_graph *f, struct ospf_lsa_header *h) +ospf_hash_get_header(struct top_graph *f, struct ospf_area *oa, struct ospf_lsa_header *h) { - return ospf_hash_get(f, h->id, h->rt, h->type); + return ospf_hash_get(f, oa, h->id, h->rt, h->type); } struct top_hash_entry * -ospf_hash_find(struct top_graph *f, u32 lsa, u32 rtr, u32 type) +ospf_hash_find(struct top_graph *f, u32 areaid, u32 lsa, u32 rtr, u32 type) { - struct top_hash_entry *e = f->hash_table[ospf_top_hash(f, lsa, rtr, type)]; + struct top_hash_entry *e; -#if 1 /* Dirty patch to make rt table calculation work. */ + e = f->hash_table[ospf_top_hash(f, areaid, lsa, rtr, type)]; + + /* Dirty patch to make rt table calculation work. */ if (type == LSA_T_NET) { - while (e && (e->lsa.id != lsa || e->lsa.type != LSA_T_NET)) + while (e && (e->lsa.id != lsa || e->lsa.type != LSA_T_NET || e->oa->areaid != areaid)) e = e->next; } - else + else if (type == LSA_T_EXT) { while (e && (e->lsa.id != lsa || e->lsa.type != type || e->lsa.rt != rtr)) e = e->next; } -#else - while (e && (e->lsa.id != lsa || e->lsa.rt != rtr || e->lsa.type != type)) - e = e->next; -#endif + else + { + while (e && (e->lsa.id != lsa || e->lsa.type != type || e->lsa.rt != rtr || e->oa->areaid != areaid)) + e = e->next; + } + return e; } struct top_hash_entry * -ospf_hash_get(struct top_graph *f, u32 lsa, u32 rtr, u32 type) +ospf_hash_get(struct top_graph *f, struct ospf_area *oa, u32 lsa, u32 rtr, u32 type) { - struct top_hash_entry **ee = - f->hash_table + ospf_top_hash(f, lsa, rtr, type); - struct top_hash_entry *e = *ee; + struct top_hash_entry **ee; + struct top_hash_entry *e; + u32 nareaid = (type == LSA_T_EXT ? 0 : oa->areaid); + + ee = f->hash_table + ospf_top_hash(f, nareaid, lsa, rtr, type); + e = *ee; + + if (type == LSA_T_EXT) + { + while (e && (e->lsa.id != lsa || e->lsa.rt != rtr || e->lsa.type != type)) + e = e->next; + } + else + { + while (e && (e->lsa.id != lsa || e->lsa.rt != rtr || e->lsa.type != type || e->oa->areaid != nareaid)) + e = e->next; + } - while (e && (e->lsa.id != lsa || e->lsa.rt != rtr || e->lsa.type != type)) - e = e->next; if (e) return e; @@ -802,6 +815,7 @@ ospf_hash_get(struct top_graph *f, u32 lsa, u32 rtr, u32 type) e->lsa.type = type; e->lsa_body = NULL; e->nhi = NULL; + e->oa = oa; e->next = *ee; *ee = e; if (f->hash_entries++ > f->hash_entries_max) @@ -812,8 +826,8 @@ ospf_hash_get(struct top_graph *f, u32 lsa, u32 rtr, u32 type) void ospf_hash_delete(struct top_graph *f, struct top_hash_entry *e) { - unsigned int h = ospf_top_hash(f, e->lsa.id, e->lsa.rt, e->lsa.type); - struct top_hash_entry **ee = f->hash_table + h; + struct top_hash_entry **ee = f->hash_table + + ospf_top_hash(f, e->oa->areaid, e->lsa.id, e->lsa.rt, e->lsa.type); while (*ee) { @@ -833,7 +847,7 @@ ospf_hash_delete(struct top_graph *f, struct top_hash_entry *e) void ospf_top_dump(struct top_graph *f, struct proto *p) { - unsigned int i; + unsigned int i; /* FIXME: Print areaids */ OSPF_TRACE(D_EVENTS, "Hash entries: %d", f->hash_entries); for (i = 0; i < f->hash_size; i++) @@ -856,22 +870,18 @@ ospf_top_dump(struct top_graph *f, struct proto *p) */ int -can_flush_lsa(struct ospf_area *oa) +can_flush_lsa(struct proto_ospf *po) { struct ospf_iface *ifa; struct ospf_neighbor *n; - WALK_LIST(ifa, iface_list) + WALK_LIST(ifa, po->iface_list) { - if (ifa->oa == oa) + WALK_LIST(n, ifa->neigh_list) { - WALK_LIST(n, ifa->neigh_list) - { - if ((n->state == NEIGHBOR_EXCHANGE) || (n->state == NEIGHBOR_LOADING)) - { - return 0; - } - } + if ((n->state == NEIGHBOR_EXCHANGE) || (n->state == NEIGHBOR_LOADING)) + return 0; + break; } } diff --git a/proto/ospf/topology.h b/proto/ospf/topology.h index c6031c5e..bccff056 100644 --- a/proto/ospf/topology.h +++ b/proto/ospf/topology.h @@ -18,6 +18,7 @@ struct top_hash_entry */ struct top_hash_entry *next; /* Next in hash chain */ struct ospf_lsa_header lsa; + struct ospf_area *oa; void *lsa_body; bird_clock_t inst_t; /* Time of installation into DB */ ip_addr nh; /* Next hop */ @@ -47,18 +48,18 @@ struct top_graph struct top_graph *ospf_top_new(pool *); void ospf_top_free(struct top_graph *); void ospf_top_dump(struct top_graph *, struct proto *); -struct top_hash_entry *ospf_hash_find_header(struct top_graph *f, +struct top_hash_entry *ospf_hash_find_header(struct top_graph *f, u32 areaid, struct ospf_lsa_header *h); -struct top_hash_entry *ospf_hash_get_header(struct top_graph *f, +struct top_hash_entry *ospf_hash_get_header(struct top_graph *f, struct ospf_area *oa, struct ospf_lsa_header *h); -struct top_hash_entry *ospf_hash_find(struct top_graph *, u32 lsa, u32 rtr, +struct top_hash_entry *ospf_hash_find(struct top_graph *, u32 areaid, u32 lsa, u32 rtr, u32 type); -struct top_hash_entry *ospf_hash_get(struct top_graph *, u32 lsa, u32 rtr, +struct top_hash_entry *ospf_hash_get(struct top_graph *, struct ospf_area *oa, u32 lsa, u32 rtr, u32 type); void ospf_hash_delete(struct top_graph *, struct top_hash_entry *); void originate_rt_lsa(struct ospf_area *oa); void originate_net_lsa(struct ospf_iface *ifa); -int can_flush_lsa(struct ospf_area *oa); +int can_flush_lsa(struct proto_ospf *po); int max_ext_lsa(unsigned pxlen); void originate_ext_lsa(net * n, rte * e, struct proto_ospf *po, struct ea_list *attrs);