ospf_nsm.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  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. #include "ospfd/ospf_snmp.h"
  48. static void nsm_clear_adj (struct ospf_neighbor *);
  49. /* OSPF NSM Timer functions. */
  50. static int
  51. ospf_inactivity_timer (struct thread *thread)
  52. {
  53. struct ospf_neighbor *nbr;
  54. nbr = THREAD_ARG (thread);
  55. nbr->t_inactivity = NULL;
  56. if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
  57. zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (Inactivity timer expire)",
  58. IF_NAME (nbr->oi), inet_ntoa (nbr->router_id));
  59. OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_InactivityTimer);
  60. return 0;
  61. }
  62. static int
  63. ospf_db_desc_timer (struct thread *thread)
  64. {
  65. struct ospf_interface *oi;
  66. struct ospf_neighbor *nbr;
  67. nbr = THREAD_ARG (thread);
  68. nbr->t_db_desc = NULL;
  69. oi = nbr->oi;
  70. if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
  71. zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (DD Retransmit timer expire)",
  72. IF_NAME (nbr->oi), inet_ntoa (nbr->src));
  73. /* resent last send DD packet. */
  74. assert (nbr->last_send);
  75. ospf_db_desc_resend (nbr);
  76. /* DD Retransmit timer set. */
  77. OSPF_NSM_TIMER_ON (nbr->t_db_desc, ospf_db_desc_timer, nbr->v_db_desc);
  78. return 0;
  79. }
  80. /* Hook function called after ospf NSM event is occured.
  81. *
  82. * Set/clear any timers whose condition is implicit to the neighbour
  83. * state. There may be other timers which are set/unset according to other
  84. * state.
  85. *
  86. * We rely on this function to properly clear timers in lower states,
  87. * particularly before deleting a neighbour.
  88. */
  89. static void
  90. nsm_timer_set (struct ospf_neighbor *nbr)
  91. {
  92. switch (nbr->state)
  93. {
  94. case NSM_Deleted:
  95. case NSM_Down:
  96. OSPF_NSM_TIMER_OFF (nbr->t_inactivity);
  97. OSPF_NSM_TIMER_OFF (nbr->t_hello_reply);
  98. case NSM_Attempt:
  99. case NSM_Init:
  100. case NSM_TwoWay:
  101. OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
  102. OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
  103. OSPF_NSM_TIMER_OFF (nbr->t_ls_req);
  104. break;
  105. case NSM_ExStart:
  106. OSPF_NSM_TIMER_ON (nbr->t_db_desc, ospf_db_desc_timer, nbr->v_db_desc);
  107. OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
  108. OSPF_NSM_TIMER_OFF (nbr->t_ls_req);
  109. break;
  110. case NSM_Exchange:
  111. OSPF_NSM_TIMER_ON (nbr->t_ls_upd, ospf_ls_upd_timer, nbr->v_ls_upd);
  112. if (!IS_SET_DD_MS (nbr->dd_flags))
  113. OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
  114. break;
  115. case NSM_Loading:
  116. case NSM_Full:
  117. default:
  118. OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
  119. break;
  120. }
  121. }
  122. /* 10.4 of RFC2328, indicate whether an adjacency is appropriate with
  123. * the given neighbour
  124. */
  125. static int
  126. nsm_should_adj (struct ospf_neighbor *nbr)
  127. {
  128. struct ospf_interface *oi = nbr->oi;
  129. /* These network types must always form adjacencies. */
  130. if (oi->type == OSPF_IFTYPE_POINTOPOINT
  131. || oi->type == OSPF_IFTYPE_POINTOMULTIPOINT
  132. || oi->type == OSPF_IFTYPE_VIRTUALLINK
  133. /* Router itself is the DRouter or the BDRouter. */
  134. || IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))
  135. || IPV4_ADDR_SAME (&oi->address->u.prefix4, &BDR (oi))
  136. /* Neighboring Router is the DRouter or the BDRouter. */
  137. || IPV4_ADDR_SAME (&nbr->address.u.prefix4, &DR (oi))
  138. || IPV4_ADDR_SAME (&nbr->address.u.prefix4, &BDR (oi)))
  139. return 1;
  140. return 0;
  141. }
  142. /* OSPF NSM functions. */
  143. static int
  144. nsm_packet_received (struct ospf_neighbor *nbr)
  145. {
  146. /* Start or Restart Inactivity Timer. */
  147. OSPF_NSM_TIMER_OFF (nbr->t_inactivity);
  148. OSPF_NSM_TIMER_ON (nbr->t_inactivity, ospf_inactivity_timer,
  149. nbr->v_inactivity);
  150. if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma)
  151. OSPF_POLL_TIMER_OFF (nbr->nbr_nbma->t_poll);
  152. return 0;
  153. }
  154. static int
  155. nsm_start (struct ospf_neighbor *nbr)
  156. {
  157. if (nbr->nbr_nbma)
  158. OSPF_POLL_TIMER_OFF (nbr->nbr_nbma->t_poll);
  159. OSPF_NSM_TIMER_OFF (nbr->t_inactivity);
  160. OSPF_NSM_TIMER_ON (nbr->t_inactivity, ospf_inactivity_timer,
  161. nbr->v_inactivity);
  162. return 0;
  163. }
  164. static int
  165. nsm_twoway_received (struct ospf_neighbor *nbr)
  166. {
  167. return (nsm_should_adj (nbr) ? NSM_ExStart : NSM_TwoWay);
  168. }
  169. int
  170. ospf_db_summary_count (struct ospf_neighbor *nbr)
  171. {
  172. return ospf_lsdb_count_all (&nbr->db_sum);
  173. }
  174. int
  175. ospf_db_summary_isempty (struct ospf_neighbor *nbr)
  176. {
  177. return ospf_lsdb_isempty (&nbr->db_sum);
  178. }
  179. static int
  180. ospf_db_summary_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
  181. {
  182. #ifdef HAVE_OPAQUE_LSA
  183. switch (lsa->data->type)
  184. {
  185. case OSPF_OPAQUE_LINK_LSA:
  186. /* Exclude type-9 LSAs that does not have the same "oi" with "nbr". */
  187. if (nbr->oi && ospf_if_exists (lsa->oi) != nbr->oi)
  188. return 0;
  189. break;
  190. case OSPF_OPAQUE_AREA_LSA:
  191. /*
  192. * It is assured by the caller function "nsm_negotiation_done()"
  193. * that every given LSA belongs to the same area with "nbr".
  194. */
  195. break;
  196. case OSPF_OPAQUE_AS_LSA:
  197. default:
  198. break;
  199. }
  200. #endif /* HAVE_OPAQUE_LSA */
  201. /* Stay away from any Local Translated Type-7 LSAs */
  202. if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
  203. return 0;
  204. if (IS_LSA_MAXAGE (lsa))
  205. ospf_ls_retransmit_add (nbr, lsa);
  206. else
  207. ospf_lsdb_add (&nbr->db_sum, lsa);
  208. return 0;
  209. }
  210. void
  211. ospf_db_summary_clear (struct ospf_neighbor *nbr)
  212. {
  213. struct ospf_lsdb *lsdb;
  214. int i;
  215. lsdb = &nbr->db_sum;
  216. for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
  217. {
  218. struct route_table *table = lsdb->type[i].db;
  219. struct route_node *rn;
  220. for (rn = route_top (table); rn; rn = route_next (rn))
  221. if (rn->info)
  222. ospf_lsdb_delete (&nbr->db_sum, rn->info);
  223. }
  224. }
  225. /* The area link state database consists of the router-LSAs,
  226. network-LSAs and summary-LSAs contained in the area structure,
  227. along with the AS-external-LSAs contained in the global structure.
  228. AS-external-LSAs are omitted from a virtual neighbor's Database
  229. summary list. AS-external-LSAs are omitted from the Database
  230. summary list if the area has been configured as a stub. */
  231. static int
  232. nsm_negotiation_done (struct ospf_neighbor *nbr)
  233. {
  234. struct ospf_area *area = nbr->oi->area;
  235. struct ospf_lsa *lsa;
  236. struct route_node *rn;
  237. LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
  238. ospf_db_summary_add (nbr, lsa);
  239. LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
  240. ospf_db_summary_add (nbr, lsa);
  241. LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
  242. ospf_db_summary_add (nbr, lsa);
  243. LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
  244. ospf_db_summary_add (nbr, lsa);
  245. #ifdef HAVE_OPAQUE_LSA
  246. /* Process only if the neighbor is opaque capable. */
  247. if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
  248. {
  249. LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
  250. ospf_db_summary_add (nbr, lsa);
  251. LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
  252. ospf_db_summary_add (nbr, lsa);
  253. }
  254. #endif /* HAVE_OPAQUE_LSA */
  255. if (CHECK_FLAG (nbr->options, OSPF_OPTION_NP))
  256. {
  257. LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
  258. ospf_db_summary_add (nbr, lsa);
  259. }
  260. if (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK
  261. && area->external_routing == OSPF_AREA_DEFAULT)
  262. LSDB_LOOP (EXTERNAL_LSDB (nbr->oi->ospf), rn, lsa)
  263. ospf_db_summary_add (nbr, lsa);
  264. #ifdef HAVE_OPAQUE_LSA
  265. if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)
  266. && (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK
  267. && area->external_routing == OSPF_AREA_DEFAULT))
  268. LSDB_LOOP (OPAQUE_AS_LSDB (nbr->oi->ospf), rn, lsa)
  269. ospf_db_summary_add (nbr, lsa);
  270. #endif /* HAVE_OPAQUE_LSA */
  271. return 0;
  272. }
  273. static int
  274. nsm_exchange_done (struct ospf_neighbor *nbr)
  275. {
  276. if (ospf_ls_request_isempty (nbr))
  277. return NSM_Full;
  278. /* Send Link State Request. */
  279. ospf_ls_req_send (nbr);
  280. return NSM_Loading;
  281. }
  282. static int
  283. nsm_adj_ok (struct ospf_neighbor *nbr)
  284. {
  285. int next_state = nbr->state;
  286. int adj = nsm_should_adj (nbr);
  287. if (nbr->state == NSM_TwoWay && adj == 1)
  288. next_state = NSM_ExStart;
  289. else if (nbr->state >= NSM_ExStart && adj == 0)
  290. next_state = NSM_TwoWay;
  291. return next_state;
  292. }
  293. /* Clear adjacency related state for a neighbour, intended where nbr
  294. * transitions from > ExStart (i.e. a Full or forming adjacency)
  295. * to <= ExStart.
  296. */
  297. static void
  298. nsm_clear_adj (struct ospf_neighbor *nbr)
  299. {
  300. /* Clear Database Summary list. */
  301. if (!ospf_db_summary_isempty (nbr))
  302. ospf_db_summary_clear (nbr);
  303. /* Clear Link State Request list. */
  304. if (!ospf_ls_request_isempty (nbr))
  305. ospf_ls_request_delete_all (nbr);
  306. /* Clear Link State Retransmission list. */
  307. if (!ospf_ls_retransmit_isempty (nbr))
  308. ospf_ls_retransmit_clear (nbr);
  309. #ifdef HAVE_OPAQUE_LSA
  310. if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
  311. UNSET_FLAG (nbr->options, OSPF_OPTION_O);
  312. #endif /* HAVE_OPAQUE_LSA */
  313. }
  314. static int
  315. nsm_kill_nbr (struct ospf_neighbor *nbr)
  316. {
  317. /* killing nbr_self is invalid */
  318. if (nbr == nbr->oi->nbr_self)
  319. {
  320. assert (nbr != nbr->oi->nbr_self);
  321. return 0;
  322. }
  323. if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma != NULL)
  324. {
  325. struct ospf_nbr_nbma *nbr_nbma = nbr->nbr_nbma;
  326. nbr_nbma->nbr = NULL;
  327. nbr_nbma->state_change = nbr->state_change;
  328. nbr->nbr_nbma = NULL;
  329. OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
  330. nbr_nbma->v_poll);
  331. if (IS_DEBUG_OSPF (nsm, NSM_EVENTS))
  332. zlog_debug ("NSM[%s:%s]: Down (PollIntervalTimer scheduled)",
  333. IF_NAME (nbr->oi), inet_ntoa (nbr->address.u.prefix4));
  334. }
  335. return 0;
  336. }
  337. /* Neighbor State Machine */
  338. struct {
  339. int (*func) (struct ospf_neighbor *);
  340. int next_state;
  341. } NSM [OSPF_NSM_STATE_MAX][OSPF_NSM_EVENT_MAX] =
  342. {
  343. {
  344. /* DependUpon: dummy state. */
  345. { NULL, NSM_DependUpon }, /* NoEvent */
  346. { NULL, NSM_DependUpon }, /* PacketReceived */
  347. { NULL, NSM_DependUpon }, /* Start */
  348. { NULL, NSM_DependUpon }, /* 2-WayReceived */
  349. { NULL, NSM_DependUpon }, /* NegotiationDone */
  350. { NULL, NSM_DependUpon }, /* ExchangeDone */
  351. { NULL, NSM_DependUpon }, /* BadLSReq */
  352. { NULL, NSM_DependUpon }, /* LoadingDone */
  353. { NULL, NSM_DependUpon }, /* AdjOK? */
  354. { NULL, NSM_DependUpon }, /* SeqNumberMismatch */
  355. { NULL, NSM_DependUpon }, /* 1-WayReceived */
  356. { NULL, NSM_DependUpon }, /* KillNbr */
  357. { NULL, NSM_DependUpon }, /* InactivityTimer */
  358. { NULL, NSM_DependUpon }, /* LLDown */
  359. },
  360. {
  361. /* Deleted: dummy state. */
  362. { NULL, NSM_Deleted }, /* NoEvent */
  363. { NULL, NSM_Deleted }, /* PacketReceived */
  364. { NULL, NSM_Deleted }, /* Start */
  365. { NULL, NSM_Deleted }, /* 2-WayReceived */
  366. { NULL, NSM_Deleted }, /* NegotiationDone */
  367. { NULL, NSM_Deleted }, /* ExchangeDone */
  368. { NULL, NSM_Deleted }, /* BadLSReq */
  369. { NULL, NSM_Deleted }, /* LoadingDone */
  370. { NULL, NSM_Deleted }, /* AdjOK? */
  371. { NULL, NSM_Deleted }, /* SeqNumberMismatch */
  372. { NULL, NSM_Deleted }, /* 1-WayReceived */
  373. { NULL, NSM_Deleted }, /* KillNbr */
  374. { NULL, NSM_Deleted }, /* InactivityTimer */
  375. { NULL, NSM_Deleted }, /* LLDown */
  376. },
  377. {
  378. /* Down: */
  379. { NULL, NSM_DependUpon }, /* NoEvent */
  380. { nsm_packet_received, NSM_Init }, /* PacketReceived */
  381. { nsm_start, NSM_Attempt }, /* Start */
  382. { NULL, NSM_Down }, /* 2-WayReceived */
  383. { NULL, NSM_Down }, /* NegotiationDone */
  384. { NULL, NSM_Down }, /* ExchangeDone */
  385. { NULL, NSM_Down }, /* BadLSReq */
  386. { NULL, NSM_Down }, /* LoadingDone */
  387. { NULL, NSM_Down }, /* AdjOK? */
  388. { NULL, NSM_Down }, /* SeqNumberMismatch */
  389. { NULL, NSM_Down }, /* 1-WayReceived */
  390. { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
  391. { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
  392. { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
  393. },
  394. {
  395. /* Attempt: */
  396. { NULL, NSM_DependUpon }, /* NoEvent */
  397. { nsm_packet_received, NSM_Init }, /* PacketReceived */
  398. { NULL, NSM_Attempt }, /* Start */
  399. { NULL, NSM_Attempt }, /* 2-WayReceived */
  400. { NULL, NSM_Attempt }, /* NegotiationDone */
  401. { NULL, NSM_Attempt }, /* ExchangeDone */
  402. { NULL, NSM_Attempt }, /* BadLSReq */
  403. { NULL, NSM_Attempt }, /* LoadingDone */
  404. { NULL, NSM_Attempt }, /* AdjOK? */
  405. { NULL, NSM_Attempt }, /* SeqNumberMismatch */
  406. { NULL, NSM_Attempt }, /* 1-WayReceived */
  407. { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
  408. { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
  409. { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
  410. },
  411. {
  412. /* Init: */
  413. { NULL, NSM_DependUpon }, /* NoEvent */
  414. { nsm_packet_received, NSM_Init }, /* PacketReceived */
  415. { NULL, NSM_Init }, /* Start */
  416. { nsm_twoway_received, NSM_DependUpon }, /* 2-WayReceived */
  417. { NULL, NSM_Init }, /* NegotiationDone */
  418. { NULL, NSM_Init }, /* ExchangeDone */
  419. { NULL, NSM_Init }, /* BadLSReq */
  420. { NULL, NSM_Init }, /* LoadingDone */
  421. { NULL, NSM_Init }, /* AdjOK? */
  422. { NULL, NSM_Init }, /* SeqNumberMismatch */
  423. { NULL, NSM_Init }, /* 1-WayReceived */
  424. { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
  425. { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
  426. { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
  427. },
  428. {
  429. /* 2-Way: */
  430. { NULL, NSM_DependUpon }, /* NoEvent */
  431. { nsm_packet_received, NSM_TwoWay }, /* HelloReceived */
  432. { NULL, NSM_TwoWay }, /* Start */
  433. { NULL, NSM_TwoWay }, /* 2-WayReceived */
  434. { NULL, NSM_TwoWay }, /* NegotiationDone */
  435. { NULL, NSM_TwoWay }, /* ExchangeDone */
  436. { NULL, NSM_TwoWay }, /* BadLSReq */
  437. { NULL, NSM_TwoWay }, /* LoadingDone */
  438. { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
  439. { NULL, NSM_TwoWay }, /* SeqNumberMismatch */
  440. { NULL, NSM_Init }, /* 1-WayReceived */
  441. { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
  442. { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
  443. { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
  444. },
  445. {
  446. /* ExStart: */
  447. { NULL, NSM_DependUpon }, /* NoEvent */
  448. { nsm_packet_received, NSM_ExStart }, /* PacaketReceived */
  449. { NULL, NSM_ExStart }, /* Start */
  450. { NULL, NSM_ExStart }, /* 2-WayReceived */
  451. { nsm_negotiation_done, NSM_Exchange }, /* NegotiationDone */
  452. { NULL, NSM_ExStart }, /* ExchangeDone */
  453. { NULL, NSM_ExStart }, /* BadLSReq */
  454. { NULL, NSM_ExStart }, /* LoadingDone */
  455. { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
  456. { NULL, NSM_ExStart }, /* SeqNumberMismatch */
  457. { NULL, NSM_Init }, /* 1-WayReceived */
  458. { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
  459. { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
  460. { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
  461. },
  462. {
  463. /* Exchange: */
  464. { NULL, NSM_DependUpon }, /* NoEvent */
  465. { nsm_packet_received, NSM_Exchange }, /* PacketReceived */
  466. { NULL, NSM_Exchange }, /* Start */
  467. { NULL, NSM_Exchange }, /* 2-WayReceived */
  468. { NULL, NSM_Exchange }, /* NegotiationDone */
  469. { nsm_exchange_done, NSM_DependUpon }, /* ExchangeDone */
  470. { NULL, NSM_ExStart }, /* BadLSReq */
  471. { NULL, NSM_Exchange }, /* LoadingDone */
  472. { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
  473. { NULL, NSM_ExStart }, /* SeqNumberMismatch */
  474. { NULL, NSM_Init }, /* 1-WayReceived */
  475. { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
  476. { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
  477. { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
  478. },
  479. {
  480. /* Loading: */
  481. { NULL, NSM_DependUpon }, /* NoEvent */
  482. { nsm_packet_received, NSM_Loading }, /* PacketReceived */
  483. { NULL, NSM_Loading }, /* Start */
  484. { NULL, NSM_Loading }, /* 2-WayReceived */
  485. { NULL, NSM_Loading }, /* NegotiationDone */
  486. { NULL, NSM_Loading }, /* ExchangeDone */
  487. { NULL, NSM_ExStart }, /* BadLSReq */
  488. { NULL, NSM_Full }, /* LoadingDone */
  489. { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
  490. { NULL, NSM_ExStart }, /* SeqNumberMismatch */
  491. { NULL, NSM_Init }, /* 1-WayReceived */
  492. { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
  493. { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
  494. { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
  495. },
  496. { /* Full: */
  497. { NULL, NSM_DependUpon }, /* NoEvent */
  498. { nsm_packet_received, NSM_Full }, /* PacketReceived */
  499. { NULL, NSM_Full }, /* Start */
  500. { NULL, NSM_Full }, /* 2-WayReceived */
  501. { NULL, NSM_Full }, /* NegotiationDone */
  502. { NULL, NSM_Full }, /* ExchangeDone */
  503. { NULL, NSM_ExStart }, /* BadLSReq */
  504. { NULL, NSM_Full }, /* LoadingDone */
  505. { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
  506. { NULL, NSM_ExStart }, /* SeqNumberMismatch */
  507. { NULL, NSM_Init }, /* 1-WayReceived */
  508. { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
  509. { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
  510. { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
  511. },
  512. };
  513. static const char *ospf_nsm_event_str[] =
  514. {
  515. "NoEvent",
  516. "PacketReceived",
  517. "Start",
  518. "2-WayReceived",
  519. "NegotiationDone",
  520. "ExchangeDone",
  521. "BadLSReq",
  522. "LoadingDone",
  523. "AdjOK?",
  524. "SeqNumberMismatch",
  525. "1-WayReceived",
  526. "KillNbr",
  527. "InactivityTimer",
  528. "LLDown",
  529. };
  530. static void
  531. nsm_notice_state_change (struct ospf_neighbor *nbr, int next_state, int event)
  532. {
  533. /* Logging change of status. */
  534. if (IS_DEBUG_OSPF (nsm, NSM_STATUS))
  535. zlog_debug ("NSM[%s:%s]: State change %s -> %s (%s)",
  536. IF_NAME (nbr->oi), inet_ntoa (nbr->router_id),
  537. LOOKUP (ospf_nsm_state_msg, nbr->state),
  538. LOOKUP (ospf_nsm_state_msg, next_state),
  539. ospf_nsm_event_str [event]);
  540. /* Optionally notify about adjacency changes */
  541. if (CHECK_FLAG(nbr->oi->ospf->config, OSPF_LOG_ADJACENCY_CHANGES) &&
  542. (CHECK_FLAG(nbr->oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL) ||
  543. (next_state == NSM_Full) || (next_state < nbr->state)))
  544. zlog_notice("AdjChg: Nbr %s on %s: %s -> %s (%s)",
  545. inet_ntoa (nbr->router_id), IF_NAME (nbr->oi),
  546. LOOKUP (ospf_nsm_state_msg, nbr->state),
  547. LOOKUP (ospf_nsm_state_msg, next_state),
  548. ospf_nsm_event_str [event]);
  549. /* Advance in NSM */
  550. if (next_state > nbr->state)
  551. nbr->ts_last_progress = recent_relative_time ();
  552. else /* regression in NSM */
  553. {
  554. nbr->ts_last_regress = recent_relative_time ();
  555. nbr->last_regress_str = ospf_nsm_event_str [event];
  556. }
  557. #ifdef HAVE_SNMP
  558. /* Terminal state or regression */
  559. if ((next_state == NSM_Full)
  560. || (next_state == NSM_TwoWay)
  561. || (next_state < nbr->state))
  562. {
  563. /* ospfVirtNbrStateChange */
  564. if (nbr->oi->type == OSPF_IFTYPE_VIRTUALLINK)
  565. ospfTrapVirtNbrStateChange(nbr);
  566. /* ospfNbrStateChange trap */
  567. else
  568. /* To/From FULL, only managed by DR */
  569. if (((next_state != NSM_Full) && (nbr->state != NSM_Full))
  570. || (nbr->oi->state == ISM_DR))
  571. ospfTrapNbrStateChange(nbr);
  572. }
  573. #endif
  574. }
  575. void
  576. nsm_change_state (struct ospf_neighbor *nbr, int state)
  577. {
  578. struct ospf_interface *oi = nbr->oi;
  579. struct ospf_area *vl_area = NULL;
  580. u_char old_state;
  581. int x;
  582. int force = 1;
  583. /* Preserve old status. */
  584. old_state = nbr->state;
  585. /* Change to new status. */
  586. nbr->state = state;
  587. /* Statistics. */
  588. nbr->state_change++;
  589. if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
  590. vl_area = ospf_area_lookup_by_area_id (oi->ospf, oi->vl_data->vl_area_id);
  591. /* One of the neighboring routers changes to/from the FULL state. */
  592. if ((old_state != NSM_Full && state == NSM_Full) ||
  593. (old_state == NSM_Full && state != NSM_Full))
  594. {
  595. if (state == NSM_Full)
  596. {
  597. oi->full_nbrs++;
  598. oi->area->full_nbrs++;
  599. ospf_check_abr_status (oi->ospf);
  600. if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area)
  601. if (++vl_area->full_vls == 1)
  602. ospf_schedule_abr_task (oi->ospf);
  603. /* kevinm: refresh any redistributions */
  604. for (x = ZEBRA_ROUTE_SYSTEM; x < ZEBRA_ROUTE_MAX; x++)
  605. {
  606. if (x == ZEBRA_ROUTE_OSPF || x == ZEBRA_ROUTE_OSPF6)
  607. continue;
  608. ospf_external_lsa_refresh_type (oi->ospf, x, force);
  609. }
  610. /* XXX: Clearly some thing is wrong with refresh of external LSAs
  611. * this added to hack around defaults not refreshing after a timer
  612. * jump.
  613. */
  614. ospf_external_lsa_refresh_default (oi->ospf);
  615. }
  616. else
  617. {
  618. oi->full_nbrs--;
  619. oi->area->full_nbrs--;
  620. ospf_check_abr_status (oi->ospf);
  621. if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area)
  622. if (vl_area->full_vls > 0)
  623. if (--vl_area->full_vls == 0)
  624. ospf_schedule_abr_task (oi->ospf);
  625. }
  626. zlog_info ("nsm_change_state(%s, %s -> %s): "
  627. "scheduling new router-LSA origination",
  628. inet_ntoa (nbr->router_id),
  629. LOOKUP(ospf_nsm_state_msg, old_state),
  630. LOOKUP(ospf_nsm_state_msg, state));
  631. ospf_router_lsa_update_area (oi->area);
  632. if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
  633. {
  634. struct ospf_area *vl_area =
  635. ospf_area_lookup_by_area_id (oi->ospf, oi->vl_data->vl_area_id);
  636. if (vl_area)
  637. ospf_router_lsa_update_area (vl_area);
  638. }
  639. /* Originate network-LSA. */
  640. if (oi->state == ISM_DR)
  641. {
  642. if (oi->network_lsa_self && oi->full_nbrs == 0)
  643. {
  644. ospf_lsa_flush_area (oi->network_lsa_self, oi->area);
  645. ospf_lsa_unlock (&oi->network_lsa_self);
  646. oi->network_lsa_self = NULL;
  647. }
  648. else
  649. ospf_network_lsa_update (oi);
  650. }
  651. }
  652. #ifdef HAVE_OPAQUE_LSA
  653. ospf_opaque_nsm_change (nbr, old_state);
  654. #endif /* HAVE_OPAQUE_LSA */
  655. /* State changes from > ExStart to <= ExStart should clear any Exchange
  656. * or Full/LSA Update related lists and state.
  657. * Potential causal events: BadLSReq, SeqNumberMismatch, AdjOK?
  658. */
  659. if ((old_state > NSM_ExStart) && (state <= NSM_ExStart))
  660. nsm_clear_adj (nbr);
  661. /* Start DD exchange protocol */
  662. if (state == NSM_ExStart)
  663. {
  664. if (nbr->dd_seqnum == 0)
  665. nbr->dd_seqnum = quagga_time (NULL);
  666. else
  667. nbr->dd_seqnum++;
  668. nbr->dd_flags = OSPF_DD_FLAG_I|OSPF_DD_FLAG_M|OSPF_DD_FLAG_MS;
  669. ospf_db_desc_send (nbr);
  670. }
  671. /* clear cryptographic sequence number */
  672. if (state == NSM_Down)
  673. nbr->crypt_seqnum = 0;
  674. /* Generete NeighborChange ISM event. */
  675. switch (oi->state) {
  676. case ISM_DROther:
  677. case ISM_Backup:
  678. case ISM_DR:
  679. if ((old_state < NSM_TwoWay && state >= NSM_TwoWay) ||
  680. (old_state >= NSM_TwoWay && state < NSM_TwoWay))
  681. OSPF_ISM_EVENT_EXECUTE (oi, ISM_NeighborChange);
  682. break;
  683. default:
  684. /* ISM_PointToPoint -> ISM_Down, ISM_Loopback -> ISM_Down, etc. */
  685. break;
  686. }
  687. /* Preserve old status? */
  688. }
  689. /* Execute NSM event process. */
  690. int
  691. ospf_nsm_event (struct thread *thread)
  692. {
  693. int event;
  694. int next_state;
  695. struct ospf_neighbor *nbr;
  696. struct in_addr router_id;
  697. nbr = THREAD_ARG (thread);
  698. event = THREAD_VAL (thread);
  699. router_id = nbr->router_id;
  700. if (IS_DEBUG_OSPF (nsm, NSM_EVENTS))
  701. zlog_debug ("NSM[%s:%s]: %s (%s)", IF_NAME (nbr->oi),
  702. inet_ntoa (nbr->router_id),
  703. LOOKUP (ospf_nsm_state_msg, nbr->state),
  704. ospf_nsm_event_str [event]);
  705. next_state = NSM [nbr->state][event].next_state;
  706. /* Call function. */
  707. if (NSM [nbr->state][event].func != NULL)
  708. {
  709. int func_state = (*(NSM [nbr->state][event].func))(nbr);
  710. if (NSM [nbr->state][event].next_state == NSM_DependUpon)
  711. next_state = func_state;
  712. else if (func_state)
  713. {
  714. /* There's a mismatch between the FSM tables and what an FSM
  715. * action/state-change function returned. State changes which
  716. * do not have conditional/DependUpon next-states should not
  717. * try set next_state.
  718. */
  719. zlog_warn ("NSM[%s:%s]: %s (%s): "
  720. "Warning: action tried to change next_state to %s",
  721. IF_NAME (nbr->oi), inet_ntoa (nbr->router_id),
  722. LOOKUP (ospf_nsm_state_msg, nbr->state),
  723. ospf_nsm_event_str [event],
  724. LOOKUP (ospf_nsm_state_msg, func_state));
  725. }
  726. }
  727. assert (next_state != NSM_DependUpon);
  728. /* If state is changed. */
  729. if (next_state != nbr->state)
  730. {
  731. nsm_notice_state_change (nbr, next_state, event);
  732. nsm_change_state (nbr, next_state);
  733. }
  734. /* Make sure timer is set. */
  735. nsm_timer_set (nbr);
  736. /* When event is NSM_KillNbr, InactivityTimer or LLDown, the neighbor
  737. * is deleted.
  738. *
  739. * Rather than encode knowledge here of which events lead to NBR
  740. * delete, we take our cue from the NSM table, via the dummy
  741. * 'Deleted' neighbour state.
  742. */
  743. if (nbr->state == NSM_Deleted)
  744. ospf_nbr_delete (nbr);
  745. return 0;
  746. }
  747. /* Check loading state. */
  748. void
  749. ospf_check_nbr_loading (struct ospf_neighbor *nbr)
  750. {
  751. if (nbr->state == NSM_Loading)
  752. {
  753. if (ospf_ls_request_isempty (nbr))
  754. OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_LoadingDone);
  755. else if (nbr->ls_req_last == NULL)
  756. ospf_ls_req_event (nbr);
  757. }
  758. }