]> git.puffer.fish Git - mirror/frr.git/commitdiff
2005-10-29 Paul Jakma <paul.jakma@sun.com>
authorpaul <paul>
Sat, 29 Oct 2005 12:50:09 +0000 (12:50 +0000)
committerpaul <paul>
Sat, 29 Oct 2005 12:50:09 +0000 (12:50 +0000)
* (general) RFC3137 stub-router support
* ospfd.h: Add OSPF_OUTPUT_COST_INFINITE define.
  (struct ospf_master) Add a OSPF_MASTER_SHUTDOWN flag for
  options, to allow shutdown to distinguish between complete
  shutdown and shutdown of a subset of ospf instances.
  (struct ospf)
  Add stub_router_{startup,shutdown_}time, configuration of startup
  and shutdown time for stub-router.
  Add t_graceful_shutdown struct thread, timer for graceful
  shutdown, if needed.
  (struct ospf_area) Add stub_router_state - run time state of
  stub-router for an area. Add flags for ADMIN, IS and WAS
  states.
  Add t_stub_router, timer thread to resend router-lsa for an
  area.
* ospf_lsa.c: (ospf_link_cost) new simple function to spit out
  either the given lnks cost or infinite cost if stub-router is
  in effect.
  (lsa_link_{ptop,broadcast,virtuallink,ptomp}_set) use
  previous function for transit-links.
  (ospf_stub_router_timer) timer thread for end of startup stub
  router. Change state as required for the area and setup
  re-origination of router-lsa.
  (ospf_stub_router_check) Check/do whether stub-router should be
  enabled, and whether it requires timer to be setup.
  (ospf_router_lsa_new) call previous function at top.
  (ospf_router_lsa_originate) no external callers, made static.
* ospf_lsa.h: (ospf_router_lsa_originate) removed.
* ospf_main.c: (sigint) make static.
  remove call to exit, as ospf_terminate now deals with
  exiting.
* ospf_route.c: (ospf_terminate) removed, now in ospfd.c.
* ospf_vty.c: (show_ip_ospf_area) print out state of
  stub-router, if active.
  (show_ip_ospf) print out configuration of stub-router
  support, and details of graceful-shutdown if the timer is
  active.
  ((no)?ospf_max_metric_router_lsa_{admin,startup,shutdown}) new
  commands to (de-)?configure stub-router support.
  (config_write_stub_router) write out config of stub-router.
  (ospf_config_write) call previous.
  (ospf_vty_init) install the new stub-router commands.
* ospfd.c: various functions made static.
  (ospf_new) Set defaults for stub-router. Graceful shutdown
  is made to default on, just to be adventerous.
  (ospf_graceful_shutdown_finish) new function, final part of
  shutdown.
  (ospf_graceful_shutdown_timer) timer thread wrapper for
  graceful-shutdown.
  (ospf_graceful_shutdown_check) check whether to setup timer
  for shutdown or proceed directly to final shutdown.
  (ospf_terminate) moved here from ospf_route.c, call
  ospf_finish for each instance.
  (ospf_finish) renamed to ospf_finish_final and made static.
  (ospf_finish) new function, exported wrapper around
  ospf_graceful_shutdown_check.
  (ospf_finish_final) complete shutdown of an instance.
  Add missing TIMER_OFF's of two timer threads.
  (ospf_area_free) opaque self lsa timer should be turned off.

ospfd/ChangeLog
ospfd/ospf_lsa.c
ospfd/ospf_lsa.h
ospfd/ospf_main.c
ospfd/ospf_route.c
ospfd/ospf_vty.c
ospfd/ospfd.c
ospfd/ospfd.h

index 72412d74c2d5e355a8cd452662ee843611003d2b..fc0d599390298b5db1c6fcd56249b67c2c529112 100644 (file)
@@ -1,3 +1,65 @@
+2005-10-29 Paul Jakma <paul.jakma@sun.com>
+
+       * (general) RFC3137 stub-router support
+       * ospfd.h: Add OSPF_OUTPUT_COST_INFINITE define.
+         (struct ospf_master) Add a OSPF_MASTER_SHUTDOWN flag for
+         options, to allow shutdown to distinguish between complete
+         shutdown and shutdown of a subset of ospf instances.
+         (struct ospf)
+         Add stub_router_{startup,shutdown_}time, configuration of startup
+         and shutdown time for stub-router.
+         Add t_graceful_shutdown struct thread, timer for graceful
+         shutdown, if needed.
+         (struct ospf_area) Add stub_router_state - run time state of
+         stub-router for an area. Add flags for ADMIN, IS and WAS
+         states.
+         Add t_stub_router, timer thread to resend router-lsa for an
+         area.
+       * ospf_lsa.c: (ospf_link_cost) new simple function to spit out
+         either the given lnks cost or infinite cost if stub-router is
+         in effect.
+         (lsa_link_{ptop,broadcast,virtuallink,ptomp}_set) use
+         previous function for transit-links.
+         (ospf_stub_router_timer) timer thread for end of startup stub
+         router. Change state as required for the area and setup
+         re-origination of router-lsa.
+         (ospf_stub_router_check) Check/do whether stub-router should be
+         enabled, and whether it requires timer to be setup.
+         (ospf_router_lsa_new) call previous function at top.
+         (ospf_router_lsa_originate) no external callers, made static.
+       * ospf_lsa.h: (ospf_router_lsa_originate) removed.
+       * ospf_main.c: (sigint) make static.
+         remove call to exit, as ospf_terminate now deals with
+         exiting.
+       * ospf_route.c: (ospf_terminate) removed, now in ospfd.c.
+       * ospf_vty.c: (show_ip_ospf_area) print out state of
+         stub-router, if active.
+         (show_ip_ospf) print out configuration of stub-router
+         support, and details of graceful-shutdown if the timer is
+         active.
+         ((no)?ospf_max_metric_router_lsa_{admin,startup,shutdown}) new
+         commands to (de-)?configure stub-router support.
+         (config_write_stub_router) write out config of stub-router.
+         (ospf_config_write) call previous.
+         (ospf_vty_init) install the new stub-router commands.
+       * ospfd.c: various functions made static.
+         (ospf_new) Set defaults for stub-router. Graceful shutdown
+         is made to default on, just to be adventerous.
+         (ospf_graceful_shutdown_finish) new function, final part of
+         shutdown.
+         (ospf_graceful_shutdown_timer) timer thread wrapper for
+         graceful-shutdown.
+         (ospf_graceful_shutdown_check) check whether to setup timer
+         for shutdown or proceed directly to final shutdown.
+         (ospf_terminate) moved here from ospf_route.c, call
+         ospf_finish for each instance.
+         (ospf_finish) renamed to ospf_finish_final and made static.
+         (ospf_finish) new function, exported wrapper around
+         ospf_graceful_shutdown_check.
+         (ospf_finish_final) complete shutdown of an instance.
+         Add missing TIMER_OFF's of two timer threads.
+         (ospf_area_free) opaque self lsa timer should be turned off.
+
 2005-10-23 Paul Jakma <paul.jakma@sun.com>
 
        * ospf_apiserver.c: (ospf_apiserver_term) This function should
index a85667e6b08951596556d91fae7a1b80b7ac9985..31b9a4f19846a6e73464e920625164ad909ccf57 100644 (file)
@@ -483,6 +483,19 @@ ospf_nbr_lookup_ptop (struct ospf_interface *oi)
   return nbr;
 }
 
+/* Determine cost of link, taking RFC3137 stub-router support into
+ * consideration
+ */
+static u_int16_t
+ospf_link_cost (struct ospf_interface *oi)
+{
+  /* RFC3137 stub router support */
+  if (!CHECK_FLAG (oi->area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
+    return oi->output_cost;
+  else
+    return OSPF_OUTPUT_COST_INFINITE;
+}
+
 /* Set a link information. */
 static void
 link_info_set (struct stream *s, struct in_addr id,
@@ -503,6 +516,7 @@ lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi)
   int links = 0;
   struct ospf_neighbor *nbr;
   struct in_addr id, mask;
+  u_int16_t cost = ospf_link_cost (oi);
 
   if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
     zlog_debug ("LSA[Type1]: Set link Point-to-Point");
@@ -513,7 +527,7 @@ lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi)
        /* For unnumbered point-to-point networks, the Link Data field
           should specify the interface's MIB-II ifIndex value. */
        link_info_set (s, nbr->router_id, oi->address->u.prefix4,
-                      LSA_LINK_TYPE_POINTOPOINT, 0, oi->output_cost);
+                      LSA_LINK_TYPE_POINTOPOINT, 0, cost);
        links++;
       }
 
@@ -548,7 +562,8 @@ lsa_link_broadcast_set (struct stream *s, struct ospf_interface *oi)
 {
   struct ospf_neighbor *dr;
   struct in_addr id, mask;
-
+  u_int16_t cost = ospf_link_cost (oi);
+  
   /* Describe Type 3 Link. */
   if (oi->state == ISM_Waiting)
     {
@@ -565,7 +580,7 @@ lsa_link_broadcast_set (struct stream *s, struct ospf_interface *oi)
       ospf_nbr_count (oi, NSM_Full) > 0)
     {
       link_info_set (s, DR (oi), oi->address->u.prefix4,
-                    LSA_LINK_TYPE_TRANSIT, 0, oi->output_cost);
+                    LSA_LINK_TYPE_TRANSIT, 0, cost);
     }
   /* Describe type 3 link. */
   else
@@ -581,7 +596,7 @@ static int
 lsa_link_loopback_set (struct stream *s, struct ospf_interface *oi)
 {
   struct in_addr id, mask;
-
+  
   /* Describe Type 3 Link. */
   if (oi->state != ISM_Loopback)
     return 0;
@@ -597,13 +612,14 @@ static int
 lsa_link_virtuallink_set (struct stream *s, struct ospf_interface *oi)
 {
   struct ospf_neighbor *nbr;
+  u_int16_t cost = ospf_link_cost (oi);
 
   if (oi->state == ISM_PointToPoint)
     if ((nbr = ospf_nbr_lookup_ptop (oi)))
       if (nbr->state == NSM_Full)
        {
          link_info_set (s, nbr->router_id, oi->address->u.prefix4,
-                        LSA_LINK_TYPE_VIRTUALLINK, 0, oi->output_cost);
+                        LSA_LINK_TYPE_VIRTUALLINK, 0, cost);
          return 1;
        }
 
@@ -623,6 +639,7 @@ lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi)
   struct route_node *rn;
   struct ospf_neighbor *nbr = NULL;
   struct in_addr id, mask;
+  u_int16_t cost = ospf_link_cost (oi);
 
   mask.s_addr = 0xffffffff;
   id.s_addr = oi->address->u.prefix4.s_addr;
@@ -641,7 +658,7 @@ lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi)
 
          {
            link_info_set (s, nbr->router_id, oi->address->u.prefix4,
-                          LSA_LINK_TYPE_POINTOPOINT, 0, oi->output_cost);
+                          LSA_LINK_TYPE_POINTOPOINT, 0, cost);
            links++;
             if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
              zlog_debug ("PointToMultipoint: set link to %s",
@@ -721,7 +738,64 @@ ospf_router_lsa_body_set (struct stream *s, struct ospf_area *area)
   /* Set # of links here. */
   stream_putw_at (s, putp, cnt);
 }
+\f
+static int
+ospf_stub_router_timer (struct thread *t)
+{
+  struct ospf_area *area = THREAD_ARG (t);
+  
+  area->t_stub_router = NULL;
+  
+  SET_FLAG (area->stub_router_state, OSPF_AREA_WAS_START_STUB_ROUTED);
+  
+  /* clear stub route state and generate router-lsa refresh, don't
+   * clobber an administratively set stub-router state though.
+   */
+  if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED))
+    return 0;
+  
+  UNSET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED);
+  
+  ospf_router_lsa_timer_add (area);
+  
+  return 0;
+}
 
+inline static void
+ospf_stub_router_check (struct ospf_area *area)
+{
+  /* area must either be administratively configured to be stub
+   * or startup-time stub-router must be configured and we must in a pre-stub
+   * state.
+   */
+  if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED))
+    {
+      SET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED);
+      return;
+    }
+  
+  /* not admin-stubbed, check whether startup stubbing is configured and
+   * whether it's not been done yet
+   */
+  if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_WAS_START_STUB_ROUTED))
+    return;
+  
+  if (area->ospf->stub_router_startup_time == OSPF_STUB_ROUTER_UNCONFIGURED)
+    {
+      /* stub-router is hence done forever for this area, even if someone
+       * tries configure it (take effect next restart).
+       */
+      SET_FLAG (area->stub_router_state, OSPF_AREA_WAS_START_STUB_ROUTED);
+      return;
+    }
+  
+  /* startup stub-router configured and not yet done */
+  SET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED);
+  
+  OSPF_AREA_TIMER_ON (area->t_stub_router, ospf_stub_router_timer,
+                      area->ospf->stub_router_startup_time);
+}
+\f 
 /* Create new router-LSA. */
 static struct ospf_lsa *
 ospf_router_lsa_new (struct ospf_area *area)
@@ -735,6 +809,11 @@ ospf_router_lsa_new (struct ospf_area *area)
   if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
     zlog_debug ("LSA[Type1]: Create router-LSA instance");
 
+  /* check whether stub-router is desired, and if this is the first 
+   * router LSA.
+   */
+  ospf_stub_router_check (area);
+  
   /* Create a stream for LSA. */
   s = stream_new (OSPF_MAX_LSA_SIZE);
   lsah = (struct lsa_header *) STREAM_DATA (s);
@@ -764,11 +843,11 @@ ospf_router_lsa_new (struct ospf_area *area)
 }
 
 /* Originate Router-LSA. */
-struct ospf_lsa *
+static struct ospf_lsa *
 ospf_router_lsa_originate (struct ospf_area *area)
 {
   struct ospf_lsa *new;
-
+  
   /* Create new router-LSA instance. */
   new = ospf_router_lsa_new (area);
 
index 5cf69c31a8eac630579f70b2c14dc1432407b863..42c08828335c580505b87d99658c07d8e8898c26 100644 (file)
@@ -252,7 +252,6 @@ extern struct lsa_header *ospf_lsa_data_dup (struct lsa_header *);
 extern void ospf_lsa_data_free (struct lsa_header *);
 
 /* Prototype for various LSAs */
-extern struct ospf_lsa *ospf_router_lsa_originate (struct ospf_area *);
 extern int ospf_router_lsa_update_timer (struct thread *);
 extern void ospf_router_lsa_timer_add (struct ospf_area *);
 
index 483b638785981ac8492736495b064c90a39d74f0..3225d7d77313d524ad14f82a88bd51c171e17b57 100644 (file)
@@ -136,15 +136,12 @@ sighup (void)
   zlog (NULL, LOG_INFO, "SIGHUP received");
 }
 
-/* SIGINT handler. */
-static void __attribute__ ((noreturn))
+/* SIGINT / SIGTERM handler. */
+static void
 sigint (void)
 {
   zlog_notice ("Terminating on signal");
-
   ospf_terminate ();
-
-  exit (0);
 }
 
 /* SIGUSR1 handler. */
index bdbdd03ea8184430ec98a7a1489d5fc42fc29bb2..5eedbd82e5cfb7605a18943fe2c99be366a637d2 100644 (file)
@@ -690,21 +690,6 @@ ospf_route_table_dump (struct route_table *rt)
   zlog_debug ("========================================");
 }
 
-void
-ospf_terminate ()
-{
-  struct ospf *ospf;
-  struct listnode *node, *nnode;
-
-  for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
-    {
-      if (ospf->new_table)
-       ospf_route_delete (ospf->new_table);
-      if (ospf->old_external_route)
-       ospf_route_delete (ospf->old_external_route);
-    }
-}
-
 /* This is 16.4.1 implementation.
    o Intra-area paths using non-backbone areas are always the most preferred.
    o The other paths, intra-area backbone paths and inter-area paths,
index e56027be5a07841a0b2e7a4d0959c1c58e7ab40c..c3cc4cb4db835ecbba649ad198a769d548837438 100644 (file)
@@ -2517,7 +2517,21 @@ show_ip_ospf_area (struct vty *vty, struct ospf_area *area)
                     VTY_NEWLINE);
           }
     }
-
+  /* Stub-router state for this area */
+  if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
+    {
+      char timebuf[9];
+      vty_out (vty, "   Originating stub / maximum-distance Router-LSA%s",
+               VTY_NEWLINE);
+      if (CHECK_FLAG(area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED))
+        vty_out (vty, "     Administratively activated (indefinitely)%s",
+                 VTY_NEWLINE);
+      if (area->t_stub_router)
+        vty_out (vty, "     Active from startup, %s remaining%s",
+                 ospf_timer_dump (area->t_stub_router, timebuf, 
+                                  sizeof(timebuf)), VTY_NEWLINE);
+    }
+  
   /* Show number of fully adjacent neighbors. */
   vty_out (vty, "   Number of fully adjacent neighbors in this area:"
                 " %d%s", area->full_nbrs, VTY_NEWLINE);
@@ -2592,7 +2606,12 @@ DEFUN (show_ip_ospf,
   vty_out (vty, " OSPF Routing Process, Router ID: %s%s",
            inet_ntoa (ospf->router_id),
            VTY_NEWLINE);
-
+  
+  /* Graceful shutdown */
+  if (ospf->t_graceful_shutdown)
+    vty_out (vty, " Graceful shutdown in progress, %s remaining%s",
+             ospf_timer_dump (ospf->t_graceful_shutdown,
+                              timebuf, sizeof (timebuf)), VTY_NEWLINE);
   /* Show capability. */
   vty_out (vty, " Supports only single TOS (TOS0) routes%s", VTY_NEWLINE);
   vty_out (vty, " This implementation conforms to RFC2328%s", VTY_NEWLINE);
@@ -2607,7 +2626,21 @@ DEFUN (show_ip_ospf,
            " (origination blocked)" : "",
            VTY_NEWLINE);
 #endif /* HAVE_OPAQUE_LSA */
-
+  
+  /* Show stub-router configuration */
+  if (ospf->stub_router_startup_time != OSPF_STUB_ROUTER_UNCONFIGURED
+      || ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
+    {
+      vty_out (vty, " Stub router advertisement is configured%s",
+               VTY_NEWLINE);
+      if (ospf->stub_router_startup_time != OSPF_STUB_ROUTER_UNCONFIGURED)
+        vty_out (vty, "   Enabled for %us after start-up%s",
+                 ospf->stub_router_startup_time, VTY_NEWLINE);
+      if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
+        vty_out (vty, "   Enabled for %us prior to full shutdown%s",
+                 ospf->stub_router_shutdown_time, VTY_NEWLINE);
+    }
+  
   /* Show SPF timers. */
   vty_out (vty, " Initial SPF scheduling delay %d millisec(s)%s"
                 " Minimum hold time between consecutive SPFs %d millisec(s)%s"
@@ -6771,7 +6804,171 @@ ALIAS (no_ip_ospf_mtu_ignore,
       "IP Information\n"
       "OSPF interface commands\n"
       "Disable mtu mismatch detection\n")
+\f
+DEFUN (ospf_max_metric_router_lsa_admin,
+       ospf_max_metric_router_lsa_admin_cmd,
+       "max-metric router-lsa administrative",
+       "OSPF maximum / infinite-distance metric\n"
+       "Advertise own Router-LSA with infinite distance (stub router)\n"
+       "Administratively applied, for an indefinite period\n")
+{
+  struct listnode *ln;
+  struct ospf_area *area;
+  struct ospf *ospf = vty->index;
     
+  for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
+    {
+      SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
+      
+      if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
+          ospf_router_lsa_timer_add (area);
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf_max_metric_router_lsa_admin,
+       no_ospf_max_metric_router_lsa_admin_cmd,
+       "no max-metric router-lsa administrative",
+       NO_STR
+       "OSPF maximum / infinite-distance metric\n"
+       "Advertise own Router-LSA with infinite distance (stub router)\n"
+       "Administratively applied, for an indefinite period\n")
+{
+  struct listnode *ln;
+  struct ospf_area *area;
+  struct ospf *ospf = vty->index;
+    
+  for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
+    {
+      UNSET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
+      
+      /* Don't trample on the start-up stub timer */
+      if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED)
+          && !area->t_stub_router)
+        {
+          UNSET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED);
+          ospf_router_lsa_timer_add (area);
+        }
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_max_metric_router_lsa_startup,
+       ospf_max_metric_router_lsa_startup_cmd,
+       "max-metric router-lsa on-startup <5-86400>",
+       "OSPF maximum / infinite-distance metric\n"
+       "Advertise own Router-LSA with infinite distance (stub router)\n"
+       "Automatically advertise stub Router-LSA on startup of OSPF\n"
+       "Time (seconds) to advertise self as stub-router\n")
+{
+  unsigned int seconds;
+  struct ospf *ospf = vty->index;
+    
+  if (argc != 1)
+    {
+      vty_out (vty, "%% Must supply stub-router period");
+      return CMD_WARNING;
+    }
+  
+  VTY_GET_INTEGER ("stub-router startup period", seconds, argv[0]);
+  
+  ospf->stub_router_startup_time = seconds;
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf_max_metric_router_lsa_startup,
+       no_ospf_max_metric_router_lsa_startup_cmd,
+       "no max-metric router-lsa on-startup",
+       NO_STR
+       "OSPF maximum / infinite-distance metric\n"
+       "Advertise own Router-LSA with infinite distance (stub router)\n"
+       "Automatically advertise stub Router-LSA on startup of OSPF\n")
+{
+  struct listnode *ln;
+  struct ospf_area *area;
+  struct ospf *ospf = vty->index;
+  
+  ospf->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED;
+  
+  for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
+    {
+      SET_FLAG (area->stub_router_state, OSPF_AREA_WAS_START_STUB_ROUTED);
+      OSPF_TIMER_OFF (area->t_stub_router);
+      
+      /* Don't trample on admin stub routed */
+      if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED))
+        {
+          UNSET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED);
+          ospf_router_lsa_timer_add (area);
+        }
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_max_metric_router_lsa_shutdown,
+       ospf_max_metric_router_lsa_shutdown_cmd,
+       "max-metric router-lsa on-shutdown <5-86400>",
+       "OSPF maximum / infinite-distance metric\n"
+       "Advertise own Router-LSA with infinite distance (stub router)\n"
+       "Advertise stub-router prior to full shutdown of OSPF\n"
+       "Time (seconds) to wait till full shutdown\n")
+{
+  unsigned int seconds;
+  struct ospf *ospf = vty->index;
+    
+  if (argc != 1)
+    {
+      vty_out (vty, "%% Must supply stub-router shutdown period");
+      return CMD_WARNING;
+    }
+  
+  VTY_GET_INTEGER ("stub-router shutdown wait period", seconds, argv[0]);
+  
+  ospf->stub_router_shutdown_time = seconds;
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf_max_metric_router_lsa_shutdown,
+       no_ospf_max_metric_router_lsa_shutdown_cmd,
+       "no max-metric router-lsa on-shutdown",
+       NO_STR
+       "OSPF maximum / infinite-distance metric\n"
+       "Advertise own Router-LSA with infinite distance (stub router)\n"
+       "Advertise stub-router prior to full shutdown of OSPF\n")
+{
+  struct ospf *ospf = vty->index;
+    
+  ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
+  
+  return CMD_SUCCESS;
+}
+
+static void
+config_write_stub_router (struct vty *vty, struct ospf *ospf)
+{
+  struct listnode *ln;
+  struct ospf_area *area;
+  
+  if (ospf->stub_router_startup_time != OSPF_STUB_ROUTER_UNCONFIGURED)
+    vty_out (vty, " max-metric router-lsa on-startup %u%s",
+             ospf->stub_router_startup_time, VTY_NEWLINE);
+  if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
+    vty_out (vty, " max-metric router-lsa on-shutdown %u%s",
+             ospf->stub_router_shutdown_time, VTY_NEWLINE);
+  for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
+    {
+      if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED))
+        {
+          vty_out (vty, " max-metric router-lsa administrative%s",
+                   VTY_NEWLINE);
+          break;
+        }
+    }
+  return;
+}
+\f
 static void
 show_ip_ospf_route_network (struct vty *vty, struct route_table *rt)
 {
@@ -7612,9 +7809,12 @@ ospf_config_write (struct vty *vty)
          ospf->spf_holdtime != OSPF_SPF_HOLDTIME_DEFAULT ||
          ospf->spf_max_holdtime != OSPF_SPF_MAX_HOLDTIME_DEFAULT)
        vty_out (vty, " timers throttle spf %d %d %d%s",
-                ospf->spf_delay, ospf->spf_holdtime, 
+                ospf->spf_delay, ospf->spf_holdtime,
                 ospf->spf_max_holdtime, VTY_NEWLINE);
-
+      
+      /* Max-metric router-lsa print */
+      config_write_stub_router (vty, ospf);
+      
       /* SPF refresh parameters print. */
       if (ospf->lsa_refresh_interval != OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
        vty_out (vty, " refresh timer %d%s",
@@ -8052,16 +8252,27 @@ ospf_vty_init (void)
 
   install_element (OSPF_NODE, &ospf_area_import_list_cmd);
   install_element (OSPF_NODE, &no_ospf_area_import_list_cmd);
-
+  
+  /* SPF timer commands */
   install_element (OSPF_NODE, &ospf_timers_spf_cmd);
   install_element (OSPF_NODE, &no_ospf_timers_spf_cmd);
   install_element (OSPF_NODE, &ospf_timers_throttle_spf_cmd);
   install_element (OSPF_NODE, &no_ospf_timers_throttle_spf_cmd);
   
+  /* refresh timer commands */
   install_element (OSPF_NODE, &ospf_refresh_timer_cmd);
   install_element (OSPF_NODE, &no_ospf_refresh_timer_val_cmd);
   install_element (OSPF_NODE, &no_ospf_refresh_timer_cmd);
   
+  /* max-metric commands */
+  install_element (OSPF_NODE, &ospf_max_metric_router_lsa_admin_cmd);
+  install_element (OSPF_NODE, &no_ospf_max_metric_router_lsa_admin_cmd);
+  install_element (OSPF_NODE, &ospf_max_metric_router_lsa_startup_cmd);
+  install_element (OSPF_NODE, &no_ospf_max_metric_router_lsa_startup_cmd);
+  install_element (OSPF_NODE, &ospf_max_metric_router_lsa_shutdown_cmd);
+  install_element (OSPF_NODE, &no_ospf_max_metric_router_lsa_shutdown_cmd);
+  
+  /* reference bandwidth commands */
   install_element (OSPF_NODE, &ospf_auto_cost_reference_bandwidth_cmd);
   install_element (OSPF_NODE, &no_ospf_auto_cost_reference_bandwidth_cmd);
 
index bf8ca4dcb046125f94379b03b6676b26122b1a6a..69f091d738ecdb26766ac6f40c0ef654a94c6a79 100644 (file)
@@ -64,13 +64,14 @@ extern struct zclient *zclient;
 extern struct in_addr router_id_zebra;
 
 \f
-void ospf_remove_vls_through_area (struct ospf *, struct ospf_area *);
-void ospf_network_free (struct ospf *, struct ospf_network *);
-void ospf_area_free (struct ospf_area *);
-void ospf_network_run (struct ospf *, struct prefix *, struct ospf_area *);
+static void ospf_remove_vls_through_area (struct ospf *, struct ospf_area *);
+static void ospf_network_free (struct ospf *, struct ospf_network *);
+static void ospf_area_free (struct ospf_area *);
+static void ospf_network_run (struct ospf *, struct prefix *, struct ospf_area *);
+static void ospf_finish_final (struct ospf *);
 
 #define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
-
+\f
 void
 ospf_router_id_update (struct ospf *ospf)
 {
@@ -172,7 +173,10 @@ ospf_new (void)
   new->new_external_route = route_table_init ();
   new->old_external_route = route_table_init ();
   new->external_lsas = route_table_init ();
-
+  
+  new->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED;
+  new->stub_router_shutdown_time = OSPF_STUB_ROUTER_SHUTDOWN_DEFAULT;
+  
   /* Distribute parameter init. */
   for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
     {
@@ -263,9 +267,116 @@ ospf_get ()
 
   return ospf;
 }
+\f
+/* Handle the second half of graceful shutdown. This is called either
+ * from the graceful-shutdown timer thread, or directly through
+ * ospf_graceful_shutdown_check.
+ *
+ * Function is to cleanup G-R state, if required then call ospf_finish_final
+ * to complete shutdown of this ospf instance. Possibly exit if the
+ * whole process is being shutdown and this was the last OSPF instance.
+ */
+static void
+ospf_graceful_shutdown_finish (struct ospf *ospf)
+{
+  ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;  
+  OSPF_TIMER_OFF (ospf->t_graceful_shutdown);
+  
+  ospf_finish_final (ospf);
+  
+  /* *ospf is now invalid */
+  
+  /* ospfd being shut-down? If so, was this the last ospf instance? */
+  if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)
+      && (listcount (om->ospf) == 0))
+    exit (0);
+
+  return;
+}
+
+/* Timer thread for G-R */
+static int
+ospf_graceful_shutdown_timer (struct thread *t)
+{
+  struct ospf *ospf = THREAD_ARG(t);
+  
+  ospf_graceful_shutdown_finish (ospf);
+  
+  return 0;
+}
+
+/* Check whether graceful-shutdown must be scheduled, otherwise call
+ * down directly into second-half of instance shutdown.
+ */
+static void
+ospf_graceful_shutdown_check (struct ospf *ospf)
+{
+  unsigned long timeout;
+  struct listnode *ln;
+  struct ospf_area *area;
+  
+  /* graceful shutdown already running? */
+  if (ospf->t_graceful_shutdown)
+    return;
+  
+  /* Should we try push out max-metric LSAs? */
+  if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
+    {
+      for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
+        {
+          SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
+          
+          if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
+              ospf_router_lsa_timer_add (area);
+        }
+      timeout = ospf->stub_router_shutdown_time;
+    }
+  else
+    /* No timer needed */
+    return ospf_graceful_shutdown_finish (ospf);
+  
+  OSPF_TIMER_ON (ospf->t_graceful_shutdown, ospf_graceful_shutdown_timer,
+                 timeout);
+  return;
+}
+\f
+/* Shut down the entire process */
+void
+ospf_terminate (void)
+{
+  struct ospf *ospf;
+  struct listnode *node, *nnode;
+  
+  /* shutdown already in progress */
+  if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN))
+    return;
+  
+  SET_FLAG (om->options, OSPF_MASTER_SHUTDOWN);
+
+  for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
+    ospf_finish (ospf);
+
+  /* Deliberately go back up, hopefully to thread scheduler, as
+   * One or more ospf_finish()'s may have deferred shutdown to a timer
+   * thread
+   */
+}
 
 void
 ospf_finish (struct ospf *ospf)
+{
+  /* let graceful shutdown decide */
+  return ospf_graceful_shutdown_check (ospf);
+      
+  /* if ospf_graceful_shutdown returns, then ospf_finish_final is
+   * deferred to expiry of G-S timer thread. Return back up, hopefully
+   * to thread scheduler.
+   */
+}
+
+/* Final cleanup of ospf instance */
+static void
+ospf_finish_final (struct ospf *ospf)
 {
   struct route_node *rn;
   struct ospf_nbr_nbma *nbr_nbma;
@@ -279,8 +390,11 @@ ospf_finish (struct ospf *ospf)
 #ifdef HAVE_OPAQUE_LSA
   ospf_opaque_type11_lsa_term (ospf);
 #endif /* HAVE_OPAQUE_LSA */
-
-  /* Unredister redistribution */
+  
+  /* be nice if this worked, but it doesn't */
+  /*ospf_flush_self_originated_lsas_now (ospf);*/
+  
+  /* Unregister redistribution */
   for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
     ospf_redistribute_unset (ospf, i);
 
@@ -347,10 +461,12 @@ ospf_finish (struct ospf *ospf)
   OSPF_TIMER_OFF (ospf->t_maxage);
   OSPF_TIMER_OFF (ospf->t_maxage_walker);
   OSPF_TIMER_OFF (ospf->t_abr_task);
+  OSPF_TIMER_OFF (ospf->t_asbr_check);
   OSPF_TIMER_OFF (ospf->t_distribute_update);
   OSPF_TIMER_OFF (ospf->t_lsa_refresher);
   OSPF_TIMER_OFF (ospf->t_read);
   OSPF_TIMER_OFF (ospf->t_write);
+  OSPF_TIMER_OFF (ospf->t_opaque_lsa_self);
 
   close (ospf->fd);
   stream_free(ospf->ibuf);
@@ -435,7 +551,7 @@ ospf_area_new (struct ospf *ospf, struct in_addr area_id)
   new->external_routing = OSPF_AREA_DEFAULT;
   new->default_cost = 1;
   new->auth_type = OSPF_AUTH_NULL;
-
+  
   /* New LSDB init. */
   new->lsdb = ospf_lsdb_new ();
 
@@ -496,7 +612,11 @@ ospf_area_free (struct ospf_area *area)
 
   /* Cancel timer. */
   OSPF_TIMER_OFF (area->t_router_lsa_self);
-
+  OSPF_TIMER_OFF (area->t_stub_router);
+#ifdef HAVE_OPAQUE_LSA
+  OSPF_TIMER_OFF (area->t_opaque_lsa_self);
+#endif /* HAVE_OPAQUE_LSA */
+  
   if (OSPF_IS_AREA_BACKBONE (area))
     area->ospf->backbone = NULL;
 
index 38e56b6f5630632c2b150c600a6f7fa224cb5b9b..ed66ebf7ec5111a79eb18a306d7ee0a2e0fb5b80 100644 (file)
@@ -94,6 +94,7 @@
 
 /* OSPF interface default values. */
 #define OSPF_OUTPUT_COST_DEFAULT           10
+#define OSPF_OUTPUT_COST_INFINITE         UINT16_MAX
 #define OSPF_ROUTER_DEAD_INTERVAL_DEFAULT  40
 #define OSPF_ROUTER_DEAD_INTERVAL_MINIMAL   1
 #define OSPF_HELLO_INTERVAL_DEFAULT        10
@@ -152,6 +153,7 @@ struct ospf_master
 
   /* Various OSPF global configuration. */
   u_char options;
+#define OSPF_MASTER_SHUTDOWN (1 << 0) /* flag for ospf_finish / graceful-shutdown */  
 };
 
 /* OSPF instance structure. */
@@ -192,10 +194,18 @@ struct ospf
 #define OPAQUE_BLOCK_TYPE_11_LSA_BIT   (1 << 3)
 #endif /* HAVE_OPAQUE_LSA */
 
-  unsigned int spf_delay;                      /* SPF delay time. */
-  unsigned int spf_holdtime;                   /* SPF hold time. */
-  unsigned int spf_max_holdtime;                       /* SPF maximum-holdtime */
-  unsigned int spf_hold_multiplier;            /* Adaptive multiplier for hold time */
+  /* RFC3137 stub router. Configured time to stay stub / max-metric */
+  unsigned int stub_router_startup_time;       /* seconds */
+  unsigned int stub_router_shutdown_time;      /* seconds */
+#define OSPF_STUB_ROUTER_UNCONFIGURED    0
+#define OSPF_STUB_ROUTER_SHUTDOWN_DEFAULT 2
+
+  /* SPF parameters */
+  unsigned int spf_delay;              /* SPF delay time. */
+  unsigned int spf_holdtime;           /* SPF hold time. */
+  unsigned int spf_max_holdtime;       /* SPF maximum-holdtime */
+  unsigned int spf_hold_multiplier;    /* Adaptive multiplier for hold time */
+  
   int default_originate;               /* Default information originate. */
 #define DEFAULT_ORIGINATE_NONE         0
 #define DEFAULT_ORIGINATE_ZEBRA                1
@@ -253,6 +263,7 @@ struct ospf
 #endif /* HAVE_OPAQUE_LSA */
   struct thread *t_maxage;              /* MaxAge LSA remover timer. */
   struct thread *t_maxage_walker;       /* MaxAge LSA checking timer. */
+  struct thread *t_graceful_shutdown;  /* Graceful/stub-router shutdown timer*/
 
   struct thread *t_write;
   struct thread *t_read;
@@ -351,6 +362,7 @@ struct ospf_area
   int shortcut_capability;              /* Other ABRs agree on S-bit */
   u_int32_t default_cost;               /* StubDefaultCost. */
   int auth_type;                        /* Authentication type. */
+  
 
   u_char NSSATranslatorRole;          /* NSSA configured role */
 #define OSPF_NSSA_ROLE_NEVER     0
@@ -365,7 +377,13 @@ struct ospf_area
 #define OSPF_TRANSIT_FALSE      0
 #define OSPF_TRANSIT_TRUE       1
   struct route_table *ranges;          /* Configured Area Ranges. */
-
+  
+  /* RFC3137 stub router state flags for area */
+  u_char stub_router_state;
+#define OSPF_AREA_ADMIN_STUB_ROUTED    (1 << 0) /* admin stub-router set */
+#define OSPF_AREA_IS_STUB_ROUTED       (1 << 1) /* stub-router active */
+#define OSPF_AREA_WAS_START_STUB_ROUTED        (1 << 2) /* startup SR was done */
+  
   /* Area related LSDBs[Type1-4]. */
   struct ospf_lsdb *lsdb;
 
@@ -415,6 +433,7 @@ struct ospf_area
 
   /* Threads. */
   struct thread *t_router_lsa_self;/* Self-originated router-LSA timer. */
+  struct thread *t_stub_router;    /* Stub-router timer */
 #ifdef HAVE_OPAQUE_LSA
   struct thread *t_opaque_lsa_self;    /* Type-10 Opaque-LSAs origin. */
 #endif /* HAVE_OPAQUE_LSA */