ospf_ism.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. /*
  2. * OSPF version 2 Interface 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 "linklist.h"
  26. #include "prefix.h"
  27. #include "if.h"
  28. #include "table.h"
  29. #include "log.h"
  30. #include "ospfd/ospfd.h"
  31. #include "ospfd/ospf_interface.h"
  32. #include "ospfd/ospf_ism.h"
  33. #include "ospfd/ospf_asbr.h"
  34. #include "ospfd/ospf_lsa.h"
  35. #include "ospfd/ospf_lsdb.h"
  36. #include "ospfd/ospf_neighbor.h"
  37. #include "ospfd/ospf_nsm.h"
  38. #include "ospfd/ospf_network.h"
  39. #include "ospfd/ospf_dump.h"
  40. #include "ospfd/ospf_packet.h"
  41. #include "ospfd/ospf_flood.h"
  42. #include "ospfd/ospf_abr.h"
  43. #include "ospfd/ospf_snmp.h"
  44. /* elect DR and BDR. Refer to RFC2319 section 9.4 */
  45. static struct ospf_neighbor *
  46. ospf_dr_election_sub (struct list *routers)
  47. {
  48. struct listnode *node;
  49. struct ospf_neighbor *nbr, *max = NULL;
  50. /* Choose highest router priority.
  51. In case of tie, choose highest Router ID. */
  52. for (ALL_LIST_ELEMENTS_RO (routers, node, nbr))
  53. {
  54. if (max == NULL)
  55. max = nbr;
  56. else
  57. {
  58. if (max->priority < nbr->priority)
  59. max = nbr;
  60. else if (max->priority == nbr->priority)
  61. if (IPV4_ADDR_CMP (&max->router_id, &nbr->router_id) < 0)
  62. max = nbr;
  63. }
  64. }
  65. return max;
  66. }
  67. static struct ospf_neighbor *
  68. ospf_elect_dr (struct ospf_interface *oi, struct list *el_list)
  69. {
  70. struct list *dr_list;
  71. struct listnode *node;
  72. struct ospf_neighbor *nbr, *dr = NULL, *bdr = NULL;
  73. dr_list = list_new ();
  74. /* Add neighbors to the list. */
  75. for (ALL_LIST_ELEMENTS_RO (el_list, node, nbr))
  76. {
  77. /* neighbor declared to be DR. */
  78. if (NBR_IS_DR (nbr))
  79. listnode_add (dr_list, nbr);
  80. /* Preserve neighbor BDR. */
  81. if (IPV4_ADDR_SAME (&BDR (oi), &nbr->address.u.prefix4))
  82. bdr = nbr;
  83. }
  84. /* Elect Designated Router. */
  85. if (listcount (dr_list) > 0)
  86. dr = ospf_dr_election_sub (dr_list);
  87. else
  88. dr = bdr;
  89. /* Set DR to interface. */
  90. if (dr)
  91. DR (oi) = dr->address.u.prefix4;
  92. else
  93. DR (oi).s_addr = 0;
  94. list_delete (dr_list);
  95. return dr;
  96. }
  97. static struct ospf_neighbor *
  98. ospf_elect_bdr (struct ospf_interface *oi, struct list *el_list)
  99. {
  100. struct list *bdr_list, *no_dr_list;
  101. struct listnode *node;
  102. struct ospf_neighbor *nbr, *bdr = NULL;
  103. bdr_list = list_new ();
  104. no_dr_list = list_new ();
  105. /* Add neighbors to the list. */
  106. for (ALL_LIST_ELEMENTS_RO (el_list, node, nbr))
  107. {
  108. /* neighbor declared to be DR. */
  109. if (NBR_IS_DR (nbr))
  110. continue;
  111. /* neighbor declared to be BDR. */
  112. if (NBR_IS_BDR (nbr))
  113. listnode_add (bdr_list, nbr);
  114. listnode_add (no_dr_list, nbr);
  115. }
  116. /* Elect Backup Designated Router. */
  117. if (listcount (bdr_list) > 0)
  118. bdr = ospf_dr_election_sub (bdr_list);
  119. else
  120. bdr = ospf_dr_election_sub (no_dr_list);
  121. /* Set BDR to interface. */
  122. if (bdr)
  123. BDR (oi) = bdr->address.u.prefix4;
  124. else
  125. BDR (oi).s_addr = 0;
  126. list_delete (bdr_list);
  127. list_delete (no_dr_list);
  128. return bdr;
  129. }
  130. static int
  131. ospf_ism_state (struct ospf_interface *oi)
  132. {
  133. if (IPV4_ADDR_SAME (&DR (oi), &oi->address->u.prefix4))
  134. return ISM_DR;
  135. else if (IPV4_ADDR_SAME (&BDR (oi), &oi->address->u.prefix4))
  136. return ISM_Backup;
  137. else
  138. return ISM_DROther;
  139. }
  140. static void
  141. ospf_dr_eligible_routers (struct route_table *nbrs, struct list *el_list)
  142. {
  143. struct route_node *rn;
  144. struct ospf_neighbor *nbr;
  145. for (rn = route_top (nbrs); rn; rn = route_next (rn))
  146. if ((nbr = rn->info) != NULL)
  147. /* Ignore 0.0.0.0 node*/
  148. if (nbr->router_id.s_addr != 0)
  149. /* Is neighbor eligible? */
  150. if (nbr->priority > 0)
  151. /* Is neighbor upper 2-Way? */
  152. if (nbr->state >= NSM_TwoWay)
  153. listnode_add (el_list, nbr);
  154. }
  155. /* Generate AdjOK? NSM event. */
  156. static void
  157. ospf_dr_change (struct ospf *ospf, struct route_table *nbrs)
  158. {
  159. struct route_node *rn;
  160. struct ospf_neighbor *nbr;
  161. for (rn = route_top (nbrs); rn; rn = route_next (rn))
  162. if ((nbr = rn->info) != NULL)
  163. /* Ignore 0.0.0.0 node*/
  164. if (nbr->router_id.s_addr != 0)
  165. /* Is neighbor upper 2-Way? */
  166. if (nbr->state >= NSM_TwoWay)
  167. /* Ignore myself. */
  168. if (!IPV4_ADDR_SAME (&nbr->router_id, &ospf->router_id))
  169. OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_AdjOK);
  170. }
  171. static int
  172. ospf_dr_election (struct ospf_interface *oi)
  173. {
  174. struct in_addr old_dr, old_bdr;
  175. int old_state, new_state;
  176. struct list *el_list;
  177. /* backup current values. */
  178. old_dr = DR (oi);
  179. old_bdr = BDR (oi);
  180. old_state = oi->state;
  181. el_list = list_new ();
  182. /* List eligible routers. */
  183. ospf_dr_eligible_routers (oi->nbrs, el_list);
  184. /* First election of DR and BDR. */
  185. ospf_elect_bdr (oi, el_list);
  186. ospf_elect_dr (oi, el_list);
  187. new_state = ospf_ism_state (oi);
  188. zlog_debug ("DR-Election[1st]: Backup %s", inet_ntoa (BDR (oi)));
  189. zlog_debug ("DR-Election[1st]: DR %s", inet_ntoa (DR (oi)));
  190. if (new_state != old_state &&
  191. !(new_state == ISM_DROther && old_state < ISM_DROther))
  192. {
  193. ospf_elect_bdr (oi, el_list);
  194. ospf_elect_dr (oi, el_list);
  195. new_state = ospf_ism_state (oi);
  196. zlog_debug ("DR-Election[2nd]: Backup %s", inet_ntoa (BDR (oi)));
  197. zlog_debug ("DR-Election[2nd]: DR %s", inet_ntoa (DR (oi)));
  198. }
  199. list_delete (el_list);
  200. /* if DR or BDR changes, cause AdjOK? neighbor event. */
  201. if (!IPV4_ADDR_SAME (&old_dr, &DR (oi)) ||
  202. !IPV4_ADDR_SAME (&old_bdr, &BDR (oi)))
  203. ospf_dr_change (oi->ospf, oi->nbrs);
  204. return new_state;
  205. }
  206. int
  207. ospf_hello_timer (struct thread *thread)
  208. {
  209. struct ospf_interface *oi;
  210. oi = THREAD_ARG (thread);
  211. oi->t_hello = NULL;
  212. if (IS_DEBUG_OSPF (ism, ISM_TIMERS))
  213. zlog (NULL, LOG_DEBUG, "ISM[%s]: Timer (Hello timer expire)",
  214. IF_NAME (oi));
  215. /* Sending hello packet. */
  216. ospf_hello_send (oi);
  217. /* Hello timer set. */
  218. OSPF_HELLO_TIMER_ON (oi);
  219. return 0;
  220. }
  221. static int
  222. ospf_wait_timer (struct thread *thread)
  223. {
  224. struct ospf_interface *oi;
  225. oi = THREAD_ARG (thread);
  226. oi->t_wait = NULL;
  227. if (IS_DEBUG_OSPF (ism, ISM_TIMERS))
  228. zlog (NULL, LOG_DEBUG, "ISM[%s]: Timer (Wait timer expire)",
  229. IF_NAME (oi));
  230. OSPF_ISM_EVENT_SCHEDULE (oi, ISM_WaitTimer);
  231. return 0;
  232. }
  233. /* Hook function called after ospf ISM event is occured. And vty's
  234. network command invoke this function after making interface
  235. structure. */
  236. static void
  237. ism_timer_set (struct ospf_interface *oi)
  238. {
  239. switch (oi->state)
  240. {
  241. case ISM_Down:
  242. /* First entry point of ospf interface state machine. In this state
  243. interface parameters must be set to initial values, and timers are
  244. reset also. */
  245. OSPF_ISM_TIMER_OFF (oi->t_hello);
  246. OSPF_ISM_TIMER_OFF (oi->t_wait);
  247. OSPF_ISM_TIMER_OFF (oi->t_ls_ack);
  248. break;
  249. case ISM_Loopback:
  250. /* In this state, the interface may be looped back and will be
  251. unavailable for regular data traffic. */
  252. OSPF_ISM_TIMER_OFF (oi->t_hello);
  253. OSPF_ISM_TIMER_OFF (oi->t_wait);
  254. OSPF_ISM_TIMER_OFF (oi->t_ls_ack);
  255. break;
  256. case ISM_Waiting:
  257. /* The router is trying to determine the identity of DRouter and
  258. BDRouter. The router begin to receive and send Hello Packets. */
  259. /* send first hello immediately */
  260. OSPF_ISM_TIMER_MSEC_ON (oi->t_hello, ospf_hello_timer, 1);
  261. OSPF_ISM_TIMER_ON (oi->t_wait, ospf_wait_timer,
  262. OSPF_IF_PARAM (oi, v_wait));
  263. OSPF_ISM_TIMER_OFF (oi->t_ls_ack);
  264. break;
  265. case ISM_PointToPoint:
  266. /* The interface connects to a physical Point-to-point network or
  267. virtual link. The router attempts to form an adjacency with
  268. neighboring router. Hello packets are also sent. */
  269. /* send first hello immediately */
  270. OSPF_ISM_TIMER_MSEC_ON (oi->t_hello, ospf_hello_timer, 1);
  271. OSPF_ISM_TIMER_OFF (oi->t_wait);
  272. OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack);
  273. break;
  274. case ISM_DROther:
  275. /* The network type of the interface is broadcast or NBMA network,
  276. and the router itself is neither Designated Router nor
  277. Backup Designated Router. */
  278. OSPF_HELLO_TIMER_ON (oi);
  279. OSPF_ISM_TIMER_OFF (oi->t_wait);
  280. OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack);
  281. break;
  282. case ISM_Backup:
  283. /* The network type of the interface is broadcast os NBMA network,
  284. and the router is Backup Designated Router. */
  285. OSPF_HELLO_TIMER_ON (oi);
  286. OSPF_ISM_TIMER_OFF (oi->t_wait);
  287. OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack);
  288. break;
  289. case ISM_DR:
  290. /* The network type of the interface is broadcast or NBMA network,
  291. and the router is Designated Router. */
  292. OSPF_HELLO_TIMER_ON (oi);
  293. OSPF_ISM_TIMER_OFF (oi->t_wait);
  294. OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack);
  295. break;
  296. }
  297. }
  298. static int
  299. ism_interface_up (struct ospf_interface *oi)
  300. {
  301. int next_state = 0;
  302. /* if network type is point-to-point, Point-to-MultiPoint or virtual link,
  303. the state transitions to Point-to-Point. */
  304. if (oi->type == OSPF_IFTYPE_POINTOPOINT ||
  305. oi->type == OSPF_IFTYPE_POINTOMULTIPOINT ||
  306. oi->type == OSPF_IFTYPE_VIRTUALLINK)
  307. next_state = ISM_PointToPoint;
  308. /* Else if the router is not eligible to DR, the state transitions to
  309. DROther. */
  310. else if (PRIORITY (oi) == 0) /* router is eligible? */
  311. next_state = ISM_DROther;
  312. else
  313. /* Otherwise, the state transitions to Waiting. */
  314. next_state = ISM_Waiting;
  315. if (oi->type == OSPF_IFTYPE_NBMA)
  316. ospf_nbr_nbma_if_update (oi->ospf, oi);
  317. /* ospf_ism_event (t); */
  318. return next_state;
  319. }
  320. static int
  321. ism_loop_ind (struct ospf_interface *oi)
  322. {
  323. int ret = 0;
  324. /* call ism_interface_down. */
  325. /* ret = ism_interface_down (oi); */
  326. return ret;
  327. }
  328. /* Interface down event handler. */
  329. static int
  330. ism_interface_down (struct ospf_interface *oi)
  331. {
  332. ospf_if_cleanup (oi);
  333. return 0;
  334. }
  335. static int
  336. ism_backup_seen (struct ospf_interface *oi)
  337. {
  338. return ospf_dr_election (oi);
  339. }
  340. static int
  341. ism_wait_timer (struct ospf_interface *oi)
  342. {
  343. return ospf_dr_election (oi);
  344. }
  345. static int
  346. ism_neighbor_change (struct ospf_interface *oi)
  347. {
  348. return ospf_dr_election (oi);
  349. }
  350. static int
  351. ism_ignore (struct ospf_interface *oi)
  352. {
  353. if (IS_DEBUG_OSPF (ism, ISM_EVENTS))
  354. zlog (NULL, LOG_DEBUG, "ISM[%s]: ism_ignore called", IF_NAME (oi));
  355. return 0;
  356. }
  357. /* Interface State Machine */
  358. struct {
  359. int (*func) (struct ospf_interface *);
  360. int next_state;
  361. } ISM [OSPF_ISM_STATE_MAX][OSPF_ISM_EVENT_MAX] =
  362. {
  363. {
  364. /* DependUpon: dummy state. */
  365. { ism_ignore, ISM_DependUpon }, /* NoEvent */
  366. { ism_ignore, ISM_DependUpon }, /* InterfaceUp */
  367. { ism_ignore, ISM_DependUpon }, /* WaitTimer */
  368. { ism_ignore, ISM_DependUpon }, /* BackupSeen */
  369. { ism_ignore, ISM_DependUpon }, /* NeighborChange */
  370. { ism_ignore, ISM_DependUpon }, /* LoopInd */
  371. { ism_ignore, ISM_DependUpon }, /* UnloopInd */
  372. { ism_ignore, ISM_DependUpon }, /* InterfaceDown */
  373. },
  374. {
  375. /* Down:*/
  376. { ism_ignore, ISM_DependUpon }, /* NoEvent */
  377. { ism_interface_up, ISM_DependUpon }, /* InterfaceUp */
  378. { ism_ignore, ISM_Down }, /* WaitTimer */
  379. { ism_ignore, ISM_Down }, /* BackupSeen */
  380. { ism_ignore, ISM_Down }, /* NeighborChange */
  381. { ism_loop_ind, ISM_Loopback }, /* LoopInd */
  382. { ism_ignore, ISM_Down }, /* UnloopInd */
  383. { ism_interface_down, ISM_Down }, /* InterfaceDown */
  384. },
  385. {
  386. /* Loopback: */
  387. { ism_ignore, ISM_DependUpon }, /* NoEvent */
  388. { ism_ignore, ISM_Loopback }, /* InterfaceUp */
  389. { ism_ignore, ISM_Loopback }, /* WaitTimer */
  390. { ism_ignore, ISM_Loopback }, /* BackupSeen */
  391. { ism_ignore, ISM_Loopback }, /* NeighborChange */
  392. { ism_ignore, ISM_Loopback }, /* LoopInd */
  393. { ism_ignore, ISM_Down }, /* UnloopInd */
  394. { ism_interface_down, ISM_Down }, /* InterfaceDown */
  395. },
  396. {
  397. /* Waiting: */
  398. { ism_ignore, ISM_DependUpon }, /* NoEvent */
  399. { ism_ignore, ISM_Waiting }, /* InterfaceUp */
  400. { ism_wait_timer, ISM_DependUpon }, /* WaitTimer */
  401. { ism_backup_seen, ISM_DependUpon }, /* BackupSeen */
  402. { ism_ignore, ISM_Waiting }, /* NeighborChange */
  403. { ism_loop_ind, ISM_Loopback }, /* LoopInd */
  404. { ism_ignore, ISM_Waiting }, /* UnloopInd */
  405. { ism_interface_down, ISM_Down }, /* InterfaceDown */
  406. },
  407. {
  408. /* Point-to-Point: */
  409. { ism_ignore, ISM_DependUpon }, /* NoEvent */
  410. { ism_ignore, ISM_PointToPoint }, /* InterfaceUp */
  411. { ism_ignore, ISM_PointToPoint }, /* WaitTimer */
  412. { ism_ignore, ISM_PointToPoint }, /* BackupSeen */
  413. { ism_ignore, ISM_PointToPoint }, /* NeighborChange */
  414. { ism_loop_ind, ISM_Loopback }, /* LoopInd */
  415. { ism_ignore, ISM_PointToPoint }, /* UnloopInd */
  416. { ism_interface_down, ISM_Down }, /* InterfaceDown */
  417. },
  418. {
  419. /* DROther: */
  420. { ism_ignore, ISM_DependUpon }, /* NoEvent */
  421. { ism_ignore, ISM_DROther }, /* InterfaceUp */
  422. { ism_ignore, ISM_DROther }, /* WaitTimer */
  423. { ism_ignore, ISM_DROther }, /* BackupSeen */
  424. { ism_neighbor_change, ISM_DependUpon }, /* NeighborChange */
  425. { ism_loop_ind, ISM_Loopback }, /* LoopInd */
  426. { ism_ignore, ISM_DROther }, /* UnloopInd */
  427. { ism_interface_down, ISM_Down }, /* InterfaceDown */
  428. },
  429. {
  430. /* Backup: */
  431. { ism_ignore, ISM_DependUpon }, /* NoEvent */
  432. { ism_ignore, ISM_Backup }, /* InterfaceUp */
  433. { ism_ignore, ISM_Backup }, /* WaitTimer */
  434. { ism_ignore, ISM_Backup }, /* BackupSeen */
  435. { ism_neighbor_change, ISM_DependUpon }, /* NeighborChange */
  436. { ism_loop_ind, ISM_Loopback }, /* LoopInd */
  437. { ism_ignore, ISM_Backup }, /* UnloopInd */
  438. { ism_interface_down, ISM_Down }, /* InterfaceDown */
  439. },
  440. {
  441. /* DR: */
  442. { ism_ignore, ISM_DependUpon }, /* NoEvent */
  443. { ism_ignore, ISM_DR }, /* InterfaceUp */
  444. { ism_ignore, ISM_DR }, /* WaitTimer */
  445. { ism_ignore, ISM_DR }, /* BackupSeen */
  446. { ism_neighbor_change, ISM_DependUpon }, /* NeighborChange */
  447. { ism_loop_ind, ISM_Loopback }, /* LoopInd */
  448. { ism_ignore, ISM_DR }, /* UnloopInd */
  449. { ism_interface_down, ISM_Down }, /* InterfaceDown */
  450. },
  451. };
  452. static const char *ospf_ism_event_str[] =
  453. {
  454. "NoEvent",
  455. "InterfaceUp",
  456. "WaitTimer",
  457. "BackupSeen",
  458. "NeighborChange",
  459. "LoopInd",
  460. "UnLoopInd",
  461. "InterfaceDown",
  462. };
  463. static void
  464. ism_change_state (struct ospf_interface *oi, int state)
  465. {
  466. int old_state;
  467. struct ospf_lsa *lsa;
  468. /* Logging change of state. */
  469. if (IS_DEBUG_OSPF (ism, ISM_STATUS))
  470. zlog (NULL, LOG_DEBUG, "ISM[%s]: State change %s -> %s", IF_NAME (oi),
  471. LOOKUP (ospf_ism_state_msg, oi->state),
  472. LOOKUP (ospf_ism_state_msg, state));
  473. old_state = oi->state;
  474. oi->state = state;
  475. oi->state_change++;
  476. #ifdef HAVE_SNMP
  477. /* Terminal state or regression */
  478. if ((state == ISM_DR) || (state == ISM_Backup) || (state == ISM_DROther) ||
  479. (state == ISM_PointToPoint) || (state < old_state))
  480. {
  481. /* ospfVirtIfStateChange */
  482. if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
  483. ospfTrapVirtIfStateChange (oi);
  484. /* ospfIfStateChange */
  485. else
  486. ospfTrapIfStateChange (oi);
  487. }
  488. #endif
  489. /* Set multicast memberships appropriately for new state. */
  490. ospf_if_set_multicast(oi);
  491. if (old_state == ISM_Down || state == ISM_Down)
  492. ospf_check_abr_status (oi->ospf);
  493. /* Originate router-LSA. */
  494. if (state == ISM_Down)
  495. {
  496. if (oi->area->act_ints > 0)
  497. oi->area->act_ints--;
  498. }
  499. else if (old_state == ISM_Down)
  500. oi->area->act_ints++;
  501. /* schedule router-LSA originate. */
  502. ospf_router_lsa_update_area (oi->area);
  503. /* Originate network-LSA. */
  504. if (old_state != ISM_DR && state == ISM_DR)
  505. ospf_network_lsa_update (oi);
  506. else if (old_state == ISM_DR && state != ISM_DR)
  507. {
  508. /* Free self originated network LSA. */
  509. lsa = oi->network_lsa_self;
  510. if (lsa)
  511. ospf_lsa_flush_area (lsa, oi->area);
  512. ospf_lsa_unlock (&oi->network_lsa_self);
  513. oi->network_lsa_self = NULL;
  514. }
  515. ospf_opaque_ism_change (oi, old_state);
  516. /* Check area border status. */
  517. ospf_check_abr_status (oi->ospf);
  518. }
  519. /* Execute ISM event process. */
  520. int
  521. ospf_ism_event (struct thread *thread)
  522. {
  523. int event;
  524. int next_state;
  525. struct ospf_interface *oi;
  526. oi = THREAD_ARG (thread);
  527. event = THREAD_VAL (thread);
  528. /* Call function. */
  529. next_state = (*(ISM [oi->state][event].func))(oi);
  530. if (! next_state)
  531. next_state = ISM [oi->state][event].next_state;
  532. if (IS_DEBUG_OSPF (ism, ISM_EVENTS))
  533. zlog (NULL, LOG_DEBUG, "ISM[%s]: %s (%s)", IF_NAME (oi),
  534. LOOKUP (ospf_ism_state_msg, oi->state),
  535. ospf_ism_event_str[event]);
  536. /* If state is changed. */
  537. if (next_state != oi->state)
  538. ism_change_state (oi, next_state);
  539. /* Make sure timer is set. */
  540. ism_timer_set (oi);
  541. return 0;
  542. }