ospf_nsm.c 28 KB

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