summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Filip <feela@network.cz>2004-07-14 23:46:20 +0200
committerOndrej Filip <feela@network.cz>2004-07-14 23:46:20 +0200
commit3b16080c97a2d89c90f7df7a8fda0401ec9abe42 (patch)
treeef885699eaa72453b99f40dba181112d7e9540b7
parenta417ad13a117d2458702cbec4aa418ba99981611 (diff)
downloadbird-3b16080c97a2d89c90f7df7a8fda0401ec9abe42.tar
bird-3b16080c97a2d89c90f7df7a8fda0401ec9abe42.zip
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!!!!
-rw-r--r--TODO2
-rw-r--r--doc/bird.conf.example8
-rw-r--r--doc/bird.sgml29
-rw-r--r--proto/ospf/config.Y21
-rw-r--r--proto/ospf/hello.c14
-rw-r--r--proto/ospf/iface.c219
-rw-r--r--proto/ospf/lsalib.c4
-rw-r--r--proto/ospf/lsupd.c25
-rw-r--r--proto/ospf/neighbor.c18
-rw-r--r--proto/ospf/ospf.c63
-rw-r--r--proto/ospf/ospf.h7
-rw-r--r--proto/ospf/packet.c25
-rw-r--r--proto/ospf/rt.c88
-rw-r--r--proto/ospf/topology.c65
14 files changed, 341 insertions, 247 deletions
diff --git a/TODO b/TODO
index 0945aac..b669336 100644
--- a/TODO
+++ b/TODO
@@ -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)
diff --git a/doc/bird.conf.example b/doc/bird.conf.example
index ace813b..1e7ba8a 100644
--- a/doc/bird.conf.example
+++ b/doc/bird.conf.example
@@ -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;
+# };
# };
#}
diff --git a/doc/bird.sgml b/doc/bird.sgml
index f81b232..aed0746 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -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;
diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y
index 87a97bc..bd3a2e5 100644
--- a/proto/ospf/config.Y
+++ b/proto/ospf/config.Y
@@ -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;
diff --git a/proto/ospf/hello.c b/proto/ospf/hello.c
index 7820cf7..350bad7 100644
--- a/proto/ospf/hello.c
+++ b/proto/ospf/hello.c
@@ -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);
}
diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c
index 62b8899..5a10cde 100644
--- a/proto/ospf/iface.c
+++ b/proto/ospf/iface.c
@@ -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);
diff --git a/proto/ospf/lsalib.c b/proto/ospf/lsalib.c
index 7ea8304..b244c3f 100644
--- a/proto/ospf/lsalib.c
+++ b/proto/ospf/lsalib.c
@@ -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);
}
diff --git a/proto/ospf/lsupd.c b/proto/ospf/lsupd.c
index 44d35d9..51b38af 100644
--- a/proto/ospf/lsupd.c
+++ b/proto/ospf/lsupd.c
@@ -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;
diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c
index e9ef476..869db2b 100644
--- a/proto/ospf/neighbor.c
+++ b/proto/ospf/neighbor.c
@@ -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
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index ccdc502..8f6b217 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -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)
add_tail(&po->area_list, NODE oa);
po->areano++;
oa->stub = ac->stub;
- oa->tick = ac->tick;
oa->areaid = ac->areaid;
oa->gr = ospf_top_new(p->pool);
s_init_list(&(oa->lsal));
oa->rt = NULL;
oa->po = po;
- oa->disp_timer = tm_new(p->pool);
- oa->disp_timer->data = oa;
- oa->disp_timer->randomize = 0;
- oa->disp_timer->hook = area_disp;
- oa->disp_timer->recurrent = oa->tick;
- tm_start(oa->disp_timer, 2);
add_area_nets(oa, ac);
fib_init(&oa->rtr, p->pool, sizeof(ort), 16, ospf_rt_initort);
if (oa->areaid == 0) po->backbone = oa;
@@ -160,10 +152,8 @@ ospf_start(struct proto *p)
struct ospf_iface_patt *ipatt;
WALK_LIST(ac, c->area_list)
{
- WALK_LIST(ipatt, ac->patt_list)
- {
- if (ipatt->type == OSPF_IT_VLINK) ospf_iface_new(po, NULL, ac, ipatt);
- }
+ WALK_LIST(ipatt, ac->vlink_list)
+ ospf_iface_new(po, NULL, ac, ipatt);
}
}
return PS_UP;
@@ -181,7 +171,7 @@ ospf_dump(struct proto *p)
WALK_LIST(ifa, po->iface_list)
{
- OSPF_TRACE(D_EVENTS, "Interface: %s", ifa->iface->name);
+ OSPF_TRACE(D_EVENTS, "Interface: %s", (ifa->iface ? ifa->iface->name : "(null)"));
OSPF_TRACE(D_EVENTS, "state: %u", ifa->state);
OSPF_TRACE(D_EVENTS, "DR: %I", ifa->drid);
OSPF_TRACE(D_EVENTS, "BDR: %I", ifa->bdrid);
@@ -311,9 +301,8 @@ schedule_rtcalc(struct proto_ospf *po)
* function for origination of router LSA and network LSAs.
*/
void
-area_disp(timer * timer)
+area_disp(struct ospf_area *oa)
{
- struct ospf_area *oa = timer->data;
struct proto_ospf *po = oa->po;
struct ospf_iface *ifa;
@@ -324,7 +313,7 @@ area_disp(timer * timer)
/* Now try to originate network LSA's */
WALK_LIST(ifa, po->iface_list)
{
- if (ifa->orignet && (ifa->an == oa->areaid))
+ if (ifa->orignet && (ifa->oa == oa))
originate_net_lsa(ifa);
}
@@ -336,6 +325,10 @@ void
ospf_disp(timer * timer)
{
struct proto_ospf *po = timer->data;
+ struct ospf_area *oa;
+
+ WALK_LIST(oa, po->area_list)
+ area_disp(oa);
/* Calculate routing table */
if (po->calcrt)
@@ -555,6 +548,13 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
struct area_net *anet, *antmp;
int found;
+ /* FIXME Temporarily disabled */
+
+ return !memcmp(((byte *) old) + sizeof(struct proto_config),
+ ((byte *) new) + sizeof(struct proto_config),
+ sizeof(struct ospf_config) - sizeof(struct proto_config));
+
+
po->rfc1583 = new->rfc1583;
schedule_rtcalc(po);
@@ -576,19 +576,6 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
if (!oa)
return 0;
- if (ac1->tick != ac2->tick)
- {
- if (oa->areaid == ac2->areaid)
- {
- oa->tick = ac2->tick;
- tm_start(oa->disp_timer, oa->tick);
- OSPF_TRACE(D_EVENTS,
- "Changing tick interval on area %I from %d to %d",
- oa->areaid, ac1->tick, ac2->tick);
- break;
- }
- }
-
/* Change net_list */
fib_free(&oa->net_fib);
add_area_nets(oa, ac2);
@@ -840,6 +827,8 @@ ospf_sh(struct proto *p)
}
cli_msg(-1014, "%s:", p->name);
+ cli_msg(-1014, "RFC1583 compatibility: %s", (po->rfc1583 ? "enable" : "disabled"));
+ cli_msg(-1014, "RT scheduler tick: %d", po->tick);
cli_msg(-1014, "Number of areas: %u", po->areano);
WALK_LIST(oa, po->area_list)
@@ -852,16 +841,18 @@ ospf_sh(struct proto *p)
WALK_LIST(ifa, po->iface_list)
{
if (oa == ifa->oa)
- ifano++;
- WALK_LIST(n, ifa->neigh_list)
{
- nno++;
- if (n->state == NEIGHBOR_FULL)
- adjno++;
+ ifano++;
+ WALK_LIST(n, ifa->neigh_list)
+ {
+ nno++;
+ if (n->state == NEIGHBOR_FULL)
+ adjno++;
+ }
}
}
cli_msg(-1014, "\t\tStub:\t%s", oa->stub ? "Yes" : "No");
- cli_msg(-1014, "\t\tRT scheduler tick:\t%u", oa->tick);
+ cli_msg(-1014, "\t\tTransit:\t%s", oa->trcap ? "Yes" : "No");
cli_msg(-1014, "\t\tNumber of interfaces:\t%u", ifano);
cli_msg(-1014, "\t\tNumber of LSAs in DB:\t%u", oa->gr->hash_entries);
cli_msg(-1014, "\t\tNumber of neighbors:\t%u", nno);
diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h
index 13a5f82..40452c2 100644
--- a/proto/ospf/ospf.h
+++ b/proto/ospf/ospf.h
@@ -52,8 +52,7 @@
#define LSINFINITY 0xffffff
#define DEFAULT_OSPFTICK 1
-#define DEFAULT_AREATICK 1
-#define DEFAULT_RFC1583 1 /* compatibility with rfc1583 */
+#define DEFAULT_RFC1583 0 /* compatibility with rfc1583 */
struct ospf_config
@@ -90,8 +89,8 @@ struct ospf_area_config
node n;
u32 areaid;
int stub;
- unsigned tick;
list patt_list;
+ list vlink_list;
list net_list;
};
@@ -130,7 +129,6 @@ struct ospf_iface
struct iface *iface; /* Nest's iface */
struct ospf_area *oa;
struct object_lock *lock;
- u32 an; /* Area number */
sock *hello_sk; /* Hello socket */
sock *dr_sk; /* For states DR or BACKUP */
sock *ip_sk; /* IP socket (for DD ...) */
@@ -519,7 +517,6 @@ struct ospf_area
int stub;
int trcap; /* Transit capability? */
struct proto_ospf *po;
- unsigned tick;
struct fib rtr; /* Routing tables for routers */
union options opt; /* RFC2328 - A.2 */
};
diff --git a/proto/ospf/packet.c b/proto/ospf/packet.c
index 488a3a2..92e0522 100644
--- a/proto/ospf/packet.c
+++ b/proto/ospf/packet.c
@@ -25,7 +25,7 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
pkt->type = h_type;
pkt->routerid = htonl(p->cf->global->router_id);
- pkt->areaid = htonl(ifa->an);
+ pkt->areaid = htonl(ifa->oa->areaid);
pkt->autype = htons(ifa->autype);
pkt->checksum = 0;
}
@@ -219,17 +219,32 @@ ospf_rx_hook(sock * sk, int size)
{
struct ospf_packet *ps;
struct ospf_iface *ifa = (struct ospf_iface *) (sk->data);
+ struct proto_ospf *po = ifa->proto;
struct proto *p = (struct proto *) (ifa->proto);
struct ospf_neighbor *n;
int osize;
char *mesg = "Bad OSPF packet from ";
+ struct ospf_iface *iff;
if (ifa->stub)
return (1);
+ ps = (struct ospf_packet *) ipv4_skip_header(sk->rbuf, &size);
+
+ if ((ifa->oa->areaid != 0) && (ntohl(ps->areaid) == 0))
+ {
+ WALK_LIST(iff, po->iface_list)
+ {
+ if ((iff->type == OSPF_IT_VLINK) && (iff->iface == ifa->iface) &&
+ (iff->voa = ifa->oa) && ipa_equal(sk->faddr, iff->vip))
+ {
+ return 1; /* Packet is for VLINK */
+ }
+ }
+ }
+
DBG("%s: RX_Hook called on interface %s.\n", p->name, sk->iface->name);
- ps = (struct ospf_packet *) ipv4_skip_header(sk->rbuf, &size);
osize = ntohs(ps->length);
if (ps == NULL)
{
@@ -263,7 +278,7 @@ ospf_rx_hook(sock * sk, int size)
return 1;
}
- if (ntohl(ps->areaid) != ifa->an)
+ if (ntohl(ps->areaid) != ifa->oa->areaid)
{
log(L_ERR "%s%I - other area %ld", mesg, sk->faddr, ps->areaid);
return 1;
@@ -374,9 +389,9 @@ ospf_send_to_agt(sock * sk, struct ospf_iface *ifa, u8 state)
void
ospf_send_to_bdr(sock * sk, struct ospf_iface *ifa)
{
- if (ipa_compare(ifa->drip, ipa_from_u32(0)) != 0)
+ if (!ipa_equal(ifa->drip, IPA_NONE))
ospf_send_to(sk, ifa->drip, ifa);
- if (ipa_compare(ifa->bdrip, ipa_from_u32(0)) != 0)
+ if (!ipa_equal(ifa->bdrip, IPA_NONE))
ospf_send_to(sk, ifa->bdrip, ifa);
}
diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c
index 3d2ee51..ef3d44d 100644
--- a/proto/ospf/rt.c
+++ b/proto/ospf/rt.c
@@ -9,7 +9,7 @@
#include "ospf.h"
static void
add_cand(list * l, struct top_hash_entry *en,
- struct top_hash_entry *par, u16 dist, struct ospf_area *oa);
+ struct top_hash_entry *par, u16 dist, struct ospf_area *oa, int vlink);
static void
calc_next_hop(struct top_hash_entry *en,
struct top_hash_entry *par, struct ospf_area *oa);
@@ -24,7 +24,7 @@ fill_ri(orta * orta)
orta->oa = NULL;
orta->metric1 = LSINFINITY;
orta->metric2 = LSINFINITY;
- orta->nh = ipa_from_u32(0);
+ orta->nh = IPA_NONE;
orta->ifa = NULL;
orta->ar = NULL;
orta->tag = 0;
@@ -63,8 +63,7 @@ ri_better(struct proto_ospf *po, orta * new, ort *nefn, orta * old, ort *oefn, i
{
if(new->oa->areaid == 0) newtype = RTS_OSPF_IA;
if(old->oa->areaid == 0) oldtype = RTS_OSPF_IA;
-
-}
+ }
if (new->type < old->type)
return 1;
@@ -146,6 +145,7 @@ ospf_rt_spfa(struct ospf_area *oa)
struct ospf_iface *iface;
struct top_hash_entry *act, *tmp;
node *n;
+ int vlink;
if (oa->rt == NULL)
@@ -155,7 +155,7 @@ ospf_rt_spfa(struct ospf_area *oa)
oa->areaid);
if (oa->rt->dist != LSINFINITY)
- ospf_age(oa);
+ bug("Aging was not processed.");
init_list(&oa->cand); /* Empty list of candidates */
oa->trcap = 0;
@@ -202,6 +202,7 @@ ospf_rt_spfa(struct ospf_area *oa)
DBG(" Number of links: %u\n", rt->links);
for (i = 0; i < rt->links; i++)
{
+ vlink = 0;
tmp = NULL;
rtl = (rr + i);
DBG(" Working on link: %I (type: %u) ", rtl->id, rtl->type);
@@ -238,6 +239,7 @@ ospf_rt_spfa(struct ospf_area *oa)
break;
case LSART_VLNK:
+ vlink = 1;
case LSART_PTP:
tmp = ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_RT);
DBG("PTP found.\n");
@@ -249,7 +251,7 @@ ospf_rt_spfa(struct ospf_area *oa)
if (tmp)
DBG("Going to add cand, Mydist: %u, Req: %u\n",
tmp->dist, act->dist + rtl->metric);
- add_cand(&oa->cand, tmp, act, act->dist + rtl->metric, oa);
+ add_cand(&oa->cand, tmp, act, act->dist + rtl->metric, oa, vlink);
}
break;
case LSA_T_NET:
@@ -275,7 +277,7 @@ ospf_rt_spfa(struct ospf_area *oa)
DBG("Found :-)\n");
else
DBG("Not found!\n");
- add_cand(&oa->cand, tmp, act, act->dist, oa);
+ add_cand(&oa->cand, tmp, act, act->dist, oa, 0);
}
break;
}
@@ -287,15 +289,24 @@ ospf_rt_spfa(struct ospf_area *oa)
if ((iface->type == OSPF_IT_VLINK) && (iface->voa == oa))
{
if ((tmp = ospf_hash_find(oa->gr, iface->vid, iface->vid, LSA_T_RT)) &&
- ipa_equal(tmp->lb, IPA_NONE))
+ (!ipa_equal(tmp->lb, IPA_NONE)))
{
- DBG("Vlink peer found\n");
- ospf_iface_sm(iface, ISM_UP); /* FIXME: Add slave iface! */
+ if ((iface->state != OSPF_IS_PTP) || (iface->iface != tmp->nhi) || (!ipa_equal(iface->vip, tmp->lb)))
+ {
+ OSPF_TRACE(D_EVENTS, "Vlink peer %I found", tmp->lsa.id);
+ ospf_iface_sm(iface, ISM_DOWN);
+ iface->iface = tmp->nhi;
+ iface->vip = tmp->lb;
+ ospf_iface_sm(iface, ISM_UP);
+ }
}
else
{
- DBG("Vlink peer not found\n");
- ospf_iface_sm(iface, ISM_DOWN);
+ if (iface->state > OSPF_IS_DOWN)
+ {
+ OSPF_TRACE(D_EVENTS, "Vlink peer %I lost", iface->vid);
+ ospf_iface_sm(iface, ISM_DOWN);
+ }
}
}
}
@@ -367,7 +378,7 @@ ospf_rt_sum_tr(struct ospf_area *oa)
{
struct proto *p = &oa->po->proto;
struct proto_ospf *po = oa->po;
- struct ospf_area *bb, *atmp;
+ struct ospf_area *bb = po->backbone;
ip_addr *mask, ip, abrip;
struct top_hash_entry *en;
int mlen = -1, type = -1;
@@ -375,17 +386,6 @@ ospf_rt_sum_tr(struct ospf_area *oa)
ort *re = NULL, *abr;
orta nf;
- bb = NULL;
-
- WALK_LIST(atmp, po->area_list)
- {
- if(atmp->areaid == 0)
- {
- bb = atmp;
- break;
- }
- }
-
if(!bb) return;
WALK_SLIST(en, oa->lsal)
@@ -672,7 +672,7 @@ ospf_ext_spfa(struct ospf_area *oa)
if (!(nf1->n.capa & ORTA_ASBR))
continue; /* It is not ASBR */
- if (ipa_compare(lt->fwaddr, ipa_from_u32(0)) == 0)
+ if (ipa_equal(lt->fwaddr, IPA_NONE))
{
if (lt->etm.etos.ebit)
{ /* FW address == 0 */
@@ -742,7 +742,7 @@ ospf_ext_spfa(struct ospf_area *oa)
/* Add LSA into list of candidates in Dijkstra's algorithm */
static void
add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
- u16 dist, struct ospf_area *oa)
+ u16 dist, struct ospf_area *oa, int vlink)
{
node *prev, *n;
int added = 0;
@@ -773,6 +773,7 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
en->nh = IPA_NONE;
calc_next_hop(en, par, oa);
+ //if (vlink) en->nh = IPA_NONE;
if (!en->nhi)
return; /* We cannot find next hop, ignore it */
@@ -901,8 +902,9 @@ rt_sync(struct proto_ospf *po)
struct fib_iterator fit;
struct fib *fib = &po->rtf;
ort *nf;
- struct ospf_area *oa;
+ struct ospf_area *oa, *oaa;
struct area_net *anet;
+ int flush;
OSPF_TRACE(D_EVENTS, "Starting routing table synchronisation");
@@ -929,6 +931,27 @@ again1:
a0.aflags = 0;
a0.iface = nf->n.ifa;
a0.gw = nf->n.nh;
+ if(!neigh_find(p, &nf->n.nh, 0))
+ {
+ int found = 0;
+ struct ospf_iface *ifa;
+ struct top_hash_entry *en;
+ DBG("Trying to find correct next hop");
+ WALK_LIST(ifa, po->iface_list)
+ {
+ if ((ifa->type == OSPF_IT_VLINK) && ipa_equal(ifa->vip, nf->n.nh))
+ {
+ if ((en = ospf_hash_find(ifa->voa->gr, ifa->vid, ifa->vid, LSA_T_RT)) &&
+ (!ipa_equal(en->nh, IPA_NONE)))
+ {
+ a0.gw = en->nh;
+ found = 1;
+ }
+ break;
+ }
+ }
+ if (!found) nf->n.metric1 = LSINFINITY; /* Delete it */
+ }
ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen);
check_sum_lsa(po, nf, ORT_NET);
if (nf->n.metric1 < LSINFINITY)
@@ -978,10 +1001,17 @@ again2:
/* Check condensed summary LSAs */
FIB_WALK(&oa->net_fib, nftmp)
{
+ flush = 1;
anet = (struct area_net *) nftmp;
if((!anet->hidden) && anet->active && (!oa->trcap))
- originate_sum_lsa(oa, &anet->fn, ORT_NET, 1);
- else flush_sum_lsa(oa, &anet->fn, ORT_NET);
+ flush = 0;
+
+ WALK_LIST(oaa, po->area_list)
+ {
+ if (oaa == oa) continue;
+ if(flush) flush_sum_lsa(oaa, &anet->fn, ORT_NET);
+ else originate_sum_lsa(oaa, &anet->fn, ORT_NET, 1);
+ }
}
FIB_WALK_END;
}
diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c
index 562ddb5..4854721 100644
--- a/proto/ospf/topology.c
+++ b/proto/ospf/topology.c
@@ -36,7 +36,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
WALK_LIST(ifa, po->iface_list)
{
- if ((ifa->an == oa->areaid) && (ifa->state != OSPF_IS_DOWN))
+ if ((ifa->oa == oa) && (ifa->state != OSPF_IS_DOWN))
{
i++;
}
@@ -51,7 +51,10 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
WALK_LIST(ifa, po->iface_list)
{
- if ((ifa->an != oa->areaid) || (ifa->state == OSPF_IS_DOWN))
+ if ((ifa->type == OSPF_IT_VLINK) && (ifa->voa == oa) && (ifa->state > OSPF_IS_DOWN))
+ rt->veb.bit.v = 1;
+
+ if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN))
continue;
if (ifa->state == OSPF_IS_LOOP)
@@ -146,7 +149,6 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
ln->id = neigh->rid;
ln->metric = ifa->cost;
ln->notos = 0;
- rt->veb.bit.v = 1;
}
else
{
@@ -351,14 +353,14 @@ originate_ext_lsa_body(net * n, rte * e, struct proto_ospf *po,
et->etm.etos.ebit = 1;
}
et->tag = tag;
- if (ipa_compare(e->attrs->gw, ipa_from_u32(0)) != 0)
+ if (!ipa_equal(e->attrs->gw, IPA_NONE))
{
if (ospf_iface_find((struct proto_ospf *) p, e->attrs->iface) != NULL)
inas = 1;
}
if (!inas)
- et->fwaddr = ipa_from_u32(0);
+ et->fwaddr = IPA_NONE;
else
et->fwaddr = e->attrs->gw;
return ext;
@@ -416,7 +418,8 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
{
en->lsa.age = LSA_MAXAGE;
en->lsa.sn = LSA_MAXSEQNO;
- OSPF_TRACE(D_EVENTS, "Flushing summary lsa.");
+ lsasum_calculate(&en->lsa, sum);
+ OSPF_TRACE(D_EVENTS, "Flushing summary lsa. (id=%I, type=%d)", en->lsa.id, en->lsa.type);
ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1);
if (can_flush_lsa(oa)) flush_lsa(en, oa);
break;
@@ -425,9 +428,6 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
}
}
-
-
-
void
originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metric)
{
@@ -436,8 +436,7 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri
struct top_hash_entry *en;
u32 rtid = po->proto.cf->global->router_id;
struct ospf_lsa_header lsa;
- void *body = NULL;
- int i, max, mlen = fn->pxlen, found = 0, free = -1;
+ int i, max, mlen = fn->pxlen, free = 0;
struct ospf_lsa_sum *sum = NULL;
union ospf_lsa_sum_tm *tm;
lsa.type = LSA_T_SUM_NET;
@@ -461,7 +460,7 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri
lsa.id = ipa_to_u32(fn->prefix) + i;
if ((en = ospf_hash_find_header(oa->gr, &lsa)) == NULL)
{
- if (free < 0) free = i;
+ if (!free) free = lsa.id;
}
else
{
@@ -477,7 +476,7 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri
}
}
- if(free < 0)
+ if(!free)
{
log("%s: got more routes for one /%d network then %d, ignoring", p->name,
fn->pxlen, max);
@@ -485,9 +484,6 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri
}
lsa.id = free;
- sum = en->lsa_body;
- tm = (union ospf_lsa_sum_tm *) (sum + 1);
-
OSPF_TRACE(D_EVENTS, "Originating summary (type %d) lsa for %I/%d.", lsa.type, fn->prefix,
fn->pxlen);
@@ -497,8 +493,8 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri
tm->metric = metric;
tm->tos.tos = 0;
- lsasum_calculate(&lsa, body);
- en = lsa_install_new(&lsa, body, oa);
+ lsasum_calculate(&lsa, sum);
+ en = lsa_install_new(&lsa, sum, oa);
ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1);
}
@@ -515,6 +511,12 @@ check_sum_lsa(struct proto_ospf *po, ort *nf, int dest)
if ((nf->n.type > RTS_OSPF_IA) && (nf->o.type > RTS_OSPF_IA)) return;
+#ifdef LOCAL_DEBUG
+ DBG("Checking...dest = %d, %I/%d", dest, nf->fn.prefix, nf->fn.pxlen);
+ if (nf->n.oa) DBG("New: met=%d, oa=%d", nf->n.metric1, nf->n.oa->areaid);
+ if (nf->o.oa) DBG("Old: met=%d, oa=%d", nf->o.metric1, nf->o.oa->areaid);
+#endif
+
WALK_LIST(oa, po->area_list)
{
flush = 0;
@@ -522,7 +524,7 @@ check_sum_lsa(struct proto_ospf *po, ort *nf, int dest)
flush = 1;
if ((dest == ORT_ROUTER) && (!(nf->n.capa & ORTA_ABR)))
flush = 1;
- if (nf->n.oa->areaid == oa->areaid)
+ if ((!nf->n.oa) || (nf->n.oa->areaid == oa->areaid))
flush = 1;
/* FIXME: Test next hop - is it in actual area? */
if ((dest == ORT_ROUTER) && oa->stub)
@@ -531,7 +533,8 @@ check_sum_lsa(struct proto_ospf *po, ort *nf, int dest)
mlen = nf->fn.pxlen;
ip = ipa_and(nf->fn.prefix, ipa_mkmask(mlen));
- if((!oa->trcap) && fib_route(&oa->net_fib, ip, mlen)) /* The route fits into some area */
+ if ((!flush) && (!nf->n.oa->trcap) &&
+ fib_route(&nf->n.oa->net_fib, ip, mlen)) /* The route fits into area networks */
flush = 1;
if(flush) /* FIXME Go on... */
@@ -543,20 +546,6 @@ check_sum_lsa(struct proto_ospf *po, ort *nf, int dest)
}
}
-void
-check_sum_areas(struct proto_ospf *po)
-{
- struct proto *p = &po->proto;
- struct ospf_area *oa;
- struct area_net *anet;
-
- WALK_LIST(oa, po->area_list)
- {
- ; /* FIXME */
- }
-}
-
-
/**
* originate_ext_lsa - new route received from nest and filters
* @n: network prefix and mask
@@ -806,8 +795,8 @@ ospf_hash_get(struct top_graph *f, u32 lsa, u32 rtr, u32 type)
e->color = OUTSPF;
e->dist = LSINFINITY;
e->nhi = NULL;
- e->nh = ipa_from_u32(0);
- e->lb = ipa_from_u32(0);
+ e->nh = IPA_NONE;
+ e->lb = IPA_NONE;
e->lsa.id = lsa;
e->lsa.rt = rtr;
e->lsa.type = type;
@@ -852,8 +841,8 @@ ospf_top_dump(struct top_graph *f, struct proto *p)
struct top_hash_entry *e = f->hash_table[i];
while (e)
{
- OSPF_TRACE(D_EVENTS, "\t%1x %-1I %-1I %4u 0x%08x",
- e->lsa.type, e->lsa.id, e->lsa.rt, e->lsa.age, e->lsa.sn);
+ OSPF_TRACE(D_EVENTS, "\t%1x %-1I %-1I %4u 0x%08x 0x%04x",
+ e->lsa.type, e->lsa.id, e->lsa.rt, e->lsa.age, e->lsa.sn, e->lsa.checksum);
e = e->next;
}
}