Added hellos on NBMA networks. (I don't violate RFC now.)

This commit is contained in:
Ondrej Filip 2000-09-02 00:03:36 +00:00
parent 94e2bbcc72
commit a190e7200b
6 changed files with 167 additions and 17 deletions

View file

@ -1015,15 +1015,18 @@ protocol ospf <name> {
{ {
cost <num>; cost <num>;
hello <num>; hello <num>;
poll <num>;
retransmit <num>; retransmit <num>;
priority <num>; priority <num>;
wait <num>; wait <num>;
dead count <num>; dead count <num>;
type [broadcast|nonbroadcast|pointopoint]; type [broadcast|nonbroadcast|pointopoint];
strict nonbroadcast <switch>;
authetication [none|simple]; authetication [none|simple];
password "<text>"; password "<text>";
neighbors { neighbors {
<ip>; <ip>;
<ip> eligible;
}; };
}; };
}; };
@ -1062,6 +1065,10 @@ protocol ospf <name> {
routers on the same network need to have the same hello interval. routers on the same network need to have the same hello interval.
Default value is 10. Default value is 10.
<tag>poll <M>num</M></tag>
Specifies interval in seconds between sending of Hello messages for
some neighbors on NBMA netwok. Default value is 20.
<tag>retransmit <M>num</M></tag> <tag>retransmit <M>num</M></tag>
Specifies interval in seconds between retransmissions of unacknowledged updates. Specifies interval in seconds between retransmissions of unacknowledged updates.
Default value is 5. Default value is 5.
@ -1107,7 +1114,12 @@ protocol ospf &lt;name&gt; {
<tag>neighbors { <m/set/ } </tag> <tag>neighbors { <m/set/ } </tag>
A set of neighbors to which Hello messages on nonbroadcast networks 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.
<tag>strict nonbroadcast <M>switch</M></tag>
If set, don't send hello to any undefined neighbor. This switch
is ignored on on any non-NBMA network. Default is No.
</descrip> </descrip>
<sect1>Attributes <sect1>Attributes
@ -1156,10 +1168,12 @@ protocol ospf MyOSPF {
interface "-arc0" , "arc*" { interface "-arc0" , "arc*" {
type nonbroadcast; type nonbroadcast;
authentication none; authentication none;
wait 50; strict nonbroadcast no;
dead count 6; wait 120;
poll 40;
dead count 8;
neighbors { neighbors {
192.168.120.1; 192.168.120.1 eligible;
192.168.120.2; 192.168.120.2;
192.168.120.10; 192.168.120.10;
}; };

View file

@ -23,7 +23,8 @@ CF_DECLS
CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG) CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG)
CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, RETRANSMIT) CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, RETRANSMIT)
CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, NONBROADCAST, POINTOPOINT, TYPE) 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 <t> opttext %type <t> opttext
@ -77,6 +78,7 @@ ospf_area_item:
ospf_iface_item: ospf_iface_item:
COST expr { OSPF_PATT->cost = $2 ; if($2<=0) cf_error("Cost must be greater than zero"); } 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"); } | 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"); } | 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"); } | 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 ; } | PRIORITY expr { OSPF_PATT->priority = $2 ; }
@ -85,6 +87,7 @@ ospf_iface_item:
| TYPE BROADCAST { OSPF_PATT->type = OSPF_IT_BCAST ; } | TYPE BROADCAST { OSPF_PATT->type = OSPF_IT_BCAST ; }
| TYPE NONBROADCAST { OSPF_PATT->type = OSPF_IT_NBMA ; } | TYPE NONBROADCAST { OSPF_PATT->type = OSPF_IT_NBMA ; }
| TYPE POINTOPOINT { OSPF_PATT->type = OSPF_IT_PTP ; } | TYPE POINTOPOINT { OSPF_PATT->type = OSPF_IT_PTP ; }
| STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; }
| NEIGHBORS '{' ipa_list '}' | NEIGHBORS '{' ipa_list '}'
| AUTHENTICATION NONE { OSPF_PATT->autype=AU_NONE ; } | AUTHENTICATION NONE { OSPF_PATT->autype=AU_NONE ; }
| AUTHENTICATION SIMPLE { OSPF_PATT->autype=AU_SIMPLE ; } | AUTHENTICATION SIMPLE { OSPF_PATT->autype=AU_SIMPLE ; }
@ -96,12 +99,26 @@ ipa_list:
/* empty */ /* empty */
| ipa_list ipa_item | ipa_list ipa_item
; ;
ipa_item:
ipa_el;
| ipa_ne;
ipa_item: IPA ';' ipa_el: IPA ';'
{ {
this_nbma = cfg_allocz(sizeof(struct nbma_node)); this_nbma = cfg_allocz(sizeof(struct nbma_node));
add_tail(&OSPF_PATT->nbma_list, NODE this_nbma); add_tail(&OSPF_PATT->nbma_list, NODE this_nbma);
this_nbma->ip=$1; 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); add_tail(&this_area->patt_list, NODE this_ipatt);
OSPF_PATT->cost = COST_D; OSPF_PATT->cost = COST_D;
OSPF_PATT->helloint = HELLOINT_D; OSPF_PATT->helloint = HELLOINT_D;
OSPF_PATT->pollint = POLLINT_D;
OSPF_PATT->rxmtint = RXMTINT_D; OSPF_PATT->rxmtint = RXMTINT_D;
OSPF_PATT->inftransdelay = INFTRANSDELAY_D; OSPF_PATT->inftransdelay = INFTRANSDELAY_D;
OSPF_PATT->priority = PRIORITY_D; OSPF_PATT->priority = PRIORITY_D;
OSPF_PATT->waitint = WAIT_DMH*HELLOINT_D; OSPF_PATT->waitint = WAIT_DMH*HELLOINT_D;
OSPF_PATT->deadc = DEADC_D; OSPF_PATT->deadc = DEADC_D;
OSPF_PATT->type = OSPF_IT_UNDEF; OSPF_PATT->type = OSPF_IT_UNDEF;
OSPF_PATT->strictnbma = 0;
init_list(&OSPF_PATT->nbma_list); init_list(&OSPF_PATT->nbma_list);
OSPF_PATT->autype=AU_NONE; OSPF_PATT->autype=AU_NONE;
} }

View file

@ -40,6 +40,13 @@ restart_hellotim(struct ospf_iface *ifa)
tm_start(ifa->hello_timer,ifa->helloint); 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 void
restart_waittim(struct ospf_iface *ifa) 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 olddr,oldbdr;
ip_addr mask; ip_addr mask;
char *beg=": Bad OSPF hello packet from ", *rec=" received: "; char *beg=": Bad OSPF hello packet from ", *rec=" received: ";
int eligible=0;
nrid=ntohl(((struct ospf_packet *)ps)->routerid); 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((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, OSPF_TRACE(D_EVENTS, "New neighbor found: %I on %s.", faddr,
ifa->iface->name); ifa->iface->name);
n=mb_allocz(p->pool, sizeof(struct ospf_neighbor)); 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); 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); ospf_neigh_sm(n, INM_HELLOREC);
} }
void
poll_timer_hook(timer *timer)
{
hello_send(timer,1, NULL);
}
void void
hello_timer_hook(timer *timer) 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_iface *ifa;
struct ospf_hello_packet *pkt; struct ospf_hello_packet *pkt;
@ -192,9 +246,11 @@ hello_timer_hook(timer *timer)
u32 *pp; u32 *pp;
u8 i; 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); 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); p->name, ifa->iface->name);
/* Now we should send a hello packet */ /* Now we should send a hello packet */
/* First a common packet header */ /* First a common packet header */
@ -248,20 +304,44 @@ hello_timer_hook(timer *timer)
struct nbma_node *nb; struct nbma_node *nb;
int send; int send;
WALK_LIST(nb,ifa->nbma_list) if(timer==NULL) /* Response to received hello */
{ {
send=1; sk_send_to(ifa->ip_sk, length, dirn->ip, OSPF_PROTO);
WALK_LIST(n1, ifa->neigh_list) }
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; if(toall||(meeli&&nb->eligible))
break; 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); OSPF_TRACE(D_PACKETS, "Hello sent via %s",ifa->iface->name);
} }

View file

@ -13,10 +13,13 @@
void install_inactim(struct ospf_neighbor *n); void install_inactim(struct ospf_neighbor *n);
void restart_inactim(struct ospf_neighbor *n); void restart_inactim(struct ospf_neighbor *n);
void restart_hellotim(struct ospf_iface *ifa); void restart_hellotim(struct ospf_iface *ifa);
void restart_polltim(struct ospf_iface *ifa);
void restart_waittim(struct ospf_iface *ifa); void restart_waittim(struct ospf_iface *ifa);
void ospf_hello_rx(struct ospf_hello_packet *ps, struct proto *p, void ospf_hello_rx(struct ospf_hello_packet *ps, struct proto *p,
struct ospf_iface *ifa, int size, ip_addr faddr); struct ospf_iface *ifa, int size, ip_addr faddr);
void hello_timer_hook(timer *timer); void hello_timer_hook(timer *timer);
void poll_timer_hook(timer *timer);
void wait_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_ */ #endif /* _BIRD_OSPF_HELLO_H_ */

View file

@ -122,6 +122,11 @@ downint(struct ospf_iface *ifa)
tm_stop(ifa->hello_timer); tm_stop(ifa->hello_timer);
rfree(ifa->hello_timer); rfree(ifa->hello_timer);
} }
if(ifa->poll_timer!=NULL)
{
tm_stop(ifa->poll_timer);
rfree(ifa->poll_timer);
}
rfree(ifa->lock); rfree(ifa->lock);
mb_free(ifa); mb_free(ifa);
} }
@ -151,6 +156,7 @@ ospf_int_sm(struct ospf_iface *ifa, int event)
{ {
/* Now, nothing should be adjacent */ /* Now, nothing should be adjacent */
restart_hellotim(ifa); restart_hellotim(ifa);
restart_polltim(ifa);
if((ifa->type==OSPF_IT_PTP) || (ifa->type==OSPF_IT_VLINK)) if((ifa->type==OSPF_IT_PTP) || (ifa->type==OSPF_IT_VLINK))
{ {
iface_chstate(ifa, OSPF_IS_PTP); iface_chstate(ifa, OSPF_IS_PTP);
@ -358,13 +364,20 @@ void
ospf_iface_info(struct ospf_iface *ifa) ospf_iface_info(struct ospf_iface *ifa)
{ {
int x; 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,"Interface \"%s\":", ifa->iface->name);
cli_msg(-1015,"\tArea: %I (%u)", ifa->oa->areaid, ifa->oa->areaid); 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,"\tState: %s", ospf_is[ifa->state]);
cli_msg(-1015,"\tPriority: %u", ifa->priority); cli_msg(-1015,"\tPriority: %u", ifa->priority);
cli_msg(-1015,"\tCost: %u", ifa->cost); cli_msg(-1015,"\tCost: %u", ifa->cost);
cli_msg(-1015,"\tHello timer: %u", ifa->helloint); 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,"\tWait timer: %u", ifa->waitint);
cli_msg(-1015,"\tDead timer: %u", ifa->deadc*ifa->helloint); cli_msg(-1015,"\tDead timer: %u", ifa->deadc*ifa->helloint);
cli_msg(-1015,"\tRetransmit timer: %u", ifa->rxmtint); cli_msg(-1015,"\tRetransmit timer: %u", ifa->rxmtint);
@ -412,6 +425,8 @@ ospf_ifa_add(struct object_lock *lock)
ifa->inftransdelay=ip->inftransdelay; ifa->inftransdelay=ip->inftransdelay;
ifa->priority=ip->priority; ifa->priority=ip->priority;
ifa->helloint=ip->helloint; ifa->helloint=ip->helloint;
ifa->pollint=ip->pollint;
ifa->strictnbma=ip->strictnbma;
ifa->waitint=ip->waitint; ifa->waitint=ip->waitint;
ifa->deadc=ip->deadc; ifa->deadc=ip->deadc;
ifa->autype=ip->autype; 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=mb_alloc(p->pool,sizeof(struct nbma_node));
nbma->ip=nb->ip; nbma->ip=nb->ip;
nbma->eligible=nb->eligible;
add_tail(&ifa->nbma_list, NODE nbma); add_tail(&ifa->nbma_list, NODE nbma);
} }
@ -464,6 +480,17 @@ ospf_ifa_add(struct object_lock *lock)
ifa->hello_timer->recurrent=ifa->helloint; ifa->hello_timer->recurrent=ifa->helloint;
DBG("%s: Installing hello timer. (%u)\n", p->name, 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=tm_new(p->pool);
ifa->wait_timer->data=ifa; ifa->wait_timer->data=ifa;
ifa->wait_timer->randomize=0; ifa->wait_timer->randomize=0;

View file

@ -62,6 +62,7 @@ struct ospf_config {
struct nbma_node { struct nbma_node {
node n; node n;
ip_addr ip; ip_addr ip;
int eligible;
}; };
struct ospf_area_config { struct ospf_area_config {
@ -91,6 +92,7 @@ struct ospf_iface {
u8 priority; /* A router priority for DR election */ u8 priority; /* A router priority for DR election */
u16 helloint; /* number of seconds between hello sending */ u16 helloint; /* number of seconds between hello sending */
u16 waitint; /* number of sec before changing state from wait */ u16 waitint; /* number of sec before changing state from wait */
u16 pollint; /* Poll interval */
u32 deadc; /* after "deadint" missing hellos is router dead */ u32 deadc; /* after "deadint" missing hellos is router dead */
u16 autype; u16 autype;
u8 aukey[8]; u8 aukey[8];
@ -100,6 +102,7 @@ struct ospf_iface {
ip_addr bdrip; /* Backup DR */ ip_addr bdrip; /* Backup DR */
u32 bdrid; u32 bdrid;
u8 type; /* OSPF view of type */ u8 type; /* OSPF view of type */
u8 strictnbma; /* Can I talk with unknown neighbors? */
#define OSPF_IT_BCAST 0 #define OSPF_IT_BCAST 0
#define OSPF_IT_NBMA 1 #define OSPF_IT_NBMA 1
#define OSPF_IT_PTP 2 #define OSPF_IT_PTP 2
@ -115,12 +118,14 @@ struct ospf_iface {
#define OSPF_IS_DR 6 /* I'm DR */ #define OSPF_IS_DR 6 /* I'm DR */
timer *wait_timer; /* WAIT timer */ timer *wait_timer; /* WAIT timer */
timer *hello_timer; /* HELLOINT timer */ timer *hello_timer; /* HELLOINT timer */
timer *poll_timer; /* Poll Interval - for NBMA */
/* Default values for interface parameters */ /* Default values for interface parameters */
#define COST_D 10 #define COST_D 10
#define RXMTINT_D 5 #define RXMTINT_D 5
#define INFTRANSDELAY_D 1 #define INFTRANSDELAY_D 1
#define PRIORITY_D 1 #define PRIORITY_D 1
#define HELLOINT_D 10 #define HELLOINT_D 10
#define POLLINT_D 20
#define DEADC_D 4 #define DEADC_D 4
#define WAIT_DMH 4 /* Value of Wait timer - not found it in RFC #define WAIT_DMH 4 /* Value of Wait timer - not found it in RFC
* - using 4*HELLO * - using 4*HELLO
@ -377,12 +382,14 @@ struct ospf_iface_patt {
int cost; int cost;
int helloint; int helloint;
int rxmtint; int rxmtint;
int pollint;
int inftransdelay; int inftransdelay;
int priority; int priority;
int waitint; int waitint;
int deadc; int deadc;
int type; int type;
int autype; int autype;
int strictnbma;
#define AU_NONE 0 #define AU_NONE 0
#define AU_SIMPLE 1 #define AU_SIMPLE 1
#define AU_CRYPT 2 #define AU_CRYPT 2