- 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)
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);
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;
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)
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);
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 */
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);
}
else i++; /* No lsa added */
- if (sn == STAIL(n->ifa->oa->lsal))
+ if (sn == STAIL(po->lsal))
{
i--;
break;
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");
{
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;
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);
}
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);
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,
u32 *pp;
int i, send;
struct nbma_node *nb;
+
if (timer == NULL)
ifa = dirn->ifa;
else
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 */
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);
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;
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;
{
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;
}
}
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 */
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;
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;
struct ospf_area *oa;
ifa = mb_allocz(p->pool, sizeof(struct ospf_iface));
- ifa->proto = po;
ifa->iface = iface;
ifa->cost = ip->cost;
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;
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);
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 */
#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);
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.
* 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;
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 >=
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
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
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);
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_ */
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;
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;
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
* @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
}
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)
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))
{
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
{
- 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)
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));
}
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))
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 */
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)
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)
#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;
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);
}
{
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)
}
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? */
{
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);
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));
int i;
ifa = n->ifa;
- p = (struct proto *) (ifa->proto);
+ p = (struct proto *) (ifa->oa->po);
i = 0;
switch (ifa->type)
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]);
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;
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");
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);
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);
* 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.
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!");
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);
}
}
- 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();
}
}
/**
- * 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.
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)
{
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;
}
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;
}
}
}
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)
{
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);
struct ospf_iface
{
node n;
- struct proto_ospf *proto;
struct iface *iface; /* Nest's iface */
struct ospf_area *oa;
struct object_lock *lock;
{
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 */
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 */
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;
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;
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;
{
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 ";
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);
}
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
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
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:
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
{
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)))
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;
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;
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;
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;
}
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)
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;
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;
if (po->areano == 0) return;
+ po->cleanup = 1;
+
OSPF_TRACE(D_EVENTS, "Starting routing table calculation");
/* Invalidate old routing table */
}
}
- 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
* 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;
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;
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;
{
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;
default:
ln--;
i--; /* No link added */
- log("Unknown interface type");
+ log("Unknown interface type %s", ifa->iface->name);
break;
}
}
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;
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;
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;
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))
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;
}
}
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;
}
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)
}
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
}
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;
}
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;
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)
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)
{
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++)
*/
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;
}
}
*/
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 */
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);