Origination of summary LSA works.
Routing table calculation works.
Virtual links works.
Well, I hope, OSPF is fully compatible with RFC2328!!!!
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)
# 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;
# hello 8;
# authentication none;
# };
+# interface "fr*";
+# virtual link 192.168.0.1 {
+# password "sdsdffsdfg";
+# authentication cryptographic;
+# };
# };
#}
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)
tick <num>;
area <id> {
stub cost <num>;
- tick <num>;
networks {
<prefix>;
<prefix> hidden;
virtual link <id>
{
hello <num>;
- poll <num>;
retransmit <num>;
wait <num>;
dead count <num>;
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.
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.
<code>
protocol ospf MyOSPF {
+ rfc1583compatibility yes;
+ tick 2;
export filter {
if source = RTS_BGP then {
ospf_metric1 = 100;
reject;
};
area 0.0.0.0 {
- tick 8;
interface "eth*" {
cost 11;
hello 15;
};
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;
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);
}
;
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:
;
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 ; }
| 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;
}
;
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;
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;
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);
u32 *pp;
int i, send;
struct nbma_node *nb;
-
if (timer == NULL)
ifa = dirn->ifa;
else
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;
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);
}
static void
poll_timer_hook(timer * timer)
{
+ log("POLL!");
ospf_hello_send(timer, 1, NULL);
}
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
{
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;
}
}
}
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);
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;
rem_node(NODE ifa);
mb_free(ifa);
}
- /* FIXME: Should I down related VLINK also? */
}
/**
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)
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);
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)
{
{
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;
}
}
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;
ifa->proto = po;
ifa->iface = iface;
- ifa->an = ac->areaid;
ifa->cost = ip->cost;
ifa->rxmtint = ip->rxmtint;
ifa->inftransdelay = ip->inftransdelay;
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));
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);
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);
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);
}
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;
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);
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);
{
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;
{
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)
|| ((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;
}
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;
if (ndr == NULL)
{
ifa->drid = 0;
- ifa->drip = ipa_from_u32(0);
+ ifa->drip = IPA_NONE;
}
else
{
if (nbdr == NULL)
{
ifa->bdrid = 0;
- ifa->bdrip = ipa_from_u32(0);
+ ifa->bdrip = IPA_NONE;
}
else
{
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
* 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.
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
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;
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;
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);
* 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;
/* 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);
}
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)
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);
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);
}
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)
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);
#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
node n;
u32 areaid;
int stub;
- unsigned tick;
list patt_list;
+ list vlink_list;
list net_list;
};
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 ...) */
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 */
};
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;
}
{
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)
{
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;
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);
}
#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);
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;
{
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;
struct ospf_iface *iface;
struct top_hash_entry *act, *tmp;
node *n;
+ int vlink;
if (oa->rt == NULL)
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;
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);
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");
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:
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;
}
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);
+ }
}
}
}
{
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;
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)
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 */
/* 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;
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 */
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");
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)
/* 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;
}
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++;
}
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)
ln->id = neigh->rid;
ln->metric = ifa->cost;
ln->notos = 0;
- rt->veb.bit.v = 1;
}
else
{
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;
{
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;
}
}
-
-
-
void
originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metric)
{
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;
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
{
}
}
- if(free < 0)
+ if(!free)
{
log("%s: got more routes for one /%d network then %d, ignoring", p->name,
fn->pxlen, max);
}
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);
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);
}
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;
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)
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... */
}
}
-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
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;
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;
}
}