2
* OSPF version 2 Neighbor State Machine
3
* From RFC2328 [OSPF Version 2]
4
* Copyright (C) 1999, 2000 Toshiaki Takada
6
* This file is part of GNU Zebra.
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
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.
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
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"
51
void nsm_reset_nbr (struct ospf_neighbor *);
54
/* OSPF NSM Timer functions. */
56
ospf_inactivity_timer (struct thread *thread)
58
struct ospf_neighbor *nbr;
60
nbr = THREAD_ARG (thread);
61
nbr->t_inactivity = NULL;
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));
67
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_InactivityTimer);
73
ospf_db_desc_timer (struct thread *thread)
75
struct ospf_interface *oi;
76
struct ospf_neighbor *nbr;
78
nbr = THREAD_ARG (thread);
79
nbr->t_db_desc = NULL;
83
if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
84
zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (DD Retransmit timer expire)",
85
IF_NAME (nbr->oi), inet_ntoa (nbr->src));
87
/* resent last send DD packet. */
88
assert (nbr->last_send);
89
ospf_db_desc_resend (nbr);
91
/* DD Retransmit timer set. */
92
OSPF_NSM_TIMER_ON (nbr->t_db_desc, ospf_db_desc_timer, nbr->v_db_desc);
97
/* Hook function called after ospf NSM event is occured. */
100
nsm_timer_set (struct ospf_neighbor *nbr)
105
OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
106
OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
109
OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
110
OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
113
OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
114
OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
117
OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
118
OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
121
OSPF_NSM_TIMER_ON (nbr->t_db_desc, ospf_db_desc_timer, nbr->v_db_desc);
122
OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
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);
130
OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
133
OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
136
OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
142
/* OSPF NSM functions. */
144
nsm_ignore (struct ospf_neighbor *nbr)
146
if (IS_DEBUG_OSPF (nsm, NSM_EVENTS))
147
zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: nsm_ignore called",
148
IF_NAME (nbr->oi), inet_ntoa (nbr->router_id));
154
nsm_hello_received (struct ospf_neighbor *nbr)
156
/* Start or Restart Inactivity Timer. */
157
OSPF_NSM_TIMER_OFF (nbr->t_inactivity);
159
OSPF_NSM_TIMER_ON (nbr->t_inactivity, ospf_inactivity_timer,
162
if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma)
163
OSPF_POLL_TIMER_OFF (nbr->nbr_nbma->t_poll);
169
nsm_start (struct ospf_neighbor *nbr)
175
OSPF_POLL_TIMER_OFF (nbr->nbr_nbma->t_poll);
177
OSPF_NSM_TIMER_OFF (nbr->t_inactivity);
179
OSPF_NSM_TIMER_ON (nbr->t_inactivity, ospf_inactivity_timer,
186
nsm_twoway_received (struct ospf_neighbor *nbr)
188
struct ospf_interface *oi;
189
int next_state = NSM_TwoWay;
193
/* These netowork types must be adjacency. */
194
if (oi->type == OSPF_IFTYPE_POINTOPOINT ||
195
oi->type == OSPF_IFTYPE_POINTOMULTIPOINT ||
196
oi->type == OSPF_IFTYPE_VIRTUALLINK)
197
next_state = NSM_ExStart;
199
/* Router itself is the DRouter or the BDRouter. */
200
if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi)) ||
201
IPV4_ADDR_SAME (&oi->address->u.prefix4, &BDR (oi)))
202
next_state = NSM_ExStart;
204
/* Neighboring Router is the DRouter or the BDRouter. */
205
if (IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->d_router) ||
206
IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->bd_router))
207
next_state = NSM_ExStart;
213
ospf_db_summary_count (struct ospf_neighbor *nbr)
215
return ospf_lsdb_count_all (&nbr->db_sum);
219
ospf_db_summary_isempty (struct ospf_neighbor *nbr)
221
return ospf_lsdb_isempty (&nbr->db_sum);
225
ospf_db_summary_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
227
#ifdef HAVE_OPAQUE_LSA
228
switch (lsa->data->type)
230
case OSPF_OPAQUE_LINK_LSA:
231
/* Exclude type-9 LSAs that does not have the same "oi" with "nbr". */
232
if (lsa->oi != nbr->oi)
235
case OSPF_OPAQUE_AREA_LSA:
237
* It is assured by the caller function "nsm_negotiation_done()"
238
* that every given LSA belongs to the same area with "nbr".
241
case OSPF_OPAQUE_AS_LSA:
245
#endif /* HAVE_OPAQUE_LSA */
247
/* Stay away from any Local Translated Type-7 LSAs */
248
if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
251
if (IS_LSA_MAXAGE (lsa))
252
ospf_ls_retransmit_add (nbr, lsa);
254
ospf_lsdb_add (&nbr->db_sum, lsa);
260
ospf_db_summary_clear (struct ospf_neighbor *nbr)
262
struct ospf_lsdb *lsdb;
266
for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
268
struct route_table *table = lsdb->type[i].db;
269
struct route_node *rn;
271
for (rn = route_top (table); rn; rn = route_next (rn))
273
ospf_lsdb_delete (&nbr->db_sum, rn->info);
279
/* The area link state database consists of the router-LSAs,
280
network-LSAs and summary-LSAs contained in the area structure,
281
along with the AS-external-LSAs contained in the global structure.
282
AS-external-LSAs are omitted from a virtual neighbor's Database
283
summary list. AS-external-LSAs are omitted from the Database
284
summary list if the area has been configured as a stub. */
286
nsm_negotiation_done (struct ospf_neighbor *nbr)
288
struct ospf_area *area = nbr->oi->area;
289
struct ospf_lsa *lsa;
290
struct route_node *rn;
292
LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
293
ospf_db_summary_add (nbr, lsa);
294
LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
295
ospf_db_summary_add (nbr, lsa);
296
LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
297
ospf_db_summary_add (nbr, lsa);
298
LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
299
ospf_db_summary_add (nbr, lsa);
301
#ifdef HAVE_OPAQUE_LSA
302
/* Process only if the neighbor is opaque capable. */
303
if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
305
LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
306
ospf_db_summary_add (nbr, lsa);
307
LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
308
ospf_db_summary_add (nbr, lsa);
310
#endif /* HAVE_OPAQUE_LSA */
312
if (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK
313
&& area->external_routing == OSPF_AREA_DEFAULT)
314
LSDB_LOOP (EXTERNAL_LSDB (nbr->oi->ospf), rn, lsa)
315
ospf_db_summary_add (nbr, lsa);
317
#ifdef HAVE_OPAQUE_LSA
318
if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)
319
&& (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK
320
&& area->external_routing == OSPF_AREA_DEFAULT))
321
LSDB_LOOP (OPAQUE_AS_LSDB (nbr->oi->ospf), rn, lsa)
322
ospf_db_summary_add (nbr, lsa);
323
#endif /* HAVE_OPAQUE_LSA */
329
nsm_exchange_done (struct ospf_neighbor *nbr)
331
if (ospf_ls_request_isempty (nbr))
334
/* Cancel dd retransmit timer. */
335
/* OSPF_NSM_TIMER_OFF (nbr->t_db_desc); */
337
/* Send Link State Request. */
338
ospf_ls_req_send (nbr);
344
nsm_bad_ls_req (struct ospf_neighbor *nbr)
346
/* Clear neighbor. */
353
nsm_adj_ok (struct ospf_neighbor *nbr)
355
struct ospf_interface *oi;
360
next_state = nbr->state;
362
/* These netowork types must be adjacency. */
363
if (oi->type == OSPF_IFTYPE_POINTOPOINT
364
|| oi->type == OSPF_IFTYPE_POINTOMULTIPOINT
365
|| oi->type == OSPF_IFTYPE_VIRTUALLINK)
368
/* Router itself is the DRouter or the BDRouter. */
369
if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))
370
|| IPV4_ADDR_SAME (&oi->address->u.prefix4, &BDR (oi)))
373
if (IPV4_ADDR_SAME (&nbr->address.u.prefix4, &DR (oi))
374
|| IPV4_ADDR_SAME (&nbr->address.u.prefix4, &BDR (oi)))
377
if (nbr->state == NSM_TwoWay && flag == 1)
378
next_state = NSM_ExStart;
379
else if (nbr->state >= NSM_ExStart && flag == 0)
380
next_state = NSM_TwoWay;
386
nsm_seq_number_mismatch (struct ospf_neighbor *nbr)
388
/* Clear neighbor. */
395
nsm_oneway_received (struct ospf_neighbor *nbr)
397
/* Clear neighbor. */
404
nsm_reset_nbr (struct ospf_neighbor *nbr)
406
/* Clear Database Summary list. */
407
if (!ospf_db_summary_isempty (nbr))
408
ospf_db_summary_clear (nbr);
410
/* Clear Link State Request list. */
411
if (!ospf_ls_request_isempty (nbr))
412
ospf_ls_request_delete_all (nbr);
414
/* Clear Link State Retransmission list. */
415
if (!ospf_ls_retransmit_isempty (nbr))
416
ospf_ls_retransmit_clear (nbr);
419
OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
420
OSPF_NSM_TIMER_OFF (nbr->t_ls_req);
421
OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
422
OSPF_NSM_TIMER_OFF (nbr->t_hello_reply);
424
#ifdef HAVE_OPAQUE_LSA
425
if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
426
UNSET_FLAG (nbr->options, OSPF_OPTION_O);
427
#endif /* HAVE_OPAQUE_LSA */
431
nsm_kill_nbr (struct ospf_neighbor *nbr)
433
/* call it here because we cannot call it from ospf_nsm_event */
434
nsm_change_state (nbr, NSM_Down);
436
/* Reset neighbor. */
439
if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma != NULL)
441
struct ospf_nbr_nbma *nbr_nbma = nbr->nbr_nbma;
443
nbr_nbma->nbr = NULL;
444
nbr_nbma->state_change = nbr->state_change;
446
nbr->nbr_nbma = NULL;
448
OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
451
if (IS_DEBUG_OSPF (nsm, NSM_EVENTS))
452
zlog_debug ("NSM[%s:%s]: Down (PollIntervalTimer scheduled)",
453
IF_NAME (nbr->oi), inet_ntoa (nbr->address.u.prefix4));
456
/* Delete neighbor from interface. */
457
ospf_nbr_delete (nbr);
463
nsm_inactivity_timer (struct ospf_neighbor *nbr)
472
nsm_ll_down (struct ospf_neighbor *nbr)
474
/* Reset neighbor. */
475
/*nsm_reset_nbr (nbr);*/
483
/* Neighbor State Machine */
487
} NSM [OSPF_NSM_STATE_MAX][OSPF_NSM_EVENT_MAX] =
490
/* DependUpon: dummy state. */
491
{ nsm_ignore, NSM_DependUpon }, /* NoEvent */
492
{ nsm_ignore, NSM_DependUpon }, /* HelloReceived */
493
{ nsm_ignore, NSM_DependUpon }, /* Start */
494
{ nsm_ignore, NSM_DependUpon }, /* 2-WayReceived */
495
{ nsm_ignore, NSM_DependUpon }, /* NegotiationDone */
496
{ nsm_ignore, NSM_DependUpon }, /* ExchangeDone */
497
{ nsm_ignore, NSM_DependUpon }, /* BadLSReq */
498
{ nsm_ignore, NSM_DependUpon }, /* LoadingDone */
499
{ nsm_ignore, NSM_DependUpon }, /* AdjOK? */
500
{ nsm_ignore, NSM_DependUpon }, /* SeqNumberMismatch */
501
{ nsm_ignore, NSM_DependUpon }, /* 1-WayReceived */
502
{ nsm_ignore, NSM_DependUpon }, /* KillNbr */
503
{ nsm_ignore, NSM_DependUpon }, /* InactivityTimer */
504
{ nsm_ignore, NSM_DependUpon }, /* LLDown */
508
{ nsm_ignore, NSM_DependUpon }, /* NoEvent */
509
{ nsm_hello_received, NSM_Init }, /* HelloReceived */
510
{ nsm_start, NSM_Attempt }, /* Start */
511
{ nsm_ignore, NSM_Down }, /* 2-WayReceived */
512
{ nsm_ignore, NSM_Down }, /* NegotiationDone */
513
{ nsm_ignore, NSM_Down }, /* ExchangeDone */
514
{ nsm_ignore, NSM_Down }, /* BadLSReq */
515
{ nsm_ignore, NSM_Down }, /* LoadingDone */
516
{ nsm_ignore, NSM_Down }, /* AdjOK? */
517
{ nsm_ignore, NSM_Down }, /* SeqNumberMismatch */
518
{ nsm_ignore, NSM_Down }, /* 1-WayReceived */
519
{ nsm_kill_nbr, NSM_Down }, /* KillNbr */
520
{ nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */
521
{ nsm_ll_down, NSM_Down }, /* LLDown */
525
{ nsm_ignore, NSM_DependUpon }, /* NoEvent */
526
{ nsm_hello_received, NSM_Init }, /* HelloReceived */
527
{ nsm_ignore, NSM_Attempt }, /* Start */
528
{ nsm_ignore, NSM_Attempt }, /* 2-WayReceived */
529
{ nsm_ignore, NSM_Attempt }, /* NegotiationDone */
530
{ nsm_ignore, NSM_Attempt }, /* ExchangeDone */
531
{ nsm_ignore, NSM_Attempt }, /* BadLSReq */
532
{ nsm_ignore, NSM_Attempt }, /* LoadingDone */
533
{ nsm_ignore, NSM_Attempt }, /* AdjOK? */
534
{ nsm_ignore, NSM_Attempt }, /* SeqNumberMismatch */
535
{ nsm_ignore, NSM_Attempt }, /* 1-WayReceived */
536
{ nsm_kill_nbr, NSM_Down }, /* KillNbr */
537
{ nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */
538
{ nsm_ll_down, NSM_Down }, /* LLDown */
542
{ nsm_ignore, NSM_DependUpon }, /* NoEvent */
543
{ nsm_hello_received, NSM_Init }, /* HelloReceived */
544
{ nsm_ignore, NSM_Init }, /* Start */
545
{ nsm_twoway_received, NSM_DependUpon }, /* 2-WayReceived */
546
{ nsm_ignore, NSM_Init }, /* NegotiationDone */
547
{ nsm_ignore, NSM_Init }, /* ExchangeDone */
548
{ nsm_ignore, NSM_Init }, /* BadLSReq */
549
{ nsm_ignore, NSM_Init }, /* LoadingDone */
550
{ nsm_ignore, NSM_Init }, /* AdjOK? */
551
{ nsm_ignore, NSM_Init }, /* SeqNumberMismatch */
552
{ nsm_ignore, NSM_Init }, /* 1-WayReceived */
553
{ nsm_kill_nbr, NSM_Down }, /* KillNbr */
554
{ nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */
555
{ nsm_ll_down, NSM_Down }, /* LLDown */
559
{ nsm_ignore, NSM_DependUpon }, /* NoEvent */
560
{ nsm_hello_received, NSM_TwoWay }, /* HelloReceived */
561
{ nsm_ignore, NSM_TwoWay }, /* Start */
562
{ nsm_ignore, NSM_TwoWay }, /* 2-WayReceived */
563
{ nsm_ignore, NSM_TwoWay }, /* NegotiationDone */
564
{ nsm_ignore, NSM_TwoWay }, /* ExchangeDone */
565
{ nsm_ignore, NSM_TwoWay }, /* BadLSReq */
566
{ nsm_ignore, NSM_TwoWay }, /* LoadingDone */
567
{ nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
568
{ nsm_ignore, NSM_TwoWay }, /* SeqNumberMismatch */
569
{ nsm_oneway_received, NSM_Init }, /* 1-WayReceived */
570
{ nsm_kill_nbr, NSM_Down }, /* KillNbr */
571
{ nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */
572
{ nsm_ll_down, NSM_Down }, /* LLDown */
576
{ nsm_ignore, NSM_DependUpon }, /* NoEvent */
577
{ nsm_hello_received, NSM_ExStart }, /* HelloReceived */
578
{ nsm_ignore, NSM_ExStart }, /* Start */
579
{ nsm_ignore, NSM_ExStart }, /* 2-WayReceived */
580
{ nsm_negotiation_done, NSM_Exchange }, /* NegotiationDone */
581
{ nsm_ignore, NSM_ExStart }, /* ExchangeDone */
582
{ nsm_ignore, NSM_ExStart }, /* BadLSReq */
583
{ nsm_ignore, NSM_ExStart }, /* LoadingDone */
584
{ nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
585
{ nsm_ignore, NSM_ExStart }, /* SeqNumberMismatch */
586
{ nsm_oneway_received, NSM_Init }, /* 1-WayReceived */
587
{ nsm_kill_nbr, NSM_Down }, /* KillNbr */
588
{ nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */
589
{ nsm_ll_down, NSM_Down }, /* LLDown */
593
{ nsm_ignore, NSM_DependUpon }, /* NoEvent */
594
{ nsm_hello_received, NSM_Exchange }, /* HelloReceived */
595
{ nsm_ignore, NSM_Exchange }, /* Start */
596
{ nsm_ignore, NSM_Exchange }, /* 2-WayReceived */
597
{ nsm_ignore, NSM_Exchange }, /* NegotiationDone */
598
{ nsm_exchange_done, NSM_DependUpon }, /* ExchangeDone */
599
{ nsm_bad_ls_req, NSM_ExStart }, /* BadLSReq */
600
{ nsm_ignore, NSM_Exchange }, /* LoadingDone */
601
{ nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
602
{ nsm_seq_number_mismatch, NSM_ExStart }, /* SeqNumberMismatch */
603
{ nsm_oneway_received, NSM_Init }, /* 1-WayReceived */
604
{ nsm_kill_nbr, NSM_Down }, /* KillNbr */
605
{ nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */
606
{ nsm_ll_down, NSM_Down }, /* LLDown */
610
{ nsm_ignore, NSM_DependUpon }, /* NoEvent */
611
{ nsm_hello_received, NSM_Loading }, /* HelloReceived */
612
{ nsm_ignore, NSM_Loading }, /* Start */
613
{ nsm_ignore, NSM_Loading }, /* 2-WayReceived */
614
{ nsm_ignore, NSM_Loading }, /* NegotiationDone */
615
{ nsm_ignore, NSM_Loading }, /* ExchangeDone */
616
{ nsm_bad_ls_req, NSM_ExStart }, /* BadLSReq */
617
{ nsm_ignore, NSM_Full }, /* LoadingDone */
618
{ nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
619
{ nsm_seq_number_mismatch, NSM_ExStart }, /* SeqNumberMismatch */
620
{ nsm_oneway_received, NSM_Init }, /* 1-WayReceived */
621
{ nsm_kill_nbr, NSM_Down }, /* KillNbr */
622
{ nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */
623
{ nsm_ll_down, NSM_Down }, /* LLDown */
626
{ nsm_ignore, NSM_DependUpon }, /* NoEvent */
627
{ nsm_hello_received, NSM_Full }, /* HelloReceived */
628
{ nsm_ignore, NSM_Full }, /* Start */
629
{ nsm_ignore, NSM_Full }, /* 2-WayReceived */
630
{ nsm_ignore, NSM_Full }, /* NegotiationDone */
631
{ nsm_ignore, NSM_Full }, /* ExchangeDone */
632
{ nsm_bad_ls_req, NSM_ExStart }, /* BadLSReq */
633
{ nsm_ignore, NSM_Full }, /* LoadingDone */
634
{ nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
635
{ nsm_seq_number_mismatch, NSM_ExStart }, /* SeqNumberMismatch */
636
{ nsm_oneway_received, NSM_Init }, /* 1-WayReceived */
637
{ nsm_kill_nbr, NSM_Down }, /* KillNbr */
638
{ nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */
639
{ nsm_ll_down, NSM_Down }, /* LLDown */
643
const static char *ospf_nsm_event_str[] =
662
nsm_change_state (struct ospf_neighbor *nbr, int state)
664
struct ospf_interface *oi = nbr->oi;
665
struct ospf_area *vl_area = NULL;
670
/* Logging change of status. */
671
if (IS_DEBUG_OSPF (nsm, NSM_STATUS))
672
zlog_debug ("NSM[%s:%s]: State change %s -> %s",
673
IF_NAME (nbr->oi), inet_ntoa (nbr->router_id),
674
LOOKUP (ospf_nsm_state_msg, nbr->state),
675
LOOKUP (ospf_nsm_state_msg, state));
677
/* Preserve old status. */
678
old_state = nbr->state;
680
/* Change to new status. */
686
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
687
vl_area = ospf_area_lookup_by_area_id (oi->ospf, oi->vl_data->vl_area_id);
689
/* One of the neighboring routers changes to/from the FULL state. */
690
if ((old_state != NSM_Full && state == NSM_Full) ||
691
(old_state == NSM_Full && state != NSM_Full))
693
if (state == NSM_Full)
696
oi->area->full_nbrs++;
698
ospf_check_abr_status (oi->ospf);
700
if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area)
701
if (++vl_area->full_vls == 1)
702
ospf_schedule_abr_task (oi->ospf);
704
/* kevinm: refresh any redistributions */
705
for (x = ZEBRA_ROUTE_SYSTEM; x < ZEBRA_ROUTE_MAX; x++)
707
if (x == ZEBRA_ROUTE_OSPF || x == ZEBRA_ROUTE_OSPF6)
709
ospf_external_lsa_refresh_type (oi->ospf, x, force);
715
oi->area->full_nbrs--;
717
ospf_check_abr_status (oi->ospf);
719
if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area)
720
if (vl_area->full_vls > 0)
721
if (--vl_area->full_vls == 0)
722
ospf_schedule_abr_task (oi->ospf);
724
/* clear neighbor retransmit list */
725
if (!ospf_ls_retransmit_isempty (nbr))
726
ospf_ls_retransmit_clear (nbr);
729
zlog_info ("nsm_change_state(%s, %s -> %s): "
730
"scheduling new router-LSA origination",
731
inet_ntoa (nbr->router_id),
732
LOOKUP(ospf_nsm_state_msg, old_state),
733
LOOKUP(ospf_nsm_state_msg, state));
735
ospf_router_lsa_timer_add (oi->area);
737
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
739
struct ospf_area *vl_area =
740
ospf_area_lookup_by_area_id (oi->ospf, oi->vl_data->vl_area_id);
743
ospf_router_lsa_timer_add (vl_area);
746
/* Originate network-LSA. */
747
if (oi->state == ISM_DR)
749
if (oi->network_lsa_self && oi->full_nbrs == 0)
751
ospf_lsa_flush_area (oi->network_lsa_self, oi->area);
752
ospf_lsa_unlock (oi->network_lsa_self);
753
oi->network_lsa_self = NULL;
754
OSPF_TIMER_OFF (oi->t_network_lsa_self);
757
ospf_network_lsa_timer_add (oi);
761
#ifdef HAVE_OPAQUE_LSA
762
ospf_opaque_nsm_change (nbr, old_state);
763
#endif /* HAVE_OPAQUE_LSA */
765
/* Start DD exchange protocol */
766
if (state == NSM_ExStart)
768
if (nbr->dd_seqnum == 0)
769
nbr->dd_seqnum = time (NULL);
773
nbr->dd_flags = OSPF_DD_FLAG_I|OSPF_DD_FLAG_M|OSPF_DD_FLAG_MS;
774
ospf_db_desc_send (nbr);
777
/* clear cryptographic sequence number */
778
if (state == NSM_Down)
779
nbr->crypt_seqnum = 0;
781
/* Generete NeighborChange ISM event. */
782
#ifdef BUGGY_ISM_TRANSITION
783
if ((old_state < NSM_TwoWay && state >= NSM_TwoWay) ||
784
(old_state >= NSM_TwoWay && state < NSM_TwoWay))
785
OSPF_ISM_EVENT_EXECUTE (oi, ISM_NeighborChange);
786
#else /* BUGGY_ISM_TRANSITION */
791
if ((old_state < NSM_TwoWay && state >= NSM_TwoWay) ||
792
(old_state >= NSM_TwoWay && state < NSM_TwoWay))
793
OSPF_ISM_EVENT_EXECUTE (oi, ISM_NeighborChange);
796
/* ISM_PointToPoint -> ISM_Down, ISM_Loopback -> ISM_Down, etc. */
799
#endif /* BUGGY_ISM_TRANSITION */
801
/* Performance hack. Send hello immideately when some neighbor enter
802
Init state. This whay we decrease neighbor discovery time. Gleb.*/
803
if (state == NSM_Init)
805
OSPF_ISM_TIMER_OFF (oi->t_hello);
806
OSPF_ISM_TIMER_ON (oi->t_hello, ospf_hello_timer, 1);
809
/* Preserve old status? */
812
/* Execute NSM event process. */
814
ospf_nsm_event (struct thread *thread)
818
struct ospf_neighbor *nbr;
819
struct in_addr router_id;
821
struct ospf_interface *oi;
823
nbr = THREAD_ARG (thread);
824
event = THREAD_VAL (thread);
825
router_id = nbr->router_id;
827
old_state = nbr->state;
831
next_state = (*(NSM [nbr->state][event].func))(nbr);
833
/* When event is NSM_KillNbr or InactivityTimer, the neighbor is
835
if (event == NSM_KillNbr || event == NSM_InactivityTimer)
837
if (IS_DEBUG_OSPF (nsm, NSM_EVENTS))
838
zlog_debug ("NSM[%s:%s]: neighbor deleted",
839
IF_NAME (oi), inet_ntoa (router_id));
841
/* Timers are canceled in ospf_nbr_free, moreover we cannot call
842
nsm_timer_set here because nbr is freed already!!!*/
843
/*nsm_timer_set (nbr);*/
849
next_state = NSM [nbr->state][event].next_state;
851
if (IS_DEBUG_OSPF (nsm, NSM_EVENTS))
852
zlog_debug ("NSM[%s:%s]: %s (%s)", IF_NAME (oi),
853
inet_ntoa (nbr->router_id),
854
LOOKUP (ospf_nsm_state_msg, nbr->state),
855
ospf_nsm_event_str [event]);
857
/* If state is changed. */
858
if (next_state != nbr->state)
859
nsm_change_state (nbr, next_state);
861
/* Make sure timer is set. */
867
/* Check loading state. */
869
ospf_check_nbr_loading (struct ospf_neighbor *nbr)
871
if (nbr->state == NSM_Loading)
873
if (ospf_ls_request_isempty (nbr))
874
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_LoadingDone);
875
else if (nbr->ls_req_last == NULL)
876
ospf_ls_req_event (nbr);