Commit 3b16080c authored by Ondřej Filip's avatar Ondřej Filip

Multiple OSPF areas can be attached.

Origination of summary LSA works.
Routing table calculation works.
Virtual links works.

Well, I hope, OSPF is fully compatible with RFC2328!!!!
parent a417ad13
......@@ -44,8 +44,6 @@ Various ideas
OSPF
~~~~
- refuse running on non-multicast devices
- importing of device routes for networks where we don't run OSPF
- check incoming packets using neighbor cache
- RFC2328 appendix E: Use a better algorithm
- automatic generation of external route tags (RFC1403)
......
......@@ -103,12 +103,11 @@ protocol static {
# export filter { print "exporting"; accept; };
#}
# Please note, multiple areas still don't work.
#protocol ospf MyOSPF {
# tick 2;
# rfc1583compat yes;
# area 0.0.0.0 {
# stub no;
# tick 1;
# interface "eth*" {
# hello 9;
# retransmit 6;
......@@ -136,6 +135,11 @@ protocol static {
# hello 8;
# authentication none;
# };
# interface "fr*";
# virtual link 192.168.0.1 {
# password "sdsdffsdfg";
# authentication cryptographic;
# };
# };
#}
......
......@@ -972,13 +972,12 @@ describing the autonomous system's topology. Each participating router
has an identical copy of the database and all routers run the same algorithm
calculating a shortest path tree with themselves as a root.
OSPF chooses the least cost path as the best path.
(OSPFv3 - OSPF for IPv6 is not supported yet.)
<p>In OSPF, the autonomous system can be split to several areas in order
to reduce the amount of resources consumed for exchanging the routing
information and to protect the other areas from incorrect routing data.
Topology of the area is hidden to the rest of the autonomous system.
Unfortunately, multiple OSPF areas are not yet fully supported
by this version of BIRD and neither is the IPv6 version (OSPFv3).
<p>Another very important feature of OSPF is that
it can keep routing information from other protocols (like Static or BGP)
......@@ -1011,7 +1010,6 @@ protocol ospf &lt;name&gt; {
tick &lt;num&gt;;
area &lt;id&gt; {
stub cost &lt;num&gt;;
tick &lt;num&gt;;
networks {
&lt;prefix&gt;;
&lt;prefix&gt; hidden;
......@@ -1047,7 +1045,6 @@ protocol ospf &lt;name&gt; {
virtual link &lt;id&gt;
{
hello &lt;num&gt;;
poll &lt;num&gt;;
retransmit &lt;num&gt;;
wait &lt;num&gt;;
dead count &lt;num&gt;;
......@@ -1077,7 +1074,7 @@ protocol ospf &lt;name&gt; {
Default value is no. (Area is not stub.)
<tag>tick <M>num</M></tag>
The routing table calculation of clean-up in areas' databases
The routing table calculation and clean-up of areas' databases
is not performed when a single link state
change arrives. To lower the CPU utilization, it's processed later
at periodical intervals of <m/num/ seconds. The default value is 1.
......@@ -1090,8 +1087,9 @@ protocol ospf &lt;name&gt; {
Defines that the specified interfaces belong to the area being defined.
<tag>virtual link <M>id</M></tag>
Virtual link to router with the router id. This item cannot be in the
backbone area (ID 0).
Virtual link to router with the router id. Virtual link acts as a
point-to-point interface belonging to backbone. The actual area is
used as transport area. This item cannot be in the backbone.
<tag>cost <M>num</M></tag>
Specifies output cost (metric) of an interface. Default value is 10.
......@@ -1205,6 +1203,8 @@ Default is <cf/metric of type 2 = 10000/ and <cf/tag = 0/.
<code>
protocol ospf MyOSPF {
rfc1583compatibility yes;
tick 2;
export filter {
if source = RTS_BGP then {
ospf_metric1 = 100;
......@@ -1213,7 +1213,6 @@ protocol ospf MyOSPF {
reject;
};
area 0.0.0.0 {
tick 8;
interface "eth*" {
cost 11;
hello 15;
......@@ -1224,11 +1223,25 @@ protocol ospf MyOSPF {
};
interface "ppp*" {
cost 100;
authentication cryptographic;
passwords {
password "abc" {
id 1;
generate to 22-04-2003 11:00:06;
accept from 17-01-2001 12:01:05;
};
password "def" {
id 2;
generate to 22-07-2005 17:03:21;
accept from 22-02-2001 11:34:06;
};
};
};
interface "arc0" {
cost 10;
stub yes;
};
interface "arc1";
};
area 120 {
stub yes;
......
......@@ -58,9 +58,9 @@ ospf_area_start: AREA idval '{' {
this_area = cfg_allocz(sizeof(struct ospf_area_config));
add_tail(&OSPF_CFG->area_list, NODE this_area);
this_area->areaid = $2;
this_area->tick = DEFAULT_AREATICK;
this_area->stub = 0;
init_list(&this_area->patt_list);
init_list(&this_area->vlink_list);
init_list(&this_area->net_list);
}
;
......@@ -75,13 +75,14 @@ ospf_area_opts:
ospf_area_item:
STUB COST expr { this_area->stub = $3 ; if($3<=0) cf_error("Stub cost must be greater than zero"); }
| TICK expr { this_area->tick = $2 ; if($2<=0) cf_error("Tick must be greater than zero"); }
| NETWORKS '{' pref_list '}'
| INTERFACE ospf_iface_list
| ospf_vlink '}'
| ospf_vlink
;
ospf_vlink: ospf_vlink_start ospf_vlink_opts
ospf_vlink:
ospf_vlink_start '{' ospf_vlink_opts '}'
| ospf_vlink_start
;
ospf_vlink_opts:
......@@ -90,8 +91,7 @@ ospf_vlink_opts:
;
ospf_vlink_item:
HELLO expr { OSPF_PATT->helloint = $2 ; if (($2<=0) || ($2>65535)) cf_error("Hello interval must be in range 1-65535"); }
| POLL expr { OSPF_PATT->pollint = $2 ; if ($2<=0) cf_error("Poll int must be greater than zero"); }
| HELLO expr { OSPF_PATT->helloint = $2 ; if (($2<=0) || ($2>65535)) cf_error("Hello interval must be in range 1-65535"); }
| 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) || ($3>65535)) cf_error("Transmit delay must be in range 1-65535"); }
| WAIT expr { OSPF_PATT->waitint = $2 ; }
......@@ -102,19 +102,21 @@ ospf_vlink_item:
| password_list {OSPF_PATT->passwords = $1; }
;
ospf_vlink_start: VIRTUAL LINK '{'
ospf_vlink_start: VIRTUAL LINK idval
{
log("Vlink start");
if (this_area->areaid == 0) cf_error("Virtual link cannot be in backbone");
this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt));
add_tail(&this_area->patt_list, NODE this_ipatt);
add_tail(&this_area->vlink_list, NODE this_ipatt);
OSPF_PATT->vid = $3;
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->waitint = WAIT_DMH*HELLOINT_D;
OSPF_PATT->deadc = DEADC_D;
OSPF_PATT->type = OSPF_IT_VLINK;
init_list(&OSPF_PATT->nbma_list);
OSPF_PATT->autype = OSPF_AUTH_NONE;
}
;
......@@ -198,6 +200,7 @@ ipa_ne: IPA ELIGIBLE ';'
ospf_iface_start:
{
log("Iface start");
this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt));
add_tail(&this_area->patt_list, NODE this_ipatt);
OSPF_PATT->cost = COST_D;
......
......@@ -19,12 +19,13 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
struct proto *p = (struct proto *) ifa->proto;
unsigned int size = ntohs(ps->ospf_packet.length), i, twoway, oldpriority, eligible = 0, peers;
OSPF_TRACE(D_PACKETS, "Received hello from %I via %s", faddr,
ifa->iface->name);
OSPF_TRACE(D_PACKETS, "Received hello from %I via %s%s", faddr,
(ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
mask = ps->netmask;
ipa_ntoh(mask);
if ((unsigned) ipa_mklen(mask) != ifa->iface->addr->pxlen)
if ((ifa->type != OSPF_IT_VLINK) &&
((unsigned) ipa_mklen(mask) != ifa->iface->addr->pxlen))
{
log(L_ERR "%s%I%sbad netmask %I.", beg, faddr, rec, mask);
return;
......@@ -151,7 +152,7 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
ospf_iface_sm(ifa, ISM_NEICH);
}
if (ifa->type != OSPF_IT_NBMA)
if (ifa->type == OSPF_IT_NBMA)
{
if ((ifa->priority == 0) && (n->priority > 0))
ospf_hello_send(NULL, 0, n);
......@@ -171,7 +172,6 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
u32 *pp;
int i, send;
struct nbma_node *nb;
if (timer == NULL)
ifa = dirn->ifa;
else
......@@ -204,6 +204,7 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
pkt->netmask = ipa_mkmask(ifa->iface->addr->pxlen);
ipa_hton(pkt->netmask);
if (ifa->type == OSPF_IT_VLINK) pkt->netmask = IPA_NONE;
pkt->helloint = ntohs(ifa->helloint);
pkt->options = ifa->oa->opt.byte;
pkt->priority = ifa->priority;
......@@ -280,5 +281,6 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
default:
ospf_send_to(ifa->hello_sk, IPA_NONE, ifa);
}
OSPF_TRACE(D_PACKETS, "Hello sent via %s", ifa->iface->name);
OSPF_TRACE(D_PACKETS, "Hello sent via %s%s",
(ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
}
......@@ -21,6 +21,7 @@ char *ospf_it[] = { "broadcast", "nbma", "point-to-point", "virtual link" };
static void
poll_timer_hook(timer * timer)
{
log("POLL!");
ospf_hello_send(timer, 1, NULL);
}
......@@ -40,6 +41,38 @@ wait_timer_hook(timer * timer)
ospf_iface_sm(ifa, ISM_WAITF);
}
static sock *
ospf_open_ip_socket(struct ospf_iface *ifa)
{
sock *ipsk;
struct proto *p;
p = (struct proto *) (ifa->proto);
ipsk = sk_new(p->pool);
ipsk->type = SK_IP;
ipsk->dport = OSPF_PROTO;
ipsk->saddr = ifa->iface->addr->ip;
ipsk->tos = IP_PREC_INTERNET_CONTROL;
ipsk->ttl = 1;
if (ifa->type == OSPF_IT_VLINK)
ipsk->ttl = 255;
ipsk->rx_hook = ospf_rx_hook;
ipsk->tx_hook = ospf_tx_hook;
ipsk->err_hook = ospf_err_hook;
ipsk->iface = ifa->iface;
ipsk->rbsize = ifa->iface->mtu;
ipsk->tbsize = ifa->iface->mtu;
ipsk->data = (void *) ifa;
if (sk_open(ipsk) != 0)
{
DBG("%s: SK_OPEN: ip open failed.\n", p->name);
return (NULL);
}
DBG("%s: SK_OPEN: ip opened.\n", p->name);
return (ipsk);
}
/**
* ospf_iface_chstate - handle changes of interface state
......@@ -55,58 +88,71 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
{
struct proto_ospf *po = ifa->proto;
struct proto *p = &po->proto;
u8 oldstate;
u8 oldstate = ifa->state;
if (ifa->state != state)
if (oldstate != state)
{
OSPF_TRACE(D_EVENTS,
"Changing state of iface: %s from \"%s\" into \"%s\".",
ifa->iface->name, ospf_is[ifa->state], ospf_is[state]);
oldstate = ifa->state;
ifa->state = state;
if (ifa->iface->flags & IF_MULTICAST)
if (ifa->type == OSPF_IT_VLINK)
{
if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
OSPF_TRACE(D_EVENTS,
"Changing state of virtual link %I from \"%s\" into \"%s\".",
ifa->vid, ospf_is[oldstate], ospf_is[state]);
if (state == OSPF_IS_PTP)
{
if ((ifa->dr_sk == NULL) && (ifa->type != OSPF_IT_NBMA))
ifa->ip_sk = ospf_open_ip_socket(ifa);
}
}
else
{
OSPF_TRACE(D_EVENTS,
"Changing state of iface: %s from \"%s\" into \"%s\".",
ifa->iface->name, ospf_is[oldstate], ospf_is[state]);
if (ifa->iface->flags & IF_MULTICAST)
{
if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
{
DBG("%s: Adding new multicast socket for (B)DR\n", p->name);
ifa->dr_sk = sk_new(p->pool);
ifa->dr_sk->type = SK_IP_MC;
ifa->dr_sk->sport = 0;
ifa->dr_sk->dport = OSPF_PROTO;
ifa->dr_sk->saddr = AllDRouters;
ifa->dr_sk->daddr = AllDRouters;
ifa->dr_sk->tos = IP_PREC_INTERNET_CONTROL;
ifa->dr_sk->ttl = 1;
ifa->dr_sk->rx_hook = ospf_rx_hook;
ifa->dr_sk->tx_hook = ospf_tx_hook;
ifa->dr_sk->err_hook = ospf_err_hook;
ifa->dr_sk->iface = ifa->iface;
ifa->dr_sk->rbsize = ifa->iface->mtu;
ifa->dr_sk->tbsize = ifa->iface->mtu;
ifa->dr_sk->data = (void *) ifa;
if (sk_open(ifa->dr_sk) != 0)
if ((ifa->dr_sk == NULL) && (ifa->type != OSPF_IT_NBMA))
{
DBG("%s: SK_OPEN: new? mc open failed.\n", p->name);
DBG("%s: Adding new multicast socket for (B)DR\n", p->name);
ifa->dr_sk = sk_new(p->pool);
ifa->dr_sk->type = SK_IP_MC;
ifa->dr_sk->sport = 0;
ifa->dr_sk->dport = OSPF_PROTO;
ifa->dr_sk->saddr = AllDRouters;
ifa->dr_sk->daddr = AllDRouters;
ifa->dr_sk->tos = IP_PREC_INTERNET_CONTROL;
ifa->dr_sk->ttl = 1;
ifa->dr_sk->rx_hook = ospf_rx_hook;
ifa->dr_sk->tx_hook = ospf_tx_hook;
ifa->dr_sk->err_hook = ospf_err_hook;
ifa->dr_sk->iface = ifa->iface;
ifa->dr_sk->rbsize = ifa->iface->mtu;
ifa->dr_sk->tbsize = ifa->iface->mtu;
ifa->dr_sk->data = (void *) ifa;
if (sk_open(ifa->dr_sk) != 0)
{
DBG("%s: SK_OPEN: new? mc open failed.\n", p->name);
}
}
}
}
else
{
rfree(ifa->dr_sk);
ifa->dr_sk = NULL;
}
if ((oldstate == OSPF_IS_DR) && (ifa->nlsa != NULL))
{
ifa->nlsa->lsa.age = LSA_MAXAGE;
if (state >= OSPF_IS_WAITING)
else
{
ospf_lsupd_flush_nlsa(ifa->nlsa, ifa->oa);
rfree(ifa->dr_sk);
ifa->dr_sk = NULL;
}
if ((oldstate == OSPF_IS_DR) && (ifa->nlsa != NULL))
{
ifa->nlsa->lsa.age = LSA_MAXAGE;
if (state >= OSPF_IS_WAITING)
{
ospf_lsupd_flush_nlsa(ifa->nlsa, ifa->oa);
}
if (can_flush_lsa(ifa->oa))
flush_lsa(ifa->nlsa, ifa->oa);
ifa->nlsa = NULL;
}
if (can_flush_lsa(ifa->oa))
flush_lsa(ifa->nlsa, ifa->oa);
ifa->nlsa = NULL;
}
}
}
......@@ -120,6 +166,16 @@ ospf_iface_down(struct ospf_iface *ifa)
struct proto_ospf *po = ifa->proto;
struct ospf_iface *iff;
/* First of all kill all the related vlinks */
if (ifa->type != OSPF_IT_VLINK)
{
WALK_LIST(iff, po->iface_list)
{
if ((iff->type == OSPF_IT_VLINK) && (iff->iface == ifa->iface))
ospf_iface_down(iff);
}
}
WALK_LIST_DELSAFE(n, nx, ifa->neigh_list)
{
OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip);
......@@ -129,7 +185,7 @@ ospf_iface_down(struct ospf_iface *ifa)
rfree(ifa->dr_sk);
rfree(ifa->ip_sk);
if(ifa->type == OSPF_IT_VLINK)
if (ifa->type == OSPF_IT_VLINK)
{
ifa->ip_sk = NULL;
ifa->iface = NULL;
......@@ -144,7 +200,6 @@ ospf_iface_down(struct ospf_iface *ifa)
rem_node(NODE ifa);
mb_free(ifa);
}
/* FIXME: Should I down related VLINK also? */
}
/**
......@@ -168,13 +223,10 @@ ospf_iface_sm(struct ospf_iface *ifa, int event)
if (ifa->state == OSPF_IS_DOWN)
{
/* Now, nothing should be adjacent */
tm_start(ifa->hello_timer, ifa->helloint);
if (ifa->poll_timer)
tm_start(ifa->poll_timer, ifa->pollint);
if ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_VLINK))
{
ospf_iface_chstate(ifa, OSPF_IS_PTP);
}
else
{
if (ifa->priority == 0)
......@@ -185,6 +237,12 @@ ospf_iface_sm(struct ospf_iface *ifa, int event)
tm_start(ifa->wait_timer, ifa->waitint);
}
}
tm_start(ifa->hello_timer, ifa->helloint);
if (ifa->poll_timer)
tm_start(ifa->poll_timer, ifa->pollint);
hello_timer_hook(ifa->hello_timer);
}
schedule_rt_lsa(ifa->oa);
......@@ -257,37 +315,6 @@ ospf_open_mc_socket(struct ospf_iface *ifa)
return (mcsk);
}
static sock *
ospf_open_ip_socket(struct ospf_iface *ifa)
{
sock *ipsk;
struct proto *p;
p = (struct proto *) (ifa->proto);
ipsk = sk_new(p->pool);
ipsk->type = SK_IP;
ipsk->dport = OSPF_PROTO;
ipsk->saddr = ifa->iface->addr->ip;
ipsk->tos = IP_PREC_INTERNET_CONTROL;
ipsk->ttl = 1;
if (ifa->type == OSPF_IT_VLINK) ipsk->ttl = 255;
ipsk->rx_hook = ospf_rx_hook;
ipsk->tx_hook = ospf_tx_hook;
ipsk->err_hook = ospf_err_hook;
ipsk->iface = ifa->iface;
ipsk->rbsize = ifa->iface->mtu;
ipsk->tbsize = ifa->iface->mtu;
ipsk->data = (void *) ifa;
if (sk_open(ipsk) != 0)
{
DBG("%s: SK_OPEN: ip open failed.\n", p->name);
return (NULL);
}
DBG("%s: SK_OPEN: ip opened.\n", p->name);
return (ipsk);
}
u8
ospf_iface_clasify(struct iface * ifa)
{
......@@ -306,7 +333,7 @@ ospf_iface_find(struct proto_ospf *p, struct iface *what)
{
struct ospf_iface *i;
WALK_LIST(i, p->iface_list) if ((i)->iface == what)
WALK_LIST(i, p->iface_list) if ((i->iface == what) && (i->type != OSPF_IT_VLINK))
return i;
return NULL;
}
......@@ -350,7 +377,8 @@ ospf_iface_add(struct object_lock *lock)
}
void
ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_config *ac, struct ospf_iface_patt *ip)
ospf_iface_new(struct proto_ospf *po, struct iface *iface,
struct ospf_area_config *ac, struct ospf_iface_patt *ip)
{
struct proto *p = &po->proto;
struct ospf_iface *ifa;
......@@ -362,7 +390,6 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_conf
ifa->proto = po;
ifa->iface = iface;
ifa->an = ac->areaid;
ifa->cost = ip->cost;
ifa->rxmtint = ip->rxmtint;
ifa->inftransdelay = ip->inftransdelay;
......@@ -383,6 +410,7 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_conf
init_list(&ifa->neigh_list);
init_list(&ifa->nbma_list);
WALK_LIST(nb, ip->nbma_list)
{
nbma = mb_alloc(p->pool, sizeof(struct nbma_node));
......@@ -420,23 +448,26 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_conf
add_tail(&((struct proto_ospf *) p)->iface_list, NODE ifa);
ifa->state = OSPF_IS_DOWN;
ifa->oa = NULL;
WALK_LIST(oa, po->area_list)
{
if (oa->areaid == ifa->an)
if (oa->areaid == ac->areaid)
{
ifa->oa = oa;
break;
}
}
if (EMPTY_LIST(po->area_list) || (oa->areaid != ifa->an)) /* New area */
if (!ifa->oa)
bug("Cannot add any area to accepted Interface");
else
ifa->oa = oa;
if (ifa->type == OSPF_IT_VLINK)
{
ifa->oa = po->backbone;
ifa->voa = oa;
ifa->vid = ip->vid;
return; /* Don't lock, don't add sockets */
return; /* Don't lock, don't add sockets */
}
lock = olock_new(p->pool);
......@@ -536,9 +567,19 @@ ospf_iface_info(struct ospf_iface *ifa)
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 %s", ospf_it[ifa->type], strict);
if (ifa->type == OSPF_IT_VLINK)
{
cli_msg(-1015, "Virtual link to %I:", ifa->vid);
cli_msg(-1015, "\tTransit area: %I (%u)", ifa->voa->areaid,
ifa->voa->areaid);
}
else
{
cli_msg(-1015, "Interface \"%s\":",
(ifa->iface ? ifa->iface->name : "(none)"));
cli_msg(-1015, "\tType: %s %s", ospf_it[ifa->type], strict);
cli_msg(-1015, "\tArea: %I (%u)", ifa->oa->areaid, ifa->oa->areaid);
}
cli_msg(-1015, "\tState: %s %s", ospf_is[ifa->state],
ifa->stub ? "(stub)" : "");
cli_msg(-1015, "\tPriority: %u", ifa->priority);
......
......@@ -55,8 +55,8 @@ ospf_age(struct ospf_area *oa)
en->color = OUTSPF;
en->dist = LSINFINITY;
en->nhi = NULL;
en->nh = ipa_from_u32(0);
en->lb = ipa_from_u32(0);
en->nh = IPA_NONE;
en->lb = IPA_NONE;
DBG("Infinitying Type: %u, Id: %I, Rt: %I\n", en->lsa.type, en->lsa.id,
en->lsa.rt);
}
......
......@@ -152,10 +152,10 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
struct ospf_packet *op;
struct ospf_lsa_header *lh;
if (ifa->type == OSPF_IT_NBMA)
if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_VLINK))
sk = ifa->ip_sk;
else
sk = ifa->hello_sk; /* FIXME is this true for PTP? */
sk = ifa->hello_sk;
pk = (struct ospf_lsupd_packet *) sk->tbuf;
op = (struct ospf_packet *) sk->tbuf;
......@@ -192,16 +192,23 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
op->length = htons(len);
OSPF_TRACE(D_PACKETS, "LS upd flooded via %s", ifa->iface->name);
DBG("ID=%I, AGE=%d, SEQ=%x", ntohl(lh->id), ntohs(lh->age),
ntohl(lh->sn));
if (ifa->type == OSPF_IT_NBMA)
switch (ifa->type)
{
case OSPF_IT_NBMA:
if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
ospf_send_to_agt(sk, ifa, NEIGHBOR_EXCHANGE);
else
ospf_send_to_bdr(sk, ifa);
}
else
{
break;
case OSPF_IT_VLINK:
ospf_send_to(sk, ifa->vip, ifa);
break;
default:
if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR) ||
(ifa->type == OSPF_IT_PTP))
ospf_send_to(sk, AllSPFRouters, ifa);
......@@ -243,6 +250,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
if ((en = ospf_hash_find(n->ifa->oa->gr, llsh->lsh.id, llsh->lsh.rt,
llsh->lsh.type)) == NULL)
continue; /* Probably flushed LSA */
/* FIXME This is a bug! I cannot flush LSA that is in lsrt */
DBG("Sending ID=%I, Type=%u, RT=%I Sn: 0x%x Age: %u\n",
llsh->lsh.id, llsh->lsh.type, llsh->lsh.rt, en->lsa.sn, en->lsa.age);
......@@ -395,8 +403,9 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
{
WALK_LIST(nifa, po->iface_list)
{
if (ipa_compare(nifa->iface->addr->ip, ipa_from_u32(lsatmp.id)) ==
0)
if (!nifa->iface)
continue;
if (ipa_equal(nifa->iface->addr->ip, ipa_from_u32(lsatmp.id)))
{
self = 1;
break;
......
......@@ -122,6 +122,7 @@ neigh_chstate(struct ospf_neighbor *n, u8 state)
{
ifa->fadj++;
schedule_rt_lsa(ifa->oa);
if (ifa->type == OSPF_IT_VLINK) schedule_rt_lsa(ifa->voa);
schedule_net_lsa(ifa);
}
if (state == NEIGHBOR_EXSTART)
......@@ -422,12 +423,12 @@ bdr_election(struct ospf_iface *ifa)
|| ((ifa->bdrid != myid) && (nbdr == &me)))
{
if (ndr == NULL)
ifa->drip = me.dr = ipa_from_u32(0);
ifa->drip = me.dr = IPA_NONE;
else
ifa->drip = me.dr = ndr->ip;
if (nbdr == NULL)
ifa->bdrip = me.bdr = ipa_from_u32(0);
ifa->bdrip = me.bdr = IPA_NONE;
else
ifa->bdrip = me.bdr = nbdr->ip;
......@@ -436,12 +437,12 @@ bdr_election(struct ospf_iface *ifa)
}
if (ndr == NULL)
ndrip = ipa_from_u32(0);
ndrip = IPA_NONE;
else
ndrip = ndr->ip;
if (nbdr == NULL)
nbdrip = ipa_from_u32(0);
nbdrip = IPA_NONE;
else
nbdrip = nbdr->ip;
......@@ -453,7 +454,7 @@ bdr_election(struct ospf_iface *ifa)
if (ndr == NULL)
{
ifa->drid = 0;
ifa->drip = ipa_from_u32(0);
ifa->drip = IPA_NONE;
}
else
{
......@@ -464,7 +465,7 @@ bdr_election(struct ospf_iface *ifa)
if (nbdr == NULL)
{
ifa->bdrid = 0;
ifa->bdrip = ipa_from_u32(0);
ifa->bdrip = IPA_NONE;
}
else
{
......@@ -591,11 +592,12 @@ ospf_sh_neigh_info(struct ospf_neighbor *n)
pos = "dr ";
if (n->rid == ifa->bdrid)
pos = "bdr ";
if (n->ifa->type == OSPF_IT_PTP)
if ((n->ifa->type == OSPF_IT_PTP) || (n->ifa->type == OSPF_IT_VLINK))
pos = "ptp ";
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);
ospf_ns[n->state], pos, etime, n->ip,
(ifa->type == OSPF_IT_VLINK ? "vlink" : ifa->iface->name));
}
void
......
......@@ -45,7 +45,7 @@
* Every area has its own area_disp() which is
* responsible for late originating of router LSA, calculating
* of the routing table and it also ages and flushes the LSAs. This
* function is called in regular intervals.
* function is called in regular intervals from ospf_disp()
* To every &ospf_iface, we connect one or more
* &ospf_neighbor's -- a structure containing many timers and queues
* for building adjacency and for exchange of routing messages.
......@@ -72,7 +72,6 @@
static int ospf_rte_better(struct rte *new, struct rte *old);
static int ospf_rte_same(struct rte *new, struct rte *old);
static void area_disp(timer *timer);
static void ospf_disp(timer *timer);
static void
......@@ -135,18 +134,11 @@ ospf_start(struct proto *p)