diff --git a/proto/ospf/dbdes.c b/proto/ospf/dbdes.c index c6aba363..16cf817f 100644 --- a/proto/ospf/dbdes.c +++ b/proto/ospf/dbdes.c @@ -76,7 +76,7 @@ ospf_dbdes_tx(struct ospf_neighbor *n) debug("\t%04x %08x %08x %p\n", en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa_body); - if(sn->next==NULL) + if(sn==STAIL(n->ifa->oa->lsal)) { break; /* Should set some flag? */ } @@ -85,7 +85,7 @@ ospf_dbdes_tx(struct ospf_neighbor *n) } i--; - if(sn->next==NULL) + if(sn==STAIL(n->ifa->oa->lsal)) { DBG("Number of LSA NOT sent: %d\n", i); DBG("M bit unset.\n"); @@ -128,7 +128,7 @@ ospf_dbdes_tx(struct ospf_neighbor *n) } sk_send_to(ifa->ip_sk,length, n->ip, OSPF_PROTO); - debug("%s: DB_DES sent for %u.\n", p->name, n->rid); + debug("%s: DB_DES sent to %u.\n", p->name, n->rid); if(n->myimms.bit.ms) tm_start(n->rxmt_timer,ifa->rxmtint); else { @@ -199,6 +199,7 @@ ospf_dbdes_reqladd(struct ospf_dbdes_packet *ps, struct proto *p, ntohlsah(plsa+i, &(sn->lsa)); s_add_tail(&(n->lsrql), SNODE sn); } + /* FIXME and the next part of condition? */ } } } diff --git a/proto/ospf/lsalib.c b/proto/ospf/lsalib.c index a7ef8040..aa7e1f9f 100644 --- a/proto/ospf/lsalib.c +++ b/proto/ospf/lsalib.c @@ -309,11 +309,52 @@ lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2) { if(l1->checksum=!l2->checksum) return l1->checksumchecksum ? CMP_OLDER : CMP_NEWER; - if(l1->age==MAXAGE) return CMP_NEWER; - if(l2->age==MAXAGE) return CMP_OLDER; - if(abs(l1->age-l2->age)>MAXAGEDIFF) + if(l1->age==LSA_MAXAGE) return CMP_NEWER; + if(l2->age==LSA_MAXAGE) return CMP_OLDER; + if(abs(l1->age-l2->age)>LSA_MAXAGEDIFF) return l1->ageage ? CMP_NEWER : CMP_OLDER; } return CMP_SAME; } +/* LSA can be temporarrily, but body must be mb_alloced. */ +struct top_hash_entry * +lsa_install_new(struct ospf_lsa_header *lsa, void *body, struct ospf_area *oa) +{ + int change=0,i; + struct top_hash_entry *en; + + if((en=ospf_hash_find_header(oa->gr,lsa))==NULL) + { + en=ospf_hash_get_header(oa->gr,lsa); + change=1; + s_add_tail(&oa->lsal, SNODE en); + } + else + { + if(en->lsa.options!=lsa->options) change=1; + if((en->lsa.age==LSA_MAXAGE)||(lsa->age==LSA_MAXAGE)) change=1; + if(en->lsa.length!=lsa->length) change=1; + else + { + u8 *k=en->lsa_body,*l=body; + for(i=0;ilength;i++) + { + if(*(k+i)!=*(l+i)) + { + change=1; + break; + } + } + s_rem_node(SNODE en); + s_add_tail(&oa->lsal, SNODE en); + } + } + en->inst_t=now; + if(en->lsa_body!=NULL)mb_free(en->lsa_body); + en->lsa_body=body; + memcpy(&en->lsa,lsa,sizeof(struct ospf_lsa_header)); + + /* FIXME decide if route calcualtion must be done and how */ + return en; +} diff --git a/proto/ospf/lsalib.h b/proto/ospf/lsalib.h index 5332d2ef..bba8c26b 100644 --- a/proto/ospf/lsalib.h +++ b/proto/ospf/lsalib.h @@ -17,10 +17,11 @@ void ntohlsab(void *n, void *h, u8 type, u16 len); void lsasum_calculate(struct ospf_lsa_header *header, void *body, struct proto_ospf *p); u16 lsasum_check(struct ospf_lsa_header *h,void *body,struct proto_ospf *po); - #define CMP_NEWER 1 #define CMP_SAME 0 #define CMP_OLDER -1 int lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2); +struct top_hash_entry *lsa_install_new(struct ospf_lsa_header *lsa, void *body, + struct ospf_area *oa); #endif /* _BIRD_OSPF_LSALIB_H_ */ diff --git a/proto/ospf/lsreq.c b/proto/ospf/lsreq.c index f894c66f..716724a7 100644 --- a/proto/ospf/lsreq.c +++ b/proto/ospf/lsreq.c @@ -45,7 +45,8 @@ ospf_lsreq_tx(struct ospf_neighbor *n) DBG("Requesting %uth LSA: Type: %u, Id: %u, RT: %u\n",i, en->lsa.type, en->lsa.id, en->lsa.rt); lsh++; - if((sn=sn->next)==NULL) break; + if(sn==STAIL(n->lsrql)) break; + sn=sn->next; } length=sizeof(struct ospf_lsreq_packet)+(j-i)*sizeof(struct ospf_lsreq_header); diff --git a/proto/ospf/lsupd.c b/proto/ospf/lsupd.c index 8ff39590..950a1f8d 100644 --- a/proto/ospf/lsupd.c +++ b/proto/ospf/lsupd.c @@ -84,7 +84,7 @@ ospf_lsupd_rx(struct ospf_lsupd_packet *ps, struct proto *p, struct ospf_iface *ifa, u16 size) { u32 area,nrid,myrid; - struct ospf_neighbor *n; + struct ospf_neighbor *n,*ntmp; struct ospf_lsa_header *lsa; struct ospf_area *oa; struct proto_ospf *po=(struct proto_ospf *)p; @@ -132,9 +132,24 @@ ospf_lsupd_rx(struct ospf_lsupd_packet *ps, struct proto *p, continue; } ntohlsah(lsa,&lsatmp); - DBG("Processing update Type: %u ID: %u RT: %u\n",lsa->type, - ntohl(lsa->id), ntohl(lsa->rt)); + DBG("Processing update Type: %u ID: %u RT: %u\n",lsatmp.type, + lsatmp.id, lsatmp.rt); lsadb=ospf_hash_find_header(oa->gr, &lsatmp); + + /* Remove it from link state request list */ + WALK_LIST(NODE ifa,po->iface_list) + WALK_LIST(NODE ntmp,ifa->neigh_list) + { + struct top_hash_entry *en; + if((en=ospf_hash_find_header(ntmp->lsrqh,&lsatmp))!=NULL) + { + s_rem_node(SNODE en); + DBG("Removing from lsreq list for neigh %u\n", ntmp->rid); + ospf_hash_delete(ntmp->lsrqh,en); + if(EMPTY_SLIST(ntmp->lsrql)) ospf_neigh_sm(ntmp, INM_LOADDONE); + } + } + if((lsatmp.age==LSA_MAXAGE)&&(lsadb==NULL)) { struct ospf_neighbor *n=NULL; @@ -142,8 +157,9 @@ ospf_lsupd_rx(struct ospf_lsupd_packet *ps, struct proto *p, int flag=0; WALK_LIST(NODE ifa,po->iface_list) - WALK_LIST(NODE n,ifa->neigh_list) - if((n->state==NEIGHBOR_EXCHANGE)&&(n->state==NEIGHBOR_LOADING)) + WALK_LIST(NODE ntmp,ifa->neigh_list) + if((ntmp->state==NEIGHBOR_EXCHANGE)&& + (ntmp->state==NEIGHBOR_LOADING)) flag=1; if(flag==0) @@ -156,30 +172,32 @@ ospf_lsupd_rx(struct ospf_lsupd_packet *ps, struct proto *p, { struct ospf_neighbor *n=NULL; struct ospf_iface *ifa=NULL; + void *body; /* FIXME self originated? */ if(lsadb && ((lsadb->inst_t-now)iface_list) - WALK_LIST(NODE n,ifa->neigh_list) - { - struct top_hash_entry *en; - if((en=ospf_hash_find_header(n->lsrth,&lsadb->lsa))!=NULL) - s_rem_node(SNODE en); - } + if(lsadb) + WALK_LIST(NODE ifa,po->iface_list) + WALK_LIST(NODE ntmp,ifa->neigh_list) + { + struct top_hash_entry *en; + if((en=ospf_hash_find_header(ntmp->lsrth,&lsadb->lsa))!=NULL) + { + s_rem_node(SNODE en); + ospf_hash_delete(ntmp->lsrth,en); + } + } /* Install new */ - memcpy(&lsadb->lsa,&lsatmp,sizeof(struct ospf_lsa_header)); - lsadb->inst_t=now; - if(lsadb->lsa_body!=NULL) mb_free(lsadb->lsa_body); - lsadb->lsa_body=mb_alloc(p->pool,lsadb->lsa.length- - sizeof(struct ospf_lsa_header)); - ntohlsab(lsa+1,lsadb->lsa_body,lsadb->lsa.type,lsadb->lsa.length); + DBG("Allocatin body, size: %u\n",lsatmp.length-sizeof(struct ospf_lsa_header)); + body=mb_alloc(p->pool,lsatmp.length-sizeof(struct ospf_lsa_header)); + ntohlsab(lsa+1,body,lsatmp.type,lsatmp.length-sizeof(struct ospf_lsa_header)); + lsadb=lsa_install_new(&lsatmp,body, oa); + DBG("New installed\n"); - /* FIXME lsa_flood(n,lsadb) */ - /* FIXME ack_lsa() */ continue; } diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index e166b4ad..371434b8 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -22,8 +22,8 @@ #define HASH_LO_STEP 2 #define HASH_LO_MIN 8 -unsigned int -make_rt_lsa(struct ospf_area *oa, struct proto_ospf *p) +void * +originate_rt_lsa_body(struct ospf_area *oa, u16 *length, struct proto_ospf *p) { struct ospf_iface *ifa; int j=0,k=0,v=0,e=0,b=0; @@ -32,8 +32,9 @@ make_rt_lsa(struct ospf_area *oa, struct proto_ospf *p) struct ospf_lsa_rt_link *ln; struct ospf_neighbor *neigh; struct top_hash_entry *old; + struct proto_ospf *po=(struct proto_ospf *)p; - old=oa->rt; + DBG("%s: Originating RT_lsa body for area \"%d\".\n", po->proto.name, oa->areaid); WALK_LIST (ifa, p->iface_list) i++; { @@ -145,9 +146,9 @@ make_rt_lsa(struct ospf_area *oa, struct proto_ospf *p) ln=(ln+1); } rt->links=i; - if(old->lsa_body!=NULL) mb_free(old->lsa_body); - old->lsa_body=rt; - return i*sizeof(struct ospf_lsa_rt_link)+sizeof(struct ospf_lsa_rt); + *length=i*sizeof(struct ospf_lsa_rt_link)+sizeof(struct ospf_lsa_rt)+ + sizeof(struct ospf_lsa_header); + return rt; } @@ -179,23 +180,42 @@ addifa_rtlsa(struct ospf_iface *ifa) oa->areaid=ifa->an; oa->gr=ospf_top_new(po); s_init_list(&(oa->lsal)); - oa->rt=ospf_hash_get(oa->gr, rtid, rtid, LSA_T_RT); - s_add_head(&(oa->lsal), (snode *)oa->rt); - ((snode *)oa->rt)->next=NULL; - lsa=&(oa->rt->lsa); - oa->rt->lsa_body=NULL; - lsa->age=0; - lsa->sn=LSA_INITSEQNO; /* FIXME Check it latter */ + oa->rt=NULL; po->areano++; DBG("%s: New OSPF area \"%d\" added.\n", po->proto.name, ifa->an); } ifa->oa=oa; - - oa->rt->lsa.length=make_rt_lsa(oa, po)+sizeof(struct ospf_lsa_header); - oa->rt->lsa.checksum=0; - lsasum_calculate(&(oa->rt->lsa),oa->rt->lsa_body,po); - /*FIXME lsa_flood(oa->rt) */ + + oa->rt=originate_rt_lsa(oa,po); +} + +struct top_hash_entry * +originate_rt_lsa(struct ospf_area *oa, struct proto_ospf *po) +{ + struct ospf_lsa_header lsa; + u32 rtid=po->proto.cf->global->router_id; + struct top_hash_entry *en; + void *body; + + DBG("%s: Originating RT_lsa for area \"%d\".\n", po->proto.name, oa->areaid); + + lsa.age=0; + lsa.id=rtid; + lsa.type=LSA_T_RT; + lsa.rt=rtid; + if(oa->rt==NULL) + { + lsa.sn=LSA_INITSEQNO; + } + else + { + lsa.sn=oa->rt->lsa.sn+1; + } + body=originate_rt_lsa_body(oa, &lsa.length, po); + lsasum_calculate(&lsa,body,po); + en=lsa_install_new(&lsa, body, oa); + return en; } @@ -296,6 +316,13 @@ ospf_hash_find_header(struct top_graph *f, struct ospf_lsa_header *h) { return ospf_hash_find(f,h->id,h->rt,h->type); } + +struct top_hash_entry * +ospf_hash_get_header(struct top_graph *f, struct ospf_lsa_header *h) +{ + return ospf_hash_get(f,h->id,h->rt,h->type); +} + struct top_hash_entry * ospf_hash_find(struct top_graph *f, u32 lsa, u32 rtr, u32 type) { diff --git a/proto/ospf/topology.h b/proto/ospf/topology.h index d0e9ad9b..e146c6f3 100644 --- a/proto/ospf/topology.h +++ b/proto/ospf/topology.h @@ -32,9 +32,12 @@ struct top_graph *ospf_top_new(struct proto_ospf *); void ospf_top_free(struct top_graph *); void ospf_top_dump(struct top_graph *); struct top_hash_entry *ospf_hash_find_header(struct top_graph *f, struct ospf_lsa_header *h); +struct top_hash_entry *ospf_hash_get_header(struct top_graph *f, struct ospf_lsa_header *h); struct top_hash_entry *ospf_hash_find(struct top_graph *, u32 lsa, u32 rtr, u32 type); struct top_hash_entry *ospf_hash_get(struct top_graph *, u32 lsa, u32 rtr, u32 type); void ospf_hash_delete(struct top_graph *, struct top_hash_entry *); void addifa_rtlsa(struct ospf_iface *ifa); +struct top_hash_entry *originate_rt_lsa(struct ospf_area *oa, + struct proto_ospf *po); #endif /* _BIRD_OSPF_TOPOLOGY_H_ */