0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +00:00

Many bugfixes in routing table calculation and summary LSA origination.

This commit is contained in:
Ondrej Filip 2005-02-13 23:36:31 +00:00
parent 0d3effcf8c
commit 5d3f555234
8 changed files with 93 additions and 50 deletions

View File

@ -24,7 +24,7 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
mask = ps->netmask; mask = ps->netmask;
ipa_ntoh(mask); ipa_ntoh(mask);
if (((ifa->type != OSPF_IT_VLINK) || (ifa->type != OSPF_IT_PTP)) && if (((ifa->type != OSPF_IT_VLINK) && (ifa->type != OSPF_IT_PTP)) &&
((unsigned) ipa_mklen(mask) != ifa->iface->addr->pxlen)) ((unsigned) ipa_mklen(mask) != ifa->iface->addr->pxlen))
{ {
log(L_ERR "%s%I%sbad netmask %I.", beg, faddr, rec, mask); log(L_ERR "%s%I%sbad netmask %I.", beg, faddr, rec, mask);

View File

@ -115,6 +115,7 @@ neigh_chstate(struct ospf_neighbor *n, u8 state)
{ {
ifa->fadj--; ifa->fadj--;
schedule_rt_lsa(ifa->oa); schedule_rt_lsa(ifa->oa);
if (ifa->type == OSPF_IT_VLINK) schedule_rt_lsa(ifa->voa);
schedule_net_lsa(ifa); schedule_net_lsa(ifa);
} }
@ -507,7 +508,7 @@ find_neigh(struct ospf_iface *ifa, u32 rid)
} }
/* Find a closest neighbor which is at leas 2-Way */ /* Find a closest neighbor which is at least 2-Way */
struct ospf_neighbor * struct ospf_neighbor *
find_neigh_noifa(struct proto_ospf *po, u32 rid) find_neigh_noifa(struct proto_ospf *po, u32 rid)
{ {

View File

@ -153,13 +153,29 @@ ospf_start(struct proto *p)
} }
/* Add all virtual links as interfaces */ /* Add all virtual links as interfaces */
if(po->backbone)
{ {
struct ospf_iface_patt *ipatt; struct ospf_iface_patt *ipatt;
WALK_LIST(ac, c->area_list) WALK_LIST(ac, c->area_list)
{ {
WALK_LIST(ipatt, ac->vlink_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->opt.byte = 0;
oa->opt.bit.e = 1;
}
ospf_iface_new(po, NULL, ac, ipatt); ospf_iface_new(po, NULL, ac, ipatt);
}
} }
} }
return PS_UP; return PS_UP;

View File

@ -149,7 +149,8 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
} }
if (ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE != size) if (ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE != size)
{ {
OSPF_TRACE(D_PACKETS, "OSPF_auth: size mismatch"); OSPF_TRACE(D_PACKETS, "OSPF_auth: size mismatch (%d vs %s)",
ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE, size);
return 0; return 0;
} }
@ -356,7 +357,7 @@ ospf_tx_hook(sock * sk)
{ {
struct ospf_iface *ifa= (struct ospf_iface *) (sk->data); struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
struct proto *p = (struct proto *) (ifa->oa->po); struct proto *p = (struct proto *) (ifa->oa->po);
DBG("%s: TX_Hook called on interface %s\n", p->name, sk->iface->name); log(L_ERR "%s: TX_Hook called on interface %s\n", p->name, sk->iface->name);
} }
void void
@ -364,7 +365,7 @@ ospf_err_hook(sock * sk, int err UNUSED)
{ {
struct ospf_iface *ifa= (struct ospf_iface *) (sk->data); struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
struct proto *p = (struct proto *) (ifa->oa->po); struct proto *p = (struct proto *) (ifa->oa->po);
DBG("%s: Err_Hook called on interface %s\n", p->name, sk->iface->name); log(L_ERR "%s: Err_Hook called on interface %s\n", p->name, sk->iface->name);
} }
void void

View File

@ -7,9 +7,10 @@
*/ */
#include "ospf.h" #include "ospf.h"
static void static void
add_cand(list * l, struct top_hash_entry *en, 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 static void
calc_next_hop(struct top_hash_entry *en, calc_next_hop(struct top_hash_entry *en,
struct top_hash_entry *par, struct ospf_area *oa); struct top_hash_entry *par, struct ospf_area *oa);
@ -145,7 +146,6 @@ ospf_rt_spfa(struct ospf_area *oa)
struct ospf_iface *iface; struct ospf_iface *iface;
struct top_hash_entry *act, *tmp; struct top_hash_entry *act, *tmp;
node *n; node *n;
int vlink;
if (oa->rt == NULL) if (oa->rt == NULL)
@ -202,7 +202,6 @@ ospf_rt_spfa(struct ospf_area *oa)
DBG(" Number of links: %u\n", rt->links); DBG(" Number of links: %u\n", rt->links);
for (i = 0; i < rt->links; i++) for (i = 0; i < rt->links; i++)
{ {
vlink = 0;
tmp = NULL; tmp = NULL;
rtl = (rr + i); rtl = (rr + i);
DBG(" Working on link: %I (type: %u) ", rtl->id, rtl->type); DBG(" Working on link: %I (type: %u) ", rtl->id, rtl->type);
@ -230,10 +229,10 @@ ospf_rt_spfa(struct ospf_area *oa)
WALK_LIST(iff, po->iface_list) WALK_LIST(iff, po->iface_list)
{ {
if (rtl->id == (ipa_to_u32(ipa_mkmask(iff->iface->addr->pxlen)) if (iff->iface && (rtl->id == (ipa_to_u32(ipa_mkmask(iff->iface->addr->pxlen))
& ipa_to_u32(iff->iface->addr->prefix))) & ipa_to_u32(iff->iface->addr->prefix))))
{ {
nf.ifa = iff->iface; nf.ifa = iff;
break; break;
} }
} }
@ -256,7 +255,6 @@ ospf_rt_spfa(struct ospf_area *oa)
break; break;
case LSART_VLNK: case LSART_VLNK:
vlink = 1;
case LSART_PTP: case LSART_PTP:
tmp = ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_RT); tmp = ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_RT);
DBG("PTP found.\n"); DBG("PTP found.\n");
@ -268,7 +266,7 @@ ospf_rt_spfa(struct ospf_area *oa)
if (tmp) if (tmp)
DBG("Going to add cand, Mydist: %u, Req: %u\n", DBG("Going to add cand, Mydist: %u, Req: %u\n",
tmp->dist, act->dist + rtl->metric); 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; break;
case LSA_T_NET: case LSA_T_NET:
@ -294,7 +292,7 @@ ospf_rt_spfa(struct ospf_area *oa)
DBG("Found :-)\n"); DBG("Found :-)\n");
else else
DBG("Not found!\n"); DBG("Not found!\n");
add_cand(&oa->cand, tmp, act, act->dist, oa, 0); add_cand(&oa->cand, tmp, act, act->dist, oa);
} }
break; break;
} }
@ -308,11 +306,11 @@ ospf_rt_spfa(struct ospf_area *oa)
if ((tmp = ospf_hash_find(po->gr, oa->areaid, iface->vid, iface->vid, LSA_T_RT)) && if ((tmp = ospf_hash_find(po->gr, oa->areaid, iface->vid, iface->vid, LSA_T_RT)) &&
(!ipa_equal(tmp->lb, IPA_NONE))) (!ipa_equal(tmp->lb, IPA_NONE)))
{ {
if ((iface->state != OSPF_IS_PTP) || (iface->iface != tmp->nhi) || (!ipa_equal(iface->vip, tmp->lb))) if ((iface->state != OSPF_IS_PTP) || (iface->iface != tmp->nhi->iface) || (!ipa_equal(iface->vip, tmp->lb)))
{ {
OSPF_TRACE(D_EVENTS, "Vlink peer %I found", tmp->lsa.id); OSPF_TRACE(D_EVENTS, "Vlink peer %I found", tmp->lsa.id);
ospf_iface_sm(iface, ISM_DOWN); ospf_iface_sm(iface, ISM_DOWN);
iface->iface = tmp->nhi; iface->iface = tmp->nhi->iface;
iface->vip = tmp->lb; iface->vip = tmp->lb;
ospf_iface_sm(iface, ISM_UP); ospf_iface_sm(iface, ISM_UP);
} }
@ -499,11 +497,21 @@ ospf_rt_sum(struct ospf_area *oa)
if (en->lsa.type == LSA_T_SUM_NET) if (en->lsa.type == LSA_T_SUM_NET)
{ {
struct ospf_area *oaa;
int skip = 0;
mlen = ipa_mklen(*mask); mlen = ipa_mklen(*mask);
ip = ipa_and(ipa_from_u32(en->lsa.id), *mask); ip = ipa_and(ipa_from_u32(en->lsa.id), *mask);
/* Page 169 (3) */ /* Page 169 (3) */
if ((anet = fib_route(&oa->net_fib, ip, mlen)) && anet->active) WALK_LIST(oaa, po->area_list)
continue; {
if ((anet = fib_find(&oaa->net_fib, &ip, mlen)) && anet->active)
{
skip = 1;
break;
}
}
if (skip) continue;
type = ORT_NET; type = ORT_NET;
} }
else else
@ -573,9 +581,6 @@ ospf_rt_spf(struct proto_ospf *po)
} }
FIB_WALK_END; 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) FIB_WALK(&oa->net_fib, nftmp)
{ {
anet = (struct area_net *) nftmp; anet = (struct area_net *) nftmp;
@ -585,13 +590,13 @@ ospf_rt_spf(struct proto_ospf *po)
ospf_rt_spfa(oa); ospf_rt_spfa(oa);
} }
if (po->areano == 1) if ((po->areano == 1) || (!po->backbone))
{ {
ospf_rt_sum(HEAD(po->area_list)); ospf_rt_sum(HEAD(po->area_list));
} }
else 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) WALK_LIST(oa, po->area_list)
@ -630,7 +635,7 @@ ospf_ext_spf(struct proto_ospf *po)
struct ospf_lsa_ext_tos *lt; struct ospf_lsa_ext_tos *lt;
int mlen; int mlen;
ip_addr ip, nh, rtid; ip_addr ip, nh, rtid;
struct iface *nhi = NULL; struct ospf_iface *nhi = NULL;
int met1, met2; int met1, met2;
neighbor *nn; neighbor *nn;
struct ospf_lsa_rt *rt; struct ospf_lsa_rt *rt;
@ -731,7 +736,7 @@ ospf_ext_spf(struct proto_ospf *po)
if ((nn = neigh_find(p, &lt->fwaddr, 0)) != NULL) if ((nn = neigh_find(p, &lt->fwaddr, 0)) != NULL)
{ {
nh = lt->fwaddr; nh = lt->fwaddr;
nhi = nn->iface; nhi = ospf_iface_find(po, nn->iface);
} }
else else
{ {
@ -760,7 +765,7 @@ ospf_ext_spf(struct proto_ospf *po)
/* Add LSA into list of candidates in Dijkstra's algorithm */ /* Add LSA into list of candidates in Dijkstra's algorithm */
static void static void
add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par, 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; node *prev, *n;
int added = 0; int added = 0;
@ -791,7 +796,6 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
en->nh = IPA_NONE; en->nh = IPA_NONE;
calc_next_hop(en, par, oa); calc_next_hop(en, par, oa);
//if (vlink) en->nh = IPA_NONE;
if (!en->nhi) if (!en->nhi)
return; /* We cannot find next hop, ignore it */ return; /* We cannot find next hop, ignore it */
@ -861,7 +865,7 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par,
if (ifa->iface && (ipa_compare if (ifa->iface && (ipa_compare
(ifa->iface->addr->ip, ipa_from_u32(en->lsa.id)) == 0)) (ifa->iface->addr->ip, ipa_from_u32(en->lsa.id)) == 0))
{ {
en->nhi = ifa->iface; en->nhi = ifa;
return; return;
} }
log(L_ERR "I didn't find interface for my self originated LSA!\n"); log(L_ERR "I didn't find interface for my self originated LSA!\n");
@ -873,7 +877,7 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par,
ip_addr ip = ipa_from_u32(en->lsa.id); ip_addr ip = ipa_from_u32(en->lsa.id);
nn = neigh_find(p, &ip, 0); nn = neigh_find(p, &ip, 0);
if (nn) if (nn)
en->nhi = nn->iface; en->nhi = ospf_iface_find(po, nn->iface);
return; return;
} }
} }
@ -881,7 +885,8 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par,
{ {
if ((neigh = find_neigh_noifa(po, en->lsa.rt)) == NULL) if ((neigh = find_neigh_noifa(po, en->lsa.rt)) == NULL)
return; 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 en->nh = neigh->ip; /* Yes, neighbor is it's
* own next hop */ * own next hop */
return; return;
@ -895,7 +900,7 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par,
bug("Did not find next hop interface for INSPF lsa!"); bug("Did not find next hop interface for INSPF lsa!");
if ((neigh = find_neigh_noifa(po, en->lsa.rt)) == NULL) if ((neigh = find_neigh_noifa(po, en->lsa.rt)) == NULL)
return; return;
en->nhi = neigh->ifa->iface; en->nhi = neigh->ifa;
en->nh = neigh->ip; /* Yes, neighbor is it's own en->nh = neigh->ip; /* Yes, neighbor is it's own
* next hop */ * next hop */
return; return;
@ -932,6 +937,7 @@ again1:
FIB_ITERATE_START(fib, &fit, nftmp) FIB_ITERATE_START(fib, &fit, nftmp)
{ {
nf = (ort *) nftmp; nf = (ort *) nftmp;
check_sum_lsa(po, nf, ORT_NET);
if (memcmp(&nf->n, &nf->o, sizeof(orta))) if (memcmp(&nf->n, &nf->o, sizeof(orta)))
{ /* Some difference */ { /* Some difference */
net *ne; net *ne;
@ -947,7 +953,8 @@ again1:
a0.dest = RTD_ROUTER; a0.dest = RTD_ROUTER;
a0.flags = 0; a0.flags = 0;
a0.aflags = 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; a0.gw = nf->n.nh;
if (ipa_equal(nf->n.nh, IPA_NONE)) a0.dest = RTD_DEVICE; if (ipa_equal(nf->n.nh, IPA_NONE)) a0.dest = RTD_DEVICE;
@ -974,7 +981,6 @@ again1:
if (!found) nf->n.metric1 = LSINFINITY; /* Delete it */ if (!found) nf->n.metric1 = LSINFINITY; /* Delete it */
} }
ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen); ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen);
check_sum_lsa(po, nf, ORT_NET);
if (nf->n.metric1 < LSINFINITY) if (nf->n.metric1 < LSINFINITY)
{ {
e = rte_get_temp(&a0); e = rte_get_temp(&a0);
@ -1024,13 +1030,18 @@ again2:
{ {
flush = 1; flush = 1;
anet = (struct area_net *) nftmp; anet = (struct area_net *) nftmp;
if((!anet->hidden) && anet->active && (!oa->trcap)) if((!anet->hidden) && anet->active)
flush = 0; flush = 0;
WALK_LIST(oaa, po->area_list) WALK_LIST(oaa, po->area_list)
{ {
int fl = flush;
if (oaa == oa) continue; 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); else originate_sum_lsa(oaa, &anet->fn, ORT_NET, 1);
} }
} }

View File

@ -24,7 +24,7 @@ typedef struct orta
int metric1; int metric1;
int metric2; int metric2;
ip_addr nh; /* Next hop */ ip_addr nh; /* Next hop */
struct iface *ifa; /* Outgoing interface */ struct ospf_iface *ifa; /* Outgoing interface */
struct top_hash_entry *ar; /* Advertising router */ struct top_hash_entry *ar; /* Advertising router */
u32 tag; u32 tag;
} }

View File

@ -24,6 +24,7 @@ static void *
originate_rt_lsa_body(struct ospf_area *oa, u16 * length) originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
{ {
struct proto_ospf *po = oa->po; struct proto_ospf *po = oa->po;
struct proto *p = &po->proto;
struct ospf_iface *ifa; struct ospf_iface *ifa;
int j = 0, k = 0; int j = 0, k = 0;
u16 i = 0; u16 i = 0;
@ -51,8 +52,12 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
WALK_LIST(ifa, po->iface_list) WALK_LIST(ifa, po->iface_list)
{ {
if ((ifa->type == OSPF_IT_VLINK) && (ifa->voa == oa) && (ifa->state > OSPF_IS_DOWN)) if ((ifa->type == OSPF_IT_VLINK) && (ifa->voa == oa) && (!EMPTY_LIST(ifa->neigh_list)))
rt->veb.bit.v = 1; {
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)) if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN))
continue; continue;
@ -413,7 +418,7 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
if ((en = ospf_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL) if ((en = ospf_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL)
{ {
sum = en->lsa_body; sum = en->lsa_body;
if (fn->pxlen == ipa_mklen(sum->netmask)) if ((type == ORT_ROUTER) || (fn->pxlen == ipa_mklen(sum->netmask)))
{ {
en->lsa.age = LSA_MAXAGE; en->lsa.age = LSA_MAXAGE;
en->lsa.sn = LSA_MAXSEQNO; en->lsa.sn = LSA_MAXSEQNO;
@ -521,27 +526,36 @@ check_sum_lsa(struct proto_ospf *po, ort *nf, int dest)
flush = 0; flush = 0;
if ((nf->n.metric1 >= LSINFINITY) || (nf->n.type > RTS_OSPF_IA)) if ((nf->n.metric1 >= LSINFINITY) || (nf->n.type > RTS_OSPF_IA))
flush = 1; flush = 1;
if ((dest == ORT_ROUTER) && (!(nf->n.capa & ORTA_ABR))) if ((dest == ORT_ROUTER) && (!(nf->n.capa & ORTA_ASBR)))
flush = 1; flush = 1;
if ((!nf->n.oa) || (nf->n.oa->areaid == oa->areaid)) if ((!nf->n.oa) || (nf->n.oa->areaid == oa->areaid))
flush = 1; 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) if ((dest == ORT_ROUTER) && oa->stub)
flush = 1; flush = 1;
/* FIXME stub for networks? */ /* FIXME stub for networks? */
mlen = nf->fn.pxlen; mlen = nf->fn.pxlen;
ip = ipa_and(nf->fn.prefix, ipa_mkmask(mlen)); 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); flush = 1;
continue; 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);
} }
} }

View File

@ -23,7 +23,7 @@ struct top_hash_entry
bird_clock_t inst_t; /* Time of installation into DB */ bird_clock_t inst_t; /* Time of installation into DB */
ip_addr nh; /* Next hop */ ip_addr nh; /* Next hop */
ip_addr lb; /* Link back */ ip_addr lb; /* Link back */
struct iface *nhi; struct ospf_iface *nhi; /* Next hop interface */
u32 dist; /* Distance from the root */ u32 dist; /* Distance from the root */
u16 ini_age; u16 ini_age;
u8 color; u8 color;