diff options
Diffstat (limited to 'proto')
-rw-r--r-- | proto/ospf/hello.c | 7 | ||||
-rw-r--r-- | proto/ospf/lsack.c | 130 | ||||
-rw-r--r-- | proto/ospf/lsack.h | 12 | ||||
-rw-r--r-- | proto/ospf/lsupd.c | 39 | ||||
-rw-r--r-- | proto/ospf/neighbor.c | 1 | ||||
-rw-r--r-- | proto/ospf/ospf.h | 2 | ||||
-rw-r--r-- | proto/ospf/packet.c | 9 | ||||
-rw-r--r-- | proto/ospf/packet.h | 1 |
8 files changed, 175 insertions, 26 deletions
diff --git a/proto/ospf/hello.c b/proto/ospf/hello.c index 77d114c..aea9c14 100644 --- a/proto/ospf/hello.c +++ b/proto/ospf/hello.c @@ -118,6 +118,13 @@ ospf_hello_rx(struct ospf_hello_packet *ps, struct proto *p, n->lsrr_timer->hook=lsrr_timer_hook; n->lsrr_timer->recurrent=ifa->rxmtint; DBG("%s: Installing lsrr timer.\n", p->name); + init_list(&n->ackl); + n->ackd_timer=tm_new(p->pool); + n->ackd_timer->data=n; + n->ackd_timer->randomize=0; + n->ackd_timer->hook=ackd_timer_hook; + n->ackd_timer->recurrent=ifa->rxmtint/2; /* FIXME use some config? */ + DBG("%s: Installing ackd timer.\n", p->name); } ospf_neigh_sm(n, INM_HELLOREC); diff --git a/proto/ospf/lsack.c b/proto/ospf/lsack.c index c5f6bed..53346bc 100644 --- a/proto/ospf/lsack.c +++ b/proto/ospf/lsack.c @@ -8,12 +8,131 @@ #include "ospf.h" +/* Note, that h is in network endianity! */ void -ospf_lsack_tx(struct ospf_neighbor *n) +ospf_lsack_direct_tx(struct ospf_neighbor *n,struct ospf_lsa_header *h) { - /* FIXME Go on! */ + struct ospf_packet *op; + struct ospf_lsack_packet *pk; + sock *sk=n->ifa->ip_sk; + u16 len; + + pk=(struct ospf_lsack_packet *)sk->tbuf; + op=(struct ospf_packet *)sk->tbuf; + + fill_ospf_pkt_hdr(n->ifa, pk, LSUPD); + + memcpy(pk+1,h,sizeof(struct ospf_lsa_header)); + len=sizeof(struct ospf_lsack_packet)+sizeof(struct ospf_lsa_header); + op->length=htons(len); + ospf_pkt_finalize(n->ifa, op); + sk_send_to(sk,len, n->ip, OSPF_PROTO); +} + +void +ospf_lsa_delay(struct ospf_neighbor *n,struct ospf_lsa_header *h, + struct proto *p) +{ + struct lsah_n *no; + + no=mb_alloc(p->pool,sizeof(struct lsah_n)); + memcpy(&no->lsa,h,sizeof(struct ospf_lsa_header)); + add_tail(&n->ackl, NODE no); + +} + +void +ackd_timer_hook(timer *t) +{ + struct ospf_neighbor *n=t->data; + if(!EMPTY_LIST(n->ackl)) ospf_lsack_delay_tx(n); +} + +void +ospf_lsack_delay_tx(struct ospf_neighbor *n) +{ + struct ospf_packet *op; + struct ospf_lsack_packet *pk; + sock *sk; + u16 len,i=0; + struct ospf_lsa_header *h; + struct lsah_n *no; + struct ospf_iface *ifa=n->ifa; + + if(ifa->type==OSPF_IT_BCAST) + { + sk=ifa->hello_sk; + } + else + { + sk=ifa->ip_sk; + } + + pk=(struct ospf_lsack_packet *)sk->tbuf; + op=(struct ospf_packet *)sk->tbuf; + + fill_ospf_pkt_hdr(n->ifa, pk, LSUPD); + h=(struct ospf_lsa_header *)(pk+1); + + while(!EMPTY_LIST(n->ackl)) + { + no=(struct lsah_n *)HEAD(n->ackl); + memcpy(h+i,&no->lsa, sizeof(struct ospf_lsa_header)); + i++; + rem_node(NODE n); + if((i*sizeof(struct ospf_lsa_header)+sizeof(struct ospf_lsack_packet)-SIPH)> + n->ifa->iface->mtu) + { + if(!EMPTY_LIST(n->ackl)) + { + len=sizeof(struct ospf_lsack_packet)+i*sizeof(struct ospf_lsa_header); + op->length=htons(len); + ospf_pkt_finalize(n->ifa, op); + if(ifa->type==OSPF_IT_BCAST) + { + if((ifa->state==OSPF_IS_DR)||(ifa->state==OSPF_IS_BACKUP)) + { + sk_send_to(sk ,len, AllSPFRouters, OSPF_PROTO); + } + else + { + sk_send_to(sk ,len, AllDRouters, OSPF_PROTO); + } + } + else + { + sk_send_to_agt(sk, len, ifa, NEIGHBOR_EXCHANGE); + } + + fill_ospf_pkt_hdr(n->ifa, pk, LSUPD); + h=(struct ospf_lsa_header *)(pk+1); + i=0; + } + } + } + + len=sizeof(struct ospf_lsack_packet)+i*sizeof(struct ospf_lsa_header); + op->length=htons(len); + ospf_pkt_finalize(n->ifa, op); + if(ifa->type==OSPF_IT_BCAST) + { + if((ifa->state==OSPF_IS_DR)||(ifa->state==OSPF_IS_BACKUP)) + { + sk_send_to(sk ,len, AllSPFRouters, OSPF_PROTO); + } + else + { + sk_send_to(sk ,len, AllDRouters, OSPF_PROTO); + } + } + else + { + sk_send_to_agt(sk, len, ifa, NEIGHBOR_EXCHANGE); + } } + + void ospf_lsack_rx(struct ospf_lsack_packet *ps, struct proto *p, struct ospf_iface *ifa, u16 size) @@ -60,10 +179,3 @@ ospf_lsack_rx(struct ospf_lsack_packet *ps, struct proto *p, ospf_hash_delete(n->lsrth,en); } } - -void -add_ack_list(struct ospf_neighbor *n,struct ospf_lsa_header *lsa) -{ - /* FIXME Go on */ -} - diff --git a/proto/ospf/lsack.h b/proto/ospf/lsack.h index 053e0b5..5c4e5c4 100644 --- a/proto/ospf/lsack.h +++ b/proto/ospf/lsack.h @@ -9,10 +9,16 @@ #ifndef _BIRD_OSPF_LSACK_H_ #define _BIRD_OSPF_LSACK_H_ +struct lsah_n { + node n; + struct ospf_lsa_header lsa; +}; -void ospf_lsack_tx(struct ospf_neighbor *n); +void ospf_lsack_direct_tx(struct ospf_neighbor *n,struct ospf_lsa_header *h); void ospf_lsack_rx(struct ospf_lsack_packet *ps, struct proto *p, struct ospf_iface *ifa, u16 size); -void add_ack_list(struct ospf_neighbor *n,struct ospf_lsa_header *lsa); - +void ackd_timer_hook(timer *t); +void ospf_lsack_delay_tx(struct ospf_neighbor *n); +void ospf_lsa_delay(struct ospf_neighbor *n,struct ospf_lsa_header *h, + struct proto *p); #endif /* _BIRD_OSPF_LSACK_H_ */ diff --git a/proto/ospf/lsupd.c b/proto/ospf/lsupd.c index 62b6f76..23e7b1c 100644 --- a/proto/ospf/lsupd.c +++ b/proto/ospf/lsupd.c @@ -122,12 +122,7 @@ flood_lsa(struct ospf_neighbor *n, struct ospf_lsa_header *hn, if(ifa->type==OSPF_IT_NBMA) { - struct ospf_neighbor *nnn; - WALK_LIST(NODE nnn,ifa->neigh_list) - { - if(nnn->state>NEIGHBOR_EXSTART) - sk_send_to(sk,len, nnn->ip, OSPF_PROTO); - } + sk_send_to_agt(sk ,len, ifa, NEIGHBOR_EXCHANGE); } else { @@ -267,19 +262,19 @@ ospf_lsupd_rx(struct ospf_lsupd_packet *ps, struct proto *p, /* pg 143 (4) */ if((lsatmp.age==LSA_MAXAGE)&&(lsadb==NULL)) { - struct ospf_neighbor *n=NULL; - struct ospf_iface *ifa=NULL; int flag=0; + struct ospf_iface *ifatmp; - WALK_LIST(NODE ifa,po->iface_list) - WALK_LIST(NODE ntmp,ifa->neigh_list) + WALK_LIST(NODE ifatmp,po->iface_list) + WALK_LIST(NODE ntmp,ifatmp->neigh_list) if((ntmp->state==NEIGHBOR_EXCHANGE)&& (ntmp->state==NEIGHBOR_LOADING)) flag=1; if(flag==0) { - add_ack_list(n,lsa); + ospf_lsack_direct_tx(n,lsa); + continue; } } @@ -317,7 +312,11 @@ ospf_lsupd_rx(struct ospf_lsupd_packet *ps, struct proto *p, lsadb=lsa_install_new(&lsatmp,body, oa); DBG("New LSA installed in DB\n"); - /* FIXME 144 (5e) ack */ + if(ifa->state==OSPF_IS_BACKUP) + { + if(ifa->drid==n->rid) ospf_lsa_delay(n, lsa, p); + } + else if(ifa->drid==n->rid) ospf_lsa_delay(n, lsa, p); /* FIXME 145 (5f) self originated? */ continue; @@ -330,13 +329,25 @@ ospf_lsupd_rx(struct ospf_lsupd_packet *ps, struct proto *p, { struct top_hash_entry *en; if((en=ospf_hash_find_header(n->lsrth,&lsadb->lsa))!=NULL) + { s_rem_node(SNODE en); - /* FIXME ack_lsa() */ + if(ifa->state==OSPF_IS_BACKUP) + { + if(n->rid==ifa->drid) ospf_lsa_delay(n, lsa, p); + } + } + else + { + ospf_lsack_direct_tx(n,lsa); + } continue; } /* pg145 (8) */ - if((lsadb->lsa.age==LSA_MAXAGE)&&(lsadb->lsa.sn==LSA_MAXSEQNO)) continue; + if((lsadb->lsa.age==LSA_MAXAGE)&&(lsadb->lsa.sn==LSA_MAXSEQNO)) + { + continue; + } { list l; diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c index e57143e..f52ff67 100644 --- a/proto/ospf/neighbor.c +++ b/proto/ospf/neighbor.c @@ -215,6 +215,7 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event) s_init(&(n->lsrqi), &(n->lsrql)); s_init(&(n->lsrti), &(n->lsrtl)); tm_start(n->lsrr_timer,n->ifa->rxmtint); + tm_start(n->ackd_timer,n->ifa->rxmtint/2); } else die("NEGDONE and I'm not in EXSTART?\n"); break; diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index 6bcaef3..0039787 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -286,6 +286,8 @@ struct ospf_neighbor void *ldbdes; /* Last database description packet */ timer *rxmt_timer; /* RXMT timer */ timer *lsrr_timer; /* Link state requiest retransmition timer */ + list ackl; + timer *ackd_timer; /* Delayed ack timer */ }; /* Definitions for interface state machine */ diff --git a/proto/ospf/packet.c b/proto/ospf/packet.c index cefc125..b04fa94 100644 --- a/proto/ospf/packet.c +++ b/proto/ospf/packet.c @@ -187,3 +187,12 @@ ospf_err_hook(sock *sk, int err) DBG("%s: Err_Hook called on interface %s\n", p->name,sk->iface->name); } +void +sk_send_to_agt(sock *sk, u16 len, struct ospf_iface *ifa, u8 state) +{ + struct ospf_neighbor *n; + + WALK_LIST(NODE n,ifa->neigh_list) + if(n->state>=state) + sk_send_to(sk, len, n->ip, OSPF_PROTO); +} diff --git a/proto/ospf/packet.h b/proto/ospf/packet.h index 1997c06..23999a2 100644 --- a/proto/ospf/packet.h +++ b/proto/ospf/packet.h @@ -16,5 +16,6 @@ void ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt); int ospf_rx_hook(sock *sk, int size); void ospf_tx_hook(sock *sk); void ospf_err_hook(sock *sk, int err); +void sk_send_to_agt(sock *sk, u16 len, struct ospf_iface *ifa, u8 state); #endif /* _BIRD_OSPF_PACKET_H_ */ |