ospf_nsm.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  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_hello_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 (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 }, /* HelloReceived */
  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 }, /* HelloReceived */
  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_hello_received, NSM_Init }, /* HelloReceived */
  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_hello_received, NSM_Init }, /* HelloReceived */
  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_hello_received, NSM_Init }, /* HelloReceived */
  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_hello_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_hello_received, NSM_ExStart }, /* HelloReceived */
  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_hello_received, NSM_Exchange }, /* HelloReceived */
  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_hello_received, NSM_Loading }, /* HelloReceived */
  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_hello_received, NSM_Full }, /* HelloReceived */
  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. "HelloReceived",
  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_timer_add (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_timer_add (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. OSPF_TIMER_OFF (oi->t_network_lsa_self);
  648. }
  649. else
  650. ospf_network_lsa_timer_add (oi);
  651. }
  652. }
  653. #ifdef HAVE_OPAQUE_LSA
  654. ospf_opaque_nsm_change (nbr, old_state);
  655. #endif /* HAVE_OPAQUE_LSA */
  656. /* State changes from > ExStart to <= ExStart should clear any Exchange
  657. * or Full/LSA Update related lists and state.
  658. * Potential causal events: BadLSReq, SeqNumberMismatch, AdjOK?
  659. */
  660. if ((old_state > NSM_ExStart) && (state <= NSM_ExStart))
  661. nsm_clear_adj (nbr);
  662. /* Start DD exchange protocol */
  663. if (state == NSM_ExStart)
  664. {
  665. if (nbr->dd_seqnum == 0)
  666. nbr->dd_seqnum = quagga_time (NULL);
  667. else
  668. nbr->dd_seqnum++;
  669. nbr->dd_flags = OSPF_DD_FLAG_I|OSPF_DD_FLAG_M|OSPF_DD_FLAG_MS;
  670. ospf_db_desc_send (nbr);
  671. }
  672. /* clear cryptographic sequence number */
  673. if (state == NSM_Down)
  674. nbr->crypt_seqnum = 0;
  675. /* Generete NeighborChange ISM event. */
  676. switch (oi->state) {
  677. case ISM_DROther:
  678. case ISM_Backup:
  679. case ISM_DR:
  680. if ((old_state < NSM_TwoWay && state >= NSM_TwoWay) ||
  681. (old_state >= NSM_TwoWay && state < NSM_TwoWay))
  682. OSPF_ISM_EVENT_EXECUTE (oi, ISM_NeighborChange);
  683. break;
  684. default:
  685. /* ISM_PointToPoint -> ISM_Down, ISM_Loopback -> ISM_Down, etc. */
  686. break;
  687. }
  688. /* Performance hack. Send hello immideately when some neighbor enter
  689. Init state. This whay we decrease neighbor discovery time. Gleb.*/
  690. if (state == NSM_Init)
  691. {
  692. OSPF_ISM_TIMER_OFF (oi->t_hello);
  693. OSPF_ISM_TIMER_MSEC_ON (oi->t_hello, ospf_hello_timer, 1);
  694. }
  695. /* Preserve old status? */
  696. }
  697. /* Execute NSM event process. */
  698. int
  699. ospf_nsm_event (struct thread *thread)
  700. {
  701. int event;
  702. int next_state;
  703. struct ospf_neighbor *nbr;
  704. struct in_addr router_id;
  705. nbr = THREAD_ARG (thread);
  706. event = THREAD_VAL (thread);
  707. router_id = nbr->router_id;
  708. if (IS_DEBUG_OSPF (nsm, NSM_EVENTS))
  709. zlog_debug ("NSM[%s:%s]: %s (%s)", IF_NAME (nbr->oi),
  710. inet_ntoa (nbr->router_id),
  711. LOOKUP (ospf_nsm_state_msg, nbr->state),
  712. ospf_nsm_event_str [event]);
  713. next_state = NSM [nbr->state][event].next_state;
  714. /* Call function. */
  715. if (NSM [nbr->state][event].func != NULL)
  716. {
  717. int func_state = (*(NSM [nbr->state][event].func))(nbr);
  718. if (NSM [nbr->state][event].next_state == NSM_DependUpon)
  719. next_state = func_state;
  720. else if (func_state)
  721. {
  722. /* There's a mismatch between the FSM tables and what an FSM
  723. * action/state-change function returned. State changes which
  724. * do not have conditional/DependUpon next-states should not
  725. * try set next_state.
  726. */
  727. zlog_warn ("NSM[%s:%s]: %s (%s): "
  728. "Warning: action tried to change next_state to %s",
  729. IF_NAME (nbr->oi), inet_ntoa (nbr->router_id),
  730. LOOKUP (ospf_nsm_state_msg, nbr->state),
  731. ospf_nsm_event_str [event],
  732. LOOKUP (ospf_nsm_state_msg, func_state));
  733. }
  734. }
  735. assert (next_state != NSM_DependUpon);
  736. /* If state is changed. */
  737. if (next_state != nbr->state)
  738. {
  739. nsm_notice_state_change (nbr, next_state, event);
  740. nsm_change_state (nbr, next_state);
  741. }
  742. /* Make sure timer is set. */
  743. nsm_timer_set (nbr);
  744. /* When event is NSM_KillNbr, InactivityTimer or LLDown, the neighbor
  745. * is deleted.
  746. *
  747. * Rather than encode knowledge here of which events lead to NBR
  748. * delete, we take our cue from the NSM table, via the dummy
  749. * 'Deleted' neighbour state.
  750. */
  751. if (nbr->state == NSM_Deleted)
  752. ospf_nbr_delete (nbr);
  753. return 0;
  754. }
  755. /* Check loading state. */
  756. void
  757. ospf_check_nbr_loading (struct ospf_neighbor *nbr)
  758. {
  759. if (nbr->state == NSM_Loading)
  760. {
  761. if (ospf_ls_request_isempty (nbr))
  762. OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_LoadingDone);
  763. else if (nbr->ls_req_last == NULL)
  764. ospf_ls_req_event (nbr);
  765. }
  766. }