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