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