blob: 5d7e9da4255525e08048663fcbef8e26ca7330d6 [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"
39#include "dict.h"
40#include "isisd.h"
41#include "isis_misc.h"
42#include "isis_adjacency.h"
43#include "isis_circuit.h"
44#include "isis_tlv.h"
45#include "isis_pdu.h"
46#include "isis_lsp.h"
47#include "isis_dynhn.h"
48#include "isis_spf.h"
49#include "isis_route.h"
50#include "isis_csm.h"
51
52extern struct isis *isis;
53extern struct thread_master *master;
54extern struct host host;
55
56int isis_run_spf_l1 (struct thread *thread);
57int isis_run_spf_l2 (struct thread *thread);
58
jardineb5d44e2003-12-23 08:09:43 +000059/* 7.2.7 */
hasso92365882005-01-18 13:53:33 +000060static void
jardineb5d44e2003-12-23 08:09:43 +000061remove_excess_adjs (struct list *adjs)
62{
hasso3fdb2dd2005-09-28 18:45:54 +000063 struct listnode *node, *excess = NULL;
jardineb5d44e2003-12-23 08:09:43 +000064 struct isis_adjacency *adj, *candidate = NULL;
65 int comp;
66
hasso3fdb2dd2005-09-28 18:45:54 +000067 for (ALL_LIST_ELEMENTS_RO (adjs, node, adj))
hassof390d2c2004-09-10 20:48:21 +000068 {
69 if (excess == NULL)
70 excess = node;
paul1eb8ef22005-04-07 07:30:20 +000071 candidate = listgetdata (excess);
72
hassof390d2c2004-09-10 20:48:21 +000073 if (candidate->sys_type < adj->sys_type)
74 {
75 excess = node;
76 candidate = adj;
77 continue;
78 }
79 if (candidate->sys_type > adj->sys_type)
80 continue;
81
82 comp = memcmp (candidate->sysid, adj->sysid, ISIS_SYS_ID_LEN);
83 if (comp > 0)
84 {
85 excess = node;
86 candidate = adj;
87 continue;
88 }
89 if (comp < 0)
90 continue;
91
92 if (candidate->circuit->circuit_id > adj->circuit->circuit_id)
93 {
94 excess = node;
95 candidate = adj;
96 continue;
97 }
98
99 if (candidate->circuit->circuit_id < adj->circuit->circuit_id)
100 continue;
101
102 comp = memcmp (candidate->snpa, adj->snpa, ETH_ALEN);
103 if (comp > 0)
104 {
105 excess = node;
106 candidate = adj;
107 continue;
108 }
jardineb5d44e2003-12-23 08:09:43 +0000109 }
110
jardineb5d44e2003-12-23 08:09:43 +0000111 list_delete_node (adjs, excess);
112
113 return;
114}
115
hasso92365882005-01-18 13:53:33 +0000116#ifdef EXTREME_DEBUG
117static const char *
jardineb5d44e2003-12-23 08:09:43 +0000118vtype2string (enum vertextype vtype)
119{
hassof390d2c2004-09-10 20:48:21 +0000120 switch (vtype)
121 {
122 case VTYPE_PSEUDO_IS:
123 return "pseudo_IS";
124 break;
hasso82a84282005-09-26 18:15:36 +0000125 case VTYPE_PSEUDO_TE_IS:
126 return "pseudo_TE-IS";
127 break;
hassof390d2c2004-09-10 20:48:21 +0000128 case VTYPE_NONPSEUDO_IS:
129 return "IS";
130 break;
hasso82a84282005-09-26 18:15:36 +0000131 case VTYPE_NONPSEUDO_TE_IS:
132 return "TE-IS";
133 break;
hassof390d2c2004-09-10 20:48:21 +0000134 case VTYPE_ES:
135 return "ES";
136 break;
137 case VTYPE_IPREACH_INTERNAL:
138 return "IP internal";
139 break;
140 case VTYPE_IPREACH_EXTERNAL:
141 return "IP external";
142 break;
hasso82a84282005-09-26 18:15:36 +0000143 case VTYPE_IPREACH_TE:
144 return "IP TE";
145 break;
jardineb5d44e2003-12-23 08:09:43 +0000146#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000147 case VTYPE_IP6REACH_INTERNAL:
148 return "IP6 internal";
149 break;
150 case VTYPE_IP6REACH_EXTERNAL:
151 return "IP6 external";
152 break;
153#endif /* HAVE_IPV6 */
154 default:
155 return "UNKNOWN";
156 }
157 return NULL; /* Not reached */
jardineb5d44e2003-12-23 08:09:43 +0000158}
159
hasso92365882005-01-18 13:53:33 +0000160static const char *
hassof390d2c2004-09-10 20:48:21 +0000161vid2string (struct isis_vertex *vertex, u_char * buff)
jardineb5d44e2003-12-23 08:09:43 +0000162{
hassof390d2c2004-09-10 20:48:21 +0000163 switch (vertex->type)
164 {
165 case VTYPE_PSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000166 case VTYPE_PSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000167 return rawlspid_print (vertex->N.id);
168 break;
169 case VTYPE_NONPSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000170 case VTYPE_NONPSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000171 case VTYPE_ES:
172 return sysid_print (vertex->N.id);
173 break;
174 case VTYPE_IPREACH_INTERNAL:
175 case VTYPE_IPREACH_EXTERNAL:
hasso82a84282005-09-26 18:15:36 +0000176 case VTYPE_IPREACH_TE:
jardineb5d44e2003-12-23 08:09:43 +0000177#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000178 case VTYPE_IP6REACH_INTERNAL:
179 case VTYPE_IP6REACH_EXTERNAL:
180#endif /* HAVE_IPV6 */
hassof7c43dc2004-09-26 16:24:14 +0000181 prefix2str ((struct prefix *) &vertex->N.prefix, (char *) buff, BUFSIZ);
hassof390d2c2004-09-10 20:48:21 +0000182 break;
183 default:
184 return "UNKNOWN";
185 }
186
hassof7c43dc2004-09-26 16:24:14 +0000187 return (char *) buff;
jardineb5d44e2003-12-23 08:09:43 +0000188}
hasso92365882005-01-18 13:53:33 +0000189#endif /* EXTREME_DEBUG */
jardineb5d44e2003-12-23 08:09:43 +0000190
hasso92365882005-01-18 13:53:33 +0000191static struct isis_spftree *
jardineb5d44e2003-12-23 08:09:43 +0000192isis_spftree_new ()
193{
194 struct isis_spftree *tree;
195
hasso3fdb2dd2005-09-28 18:45:54 +0000196 tree = XCALLOC (MTYPE_ISIS_SPFTREE, sizeof (struct isis_spftree));
hassof390d2c2004-09-10 20:48:21 +0000197 if (tree == NULL)
198 {
199 zlog_err ("ISIS-Spf: isis_spftree_new Out of memory!");
200 return NULL;
201 }
jardineb5d44e2003-12-23 08:09:43 +0000202
203 tree->tents = list_new ();
hassof390d2c2004-09-10 20:48:21 +0000204 tree->paths = list_new ();
jardineb5d44e2003-12-23 08:09:43 +0000205 return tree;
206}
207
hasso92365882005-01-18 13:53:33 +0000208static void
jardineb5d44e2003-12-23 08:09:43 +0000209isis_vertex_del (struct isis_vertex *vertex)
210{
jardineb5d44e2003-12-23 08:09:43 +0000211 list_delete (vertex->Adj_N);
212
213 XFREE (MTYPE_ISIS_VERTEX, vertex);
hassof390d2c2004-09-10 20:48:21 +0000214
jardineb5d44e2003-12-23 08:09:43 +0000215 return;
216}
217
hasso92365882005-01-18 13:53:33 +0000218#if 0 /* HT: Not used yet. */
219static void
jardineb5d44e2003-12-23 08:09:43 +0000220isis_spftree_del (struct isis_spftree *spftree)
221{
hassof7c43dc2004-09-26 16:24:14 +0000222 spftree->tents->del = (void (*)(void *)) isis_vertex_del;
jardineb5d44e2003-12-23 08:09:43 +0000223 list_delete (spftree->tents);
hassof390d2c2004-09-10 20:48:21 +0000224
hassof7c43dc2004-09-26 16:24:14 +0000225 spftree->paths->del = (void (*)(void *)) isis_vertex_del;
jardineb5d44e2003-12-23 08:09:43 +0000226 list_delete (spftree->paths);
227
228 XFREE (MTYPE_ISIS_SPFTREE, spftree);
229
230 return;
231}
hasso92365882005-01-18 13:53:33 +0000232#endif
jardineb5d44e2003-12-23 08:09:43 +0000233
hassof390d2c2004-09-10 20:48:21 +0000234void
jardineb5d44e2003-12-23 08:09:43 +0000235spftree_area_init (struct isis_area *area)
236{
hassof390d2c2004-09-10 20:48:21 +0000237 if ((area->is_type & IS_LEVEL_1) && area->spftree[0] == NULL)
238 {
239 area->spftree[0] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000240#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000241 area->spftree6[0] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000242#endif
243
hassof390d2c2004-09-10 20:48:21 +0000244 /* thread_add_timer (master, isis_run_spf_l1, area,
245 isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */
246 }
247
248 if ((area->is_type & IS_LEVEL_2) && area->spftree[1] == NULL)
249 {
250 area->spftree[1] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000251#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000252 area->spftree6[1] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000253#endif
hassof390d2c2004-09-10 20:48:21 +0000254 /* thread_add_timer (master, isis_run_spf_l2, area,
255 isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */
256 }
jardineb5d44e2003-12-23 08:09:43 +0000257
258 return;
259}
260
hasso92365882005-01-18 13:53:33 +0000261static struct isis_vertex *
jardineb5d44e2003-12-23 08:09:43 +0000262isis_vertex_new (void *id, enum vertextype vtype)
263{
264 struct isis_vertex *vertex;
265
hasso3fdb2dd2005-09-28 18:45:54 +0000266 vertex = XCALLOC (MTYPE_ISIS_VERTEX, sizeof (struct isis_vertex));
hassof390d2c2004-09-10 20:48:21 +0000267 if (vertex == NULL)
268 {
269 zlog_err ("isis_vertex_new Out of memory!");
270 return NULL;
271 }
272
jardineb5d44e2003-12-23 08:09:43 +0000273 vertex->type = vtype;
hassof390d2c2004-09-10 20:48:21 +0000274 switch (vtype)
275 {
276 case VTYPE_ES:
277 case VTYPE_NONPSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000278 case VTYPE_NONPSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000279 memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN);
280 break;
281 case VTYPE_PSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000282 case VTYPE_PSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000283 memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN + 1);
284 break;
285 case VTYPE_IPREACH_INTERNAL:
286 case VTYPE_IPREACH_EXTERNAL:
hasso82a84282005-09-26 18:15:36 +0000287 case VTYPE_IPREACH_TE:
jardineb5d44e2003-12-23 08:09:43 +0000288#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000289 case VTYPE_IP6REACH_INTERNAL:
290 case VTYPE_IP6REACH_EXTERNAL:
291#endif /* HAVE_IPV6 */
292 memcpy (&vertex->N.prefix, (struct prefix *) id,
293 sizeof (struct prefix));
294 break;
295 default:
296 zlog_err ("WTF!");
297 }
jardineb5d44e2003-12-23 08:09:43 +0000298
299 vertex->Adj_N = list_new ();
hassof390d2c2004-09-10 20:48:21 +0000300
jardineb5d44e2003-12-23 08:09:43 +0000301 return vertex;
302}
303
304/*
305 * Add this IS to the root of SPT
306 */
hasso92365882005-01-18 13:53:33 +0000307static void
jardineb5d44e2003-12-23 08:09:43 +0000308isis_spf_add_self (struct isis_spftree *spftree, struct isis_area *area,
hassof390d2c2004-09-10 20:48:21 +0000309 int level)
jardineb5d44e2003-12-23 08:09:43 +0000310{
311 struct isis_vertex *vertex;
312 struct isis_lsp *lsp;
313 u_char lspid[ISIS_SYS_ID_LEN + 2];
314#ifdef EXTREME_DEBUG
315 u_char buff[BUFSIZ];
316#endif /* EXTREME_DEBUG */
317 memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN);
hassof390d2c2004-09-10 20:48:21 +0000318 LSP_PSEUDO_ID (lspid) = 0;
319 LSP_FRAGMENT (lspid) = 0;
320
jardineb5d44e2003-12-23 08:09:43 +0000321 lsp = lsp_search (lspid, area->lspdb[level - 1]);
hassof390d2c2004-09-10 20:48:21 +0000322
jardineb5d44e2003-12-23 08:09:43 +0000323 if (lsp == NULL)
324 zlog_warn ("ISIS-Spf: could not find own l%d LSP!", level);
hassof390d2c2004-09-10 20:48:21 +0000325
hasso82a84282005-09-26 18:15:36 +0000326 if (!area->oldmetric)
327 vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_TE_IS);
328 else
329 vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_IS);
330
jardineb5d44e2003-12-23 08:09:43 +0000331 vertex->lsp = lsp;
332
333 listnode_add (spftree->paths, vertex);
334
335#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000336 zlog_debug ("ISIS-Spf: added this IS %s %s depth %d dist %d to PATHS",
337 vtype2string (vertex->type), vid2string (vertex, buff),
338 vertex->depth, vertex->d_N);
jardineb5d44e2003-12-23 08:09:43 +0000339#endif /* EXTREME_DEBUG */
340
341 return;
342}
343
hasso92365882005-01-18 13:53:33 +0000344static struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000345isis_find_vertex (struct list *list, void *id, enum vertextype vtype)
jardineb5d44e2003-12-23 08:09:43 +0000346{
347 struct listnode *node;
348 struct isis_vertex *vertex;
349 struct prefix *p1, *p2;
350
paul1eb8ef22005-04-07 07:30:20 +0000351 for (ALL_LIST_ELEMENTS_RO (list, node, vertex))
hassof390d2c2004-09-10 20:48:21 +0000352 {
hassof390d2c2004-09-10 20:48:21 +0000353 if (vertex->type != vtype)
354 continue;
355 switch (vtype)
356 {
357 case VTYPE_ES:
358 case VTYPE_NONPSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000359 case VTYPE_NONPSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000360 if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN) == 0)
361 return vertex;
362 break;
363 case VTYPE_PSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000364 case VTYPE_PSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000365 if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN + 1) == 0)
366 return vertex;
367 break;
368 case VTYPE_IPREACH_INTERNAL:
369 case VTYPE_IPREACH_EXTERNAL:
hasso82a84282005-09-26 18:15:36 +0000370 case VTYPE_IPREACH_TE:
jardineb5d44e2003-12-23 08:09:43 +0000371#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000372 case VTYPE_IP6REACH_INTERNAL:
373 case VTYPE_IP6REACH_EXTERNAL:
jardineb5d44e2003-12-23 08:09:43 +0000374#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000375 p1 = (struct prefix *) id;
376 p2 = (struct prefix *) &vertex->N.id;
377 if (p1->family == p2->family && p1->prefixlen == p2->prefixlen &&
378 memcmp (&p1->u.prefix, &p2->u.prefix,
379 PSIZE (p1->prefixlen)) == 0)
380 return vertex;
381 break;
382 }
jardineb5d44e2003-12-23 08:09:43 +0000383 }
jardineb5d44e2003-12-23 08:09:43 +0000384
385 return NULL;
386}
387
jardineb5d44e2003-12-23 08:09:43 +0000388/*
389 * Add a vertex to TENT sorted by cost and by vertextype on tie break situation
390 */
hasso92365882005-01-18 13:53:33 +0000391static struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000392isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype,
hassofac1f7c2005-09-26 18:26:26 +0000393 void *id, struct isis_adjacency *adj, u_int32_t cost,
hassof390d2c2004-09-10 20:48:21 +0000394 int depth, int family)
jardineb5d44e2003-12-23 08:09:43 +0000395{
396 struct isis_vertex *vertex, *v;
397 struct listnode *node;
hassof390d2c2004-09-10 20:48:21 +0000398#ifdef EXTREME_DEBUG
jardineb5d44e2003-12-23 08:09:43 +0000399 u_char buff[BUFSIZ];
400#endif
401
402 vertex = isis_vertex_new (id, vtype);
403 vertex->d_N = cost;
404 vertex->depth = depth;
hassof390d2c2004-09-10 20:48:21 +0000405
jardineb5d44e2003-12-23 08:09:43 +0000406 if (adj)
407 listnode_add (vertex->Adj_N, adj);
hassof390d2c2004-09-10 20:48:21 +0000408#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000409 zlog_debug ("ISIS-Spf: add to TENT %s %s depth %d dist %d",
410 vtype2string (vertex->type), vid2string (vertex, buff),
411 vertex->depth, vertex->d_N);
jardineb5d44e2003-12-23 08:09:43 +0000412#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000413 listnode_add (spftree->tents, vertex);
414 if (list_isempty (spftree->tents))
415 {
416 listnode_add (spftree->tents, vertex);
417 return vertex;
jardineb5d44e2003-12-23 08:09:43 +0000418 }
paul1eb8ef22005-04-07 07:30:20 +0000419
420 /* XXX: This cant use the standard ALL_LIST_ELEMENT macro */
421 for (node = listhead (spftree->tents); node; node = listnextnode (node))
hassof390d2c2004-09-10 20:48:21 +0000422 {
paul1eb8ef22005-04-07 07:30:20 +0000423 v = listgetdata (node);
hassof390d2c2004-09-10 20:48:21 +0000424 if (v->d_N > vertex->d_N)
425 {
426 list_add_node_prev (spftree->tents, node, vertex);
427 break;
428 }
429 else if (v->d_N == vertex->d_N)
430 {
431 /* Tie break, add according to type */
432 while (v && v->d_N == vertex->d_N && v->type > vertex->type)
433 {
434 if (v->type > vertex->type)
435 {
436 break;
437 }
paul1eb8ef22005-04-07 07:30:20 +0000438 /* XXX: this seems dubious, node is the loop iterator */
439 node = listnextnode (node);
440 (node) ? (v = listgetdata (node)) : (v = NULL);
hassof390d2c2004-09-10 20:48:21 +0000441 }
442 list_add_node_prev (spftree->tents, node, vertex);
443 break;
444 }
445 else if (node->next == NULL)
446 {
447 list_add_node_next (spftree->tents, node, vertex);
448 break;
449 }
450 }
jardineb5d44e2003-12-23 08:09:43 +0000451 return vertex;
452}
453
hasso92365882005-01-18 13:53:33 +0000454static struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000455isis_spf_add_local (struct isis_spftree *spftree, enum vertextype vtype,
hassofac1f7c2005-09-26 18:26:26 +0000456 void *id, struct isis_adjacency *adj, u_int32_t cost,
hassof390d2c2004-09-10 20:48:21 +0000457 int family)
jardineb5d44e2003-12-23 08:09:43 +0000458{
459 struct isis_vertex *vertex;
jardineb5d44e2003-12-23 08:09:43 +0000460
hassof390d2c2004-09-10 20:48:21 +0000461 vertex = isis_find_vertex (spftree->tents, id, vtype);
462
463 if (vertex)
464 {
465 /* C.2.5 c) */
466 if (vertex->d_N == cost)
467 {
468 if (adj)
469 listnode_add (vertex->Adj_N, adj);
470 /* d) */
471 if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
472 remove_excess_adjs (vertex->Adj_N);
473 }
474 /* f) */
475 else if (vertex->d_N > cost)
476 {
477 listnode_delete (spftree->tents, vertex);
478 goto add2tent;
479 }
480 /* e) do nothing */
481 return vertex;
482 }
483
484add2tent:
jardineb5d44e2003-12-23 08:09:43 +0000485 return isis_spf_add2tent (spftree, vtype, id, adj, cost, 1, family);
486}
487
hasso92365882005-01-18 13:53:33 +0000488static void
hassof390d2c2004-09-10 20:48:21 +0000489process_N (struct isis_spftree *spftree, enum vertextype vtype, void *id,
490 u_int16_t dist, u_int16_t depth, struct isis_adjacency *adj,
491 int family)
jardineb5d44e2003-12-23 08:09:43 +0000492{
493 struct isis_vertex *vertex;
494#ifdef EXTREME_DEBUG
495 u_char buff[255];
496#endif
497
498 /* C.2.6 b) */
499 if (dist > MAX_PATH_METRIC)
500 return;
501 /* c) */
502 vertex = isis_find_vertex (spftree->paths, id, vtype);
hassof390d2c2004-09-10 20:48:21 +0000503 if (vertex)
504 {
jardineb5d44e2003-12-23 08:09:43 +0000505#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000506 zlog_debug ("ISIS-Spf: process_N %s %s dist %d already found from PATH",
507 vtype2string (vtype), vid2string (vertex, buff), dist);
jardineb5d44e2003-12-23 08:09:43 +0000508#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000509 assert (dist >= vertex->d_N);
510 return;
511 }
jardineb5d44e2003-12-23 08:09:43 +0000512
513 vertex = isis_find_vertex (spftree->tents, id, vtype);
hassof390d2c2004-09-10 20:48:21 +0000514 /* d) */
515 if (vertex)
516 {
517 /* 1) */
jardineb5d44e2003-12-23 08:09:43 +0000518#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000519 zlog_debug ("ISIS-Spf: process_N %s %s dist %d",
520 vtype2string (vtype), vid2string (vertex, buff), dist);
jardineb5d44e2003-12-23 08:09:43 +0000521#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000522 if (vertex->d_N == dist)
523 {
524 if (adj)
525 listnode_add (vertex->Adj_N, adj);
526 /* 2) */
527 if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
528 remove_excess_adjs (vertex->Adj_N);
529 /* 3) */
530 return;
531 }
532 else if (vertex->d_N < dist)
533 {
534 return;
535 /* 4) */
536 }
537 else
538 {
539 listnode_delete (spftree->tents, vertex);
540 }
jardineb5d44e2003-12-23 08:09:43 +0000541 }
hassof390d2c2004-09-10 20:48:21 +0000542
jardineb5d44e2003-12-23 08:09:43 +0000543 isis_spf_add2tent (spftree, vtype, id, adj, dist, depth, family);
544 return;
545}
546
547/*
548 * C.2.6 Step 1
549 */
hasso92365882005-01-18 13:53:33 +0000550static int
hassof390d2c2004-09-10 20:48:21 +0000551isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp,
hassofac1f7c2005-09-26 18:26:26 +0000552 uint32_t cost, uint16_t depth, int family)
jardineb5d44e2003-12-23 08:09:43 +0000553{
554 struct listnode *node, *fragnode = NULL;
555 u_int16_t dist;
556 struct is_neigh *is_neigh;
hasso82a84282005-09-26 18:15:36 +0000557 struct te_is_neigh *te_is_neigh;
jardineb5d44e2003-12-23 08:09:43 +0000558 struct ipv4_reachability *ipreach;
hasso82a84282005-09-26 18:15:36 +0000559 struct te_ipv4_reachability *te_ipv4_reach;
jardineb5d44e2003-12-23 08:09:43 +0000560 enum vertextype vtype;
561 struct prefix prefix;
562#ifdef HAVE_IPV6
563 struct ipv6_reachability *ip6reach;
564#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000565
jardineb5d44e2003-12-23 08:09:43 +0000566
567 if (!lsp->adj)
568 return ISIS_WARNING;
hassof390d2c2004-09-10 20:48:21 +0000569 if (lsp->tlv_data.nlpids == NULL || !speaks (lsp->tlv_data.nlpids, family))
jardineb5d44e2003-12-23 08:09:43 +0000570 return ISIS_OK;
571
hassof390d2c2004-09-10 20:48:21 +0000572lspfragloop:
573 if (lsp->lsp_header->seq_num == 0)
574 {
575 zlog_warn ("isis_spf_process_lsp(): lsp with 0 seq_num"
576 " - do not process");
577 return ISIS_WARNING;
578 }
jardineb5d44e2003-12-23 08:09:43 +0000579
hassof390d2c2004-09-10 20:48:21 +0000580 if (!ISIS_MASK_LSP_OL_BIT (lsp->lsp_header->lsp_bits))
581 {
582 if (lsp->tlv_data.is_neighs)
583 {
paul1eb8ef22005-04-07 07:30:20 +0000584 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh))
hassof390d2c2004-09-10 20:48:21 +0000585 {
hassof390d2c2004-09-10 20:48:21 +0000586 /* C.2.6 a) */
587 /* Two way connectivity */
588 if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
589 continue;
590 dist = cost + is_neigh->metrics.metric_default;
591 vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
592 : VTYPE_NONPSEUDO_IS;
593 process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist,
594 depth + 1, lsp->adj, family);
595 }
596 }
hasso82a84282005-09-26 18:15:36 +0000597 if (lsp->tlv_data.te_is_neighs)
598 {
599 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node,
600 te_is_neigh))
601 {
602 uint32_t metric;
603 if (!memcmp (te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
604 continue;
605 memcpy (&metric, te_is_neigh->te_metric, 3);
606 dist = cost + ntohl (metric << 8);
607 vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS
608 : VTYPE_NONPSEUDO_TE_IS;
609 process_N (spftree, vtype, (void *) te_is_neigh->neigh_id, dist,
610 depth + 1, lsp->adj, family);
611 }
612 }
hassof390d2c2004-09-10 20:48:21 +0000613 if (family == AF_INET && lsp->tlv_data.ipv4_int_reachs)
614 {
615 prefix.family = AF_INET;
paul1eb8ef22005-04-07 07:30:20 +0000616 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_int_reachs,
617 node, ipreach))
hassof390d2c2004-09-10 20:48:21 +0000618 {
hassof390d2c2004-09-10 20:48:21 +0000619 dist = cost + ipreach->metrics.metric_default;
620 vtype = VTYPE_IPREACH_INTERNAL;
621 prefix.u.prefix4 = ipreach->prefix;
622 prefix.prefixlen = ip_masklen (ipreach->mask);
623 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
624 lsp->adj, family);
625 }
626 }
627
628 if (family == AF_INET && lsp->tlv_data.ipv4_ext_reachs)
629 {
630 prefix.family = AF_INET;
paul1eb8ef22005-04-07 07:30:20 +0000631 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_ext_reachs,
632 node, ipreach))
hassof390d2c2004-09-10 20:48:21 +0000633 {
hassof390d2c2004-09-10 20:48:21 +0000634 dist = cost + ipreach->metrics.metric_default;
635 vtype = VTYPE_IPREACH_EXTERNAL;
636 prefix.u.prefix4 = ipreach->prefix;
637 prefix.prefixlen = ip_masklen (ipreach->mask);
638 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
639 lsp->adj, family);
640 }
641 }
hasso82a84282005-09-26 18:15:36 +0000642 if (family == AF_INET && lsp->tlv_data.te_ipv4_reachs)
643 {
644 prefix.family = AF_INET;
645 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_ipv4_reachs,
646 node, te_ipv4_reach))
647 {
648 dist = cost + ntohl (te_ipv4_reach->te_metric);
649 vtype = VTYPE_IPREACH_TE;
650 prefix.u.prefix4 = newprefix2inaddr (&te_ipv4_reach->prefix_start,
651 te_ipv4_reach->control);
652 prefix.prefixlen = (te_ipv4_reach->control & 0x3F);
653 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
654 lsp->adj, family);
655 }
656 }
jardineb5d44e2003-12-23 08:09:43 +0000657#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000658 if (family == AF_INET6 && lsp->tlv_data.ipv6_reachs)
659 {
660 prefix.family = AF_INET6;
paul1eb8ef22005-04-07 07:30:20 +0000661 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv6_reachs,
662 node, ip6reach))
hassof390d2c2004-09-10 20:48:21 +0000663 {
hassof390d2c2004-09-10 20:48:21 +0000664 dist = cost + ip6reach->metric;
665 vtype = (ip6reach->control_info & CTRL_INFO_DISTRIBUTION) ?
666 VTYPE_IP6REACH_EXTERNAL : VTYPE_IP6REACH_INTERNAL;
667 prefix.prefixlen = ip6reach->prefix_len;
668 memcpy (&prefix.u.prefix6.s6_addr, ip6reach->prefix,
669 PSIZE (ip6reach->prefix_len));
670 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
671 lsp->adj, family);
672 }
673 }
jardineb5d44e2003-12-23 08:09:43 +0000674#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000675 }
676
jardineb5d44e2003-12-23 08:09:43 +0000677 if (fragnode == NULL)
678 fragnode = listhead (lsp->lspu.frags);
hassof390d2c2004-09-10 20:48:21 +0000679 else
paul1eb8ef22005-04-07 07:30:20 +0000680 fragnode = listnextnode (fragnode);
jardineb5d44e2003-12-23 08:09:43 +0000681
hassof390d2c2004-09-10 20:48:21 +0000682 if (fragnode)
683 {
paul1eb8ef22005-04-07 07:30:20 +0000684 lsp = listgetdata (fragnode);
hassof390d2c2004-09-10 20:48:21 +0000685 goto lspfragloop;
686 }
687
jardineb5d44e2003-12-23 08:09:43 +0000688 return ISIS_OK;
689}
690
hasso92365882005-01-18 13:53:33 +0000691static int
hassof390d2c2004-09-10 20:48:21 +0000692isis_spf_process_pseudo_lsp (struct isis_spftree *spftree,
693 struct isis_lsp *lsp, uint16_t cost,
694 uint16_t depth, int family)
jardineb5d44e2003-12-23 08:09:43 +0000695{
hasso3fdb2dd2005-09-28 18:45:54 +0000696 struct listnode *node, *fragnode = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000697 struct is_neigh *is_neigh;
hasso82a84282005-09-26 18:15:36 +0000698 struct te_is_neigh *te_is_neigh;
jardineb5d44e2003-12-23 08:09:43 +0000699 enum vertextype vtype;
hassof390d2c2004-09-10 20:48:21 +0000700
701pseudofragloop:
702
703 if (lsp->lsp_header->seq_num == 0)
704 {
705 zlog_warn ("isis_spf_process_pseudo_lsp(): lsp with 0 seq_num"
706 " - do not process");
707 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +0000708 }
hassof390d2c2004-09-10 20:48:21 +0000709
hasso82a84282005-09-26 18:15:36 +0000710 if (lsp->tlv_data.is_neighs)
hasso3fdb2dd2005-09-28 18:45:54 +0000711 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh))
hasso82a84282005-09-26 18:15:36 +0000712 {
713 vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
714 : VTYPE_NONPSEUDO_IS;
715 /* Two way connectivity */
716 if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
717 continue;
718 if (isis_find_vertex
719 (spftree->tents, (void *) is_neigh->neigh_id, vtype) == NULL
720 && isis_find_vertex (spftree->paths, (void *) is_neigh->neigh_id,
hassof390d2c2004-09-10 20:48:21 +0000721 vtype) == NULL)
hasso82a84282005-09-26 18:15:36 +0000722 {
723 /* C.2.5 i) */
724 isis_spf_add2tent (spftree, vtype, is_neigh->neigh_id, lsp->adj,
hassof390d2c2004-09-10 20:48:21 +0000725 cost, depth, family);
hasso82a84282005-09-26 18:15:36 +0000726 }
727 }
728 if (lsp->tlv_data.te_is_neighs)
hasso3fdb2dd2005-09-28 18:45:54 +0000729 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node, te_is_neigh))
hasso82a84282005-09-26 18:15:36 +0000730 {
731 vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS
732 : VTYPE_NONPSEUDO_TE_IS;
733 /* Two way connectivity */
734 if (!memcmp (te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
735 continue;
736 if (isis_find_vertex
737 (spftree->tents, (void *) te_is_neigh->neigh_id, vtype) == NULL
738 && isis_find_vertex (spftree->paths, (void *) te_is_neigh->neigh_id,
739 vtype) == NULL)
740 {
741 /* C.2.5 i) */
742 isis_spf_add2tent (spftree, vtype, te_is_neigh->neigh_id, lsp->adj,
743 cost, depth, family);
744 }
745 }
hassof390d2c2004-09-10 20:48:21 +0000746
jardineb5d44e2003-12-23 08:09:43 +0000747 if (fragnode == NULL)
748 fragnode = listhead (lsp->lspu.frags);
hassof390d2c2004-09-10 20:48:21 +0000749 else
paul1eb8ef22005-04-07 07:30:20 +0000750 fragnode = listnextnode (fragnode);
jardineb5d44e2003-12-23 08:09:43 +0000751
hassof390d2c2004-09-10 20:48:21 +0000752 if (fragnode)
753 {
paul1eb8ef22005-04-07 07:30:20 +0000754 lsp = listgetdata (fragnode);
hassof390d2c2004-09-10 20:48:21 +0000755 goto pseudofragloop;
756 }
jardineb5d44e2003-12-23 08:09:43 +0000757
jardineb5d44e2003-12-23 08:09:43 +0000758 return ISIS_OK;
759}
hassof390d2c2004-09-10 20:48:21 +0000760
hasso92365882005-01-18 13:53:33 +0000761static int
hassof390d2c2004-09-10 20:48:21 +0000762isis_spf_preload_tent (struct isis_spftree *spftree,
763 struct isis_area *area, int level, int family)
jardineb5d44e2003-12-23 08:09:43 +0000764{
765 struct isis_vertex *vertex;
766 struct isis_circuit *circuit;
hasso3fdb2dd2005-09-28 18:45:54 +0000767 struct listnode *cnode, *anode, *ipnode;
jardineb5d44e2003-12-23 08:09:43 +0000768 struct isis_adjacency *adj;
769 struct isis_lsp *lsp;
770 struct list *adj_list;
771 struct list *adjdb;
772 struct prefix_ipv4 *ipv4;
773 struct prefix prefix;
774 int retval = ISIS_OK;
775 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
776#ifdef HAVE_IPV6
777 struct prefix_ipv6 *ipv6;
778#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000779
hasso3fdb2dd2005-09-28 18:45:54 +0000780 for (ALL_LIST_ELEMENTS_RO (area->circuit_list, cnode, circuit))
hassof390d2c2004-09-10 20:48:21 +0000781 {
hassof390d2c2004-09-10 20:48:21 +0000782 if (circuit->state != C_STATE_UP)
jardineb5d44e2003-12-23 08:09:43 +0000783 continue;
hassof390d2c2004-09-10 20:48:21 +0000784 if (!(circuit->circuit_is_type & level))
785 continue;
786 if (family == AF_INET && !circuit->ip_router)
787 continue;
788#ifdef HAVE_IPV6
789 if (family == AF_INET6 && !circuit->ipv6_router)
790 continue;
791#endif /* HAVE_IPV6 */
792 /*
793 * Add IP(v6) addresses of this circuit
jardineb5d44e2003-12-23 08:09:43 +0000794 */
hassof390d2c2004-09-10 20:48:21 +0000795 if (family == AF_INET)
796 {
797 prefix.family = AF_INET;
hasso3fdb2dd2005-09-28 18:45:54 +0000798 for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, ipnode, ipv4))
hassof390d2c2004-09-10 20:48:21 +0000799 {
hassof390d2c2004-09-10 20:48:21 +0000800 prefix.u.prefix4 = ipv4->prefix;
801 prefix.prefixlen = ipv4->prefixlen;
802 isis_spf_add_local (spftree, VTYPE_IPREACH_INTERNAL, &prefix,
803 NULL, 0, family);
804 }
805 }
806#ifdef HAVE_IPV6
807 if (family == AF_INET6)
808 {
809 prefix.family = AF_INET6;
hasso3fdb2dd2005-09-28 18:45:54 +0000810 for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, ipnode, ipv6))
hassof390d2c2004-09-10 20:48:21 +0000811 {
hassof390d2c2004-09-10 20:48:21 +0000812 prefix.prefixlen = ipv6->prefixlen;
813 prefix.u.prefix6 = ipv6->prefix;
814 isis_spf_add_local (spftree, VTYPE_IP6REACH_INTERNAL,
815 &prefix, NULL, 0, family);
816 }
817 }
818#endif /* HAVE_IPV6 */
819 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
820 {
821 /*
822 * Add the adjacencies
823 */
824 adj_list = list_new ();
825 adjdb = circuit->u.bc.adjdb[level - 1];
826 isis_adj_build_up_list (adjdb, adj_list);
827 if (listcount (adj_list) == 0)
828 {
829 list_delete (adj_list);
hassoc89c05d2005-09-04 21:36:36 +0000830 if (isis->debugs & DEBUG_SPF_EVENTS)
831 zlog_debug ("ISIS-Spf: no L%d adjacencies on circuit %s",
832 level, circuit->interface->name);
hassof390d2c2004-09-10 20:48:21 +0000833 continue;
834 }
835 anode = listhead (adj_list);
836 while (anode)
837 {
paul1eb8ef22005-04-07 07:30:20 +0000838 adj = listgetdata (anode);
hassof390d2c2004-09-10 20:48:21 +0000839 if (!speaks (&adj->nlpids, family))
840 {
paul1eb8ef22005-04-07 07:30:20 +0000841 anode = listnextnode (anode);
hassof390d2c2004-09-10 20:48:21 +0000842 continue;
843 }
844 switch (adj->sys_type)
845 {
846 case ISIS_SYSTYPE_ES:
847 isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
hasso82a84282005-09-26 18:15:36 +0000848 circuit->te_metric[level - 1], family);
hassof390d2c2004-09-10 20:48:21 +0000849 break;
850 case ISIS_SYSTYPE_IS:
851 case ISIS_SYSTYPE_L1_IS:
852 case ISIS_SYSTYPE_L2_IS:
853 vertex =
854 isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS,
855 adj->sysid, adj,
hasso82a84282005-09-26 18:15:36 +0000856 circuit->te_metric[level - 1], family);
hassof390d2c2004-09-10 20:48:21 +0000857 memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN);
858 LSP_PSEUDO_ID (lsp_id) = 0;
859 LSP_FRAGMENT (lsp_id) = 0;
860 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
861 if (!lsp)
862 zlog_warn ("No lsp found for IS adjacency");
863 /* else {
864 isis_spf_process_lsp (spftree, lsp, vertex->d_N, 1, family);
865 } */
866 break;
867 case ISIS_SYSTYPE_UNKNOWN:
868 default:
869 zlog_warn ("isis_spf_preload_tent unknow adj type");
870 }
paul1eb8ef22005-04-07 07:30:20 +0000871 anode = listnextnode (anode);
hassof390d2c2004-09-10 20:48:21 +0000872 }
873 list_delete (adj_list);
874 /*
875 * Add the pseudonode
876 */
877 if (level == 1)
878 memcpy (lsp_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
879 else
880 memcpy (lsp_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
881 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
882 adj = isis_adj_lookup (lsp_id, adjdb);
883 /* if no adj, we are the dis or error */
884 if (!adj && !circuit->u.bc.is_dr[level - 1])
885 {
886 zlog_warn ("ISIS-Spf: No adjacency found for DR");
887 }
888 if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0)
889 {
890 zlog_warn ("ISIS-Spf: No lsp found for DR");
891 }
892 else
893 {
hasso82a84282005-09-26 18:15:36 +0000894 isis_spf_process_pseudo_lsp (spftree, lsp,
895 circuit->te_metric[level - 1], 0, family);
hassof390d2c2004-09-10 20:48:21 +0000896
897 }
898 }
899 else if (circuit->circ_type == CIRCUIT_T_P2P)
900 {
901 adj = circuit->u.p2p.neighbor;
902 if (!adj)
903 continue;
904 switch (adj->sys_type)
905 {
906 case ISIS_SYSTYPE_ES:
907 isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
hasso82a84282005-09-26 18:15:36 +0000908 circuit->te_metric[level - 1], family);
hassof390d2c2004-09-10 20:48:21 +0000909 break;
910 case ISIS_SYSTYPE_IS:
911 case ISIS_SYSTYPE_L1_IS:
912 case ISIS_SYSTYPE_L2_IS:
913 if (speaks (&adj->nlpids, family))
914 isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS, adj->sysid,
hasso82a84282005-09-26 18:15:36 +0000915 adj, circuit->te_metric[level - 1],
hassof390d2c2004-09-10 20:48:21 +0000916 family);
917 break;
918 case ISIS_SYSTYPE_UNKNOWN:
919 default:
920 zlog_warn ("isis_spf_preload_tent unknow adj type");
921 break;
922 }
923 }
jardineb5d44e2003-12-23 08:09:43 +0000924 else
hassof390d2c2004-09-10 20:48:21 +0000925 {
926 zlog_warn ("isis_spf_preload_tent unsupported media");
927 retval = ISIS_WARNING;
928 }
929
jardineb5d44e2003-12-23 08:09:43 +0000930 }
jardineb5d44e2003-12-23 08:09:43 +0000931
932 return retval;
933}
934
935/*
936 * The parent(s) for vertex is set when added to TENT list
937 * now we just put the child pointer(s) in place
938 */
hasso92365882005-01-18 13:53:33 +0000939static void
jardineb5d44e2003-12-23 08:09:43 +0000940add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex,
hassofac1f7c2005-09-26 18:26:26 +0000941 struct isis_area *area, int level)
jardineb5d44e2003-12-23 08:09:43 +0000942{
jardineb5d44e2003-12-23 08:09:43 +0000943#ifdef EXTREME_DEBUG
944 u_char buff[BUFSIZ];
945#endif /* EXTREME_DEBUG */
946 listnode_add (spftree->paths, vertex);
947
hassof390d2c2004-09-10 20:48:21 +0000948#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000949 zlog_debug ("ISIS-Spf: added %s %s depth %d dist %d to PATHS",
950 vtype2string (vertex->type), vid2string (vertex, buff),
951 vertex->depth, vertex->d_N);
hassof390d2c2004-09-10 20:48:21 +0000952#endif /* EXTREME_DEBUG */
953 if (vertex->type > VTYPE_ES)
954 {
955 if (listcount (vertex->Adj_N) > 0)
hassofac1f7c2005-09-26 18:26:26 +0000956 isis_route_create ((struct prefix *) &vertex->N.prefix, vertex->d_N,
957 vertex->depth, vertex->Adj_N, area, level);
hassof390d2c2004-09-10 20:48:21 +0000958 else if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000959 zlog_debug ("ISIS-Spf: no adjacencies do not install route");
hassof390d2c2004-09-10 20:48:21 +0000960 }
961
jardineb5d44e2003-12-23 08:09:43 +0000962 return;
963}
964
hasso92365882005-01-18 13:53:33 +0000965static void
jardineb5d44e2003-12-23 08:09:43 +0000966init_spt (struct isis_spftree *spftree)
967{
hassof7c43dc2004-09-26 16:24:14 +0000968 spftree->tents->del = spftree->paths->del = (void (*)(void *)) isis_vertex_del;
jardineb5d44e2003-12-23 08:09:43 +0000969 list_delete_all_node (spftree->tents);
970 list_delete_all_node (spftree->paths);
971 spftree->tents->del = spftree->paths->del = NULL;
hassof390d2c2004-09-10 20:48:21 +0000972
jardineb5d44e2003-12-23 08:09:43 +0000973 return;
974}
975
hasso92365882005-01-18 13:53:33 +0000976static int
jardineb5d44e2003-12-23 08:09:43 +0000977isis_run_spf (struct isis_area *area, int level, int family)
978{
979 int retval = ISIS_OK;
980 struct listnode *node;
981 struct isis_vertex *vertex;
hassof390d2c2004-09-10 20:48:21 +0000982 struct isis_spftree *spftree = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000983 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
984 struct isis_lsp *lsp;
hassofac1f7c2005-09-26 18:26:26 +0000985 struct route_table *table = NULL;
986 struct route_node *rode;
987 struct isis_route_info *rinfo;
hassof390d2c2004-09-10 20:48:21 +0000988
jardineb5d44e2003-12-23 08:09:43 +0000989 if (family == AF_INET)
990 spftree = area->spftree[level - 1];
991#ifdef HAVE_IPV6
992 else if (family == AF_INET6)
993 spftree = area->spftree6[level - 1];
994#endif
hassof390d2c2004-09-10 20:48:21 +0000995
jardineb5d44e2003-12-23 08:09:43 +0000996 assert (spftree);
997
hassofac1f7c2005-09-26 18:26:26 +0000998 /* Make all routes in current route table inactive. */
999 if (family == AF_INET)
1000 table = area->route_table[level - 1];
Paul Jakma41b36e92006-12-08 01:09:50 +00001001#ifdef HAVE_IPV6
hassofac1f7c2005-09-26 18:26:26 +00001002 else if (family == AF_INET6)
1003 table = area->route_table6[level - 1];
Paul Jakma41b36e92006-12-08 01:09:50 +00001004#endif
hassofac1f7c2005-09-26 18:26:26 +00001005
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");
hasso13fb40a2005-10-01 06:03:04 +00001030 goto out;
jardineb5d44e2003-12-23 08:09:43 +00001031 }
hassof390d2c2004-09-10 20:48:21 +00001032
1033 while (listcount (spftree->tents) > 0)
1034 {
1035 node = listhead (spftree->tents);
paul1eb8ef22005-04-07 07:30:20 +00001036 vertex = listgetdata (node);
hassof390d2c2004-09-10 20:48:21 +00001037 /* Remove from tent list */
1038 list_delete_node (spftree->tents, node);
1039 if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type))
1040 continue;
hassofac1f7c2005-09-26 18:26:26 +00001041 add_to_paths (spftree, vertex, area, level);
hassof390d2c2004-09-10 20:48:21 +00001042 if (vertex->type == VTYPE_PSEUDO_IS ||
1043 vertex->type == VTYPE_NONPSEUDO_IS)
1044 {
1045 memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
1046 LSP_FRAGMENT (lsp_id) = 0;
1047 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
1048 if (lsp)
1049 {
1050 if (LSP_PSEUDO_ID (lsp_id))
1051 {
1052 isis_spf_process_pseudo_lsp (spftree, lsp, vertex->d_N,
1053 vertex->depth, family);
1054
1055 }
1056 else
1057 {
1058 isis_spf_process_lsp (spftree, lsp, vertex->d_N,
1059 vertex->depth, family);
1060 }
1061 }
1062 else
1063 {
1064 zlog_warn ("ISIS-Spf: No LSP found for %s",
1065 rawlspid_print (lsp_id));
1066 }
1067 }
1068 }
1069
hasso13fb40a2005-10-01 06:03:04 +00001070out:
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 :
Paul Jakma41b36e92006-12-08 01:09:50 +00001338 (const u_char *)rawlspid_print ((u_char *) vertex->N.id),
hassof390d2c2004-09-10 20:48:21 +00001339 vertex->d_N, (nh_dyn != NULL) ? nh_dyn->name.name :
Paul Jakma41b36e92006-12-08 01:09:50 +00001340 (const u_char *)rawlspid_print (adj->sysid),
hassof390d2c2004-09-10 20:48:21 +00001341 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 :
Paul Jakma41b36e92006-12-08 01:09:50 +00001347 (const u_char *) rawlspid_print (vertex->N.id),
hassof390d2c2004-09-10 20:48:21 +00001348 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}