blob: ac4c71f3f503cd4645c9a7695c7f61f2dcd92924 [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{
paul1eb8ef22005-04-07 07:30:20 +000065 struct listnode *node, *nnode, *excess = NULL;
jardineb5d44e2003-12-23 08:09:43 +000066 struct isis_adjacency *adj, *candidate = NULL;
67 int comp;
68
paul1eb8ef22005-04-07 07:30:20 +000069 for (ALL_LIST_ELEMENTS (adjs, node, nnode, 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
198 tree = XMALLOC (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 memset (tree, 0, sizeof (struct isis_spftree));
205
206 tree->tents = list_new ();
hassof390d2c2004-09-10 20:48:21 +0000207 tree->paths = list_new ();
jardineb5d44e2003-12-23 08:09:43 +0000208 return tree;
209}
210
hasso92365882005-01-18 13:53:33 +0000211static void
jardineb5d44e2003-12-23 08:09:43 +0000212isis_vertex_del (struct isis_vertex *vertex)
213{
jardineb5d44e2003-12-23 08:09:43 +0000214 list_delete (vertex->Adj_N);
215
216 XFREE (MTYPE_ISIS_VERTEX, vertex);
hassof390d2c2004-09-10 20:48:21 +0000217
jardineb5d44e2003-12-23 08:09:43 +0000218 return;
219}
220
hasso92365882005-01-18 13:53:33 +0000221#if 0 /* HT: Not used yet. */
222static void
jardineb5d44e2003-12-23 08:09:43 +0000223isis_spftree_del (struct isis_spftree *spftree)
224{
hassof7c43dc2004-09-26 16:24:14 +0000225 spftree->tents->del = (void (*)(void *)) isis_vertex_del;
jardineb5d44e2003-12-23 08:09:43 +0000226 list_delete (spftree->tents);
hassof390d2c2004-09-10 20:48:21 +0000227
hassof7c43dc2004-09-26 16:24:14 +0000228 spftree->paths->del = (void (*)(void *)) isis_vertex_del;
jardineb5d44e2003-12-23 08:09:43 +0000229 list_delete (spftree->paths);
230
231 XFREE (MTYPE_ISIS_SPFTREE, spftree);
232
233 return;
234}
hasso92365882005-01-18 13:53:33 +0000235#endif
jardineb5d44e2003-12-23 08:09:43 +0000236
hassof390d2c2004-09-10 20:48:21 +0000237void
jardineb5d44e2003-12-23 08:09:43 +0000238spftree_area_init (struct isis_area *area)
239{
hassof390d2c2004-09-10 20:48:21 +0000240 if ((area->is_type & IS_LEVEL_1) && area->spftree[0] == NULL)
241 {
242 area->spftree[0] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000243#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000244 area->spftree6[0] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000245#endif
246
hassof390d2c2004-09-10 20:48:21 +0000247 /* thread_add_timer (master, isis_run_spf_l1, area,
248 isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */
249 }
250
251 if ((area->is_type & IS_LEVEL_2) && area->spftree[1] == NULL)
252 {
253 area->spftree[1] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000254#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000255 area->spftree6[1] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000256#endif
hassof390d2c2004-09-10 20:48:21 +0000257 /* thread_add_timer (master, isis_run_spf_l2, area,
258 isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */
259 }
jardineb5d44e2003-12-23 08:09:43 +0000260
261 return;
262}
263
hasso92365882005-01-18 13:53:33 +0000264static struct isis_vertex *
jardineb5d44e2003-12-23 08:09:43 +0000265isis_vertex_new (void *id, enum vertextype vtype)
266{
267 struct isis_vertex *vertex;
268
269 vertex = XMALLOC (MTYPE_ISIS_VERTEX, sizeof (struct isis_vertex));
hassof390d2c2004-09-10 20:48:21 +0000270 if (vertex == NULL)
271 {
272 zlog_err ("isis_vertex_new Out of memory!");
273 return NULL;
274 }
275
jardineb5d44e2003-12-23 08:09:43 +0000276 memset (vertex, 0, sizeof (struct isis_vertex));
277 vertex->type = vtype;
hassof390d2c2004-09-10 20:48:21 +0000278 switch (vtype)
279 {
280 case VTYPE_ES:
281 case VTYPE_NONPSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000282 case VTYPE_NONPSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000283 memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN);
284 break;
285 case VTYPE_PSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000286 case VTYPE_PSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000287 memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN + 1);
288 break;
289 case VTYPE_IPREACH_INTERNAL:
290 case VTYPE_IPREACH_EXTERNAL:
hasso82a84282005-09-26 18:15:36 +0000291 case VTYPE_IPREACH_TE:
jardineb5d44e2003-12-23 08:09:43 +0000292#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000293 case VTYPE_IP6REACH_INTERNAL:
294 case VTYPE_IP6REACH_EXTERNAL:
295#endif /* HAVE_IPV6 */
296 memcpy (&vertex->N.prefix, (struct prefix *) id,
297 sizeof (struct prefix));
298 break;
299 default:
300 zlog_err ("WTF!");
301 }
jardineb5d44e2003-12-23 08:09:43 +0000302
303 vertex->Adj_N = list_new ();
hassof390d2c2004-09-10 20:48:21 +0000304
jardineb5d44e2003-12-23 08:09:43 +0000305 return vertex;
306}
307
308/*
309 * Add this IS to the root of SPT
310 */
hasso92365882005-01-18 13:53:33 +0000311static void
jardineb5d44e2003-12-23 08:09:43 +0000312isis_spf_add_self (struct isis_spftree *spftree, struct isis_area *area,
hassof390d2c2004-09-10 20:48:21 +0000313 int level)
jardineb5d44e2003-12-23 08:09:43 +0000314{
315 struct isis_vertex *vertex;
316 struct isis_lsp *lsp;
317 u_char lspid[ISIS_SYS_ID_LEN + 2];
318#ifdef EXTREME_DEBUG
319 u_char buff[BUFSIZ];
320#endif /* EXTREME_DEBUG */
321 memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN);
hassof390d2c2004-09-10 20:48:21 +0000322 LSP_PSEUDO_ID (lspid) = 0;
323 LSP_FRAGMENT (lspid) = 0;
324
jardineb5d44e2003-12-23 08:09:43 +0000325 lsp = lsp_search (lspid, area->lspdb[level - 1]);
hassof390d2c2004-09-10 20:48:21 +0000326
jardineb5d44e2003-12-23 08:09:43 +0000327 if (lsp == NULL)
328 zlog_warn ("ISIS-Spf: could not find own l%d LSP!", level);
hassof390d2c2004-09-10 20:48:21 +0000329
hasso82a84282005-09-26 18:15:36 +0000330 if (!area->oldmetric)
331 vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_TE_IS);
332 else
333 vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_IS);
334
jardineb5d44e2003-12-23 08:09:43 +0000335 vertex->lsp = lsp;
336
337 listnode_add (spftree->paths, vertex);
338
339#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000340 zlog_debug ("ISIS-Spf: added this IS %s %s depth %d dist %d to PATHS",
341 vtype2string (vertex->type), vid2string (vertex, buff),
342 vertex->depth, vertex->d_N);
jardineb5d44e2003-12-23 08:09:43 +0000343#endif /* EXTREME_DEBUG */
344
345 return;
346}
347
hasso92365882005-01-18 13:53:33 +0000348static struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000349isis_find_vertex (struct list *list, void *id, enum vertextype vtype)
jardineb5d44e2003-12-23 08:09:43 +0000350{
351 struct listnode *node;
352 struct isis_vertex *vertex;
353 struct prefix *p1, *p2;
354
paul1eb8ef22005-04-07 07:30:20 +0000355 for (ALL_LIST_ELEMENTS_RO (list, node, vertex))
hassof390d2c2004-09-10 20:48:21 +0000356 {
hassof390d2c2004-09-10 20:48:21 +0000357 if (vertex->type != vtype)
358 continue;
359 switch (vtype)
360 {
361 case VTYPE_ES:
362 case VTYPE_NONPSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000363 case VTYPE_NONPSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000364 if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN) == 0)
365 return vertex;
366 break;
367 case VTYPE_PSEUDO_IS:
hasso82a84282005-09-26 18:15:36 +0000368 case VTYPE_PSEUDO_TE_IS:
hassof390d2c2004-09-10 20:48:21 +0000369 if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN + 1) == 0)
370 return vertex;
371 break;
372 case VTYPE_IPREACH_INTERNAL:
373 case VTYPE_IPREACH_EXTERNAL:
hasso82a84282005-09-26 18:15:36 +0000374 case VTYPE_IPREACH_TE:
jardineb5d44e2003-12-23 08:09:43 +0000375#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000376 case VTYPE_IP6REACH_INTERNAL:
377 case VTYPE_IP6REACH_EXTERNAL:
jardineb5d44e2003-12-23 08:09:43 +0000378#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000379 p1 = (struct prefix *) id;
380 p2 = (struct prefix *) &vertex->N.id;
381 if (p1->family == p2->family && p1->prefixlen == p2->prefixlen &&
382 memcmp (&p1->u.prefix, &p2->u.prefix,
383 PSIZE (p1->prefixlen)) == 0)
384 return vertex;
385 break;
386 }
jardineb5d44e2003-12-23 08:09:43 +0000387 }
jardineb5d44e2003-12-23 08:09:43 +0000388
389 return NULL;
390}
391
jardineb5d44e2003-12-23 08:09:43 +0000392/*
393 * Add a vertex to TENT sorted by cost and by vertextype on tie break situation
394 */
hasso92365882005-01-18 13:53:33 +0000395static struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000396isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype,
397 void *id, struct isis_adjacency *adj, u_int16_t cost,
398 int depth, int family)
jardineb5d44e2003-12-23 08:09:43 +0000399{
400 struct isis_vertex *vertex, *v;
401 struct listnode *node;
hassof390d2c2004-09-10 20:48:21 +0000402#ifdef EXTREME_DEBUG
jardineb5d44e2003-12-23 08:09:43 +0000403 u_char buff[BUFSIZ];
404#endif
405
406 vertex = isis_vertex_new (id, vtype);
407 vertex->d_N = cost;
408 vertex->depth = depth;
hassof390d2c2004-09-10 20:48:21 +0000409
jardineb5d44e2003-12-23 08:09:43 +0000410 if (adj)
411 listnode_add (vertex->Adj_N, adj);
hassof390d2c2004-09-10 20:48:21 +0000412#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000413 zlog_debug ("ISIS-Spf: add to TENT %s %s depth %d dist %d",
414 vtype2string (vertex->type), vid2string (vertex, buff),
415 vertex->depth, vertex->d_N);
jardineb5d44e2003-12-23 08:09:43 +0000416#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000417 listnode_add (spftree->tents, vertex);
418 if (list_isempty (spftree->tents))
419 {
420 listnode_add (spftree->tents, vertex);
421 return vertex;
jardineb5d44e2003-12-23 08:09:43 +0000422 }
paul1eb8ef22005-04-07 07:30:20 +0000423
424 /* XXX: This cant use the standard ALL_LIST_ELEMENT macro */
425 for (node = listhead (spftree->tents); node; node = listnextnode (node))
hassof390d2c2004-09-10 20:48:21 +0000426 {
paul1eb8ef22005-04-07 07:30:20 +0000427 v = listgetdata (node);
hassof390d2c2004-09-10 20:48:21 +0000428 if (v->d_N > vertex->d_N)
429 {
430 list_add_node_prev (spftree->tents, node, vertex);
431 break;
432 }
433 else if (v->d_N == vertex->d_N)
434 {
435 /* Tie break, add according to type */
436 while (v && v->d_N == vertex->d_N && v->type > vertex->type)
437 {
438 if (v->type > vertex->type)
439 {
440 break;
441 }
paul1eb8ef22005-04-07 07:30:20 +0000442 /* XXX: this seems dubious, node is the loop iterator */
443 node = listnextnode (node);
444 (node) ? (v = listgetdata (node)) : (v = NULL);
hassof390d2c2004-09-10 20:48:21 +0000445 }
446 list_add_node_prev (spftree->tents, node, vertex);
447 break;
448 }
449 else if (node->next == NULL)
450 {
451 list_add_node_next (spftree->tents, node, vertex);
452 break;
453 }
454 }
jardineb5d44e2003-12-23 08:09:43 +0000455 return vertex;
456}
457
hasso92365882005-01-18 13:53:33 +0000458static struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000459isis_spf_add_local (struct isis_spftree *spftree, enum vertextype vtype,
460 void *id, struct isis_adjacency *adj, u_int16_t cost,
461 int family)
jardineb5d44e2003-12-23 08:09:43 +0000462{
463 struct isis_vertex *vertex;
jardineb5d44e2003-12-23 08:09:43 +0000464
hassof390d2c2004-09-10 20:48:21 +0000465 vertex = isis_find_vertex (spftree->tents, id, vtype);
466
467 if (vertex)
468 {
469 /* C.2.5 c) */
470 if (vertex->d_N == cost)
471 {
472 if (adj)
473 listnode_add (vertex->Adj_N, adj);
474 /* d) */
475 if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
476 remove_excess_adjs (vertex->Adj_N);
477 }
478 /* f) */
479 else if (vertex->d_N > cost)
480 {
481 listnode_delete (spftree->tents, vertex);
482 goto add2tent;
483 }
484 /* e) do nothing */
485 return vertex;
486 }
487
488add2tent:
jardineb5d44e2003-12-23 08:09:43 +0000489 return isis_spf_add2tent (spftree, vtype, id, adj, cost, 1, family);
490}
491
hasso92365882005-01-18 13:53:33 +0000492static void
hassof390d2c2004-09-10 20:48:21 +0000493process_N (struct isis_spftree *spftree, enum vertextype vtype, void *id,
494 u_int16_t dist, u_int16_t depth, struct isis_adjacency *adj,
495 int family)
jardineb5d44e2003-12-23 08:09:43 +0000496{
497 struct isis_vertex *vertex;
498#ifdef EXTREME_DEBUG
499 u_char buff[255];
500#endif
501
502 /* C.2.6 b) */
503 if (dist > MAX_PATH_METRIC)
504 return;
505 /* c) */
506 vertex = isis_find_vertex (spftree->paths, id, vtype);
hassof390d2c2004-09-10 20:48:21 +0000507 if (vertex)
508 {
jardineb5d44e2003-12-23 08:09:43 +0000509#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000510 zlog_debug ("ISIS-Spf: process_N %s %s dist %d already found from PATH",
511 vtype2string (vtype), vid2string (vertex, buff), dist);
jardineb5d44e2003-12-23 08:09:43 +0000512#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000513 assert (dist >= vertex->d_N);
514 return;
515 }
jardineb5d44e2003-12-23 08:09:43 +0000516
517 vertex = isis_find_vertex (spftree->tents, id, vtype);
hassof390d2c2004-09-10 20:48:21 +0000518 /* d) */
519 if (vertex)
520 {
521 /* 1) */
jardineb5d44e2003-12-23 08:09:43 +0000522#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000523 zlog_debug ("ISIS-Spf: process_N %s %s dist %d",
524 vtype2string (vtype), vid2string (vertex, buff), dist);
jardineb5d44e2003-12-23 08:09:43 +0000525#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000526 if (vertex->d_N == dist)
527 {
528 if (adj)
529 listnode_add (vertex->Adj_N, adj);
530 /* 2) */
531 if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
532 remove_excess_adjs (vertex->Adj_N);
533 /* 3) */
534 return;
535 }
536 else if (vertex->d_N < dist)
537 {
538 return;
539 /* 4) */
540 }
541 else
542 {
543 listnode_delete (spftree->tents, vertex);
544 }
jardineb5d44e2003-12-23 08:09:43 +0000545 }
hassof390d2c2004-09-10 20:48:21 +0000546
jardineb5d44e2003-12-23 08:09:43 +0000547 isis_spf_add2tent (spftree, vtype, id, adj, dist, depth, family);
548 return;
549}
550
551/*
552 * C.2.6 Step 1
553 */
hasso92365882005-01-18 13:53:33 +0000554static int
hassof390d2c2004-09-10 20:48:21 +0000555isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp,
556 uint16_t cost, uint16_t depth, int family)
jardineb5d44e2003-12-23 08:09:43 +0000557{
558 struct listnode *node, *fragnode = NULL;
559 u_int16_t dist;
560 struct is_neigh *is_neigh;
hasso82a84282005-09-26 18:15:36 +0000561 struct te_is_neigh *te_is_neigh;
jardineb5d44e2003-12-23 08:09:43 +0000562 struct ipv4_reachability *ipreach;
hasso82a84282005-09-26 18:15:36 +0000563 struct te_ipv4_reachability *te_ipv4_reach;
jardineb5d44e2003-12-23 08:09:43 +0000564 enum vertextype vtype;
565 struct prefix prefix;
566#ifdef HAVE_IPV6
567 struct ipv6_reachability *ip6reach;
568#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000569
jardineb5d44e2003-12-23 08:09:43 +0000570
571 if (!lsp->adj)
572 return ISIS_WARNING;
hassof390d2c2004-09-10 20:48:21 +0000573 if (lsp->tlv_data.nlpids == NULL || !speaks (lsp->tlv_data.nlpids, family))
jardineb5d44e2003-12-23 08:09:43 +0000574 return ISIS_OK;
575
hassof390d2c2004-09-10 20:48:21 +0000576lspfragloop:
577 if (lsp->lsp_header->seq_num == 0)
578 {
579 zlog_warn ("isis_spf_process_lsp(): lsp with 0 seq_num"
580 " - do not process");
581 return ISIS_WARNING;
582 }
jardineb5d44e2003-12-23 08:09:43 +0000583
hassof390d2c2004-09-10 20:48:21 +0000584 if (!ISIS_MASK_LSP_OL_BIT (lsp->lsp_header->lsp_bits))
585 {
586 if (lsp->tlv_data.is_neighs)
587 {
paul1eb8ef22005-04-07 07:30:20 +0000588 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh))
hassof390d2c2004-09-10 20:48:21 +0000589 {
hassof390d2c2004-09-10 20:48:21 +0000590 /* C.2.6 a) */
591 /* Two way connectivity */
592 if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
593 continue;
594 dist = cost + is_neigh->metrics.metric_default;
595 vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
596 : VTYPE_NONPSEUDO_IS;
597 process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist,
598 depth + 1, lsp->adj, family);
599 }
600 }
hasso82a84282005-09-26 18:15:36 +0000601 if (lsp->tlv_data.te_is_neighs)
602 {
603 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node,
604 te_is_neigh))
605 {
606 uint32_t metric;
607 if (!memcmp (te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
608 continue;
609 memcpy (&metric, te_is_neigh->te_metric, 3);
610 dist = cost + ntohl (metric << 8);
611 vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS
612 : VTYPE_NONPSEUDO_TE_IS;
613 process_N (spftree, vtype, (void *) te_is_neigh->neigh_id, dist,
614 depth + 1, lsp->adj, family);
615 }
616 }
hassof390d2c2004-09-10 20:48:21 +0000617 if (family == AF_INET && lsp->tlv_data.ipv4_int_reachs)
618 {
619 prefix.family = AF_INET;
paul1eb8ef22005-04-07 07:30:20 +0000620 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_int_reachs,
621 node, ipreach))
hassof390d2c2004-09-10 20:48:21 +0000622 {
hassof390d2c2004-09-10 20:48:21 +0000623 dist = cost + ipreach->metrics.metric_default;
624 vtype = VTYPE_IPREACH_INTERNAL;
625 prefix.u.prefix4 = ipreach->prefix;
626 prefix.prefixlen = ip_masklen (ipreach->mask);
627 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
628 lsp->adj, family);
629 }
630 }
631
632 if (family == AF_INET && lsp->tlv_data.ipv4_ext_reachs)
633 {
634 prefix.family = AF_INET;
paul1eb8ef22005-04-07 07:30:20 +0000635 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_ext_reachs,
636 node, ipreach))
hassof390d2c2004-09-10 20:48:21 +0000637 {
hassof390d2c2004-09-10 20:48:21 +0000638 dist = cost + ipreach->metrics.metric_default;
639 vtype = VTYPE_IPREACH_EXTERNAL;
640 prefix.u.prefix4 = ipreach->prefix;
641 prefix.prefixlen = ip_masklen (ipreach->mask);
642 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
643 lsp->adj, family);
644 }
645 }
hasso82a84282005-09-26 18:15:36 +0000646 if (family == AF_INET && lsp->tlv_data.te_ipv4_reachs)
647 {
648 prefix.family = AF_INET;
649 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_ipv4_reachs,
650 node, te_ipv4_reach))
651 {
652 dist = cost + ntohl (te_ipv4_reach->te_metric);
653 vtype = VTYPE_IPREACH_TE;
654 prefix.u.prefix4 = newprefix2inaddr (&te_ipv4_reach->prefix_start,
655 te_ipv4_reach->control);
656 prefix.prefixlen = (te_ipv4_reach->control & 0x3F);
657 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
658 lsp->adj, family);
659 }
660 }
jardineb5d44e2003-12-23 08:09:43 +0000661#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000662 if (family == AF_INET6 && lsp->tlv_data.ipv6_reachs)
663 {
664 prefix.family = AF_INET6;
paul1eb8ef22005-04-07 07:30:20 +0000665 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv6_reachs,
666 node, ip6reach))
hassof390d2c2004-09-10 20:48:21 +0000667 {
hassof390d2c2004-09-10 20:48:21 +0000668 dist = cost + ip6reach->metric;
669 vtype = (ip6reach->control_info & CTRL_INFO_DISTRIBUTION) ?
670 VTYPE_IP6REACH_EXTERNAL : VTYPE_IP6REACH_INTERNAL;
671 prefix.prefixlen = ip6reach->prefix_len;
672 memcpy (&prefix.u.prefix6.s6_addr, ip6reach->prefix,
673 PSIZE (ip6reach->prefix_len));
674 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
675 lsp->adj, family);
676 }
677 }
jardineb5d44e2003-12-23 08:09:43 +0000678#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000679 }
680
jardineb5d44e2003-12-23 08:09:43 +0000681 if (fragnode == NULL)
682 fragnode = listhead (lsp->lspu.frags);
hassof390d2c2004-09-10 20:48:21 +0000683 else
paul1eb8ef22005-04-07 07:30:20 +0000684 fragnode = listnextnode (fragnode);
jardineb5d44e2003-12-23 08:09:43 +0000685
hassof390d2c2004-09-10 20:48:21 +0000686 if (fragnode)
687 {
paul1eb8ef22005-04-07 07:30:20 +0000688 lsp = listgetdata (fragnode);
hassof390d2c2004-09-10 20:48:21 +0000689 goto lspfragloop;
690 }
691
jardineb5d44e2003-12-23 08:09:43 +0000692 return ISIS_OK;
693}
694
hasso92365882005-01-18 13:53:33 +0000695static int
hassof390d2c2004-09-10 20:48:21 +0000696isis_spf_process_pseudo_lsp (struct isis_spftree *spftree,
697 struct isis_lsp *lsp, uint16_t cost,
698 uint16_t depth, int family)
jardineb5d44e2003-12-23 08:09:43 +0000699{
paul1eb8ef22005-04-07 07:30:20 +0000700 struct listnode *node, *nnode, *fragnode = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000701 struct is_neigh *is_neigh;
hasso82a84282005-09-26 18:15:36 +0000702 struct te_is_neigh *te_is_neigh;
jardineb5d44e2003-12-23 08:09:43 +0000703 enum vertextype vtype;
hassof390d2c2004-09-10 20:48:21 +0000704
705pseudofragloop:
706
707 if (lsp->lsp_header->seq_num == 0)
708 {
709 zlog_warn ("isis_spf_process_pseudo_lsp(): lsp with 0 seq_num"
710 " - do not process");
711 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +0000712 }
hassof390d2c2004-09-10 20:48:21 +0000713
hasso82a84282005-09-26 18:15:36 +0000714 if (lsp->tlv_data.is_neighs)
715 for (ALL_LIST_ELEMENTS (lsp->tlv_data.is_neighs, node, nnode, is_neigh))
716 {
717 vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
718 : VTYPE_NONPSEUDO_IS;
719 /* Two way connectivity */
720 if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
721 continue;
722 if (isis_find_vertex
723 (spftree->tents, (void *) is_neigh->neigh_id, vtype) == NULL
724 && isis_find_vertex (spftree->paths, (void *) is_neigh->neigh_id,
hassof390d2c2004-09-10 20:48:21 +0000725 vtype) == NULL)
hasso82a84282005-09-26 18:15:36 +0000726 {
727 /* C.2.5 i) */
728 isis_spf_add2tent (spftree, vtype, is_neigh->neigh_id, lsp->adj,
hassof390d2c2004-09-10 20:48:21 +0000729 cost, depth, family);
hasso82a84282005-09-26 18:15:36 +0000730 }
731 }
732 if (lsp->tlv_data.te_is_neighs)
733 for (ALL_LIST_ELEMENTS (lsp->tlv_data.te_is_neighs, node, nnode, te_is_neigh))
734 {
735 vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS
736 : VTYPE_NONPSEUDO_TE_IS;
737 /* Two way connectivity */
738 if (!memcmp (te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
739 continue;
740 if (isis_find_vertex
741 (spftree->tents, (void *) te_is_neigh->neigh_id, vtype) == NULL
742 && isis_find_vertex (spftree->paths, (void *) te_is_neigh->neigh_id,
743 vtype) == NULL)
744 {
745 /* C.2.5 i) */
746 isis_spf_add2tent (spftree, vtype, te_is_neigh->neigh_id, lsp->adj,
747 cost, depth, family);
748 }
749 }
hassof390d2c2004-09-10 20:48:21 +0000750
jardineb5d44e2003-12-23 08:09:43 +0000751 if (fragnode == NULL)
752 fragnode = listhead (lsp->lspu.frags);
hassof390d2c2004-09-10 20:48:21 +0000753 else
paul1eb8ef22005-04-07 07:30:20 +0000754 fragnode = listnextnode (fragnode);
jardineb5d44e2003-12-23 08:09:43 +0000755
hassof390d2c2004-09-10 20:48:21 +0000756 if (fragnode)
757 {
paul1eb8ef22005-04-07 07:30:20 +0000758 lsp = listgetdata (fragnode);
hassof390d2c2004-09-10 20:48:21 +0000759 goto pseudofragloop;
760 }
jardineb5d44e2003-12-23 08:09:43 +0000761
jardineb5d44e2003-12-23 08:09:43 +0000762 return ISIS_OK;
763}
hassof390d2c2004-09-10 20:48:21 +0000764
hasso92365882005-01-18 13:53:33 +0000765static int
hassof390d2c2004-09-10 20:48:21 +0000766isis_spf_preload_tent (struct isis_spftree *spftree,
767 struct isis_area *area, int level, int family)
jardineb5d44e2003-12-23 08:09:43 +0000768{
769 struct isis_vertex *vertex;
770 struct isis_circuit *circuit;
paul1eb8ef22005-04-07 07:30:20 +0000771 struct listnode *cnode, *cnnode;
772 struct listnode *anode;
773 struct listnode *ipnode, *ipnnode;
jardineb5d44e2003-12-23 08:09:43 +0000774 struct isis_adjacency *adj;
775 struct isis_lsp *lsp;
776 struct list *adj_list;
777 struct list *adjdb;
778 struct prefix_ipv4 *ipv4;
779 struct prefix prefix;
780 int retval = ISIS_OK;
781 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
782#ifdef HAVE_IPV6
783 struct prefix_ipv6 *ipv6;
784#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000785
paul1eb8ef22005-04-07 07:30:20 +0000786 for (ALL_LIST_ELEMENTS (area->circuit_list, cnode, cnnode, circuit))
hassof390d2c2004-09-10 20:48:21 +0000787 {
hassof390d2c2004-09-10 20:48:21 +0000788 if (circuit->state != C_STATE_UP)
jardineb5d44e2003-12-23 08:09:43 +0000789 continue;
hassof390d2c2004-09-10 20:48:21 +0000790 if (!(circuit->circuit_is_type & level))
791 continue;
792 if (family == AF_INET && !circuit->ip_router)
793 continue;
794#ifdef HAVE_IPV6
795 if (family == AF_INET6 && !circuit->ipv6_router)
796 continue;
797#endif /* HAVE_IPV6 */
798 /*
799 * Add IP(v6) addresses of this circuit
jardineb5d44e2003-12-23 08:09:43 +0000800 */
hassof390d2c2004-09-10 20:48:21 +0000801 if (family == AF_INET)
802 {
803 prefix.family = AF_INET;
paul1eb8ef22005-04-07 07:30:20 +0000804 for (ALL_LIST_ELEMENTS (circuit->ip_addrs, ipnode, ipnnode, ipv4))
hassof390d2c2004-09-10 20:48:21 +0000805 {
hassof390d2c2004-09-10 20:48:21 +0000806 prefix.u.prefix4 = ipv4->prefix;
807 prefix.prefixlen = ipv4->prefixlen;
808 isis_spf_add_local (spftree, VTYPE_IPREACH_INTERNAL, &prefix,
809 NULL, 0, family);
810 }
811 }
812#ifdef HAVE_IPV6
813 if (family == AF_INET6)
814 {
815 prefix.family = AF_INET6;
paul1eb8ef22005-04-07 07:30:20 +0000816 for (ALL_LIST_ELEMENTS (circuit->ipv6_non_link,
817 ipnode, ipnnode, ipv6))
hassof390d2c2004-09-10 20:48:21 +0000818 {
hassof390d2c2004-09-10 20:48:21 +0000819 prefix.prefixlen = ipv6->prefixlen;
820 prefix.u.prefix6 = ipv6->prefix;
821 isis_spf_add_local (spftree, VTYPE_IP6REACH_INTERNAL,
822 &prefix, NULL, 0, family);
823 }
824 }
825#endif /* HAVE_IPV6 */
826 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
827 {
828 /*
829 * Add the adjacencies
830 */
831 adj_list = list_new ();
832 adjdb = circuit->u.bc.adjdb[level - 1];
833 isis_adj_build_up_list (adjdb, adj_list);
834 if (listcount (adj_list) == 0)
835 {
836 list_delete (adj_list);
hassoc89c05d2005-09-04 21:36:36 +0000837 if (isis->debugs & DEBUG_SPF_EVENTS)
838 zlog_debug ("ISIS-Spf: no L%d adjacencies on circuit %s",
839 level, circuit->interface->name);
hassof390d2c2004-09-10 20:48:21 +0000840 continue;
841 }
842 anode = listhead (adj_list);
843 while (anode)
844 {
paul1eb8ef22005-04-07 07:30:20 +0000845 adj = listgetdata (anode);
hassof390d2c2004-09-10 20:48:21 +0000846 if (!speaks (&adj->nlpids, family))
847 {
paul1eb8ef22005-04-07 07:30:20 +0000848 anode = listnextnode (anode);
hassof390d2c2004-09-10 20:48:21 +0000849 continue;
850 }
851 switch (adj->sys_type)
852 {
853 case ISIS_SYSTYPE_ES:
854 isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
hasso82a84282005-09-26 18:15:36 +0000855 circuit->te_metric[level - 1], family);
hassof390d2c2004-09-10 20:48:21 +0000856 break;
857 case ISIS_SYSTYPE_IS:
858 case ISIS_SYSTYPE_L1_IS:
859 case ISIS_SYSTYPE_L2_IS:
860 vertex =
861 isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS,
862 adj->sysid, adj,
hasso82a84282005-09-26 18:15:36 +0000863 circuit->te_metric[level - 1], family);
hassof390d2c2004-09-10 20:48:21 +0000864 memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN);
865 LSP_PSEUDO_ID (lsp_id) = 0;
866 LSP_FRAGMENT (lsp_id) = 0;
867 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
868 if (!lsp)
869 zlog_warn ("No lsp found for IS adjacency");
870 /* else {
871 isis_spf_process_lsp (spftree, lsp, vertex->d_N, 1, family);
872 } */
873 break;
874 case ISIS_SYSTYPE_UNKNOWN:
875 default:
876 zlog_warn ("isis_spf_preload_tent unknow adj type");
877 }
paul1eb8ef22005-04-07 07:30:20 +0000878 anode = listnextnode (anode);
hassof390d2c2004-09-10 20:48:21 +0000879 }
880 list_delete (adj_list);
881 /*
882 * Add the pseudonode
883 */
884 if (level == 1)
885 memcpy (lsp_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
886 else
887 memcpy (lsp_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
888 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
889 adj = isis_adj_lookup (lsp_id, adjdb);
890 /* if no adj, we are the dis or error */
891 if (!adj && !circuit->u.bc.is_dr[level - 1])
892 {
893 zlog_warn ("ISIS-Spf: No adjacency found for DR");
894 }
895 if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0)
896 {
897 zlog_warn ("ISIS-Spf: No lsp found for DR");
898 }
899 else
900 {
hasso82a84282005-09-26 18:15:36 +0000901 isis_spf_process_pseudo_lsp (spftree, lsp,
902 circuit->te_metric[level - 1], 0, family);
hassof390d2c2004-09-10 20:48:21 +0000903
904 }
905 }
906 else if (circuit->circ_type == CIRCUIT_T_P2P)
907 {
908 adj = circuit->u.p2p.neighbor;
909 if (!adj)
910 continue;
911 switch (adj->sys_type)
912 {
913 case ISIS_SYSTYPE_ES:
914 isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
hasso82a84282005-09-26 18:15:36 +0000915 circuit->te_metric[level - 1], family);
hassof390d2c2004-09-10 20:48:21 +0000916 break;
917 case ISIS_SYSTYPE_IS:
918 case ISIS_SYSTYPE_L1_IS:
919 case ISIS_SYSTYPE_L2_IS:
920 if (speaks (&adj->nlpids, family))
921 isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS, adj->sysid,
hasso82a84282005-09-26 18:15:36 +0000922 adj, circuit->te_metric[level - 1],
hassof390d2c2004-09-10 20:48:21 +0000923 family);
924 break;
925 case ISIS_SYSTYPE_UNKNOWN:
926 default:
927 zlog_warn ("isis_spf_preload_tent unknow adj type");
928 break;
929 }
930 }
jardineb5d44e2003-12-23 08:09:43 +0000931 else
hassof390d2c2004-09-10 20:48:21 +0000932 {
933 zlog_warn ("isis_spf_preload_tent unsupported media");
934 retval = ISIS_WARNING;
935 }
936
jardineb5d44e2003-12-23 08:09:43 +0000937 }
jardineb5d44e2003-12-23 08:09:43 +0000938
939 return retval;
940}
941
942/*
943 * The parent(s) for vertex is set when added to TENT list
944 * now we just put the child pointer(s) in place
945 */
hasso92365882005-01-18 13:53:33 +0000946static void
jardineb5d44e2003-12-23 08:09:43 +0000947add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex,
hassof390d2c2004-09-10 20:48:21 +0000948 struct isis_area *area)
jardineb5d44e2003-12-23 08:09:43 +0000949{
jardineb5d44e2003-12-23 08:09:43 +0000950#ifdef EXTREME_DEBUG
951 u_char buff[BUFSIZ];
952#endif /* EXTREME_DEBUG */
953 listnode_add (spftree->paths, vertex);
954
hassof390d2c2004-09-10 20:48:21 +0000955#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000956 zlog_debug ("ISIS-Spf: added %s %s depth %d dist %d to PATHS",
957 vtype2string (vertex->type), vid2string (vertex, buff),
958 vertex->depth, vertex->d_N);
hassof390d2c2004-09-10 20:48:21 +0000959#endif /* EXTREME_DEBUG */
960 if (vertex->type > VTYPE_ES)
961 {
962 if (listcount (vertex->Adj_N) > 0)
963 isis_route_create ((struct prefix *) &vertex->N.prefix,
964 vertex->d_N, vertex->depth, vertex->Adj_N, area);
965 else if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000966 zlog_debug ("ISIS-Spf: no adjacencies do not install route");
hassof390d2c2004-09-10 20:48:21 +0000967 }
968
jardineb5d44e2003-12-23 08:09:43 +0000969 return;
970}
971
hasso92365882005-01-18 13:53:33 +0000972static void
jardineb5d44e2003-12-23 08:09:43 +0000973init_spt (struct isis_spftree *spftree)
974{
hassof7c43dc2004-09-26 16:24:14 +0000975 spftree->tents->del = spftree->paths->del = (void (*)(void *)) isis_vertex_del;
jardineb5d44e2003-12-23 08:09:43 +0000976 list_delete_all_node (spftree->tents);
977 list_delete_all_node (spftree->paths);
978 spftree->tents->del = spftree->paths->del = NULL;
hassof390d2c2004-09-10 20:48:21 +0000979
jardineb5d44e2003-12-23 08:09:43 +0000980 return;
981}
982
hasso92365882005-01-18 13:53:33 +0000983static int
jardineb5d44e2003-12-23 08:09:43 +0000984isis_run_spf (struct isis_area *area, int level, int family)
985{
986 int retval = ISIS_OK;
987 struct listnode *node;
988 struct isis_vertex *vertex;
hassof390d2c2004-09-10 20:48:21 +0000989 struct isis_spftree *spftree = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000990 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
991 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +0000992
jardineb5d44e2003-12-23 08:09:43 +0000993 if (family == AF_INET)
994 spftree = area->spftree[level - 1];
995#ifdef HAVE_IPV6
996 else if (family == AF_INET6)
997 spftree = area->spftree6[level - 1];
998#endif
hassof390d2c2004-09-10 20:48:21 +0000999
jardineb5d44e2003-12-23 08:09:43 +00001000 assert (spftree);
1001
1002 /*
1003 * C.2.5 Step 0
1004 */
1005 init_spt (spftree);
1006 /* a) */
1007 isis_spf_add_self (spftree, area, level);
1008 /* b) */
1009 retval = isis_spf_preload_tent (spftree, area, level, family);
hassof390d2c2004-09-10 20:48:21 +00001010
jardineb5d44e2003-12-23 08:09:43 +00001011 /*
1012 * C.2.7 Step 2
1013 */
hassof390d2c2004-09-10 20:48:21 +00001014 if (listcount (spftree->tents) == 0)
1015 {
1016 zlog_warn ("ISIS-Spf: TENT is empty");
1017 spftree->lastrun = time (NULL);
1018 return retval;
jardineb5d44e2003-12-23 08:09:43 +00001019 }
hassof390d2c2004-09-10 20:48:21 +00001020
1021 while (listcount (spftree->tents) > 0)
1022 {
1023 node = listhead (spftree->tents);
paul1eb8ef22005-04-07 07:30:20 +00001024 vertex = listgetdata (node);
hassof390d2c2004-09-10 20:48:21 +00001025 /* Remove from tent list */
1026 list_delete_node (spftree->tents, node);
1027 if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type))
1028 continue;
1029 add_to_paths (spftree, vertex, area);
1030 if (vertex->type == VTYPE_PSEUDO_IS ||
1031 vertex->type == VTYPE_NONPSEUDO_IS)
1032 {
1033 memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
1034 LSP_FRAGMENT (lsp_id) = 0;
1035 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
1036 if (lsp)
1037 {
1038 if (LSP_PSEUDO_ID (lsp_id))
1039 {
1040 isis_spf_process_pseudo_lsp (spftree, lsp, vertex->d_N,
1041 vertex->depth, family);
1042
1043 }
1044 else
1045 {
1046 isis_spf_process_lsp (spftree, lsp, vertex->d_N,
1047 vertex->depth, family);
1048 }
1049 }
1050 else
1051 {
1052 zlog_warn ("ISIS-Spf: No LSP found for %s",
1053 rawlspid_print (lsp_id));
1054 }
1055 }
1056 }
1057
jardineb5d44e2003-12-23 08:09:43 +00001058 thread_add_event (master, isis_route_validate, area, 0);
1059 spftree->lastrun = time (NULL);
1060 spftree->pending = 0;
hassof390d2c2004-09-10 20:48:21 +00001061
jardineb5d44e2003-12-23 08:09:43 +00001062 return retval;
1063}
1064
1065int
1066isis_run_spf_l1 (struct thread *thread)
1067{
1068 struct isis_area *area;
1069 int retval = ISIS_OK;
1070
hassof390d2c2004-09-10 20:48:21 +00001071 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001072 assert (area);
1073
hasso12a5cae2004-09-19 19:39:26 +00001074 area->spftree[0]->t_spf = NULL;
1075
hassof390d2c2004-09-10 20:48:21 +00001076 if (!(area->is_type & IS_LEVEL_1))
1077 {
1078 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001079 zlog_warn ("ISIS-SPF (%s) area does not share level",
1080 area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001081 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001082 }
jardineb5d44e2003-12-23 08:09:43 +00001083
hassof390d2c2004-09-10 20:48:21 +00001084 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001085 zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001086
jardineb5d44e2003-12-23 08:09:43 +00001087 if (area->ip_circuits)
1088 retval = isis_run_spf (area, 1, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001089
1090 THREAD_TIMER_ON (master, area->spftree[0]->t_spf, isis_run_spf_l1, area,
1091 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1092
jardineb5d44e2003-12-23 08:09:43 +00001093 return retval;
1094}
1095
1096int
1097isis_run_spf_l2 (struct thread *thread)
1098{
1099 struct isis_area *area;
1100 int retval = ISIS_OK;
1101
hassof390d2c2004-09-10 20:48:21 +00001102 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001103 assert (area);
hassof390d2c2004-09-10 20:48:21 +00001104
hasso12a5cae2004-09-19 19:39:26 +00001105 area->spftree[1]->t_spf = NULL;
1106
hassof390d2c2004-09-10 20:48:21 +00001107 if (!(area->is_type & IS_LEVEL_2))
1108 {
1109 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001110 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001111 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001112 }
hassof390d2c2004-09-10 20:48:21 +00001113
1114 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001115 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag);
jardineb5d44e2003-12-23 08:09:43 +00001116
1117 if (area->ip_circuits)
1118 retval = isis_run_spf (area, 2, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001119
1120 THREAD_TIMER_ON (master, area->spftree[1]->t_spf, isis_run_spf_l2, area,
1121 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
jardineb5d44e2003-12-23 08:09:43 +00001122
1123 return retval;
1124}
1125
hassof390d2c2004-09-10 20:48:21 +00001126int
jardineb5d44e2003-12-23 08:09:43 +00001127isis_spf_schedule (struct isis_area *area, int level)
1128{
1129 int retval = ISIS_OK;
1130 struct isis_spftree *spftree = area->spftree[level - 1];
1131 time_t diff, now = time (NULL);
1132
1133 if (spftree->pending)
1134 return retval;
1135
hassof390d2c2004-09-10 20:48:21 +00001136 diff = now - spftree->lastrun;
jardineb5d44e2003-12-23 08:09:43 +00001137
1138 /* FIXME: let's wait a minute before doing the SPF */
hassof390d2c2004-09-10 20:48:21 +00001139 if (now - isis->uptime < 60 || isis->uptime == 0)
1140 {
1141 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001142 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area, 60);
hassof390d2c2004-09-10 20:48:21 +00001143 else
hasso12a5cae2004-09-19 19:39:26 +00001144 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area, 60);
jardineb5d44e2003-12-23 08:09:43 +00001145
hassof390d2c2004-09-10 20:48:21 +00001146 spftree->pending = 1;
1147 return retval;
1148 }
hasso12a5cae2004-09-19 19:39:26 +00001149
1150 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001151
hassof390d2c2004-09-10 20:48:21 +00001152 if (diff < MINIMUM_SPF_INTERVAL)
1153 {
1154 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001155 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
1156 MINIMUM_SPF_INTERVAL - diff);
hassof390d2c2004-09-10 20:48:21 +00001157 else
hasso12a5cae2004-09-19 19:39:26 +00001158 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
1159 MINIMUM_SPF_INTERVAL - diff);
jardineb5d44e2003-12-23 08:09:43 +00001160
hassof390d2c2004-09-10 20:48:21 +00001161 spftree->pending = 1;
1162 }
1163 else
1164 {
1165 spftree->pending = 0;
1166 retval = isis_run_spf (area, level, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001167 if (level == 1)
1168 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
1169 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1170 else
1171 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
1172 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
hassof390d2c2004-09-10 20:48:21 +00001173 }
jardineb5d44e2003-12-23 08:09:43 +00001174
1175 return retval;
1176}
1177
1178#ifdef HAVE_IPV6
hasso92365882005-01-18 13:53:33 +00001179static int
hasso12a5cae2004-09-19 19:39:26 +00001180isis_run_spf6_l1 (struct thread *thread)
1181{
1182 struct isis_area *area;
1183 int retval = ISIS_OK;
1184
1185 area = THREAD_ARG (thread);
1186 assert (area);
1187
1188 area->spftree6[0]->t_spf = NULL;
1189
1190 if (!(area->is_type & IS_LEVEL_1))
1191 {
1192 if (isis->debugs & DEBUG_SPF_EVENTS)
1193 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
1194 return ISIS_WARNING;
1195 }
1196
1197 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001198 zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001199
1200 if (area->ipv6_circuits)
1201 retval = isis_run_spf (area, 1, AF_INET6);
1202
1203 THREAD_TIMER_ON (master, area->spftree6[0]->t_spf, isis_run_spf6_l1, area,
1204 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1205
1206 return retval;
1207}
1208
hasso92365882005-01-18 13:53:33 +00001209static int
hasso12a5cae2004-09-19 19:39:26 +00001210isis_run_spf6_l2 (struct thread *thread)
1211{
1212 struct isis_area *area;
1213 int retval = ISIS_OK;
1214
1215 area = THREAD_ARG (thread);
1216 assert (area);
1217
1218 area->spftree6[1]->t_spf = NULL;
1219
1220 if (!(area->is_type & IS_LEVEL_2))
1221 {
1222 if (isis->debugs & DEBUG_SPF_EVENTS)
1223 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
1224 return ISIS_WARNING;
1225 }
1226
1227 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001228 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001229
1230 if (area->ipv6_circuits)
1231 retval = isis_run_spf (area, 2, AF_INET6);
1232
1233 THREAD_TIMER_ON (master, area->spftree6[1]->t_spf, isis_run_spf6_l2, area,
1234 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1235
1236 return retval;
1237}
1238
1239int
jardineb5d44e2003-12-23 08:09:43 +00001240isis_spf_schedule6 (struct isis_area *area, int level)
1241{
1242 int retval = ISIS_OK;
1243 struct isis_spftree *spftree = area->spftree6[level - 1];
1244 time_t diff, now = time (NULL);
1245
1246 if (spftree->pending)
1247 return retval;
1248
hassof390d2c2004-09-10 20:48:21 +00001249 diff = now - spftree->lastrun;
1250
jardineb5d44e2003-12-23 08:09:43 +00001251 /* FIXME: let's wait a minute before doing the SPF */
hassof390d2c2004-09-10 20:48:21 +00001252 if (now - isis->uptime < 60 || isis->uptime == 0)
1253 {
1254 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001255 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area, 60);
hassof390d2c2004-09-10 20:48:21 +00001256 else
hasso12a5cae2004-09-19 19:39:26 +00001257 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area, 60);
jardineb5d44e2003-12-23 08:09:43 +00001258
hassof390d2c2004-09-10 20:48:21 +00001259 spftree->pending = 1;
1260 return retval;
1261 }
hasso12a5cae2004-09-19 19:39:26 +00001262
1263 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001264
hassof390d2c2004-09-10 20:48:21 +00001265 if (diff < MINIMUM_SPF_INTERVAL)
1266 {
1267 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001268 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
1269 MINIMUM_SPF_INTERVAL - diff);
hassof390d2c2004-09-10 20:48:21 +00001270 else
hasso12a5cae2004-09-19 19:39:26 +00001271 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
1272 MINIMUM_SPF_INTERVAL - diff);
jardineb5d44e2003-12-23 08:09:43 +00001273
hassof390d2c2004-09-10 20:48:21 +00001274 spftree->pending = 1;
1275 }
1276 else
1277 {
1278 spftree->pending = 0;
1279 retval = isis_run_spf (area, level, AF_INET6);
hasso12a5cae2004-09-19 19:39:26 +00001280
1281 if (level == 1)
1282 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
1283 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1284 else
1285 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
1286 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
hassof390d2c2004-09-10 20:48:21 +00001287 }
jardineb5d44e2003-12-23 08:09:43 +00001288
1289 return retval;
1290}
jardineb5d44e2003-12-23 08:09:43 +00001291#endif
1292
hasso92365882005-01-18 13:53:33 +00001293static void
jardineb5d44e2003-12-23 08:09:43 +00001294isis_print_paths (struct vty *vty, struct list *paths)
1295{
paul1eb8ef22005-04-07 07:30:20 +00001296 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +00001297 struct isis_vertex *vertex;
1298 struct isis_dynhn *dyn, *nh_dyn = NULL;
1299 struct isis_adjacency *adj;
hasso92365882005-01-18 13:53:33 +00001300#if 0
jardineb5d44e2003-12-23 08:09:43 +00001301 u_char buff[255];
hasso92365882005-01-18 13:53:33 +00001302#endif /* 0 */
jardineb5d44e2003-12-23 08:09:43 +00001303
1304 vty_out (vty, "System Id Metric Next-Hop"
hassof390d2c2004-09-10 20:48:21 +00001305 " Interface SNPA%s", VTY_NEWLINE);
paul1eb8ef22005-04-07 07:30:20 +00001306
1307 for (ALL_LIST_ELEMENTS_RO (paths, node, vertex))
hassof390d2c2004-09-10 20:48:21 +00001308 {
hassof390d2c2004-09-10 20:48:21 +00001309 if (vertex->type != VTYPE_NONPSEUDO_IS)
1310 continue;
1311 if (memcmp (vertex->N.id, isis->sysid, ISIS_SYS_ID_LEN) == 0)
1312 {
hassoc3d26c72005-03-07 08:54:41 +00001313 vty_out (vty, "%s --%s", host.name?host.name:"",
1314 VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +00001315 }
1316 else
1317 {
1318 dyn = dynhn_find_by_id ((u_char *) vertex->N.id);
paul1eb8ef22005-04-07 07:30:20 +00001319 adj = listgetdata (listhead (vertex->Adj_N));
hassof390d2c2004-09-10 20:48:21 +00001320 if (adj)
1321 {
1322 nh_dyn = dynhn_find_by_id (adj->sysid);
1323 vty_out (vty, "%-20s %-10u %-20s %-11s %-5s%s",
1324 (dyn != NULL) ? dyn->name.name :
1325 (u_char *) rawlspid_print ((u_char *) vertex->N.id),
1326 vertex->d_N, (nh_dyn != NULL) ? nh_dyn->name.name :
1327 (u_char *) rawlspid_print (adj->sysid),
1328 adj->circuit->interface->name,
1329 snpa_print (adj->snpa), VTY_NEWLINE);
1330 }
1331 else
1332 {
1333 vty_out (vty, "%s %u %s", dyn ? dyn->name.name :
1334 (u_char *) rawlspid_print (vertex->N.id),
1335 vertex->d_N, VTY_NEWLINE);
1336 }
1337 }
jardineb5d44e2003-12-23 08:09:43 +00001338#if 0
hassof390d2c2004-09-10 20:48:21 +00001339 vty_out (vty, "%s %s %u %s", vtype2string (vertex->type),
1340 vid2string (vertex, buff), vertex->d_N, VTY_NEWLINE);
jardineb5d44e2003-12-23 08:09:43 +00001341#endif
hassof390d2c2004-09-10 20:48:21 +00001342 }
jardineb5d44e2003-12-23 08:09:43 +00001343}
1344
1345DEFUN (show_isis_topology,
1346 show_isis_topology_cmd,
1347 "show isis topology",
1348 SHOW_STR
1349 "IS-IS information\n"
1350 "IS-IS paths to Intermediate Systems\n")
1351{
1352 struct listnode *node;
1353 struct isis_area *area;
1354 int level;
hassof390d2c2004-09-10 20:48:21 +00001355
jardineb5d44e2003-12-23 08:09:43 +00001356 if (!isis->area_list || isis->area_list->count == 0)
1357 return CMD_SUCCESS;
1358
paul1eb8ef22005-04-07 07:30:20 +00001359 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001360 {
hassof390d2c2004-09-10 20:48:21 +00001361 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1362 VTY_NEWLINE);
1363
1364 for (level = 0; level < ISIS_LEVELS; level++)
1365 {
1366 if (area->ip_circuits > 0 && area->spftree[level]
1367 && area->spftree[level]->paths->count > 0)
1368 {
1369 vty_out (vty, "IS-IS paths to level-%d routers that speak IP%s",
1370 level + 1, VTY_NEWLINE);
1371 isis_print_paths (vty, area->spftree[level]->paths);
1372 }
jardineb5d44e2003-12-23 08:09:43 +00001373#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001374 if (area->ipv6_circuits > 0 && area->spftree6[level]
1375 && area->spftree6[level]->paths->count > 0)
1376 {
1377 vty_out (vty,
1378 "IS-IS paths to level-%d routers that speak IPv6%s",
1379 level + 1, VTY_NEWLINE);
1380 isis_print_paths (vty, area->spftree6[level]->paths);
1381 }
jardineb5d44e2003-12-23 08:09:43 +00001382#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +00001383 }
jardineb5d44e2003-12-23 08:09:43 +00001384 }
jardineb5d44e2003-12-23 08:09:43 +00001385
1386 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001387}
jardineb5d44e2003-12-23 08:09:43 +00001388
1389DEFUN (show_isis_topology_l1,
1390 show_isis_topology_l1_cmd,
1391 "show isis topology level-1",
1392 SHOW_STR
1393 "IS-IS information\n"
1394 "IS-IS paths to Intermediate Systems\n"
1395 "Paths to all level-1 routers in the area\n")
1396{
1397 struct listnode *node;
1398 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001399
jardineb5d44e2003-12-23 08:09:43 +00001400 if (!isis->area_list || isis->area_list->count == 0)
1401 return CMD_SUCCESS;
1402
paul1eb8ef22005-04-07 07:30:20 +00001403 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001404 {
hassof390d2c2004-09-10 20:48:21 +00001405 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1406 VTY_NEWLINE);
1407
1408 if (area->ip_circuits > 0 && area->spftree[0]
1409 && area->spftree[0]->paths->count > 0)
1410 {
1411 vty_out (vty, "IS-IS paths to level-1 routers that speak IP%s",
1412 VTY_NEWLINE);
1413 isis_print_paths (vty, area->spftree[0]->paths);
1414 }
jardineb5d44e2003-12-23 08:09:43 +00001415#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001416 if (area->ipv6_circuits > 0 && area->spftree6[0]
1417 && area->spftree6[0]->paths->count > 0)
1418 {
1419 vty_out (vty, "IS-IS paths to level-1 routers that speak IPv6%s",
1420 VTY_NEWLINE);
1421 isis_print_paths (vty, area->spftree6[0]->paths);
1422 }
jardineb5d44e2003-12-23 08:09:43 +00001423#endif /* HAVE_IPV6 */
1424 }
1425
jardineb5d44e2003-12-23 08:09:43 +00001426 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001427}
jardineb5d44e2003-12-23 08:09:43 +00001428
1429DEFUN (show_isis_topology_l2,
1430 show_isis_topology_l2_cmd,
1431 "show isis topology level-2",
1432 SHOW_STR
1433 "IS-IS information\n"
1434 "IS-IS paths to Intermediate Systems\n"
1435 "Paths to all level-2 routers in the domain\n")
1436{
1437 struct listnode *node;
1438 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001439
jardineb5d44e2003-12-23 08:09:43 +00001440 if (!isis->area_list || isis->area_list->count == 0)
1441 return CMD_SUCCESS;
1442
paul1eb8ef22005-04-07 07:30:20 +00001443 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001444 {
hassof390d2c2004-09-10 20:48:21 +00001445 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1446 VTY_NEWLINE);
1447
1448 if (area->ip_circuits > 0 && area->spftree[1]
1449 && area->spftree[1]->paths->count > 0)
1450 {
1451 vty_out (vty, "IS-IS paths to level-2 routers that speak IP%s",
1452 VTY_NEWLINE);
1453 isis_print_paths (vty, area->spftree[1]->paths);
1454 }
jardineb5d44e2003-12-23 08:09:43 +00001455#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001456 if (area->ipv6_circuits > 0 && area->spftree6[1]
1457 && area->spftree6[1]->paths->count > 0)
1458 {
1459 vty_out (vty, "IS-IS paths to level-2 routers that speak IPv6%s",
1460 VTY_NEWLINE);
1461 isis_print_paths (vty, area->spftree6[1]->paths);
1462 }
jardineb5d44e2003-12-23 08:09:43 +00001463#endif /* HAVE_IPV6 */
1464 }
1465
jardineb5d44e2003-12-23 08:09:43 +00001466 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001467}
jardineb5d44e2003-12-23 08:09:43 +00001468
1469void
1470isis_spf_cmds_init ()
1471{
1472 install_element (VIEW_NODE, &show_isis_topology_cmd);
1473 install_element (VIEW_NODE, &show_isis_topology_l1_cmd);
1474 install_element (VIEW_NODE, &show_isis_topology_l2_cmd);
1475
1476 install_element (ENABLE_NODE, &show_isis_topology_cmd);
1477 install_element (ENABLE_NODE, &show_isis_topology_l1_cmd);
1478 install_element (ENABLE_NODE, &show_isis_topology_l2_cmd);
1479}