ospf_nsm.c 29 KB

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