]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
OSPF NSSA translator election.
authorOndrej Zajicek <santiago@crfreenet.org>
Fri, 22 Jul 2011 18:00:24 +0000 (20:00 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Fri, 22 Jul 2011 18:00:24 +0000 (20:00 +0200)
proto/ospf/config.Y
proto/ospf/ospf.c
proto/ospf/ospf.h
proto/ospf/rt.c
proto/ospf/topology.c

index 35060aa74b6d9c06efe29949bb6b8b7446677782..1099b729388aa825178cbd0e7c7d794f284d777c 100644 (file)
@@ -101,7 +101,7 @@ CF_KEYWORDS(NONBROADCAST, NBMA, POINTOPOINT, PTP, POINTOMULTIPOINT, PTMP)
 CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC)
 CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK)
 CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY)
-CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA)
+CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY)
 
 %type <t> opttext
 
@@ -159,6 +159,8 @@ ospf_area_item:
  | STUB bool { this_area->type = $2 ? 0 : OPT_E; /* We should remove the option */ }
  | NSSA { this_area->type = OPT_N; }
  | SUMMARY bool { this_area->summary = $2; }
+ | TRANSLATOR bool { this_area->translator = $2; }
+ | TRANSLATOR STABILITY bool { this_area->transint = $3; }
  | NETWORKS '{' pref_list '}'
  | STUBNET ospf_stubnet
  | INTERFACE ospf_iface
index 320f45774f134e76963192b01f23d6d1c733cc98..83bcad75d370a0c4df4c2ec408ce6e93f930fc2d 100644 (file)
@@ -178,6 +178,9 @@ ospf_area_remove(struct ospf_area *oa)
   fib_free(&oa->rtr);
   fib_free(&oa->net_fib);
 
+  if (oa->translator_timer)
+    rfree(oa->translator_timer);
+
   oa->po->areano--;
   rem_node(NODE oa);
   mb_free(oa);
@@ -803,6 +806,8 @@ ospf_sh(struct proto *p)
     }
     // FIXME NSSA:
     // cli_msg(-1014, "\t\tStub:\t%s", oa->stub ? "Yes" : "No");
+    cli_msg(-1014, "\t\tNSSA translation:\t%s%s", oa->translate ? "Yes" : "No",
+           oa->translate == TRANS_WAIT ? " (run down)" : "");
     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 neighbors:\t%u", nno);
index a8b4a980cf733c7c02e8cc3f5525dffb0fd985bd..68c19424dea00211b73f3849ab41d5f00915b304 100644 (file)
@@ -127,6 +127,8 @@ struct ospf_area_config
   u8 type;                     /* Area type (standard, stub, NSSA), represented
                                   by option flags (OPT_E, OPT_N) */
   u8 summary;                  /* Import summaries to this stub/NSSA area, valid for ABR */
+  u8 translator;               /* Translator role, for NSSA ABR */
+  u32 transint;                        /* Translator stability interval */
   list patt_list;
   list net_list;               /* List of aggregate networks for that area */
   list stubnet_list;           /* List of stub networks added to Router LSA */
@@ -736,10 +738,16 @@ struct ospf_area
   byte origrt;                 /* Rt lsa origination scheduled? */
   byte trcap;                  /* Transit capability? */
   byte marked;                 /* Used in OSPF reconfigure */
+  byte translate;              /* Translator state (TRANS_*), for NSSA ABR  */
+  timer *translator_timer;     /* For NSSA translator switch */
   struct proto_ospf *po;
   struct fib rtr;              /* Routing tables for routers */
 };
 
+#define TRANS_OFF      0
+#define TRANS_ON       1
+#define TRANS_WAIT     2       /* Waiting before the end of translation */
+
 struct proto_ospf
 {
   struct proto proto;
index e8d661cdf13bd4542a5cc479af7fd24db04202bc..71acd8be88137ec175dbaac39347adcc1d3b27de 100644 (file)
@@ -1000,12 +1000,26 @@ ospf_check_vlinks(struct proto_ospf *po)
   }
 }
 
+static void
+translator_timer_hook(timer *timer)
+{
+  struct ospf_area *oa = timer->data;
+  
+  if (oa->translate != TRANS_WAIT)
+    return;
+
+  oa->translate = TRANS_OFF;
+  schedule_rtcalc(oa->po);
+}
+
+
 /* Miscellaneous route processing that needs to be done by ABRs */
 static void
 ospf_rt_abr(struct proto_ospf *po)
 {
+  struct top_hash_entry *en;
   struct area_net *anet;
-  ort *nf, *default_nf;
+  ort *nf, *nf2, *default_nf;
 
   FIB_WALK(&po->rtf, nftmp)
   {
@@ -1073,6 +1087,62 @@ ospf_rt_abr(struct proto_ospf *po)
   }
 
 
+  /* RFC 3103 3.1 - type-7 translator election */
+  struct ospf_area *bb = oa->po->backbone;
+  WALK_LIST(oa, po->area_list)
+    if (oa_is_nssa(oa))
+    {
+      int translate = 1;
+
+      if (oa->ac->translator)
+       goto decided;
+
+      FIB_WALK(&oa->rtr, nftmp)
+      {
+       nf = (ort *) nftmp;
+       if (!nf->n.type || !(nf->n.options & ORTA_ABR))
+         continue;
+
+       nf2 = fib_find(&bb->rtr, &nf->fn.prefix, MAX_PREFIX_LENGTH);
+       if (!nf2 || !nf2->n.type || !(nf2->n.options & ORTA_ABR))
+         continue;
+
+       en = ospf_hash_find_rt(po->gr, oa->areaid, nf->n.rid);
+       if (!en || (en->color != INSPF))
+         continue;
+
+       struct ospf_lsa_rt *rt = en->lsa_body;
+       /* There is better candidate - Nt-bit or higher Router ID */
+       if ((rt->options & OPT_RT_NT) || (po->router_id < nf->n.rid))
+       {
+         translate = 0;
+         goto decided;
+         break;
+       }
+      }
+      FIB_WALK_END;
+
+    decided:
+      if (translate && (oa->translate != TRANS_ON))
+      {
+       if (oa->translate == TRANS_WAIT)
+         tm_stop(oa->translator_timer);
+
+       oa->translate = TRANS_ON;
+      }
+
+      if (!translate && (oa->translate == TRANS_ON))
+      {
+       if (oa->translator_timer == NULL)
+         oa->translator_timer = tm_new_set(po->proto.pool, translator_timer_hook, oa, 0, 0);
+
+       /* Schedule the end of translation */
+       tm_start(oa->translator_timer, oa->ac->transint);
+       oa->translate = TRANS_WAIT;
+      }
+    }
+
+
   /* Originate or flush ASBR summary LSAs */
   FIB_WALK(&po->backbone->rtr, nftmp)
   {
index 54bc09cb6e0950963a64d4f9076ffbb8ef4b27f7..f5f041eb254cb744c04d248c057b3a961d5d44b3 100644 (file)
@@ -222,6 +222,9 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
   if (po->areano > 1)
     rt->options |= OPT_RT_B;
 
+  if ((po->areano > 1) && oa_is_nssa(oa) && oa->ac->translator)
+    rt->options |= OPT_RT_NT;
+
   if (po->ebit && !oa_is_stub(oa))
     rt->options |= OPT_RT_E;
 
@@ -388,6 +391,9 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
   if (po->areano > 1)
     rt->options |= OPT_RT_B;
 
+  if ((po->areano > 1) && oa_is_nssa(oa) && oa->ac->translator)
+    rt->options |= OPT_RT_NT;
+
   if (po->ebit && !oa_is_stub(oa))
     rt->options |= OPT_RT_E;