summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Filip <feela@network.cz>2004-07-15 18:37:52 +0200
committerOndrej Filip <feela@network.cz>2004-07-15 18:37:52 +0200
commit86c84d76b706e77ec5977a3c9e300b0fca9f6b10 (patch)
tree77663b13c8f4741893df9d4334c032c848820c46
parent777acf91bb0d8ca0f33f367ae5fa00f46dde5a9a (diff)
downloadbird-86c84d76b706e77ec5977a3c9e300b0fca9f6b10.tar
bird-86c84d76b706e77ec5977a3c9e300b0fca9f6b10.zip
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.
-rw-r--r--TODO1
-rw-r--r--proto/ospf/config.Y2
-rw-r--r--proto/ospf/dbdes.c40
-rw-r--r--proto/ospf/hello.c5
-rw-r--r--proto/ospf/iface.c25
-rw-r--r--proto/ospf/lsack.c6
-rw-r--r--proto/ospf/lsalib.c38
-rw-r--r--proto/ospf/lsalib.h4
-rw-r--r--proto/ospf/lsreq.c8
-rw-r--r--proto/ospf/lsupd.c47
-rw-r--r--proto/ospf/neighbor.c27
-rw-r--r--proto/ospf/ospf.c62
-rw-r--r--proto/ospf/ospf.h7
-rw-r--r--proto/ospf/packet.c28
-rw-r--r--proto/ospf/rt.c52
-rw-r--r--proto/ospf/topology.c104
-rw-r--r--proto/ospf/topology.h11
17 files changed, 233 insertions, 234 deletions
diff --git a/TODO b/TODO
index b669336..f0c60b6 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 bd3a2e5..4a62549 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 6e84edd..7f181fb 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 350bad7..58d1423 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 5a10cde..68b6377 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 14832b8..bb1afa0 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 b244c3f..af3f743 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 43f9513..c7f16d5 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 64f1082..3c8b722 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 51b38af..c619442 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 869db2b..af6b853 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 8f6b217..e9e45d7 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 40452c2..8f0b498 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 92e0522..5b0ad80 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 ef3d44d..a6db9ca 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 4854721..b0c97b3 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 c6031c5..bccff05 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);