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.
This commit is contained in:
Ondrej Filip 2004-07-15 16:37:52 +00:00
parent 777acf91bb
commit 86c84d76b7
17 changed files with 233 additions and 234 deletions

1
TODO
View file

@ -49,5 +49,4 @@ OSPF
- automatic generation of external route tags (RFC1403) - automatic generation of external route tags (RFC1403)
- RFC1587 NSSA areas - RFC1587 NSSA areas
- RFC2370 opaque LSA's - RFC2370 opaque LSA's
- AS external LSAs are in topology database of every OSPF Area
- Limit export rate of external LSAs (like Gated does) - Limit export rate of external LSAs (like Gated does)

View file

@ -104,7 +104,6 @@ ospf_vlink_item:
ospf_vlink_start: VIRTUAL LINK idval ospf_vlink_start: VIRTUAL LINK idval
{ {
log("Vlink start");
if (this_area->areaid == 0) cf_error("Virtual link cannot be in backbone"); if (this_area->areaid == 0) cf_error("Virtual link cannot be in backbone");
this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt)); this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt));
add_tail(&this_area->vlink_list, NODE this_ipatt); add_tail(&this_area->vlink_list, NODE this_ipatt);
@ -200,7 +199,6 @@ ipa_ne: IPA ELIGIBLE ';'
ospf_iface_start: ospf_iface_start:
{ {
log("Iface start");
this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt)); this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt));
add_tail(&this_area->patt_list, NODE this_ipatt); add_tail(&this_area->patt_list, NODE this_ipatt);
OSPF_PATT->cost = COST_D; OSPF_PATT->cost = COST_D;

View file

@ -25,11 +25,11 @@ ospf_dbdes_send(struct ospf_neighbor *n)
struct ospf_packet *op; struct ospf_packet *op;
struct ospf_iface *ifa = n->ifa; struct ospf_iface *ifa = n->ifa;
struct ospf_area *oa = ifa->oa; struct ospf_area *oa = ifa->oa;
u16 length; struct proto_ospf *po = oa->po;
struct proto *p = (struct proto *) (ifa->proto); struct proto *p = &po->proto;
u16 i, j; u16 length, i, j;
if ((oa->rt == NULL) || (EMPTY_LIST(oa->lsal))) if ((oa->rt == NULL) || (EMPTY_LIST(po->lsal)))
originate_rt_lsa(oa); originate_rt_lsa(oa);
switch (n->state) switch (n->state)
@ -40,7 +40,7 @@ ospf_dbdes_send(struct ospf_neighbor *n)
op = (struct ospf_packet *) pkt; op = (struct ospf_packet *) pkt;
ospf_pkt_fill_hdr(ifa, pkt, DBDES_P); ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
pkt->iface_mtu = htons(ifa->iface->mtu); pkt->iface_mtu = htons(ifa->iface->mtu);
pkt->options = ifa->oa->opt.byte; pkt->options = oa->opt.byte;
pkt->imms = n->myimms; pkt->imms = n->myimms;
pkt->ddseq = htonl(n->dds); pkt->ddseq = htonl(n->dds);
length = sizeof(struct ospf_dbdes_packet); 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); ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
pkt->iface_mtu = htons(ifa->iface->mtu); pkt->iface_mtu = htons(ifa->iface->mtu);
pkt->options = ifa->oa->opt.byte; pkt->options = oa->opt.byte;
pkt->ddseq = htonl(n->dds); 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 */ 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); DBG("Number of LSA: %d\n", j);
for (; i > 0; i--) for (; i > 0; i--)
{ {
struct top_hash_entry *en; struct top_hash_entry *en= (struct top_hash_entry *) sn;
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); htonlsah(&(en->lsa), lsa);
DBG("Working on: %d\n", i); DBG("Working on: %d\n", i);
@ -91,7 +98,7 @@ ospf_dbdes_send(struct ospf_neighbor *n)
} }
else i++; /* No lsa added */ else i++; /* No lsa added */
if (sn == STAIL(n->ifa->oa->lsal)) if (sn == STAIL(po->lsal))
{ {
i--; i--;
break; break;
@ -100,7 +107,7 @@ ospf_dbdes_send(struct ospf_neighbor *n)
sn = sn->next; 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("Number of LSA NOT sent: %d\n", i);
DBG("M bit unset.\n"); 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 ospf_lsa_header *plsa, lsa;
struct top_hash_entry *he, *sn; 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; struct ospf_packet *op;
int i, j; 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++) for (i = 0; i < j; i++)
{ {
ntohlsah(plsa + i, &lsa); 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)) (lsa_comp(&lsa, &(he->lsa)) == 1))
{ {
/* Is this condition necessary? */ /* 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)); ntohlsah(plsa + i, &(sn->lsa));
s_add_tail(&(n->lsrql), SNODE sn); s_add_tail(&(n->lsrql), SNODE sn);
} }
@ -195,7 +203,7 @@ void
ospf_dbdes_receive(struct ospf_dbdes_packet *ps, ospf_dbdes_receive(struct ospf_dbdes_packet *ps,
struct ospf_iface *ifa, struct ospf_neighbor *n) 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; u32 myrid = p->cf->global->router_id;
unsigned int size = ntohs(ps->ospf_packet.length); unsigned int size = ntohs(ps->ospf_packet.length);

View file

@ -16,7 +16,7 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
ip_addr olddr, oldbdr; ip_addr olddr, oldbdr;
ip_addr mask; ip_addr mask;
char *beg = "Bad OSPF hello packet from ", *rec = " received: "; 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; 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, 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; u32 *pp;
int i, send; int i, send;
struct nbma_node *nb; struct nbma_node *nb;
if (timer == NULL) if (timer == NULL)
ifa = dirn->ifa; ifa = dirn->ifa;
else else
@ -183,7 +184,7 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
if (ifa->stub) if (ifa->stub)
return; /* Don't send any packet on stub iface */ 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", DBG("%s: Hello/Poll timer fired on interface %s.\n",
p->name, ifa->iface->name); p->name, ifa->iface->name);
/* Now we should send a hello packet */ /* Now we should send a hello packet */

View file

@ -35,7 +35,7 @@ static void
wait_timer_hook(timer * timer) wait_timer_hook(timer * timer)
{ {
struct ospf_iface *ifa = (struct ospf_iface *) timer->data; 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_TRACE(D_EVENTS, "Wait timer fired on interface %s.", ifa->iface->name);
ospf_iface_sm(ifa, ISM_WAITF); ospf_iface_sm(ifa, ISM_WAITF);
@ -45,9 +45,7 @@ static sock *
ospf_open_ip_socket(struct ospf_iface *ifa) ospf_open_ip_socket(struct ospf_iface *ifa)
{ {
sock *ipsk; sock *ipsk;
struct proto *p; struct proto *p = &ifa->oa->po->proto;
p = (struct proto *) (ifa->proto);
ipsk = sk_new(p->pool); ipsk = sk_new(p->pool);
ipsk->type = SK_IP; ipsk->type = SK_IP;
@ -86,7 +84,7 @@ ospf_open_ip_socket(struct ospf_iface *ifa)
void void
ospf_iface_chstate(struct ospf_iface *ifa, u8 state) 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; struct proto *p = &po->proto;
u8 oldstate = ifa->state; 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); ospf_lsupd_flush_nlsa(ifa->nlsa, ifa->oa);
} }
if (can_flush_lsa(ifa->oa)) if (can_flush_lsa(po))
flush_lsa(ifa->nlsa, ifa->oa); flush_lsa(ifa->nlsa, po);
ifa->nlsa = NULL; ifa->nlsa = NULL;
} }
} }
@ -162,8 +160,8 @@ static void
ospf_iface_down(struct ospf_iface *ifa) ospf_iface_down(struct ospf_iface *ifa)
{ {
struct ospf_neighbor *n, *nx; struct ospf_neighbor *n, *nx;
struct proto *p = &ifa->proto->proto; struct proto_ospf *po = ifa->oa->po;
struct proto_ospf *po = ifa->proto; struct proto *p = &po->proto;
struct ospf_iface *iff; struct ospf_iface *iff;
/* First of all kill all the related vlinks */ /* First of all kill all the related vlinks */
@ -287,9 +285,7 @@ static sock *
ospf_open_mc_socket(struct ospf_iface *ifa) ospf_open_mc_socket(struct ospf_iface *ifa)
{ {
sock *mcsk; sock *mcsk;
struct proto *p; struct proto *p = &ifa->oa->po->proto;
p = (struct proto *) (ifa->proto);
mcsk = sk_new(p->pool); mcsk = sk_new(p->pool);
mcsk->type = SK_IP_MC; mcsk->type = SK_IP_MC;
@ -342,9 +338,9 @@ static void
ospf_iface_add(struct object_lock *lock) ospf_iface_add(struct object_lock *lock)
{ {
struct ospf_iface *ifa = lock->data; struct ospf_iface *ifa = lock->data;
struct proto_ospf *po = ifa->proto; struct proto_ospf *po = ifa->oa->po;
struct iface *iface = lock->iface;
struct proto *p = &po->proto; struct proto *p = &po->proto;
struct iface *iface = lock->iface;
ifa->lock = lock; ifa->lock = lock;
@ -387,7 +383,6 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface,
struct ospf_area *oa; struct ospf_area *oa;
ifa = mb_allocz(p->pool, sizeof(struct ospf_iface)); ifa = mb_allocz(p->pool, sizeof(struct ospf_iface));
ifa->proto = po;
ifa->iface = iface; ifa->iface = iface;
ifa->cost = ip->cost; ifa->cost = ip->cost;

View file

@ -37,7 +37,7 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
struct ospf_lsa_header *h; struct ospf_lsa_header *h;
struct lsah_n *no; struct lsah_n *no;
struct ospf_iface *ifa = n->ifa; 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])) if (EMPTY_LIST(n->ackl[queue]))
return; return;
@ -122,7 +122,7 @@ ospf_lsack_receive(struct ospf_lsack_packet *ps,
struct ospf_lsa_header lsa, *plsa; struct ospf_lsa_header lsa, *plsa;
u16 nolsa; u16 nolsa;
struct top_hash_entry *en; 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; unsigned int size = ntohs(ps->ospf_packet.length), i;
OSPF_TRACE(D_PACKETS, "Received LS ack from %I", n->ip); 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++) for (i = 0; i < nolsa; i++)
{ {
ntohlsah(plsa + i, &lsa); 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 */ continue; /* pg 155 */
if (lsa_comp(&lsa, &en->lsa) != CMP_SAME) /* pg 156 */ if (lsa_comp(&lsa, &en->lsa) != CMP_SAME) /* pg 156 */

View file

@ -9,9 +9,10 @@
#include "ospf.h" #include "ospf.h"
void 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, OSPF_TRACE(D_EVENTS,
"Going to remove node Type: %u, Id: %I, Rt: %I, Age: %u, SN: 0x%x", "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); 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) if (en->lsa_body != NULL)
mb_free(en->lsa_body); mb_free(en->lsa_body);
en->lsa_body = NULL; en->lsa_body = NULL;
ospf_hash_delete(oa->gr, en); ospf_hash_delete(po->gr, en);
} }
/** /**
* ospf_age * 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 * 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 * whenever possible. If an LSA originated by the router itself is older
* than %LSREFRESHTIME a new instance is originated. * 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. * table calculation results.
*/ */
void void
ospf_age(struct ospf_area *oa) ospf_age(struct proto_ospf *po)
{ {
struct proto *p = &oa->po->proto; struct proto *p = &po->proto;
struct proto_ospf *po = (struct proto_ospf *) p;
struct top_hash_entry *en, *nxt; struct top_hash_entry *en, *nxt;
int flush = can_flush_lsa(oa); int flush = can_flush_lsa(po);
int cleanup = (oa->rt && (oa->rt->dist != LSINFINITY));
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->color = OUTSPF;
en->dist = LSINFINITY; en->dist = LSINFINITY;
@ -63,7 +62,7 @@ ospf_age(struct ospf_area *oa)
if (en->lsa.age == LSA_MAXAGE) if (en->lsa.age == LSA_MAXAGE)
{ {
if (flush) if (flush)
flush_lsa(en, oa); flush_lsa(en, po);
continue; continue;
} }
if ((en->lsa.rt == p->cf->global->router_id) &&(en->lsa.age >= 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->inst_t = now;
en->ini_age = 0; en->ini_age = 0;
lsasum_calculate(&en->lsa, en->lsa_body); 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; continue;
} }
if ((en->lsa.age = (en->ini_age + (now - en->inst_t))) >= LSA_MAXAGE) if ((en->lsa.age = (en->ini_age + (now - en->inst_t))) >= LSA_MAXAGE)
{ {
if (flush) if (flush)
{ {
flush_lsa(en, oa); flush_lsa(en, po);
schedule_rtcalc(po); schedule_rtcalc(po);
} }
else else
en->lsa.age = LSA_MAXAGE; en->lsa.age = LSA_MAXAGE;
} }
} }
po->cleanup = 0;
} }
void 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 top_hash_entry *en;
struct proto_ospf *po = oa->po; 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; change = 1;
} }
else 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", 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); 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; en->inst_t = now;
if (en->lsa_body != NULL) if (en->lsa_body != NULL)
mb_free(en->lsa_body); mb_free(en->lsa_body);

View file

@ -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); 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, struct top_hash_entry *lsa_install_new(struct ospf_lsa_header *lsa,
void *body, struct ospf_area *oa); void *body, struct ospf_area *oa);
void ospf_age(struct ospf_area *oa); void ospf_age(struct proto_ospf *po);
void flush_lsa(struct top_hash_entry *en, struct ospf_area *oa); void flush_lsa(struct top_hash_entry *en, struct proto_ospf *po);
#endif /* _BIRD_OSPF_LSALIB_H_ */ #endif /* _BIRD_OSPF_LSALIB_H_ */

View file

@ -18,7 +18,7 @@ ospf_lsreq_send(struct ospf_neighbor *n)
struct ospf_lsreq_header *lsh; struct ospf_lsreq_header *lsh;
u16 length; u16 length;
int i, j; 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; pk = (struct ospf_lsreq_packet *) n->ifa->ip_sk->tbuf;
op = (struct ospf_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; slab *upslab;
unsigned int size = ntohs(ps->ospf_packet.length); unsigned int size = ntohs(ps->ospf_packet.length);
int i, lsano; 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) if (n->state < NEIGHBOR_EXCHANGE)
return; return;
@ -96,7 +98,7 @@ ospf_lsreq_receive(struct ospf_lsreq_packet *ps,
llsh->lsh.rt = ntohl(lsh->rt); llsh->lsh.rt = ntohl(lsh->rt);
llsh->lsh.type = lsh->type; llsh->lsh.type = lsh->type;
add_tail(&uplist, NODE llsh); 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) llsh->lsh.type) == NULL)
{ {
log(L_WARN log(L_WARN

View file

@ -13,7 +13,6 @@
* @n: neighbor than sent this lsa (or NULL if generated) * @n: neighbor than sent this lsa (or NULL if generated)
* @hn: LSA header followed by lsa body in network endianity (may be NULL) * @hn: LSA header followed by lsa body in network endianity (may be NULL)
* @hh: LSA header in host endianity (must be filled) * @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) * @iff: interface which received this LSA (or NULL if LSA is generated)
* @oa: ospf_area which is the LSA generated for * @oa: ospf_area which is the LSA generated for
* @rtl: add this LSA into retransmission list * @rtl: add this LSA into retransmission list
@ -48,16 +47,8 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
} }
else else
{ {
if (oa->areaid == BACKBONE) if (ifa->oa != oa)
{ continue;
if ((ifa->type != OSPF_IT_VLINK) && (ifa->oa != oa))
continue;
}
else
{
if (ifa->oa != oa)
continue;
}
} }
ret = 0; ret = 0;
WALK_LIST(NODE nn, ifa->neigh_list) WALK_LIST(NODE nn, ifa->neigh_list)
@ -66,7 +57,7 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
continue; continue;
if (nn->state < NEIGHBOR_FULL) 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)) 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 (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 else
{ {
@ -120,7 +111,7 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
} }
else 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); s_rem_node(SNODE en);
if (en->lsa_body != NULL) if (en->lsa_body != NULL)
@ -177,7 +168,7 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
htonlsah(hh, lh); htonlsah(hh, lh);
help = (u8 *) (lh + 1); 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 htonlsab(en->lsa_body, help, hh->type, hh->length
- sizeof(struct ospf_lsa_header)); - 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 top_hash_entry *en;
struct ospf_lsupd_packet *pk; struct ospf_lsupd_packet *pk;
struct ospf_packet *op; 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; void *pktpos;
if (EMPTY_LIST(*l)) if (EMPTY_LIST(*l))
@ -247,7 +240,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
WALK_LIST(llsh, *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) llsh->lsh.type)) == NULL)
continue; /* Probably flushed LSA */ continue; /* Probably flushed LSA */
/* FIXME This is a bug! I cannot flush LSA that is in lsrt */ /* 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_neighbor *ntmp;
struct ospf_lsa_header *lsa; struct ospf_lsa_header *lsa;
struct ospf_area *oa; struct ospf_area *oa;
struct proto_ospf *po = ifa->proto; struct proto_ospf *po = ifa->oa->po;
struct proto *p = (struct proto *) po; struct proto *p = &po->proto;
unsigned int i, sendreq = 1, size = ntohs(ps->ospf_packet.length); unsigned int i, sendreq = 1, size = ntohs(ps->ospf_packet.length);
if (n->state < NEIGHBOR_EXCHANGE) 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.type, lsatmp.id, lsatmp.rt, lsatmp.sn, lsatmp.age,
lsatmp.checksum); lsatmp.checksum);
lsadb = ospf_hash_find_header(oa->gr, &lsatmp); lsadb = ospf_hash_find_header(po->gr, oa->areaid, &lsatmp);
#ifdef LOCAL_DEBUG #ifdef LOCAL_DEBUG
if (lsadb) if (lsadb)
@ -382,7 +375,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
#endif #endif
/* pg 143 (4) */ /* 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); ospf_lsack_enqueue(n, lsa, ACKL_DIRECT);
continue; continue;
@ -433,7 +426,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
lsasum_check(lsa, (lsa + 1)); /* It also calculates chsum! */ lsasum_check(lsa, (lsa + 1)); /* It also calculates chsum! */
lsatmp.checksum = ntohs(lsa->checksum); lsatmp.checksum = ntohs(lsa->checksum);
ospf_lsupd_flood(NULL, lsa, &lsatmp, NULL, oa, 0); 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); 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; struct top_hash_entry *en;
if (ntmp->state > NEIGHBOR_EXSTART) 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); s_rem_node(SNODE en);
if (en->lsa_body != NULL) 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) 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); schedule_rtcalc(po);
continue; continue;
} /* FIXME lsack? */ } /* FIXME lsack? */
@ -504,7 +497,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
{ {
struct top_hash_entry *en; struct top_hash_entry *en;
DBG("PG145(7) Got the same LSA\n"); 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) */ /* pg145 (7a) */
s_rem_node(SNODE en); s_rem_node(SNODE en);

View file

@ -33,7 +33,7 @@ void ackd_timer_hook(timer * t);
struct ospf_neighbor * struct ospf_neighbor *
ospf_neighbor_new(struct ospf_iface *ifa) 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 pool *pool = rp_new(p->pool, "OSPF Neighbor");
struct ospf_neighbor *n = mb_allocz(pool, sizeof(struct 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; int i;
ifa = n->ifa; ifa = n->ifa;
p = (struct proto *) (ifa->proto); p = (struct proto *) (ifa->oa->po);
i = 0; i = 0;
switch (ifa->type) switch (ifa->type)
@ -289,8 +289,8 @@ can_do_adj(struct ospf_neighbor *n)
void void
ospf_neigh_sm(struct ospf_neighbor *n, int event) ospf_neigh_sm(struct ospf_neighbor *n, int event)
{ {
struct proto_ospf *po = n->ifa->proto; struct proto_ospf *po = n->ifa->oa->po;
struct proto *p = (struct proto *) po; struct proto *p = &po->proto;
DBG("Neighbor state machine for neighbor %I, event \"%s\".", n->ip, DBG("Neighbor state machine for neighbor %I, event \"%s\".", n->ip,
ospf_inm[event]); ospf_inm[event]);
@ -322,7 +322,7 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event)
if (n->state == NEIGHBOR_EXSTART) if (n->state == NEIGHBOR_EXSTART)
{ {
neigh_chstate(n, NEIGHBOR_EXCHANGE); 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])) while (!EMPTY_LIST(n->ackl[ACKL_DELAY]))
{ {
struct lsah_n *no; struct lsah_n *no;
@ -396,7 +396,7 @@ bdr_election(struct ospf_iface *ifa)
u32 myid; u32 myid;
ip_addr ndrip, nbdrip; ip_addr ndrip, nbdrip;
int doadj; int doadj;
struct proto *p = &ifa->proto->proto; struct proto *p = &ifa->oa->po->proto;
DBG("(B)DR election.\n"); DBG("(B)DR election.\n");
@ -541,13 +541,10 @@ ospf_find_area(struct proto_ospf *po, u32 aid)
void void
neighbor_timer_hook(timer * timer) neighbor_timer_hook(timer * timer)
{ {
struct ospf_neighbor *n; struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
struct ospf_iface *ifa; struct ospf_iface *ifa = n->ifa;
struct proto *p; 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, OSPF_TRACE(D_EVENTS,
"Inactivity timer fired on interface %s for neighbor %I.", "Inactivity timer fired on interface %s for neighbor %I.",
ifa->iface->name, n->ip); ifa->iface->name, n->ip);
@ -557,11 +554,9 @@ neighbor_timer_hook(timer * timer)
void void
ospf_neigh_remove(struct ospf_neighbor *n) ospf_neigh_remove(struct ospf_neighbor *n)
{ {
struct ospf_iface *ifa; struct ospf_iface *ifa = n->ifa;
struct proto *p; struct proto *p = &ifa->oa->po->proto;
ifa = n->ifa;
p = (struct proto *) (ifa->proto);
neigh_chstate(n, NEIGHBOR_DOWN); neigh_chstate(n, NEIGHBOR_DOWN);
rem_node(NODE n); rem_node(NODE n);
rfree(n->pool); rfree(n->pool);

View file

@ -42,10 +42,15 @@
* and deletion. Each LSA is kept in two pieces: header and body. Both of them are * and deletion. Each LSA is kept in two pieces: header and body. Both of them are
* kept in the endianity of the CPU. * kept in the endianity of the CPU.
* *
* Every area has its own area_disp() which is * The heart beat of ospf is ospf_disp(). It is called at regular intervals
* responsible for late originating of router LSA, calculating * (&proto_ospf->tick). It is responsible for aging and flushing of LSAs in
* of the routing table and it also ages and flushes the LSAs. This * the database, for routing table calculaction and it call area_disp() of every
* function is called in regular intervals from ospf_disp() * ospf_area.
*
* 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 * To every &ospf_iface, we connect one or more
* &ospf_neighbor's -- a structure containing many timers and queues * &ospf_neighbor's -- a structure containing many timers and queues
* for building adjacency and for exchange of routing messages. * for building adjacency and for exchange of routing messages.
@ -122,6 +127,9 @@ ospf_start(struct proto *p)
init_list(&(po->area_list)); init_list(&(po->area_list));
fib_init(&po->rtf, p->pool, sizeof(ort), 16, ospf_rt_initort); fib_init(&po->rtf, p->pool, sizeof(ort), 16, ospf_rt_initort);
po->areano = 0; po->areano = 0;
po->gr = ospf_top_new(p->pool);
po->cleanup = 1;
s_init_list(&(po->lsal));
if (EMPTY_LIST(c->area_list)) if (EMPTY_LIST(c->area_list))
{ {
log(L_ERR "Cannot start, no OSPF areas configured!"); log(L_ERR "Cannot start, no OSPF areas configured!");
@ -135,8 +143,6 @@ ospf_start(struct proto *p)
po->areano++; po->areano++;
oa->stub = ac->stub; oa->stub = ac->stub;
oa->areaid = ac->areaid; oa->areaid = ac->areaid;
oa->gr = ospf_top_new(p->pool);
s_init_list(&(oa->lsal));
oa->rt = NULL; oa->rt = NULL;
oa->po = po; oa->po = po;
add_area_nets(oa, ac); 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 start:");
{ ospf_top_dump(po->gr, p);
OSPF_TRACE(D_EVENTS, "LSA graph dump for area \"%I\" start:", oa->areaid); OSPF_TRACE(D_EVENTS, "LSA graph dump finished");
ospf_top_dump(oa->gr, p);
OSPF_TRACE(D_EVENTS, "LSA graph dump for area \"%I\" finished",
oa->areaid);
}
neigh_dump_all(); neigh_dump_all();
} }
@ -293,9 +295,9 @@ schedule_rtcalc(struct proto_ospf *po)
} }
/** /**
* area_disp - invokes link-state database aging, origination of * area_disp - invokes origination of
* router LSA and routing table calculation * router LSA and routing table cleanup
* @timer: it's called every @ospf_area->tick seconds * @oa: ospf area
* *
* It invokes aging and when @ospf_area->origrt is set to 1, start * It invokes aging and when @ospf_area->origrt is set to 1, start
* function for origination of router LSA and network LSAs. * 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)) if (ifa->orignet && (ifa->oa == oa))
originate_net_lsa(ifa); 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 void
ospf_disp(timer * timer) ospf_disp(timer * timer)
{ {
@ -330,10 +334,12 @@ ospf_disp(timer * timer)
WALK_LIST(oa, po->area_list) WALK_LIST(oa, po->area_list)
area_disp(oa); area_disp(oa);
/* Age LSA DB */
ospf_age(po);
/* Calculate routing table */ /* Calculate routing table */
if (po->calcrt) if (po->calcrt)
ospf_rt_spf (po); 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); int max = max_ext_lsa(n->n.pxlen);
/* Flush old external LSA */ /* 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; WALK_LIST(oa, po->area_list)
if (ipa_compare(ext->netmask, ipa_mkmask(n->n.pxlen)) == 0) {
{
ospf_lsupd_flush_nlsa(en, oa); 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, "RFC1583 compatibility: %s", (po->rfc1583 ? "enable" : "disabled"));
cli_msg(-1014, "RT scheduler tick: %d", po->tick); cli_msg(-1014, "RT scheduler tick: %d", po->tick);
cli_msg(-1014, "Number of areas: %u", po->areano); 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) 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\tStub:\t%s", oa->stub ? "Yes" : "No");
cli_msg(-1014, "\t\tTransit:\t%s", oa->trcap ? "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 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 neighbors:\t%u", nno);
cli_msg(-1014, "\t\tNumber of adjacent neighbors:\t%u", adjno); cli_msg(-1014, "\t\tNumber of adjacent neighbors:\t%u", adjno);

View file

@ -125,7 +125,6 @@ union options
struct ospf_iface struct ospf_iface
{ {
node n; node n;
struct proto_ospf *proto;
struct iface *iface; /* Nest's iface */ struct iface *iface; /* Nest's iface */
struct ospf_area *oa; struct ospf_area *oa;
struct object_lock *lock; struct object_lock *lock;
@ -507,10 +506,7 @@ struct ospf_area
{ {
node n; node n;
u32 areaid; u32 areaid;
timer *disp_timer; /* Area's dispatcher hear beat */
int origrt; /* Rt lsa origination scheduled? */ 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 */ struct top_hash_entry *rt; /* My own router LSA */
list cand; /* List of candidates for RT calc. */ list cand; /* List of candidates for RT calc. */
struct fib net_fib; /* Networks to advertise or not */ struct fib net_fib; /* Networks to advertise or not */
@ -526,7 +522,10 @@ struct proto_ospf
struct proto proto; struct proto proto;
timer *disp_timer; /* OSPF proto dispatcher */ timer *disp_timer; /* OSPF proto dispatcher */
unsigned tick; unsigned tick;
struct top_graph *gr; /* LSA graph */
slist lsal; /* List of all LSA's */
int calcrt; /* Routing table calculation scheduled? */ int calcrt; /* Routing table calculation scheduled? */
int cleanup; /* Should I cleanup after RT calculation? */
list iface_list; /* Interfaces we really use */ list iface_list; /* Interfaces we really use */
list area_list; list area_list;
int areano; /* Number of area I belong to */ int areano; /* Number of area I belong to */

View file

@ -14,9 +14,7 @@ void
ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type) ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
{ {
struct ospf_packet *pkt; struct ospf_packet *pkt;
struct proto *p; struct proto *p = (struct proto *) (ifa->oa->po);
p = (struct proto *) (ifa->proto);
pkt = (struct ospf_packet *) buf; pkt = (struct ospf_packet *) buf;
@ -40,7 +38,7 @@ ospf_pkt_maxsize(struct ospf_iface *ifa)
void void
ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt) 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 proto *p = &po->proto;
struct password_item *passwd = password_find (ifa->passwords); struct password_item *passwd = password_find (ifa->passwords);
void *tail; 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) ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, int size)
{ {
int i; int i;
struct proto_ospf *po = ifa->proto; struct proto_ospf *po = ifa->oa->po;
struct proto *p = &po->proto; struct proto *p = &po->proto;
struct password_item *pass = NULL, *ptmp; struct password_item *pass = NULL, *ptmp;
void *tail; void *tail;
@ -219,8 +217,8 @@ ospf_rx_hook(sock * sk, int size)
{ {
struct ospf_packet *ps; struct ospf_packet *ps;
struct ospf_iface *ifa = (struct ospf_iface *) (sk->data); struct ospf_iface *ifa = (struct ospf_iface *) (sk->data);
struct proto_ospf *po = ifa->proto; struct proto_ospf *po = ifa->oa->po;
struct proto *p = (struct proto *) (ifa->proto); struct proto *p = &po->proto;
struct ospf_neighbor *n; struct ospf_neighbor *n;
int osize; int osize;
char *mesg = "Bad OSPF packet from "; char *mesg = "Bad OSPF packet from ";
@ -356,24 +354,16 @@ ospf_rx_hook(sock * sk, int size)
void void
ospf_tx_hook(sock * sk) ospf_tx_hook(sock * sk)
{ {
struct ospf_iface *ifa; struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
struct proto *p; struct proto *p = (struct proto *) (ifa->oa->po);
ifa = (struct ospf_iface *) (sk->data);
p = (struct proto *) (ifa->proto);
DBG("%s: TX_Hook called on interface %s\n", p->name, sk->iface->name); DBG("%s: TX_Hook called on interface %s\n", p->name, sk->iface->name);
} }
void void
ospf_err_hook(sock * sk, int err UNUSED) ospf_err_hook(sock * sk, int err UNUSED)
{ {
struct ospf_iface *ifa; struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
struct proto *p; struct proto *p = (struct proto *) (ifa->oa->po);
ifa = (struct ospf_iface *) (sk->data);
p = (struct proto *) (ifa->proto);
DBG("%s: Err_Hook called on interface %s\n", p->name, sk->iface->name); DBG("%s: Err_Hook called on interface %s\n", p->name, sk->iface->name);
} }

View file

@ -13,7 +13,7 @@ add_cand(list * l, struct top_hash_entry *en,
static void static void
calc_next_hop(struct top_hash_entry *en, calc_next_hop(struct top_hash_entry *en,
struct top_hash_entry *par, struct ospf_area *oa); 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 rt_sync(struct proto_ospf *po);
static void static void
@ -231,7 +231,7 @@ ospf_rt_spfa(struct ospf_area *oa)
break; break;
case LSART_NET: 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) if (tmp == NULL)
DBG("Not found!\n"); DBG("Not found!\n");
else else
@ -241,7 +241,7 @@ ospf_rt_spfa(struct ospf_area *oa)
case LSART_VLNK: case LSART_VLNK:
vlink = 1; vlink = 1;
case LSART_PTP: 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"); DBG("PTP found.\n");
break; break;
default: default:
@ -272,7 +272,7 @@ ospf_rt_spfa(struct ospf_area *oa)
sizeof(struct ospf_lsa_net)) / sizeof(u32); i++) sizeof(struct ospf_lsa_net)) / sizeof(u32); i++)
{ {
DBG(" Working on router %I ", *(rts + 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) if (tmp != NULL)
DBG("Found :-)\n"); DBG("Found :-)\n");
else else
@ -288,7 +288,7 @@ ospf_rt_spfa(struct ospf_area *oa)
{ {
if ((iface->type == OSPF_IT_VLINK) && (iface->voa == 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))) (!ipa_equal(tmp->lb, IPA_NONE)))
{ {
if ((iface->state != OSPF_IS_PTP) || (iface->iface != tmp->nhi) || (!ipa_equal(iface->vip, tmp->lb))) 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_net *ln;
struct ospf_lsa_rt *rt; struct ospf_lsa_rt *rt;
struct ospf_lsa_rt_link *rtl, *rr; struct ospf_lsa_rt_link *rtl, *rr;
struct proto_ospf *po = oa->po;
if(!pre) return 0; if(!pre) return 0;
if(!fol) 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: case LSART_STUB:
break; break;
case LSART_NET: 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); fol->lb = ipa_from_u32(rtl->data);
return 1; return 1;
@ -343,7 +344,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr
break; break;
case LSART_VLNK: case LSART_VLNK:
case LSART_PTP: 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); fol->lb = ipa_from_u32(rtl->data);
return 1; 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) - for (i = 0; i < (fol->lsa.length - sizeof(struct ospf_lsa_header) -
sizeof(struct ospf_lsa_net)) / sizeof(u32); i++) 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; return 1;
} }
@ -388,8 +389,10 @@ ospf_rt_sum_tr(struct ospf_area *oa)
if(!bb) return; if(!bb) return;
WALK_SLIST(en, oa->lsal) WALK_SLIST(en, po->lsal)
{ {
if (en->oa != oa)
continue;
if (en->lsa.age == LSA_MAXAGE) if (en->lsa.age == LSA_MAXAGE)
continue; continue;
if (en->dist == LSINFINITY) 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) if (en->lsa.rt == p->cf->global->router_id)
continue; 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; continue;
mask = (ip_addr *)en->lsa_body; 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"); 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) */ /* Page 169 (1) */
if (en->lsa.age == LSA_MAXAGE) if (en->lsa.age == LSA_MAXAGE)
continue; continue;
@ -528,6 +533,8 @@ ospf_rt_spf(struct proto_ospf *po)
if (po->areano == 0) return; if (po->areano == 0) return;
po->cleanup = 1;
OSPF_TRACE(D_EVENTS, "Starting routing table calculation"); OSPF_TRACE(D_EVENTS, "Starting routing table calculation");
/* Invalidate old routing table */ /* Invalidate old routing table */
@ -580,20 +587,16 @@ ospf_rt_spf(struct proto_ospf *po)
} }
} }
WALK_LIST(oa, po->area_list) ospf_ext_spf(po);
{
if (!oa->stub)
{
ospf_ext_spfa(oa);
break;
}
}
rt_sync(po); rt_sync(po);
po->calcrt = 0;
} }
/** /**
* ospf_ext_spfa - calculate external paths * ospf_ext_spf - calculate external paths
* @po: protocol * @po: protocol
* *
* After routing table for any area is calculated, calculation of external * 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. * Inter- and Intra-area paths are always prefered over externals.
*/ */
static void 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; ort *nf1, *nf2, *nfh;
orta nfa; orta nfa;
struct top_hash_entry *en; 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"); 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) if (en->lsa.type != LSA_T_EXT)
continue; continue;
@ -729,7 +731,7 @@ ospf_ext_spfa(struct ospf_area *oa)
nfa.capa = 0; nfa.capa = 0;
nfa.metric1 = met1; nfa.metric1 = met1;
nfa.metric2 = met2; nfa.metric2 = met2;
nfa.oa = oa; nfa.oa = NULL;
nfa.ar = nf1->n.ar; nfa.ar = nf1->n.ar;
nfa.nh = nh; nfa.nh = nh;
nfa.ifa = nhi; nfa.ifa = nhi;
@ -941,7 +943,7 @@ again1:
{ {
if ((ifa->type == OSPF_IT_VLINK) && ipa_equal(ifa->vip, nf->n.nh)) 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))) (!ipa_equal(en->nh, IPA_NONE)))
{ {
a0.gw = en->nh; a0.gw = en->nh;

View file

@ -159,7 +159,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
default: default:
ln--; ln--;
i--; /* No link added */ i--; /* No link added */
log("Unknown interface type"); log("Unknown interface type %s", ifa->iface->name);
break; break;
} }
} }
@ -217,7 +217,6 @@ originate_rt_lsa(struct ospf_area *oa)
lsasum_calculate(&lsa, body); lsasum_calculate(&lsa, body);
en = lsa_install_new(&lsa, body, oa); en = lsa_install_new(&lsa, body, oa);
oa->rt = en; oa->rt = en;
en->dist = 0; /* Force area aging */
ospf_lsupd_flood(NULL, NULL, &oa->rt->lsa, NULL, oa, 1); ospf_lsupd_flood(NULL, NULL, &oa->rt->lsa, NULL, oa, 1);
schedule_rtcalc(po); schedule_rtcalc(po);
oa->origrt = 0; oa->origrt = 0;
@ -264,7 +263,7 @@ originate_net_lsa_body(struct ospf_iface *ifa, u16 * length,
void void
originate_net_lsa(struct ospf_iface *ifa) 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; struct ospf_lsa_header lsa;
u32 rtid = po->proto.cf->global->router_id; u32 rtid = po->proto.cf->global->router_id;
struct proto *p = &po->proto; struct proto *p = &po->proto;
@ -291,7 +290,7 @@ originate_net_lsa(struct ospf_iface *ifa)
if (ifa->nlsa->lsa_body != NULL) if (ifa->nlsa->lsa_body != NULL)
mb_free(ifa->nlsa->lsa_body); mb_free(ifa->nlsa->lsa_body);
ifa->nlsa->lsa_body = NULL; ifa->nlsa->lsa_body = NULL;
ospf_hash_delete(ifa->oa->gr, ifa->nlsa); ospf_hash_delete(po->gr, ifa->nlsa);
schedule_rtcalc(po); schedule_rtcalc(po);
ifa->nlsa = NULL; ifa->nlsa = NULL;
return; return;
@ -411,7 +410,7 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
for (i = 0; i < max; i++) for (i = 0; i < max; i++)
{ {
lsa.id = ipa_to_u32(fn->prefix) + 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; sum = en->lsa_body;
if (fn->pxlen == ipa_mklen(sum->netmask)) 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); lsasum_calculate(&en->lsa, sum);
OSPF_TRACE(D_EVENTS, "Flushing summary lsa. (id=%I, type=%d)", en->lsa.id, en->lsa.type); 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); 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; 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++) for (i = 0; i < max; i++)
{ {
lsa.id = ipa_to_u32(fn->prefix) + 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; if (!free) free = lsa.id;
} }
@ -590,11 +589,9 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
ext1 = body; ext1 = body;
max = max_ext_lsa(n->n.pxlen); max = max_ext_lsa(n->n.pxlen);
oa = HEAD(po->area_list);
for (i = 0; i < max; i++) 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; ext2 = en->lsa_body;
if (ipa_compare(ext1->netmask, ext2->netmask) != 0) if (ipa_compare(ext1->netmask, ext2->netmask) != 0)
@ -672,16 +669,16 @@ ospf_top_hash_u32(u32 a)
} }
static inline unsigned 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. */ #if 1 /* Dirty patch to make rt table calculation work. */
return (ospf_top_hash_u32(lsaid) + return (ospf_top_hash_u32(lsaid) +
ospf_top_hash_u32((type == ospf_top_hash_u32((type ==
LSA_T_NET) ? lsaid : rtrid) + LSA_T_NET) ? lsaid : rtrid) + type +
type) & f->hash_mask; (type == LSA_T_EXT ? 0 : areaid)) & f->hash_mask;
#else #else
return (ospf_top_hash_u32(lsaid) + ospf_top_hash_u32(rtrid) + return (ospf_top_hash_u32(lsaid) + ospf_top_hash_u32(rtrid) +
type) & f->hash_mask; type + areaid) & f->hash_mask;
#endif #endif
} }
@ -735,7 +732,7 @@ ospf_top_rehash(struct top_graph *f, int step)
while (e) while (e)
{ {
x = e->next; 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; e->next = *n;
*n = e; *n = e;
e = x; e = x;
@ -745,49 +742,65 @@ ospf_top_rehash(struct top_graph *f, int step)
} }
struct top_hash_entry * 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 * 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 * 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) 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; e = e->next;
} }
else else if (type == LSA_T_EXT)
{ {
while (e && (e->lsa.id != lsa || e->lsa.type != type || e->lsa.rt != rtr)) while (e && (e->lsa.id != lsa || e->lsa.type != type || e->lsa.rt != rtr))
e = e->next; e = e->next;
} }
#else else
while (e && (e->lsa.id != lsa || e->lsa.rt != rtr || e->lsa.type != type)) {
e = e->next; while (e && (e->lsa.id != lsa || e->lsa.type != type || e->lsa.rt != rtr || e->oa->areaid != areaid))
#endif e = e->next;
}
return e; return e;
} }
struct top_hash_entry * 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 = struct top_hash_entry **ee;
f->hash_table + ospf_top_hash(f, lsa, rtr, type); struct top_hash_entry *e;
struct top_hash_entry *e = *ee; 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) if (e)
return 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.type = type;
e->lsa_body = NULL; e->lsa_body = NULL;
e->nhi = NULL; e->nhi = NULL;
e->oa = oa;
e->next = *ee; e->next = *ee;
*ee = e; *ee = e;
if (f->hash_entries++ > f->hash_entries_max) 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 void
ospf_hash_delete(struct top_graph *f, struct top_hash_entry *e) 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 +
struct top_hash_entry **ee = f->hash_table + h; ospf_top_hash(f, e->oa->areaid, e->lsa.id, e->lsa.rt, e->lsa.type);
while (*ee) while (*ee)
{ {
@ -833,7 +847,7 @@ ospf_hash_delete(struct top_graph *f, struct top_hash_entry *e)
void void
ospf_top_dump(struct top_graph *f, struct proto *p) 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); OSPF_TRACE(D_EVENTS, "Hash entries: %d", f->hash_entries);
for (i = 0; i < f->hash_size; i++) for (i = 0; i < f->hash_size; i++)
@ -856,22 +870,18 @@ ospf_top_dump(struct top_graph *f, struct proto *p)
*/ */
int int
can_flush_lsa(struct ospf_area *oa) can_flush_lsa(struct proto_ospf *po)
{ {
struct ospf_iface *ifa; struct ospf_iface *ifa;
struct ospf_neighbor *n; 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; break;
} }
} }

View file

@ -18,6 +18,7 @@ struct top_hash_entry
*/ */
struct top_hash_entry *next; /* Next in hash chain */ struct top_hash_entry *next; /* Next in hash chain */
struct ospf_lsa_header lsa; struct ospf_lsa_header lsa;
struct ospf_area *oa;
void *lsa_body; void *lsa_body;
bird_clock_t inst_t; /* Time of installation into DB */ bird_clock_t inst_t; /* Time of installation into DB */
ip_addr nh; /* Next hop */ ip_addr nh; /* Next hop */
@ -47,18 +48,18 @@ struct top_graph
struct top_graph *ospf_top_new(pool *); struct top_graph *ospf_top_new(pool *);
void ospf_top_free(struct top_graph *); void ospf_top_free(struct top_graph *);
void ospf_top_dump(struct top_graph *, struct proto *); 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 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 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); 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); u32 type);
void ospf_hash_delete(struct top_graph *, struct top_hash_entry *); void ospf_hash_delete(struct top_graph *, struct top_hash_entry *);
void originate_rt_lsa(struct ospf_area *oa); void originate_rt_lsa(struct ospf_area *oa);
void originate_net_lsa(struct ospf_iface *ifa); 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); int max_ext_lsa(unsigned pxlen);
void originate_ext_lsa(net * n, rte * e, struct proto_ospf *po, void originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
struct ea_list *attrs); struct ea_list *attrs);