summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2013-06-11 12:12:11 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2013-06-11 12:12:11 +0200
commitf623ab9875cad2d129f708e95021d3a252930000 (patch)
tree03c6bae47798d39ebe85853fb573f6c0d025c5b6
parent924868543c2010f3ef2cfcb7ba6bac5988ab3264 (diff)
Implements OSPF stub router option (RFC 3137).
Also fixes OSPFv3 routing table calculcation w.r.t. errata 2078 to RFC 5340.
-rw-r--r--doc/bird.sgml10
-rw-r--r--proto/ospf/config.Y1
-rw-r--r--proto/ospf/ospf.c7
-rw-r--r--proto/ospf/ospf.h2
-rw-r--r--proto/ospf/rt.c6
-rw-r--r--proto/ospf/topology.c8
6 files changed, 27 insertions, 7 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml
index 18f3601b..0681bd53 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -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
diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y
index 2cc0b963..ba050d85 100644
--- a/proto/ospf/config.Y
+++ b/proto/ospf/config.Y
@@ -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"); }
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index a3b6b2e7..2fa87201 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -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);
diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h
index d924e657..7608225f 100644
--- a/proto/ospf/ospf.h
+++ b/proto/ospf/ospf.h
@@ -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 */
diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c
index 4b8de4b8..f509b896 100644
--- a/proto/ospf/rt.c
+++ b/proto/ospf/rt.c
@@ -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
diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c
index 5f4d1d54..5d93c0e9 100644
--- a/proto/ospf/topology.c
+++ b/proto/ospf/topology.c
@@ -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++;
}