blob: d9375496e1cdc49d2f6b99c65035c8169330f565 [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
24#include <stdlib.h>
25#include <stdio.h>
26#include <zebra.h>
jardineb5d44e2003-12-23 08:09:43 +000027
28#include "thread.h"
29#include "linklist.h"
30#include "vty.h"
31#include "log.h"
32#include "command.h"
33#include "memory.h"
34#include "prefix.h"
35#include "hash.h"
36#include "if.h"
37#include "table.h"
38
39#include "isis_constants.h"
40#include "isis_common.h"
41#include "dict.h"
42#include "isisd.h"
43#include "isis_misc.h"
44#include "isis_adjacency.h"
45#include "isis_circuit.h"
46#include "isis_tlv.h"
47#include "isis_pdu.h"
48#include "isis_lsp.h"
49#include "isis_dynhn.h"
50#include "isis_spf.h"
51#include "isis_route.h"
52#include "isis_csm.h"
53
54extern struct isis *isis;
55extern struct thread_master *master;
56extern struct host host;
57
58int isis_run_spf_l1 (struct thread *thread);
59int isis_run_spf_l2 (struct thread *thread);
60
jardineb5d44e2003-12-23 08:09:43 +000061/* 7.2.7 */
hasso92365882005-01-18 13:53:33 +000062static void
jardineb5d44e2003-12-23 08:09:43 +000063remove_excess_adjs (struct list *adjs)
64{
hasso3fdb2dd2005-09-28 18:45:54 +000065 struct listnode *node, *excess = NULL;
jardineb5d44e2003-12-23 08:09:43 +000066 struct isis_adjacency *adj, *candidate = NULL;
67 int comp;
68
hasso3fdb2dd2005-09-28 18:45:54 +000069 for (ALL_LIST_ELEMENTS_RO (adjs, node, adj))
hassof390d2c2004-09-10 20:48:21 +000070 {
71 if (excess == NULL)
72 excess = node;
paul1eb8ef22005-04-07 07:30:20 +000073 candidate = listgetdata (excess);
74
hassof390d2c2004-09-10 20:48:21 +000075 if (candidate->sys_type < adj->sys_type)
76 {
77 excess = node;
78 candidate = adj;
79 continue;
80 }
81 if (candidate->sys_type > adj->sys_type)
82 continue;
83
84 comp = memcmp (candidate->sysid, adj->sysid, ISIS_SYS_ID_LEN);
85 if (comp > 0)
86 {
87 excess = node;
88 candidate = adj;
89 continue;
90 }
91 if (comp < 0)
92 continue;
93
94 if (candidate->circuit->circuit_id > adj->circuit->circuit_id)
95 {
96 excess = node;
97 candidate = adj;
98 continue;
99 }
100
101 if (candidate->circuit->circuit_id < adj->circuit->circuit_id)
102 continue;
103
104 comp = memcmp (candidate->snpa, adj->snpa, ETH_ALEN);
105 if (comp > 0)
106 {
107 excess = node;
108 candidate = adj;
109 continue;
110 }
jardineb5d44e2003-12-23 08:09:43 +0000111 }
112
jardineb5d44e2003-12-23 08:09:43 +0000113 list_delete_node (adjs, excess);
114
115 return;
116}
117
hasso92365882005-01-18 13:53:33 +0000118#ifdef EXTREME_DEBUG
119static const char *
jardineb5d44e2003-12-23 08:09:43 +0000120vtype2string (enum vertextype vtype)
121{
hassof390d2c2004-09-10 20:48:21 +0000122 switch (vtype)
123 {
124 case VTYPE_PSEUDO_IS:
125 return "pseudo_IS";
126 break;
hasso82a84282005-09-26 18:15:36 +0000127 case VTYPE_PSEUDO_TE_IS:
128 return "pseudo_TE-IS";
129 break;
hassof390d2c2004-09-10 20:48:21 +0000130 case VTYPE_NONPSEUDO_IS:
131 return "IS";
132 break;
hasso82a84282005-09-26 18:15:36 +0000133 case VTYPE_NONPSEUDO_TE_IS:
134 return "TE-IS";
135 break;
hassof390d2c2004-09-10 20:48:21 +0000136 case VTYPE_ES:
137 return "ES";
138 break;
139 case VTYPE_IPREACH_INTERNAL:
140 return "IP internal";
141 break;
142 case VTYPE_IPREACH_EXTERNAL:
143 return "IP external";
144 break;
hasso82a84282005-09-26 18:15:36 +0000145 case VTYPE_IPREACH_TE:
146 return "IP TE";
147 break;
jardineb5d44e2003-12-23 08:09:43 +0000148#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000149 case VTYPE_IP6REACH_INTERNAL:
150 return "IP6 internal";
151 break;
152 case VTYPE_IP6REACH_EXTERNAL:
153 return "IP6 external";
154 break;
155#endif /* HAVE_IPV6 */
156 default:
157 return "UNKNOWN";
158 }
159 return NULL; /* Not reached */
jardineb5d44e2003-12-23 08:09:43 +0000160}
161
hasso92365882005-01-18 13:53:33 +0000162static const char *
hassof390d2c2004-09-10 20:48:21 +0000163vid2string (struct isis_vertex *vertex, u_char * buff)
jardineb5d44e2003-12-23 08:09:43 +0000164{
hassof390d2c2004-09-10 20:48:21 +0000165 switch (vertex->type)
166 {
167 case VTYPE_PSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000168 case VTYPE_PSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000169 return rawlspid_print (vertex->N.id);
170 break;
171 case VTYPE_NONPSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000172 case VTYPE_NONPSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000173 case VTYPE_ES:
174 return sysid_print (vertex->N.id);
175 break;
176 case VTYPE_IPREACH_INTERNAL:
177 case VTYPE_IPREACH_EXTERNAL:
hasso82a84282005-09-26 18:15:36 +0000178 case VTYPE_IPREACH_TE:
jardineb5d44e2003-12-23 08:09:43 +0000179#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000180 case VTYPE_IP6REACH_INTERNAL:
181 case VTYPE_IP6REACH_EXTERNAL:
182#endif /* HAVE_IPV6 */
hassof7c43dc2004-09-26 16:24:14 +0000183 prefix2str ((struct prefix *) &vertex->N.prefix, (char *) buff, BUFSIZ);
hassof390d2c2004-09-10 20:48:21 +0000184 break;
185 default:
186 return "UNKNOWN";
187 }
188
hassof7c43dc2004-09-26 16:24:14 +0000189 return (char *) buff;
jardineb5d44e2003-12-23 08:09:43 +0000190}
hasso92365882005-01-18 13:53:33 +0000191#endif /* EXTREME_DEBUG */
jardineb5d44e2003-12-23 08:09:43 +0000192
hasso92365882005-01-18 13:53:33 +0000193static struct isis_spftree *
jardineb5d44e2003-12-23 08:09:43 +0000194isis_spftree_new ()
195{
196 struct isis_spftree *tree;
197
hasso3fdb2dd2005-09-28 18:45:54 +0000198 tree = XCALLOC (MTYPE_ISIS_SPFTREE, sizeof (struct isis_spftree));
hassof390d2c2004-09-10 20:48:21 +0000199 if (tree == NULL)
200 {
201 zlog_err ("ISIS-Spf: isis_spftree_new Out of memory!");
202 return NULL;
203 }
jardineb5d44e2003-12-23 08:09:43 +0000204
205 tree->tents = list_new ();
hassof390d2c2004-09-10 20:48:21 +0000206 tree->paths = list_new ();
jardineb5d44e2003-12-23 08:09:43 +0000207 return tree;
208}
209
hasso92365882005-01-18 13:53:33 +0000210static void
jardineb5d44e2003-12-23 08:09:43 +0000211isis_vertex_del (struct isis_vertex *vertex)
212{
jardineb5d44e2003-12-23 08:09:43 +0000213 list_delete (vertex->Adj_N);
214
215 XFREE (MTYPE_ISIS_VERTEX, vertex);
hassof390d2c2004-09-10 20:48:21 +0000216
jardineb5d44e2003-12-23 08:09:43 +0000217 return;
218}
219
hasso92365882005-01-18 13:53:33 +0000220#if 0 /* HT: Not used yet. */
221static void
jardineb5d44e2003-12-23 08:09:43 +0000222isis_spftree_del (struct isis_spftree *spftree)
223{
hassof7c43dc2004-09-26 16:24:14 +0000224 spftree->tents->del = (void (*)(void *)) isis_vertex_del;
jardineb5d44e2003-12-23 08:09:43 +0000225 list_delete (spftree->tents);
hassof390d2c2004-09-10 20:48:21 +0000226
hassof7c43dc2004-09-26 16:24:14 +0000227 spftree->paths->del = (void (*)(void *)) isis_vertex_del;
jardineb5d44e2003-12-23 08:09:43 +0000228 list_delete (spftree->paths);
229
230 XFREE (MTYPE_ISIS_SPFTREE, spftree);
231
232 return;
233}
hasso92365882005-01-18 13:53:33 +0000234#endif
jardineb5d44e2003-12-23 08:09:43 +0000235
hassof390d2c2004-09-10 20:48:21 +0000236void
jardineb5d44e2003-12-23 08:09:43 +0000237spftree_area_init (struct isis_area *area)
238{
hassof390d2c2004-09-10 20:48:21 +0000239 if ((area->is_type & IS_LEVEL_1) && area->spftree[0] == NULL)
240 {
241 area->spftree[0] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000242#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000243 area->spftree6[0] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000244#endif
245
hassof390d2c2004-09-10 20:48:21 +0000246 /* thread_add_timer (master, isis_run_spf_l1, area,
247 isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */
248 }
249
250 if ((area->is_type & IS_LEVEL_2) && area->spftree[1] == NULL)
251 {
252 area->spftree[1] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000253#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000254 area->spftree6[1] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000255#endif
hassof390d2c2004-09-10 20:48:21 +0000256 /* thread_add_timer (master, isis_run_spf_l2, area,
257 isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */
258 }
jardineb5d44e2003-12-23 08:09:43 +0000259
260 return;
261}
262
hasso92365882005-01-18 13:53:33 +0000263static struct isis_vertex *
jardineb5d44e2003-12-23 08:09:43 +0000264isis_vertex_new (void *id, enum vertextype vtype)
265{
266 struct isis_vertex *vertex;
267
hasso3fdb2dd2005-09-28 18:45:54 +0000268 vertex = XCALLOC (MTYPE_ISIS_VERTEX, sizeof (struct isis_vertex));
hassof390d2c2004-09-10 20:48:21 +0000269 if (vertex == NULL)
270 {
271 zlog_err ("isis_vertex_new Out of memory!");
272 return NULL;
273 }
274
jardineb5d44e2003-12-23 08:09:43 +0000275 vertex->type = vtype;
hassof390d2c2004-09-10 20:48:21 +0000276 switch (vtype)
277 {
278 case VTYPE_ES:
279 case VTYPE_NONPSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000280 case VTYPE_NONPSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000281 memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN);
282 break;
283 case VTYPE_PSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000284 case VTYPE_PSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000285 memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN + 1);
286 break;
287 case VTYPE_IPREACH_INTERNAL:
288 case VTYPE_IPREACH_EXTERNAL:
hasso82a84282005-09-26 18:15:36 +0000289 case VTYPE_IPREACH_TE:
jardineb5d44e2003-12-23 08:09:43 +0000290#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000291 case VTYPE_IP6REACH_INTERNAL:
292 case VTYPE_IP6REACH_EXTERNAL:
293#endif /* HAVE_IPV6 */
294 memcpy (&vertex->N.prefix, (struct prefix *) id,
295 sizeof (struct prefix));
296 break;
297 default:
298 zlog_err ("WTF!");
299 }
jardineb5d44e2003-12-23 08:09:43 +0000300
301 vertex->Adj_N = list_new ();
hassof390d2c2004-09-10 20:48:21 +0000302
jardineb5d44e2003-12-23 08:09:43 +0000303 return vertex;
304}
305
306/*
307 * Add this IS to the root of SPT
308 */
hasso92365882005-01-18 13:53:33 +0000309static void
jardineb5d44e2003-12-23 08:09:43 +0000310isis_spf_add_self (struct isis_spftree *spftree, struct isis_area *area,
hassof390d2c2004-09-10 20:48:21 +0000311 int level)
jardineb5d44e2003-12-23 08:09:43 +0000312{
313 struct isis_vertex *vertex;
314 struct isis_lsp *lsp;
315 u_char lspid[ISIS_SYS_ID_LEN + 2];
316#ifdef EXTREME_DEBUG
317 u_char buff[BUFSIZ];
318#endif /* EXTREME_DEBUG */
319 memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN);
hassof390d2c2004-09-10 20:48:21 +0000320 LSP_PSEUDO_ID (lspid) = 0;
321 LSP_FRAGMENT (lspid) = 0;
322
jardineb5d44e2003-12-23 08:09:43 +0000323 lsp = lsp_search (lspid, area->lspdb[level - 1]);
hassof390d2c2004-09-10 20:48:21 +0000324
jardineb5d44e2003-12-23 08:09:43 +0000325 if (lsp == NULL)
326 zlog_warn ("ISIS-Spf: could not find own l%d LSP!", level);
hassof390d2c2004-09-10 20:48:21 +0000327
hasso82a84282005-09-26 18:15:36 +0000328 if (!area->oldmetric)
329 vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_TE_IS);
330 else
331 vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_IS);
332
jardineb5d44e2003-12-23 08:09:43 +0000333 vertex->lsp = lsp;
334
335 listnode_add (spftree->paths, vertex);
336
337#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000338 zlog_debug ("ISIS-Spf: added this IS %s %s depth %d dist %d to PATHS",
339 vtype2string (vertex->type), vid2string (vertex, buff),
340 vertex->depth, vertex->d_N);
jardineb5d44e2003-12-23 08:09:43 +0000341#endif /* EXTREME_DEBUG */
342
343 return;
344}
345
hasso92365882005-01-18 13:53:33 +0000346static struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000347isis_find_vertex (struct list *list, void *id, enum vertextype vtype)
jardineb5d44e2003-12-23 08:09:43 +0000348{
349 struct listnode *node;
350 struct isis_vertex *vertex;
351 struct prefix *p1, *p2;
352
paul1eb8ef22005-04-07 07:30:20 +0000353 for (ALL_LIST_ELEMENTS_RO (list, node, vertex))
hassof390d2c2004-09-10 20:48:21 +0000354 {
hassof390d2c2004-09-10 20:48:21 +0000355 if (vertex->type != vtype)
356 continue;
357 switch (vtype)
358 {
359 case VTYPE_ES:
360 case VTYPE_NONPSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000361 case VTYPE_NONPSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000362 if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN) == 0)
363 return vertex;
364 break;
365 case VTYPE_PSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000366 case VTYPE_PSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000367 if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN + 1) == 0)
368 return vertex;
369 break;
370 case VTYPE_IPREACH_INTERNAL:
371 case VTYPE_IPREACH_EXTERNAL:
hasso82a84282005-09-26 18:15:36 +0000372 case VTYPE_IPREACH_TE:
jardineb5d44e2003-12-23 08:09:43 +0000373#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000374 case VTYPE_IP6REACH_INTERNAL:
375 case VTYPE_IP6REACH_EXTERNAL:
jardineb5d44e2003-12-23 08:09:43 +0000376#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000377 p1 = (struct prefix *) id;
378 p2 = (struct prefix *) &vertex->N.id;
379 if (p1->family == p2->family && p1->prefixlen == p2->prefixlen &&
380 memcmp (&p1->u.prefix, &p2->u.prefix,
381 PSIZE (p1->prefixlen)) == 0)
382 return vertex;
383 break;
384 }
jardineb5d44e2003-12-23 08:09:43 +0000385 }
jardineb5d44e2003-12-23 08:09:43 +0000386
387 return NULL;
388}
389
jardineb5d44e2003-12-23 08:09:43 +0000390/*
391 * Add a vertex to TENT sorted by cost and by vertextype on tie break situation
392 */
hasso92365882005-01-18 13:53:33 +0000393static struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000394isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype,
hassofac1f7c2005-09-26 18:26:26 +0000395 void *id, struct isis_adjacency *adj, u_int32_t cost,
hassof390d2c2004-09-10 20:48:21 +0000396 int depth, int family)
jardineb5d44e2003-12-23 08:09:43 +0000397{
398 struct isis_vertex *vertex, *v;
399 struct listnode *node;
hassof390d2c2004-09-10 20:48:21 +0000400#ifdef EXTREME_DEBUG
jardineb5d44e2003-12-23 08:09:43 +0000401 u_char buff[BUFSIZ];
402#endif
403
404 vertex = isis_vertex_new (id, vtype);
405 vertex->d_N = cost;
406 vertex->depth = depth;
hassof390d2c2004-09-10 20:48:21 +0000407
jardineb5d44e2003-12-23 08:09:43 +0000408 if (adj)
409 listnode_add (vertex->Adj_N, adj);
hassof390d2c2004-09-10 20:48:21 +0000410#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000411 zlog_debug ("ISIS-Spf: add to TENT %s %s depth %d dist %d",
412 vtype2string (vertex->type), vid2string (vertex, buff),
413 vertex->depth, vertex->d_N);
jardineb5d44e2003-12-23 08:09:43 +0000414#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000415 listnode_add (spftree->tents, vertex);
416 if (list_isempty (spftree->tents))
417 {
418 listnode_add (spftree->tents, vertex);
419 return vertex;
jardineb5d44e2003-12-23 08:09:43 +0000420 }
paul1eb8ef22005-04-07 07:30:20 +0000421
422 /* XXX: This cant use the standard ALL_LIST_ELEMENT macro */
423 for (node = listhead (spftree->tents); node; node = listnextnode (node))
hassof390d2c2004-09-10 20:48:21 +0000424 {
paul1eb8ef22005-04-07 07:30:20 +0000425 v = listgetdata (node);
hassof390d2c2004-09-10 20:48:21 +0000426 if (v->d_N > vertex->d_N)
427 {
428 list_add_node_prev (spftree->tents, node, vertex);
429 break;
430 }
431 else if (v->d_N == vertex->d_N)
432 {
433 /* Tie break, add according to type */
434 while (v && v->d_N == vertex->d_N && v->type > vertex->type)
435 {
436 if (v->type > vertex->type)
437 {
438 break;
439 }
paul1eb8ef22005-04-07 07:30:20 +0000440 /* XXX: this seems dubious, node is the loop iterator */
441 node = listnextnode (node);
442 (node) ? (v = listgetdata (node)) : (v = NULL);
hassof390d2c2004-09-10 20:48:21 +0000443 }
444 list_add_node_prev (spftree->tents, node, vertex);
445 break;
446 }
447 else if (node->next == NULL)
448 {
449 list_add_node_next (spftree->tents, node, vertex);
450 break;
451 }
452 }
jardineb5d44e2003-12-23 08:09:43 +0000453 return vertex;
454}
455
hasso92365882005-01-18 13:53:33 +0000456static struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000457isis_spf_add_local (struct isis_spftree *spftree, enum vertextype vtype,
hassofac1f7c2005-09-26 18:26:26 +0000458 void *id, struct isis_adjacency *adj, u_int32_t cost,
hassof390d2c2004-09-10 20:48:21 +0000459 int family)
jardineb5d44e2003-12-23 08:09:43 +0000460{
461 struct isis_vertex *vertex;
jardineb5d44e2003-12-23 08:09:43 +0000462
hassof390d2c2004-09-10 20:48:21 +0000463 vertex = isis_find_vertex (spftree->tents, id, vtype);
464
465 if (vertex)
466 {
467 /* C.2.5 c) */
468 if (vertex->d_N == cost)
469 {
470 if (adj)
471 listnode_add (vertex->Adj_N, adj);
472 /* d) */
473 if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
474 remove_excess_adjs (vertex->Adj_N);
475 }
476 /* f) */
477 else if (vertex->d_N > cost)
478 {
479 listnode_delete (spftree->tents, vertex);
480 goto add2tent;
481 }
482 /* e) do nothing */
483 return vertex;
484 }
485
486add2tent:
jardineb5d44e2003-12-23 08:09:43 +0000487 return isis_spf_add2tent (spftree, vtype, id, adj, cost, 1, family);
488}
489
hasso92365882005-01-18 13:53:33 +0000490static void
hassof390d2c2004-09-10 20:48:21 +0000491process_N (struct isis_spftree *spftree, enum vertextype vtype, void *id,
492 u_int16_t dist, u_int16_t depth, struct isis_adjacency *adj,
493 int family)
jardineb5d44e2003-12-23 08:09:43 +0000494{
495 struct isis_vertex *vertex;
496#ifdef EXTREME_DEBUG
497 u_char buff[255];
498#endif
499
500 /* C.2.6 b) */
501 if (dist > MAX_PATH_METRIC)
502 return;
503 /* c) */
504 vertex = isis_find_vertex (spftree->paths, id, vtype);
hassof390d2c2004-09-10 20:48:21 +0000505 if (vertex)
506 {
jardineb5d44e2003-12-23 08:09:43 +0000507#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000508 zlog_debug ("ISIS-Spf: process_N %s %s dist %d already found from PATH",
509 vtype2string (vtype), vid2string (vertex, buff), dist);
jardineb5d44e2003-12-23 08:09:43 +0000510#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000511 assert (dist >= vertex->d_N);
512 return;
513 }
jardineb5d44e2003-12-23 08:09:43 +0000514
515 vertex = isis_find_vertex (spftree->tents, id, vtype);
hassof390d2c2004-09-10 20:48:21 +0000516 /* d) */
517 if (vertex)
518 {
519 /* 1) */
jardineb5d44e2003-12-23 08:09:43 +0000520#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000521 zlog_debug ("ISIS-Spf: process_N %s %s dist %d",
522 vtype2string (vtype), vid2string (vertex, buff), dist);
jardineb5d44e2003-12-23 08:09:43 +0000523#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000524 if (vertex->d_N == dist)
525 {
526 if (adj)
527 listnode_add (vertex->Adj_N, adj);
528 /* 2) */
529 if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
530 remove_excess_adjs (vertex->Adj_N);
531 /* 3) */
532 return;
533 }
534 else if (vertex->d_N < dist)
535 {
536 return;
537 /* 4) */
538 }
539 else
540 {
541 listnode_delete (spftree->tents, vertex);
542 }
jardineb5d44e2003-12-23 08:09:43 +0000543 }
hassof390d2c2004-09-10 20:48:21 +0000544
jardineb5d44e2003-12-23 08:09:43 +0000545 isis_spf_add2tent (spftree, vtype, id, adj, dist, depth, family);
546 return;
547}
548
549/*
550 * C.2.6 Step 1
551 */
hasso92365882005-01-18 13:53:33 +0000552static int
hassof390d2c2004-09-10 20:48:21 +0000553isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp,
hassofac1f7c2005-09-26 18:26:26 +0000554 uint32_t cost, uint16_t depth, int family)
jardineb5d44e2003-12-23 08:09:43 +0000555{
556 struct listnode *node, *fragnode = NULL;
557 u_int16_t dist;
558 struct is_neigh *is_neigh;
hasso82a84282005-09-26 18:15:36 +0000559 struct te_is_neigh *te_is_neigh;
jardineb5d44e2003-12-23 08:09:43 +0000560 struct ipv4_reachability *ipreach;
hasso82a84282005-09-26 18:15:36 +0000561 struct te_ipv4_reachability *te_ipv4_reach;
jardineb5d44e2003-12-23 08:09:43 +0000562 enum vertextype vtype;
563 struct prefix prefix;
564#ifdef HAVE_IPV6
565 struct ipv6_reachability *ip6reach;
566#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000567
jardineb5d44e2003-12-23 08:09:43 +0000568
569 if (!lsp->adj)
570 return ISIS_WARNING;
hassof390d2c2004-09-10 20:48:21 +0000571 if (lsp->tlv_data.nlpids == NULL || !speaks (lsp->tlv_data.nlpids, family))
jardineb5d44e2003-12-23 08:09:43 +0000572 return ISIS_OK;
573
hassof390d2c2004-09-10 20:48:21 +0000574lspfragloop:
575 if (lsp->lsp_header->seq_num == 0)
576 {
577 zlog_warn ("isis_spf_process_lsp(): lsp with 0 seq_num"
578 " - do not process");
579 return ISIS_WARNING;
580 }
jardineb5d44e2003-12-23 08:09:43 +0000581
hassof390d2c2004-09-10 20:48:21 +0000582 if (!ISIS_MASK_LSP_OL_BIT (lsp->lsp_header->lsp_bits))
583 {
584 if (lsp->tlv_data.is_neighs)
585 {
paul1eb8ef22005-04-07 07:30:20 +0000586 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh))
hassof390d2c2004-09-10 20:48:21 +0000587 {
hassof390d2c2004-09-10 20:48:21 +0000588 /* C.2.6 a) */
589 /* Two way connectivity */
590 if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
591 continue;
592 dist = cost + is_neigh->metrics.metric_default;
593 vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
594 : VTYPE_NONPSEUDO_IS;
595 process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist,
596 depth + 1, lsp->adj, family);
597 }
598 }
hasso82a84282005-09-26 18:15:36 +0000599 if (lsp->tlv_data.te_is_neighs)
600 {
601 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node,
602 te_is_neigh))
603 {
604 uint32_t metric;
605 if (!memcmp (te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
606 continue;
607 memcpy (&metric, te_is_neigh->te_metric, 3);
608 dist = cost + ntohl (metric << 8);
609 vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS
610 : VTYPE_NONPSEUDO_TE_IS;
611 process_N (spftree, vtype, (void *) te_is_neigh->neigh_id, dist,
612 depth + 1, lsp->adj, family);
613 }
614 }
hassof390d2c2004-09-10 20:48:21 +0000615 if (family == AF_INET && lsp->tlv_data.ipv4_int_reachs)
616 {
617 prefix.family = AF_INET;
paul1eb8ef22005-04-07 07:30:20 +0000618 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_int_reachs,
619 node, ipreach))
hassof390d2c2004-09-10 20:48:21 +0000620 {
hassof390d2c2004-09-10 20:48:21 +0000621 dist = cost + ipreach->metrics.metric_default;
622 vtype = VTYPE_IPREACH_INTERNAL;
623 prefix.u.prefix4 = ipreach->prefix;
624 prefix.prefixlen = ip_masklen (ipreach->mask);
625 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
626 lsp->adj, family);
627 }
628 }
629
630 if (family == AF_INET && lsp->tlv_data.ipv4_ext_reachs)
631 {
632 prefix.family = AF_INET;
paul1eb8ef22005-04-07 07:30:20 +0000633 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_ext_reachs,
634 node, ipreach))
hassof390d2c2004-09-10 20:48:21 +0000635 {
hassof390d2c2004-09-10 20:48:21 +0000636 dist = cost + ipreach->metrics.metric_default;
637 vtype = VTYPE_IPREACH_EXTERNAL;
638 prefix.u.prefix4 = ipreach->prefix;
639 prefix.prefixlen = ip_masklen (ipreach->mask);
640 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
641 lsp->adj, family);
642 }
643 }
hasso82a84282005-09-26 18:15:36 +0000644 if (family == AF_INET && lsp->tlv_data.te_ipv4_reachs)
645 {
646 prefix.family = AF_INET;
647 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_ipv4_reachs,
648 node, te_ipv4_reach))
649 {
650 dist = cost + ntohl (te_ipv4_reach->te_metric);
651 vtype = VTYPE_IPREACH_TE;
652 prefix.u.prefix4 = newprefix2inaddr (&te_ipv4_reach->prefix_start,
653 te_ipv4_reach->control);
654 prefix.prefixlen = (te_ipv4_reach->control & 0x3F);
655 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
656 lsp->adj, family);
657 }
658 }
jardineb5d44e2003-12-23 08:09:43 +0000659#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000660 if (family == AF_INET6 && lsp->tlv_data.ipv6_reachs)
661 {
662 prefix.family = AF_INET6;
paul1eb8ef22005-04-07 07:30:20 +0000663 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv6_reachs,
664 node, ip6reach))
hassof390d2c2004-09-10 20:48:21 +0000665 {
hassof390d2c2004-09-10 20:48:21 +0000666 dist = cost + ip6reach->metric;
667 vtype = (ip6reach->control_info & CTRL_INFO_DISTRIBUTION) ?
668 VTYPE_IP6REACH_EXTERNAL : VTYPE_IP6REACH_INTERNAL;
669 prefix.prefixlen = ip6reach->prefix_len;
670 memcpy (&prefix.u.prefix6.s6_addr, ip6reach->prefix,
671 PSIZE (ip6reach->prefix_len));
672 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
673 lsp->adj, family);
674 }
675 }
jardineb5d44e2003-12-23 08:09:43 +0000676#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000677 }
678
jardineb5d44e2003-12-23 08:09:43 +0000679 if (fragnode == NULL)
680 fragnode = listhead (lsp->lspu.frags);
hassof390d2c2004-09-10 20:48:21 +0000681 else
paul1eb8ef22005-04-07 07:30:20 +0000682 fragnode = listnextnode (fragnode);
jardineb5d44e2003-12-23 08:09:43 +0000683
hassof390d2c2004-09-10 20:48:21 +0000684 if (fragnode)
685 {
paul1eb8ef22005-04-07 07:30:20 +0000686 lsp = listgetdata (fragnode);
hassof390d2c2004-09-10 20:48:21 +0000687 goto lspfragloop;
688 }
689
jardineb5d44e2003-12-23 08:09:43 +0000690 return ISIS_OK;
691}
692
hasso92365882005-01-18 13:53:33 +0000693static int
hassof390d2c2004-09-10 20:48:21 +0000694isis_spf_process_pseudo_lsp (struct isis_spftree *spftree,
695 struct isis_lsp *lsp, uint16_t cost,
696 uint16_t depth, int family)
jardineb5d44e2003-12-23 08:09:43 +0000697{
hasso3fdb2dd2005-09-28 18:45:54 +0000698 struct listnode *node, *fragnode = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000699 struct is_neigh *is_neigh;
hasso82a84282005-09-26 18:15:36 +0000700 struct te_is_neigh *te_is_neigh;
jardineb5d44e2003-12-23 08:09:43 +0000701 enum vertextype vtype;
hassof390d2c2004-09-10 20:48:21 +0000702
703pseudofragloop:
704
705 if (lsp->lsp_header->seq_num == 0)
706 {
707 zlog_warn ("isis_spf_process_pseudo_lsp(): lsp with 0 seq_num"
708 " - do not process");
709 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +0000710 }
hassof390d2c2004-09-10 20:48:21 +0000711
hasso82a84282005-09-26 18:15:36 +0000712 if (lsp->tlv_data.is_neighs)
hasso3fdb2dd2005-09-28 18:45:54 +0000713 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh))
hasso82a84282005-09-26 18:15:36 +0000714 {
715 vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
716 : VTYPE_NONPSEUDO_IS;
717 /* Two way connectivity */
718 if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
719 continue;
720 if (isis_find_vertex
721 (spftree->tents, (void *) is_neigh->neigh_id, vtype) == NULL
722 && isis_find_vertex (spftree->paths, (void *) is_neigh->neigh_id,
hassof390d2c2004-09-10 20:48:21 +0000723 vtype) == NULL)
hasso82a84282005-09-26 18:15:36 +0000724 {
725 /* C.2.5 i) */
726 isis_spf_add2tent (spftree, vtype, is_neigh->neigh_id, lsp->adj,
hassof390d2c2004-09-10 20:48:21 +0000727 cost, depth, family);
hasso82a84282005-09-26 18:15:36 +0000728 }
729 }
730 if (lsp->tlv_data.te_is_neighs)
hasso3fdb2dd2005-09-28 18:45:54 +0000731 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node, te_is_neigh))
hasso82a84282005-09-26 18:15:36 +0000732 {
733 vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS
734 : VTYPE_NONPSEUDO_TE_IS;
735 /* Two way connectivity */
736 if (!memcmp (te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
737 continue;
738 if (isis_find_vertex
739 (spftree->tents, (void *) te_is_neigh->neigh_id, vtype) == NULL
740 && isis_find_vertex (spftree->paths, (void *) te_is_neigh->neigh_id,
741 vtype) == NULL)
742 {
743 /* C.2.5 i) */
744 isis_spf_add2tent (spftree, vtype, te_is_neigh->neigh_id, lsp->adj,
745 cost, depth, family);
746 }
747 }
hassof390d2c2004-09-10 20:48:21 +0000748
jardineb5d44e2003-12-23 08:09:43 +0000749 if (fragnode == NULL)
750 fragnode = listhead (lsp->lspu.frags);
hassof390d2c2004-09-10 20:48:21 +0000751 else
paul1eb8ef22005-04-07 07:30:20 +0000752 fragnode = listnextnode (fragnode);
jardineb5d44e2003-12-23 08:09:43 +0000753
hassof390d2c2004-09-10 20:48:21 +0000754 if (fragnode)
755 {
paul1eb8ef22005-04-07 07:30:20 +0000756 lsp = listgetdata (fragnode);
hassof390d2c2004-09-10 20:48:21 +0000757 goto pseudofragloop;
758 }
jardineb5d44e2003-12-23 08:09:43 +0000759
jardineb5d44e2003-12-23 08:09:43 +0000760 return ISIS_OK;
761}
hassof390d2c2004-09-10 20:48:21 +0000762
hasso92365882005-01-18 13:53:33 +0000763static int
hassof390d2c2004-09-10 20:48:21 +0000764isis_spf_preload_tent (struct isis_spftree *spftree,
765 struct isis_area *area, int level, int family)
jardineb5d44e2003-12-23 08:09:43 +0000766{
767 struct isis_vertex *vertex;
768 struct isis_circuit *circuit;
hasso3fdb2dd2005-09-28 18:45:54 +0000769 struct listnode *cnode, *anode, *ipnode;
jardineb5d44e2003-12-23 08:09:43 +0000770 struct isis_adjacency *adj;
771 struct isis_lsp *lsp;
772 struct list *adj_list;
773 struct list *adjdb;
774 struct prefix_ipv4 *ipv4;
775 struct prefix prefix;
776 int retval = ISIS_OK;
777 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
778#ifdef HAVE_IPV6
779 struct prefix_ipv6 *ipv6;
780#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000781
hasso3fdb2dd2005-09-28 18:45:54 +0000782 for (ALL_LIST_ELEMENTS_RO (area->circuit_list, cnode, circuit))
hassof390d2c2004-09-10 20:48:21 +0000783 {
hassof390d2c2004-09-10 20:48:21 +0000784 if (circuit->state != C_STATE_UP)
jardineb5d44e2003-12-23 08:09:43 +0000785 continue;
hassof390d2c2004-09-10 20:48:21 +0000786 if (!(circuit->circuit_is_type & level))
787 continue;
788 if (family == AF_INET && !circuit->ip_router)
789 continue;
790#ifdef HAVE_IPV6
791 if (family == AF_INET6 && !circuit->ipv6_router)
792 continue;
793#endif /* HAVE_IPV6 */
794 /*
795 * Add IP(v6) addresses of this circuit
jardineb5d44e2003-12-23 08:09:43 +0000796 */
hassof390d2c2004-09-10 20:48:21 +0000797 if (family == AF_INET)
798 {
799 prefix.family = AF_INET;
hasso3fdb2dd2005-09-28 18:45:54 +0000800 for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, ipnode, ipv4))
hassof390d2c2004-09-10 20:48:21 +0000801 {
hassof390d2c2004-09-10 20:48:21 +0000802 prefix.u.prefix4 = ipv4->prefix;
803 prefix.prefixlen = ipv4->prefixlen;
804 isis_spf_add_local (spftree, VTYPE_IPREACH_INTERNAL, &prefix,
805 NULL, 0, family);
806 }
807 }
808#ifdef HAVE_IPV6
809 if (family == AF_INET6)
810 {
811 prefix.family = AF_INET6;
hasso3fdb2dd2005-09-28 18:45:54 +0000812 for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, ipnode, ipv6))
hassof390d2c2004-09-10 20:48:21 +0000813 {
hassof390d2c2004-09-10 20:48:21 +0000814 prefix.prefixlen = ipv6->prefixlen;
815 prefix.u.prefix6 = ipv6->prefix;
816 isis_spf_add_local (spftree, VTYPE_IP6REACH_INTERNAL,
817 &prefix, NULL, 0, family);
818 }
819 }
820#endif /* HAVE_IPV6 */
821 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
822 {
823 /*
824 * Add the adjacencies
825 */
826 adj_list = list_new ();
827 adjdb = circuit->u.bc.adjdb[level - 1];
828 isis_adj_build_up_list (adjdb, adj_list);
829 if (listcount (adj_list) == 0)
830 {
831 list_delete (adj_list);
hassoc89c05d2005-09-04 21:36:36 +0000832 if (isis->debugs & DEBUG_SPF_EVENTS)
833 zlog_debug ("ISIS-Spf: no L%d adjacencies on circuit %s",
834 level, circuit->interface->name);
hassof390d2c2004-09-10 20:48:21 +0000835 continue;
836 }
837 anode = listhead (adj_list);
838 while (anode)
839 {
paul1eb8ef22005-04-07 07:30:20 +0000840 adj = listgetdata (anode);
hassof390d2c2004-09-10 20:48:21 +0000841 if (!speaks (&adj->nlpids, family))
842 {
paul1eb8ef22005-04-07 07:30:20 +0000843 anode = listnextnode (anode);
hassof390d2c2004-09-10 20:48:21 +0000844 continue;
845 }
846 switch (adj->sys_type)
847 {
848 case ISIS_SYSTYPE_ES:
849 isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
hasso82a84282005-09-26 18:15:36 +0000850 circuit->te_metric[level - 1], family);
hassof390d2c2004-09-10 20:48:21 +0000851 break;
852 case ISIS_SYSTYPE_IS:
853 case ISIS_SYSTYPE_L1_IS:
854 case ISIS_SYSTYPE_L2_IS:
855 vertex =
856 isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS,
857 adj->sysid, adj,
hasso82a84282005-09-26 18:15:36 +0000858 circuit->te_metric[level - 1], family);
hassof390d2c2004-09-10 20:48:21 +0000859 memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN);
860 LSP_PSEUDO_ID (lsp_id) = 0;
861 LSP_FRAGMENT (lsp_id) = 0;
862 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
863 if (!lsp)
864 zlog_warn ("No lsp found for IS adjacency");
865 /* else {
866 isis_spf_process_lsp (spftree, lsp, vertex->d_N, 1, family);
867 } */
868 break;
869 case ISIS_SYSTYPE_UNKNOWN:
870 default:
871 zlog_warn ("isis_spf_preload_tent unknow adj type");
872 }
paul1eb8ef22005-04-07 07:30:20 +0000873 anode = listnextnode (anode);
hassof390d2c2004-09-10 20:48:21 +0000874 }
875 list_delete (adj_list);
876 /*
877 * Add the pseudonode
878 */
879 if (level == 1)
880 memcpy (lsp_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
881 else
882 memcpy (lsp_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
883 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
884 adj = isis_adj_lookup (lsp_id, adjdb);
885 /* if no adj, we are the dis or error */
886 if (!adj && !circuit->u.bc.is_dr[level - 1])
887 {
888 zlog_warn ("ISIS-Spf: No adjacency found for DR");
889 }
890 if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0)
891 {
892 zlog_warn ("ISIS-Spf: No lsp found for DR");
893 }
894 else
895 {
hasso82a84282005-09-26 18:15:36 +0000896 isis_spf_process_pseudo_lsp (spftree, lsp,
897 circuit->te_metric[level - 1], 0, family);
hassof390d2c2004-09-10 20:48:21 +0000898
899 }
900 }
901 else if (circuit->circ_type == CIRCUIT_T_P2P)
902 {
903 adj = circuit->u.p2p.neighbor;
904 if (!adj)
905 continue;
906 switch (adj->sys_type)
907 {
908 case ISIS_SYSTYPE_ES:
909 isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
hasso82a84282005-09-26 18:15:36 +0000910 circuit->te_metric[level - 1], family);
hassof390d2c2004-09-10 20:48:21 +0000911 break;
912 case ISIS_SYSTYPE_IS:
913 case ISIS_SYSTYPE_L1_IS:
914 case ISIS_SYSTYPE_L2_IS:
915 if (speaks (&adj->nlpids, family))
916 isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS, adj->sysid,
hasso82a84282005-09-26 18:15:36 +0000917 adj, circuit->te_metric[level - 1],
hassof390d2c2004-09-10 20:48:21 +0000918 family);
919 break;
920 case ISIS_SYSTYPE_UNKNOWN:
921 default:
922 zlog_warn ("isis_spf_preload_tent unknow adj type");
923 break;
924 }
925 }
jardineb5d44e2003-12-23 08:09:43 +0000926 else
hassof390d2c2004-09-10 20:48:21 +0000927 {
928 zlog_warn ("isis_spf_preload_tent unsupported media");
929 retval = ISIS_WARNING;
930 }
931
jardineb5d44e2003-12-23 08:09:43 +0000932 }
jardineb5d44e2003-12-23 08:09:43 +0000933
934 return retval;
935}
936
937/*
938 * The parent(s) for vertex is set when added to TENT list
939 * now we just put the child pointer(s) in place
940 */
hasso92365882005-01-18 13:53:33 +0000941static void
jardineb5d44e2003-12-23 08:09:43 +0000942add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex,
hassofac1f7c2005-09-26 18:26:26 +0000943 struct isis_area *area, int level)
jardineb5d44e2003-12-23 08:09:43 +0000944{
jardineb5d44e2003-12-23 08:09:43 +0000945#ifdef EXTREME_DEBUG
946 u_char buff[BUFSIZ];
947#endif /* EXTREME_DEBUG */
948 listnode_add (spftree->paths, vertex);
949
hassof390d2c2004-09-10 20:48:21 +0000950#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000951 zlog_debug ("ISIS-Spf: added %s %s depth %d dist %d to PATHS",
952 vtype2string (vertex->type), vid2string (vertex, buff),
953 vertex->depth, vertex->d_N);
hassof390d2c2004-09-10 20:48:21 +0000954#endif /* EXTREME_DEBUG */
955 if (vertex->type > VTYPE_ES)
956 {
957 if (listcount (vertex->Adj_N) > 0)
hassofac1f7c2005-09-26 18:26:26 +0000958 isis_route_create ((struct prefix *) &vertex->N.prefix, vertex->d_N,
959 vertex->depth, vertex->Adj_N, area, level);
hassof390d2c2004-09-10 20:48:21 +0000960 else if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000961 zlog_debug ("ISIS-Spf: no adjacencies do not install route");
hassof390d2c2004-09-10 20:48:21 +0000962 }
963
jardineb5d44e2003-12-23 08:09:43 +0000964 return;
965}
966
hasso92365882005-01-18 13:53:33 +0000967static void
jardineb5d44e2003-12-23 08:09:43 +0000968init_spt (struct isis_spftree *spftree)
969{
hassof7c43dc2004-09-26 16:24:14 +0000970 spftree->tents->del = spftree->paths->del = (void (*)(void *)) isis_vertex_del;
jardineb5d44e2003-12-23 08:09:43 +0000971 list_delete_all_node (spftree->tents);
972 list_delete_all_node (spftree->paths);
973 spftree->tents->del = spftree->paths->del = NULL;
hassof390d2c2004-09-10 20:48:21 +0000974
jardineb5d44e2003-12-23 08:09:43 +0000975 return;
976}
977
hasso92365882005-01-18 13:53:33 +0000978static int
jardineb5d44e2003-12-23 08:09:43 +0000979isis_run_spf (struct isis_area *area, int level, int family)
980{
981 int retval = ISIS_OK;
982 struct listnode *node;
983 struct isis_vertex *vertex;
hassof390d2c2004-09-10 20:48:21 +0000984 struct isis_spftree *spftree = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000985 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
986 struct isis_lsp *lsp;
hassofac1f7c2005-09-26 18:26:26 +0000987 struct route_table *table = NULL;
988 struct route_node *rode;
989 struct isis_route_info *rinfo;
hassof390d2c2004-09-10 20:48:21 +0000990
jardineb5d44e2003-12-23 08:09:43 +0000991 if (family == AF_INET)
992 spftree = area->spftree[level - 1];
993#ifdef HAVE_IPV6
994 else if (family == AF_INET6)
995 spftree = area->spftree6[level - 1];
996#endif
hassof390d2c2004-09-10 20:48:21 +0000997
jardineb5d44e2003-12-23 08:09:43 +0000998 assert (spftree);
999
hassofac1f7c2005-09-26 18:26:26 +00001000 /* Make all routes in current route table inactive. */
1001 if (family == AF_INET)
1002 table = area->route_table[level - 1];
1003 else if (family == AF_INET6)
1004 table = area->route_table6[level - 1];
1005
1006 for (rode = route_top (table); rode; rode = route_next (rode))
1007 {
1008 if (rode->info == NULL)
1009 continue;
1010 rinfo = rode->info;
1011
1012 UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
1013 }
1014
jardineb5d44e2003-12-23 08:09:43 +00001015 /*
1016 * C.2.5 Step 0
1017 */
1018 init_spt (spftree);
1019 /* a) */
1020 isis_spf_add_self (spftree, area, level);
1021 /* b) */
1022 retval = isis_spf_preload_tent (spftree, area, level, family);
hassof390d2c2004-09-10 20:48:21 +00001023
jardineb5d44e2003-12-23 08:09:43 +00001024 /*
1025 * C.2.7 Step 2
1026 */
hassof390d2c2004-09-10 20:48:21 +00001027 if (listcount (spftree->tents) == 0)
1028 {
1029 zlog_warn ("ISIS-Spf: TENT is empty");
1030 spftree->lastrun = time (NULL);
1031 return retval;
jardineb5d44e2003-12-23 08:09:43 +00001032 }
hassof390d2c2004-09-10 20:48:21 +00001033
1034 while (listcount (spftree->tents) > 0)
1035 {
1036 node = listhead (spftree->tents);
paul1eb8ef22005-04-07 07:30:20 +00001037 vertex = listgetdata (node);
hassof390d2c2004-09-10 20:48:21 +00001038 /* Remove from tent list */
1039 list_delete_node (spftree->tents, node);
1040 if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type))
1041 continue;
hassofac1f7c2005-09-26 18:26:26 +00001042 add_to_paths (spftree, vertex, area, level);
hassof390d2c2004-09-10 20:48:21 +00001043 if (vertex->type == VTYPE_PSEUDO_IS ||
1044 vertex->type == VTYPE_NONPSEUDO_IS)
1045 {
1046 memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
1047 LSP_FRAGMENT (lsp_id) = 0;
1048 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
1049 if (lsp)
1050 {
1051 if (LSP_PSEUDO_ID (lsp_id))
1052 {
1053 isis_spf_process_pseudo_lsp (spftree, lsp, vertex->d_N,
1054 vertex->depth, family);
1055
1056 }
1057 else
1058 {
1059 isis_spf_process_lsp (spftree, lsp, vertex->d_N,
1060 vertex->depth, family);
1061 }
1062 }
1063 else
1064 {
1065 zlog_warn ("ISIS-Spf: No LSP found for %s",
1066 rawlspid_print (lsp_id));
1067 }
1068 }
1069 }
1070
jardineb5d44e2003-12-23 08:09:43 +00001071 thread_add_event (master, isis_route_validate, area, 0);
1072 spftree->lastrun = time (NULL);
1073 spftree->pending = 0;
hassof390d2c2004-09-10 20:48:21 +00001074
jardineb5d44e2003-12-23 08:09:43 +00001075 return retval;
1076}
1077
1078int
1079isis_run_spf_l1 (struct thread *thread)
1080{
1081 struct isis_area *area;
1082 int retval = ISIS_OK;
1083
hassof390d2c2004-09-10 20:48:21 +00001084 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001085 assert (area);
1086
hasso12a5cae2004-09-19 19:39:26 +00001087 area->spftree[0]->t_spf = NULL;
1088
hassof390d2c2004-09-10 20:48:21 +00001089 if (!(area->is_type & IS_LEVEL_1))
1090 {
1091 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001092 zlog_warn ("ISIS-SPF (%s) area does not share level",
1093 area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001094 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001095 }
jardineb5d44e2003-12-23 08:09:43 +00001096
hassof390d2c2004-09-10 20:48:21 +00001097 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001098 zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001099
jardineb5d44e2003-12-23 08:09:43 +00001100 if (area->ip_circuits)
1101 retval = isis_run_spf (area, 1, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001102
1103 THREAD_TIMER_ON (master, area->spftree[0]->t_spf, isis_run_spf_l1, area,
1104 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1105
jardineb5d44e2003-12-23 08:09:43 +00001106 return retval;
1107}
1108
1109int
1110isis_run_spf_l2 (struct thread *thread)
1111{
1112 struct isis_area *area;
1113 int retval = ISIS_OK;
1114
hassof390d2c2004-09-10 20:48:21 +00001115 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001116 assert (area);
hassof390d2c2004-09-10 20:48:21 +00001117
hasso12a5cae2004-09-19 19:39:26 +00001118 area->spftree[1]->t_spf = NULL;
1119
hassof390d2c2004-09-10 20:48:21 +00001120 if (!(area->is_type & IS_LEVEL_2))
1121 {
1122 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001123 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001124 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001125 }
hassof390d2c2004-09-10 20:48:21 +00001126
1127 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001128 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag);
jardineb5d44e2003-12-23 08:09:43 +00001129
1130 if (area->ip_circuits)
1131 retval = isis_run_spf (area, 2, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001132
1133 THREAD_TIMER_ON (master, area->spftree[1]->t_spf, isis_run_spf_l2, area,
1134 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
jardineb5d44e2003-12-23 08:09:43 +00001135
1136 return retval;
1137}
1138
hassof390d2c2004-09-10 20:48:21 +00001139int
jardineb5d44e2003-12-23 08:09:43 +00001140isis_spf_schedule (struct isis_area *area, int level)
1141{
1142 int retval = ISIS_OK;
1143 struct isis_spftree *spftree = area->spftree[level - 1];
1144 time_t diff, now = time (NULL);
1145
1146 if (spftree->pending)
1147 return retval;
1148
hassof390d2c2004-09-10 20:48:21 +00001149 diff = now - spftree->lastrun;
jardineb5d44e2003-12-23 08:09:43 +00001150
1151 /* FIXME: let's wait a minute before doing the SPF */
hassof390d2c2004-09-10 20:48:21 +00001152 if (now - isis->uptime < 60 || isis->uptime == 0)
1153 {
1154 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001155 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area, 60);
hassof390d2c2004-09-10 20:48:21 +00001156 else
hasso12a5cae2004-09-19 19:39:26 +00001157 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area, 60);
jardineb5d44e2003-12-23 08:09:43 +00001158
hassof390d2c2004-09-10 20:48:21 +00001159 spftree->pending = 1;
1160 return retval;
1161 }
hasso12a5cae2004-09-19 19:39:26 +00001162
1163 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001164
hassof390d2c2004-09-10 20:48:21 +00001165 if (diff < MINIMUM_SPF_INTERVAL)
1166 {
1167 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001168 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
1169 MINIMUM_SPF_INTERVAL - diff);
hassof390d2c2004-09-10 20:48:21 +00001170 else
hasso12a5cae2004-09-19 19:39:26 +00001171 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
1172 MINIMUM_SPF_INTERVAL - diff);
jardineb5d44e2003-12-23 08:09:43 +00001173
hassof390d2c2004-09-10 20:48:21 +00001174 spftree->pending = 1;
1175 }
1176 else
1177 {
1178 spftree->pending = 0;
1179 retval = isis_run_spf (area, level, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001180 if (level == 1)
1181 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
1182 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1183 else
1184 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
1185 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
hassof390d2c2004-09-10 20:48:21 +00001186 }
jardineb5d44e2003-12-23 08:09:43 +00001187
1188 return retval;
1189}
1190
1191#ifdef HAVE_IPV6
hasso92365882005-01-18 13:53:33 +00001192static int
hasso12a5cae2004-09-19 19:39:26 +00001193isis_run_spf6_l1 (struct thread *thread)
1194{
1195 struct isis_area *area;
1196 int retval = ISIS_OK;
1197
1198 area = THREAD_ARG (thread);
1199 assert (area);
1200
1201 area->spftree6[0]->t_spf = NULL;
1202
1203 if (!(area->is_type & IS_LEVEL_1))
1204 {
1205 if (isis->debugs & DEBUG_SPF_EVENTS)
1206 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
1207 return ISIS_WARNING;
1208 }
1209
1210 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001211 zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001212
1213 if (area->ipv6_circuits)
1214 retval = isis_run_spf (area, 1, AF_INET6);
1215
1216 THREAD_TIMER_ON (master, area->spftree6[0]->t_spf, isis_run_spf6_l1, area,
1217 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1218
1219 return retval;
1220}
1221
hasso92365882005-01-18 13:53:33 +00001222static int
hasso12a5cae2004-09-19 19:39:26 +00001223isis_run_spf6_l2 (struct thread *thread)
1224{
1225 struct isis_area *area;
1226 int retval = ISIS_OK;
1227
1228 area = THREAD_ARG (thread);
1229 assert (area);
1230
1231 area->spftree6[1]->t_spf = NULL;
1232
1233 if (!(area->is_type & IS_LEVEL_2))
1234 {
1235 if (isis->debugs & DEBUG_SPF_EVENTS)
1236 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
1237 return ISIS_WARNING;
1238 }
1239
1240 if (isis->debugs & DEBUG_SPF_EVENTS)
hassofac1f7c2005-09-26 18:26:26 +00001241 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF.", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001242
1243 if (area->ipv6_circuits)
1244 retval = isis_run_spf (area, 2, AF_INET6);
1245
1246 THREAD_TIMER_ON (master, area->spftree6[1]->t_spf, isis_run_spf6_l2, area,
1247 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1248
1249 return retval;
1250}
1251
1252int
jardineb5d44e2003-12-23 08:09:43 +00001253isis_spf_schedule6 (struct isis_area *area, int level)
1254{
1255 int retval = ISIS_OK;
1256 struct isis_spftree *spftree = area->spftree6[level - 1];
1257 time_t diff, now = time (NULL);
1258
1259 if (spftree->pending)
1260 return retval;
1261
hassof390d2c2004-09-10 20:48:21 +00001262 diff = now - spftree->lastrun;
1263
jardineb5d44e2003-12-23 08:09:43 +00001264 /* FIXME: let's wait a minute before doing the SPF */
hassof390d2c2004-09-10 20:48:21 +00001265 if (now - isis->uptime < 60 || isis->uptime == 0)
1266 {
1267 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001268 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area, 60);
hassof390d2c2004-09-10 20:48:21 +00001269 else
hasso12a5cae2004-09-19 19:39:26 +00001270 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area, 60);
jardineb5d44e2003-12-23 08:09:43 +00001271
hassof390d2c2004-09-10 20:48:21 +00001272 spftree->pending = 1;
1273 return retval;
1274 }
hasso12a5cae2004-09-19 19:39:26 +00001275
1276 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001277
hassof390d2c2004-09-10 20:48:21 +00001278 if (diff < MINIMUM_SPF_INTERVAL)
1279 {
1280 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001281 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
1282 MINIMUM_SPF_INTERVAL - diff);
hassof390d2c2004-09-10 20:48:21 +00001283 else
hasso12a5cae2004-09-19 19:39:26 +00001284 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
1285 MINIMUM_SPF_INTERVAL - diff);
jardineb5d44e2003-12-23 08:09:43 +00001286
hassof390d2c2004-09-10 20:48:21 +00001287 spftree->pending = 1;
1288 }
1289 else
1290 {
1291 spftree->pending = 0;
1292 retval = isis_run_spf (area, level, AF_INET6);
hasso12a5cae2004-09-19 19:39:26 +00001293
1294 if (level == 1)
1295 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
1296 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1297 else
1298 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
1299 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
hassof390d2c2004-09-10 20:48:21 +00001300 }
jardineb5d44e2003-12-23 08:09:43 +00001301
1302 return retval;
1303}
jardineb5d44e2003-12-23 08:09:43 +00001304#endif
1305
hasso92365882005-01-18 13:53:33 +00001306static void
jardineb5d44e2003-12-23 08:09:43 +00001307isis_print_paths (struct vty *vty, struct list *paths)
1308{
paul1eb8ef22005-04-07 07:30:20 +00001309 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +00001310 struct isis_vertex *vertex;
1311 struct isis_dynhn *dyn, *nh_dyn = NULL;
1312 struct isis_adjacency *adj;
hasso92365882005-01-18 13:53:33 +00001313#if 0
jardineb5d44e2003-12-23 08:09:43 +00001314 u_char buff[255];
hasso92365882005-01-18 13:53:33 +00001315#endif /* 0 */
jardineb5d44e2003-12-23 08:09:43 +00001316
1317 vty_out (vty, "System Id Metric Next-Hop"
hassof390d2c2004-09-10 20:48:21 +00001318 " Interface SNPA%s", VTY_NEWLINE);
paul1eb8ef22005-04-07 07:30:20 +00001319
1320 for (ALL_LIST_ELEMENTS_RO (paths, node, vertex))
hassof390d2c2004-09-10 20:48:21 +00001321 {
hassof390d2c2004-09-10 20:48:21 +00001322 if (vertex->type != VTYPE_NONPSEUDO_IS)
1323 continue;
1324 if (memcmp (vertex->N.id, isis->sysid, ISIS_SYS_ID_LEN) == 0)
1325 {
hassoc3d26c72005-03-07 08:54:41 +00001326 vty_out (vty, "%s --%s", host.name?host.name:"",
1327 VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +00001328 }
1329 else
1330 {
1331 dyn = dynhn_find_by_id ((u_char *) vertex->N.id);
paul1eb8ef22005-04-07 07:30:20 +00001332 adj = listgetdata (listhead (vertex->Adj_N));
hassof390d2c2004-09-10 20:48:21 +00001333 if (adj)
1334 {
1335 nh_dyn = dynhn_find_by_id (adj->sysid);
1336 vty_out (vty, "%-20s %-10u %-20s %-11s %-5s%s",
1337 (dyn != NULL) ? dyn->name.name :
1338 (u_char *) rawlspid_print ((u_char *) vertex->N.id),
1339 vertex->d_N, (nh_dyn != NULL) ? nh_dyn->name.name :
1340 (u_char *) rawlspid_print (adj->sysid),
1341 adj->circuit->interface->name,
1342 snpa_print (adj->snpa), VTY_NEWLINE);
1343 }
1344 else
1345 {
1346 vty_out (vty, "%s %u %s", dyn ? dyn->name.name :
1347 (u_char *) rawlspid_print (vertex->N.id),
1348 vertex->d_N, VTY_NEWLINE);
1349 }
1350 }
jardineb5d44e2003-12-23 08:09:43 +00001351#if 0
hassof390d2c2004-09-10 20:48:21 +00001352 vty_out (vty, "%s %s %u %s", vtype2string (vertex->type),
1353 vid2string (vertex, buff), vertex->d_N, VTY_NEWLINE);
jardineb5d44e2003-12-23 08:09:43 +00001354#endif
hassof390d2c2004-09-10 20:48:21 +00001355 }
jardineb5d44e2003-12-23 08:09:43 +00001356}
1357
1358DEFUN (show_isis_topology,
1359 show_isis_topology_cmd,
1360 "show isis topology",
1361 SHOW_STR
1362 "IS-IS information\n"
1363 "IS-IS paths to Intermediate Systems\n")
1364{
1365 struct listnode *node;
1366 struct isis_area *area;
1367 int level;
hassof390d2c2004-09-10 20:48:21 +00001368
jardineb5d44e2003-12-23 08:09:43 +00001369 if (!isis->area_list || isis->area_list->count == 0)
1370 return CMD_SUCCESS;
1371
paul1eb8ef22005-04-07 07:30:20 +00001372 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001373 {
hassof390d2c2004-09-10 20:48:21 +00001374 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1375 VTY_NEWLINE);
1376
1377 for (level = 0; level < ISIS_LEVELS; level++)
1378 {
1379 if (area->ip_circuits > 0 && area->spftree[level]
1380 && area->spftree[level]->paths->count > 0)
1381 {
1382 vty_out (vty, "IS-IS paths to level-%d routers that speak IP%s",
1383 level + 1, VTY_NEWLINE);
1384 isis_print_paths (vty, area->spftree[level]->paths);
1385 }
jardineb5d44e2003-12-23 08:09:43 +00001386#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001387 if (area->ipv6_circuits > 0 && area->spftree6[level]
1388 && area->spftree6[level]->paths->count > 0)
1389 {
1390 vty_out (vty,
1391 "IS-IS paths to level-%d routers that speak IPv6%s",
1392 level + 1, VTY_NEWLINE);
1393 isis_print_paths (vty, area->spftree6[level]->paths);
1394 }
jardineb5d44e2003-12-23 08:09:43 +00001395#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +00001396 }
jardineb5d44e2003-12-23 08:09:43 +00001397 }
jardineb5d44e2003-12-23 08:09:43 +00001398
1399 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001400}
jardineb5d44e2003-12-23 08:09:43 +00001401
1402DEFUN (show_isis_topology_l1,
1403 show_isis_topology_l1_cmd,
1404 "show isis topology level-1",
1405 SHOW_STR
1406 "IS-IS information\n"
1407 "IS-IS paths to Intermediate Systems\n"
1408 "Paths to all level-1 routers in the area\n")
1409{
1410 struct listnode *node;
1411 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001412
jardineb5d44e2003-12-23 08:09:43 +00001413 if (!isis->area_list || isis->area_list->count == 0)
1414 return CMD_SUCCESS;
1415
paul1eb8ef22005-04-07 07:30:20 +00001416 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001417 {
hassof390d2c2004-09-10 20:48:21 +00001418 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1419 VTY_NEWLINE);
1420
1421 if (area->ip_circuits > 0 && area->spftree[0]
1422 && area->spftree[0]->paths->count > 0)
1423 {
1424 vty_out (vty, "IS-IS paths to level-1 routers that speak IP%s",
1425 VTY_NEWLINE);
1426 isis_print_paths (vty, area->spftree[0]->paths);
1427 }
jardineb5d44e2003-12-23 08:09:43 +00001428#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001429 if (area->ipv6_circuits > 0 && area->spftree6[0]
1430 && area->spftree6[0]->paths->count > 0)
1431 {
1432 vty_out (vty, "IS-IS paths to level-1 routers that speak IPv6%s",
1433 VTY_NEWLINE);
1434 isis_print_paths (vty, area->spftree6[0]->paths);
1435 }
jardineb5d44e2003-12-23 08:09:43 +00001436#endif /* HAVE_IPV6 */
1437 }
1438
jardineb5d44e2003-12-23 08:09:43 +00001439 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001440}
jardineb5d44e2003-12-23 08:09:43 +00001441
1442DEFUN (show_isis_topology_l2,
1443 show_isis_topology_l2_cmd,
1444 "show isis topology level-2",
1445 SHOW_STR
1446 "IS-IS information\n"
1447 "IS-IS paths to Intermediate Systems\n"
1448 "Paths to all level-2 routers in the domain\n")
1449{
1450 struct listnode *node;
1451 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001452
jardineb5d44e2003-12-23 08:09:43 +00001453 if (!isis->area_list || isis->area_list->count == 0)
1454 return CMD_SUCCESS;
1455
paul1eb8ef22005-04-07 07:30:20 +00001456 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001457 {
hassof390d2c2004-09-10 20:48:21 +00001458 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1459 VTY_NEWLINE);
1460
1461 if (area->ip_circuits > 0 && area->spftree[1]
1462 && area->spftree[1]->paths->count > 0)
1463 {
1464 vty_out (vty, "IS-IS paths to level-2 routers that speak IP%s",
1465 VTY_NEWLINE);
1466 isis_print_paths (vty, area->spftree[1]->paths);
1467 }
jardineb5d44e2003-12-23 08:09:43 +00001468#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001469 if (area->ipv6_circuits > 0 && area->spftree6[1]
1470 && area->spftree6[1]->paths->count > 0)
1471 {
1472 vty_out (vty, "IS-IS paths to level-2 routers that speak IPv6%s",
1473 VTY_NEWLINE);
1474 isis_print_paths (vty, area->spftree6[1]->paths);
1475 }
jardineb5d44e2003-12-23 08:09:43 +00001476#endif /* HAVE_IPV6 */
1477 }
1478
jardineb5d44e2003-12-23 08:09:43 +00001479 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001480}
jardineb5d44e2003-12-23 08:09:43 +00001481
1482void
1483isis_spf_cmds_init ()
1484{
1485 install_element (VIEW_NODE, &show_isis_topology_cmd);
1486 install_element (VIEW_NODE, &show_isis_topology_l1_cmd);
1487 install_element (VIEW_NODE, &show_isis_topology_l2_cmd);
1488
1489 install_element (ENABLE_NODE, &show_isis_topology_cmd);
1490 install_element (ENABLE_NODE, &show_isis_topology_l1_cmd);
1491 install_element (ENABLE_NODE, &show_isis_topology_l2_cmd);
1492}