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