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!!!!
This commit is contained in:
Ondrej Filip 2004-07-14 21:46:20 +00:00
parent a417ad13a1
commit 3b16080c97
14 changed files with 341 additions and 247 deletions

2
TODO
View file

@ -44,8 +44,6 @@ Various ideas
OSPF 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 - check incoming packets using neighbor cache
- RFC2328 appendix E: Use a better algorithm - RFC2328 appendix E: Use a better algorithm
- automatic generation of external route tags (RFC1403) - automatic generation of external route tags (RFC1403)

View file

@ -103,12 +103,11 @@ protocol static {
# export filter { print "exporting"; accept; }; # export filter { print "exporting"; accept; };
#} #}
# Please note, multiple areas still don't work.
#protocol ospf MyOSPF { #protocol ospf MyOSPF {
# tick 2;
# rfc1583compat yes; # rfc1583compat yes;
# area 0.0.0.0 { # area 0.0.0.0 {
# stub no; # stub no;
# tick 1;
# interface "eth*" { # interface "eth*" {
# hello 9; # hello 9;
# retransmit 6; # retransmit 6;
@ -136,6 +135,11 @@ protocol static {
# hello 8; # hello 8;
# authentication none; # authentication none;
# }; # };
# interface "fr*";
# virtual link 192.168.0.1 {
# password "sdsdffsdfg";
# authentication cryptographic;
# };
# }; # };
#} #}

View file

@ -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 has an identical copy of the database and all routers run the same algorithm
calculating a shortest path tree with themselves as a root. calculating a shortest path tree with themselves as a root.
OSPF chooses the least cost path as the best path. 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 <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 to reduce the amount of resources consumed for exchanging the routing
information and to protect the other areas from incorrect routing data. information and to protect the other areas from incorrect routing data.
Topology of the area is hidden to the rest of the autonomous system. 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 <p>Another very important feature of OSPF is that
it can keep routing information from other protocols (like Static or BGP) 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;; tick &lt;num&gt;;
area &lt;id&gt; { area &lt;id&gt; {
stub cost &lt;num&gt;; stub cost &lt;num&gt;;
tick &lt;num&gt;;
networks { networks {
&lt;prefix&gt;; &lt;prefix&gt;;
&lt;prefix&gt; hidden; &lt;prefix&gt; hidden;
@ -1047,7 +1045,6 @@ protocol ospf &lt;name&gt; {
virtual link &lt;id&gt; virtual link &lt;id&gt;
{ {
hello &lt;num&gt;; hello &lt;num&gt;;
poll &lt;num&gt;;
retransmit &lt;num&gt;; retransmit &lt;num&gt;;
wait &lt;num&gt;; wait &lt;num&gt;;
dead count &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.) Default value is no. (Area is not stub.)
<tag>tick <M>num</M></tag> <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 is not performed when a single link state
change arrives. To lower the CPU utilization, it's processed later change arrives. To lower the CPU utilization, it's processed later
at periodical intervals of <m/num/ seconds. The default value is 1. 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. Defines that the specified interfaces belong to the area being defined.
<tag>virtual link <M>id</M></tag> <tag>virtual link <M>id</M></tag>
Virtual link to router with the router id. This item cannot be in the Virtual link to router with the router id. Virtual link acts as a
backbone area (ID 0). 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> <tag>cost <M>num</M></tag>
Specifies output cost (metric) of an interface. Default value is 10. 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> <code>
protocol ospf MyOSPF { protocol ospf MyOSPF {
rfc1583compatibility yes;
tick 2;
export filter { export filter {
if source = RTS_BGP then { if source = RTS_BGP then {
ospf_metric1 = 100; ospf_metric1 = 100;
@ -1213,7 +1213,6 @@ protocol ospf MyOSPF {
reject; reject;
}; };
area 0.0.0.0 { area 0.0.0.0 {
tick 8;
interface "eth*" { interface "eth*" {
cost 11; cost 11;
hello 15; hello 15;
@ -1224,11 +1223,25 @@ protocol ospf MyOSPF {
}; };
interface "ppp*" { interface "ppp*" {
cost 100; 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" { interface "arc0" {
cost 10; cost 10;
stub yes; stub yes;
}; };
interface "arc1";
}; };
area 120 { area 120 {
stub yes; stub yes;

View file

@ -58,9 +58,9 @@ ospf_area_start: AREA idval '{' {
this_area = cfg_allocz(sizeof(struct ospf_area_config)); this_area = cfg_allocz(sizeof(struct ospf_area_config));
add_tail(&OSPF_CFG->area_list, NODE this_area); add_tail(&OSPF_CFG->area_list, NODE this_area);
this_area->areaid = $2; this_area->areaid = $2;
this_area->tick = DEFAULT_AREATICK;
this_area->stub = 0; this_area->stub = 0;
init_list(&this_area->patt_list); init_list(&this_area->patt_list);
init_list(&this_area->vlink_list);
init_list(&this_area->net_list); init_list(&this_area->net_list);
} }
; ;
@ -75,13 +75,14 @@ ospf_area_opts:
ospf_area_item: ospf_area_item:
STUB COST expr { this_area->stub = $3 ; if($3<=0) cf_error("Stub cost must be greater than zero"); } 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 '}' | NETWORKS '{' pref_list '}'
| INTERFACE ospf_iface_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: ospf_vlink_opts:
@ -90,8 +91,7 @@ ospf_vlink_opts:
; ;
ospf_vlink_item: ospf_vlink_item:
HELLO expr { OSPF_PATT->helloint = $2 ; if (($2<=0) || ($2>65535)) cf_error("Hello interval must be in range 1-65535"); } | 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"); }
| 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) || ($3>65535)) cf_error("Transmit delay must be in range 1-65535"); } | 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 ; } | WAIT expr { OSPF_PATT->waitint = $2 ; }
@ -102,19 +102,21 @@ ospf_vlink_item:
| password_list {OSPF_PATT->passwords = $1; } | 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"); if (this_area->areaid == 0) cf_error("Virtual link cannot be in backbone");
this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt)); 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->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->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_VLINK; OSPF_PATT->type = OSPF_IT_VLINK;
init_list(&OSPF_PATT->nbma_list);
OSPF_PATT->autype = OSPF_AUTH_NONE; OSPF_PATT->autype = OSPF_AUTH_NONE;
} }
; ;
@ -198,6 +200,7 @@ ipa_ne: IPA ELIGIBLE ';'
ospf_iface_start: ospf_iface_start:
{ {
log("Iface start");
this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt)); this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt));
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;

View file

@ -19,12 +19,13 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
struct proto *p = (struct proto *) ifa->proto; struct proto *p = (struct proto *) ifa->proto;
unsigned int size = ntohs(ps->ospf_packet.length), i, twoway, oldpriority, eligible = 0, peers; 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, OSPF_TRACE(D_PACKETS, "Received hello from %I via %s%s", faddr,
ifa->iface->name); (ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
mask = ps->netmask; mask = ps->netmask;
ipa_ntoh(mask); 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); log(L_ERR "%s%I%sbad netmask %I.", beg, faddr, rec, mask);
return; return;
@ -151,7 +152,7 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
ospf_iface_sm(ifa, ISM_NEICH); 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)) if ((ifa->priority == 0) && (n->priority > 0))
ospf_hello_send(NULL, 0, n); ospf_hello_send(NULL, 0, n);
@ -171,7 +172,6 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
u32 *pp; u32 *pp;
int i, send; int i, send;
struct nbma_node *nb; struct nbma_node *nb;
if (timer == NULL) if (timer == NULL)
ifa = dirn->ifa; ifa = dirn->ifa;
else else
@ -204,6 +204,7 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
pkt->netmask = ipa_mkmask(ifa->iface->addr->pxlen); pkt->netmask = ipa_mkmask(ifa->iface->addr->pxlen);
ipa_hton(pkt->netmask); ipa_hton(pkt->netmask);
if (ifa->type == OSPF_IT_VLINK) pkt->netmask = IPA_NONE;
pkt->helloint = ntohs(ifa->helloint); pkt->helloint = ntohs(ifa->helloint);
pkt->options = ifa->oa->opt.byte; pkt->options = ifa->oa->opt.byte;
pkt->priority = ifa->priority; pkt->priority = ifa->priority;
@ -280,5 +281,6 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
default: default:
ospf_send_to(ifa->hello_sk, IPA_NONE, ifa); 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);
} }

View file

@ -21,6 +21,7 @@ char *ospf_it[] = { "broadcast", "nbma", "point-to-point", "virtual link" };
static void static void
poll_timer_hook(timer * timer) poll_timer_hook(timer * timer)
{ {
log("POLL!");
ospf_hello_send(timer, 1, NULL); ospf_hello_send(timer, 1, NULL);
} }
@ -40,6 +41,38 @@ wait_timer_hook(timer * timer)
ospf_iface_sm(ifa, ISM_WAITF); 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 * ospf_iface_chstate - handle changes of interface state
@ -55,15 +88,27 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
{ {
struct proto_ospf *po = ifa->proto; struct proto_ospf *po = ifa->proto;
struct proto *p = &po->proto; struct proto *p = &po->proto;
u8 oldstate; u8 oldstate = ifa->state;
if (ifa->state != state) if (oldstate != state)
{
ifa->state = state;
if (ifa->type == OSPF_IT_VLINK)
{
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)
{
ifa->ip_sk = ospf_open_ip_socket(ifa);
}
}
else
{ {
OSPF_TRACE(D_EVENTS, OSPF_TRACE(D_EVENTS,
"Changing state of iface: %s from \"%s\" into \"%s\".", "Changing state of iface: %s from \"%s\" into \"%s\".",
ifa->iface->name, ospf_is[ifa->state], ospf_is[state]); ifa->iface->name, ospf_is[oldstate], ospf_is[state]);
oldstate = ifa->state;
ifa->state = state;
if (ifa->iface->flags & IF_MULTICAST) if (ifa->iface->flags & IF_MULTICAST)
{ {
if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR)) if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
@ -111,6 +156,7 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
} }
} }
} }
}
static void static void
ospf_iface_down(struct ospf_iface *ifa) ospf_iface_down(struct ospf_iface *ifa)
@ -120,6 +166,16 @@ ospf_iface_down(struct ospf_iface *ifa)
struct proto_ospf *po = ifa->proto; struct proto_ospf *po = ifa->proto;
struct ospf_iface *iff; 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) WALK_LIST_DELSAFE(n, nx, ifa->neigh_list)
{ {
OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip); OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip);
@ -144,7 +200,6 @@ ospf_iface_down(struct ospf_iface *ifa)
rem_node(NODE ifa); rem_node(NODE ifa);
mb_free(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) if (ifa->state == OSPF_IS_DOWN)
{ {
/* Now, nothing should be adjacent */ /* 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)) if ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_VLINK))
{
ospf_iface_chstate(ifa, OSPF_IS_PTP); ospf_iface_chstate(ifa, OSPF_IS_PTP);
}
else else
{ {
if (ifa->priority == 0) 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->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); hello_timer_hook(ifa->hello_timer);
} }
schedule_rt_lsa(ifa->oa); schedule_rt_lsa(ifa->oa);
@ -257,37 +315,6 @@ ospf_open_mc_socket(struct ospf_iface *ifa)
return (mcsk); 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 u8
ospf_iface_clasify(struct iface * ifa) ospf_iface_clasify(struct iface * ifa)
{ {
@ -306,7 +333,7 @@ ospf_iface_find(struct proto_ospf *p, struct iface *what)
{ {
struct ospf_iface *i; 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 i;
return NULL; return NULL;
} }
@ -350,7 +377,8 @@ ospf_iface_add(struct object_lock *lock)
} }
void 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 proto *p = &po->proto;
struct ospf_iface *ifa; 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->proto = po;
ifa->iface = iface; ifa->iface = iface;
ifa->an = ac->areaid;
ifa->cost = ip->cost; ifa->cost = ip->cost;
ifa->rxmtint = ip->rxmtint; ifa->rxmtint = ip->rxmtint;
ifa->inftransdelay = ip->inftransdelay; 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->neigh_list);
init_list(&ifa->nbma_list); init_list(&ifa->nbma_list);
WALK_LIST(nb, ip->nbma_list) WALK_LIST(nb, ip->nbma_list)
{ {
nbma = mb_alloc(p->pool, sizeof(struct nbma_node)); nbma = mb_alloc(p->pool, sizeof(struct nbma_node));
@ -420,16 +448,19 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_conf
add_tail(&((struct proto_ospf *) p)->iface_list, NODE ifa); add_tail(&((struct proto_ospf *) p)->iface_list, NODE ifa);
ifa->state = OSPF_IS_DOWN; ifa->state = OSPF_IS_DOWN;
ifa->oa = NULL;
WALK_LIST(oa, po->area_list) WALK_LIST(oa, po->area_list)
{ {
if (oa->areaid == ifa->an) if (oa->areaid == ac->areaid)
{
ifa->oa = oa;
break; break;
} }
}
if (EMPTY_LIST(po->area_list) || (oa->areaid != ifa->an)) /* New area */ if (!ifa->oa)
bug("Cannot add any area to accepted Interface"); bug("Cannot add any area to accepted Interface");
else else
ifa->oa = oa;
if (ifa->type == OSPF_IT_VLINK) if (ifa->type == OSPF_IT_VLINK)
{ {
@ -536,9 +567,19 @@ ospf_iface_info(struct ospf_iface *ifa)
if ((ifa->type != OSPF_IT_NBMA) || (ifa->strictnbma == 0)) if ((ifa->type != OSPF_IT_NBMA) || (ifa->strictnbma == 0))
strict = ""; strict = "";
cli_msg(-1015, "Interface \"%s\":", ifa->iface->name); if (ifa->type == OSPF_IT_VLINK)
cli_msg(-1015, "\tArea: %I (%u)", ifa->oa->areaid, ifa->oa->areaid); {
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, "\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], cli_msg(-1015, "\tState: %s %s", ospf_is[ifa->state],
ifa->stub ? "(stub)" : ""); ifa->stub ? "(stub)" : "");
cli_msg(-1015, "\tPriority: %u", ifa->priority); cli_msg(-1015, "\tPriority: %u", ifa->priority);

View file

@ -55,8 +55,8 @@ ospf_age(struct ospf_area *oa)
en->color = OUTSPF; en->color = OUTSPF;
en->dist = LSINFINITY; en->dist = LSINFINITY;
en->nhi = NULL; en->nhi = NULL;
en->nh = ipa_from_u32(0); en->nh = IPA_NONE;
en->lb = ipa_from_u32(0); en->lb = IPA_NONE;
DBG("Infinitying Type: %u, Id: %I, Rt: %I\n", en->lsa.type, en->lsa.id, DBG("Infinitying Type: %u, Id: %I, Rt: %I\n", en->lsa.type, en->lsa.id,
en->lsa.rt); en->lsa.rt);
} }

View file

@ -152,10 +152,10 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
struct ospf_packet *op; struct ospf_packet *op;
struct ospf_lsa_header *lh; 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; sk = ifa->ip_sk;
else else
sk = ifa->hello_sk; /* FIXME is this true for PTP? */ sk = ifa->hello_sk;
pk = (struct ospf_lsupd_packet *) sk->tbuf; pk = (struct ospf_lsupd_packet *) sk->tbuf;
op = (struct ospf_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); op->length = htons(len);
OSPF_TRACE(D_PACKETS, "LS upd flooded via %s", ifa->iface->name); 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)) if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
ospf_send_to_agt(sk, ifa, NEIGHBOR_EXCHANGE); ospf_send_to_agt(sk, ifa, NEIGHBOR_EXCHANGE);
else else
ospf_send_to_bdr(sk, ifa); ospf_send_to_bdr(sk, ifa);
} break;
else
{ case OSPF_IT_VLINK:
ospf_send_to(sk, ifa->vip, ifa);
break;
default:
if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR) || if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR) ||
(ifa->type == OSPF_IT_PTP)) (ifa->type == OSPF_IT_PTP))
ospf_send_to(sk, AllSPFRouters, ifa); 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, if ((en = ospf_hash_find(n->ifa->oa->gr, llsh->lsh.id, llsh->lsh.rt,
llsh->lsh.type)) == NULL) llsh->lsh.type)) == NULL)
continue; /* Probably flushed LSA */ 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", 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); 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) WALK_LIST(nifa, po->iface_list)
{ {
if (ipa_compare(nifa->iface->addr->ip, ipa_from_u32(lsatmp.id)) == if (!nifa->iface)
0) continue;
if (ipa_equal(nifa->iface->addr->ip, ipa_from_u32(lsatmp.id)))
{ {
self = 1; self = 1;
break; break;

View file

@ -122,6 +122,7 @@ neigh_chstate(struct ospf_neighbor *n, u8 state)
{ {
ifa->fadj++; ifa->fadj++;
schedule_rt_lsa(ifa->oa); schedule_rt_lsa(ifa->oa);
if (ifa->type == OSPF_IT_VLINK) schedule_rt_lsa(ifa->voa);
schedule_net_lsa(ifa); schedule_net_lsa(ifa);
} }
if (state == NEIGHBOR_EXSTART) if (state == NEIGHBOR_EXSTART)
@ -422,12 +423,12 @@ bdr_election(struct ospf_iface *ifa)
|| ((ifa->bdrid != myid) && (nbdr == &me))) || ((ifa->bdrid != myid) && (nbdr == &me)))
{ {
if (ndr == NULL) if (ndr == NULL)
ifa->drip = me.dr = ipa_from_u32(0); ifa->drip = me.dr = IPA_NONE;
else else
ifa->drip = me.dr = ndr->ip; ifa->drip = me.dr = ndr->ip;
if (nbdr == NULL) if (nbdr == NULL)
ifa->bdrip = me.bdr = ipa_from_u32(0); ifa->bdrip = me.bdr = IPA_NONE;
else else
ifa->bdrip = me.bdr = nbdr->ip; ifa->bdrip = me.bdr = nbdr->ip;
@ -436,12 +437,12 @@ bdr_election(struct ospf_iface *ifa)
} }
if (ndr == NULL) if (ndr == NULL)
ndrip = ipa_from_u32(0); ndrip = IPA_NONE;
else else
ndrip = ndr->ip; ndrip = ndr->ip;
if (nbdr == NULL) if (nbdr == NULL)
nbdrip = ipa_from_u32(0); nbdrip = IPA_NONE;
else else
nbdrip = nbdr->ip; nbdrip = nbdr->ip;
@ -453,7 +454,7 @@ bdr_election(struct ospf_iface *ifa)
if (ndr == NULL) if (ndr == NULL)
{ {
ifa->drid = 0; ifa->drid = 0;
ifa->drip = ipa_from_u32(0); ifa->drip = IPA_NONE;
} }
else else
{ {
@ -464,7 +465,7 @@ bdr_election(struct ospf_iface *ifa)
if (nbdr == NULL) if (nbdr == NULL)
{ {
ifa->bdrid = 0; ifa->bdrid = 0;
ifa->bdrip = ipa_from_u32(0); ifa->bdrip = IPA_NONE;
} }
else else
{ {
@ -591,11 +592,12 @@ ospf_sh_neigh_info(struct ospf_neighbor *n)
pos = "dr "; pos = "dr ";
if (n->rid == ifa->bdrid) if (n->rid == ifa->bdrid)
pos = "bdr "; pos = "bdr ";
if (n->ifa->type == OSPF_IT_PTP) if ((n->ifa->type == OSPF_IT_PTP) || (n->ifa->type == OSPF_IT_VLINK))
pos = "ptp "; pos = "ptp ";
cli_msg(-1013, "%-1I\t%3u\t%s/%s\t%-5s\t%-1I\t%-10s", n->rid, n->priority, 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 void

View file

@ -45,7 +45,7 @@
* Every area has its own area_disp() which is * Every area has its own area_disp() which is
* responsible for late originating of router LSA, calculating * responsible for late originating of router LSA, calculating
* of the routing table and it also ages and flushes the LSAs. This * 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 * To every &ospf_iface, we connect one or more
* &ospf_neighbor's -- a structure containing many timers and queues * &ospf_neighbor's -- a structure containing many timers and queues
* for building adjacency and for exchange of routing messages. * 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_better(struct rte *new, struct rte *old);
static int ospf_rte_same(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 ospf_disp(timer *timer);
static void static void
@ -135,18 +134,11 @@ ospf_start(struct proto *p)
add_tail(&po->area_list, NODE oa); add_tail(&po->area_list, NODE oa);
po->areano++; po->areano++;
oa->stub = ac->stub; oa->stub = ac->stub;
oa->tick = ac->tick;
oa->areaid = ac->areaid; oa->areaid = ac->areaid;
oa->gr = ospf_top_new(p->pool); oa->gr = ospf_top_new(p->pool);
s_init_list(&(oa->lsal)); s_init_list(&(oa->lsal));
oa->rt = NULL; oa->rt = NULL;
oa->po = po; 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); add_area_nets(oa, ac);
fib_init(&oa->rtr, p->pool, sizeof(ort), 16, ospf_rt_initort); fib_init(&oa->rtr, p->pool, sizeof(ort), 16, ospf_rt_initort);
if (oa->areaid == 0) po->backbone = oa; if (oa->areaid == 0) po->backbone = oa;
@ -160,10 +152,8 @@ ospf_start(struct proto *p)
struct ospf_iface_patt *ipatt; struct ospf_iface_patt *ipatt;
WALK_LIST(ac, c->area_list) WALK_LIST(ac, c->area_list)
{ {
WALK_LIST(ipatt, ac->patt_list) WALK_LIST(ipatt, ac->vlink_list)
{ ospf_iface_new(po, NULL, ac, ipatt);
if (ipatt->type == OSPF_IT_VLINK) ospf_iface_new(po, NULL, ac, ipatt);
}
} }
} }
return PS_UP; return PS_UP;
@ -181,7 +171,7 @@ ospf_dump(struct proto *p)
WALK_LIST(ifa, po->iface_list) 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, "state: %u", ifa->state);
OSPF_TRACE(D_EVENTS, "DR: %I", ifa->drid); OSPF_TRACE(D_EVENTS, "DR: %I", ifa->drid);
OSPF_TRACE(D_EVENTS, "BDR: %I", ifa->bdrid); 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. * function for origination of router LSA and network LSAs.
*/ */
void void
area_disp(timer * timer) area_disp(struct ospf_area *oa)
{ {
struct ospf_area *oa = timer->data;
struct proto_ospf *po = oa->po; struct proto_ospf *po = oa->po;
struct ospf_iface *ifa; struct ospf_iface *ifa;
@ -324,7 +313,7 @@ area_disp(timer * timer)
/* Now try to originate network LSA's */ /* Now try to originate network LSA's */
WALK_LIST(ifa, po->iface_list) WALK_LIST(ifa, po->iface_list)
{ {
if (ifa->orignet && (ifa->an == oa->areaid)) if (ifa->orignet && (ifa->oa == oa))
originate_net_lsa(ifa); originate_net_lsa(ifa);
} }
@ -336,6 +325,10 @@ void
ospf_disp(timer * timer) ospf_disp(timer * timer)
{ {
struct proto_ospf *po = timer->data; struct proto_ospf *po = timer->data;
struct ospf_area *oa;
WALK_LIST(oa, po->area_list)
area_disp(oa);
/* Calculate routing table */ /* Calculate routing table */
if (po->calcrt) if (po->calcrt)
@ -555,6 +548,13 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
struct area_net *anet, *antmp; struct area_net *anet, *antmp;
int found; 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; po->rfc1583 = new->rfc1583;
schedule_rtcalc(po); schedule_rtcalc(po);
@ -576,19 +576,6 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
if (!oa) if (!oa)
return 0; 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 */ /* Change net_list */
fib_free(&oa->net_fib); fib_free(&oa->net_fib);
add_area_nets(oa, ac2); add_area_nets(oa, ac2);
@ -840,6 +827,8 @@ ospf_sh(struct proto *p)
} }
cli_msg(-1014, "%s:", p->name); 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); cli_msg(-1014, "Number of areas: %u", po->areano);
WALK_LIST(oa, po->area_list) WALK_LIST(oa, po->area_list)
@ -852,6 +841,7 @@ ospf_sh(struct proto *p)
WALK_LIST(ifa, po->iface_list) WALK_LIST(ifa, po->iface_list)
{ {
if (oa == ifa->oa) if (oa == ifa->oa)
{
ifano++; ifano++;
WALK_LIST(n, ifa->neigh_list) WALK_LIST(n, ifa->neigh_list)
{ {
@ -860,8 +850,9 @@ ospf_sh(struct proto *p)
adjno++; adjno++;
} }
} }
}
cli_msg(-1014, "\t\tStub:\t%s", oa->stub ? "Yes" : "No"); 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 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 LSAs in DB:\t%u", oa->gr->hash_entries);
cli_msg(-1014, "\t\tNumber of neighbors:\t%u", nno); cli_msg(-1014, "\t\tNumber of neighbors:\t%u", nno);

View file

@ -52,8 +52,7 @@
#define LSINFINITY 0xffffff #define LSINFINITY 0xffffff
#define DEFAULT_OSPFTICK 1 #define DEFAULT_OSPFTICK 1
#define DEFAULT_AREATICK 1 #define DEFAULT_RFC1583 0 /* compatibility with rfc1583 */
#define DEFAULT_RFC1583 1 /* compatibility with rfc1583 */
struct ospf_config struct ospf_config
@ -90,8 +89,8 @@ struct ospf_area_config
node n; node n;
u32 areaid; u32 areaid;
int stub; int stub;
unsigned tick;
list patt_list; list patt_list;
list vlink_list;
list net_list; list net_list;
}; };
@ -130,7 +129,6 @@ struct ospf_iface
struct iface *iface; /* Nest's iface */ struct iface *iface; /* Nest's iface */
struct ospf_area *oa; struct ospf_area *oa;
struct object_lock *lock; struct object_lock *lock;
u32 an; /* Area number */
sock *hello_sk; /* Hello socket */ sock *hello_sk; /* Hello socket */
sock *dr_sk; /* For states DR or BACKUP */ sock *dr_sk; /* For states DR or BACKUP */
sock *ip_sk; /* IP socket (for DD ...) */ sock *ip_sk; /* IP socket (for DD ...) */
@ -519,7 +517,6 @@ struct ospf_area
int stub; int stub;
int trcap; /* Transit capability? */ int trcap; /* Transit capability? */
struct proto_ospf *po; struct proto_ospf *po;
unsigned tick;
struct fib rtr; /* Routing tables for routers */ struct fib rtr; /* Routing tables for routers */
union options opt; /* RFC2328 - A.2 */ union options opt; /* RFC2328 - A.2 */
}; };

View file

@ -25,7 +25,7 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
pkt->type = h_type; pkt->type = h_type;
pkt->routerid = htonl(p->cf->global->router_id); 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->autype = htons(ifa->autype);
pkt->checksum = 0; pkt->checksum = 0;
} }
@ -219,17 +219,32 @@ ospf_rx_hook(sock * sk, int size)
{ {
struct ospf_packet *ps; struct ospf_packet *ps;
struct ospf_iface *ifa = (struct ospf_iface *) (sk->data); struct ospf_iface *ifa = (struct ospf_iface *) (sk->data);
struct proto_ospf *po = ifa->proto;
struct proto *p = (struct proto *) (ifa->proto); struct proto *p = (struct proto *) (ifa->proto);
struct ospf_neighbor *n; struct ospf_neighbor *n;
int osize; int osize;
char *mesg = "Bad OSPF packet from "; char *mesg = "Bad OSPF packet from ";
struct ospf_iface *iff;
if (ifa->stub) if (ifa->stub)
return (1); 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); 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); osize = ntohs(ps->length);
if (ps == NULL) if (ps == NULL)
{ {
@ -263,7 +278,7 @@ ospf_rx_hook(sock * sk, int size)
return 1; 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); log(L_ERR "%s%I - other area %ld", mesg, sk->faddr, ps->areaid);
return 1; return 1;
@ -374,9 +389,9 @@ ospf_send_to_agt(sock * sk, struct ospf_iface *ifa, u8 state)
void void
ospf_send_to_bdr(sock * sk, struct ospf_iface *ifa) 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); 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); ospf_send_to(sk, ifa->bdrip, ifa);
} }

View file

@ -9,7 +9,7 @@
#include "ospf.h" #include "ospf.h"
static void static void
add_cand(list * l, struct top_hash_entry *en, 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 static void
calc_next_hop(struct top_hash_entry *en, calc_next_hop(struct top_hash_entry *en,
struct top_hash_entry *par, struct ospf_area *oa); struct top_hash_entry *par, struct ospf_area *oa);
@ -24,7 +24,7 @@ fill_ri(orta * orta)
orta->oa = NULL; orta->oa = NULL;
orta->metric1 = LSINFINITY; orta->metric1 = LSINFINITY;
orta->metric2 = LSINFINITY; orta->metric2 = LSINFINITY;
orta->nh = ipa_from_u32(0); orta->nh = IPA_NONE;
orta->ifa = NULL; orta->ifa = NULL;
orta->ar = NULL; orta->ar = NULL;
orta->tag = 0; orta->tag = 0;
@ -63,7 +63,6 @@ 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(new->oa->areaid == 0) newtype = RTS_OSPF_IA;
if(old->oa->areaid == 0) oldtype = RTS_OSPF_IA; if(old->oa->areaid == 0) oldtype = RTS_OSPF_IA;
} }
if (new->type < old->type) if (new->type < old->type)
@ -146,6 +145,7 @@ ospf_rt_spfa(struct ospf_area *oa)
struct ospf_iface *iface; struct ospf_iface *iface;
struct top_hash_entry *act, *tmp; struct top_hash_entry *act, *tmp;
node *n; node *n;
int vlink;
if (oa->rt == NULL) if (oa->rt == NULL)
@ -155,7 +155,7 @@ ospf_rt_spfa(struct ospf_area *oa)
oa->areaid); oa->areaid);
if (oa->rt->dist != LSINFINITY) if (oa->rt->dist != LSINFINITY)
ospf_age(oa); bug("Aging was not processed.");
init_list(&oa->cand); /* Empty list of candidates */ init_list(&oa->cand); /* Empty list of candidates */
oa->trcap = 0; oa->trcap = 0;
@ -202,6 +202,7 @@ ospf_rt_spfa(struct ospf_area *oa)
DBG(" Number of links: %u\n", rt->links); DBG(" Number of links: %u\n", rt->links);
for (i = 0; i < rt->links; i++) for (i = 0; i < rt->links; i++)
{ {
vlink = 0;
tmp = NULL; tmp = NULL;
rtl = (rr + i); rtl = (rr + i);
DBG(" Working on link: %I (type: %u) ", rtl->id, rtl->type); DBG(" Working on link: %I (type: %u) ", rtl->id, rtl->type);
@ -238,6 +239,7 @@ ospf_rt_spfa(struct ospf_area *oa)
break; break;
case LSART_VLNK: case LSART_VLNK:
vlink = 1;
case LSART_PTP: case LSART_PTP:
tmp = ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_RT); tmp = ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_RT);
DBG("PTP found.\n"); DBG("PTP found.\n");
@ -249,7 +251,7 @@ ospf_rt_spfa(struct ospf_area *oa)
if (tmp) if (tmp)
DBG("Going to add cand, Mydist: %u, Req: %u\n", DBG("Going to add cand, Mydist: %u, Req: %u\n",
tmp->dist, act->dist + rtl->metric); 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; break;
case LSA_T_NET: case LSA_T_NET:
@ -275,7 +277,7 @@ ospf_rt_spfa(struct ospf_area *oa)
DBG("Found :-)\n"); DBG("Found :-)\n");
else else
DBG("Not found!\n"); DBG("Not found!\n");
add_cand(&oa->cand, tmp, act, act->dist, oa); add_cand(&oa->cand, tmp, act, act->dist, oa, 0);
} }
break; break;
} }
@ -287,19 +289,28 @@ ospf_rt_spfa(struct ospf_area *oa)
if ((iface->type == OSPF_IT_VLINK) && (iface->voa == oa)) if ((iface->type == OSPF_IT_VLINK) && (iface->voa == oa))
{ {
if ((tmp = ospf_hash_find(oa->gr, iface->vid, iface->vid, LSA_T_RT)) && 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"); if ((iface->state != OSPF_IS_PTP) || (iface->iface != tmp->nhi) || (!ipa_equal(iface->vip, tmp->lb)))
ospf_iface_sm(iface, ISM_UP); /* FIXME: Add slave iface! */ {
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 else
{ {
DBG("Vlink peer not found\n"); if (iface->state > OSPF_IS_DOWN)
{
OSPF_TRACE(D_EVENTS, "Vlink peer %I lost", iface->vid);
ospf_iface_sm(iface, ISM_DOWN); ospf_iface_sm(iface, ISM_DOWN);
} }
} }
} }
} }
}
static int static int
link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entry *pre) link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entry *pre)
@ -367,7 +378,7 @@ ospf_rt_sum_tr(struct ospf_area *oa)
{ {
struct proto *p = &oa->po->proto; struct proto *p = &oa->po->proto;
struct proto_ospf *po = oa->po; struct proto_ospf *po = oa->po;
struct ospf_area *bb, *atmp; struct ospf_area *bb = po->backbone;
ip_addr *mask, ip, abrip; ip_addr *mask, ip, abrip;
struct top_hash_entry *en; struct top_hash_entry *en;
int mlen = -1, type = -1; int mlen = -1, type = -1;
@ -375,17 +386,6 @@ ospf_rt_sum_tr(struct ospf_area *oa)
ort *re = NULL, *abr; ort *re = NULL, *abr;
orta nf; orta nf;
bb = NULL;
WALK_LIST(atmp, po->area_list)
{
if(atmp->areaid == 0)
{
bb = atmp;
break;
}
}
if(!bb) return; if(!bb) return;
WALK_SLIST(en, oa->lsal) WALK_SLIST(en, oa->lsal)
@ -672,7 +672,7 @@ ospf_ext_spfa(struct ospf_area *oa)
if (!(nf1->n.capa & ORTA_ASBR)) if (!(nf1->n.capa & ORTA_ASBR))
continue; /* It is not 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) if (lt->etm.etos.ebit)
{ /* FW address == 0 */ { /* FW address == 0 */
@ -742,7 +742,7 @@ ospf_ext_spfa(struct ospf_area *oa)
/* Add LSA into list of candidates in Dijkstra's algorithm */ /* Add LSA into list of candidates in Dijkstra's algorithm */
static void static void
add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par, 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; node *prev, *n;
int added = 0; 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; en->nh = IPA_NONE;
calc_next_hop(en, par, oa); calc_next_hop(en, par, oa);
//if (vlink) en->nh = IPA_NONE;
if (!en->nhi) if (!en->nhi)
return; /* We cannot find next hop, ignore it */ return; /* We cannot find next hop, ignore it */
@ -901,8 +902,9 @@ rt_sync(struct proto_ospf *po)
struct fib_iterator fit; struct fib_iterator fit;
struct fib *fib = &po->rtf; struct fib *fib = &po->rtf;
ort *nf; ort *nf;
struct ospf_area *oa; struct ospf_area *oa, *oaa;
struct area_net *anet; struct area_net *anet;
int flush;
OSPF_TRACE(D_EVENTS, "Starting routing table synchronisation"); OSPF_TRACE(D_EVENTS, "Starting routing table synchronisation");
@ -929,6 +931,27 @@ again1:
a0.aflags = 0; a0.aflags = 0;
a0.iface = nf->n.ifa; a0.iface = nf->n.ifa;
a0.gw = nf->n.nh; 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); ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen);
check_sum_lsa(po, nf, ORT_NET); check_sum_lsa(po, nf, ORT_NET);
if (nf->n.metric1 < LSINFINITY) if (nf->n.metric1 < LSINFINITY)
@ -978,10 +1001,17 @@ again2:
/* Check condensed summary LSAs */ /* Check condensed summary LSAs */
FIB_WALK(&oa->net_fib, nftmp) FIB_WALK(&oa->net_fib, nftmp)
{ {
flush = 1;
anet = (struct area_net *) nftmp; anet = (struct area_net *) nftmp;
if((!anet->hidden) && anet->active && (!oa->trcap)) if((!anet->hidden) && anet->active && (!oa->trcap))
originate_sum_lsa(oa, &anet->fn, ORT_NET, 1); flush = 0;
else flush_sum_lsa(oa, &anet->fn, ORT_NET);
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; FIB_WALK_END;
} }

View file

@ -36,7 +36,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
WALK_LIST(ifa, po->iface_list) 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++; i++;
} }
@ -51,7 +51,10 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
WALK_LIST(ifa, po->iface_list) 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; continue;
if (ifa->state == OSPF_IS_LOOP) 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->id = neigh->rid;
ln->metric = ifa->cost; ln->metric = ifa->cost;
ln->notos = 0; ln->notos = 0;
rt->veb.bit.v = 1;
} }
else else
{ {
@ -351,14 +353,14 @@ originate_ext_lsa_body(net * n, rte * e, struct proto_ospf *po,
et->etm.etos.ebit = 1; et->etm.etos.ebit = 1;
} }
et->tag = tag; 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) if (ospf_iface_find((struct proto_ospf *) p, e->attrs->iface) != NULL)
inas = 1; inas = 1;
} }
if (!inas) if (!inas)
et->fwaddr = ipa_from_u32(0); et->fwaddr = IPA_NONE;
else else
et->fwaddr = e->attrs->gw; et->fwaddr = e->attrs->gw;
return ext; 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.age = LSA_MAXAGE;
en->lsa.sn = LSA_MAXSEQNO; 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); ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1);
if (can_flush_lsa(oa)) flush_lsa(en, oa); if (can_flush_lsa(oa)) flush_lsa(en, oa);
break; break;
@ -425,9 +428,6 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
} }
} }
void void
originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metric) 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; struct top_hash_entry *en;
u32 rtid = po->proto.cf->global->router_id; u32 rtid = po->proto.cf->global->router_id;
struct ospf_lsa_header lsa; struct ospf_lsa_header lsa;
void *body = NULL; int i, max, mlen = fn->pxlen, free = 0;
int i, max, mlen = fn->pxlen, found = 0, free = -1;
struct ospf_lsa_sum *sum = NULL; struct ospf_lsa_sum *sum = NULL;
union ospf_lsa_sum_tm *tm; union ospf_lsa_sum_tm *tm;
lsa.type = LSA_T_SUM_NET; 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; lsa.id = ipa_to_u32(fn->prefix) + i;
if ((en = ospf_hash_find_header(oa->gr, &lsa)) == NULL) if ((en = ospf_hash_find_header(oa->gr, &lsa)) == NULL)
{ {
if (free < 0) free = i; if (!free) free = lsa.id;
} }
else 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, log("%s: got more routes for one /%d network then %d, ignoring", p->name,
fn->pxlen, max); 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; 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, OSPF_TRACE(D_EVENTS, "Originating summary (type %d) lsa for %I/%d.", lsa.type, fn->prefix,
fn->pxlen); 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->metric = metric;
tm->tos.tos = 0; tm->tos.tos = 0;
lsasum_calculate(&lsa, body); lsasum_calculate(&lsa, sum);
en = lsa_install_new(&lsa, body, oa); en = lsa_install_new(&lsa, sum, oa);
ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1); 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; 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) WALK_LIST(oa, po->area_list)
{ {
flush = 0; flush = 0;
@ -522,7 +524,7 @@ check_sum_lsa(struct proto_ospf *po, ort *nf, int dest)
flush = 1; flush = 1;
if ((dest == ORT_ROUTER) && (!(nf->n.capa & ORTA_ABR))) if ((dest == ORT_ROUTER) && (!(nf->n.capa & ORTA_ABR)))
flush = 1; flush = 1;
if (nf->n.oa->areaid == oa->areaid) if ((!nf->n.oa) || (nf->n.oa->areaid == oa->areaid))
flush = 1; flush = 1;
/* FIXME: Test next hop - is it in actual area? */ /* FIXME: Test next hop - is it in actual area? */
if ((dest == ORT_ROUTER) && oa->stub) 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; mlen = nf->fn.pxlen;
ip = ipa_and(nf->fn.prefix, ipa_mkmask(mlen)); 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; flush = 1;
if(flush) /* FIXME Go on... */ 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 * originate_ext_lsa - new route received from nest and filters
* @n: network prefix and mask * @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->color = OUTSPF;
e->dist = LSINFINITY; e->dist = LSINFINITY;
e->nhi = NULL; e->nhi = NULL;
e->nh = ipa_from_u32(0); e->nh = IPA_NONE;
e->lb = ipa_from_u32(0); e->lb = IPA_NONE;
e->lsa.id = lsa; e->lsa.id = lsa;
e->lsa.rt = rtr; e->lsa.rt = rtr;
e->lsa.type = type; 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]; struct top_hash_entry *e = f->hash_table[i];
while (e) while (e)
{ {
OSPF_TRACE(D_EVENTS, "\t%1x %-1I %-1I %4u 0x%08x", 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.type, e->lsa.id, e->lsa.rt, e->lsa.age, e->lsa.sn, e->lsa.checksum);
e = e->next; e = e->next;
} }
} }