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.
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index e56027b..c3cc4cb 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -2517,7 +2517,21 @@
 	             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 @@
   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 @@
            " (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 @@
       "IP Information\n"
       "OSPF interface commands\n"
       "Disable mtu mismatch detection\n")
+
+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;
+}
+
 static void
 show_ip_ospf_route_network (struct vty *vty, struct route_table *rt)
 {
@@ -7612,9 +7809,12 @@
 	  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 @@
 
   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);