blob: 28525ce6afccaa250c960732b7a3fd5a7d0eb8b0 [file] [log] [blame]
jardineb5d44e2003-12-23 08:09:43 +00001/*
2 * IS-IS Rout(e)ing protocol - isis_spf.c
3 * The SPT algorithm
4 *
5 * Copyright (C) 2001,2002 Sampo Saaristo
6 * Tampere University of Technology
7 * Institute of Communications Engineering
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public Licenseas published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
jardineb5d44e2003-12-23 08:09:43 +000024#include <zebra.h>
jardineb5d44e2003-12-23 08:09:43 +000025
26#include "thread.h"
27#include "linklist.h"
28#include "vty.h"
29#include "log.h"
30#include "command.h"
31#include "memory.h"
32#include "prefix.h"
33#include "hash.h"
34#include "if.h"
35#include "table.h"
36
37#include "isis_constants.h"
38#include "isis_common.h"
Josh Bailey3f045a02012-03-24 08:35:20 -070039#include "isis_flags.h"
jardineb5d44e2003-12-23 08:09:43 +000040#include "dict.h"
41#include "isisd.h"
42#include "isis_misc.h"
43#include "isis_adjacency.h"
44#include "isis_circuit.h"
45#include "isis_tlv.h"
46#include "isis_pdu.h"
47#include "isis_lsp.h"
48#include "isis_dynhn.h"
49#include "isis_spf.h"
50#include "isis_route.h"
51#include "isis_csm.h"
52
jardineb5d44e2003-12-23 08:09:43 +000053int isis_run_spf_l1 (struct thread *thread);
54int isis_run_spf_l2 (struct thread *thread);
55
jardineb5d44e2003-12-23 08:09:43 +000056/* 7.2.7 */
hasso92365882005-01-18 13:53:33 +000057static void
jardineb5d44e2003-12-23 08:09:43 +000058remove_excess_adjs (struct list *adjs)
59{
hasso3fdb2dd2005-09-28 18:45:54 +000060 struct listnode *node, *excess = NULL;
jardineb5d44e2003-12-23 08:09:43 +000061 struct isis_adjacency *adj, *candidate = NULL;
62 int comp;
63
hasso3fdb2dd2005-09-28 18:45:54 +000064 for (ALL_LIST_ELEMENTS_RO (adjs, node, adj))
hassof390d2c2004-09-10 20:48:21 +000065 {
66 if (excess == NULL)
67 excess = node;
paul1eb8ef22005-04-07 07:30:20 +000068 candidate = listgetdata (excess);
69
hassof390d2c2004-09-10 20:48:21 +000070 if (candidate->sys_type < adj->sys_type)
71 {
72 excess = node;
73 candidate = adj;
74 continue;
75 }
76 if (candidate->sys_type > adj->sys_type)
77 continue;
78
79 comp = memcmp (candidate->sysid, adj->sysid, ISIS_SYS_ID_LEN);
80 if (comp > 0)
81 {
82 excess = node;
83 candidate = adj;
84 continue;
85 }
86 if (comp < 0)
87 continue;
88
89 if (candidate->circuit->circuit_id > adj->circuit->circuit_id)
90 {
91 excess = node;
92 candidate = adj;
93 continue;
94 }
95
96 if (candidate->circuit->circuit_id < adj->circuit->circuit_id)
97 continue;
98
99 comp = memcmp (candidate->snpa, adj->snpa, ETH_ALEN);
100 if (comp > 0)
101 {
102 excess = node;
103 candidate = adj;
104 continue;
105 }
jardineb5d44e2003-12-23 08:09:43 +0000106 }
107
jardineb5d44e2003-12-23 08:09:43 +0000108 list_delete_node (adjs, excess);
109
110 return;
111}
112
hasso92365882005-01-18 13:53:33 +0000113static const char *
jardineb5d44e2003-12-23 08:09:43 +0000114vtype2string (enum vertextype vtype)
115{
hassof390d2c2004-09-10 20:48:21 +0000116 switch (vtype)
117 {
118 case VTYPE_PSEUDO_IS:
119 return "pseudo_IS";
120 break;
hasso82a84282005-09-26 18:15:36 +0000121 case VTYPE_PSEUDO_TE_IS:
122 return "pseudo_TE-IS";
123 break;
hassof390d2c2004-09-10 20:48:21 +0000124 case VTYPE_NONPSEUDO_IS:
125 return "IS";
126 break;
hasso82a84282005-09-26 18:15:36 +0000127 case VTYPE_NONPSEUDO_TE_IS:
128 return "TE-IS";
129 break;
hassof390d2c2004-09-10 20:48:21 +0000130 case VTYPE_ES:
131 return "ES";
132 break;
133 case VTYPE_IPREACH_INTERNAL:
134 return "IP internal";
135 break;
136 case VTYPE_IPREACH_EXTERNAL:
137 return "IP external";
138 break;
hasso82a84282005-09-26 18:15:36 +0000139 case VTYPE_IPREACH_TE:
140 return "IP TE";
141 break;
jardineb5d44e2003-12-23 08:09:43 +0000142#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000143 case VTYPE_IP6REACH_INTERNAL:
144 return "IP6 internal";
145 break;
146 case VTYPE_IP6REACH_EXTERNAL:
147 return "IP6 external";
148 break;
149#endif /* HAVE_IPV6 */
150 default:
151 return "UNKNOWN";
152 }
153 return NULL; /* Not reached */
jardineb5d44e2003-12-23 08:09:43 +0000154}
155
hasso92365882005-01-18 13:53:33 +0000156static const char *
hassof390d2c2004-09-10 20:48:21 +0000157vid2string (struct isis_vertex *vertex, u_char * buff)
jardineb5d44e2003-12-23 08:09:43 +0000158{
hassof390d2c2004-09-10 20:48:21 +0000159 switch (vertex->type)
160 {
161 case VTYPE_PSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000162 case VTYPE_PSEUDO_TE_IS:
Josh Bailey3f045a02012-03-24 08:35:20 -0700163 return print_sys_hostname (vertex->N.id);
hassof390d2c2004-09-10 20:48:21 +0000164 break;
165 case VTYPE_NONPSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000166 case VTYPE_NONPSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000167 case VTYPE_ES:
Josh Bailey3f045a02012-03-24 08:35:20 -0700168 return print_sys_hostname (vertex->N.id);
hassof390d2c2004-09-10 20:48:21 +0000169 break;
170 case VTYPE_IPREACH_INTERNAL:
171 case VTYPE_IPREACH_EXTERNAL:
hasso82a84282005-09-26 18:15:36 +0000172 case VTYPE_IPREACH_TE:
jardineb5d44e2003-12-23 08:09:43 +0000173#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000174 case VTYPE_IP6REACH_INTERNAL:
175 case VTYPE_IP6REACH_EXTERNAL:
176#endif /* HAVE_IPV6 */
hassof7c43dc2004-09-26 16:24:14 +0000177 prefix2str ((struct prefix *) &vertex->N.prefix, (char *) buff, BUFSIZ);
hassof390d2c2004-09-10 20:48:21 +0000178 break;
179 default:
180 return "UNKNOWN";
181 }
182
hassof7c43dc2004-09-26 16:24:14 +0000183 return (char *) buff;
jardineb5d44e2003-12-23 08:09:43 +0000184}
jardineb5d44e2003-12-23 08:09:43 +0000185
hasso92365882005-01-18 13:53:33 +0000186static struct isis_vertex *
jardineb5d44e2003-12-23 08:09:43 +0000187isis_vertex_new (void *id, enum vertextype vtype)
188{
189 struct isis_vertex *vertex;
190
hasso3fdb2dd2005-09-28 18:45:54 +0000191 vertex = XCALLOC (MTYPE_ISIS_VERTEX, sizeof (struct isis_vertex));
hassof390d2c2004-09-10 20:48:21 +0000192 if (vertex == NULL)
193 {
194 zlog_err ("isis_vertex_new Out of memory!");
195 return NULL;
196 }
197
jardineb5d44e2003-12-23 08:09:43 +0000198 vertex->type = vtype;
hassof390d2c2004-09-10 20:48:21 +0000199 switch (vtype)
200 {
201 case VTYPE_ES:
202 case VTYPE_NONPSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000203 case VTYPE_NONPSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000204 memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN);
205 break;
206 case VTYPE_PSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000207 case VTYPE_PSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000208 memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN + 1);
209 break;
210 case VTYPE_IPREACH_INTERNAL:
211 case VTYPE_IPREACH_EXTERNAL:
hasso82a84282005-09-26 18:15:36 +0000212 case VTYPE_IPREACH_TE:
jardineb5d44e2003-12-23 08:09:43 +0000213#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000214 case VTYPE_IP6REACH_INTERNAL:
215 case VTYPE_IP6REACH_EXTERNAL:
216#endif /* HAVE_IPV6 */
217 memcpy (&vertex->N.prefix, (struct prefix *) id,
218 sizeof (struct prefix));
219 break;
220 default:
221 zlog_err ("WTF!");
222 }
jardineb5d44e2003-12-23 08:09:43 +0000223
224 vertex->Adj_N = list_new ();
Josh Bailey3f045a02012-03-24 08:35:20 -0700225 vertex->parents = list_new ();
226 vertex->children = list_new ();
hassof390d2c2004-09-10 20:48:21 +0000227
jardineb5d44e2003-12-23 08:09:43 +0000228 return vertex;
229}
230
Josh Bailey3f045a02012-03-24 08:35:20 -0700231static void
232isis_vertex_del (struct isis_vertex *vertex)
233{
234 list_delete (vertex->Adj_N);
235 vertex->Adj_N = NULL;
236 list_delete (vertex->parents);
237 vertex->parents = NULL;
238 list_delete (vertex->children);
239 vertex->children = NULL;
240
241 memset(vertex, 0, sizeof(struct isis_vertex));
242 XFREE (MTYPE_ISIS_VERTEX, vertex);
243
244 return;
245}
246
247static void
248isis_vertex_adj_del (struct isis_vertex *vertex, struct isis_adjacency *adj)
249{
250 struct listnode *node, *nextnode;
251 if (!vertex)
252 return;
253 for (node = listhead (vertex->Adj_N); node; node = nextnode)
254 {
255 nextnode = listnextnode(node);
256 if (listgetdata(node) == adj)
257 list_delete_node(vertex->Adj_N, node);
258 }
259 return;
260}
261
262struct isis_spftree *
263isis_spftree_new (struct isis_area *area)
264{
265 struct isis_spftree *tree;
266
267 tree = XCALLOC (MTYPE_ISIS_SPFTREE, sizeof (struct isis_spftree));
268 if (tree == NULL)
269 {
270 zlog_err ("ISIS-Spf: isis_spftree_new Out of memory!");
271 return NULL;
272 }
273
274 tree->tents = list_new ();
275 tree->paths = list_new ();
276 tree->area = area;
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -0700277 tree->last_run_timestamp = 0;
278 tree->last_run_duration = 0;
Josh Bailey3f045a02012-03-24 08:35:20 -0700279 tree->runcount = 0;
280 tree->pending = 0;
281 return tree;
282}
283
284void
285isis_spftree_del (struct isis_spftree *spftree)
286{
287 THREAD_TIMER_OFF (spftree->t_spf);
288
289 spftree->tents->del = (void (*)(void *)) isis_vertex_del;
290 list_delete (spftree->tents);
291 spftree->tents = NULL;
292
293 spftree->paths->del = (void (*)(void *)) isis_vertex_del;
294 list_delete (spftree->paths);
295 spftree->paths = NULL;
296
297 XFREE (MTYPE_ISIS_SPFTREE, spftree);
298
299 return;
300}
301
302void
303isis_spftree_adj_del (struct isis_spftree *spftree, struct isis_adjacency *adj)
304{
305 struct listnode *node;
306 if (!adj)
307 return;
308 for (node = listhead (spftree->tents); node; node = listnextnode (node))
309 isis_vertex_adj_del (listgetdata (node), adj);
310 for (node = listhead (spftree->paths); node; node = listnextnode (node))
311 isis_vertex_adj_del (listgetdata (node), adj);
312 return;
313}
314
315void
316spftree_area_init (struct isis_area *area)
317{
318 if (area->is_type & IS_LEVEL_1)
319 {
320 if (area->spftree[0] == NULL)
321 area->spftree[0] = isis_spftree_new (area);
322#ifdef HAVE_IPV6
323 if (area->spftree6[0] == NULL)
324 area->spftree6[0] = isis_spftree_new (area);
325#endif
326 }
327
328 if (area->is_type & IS_LEVEL_2)
329 {
330 if (area->spftree[1] == NULL)
331 area->spftree[1] = isis_spftree_new (area);
332#ifdef HAVE_IPV6
333 if (area->spftree6[1] == NULL)
334 area->spftree6[1] = isis_spftree_new (area);
335#endif
336 }
337
338 return;
339}
340
341void
342spftree_area_del (struct isis_area *area)
343{
344 if (area->is_type & IS_LEVEL_1)
345 {
346 if (area->spftree[0] != NULL)
347 {
348 isis_spftree_del (area->spftree[0]);
349 area->spftree[0] = NULL;
350 }
351#ifdef HAVE_IPV6
352 if (area->spftree6[0])
353 {
354 isis_spftree_del (area->spftree6[0]);
355 area->spftree6[0] = NULL;
356 }
357#endif
358 }
359
360 if (area->is_type & IS_LEVEL_2)
361 {
362 if (area->spftree[1] != NULL)
363 {
364 isis_spftree_del (area->spftree[1]);
365 area->spftree[1] = NULL;
366 }
367#ifdef HAVE_IPV6
David Lamparterde543de2012-11-27 01:10:27 +0000368 if (area->spftree6[1] != NULL)
Josh Bailey3f045a02012-03-24 08:35:20 -0700369 {
370 isis_spftree_del (area->spftree6[1]);
371 area->spftree6[1] = NULL;
372 }
373#endif
374 }
375
376 return;
377}
378
379void
380spftree_area_adj_del (struct isis_area *area, struct isis_adjacency *adj)
381{
382 if (area->is_type & IS_LEVEL_1)
383 {
384 if (area->spftree[0] != NULL)
385 isis_spftree_adj_del (area->spftree[0], adj);
386#ifdef HAVE_IPV6
387 if (area->spftree6[0] != NULL)
388 isis_spftree_adj_del (area->spftree6[0], adj);
389#endif
390 }
391
392 if (area->is_type & IS_LEVEL_2)
393 {
394 if (area->spftree[1] != NULL)
395 isis_spftree_adj_del (area->spftree[1], adj);
396#ifdef HAVE_IPV6
397 if (area->spftree6[1] != NULL)
398 isis_spftree_adj_del (area->spftree6[1], adj);
399#endif
400 }
401
402 return;
403}
404
405/*
406 * Find the system LSP: returns the LSP in our LSP database
407 * associated with the given system ID.
408 */
409static struct isis_lsp *
410isis_root_system_lsp (struct isis_area *area, int level, u_char *sysid)
411{
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -0700412 struct isis_lsp *lsp;
Josh Bailey3f045a02012-03-24 08:35:20 -0700413 u_char lspid[ISIS_SYS_ID_LEN + 2];
414
415 memcpy (lspid, sysid, ISIS_SYS_ID_LEN);
416 LSP_PSEUDO_ID (lspid) = 0;
417 LSP_FRAGMENT (lspid) = 0;
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -0700418 lsp = lsp_search (lspid, area->lspdb[level - 1]);
419 if (lsp && lsp->lsp_header->rem_lifetime != 0)
420 return lsp;
421 return NULL;
Josh Bailey3f045a02012-03-24 08:35:20 -0700422}
423
jardineb5d44e2003-12-23 08:09:43 +0000424/*
425 * Add this IS to the root of SPT
426 */
Josh Bailey3f045a02012-03-24 08:35:20 -0700427static struct isis_vertex *
428isis_spf_add_root (struct isis_spftree *spftree, int level, u_char *sysid)
jardineb5d44e2003-12-23 08:09:43 +0000429{
430 struct isis_vertex *vertex;
431 struct isis_lsp *lsp;
jardineb5d44e2003-12-23 08:09:43 +0000432#ifdef EXTREME_DEBUG
433 u_char buff[BUFSIZ];
434#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000435
Josh Bailey3f045a02012-03-24 08:35:20 -0700436 lsp = isis_root_system_lsp (spftree->area, level, sysid);
jardineb5d44e2003-12-23 08:09:43 +0000437 if (lsp == NULL)
438 zlog_warn ("ISIS-Spf: could not find own l%d LSP!", level);
hassof390d2c2004-09-10 20:48:21 +0000439
Josh Bailey3f045a02012-03-24 08:35:20 -0700440 if (!spftree->area->oldmetric)
441 vertex = isis_vertex_new (sysid, VTYPE_NONPSEUDO_TE_IS);
hasso82a84282005-09-26 18:15:36 +0000442 else
Josh Bailey3f045a02012-03-24 08:35:20 -0700443 vertex = isis_vertex_new (sysid, VTYPE_NONPSEUDO_IS);
jardineb5d44e2003-12-23 08:09:43 +0000444
445 listnode_add (spftree->paths, vertex);
446
447#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000448 zlog_debug ("ISIS-Spf: added this IS %s %s depth %d dist %d to PATHS",
449 vtype2string (vertex->type), vid2string (vertex, buff),
450 vertex->depth, vertex->d_N);
jardineb5d44e2003-12-23 08:09:43 +0000451#endif /* EXTREME_DEBUG */
452
Josh Bailey3f045a02012-03-24 08:35:20 -0700453 return vertex;
jardineb5d44e2003-12-23 08:09:43 +0000454}
455
hasso92365882005-01-18 13:53:33 +0000456static struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000457isis_find_vertex (struct list *list, void *id, enum vertextype vtype)
jardineb5d44e2003-12-23 08:09:43 +0000458{
459 struct listnode *node;
460 struct isis_vertex *vertex;
461 struct prefix *p1, *p2;
462
paul1eb8ef22005-04-07 07:30:20 +0000463 for (ALL_LIST_ELEMENTS_RO (list, node, vertex))
hassof390d2c2004-09-10 20:48:21 +0000464 {
hassof390d2c2004-09-10 20:48:21 +0000465 if (vertex->type != vtype)
466 continue;
467 switch (vtype)
468 {
469 case VTYPE_ES:
470 case VTYPE_NONPSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000471 case VTYPE_NONPSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000472 if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN) == 0)
473 return vertex;
474 break;
475 case VTYPE_PSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000476 case VTYPE_PSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000477 if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN + 1) == 0)
478 return vertex;
479 break;
480 case VTYPE_IPREACH_INTERNAL:
481 case VTYPE_IPREACH_EXTERNAL:
hasso82a84282005-09-26 18:15:36 +0000482 case VTYPE_IPREACH_TE:
jardineb5d44e2003-12-23 08:09:43 +0000483#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000484 case VTYPE_IP6REACH_INTERNAL:
485 case VTYPE_IP6REACH_EXTERNAL:
jardineb5d44e2003-12-23 08:09:43 +0000486#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000487 p1 = (struct prefix *) id;
488 p2 = (struct prefix *) &vertex->N.id;
489 if (p1->family == p2->family && p1->prefixlen == p2->prefixlen &&
490 memcmp (&p1->u.prefix, &p2->u.prefix,
491 PSIZE (p1->prefixlen)) == 0)
492 return vertex;
493 break;
494 }
jardineb5d44e2003-12-23 08:09:43 +0000495 }
jardineb5d44e2003-12-23 08:09:43 +0000496
497 return NULL;
498}
499
jardineb5d44e2003-12-23 08:09:43 +0000500/*
501 * Add a vertex to TENT sorted by cost and by vertextype on tie break situation
502 */
hasso92365882005-01-18 13:53:33 +0000503static struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000504isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype,
Josh Bailey3f045a02012-03-24 08:35:20 -0700505 void *id, uint32_t cost, int depth, int family,
506 struct isis_adjacency *adj, struct isis_vertex *parent)
jardineb5d44e2003-12-23 08:09:43 +0000507{
508 struct isis_vertex *vertex, *v;
509 struct listnode *node;
Josh Bailey3f045a02012-03-24 08:35:20 -0700510 struct isis_adjacency *parent_adj;
hassof390d2c2004-09-10 20:48:21 +0000511#ifdef EXTREME_DEBUG
jardineb5d44e2003-12-23 08:09:43 +0000512 u_char buff[BUFSIZ];
513#endif
514
Josh Bailey3f045a02012-03-24 08:35:20 -0700515 assert (isis_find_vertex (spftree->paths, id, vtype) == NULL);
516 assert (isis_find_vertex (spftree->tents, id, vtype) == NULL);
jardineb5d44e2003-12-23 08:09:43 +0000517 vertex = isis_vertex_new (id, vtype);
518 vertex->d_N = cost;
519 vertex->depth = depth;
hassof390d2c2004-09-10 20:48:21 +0000520
Josh Bailey3f045a02012-03-24 08:35:20 -0700521 if (parent) {
522 listnode_add (vertex->parents, parent);
523 if (listnode_lookup (parent->children, vertex) == NULL)
524 listnode_add (parent->children, vertex);
525 }
526
527 if (parent && parent->Adj_N && listcount(parent->Adj_N) > 0) {
528 for (ALL_LIST_ELEMENTS_RO (parent->Adj_N, node, parent_adj))
529 listnode_add (vertex->Adj_N, parent_adj);
530 } else if (adj) {
jardineb5d44e2003-12-23 08:09:43 +0000531 listnode_add (vertex->Adj_N, adj);
Josh Bailey3f045a02012-03-24 08:35:20 -0700532 }
533
hassof390d2c2004-09-10 20:48:21 +0000534#ifdef EXTREME_DEBUG
Josh Bailey3f045a02012-03-24 08:35:20 -0700535 zlog_debug ("ISIS-Spf: add to TENT %s %s %s depth %d dist %d adjcount %d",
536 print_sys_hostname (vertex->N.id),
hasso529d65b2004-12-24 00:14:50 +0000537 vtype2string (vertex->type), vid2string (vertex, buff),
Josh Bailey3f045a02012-03-24 08:35:20 -0700538 vertex->depth, vertex->d_N, listcount(vertex->Adj_N));
jardineb5d44e2003-12-23 08:09:43 +0000539#endif /* EXTREME_DEBUG */
Josh Bailey3f045a02012-03-24 08:35:20 -0700540
hassof390d2c2004-09-10 20:48:21 +0000541 if (list_isempty (spftree->tents))
542 {
543 listnode_add (spftree->tents, vertex);
544 return vertex;
jardineb5d44e2003-12-23 08:09:43 +0000545 }
Josh Bailey3f045a02012-03-24 08:35:20 -0700546
547 /* XXX: This cant use the standard ALL_LIST_ELEMENTS macro */
paul1eb8ef22005-04-07 07:30:20 +0000548 for (node = listhead (spftree->tents); node; node = listnextnode (node))
hassof390d2c2004-09-10 20:48:21 +0000549 {
paul1eb8ef22005-04-07 07:30:20 +0000550 v = listgetdata (node);
hassof390d2c2004-09-10 20:48:21 +0000551 if (v->d_N > vertex->d_N)
552 {
553 list_add_node_prev (spftree->tents, node, vertex);
554 break;
555 }
Josh Bailey3f045a02012-03-24 08:35:20 -0700556 else if (v->d_N == vertex->d_N && v->type > vertex->type)
hassof390d2c2004-09-10 20:48:21 +0000557 {
558 /* Tie break, add according to type */
Josh Bailey3f045a02012-03-24 08:35:20 -0700559 list_add_node_prev (spftree->tents, node, vertex);
hassof390d2c2004-09-10 20:48:21 +0000560 break;
561 }
562 }
Josh Bailey3f045a02012-03-24 08:35:20 -0700563
564 if (node == NULL)
565 listnode_add (spftree->tents, vertex);
566
jardineb5d44e2003-12-23 08:09:43 +0000567 return vertex;
568}
569
Josh Bailey3f045a02012-03-24 08:35:20 -0700570static void
hassof390d2c2004-09-10 20:48:21 +0000571isis_spf_add_local (struct isis_spftree *spftree, enum vertextype vtype,
Josh Bailey3f045a02012-03-24 08:35:20 -0700572 void *id, struct isis_adjacency *adj, uint32_t cost,
573 int family, struct isis_vertex *parent)
jardineb5d44e2003-12-23 08:09:43 +0000574{
575 struct isis_vertex *vertex;
jardineb5d44e2003-12-23 08:09:43 +0000576
hassof390d2c2004-09-10 20:48:21 +0000577 vertex = isis_find_vertex (spftree->tents, id, vtype);
578
579 if (vertex)
580 {
581 /* C.2.5 c) */
582 if (vertex->d_N == cost)
583 {
584 if (adj)
585 listnode_add (vertex->Adj_N, adj);
586 /* d) */
587 if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
588 remove_excess_adjs (vertex->Adj_N);
Josh Bailey3f045a02012-03-24 08:35:20 -0700589 if (parent && (listnode_lookup (vertex->parents, parent) == NULL))
590 listnode_add (vertex->parents, parent);
591 if (parent && (listnode_lookup (parent->children, vertex) == NULL))
592 listnode_add (parent->children, vertex);
593 return;
hassof390d2c2004-09-10 20:48:21 +0000594 }
Josh Bailey3f045a02012-03-24 08:35:20 -0700595 else if (vertex->d_N < cost)
hassof390d2c2004-09-10 20:48:21 +0000596 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700597 /* e) do nothing */
598 return;
hassof390d2c2004-09-10 20:48:21 +0000599 }
Josh Bailey3f045a02012-03-24 08:35:20 -0700600 else { /* vertex->d_N > cost */
601 /* f) */
602 struct listnode *pnode, *pnextnode;
603 struct isis_vertex *pvertex;
604 listnode_delete (spftree->tents, vertex);
605 assert (listcount (vertex->children) == 0);
606 for (ALL_LIST_ELEMENTS (vertex->parents, pnode, pnextnode, pvertex))
607 listnode_delete(pvertex->children, vertex);
608 isis_vertex_del (vertex);
609 }
hassof390d2c2004-09-10 20:48:21 +0000610 }
611
Josh Bailey3f045a02012-03-24 08:35:20 -0700612 isis_spf_add2tent (spftree, vtype, id, cost, 1, family, adj, parent);
613 return;
jardineb5d44e2003-12-23 08:09:43 +0000614}
615
hasso92365882005-01-18 13:53:33 +0000616static void
hassof390d2c2004-09-10 20:48:21 +0000617process_N (struct isis_spftree *spftree, enum vertextype vtype, void *id,
Josh Bailey3f045a02012-03-24 08:35:20 -0700618 uint32_t dist, uint16_t depth, int family,
619 struct isis_vertex *parent)
jardineb5d44e2003-12-23 08:09:43 +0000620{
621 struct isis_vertex *vertex;
622#ifdef EXTREME_DEBUG
623 u_char buff[255];
624#endif
625
Josh Bailey3f045a02012-03-24 08:35:20 -0700626 assert (spftree && parent);
627
628 /* RFC3787 section 5.1 */
629 if (spftree->area->newmetric == 1)
630 {
631 if (dist > MAX_WIDE_PATH_METRIC)
632 return;
633 }
jardineb5d44e2003-12-23 08:09:43 +0000634 /* C.2.6 b) */
Josh Bailey3f045a02012-03-24 08:35:20 -0700635 else if (spftree->area->oldmetric == 1)
636 {
637 if (dist > MAX_NARROW_PATH_METRIC)
638 return;
639 }
640
jardineb5d44e2003-12-23 08:09:43 +0000641 /* c) */
642 vertex = isis_find_vertex (spftree->paths, id, vtype);
hassof390d2c2004-09-10 20:48:21 +0000643 if (vertex)
644 {
jardineb5d44e2003-12-23 08:09:43 +0000645#ifdef EXTREME_DEBUG
Josh Bailey3f045a02012-03-24 08:35:20 -0700646 zlog_debug ("ISIS-Spf: process_N %s %s %s dist %d already found from PATH",
647 print_sys_hostname (vertex->N.id),
hasso529d65b2004-12-24 00:14:50 +0000648 vtype2string (vtype), vid2string (vertex, buff), dist);
jardineb5d44e2003-12-23 08:09:43 +0000649#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000650 assert (dist >= vertex->d_N);
651 return;
652 }
jardineb5d44e2003-12-23 08:09:43 +0000653
654 vertex = isis_find_vertex (spftree->tents, id, vtype);
hassof390d2c2004-09-10 20:48:21 +0000655 /* d) */
656 if (vertex)
657 {
658 /* 1) */
jardineb5d44e2003-12-23 08:09:43 +0000659#ifdef EXTREME_DEBUG
Josh Bailey3f045a02012-03-24 08:35:20 -0700660 zlog_debug ("ISIS-Spf: process_N %s %s %s dist %d parent %s adjcount %d",
661 print_sys_hostname (vertex->N.id),
662 vtype2string (vtype), vid2string (vertex, buff), dist,
663 (parent ? print_sys_hostname (parent->N.id) : "null"),
664 (parent ? listcount (parent->Adj_N) : 0));
jardineb5d44e2003-12-23 08:09:43 +0000665#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000666 if (vertex->d_N == dist)
667 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700668 struct listnode *node;
669 struct isis_adjacency *parent_adj;
670 for (ALL_LIST_ELEMENTS_RO (parent->Adj_N, node, parent_adj))
671 if (listnode_lookup(vertex->Adj_N, parent_adj) == NULL)
672 listnode_add (vertex->Adj_N, parent_adj);
hassof390d2c2004-09-10 20:48:21 +0000673 /* 2) */
674 if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
675 remove_excess_adjs (vertex->Adj_N);
Josh Bailey3f045a02012-03-24 08:35:20 -0700676 if (listnode_lookup (vertex->parents, parent) == NULL)
677 listnode_add (vertex->parents, parent);
678 if (listnode_lookup (parent->children, vertex) == NULL)
679 listnode_add (parent->children, vertex);
hassof390d2c2004-09-10 20:48:21 +0000680 /* 3) */
681 return;
682 }
683 else if (vertex->d_N < dist)
684 {
685 return;
686 /* 4) */
687 }
688 else
689 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700690 struct listnode *pnode, *pnextnode;
691 struct isis_vertex *pvertex;
hassof390d2c2004-09-10 20:48:21 +0000692 listnode_delete (spftree->tents, vertex);
Josh Bailey3f045a02012-03-24 08:35:20 -0700693 assert (listcount (vertex->children) == 0);
694 for (ALL_LIST_ELEMENTS (vertex->parents, pnode, pnextnode, pvertex))
695 listnode_delete(pvertex->children, vertex);
696 isis_vertex_del (vertex);
hassof390d2c2004-09-10 20:48:21 +0000697 }
jardineb5d44e2003-12-23 08:09:43 +0000698 }
hassof390d2c2004-09-10 20:48:21 +0000699
Josh Bailey3f045a02012-03-24 08:35:20 -0700700#ifdef EXTREME_DEBUG
701 zlog_debug ("ISIS-Spf: process_N add2tent %s %s dist %d parent %s",
702 print_sys_hostname(id), vtype2string (vtype), dist,
703 (parent ? print_sys_hostname (parent->N.id) : "null"));
704#endif /* EXTREME_DEBUG */
705
706 isis_spf_add2tent (spftree, vtype, id, dist, depth, family, NULL, parent);
jardineb5d44e2003-12-23 08:09:43 +0000707 return;
708}
709
710/*
711 * C.2.6 Step 1
712 */
hasso92365882005-01-18 13:53:33 +0000713static int
hassof390d2c2004-09-10 20:48:21 +0000714isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp,
Josh Bailey3f045a02012-03-24 08:35:20 -0700715 uint32_t cost, uint16_t depth, int family,
716 u_char *root_sysid, struct isis_vertex *parent)
jardineb5d44e2003-12-23 08:09:43 +0000717{
718 struct listnode *node, *fragnode = NULL;
Josh Bailey3f045a02012-03-24 08:35:20 -0700719 uint32_t dist;
jardineb5d44e2003-12-23 08:09:43 +0000720 struct is_neigh *is_neigh;
hasso82a84282005-09-26 18:15:36 +0000721 struct te_is_neigh *te_is_neigh;
jardineb5d44e2003-12-23 08:09:43 +0000722 struct ipv4_reachability *ipreach;
hasso82a84282005-09-26 18:15:36 +0000723 struct te_ipv4_reachability *te_ipv4_reach;
jardineb5d44e2003-12-23 08:09:43 +0000724 enum vertextype vtype;
725 struct prefix prefix;
726#ifdef HAVE_IPV6
727 struct ipv6_reachability *ip6reach;
728#endif /* HAVE_IPV6 */
Josh Bailey3f045a02012-03-24 08:35:20 -0700729 static const u_char null_sysid[ISIS_SYS_ID_LEN];
hassof390d2c2004-09-10 20:48:21 +0000730
Josh Bailey3f045a02012-03-24 08:35:20 -0700731 if (!speaks (lsp->tlv_data.nlpids, family))
jardineb5d44e2003-12-23 08:09:43 +0000732 return ISIS_OK;
733
hassof390d2c2004-09-10 20:48:21 +0000734lspfragloop:
735 if (lsp->lsp_header->seq_num == 0)
736 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700737 zlog_warn ("isis_spf_process_lsp(): lsp with 0 seq_num - ignore");
hassof390d2c2004-09-10 20:48:21 +0000738 return ISIS_WARNING;
739 }
jardineb5d44e2003-12-23 08:09:43 +0000740
Josh Bailey3f045a02012-03-24 08:35:20 -0700741#ifdef EXTREME_DEBUG
742 zlog_debug ("ISIS-Spf: process_lsp %s", print_sys_hostname(lsp->lsp_header->lsp_id));
743#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000744
Josh Bailey3f045a02012-03-24 08:35:20 -0700745 if (!ISIS_MASK_LSP_OL_BIT (lsp->lsp_header->lsp_bits))
746 {
747 if (lsp->tlv_data.is_neighs)
748 {
749 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh))
750 {
751 /* C.2.6 a) */
752 /* Two way connectivity */
753 if (!memcmp (is_neigh->neigh_id, root_sysid, ISIS_SYS_ID_LEN))
754 continue;
755 if (!memcmp (is_neigh->neigh_id, null_sysid, ISIS_SYS_ID_LEN))
756 continue;
757 dist = cost + is_neigh->metrics.metric_default;
758 vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
759 : VTYPE_NONPSEUDO_IS;
760 process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist,
761 depth + 1, family, parent);
762 }
hassof390d2c2004-09-10 20:48:21 +0000763 }
Josh Bailey3f045a02012-03-24 08:35:20 -0700764 if (lsp->tlv_data.te_is_neighs)
765 {
766 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node,
767 te_is_neigh))
768 {
769 if (!memcmp (te_is_neigh->neigh_id, root_sysid, ISIS_SYS_ID_LEN))
770 continue;
771 if (!memcmp (te_is_neigh->neigh_id, null_sysid, ISIS_SYS_ID_LEN))
772 continue;
773 dist = cost + GET_TE_METRIC(te_is_neigh);
774 vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS
775 : VTYPE_NONPSEUDO_TE_IS;
776 process_N (spftree, vtype, (void *) te_is_neigh->neigh_id, dist,
777 depth + 1, family, parent);
778 }
779 }
780 }
781
782 if (family == AF_INET && lsp->tlv_data.ipv4_int_reachs)
783 {
784 prefix.family = AF_INET;
785 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_int_reachs, node, ipreach))
786 {
787 dist = cost + ipreach->metrics.metric_default;
788 vtype = VTYPE_IPREACH_INTERNAL;
789 prefix.u.prefix4 = ipreach->prefix;
790 prefix.prefixlen = ip_masklen (ipreach->mask);
791 apply_mask (&prefix);
792 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
793 family, parent);
794 }
795 }
796 if (family == AF_INET && lsp->tlv_data.ipv4_ext_reachs)
797 {
798 prefix.family = AF_INET;
799 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_ext_reachs, node, ipreach))
800 {
801 dist = cost + ipreach->metrics.metric_default;
802 vtype = VTYPE_IPREACH_EXTERNAL;
803 prefix.u.prefix4 = ipreach->prefix;
804 prefix.prefixlen = ip_masklen (ipreach->mask);
805 apply_mask (&prefix);
806 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
807 family, parent);
808 }
809 }
810 if (family == AF_INET && lsp->tlv_data.te_ipv4_reachs)
811 {
812 prefix.family = AF_INET;
813 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_ipv4_reachs,
814 node, te_ipv4_reach))
815 {
David Lamparter948b6be2012-05-08 06:27:04 +0200816 assert ((te_ipv4_reach->control & 0x3F) <= IPV4_MAX_BITLEN);
817
Josh Bailey3f045a02012-03-24 08:35:20 -0700818 dist = cost + ntohl (te_ipv4_reach->te_metric);
819 vtype = VTYPE_IPREACH_TE;
820 prefix.u.prefix4 = newprefix2inaddr (&te_ipv4_reach->prefix_start,
821 te_ipv4_reach->control);
822 prefix.prefixlen = (te_ipv4_reach->control & 0x3F);
823 apply_mask (&prefix);
824 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
825 family, parent);
826 }
827 }
828#ifdef HAVE_IPV6
829 if (family == AF_INET6 && lsp->tlv_data.ipv6_reachs)
830 {
831 prefix.family = AF_INET6;
832 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv6_reachs, node, ip6reach))
833 {
David Lamparter948b6be2012-05-08 06:27:04 +0200834 assert (ip6reach->prefix_len <= IPV6_MAX_BITLEN);
835
Nick Hilliarde1a555b2012-11-28 14:39:56 +0000836 dist = cost + ntohl(ip6reach->metric);
Josh Bailey3f045a02012-03-24 08:35:20 -0700837 vtype = (ip6reach->control_info & CTRL_INFO_DISTRIBUTION) ?
838 VTYPE_IP6REACH_EXTERNAL : VTYPE_IP6REACH_INTERNAL;
839 prefix.prefixlen = ip6reach->prefix_len;
840 memcpy (&prefix.u.prefix6.s6_addr, ip6reach->prefix,
841 PSIZE (ip6reach->prefix_len));
842 apply_mask (&prefix);
843 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
844 family, parent);
845 }
846 }
847#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000848
jardineb5d44e2003-12-23 08:09:43 +0000849 if (fragnode == NULL)
850 fragnode = listhead (lsp->lspu.frags);
hassof390d2c2004-09-10 20:48:21 +0000851 else
paul1eb8ef22005-04-07 07:30:20 +0000852 fragnode = listnextnode (fragnode);
jardineb5d44e2003-12-23 08:09:43 +0000853
hassof390d2c2004-09-10 20:48:21 +0000854 if (fragnode)
855 {
paul1eb8ef22005-04-07 07:30:20 +0000856 lsp = listgetdata (fragnode);
hassof390d2c2004-09-10 20:48:21 +0000857 goto lspfragloop;
858 }
859
jardineb5d44e2003-12-23 08:09:43 +0000860 return ISIS_OK;
861}
862
hasso92365882005-01-18 13:53:33 +0000863static int
hassof390d2c2004-09-10 20:48:21 +0000864isis_spf_process_pseudo_lsp (struct isis_spftree *spftree,
Josh Bailey3f045a02012-03-24 08:35:20 -0700865 struct isis_lsp *lsp, uint32_t cost,
866 uint16_t depth, int family,
867 u_char *root_sysid,
868 struct isis_vertex *parent)
jardineb5d44e2003-12-23 08:09:43 +0000869{
hasso3fdb2dd2005-09-28 18:45:54 +0000870 struct listnode *node, *fragnode = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000871 struct is_neigh *is_neigh;
hasso82a84282005-09-26 18:15:36 +0000872 struct te_is_neigh *te_is_neigh;
jardineb5d44e2003-12-23 08:09:43 +0000873 enum vertextype vtype;
Josh Bailey3f045a02012-03-24 08:35:20 -0700874 uint32_t dist;
hassof390d2c2004-09-10 20:48:21 +0000875
876pseudofragloop:
877
878 if (lsp->lsp_header->seq_num == 0)
879 {
880 zlog_warn ("isis_spf_process_pseudo_lsp(): lsp with 0 seq_num"
881 " - do not process");
882 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +0000883 }
hassof390d2c2004-09-10 20:48:21 +0000884
Josh Bailey3f045a02012-03-24 08:35:20 -0700885#ifdef EXTREME_DEBUG
886 zlog_debug ("ISIS-Spf: process_pseudo_lsp %s",
887 print_sys_hostname(lsp->lsp_header->lsp_id));
888#endif /* EXTREME_DEBUG */
889
890 /* RFC3787 section 4 SHOULD ignore overload bit in pseudo LSPs */
891
hasso82a84282005-09-26 18:15:36 +0000892 if (lsp->tlv_data.is_neighs)
hasso3fdb2dd2005-09-28 18:45:54 +0000893 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh))
hasso82a84282005-09-26 18:15:36 +0000894 {
hasso82a84282005-09-26 18:15:36 +0000895 /* Two way connectivity */
Josh Bailey3f045a02012-03-24 08:35:20 -0700896 if (!memcmp (is_neigh->neigh_id, root_sysid, ISIS_SYS_ID_LEN))
hasso82a84282005-09-26 18:15:36 +0000897 continue;
Josh Bailey3f045a02012-03-24 08:35:20 -0700898 dist = cost + is_neigh->metrics.metric_default;
899 vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
900 : VTYPE_NONPSEUDO_IS;
901 process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist,
902 depth + 1, family, parent);
hasso82a84282005-09-26 18:15:36 +0000903 }
904 if (lsp->tlv_data.te_is_neighs)
hasso3fdb2dd2005-09-28 18:45:54 +0000905 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node, te_is_neigh))
hasso82a84282005-09-26 18:15:36 +0000906 {
hasso82a84282005-09-26 18:15:36 +0000907 /* Two way connectivity */
Josh Bailey3f045a02012-03-24 08:35:20 -0700908 if (!memcmp (te_is_neigh->neigh_id, root_sysid, ISIS_SYS_ID_LEN))
hasso82a84282005-09-26 18:15:36 +0000909 continue;
Josh Bailey3f045a02012-03-24 08:35:20 -0700910 dist = cost + GET_TE_METRIC(te_is_neigh);
911 vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS
912 : VTYPE_NONPSEUDO_TE_IS;
913 process_N (spftree, vtype, (void *) te_is_neigh->neigh_id, dist,
914 depth + 1, family, parent);
hasso82a84282005-09-26 18:15:36 +0000915 }
hassof390d2c2004-09-10 20:48:21 +0000916
jardineb5d44e2003-12-23 08:09:43 +0000917 if (fragnode == NULL)
918 fragnode = listhead (lsp->lspu.frags);
hassof390d2c2004-09-10 20:48:21 +0000919 else
paul1eb8ef22005-04-07 07:30:20 +0000920 fragnode = listnextnode (fragnode);
jardineb5d44e2003-12-23 08:09:43 +0000921
hassof390d2c2004-09-10 20:48:21 +0000922 if (fragnode)
923 {
paul1eb8ef22005-04-07 07:30:20 +0000924 lsp = listgetdata (fragnode);
hassof390d2c2004-09-10 20:48:21 +0000925 goto pseudofragloop;
926 }
jardineb5d44e2003-12-23 08:09:43 +0000927
jardineb5d44e2003-12-23 08:09:43 +0000928 return ISIS_OK;
929}
hassof390d2c2004-09-10 20:48:21 +0000930
hasso92365882005-01-18 13:53:33 +0000931static int
Josh Bailey3f045a02012-03-24 08:35:20 -0700932isis_spf_preload_tent (struct isis_spftree *spftree, int level,
933 int family, u_char *root_sysid,
934 struct isis_vertex *parent)
jardineb5d44e2003-12-23 08:09:43 +0000935{
jardineb5d44e2003-12-23 08:09:43 +0000936 struct isis_circuit *circuit;
hasso3fdb2dd2005-09-28 18:45:54 +0000937 struct listnode *cnode, *anode, *ipnode;
jardineb5d44e2003-12-23 08:09:43 +0000938 struct isis_adjacency *adj;
939 struct isis_lsp *lsp;
940 struct list *adj_list;
941 struct list *adjdb;
942 struct prefix_ipv4 *ipv4;
943 struct prefix prefix;
944 int retval = ISIS_OK;
945 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
Josh Bailey3f045a02012-03-24 08:35:20 -0700946 static u_char null_lsp_id[ISIS_SYS_ID_LEN + 2];
jardineb5d44e2003-12-23 08:09:43 +0000947#ifdef HAVE_IPV6
948 struct prefix_ipv6 *ipv6;
949#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000950
Josh Bailey3f045a02012-03-24 08:35:20 -0700951 for (ALL_LIST_ELEMENTS_RO (spftree->area->circuit_list, cnode, circuit))
hassof390d2c2004-09-10 20:48:21 +0000952 {
hassof390d2c2004-09-10 20:48:21 +0000953 if (circuit->state != C_STATE_UP)
jardineb5d44e2003-12-23 08:09:43 +0000954 continue;
Josh Bailey3f045a02012-03-24 08:35:20 -0700955 if (!(circuit->is_type & level))
hassof390d2c2004-09-10 20:48:21 +0000956 continue;
957 if (family == AF_INET && !circuit->ip_router)
958 continue;
959#ifdef HAVE_IPV6
960 if (family == AF_INET6 && !circuit->ipv6_router)
961 continue;
962#endif /* HAVE_IPV6 */
963 /*
964 * Add IP(v6) addresses of this circuit
jardineb5d44e2003-12-23 08:09:43 +0000965 */
hassof390d2c2004-09-10 20:48:21 +0000966 if (family == AF_INET)
967 {
968 prefix.family = AF_INET;
hasso3fdb2dd2005-09-28 18:45:54 +0000969 for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, ipnode, ipv4))
hassof390d2c2004-09-10 20:48:21 +0000970 {
hassof390d2c2004-09-10 20:48:21 +0000971 prefix.u.prefix4 = ipv4->prefix;
972 prefix.prefixlen = ipv4->prefixlen;
Josh Bailey3f045a02012-03-24 08:35:20 -0700973 apply_mask (&prefix);
hassof390d2c2004-09-10 20:48:21 +0000974 isis_spf_add_local (spftree, VTYPE_IPREACH_INTERNAL, &prefix,
Josh Bailey3f045a02012-03-24 08:35:20 -0700975 NULL, 0, family, parent);
hassof390d2c2004-09-10 20:48:21 +0000976 }
977 }
978#ifdef HAVE_IPV6
979 if (family == AF_INET6)
980 {
981 prefix.family = AF_INET6;
hasso3fdb2dd2005-09-28 18:45:54 +0000982 for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, ipnode, ipv6))
hassof390d2c2004-09-10 20:48:21 +0000983 {
hassof390d2c2004-09-10 20:48:21 +0000984 prefix.prefixlen = ipv6->prefixlen;
985 prefix.u.prefix6 = ipv6->prefix;
Josh Bailey3f045a02012-03-24 08:35:20 -0700986 apply_mask (&prefix);
hassof390d2c2004-09-10 20:48:21 +0000987 isis_spf_add_local (spftree, VTYPE_IP6REACH_INTERNAL,
Josh Bailey3f045a02012-03-24 08:35:20 -0700988 &prefix, NULL, 0, family, parent);
hassof390d2c2004-09-10 20:48:21 +0000989 }
990 }
991#endif /* HAVE_IPV6 */
992 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
993 {
994 /*
995 * Add the adjacencies
996 */
997 adj_list = list_new ();
998 adjdb = circuit->u.bc.adjdb[level - 1];
999 isis_adj_build_up_list (adjdb, adj_list);
1000 if (listcount (adj_list) == 0)
1001 {
1002 list_delete (adj_list);
hassoc89c05d2005-09-04 21:36:36 +00001003 if (isis->debugs & DEBUG_SPF_EVENTS)
1004 zlog_debug ("ISIS-Spf: no L%d adjacencies on circuit %s",
1005 level, circuit->interface->name);
hassof390d2c2004-09-10 20:48:21 +00001006 continue;
1007 }
Josh Bailey3f045a02012-03-24 08:35:20 -07001008 for (ALL_LIST_ELEMENTS_RO (adj_list, anode, adj))
hassof390d2c2004-09-10 20:48:21 +00001009 {
hassof390d2c2004-09-10 20:48:21 +00001010 if (!speaks (&adj->nlpids, family))
hassof390d2c2004-09-10 20:48:21 +00001011 continue;
hassof390d2c2004-09-10 20:48:21 +00001012 switch (adj->sys_type)
1013 {
1014 case ISIS_SYSTYPE_ES:
1015 isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
Josh Bailey3f045a02012-03-24 08:35:20 -07001016 circuit->te_metric[level - 1],
1017 family, parent);
hassof390d2c2004-09-10 20:48:21 +00001018 break;
1019 case ISIS_SYSTYPE_IS:
1020 case ISIS_SYSTYPE_L1_IS:
1021 case ISIS_SYSTYPE_L2_IS:
Josh Bailey3f045a02012-03-24 08:35:20 -07001022 isis_spf_add_local (spftree,
1023 spftree->area->oldmetric ?
1024 VTYPE_NONPSEUDO_IS :
1025 VTYPE_NONPSEUDO_TE_IS,
1026 adj->sysid, adj,
1027 circuit->te_metric[level - 1],
1028 family, parent);
hassof390d2c2004-09-10 20:48:21 +00001029 memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN);
1030 LSP_PSEUDO_ID (lsp_id) = 0;
1031 LSP_FRAGMENT (lsp_id) = 0;
Josh Bailey3f045a02012-03-24 08:35:20 -07001032 lsp = lsp_search (lsp_id, spftree->area->lspdb[level - 1]);
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001033 if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0)
Josh Bailey3f045a02012-03-24 08:35:20 -07001034 zlog_warn ("ISIS-Spf: No LSP %s found for IS adjacency "
1035 "L%d on %s (ID %u)",
1036 rawlspid_print (lsp_id), level,
1037 circuit->interface->name, circuit->circuit_id);
hassof390d2c2004-09-10 20:48:21 +00001038 break;
1039 case ISIS_SYSTYPE_UNKNOWN:
1040 default:
1041 zlog_warn ("isis_spf_preload_tent unknow adj type");
1042 }
hassof390d2c2004-09-10 20:48:21 +00001043 }
1044 list_delete (adj_list);
1045 /*
1046 * Add the pseudonode
1047 */
1048 if (level == 1)
1049 memcpy (lsp_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
1050 else
1051 memcpy (lsp_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
Josh Bailey3f045a02012-03-24 08:35:20 -07001052 /* can happen during DR reboot */
1053 if (memcmp (lsp_id, null_lsp_id, ISIS_SYS_ID_LEN + 1) == 0)
1054 {
1055 if (isis->debugs & DEBUG_SPF_EVENTS)
1056 zlog_debug ("ISIS-Spf: No L%d DR on %s (ID %d)",
1057 level, circuit->interface->name, circuit->circuit_id);
1058 continue;
1059 }
hassof390d2c2004-09-10 20:48:21 +00001060 adj = isis_adj_lookup (lsp_id, adjdb);
1061 /* if no adj, we are the dis or error */
1062 if (!adj && !circuit->u.bc.is_dr[level - 1])
1063 {
Josh Bailey3f045a02012-03-24 08:35:20 -07001064 zlog_warn ("ISIS-Spf: No adjacency found from root "
1065 "to L%d DR %s on %s (ID %d)",
1066 level, rawlspid_print (lsp_id),
1067 circuit->interface->name, circuit->circuit_id);
1068 continue;
hassof390d2c2004-09-10 20:48:21 +00001069 }
Josh Bailey3f045a02012-03-24 08:35:20 -07001070 lsp = lsp_search (lsp_id, spftree->area->lspdb[level - 1]);
hassof390d2c2004-09-10 20:48:21 +00001071 if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0)
1072 {
Josh Bailey3f045a02012-03-24 08:35:20 -07001073 zlog_warn ("ISIS-Spf: No lsp (%p) found from root "
1074 "to L%d DR %s on %s (ID %d)",
David Lampartereed3c482015-03-03 08:51:53 +01001075 (void *)lsp, level, rawlspid_print (lsp_id),
1076 circuit->interface->name, circuit->circuit_id);
Josh Bailey3f045a02012-03-24 08:35:20 -07001077 continue;
hassof390d2c2004-09-10 20:48:21 +00001078 }
Josh Bailey3f045a02012-03-24 08:35:20 -07001079 isis_spf_process_pseudo_lsp (spftree, lsp,
1080 circuit->te_metric[level - 1], 0,
1081 family, root_sysid, parent);
hassof390d2c2004-09-10 20:48:21 +00001082 }
1083 else if (circuit->circ_type == CIRCUIT_T_P2P)
1084 {
1085 adj = circuit->u.p2p.neighbor;
1086 if (!adj)
1087 continue;
1088 switch (adj->sys_type)
1089 {
1090 case ISIS_SYSTYPE_ES:
1091 isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
Josh Bailey3f045a02012-03-24 08:35:20 -07001092 circuit->te_metric[level - 1], family,
1093 parent);
hassof390d2c2004-09-10 20:48:21 +00001094 break;
1095 case ISIS_SYSTYPE_IS:
1096 case ISIS_SYSTYPE_L1_IS:
1097 case ISIS_SYSTYPE_L2_IS:
1098 if (speaks (&adj->nlpids, family))
Josh Bailey3f045a02012-03-24 08:35:20 -07001099 isis_spf_add_local (spftree,
1100 spftree->area->oldmetric ?
1101 VTYPE_NONPSEUDO_IS :
1102 VTYPE_NONPSEUDO_TE_IS,
1103 adj->sysid,
hasso82a84282005-09-26 18:15:36 +00001104 adj, circuit->te_metric[level - 1],
Josh Bailey3f045a02012-03-24 08:35:20 -07001105 family, parent);
hassof390d2c2004-09-10 20:48:21 +00001106 break;
1107 case ISIS_SYSTYPE_UNKNOWN:
1108 default:
Josh Bailey3f045a02012-03-24 08:35:20 -07001109 zlog_warn ("isis_spf_preload_tent unknown adj type");
hassof390d2c2004-09-10 20:48:21 +00001110 break;
1111 }
1112 }
Josh Bailey3f045a02012-03-24 08:35:20 -07001113 else if (circuit->circ_type == CIRCUIT_T_LOOPBACK)
1114 {
1115 continue;
1116 }
jardineb5d44e2003-12-23 08:09:43 +00001117 else
hassof390d2c2004-09-10 20:48:21 +00001118 {
1119 zlog_warn ("isis_spf_preload_tent unsupported media");
1120 retval = ISIS_WARNING;
1121 }
jardineb5d44e2003-12-23 08:09:43 +00001122 }
jardineb5d44e2003-12-23 08:09:43 +00001123
1124 return retval;
1125}
1126
1127/*
1128 * The parent(s) for vertex is set when added to TENT list
1129 * now we just put the child pointer(s) in place
1130 */
hasso92365882005-01-18 13:53:33 +00001131static void
jardineb5d44e2003-12-23 08:09:43 +00001132add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex,
Josh Bailey3f045a02012-03-24 08:35:20 -07001133 int level)
jardineb5d44e2003-12-23 08:09:43 +00001134{
jardineb5d44e2003-12-23 08:09:43 +00001135 u_char buff[BUFSIZ];
Josh Bailey3f045a02012-03-24 08:35:20 -07001136
1137 if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type))
1138 return;
jardineb5d44e2003-12-23 08:09:43 +00001139 listnode_add (spftree->paths, vertex);
1140
hassof390d2c2004-09-10 20:48:21 +00001141#ifdef EXTREME_DEBUG
Josh Bailey3f045a02012-03-24 08:35:20 -07001142 zlog_debug ("ISIS-Spf: added %s %s %s depth %d dist %d to PATHS",
1143 print_sys_hostname (vertex->N.id),
hasso529d65b2004-12-24 00:14:50 +00001144 vtype2string (vertex->type), vid2string (vertex, buff),
1145 vertex->depth, vertex->d_N);
hassof390d2c2004-09-10 20:48:21 +00001146#endif /* EXTREME_DEBUG */
Josh Bailey3f045a02012-03-24 08:35:20 -07001147
hassof390d2c2004-09-10 20:48:21 +00001148 if (vertex->type > VTYPE_ES)
1149 {
1150 if (listcount (vertex->Adj_N) > 0)
hassofac1f7c2005-09-26 18:26:26 +00001151 isis_route_create ((struct prefix *) &vertex->N.prefix, vertex->d_N,
Josh Bailey3f045a02012-03-24 08:35:20 -07001152 vertex->depth, vertex->Adj_N, spftree->area, level);
hassof390d2c2004-09-10 20:48:21 +00001153 else if (isis->debugs & DEBUG_SPF_EVENTS)
Josh Bailey3f045a02012-03-24 08:35:20 -07001154 zlog_debug ("ISIS-Spf: no adjacencies do not install route for "
1155 "%s depth %d dist %d", vid2string (vertex, buff),
1156 vertex->depth, vertex->d_N);
hassof390d2c2004-09-10 20:48:21 +00001157 }
1158
jardineb5d44e2003-12-23 08:09:43 +00001159 return;
1160}
1161
hasso92365882005-01-18 13:53:33 +00001162static void
jardineb5d44e2003-12-23 08:09:43 +00001163init_spt (struct isis_spftree *spftree)
1164{
hassof7c43dc2004-09-26 16:24:14 +00001165 spftree->tents->del = spftree->paths->del = (void (*)(void *)) isis_vertex_del;
jardineb5d44e2003-12-23 08:09:43 +00001166 list_delete_all_node (spftree->tents);
1167 list_delete_all_node (spftree->paths);
1168 spftree->tents->del = spftree->paths->del = NULL;
jardineb5d44e2003-12-23 08:09:43 +00001169 return;
1170}
1171
hasso92365882005-01-18 13:53:33 +00001172static int
Josh Bailey3f045a02012-03-24 08:35:20 -07001173isis_run_spf (struct isis_area *area, int level, int family, u_char *sysid)
jardineb5d44e2003-12-23 08:09:43 +00001174{
1175 int retval = ISIS_OK;
1176 struct listnode *node;
1177 struct isis_vertex *vertex;
Josh Bailey3f045a02012-03-24 08:35:20 -07001178 struct isis_vertex *root_vertex;
hassof390d2c2004-09-10 20:48:21 +00001179 struct isis_spftree *spftree = NULL;
jardineb5d44e2003-12-23 08:09:43 +00001180 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
1181 struct isis_lsp *lsp;
hassofac1f7c2005-09-26 18:26:26 +00001182 struct route_table *table = NULL;
Hasso Tepper43057bf2012-10-11 11:19:51 +00001183 struct timeval time_now;
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001184 unsigned long long start_time, end_time;
1185
1186 /* Get time that can't roll backwards. */
Hasso Tepper43057bf2012-10-11 11:19:51 +00001187 quagga_gettime(QUAGGA_CLK_MONOTONIC, &time_now);
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001188 start_time = time_now.tv_sec;
Hasso Tepper43057bf2012-10-11 11:19:51 +00001189 start_time = (start_time * 1000000) + time_now.tv_usec;
hassof390d2c2004-09-10 20:48:21 +00001190
jardineb5d44e2003-12-23 08:09:43 +00001191 if (family == AF_INET)
1192 spftree = area->spftree[level - 1];
1193#ifdef HAVE_IPV6
1194 else if (family == AF_INET6)
1195 spftree = area->spftree6[level - 1];
1196#endif
jardineb5d44e2003-12-23 08:09:43 +00001197 assert (spftree);
Josh Bailey3f045a02012-03-24 08:35:20 -07001198 assert (sysid);
jardineb5d44e2003-12-23 08:09:43 +00001199
hassofac1f7c2005-09-26 18:26:26 +00001200 /* Make all routes in current route table inactive. */
1201 if (family == AF_INET)
1202 table = area->route_table[level - 1];
Paul Jakma41b36e92006-12-08 01:09:50 +00001203#ifdef HAVE_IPV6
hassofac1f7c2005-09-26 18:26:26 +00001204 else if (family == AF_INET6)
1205 table = area->route_table6[level - 1];
Paul Jakma41b36e92006-12-08 01:09:50 +00001206#endif
hassofac1f7c2005-09-26 18:26:26 +00001207
Josh Bailey3f045a02012-03-24 08:35:20 -07001208 isis_route_invalidate_table (area, table);
hassofac1f7c2005-09-26 18:26:26 +00001209
jardineb5d44e2003-12-23 08:09:43 +00001210 /*
1211 * C.2.5 Step 0
1212 */
1213 init_spt (spftree);
1214 /* a) */
Josh Bailey3f045a02012-03-24 08:35:20 -07001215 root_vertex = isis_spf_add_root (spftree, level, sysid);
jardineb5d44e2003-12-23 08:09:43 +00001216 /* b) */
Josh Bailey3f045a02012-03-24 08:35:20 -07001217 retval = isis_spf_preload_tent (spftree, level, family, sysid, root_vertex);
1218 if (retval != ISIS_OK)
1219 {
1220 zlog_warn ("ISIS-Spf: failed to load TENT SPF-root:%s", print_sys_hostname(sysid));
1221 goto out;
1222 }
hassof390d2c2004-09-10 20:48:21 +00001223
jardineb5d44e2003-12-23 08:09:43 +00001224 /*
1225 * C.2.7 Step 2
1226 */
hassof390d2c2004-09-10 20:48:21 +00001227 if (listcount (spftree->tents) == 0)
1228 {
Josh Bailey3f045a02012-03-24 08:35:20 -07001229 zlog_warn ("ISIS-Spf: TENT is empty SPF-root:%s", print_sys_hostname(sysid));
hasso13fb40a2005-10-01 06:03:04 +00001230 goto out;
jardineb5d44e2003-12-23 08:09:43 +00001231 }
hassof390d2c2004-09-10 20:48:21 +00001232
1233 while (listcount (spftree->tents) > 0)
1234 {
1235 node = listhead (spftree->tents);
paul1eb8ef22005-04-07 07:30:20 +00001236 vertex = listgetdata (node);
Josh Bailey3f045a02012-03-24 08:35:20 -07001237
1238#ifdef EXTREME_DEBUG
1239 zlog_debug ("ISIS-Spf: get TENT node %s %s depth %d dist %d to PATHS",
1240 print_sys_hostname (vertex->N.id),
1241 vtype2string (vertex->type), vertex->depth, vertex->d_N);
1242#endif /* EXTREME_DEBUG */
1243
1244 /* Remove from tent list and add to paths list */
hassof390d2c2004-09-10 20:48:21 +00001245 list_delete_node (spftree->tents, node);
Josh Bailey3f045a02012-03-24 08:35:20 -07001246 add_to_paths (spftree, vertex, level);
1247 switch (vertex->type)
1248 {
1249 case VTYPE_PSEUDO_IS:
1250 case VTYPE_NONPSEUDO_IS:
1251 case VTYPE_PSEUDO_TE_IS:
1252 case VTYPE_NONPSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +00001253 memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
1254 LSP_FRAGMENT (lsp_id) = 0;
1255 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001256 if (lsp && lsp->lsp_header->rem_lifetime != 0)
hassof390d2c2004-09-10 20:48:21 +00001257 {
1258 if (LSP_PSEUDO_ID (lsp_id))
1259 {
1260 isis_spf_process_pseudo_lsp (spftree, lsp, vertex->d_N,
Josh Bailey3f045a02012-03-24 08:35:20 -07001261 vertex->depth, family, sysid,
1262 vertex);
hassof390d2c2004-09-10 20:48:21 +00001263 }
1264 else
1265 {
1266 isis_spf_process_lsp (spftree, lsp, vertex->d_N,
Josh Bailey3f045a02012-03-24 08:35:20 -07001267 vertex->depth, family, sysid, vertex);
hassof390d2c2004-09-10 20:48:21 +00001268 }
1269 }
1270 else
1271 {
1272 zlog_warn ("ISIS-Spf: No LSP found for %s",
1273 rawlspid_print (lsp_id));
1274 }
Josh Bailey3f045a02012-03-24 08:35:20 -07001275 break;
1276 default:;
hassof390d2c2004-09-10 20:48:21 +00001277 }
1278 }
1279
hasso13fb40a2005-10-01 06:03:04 +00001280out:
Josh Bailey3f045a02012-03-24 08:35:20 -07001281 isis_route_validate (area);
jardineb5d44e2003-12-23 08:09:43 +00001282 spftree->pending = 0;
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001283 spftree->runcount++;
1284 spftree->last_run_timestamp = time (NULL);
Hasso Tepper43057bf2012-10-11 11:19:51 +00001285 quagga_gettime(QUAGGA_CLK_MONOTONIC, &time_now);
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001286 end_time = time_now.tv_sec;
Hasso Tepper43057bf2012-10-11 11:19:51 +00001287 end_time = (end_time * 1000000) + time_now.tv_usec;
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001288 spftree->last_run_duration = end_time - start_time;
1289
hassof390d2c2004-09-10 20:48:21 +00001290
jardineb5d44e2003-12-23 08:09:43 +00001291 return retval;
1292}
1293
1294int
1295isis_run_spf_l1 (struct thread *thread)
1296{
1297 struct isis_area *area;
1298 int retval = ISIS_OK;
1299
hassof390d2c2004-09-10 20:48:21 +00001300 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001301 assert (area);
1302
hasso12a5cae2004-09-19 19:39:26 +00001303 area->spftree[0]->t_spf = NULL;
Josh Bailey3f045a02012-03-24 08:35:20 -07001304 area->spftree[0]->pending = 0;
hasso12a5cae2004-09-19 19:39:26 +00001305
hassof390d2c2004-09-10 20:48:21 +00001306 if (!(area->is_type & IS_LEVEL_1))
1307 {
1308 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001309 zlog_warn ("ISIS-SPF (%s) area does not share level",
1310 area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001311 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001312 }
jardineb5d44e2003-12-23 08:09:43 +00001313
hassof390d2c2004-09-10 20:48:21 +00001314 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001315 zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001316
jardineb5d44e2003-12-23 08:09:43 +00001317 if (area->ip_circuits)
Josh Bailey3f045a02012-03-24 08:35:20 -07001318 retval = isis_run_spf (area, 1, AF_INET, isis->sysid);
hasso12a5cae2004-09-19 19:39:26 +00001319
jardineb5d44e2003-12-23 08:09:43 +00001320 return retval;
1321}
1322
1323int
1324isis_run_spf_l2 (struct thread *thread)
1325{
1326 struct isis_area *area;
1327 int retval = ISIS_OK;
1328
hassof390d2c2004-09-10 20:48:21 +00001329 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001330 assert (area);
hassof390d2c2004-09-10 20:48:21 +00001331
hasso12a5cae2004-09-19 19:39:26 +00001332 area->spftree[1]->t_spf = NULL;
Josh Bailey3f045a02012-03-24 08:35:20 -07001333 area->spftree[1]->pending = 0;
hasso12a5cae2004-09-19 19:39:26 +00001334
hassof390d2c2004-09-10 20:48:21 +00001335 if (!(area->is_type & IS_LEVEL_2))
1336 {
1337 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001338 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001339 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001340 }
hassof390d2c2004-09-10 20:48:21 +00001341
1342 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001343 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag);
jardineb5d44e2003-12-23 08:09:43 +00001344
1345 if (area->ip_circuits)
Josh Bailey3f045a02012-03-24 08:35:20 -07001346 retval = isis_run_spf (area, 2, AF_INET, isis->sysid);
jardineb5d44e2003-12-23 08:09:43 +00001347
1348 return retval;
1349}
1350
hassof390d2c2004-09-10 20:48:21 +00001351int
jardineb5d44e2003-12-23 08:09:43 +00001352isis_spf_schedule (struct isis_area *area, int level)
1353{
jardineb5d44e2003-12-23 08:09:43 +00001354 struct isis_spftree *spftree = area->spftree[level - 1];
Josh Bailey3f045a02012-03-24 08:35:20 -07001355 time_t now = time (NULL);
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001356 int diff = now - spftree->last_run_timestamp;
Josh Bailey3f045a02012-03-24 08:35:20 -07001357
1358 assert (diff >= 0);
1359 assert (area->is_type & level);
1360
1361 if (isis->debugs & DEBUG_SPF_EVENTS)
1362 zlog_debug ("ISIS-Spf (%s) L%d SPF schedule called, lastrun %d sec ago",
1363 area->area_tag, level, diff);
jardineb5d44e2003-12-23 08:09:43 +00001364
1365 if (spftree->pending)
Josh Bailey3f045a02012-03-24 08:35:20 -07001366 return ISIS_OK;
hasso12a5cae2004-09-19 19:39:26 +00001367
1368 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001369
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001370 /* wait configured min_spf_interval before doing the SPF */
1371 if (diff >= area->min_spf_interval[level-1])
Josh Bailey3f045a02012-03-24 08:35:20 -07001372 return isis_run_spf (area, level, AF_INET, isis->sysid);
jardineb5d44e2003-12-23 08:09:43 +00001373
Josh Bailey3f045a02012-03-24 08:35:20 -07001374 if (level == 1)
1375 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001376 area->min_spf_interval[0] - diff);
hassof390d2c2004-09-10 20:48:21 +00001377 else
Josh Bailey3f045a02012-03-24 08:35:20 -07001378 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001379 area->min_spf_interval[1] - diff);
jardineb5d44e2003-12-23 08:09:43 +00001380
Josh Bailey3f045a02012-03-24 08:35:20 -07001381 if (isis->debugs & DEBUG_SPF_EVENTS)
1382 zlog_debug ("ISIS-Spf (%s) L%d SPF scheduled %d sec from now",
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001383 area->area_tag, level, area->min_spf_interval[level-1] - diff);
Josh Bailey3f045a02012-03-24 08:35:20 -07001384
1385 spftree->pending = 1;
1386
1387 return ISIS_OK;
jardineb5d44e2003-12-23 08:09:43 +00001388}
1389
1390#ifdef HAVE_IPV6
hasso92365882005-01-18 13:53:33 +00001391static int
hasso12a5cae2004-09-19 19:39:26 +00001392isis_run_spf6_l1 (struct thread *thread)
1393{
1394 struct isis_area *area;
1395 int retval = ISIS_OK;
1396
1397 area = THREAD_ARG (thread);
1398 assert (area);
1399
1400 area->spftree6[0]->t_spf = NULL;
Josh Bailey3f045a02012-03-24 08:35:20 -07001401 area->spftree6[0]->pending = 0;
hasso12a5cae2004-09-19 19:39:26 +00001402
1403 if (!(area->is_type & IS_LEVEL_1))
1404 {
1405 if (isis->debugs & DEBUG_SPF_EVENTS)
Josh Bailey3f045a02012-03-24 08:35:20 -07001406 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001407 return ISIS_WARNING;
1408 }
1409
1410 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001411 zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001412
1413 if (area->ipv6_circuits)
Josh Bailey3f045a02012-03-24 08:35:20 -07001414 retval = isis_run_spf (area, 1, AF_INET6, isis->sysid);
hasso12a5cae2004-09-19 19:39:26 +00001415
1416 return retval;
1417}
1418
hasso92365882005-01-18 13:53:33 +00001419static int
hasso12a5cae2004-09-19 19:39:26 +00001420isis_run_spf6_l2 (struct thread *thread)
1421{
1422 struct isis_area *area;
1423 int retval = ISIS_OK;
1424
1425 area = THREAD_ARG (thread);
1426 assert (area);
1427
1428 area->spftree6[1]->t_spf = NULL;
Josh Bailey3f045a02012-03-24 08:35:20 -07001429 area->spftree6[1]->pending = 0;
hasso12a5cae2004-09-19 19:39:26 +00001430
1431 if (!(area->is_type & IS_LEVEL_2))
1432 {
1433 if (isis->debugs & DEBUG_SPF_EVENTS)
1434 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
1435 return ISIS_WARNING;
1436 }
1437
1438 if (isis->debugs & DEBUG_SPF_EVENTS)
hassofac1f7c2005-09-26 18:26:26 +00001439 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF.", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001440
1441 if (area->ipv6_circuits)
Josh Bailey3f045a02012-03-24 08:35:20 -07001442 retval = isis_run_spf (area, 2, AF_INET6, isis->sysid);
hasso12a5cae2004-09-19 19:39:26 +00001443
1444 return retval;
1445}
1446
1447int
jardineb5d44e2003-12-23 08:09:43 +00001448isis_spf_schedule6 (struct isis_area *area, int level)
1449{
1450 int retval = ISIS_OK;
1451 struct isis_spftree *spftree = area->spftree6[level - 1];
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001452 time_t now = time (NULL);
1453 time_t diff = now - spftree->last_run_timestamp;
1454
1455 assert (diff >= 0);
1456 assert (area->is_type & level);
1457
1458 if (isis->debugs & DEBUG_SPF_EVENTS)
David Lamparteref008d22015-03-03 08:48:11 +01001459 zlog_debug ("ISIS-Spf (%s) L%d SPF schedule called, lastrun %lld sec ago",
1460 area->area_tag, level, (long long)diff);
jardineb5d44e2003-12-23 08:09:43 +00001461
1462 if (spftree->pending)
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001463 return ISIS_OK;
jardineb5d44e2003-12-23 08:09:43 +00001464
hasso12a5cae2004-09-19 19:39:26 +00001465 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001466
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001467 /* wait configured min_spf_interval before doing the SPF */
1468 if (diff >= area->min_spf_interval[level-1])
1469 return isis_run_spf (area, level, AF_INET6, isis->sysid);
Josh Bailey3f045a02012-03-24 08:35:20 -07001470
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001471 if (level == 1)
1472 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
1473 area->min_spf_interval[0] - diff);
hassof390d2c2004-09-10 20:48:21 +00001474 else
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001475 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
1476 area->min_spf_interval[1] - diff);
1477
1478 if (isis->debugs & DEBUG_SPF_EVENTS)
David Lamparteref008d22015-03-03 08:48:11 +01001479 zlog_debug ("ISIS-Spf (%s) L%d SPF scheduled %lld sec from now",
1480 area->area_tag, level,
1481 (long long)(area->min_spf_interval[level-1] - diff));
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001482
1483 spftree->pending = 1;
jardineb5d44e2003-12-23 08:09:43 +00001484
1485 return retval;
1486}
jardineb5d44e2003-12-23 08:09:43 +00001487#endif
1488
hasso92365882005-01-18 13:53:33 +00001489static void
Josh Bailey3f045a02012-03-24 08:35:20 -07001490isis_print_paths (struct vty *vty, struct list *paths, u_char *root_sysid)
jardineb5d44e2003-12-23 08:09:43 +00001491{
paul1eb8ef22005-04-07 07:30:20 +00001492 struct listnode *node;
Josh Bailey3f045a02012-03-24 08:35:20 -07001493 struct listnode *anode;
jardineb5d44e2003-12-23 08:09:43 +00001494 struct isis_vertex *vertex;
jardineb5d44e2003-12-23 08:09:43 +00001495 struct isis_adjacency *adj;
David Lampartere8aca322012-11-27 01:10:30 +00001496 u_char buff[BUFSIZ];
jardineb5d44e2003-12-23 08:09:43 +00001497
Josh Bailey3f045a02012-03-24 08:35:20 -07001498 vty_out (vty, "Vertex Type Metric "
1499 "Next-Hop Interface Parent%s", VTY_NEWLINE);
paul1eb8ef22005-04-07 07:30:20 +00001500
Josh Bailey3f045a02012-03-24 08:35:20 -07001501 for (ALL_LIST_ELEMENTS_RO (paths, node, vertex)) {
1502 if (memcmp (vertex->N.id, root_sysid, ISIS_SYS_ID_LEN) == 0) {
1503 vty_out (vty, "%-20s %-12s %-6s", print_sys_hostname (root_sysid),
1504 "", "");
1505 vty_out (vty, "%-30s", "");
1506 } else {
1507 int rows = 0;
1508 vty_out (vty, "%-20s %-12s %-6u ", vid2string (vertex, buff),
1509 vtype2string (vertex->type), vertex->d_N);
1510 for (ALL_LIST_ELEMENTS_RO (vertex->Adj_N, anode, adj)) {
1511 if (adj) {
1512 if (rows) {
1513 vty_out (vty, "%s", VTY_NEWLINE);
1514 vty_out (vty, "%-20s %-12s %-6s ", "", "", "");
hassof390d2c2004-09-10 20:48:21 +00001515 }
Josh Bailey3f045a02012-03-24 08:35:20 -07001516 vty_out (vty, "%-20s %-9s ",
1517 print_sys_hostname (adj->sysid),
1518 adj->circuit->interface->name);
1519 ++rows;
1520 }
hassof390d2c2004-09-10 20:48:21 +00001521 }
Josh Bailey3f045a02012-03-24 08:35:20 -07001522 if (rows == 0)
1523 vty_out (vty, "%-30s ", "");
1524 }
1525
1526 /* Print list of parents for the ECMP DAG */
1527 if (listcount (vertex->parents) > 0) {
1528 struct listnode *pnode;
1529 struct isis_vertex *pvertex;
1530 int rows = 0;
1531 for (ALL_LIST_ELEMENTS_RO (vertex->parents, pnode, pvertex)) {
1532 if (rows) {
1533 vty_out (vty, "%s", VTY_NEWLINE);
1534 vty_out (vty, "%-72s", "");
1535 }
1536 vty_out (vty, "%s(%d)",
1537 vid2string (pvertex, buff), pvertex->type);
1538 ++rows;
1539 }
1540 } else {
1541 vty_out (vty, " NULL ");
1542 }
1543
jardineb5d44e2003-12-23 08:09:43 +00001544#if 0
Josh Bailey3f045a02012-03-24 08:35:20 -07001545 if (listcount (vertex->children) > 0) {
1546 struct listnode *cnode;
1547 struct isis_vertex *cvertex;
1548 for (ALL_LIST_ELEMENTS_RO (vertex->children, cnode, cvertex)) {
1549 vty_out (vty, "%s", VTY_NEWLINE);
1550 vty_out (vty, "%-72s", "");
1551 vty_out (vty, "%s(%d) ",
1552 vid2string (cvertex, buff), cvertex->type);
1553 }
1554 }
jardineb5d44e2003-12-23 08:09:43 +00001555#endif
Josh Bailey3f045a02012-03-24 08:35:20 -07001556 vty_out (vty, "%s", VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +00001557 }
jardineb5d44e2003-12-23 08:09:43 +00001558}
1559
1560DEFUN (show_isis_topology,
1561 show_isis_topology_cmd,
1562 "show isis topology",
1563 SHOW_STR
1564 "IS-IS information\n"
1565 "IS-IS paths to Intermediate Systems\n")
1566{
1567 struct listnode *node;
1568 struct isis_area *area;
1569 int level;
hassof390d2c2004-09-10 20:48:21 +00001570
jardineb5d44e2003-12-23 08:09:43 +00001571 if (!isis->area_list || isis->area_list->count == 0)
1572 return CMD_SUCCESS;
1573
paul1eb8ef22005-04-07 07:30:20 +00001574 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001575 {
hassof390d2c2004-09-10 20:48:21 +00001576 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1577 VTY_NEWLINE);
1578
1579 for (level = 0; level < ISIS_LEVELS; level++)
1580 {
1581 if (area->ip_circuits > 0 && area->spftree[level]
1582 && area->spftree[level]->paths->count > 0)
1583 {
1584 vty_out (vty, "IS-IS paths to level-%d routers that speak IP%s",
1585 level + 1, VTY_NEWLINE);
Josh Bailey3f045a02012-03-24 08:35:20 -07001586 isis_print_paths (vty, area->spftree[level]->paths, isis->sysid);
1587 vty_out (vty, "%s", VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +00001588 }
jardineb5d44e2003-12-23 08:09:43 +00001589#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001590 if (area->ipv6_circuits > 0 && area->spftree6[level]
1591 && area->spftree6[level]->paths->count > 0)
1592 {
1593 vty_out (vty,
1594 "IS-IS paths to level-%d routers that speak IPv6%s",
1595 level + 1, VTY_NEWLINE);
Josh Bailey3f045a02012-03-24 08:35:20 -07001596 isis_print_paths (vty, area->spftree6[level]->paths, isis->sysid);
1597 vty_out (vty, "%s", VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +00001598 }
jardineb5d44e2003-12-23 08:09:43 +00001599#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +00001600 }
Josh Bailey3f045a02012-03-24 08:35:20 -07001601
1602 vty_out (vty, "%s", VTY_NEWLINE);
jardineb5d44e2003-12-23 08:09:43 +00001603 }
jardineb5d44e2003-12-23 08:09:43 +00001604
1605 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001606}
jardineb5d44e2003-12-23 08:09:43 +00001607
1608DEFUN (show_isis_topology_l1,
1609 show_isis_topology_l1_cmd,
1610 "show isis topology level-1",
1611 SHOW_STR
1612 "IS-IS information\n"
1613 "IS-IS paths to Intermediate Systems\n"
1614 "Paths to all level-1 routers in the area\n")
1615{
1616 struct listnode *node;
1617 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001618
jardineb5d44e2003-12-23 08:09:43 +00001619 if (!isis->area_list || isis->area_list->count == 0)
1620 return CMD_SUCCESS;
1621
paul1eb8ef22005-04-07 07:30:20 +00001622 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001623 {
hassof390d2c2004-09-10 20:48:21 +00001624 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1625 VTY_NEWLINE);
1626
1627 if (area->ip_circuits > 0 && area->spftree[0]
1628 && area->spftree[0]->paths->count > 0)
1629 {
1630 vty_out (vty, "IS-IS paths to level-1 routers that speak IP%s",
1631 VTY_NEWLINE);
Josh Bailey3f045a02012-03-24 08:35:20 -07001632 isis_print_paths (vty, area->spftree[0]->paths, isis->sysid);
1633 vty_out (vty, "%s", VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +00001634 }
jardineb5d44e2003-12-23 08:09:43 +00001635#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001636 if (area->ipv6_circuits > 0 && area->spftree6[0]
1637 && area->spftree6[0]->paths->count > 0)
1638 {
1639 vty_out (vty, "IS-IS paths to level-1 routers that speak IPv6%s",
1640 VTY_NEWLINE);
Josh Bailey3f045a02012-03-24 08:35:20 -07001641 isis_print_paths (vty, area->spftree6[0]->paths, isis->sysid);
1642 vty_out (vty, "%s", VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +00001643 }
jardineb5d44e2003-12-23 08:09:43 +00001644#endif /* HAVE_IPV6 */
Josh Bailey3f045a02012-03-24 08:35:20 -07001645 vty_out (vty, "%s", VTY_NEWLINE);
jardineb5d44e2003-12-23 08:09:43 +00001646 }
1647
jardineb5d44e2003-12-23 08:09:43 +00001648 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001649}
jardineb5d44e2003-12-23 08:09:43 +00001650
1651DEFUN (show_isis_topology_l2,
1652 show_isis_topology_l2_cmd,
1653 "show isis topology level-2",
1654 SHOW_STR
1655 "IS-IS information\n"
1656 "IS-IS paths to Intermediate Systems\n"
1657 "Paths to all level-2 routers in the domain\n")
1658{
1659 struct listnode *node;
1660 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001661
jardineb5d44e2003-12-23 08:09:43 +00001662 if (!isis->area_list || isis->area_list->count == 0)
1663 return CMD_SUCCESS;
1664
paul1eb8ef22005-04-07 07:30:20 +00001665 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001666 {
hassof390d2c2004-09-10 20:48:21 +00001667 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1668 VTY_NEWLINE);
1669
1670 if (area->ip_circuits > 0 && area->spftree[1]
1671 && area->spftree[1]->paths->count > 0)
1672 {
1673 vty_out (vty, "IS-IS paths to level-2 routers that speak IP%s",
1674 VTY_NEWLINE);
Josh Bailey3f045a02012-03-24 08:35:20 -07001675 isis_print_paths (vty, area->spftree[1]->paths, isis->sysid);
1676 vty_out (vty, "%s", VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +00001677 }
jardineb5d44e2003-12-23 08:09:43 +00001678#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001679 if (area->ipv6_circuits > 0 && area->spftree6[1]
1680 && area->spftree6[1]->paths->count > 0)
1681 {
1682 vty_out (vty, "IS-IS paths to level-2 routers that speak IPv6%s",
1683 VTY_NEWLINE);
Josh Bailey3f045a02012-03-24 08:35:20 -07001684 isis_print_paths (vty, area->spftree6[1]->paths, isis->sysid);
1685 vty_out (vty, "%s", VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +00001686 }
jardineb5d44e2003-12-23 08:09:43 +00001687#endif /* HAVE_IPV6 */
Josh Bailey3f045a02012-03-24 08:35:20 -07001688 vty_out (vty, "%s", VTY_NEWLINE);
jardineb5d44e2003-12-23 08:09:43 +00001689 }
1690
jardineb5d44e2003-12-23 08:09:43 +00001691 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001692}
jardineb5d44e2003-12-23 08:09:43 +00001693
1694void
1695isis_spf_cmds_init ()
1696{
1697 install_element (VIEW_NODE, &show_isis_topology_cmd);
1698 install_element (VIEW_NODE, &show_isis_topology_l1_cmd);
1699 install_element (VIEW_NODE, &show_isis_topology_l2_cmd);
1700
1701 install_element (ENABLE_NODE, &show_isis_topology_cmd);
1702 install_element (ENABLE_NODE, &show_isis_topology_l1_cmd);
1703 install_element (ENABLE_NODE, &show_isis_topology_l2_cmd);
1704}