diff options
Diffstat (limited to 'ospfd')
| -rw-r--r-- | ospfd/ChangeLog | 62 | ||||
| -rw-r--r-- | ospfd/ospf_lsa.c | 95 | ||||
| -rw-r--r-- | ospfd/ospf_lsa.h | 1 | ||||
| -rw-r--r-- | ospfd/ospf_main.c | 7 | ||||
| -rw-r--r-- | ospfd/ospf_route.c | 15 | ||||
| -rw-r--r-- | ospfd/ospf_vty.c | 223 | ||||
| -rw-r--r-- | ospfd/ospfd.c | 140 | ||||
| -rw-r--r-- | ospfd/ospfd.h | 29 | 
8 files changed, 522 insertions, 50 deletions
| diff --git a/ospfd/ChangeLog b/ospfd/ChangeLog index 72412d74..fc0d5993 100644 --- a/ospfd/ChangeLog +++ b/ospfd/ChangeLog @@ -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 diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index a85667e6..31b9a4f1 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -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);  } + +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); +} +   /* 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); diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index 5cf69c31..42c08828 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -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 *); diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index 483b6387..3225d7d7 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -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. */ diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c index bdbdd03e..5eedbd82 100644 --- a/ospfd/ospf_route.c +++ b/ospfd/ospf_route.c @@ -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, diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index e56027be..c3cc4cb4 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -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") + +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_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); diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index bf8ca4dc..69f091d7 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -64,13 +64,14 @@ extern struct zclient *zclient;  extern struct in_addr router_id_zebra; -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 - +  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,10 +267,117 @@ ospf_get ()    return ospf;  } + +/* 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; +} + +/* 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;    struct ospf_lsa *lsa; @@ -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; diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index 38e56b6f..ed66ebf7 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -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 */ | 
