]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Implements OSPF stub router option (RFC 3137).
authorOndrej Zajicek <santiago@crfreenet.org>
Tue, 11 Jun 2013 10:12:11 +0000 (12:12 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Tue, 11 Jun 2013 10:12:11 +0000 (12:12 +0200)
Also fixes OSPFv3 routing table calculcation w.r.t.
errata 2078 to RFC 5340.

doc/bird.sgml
proto/ospf/config.Y
proto/ospf/ospf.c
proto/ospf/ospf.h
proto/ospf/rt.c
proto/ospf/topology.c

index 18f3601ba5ab0f2fd9b81c3adebe110bcff8da4f..0681bd535cf4c9e42da95ecb9baf8af9ef07f496 100644 (file)
@@ -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
index 2cc0b9634d65509881b51c5650af4dbd8c47a73e..ba050d852a18e9c06373dc3521baa3ba61e562b3 100644 (file)
@@ -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"); }
index a3b6b2e722a3d4f610cf351c94296d28af86dbda..2fa872017924d4e672819336e28c4e6b1ba0054c 100644 (file)
@@ -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);
index d924e6574a37d42cf571775ef18d26af763ce01f..7608225ff224782a4cd1c0c78e98ee653e4ee746 100644 (file)
@@ -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 */
index 4b8de4b8325c80ee4b944c646150026735e53c5a..f509b8965465711133010c5aaa0b4319a6138d1a 100644 (file)
@@ -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
index 5f4d1d5434a1d0fb22ce91683b6d7599deca7307..5d93c0e987aae344d79cc6623d8e273be8ef0ccb 100644 (file)
@@ -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++;
         }