*/
#include "ospf.h"
+
static void
add_cand(list * l, struct top_hash_entry *en,
- struct top_hash_entry *par, u16 dist, struct ospf_area *oa, int vlink);
+ struct top_hash_entry *par, u16 dist, struct ospf_area *oa);
static void
calc_next_hop(struct top_hash_entry *en,
struct top_hash_entry *par, struct ospf_area *oa);
struct ospf_iface *iface;
struct top_hash_entry *act, *tmp;
node *n;
- int vlink;
if (oa->rt == NULL)
DBG(" Number of links: %u\n", rt->links);
for (i = 0; i < rt->links; i++)
{
- vlink = 0;
tmp = NULL;
rtl = (rr + i);
DBG(" Working on link: %I (type: %u) ", rtl->id, rtl->type);
WALK_LIST(iff, po->iface_list)
{
- if (rtl->id == (ipa_to_u32(ipa_mkmask(iff->iface->addr->pxlen))
- & ipa_to_u32(iff->iface->addr->prefix)))
+ if (iff->iface && (rtl->id == (ipa_to_u32(ipa_mkmask(iff->iface->addr->pxlen))
+ & ipa_to_u32(iff->iface->addr->prefix))))
{
- nf.ifa = iff->iface;
+ nf.ifa = iff;
break;
}
}
break;
case LSART_VLNK:
- vlink = 1;
case LSART_PTP:
tmp = ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_RT);
DBG("PTP found.\n");
if (tmp)
DBG("Going to add cand, Mydist: %u, Req: %u\n",
tmp->dist, act->dist + rtl->metric);
- add_cand(&oa->cand, tmp, act, act->dist + rtl->metric, oa, vlink);
+ add_cand(&oa->cand, tmp, act, act->dist + rtl->metric, oa);
}
break;
case LSA_T_NET:
DBG("Found :-)\n");
else
DBG("Not found!\n");
- add_cand(&oa->cand, tmp, act, act->dist, oa, 0);
+ add_cand(&oa->cand, tmp, act, act->dist, oa);
}
break;
}
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)))
+ if ((iface->state != OSPF_IS_PTP) || (iface->iface != tmp->nhi->iface) || (!ipa_equal(iface->vip, tmp->lb)))
{
OSPF_TRACE(D_EVENTS, "Vlink peer %I found", tmp->lsa.id);
ospf_iface_sm(iface, ISM_DOWN);
- iface->iface = tmp->nhi;
+ iface->iface = tmp->nhi->iface;
iface->vip = tmp->lb;
ospf_iface_sm(iface, ISM_UP);
}
if (en->lsa.type == LSA_T_SUM_NET)
{
+ struct ospf_area *oaa;
+ int skip = 0;
mlen = ipa_mklen(*mask);
ip = ipa_and(ipa_from_u32(en->lsa.id), *mask);
/* Page 169 (3) */
- if ((anet = fib_route(&oa->net_fib, ip, mlen)) && anet->active)
- continue;
+ WALK_LIST(oaa, po->area_list)
+ {
+ if ((anet = fib_find(&oaa->net_fib, &ip, mlen)) && anet->active)
+ {
+ skip = 1;
+ break;
+ }
+ }
+ if (skip) continue;
+
type = ORT_NET;
}
else
}
FIB_WALK_END;
- fib_free(&oa->rtr);
- fib_init(&oa->rtr, p->pool, sizeof(ort), 16, ospf_rt_initort);
-
FIB_WALK(&oa->net_fib, nftmp)
{
anet = (struct area_net *) nftmp;
ospf_rt_spfa(oa);
}
- if (po->areano == 1)
+ if ((po->areano == 1) || (!po->backbone))
{
ospf_rt_sum(HEAD(po->area_list));
}
else
{
- if (po->backbone) ospf_rt_sum(po->backbone); /* And if backbone is not connected? */
+ ospf_rt_sum(po->backbone);
}
WALK_LIST(oa, po->area_list)
struct ospf_lsa_ext_tos *lt;
int mlen;
ip_addr ip, nh, rtid;
- struct iface *nhi = NULL;
+ struct ospf_iface *nhi = NULL;
int met1, met2;
neighbor *nn;
struct ospf_lsa_rt *rt;
if ((nn = neigh_find(p, <->fwaddr, 0)) != NULL)
{
nh = lt->fwaddr;
- nhi = nn->iface;
+ nhi = ospf_iface_find(po, nn->iface);
}
else
{
/* Add LSA into list of candidates in Dijkstra's algorithm */
static void
add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
- u16 dist, struct ospf_area *oa, int vlink)
+ u16 dist, struct ospf_area *oa)
{
node *prev, *n;
int added = 0;
en->nh = IPA_NONE;
calc_next_hop(en, par, oa);
- //if (vlink) en->nh = IPA_NONE;
if (!en->nhi)
return; /* We cannot find next hop, ignore it */
if (ifa->iface && (ipa_compare
(ifa->iface->addr->ip, ipa_from_u32(en->lsa.id)) == 0))
{
- en->nhi = ifa->iface;
+ en->nhi = ifa;
return;
}
log(L_ERR "I didn't find interface for my self originated LSA!\n");
ip_addr ip = ipa_from_u32(en->lsa.id);
nn = neigh_find(p, &ip, 0);
if (nn)
- en->nhi = nn->iface;
+ en->nhi = ospf_iface_find(po, nn->iface);
return;
}
}
{
if ((neigh = find_neigh_noifa(po, en->lsa.rt)) == NULL)
return;
- en->nhi = neigh->ifa->iface;
+ en->nhi = neigh->ifa;
+ if (neigh->ifa->type == OSPF_IT_VLINK)
en->nh = neigh->ip; /* Yes, neighbor is it's
* own next hop */
return;
bug("Did not find next hop interface for INSPF lsa!");
if ((neigh = find_neigh_noifa(po, en->lsa.rt)) == NULL)
return;
- en->nhi = neigh->ifa->iface;
+ en->nhi = neigh->ifa;
en->nh = neigh->ip; /* Yes, neighbor is it's own
* next hop */
return;
FIB_ITERATE_START(fib, &fit, nftmp)
{
nf = (ort *) nftmp;
+ check_sum_lsa(po, nf, ORT_NET);
if (memcmp(&nf->n, &nf->o, sizeof(orta)))
{ /* Some difference */
net *ne;
a0.dest = RTD_ROUTER;
a0.flags = 0;
a0.aflags = 0;
- a0.iface = nf->n.ifa;
+ a0.iface = NULL;
+ if (nf->n.ifa) a0.iface = nf->n.ifa->iface;
a0.gw = nf->n.nh;
if (ipa_equal(nf->n.nh, IPA_NONE)) a0.dest = RTD_DEVICE;
if (!found) nf->n.metric1 = LSINFINITY; /* Delete it */
}
ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen);
- check_sum_lsa(po, nf, ORT_NET);
if (nf->n.metric1 < LSINFINITY)
{
e = rte_get_temp(&a0);
{
flush = 1;
anet = (struct area_net *) nftmp;
- if((!anet->hidden) && anet->active && (!oa->trcap))
+ if((!anet->hidden) && anet->active)
flush = 0;
WALK_LIST(oaa, po->area_list)
{
+ int fl = flush;
+
if (oaa == oa) continue;
- if(flush) flush_sum_lsa(oaa, &anet->fn, ORT_NET);
+
+ if ((oa == po->backbone) && oaa->trcap) fl = 1;
+
+ if(fl) flush_sum_lsa(oaa, &anet->fn, ORT_NET);
else originate_sum_lsa(oaa, &anet->fn, ORT_NET, 1);
}
}
originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
{
struct proto_ospf *po = oa->po;
+ struct proto *p = &po->proto;
struct ospf_iface *ifa;
int j = 0, k = 0;
u16 i = 0;
WALK_LIST(ifa, po->iface_list)
{
- if ((ifa->type == OSPF_IT_VLINK) && (ifa->voa == oa) && (ifa->state > OSPF_IS_DOWN))
- rt->veb.bit.v = 1;
+ if ((ifa->type == OSPF_IT_VLINK) && (ifa->voa == oa) && (!EMPTY_LIST(ifa->neigh_list)))
+ {
+ neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
+ if ((neigh->state == NEIGHBOR_FULL) && (ifa->cost <= 0xffff))
+ rt->veb.bit.v = 1;
+ }
if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN))
continue;
if ((en = ospf_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL)
{
sum = en->lsa_body;
- if (fn->pxlen == ipa_mklen(sum->netmask))
+ if ((type == ORT_ROUTER) || (fn->pxlen == ipa_mklen(sum->netmask)))
{
en->lsa.age = LSA_MAXAGE;
en->lsa.sn = LSA_MAXSEQNO;
flush = 0;
if ((nf->n.metric1 >= LSINFINITY) || (nf->n.type > RTS_OSPF_IA))
flush = 1;
- if ((dest == ORT_ROUTER) && (!(nf->n.capa & ORTA_ABR)))
+ if ((dest == ORT_ROUTER) && (!(nf->n.capa & ORTA_ASBR)))
flush = 1;
if ((!nf->n.oa) || (nf->n.oa->areaid == oa->areaid))
flush = 1;
- /* FIXME: Test next hop - is it in actual area? */
+
+ if (nf->n.ifa) {
+ if (nf->n.ifa->oa->areaid == oa->areaid)
+ flush = 1;
+ }
+ else flush = 1;
+
if ((dest == ORT_ROUTER) && oa->stub)
flush = 1;
/* FIXME stub for networks? */
mlen = nf->fn.pxlen;
ip = ipa_and(nf->fn.prefix, ipa_mkmask(mlen));
- if ((!flush) && (!nf->n.oa->trcap) &&
- fib_route(&nf->n.oa->net_fib, ip, mlen)) /* The route fits into area networks */
- flush = 1;
- if(flush) /* FIXME Go on... */
+ 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_sum_lsa(oa, &nf->fn, dest);
- continue;
+ flush = 1;
+ if ((nf->n.oa == po->backbone) && (oa->trcap)) flush = 0;
}
- originate_sum_lsa(oa, &nf->fn, dest, nf->n.metric1);
+
+ if(flush)
+ flush_sum_lsa(oa, &nf->fn, dest);
+ else
+ originate_sum_lsa(oa, &nf->fn, dest, nf->n.metric1);
}
}