Commit 6384c7d7 authored by Ondřej Zajíček's avatar Ondřej Zajíček

OSPF: most of summary LSA orig./flush logic rewritten.

Fixes many bugs in the old code and makes it much cleaner.
parent ba321706
......@@ -95,7 +95,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
}
tmp = !(ps->options & OPT_E);
if (tmp != ifa->oa->stub)
if (tmp != !!ifa->oa->stub)
{
log(L_ERR "%s%I - stub area flag mismatch (%d)", beg, faddr, tmp);
return;
......
......@@ -236,11 +236,11 @@ ospf_iface_down(struct ospf_iface *ifa)
struct proto *p = &po->proto;
struct ospf_iface *iff;
OSPF_TRACE(D_EVENTS, "Removing interface %s", ifa->iface->name);
/* First of all kill all the related vlinks */
if (ifa->type != OSPF_IT_VLINK)
{
OSPF_TRACE(D_EVENTS, "Removing interface %s", ifa->iface->name);
/* First of all kill all the related vlinks */
WALK_LIST(iff, po->iface_list)
{
if ((iff->type == OSPF_IT_VLINK) && (iff->vifa == ifa))
......
......@@ -47,15 +47,6 @@ ospf_age(struct proto_ospf *po)
WALK_SLIST_DELSAFE(en, nxt, po->lsal)
{
if (po->calcrt)
{
/* Cleanup before ospf_rt_spf() */
en->color = OUTSPF;
en->dist = LSINFINITY;
en->nhi = NULL;
en->nh = IPA_NONE;
en->lb = IPA_NONE;
}
if (en->lsa.age == LSA_MAXAGE)
{
if (flush)
......
......@@ -142,6 +142,7 @@ ospf_start(struct proto *p)
struct ospf_config *c = (struct ospf_config *) (p->cf);
struct ospf_area_config *ac;
struct ospf_area *oa;
int vlinks = 0;
po->router_id = proto_get_router_id(p->cf);
po->rfc1583 = c->rfc1583;
......@@ -188,6 +189,9 @@ ospf_start(struct proto *p)
oa->stub = 0;
}
if (!EMPTY_LIST(ac->vlink_list))
vlinks = 1;
#ifdef OSPFv2
oa->options = (oa->stub ? 0 : OPT_E);
#else /* OSPFv3 */
......@@ -195,35 +199,32 @@ ospf_start(struct proto *p)
#endif
}
/* Add all virtual links as interfaces */
/* ABR is always in the backbone */
if (((po->areano > 1) || vlinks) && !po->backbone)
{
struct ospf_iface_patt *ipatt;
WALK_LIST(ac, c->area_list)
{
WALK_LIST(ipatt, ac->vlink_list)
{
if(!po->backbone)
{
oa = mb_allocz(p->pool, sizeof(struct ospf_area));
add_tail(&po->area_list, NODE oa);
po->areano++;
oa->stub = 0;
oa->areaid = 0;
oa->rt = NULL;
oa->po = po;
fib_init(&oa->net_fib, p->pool, sizeof(struct area_net), 16, ospf_area_initfib);
fib_init(&oa->rtr, p->pool, sizeof(ort), 16, ospf_rt_initort);
po->backbone = oa;
oa = mb_allocz(p->pool, sizeof(struct ospf_area));
add_tail(&po->area_list, NODE oa);
po->areano++;
oa->stub = 0;
oa->areaid = 0;
oa->rt = NULL;
oa->po = po;
fib_init(&oa->net_fib, p->pool, sizeof(struct area_net), 16, ospf_area_initfib);
fib_init(&oa->rtr, p->pool, sizeof(ort), 16, ospf_rt_initort);
po->backbone = oa;
#ifdef OSPFv2
oa->options = OPT_E;
oa->options = OPT_E;
#else /* OSPFv3 */
oa->options = OPT_R | OPT_E | OPT_V6;
oa->options = OPT_R | OPT_E | OPT_V6;
#endif
}
ospf_iface_new(po, NULL, NULL, ac, ipatt);
}
}
}
/* Add all virtual links as interfaces */
struct ospf_iface_patt *ipatt;
WALK_LIST(ac, c->area_list)
WALK_LIST(ipatt, ac->vlink_list)
ospf_iface_new(po, NULL, NULL, ac, ipatt);
return PS_UP;
}
......@@ -635,9 +636,7 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
struct nbma_node *nb1, *nb2, *nbnx;
struct ospf_area *oa = NULL;
int found, olddead, newdead;
struct area_net_config *anc;
struct area_net *an;
if (po->rfc1583 != new->rfc1583)
return 0;
......@@ -690,26 +689,8 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
schedule_rt_lsa(oa);
/* Change net_list */
FIB_WALK(&oa->net_fib, nf) /* First check if some networks are deleted */
{
found = 0;
WALK_LIST(anc, newac->net_list)
{
if (ipa_equal(anc->px.addr, nf->prefix) && (anc->px.len == nf->pxlen))
{
found = 1;
break;
}
if (!found) flush_sum_lsa(oa, nf, ORT_NET); /* And flush them */
}
}
FIB_WALK_END;
WALK_LIST(anc, newac->net_list) /* Second add new networks */
{
an = fib_get(&oa->net_fib, &anc->px.addr, anc->px.len);
an->hidden = anc->hidden;
}
fib_free(&oa->net_fib);
add_area_nets(oa, newac);
if (!iface_patts_equal(&oldac->patt_list, &newac->patt_list,
(void *) ospf_patt_compare))
......
This diff is collapsed.
......@@ -47,12 +47,35 @@ orta;
typedef struct ort
{
/*
* We use fn.x0 to mark persistent rt entries, that are needed for summary
* LSAs that don't have 'proper' rt entry (area networks + default to stubs)
* to keep uid stable (used for LSA ID in OSPFv3 - see fibnode_to_lsaid()).
*/
struct fib_node fn;
orta n;
orta o;
}
ort;
/*
* Invariants for structs top_hash_entry (nodes of LSA db)
* enforced by SPF calculation for final nodes (color == INSPF):
* - only router, network and AS-external LSAs
* - lsa.age < LSA_MAXAGE
* - dist < LSINFINITY (or 2*LSINFINITY for ext-LSAs)
* - nhi are non-NULL unless the node is oa->rt (calculating router itself)
* - beware, nhi is not valid after SPF calculation
* - nh is IFA_NONE iff the node is a local network
*
* Invariants for structs orta nodes of fib tables po->rtf, oa->rtr:
* - nodes may be invalid (fn.type == 0), in that case other invariants don't hold
* - n.metric1 may be at most a small multiple of LSINFINITY,
* therefore sums do not overflow
* - n.oa and n.ifa are always non-NULL
* - oa->rtr does not contain calculating router itself
*/
void ospf_rt_spf(struct proto_ospf *po);
void ospf_rt_initort(struct fib_node *fn);
......
......@@ -81,10 +81,14 @@ fibnode_to_lsaid(struct proto_ospf *po, struct fib_node *fn)
static inline u32
fibnode_to_lsaid(struct proto_ospf *po, struct fib_node *fn)
{
/* In OSPFv3, it is simpler. There is not a requirement
for membership of the result in input network, so we
just use hash-based unique ID. */
/*
* In OSPFv3, it is simpler. There is not a requirement for
* membership of the result in the input network, so we just use a
* hash-based unique ID of a routing table entry for a route that
* originated given LSA. For ext-LSA, it is an imported route in the
* nest's routing table (p->table). For summary-LSA, it is a
* 'source' route in the protocol internal routing table (po->rtf).
*/
return fn->uid;
}
......@@ -769,17 +773,6 @@ originate_sum_rt_lsa(struct ospf_area *oa, struct fib_node *fn, int metric, u32
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
}
void
originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metric, u32 options)
{
if (type == ORT_NET)
originate_sum_net_lsa(oa, fn, metric);
else
originate_sum_rt_lsa(oa, fn, metric, options);
}
void
flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
{
......@@ -823,65 +816,6 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
}
void
check_sum_lsa(struct proto_ospf *po, ort *nf, int dest)
{
struct ospf_area *oa;
int flush, mlen;
ip_addr ip;
if (po->areano < 2) return;
if ((nf->n.type > RTS_OSPF_IA) && (nf->o.type > RTS_OSPF_IA)) return;
#ifdef LOCAL_DEBUG
DBG("Checking...dest = %d, %I/%d\n", dest, nf->fn.prefix, nf->fn.pxlen);
if (nf->n.oa) DBG("New: met=%d, oa=%d\n", nf->n.metric1, nf->n.oa->areaid);
if (nf->o.oa) DBG("Old: met=%d, oa=%d\n", nf->o.metric1, nf->o.oa->areaid);
#endif
WALK_LIST(oa, po->area_list)
{
flush = 0;
if ((nf->n.metric1 >= LSINFINITY) || (nf->n.type > RTS_OSPF_IA))
flush = 1;
if ((dest == ORT_ROUTER) && (!(nf->n.options & ORTA_ASBR)))
flush = 1;
if ((!nf->n.oa) || (nf->n.oa->areaid == oa->areaid))
flush = 1;
if (nf->n.ifa) {
if (nf->n.ifa->oa->areaid == oa->areaid)
flush = 1;
}
else flush = 1;
/* Don't send summary into stub areas
* We send just default route (and later) */
if (oa->stub)
flush = 1;
mlen = nf->fn.pxlen;
ip = ipa_and(nf->fn.prefix, ipa_mkmask(mlen));
if ((oa == po->backbone) && (nf->n.type == RTS_OSPF_IA))
flush = 1; /* Only intra-area can go to the backbone */
if ((!flush) && (dest == ORT_NET) && fib_route(&nf->n.oa->net_fib, ip, mlen))
{
/* The route fits into area networks */
flush = 1;
if ((nf->n.oa == po->backbone) && (oa->trcap)) flush = 0;
}
if (flush)
flush_sum_lsa(oa, &nf->fn, dest);
else
originate_sum_lsa(oa, &nf->fn, dest, nf->n.metric1, nf->n.options);
}
}
static void *
originate_ext_lsa_body(net *n, rte *e, u16 *length, struct proto_ospf *po,
struct ea_list *attrs)
......
......@@ -67,13 +67,15 @@ void originate_net_lsa(struct ospf_iface *ifa);
void update_net_lsa(struct ospf_iface *ifa);
void update_link_lsa(struct ospf_iface *ifa);
int can_flush_lsa(struct proto_ospf *po);
int max_ext_lsa(unsigned pxlen);
void originate_sum_net_lsa(struct ospf_area *oa, struct fib_node *fn, int metric);
void originate_sum_rt_lsa(struct ospf_area *oa, struct fib_node *fn, int metric, u32 options UNUSED);
void flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type);
void originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
struct ea_list *attrs);
void flush_ext_lsa(net *n, struct proto_ospf *po);
void check_sum_lsa(struct proto_ospf *po, ort *nf, int);
void originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metric, u32 options);
void flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type);
#ifdef OSPFv2
struct top_hash_entry * ospf_hash_find_net(struct top_graph *f, u32 domain, u32 lsa);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment