ospf_ism.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  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. struct ospf_neighbor *dr, *bdr;
  178. /* backup current values. */
  179. old_dr = DR (oi);
  180. old_bdr = BDR (oi);
  181. old_state = oi->state;
  182. el_list = list_new ();
  183. /* List eligible routers. */
  184. ospf_dr_eligible_routers (oi->nbrs, el_list);
  185. /* First election of DR and BDR. */
  186. bdr = ospf_elect_bdr (oi, el_list);
  187. dr = ospf_elect_dr (oi, el_list);
  188. new_state = ospf_ism_state (oi);
  189. zlog_info ("DR-Election[1st]: Backup %s", inet_ntoa (BDR (oi)));
  190. zlog_info ("DR-Election[1st]: DR %s", inet_ntoa (DR (oi)));
  191. if (new_state != old_state &&
  192. !(new_state == ISM_DROther && old_state < ISM_DROther))
  193. {
  194. ospf_elect_bdr (oi, el_list);
  195. ospf_elect_dr (oi, el_list);
  196. new_state = ospf_ism_state (oi);
  197. zlog_info ("DR-Election[2nd]: Backup %s", inet_ntoa (BDR (oi)));
  198. zlog_info ("DR-Election[2nd]: DR %s", inet_ntoa (DR (oi)));
  199. }
  200. list_delete (el_list);
  201. /* if DR or BDR changes, cause AdjOK? neighbor event. */
  202. if (!IPV4_ADDR_SAME (&old_dr, &DR (oi)) ||
  203. !IPV4_ADDR_SAME (&old_bdr, &BDR (oi)))
  204. ospf_dr_change (oi->ospf, oi->nbrs);
  205. return new_state;
  206. }
  207. int
  208. ospf_hello_timer (struct thread *thread)
  209. {
  210. struct ospf_interface *oi;
  211. oi = THREAD_ARG (thread);
  212. oi->t_hello = NULL;
  213. if (IS_DEBUG_OSPF (ism, ISM_TIMERS))
  214. zlog (NULL, LOG_DEBUG, "ISM[%s]: Timer (Hello timer expire)",
  215. IF_NAME (oi));
  216. /* Sending hello packet. */
  217. ospf_hello_send (oi);
  218. /* Hello timer set. */
  219. OSPF_HELLO_TIMER_ON (oi);
  220. return 0;
  221. }
  222. static int
  223. ospf_wait_timer (struct thread *thread)
  224. {
  225. struct ospf_interface *oi;
  226. oi = THREAD_ARG (thread);
  227. oi->t_wait = NULL;
  228. if (IS_DEBUG_OSPF (ism, ISM_TIMERS))
  229. zlog (NULL, LOG_DEBUG, "ISM[%s]: Timer (Wait timer expire)",
  230. IF_NAME (oi));
  231. OSPF_ISM_EVENT_SCHEDULE (oi, ISM_WaitTimer);
  232. return 0;
  233. }
  234. /* Hook function called after ospf ISM event is occured. And vty's
  235. network command invoke this function after making interface
  236. structure. */
  237. static void
  238. ism_timer_set (struct ospf_interface *oi)
  239. {
  240. switch (oi->state)
  241. {
  242. case ISM_Down:
  243. /* First entry point of ospf interface state machine. In this state
  244. interface parameters must be set to initial values, and timers are
  245. reset also. */
  246. OSPF_ISM_TIMER_OFF (oi->t_hello);
  247. OSPF_ISM_TIMER_OFF (oi->t_wait);
  248. OSPF_ISM_TIMER_OFF (oi->t_ls_ack);
  249. break;
  250. case ISM_Loopback:
  251. /* In this state, the interface may be looped back and will be
  252. unavailable for regular data traffic. */
  253. OSPF_ISM_TIMER_OFF (oi->t_hello);
  254. OSPF_ISM_TIMER_OFF (oi->t_wait);
  255. OSPF_ISM_TIMER_OFF (oi->t_ls_ack);
  256. break;
  257. case ISM_Waiting:
  258. /* The router is trying to determine the identity of DRouter and
  259. BDRouter. The router begin to receive and send Hello Packets. */
  260. /* send first hello immediately */
  261. OSPF_ISM_TIMER_MSEC_ON (oi->t_hello, ospf_hello_timer, 1);
  262. OSPF_ISM_TIMER_ON (oi->t_wait, ospf_wait_timer,
  263. OSPF_IF_PARAM (oi, v_wait));
  264. OSPF_ISM_TIMER_OFF (oi->t_ls_ack);
  265. break;
  266. case ISM_PointToPoint:
  267. /* The interface connects to a physical Point-to-point network or
  268. virtual link. The router attempts to form an adjacency with
  269. neighboring router. Hello packets are also sent. */
  270. /* send first hello immediately */
  271. OSPF_ISM_TIMER_MSEC_ON (oi->t_hello, ospf_hello_timer, 1);
  272. OSPF_ISM_TIMER_OFF (oi->t_wait);
  273. OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack);
  274. break;
  275. case ISM_DROther:
  276. /* The network type of the interface is broadcast or NBMA network,
  277. and the router itself is neither Designated Router nor
  278. Backup Designated Router. */
  279. OSPF_HELLO_TIMER_ON (oi);
  280. OSPF_ISM_TIMER_OFF (oi->t_wait);
  281. OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack);
  282. break;
  283. case ISM_Backup:
  284. /* The network type of the interface is broadcast os NBMA network,
  285. and the router is Backup Designated Router. */
  286. OSPF_HELLO_TIMER_ON (oi);
  287. OSPF_ISM_TIMER_OFF (oi->t_wait);
  288. OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack);
  289. break;
  290. case ISM_DR:
  291. /* The network type of the interface is broadcast or NBMA network,
  292. and the router is Designated Router. */
  293. OSPF_HELLO_TIMER_ON (oi);
  294. OSPF_ISM_TIMER_OFF (oi->t_wait);
  295. OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack);
  296. break;
  297. }
  298. }
  299. static int
  300. ism_interface_up (struct ospf_interface *oi)
  301. {
  302. int next_state = 0;
  303. /* if network type is point-to-point, Point-to-MultiPoint or virtual link,
  304. the state transitions to Point-to-Point. */
  305. if (oi->type == OSPF_IFTYPE_POINTOPOINT ||
  306. oi->type == OSPF_IFTYPE_POINTOMULTIPOINT ||
  307. oi->type == OSPF_IFTYPE_VIRTUALLINK)
  308. next_state = ISM_PointToPoint;
  309. /* Else if the router is not eligible to DR, the state transitions to
  310. DROther. */
  311. else if (PRIORITY (oi) == 0) /* router is eligible? */
  312. next_state = ISM_DROther;
  313. else
  314. /* Otherwise, the state transitions to Waiting. */
  315. next_state = ISM_Waiting;
  316. if (oi->type == OSPF_IFTYPE_NBMA)
  317. ospf_nbr_nbma_if_update (oi->ospf, oi);
  318. /* ospf_ism_event (t); */
  319. return next_state;
  320. }
  321. static int
  322. ism_loop_ind (struct ospf_interface *oi)
  323. {
  324. int ret = 0;
  325. /* call ism_interface_down. */
  326. /* ret = ism_interface_down (oi); */
  327. return ret;
  328. }
  329. /* Interface down event handler. */
  330. static int
  331. ism_interface_down (struct ospf_interface *oi)
  332. {
  333. ospf_if_cleanup (oi);
  334. return 0;
  335. }
  336. static int
  337. ism_backup_seen (struct ospf_interface *oi)
  338. {
  339. return ospf_dr_election (oi);
  340. }
  341. static int
  342. ism_wait_timer (struct ospf_interface *oi)
  343. {
  344. return ospf_dr_election (oi);
  345. }
  346. static int
  347. ism_neighbor_change (struct ospf_interface *oi)
  348. {
  349. return ospf_dr_election (oi);
  350. }
  351. static int
  352. ism_ignore (struct ospf_interface *oi)
  353. {
  354. if (IS_DEBUG_OSPF (ism, ISM_EVENTS))
  355. zlog (NULL, LOG_DEBUG, "ISM[%s]: ism_ignore called", IF_NAME (oi));
  356. return 0;
  357. }
  358. /* Interface State Machine */
  359. struct {
  360. int (*func) (struct ospf_interface *);
  361. int next_state;
  362. } ISM [OSPF_ISM_STATE_MAX][OSPF_ISM_EVENT_MAX] =
  363. {
  364. {
  365. /* DependUpon: dummy state. */
  366. { ism_ignore, ISM_DependUpon }, /* NoEvent */
  367. { ism_ignore, ISM_DependUpon }, /* InterfaceUp */
  368. { ism_ignore, ISM_DependUpon }, /* WaitTimer */
  369. { ism_ignore, ISM_DependUpon }, /* BackupSeen */
  370. { ism_ignore, ISM_DependUpon }, /* NeighborChange */
  371. { ism_ignore, ISM_DependUpon }, /* LoopInd */
  372. { ism_ignore, ISM_DependUpon }, /* UnloopInd */
  373. { ism_ignore, ISM_DependUpon }, /* InterfaceDown */
  374. },
  375. {
  376. /* Down:*/
  377. { ism_ignore, ISM_DependUpon }, /* NoEvent */
  378. { ism_interface_up, ISM_DependUpon }, /* InterfaceUp */
  379. { ism_ignore, ISM_Down }, /* WaitTimer */
  380. { ism_ignore, ISM_Down }, /* BackupSeen */
  381. { ism_ignore, ISM_Down }, /* NeighborChange */
  382. { ism_loop_ind, ISM_Loopback }, /* LoopInd */
  383. { ism_ignore, ISM_Down }, /* UnloopInd */
  384. { ism_interface_down, ISM_Down }, /* InterfaceDown */
  385. },
  386. {
  387. /* Loopback: */
  388. { ism_ignore, ISM_DependUpon }, /* NoEvent */
  389. { ism_ignore, ISM_Loopback }, /* InterfaceUp */
  390. { ism_ignore, ISM_Loopback }, /* WaitTimer */
  391. { ism_ignore, ISM_Loopback }, /* BackupSeen */
  392. { ism_ignore, ISM_Loopback }, /* NeighborChange */
  393. { ism_ignore, ISM_Loopback }, /* LoopInd */
  394. { ism_ignore, ISM_Down }, /* UnloopInd */
  395. { ism_interface_down, ISM_Down }, /* InterfaceDown */
  396. },
  397. {
  398. /* Waiting: */
  399. { ism_ignore, ISM_DependUpon }, /* NoEvent */
  400. { ism_ignore, ISM_Waiting }, /* InterfaceUp */
  401. { ism_wait_timer, ISM_DependUpon }, /* WaitTimer */
  402. { ism_backup_seen, ISM_DependUpon }, /* BackupSeen */
  403. { ism_ignore, ISM_Waiting }, /* NeighborChange */
  404. { ism_loop_ind, ISM_Loopback }, /* LoopInd */
  405. { ism_ignore, ISM_Waiting }, /* UnloopInd */
  406. { ism_interface_down, ISM_Down }, /* InterfaceDown */
  407. },
  408. {
  409. /* Point-to-Point: */
  410. { ism_ignore, ISM_DependUpon }, /* NoEvent */
  411. { ism_ignore, ISM_PointToPoint }, /* InterfaceUp */
  412. { ism_ignore, ISM_PointToPoint }, /* WaitTimer */
  413. { ism_ignore, ISM_PointToPoint }, /* BackupSeen */
  414. { ism_ignore, ISM_PointToPoint }, /* NeighborChange */
  415. { ism_loop_ind, ISM_Loopback }, /* LoopInd */
  416. { ism_ignore, ISM_PointToPoint }, /* UnloopInd */
  417. { ism_interface_down, ISM_Down }, /* InterfaceDown */
  418. },
  419. {
  420. /* DROther: */
  421. { ism_ignore, ISM_DependUpon }, /* NoEvent */
  422. { ism_ignore, ISM_DROther }, /* InterfaceUp */
  423. { ism_ignore, ISM_DROther }, /* WaitTimer */
  424. { ism_ignore, ISM_DROther }, /* BackupSeen */
  425. { ism_neighbor_change, ISM_DependUpon }, /* NeighborChange */
  426. { ism_loop_ind, ISM_Loopback }, /* LoopInd */
  427. { ism_ignore, ISM_DROther }, /* UnloopInd */
  428. { ism_interface_down, ISM_Down }, /* InterfaceDown */
  429. },
  430. {
  431. /* Backup: */
  432. { ism_ignore, ISM_DependUpon }, /* NoEvent */
  433. { ism_ignore, ISM_Backup }, /* InterfaceUp */
  434. { ism_ignore, ISM_Backup }, /* WaitTimer */
  435. { ism_ignore, ISM_Backup }, /* BackupSeen */
  436. { ism_neighbor_change, ISM_DependUpon }, /* NeighborChange */
  437. { ism_loop_ind, ISM_Loopback }, /* LoopInd */
  438. { ism_ignore, ISM_Backup }, /* UnloopInd */
  439. { ism_interface_down, ISM_Down }, /* InterfaceDown */
  440. },
  441. {
  442. /* DR: */
  443. { ism_ignore, ISM_DependUpon }, /* NoEvent */
  444. { ism_ignore, ISM_DR }, /* InterfaceUp */
  445. { ism_ignore, ISM_DR }, /* WaitTimer */
  446. { ism_ignore, ISM_DR }, /* BackupSeen */
  447. { ism_neighbor_change, ISM_DependUpon }, /* NeighborChange */
  448. { ism_loop_ind, ISM_Loopback }, /* LoopInd */
  449. { ism_ignore, ISM_DR }, /* UnloopInd */
  450. { ism_interface_down, ISM_Down }, /* InterfaceDown */
  451. },
  452. };
  453. static const char *ospf_ism_event_str[] =
  454. {
  455. "NoEvent",
  456. "InterfaceUp",
  457. "WaitTimer",
  458. "BackupSeen",
  459. "NeighborChange",
  460. "LoopInd",
  461. "UnLoopInd",
  462. "InterfaceDown",
  463. };
  464. static void
  465. ism_change_state (struct ospf_interface *oi, int state)
  466. {
  467. int old_state;
  468. struct ospf_lsa *lsa;
  469. /* Logging change of state. */
  470. if (IS_DEBUG_OSPF (ism, ISM_STATUS))
  471. zlog (NULL, LOG_DEBUG, "ISM[%s]: State change %s -> %s", IF_NAME (oi),
  472. LOOKUP (ospf_ism_state_msg, oi->state),
  473. LOOKUP (ospf_ism_state_msg, state));
  474. old_state = oi->state;
  475. oi->state = state;
  476. oi->state_change++;
  477. #ifdef HAVE_SNMP
  478. /* Terminal state or regression */
  479. if ((state == ISM_DR) || (state == ISM_Backup) || (state == ISM_DROther) ||
  480. (state == ISM_PointToPoint) || (state < old_state))
  481. {
  482. /* ospfVirtIfStateChange */
  483. if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
  484. ospfTrapVirtIfStateChange (oi);
  485. /* ospfIfStateChange */
  486. else
  487. ospfTrapIfStateChange (oi);
  488. }
  489. #endif
  490. /* Set multicast memberships appropriately for new state. */
  491. ospf_if_set_multicast(oi);
  492. if (old_state == ISM_Down || state == ISM_Down)
  493. ospf_check_abr_status (oi->ospf);
  494. /* Originate router-LSA. */
  495. if (state == ISM_Down)
  496. {
  497. if (oi->area->act_ints > 0)
  498. oi->area->act_ints--;
  499. }
  500. else if (old_state == ISM_Down)
  501. oi->area->act_ints++;
  502. /* schedule router-LSA originate. */
  503. ospf_router_lsa_timer_add (oi->area);
  504. /* Originate network-LSA. */
  505. if (old_state != ISM_DR && state == ISM_DR)
  506. ospf_network_lsa_timer_add (oi);
  507. else if (old_state == ISM_DR && state != ISM_DR)
  508. {
  509. /* Free self originated network LSA. */
  510. lsa = oi->network_lsa_self;
  511. if (lsa)
  512. {
  513. ospf_lsa_flush_area (lsa, oi->area);
  514. OSPF_TIMER_OFF (oi->t_network_lsa_self);
  515. }
  516. ospf_lsa_unlock (&oi->network_lsa_self);
  517. oi->network_lsa_self = NULL;
  518. }
  519. #ifdef HAVE_OPAQUE_LSA
  520. ospf_opaque_ism_change (oi, old_state);
  521. #endif /* HAVE_OPAQUE_LSA */
  522. /* Check area border status. */
  523. ospf_check_abr_status (oi->ospf);
  524. }
  525. /* Execute ISM event process. */
  526. int
  527. ospf_ism_event (struct thread *thread)
  528. {
  529. int event;
  530. int next_state;
  531. struct ospf_interface *oi;
  532. oi = THREAD_ARG (thread);
  533. event = THREAD_VAL (thread);
  534. /* Call function. */
  535. next_state = (*(ISM [oi->state][event].func))(oi);
  536. if (! next_state)
  537. next_state = ISM [oi->state][event].next_state;
  538. if (IS_DEBUG_OSPF (ism, ISM_EVENTS))
  539. zlog (NULL, LOG_DEBUG, "ISM[%s]: %s (%s)", IF_NAME (oi),
  540. LOOKUP (ospf_ism_state_msg, oi->state),
  541. ospf_ism_event_str[event]);
  542. /* If state is changed. */
  543. if (next_state != oi->state)
  544. ism_change_state (oi, next_state);
  545. /* Make sure timer is set. */
  546. ism_timer_set (oi);
  547. return 0;
  548. }