Commit f623ab98 authored by Ondřej Zajíček's avatar Ondřej Zajíček

Implements OSPF stub router option (RFC 3137).

Also fixes OSPFv3 routing table calculcation w.r.t.
errata 2078 to RFC 5340.
parent 92486854
......@@ -1904,6 +1904,7 @@ on nonbroadcast networks.
<code>
protocol ospf &lt;name&gt; {
rfc1583compat &lt;switch&gt;;
stub router &lt;switch&gt;;
tick &lt;num&gt;;
ecmp &lt;switch&gt; [limit &lt;num&gt;];
area &lt;id&gt; {
......@@ -1983,6 +1984,15 @@ protocol ospf &lt;name&gt; {
url="ftp://ftp.rfc-editor.org/in-notes/rfc1583.txt">. Default
value is no.
<tag>stub router <M>switch</M></tag>
This option configures the router to be a stub router, i.e.,
a router that participates in the OSPF topology but does not
allow transit traffic. In OSPFv2, this is implemented by
advertising maximum metric for outgoing links, as suggested
by RFC 3137<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc3137.txt">.
In OSPFv3, the stub router behavior is announced by clearing
the R-bit in the router LSA. Default value is no.
<tag>tick <M>num</M></tag>
The routing table calculation and clean-up of areas' databases
is not performed when a single link state
......
......@@ -158,6 +158,7 @@ ospf_proto:
ospf_proto_item:
proto_item
| RFC1583COMPAT bool { OSPF_CFG->rfc1583 = $2; }
| STUB ROUTER bool { OSPF_CFG->stub_router = $3; }
| ECMP bool { OSPF_CFG->ecmp = $2 ? DEFAULT_ECMP_LIMIT : 0; }
| ECMP bool LIMIT expr { OSPF_CFG->ecmp = $2 ? $4 : 0; if ($4 < 0) cf_error("ECMP limit cannot be negative"); }
| TICK expr { OSPF_CFG->tick = $2; if($2<=0) cf_error("Tick must be greater than zero"); }
......
......@@ -167,7 +167,7 @@ ospf_area_add(struct proto_ospf *po, struct ospf_area_config *ac, int reconf)
#ifdef OSPFv2
oa->options = ac->type;
#else /* OSPFv3 */
oa->options = OPT_R | ac->type | OPT_V6;
oa->options = ac->type | OPT_V6 | (po->stub_router ? 0 : OPT_R);
#endif
/*
......@@ -234,6 +234,7 @@ ospf_start(struct proto *p)
po->router_id = proto_get_router_id(p->cf);
po->last_vlink_id = 0x80000000;
po->rfc1583 = c->rfc1583;
po->stub_router = c->stub_router;
po->ebit = 0;
po->ecmp = c->ecmp;
po->tick = c->tick;
......@@ -690,7 +691,7 @@ ospf_area_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
#ifdef OSPFv2
oa->options = nac->type;
#else /* OSPFv3 */
oa->options = OPT_R | nac->type | OPT_V6;
oa->options = nac->type | OPT_V6 | (oa->po->stub_router ? 0 : OPT_R);
#endif
if (oa_is_nssa(oa) && (oa->po->areano > 1))
oa->po->ebit = 1;
......@@ -738,6 +739,7 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
if (old->abr != new->abr)
return 0;
po->stub_router = new->stub_router;
po->ecmp = new->ecmp;
po->tick = new->tick;
po->disp_timer->recurrent = po->tick;
......@@ -831,6 +833,7 @@ ospf_sh(struct proto *p)
cli_msg(-1014, "%s:", p->name);
cli_msg(-1014, "RFC1583 compatibility: %s", (po->rfc1583 ? "enable" : "disabled"));
cli_msg(-1014, "Stub router: %s", (po->stub_router ? "Yes" : "No"));
cli_msg(-1014, "RT scheduler tick: %d", po->tick);
cli_msg(-1014, "Number of areas: %u", po->areano);
cli_msg(-1014, "Number of LSAs in DB:\t%u", po->gr->hash_entries);
......
......@@ -83,6 +83,7 @@ struct ospf_config
struct proto_config c;
unsigned tick;
byte rfc1583;
byte stub_router;
byte abr;
int ecmp;
list area_list; /* list of struct ospf_area_config */
......@@ -771,6 +772,7 @@ struct proto_ospf
int areano; /* Number of area I belong to */
struct fib rtf; /* Routing table */
byte rfc1583; /* RFC1583 compatibility */
byte stub_router; /* Do not forward transit traffic */
byte ebit; /* Did I originate any ext lsa? */
byte ecmp; /* Maximal number of nexthops in ECMP route, or 0 */
struct ospf_area *backbone; /* If exists */
......
......@@ -501,6 +501,10 @@ ospf_rt_spfa(struct ospf_area *oa)
#ifdef OSPFv2
ospf_rt_spfa_rtlinks(oa, act, act);
#else /* OSPFv3 */
/* Errata 2078 to RFC 5340 4.8.1 - skip links from non-routing nodes */
if ((act != oa->rt) && !(rt->options & OPT_R))
break;
for (tmp = ospf_hash_find_rt_first(po->gr, act->domain, act->lsa.rt);
tmp; tmp = ospf_hash_find_rt_next(tmp))
ospf_rt_spfa_rtlinks(oa, act, tmp);
......@@ -1839,7 +1843,7 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
if (en->lsa.type == LSA_T_RT)
{
struct ospf_lsa_rt *rt = en->lsa_body;
if (!(rt->options & OPT_V6) || !(rt->options & OPT_R))
if (!(rt->options & OPT_V6))
return;
}
#endif
......
......@@ -233,6 +233,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
WALK_LIST(ifa, po->iface_list)
{
int net_lsa = 0;
u32 link_cost = po->stub_router ? 0xffff : ifa->cost;
if ((ifa->type == OSPF_IT_VLINK) && (ifa->voa == oa) &&
(!EMPTY_LIST(ifa->neigh_list)))
......@@ -268,8 +269,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
* this address as a next-hop.
*/
ln->data = ipa_to_u32(ifa->addr->ip);
ln->metric = ifa->cost;
ln->metric = link_cost;
ln->padding = 0;
i++;
}
......@@ -283,7 +283,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
ln->type = LSART_NET;
ln->id = ipa_to_u32(ifa->drip);
ln->data = ipa_to_u32(ifa->addr->ip);
ln->metric = ifa->cost;
ln->metric = link_cost;
ln->padding = 0;
i++;
net_lsa = 1;
......@@ -298,7 +298,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
ln->type = LSART_VLNK;
ln->id = neigh->rid;
ln->data = ipa_to_u32(ifa->addr->ip);
ln->metric = ifa->cost;
ln->metric = link_cost;
ln->padding = 0;
i++;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment