summaryrefslogtreecommitdiffstats
path: root/proto/ospf/neighbor.c
diff options
context:
space:
mode:
Diffstat (limited to 'proto/ospf/neighbor.c')
-rw-r--r--proto/ospf/neighbor.c121
1 files changed, 99 insertions, 22 deletions
diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c
index f2bb636..61bf555 100644
--- a/proto/ospf/neighbor.c
+++ b/proto/ospf/neighbor.c
@@ -1,7 +1,7 @@
/*
* BIRD -- OSPF
*
- * (c) 1999 - 2000 Ondrej Filip <feela@network.cz>
+ * (c) 1999 - 2004 Ondrej Filip <feela@network.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
@@ -22,6 +22,60 @@ const char *ospf_inm[]={ "hello received", "neighbor start", "2-way received",
"adjacency ok?", "sequence mismatch", "1-way received", "kill neighbor",
"inactivity timer", "line down" };
+
+void neighbor_timer_hook(timer *timer);
+void rxmt_timer_hook(timer *timer);
+
+
+
+struct ospf_neighbor *
+ospf_neighbor_new(struct ospf_iface *ifa)
+{
+ struct proto *p = (struct proto *)(ifa->proto);
+ struct pool *pool = rp_new(p->pool, "OSPF Neighbor");
+ struct ospf_neighbor *n = mb_allocz(pool, sizeof(struct ospf_neighbor));
+
+ n->pool = pool;
+ n->ifa = ifa;
+ add_tail(&ifa->neigh_list, NODE n);
+ n->adj = 0;
+ n->ldbdes=mb_alloc(pool, ifa->iface->mtu);
+ n->state=NEIGHBOR_DOWN;
+
+ n->inactim = tm_new(pool);
+ n->inactim->data = n;
+ n->inactim->randomize = 0;
+ n->inactim->hook = neighbor_timer_hook;
+ n->inactim->recurrent = 0;
+ DBG("%s: Installing inactivity timer.\n", p->name);
+
+ n->rxmt_timer = tm_new(pool);
+ n->rxmt_timer->data = n;
+ n->rxmt_timer->randomize = 0;
+ n->rxmt_timer->hook = rxmt_timer_hook;
+ n->rxmt_timer->recurrent = ifa->rxmtint;
+ s_init_list(&(n->lsrql));
+ n->lsrqh = ospf_top_new(pool, n->ifa->proto);
+ s_init_list(&(n->lsrtl));
+ n->lsrth = ospf_top_new(pool, n->ifa->proto);
+ s_init(&(n->dbsi), &(n->ifa->oa->lsal));
+ s_init(&(n->lsrqi), &(n->lsrql));
+ s_init(&(n->lsrti), &(n->lsrtl));
+ tm_start(n->rxmt_timer,n->ifa->rxmtint);
+ DBG("%s: Installing rxmt timer.\n", p->name);
+
+ n->ackd_timer = tm_new(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;
+ init_list(&n->ackl);
+ tm_start(n->ackd_timer,n->ifa->rxmtint/2);
+ DBG("%s: Installing ackd timer.\n", p->name);
+
+ return(n);
+}
+
/**
* neigh_chstate - handles changes related to new or lod state of neighbor
* @n: OSPF neighbor
@@ -67,11 +121,6 @@ neigh_chstate(struct ospf_neighbor *n, u8 state)
schedule_rt_lsa(ifa->oa);
schedule_net_lsa(ifa);
}
- if(oldstate>=NEIGHBOR_EXSTART && state<NEIGHBOR_EXSTART)
- {
- /* Stop RXMT timer */
- tm_stop(n->rxmt_timer);
- }
if(state==NEIGHBOR_EXSTART)
{
if(n->adj==0) /* First time adjacency */
@@ -83,10 +132,7 @@ neigh_chstate(struct ospf_neighbor *n, u8 state)
n->myimms.bit.ms=1;
n->myimms.bit.m=1;
n->myimms.bit.i=1;
- tm_start(n->rxmt_timer,1); /* Or some other number ? */
}
- if(state<NEIGHBOR_EXCHANGE) tm_stop(n->lsrr_timer);
- if(state<NEIGHBOR_EXSTART) tm_stop(n->rxmt_timer);
if(state>NEIGHBOR_EXSTART) n->myimms.bit.i=0;
}
}
@@ -246,9 +292,9 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event)
{
case NEIGHBOR_ATTEMPT:
case NEIGHBOR_DOWN:
- neigh_chstate(n,NEIGHBOR_INIT);
+ neigh_chstate(n, NEIGHBOR_INIT);
default:
- restart_inactim(n);
+ tm_start(n->inactim, n->ifa->deadc*n->ifa->helloint); /* Restart inactivity timer */
break;
}
break;
@@ -268,17 +314,6 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event)
rem_node(NODE no);
mb_free(no);
}
- s_init_list(&(n->lsrql));
- if(n->lsrqh) ospf_top_free(n->lsrqh);
- n->lsrqh=ospf_top_new(n->pool, n->ifa->proto);
- s_init_list(&(n->lsrtl));
- if(n->lsrth) ospf_top_free(n->lsrth);
- n->lsrth=ospf_top_new(n->pool, n->ifa->proto);
- s_init(&(n->dbsi), &(n->ifa->oa->lsal));
- 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 bug("NEGDONE and I'm not in EXSTART?");
break;
@@ -531,3 +566,45 @@ ospf_sh_neigh_info(struct ospf_neighbor *n)
cli_msg(-1013,"%-1I\t%3u\t%s/%s\t%-5s\t%-1I\t%-10s",n->rid, n->priority,
ospf_ns[n->state], pos, etime, n->ip,ifa->iface->name);
}
+
+void
+rxmt_timer_hook(timer *timer)
+{
+ struct ospf_neighbor *n = (struct ospf_neighbor *)timer->data;
+ struct ospf_iface *ifa = n->ifa;
+ struct proto *p = (struct proto *)(ifa->proto);
+ struct top_hash_entry *en;
+
+ DBG("%s: RXMT timer fired on interface %s for neigh: %I.\n",
+ p->name, ifa->iface->name, n->ip);
+ if (n->state < NEIGHBOR_LOADING) ospf_dbdes_tx(n);
+
+ if(n->state < NEIGHBOR_FULL) ospf_lsreq_tx(n);
+ else
+ {
+ if(!EMPTY_SLIST(n->lsrtl))
+ {
+ list uplist;
+ slab *upslab;
+ struct l_lsr_head *llsh;
+
+ init_list(&uplist);
+ upslab=sl_new(n->pool,sizeof(struct l_lsr_head));
+
+ WALK_SLIST(SNODE en,n->lsrtl)
+ {
+ if((SNODE en)->next==(SNODE en)) bug("RTList is cycled");
+ llsh=sl_alloc(upslab);
+ llsh->lsh.id=en->lsa.id;
+ llsh->lsh.rt=en->lsa.rt;
+ llsh->lsh.type=en->lsa.type;
+ DBG("Working on ID: %I, RT: %I, Type: %u\n",
+ en->lsa.id, en->lsa.rt, en->lsa.type);
+ add_tail(&uplist, NODE llsh);
+ }
+ ospf_lsupd_tx_list(n, &uplist);
+ rfree(upslab);
+ }
+ }
+}
+