blob: 706ed16c3ed78e6aa47aa814c00b0672d62352ee [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];
1001 else if (family == AF_INET6)
1002 table = area->route_table6[level - 1];
1003
1004 for (rode = route_top (table); rode; rode = route_next (rode))
1005 {
1006 if (rode->info == NULL)
1007 continue;
1008 rinfo = rode->info;
1009
1010 UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
1011 }
1012
jardineb5d44e2003-12-23 08:09:43 +00001013 /*
1014 * C.2.5 Step 0
1015 */
1016 init_spt (spftree);
1017 /* a) */
1018 isis_spf_add_self (spftree, area, level);
1019 /* b) */
1020 retval = isis_spf_preload_tent (spftree, area, level, family);
hassof390d2c2004-09-10 20:48:21 +00001021
jardineb5d44e2003-12-23 08:09:43 +00001022 /*
1023 * C.2.7 Step 2
1024 */
hassof390d2c2004-09-10 20:48:21 +00001025 if (listcount (spftree->tents) == 0)
1026 {
1027 zlog_warn ("ISIS-Spf: TENT is empty");
hasso13fb40a2005-10-01 06:03:04 +00001028 goto out;
jardineb5d44e2003-12-23 08:09:43 +00001029 }
hassof390d2c2004-09-10 20:48:21 +00001030
1031 while (listcount (spftree->tents) > 0)
1032 {
1033 node = listhead (spftree->tents);
paul1eb8ef22005-04-07 07:30:20 +00001034 vertex = listgetdata (node);
hassof390d2c2004-09-10 20:48:21 +00001035 /* Remove from tent list */
1036 list_delete_node (spftree->tents, node);
1037 if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type))
1038 continue;
hassofac1f7c2005-09-26 18:26:26 +00001039 add_to_paths (spftree, vertex, area, level);
hassof390d2c2004-09-10 20:48:21 +00001040 if (vertex->type == VTYPE_PSEUDO_IS ||
1041 vertex->type == VTYPE_NONPSEUDO_IS)
1042 {
1043 memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
1044 LSP_FRAGMENT (lsp_id) = 0;
1045 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
1046 if (lsp)
1047 {
1048 if (LSP_PSEUDO_ID (lsp_id))
1049 {
1050 isis_spf_process_pseudo_lsp (spftree, lsp, vertex->d_N,
1051 vertex->depth, family);
1052
1053 }
1054 else
1055 {
1056 isis_spf_process_lsp (spftree, lsp, vertex->d_N,
1057 vertex->depth, family);
1058 }
1059 }
1060 else
1061 {
1062 zlog_warn ("ISIS-Spf: No LSP found for %s",
1063 rawlspid_print (lsp_id));
1064 }
1065 }
1066 }
1067
hasso13fb40a2005-10-01 06:03:04 +00001068out:
jardineb5d44e2003-12-23 08:09:43 +00001069 thread_add_event (master, isis_route_validate, area, 0);
1070 spftree->lastrun = time (NULL);
1071 spftree->pending = 0;
hassof390d2c2004-09-10 20:48:21 +00001072
jardineb5d44e2003-12-23 08:09:43 +00001073 return retval;
1074}
1075
1076int
1077isis_run_spf_l1 (struct thread *thread)
1078{
1079 struct isis_area *area;
1080 int retval = ISIS_OK;
1081
hassof390d2c2004-09-10 20:48:21 +00001082 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001083 assert (area);
1084
hasso12a5cae2004-09-19 19:39:26 +00001085 area->spftree[0]->t_spf = NULL;
1086
hassof390d2c2004-09-10 20:48:21 +00001087 if (!(area->is_type & IS_LEVEL_1))
1088 {
1089 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001090 zlog_warn ("ISIS-SPF (%s) area does not share level",
1091 area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001092 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001093 }
jardineb5d44e2003-12-23 08:09:43 +00001094
hassof390d2c2004-09-10 20:48:21 +00001095 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001096 zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001097
jardineb5d44e2003-12-23 08:09:43 +00001098 if (area->ip_circuits)
1099 retval = isis_run_spf (area, 1, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001100
1101 THREAD_TIMER_ON (master, area->spftree[0]->t_spf, isis_run_spf_l1, area,
1102 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1103
jardineb5d44e2003-12-23 08:09:43 +00001104 return retval;
1105}
1106
1107int
1108isis_run_spf_l2 (struct thread *thread)
1109{
1110 struct isis_area *area;
1111 int retval = ISIS_OK;
1112
hassof390d2c2004-09-10 20:48:21 +00001113 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001114 assert (area);
hassof390d2c2004-09-10 20:48:21 +00001115
hasso12a5cae2004-09-19 19:39:26 +00001116 area->spftree[1]->t_spf = NULL;
1117
hassof390d2c2004-09-10 20:48:21 +00001118 if (!(area->is_type & IS_LEVEL_2))
1119 {
1120 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001121 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001122 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001123 }
hassof390d2c2004-09-10 20:48:21 +00001124
1125 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001126 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag);
jardineb5d44e2003-12-23 08:09:43 +00001127
1128 if (area->ip_circuits)
1129 retval = isis_run_spf (area, 2, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001130
1131 THREAD_TIMER_ON (master, area->spftree[1]->t_spf, isis_run_spf_l2, area,
1132 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
jardineb5d44e2003-12-23 08:09:43 +00001133
1134 return retval;
1135}
1136
hassof390d2c2004-09-10 20:48:21 +00001137int
jardineb5d44e2003-12-23 08:09:43 +00001138isis_spf_schedule (struct isis_area *area, int level)
1139{
1140 int retval = ISIS_OK;
1141 struct isis_spftree *spftree = area->spftree[level - 1];
1142 time_t diff, now = time (NULL);
1143
1144 if (spftree->pending)
1145 return retval;
1146
hassof390d2c2004-09-10 20:48:21 +00001147 diff = now - spftree->lastrun;
jardineb5d44e2003-12-23 08:09:43 +00001148
1149 /* FIXME: let's wait a minute before doing the SPF */
hassof390d2c2004-09-10 20:48:21 +00001150 if (now - isis->uptime < 60 || isis->uptime == 0)
1151 {
1152 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001153 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area, 60);
hassof390d2c2004-09-10 20:48:21 +00001154 else
hasso12a5cae2004-09-19 19:39:26 +00001155 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area, 60);
jardineb5d44e2003-12-23 08:09:43 +00001156
hassof390d2c2004-09-10 20:48:21 +00001157 spftree->pending = 1;
1158 return retval;
1159 }
hasso12a5cae2004-09-19 19:39:26 +00001160
1161 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001162
hassof390d2c2004-09-10 20:48:21 +00001163 if (diff < MINIMUM_SPF_INTERVAL)
1164 {
1165 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001166 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
1167 MINIMUM_SPF_INTERVAL - diff);
hassof390d2c2004-09-10 20:48:21 +00001168 else
hasso12a5cae2004-09-19 19:39:26 +00001169 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
1170 MINIMUM_SPF_INTERVAL - diff);
jardineb5d44e2003-12-23 08:09:43 +00001171
hassof390d2c2004-09-10 20:48:21 +00001172 spftree->pending = 1;
1173 }
1174 else
1175 {
1176 spftree->pending = 0;
1177 retval = isis_run_spf (area, level, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001178 if (level == 1)
1179 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
1180 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1181 else
1182 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
1183 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
hassof390d2c2004-09-10 20:48:21 +00001184 }
jardineb5d44e2003-12-23 08:09:43 +00001185
1186 return retval;
1187}
1188
1189#ifdef HAVE_IPV6
hasso92365882005-01-18 13:53:33 +00001190static int
hasso12a5cae2004-09-19 19:39:26 +00001191isis_run_spf6_l1 (struct thread *thread)
1192{
1193 struct isis_area *area;
1194 int retval = ISIS_OK;
1195
1196 area = THREAD_ARG (thread);
1197 assert (area);
1198
1199 area->spftree6[0]->t_spf = NULL;
1200
1201 if (!(area->is_type & IS_LEVEL_1))
1202 {
1203 if (isis->debugs & DEBUG_SPF_EVENTS)
1204 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
1205 return ISIS_WARNING;
1206 }
1207
1208 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001209 zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001210
1211 if (area->ipv6_circuits)
1212 retval = isis_run_spf (area, 1, AF_INET6);
1213
1214 THREAD_TIMER_ON (master, area->spftree6[0]->t_spf, isis_run_spf6_l1, area,
1215 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1216
1217 return retval;
1218}
1219
hasso92365882005-01-18 13:53:33 +00001220static int
hasso12a5cae2004-09-19 19:39:26 +00001221isis_run_spf6_l2 (struct thread *thread)
1222{
1223 struct isis_area *area;
1224 int retval = ISIS_OK;
1225
1226 area = THREAD_ARG (thread);
1227 assert (area);
1228
1229 area->spftree6[1]->t_spf = NULL;
1230
1231 if (!(area->is_type & IS_LEVEL_2))
1232 {
1233 if (isis->debugs & DEBUG_SPF_EVENTS)
1234 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
1235 return ISIS_WARNING;
1236 }
1237
1238 if (isis->debugs & DEBUG_SPF_EVENTS)
hassofac1f7c2005-09-26 18:26:26 +00001239 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF.", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001240
1241 if (area->ipv6_circuits)
1242 retval = isis_run_spf (area, 2, AF_INET6);
1243
1244 THREAD_TIMER_ON (master, area->spftree6[1]->t_spf, isis_run_spf6_l2, area,
1245 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1246
1247 return retval;
1248}
1249
1250int
jardineb5d44e2003-12-23 08:09:43 +00001251isis_spf_schedule6 (struct isis_area *area, int level)
1252{
1253 int retval = ISIS_OK;
1254 struct isis_spftree *spftree = area->spftree6[level - 1];
1255 time_t diff, now = time (NULL);
1256
1257 if (spftree->pending)
1258 return retval;
1259
hassof390d2c2004-09-10 20:48:21 +00001260 diff = now - spftree->lastrun;
1261
jardineb5d44e2003-12-23 08:09:43 +00001262 /* FIXME: let's wait a minute before doing the SPF */
hassof390d2c2004-09-10 20:48:21 +00001263 if (now - isis->uptime < 60 || isis->uptime == 0)
1264 {
1265 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001266 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area, 60);
hassof390d2c2004-09-10 20:48:21 +00001267 else
hasso12a5cae2004-09-19 19:39:26 +00001268 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area, 60);
jardineb5d44e2003-12-23 08:09:43 +00001269
hassof390d2c2004-09-10 20:48:21 +00001270 spftree->pending = 1;
1271 return retval;
1272 }
hasso12a5cae2004-09-19 19:39:26 +00001273
1274 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001275
hassof390d2c2004-09-10 20:48:21 +00001276 if (diff < MINIMUM_SPF_INTERVAL)
1277 {
1278 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001279 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
1280 MINIMUM_SPF_INTERVAL - diff);
hassof390d2c2004-09-10 20:48:21 +00001281 else
hasso12a5cae2004-09-19 19:39:26 +00001282 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
1283 MINIMUM_SPF_INTERVAL - diff);
jardineb5d44e2003-12-23 08:09:43 +00001284
hassof390d2c2004-09-10 20:48:21 +00001285 spftree->pending = 1;
1286 }
1287 else
1288 {
1289 spftree->pending = 0;
1290 retval = isis_run_spf (area, level, AF_INET6);
hasso12a5cae2004-09-19 19:39:26 +00001291
1292 if (level == 1)
1293 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
1294 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1295 else
1296 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
1297 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
hassof390d2c2004-09-10 20:48:21 +00001298 }
jardineb5d44e2003-12-23 08:09:43 +00001299
1300 return retval;
1301}
jardineb5d44e2003-12-23 08:09:43 +00001302#endif
1303
hasso92365882005-01-18 13:53:33 +00001304static void
jardineb5d44e2003-12-23 08:09:43 +00001305isis_print_paths (struct vty *vty, struct list *paths)
1306{
paul1eb8ef22005-04-07 07:30:20 +00001307 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +00001308 struct isis_vertex *vertex;
1309 struct isis_dynhn *dyn, *nh_dyn = NULL;
1310 struct isis_adjacency *adj;
hasso92365882005-01-18 13:53:33 +00001311#if 0
jardineb5d44e2003-12-23 08:09:43 +00001312 u_char buff[255];
hasso92365882005-01-18 13:53:33 +00001313#endif /* 0 */
jardineb5d44e2003-12-23 08:09:43 +00001314
1315 vty_out (vty, "System Id Metric Next-Hop"
hassof390d2c2004-09-10 20:48:21 +00001316 " Interface SNPA%s", VTY_NEWLINE);
paul1eb8ef22005-04-07 07:30:20 +00001317
1318 for (ALL_LIST_ELEMENTS_RO (paths, node, vertex))
hassof390d2c2004-09-10 20:48:21 +00001319 {
hassof390d2c2004-09-10 20:48:21 +00001320 if (vertex->type != VTYPE_NONPSEUDO_IS)
1321 continue;
1322 if (memcmp (vertex->N.id, isis->sysid, ISIS_SYS_ID_LEN) == 0)
1323 {
hassoc3d26c72005-03-07 08:54:41 +00001324 vty_out (vty, "%s --%s", host.name?host.name:"",
1325 VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +00001326 }
1327 else
1328 {
1329 dyn = dynhn_find_by_id ((u_char *) vertex->N.id);
paul1eb8ef22005-04-07 07:30:20 +00001330 adj = listgetdata (listhead (vertex->Adj_N));
hassof390d2c2004-09-10 20:48:21 +00001331 if (adj)
1332 {
1333 nh_dyn = dynhn_find_by_id (adj->sysid);
1334 vty_out (vty, "%-20s %-10u %-20s %-11s %-5s%s",
1335 (dyn != NULL) ? dyn->name.name :
1336 (u_char *) rawlspid_print ((u_char *) vertex->N.id),
1337 vertex->d_N, (nh_dyn != NULL) ? nh_dyn->name.name :
1338 (u_char *) rawlspid_print (adj->sysid),
1339 adj->circuit->interface->name,
1340 snpa_print (adj->snpa), VTY_NEWLINE);
1341 }
1342 else
1343 {
1344 vty_out (vty, "%s %u %s", dyn ? dyn->name.name :
1345 (u_char *) rawlspid_print (vertex->N.id),
1346 vertex->d_N, VTY_NEWLINE);
1347 }
1348 }
jardineb5d44e2003-12-23 08:09:43 +00001349#if 0
hassof390d2c2004-09-10 20:48:21 +00001350 vty_out (vty, "%s %s %u %s", vtype2string (vertex->type),
1351 vid2string (vertex, buff), vertex->d_N, VTY_NEWLINE);
jardineb5d44e2003-12-23 08:09:43 +00001352#endif
hassof390d2c2004-09-10 20:48:21 +00001353 }
jardineb5d44e2003-12-23 08:09:43 +00001354}
1355
1356DEFUN (show_isis_topology,
1357 show_isis_topology_cmd,
1358 "show isis topology",
1359 SHOW_STR
1360 "IS-IS information\n"
1361 "IS-IS paths to Intermediate Systems\n")
1362{
1363 struct listnode *node;
1364 struct isis_area *area;
1365 int level;
hassof390d2c2004-09-10 20:48:21 +00001366
jardineb5d44e2003-12-23 08:09:43 +00001367 if (!isis->area_list || isis->area_list->count == 0)
1368 return CMD_SUCCESS;
1369
paul1eb8ef22005-04-07 07:30:20 +00001370 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001371 {
hassof390d2c2004-09-10 20:48:21 +00001372 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1373 VTY_NEWLINE);
1374
1375 for (level = 0; level < ISIS_LEVELS; level++)
1376 {
1377 if (area->ip_circuits > 0 && area->spftree[level]
1378 && area->spftree[level]->paths->count > 0)
1379 {
1380 vty_out (vty, "IS-IS paths to level-%d routers that speak IP%s",
1381 level + 1, VTY_NEWLINE);
1382 isis_print_paths (vty, area->spftree[level]->paths);
1383 }
jardineb5d44e2003-12-23 08:09:43 +00001384#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001385 if (area->ipv6_circuits > 0 && area->spftree6[level]
1386 && area->spftree6[level]->paths->count > 0)
1387 {
1388 vty_out (vty,
1389 "IS-IS paths to level-%d routers that speak IPv6%s",
1390 level + 1, VTY_NEWLINE);
1391 isis_print_paths (vty, area->spftree6[level]->paths);
1392 }
jardineb5d44e2003-12-23 08:09:43 +00001393#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +00001394 }
jardineb5d44e2003-12-23 08:09:43 +00001395 }
jardineb5d44e2003-12-23 08:09:43 +00001396
1397 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001398}
jardineb5d44e2003-12-23 08:09:43 +00001399
1400DEFUN (show_isis_topology_l1,
1401 show_isis_topology_l1_cmd,
1402 "show isis topology level-1",
1403 SHOW_STR
1404 "IS-IS information\n"
1405 "IS-IS paths to Intermediate Systems\n"
1406 "Paths to all level-1 routers in the area\n")
1407{
1408 struct listnode *node;
1409 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001410
jardineb5d44e2003-12-23 08:09:43 +00001411 if (!isis->area_list || isis->area_list->count == 0)
1412 return CMD_SUCCESS;
1413
paul1eb8ef22005-04-07 07:30:20 +00001414 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001415 {
hassof390d2c2004-09-10 20:48:21 +00001416 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1417 VTY_NEWLINE);
1418
1419 if (area->ip_circuits > 0 && area->spftree[0]
1420 && area->spftree[0]->paths->count > 0)
1421 {
1422 vty_out (vty, "IS-IS paths to level-1 routers that speak IP%s",
1423 VTY_NEWLINE);
1424 isis_print_paths (vty, area->spftree[0]->paths);
1425 }
jardineb5d44e2003-12-23 08:09:43 +00001426#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001427 if (area->ipv6_circuits > 0 && area->spftree6[0]
1428 && area->spftree6[0]->paths->count > 0)
1429 {
1430 vty_out (vty, "IS-IS paths to level-1 routers that speak IPv6%s",
1431 VTY_NEWLINE);
1432 isis_print_paths (vty, area->spftree6[0]->paths);
1433 }
jardineb5d44e2003-12-23 08:09:43 +00001434#endif /* HAVE_IPV6 */
1435 }
1436
jardineb5d44e2003-12-23 08:09:43 +00001437 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001438}
jardineb5d44e2003-12-23 08:09:43 +00001439
1440DEFUN (show_isis_topology_l2,
1441 show_isis_topology_l2_cmd,
1442 "show isis topology level-2",
1443 SHOW_STR
1444 "IS-IS information\n"
1445 "IS-IS paths to Intermediate Systems\n"
1446 "Paths to all level-2 routers in the domain\n")
1447{
1448 struct listnode *node;
1449 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001450
jardineb5d44e2003-12-23 08:09:43 +00001451 if (!isis->area_list || isis->area_list->count == 0)
1452 return CMD_SUCCESS;
1453
paul1eb8ef22005-04-07 07:30:20 +00001454 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001455 {
hassof390d2c2004-09-10 20:48:21 +00001456 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1457 VTY_NEWLINE);
1458
1459 if (area->ip_circuits > 0 && area->spftree[1]
1460 && area->spftree[1]->paths->count > 0)
1461 {
1462 vty_out (vty, "IS-IS paths to level-2 routers that speak IP%s",
1463 VTY_NEWLINE);
1464 isis_print_paths (vty, area->spftree[1]->paths);
1465 }
jardineb5d44e2003-12-23 08:09:43 +00001466#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001467 if (area->ipv6_circuits > 0 && area->spftree6[1]
1468 && area->spftree6[1]->paths->count > 0)
1469 {
1470 vty_out (vty, "IS-IS paths to level-2 routers that speak IPv6%s",
1471 VTY_NEWLINE);
1472 isis_print_paths (vty, area->spftree6[1]->paths);
1473 }
jardineb5d44e2003-12-23 08:09:43 +00001474#endif /* HAVE_IPV6 */
1475 }
1476
jardineb5d44e2003-12-23 08:09:43 +00001477 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001478}
jardineb5d44e2003-12-23 08:09:43 +00001479
1480void
1481isis_spf_cmds_init ()
1482{
1483 install_element (VIEW_NODE, &show_isis_topology_cmd);
1484 install_element (VIEW_NODE, &show_isis_topology_l1_cmd);
1485 install_element (VIEW_NODE, &show_isis_topology_l2_cmd);
1486
1487 install_element (ENABLE_NODE, &show_isis_topology_cmd);
1488 install_element (ENABLE_NODE, &show_isis_topology_l1_cmd);
1489 install_element (ENABLE_NODE, &show_isis_topology_l2_cmd);
1490}