summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--proto/ospf/ospf.c213
-rw-r--r--proto/ospf/ospf.h1
2 files changed, 165 insertions, 49 deletions
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index a5ec2d1..a435686 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -46,7 +46,7 @@ neighbor_timer_hook(timer *timer)
n=(struct ospf_neighbor *)timer->data;
ifa=n->ifa;
p=(struct proto *)(ifa->proto);
- debug("%s: Inactivity timer fired on interface %s for neighbor %d.\n",
+ debug("%s: Inactivity timer fired on interface %s for neighbor %u.\n",
p->name, ifa->iface->name, n->rid);
tm_stop(n->inactim);
rfree(n->inactim);
@@ -55,13 +55,151 @@ neighbor_timer_hook(timer *timer)
debug("%s: Deleting neigbor.\n", p->name);
}
-/*
void
-backupseen()
+iface_chstate(struct ospf_iface *ifa, u8 state)
+{
+ struct proto *p;
+
+ p=(struct proto *)(ifa->proto);
+ debug("%s: Changing state of iface: %s from %u into %u.\n",
+ p->name, ifa->iface->name, ifa->state, state);
+ ifa->state=state;
+}
+
+struct ospf_neighbor *
+electbdr(list nl)
{
- ; /* Backup Seen Event *
+ struct ospf_neighbor *neigh,*n1,*n2;
+
+ n1=NULL;
+ n2=NULL;
+ WALK_LIST (neigh, nl) /* First try those decl. themselves */
+ {
+ if(neigh->state>=NEIGHBOR_2WAY) /* Higher than 2WAY */
+ if(neigh->priority>0) /* Eligible */
+ if(neigh->rid!=neigh->dr) /* And not declaring itself DR */
+ {
+ if(neigh->rid==neigh->bdr) /* Declaring BDR */
+ {
+ if(n1!=NULL)
+ {
+ if(neigh->priority>n1->priority) n1=neigh;
+ else if(neigh->priority==n1->priority)
+ if(neigh->rid>n1->rid) n1=neigh;
+ }
+ else
+ {
+ n1=neigh;
+ }
+ }
+ else /* And NOT declaring BDR */
+ {
+ if(n2!=NULL)
+ {
+ if(neigh->priority>n2->priority) n2=neigh;
+ else if(neigh->priority==n2->priority)
+ if(neigh->rid>n2->rid) n2=neigh;
+ }
+ else
+ {
+ n2=neigh;
+ }
+ }
+ }
+ }
+ if(n1==NULL) n1=n2;
+
+ return(n1);
+}
+
+struct ospf_neighbor *
+electdr(list nl)
+{
+ struct ospf_neighbor *neigh,*n;
+
+ n=NULL;
+ WALK_LIST (neigh, nl) /* And now DR */
+ {
+ if(neigh->state>=NEIGHBOR_2WAY) /* Higher than 2WAY */
+ if(neigh->priority>0) /* Eligible */
+ if(neigh->rid==neigh->dr) /* And declaring itself DR */
+ {
+ if(n!=NULL)
+ {
+ if(neigh->priority>n->priority) n=neigh;
+ else if(neigh->priority==n->priority)
+ if(neigh->rid>n->rid) n=neigh;
+ }
+ else
+ {
+ n=neigh;
+ }
+ }
+ }
+
+ return(n);
+}
+
+void
+backupseen(struct ospf_iface *ifa)
+{
+ struct proto *p;
+ struct ospf_neighbor *neigh,*ndr,*nbdr,me;
+ u32 myid;
+
+ p=(struct proto *)(ifa->proto);
+
+ DBG("%s: (B)DR election.\n",p->name);
+
+ myid=p->cf->global->router_id;
+
+ me.state=NEIGHBOR_2WAY;
+ me.rid=myid;
+ me.priority=ifa->priority;
+ me.dr=ifa->drid;
+ me.bdr=ifa->bdrid;
+
+ add_tail(&ifa->neigh_list, NODE &me);
+
+ nbdr=electbdr(ifa->neigh_list);
+ ndr=electdr(ifa->neigh_list);
+
+ if(ndr==NULL) ndr=nbdr;
+
+ if(((ifa->drid==myid) && (ndr!=myid))
+ || ((ifa->drid!=myid) && (ndr==myid))
+ || ((ifa->bdrid==myid) && (nbdr!=myid))
+ || ((ifa->bdrid!=myid) && (nbdr==myid)))
+ {
+ if(ndr==NULL) ifa->drid=me.dr=0;
+ else ifa->drid=me.dr=ndr->rid;
+
+ if(nbdr==NULL) ifa->bdrid=me.bdr=0;
+ else ifa->bdrid=me.bdr=nbdr->rid;
+
+ nbdr=electbdr(ifa->neigh_list);
+ ndr=electdr(ifa->neigh_list);
+ }
+ if(ndr==NULL) ifa->drid=0;
+ else ifa->drid=ndr->rid;
+
+ if(nbdr==NULL) ifa->bdrid=0;
+ else ifa->bdrid=me.bdr=nbdr->rid;
+
+ DBG("%s: DR=%u, BDR=%u\n",p->name, ifa->drid, ifa->bdrid);
+
+ tm_stop(ifa->wait_timer);
+ DBG("%s: Stoping wait timer\n",p->name);
+
+ if(myid==ifa->drid) iface_chstate(ifa, OSPF_IS_DR);
+ else
+ {
+ if(myid==ifa->bdrid) iface_chstate(ifa, OSPF_IS_BACKUP);
+ else iface_chstate(ifa, OSPF_IS_DROTHER);
+ }
+
+ rem_node(NODE &me);
}
-*/
void
ospf_hello_rx(struct ospf_hello_packet *ps, struct proto *p,
@@ -77,7 +215,7 @@ ospf_hello_rx(struct ospf_hello_packet *ps, struct proto *p,
if(ipa_mklen(ipa_ntoh(ps->netmask))!=ifa->iface->addr->pxlen)
{
ip_ntop(ps->netmask,sip);
- log("%s: Bad OSPF packet from %d received: bad netmask %s.",
+ log("%s: Bad OSPF packet from %u received: bad netmask %s.",
p->name, nrid, sip);
log("%s: Discarding",p->name);
return;
@@ -85,7 +223,7 @@ ospf_hello_rx(struct ospf_hello_packet *ps, struct proto *p,
if(ntohs(ps->helloint)!=ifa->helloint)
{
- log("%s: Bad OSPF packet from %d received: hello interval mismatch.",
+ log("%s: Bad OSPF packet from %u received: hello interval mismatch.",
p->name, nrid);
log("%s: Discarding",p->name);
return;
@@ -93,7 +231,7 @@ ospf_hello_rx(struct ospf_hello_packet *ps, struct proto *p,
if(ntohl(ps->deadint)!=ifa->helloint*ifa->deadc)
{
- log("%s: Bad OSPF packet from %d received: dead interval mismatch.",
+ log("%s: Bad OSPF packet from %u received: dead interval mismatch.",
p->name, nrid);
log("%s: Discarding",p->name);
return;
@@ -102,7 +240,7 @@ ospf_hello_rx(struct ospf_hello_packet *ps, struct proto *p,
if(ps->options!=ifa->options)
{
- log("%s: Bad OSPF packet from %d received: options mismatch.",
+ log("%s: Bad OSPF packet from %u received: options mismatch.",
p->name, nrid); /* FIXME: This not good */
log("%s: Discarding",p->name);
return;
@@ -120,7 +258,7 @@ ospf_hello_rx(struct ospf_hello_packet *ps, struct proto *p,
if(n==NULL)
{
- log("%s: New neighbor found: %d.",p->name,nrid);
+ log("%s: New neighbor found: %u.",p->name,nrid);
n=mb_alloc(p->pool, sizeof(struct ospf_neighbor));
add_tail(&ifa->neigh_list, NODE n);
n->inactim=tm_new(p->pool);
@@ -146,7 +284,7 @@ ospf_hello_rx(struct ospf_hello_packet *ps, struct proto *p,
if(ntohl(*(pnrid+i))==p->cf->global->router_id)
{
twoway=1;
- DBG("%s: Twoway received. %d\n", p->name, nrid);
+ DBG("%s: Twoway received. %u\n", p->name, nrid);
break;
}
}
@@ -172,9 +310,9 @@ ospf_hello_rx(struct ospf_hello_packet *ps, struct proto *p,
/* Check neighbor's designed router idea */
if((n->rid!=ntohl(ps->dr)) && (ntohl(ps->bdr)==0) &&
- (ifa->state==OSPF_IS_WAITING))
+ (ifa->state==OSPF_IS_WAITING) && (n->state>=NEIGHBOR_2WAY))
{
- /* FIXME BackupSeen */;
+ backupseen(ifa);
}
if((n->rid==ntohl(ps->dr)) && (n->dr!=ntohl(ps->dr)))
{
@@ -187,9 +325,10 @@ ospf_hello_rx(struct ospf_hello_packet *ps, struct proto *p,
n->dr=ntohl(ps->dr); /* And update it */
/* Check neighbor's backup designed router idea */
- if((n->rid==ntohl(ps->bdr)) && (ifa->state==OSPF_IS_WAITING))
+ if((n->rid==ntohl(ps->bdr)) && (ifa->state==OSPF_IS_WAITING)
+ && (n->state>=NEIGHBOR_2WAY))
{
- /* FIXME BackupSeen */;
+ backupseen(ifa);
}
if((n->rid==ntohl(ps->bdr)) && (n->bdr!=ntohl(ps->bdr)))
{
@@ -278,7 +417,7 @@ ospf_rx_hook(sock *sk, int size)
if(size < sizeof(struct ospf_packet))
{
- log("%s: Bad packet received: too short (%d bytes)", p->name, size);
+ log("%s: Bad packet received: too short (%u bytes)", p->name, size);
log("%s: Discarding",p->name);
return(1);
}
@@ -292,7 +431,7 @@ ospf_rx_hook(sock *sk, int size)
if(ps->version!=OSPF_VERSION)
{
- log("%s: Bad packet received: version %d", p->name, ps->version);
+ log("%s: Bad packet received: version %u", p->name, ps->version);
log("%s: Discarding",p->name);
return(1);
}
@@ -317,9 +456,9 @@ ospf_rx_hook(sock *sk, int size)
/* Dump packet */
pu8=(u8 *)(sk->rbuf+5*4);
for(i=0;i<ntohs(ps->length);i+=4)
- debug("%s: received %d,%d,%d,%d\n",p->name, pu8[i+0], pu8[i+1], pu8[i+2],
+ debug("%s: received %u,%u,%u,%u\n",p->name, pu8[i+0], pu8[i+1], pu8[i+2],
pu8[i+3]);
- debug("%s: received size: %d\n",p->name,size);
+ debug("%s: received size: %u\n",p->name,size);
switch(ps->type)
{
@@ -337,7 +476,7 @@ ospf_rx_hook(sock *sk, int size)
case LSACK:
break;
default:
- log("%s: Bad packet received: wrong type %d", p->name, ps->type);
+ log("%s: Bad packet received: wrong type %u", p->name, ps->type);
log("%s: Discarding",p->name);
return(1);
};
@@ -537,32 +676,8 @@ wait_timer_hook(timer *timer)
p=(struct proto *)(ifa->proto);
debug("%s: Wait timer fired on interface %s.\n",
p->name, ifa->iface->name);
- if(ifa->state=OSPF_IS_WAITING)
- {
- /*
- * Wait time fired. Now we must change state
- * to DR or DROTHER depending on priority
- * FIXME: I can be also BDR
- */
- if(ifa->priority!=0)
- {
- debug("%s: Changing state into DR.\n", p->name);
-
- ifa->state=OSPF_IS_DR;
- ifa->drip=ifa->iface->addr->ip;
- ifa->drid=p->cf->global->router_id;
- /* FIXME: Set ifa->drid */
- }
- else
- {
- debug("%s: Changing state into DROTHER.\n",p->name);
- ifa->state=OSPF_IS_DROTHER;
- }
- }
- else
- {
- die("%s: Wait timer fired I'm not in WAITING state?", p->name);
- }
+ if(ifa->state=OSPF_IS_WAITING) backupseen(ifa);
+ else die("%s: Wait timer fired I'm not in WAITING state?", p->name);
}
void
@@ -579,7 +694,7 @@ ospf_add_timers(struct ospf_iface *ifa, pool *pool, int wait)
ifa->hello_timer->hook=hello_timer_hook;
ifa->hello_timer->recurrent=ifa->helloint;
tm_start(ifa->hello_timer,ifa->helloint);
- DBG("%s: Installing hello timer. (%d)\n", p->name, ifa->helloint);
+ DBG("%s: Installing hello timer. (%u)\n", p->name, ifa->helloint);
if((ifa->type!=OSPF_IT_PTP))
{
/* Install wait timer on NOT-PtP interfaces */
@@ -590,7 +705,7 @@ ospf_add_timers(struct ospf_iface *ifa, pool *pool, int wait)
ifa->wait_timer->recurrent=0;
ifa->state=OSPF_IS_WAITING;
tm_start(ifa->wait_timer,(wait!=0 ? wait : WAIT_DMH*ifa->helloint));
- DBG("%s: Installing wait timer. (%d)\n", p->name, (wait!=0 ? wait : WAIT_DMH*ifa->helloint));
+ DBG("%s: Installing wait timer. (%u)\n", p->name, (wait!=0 ? wait : WAIT_DMH*ifa->helloint));
}
else ifa->state=OSPF_IS_PTP;
}
@@ -712,7 +827,7 @@ ospf_dump(struct proto *p)
DBG(p->name);
DBG(": Dump.\n");
- debug(" -AreaID: %d\n", c->area );
+ debug(" -AreaID: %u\n", c->area );
}
static struct proto *
diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h
index 164bed3..ca563a4 100644
--- a/proto/ospf/ospf.h
+++ b/proto/ospf/ospf.h
@@ -110,6 +110,7 @@ struct ospf_hello_packet {
struct ospf_neighbor
{
+ node n;
struct ospf_iface *ifa;
int state;
#define NEIGHBOR_DOWN 0