blob: b43d885507e1f26611c5698064cb246ca1eb2a12 [file] [log] [blame]
paul2d598362003-01-17 23:48:42 +00001/*
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
24#include <zebra.h>
25
26#include "thread.h"
27#include "memory.h"
28#include "hash.h"
29#include "linklist.h"
30#include "prefix.h"
31#include "if.h"
32#include "table.h"
33#include "stream.h"
34#include "table.h"
35#include "log.h"
36
37#include "ospfd/ospfd.h"
38#include "ospfd/ospf_interface.h"
39#include "ospfd/ospf_ism.h"
40#include "ospfd/ospf_asbr.h"
41#include "ospfd/ospf_lsa.h"
42#include "ospfd/ospf_lsdb.h"
43#include "ospfd/ospf_neighbor.h"
44#include "ospfd/ospf_nsm.h"
45#include "ospfd/ospf_network.h"
46#include "ospfd/ospf_packet.h"
47#include "ospfd/ospf_dump.h"
48#include "ospfd/ospf_flood.h"
49#include "ospfd/ospf_abr.h"
vincent5e4914c2005-09-29 16:34:30 +000050#include "ospfd/ospf_snmp.h"
paul2d598362003-01-17 23:48:42 +000051
Paul Jakmad1b1cd82006-07-04 13:50:44 +000052static void nsm_clear_adj (struct ospf_neighbor *);
David Lamparter6b0655a2014-06-04 06:53:35 +020053
paul2d598362003-01-17 23:48:42 +000054/* OSPF NSM Timer functions. */
paul4dadc292005-05-06 21:37:42 +000055static int
paul2d598362003-01-17 23:48:42 +000056ospf_inactivity_timer (struct thread *thread)
57{
58 struct ospf_neighbor *nbr;
59
60 nbr = THREAD_ARG (thread);
61 nbr->t_inactivity = NULL;
62
63 if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
64 zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (Inactivity timer expire)",
65 IF_NAME (nbr->oi), inet_ntoa (nbr->router_id));
66
67 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_InactivityTimer);
68
69 return 0;
70}
71
paul4dadc292005-05-06 21:37:42 +000072static int
paul2d598362003-01-17 23:48:42 +000073ospf_db_desc_timer (struct thread *thread)
74{
paul2d598362003-01-17 23:48:42 +000075 struct ospf_neighbor *nbr;
76
77 nbr = THREAD_ARG (thread);
78 nbr->t_db_desc = NULL;
79
paul2d598362003-01-17 23:48:42 +000080 if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
ajs2a42e282004-12-08 18:43:03 +000081 zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (DD Retransmit timer expire)",
paul2d598362003-01-17 23:48:42 +000082 IF_NAME (nbr->oi), inet_ntoa (nbr->src));
83
84 /* resent last send DD packet. */
85 assert (nbr->last_send);
86 ospf_db_desc_resend (nbr);
87
88 /* DD Retransmit timer set. */
89 OSPF_NSM_TIMER_ON (nbr->t_db_desc, ospf_db_desc_timer, nbr->v_db_desc);
90
91 return 0;
92}
93
Paul Jakma1f2c2742006-07-10 07:45:13 +000094/* Hook function called after ospf NSM event is occured.
95 *
96 * Set/clear any timers whose condition is implicit to the neighbour
97 * state. There may be other timers which are set/unset according to other
98 * state.
99 *
100 * We rely on this function to properly clear timers in lower states,
101 * particularly before deleting a neighbour.
102 */
paul4dadc292005-05-06 21:37:42 +0000103static void
paul2d598362003-01-17 23:48:42 +0000104nsm_timer_set (struct ospf_neighbor *nbr)
105{
106 switch (nbr->state)
107 {
Paul Jakma1f2c2742006-07-10 07:45:13 +0000108 case NSM_Deleted:
paul2d598362003-01-17 23:48:42 +0000109 case NSM_Down:
Paul Jakmae55dd532006-07-04 13:46:14 +0000110 OSPF_NSM_TIMER_OFF (nbr->t_inactivity);
Paul Jakma1f2c2742006-07-10 07:45:13 +0000111 OSPF_NSM_TIMER_OFF (nbr->t_hello_reply);
paul2d598362003-01-17 23:48:42 +0000112 case NSM_Attempt:
paul2d598362003-01-17 23:48:42 +0000113 case NSM_Init:
paul2d598362003-01-17 23:48:42 +0000114 case NSM_TwoWay:
115 OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
116 OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
Paul Jakmae55dd532006-07-04 13:46:14 +0000117 OSPF_NSM_TIMER_OFF (nbr->t_ls_req);
paul2d598362003-01-17 23:48:42 +0000118 break;
119 case NSM_ExStart:
120 OSPF_NSM_TIMER_ON (nbr->t_db_desc, ospf_db_desc_timer, nbr->v_db_desc);
121 OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
Paul Jakmae55dd532006-07-04 13:46:14 +0000122 OSPF_NSM_TIMER_OFF (nbr->t_ls_req);
paul2d598362003-01-17 23:48:42 +0000123 break;
124 case NSM_Exchange:
125 OSPF_NSM_TIMER_ON (nbr->t_ls_upd, ospf_ls_upd_timer, nbr->v_ls_upd);
126 if (!IS_SET_DD_MS (nbr->dd_flags))
127 OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
128 break;
129 case NSM_Loading:
paul2d598362003-01-17 23:48:42 +0000130 case NSM_Full:
paul2d598362003-01-17 23:48:42 +0000131 default:
132 OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
133 break;
134 }
135}
136
Paul Jakmad7b0fb62006-07-04 13:35:24 +0000137/* 10.4 of RFC2328, indicate whether an adjacency is appropriate with
138 * the given neighbour
139 */
140static int
141nsm_should_adj (struct ospf_neighbor *nbr)
142{
Paul Jakmaf7a76ab2006-07-04 13:57:49 +0000143 struct ospf_interface *oi = nbr->oi;
Paul Jakmad7b0fb62006-07-04 13:35:24 +0000144
Paul Jakmaf7a76ab2006-07-04 13:57:49 +0000145 /* These network types must always form adjacencies. */
Paul Jakmad7b0fb62006-07-04 13:35:24 +0000146 if (oi->type == OSPF_IFTYPE_POINTOPOINT
147 || oi->type == OSPF_IFTYPE_POINTOMULTIPOINT
Paul Jakmaf7a76ab2006-07-04 13:57:49 +0000148 || oi->type == OSPF_IFTYPE_VIRTUALLINK
149 /* Router itself is the DRouter or the BDRouter. */
150 || IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))
151 || IPV4_ADDR_SAME (&oi->address->u.prefix4, &BDR (oi))
152 /* Neighboring Router is the DRouter or the BDRouter. */
153 || IPV4_ADDR_SAME (&nbr->address.u.prefix4, &DR (oi))
Paul Jakmad7b0fb62006-07-04 13:35:24 +0000154 || IPV4_ADDR_SAME (&nbr->address.u.prefix4, &BDR (oi)))
155 return 1;
156
157 return 0;
158}
David Lamparter6b0655a2014-06-04 06:53:35 +0200159
paul2d598362003-01-17 23:48:42 +0000160/* OSPF NSM functions. */
paul4dadc292005-05-06 21:37:42 +0000161static int
Paul Jakma57c5c652010-01-07 06:12:53 +0000162nsm_packet_received (struct ospf_neighbor *nbr)
paul2d598362003-01-17 23:48:42 +0000163{
164 /* Start or Restart Inactivity Timer. */
165 OSPF_NSM_TIMER_OFF (nbr->t_inactivity);
166
167 OSPF_NSM_TIMER_ON (nbr->t_inactivity, ospf_inactivity_timer,
168 nbr->v_inactivity);
169
170 if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma)
171 OSPF_POLL_TIMER_OFF (nbr->nbr_nbma->t_poll);
172
173 return 0;
174}
175
paul4dadc292005-05-06 21:37:42 +0000176static int
paul2d598362003-01-17 23:48:42 +0000177nsm_start (struct ospf_neighbor *nbr)
178{
paul2d598362003-01-17 23:48:42 +0000179 if (nbr->nbr_nbma)
180 OSPF_POLL_TIMER_OFF (nbr->nbr_nbma->t_poll);
181
182 OSPF_NSM_TIMER_OFF (nbr->t_inactivity);
183
184 OSPF_NSM_TIMER_ON (nbr->t_inactivity, ospf_inactivity_timer,
185 nbr->v_inactivity);
186
187 return 0;
188}
189
paul4dadc292005-05-06 21:37:42 +0000190static int
paul2d598362003-01-17 23:48:42 +0000191nsm_twoway_received (struct ospf_neighbor *nbr)
192{
Paul Jakmaf7a76ab2006-07-04 13:57:49 +0000193 return (nsm_should_adj (nbr) ? NSM_ExStart : NSM_TwoWay);
paul2d598362003-01-17 23:48:42 +0000194}
195
196int
197ospf_db_summary_count (struct ospf_neighbor *nbr)
198{
199 return ospf_lsdb_count_all (&nbr->db_sum);
200}
201
202int
203ospf_db_summary_isempty (struct ospf_neighbor *nbr)
204{
205 return ospf_lsdb_isempty (&nbr->db_sum);
206}
207
paul4dadc292005-05-06 21:37:42 +0000208static int
paul68980082003-03-25 05:07:42 +0000209ospf_db_summary_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
paul2d598362003-01-17 23:48:42 +0000210{
paul09e4efd2003-01-18 00:12:02 +0000211 switch (lsa->data->type)
212 {
213 case OSPF_OPAQUE_LINK_LSA:
214 /* Exclude type-9 LSAs that does not have the same "oi" with "nbr". */
Paul Jakmad71ea652011-03-22 15:23:55 +0000215 if (nbr->oi && ospf_if_exists (lsa->oi) != nbr->oi)
paul09e4efd2003-01-18 00:12:02 +0000216 return 0;
217 break;
218 case OSPF_OPAQUE_AREA_LSA:
219 /*
220 * It is assured by the caller function "nsm_negotiation_done()"
221 * that every given LSA belongs to the same area with "nbr".
222 */
223 break;
224 case OSPF_OPAQUE_AS_LSA:
225 default:
226 break;
227 }
paul09e4efd2003-01-18 00:12:02 +0000228
paul2d598362003-01-17 23:48:42 +0000229 /* Stay away from any Local Translated Type-7 LSAs */
230 if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
231 return 0;
paul2d598362003-01-17 23:48:42 +0000232
233 if (IS_LSA_MAXAGE (lsa))
234 ospf_ls_retransmit_add (nbr, lsa);
235 else
236 ospf_lsdb_add (&nbr->db_sum, lsa);
237
238 return 0;
239}
240
241void
242ospf_db_summary_clear (struct ospf_neighbor *nbr)
243{
244 struct ospf_lsdb *lsdb;
245 int i;
246
247 lsdb = &nbr->db_sum;
248 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
249 {
250 struct route_table *table = lsdb->type[i].db;
251 struct route_node *rn;
252
253 for (rn = route_top (table); rn; rn = route_next (rn))
254 if (rn->info)
255 ospf_lsdb_delete (&nbr->db_sum, rn->info);
256 }
257}
258
David Lamparter6b0655a2014-06-04 06:53:35 +0200259
paul2d598362003-01-17 23:48:42 +0000260
paul2d598362003-01-17 23:48:42 +0000261/* The area link state database consists of the router-LSAs,
262 network-LSAs and summary-LSAs contained in the area structure,
paul68980082003-03-25 05:07:42 +0000263 along with the AS-external-LSAs contained in the global structure.
264 AS-external-LSAs are omitted from a virtual neighbor's Database
paul2d598362003-01-17 23:48:42 +0000265 summary list. AS-external-LSAs are omitted from the Database
266 summary list if the area has been configured as a stub. */
paul4dadc292005-05-06 21:37:42 +0000267static int
paul2d598362003-01-17 23:48:42 +0000268nsm_negotiation_done (struct ospf_neighbor *nbr)
269{
paul68980082003-03-25 05:07:42 +0000270 struct ospf_area *area = nbr->oi->area;
271 struct ospf_lsa *lsa;
272 struct route_node *rn;
paul2d598362003-01-17 23:48:42 +0000273
paul68980082003-03-25 05:07:42 +0000274 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
275 ospf_db_summary_add (nbr, lsa);
276 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
277 ospf_db_summary_add (nbr, lsa);
278 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
279 ospf_db_summary_add (nbr, lsa);
280 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
281 ospf_db_summary_add (nbr, lsa);
paul2d598362003-01-17 23:48:42 +0000282
paul2d598362003-01-17 23:48:42 +0000283 /* Process only if the neighbor is opaque capable. */
284 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
285 {
paul68980082003-03-25 05:07:42 +0000286 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
287 ospf_db_summary_add (nbr, lsa);
288 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
289 ospf_db_summary_add (nbr, lsa);
paul2d598362003-01-17 23:48:42 +0000290 }
paul2d598362003-01-17 23:48:42 +0000291
hassof4833e92005-06-20 20:42:26 +0000292 if (CHECK_FLAG (nbr->options, OSPF_OPTION_NP))
293 {
294 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
295 ospf_db_summary_add (nbr, lsa);
296 }
297
paul68980082003-03-25 05:07:42 +0000298 if (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK
299 && area->external_routing == OSPF_AREA_DEFAULT)
300 LSDB_LOOP (EXTERNAL_LSDB (nbr->oi->ospf), rn, lsa)
301 ospf_db_summary_add (nbr, lsa);
paul2d598362003-01-17 23:48:42 +0000302
paul68980082003-03-25 05:07:42 +0000303 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)
304 && (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK
305 && area->external_routing == OSPF_AREA_DEFAULT))
306 LSDB_LOOP (OPAQUE_AS_LSDB (nbr->oi->ospf), rn, lsa)
307 ospf_db_summary_add (nbr, lsa);
paul2d598362003-01-17 23:48:42 +0000308
paul2d598362003-01-17 23:48:42 +0000309 return 0;
310}
311
paul4dadc292005-05-06 21:37:42 +0000312static int
paul2d598362003-01-17 23:48:42 +0000313nsm_exchange_done (struct ospf_neighbor *nbr)
314{
paul2d598362003-01-17 23:48:42 +0000315 if (ospf_ls_request_isempty (nbr))
316 return NSM_Full;
317
paul2d598362003-01-17 23:48:42 +0000318 /* Send Link State Request. */
319 ospf_ls_req_send (nbr);
320
321 return NSM_Loading;
322}
323
paul4dadc292005-05-06 21:37:42 +0000324static int
paul2d598362003-01-17 23:48:42 +0000325nsm_adj_ok (struct ospf_neighbor *nbr)
326{
Paul Jakmad7b0fb62006-07-04 13:35:24 +0000327 int next_state = nbr->state;
328 int adj = nsm_should_adj (nbr);
paul2d598362003-01-17 23:48:42 +0000329
Paul Jakmad7b0fb62006-07-04 13:35:24 +0000330 if (nbr->state == NSM_TwoWay && adj == 1)
paul2d598362003-01-17 23:48:42 +0000331 next_state = NSM_ExStart;
Paul Jakmad7b0fb62006-07-04 13:35:24 +0000332 else if (nbr->state >= NSM_ExStart && adj == 0)
paul2d598362003-01-17 23:48:42 +0000333 next_state = NSM_TwoWay;
334
335 return next_state;
336}
337
Paul Jakmad1b1cd82006-07-04 13:50:44 +0000338/* Clear adjacency related state for a neighbour, intended where nbr
339 * transitions from > ExStart (i.e. a Full or forming adjacency)
340 * to <= ExStart.
341 */
342static void
343nsm_clear_adj (struct ospf_neighbor *nbr)
paul2d598362003-01-17 23:48:42 +0000344{
345 /* Clear Database Summary list. */
346 if (!ospf_db_summary_isempty (nbr))
347 ospf_db_summary_clear (nbr);
348
349 /* Clear Link State Request list. */
350 if (!ospf_ls_request_isempty (nbr))
351 ospf_ls_request_delete_all (nbr);
352
353 /* Clear Link State Retransmission list. */
354 if (!ospf_ls_retransmit_isempty (nbr))
355 ospf_ls_retransmit_clear (nbr);
paul2d598362003-01-17 23:48:42 +0000356
paul2d598362003-01-17 23:48:42 +0000357 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
358 UNSET_FLAG (nbr->options, OSPF_OPTION_O);
paul2d598362003-01-17 23:48:42 +0000359}
360
paul4dadc292005-05-06 21:37:42 +0000361static int
paul2d598362003-01-17 23:48:42 +0000362nsm_kill_nbr (struct ospf_neighbor *nbr)
363{
Paul Jakma478aab92006-04-03 21:25:32 +0000364 /* killing nbr_self is invalid */
Paul Jakma478aab92006-04-03 21:25:32 +0000365 if (nbr == nbr->oi->nbr_self)
Paul Jakma1f2c2742006-07-10 07:45:13 +0000366 {
367 assert (nbr != nbr->oi->nbr_self);
368 return 0;
369 }
Paul Jakma478aab92006-04-03 21:25:32 +0000370
paul2d598362003-01-17 23:48:42 +0000371 if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma != NULL)
372 {
373 struct ospf_nbr_nbma *nbr_nbma = nbr->nbr_nbma;
374
375 nbr_nbma->nbr = NULL;
376 nbr_nbma->state_change = nbr->state_change;
377
378 nbr->nbr_nbma = NULL;
379
380 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
381 nbr_nbma->v_poll);
382
383 if (IS_DEBUG_OSPF (nsm, NSM_EVENTS))
ajs2a42e282004-12-08 18:43:03 +0000384 zlog_debug ("NSM[%s:%s]: Down (PollIntervalTimer scheduled)",
paul2d598362003-01-17 23:48:42 +0000385 IF_NAME (nbr->oi), inet_ntoa (nbr->address.u.prefix4));
386 }
387
paul2d598362003-01-17 23:48:42 +0000388 return 0;
389}
390
paul2d598362003-01-17 23:48:42 +0000391/* Neighbor State Machine */
392struct {
paul4dadc292005-05-06 21:37:42 +0000393 int (*func) (struct ospf_neighbor *);
paul2d598362003-01-17 23:48:42 +0000394 int next_state;
395} NSM [OSPF_NSM_STATE_MAX][OSPF_NSM_EVENT_MAX] =
396{
397 {
398 /* DependUpon: dummy state. */
Paul Jakma539e1522006-07-11 17:49:22 +0000399 { NULL, NSM_DependUpon }, /* NoEvent */
Paul Jakma57c5c652010-01-07 06:12:53 +0000400 { NULL, NSM_DependUpon }, /* PacketReceived */
Paul Jakma539e1522006-07-11 17:49:22 +0000401 { NULL, NSM_DependUpon }, /* Start */
402 { NULL, NSM_DependUpon }, /* 2-WayReceived */
403 { NULL, NSM_DependUpon }, /* NegotiationDone */
404 { NULL, NSM_DependUpon }, /* ExchangeDone */
405 { NULL, NSM_DependUpon }, /* BadLSReq */
406 { NULL, NSM_DependUpon }, /* LoadingDone */
407 { NULL, NSM_DependUpon }, /* AdjOK? */
408 { NULL, NSM_DependUpon }, /* SeqNumberMismatch */
409 { NULL, NSM_DependUpon }, /* 1-WayReceived */
410 { NULL, NSM_DependUpon }, /* KillNbr */
411 { NULL, NSM_DependUpon }, /* InactivityTimer */
412 { NULL, NSM_DependUpon }, /* LLDown */
paul2d598362003-01-17 23:48:42 +0000413 },
414 {
Paul Jakma1f2c2742006-07-10 07:45:13 +0000415 /* Deleted: dummy state. */
Paul Jakma539e1522006-07-11 17:49:22 +0000416 { NULL, NSM_Deleted }, /* NoEvent */
Paul Jakma57c5c652010-01-07 06:12:53 +0000417 { NULL, NSM_Deleted }, /* PacketReceived */
Paul Jakma539e1522006-07-11 17:49:22 +0000418 { NULL, NSM_Deleted }, /* Start */
419 { NULL, NSM_Deleted }, /* 2-WayReceived */
420 { NULL, NSM_Deleted }, /* NegotiationDone */
421 { NULL, NSM_Deleted }, /* ExchangeDone */
422 { NULL, NSM_Deleted }, /* BadLSReq */
423 { NULL, NSM_Deleted }, /* LoadingDone */
424 { NULL, NSM_Deleted }, /* AdjOK? */
425 { NULL, NSM_Deleted }, /* SeqNumberMismatch */
426 { NULL, NSM_Deleted }, /* 1-WayReceived */
427 { NULL, NSM_Deleted }, /* KillNbr */
428 { NULL, NSM_Deleted }, /* InactivityTimer */
429 { NULL, NSM_Deleted }, /* LLDown */
Paul Jakma1f2c2742006-07-10 07:45:13 +0000430 },
431 {
paul2d598362003-01-17 23:48:42 +0000432 /* Down: */
Paul Jakma539e1522006-07-11 17:49:22 +0000433 { NULL, NSM_DependUpon }, /* NoEvent */
Paul Jakma57c5c652010-01-07 06:12:53 +0000434 { nsm_packet_received, NSM_Init }, /* PacketReceived */
paul2d598362003-01-17 23:48:42 +0000435 { nsm_start, NSM_Attempt }, /* Start */
Paul Jakma539e1522006-07-11 17:49:22 +0000436 { NULL, NSM_Down }, /* 2-WayReceived */
437 { NULL, NSM_Down }, /* NegotiationDone */
438 { NULL, NSM_Down }, /* ExchangeDone */
439 { NULL, NSM_Down }, /* BadLSReq */
440 { NULL, NSM_Down }, /* LoadingDone */
441 { NULL, NSM_Down }, /* AdjOK? */
442 { NULL, NSM_Down }, /* SeqNumberMismatch */
443 { NULL, NSM_Down }, /* 1-WayReceived */
Paul Jakma1f2c2742006-07-10 07:45:13 +0000444 { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
Paul Jakma539e1522006-07-11 17:49:22 +0000445 { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
446 { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
paul2d598362003-01-17 23:48:42 +0000447 },
448 {
449 /* Attempt: */
Paul Jakma539e1522006-07-11 17:49:22 +0000450 { NULL, NSM_DependUpon }, /* NoEvent */
Paul Jakma57c5c652010-01-07 06:12:53 +0000451 { nsm_packet_received, NSM_Init }, /* PacketReceived */
Paul Jakma539e1522006-07-11 17:49:22 +0000452 { NULL, NSM_Attempt }, /* Start */
453 { NULL, NSM_Attempt }, /* 2-WayReceived */
454 { NULL, NSM_Attempt }, /* NegotiationDone */
455 { NULL, NSM_Attempt }, /* ExchangeDone */
456 { NULL, NSM_Attempt }, /* BadLSReq */
457 { NULL, NSM_Attempt }, /* LoadingDone */
458 { NULL, NSM_Attempt }, /* AdjOK? */
459 { NULL, NSM_Attempt }, /* SeqNumberMismatch */
460 { NULL, NSM_Attempt }, /* 1-WayReceived */
Paul Jakma1f2c2742006-07-10 07:45:13 +0000461 { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
Paul Jakma539e1522006-07-11 17:49:22 +0000462 { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
463 { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
paul2d598362003-01-17 23:48:42 +0000464 },
465 {
466 /* Init: */
Paul Jakma539e1522006-07-11 17:49:22 +0000467 { NULL, NSM_DependUpon }, /* NoEvent */
Paul Jakma57c5c652010-01-07 06:12:53 +0000468 { nsm_packet_received, NSM_Init }, /* PacketReceived */
Paul Jakma539e1522006-07-11 17:49:22 +0000469 { NULL, NSM_Init }, /* Start */
paul2d598362003-01-17 23:48:42 +0000470 { nsm_twoway_received, NSM_DependUpon }, /* 2-WayReceived */
Paul Jakma539e1522006-07-11 17:49:22 +0000471 { NULL, NSM_Init }, /* NegotiationDone */
472 { NULL, NSM_Init }, /* ExchangeDone */
473 { NULL, NSM_Init }, /* BadLSReq */
474 { NULL, NSM_Init }, /* LoadingDone */
475 { NULL, NSM_Init }, /* AdjOK? */
476 { NULL, NSM_Init }, /* SeqNumberMismatch */
477 { NULL, NSM_Init }, /* 1-WayReceived */
Paul Jakma1f2c2742006-07-10 07:45:13 +0000478 { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
Paul Jakma539e1522006-07-11 17:49:22 +0000479 { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
480 { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
paul2d598362003-01-17 23:48:42 +0000481 },
482 {
483 /* 2-Way: */
Paul Jakma539e1522006-07-11 17:49:22 +0000484 { NULL, NSM_DependUpon }, /* NoEvent */
Paul Jakma57c5c652010-01-07 06:12:53 +0000485 { nsm_packet_received, NSM_TwoWay }, /* HelloReceived */
Paul Jakma539e1522006-07-11 17:49:22 +0000486 { NULL, NSM_TwoWay }, /* Start */
487 { NULL, NSM_TwoWay }, /* 2-WayReceived */
488 { NULL, NSM_TwoWay }, /* NegotiationDone */
489 { NULL, NSM_TwoWay }, /* ExchangeDone */
490 { NULL, NSM_TwoWay }, /* BadLSReq */
491 { NULL, NSM_TwoWay }, /* LoadingDone */
paul2d598362003-01-17 23:48:42 +0000492 { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
Paul Jakma539e1522006-07-11 17:49:22 +0000493 { NULL, NSM_TwoWay }, /* SeqNumberMismatch */
494 { NULL, NSM_Init }, /* 1-WayReceived */
Paul Jakma1f2c2742006-07-10 07:45:13 +0000495 { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
Paul Jakma539e1522006-07-11 17:49:22 +0000496 { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
497 { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
paul2d598362003-01-17 23:48:42 +0000498 },
499 {
500 /* ExStart: */
Paul Jakma539e1522006-07-11 17:49:22 +0000501 { NULL, NSM_DependUpon }, /* NoEvent */
Paul Jakma57c5c652010-01-07 06:12:53 +0000502 { nsm_packet_received, NSM_ExStart }, /* PacaketReceived */
Paul Jakma539e1522006-07-11 17:49:22 +0000503 { NULL, NSM_ExStart }, /* Start */
504 { NULL, NSM_ExStart }, /* 2-WayReceived */
paul2d598362003-01-17 23:48:42 +0000505 { nsm_negotiation_done, NSM_Exchange }, /* NegotiationDone */
Paul Jakma539e1522006-07-11 17:49:22 +0000506 { NULL, NSM_ExStart }, /* ExchangeDone */
507 { NULL, NSM_ExStart }, /* BadLSReq */
508 { NULL, NSM_ExStart }, /* LoadingDone */
paul2d598362003-01-17 23:48:42 +0000509 { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
Paul Jakma539e1522006-07-11 17:49:22 +0000510 { NULL, NSM_ExStart }, /* SeqNumberMismatch */
511 { NULL, NSM_Init }, /* 1-WayReceived */
Paul Jakma1f2c2742006-07-10 07:45:13 +0000512 { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
Paul Jakma539e1522006-07-11 17:49:22 +0000513 { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
514 { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
paul2d598362003-01-17 23:48:42 +0000515 },
516 {
517 /* Exchange: */
Paul Jakma539e1522006-07-11 17:49:22 +0000518 { NULL, NSM_DependUpon }, /* NoEvent */
Paul Jakma57c5c652010-01-07 06:12:53 +0000519 { nsm_packet_received, NSM_Exchange }, /* PacketReceived */
Paul Jakma539e1522006-07-11 17:49:22 +0000520 { NULL, NSM_Exchange }, /* Start */
521 { NULL, NSM_Exchange }, /* 2-WayReceived */
522 { NULL, NSM_Exchange }, /* NegotiationDone */
paul2d598362003-01-17 23:48:42 +0000523 { nsm_exchange_done, NSM_DependUpon }, /* ExchangeDone */
Paul Jakma539e1522006-07-11 17:49:22 +0000524 { NULL, NSM_ExStart }, /* BadLSReq */
525 { NULL, NSM_Exchange }, /* LoadingDone */
paul2d598362003-01-17 23:48:42 +0000526 { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
Paul Jakma539e1522006-07-11 17:49:22 +0000527 { NULL, NSM_ExStart }, /* SeqNumberMismatch */
528 { NULL, NSM_Init }, /* 1-WayReceived */
Paul Jakma1f2c2742006-07-10 07:45:13 +0000529 { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
Paul Jakma539e1522006-07-11 17:49:22 +0000530 { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
531 { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
paul2d598362003-01-17 23:48:42 +0000532 },
533 {
534 /* Loading: */
Paul Jakma539e1522006-07-11 17:49:22 +0000535 { NULL, NSM_DependUpon }, /* NoEvent */
Paul Jakma57c5c652010-01-07 06:12:53 +0000536 { nsm_packet_received, NSM_Loading }, /* PacketReceived */
Paul Jakma539e1522006-07-11 17:49:22 +0000537 { NULL, NSM_Loading }, /* Start */
538 { NULL, NSM_Loading }, /* 2-WayReceived */
539 { NULL, NSM_Loading }, /* NegotiationDone */
540 { NULL, NSM_Loading }, /* ExchangeDone */
541 { NULL, NSM_ExStart }, /* BadLSReq */
542 { NULL, NSM_Full }, /* LoadingDone */
paul2d598362003-01-17 23:48:42 +0000543 { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
Paul Jakma539e1522006-07-11 17:49:22 +0000544 { NULL, NSM_ExStart }, /* SeqNumberMismatch */
545 { NULL, NSM_Init }, /* 1-WayReceived */
Paul Jakma1f2c2742006-07-10 07:45:13 +0000546 { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
Paul Jakma539e1522006-07-11 17:49:22 +0000547 { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
548 { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
paul2d598362003-01-17 23:48:42 +0000549 },
550 { /* Full: */
Paul Jakma539e1522006-07-11 17:49:22 +0000551 { NULL, NSM_DependUpon }, /* NoEvent */
Paul Jakma57c5c652010-01-07 06:12:53 +0000552 { nsm_packet_received, NSM_Full }, /* PacketReceived */
Paul Jakma539e1522006-07-11 17:49:22 +0000553 { NULL, NSM_Full }, /* Start */
554 { NULL, NSM_Full }, /* 2-WayReceived */
555 { NULL, NSM_Full }, /* NegotiationDone */
556 { NULL, NSM_Full }, /* ExchangeDone */
557 { NULL, NSM_ExStart }, /* BadLSReq */
558 { NULL, NSM_Full }, /* LoadingDone */
paul2d598362003-01-17 23:48:42 +0000559 { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
Paul Jakma539e1522006-07-11 17:49:22 +0000560 { NULL, NSM_ExStart }, /* SeqNumberMismatch */
561 { NULL, NSM_Init }, /* 1-WayReceived */
Paul Jakma1f2c2742006-07-10 07:45:13 +0000562 { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
Paul Jakma539e1522006-07-11 17:49:22 +0000563 { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
564 { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
paul2d598362003-01-17 23:48:42 +0000565 },
566};
567
Paul Jakma30a22312008-08-15 14:05:22 +0100568static const char *ospf_nsm_event_str[] =
paul2d598362003-01-17 23:48:42 +0000569{
570 "NoEvent",
Paul Jakma57c5c652010-01-07 06:12:53 +0000571 "PacketReceived",
paul2d598362003-01-17 23:48:42 +0000572 "Start",
573 "2-WayReceived",
574 "NegotiationDone",
575 "ExchangeDone",
576 "BadLSReq",
577 "LoadingDone",
578 "AdjOK?",
579 "SeqNumberMismatch",
580 "1-WayReceived",
581 "KillNbr",
582 "InactivityTimer",
583 "LLDown",
584};
585
Paul Jakma3d63f382006-07-11 17:52:53 +0000586static void
587nsm_notice_state_change (struct ospf_neighbor *nbr, int next_state, int event)
588{
589 /* Logging change of status. */
590 if (IS_DEBUG_OSPF (nsm, NSM_STATUS))
591 zlog_debug ("NSM[%s:%s]: State change %s -> %s (%s)",
592 IF_NAME (nbr->oi), inet_ntoa (nbr->router_id),
593 LOOKUP (ospf_nsm_state_msg, nbr->state),
594 LOOKUP (ospf_nsm_state_msg, next_state),
595 ospf_nsm_event_str [event]);
596
597 /* Optionally notify about adjacency changes */
598 if (CHECK_FLAG(nbr->oi->ospf->config, OSPF_LOG_ADJACENCY_CHANGES) &&
599 (CHECK_FLAG(nbr->oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL) ||
600 (next_state == NSM_Full) || (next_state < nbr->state)))
601 zlog_notice("AdjChg: Nbr %s on %s: %s -> %s (%s)",
602 inet_ntoa (nbr->router_id), IF_NAME (nbr->oi),
603 LOOKUP (ospf_nsm_state_msg, nbr->state),
604 LOOKUP (ospf_nsm_state_msg, next_state),
605 ospf_nsm_event_str [event]);
606
Paul Jakma3fed4162006-07-25 20:44:12 +0000607 /* Advance in NSM */
608 if (next_state > nbr->state)
Paul Jakma2518efd2006-08-27 06:49:29 +0000609 nbr->ts_last_progress = recent_relative_time ();
Paul Jakma3fed4162006-07-25 20:44:12 +0000610 else /* regression in NSM */
611 {
Paul Jakma2518efd2006-08-27 06:49:29 +0000612 nbr->ts_last_regress = recent_relative_time ();
Paul Jakma3fed4162006-07-25 20:44:12 +0000613 nbr->last_regress_str = ospf_nsm_event_str [event];
614 }
Paul Jakma90c33172006-07-11 17:57:25 +0000615
Paul Jakma3d63f382006-07-11 17:52:53 +0000616}
617
Andrew Certainde54b262012-12-04 13:40:58 -0800618static void
paul2d598362003-01-17 23:48:42 +0000619nsm_change_state (struct ospf_neighbor *nbr, int state)
620{
paul68980082003-03-25 05:07:42 +0000621 struct ospf_interface *oi = nbr->oi;
paul2d598362003-01-17 23:48:42 +0000622 struct ospf_area *vl_area = NULL;
623 u_char old_state;
624 int x;
625 int force = 1;
626
paul2d598362003-01-17 23:48:42 +0000627 /* Preserve old status. */
628 old_state = nbr->state;
629
630 /* Change to new status. */
631 nbr->state = state;
632
633 /* Statistics. */
634 nbr->state_change++;
635
paul2d598362003-01-17 23:48:42 +0000636 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
paul68980082003-03-25 05:07:42 +0000637 vl_area = ospf_area_lookup_by_area_id (oi->ospf, oi->vl_data->vl_area_id);
Andrew J. Schorrd7e60dd2006-06-29 20:20:52 +0000638
Christian Franke7a9d9832013-07-10 11:56:18 +0000639 /* Generate NeighborChange ISM event.
640 *
641 * In response to NeighborChange, DR election is rerun. The information
642 * from the election process is required by the router-lsa construction.
643 *
644 * Therefore, trigger the event prior to refreshing the LSAs. */
645 switch (oi->state) {
646 case ISM_DROther:
647 case ISM_Backup:
648 case ISM_DR:
649 if ((old_state < NSM_TwoWay && state >= NSM_TwoWay) ||
650 (old_state >= NSM_TwoWay && state < NSM_TwoWay))
651 OSPF_ISM_EVENT_EXECUTE (oi, ISM_NeighborChange);
652 break;
653 default:
654 /* ISM_PointToPoint -> ISM_Down, ISM_Loopback -> ISM_Down, etc. */
655 break;
656 }
657
paul2d598362003-01-17 23:48:42 +0000658 /* One of the neighboring routers changes to/from the FULL state. */
659 if ((old_state != NSM_Full && state == NSM_Full) ||
660 (old_state == NSM_Full && state != NSM_Full))
ajs3aa8d5f2004-12-11 18:00:06 +0000661 {
paul2d598362003-01-17 23:48:42 +0000662 if (state == NSM_Full)
663 {
664 oi->full_nbrs++;
665 oi->area->full_nbrs++;
666
paul68980082003-03-25 05:07:42 +0000667 ospf_check_abr_status (oi->ospf);
paul2d598362003-01-17 23:48:42 +0000668
669 if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area)
670 if (++vl_area->full_vls == 1)
paul68980082003-03-25 05:07:42 +0000671 ospf_schedule_abr_task (oi->ospf);
paul2d598362003-01-17 23:48:42 +0000672
673 /* kevinm: refresh any redistributions */
paul68980082003-03-25 05:07:42 +0000674 for (x = ZEBRA_ROUTE_SYSTEM; x < ZEBRA_ROUTE_MAX; x++)
675 {
676 if (x == ZEBRA_ROUTE_OSPF || x == ZEBRA_ROUTE_OSPF6)
677 continue;
678 ospf_external_lsa_refresh_type (oi->ospf, x, force);
679 }
Daniel Ng9fd49582008-08-13 20:37:52 +0100680 /* XXX: Clearly some thing is wrong with refresh of external LSAs
681 * this added to hack around defaults not refreshing after a timer
682 * jump.
683 */
684 ospf_external_lsa_refresh_default (oi->ospf);
paul2d598362003-01-17 23:48:42 +0000685 }
686 else
687 {
688 oi->full_nbrs--;
689 oi->area->full_nbrs--;
690
paul68980082003-03-25 05:07:42 +0000691 ospf_check_abr_status (oi->ospf);
paul2d598362003-01-17 23:48:42 +0000692
693 if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area)
694 if (vl_area->full_vls > 0)
695 if (--vl_area->full_vls == 0)
paul68980082003-03-25 05:07:42 +0000696 ospf_schedule_abr_task (oi->ospf);
paul2d598362003-01-17 23:48:42 +0000697 }
698
ajs3aa8d5f2004-12-11 18:00:06 +0000699 zlog_info ("nsm_change_state(%s, %s -> %s): "
700 "scheduling new router-LSA origination",
701 inet_ntoa (nbr->router_id),
702 LOOKUP(ospf_nsm_state_msg, old_state),
703 LOOKUP(ospf_nsm_state_msg, state));
paul2d598362003-01-17 23:48:42 +0000704
Paul Jakmac363d382010-01-24 22:42:13 +0000705 ospf_router_lsa_update_area (oi->area);
paul2d598362003-01-17 23:48:42 +0000706
707 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
708 {
709 struct ospf_area *vl_area =
paul68980082003-03-25 05:07:42 +0000710 ospf_area_lookup_by_area_id (oi->ospf, oi->vl_data->vl_area_id);
paul2d598362003-01-17 23:48:42 +0000711
712 if (vl_area)
Paul Jakmac363d382010-01-24 22:42:13 +0000713 ospf_router_lsa_update_area (vl_area);
paul2d598362003-01-17 23:48:42 +0000714 }
715
716 /* Originate network-LSA. */
717 if (oi->state == ISM_DR)
718 {
719 if (oi->network_lsa_self && oi->full_nbrs == 0)
720 {
721 ospf_lsa_flush_area (oi->network_lsa_self, oi->area);
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000722 ospf_lsa_unlock (&oi->network_lsa_self);
paul2d598362003-01-17 23:48:42 +0000723 oi->network_lsa_self = NULL;
paul2d598362003-01-17 23:48:42 +0000724 }
725 else
Paul Jakmac363d382010-01-24 22:42:13 +0000726 ospf_network_lsa_update (oi);
paul2d598362003-01-17 23:48:42 +0000727 }
728 }
729
paul2d598362003-01-17 23:48:42 +0000730 ospf_opaque_nsm_change (nbr, old_state);
paul2d598362003-01-17 23:48:42 +0000731
Paul Jakmad1b1cd82006-07-04 13:50:44 +0000732 /* State changes from > ExStart to <= ExStart should clear any Exchange
733 * or Full/LSA Update related lists and state.
734 * Potential causal events: BadLSReq, SeqNumberMismatch, AdjOK?
Paul Jakmad1b1cd82006-07-04 13:50:44 +0000735 */
Paul Jakma539e1522006-07-11 17:49:22 +0000736 if ((old_state > NSM_ExStart) && (state <= NSM_ExStart))
Paul Jakmad1b1cd82006-07-04 13:50:44 +0000737 nsm_clear_adj (nbr);
738
paul2d598362003-01-17 23:48:42 +0000739 /* Start DD exchange protocol */
740 if (state == NSM_ExStart)
741 {
742 if (nbr->dd_seqnum == 0)
Paul Jakma2518efd2006-08-27 06:49:29 +0000743 nbr->dd_seqnum = quagga_time (NULL);
paul2d598362003-01-17 23:48:42 +0000744 else
745 nbr->dd_seqnum++;
746
747 nbr->dd_flags = OSPF_DD_FLAG_I|OSPF_DD_FLAG_M|OSPF_DD_FLAG_MS;
748 ospf_db_desc_send (nbr);
749 }
750
751 /* clear cryptographic sequence number */
752 if (state == NSM_Down)
753 nbr->crypt_seqnum = 0;
754
paul2d598362003-01-17 23:48:42 +0000755 /* Preserve old status? */
756}
757
758/* Execute NSM event process. */
759int
760ospf_nsm_event (struct thread *thread)
761{
762 int event;
763 int next_state;
764 struct ospf_neighbor *nbr;
paul2d598362003-01-17 23:48:42 +0000765
766 nbr = THREAD_ARG (thread);
767 event = THREAD_VAL (thread);
paul2d598362003-01-17 23:48:42 +0000768
Paul Jakma3d63f382006-07-11 17:52:53 +0000769 if (IS_DEBUG_OSPF (nsm, NSM_EVENTS))
770 zlog_debug ("NSM[%s:%s]: %s (%s)", IF_NAME (nbr->oi),
771 inet_ntoa (nbr->router_id),
772 LOOKUP (ospf_nsm_state_msg, nbr->state),
773 ospf_nsm_event_str [event]);
774
Paul Jakma539e1522006-07-11 17:49:22 +0000775 next_state = NSM [nbr->state][event].next_state;
paul2d598362003-01-17 23:48:42 +0000776
Paul Jakma539e1522006-07-11 17:49:22 +0000777 /* Call function. */
778 if (NSM [nbr->state][event].func != NULL)
Paul Jakmaba0beb42006-07-04 13:44:19 +0000779 {
Paul Jakma539e1522006-07-11 17:49:22 +0000780 int func_state = (*(NSM [nbr->state][event].func))(nbr);
Paul Jakmaba0beb42006-07-04 13:44:19 +0000781
Paul Jakma539e1522006-07-11 17:49:22 +0000782 if (NSM [nbr->state][event].next_state == NSM_DependUpon)
783 next_state = func_state;
784 else if (func_state)
785 {
786 /* There's a mismatch between the FSM tables and what an FSM
787 * action/state-change function returned. State changes which
788 * do not have conditional/DependUpon next-states should not
789 * try set next_state.
790 */
791 zlog_warn ("NSM[%s:%s]: %s (%s): "
792 "Warning: action tried to change next_state to %s",
793 IF_NAME (nbr->oi), inet_ntoa (nbr->router_id),
794 LOOKUP (ospf_nsm_state_msg, nbr->state),
795 ospf_nsm_event_str [event],
796 LOOKUP (ospf_nsm_state_msg, func_state));
797 }
Paul Jakmaba0beb42006-07-04 13:44:19 +0000798 }
paul2d598362003-01-17 23:48:42 +0000799
Paul Jakma539e1522006-07-11 17:49:22 +0000800 assert (next_state != NSM_DependUpon);
801
paul2d598362003-01-17 23:48:42 +0000802 /* If state is changed. */
803 if (next_state != nbr->state)
Paul Jakma3d63f382006-07-11 17:52:53 +0000804 {
805 nsm_notice_state_change (nbr, next_state, event);
Fernando Sotob6404392015-05-11 20:52:00 +0000806#ifdef HAVE_SNMP
807 int send_trap_virt = 0;
808 int send_trap = 0;
809 /* Terminal state or regression */
810 if ((next_state == NSM_Full)
811 || (next_state == NSM_TwoWay)
812 || (next_state < nbr->state))
813 {
814 /* ospfVirtNbrStateChange */
815 if (nbr->oi->type == OSPF_IFTYPE_VIRTUALLINK)
816 send_trap_virt = 1;
817 /* ospfNbrStateChange trap */
818 else
819 /* To/From FULL, only managed by DR */
820 if (((next_state != NSM_Full) && (nbr->state != NSM_Full))
821 || (nbr->oi->state == ISM_DR))
822 send_trap = 1;
823 }
824#endif
Paul Jakma3d63f382006-07-11 17:52:53 +0000825 nsm_change_state (nbr, next_state);
Fernando Sotob6404392015-05-11 20:52:00 +0000826
827#ifdef HAVE_SNMP
828 if (send_trap_virt) {
829 ospfTrapVirtNbrStateChange(nbr);
830 } else if (send_trap) {
831 ospfTrapNbrStateChange(nbr);
832 }
833#endif
Paul Jakma3d63f382006-07-11 17:52:53 +0000834 }
paul2d598362003-01-17 23:48:42 +0000835
836 /* Make sure timer is set. */
837 nsm_timer_set (nbr);
838
Paul Jakma1f2c2742006-07-10 07:45:13 +0000839 /* When event is NSM_KillNbr, InactivityTimer or LLDown, the neighbor
840 * is deleted.
841 *
842 * Rather than encode knowledge here of which events lead to NBR
843 * delete, we take our cue from the NSM table, via the dummy
844 * 'Deleted' neighbour state.
845 */
846 if (nbr->state == NSM_Deleted)
847 ospf_nbr_delete (nbr);
848
paul2d598362003-01-17 23:48:42 +0000849 return 0;
850}
851
852/* Check loading state. */
853void
854ospf_check_nbr_loading (struct ospf_neighbor *nbr)
855{
856 if (nbr->state == NSM_Loading)
857 {
858 if (ospf_ls_request_isempty (nbr))
859 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_LoadingDone);
860 else if (nbr->ls_req_last == NULL)
861 ospf_ls_req_event (nbr);
862 }
863}