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