Many bugfixes (I don't remember all of them):
Added link ID calculation for external routes with same prefix but different mask. Bugfix in NET lsa origination. Bugfix in NET hashing. Bugfix in LSA installing.
This commit is contained in:
parent
2d37d36c67
commit
273fd2c164
6 changed files with 148 additions and 55 deletions
|
@ -11,6 +11,8 @@
|
|||
void
|
||||
flush_lsa(struct top_hash_entry *en, struct ospf_area *oa)
|
||||
{
|
||||
debug("Going to remove node: Type: %u, Id: %I, Rt: %I, Age: %u\n",
|
||||
en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa.age);
|
||||
s_rem_node(SNODE en);
|
||||
ospf_hash_delete(oa->gr,en);
|
||||
}
|
||||
|
@ -368,7 +370,6 @@ lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2)
|
|||
if((l1->age==LSA_MAXAGE)&&(l2->age!=LSA_MAXAGE)) return CMP_NEWER;
|
||||
if((l2->age==LSA_MAXAGE)&&(l1->age!=LSA_MAXAGE)) return CMP_OLDER;
|
||||
|
||||
debug("Abs=%u\n",abs(l1->age-l2->age));
|
||||
if(abs(l1->age-l2->age)>LSA_MAXAGEDIFF)
|
||||
return l1->age<l2->age ? CMP_NEWER : CMP_OLDER;
|
||||
|
||||
|
@ -384,8 +385,6 @@ lsa_install_new(struct ospf_lsa_header *lsa, void *body, struct ospf_area *oa,
|
|||
unsigned i;
|
||||
struct top_hash_entry *en;
|
||||
|
||||
if(body==NULL) die("AA");
|
||||
|
||||
if((en=ospf_hash_find_header(oa->gr,lsa))==NULL)
|
||||
{
|
||||
en=ospf_hash_get_header(oa->gr,lsa);
|
||||
|
@ -407,9 +406,12 @@ lsa_install_new(struct ospf_lsa_header *lsa, void *body, struct ospf_area *oa,
|
|||
}
|
||||
}
|
||||
}
|
||||
if(change) s_rem_node(SNODE en);
|
||||
s_rem_node(SNODE en);
|
||||
}
|
||||
|
||||
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);
|
||||
en->inst_t=now;
|
||||
if(en->lsa_body!=NULL) mb_free(en->lsa_body);
|
||||
|
|
|
@ -308,12 +308,12 @@ ospf_lsupd_rx(struct ospf_lsupd_packet *ps, struct proto *p,
|
|||
continue;
|
||||
}
|
||||
ntohlsah(lsa,&lsatmp);
|
||||
debug("Update Type: %u ID: %I RT: %I, Sn: 0x%08x Age: %u, Sum: %u\n",
|
||||
DBG("Update Type: %u ID: %I RT: %I, Sn: 0x%08x Age: %u, Sum: %u\n",
|
||||
lsatmp.type, lsatmp.id, lsatmp.rt, lsatmp.sn, lsatmp.age,
|
||||
lsatmp.checksum);
|
||||
lsadb=ospf_hash_find_header(oa->gr, &lsatmp);
|
||||
if(lsadb)
|
||||
debug("I have Type: %u ID: %I RT: %I, Sn: 0x%08x Age: %u, Sum: %u\n",
|
||||
DBG("I have Type: %u ID: %I RT: %I, Sn: 0x%08x Age: %u, Sum: %u\n",
|
||||
lsadb->lsa.type, lsadb->lsa.id, lsadb->lsa.rt, lsadb->lsa.sn,
|
||||
lsadb->lsa.age, lsadb->lsa.checksum);
|
||||
|
||||
|
|
|
@ -247,12 +247,25 @@ ospf_rt_notify(struct proto *p, net *n, rte *new, rte *old, ea_list *attrs)
|
|||
u32 rtid=po->proto.cf->global->router_id;
|
||||
struct ospf_area *oa;
|
||||
struct top_hash_entry *en;
|
||||
u32 pr=ipa_to_u32(n->n.prefix);
|
||||
struct ospf_lsa_ext *ext;
|
||||
int i;
|
||||
|
||||
/* Flush old external LSA */
|
||||
WALK_LIST(oa, po->area_list)
|
||||
{
|
||||
if(en=ospf_hash_find(oa->gr, ipa_to_u32(n->n.prefix), rtid, LSA_T_EXT))
|
||||
net_flush_lsa(en,po,oa);
|
||||
for(i=0;i<MAXNETS;i++,pr++)
|
||||
{
|
||||
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)
|
||||
{
|
||||
net_flush_lsa(en,po,oa);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
|
||||
#define SIPH 64 /* FIXME Size Of IP header */
|
||||
#define MAXNETS 10
|
||||
|
||||
#include "nest/bird.h"
|
||||
|
||||
|
|
122
proto/ospf/rt.c
122
proto/ospf/rt.c
|
@ -8,8 +8,6 @@
|
|||
|
||||
#include "ospf.h"
|
||||
|
||||
#define LOCAL_DEBUG
|
||||
|
||||
void
|
||||
init_infib(struct fib_node *fn)
|
||||
{
|
||||
|
@ -57,12 +55,16 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
en->color=OUTSPF;
|
||||
en->dist=LSINFINITY;
|
||||
en->nhi=NULL;
|
||||
en->nh=ipa_from_u32(0);
|
||||
DBG("Infinitying Type: %u, Id: %I, Rt: %I\n", en->lsa.type, en->lsa.id,
|
||||
en->lsa.rt);
|
||||
}
|
||||
|
||||
FIB_WALK(in,nftmp)
|
||||
{
|
||||
nf=(struct infib *)nftmp;
|
||||
nf->metric=LSINFINITY;
|
||||
nf->en=NULL;
|
||||
}
|
||||
FIB_WALK_END;
|
||||
|
||||
|
@ -109,16 +111,22 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
nf=fib_get(in,&ip, ipa_mklen(ipa_from_u32(rtl->data)));
|
||||
if(nf->metric>(met=act->dist+rtl->metric))
|
||||
{
|
||||
DBG(" Adding stub route....\n");
|
||||
if(oa->rt==act) break;
|
||||
if(act->nhi==NULL) break;
|
||||
nf->metric=met;
|
||||
nf->en=act;
|
||||
DBG(" Adding stub route: %I\n",ip);
|
||||
DBG(" Next hop=%I\n",nf->en->nh);
|
||||
}
|
||||
else DBG(" NOT adding stub route: %I\n",ip);
|
||||
break;
|
||||
case LSART_VLNK:
|
||||
DBG("Ignoring\n");
|
||||
continue;
|
||||
break;
|
||||
case LSART_NET:
|
||||
tmp=ospf_hash_find(oa->gr,rtl->id,rtl->id,LSA_T_NET);
|
||||
tmp=ospf_hash_find(oa->gr,rtl->data,rtl->id,LSA_T_NET);
|
||||
if(tmp==NULL) DBG("Fuck!\n");
|
||||
else DBG("Found. :-)\n");
|
||||
break;
|
||||
|
@ -130,10 +138,12 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
log("Unknown link type in router lsa.");
|
||||
break;
|
||||
}
|
||||
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);
|
||||
}
|
||||
break;
|
||||
case LSA_T_NET: /* FIXME Add to fib */
|
||||
case LSA_T_NET:
|
||||
ln=act->lsa_body;
|
||||
ip=ipa_and(ipa_from_u32(act->lsa.id),ln->netmask);
|
||||
nf=fib_get(in,&ip, ipa_mklen(ln->netmask));
|
||||
|
@ -141,13 +151,13 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
{
|
||||
nf->metric=act->dist;
|
||||
nf->en=act;
|
||||
DBG(" Adding into routing table\n");
|
||||
}
|
||||
|
||||
rts=(u32 *)(ln+1);
|
||||
for(i=0;i<(act->lsa.length-sizeof(struct ospf_lsa_header)-
|
||||
sizeof(struct ospf_lsa_net))/sizeof(u32);i++)
|
||||
{
|
||||
DBG(" Working on router %I ",*(rts+i));
|
||||
DBG(" Working on router %I ", *(rts+i));
|
||||
tmp=ospf_hash_find(oa->gr, *(rts+i), *(rts+i), LSA_T_RT);
|
||||
if(tmp!=NULL) DBG("Found :-)\n");
|
||||
else DBG("Fuck!\n");
|
||||
|
@ -170,8 +180,9 @@ again:
|
|||
ln=en->lsa_body;
|
||||
|
||||
ne=net_get(p->table, nf->fn.prefix, nf->fn.pxlen);
|
||||
DBG("Deleting rt entry %I\n (IP: %I, GW: %I, Iface: %s)\n",
|
||||
nf->fn.prefix,ip,en->nh,en->nhi->name);
|
||||
if((en!=NULL)&&(en->nhi!=NULL))
|
||||
DBG("Deleting rt entry %I\n (P: %x, GW: %I, Iface: %s)\n",
|
||||
nf->fn.prefix, en, en->nh,en->nhi->name);
|
||||
rte_update(p->table, ne, p, NULL);
|
||||
|
||||
/* Now delete my fib */
|
||||
|
@ -211,12 +222,12 @@ again:
|
|||
a0.source=RTS_OSPF;
|
||||
a0.scope=SCOPE_UNIVERSE; /* What's this good for? */
|
||||
a0.cast=RTC_UNICAST;
|
||||
a0.dest=RTD_ROUTER;
|
||||
if(ipa_to_u32(en->nh)==0) a0.dest=RTD_DEVICE;
|
||||
else a0.dest=RTD_ROUTER;
|
||||
a0.flags=0;
|
||||
a0.aflags=0;
|
||||
a0.iface=en->nhi;
|
||||
a0.gw=en->nh;
|
||||
a0.from=en->nh; /* FIXME Just a test */
|
||||
ne=net_get(p->table, nf->fn.prefix, nf->fn.pxlen);
|
||||
e=rte_get_temp(&a0);
|
||||
e->u.ospf.metric1=nf->metric;
|
||||
|
@ -225,8 +236,8 @@ again:
|
|||
e->pflags = 0;
|
||||
e->net=ne;
|
||||
e->pref = p->preference;
|
||||
DBG("Modifying rt entry %I\n (IP: %I, GW: %I, Iface: %s)\n",
|
||||
nf->fn.prefix,ip,en->nh,en->nhi->name);
|
||||
DBG("Modifying rt entry %I\n (GW: %I, Iface: %s)\n",
|
||||
nf->fn.prefix,en->nh,en->nhi->name);
|
||||
rte_update(p->table, ne, p, e);
|
||||
}
|
||||
}
|
||||
|
@ -282,6 +293,9 @@ ospf_ext_spfa(struct proto_ospf *po) /* FIXME looking into inter-area */
|
|||
le=en->lsa_body;
|
||||
lt=(struct ospf_lsa_ext_tos *)(le+1);
|
||||
|
||||
DBG("%s: Working on LSA. ID: %I, RT: %I, Type: %u, Mask %I\n",
|
||||
p->name,en->lsa.id,en->lsa.rt,en->lsa.type,le->netmask);
|
||||
|
||||
if(lt->metric==LSINFINITY) continue;
|
||||
ip=ipa_and(ipa_from_u32(en->lsa.id),le->netmask);
|
||||
mlen=ipa_mklen(le->netmask);
|
||||
|
@ -296,11 +310,10 @@ ospf_ext_spfa(struct proto_ospf *po) /* FIXME looking into inter-area */
|
|||
|
||||
WALK_LIST(atmp,po->area_list)
|
||||
{
|
||||
if((nf=fib_find(&atmp->infib,&ip, mlen))!=NULL) break;
|
||||
if((nf=fib_find(&atmp->infib,&ip, mlen))!=NULL) continue;
|
||||
/* Some intra area path exists */
|
||||
}
|
||||
|
||||
if(nf!=NULL) continue; /* Some intra area path exists */
|
||||
|
||||
absr=NULL;
|
||||
absroa=NULL;
|
||||
nnhi=NULL;
|
||||
|
@ -320,7 +333,11 @@ ospf_ext_spfa(struct proto_ospf *po) /* FIXME looking into inter-area */
|
|||
}
|
||||
}
|
||||
}
|
||||
if((absr==NULL)||(absr->dist==LSINFINITY)) continue;
|
||||
if((absr==NULL)||(absr->dist==LSINFINITY))
|
||||
{
|
||||
DBG("ABSR is null or its dist=INF\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(ipa_compare(lt->fwaddr,ipa_from_u32(0))==0)
|
||||
{
|
||||
|
@ -346,7 +363,13 @@ ospf_ext_spfa(struct proto_ospf *po) /* FIXME looking into inter-area */
|
|||
break;
|
||||
}
|
||||
}
|
||||
if(nf==NULL) continue;
|
||||
|
||||
if(nf==NULL)
|
||||
{
|
||||
DBG("Cannot find network route (GW=%I\n",lt->fwaddr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(lt->etos>0)
|
||||
{
|
||||
met=nf->metric;
|
||||
|
@ -385,6 +408,7 @@ ospf_ext_spfa(struct proto_ospf *po) /* FIXME looking into inter-area */
|
|||
|
||||
if((neigh=find_neigh_noifa(po,absr->lsa.rt))==NULL)
|
||||
{
|
||||
DBG("Cannot find neighbor\n");
|
||||
continue;
|
||||
}
|
||||
nn=neigh_find(p,&neigh->ip,0);
|
||||
|
@ -438,7 +462,6 @@ noch:
|
|||
a0.aflags=0;
|
||||
a0.iface=nf->nhi;
|
||||
a0.gw=nf->nh;
|
||||
a0.from=nf->nh; /* FIXME Just a test */
|
||||
ne=net_get(p->table, nf->fn.prefix, nf->fn.pxlen);
|
||||
e=rte_get_temp(&a0);
|
||||
e->u.ospf.metric1=nf->metric;
|
||||
|
@ -526,22 +549,65 @@ calc_next_hop(struct top_hash_entry *par, struct top_hash_entry *en,
|
|||
struct ospf_neighbor *neigh;
|
||||
struct proto *p=&oa->po->proto;
|
||||
struct proto_ospf *po=oa->po;
|
||||
struct ospf_iface *ifa;
|
||||
DBG(" Next hop called\n");
|
||||
if(par==oa->rt) return;
|
||||
if(par->nhi==NULL)
|
||||
if(ipa_to_u32(par->nh)==0)
|
||||
{
|
||||
neighbor *nn;
|
||||
DBG(" Next hop calculating for id: %I rt: %I type: %u\n",en->lsa.id,en->lsa.rt,en->lsa.type);
|
||||
if(par->lsa.type!=LSA_T_RT) return;
|
||||
if((neigh=find_neigh_noifa(po,par->lsa.rt))==NULL) return;
|
||||
nn=neigh_find(p,&neigh->ip,0);
|
||||
DBG(" Next hop calculated: %I\n", nn->addr);
|
||||
en->nh=nn->addr;
|
||||
en->nhi=nn->iface;
|
||||
return;
|
||||
if(par->lsa.type!=LSA_T_RT)
|
||||
{
|
||||
if((neigh=find_neigh_noifa(po,par->lsa.rt))==NULL) return;
|
||||
nn=neigh_find(p,&neigh->ip,0);
|
||||
DBG(" Next hop calculated: %I.\n", nn->addr);
|
||||
en->nh=nn->addr;
|
||||
en->nhi=nn->iface;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(par==oa->rt)
|
||||
{
|
||||
if(en->lsa.type==LSA_T_NET)
|
||||
{
|
||||
struct ospf_lsa_net *ne;
|
||||
ne=en->lsa_body;
|
||||
|
||||
DBG("I'm parent (Net=%I)\n",(en->lsa.id & ipa_to_u32(ne->netmask)));
|
||||
|
||||
WALK_LIST(ifa, oa->po->iface_list)
|
||||
{
|
||||
if(ipa_to_u32(ipa_and(ifa->iface->addr->ip,
|
||||
ipa_mkmask(ifa->iface->addr->pxlen))) ==
|
||||
(en->lsa.id & ipa_to_u32(ne->netmask)))
|
||||
{
|
||||
en->nhi=ifa->iface;
|
||||
en->nh=ipa_from_u32(0);
|
||||
DBG("Ifa: %s\n",en->nhi->name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if((neigh=find_neigh_noifa(po,par->lsa.rt))==NULL) return;
|
||||
nn=neigh_find(p,&neigh->ip,0);
|
||||
en->nh=ipa_from_u32(0);
|
||||
en->nhi=nn->iface;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if((neigh=find_neigh_noifa(po,par->lsa.rt))==NULL) return;
|
||||
nn=neigh_find(p,&neigh->ip,0);
|
||||
DBG(" Next hop calculated: %I\n", nn->addr);
|
||||
en->nh=nn->addr;
|
||||
en->nhi=nn->iface;
|
||||
return;
|
||||
}
|
||||
}
|
||||
en->nh=par->nh;
|
||||
en->nhi=par->nhi;
|
||||
DBG(" Next hop calculated: %I\n", en->nh);
|
||||
DBG(" Next hop calculated: %I..\n", en->nh);
|
||||
}
|
||||
|
||||
|
|
|
@ -120,8 +120,8 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length, struct proto_ospf *p)
|
|||
if(((ifa->state==OSPF_IS_DR) && (j==1)) || (k==1))
|
||||
{
|
||||
ln->type=LSART_NET;
|
||||
ln->id=ipa_to_u32(ifa->drip);
|
||||
ln->data=ipa_to_u32(ifa->iface->addr->ip);
|
||||
ln->id=ifa->drid;
|
||||
ln->data=ipa_to_u32(ifa->drip);
|
||||
ln->metric=ifa->cost;
|
||||
ln->notos=0;
|
||||
}
|
||||
|
@ -227,6 +227,7 @@ originate_rt_lsa(struct ospf_area *oa)
|
|||
en=lsa_install_new(&lsa, body, oa, &po->proto);
|
||||
oa->rt=en;
|
||||
flood_lsa(NULL,NULL,&oa->rt->lsa,po,NULL,oa,1);
|
||||
schedule_rtcalc(oa);
|
||||
}
|
||||
|
||||
void *
|
||||
|
@ -300,6 +301,8 @@ originate_net_lsa(struct ospf_iface *ifa, struct proto_ospf *po)
|
|||
body=originate_net_lsa_body(ifa, &lsa.length, po);
|
||||
lsasum_calculate(&lsa,body,po);
|
||||
ifa->nlsa=lsa_install_new(&lsa, body, ifa->oa, &po->proto);
|
||||
debug("NetLsa: Id: %I, Sum: %u Sn: 0x%x\n",ifa->nlsa->lsa.id,
|
||||
ifa->nlsa->lsa.checksum, ifa->nlsa->lsa.sn);
|
||||
flood_lsa(NULL,NULL,&ifa->nlsa->lsa,po,NULL,ifa->oa,1);
|
||||
}
|
||||
|
||||
|
@ -350,7 +353,10 @@ originate_ext_lsa(net *n, rte *e, struct proto_ospf *po, struct ea_list *attrs)
|
|||
u32 rtid=po->proto.cf->global->router_id;
|
||||
struct top_hash_entry *en=NULL;
|
||||
void *body=NULL;
|
||||
struct proto *p=&po->proto;
|
||||
struct ospf_area *oa;
|
||||
struct ospf_lsa_ext *ext1,*ext2;
|
||||
int i;
|
||||
|
||||
debug("%s: Originating Ext lsa for %I/%d.\n", po->proto.name, n->n.prefix,
|
||||
n->n.pxlen);
|
||||
|
@ -363,6 +369,28 @@ originate_ext_lsa(net *n, rte *e, struct proto_ospf *po, struct ea_list *attrs)
|
|||
body=originate_ext_lsa_body(n, e, po, attrs);
|
||||
lsa.length=sizeof(struct ospf_lsa_ext)+sizeof(struct ospf_lsa_ext_tos)+
|
||||
sizeof(struct ospf_lsa_header);
|
||||
ext1=body;
|
||||
|
||||
oa=HEAD(po->area_list);
|
||||
|
||||
for(i=0;i<MAXNETS;i++)
|
||||
{
|
||||
if((en=ospf_hash_find_header(oa->gr, &lsa))!=NULL)
|
||||
{
|
||||
ext2=en->lsa_body;
|
||||
if(ipa_compare(ext1->netmask,ext2->netmask)!=0) lsa.id++;
|
||||
else break;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
if(i==MAXNETS)
|
||||
{
|
||||
log("%s: got more routes for one network then %d, ignoring",p->name,
|
||||
MAXNETS);
|
||||
mb_free(body);
|
||||
return;
|
||||
}
|
||||
lsasum_calculate(&lsa,body,po);
|
||||
WALK_LIST(oa, po->area_list)
|
||||
{
|
||||
|
@ -411,11 +439,7 @@ ospf_top_hash_u32(u32 a)
|
|||
static inline unsigned
|
||||
ospf_top_hash(struct top_graph *f, 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==2) ? lsaid : rtrid) + type) & f->hash_mask;
|
||||
#else
|
||||
return (ospf_top_hash_u32(lsaid) + ospf_top_hash_u32(rtrid) + type) & f->hash_mask;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct top_graph *
|
||||
|
@ -486,21 +510,8 @@ ospf_hash_find(struct top_graph *f, u32 lsa, u32 rtr, u32 type)
|
|||
{
|
||||
struct top_hash_entry *e = f->hash_table[ospf_top_hash(f, lsa, rtr, type)];
|
||||
|
||||
#if 1
|
||||
if(type==2 && lsa==rtr)
|
||||
{
|
||||
while (e && (e->lsa.id != lsa || e->lsa.type != 2 ))
|
||||
e = e->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
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
|
||||
return e;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue