ospf_nsm.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:27k
源码类别:

网络

开发平台:

Unix_Linux

  1. /*
  2.  * OSPF version 2  Neighbor State Machine
  3.  * From RFC2328 [OSPF Version 2]
  4.  * Copyright (C) 1999, 2000 Toshiaki Takada
  5.  *
  6.  * This file is part of GNU Zebra.
  7.  *
  8.  * GNU Zebra is free software; you can redistribute it and/or modify it
  9.  * under the terms of the GNU General Public License as published by the
  10.  * Free Software Foundation; either version 2, or (at your option) any
  11.  * later version.
  12.  *
  13.  * GNU Zebra is distributed in the hope that it will be useful, but
  14.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
  20.  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  21.  * 02111-1307, USA.
  22.  */
  23. #include <zebra.h>
  24. #include "thread.h"
  25. #include "memory.h"
  26. #include "hash.h"
  27. #include "linklist.h"
  28. #include "prefix.h"
  29. #include "if.h"
  30. #include "table.h"
  31. #include "stream.h"
  32. #include "table.h"
  33. #include "log.h"
  34. #include "ospfd/ospfd.h"
  35. #include "ospfd/ospf_interface.h"
  36. #include "ospfd/ospf_ism.h"
  37. #include "ospfd/ospf_asbr.h"
  38. #include "ospfd/ospf_lsa.h"
  39. #include "ospfd/ospf_lsdb.h"
  40. #include "ospfd/ospf_neighbor.h"
  41. #include "ospfd/ospf_nsm.h"
  42. #include "ospfd/ospf_network.h"
  43. #include "ospfd/ospf_packet.h"
  44. #include "ospfd/ospf_dump.h"
  45. #include "ospfd/ospf_flood.h"
  46. #include "ospfd/ospf_abr.h"
  47. void nsm_reset_nbr (struct ospf_neighbor *);
  48. /* OSPF NSM Timer functions. */
  49. int
  50. ospf_inactivity_timer (struct thread *thread)
  51. {
  52.   struct ospf_neighbor *nbr;
  53.   nbr = THREAD_ARG (thread);
  54.   nbr->t_inactivity = NULL;
  55.   if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
  56.     zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (Inactivity timer expire)",
  57.   IF_NAME (nbr->oi), inet_ntoa (nbr->router_id));
  58.   OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_InactivityTimer);
  59.   return 0;
  60. }
  61. int
  62. ospf_db_desc_timer (struct thread *thread)
  63. {
  64.   struct ospf_interface *oi;
  65.   struct ospf_neighbor *nbr;
  66.   nbr = THREAD_ARG (thread);
  67.   nbr->t_db_desc = NULL;
  68.   oi = nbr->oi;
  69.   if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
  70.     zlog (NULL, LOG_INFO, "NSM[%s:%s]: Timer (DD Retransmit timer expire)",
  71.   IF_NAME (nbr->oi), inet_ntoa (nbr->src));
  72.   /* resent last send DD packet. */
  73.   assert (nbr->last_send);
  74.   ospf_db_desc_resend (nbr);
  75.   /* DD Retransmit timer set. */
  76.   OSPF_NSM_TIMER_ON (nbr->t_db_desc, ospf_db_desc_timer, nbr->v_db_desc);
  77.   return 0;
  78. }
  79. /* Hook function called after ospf NSM event is occured. */
  80. void
  81. nsm_timer_set (struct ospf_neighbor *nbr)
  82. {
  83.   switch (nbr->state)
  84.     {
  85.     case NSM_Down:
  86.       OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
  87.       OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
  88.       break;
  89.     case NSM_Attempt:
  90.       OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
  91.       OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
  92.       break;
  93.     case NSM_Init:
  94.       OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
  95.       OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
  96.       break;
  97.     case NSM_TwoWay:
  98.       OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
  99.       OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
  100.       break;
  101.     case NSM_ExStart:
  102.       OSPF_NSM_TIMER_ON (nbr->t_db_desc, ospf_db_desc_timer, nbr->v_db_desc);
  103.       OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
  104.       break;
  105.     case NSM_Exchange:
  106.       OSPF_NSM_TIMER_ON (nbr->t_ls_upd, ospf_ls_upd_timer, nbr->v_ls_upd);
  107.       if (!IS_SET_DD_MS (nbr->dd_flags))      
  108. OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
  109.       break;
  110.     case NSM_Loading:
  111.       OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
  112.       break;
  113.     case NSM_Full:
  114.       OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
  115.       break;
  116.     default:
  117.       OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
  118.       break;
  119.     }
  120. }
  121. /* OSPF NSM functions. */
  122. int
  123. nsm_ignore (struct ospf_neighbor *nbr)
  124. {
  125.   if (IS_DEBUG_OSPF (nsm, NSM_EVENTS))
  126.     zlog (NULL, LOG_INFO, "NSM[%s:%s]: nsm_ignore called",
  127.   IF_NAME (nbr->oi), inet_ntoa (nbr->router_id));
  128.   return 0;
  129. }
  130. int
  131. nsm_hello_received (struct ospf_neighbor *nbr)
  132. {
  133.   /* Start or Restart Inactivity Timer. */
  134.   OSPF_NSM_TIMER_OFF (nbr->t_inactivity);
  135.   
  136.   OSPF_NSM_TIMER_ON (nbr->t_inactivity, ospf_inactivity_timer,
  137.      nbr->v_inactivity);
  138.   if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma)
  139.     OSPF_POLL_TIMER_OFF (nbr->nbr_nbma->t_poll);
  140.   return 0;
  141. }
  142. int
  143. nsm_start (struct ospf_neighbor *nbr)
  144. {
  145.   nsm_reset_nbr (nbr);
  146.   if (nbr->nbr_nbma)
  147.       OSPF_POLL_TIMER_OFF (nbr->nbr_nbma->t_poll);
  148.   OSPF_NSM_TIMER_OFF (nbr->t_inactivity);
  149.   
  150.   OSPF_NSM_TIMER_ON (nbr->t_inactivity, ospf_inactivity_timer,
  151.                      nbr->v_inactivity);
  152.   return 0;
  153. }
  154. int
  155. nsm_twoway_received (struct ospf_neighbor *nbr)
  156. {
  157.   struct ospf_interface *oi;
  158.   int next_state = NSM_TwoWay;
  159.   oi = nbr->oi;
  160.   /* These netowork types must be adjacency. */
  161.   if (oi->type == OSPF_IFTYPE_POINTOPOINT ||
  162.       oi->type == OSPF_IFTYPE_POINTOMULTIPOINT ||
  163.       oi->type == OSPF_IFTYPE_VIRTUALLINK)
  164.     next_state = NSM_ExStart;
  165.   /* Router itself is the DRouter or the BDRouter. */
  166.   if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi)) ||
  167.       IPV4_ADDR_SAME (&oi->address->u.prefix4, &BDR (oi)))
  168.     next_state = NSM_ExStart;
  169.   /* Neighboring Router is the DRouter or the BDRouter. */
  170.   if (IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->d_router) ||
  171.       IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->bd_router))
  172.     next_state = NSM_ExStart;
  173.   return next_state;
  174. }
  175. int
  176. ospf_db_summary_count (struct ospf_neighbor *nbr)
  177. {
  178.   return ospf_lsdb_count_all (&nbr->db_sum);
  179. }
  180. int
  181. ospf_db_summary_isempty (struct ospf_neighbor *nbr)
  182. {
  183.   return ospf_lsdb_isempty (&nbr->db_sum);
  184. }
  185. int
  186. ospf_db_summary_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
  187. {
  188. #ifdef HAVE_OPAQUE_LSA
  189.   switch (lsa->data->type)
  190.     {
  191.     case OSPF_OPAQUE_LINK_LSA:
  192.       /* Exclude type-9 LSAs that does not have the same "oi" with "nbr". */
  193.       if (lsa->oi != nbr->oi)
  194.           return 0;
  195.       break;
  196.     case OSPF_OPAQUE_AREA_LSA:
  197.       /*
  198.        * It is assured by the caller function "nsm_negotiation_done()"
  199.        * that every given LSA belongs to the same area with "nbr".
  200.        */
  201.       break;
  202.     case OSPF_OPAQUE_AS_LSA:
  203.     default:
  204.       break;
  205.     }
  206. #endif /* HAVE_OPAQUE_LSA */
  207. #ifdef HAVE_NSSA
  208.   /* Stay away from any Local Translated Type-7 LSAs */
  209.   if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
  210.     return 0;
  211. #endif /* HAVE_NSSA */
  212.   if (IS_LSA_MAXAGE (lsa))
  213.     ospf_ls_retransmit_add (nbr, lsa);                      
  214.   else 
  215.     ospf_lsdb_add (&nbr->db_sum, lsa);
  216.   return 0;
  217. }
  218. void
  219. ospf_db_summary_clear (struct ospf_neighbor *nbr)
  220. {
  221.   struct ospf_lsdb *lsdb;
  222.   int i;
  223.   lsdb = &nbr->db_sum;
  224.   for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
  225.     {
  226.       struct route_table *table = lsdb->type[i].db;
  227.       struct route_node *rn;
  228.       for (rn = route_top (table); rn; rn = route_next (rn))
  229. if (rn->info)
  230.   ospf_lsdb_delete (&nbr->db_sum, rn->info);
  231.     }
  232. }
  233. /* The area link state database consists of the router-LSAs,
  234.    network-LSAs and summary-LSAs contained in the area structure,
  235.    along with the AS-external-LSAs contained in the global structure.
  236.    AS-external-LSAs are omitted from a virtual neighbor's Database
  237.    summary list.  AS-external-LSAs are omitted from the Database
  238.    summary list if the area has been configured as a stub. */
  239. int
  240. nsm_negotiation_done (struct ospf_neighbor *nbr)
  241. {
  242.   struct ospf_area *area = nbr->oi->area;
  243.   struct ospf_lsa *lsa;
  244.   struct route_node *rn;
  245.   LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
  246.     ospf_db_summary_add (nbr, lsa);
  247.   LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
  248.     ospf_db_summary_add (nbr, lsa);
  249.   LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
  250.     ospf_db_summary_add (nbr, lsa);
  251.   LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
  252.     ospf_db_summary_add (nbr, lsa);
  253. #ifdef HAVE_OPAQUE_LSA
  254.   /* Process only if the neighbor is opaque capable. */
  255.   if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
  256.     {
  257.       LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
  258. ospf_db_summary_add (nbr, lsa);
  259.       LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
  260. ospf_db_summary_add (nbr, lsa);
  261.     }
  262. #endif /* HAVE_OPAQUE_LSA */
  263.   if (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK
  264.       && area->external_routing == OSPF_AREA_DEFAULT)
  265.     LSDB_LOOP (EXTERNAL_LSDB (nbr->oi->ospf), rn, lsa)
  266.       ospf_db_summary_add (nbr, lsa);
  267. #ifdef HAVE_OPAQUE_LSA
  268.   if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)
  269.       && (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK
  270.   && area->external_routing == OSPF_AREA_DEFAULT))
  271.     LSDB_LOOP (OPAQUE_AS_LSDB (nbr->oi->ospf), rn, lsa)
  272.       ospf_db_summary_add (nbr, lsa);
  273. #endif /* HAVE_OPAQUE_LSA */
  274.   return 0;
  275. }
  276. int
  277. nsm_exchange_done (struct ospf_neighbor *nbr)
  278. {
  279.   if (ospf_ls_request_isempty (nbr))
  280.     return NSM_Full;
  281.   /* Cancel dd retransmit timer. */
  282.   /* OSPF_NSM_TIMER_OFF (nbr->t_db_desc); */
  283.   /* Send Link State Request. */
  284.   ospf_ls_req_send (nbr);
  285.   return NSM_Loading;
  286. }
  287. int
  288. nsm_bad_ls_req (struct ospf_neighbor *nbr)
  289. {
  290.   /* Clear neighbor. */
  291.   nsm_reset_nbr (nbr);
  292.   return 0;
  293. }
  294. int
  295. nsm_adj_ok (struct ospf_neighbor *nbr)
  296. {
  297.   struct ospf_interface *oi;
  298.   int next_state;
  299.   int flag = 0;
  300.   oi = nbr->oi;
  301.   next_state = nbr->state;
  302.   /* These netowork types must be adjacency. */
  303.   if (oi->type == OSPF_IFTYPE_POINTOPOINT
  304.       || oi->type == OSPF_IFTYPE_POINTOMULTIPOINT
  305.       || oi->type == OSPF_IFTYPE_VIRTUALLINK)
  306.     flag = 1;
  307.   /* Router itself is the DRouter or the BDRouter. */
  308.   if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))
  309.       || IPV4_ADDR_SAME (&oi->address->u.prefix4, &BDR (oi)))
  310.     flag = 1;
  311.   if (IPV4_ADDR_SAME (&nbr->address.u.prefix4, &DR (oi))
  312.       || IPV4_ADDR_SAME (&nbr->address.u.prefix4, &BDR (oi)))
  313.     flag = 1;
  314.   if (nbr->state == NSM_TwoWay && flag == 1)
  315.     next_state = NSM_ExStart;
  316.   else if (nbr->state >= NSM_ExStart && flag == 0)
  317.     next_state = NSM_TwoWay;
  318.   return next_state;
  319. }
  320. int
  321. nsm_seq_number_mismatch (struct ospf_neighbor *nbr)
  322. {
  323.   /* Clear neighbor. */
  324.   nsm_reset_nbr (nbr);
  325.   return 0;
  326. }
  327. int
  328. nsm_oneway_received (struct ospf_neighbor *nbr)
  329. {
  330.   /* Clear neighbor. */
  331.   nsm_reset_nbr (nbr);
  332.   return 0;
  333. }
  334. void
  335. nsm_reset_nbr (struct ospf_neighbor *nbr)
  336. {
  337.   /* Clear Database Summary list. */
  338.   if (!ospf_db_summary_isempty (nbr))
  339.     ospf_db_summary_clear (nbr);
  340.   /* Clear Link State Request list. */
  341.   if (!ospf_ls_request_isempty (nbr))
  342.     ospf_ls_request_delete_all (nbr);
  343.   /* Clear Link State Retransmission list. */
  344.   if (!ospf_ls_retransmit_isempty (nbr))
  345.     ospf_ls_retransmit_clear (nbr);
  346.   /* Cancel thread. */
  347.   OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
  348.   OSPF_NSM_TIMER_OFF (nbr->t_ls_req);
  349.   OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
  350.   OSPF_NSM_TIMER_OFF (nbr->t_hello_reply);
  351. #ifdef HAVE_OPAQUE_LSA
  352.   if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
  353.     UNSET_FLAG (nbr->options, OSPF_OPTION_O);
  354. #endif /* HAVE_OPAQUE_LSA */
  355. }
  356. int
  357. nsm_kill_nbr (struct ospf_neighbor *nbr)
  358. {
  359.   /* call it here because we cannot call it from ospf_nsm_event */
  360.   nsm_change_state (nbr, NSM_Down);
  361.   
  362.   /* Reset neighbor. */
  363.   nsm_reset_nbr (nbr);
  364.   if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma != NULL)
  365.     {
  366.       struct ospf_nbr_nbma *nbr_nbma = nbr->nbr_nbma;
  367.       nbr_nbma->nbr = NULL;
  368.       nbr_nbma->state_change = nbr->state_change;
  369.       nbr->nbr_nbma = NULL;
  370.       OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
  371.   nbr_nbma->v_poll);
  372.       if (IS_DEBUG_OSPF (nsm, NSM_EVENTS))
  373. zlog_info ("NSM[%s:%s]: Down (PollIntervalTimer scheduled)",
  374.    IF_NAME (nbr->oi), inet_ntoa (nbr->address.u.prefix4));  
  375.     }
  376.   /* Delete neighbor from interface. */
  377.   ospf_nbr_delete (nbr);
  378.   return 0;
  379. }
  380. int
  381. nsm_inactivity_timer (struct ospf_neighbor *nbr)
  382. {
  383.   /* Kill neighbor. */
  384.   nsm_kill_nbr (nbr);
  385.   return 0;
  386. }
  387. int
  388. nsm_ll_down (struct ospf_neighbor *nbr)
  389. {
  390.   /* Reset neighbor. */
  391.   /*nsm_reset_nbr (nbr);*/
  392.   
  393.   /* Kill neighbor. */
  394.   nsm_kill_nbr (nbr);
  395.   return 0;
  396. }
  397. /* Neighbor State Machine */
  398. struct {
  399.   int (*func) ();
  400.   int next_state;
  401. } NSM [OSPF_NSM_STATE_MAX][OSPF_NSM_EVENT_MAX] =
  402. {
  403.   {
  404.     /* DependUpon: dummy state. */
  405.     { nsm_ignore,              NSM_DependUpon }, /* NoEvent           */
  406.     { nsm_ignore,              NSM_DependUpon }, /* HelloReceived     */
  407.     { nsm_ignore,              NSM_DependUpon }, /* Start             */
  408.     { nsm_ignore,              NSM_DependUpon }, /* 2-WayReceived     */
  409.     { nsm_ignore,              NSM_DependUpon }, /* NegotiationDone   */
  410.     { nsm_ignore,              NSM_DependUpon }, /* ExchangeDone      */
  411.     { nsm_ignore,              NSM_DependUpon }, /* BadLSReq          */
  412.     { nsm_ignore,              NSM_DependUpon }, /* LoadingDone       */
  413.     { nsm_ignore,              NSM_DependUpon }, /* AdjOK?            */
  414.     { nsm_ignore,              NSM_DependUpon }, /* SeqNumberMismatch */
  415.     { nsm_ignore,              NSM_DependUpon }, /* 1-WayReceived     */
  416.     { nsm_ignore,              NSM_DependUpon }, /* KillNbr           */
  417.     { nsm_ignore,              NSM_DependUpon }, /* InactivityTimer   */
  418.     { nsm_ignore,              NSM_DependUpon }, /* LLDown            */
  419.   },
  420.   {
  421.     /* Down: */
  422.     { nsm_ignore,              NSM_DependUpon }, /* NoEvent           */
  423.     { nsm_hello_received,      NSM_Init       }, /* HelloReceived     */
  424.     { nsm_start,               NSM_Attempt    }, /* Start             */
  425.     { nsm_ignore,              NSM_Down       }, /* 2-WayReceived     */
  426.     { nsm_ignore,              NSM_Down       }, /* NegotiationDone   */
  427.     { nsm_ignore,              NSM_Down       }, /* ExchangeDone      */
  428.     { nsm_ignore,              NSM_Down       }, /* BadLSReq          */
  429.     { nsm_ignore,              NSM_Down       }, /* LoadingDone       */
  430.     { nsm_ignore,              NSM_Down       }, /* AdjOK?            */
  431.     { nsm_ignore,              NSM_Down       }, /* SeqNumberMismatch */
  432.     { nsm_ignore,              NSM_Down       }, /* 1-WayReceived     */
  433.     { nsm_kill_nbr,            NSM_Down       }, /* KillNbr           */
  434.     { nsm_inactivity_timer,    NSM_Down       }, /* InactivityTimer   */
  435.     { nsm_ll_down,             NSM_Down       }, /* LLDown            */
  436.   },
  437.   {
  438.     /* Attempt: */
  439.     { nsm_ignore,              NSM_DependUpon }, /* NoEvent           */
  440.     { nsm_hello_received,      NSM_Init       }, /* HelloReceived     */
  441.     { nsm_ignore,              NSM_Attempt    }, /* Start             */
  442.     { nsm_ignore,              NSM_Attempt    }, /* 2-WayReceived     */
  443.     { nsm_ignore,              NSM_Attempt    }, /* NegotiationDone   */
  444.     { nsm_ignore,              NSM_Attempt    }, /* ExchangeDone      */
  445.     { nsm_ignore,              NSM_Attempt    }, /* BadLSReq          */
  446.     { nsm_ignore,              NSM_Attempt    }, /* LoadingDone       */
  447.     { nsm_ignore,              NSM_Attempt    }, /* AdjOK?            */
  448.     { nsm_ignore,              NSM_Attempt    }, /* SeqNumberMismatch */
  449.     { nsm_ignore,              NSM_Attempt    }, /* 1-WayReceived     */
  450.     { nsm_kill_nbr,            NSM_Down       }, /* KillNbr           */
  451.     { nsm_inactivity_timer,    NSM_Down       }, /* InactivityTimer   */
  452.     { nsm_ll_down,             NSM_Down       }, /* LLDown            */
  453.   },
  454.   {
  455.     /* Init: */
  456.     { nsm_ignore,              NSM_DependUpon }, /* NoEvent           */
  457.     { nsm_hello_received,      NSM_Init       }, /* HelloReceived     */
  458.     { nsm_ignore,              NSM_Init       }, /* Start             */
  459.     { nsm_twoway_received,     NSM_DependUpon }, /* 2-WayReceived     */
  460.     { nsm_ignore,              NSM_Init       }, /* NegotiationDone   */
  461.     { nsm_ignore,              NSM_Init       }, /* ExchangeDone      */
  462.     { nsm_ignore,              NSM_Init       }, /* BadLSReq          */
  463.     { nsm_ignore,              NSM_Init       }, /* LoadingDone       */
  464.     { nsm_ignore,              NSM_Init       }, /* AdjOK?            */
  465.     { nsm_ignore,              NSM_Init       }, /* SeqNumberMismatch */
  466.     { nsm_ignore,              NSM_Init       }, /* 1-WayReceived     */
  467.     { nsm_kill_nbr,            NSM_Down       }, /* KillNbr           */
  468.     { nsm_inactivity_timer,    NSM_Down       }, /* InactivityTimer   */
  469.     { nsm_ll_down,             NSM_Down       }, /* LLDown            */
  470.   },
  471.   {
  472.     /* 2-Way: */
  473.     { nsm_ignore,              NSM_DependUpon }, /* NoEvent           */
  474.     { nsm_hello_received,      NSM_TwoWay     }, /* HelloReceived     */
  475.     { nsm_ignore,              NSM_TwoWay     }, /* Start             */
  476.     { nsm_ignore,              NSM_TwoWay     }, /* 2-WayReceived     */
  477.     { nsm_ignore,              NSM_TwoWay     }, /* NegotiationDone   */
  478.     { nsm_ignore,              NSM_TwoWay     }, /* ExchangeDone      */
  479.     { nsm_ignore,              NSM_TwoWay     }, /* BadLSReq          */
  480.     { nsm_ignore,              NSM_TwoWay     }, /* LoadingDone       */
  481.     { nsm_adj_ok,              NSM_DependUpon }, /* AdjOK?            */
  482.     { nsm_ignore,              NSM_TwoWay     }, /* SeqNumberMismatch */
  483.     { nsm_oneway_received,     NSM_Init       }, /* 1-WayReceived     */
  484.     { nsm_kill_nbr,            NSM_Down       }, /* KillNbr           */
  485.     { nsm_inactivity_timer,    NSM_Down       }, /* InactivityTimer   */
  486.     { nsm_ll_down,             NSM_Down       }, /* LLDown            */
  487.   },
  488.   {
  489.     /* ExStart: */
  490.     { nsm_ignore,              NSM_DependUpon }, /* NoEvent           */
  491.     { nsm_hello_received,      NSM_ExStart    }, /* HelloReceived     */
  492.     { nsm_ignore,              NSM_ExStart    }, /* Start             */
  493.     { nsm_ignore,              NSM_ExStart    }, /* 2-WayReceived     */
  494.     { nsm_negotiation_done,    NSM_Exchange   }, /* NegotiationDone   */
  495.     { nsm_ignore,              NSM_ExStart    }, /* ExchangeDone      */
  496.     { nsm_ignore,              NSM_ExStart    }, /* BadLSReq          */
  497.     { nsm_ignore,              NSM_ExStart    }, /* LoadingDone       */
  498.     { nsm_adj_ok,              NSM_DependUpon }, /* AdjOK?            */
  499.     { nsm_ignore,              NSM_ExStart    }, /* SeqNumberMismatch */
  500.     { nsm_oneway_received,     NSM_Init       }, /* 1-WayReceived     */
  501.     { nsm_kill_nbr,            NSM_Down       }, /* KillNbr           */
  502.     { nsm_inactivity_timer,    NSM_Down       }, /* InactivityTimer   */
  503.     { nsm_ll_down,             NSM_Down       }, /* LLDown            */
  504.   },
  505.   {
  506.     /* Exchange: */
  507.     { nsm_ignore,              NSM_DependUpon }, /* NoEvent           */
  508.     { nsm_hello_received,      NSM_Exchange   }, /* HelloReceived     */
  509.     { nsm_ignore,              NSM_Exchange   }, /* Start             */
  510.     { nsm_ignore,              NSM_Exchange   }, /* 2-WayReceived     */
  511.     { nsm_ignore,              NSM_Exchange   }, /* NegotiationDone   */
  512.     { nsm_exchange_done,       NSM_DependUpon }, /* ExchangeDone      */
  513.     { nsm_bad_ls_req,          NSM_ExStart    }, /* BadLSReq          */
  514.     { nsm_ignore,              NSM_Exchange   }, /* LoadingDone       */
  515.     { nsm_adj_ok,              NSM_DependUpon }, /* AdjOK?            */
  516.     { nsm_seq_number_mismatch, NSM_ExStart    }, /* SeqNumberMismatch */
  517.     { nsm_oneway_received,     NSM_Init       }, /* 1-WayReceived     */
  518.     { nsm_kill_nbr,            NSM_Down       }, /* KillNbr           */
  519.     { nsm_inactivity_timer,    NSM_Down       }, /* InactivityTimer   */
  520.     { nsm_ll_down,             NSM_Down       }, /* LLDown            */
  521.   },
  522.   {
  523.     /* Loading: */
  524.     { nsm_ignore,              NSM_DependUpon }, /* NoEvent           */
  525.     { nsm_hello_received,      NSM_Loading    }, /* HelloReceived     */
  526.     { nsm_ignore,              NSM_Loading    }, /* Start             */
  527.     { nsm_ignore,              NSM_Loading    }, /* 2-WayReceived     */
  528.     { nsm_ignore,              NSM_Loading    }, /* NegotiationDone   */
  529.     { nsm_ignore,              NSM_Loading    }, /* ExchangeDone      */
  530.     { nsm_bad_ls_req,          NSM_ExStart    }, /* BadLSReq          */
  531.     { nsm_ignore,              NSM_Full       }, /* LoadingDone       */
  532.     { nsm_adj_ok,              NSM_DependUpon }, /* AdjOK?            */
  533.     { nsm_seq_number_mismatch, NSM_ExStart    }, /* SeqNumberMismatch */
  534.     { nsm_oneway_received,     NSM_Init       }, /* 1-WayReceived     */
  535.     { nsm_kill_nbr,            NSM_Down       }, /* KillNbr           */
  536.     { nsm_inactivity_timer,    NSM_Down       }, /* InactivityTimer   */
  537.     { nsm_ll_down,             NSM_Down       }, /* LLDown            */
  538.   },
  539.   { /* Full: */
  540.     { nsm_ignore,              NSM_DependUpon }, /* NoEvent           */
  541.     { nsm_hello_received,      NSM_Full       }, /* HelloReceived     */
  542.     { nsm_ignore,              NSM_Full       }, /* Start             */
  543.     { nsm_ignore,              NSM_Full       }, /* 2-WayReceived     */
  544.     { nsm_ignore,              NSM_Full       }, /* NegotiationDone   */
  545.     { nsm_ignore,              NSM_Full       }, /* ExchangeDone      */
  546.     { nsm_bad_ls_req,          NSM_ExStart    }, /* BadLSReq          */
  547.     { nsm_ignore,              NSM_Full       }, /* LoadingDone       */
  548.     { nsm_adj_ok,              NSM_DependUpon }, /* AdjOK?            */
  549.     { nsm_seq_number_mismatch, NSM_ExStart    }, /* SeqNumberMismatch */
  550.     { nsm_oneway_received,     NSM_Init       }, /* 1-WayReceived     */
  551.     { nsm_kill_nbr,            NSM_Down       }, /* KillNbr           */
  552.     { nsm_inactivity_timer,    NSM_Down       }, /* InactivityTimer   */
  553.     { nsm_ll_down,             NSM_Down       }, /* LLDown            */
  554.   },
  555. };
  556. static char *ospf_nsm_event_str[] =
  557. {
  558.   "NoEvent",
  559.   "HelloReceived",
  560.   "Start",
  561.   "2-WayReceived",
  562.   "NegotiationDone",
  563.   "ExchangeDone",
  564.   "BadLSReq",
  565.   "LoadingDone",
  566.   "AdjOK?",
  567.   "SeqNumberMismatch",
  568.   "1-WayReceived",
  569.   "KillNbr",
  570.   "InactivityTimer",
  571.   "LLDown",
  572. };
  573. void
  574. nsm_change_state (struct ospf_neighbor *nbr, int state)
  575. {
  576.   struct ospf_interface *oi = nbr->oi;
  577.   struct ospf_area *vl_area = NULL;
  578.   u_char old_state;
  579.   int x;
  580.   int force = 1;
  581.   
  582.   /* Logging change of status. */
  583.   if (IS_DEBUG_OSPF (nsm, NSM_STATUS))
  584.     zlog_info ("NSM[%s:%s]: State change %s -> %s",
  585.        IF_NAME (nbr->oi), inet_ntoa (nbr->router_id),
  586.        LOOKUP (ospf_nsm_state_msg, nbr->state),
  587.        LOOKUP (ospf_nsm_state_msg, state));
  588.   /* Preserve old status. */
  589.   old_state = nbr->state;
  590.   /* Change to new status. */
  591.   nbr->state = state;
  592.   /* Statistics. */
  593.   nbr->state_change++;
  594.   if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
  595.     vl_area = ospf_area_lookup_by_area_id (oi->ospf, oi->vl_data->vl_area_id);
  596.   
  597.   /* One of the neighboring routers changes to/from the FULL state. */
  598.   if ((old_state != NSM_Full && state == NSM_Full) ||
  599.       (old_state == NSM_Full && state != NSM_Full))
  600.     { 
  601.       if (state == NSM_Full)
  602. {
  603.   oi->full_nbrs++;
  604.   oi->area->full_nbrs++;
  605.           ospf_check_abr_status (oi->ospf);
  606.   if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area)
  607.             if (++vl_area->full_vls == 1)
  608.       ospf_schedule_abr_task (oi->ospf);
  609.   /* kevinm: refresh any redistributions */
  610.   for (x = ZEBRA_ROUTE_SYSTEM; x < ZEBRA_ROUTE_MAX; x++)
  611.     {
  612.       if (x == ZEBRA_ROUTE_OSPF || x == ZEBRA_ROUTE_OSPF6)
  613. continue;
  614.       ospf_external_lsa_refresh_type (oi->ospf, x, force);
  615.     }
  616. }
  617.       else
  618. {
  619.   oi->full_nbrs--;
  620.   oi->area->full_nbrs--;
  621.           ospf_check_abr_status (oi->ospf);
  622.   if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area)
  623.     if (vl_area->full_vls > 0)
  624.       if (--vl_area->full_vls == 0)
  625. ospf_schedule_abr_task (oi->ospf);
  626.  
  627.           /* clear neighbor retransmit list */
  628.           if (!ospf_ls_retransmit_isempty (nbr))
  629.             ospf_ls_retransmit_clear (nbr);
  630. }
  631.       zlog_info ("nsm_change_state(): "
  632.  "scheduling new router-LSA origination");
  633.       ospf_router_lsa_timer_add (oi->area);
  634.       if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
  635. {
  636.   struct ospf_area *vl_area =
  637.     ospf_area_lookup_by_area_id (oi->ospf, oi->vl_data->vl_area_id);
  638.   
  639.   if (vl_area)
  640.     ospf_router_lsa_timer_add (vl_area);
  641. }
  642.       /* Originate network-LSA. */
  643.       if (oi->state == ISM_DR)
  644. {
  645.   if (oi->network_lsa_self && oi->full_nbrs == 0)
  646.     {
  647.       ospf_lsa_flush_area (oi->network_lsa_self, oi->area);
  648.       ospf_lsa_unlock (oi->network_lsa_self);
  649.       oi->network_lsa_self = NULL;
  650.       OSPF_TIMER_OFF (oi->t_network_lsa_self);
  651.     }
  652.   else
  653.     ospf_network_lsa_timer_add (oi);
  654. }
  655.     }
  656. #ifdef HAVE_OPAQUE_LSA
  657.   ospf_opaque_nsm_change (nbr, old_state);
  658. #endif /* HAVE_OPAQUE_LSA */
  659.   /* Start DD exchange protocol */
  660.   if (state == NSM_ExStart)
  661.     {
  662.       if (nbr->dd_seqnum == 0)
  663. nbr->dd_seqnum = time (NULL);
  664.       else
  665. nbr->dd_seqnum++;
  666.       nbr->dd_flags = OSPF_DD_FLAG_I|OSPF_DD_FLAG_M|OSPF_DD_FLAG_MS;
  667.       ospf_db_desc_send (nbr);
  668.     }
  669.   /* clear cryptographic sequence number */
  670.   if (state == NSM_Down)
  671.     nbr->crypt_seqnum = 0;
  672.   
  673.   /* Generete NeighborChange ISM event. */
  674. #ifdef BUGGY_ISM_TRANSITION
  675.   if ((old_state < NSM_TwoWay && state >= NSM_TwoWay) ||
  676.       (old_state >= NSM_TwoWay && state < NSM_TwoWay))
  677.     OSPF_ISM_EVENT_EXECUTE (oi, ISM_NeighborChange);
  678. #else /* BUGGY_ISM_TRANSITION */
  679.   switch (oi->state) {
  680.   case ISM_DROther:
  681.   case ISM_Backup:
  682.   case ISM_DR:
  683.     if ((old_state < NSM_TwoWay && state >= NSM_TwoWay) ||
  684.         (old_state >= NSM_TwoWay && state < NSM_TwoWay))
  685.       OSPF_ISM_EVENT_EXECUTE (oi, ISM_NeighborChange);
  686.     break;
  687.   default:
  688.     /* ISM_PointToPoint -> ISM_Down, ISM_Loopback -> ISM_Down, etc. */
  689.     break;
  690.   }
  691. #endif /* BUGGY_ISM_TRANSITION */
  692.   /* Performance hack. Send hello immideately when some neighbor enter
  693.      Init state.  This whay we decrease neighbor discovery time. Gleb.*/
  694.   if (state == NSM_Init)
  695.     {
  696.       OSPF_ISM_TIMER_OFF (oi->t_hello);
  697.       OSPF_ISM_TIMER_ON (oi->t_hello, ospf_hello_timer, 1);
  698.     }
  699.   /* Preserve old status? */
  700. }
  701. /* Execute NSM event process. */
  702. int
  703. ospf_nsm_event (struct thread *thread)
  704. {
  705.   int event;
  706.   int next_state;
  707.   struct ospf_neighbor *nbr;
  708.   struct in_addr router_id;
  709.   int old_state;
  710.   struct ospf_interface *oi;
  711.   nbr = THREAD_ARG (thread);
  712.   event = THREAD_VAL (thread);
  713.   router_id = nbr->router_id;
  714.   old_state = nbr->state;
  715.   oi = nbr->oi ;
  716.   
  717.   /* Call function. */
  718.   next_state = (*(NSM [nbr->state][event].func))(nbr);
  719.   /* When event is NSM_KillNbr or InactivityTimer, the neighbor is
  720.      deleted. */
  721.   if (event == NSM_KillNbr || event == NSM_InactivityTimer)
  722.     {
  723.       if (IS_DEBUG_OSPF (nsm, NSM_EVENTS))
  724. zlog_info ("NSM[%s:%s]: neighbor deleted",
  725.    IF_NAME (oi), inet_ntoa (router_id));
  726.       /* Timers are canceled in ospf_nbr_free, moreover we cannot call
  727.          nsm_timer_set here because nbr is freed already!!!*/
  728.       /*nsm_timer_set (nbr);*/
  729.       return 0;
  730.     }
  731.   if (! next_state)
  732.     next_state = NSM [nbr->state][event].next_state;
  733.   if (IS_DEBUG_OSPF (nsm, NSM_EVENTS))
  734.     zlog_info ("NSM[%s:%s]: %s (%s)", IF_NAME (oi),
  735.        inet_ntoa (nbr->router_id),
  736.        LOOKUP (ospf_nsm_state_msg, nbr->state),
  737.        ospf_nsm_event_str [event]);
  738.   
  739.   /* If state is changed. */
  740.   if (next_state != nbr->state)
  741.     nsm_change_state (nbr, next_state);
  742.   /* Make sure timer is set. */
  743.   nsm_timer_set (nbr);
  744.   return 0;
  745. }
  746. /* Check loading state. */
  747. void
  748. ospf_check_nbr_loading (struct ospf_neighbor *nbr)
  749. {
  750.   if (nbr->state == NSM_Loading)
  751.     {
  752.       if (ospf_ls_request_isempty (nbr))
  753. OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_LoadingDone);
  754.       else if (nbr->ls_req_last == NULL)
  755. ospf_ls_req_event (nbr);
  756.     }
  757. }