Commit a190e720 authored by Ondřej Filip's avatar Ondřej Filip

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

parent 94e2bbcc
......@@ -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.
<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>
Specifies interval in seconds between retransmissions of unacknowledged updates.
Default value is 5.
......@@ -1107,7 +1114,12 @@ protocol ospf &lt;name&gt; {
<tag>neighbors { <m/set/ } </tag>
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>
<sect1>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;
};
......
......@@ -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 <t> 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;
}
......
......@@ -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 */
{
sk_send_to(ifa->ip_sk, length, dirn->ip, OSPF_PROTO);
}
else
{
send=1;
WALK_LIST(n1, ifa->neigh_list)
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);
}
......
......@@ -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_ */
......@@ -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;
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment