]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_nsm.c
ospfd: Remove HAVE_OPAQUE_LSA
[mirror_frr.git] / ospfd / ospf_nsm.c
1 /*
2 * OSPF version 2 Neighbor State Machine
3 * From RFC2328 [OSPF Version 2]
4 * Copyright (C) 1999, 2000 Toshiaki Takada
5 *
6 * This file is part of GNU Zebra.
7 *
8 * GNU Zebra is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
11 * later version.
12 *
13 * GNU Zebra is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with GNU Zebra; see the file COPYING. If not, write to the Free
20 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 * 02111-1307, USA.
22 */
23
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"
50 #include "ospfd/ospf_snmp.h"
51 #include "ospfd/ospf_bfd.h"
52
53 static void nsm_clear_adj (struct ospf_neighbor *);
54
55 /* OSPF NSM Timer functions. */
56 static int
57 ospf_inactivity_timer (struct thread *thread)
58 {
59 struct ospf_neighbor *nbr;
60
61 nbr = THREAD_ARG (thread);
62 nbr->t_inactivity = NULL;
63
64 if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
65 zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (Inactivity timer expire)",
66 IF_NAME (nbr->oi), inet_ntoa (nbr->router_id));
67
68 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_InactivityTimer);
69
70 return 0;
71 }
72
73 static int
74 ospf_db_desc_timer (struct thread *thread)
75 {
76 struct ospf_neighbor *nbr;
77
78 nbr = THREAD_ARG (thread);
79 nbr->t_db_desc = NULL;
80
81 if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
82 zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (DD Retransmit timer expire)",
83 IF_NAME (nbr->oi), inet_ntoa (nbr->src));
84
85 /* resent last send DD packet. */
86 assert (nbr->last_send);
87 ospf_db_desc_resend (nbr);
88
89 /* DD Retransmit timer set. */
90 OSPF_NSM_TIMER_ON (nbr->t_db_desc, ospf_db_desc_timer, nbr->v_db_desc);
91
92 return 0;
93 }
94
95 /* Hook function called after ospf NSM event is occured.
96 *
97 * Set/clear any timers whose condition is implicit to the neighbour
98 * state. There may be other timers which are set/unset according to other
99 * state.
100 *
101 * We rely on this function to properly clear timers in lower states,
102 * particularly before deleting a neighbour.
103 */
104 static void
105 nsm_timer_set (struct ospf_neighbor *nbr)
106 {
107 switch (nbr->state)
108 {
109 case NSM_Deleted:
110 case NSM_Down:
111 OSPF_NSM_TIMER_OFF (nbr->t_inactivity);
112 OSPF_NSM_TIMER_OFF (nbr->t_hello_reply);
113 case NSM_Attempt:
114 case NSM_Init:
115 case NSM_TwoWay:
116 OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
117 OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
118 OSPF_NSM_TIMER_OFF (nbr->t_ls_req);
119 break;
120 case NSM_ExStart:
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);
123 OSPF_NSM_TIMER_OFF (nbr->t_ls_req);
124 break;
125 case NSM_Exchange:
126 OSPF_NSM_TIMER_ON (nbr->t_ls_upd, ospf_ls_upd_timer, nbr->v_ls_upd);
127 if (!IS_SET_DD_MS (nbr->dd_flags))
128 OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
129 break;
130 case NSM_Loading:
131 case NSM_Full:
132 default:
133 OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
134 break;
135 }
136 }
137
138 /* 10.4 of RFC2328, indicate whether an adjacency is appropriate with
139 * the given neighbour
140 */
141 static int
142 nsm_should_adj (struct ospf_neighbor *nbr)
143 {
144 struct ospf_interface *oi = nbr->oi;
145
146 /* These network types must always form adjacencies. */
147 if (oi->type == OSPF_IFTYPE_POINTOPOINT
148 || oi->type == OSPF_IFTYPE_POINTOMULTIPOINT
149 || oi->type == OSPF_IFTYPE_VIRTUALLINK
150 /* Router itself is the DRouter or the BDRouter. */
151 || IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))
152 || IPV4_ADDR_SAME (&oi->address->u.prefix4, &BDR (oi))
153 /* Neighboring Router is the DRouter or the BDRouter. */
154 || IPV4_ADDR_SAME (&nbr->address.u.prefix4, &DR (oi))
155 || IPV4_ADDR_SAME (&nbr->address.u.prefix4, &BDR (oi)))
156 return 1;
157
158 return 0;
159 }
160
161 /* OSPF NSM functions. */
162 static int
163 nsm_packet_received (struct ospf_neighbor *nbr)
164 {
165 /* Start or Restart Inactivity Timer. */
166 OSPF_NSM_TIMER_OFF (nbr->t_inactivity);
167
168 OSPF_NSM_TIMER_ON (nbr->t_inactivity, ospf_inactivity_timer,
169 nbr->v_inactivity);
170
171 if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma)
172 OSPF_POLL_TIMER_OFF (nbr->nbr_nbma->t_poll);
173
174 /* Send proactive ARP requests */
175 if (nbr->state < NSM_Exchange)
176 ospf_proactively_arp (nbr);
177
178 return 0;
179 }
180
181 static int
182 nsm_start (struct ospf_neighbor *nbr)
183 {
184 if (nbr->nbr_nbma)
185 OSPF_POLL_TIMER_OFF (nbr->nbr_nbma->t_poll);
186
187 OSPF_NSM_TIMER_OFF (nbr->t_inactivity);
188
189 OSPF_NSM_TIMER_ON (nbr->t_inactivity, ospf_inactivity_timer,
190 nbr->v_inactivity);
191
192 /* Send proactive ARP requests */
193 ospf_proactively_arp (nbr);
194
195 return 0;
196 }
197
198 static int
199 nsm_twoway_received (struct ospf_neighbor *nbr)
200 {
201 int adj = nsm_should_adj (nbr);
202
203 /* Send proactive ARP requests */
204 if (adj)
205 ospf_proactively_arp (nbr);
206
207 return (adj ? NSM_ExStart : NSM_TwoWay);
208 }
209
210 int
211 ospf_db_summary_count (struct ospf_neighbor *nbr)
212 {
213 return ospf_lsdb_count_all (&nbr->db_sum);
214 }
215
216 int
217 ospf_db_summary_isempty (struct ospf_neighbor *nbr)
218 {
219 return ospf_lsdb_isempty (&nbr->db_sum);
220 }
221
222 static int
223 ospf_db_summary_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
224 {
225 switch (lsa->data->type)
226 {
227 case OSPF_OPAQUE_LINK_LSA:
228 /* Exclude type-9 LSAs that does not have the same "oi" with "nbr". */
229 if (nbr->oi && ospf_if_exists (lsa->oi) != nbr->oi)
230 return 0;
231 break;
232 case OSPF_OPAQUE_AREA_LSA:
233 /*
234 * It is assured by the caller function "nsm_negotiation_done()"
235 * that every given LSA belongs to the same area with "nbr".
236 */
237 break;
238 case OSPF_OPAQUE_AS_LSA:
239 default:
240 break;
241 }
242
243 /* Stay away from any Local Translated Type-7 LSAs */
244 if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
245 return 0;
246
247 if (IS_LSA_MAXAGE (lsa))
248 ospf_ls_retransmit_add (nbr, lsa);
249 else
250 ospf_lsdb_add (&nbr->db_sum, lsa);
251
252 return 0;
253 }
254
255 void
256 ospf_db_summary_clear (struct ospf_neighbor *nbr)
257 {
258 struct ospf_lsdb *lsdb;
259 int i;
260
261 lsdb = &nbr->db_sum;
262 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
263 {
264 struct route_table *table = lsdb->type[i].db;
265 struct route_node *rn;
266
267 for (rn = route_top (table); rn; rn = route_next (rn))
268 if (rn->info)
269 ospf_lsdb_delete (&nbr->db_sum, rn->info);
270 }
271 }
272
273
274
275 /* The area link state database consists of the router-LSAs,
276 network-LSAs and summary-LSAs contained in the area structure,
277 along with the AS-external-LSAs contained in the global structure.
278 AS-external-LSAs are omitted from a virtual neighbor's Database
279 summary list. AS-external-LSAs are omitted from the Database
280 summary list if the area has been configured as a stub. */
281 static int
282 nsm_negotiation_done (struct ospf_neighbor *nbr)
283 {
284 struct ospf_area *area = nbr->oi->area;
285 struct ospf_lsa *lsa;
286 struct route_node *rn;
287
288 /* Send proactive ARP requests */
289 ospf_proactively_arp (nbr);
290
291 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
292 ospf_db_summary_add (nbr, lsa);
293 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
294 ospf_db_summary_add (nbr, lsa);
295 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
296 ospf_db_summary_add (nbr, lsa);
297 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
298 ospf_db_summary_add (nbr, lsa);
299
300 /* Process only if the neighbor is opaque capable. */
301 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
302 {
303 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
304 ospf_db_summary_add (nbr, lsa);
305 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
306 ospf_db_summary_add (nbr, lsa);
307 }
308
309 if (CHECK_FLAG (nbr->options, OSPF_OPTION_NP))
310 {
311 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
312 ospf_db_summary_add (nbr, lsa);
313 }
314
315 if (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK
316 && area->external_routing == OSPF_AREA_DEFAULT)
317 LSDB_LOOP (EXTERNAL_LSDB (nbr->oi->ospf), rn, lsa)
318 ospf_db_summary_add (nbr, lsa);
319
320 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)
321 && (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK
322 && area->external_routing == OSPF_AREA_DEFAULT))
323 LSDB_LOOP (OPAQUE_AS_LSDB (nbr->oi->ospf), rn, lsa)
324 ospf_db_summary_add (nbr, lsa);
325
326 return 0;
327 }
328
329 static int
330 nsm_exchange_done (struct ospf_neighbor *nbr)
331 {
332 if (ospf_ls_request_isempty (nbr))
333 return NSM_Full;
334
335 /* Send Link State Request. */
336 if (nbr->t_ls_req == NULL)
337 ospf_ls_req_send (nbr);
338
339 return NSM_Loading;
340 }
341
342 static int
343 nsm_adj_ok (struct ospf_neighbor *nbr)
344 {
345 int next_state = nbr->state;
346 int adj = nsm_should_adj (nbr);
347
348 if (nbr->state == NSM_TwoWay && adj == 1)
349 {
350 next_state = NSM_ExStart;
351
352 /* Send proactive ARP requests */
353 ospf_proactively_arp (nbr);
354 }
355 else if (nbr->state >= NSM_ExStart && adj == 0)
356 next_state = NSM_TwoWay;
357
358 return next_state;
359 }
360
361 /* Clear adjacency related state for a neighbour, intended where nbr
362 * transitions from > ExStart (i.e. a Full or forming adjacency)
363 * to <= ExStart.
364 */
365 static void
366 nsm_clear_adj (struct ospf_neighbor *nbr)
367 {
368 /* Clear Database Summary list. */
369 if (!ospf_db_summary_isempty (nbr))
370 ospf_db_summary_clear (nbr);
371
372 /* Clear Link State Request list. */
373 if (!ospf_ls_request_isempty (nbr))
374 ospf_ls_request_delete_all (nbr);
375
376 /* Clear Link State Retransmission list. */
377 if (!ospf_ls_retransmit_isempty (nbr))
378 ospf_ls_retransmit_clear (nbr);
379
380 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
381 UNSET_FLAG (nbr->options, OSPF_OPTION_O);
382 }
383
384 static int
385 nsm_kill_nbr (struct ospf_neighbor *nbr)
386 {
387 /* killing nbr_self is invalid */
388 if (nbr == nbr->oi->nbr_self)
389 {
390 assert (nbr != nbr->oi->nbr_self);
391 return 0;
392 }
393
394 if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma != NULL)
395 {
396 struct ospf_nbr_nbma *nbr_nbma = nbr->nbr_nbma;
397
398 nbr_nbma->nbr = NULL;
399 nbr_nbma->state_change = nbr->state_change;
400
401 nbr->nbr_nbma = NULL;
402
403 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
404 nbr_nbma->v_poll);
405
406 if (IS_DEBUG_OSPF (nsm, NSM_EVENTS))
407 zlog_debug ("NSM[%s:%s]: Down (PollIntervalTimer scheduled)",
408 IF_NAME (nbr->oi), inet_ntoa (nbr->address.u.prefix4));
409 }
410
411 return 0;
412 }
413
414 /* Neighbor State Machine */
415 struct {
416 int (*func) (struct ospf_neighbor *);
417 int next_state;
418 } NSM [OSPF_NSM_STATE_MAX][OSPF_NSM_EVENT_MAX] =
419 {
420 {
421 /* DependUpon: dummy state. */
422 { NULL, NSM_DependUpon }, /* NoEvent */
423 { NULL, NSM_DependUpon }, /* PacketReceived */
424 { NULL, NSM_DependUpon }, /* Start */
425 { NULL, NSM_DependUpon }, /* 2-WayReceived */
426 { NULL, NSM_DependUpon }, /* NegotiationDone */
427 { NULL, NSM_DependUpon }, /* ExchangeDone */
428 { NULL, NSM_DependUpon }, /* BadLSReq */
429 { NULL, NSM_DependUpon }, /* LoadingDone */
430 { NULL, NSM_DependUpon }, /* AdjOK? */
431 { NULL, NSM_DependUpon }, /* SeqNumberMismatch */
432 { NULL, NSM_DependUpon }, /* 1-WayReceived */
433 { NULL, NSM_DependUpon }, /* KillNbr */
434 { NULL, NSM_DependUpon }, /* InactivityTimer */
435 { NULL, NSM_DependUpon }, /* LLDown */
436 },
437 {
438 /* Deleted: dummy state. */
439 { NULL, NSM_Deleted }, /* NoEvent */
440 { NULL, NSM_Deleted }, /* PacketReceived */
441 { NULL, NSM_Deleted }, /* Start */
442 { NULL, NSM_Deleted }, /* 2-WayReceived */
443 { NULL, NSM_Deleted }, /* NegotiationDone */
444 { NULL, NSM_Deleted }, /* ExchangeDone */
445 { NULL, NSM_Deleted }, /* BadLSReq */
446 { NULL, NSM_Deleted }, /* LoadingDone */
447 { NULL, NSM_Deleted }, /* AdjOK? */
448 { NULL, NSM_Deleted }, /* SeqNumberMismatch */
449 { NULL, NSM_Deleted }, /* 1-WayReceived */
450 { NULL, NSM_Deleted }, /* KillNbr */
451 { NULL, NSM_Deleted }, /* InactivityTimer */
452 { NULL, NSM_Deleted }, /* LLDown */
453 },
454 {
455 /* Down: */
456 { NULL, NSM_DependUpon }, /* NoEvent */
457 { nsm_packet_received, NSM_Init }, /* PacketReceived */
458 { nsm_start, NSM_Attempt }, /* Start */
459 { NULL, NSM_Down }, /* 2-WayReceived */
460 { NULL, NSM_Down }, /* NegotiationDone */
461 { NULL, NSM_Down }, /* ExchangeDone */
462 { NULL, NSM_Down }, /* BadLSReq */
463 { NULL, NSM_Down }, /* LoadingDone */
464 { NULL, NSM_Down }, /* AdjOK? */
465 { NULL, NSM_Down }, /* SeqNumberMismatch */
466 { NULL, NSM_Down }, /* 1-WayReceived */
467 { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
468 { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
469 { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
470 },
471 {
472 /* Attempt: */
473 { NULL, NSM_DependUpon }, /* NoEvent */
474 { nsm_packet_received, NSM_Init }, /* PacketReceived */
475 { NULL, NSM_Attempt }, /* Start */
476 { NULL, NSM_Attempt }, /* 2-WayReceived */
477 { NULL, NSM_Attempt }, /* NegotiationDone */
478 { NULL, NSM_Attempt }, /* ExchangeDone */
479 { NULL, NSM_Attempt }, /* BadLSReq */
480 { NULL, NSM_Attempt }, /* LoadingDone */
481 { NULL, NSM_Attempt }, /* AdjOK? */
482 { NULL, NSM_Attempt }, /* SeqNumberMismatch */
483 { NULL, NSM_Attempt }, /* 1-WayReceived */
484 { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
485 { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
486 { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
487 },
488 {
489 /* Init: */
490 { NULL, NSM_DependUpon }, /* NoEvent */
491 { nsm_packet_received, NSM_Init }, /* PacketReceived */
492 { NULL, NSM_Init }, /* Start */
493 { nsm_twoway_received, NSM_DependUpon }, /* 2-WayReceived */
494 { NULL, NSM_Init }, /* NegotiationDone */
495 { NULL, NSM_Init }, /* ExchangeDone */
496 { NULL, NSM_Init }, /* BadLSReq */
497 { NULL, NSM_Init }, /* LoadingDone */
498 { NULL, NSM_Init }, /* AdjOK? */
499 { NULL, NSM_Init }, /* SeqNumberMismatch */
500 { NULL, NSM_Init }, /* 1-WayReceived */
501 { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
502 { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
503 { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
504 },
505 {
506 /* 2-Way: */
507 { NULL, NSM_DependUpon }, /* NoEvent */
508 { nsm_packet_received, NSM_TwoWay }, /* HelloReceived */
509 { NULL, NSM_TwoWay }, /* Start */
510 { NULL, NSM_TwoWay }, /* 2-WayReceived */
511 { NULL, NSM_TwoWay }, /* NegotiationDone */
512 { NULL, NSM_TwoWay }, /* ExchangeDone */
513 { NULL, NSM_TwoWay }, /* BadLSReq */
514 { NULL, NSM_TwoWay }, /* LoadingDone */
515 { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
516 { NULL, NSM_TwoWay }, /* SeqNumberMismatch */
517 { NULL, NSM_Init }, /* 1-WayReceived */
518 { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
519 { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
520 { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
521 },
522 {
523 /* ExStart: */
524 { NULL, NSM_DependUpon }, /* NoEvent */
525 { nsm_packet_received, NSM_ExStart }, /* PacaketReceived */
526 { NULL, NSM_ExStart }, /* Start */
527 { NULL, NSM_ExStart }, /* 2-WayReceived */
528 { nsm_negotiation_done, NSM_Exchange }, /* NegotiationDone */
529 { NULL, NSM_ExStart }, /* ExchangeDone */
530 { NULL, NSM_ExStart }, /* BadLSReq */
531 { NULL, NSM_ExStart }, /* LoadingDone */
532 { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
533 { NULL, NSM_ExStart }, /* SeqNumberMismatch */
534 { NULL, NSM_Init }, /* 1-WayReceived */
535 { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
536 { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
537 { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
538 },
539 {
540 /* Exchange: */
541 { NULL, NSM_DependUpon }, /* NoEvent */
542 { nsm_packet_received, NSM_Exchange }, /* PacketReceived */
543 { NULL, NSM_Exchange }, /* Start */
544 { NULL, NSM_Exchange }, /* 2-WayReceived */
545 { NULL, NSM_Exchange }, /* NegotiationDone */
546 { nsm_exchange_done, NSM_DependUpon }, /* ExchangeDone */
547 { NULL, NSM_ExStart }, /* BadLSReq */
548 { NULL, NSM_Exchange }, /* LoadingDone */
549 { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
550 { NULL, NSM_ExStart }, /* SeqNumberMismatch */
551 { NULL, NSM_Init }, /* 1-WayReceived */
552 { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
553 { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
554 { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
555 },
556 {
557 /* Loading: */
558 { NULL, NSM_DependUpon }, /* NoEvent */
559 { nsm_packet_received, NSM_Loading }, /* PacketReceived */
560 { NULL, NSM_Loading }, /* Start */
561 { NULL, NSM_Loading }, /* 2-WayReceived */
562 { NULL, NSM_Loading }, /* NegotiationDone */
563 { NULL, NSM_Loading }, /* ExchangeDone */
564 { NULL, NSM_ExStart }, /* BadLSReq */
565 { NULL, NSM_Full }, /* LoadingDone */
566 { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
567 { NULL, NSM_ExStart }, /* SeqNumberMismatch */
568 { NULL, NSM_Init }, /* 1-WayReceived */
569 { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
570 { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
571 { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
572 },
573 { /* Full: */
574 { NULL, NSM_DependUpon }, /* NoEvent */
575 { nsm_packet_received, NSM_Full }, /* PacketReceived */
576 { NULL, NSM_Full }, /* Start */
577 { NULL, NSM_Full }, /* 2-WayReceived */
578 { NULL, NSM_Full }, /* NegotiationDone */
579 { NULL, NSM_Full }, /* ExchangeDone */
580 { NULL, NSM_ExStart }, /* BadLSReq */
581 { NULL, NSM_Full }, /* LoadingDone */
582 { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */
583 { NULL, NSM_ExStart }, /* SeqNumberMismatch */
584 { NULL, NSM_Init }, /* 1-WayReceived */
585 { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */
586 { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */
587 { nsm_kill_nbr, NSM_Deleted }, /* LLDown */
588 },
589 };
590
591 static const char *ospf_nsm_event_str[] =
592 {
593 "NoEvent",
594 "PacketReceived",
595 "Start",
596 "2-WayReceived",
597 "NegotiationDone",
598 "ExchangeDone",
599 "BadLSReq",
600 "LoadingDone",
601 "AdjOK?",
602 "SeqNumberMismatch",
603 "1-WayReceived",
604 "KillNbr",
605 "InactivityTimer",
606 "LLDown",
607 };
608
609 static void
610 nsm_notice_state_change (struct ospf_neighbor *nbr, int next_state, int event)
611 {
612 /* Logging change of status. */
613 if (IS_DEBUG_OSPF (nsm, NSM_STATUS))
614 zlog_debug ("NSM[%s:%s]: State change %s -> %s (%s)",
615 IF_NAME (nbr->oi), inet_ntoa (nbr->router_id),
616 LOOKUP (ospf_nsm_state_msg, nbr->state),
617 LOOKUP (ospf_nsm_state_msg, next_state),
618 ospf_nsm_event_str [event]);
619
620 /* Optionally notify about adjacency changes */
621 if (CHECK_FLAG(nbr->oi->ospf->config, OSPF_LOG_ADJACENCY_CHANGES) &&
622 (CHECK_FLAG(nbr->oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL) ||
623 (next_state == NSM_Full) || (next_state < nbr->state)))
624 zlog_notice("AdjChg: Nbr %s on %s: %s -> %s (%s)",
625 inet_ntoa (nbr->router_id), IF_NAME (nbr->oi),
626 LOOKUP (ospf_nsm_state_msg, nbr->state),
627 LOOKUP (ospf_nsm_state_msg, next_state),
628 ospf_nsm_event_str [event]);
629
630 /* Advance in NSM */
631 if (next_state > nbr->state)
632 nbr->ts_last_progress = recent_relative_time ();
633 else /* regression in NSM */
634 {
635 nbr->ts_last_regress = recent_relative_time ();
636 nbr->last_regress_str = ospf_nsm_event_str [event];
637 }
638
639 }
640
641 static void
642 nsm_change_state (struct ospf_neighbor *nbr, int state)
643 {
644 struct ospf_interface *oi = nbr->oi;
645 struct ospf_area *vl_area = NULL;
646 u_char old_state;
647 int x;
648 int force = 1;
649
650 /* Preserve old status. */
651 old_state = nbr->state;
652
653 /* Change to new status. */
654 nbr->state = state;
655
656 /* Statistics. */
657 nbr->state_change++;
658
659 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
660 vl_area = ospf_area_lookup_by_area_id (oi->ospf, oi->vl_data->vl_area_id);
661
662 /* Generate NeighborChange ISM event.
663 *
664 * In response to NeighborChange, DR election is rerun. The information
665 * from the election process is required by the router-lsa construction.
666 *
667 * Therefore, trigger the event prior to refreshing the LSAs. */
668 switch (oi->state) {
669 case ISM_DROther:
670 case ISM_Backup:
671 case ISM_DR:
672 if ((old_state < NSM_TwoWay && state >= NSM_TwoWay) ||
673 (old_state >= NSM_TwoWay && state < NSM_TwoWay))
674 OSPF_ISM_EVENT_EXECUTE (oi, ISM_NeighborChange);
675 break;
676 default:
677 /* ISM_PointToPoint -> ISM_Down, ISM_Loopback -> ISM_Down, etc. */
678 break;
679 }
680
681 /* One of the neighboring routers changes to/from the FULL state. */
682 if ((old_state != NSM_Full && state == NSM_Full) ||
683 (old_state == NSM_Full && state != NSM_Full))
684 {
685 if (state == NSM_Full)
686 {
687 oi->full_nbrs++;
688 oi->area->full_nbrs++;
689
690 ospf_check_abr_status (oi->ospf);
691
692 if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area)
693 if (++vl_area->full_vls == 1)
694 ospf_schedule_abr_task (oi->ospf);
695
696 /* kevinm: refresh any redistributions */
697 for (x = ZEBRA_ROUTE_SYSTEM; x < ZEBRA_ROUTE_MAX; x++)
698 {
699 struct list *red_list;
700 struct listnode *node;
701 struct ospf_redist *red;
702
703 if (x == ZEBRA_ROUTE_OSPF6)
704 continue;
705
706 red_list = oi->ospf->redist[x];
707 if (!red_list)
708 continue;
709
710 for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
711 ospf_external_lsa_refresh_type (oi->ospf, x, red->instance, force);
712 }
713 /* XXX: Clearly some thing is wrong with refresh of external LSAs
714 * this added to hack around defaults not refreshing after a timer
715 * jump.
716 */
717 ospf_external_lsa_refresh_default (oi->ospf);
718 }
719 else
720 {
721 oi->full_nbrs--;
722 oi->area->full_nbrs--;
723
724 ospf_check_abr_status (oi->ospf);
725
726 if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area)
727 if (vl_area->full_vls > 0)
728 if (--vl_area->full_vls == 0)
729 ospf_schedule_abr_task (oi->ospf);
730 }
731
732 zlog_info ("nsm_change_state(%s, %s -> %s): "
733 "scheduling new router-LSA origination",
734 inet_ntoa (nbr->router_id),
735 LOOKUP(ospf_nsm_state_msg, old_state),
736 LOOKUP(ospf_nsm_state_msg, state));
737
738 ospf_router_lsa_update_area (oi->area);
739
740 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
741 {
742 struct ospf_area *vl_area =
743 ospf_area_lookup_by_area_id (oi->ospf, oi->vl_data->vl_area_id);
744
745 if (vl_area)
746 ospf_router_lsa_update_area (vl_area);
747 }
748
749 /* Originate network-LSA. */
750 if (oi->state == ISM_DR)
751 {
752 if (oi->network_lsa_self && oi->full_nbrs == 0)
753 {
754 ospf_lsa_flush_area (oi->network_lsa_self, oi->area);
755 ospf_lsa_unlock (&oi->network_lsa_self);
756 oi->network_lsa_self = NULL;
757 }
758 else
759 ospf_network_lsa_update (oi);
760 }
761 }
762
763 ospf_opaque_nsm_change (nbr, old_state);
764
765 /* State changes from > ExStart to <= ExStart should clear any Exchange
766 * or Full/LSA Update related lists and state.
767 * Potential causal events: BadLSReq, SeqNumberMismatch, AdjOK?
768 */
769 if ((old_state > NSM_ExStart) && (state <= NSM_ExStart))
770 nsm_clear_adj (nbr);
771
772 /* Start DD exchange protocol */
773 if (state == NSM_ExStart)
774 {
775 if (nbr->dd_seqnum == 0)
776 nbr->dd_seqnum = (uint32_t)random ();
777 else
778 nbr->dd_seqnum++;
779
780 nbr->dd_flags = OSPF_DD_FLAG_I|OSPF_DD_FLAG_M|OSPF_DD_FLAG_MS;
781 ospf_db_desc_send (nbr);
782 }
783
784 /* clear cryptographic sequence number */
785 if (state == NSM_Down)
786 nbr->crypt_seqnum = 0;
787
788 ospf_bfd_trigger_event(nbr, old_state, state);
789
790 /* Preserve old status? */
791 }
792
793 /* Execute NSM event process. */
794 int
795 ospf_nsm_event (struct thread *thread)
796 {
797 int event;
798 int next_state;
799 struct ospf_neighbor *nbr;
800
801 nbr = THREAD_ARG (thread);
802 event = THREAD_VAL (thread);
803
804 if (IS_DEBUG_OSPF (nsm, NSM_EVENTS))
805 zlog_debug ("NSM[%s:%s]: %s (%s)", IF_NAME (nbr->oi),
806 inet_ntoa (nbr->router_id),
807 LOOKUP (ospf_nsm_state_msg, nbr->state),
808 ospf_nsm_event_str [event]);
809
810 next_state = NSM [nbr->state][event].next_state;
811
812 /* Call function. */
813 if (NSM [nbr->state][event].func != NULL)
814 {
815 int func_state = (*(NSM [nbr->state][event].func))(nbr);
816
817 if (NSM [nbr->state][event].next_state == NSM_DependUpon)
818 next_state = func_state;
819 else if (func_state)
820 {
821 /* There's a mismatch between the FSM tables and what an FSM
822 * action/state-change function returned. State changes which
823 * do not have conditional/DependUpon next-states should not
824 * try set next_state.
825 */
826 zlog_warn ("NSM[%s:%s]: %s (%s): "
827 "Warning: action tried to change next_state to %s",
828 IF_NAME (nbr->oi), inet_ntoa (nbr->router_id),
829 LOOKUP (ospf_nsm_state_msg, nbr->state),
830 ospf_nsm_event_str [event],
831 LOOKUP (ospf_nsm_state_msg, func_state));
832 }
833 }
834
835 assert (next_state != NSM_DependUpon);
836
837 /* If state is changed. */
838 if (next_state != nbr->state)
839 {
840 nsm_notice_state_change (nbr, next_state, event);
841 #ifdef HAVE_SNMP
842 int send_trap_virt = 0;
843 int send_trap = 0;
844 /* Terminal state or regression */
845 if ((next_state == NSM_Full)
846 || (next_state == NSM_TwoWay)
847 || (next_state < nbr->state))
848 {
849 /* ospfVirtNbrStateChange */
850 if (nbr->oi->type == OSPF_IFTYPE_VIRTUALLINK)
851 send_trap_virt = 1;
852 /* ospfNbrStateChange trap */
853 else
854 /* To/From FULL, only managed by DR */
855 if (((next_state != NSM_Full) && (nbr->state != NSM_Full))
856 || (nbr->oi->state == ISM_DR))
857 send_trap = 1;
858 }
859 #endif
860 nsm_change_state (nbr, next_state);
861
862 #ifdef HAVE_SNMP
863 if (send_trap_virt) {
864 ospfTrapVirtNbrStateChange(nbr);
865 } else if (send_trap) {
866 ospfTrapNbrStateChange(nbr);
867 }
868 #endif
869 }
870
871 /* Make sure timer is set. */
872 nsm_timer_set (nbr);
873
874 /* When event is NSM_KillNbr, InactivityTimer or LLDown, the neighbor
875 * is deleted.
876 *
877 * Rather than encode knowledge here of which events lead to NBR
878 * delete, we take our cue from the NSM table, via the dummy
879 * 'Deleted' neighbour state.
880 */
881 if (nbr->state == NSM_Deleted)
882 ospf_nbr_delete (nbr);
883
884 return 0;
885 }
886
887 /* Check loading state. */
888 void
889 ospf_check_nbr_loading (struct ospf_neighbor *nbr)
890 {
891 if (nbr->state == NSM_Loading)
892 {
893 if (ospf_ls_request_isempty (nbr))
894 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_LoadingDone);
895 else if (nbr->ls_req_last == NULL)
896 ospf_ls_req_event (nbr);
897 }
898 }