diff options
author | Ondrej Filip <feela@network.cz> | 2001-06-09 16:55:10 +0200 |
---|---|---|
committer | Ondrej Filip <feela@network.cz> | 2001-06-09 16:55:10 +0200 |
commit | e9d3c3aaea24724c285027154bd9f5ddef8394e0 (patch) | |
tree | e67326729beae873e2ffeb28e23ad3e9ecc15d6a | |
parent | ea31425a6191f0b3e181f8a1c7368fc4dfca24b4 (diff) | |
download | bird-e9d3c3aaea24724c285027154bd9f5ddef8394e0.tar bird-e9d3c3aaea24724c285027154bd9f5ddef8394e0.zip |
Bug in next-hop calculation fixed. (For dual connected neighbors.)
-rw-r--r-- | proto/ospf/neighbor.c | 17 | ||||
-rw-r--r-- | proto/ospf/rt.c | 38 |
2 files changed, 38 insertions, 17 deletions
diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c index d22a60e..ca92e9d 100644 --- a/proto/ospf/neighbor.c +++ b/proto/ospf/neighbor.c @@ -432,16 +432,25 @@ find_neigh(struct ospf_iface *ifa, u32 rid) return NULL; } + +/* Find a closest neighbor which is at leas 2-Way */ struct ospf_neighbor * find_neigh_noifa(struct proto_ospf *po, u32 rid) { - struct ospf_neighbor *n; + struct ospf_neighbor *n=NULL,*m; struct ospf_iface *ifa; WALK_LIST (ifa, po->iface_list) - if((n=find_neigh(ifa, rid))!=NULL) - return n; - return NULL; + if((m=find_neigh(ifa, rid))!=NULL) + { + if(m->state>=NEIGHBOR_2WAY) + { + if(n==NULL) n=m; + else + if(m->ifa->cost < n->ifa->cost) n=m; + } + } + return n; } struct ospf_area * diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index 5ab9b6a..c7131fc 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -107,6 +107,7 @@ ospf_rt_spfa(struct ospf_area *oa) switch(rtl->type) { case LSART_STUB: + /* This violates rfc2328! but I hope it's also correct. */ DBG("\n"); ip=ipa_from_u32(rtl->id); nf=fib_get(in,&ip, ipa_mklen(ipa_from_u32(rtl->data))); @@ -128,12 +129,12 @@ ospf_rt_spfa(struct ospf_area *oa) break; case LSART_NET: tmp=ospf_hash_find(oa->gr,rtl->id,rtl->id,LSA_T_NET); - if(tmp==NULL) DBG("Fuck!\n"); + if(tmp==NULL) DBG("Not found!\n"); else DBG("Found. :-)\n"); break; case LSART_PTP: tmp=ospf_hash_find(oa->gr,rtl->id,rtl->id,LSA_T_RT); - DBG("PTP searched.\n"); + DBG("PTP found.\n"); break; default: log("Unknown link type in router lsa."); @@ -161,7 +162,7 @@ ospf_rt_spfa(struct ospf_area *oa) 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"); + else DBG("Not found!\n"); add_cand(&oa->cand,tmp,act,act->dist,oa); } break; @@ -512,6 +513,7 @@ let: FIB_ITERATE_END(nftmp); } +/* Add LSA into list of candidates in Dijkstra alogithm */ void add_cand(list *l, struct top_hash_entry *en, struct top_hash_entry *par, u16 dist, struct ospf_area *oa) @@ -535,7 +537,7 @@ add_cand(list *l, struct top_hash_entry *en, struct top_hash_entry *par, en->nhi=NULL; - calc_next_hop(par,en,oa); + calc_next_hop(en, par, oa); if(en->color==CANDIDATE) /* We found a shorter path */ { @@ -572,11 +574,11 @@ add_cand(list *l, struct top_hash_entry *en, struct top_hash_entry *par, add_tail(l,&en->cn); } } - /* FIXME Some VLINK staff should be here */ + /* FIXME Some VLINK stuff should be here */ } void -calc_next_hop(struct top_hash_entry *par, struct top_hash_entry *en, +calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par, struct ospf_area *oa) { struct ospf_neighbor *neigh; @@ -585,13 +587,14 @@ calc_next_hop(struct top_hash_entry *par, struct top_hash_entry *en, struct ospf_iface *ifa; u32 myrid=p->cf->global->router_id; - DBG(" Next hop called\n"); + DBG(" Next hop called.\n"); 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); +/* xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ if(par==oa->rt) { if(en->lsa.type==LSA_T_NET) @@ -625,14 +628,23 @@ calc_next_hop(struct top_hash_entry *par, struct top_hash_entry *en, if(par->lsa.type==LSA_T_NET) { if(en->lsa.type==LSA_T_NET) bug("Parent for net is net?"); - en->nhi=par->nhi; - if((neigh=find_neigh_noifa(po,en->lsa.rt))==NULL) return; - en->nh=neigh->ip; + if((en->nhi=par->nhi)==NULL) + bug("Did not find next hop interface for INSPF lsa!"); return; } - else + else /* Parent is some RT neighbor */ { - if((neigh=find_neigh_noifa(po,par->lsa.rt))==NULL) return; + /* FIXME: I should probably hold ospf_iface in top_hash_entry */ + neigh=NULL; + WALK_LIST(ifa,po->iface_list) + { + if(ifa->iface==par->nhi) + { + if((neigh=find_neigh(ifa,par->lsa.rt))==NULL) return; + break; + } + } + if(neigh==NULL) bug("I cannot find my neighbor."); nn=neigh_find(p,&neigh->ip,0); if(nn) { @@ -644,6 +656,6 @@ calc_next_hop(struct top_hash_entry *par, struct top_hash_entry *en, } en->nh=par->nh; en->nhi=par->nhi; - DBG(" Next hop calculated: %I..\n", en->nh); + DBG(" Next hop calculated: %I.\n", en->nh); } |