diff --git a/doc/bird.sgml b/doc/bird.sgml
index 3722e489..5441e31e 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -1015,15 +1015,18 @@ protocol ospf <name> {
{
cost <num>;
hello <num>;
+ poll <num>;
retransmit <num>;
priority <num>;
wait <num>;
dead count <num>;
type [broadcast|nonbroadcast|pointopoint];
+ strict nonbroadcast <switch>;
authetication [none|simple];
password "<text>";
neighbors {
<ip>;
+ <ip> eligible;
};
};
};
@@ -1062,6 +1065,10 @@ protocol ospf <name> {
routers on the same network need to have the same hello interval.
Default value is 10.
+ poll num
+ Specifies interval in seconds between sending of Hello messages for
+ some neighbors on NBMA netwok. Default value is 20.
+
retransmit num
Specifies interval in seconds between retransmissions of unacknowledged updates.
Default value is 5.
@@ -1107,7 +1114,12 @@ protocol ospf <name> {
neighbors {
A set of neighbors to which Hello messages on nonbroadcast networks
- are to be sent.
+ are to be sent. Some of them could be marked as eligible.
+
+ strict nonbroadcast switch
+ If set, don't send hello to any undefined neighbor. This switch
+ is ignored on on any non-NBMA network. Default is No.
+
Attributes
@@ -1156,10 +1168,12 @@ protocol ospf MyOSPF {
interface "-arc0" , "arc*" {
type nonbroadcast;
authentication none;
- wait 50;
- dead count 6;
+ strict nonbroadcast no;
+ wait 120;
+ poll 40;
+ dead count 8;
neighbors {
- 192.168.120.1;
+ 192.168.120.1 eligible;
192.168.120.2;
192.168.120.10;
};
diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y
index c7802380..50ba371a 100644
--- a/proto/ospf/config.Y
+++ b/proto/ospf/config.Y
@@ -23,7 +23,8 @@ CF_DECLS
CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG)
CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, RETRANSMIT)
CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, NONBROADCAST, POINTOPOINT, TYPE)
-CF_KEYWORDS(NEIGHBORS, NONE, SIMPLE, AUTHENTICATION, PASSWORD)
+CF_KEYWORDS(NEIGHBORS, NONE, SIMPLE, AUTHENTICATION, PASSWORD, STRICT)
+CF_KEYWORDS(ELIGIBLE, POLL)
%type opttext
@@ -77,6 +78,7 @@ ospf_area_item:
ospf_iface_item:
COST expr { OSPF_PATT->cost = $2 ; if($2<=0) cf_error("Cost must be greater than zero"); }
| HELLO expr { OSPF_PATT->helloint = $2 ; if($2<=0) cf_error("Hello int must be greater than zero"); }
+ | POLL expr { OSPF_PATT->pollint = $2 ; if($2<=0) cf_error("Poll int must be greater than zero"); }
| RETRANSMIT expr { OSPF_PATT->rxmtint = $2 ; if($2<=0) cf_error("Retransmit int must be greater than zero"); }
| TRANSMIT DELAY expr { OSPF_PATT->inftransdelay = $3 ; if($3<=0) cf_error("Transmit delay must be greater than zero"); }
| PRIORITY expr { OSPF_PATT->priority = $2 ; }
@@ -85,6 +87,7 @@ ospf_iface_item:
| TYPE BROADCAST { OSPF_PATT->type = OSPF_IT_BCAST ; }
| TYPE NONBROADCAST { OSPF_PATT->type = OSPF_IT_NBMA ; }
| TYPE POINTOPOINT { OSPF_PATT->type = OSPF_IT_PTP ; }
+ | STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; }
| NEIGHBORS '{' ipa_list '}'
| AUTHENTICATION NONE { OSPF_PATT->autype=AU_NONE ; }
| AUTHENTICATION SIMPLE { OSPF_PATT->autype=AU_SIMPLE ; }
@@ -96,12 +99,26 @@ ipa_list:
/* empty */
| ipa_list ipa_item
;
+
+ipa_item:
+ ipa_el;
+ | ipa_ne;
-ipa_item: IPA ';'
+ipa_el: IPA ';'
{
this_nbma = cfg_allocz(sizeof(struct nbma_node));
add_tail(&OSPF_PATT->nbma_list, NODE this_nbma);
this_nbma->ip=$1;
+ this_nbma->eligible=0;
+ }
+;
+
+ipa_ne: IPA ELIGIBLE ';'
+ {
+ this_nbma = cfg_allocz(sizeof(struct nbma_node));
+ add_tail(&OSPF_PATT->nbma_list, NODE this_nbma);
+ this_nbma->ip=$1;
+ this_nbma->eligible=1;
}
;
@@ -112,12 +129,14 @@ ospf_iface_start:
add_tail(&this_area->patt_list, NODE this_ipatt);
OSPF_PATT->cost = COST_D;
OSPF_PATT->helloint = HELLOINT_D;
+ OSPF_PATT->pollint = POLLINT_D;
OSPF_PATT->rxmtint = RXMTINT_D;
OSPF_PATT->inftransdelay = INFTRANSDELAY_D;
OSPF_PATT->priority = PRIORITY_D;
OSPF_PATT->waitint = WAIT_DMH*HELLOINT_D;
OSPF_PATT->deadc = DEADC_D;
OSPF_PATT->type = OSPF_IT_UNDEF;
+ OSPF_PATT->strictnbma = 0;
init_list(&OSPF_PATT->nbma_list);
OSPF_PATT->autype=AU_NONE;
}
diff --git a/proto/ospf/hello.c b/proto/ospf/hello.c
index d902bbdd..94326c5d 100644
--- a/proto/ospf/hello.c
+++ b/proto/ospf/hello.c
@@ -40,6 +40,13 @@ restart_hellotim(struct ospf_iface *ifa)
tm_start(ifa->hello_timer,ifa->helloint);
}
+void
+restart_polltim(struct ospf_iface *ifa)
+{
+ if(ifa->poll_timer)
+ tm_start(ifa->poll_timer,ifa->pollint);
+}
+
void
restart_waittim(struct ospf_iface *ifa)
{
@@ -56,6 +63,7 @@ ospf_hello_rx(struct ospf_hello_packet *ps, struct proto *p,
ip_addr olddr,oldbdr;
ip_addr mask;
char *beg=": Bad OSPF hello packet from ", *rec=" received: ";
+ int eligible=0;
nrid=ntohl(((struct ospf_packet *)ps)->routerid);
@@ -90,6 +98,36 @@ ospf_hello_rx(struct ospf_hello_packet *ps, struct proto *p,
if((n=find_neigh(ifa, nrid))==NULL)
{
+ if((ifa->type==OSPF_IT_NBMA))
+ {
+ struct nbma_node *nn;
+ int found=0;
+
+ WALK_LIST(nn,ifa->nbma_list)
+ {
+ if(ipa_compare(faddr,nn->ip)==0)
+ {
+ found=1;
+ break;
+ }
+ }
+ if((found==0)&&(ifa->strictnbma))
+ {
+ OSPF_TRACE(D_EVENTS, "Ignoring new neighbor: %I on %s.", faddr,
+ ifa->iface->name);
+ return;
+ }
+ if(found)
+ {
+ eligible=nn->eligible;
+ if(((ps->priority==0)&&eligible)||((ps->priority>0)&&(eligible==0)))
+ {
+ OSPF_TRACE(D_EVENTS, "Eligibility mismatch for neighbor: %I on %s",
+ faddr, ifa->iface->name);
+ return;
+ }
+ }
+ }
OSPF_TRACE(D_EVENTS, "New neighbor found: %I on %s.", faddr,
ifa->iface->name);
n=mb_allocz(p->pool, sizeof(struct ospf_neighbor));
@@ -177,11 +215,27 @@ ospf_hello_rx(struct ospf_hello_packet *ps, struct proto *p,
ospf_int_sm(ifa, ISM_NEICH);
}
+ if(ifa->type!=OSPF_IT_NBMA)
+ {
+ if((ifa->priority==0)&&(n->priority>0)) hello_send(NULL,0, n);
+ }
ospf_neigh_sm(n, INM_HELLOREC);
}
+void
+poll_timer_hook(timer *timer)
+{
+ hello_send(timer,1, NULL);
+}
+
void
hello_timer_hook(timer *timer)
+{
+ hello_send(timer,0, NULL);
+}
+
+void
+hello_send(timer *timer,int poll, struct ospf_neighbor *dirn)
{
struct ospf_iface *ifa;
struct ospf_hello_packet *pkt;
@@ -192,9 +246,11 @@ hello_timer_hook(timer *timer)
u32 *pp;
u8 i;
- ifa=(struct ospf_iface *)timer->data;
+ if(timer==NULL) ifa=dirn->ifa;
+ else ifa=(struct ospf_iface *)timer->data;
+
p=(struct proto *)(ifa->proto);
- DBG("%s: Hello timer fired on interface %s.\n",
+ DBG("%s: Hello/Poll timer fired on interface %s.\n",
p->name, ifa->iface->name);
/* Now we should send a hello packet */
/* First a common packet header */
@@ -248,20 +304,44 @@ hello_timer_hook(timer *timer)
struct nbma_node *nb;
int send;
- WALK_LIST(nb,ifa->nbma_list)
+ if(timer==NULL) /* Response to received hello */
{
- send=1;
- WALK_LIST(n1, ifa->neigh_list)
+ sk_send_to(ifa->ip_sk, length, dirn->ip, OSPF_PROTO);
+ }
+ else
+ {
+ int toall=0;
+ int meeli=0;
+ if(ifa->state>OSPF_IS_DROTHER) toall=1;
+ if(ifa->priority>0) meeli=1;
+
+ WALK_LIST(nb,ifa->nbma_list)
{
- if(ipa_compare(nb->ip,n1->ip)==0)
+ send=1;
+ WALK_LIST(n1, ifa->neigh_list)
+ {
+ if(ipa_compare(nb->ip,n1->ip)==0)
+ {
+ send=0;
+ break;
+ }
+ }
+ if((poll==1)&&(send))
{
- send=0;
- break;
+ if(toall||(meeli&&nb->eligible))
+ sk_send_to(ifa->ip_sk, length, nb->ip, OSPF_PROTO);
}
}
- if(send) sk_send_to(ifa->ip_sk, length, nb->ip, OSPF_PROTO);
+ if(poll==0)
+ {
+ WALK_LIST(n1,ifa->neigh_list)
+ {
+ if(toall||(n1->rid==ifa->drid)||(n1->rid==ifa->bdrid)||
+ (meeli&&(n1->priority>0)))
+ sk_send_to(ifa->ip_sk, length, n1->ip, OSPF_PROTO);
+ }
+ }
}
- sk_send_to_agt(ifa->ip_sk, length, ifa, NEIGHBOR_DOWN);
}
OSPF_TRACE(D_PACKETS, "Hello sent via %s",ifa->iface->name);
}
diff --git a/proto/ospf/hello.h b/proto/ospf/hello.h
index fe53c104..4a5d5042 100644
--- a/proto/ospf/hello.h
+++ b/proto/ospf/hello.h
@@ -13,10 +13,13 @@
void install_inactim(struct ospf_neighbor *n);
void restart_inactim(struct ospf_neighbor *n);
void restart_hellotim(struct ospf_iface *ifa);
+void restart_polltim(struct ospf_iface *ifa);
void restart_waittim(struct ospf_iface *ifa);
void ospf_hello_rx(struct ospf_hello_packet *ps, struct proto *p,
struct ospf_iface *ifa, int size, ip_addr faddr);
void hello_timer_hook(timer *timer);
+void poll_timer_hook(timer *timer);
void wait_timer_hook(timer *timer);
+void hello_send(timer *timer,int poll, struct ospf_neighbor *dirn);
#endif /* _BIRD_OSPF_HELLO_H_ */
diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c
index 172a60ab..4c0e2866 100644
--- a/proto/ospf/iface.c
+++ b/proto/ospf/iface.c
@@ -122,6 +122,11 @@ downint(struct ospf_iface *ifa)
tm_stop(ifa->hello_timer);
rfree(ifa->hello_timer);
}
+ if(ifa->poll_timer!=NULL)
+ {
+ tm_stop(ifa->poll_timer);
+ rfree(ifa->poll_timer);
+ }
rfree(ifa->lock);
mb_free(ifa);
}
@@ -151,6 +156,7 @@ ospf_int_sm(struct ospf_iface *ifa, int event)
{
/* Now, nothing should be adjacent */
restart_hellotim(ifa);
+ restart_polltim(ifa);
if((ifa->type==OSPF_IT_PTP) || (ifa->type==OSPF_IT_VLINK))
{
iface_chstate(ifa, OSPF_IS_PTP);
@@ -358,13 +364,20 @@ void
ospf_iface_info(struct ospf_iface *ifa)
{
int x;
+ char *strict="(strict)";
+
+ if((ifa->type!=OSPF_IT_NBMA)||(ifa->strictnbma==0)) strict="";
cli_msg(-1015,"Interface \"%s\":", ifa->iface->name);
cli_msg(-1015,"\tArea: %I (%u)", ifa->oa->areaid, ifa->oa->areaid);
- cli_msg(-1015,"\tType: %s", ospf_it[ifa->type]);
+ cli_msg(-1015,"\tType: %s %s", ospf_it[ifa->type], strict);
cli_msg(-1015,"\tState: %s", ospf_is[ifa->state]);
cli_msg(-1015,"\tPriority: %u", ifa->priority);
cli_msg(-1015,"\tCost: %u", ifa->cost);
cli_msg(-1015,"\tHello timer: %u", ifa->helloint);
+ if(ifa->type==OSPF_IT_NBMA)
+ {
+ cli_msg(-1015,"\tPoll timer: %u", ifa->pollint);
+ }
cli_msg(-1015,"\tWait timer: %u", ifa->waitint);
cli_msg(-1015,"\tDead timer: %u", ifa->deadc*ifa->helloint);
cli_msg(-1015,"\tRetransmit timer: %u", ifa->rxmtint);
@@ -412,6 +425,8 @@ ospf_ifa_add(struct object_lock *lock)
ifa->inftransdelay=ip->inftransdelay;
ifa->priority=ip->priority;
ifa->helloint=ip->helloint;
+ ifa->pollint=ip->pollint;
+ ifa->strictnbma=ip->strictnbma;
ifa->waitint=ip->waitint;
ifa->deadc=ip->deadc;
ifa->autype=ip->autype;
@@ -453,6 +468,7 @@ ospf_ifa_add(struct object_lock *lock)
{
nbma=mb_alloc(p->pool,sizeof(struct nbma_node));
nbma->ip=nb->ip;
+ nbma->eligible=nb->eligible;
add_tail(&ifa->nbma_list, NODE nbma);
}
@@ -464,6 +480,17 @@ ospf_ifa_add(struct object_lock *lock)
ifa->hello_timer->recurrent=ifa->helloint;
DBG("%s: Installing hello timer. (%u)\n", p->name, ifa->helloint);
+ if(ifa->type==OSPF_IT_NBMA)
+ {
+ ifa->poll_timer=tm_new(p->pool);
+ ifa->poll_timer->data=ifa;
+ ifa->poll_timer->randomize=0;
+ ifa->poll_timer->hook=poll_timer_hook;
+ ifa->poll_timer->recurrent=ifa->pollint;
+ DBG("%s: Installing poll timer. (%u)\n", p->name, ifa->pollint);
+ }
+ else ifa->poll_timer=NULL;
+
ifa->wait_timer=tm_new(p->pool);
ifa->wait_timer->data=ifa;
ifa->wait_timer->randomize=0;
diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h
index 8854d8da..6a7c753b 100644
--- a/proto/ospf/ospf.h
+++ b/proto/ospf/ospf.h
@@ -62,6 +62,7 @@ struct ospf_config {
struct nbma_node {
node n;
ip_addr ip;
+ int eligible;
};
struct ospf_area_config {
@@ -91,6 +92,7 @@ struct ospf_iface {
u8 priority; /* A router priority for DR election */
u16 helloint; /* number of seconds between hello sending */
u16 waitint; /* number of sec before changing state from wait */
+ u16 pollint; /* Poll interval */
u32 deadc; /* after "deadint" missing hellos is router dead */
u16 autype;
u8 aukey[8];
@@ -100,6 +102,7 @@ struct ospf_iface {
ip_addr bdrip; /* Backup DR */
u32 bdrid;
u8 type; /* OSPF view of type */
+ u8 strictnbma; /* Can I talk with unknown neighbors? */
#define OSPF_IT_BCAST 0
#define OSPF_IT_NBMA 1
#define OSPF_IT_PTP 2
@@ -115,12 +118,14 @@ struct ospf_iface {
#define OSPF_IS_DR 6 /* I'm DR */
timer *wait_timer; /* WAIT timer */
timer *hello_timer; /* HELLOINT timer */
+ timer *poll_timer; /* Poll Interval - for NBMA */
/* Default values for interface parameters */
#define COST_D 10
#define RXMTINT_D 5
#define INFTRANSDELAY_D 1
#define PRIORITY_D 1
#define HELLOINT_D 10
+#define POLLINT_D 20
#define DEADC_D 4
#define WAIT_DMH 4 /* Value of Wait timer - not found it in RFC
* - using 4*HELLO
@@ -377,12 +382,14 @@ struct ospf_iface_patt {
int cost;
int helloint;
int rxmtint;
+ int pollint;
int inftransdelay;
int priority;
int waitint;
int deadc;
int type;
int autype;
+ int strictnbma;
#define AU_NONE 0
#define AU_SIMPLE 1
#define AU_CRYPT 2