summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--proto/ospf/hello.c7
-rw-r--r--proto/ospf/lsack.c130
-rw-r--r--proto/ospf/lsack.h12
-rw-r--r--proto/ospf/lsupd.c39
-rw-r--r--proto/ospf/neighbor.c1
-rw-r--r--proto/ospf/ospf.h2
-rw-r--r--proto/ospf/packet.c9
-rw-r--r--proto/ospf/packet.h1
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_ */