blob: b6178e3a29df43ce59793cebb153ccbb243d78a0 [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);
Peter Szilagyid034aa02011-10-01 17:22:51 +0400408
hassof390d2c2004-09-10 20:48:21 +0000409#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000410 zlog_debug ("ISIS-Spf: add to TENT %s %s depth %d dist %d",
411 vtype2string (vertex->type), vid2string (vertex, buff),
412 vertex->depth, vertex->d_N);
jardineb5d44e2003-12-23 08:09:43 +0000413#endif /* EXTREME_DEBUG */
Peter Szilagyid034aa02011-10-01 17:22:51 +0400414
hassof390d2c2004-09-10 20:48:21 +0000415 if (list_isempty (spftree->tents))
416 {
417 listnode_add (spftree->tents, vertex);
418 return vertex;
jardineb5d44e2003-12-23 08:09:43 +0000419 }
paul1eb8ef22005-04-07 07:30:20 +0000420
421 /* XXX: This cant use the standard ALL_LIST_ELEMENT macro */
422 for (node = listhead (spftree->tents); node; node = listnextnode (node))
hassof390d2c2004-09-10 20:48:21 +0000423 {
paul1eb8ef22005-04-07 07:30:20 +0000424 v = listgetdata (node);
hassof390d2c2004-09-10 20:48:21 +0000425 if (v->d_N > vertex->d_N)
426 {
427 list_add_node_prev (spftree->tents, node, vertex);
428 break;
429 }
430 else if (v->d_N == vertex->d_N)
431 {
432 /* Tie break, add according to type */
433 while (v && v->d_N == vertex->d_N && v->type > vertex->type)
434 {
435 if (v->type > vertex->type)
436 {
437 break;
438 }
paul1eb8ef22005-04-07 07:30:20 +0000439 /* XXX: this seems dubious, node is the loop iterator */
440 node = listnextnode (node);
441 (node) ? (v = listgetdata (node)) : (v = NULL);
hassof390d2c2004-09-10 20:48:21 +0000442 }
443 list_add_node_prev (spftree->tents, node, vertex);
444 break;
445 }
446 else if (node->next == NULL)
447 {
448 list_add_node_next (spftree->tents, node, vertex);
449 break;
450 }
451 }
jardineb5d44e2003-12-23 08:09:43 +0000452 return vertex;
453}
454
hasso92365882005-01-18 13:53:33 +0000455static struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000456isis_spf_add_local (struct isis_spftree *spftree, enum vertextype vtype,
hassofac1f7c2005-09-26 18:26:26 +0000457 void *id, struct isis_adjacency *adj, u_int32_t cost,
hassof390d2c2004-09-10 20:48:21 +0000458 int family)
jardineb5d44e2003-12-23 08:09:43 +0000459{
460 struct isis_vertex *vertex;
jardineb5d44e2003-12-23 08:09:43 +0000461
hassof390d2c2004-09-10 20:48:21 +0000462 vertex = isis_find_vertex (spftree->tents, id, vtype);
463
464 if (vertex)
465 {
466 /* C.2.5 c) */
467 if (vertex->d_N == cost)
468 {
469 if (adj)
470 listnode_add (vertex->Adj_N, adj);
471 /* d) */
472 if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
473 remove_excess_adjs (vertex->Adj_N);
474 }
475 /* f) */
476 else if (vertex->d_N > cost)
477 {
478 listnode_delete (spftree->tents, vertex);
479 goto add2tent;
480 }
481 /* e) do nothing */
482 return vertex;
483 }
484
485add2tent:
jardineb5d44e2003-12-23 08:09:43 +0000486 return isis_spf_add2tent (spftree, vtype, id, adj, cost, 1, family);
487}
488
hasso92365882005-01-18 13:53:33 +0000489static void
hassof390d2c2004-09-10 20:48:21 +0000490process_N (struct isis_spftree *spftree, enum vertextype vtype, void *id,
491 u_int16_t dist, u_int16_t depth, struct isis_adjacency *adj,
492 int family)
jardineb5d44e2003-12-23 08:09:43 +0000493{
494 struct isis_vertex *vertex;
495#ifdef EXTREME_DEBUG
496 u_char buff[255];
497#endif
498
499 /* C.2.6 b) */
500 if (dist > MAX_PATH_METRIC)
501 return;
502 /* c) */
503 vertex = isis_find_vertex (spftree->paths, id, vtype);
hassof390d2c2004-09-10 20:48:21 +0000504 if (vertex)
505 {
jardineb5d44e2003-12-23 08:09:43 +0000506#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000507 zlog_debug ("ISIS-Spf: process_N %s %s dist %d already found from PATH",
508 vtype2string (vtype), vid2string (vertex, buff), dist);
jardineb5d44e2003-12-23 08:09:43 +0000509#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000510 assert (dist >= vertex->d_N);
511 return;
512 }
jardineb5d44e2003-12-23 08:09:43 +0000513
514 vertex = isis_find_vertex (spftree->tents, id, vtype);
hassof390d2c2004-09-10 20:48:21 +0000515 /* d) */
516 if (vertex)
517 {
518 /* 1) */
jardineb5d44e2003-12-23 08:09:43 +0000519#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000520 zlog_debug ("ISIS-Spf: process_N %s %s dist %d",
521 vtype2string (vtype), vid2string (vertex, buff), dist);
jardineb5d44e2003-12-23 08:09:43 +0000522#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000523 if (vertex->d_N == dist)
524 {
525 if (adj)
526 listnode_add (vertex->Adj_N, adj);
527 /* 2) */
528 if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
529 remove_excess_adjs (vertex->Adj_N);
530 /* 3) */
531 return;
532 }
533 else if (vertex->d_N < dist)
534 {
535 return;
536 /* 4) */
537 }
538 else
539 {
540 listnode_delete (spftree->tents, vertex);
541 }
jardineb5d44e2003-12-23 08:09:43 +0000542 }
hassof390d2c2004-09-10 20:48:21 +0000543
jardineb5d44e2003-12-23 08:09:43 +0000544 isis_spf_add2tent (spftree, vtype, id, adj, dist, depth, family);
545 return;
546}
547
548/*
549 * C.2.6 Step 1
550 */
hasso92365882005-01-18 13:53:33 +0000551static int
hassof390d2c2004-09-10 20:48:21 +0000552isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp,
Peter Szilagyid034aa02011-10-01 17:22:51 +0400553 uint32_t cost, uint16_t depth, int family,
554 struct isis_adjacency *adj)
jardineb5d44e2003-12-23 08:09:43 +0000555{
556 struct listnode *node, *fragnode = NULL;
557 u_int16_t dist;
558 struct is_neigh *is_neigh;
hasso82a84282005-09-26 18:15:36 +0000559 struct te_is_neigh *te_is_neigh;
jardineb5d44e2003-12-23 08:09:43 +0000560 struct ipv4_reachability *ipreach;
hasso82a84282005-09-26 18:15:36 +0000561 struct te_ipv4_reachability *te_ipv4_reach;
jardineb5d44e2003-12-23 08:09:43 +0000562 enum vertextype vtype;
563 struct prefix prefix;
564#ifdef HAVE_IPV6
565 struct ipv6_reachability *ip6reach;
566#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000567
hassof390d2c2004-09-10 20:48:21 +0000568 if (lsp->tlv_data.nlpids == NULL || !speaks (lsp->tlv_data.nlpids, family))
jardineb5d44e2003-12-23 08:09:43 +0000569 return ISIS_OK;
570
hassof390d2c2004-09-10 20:48:21 +0000571lspfragloop:
572 if (lsp->lsp_header->seq_num == 0)
573 {
574 zlog_warn ("isis_spf_process_lsp(): lsp with 0 seq_num"
575 " - do not process");
576 return ISIS_WARNING;
577 }
jardineb5d44e2003-12-23 08:09:43 +0000578
hassof390d2c2004-09-10 20:48:21 +0000579 if (!ISIS_MASK_LSP_OL_BIT (lsp->lsp_header->lsp_bits))
580 {
581 if (lsp->tlv_data.is_neighs)
582 {
paul1eb8ef22005-04-07 07:30:20 +0000583 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh))
hassof390d2c2004-09-10 20:48:21 +0000584 {
hassof390d2c2004-09-10 20:48:21 +0000585 /* C.2.6 a) */
586 /* Two way connectivity */
587 if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
588 continue;
589 dist = cost + is_neigh->metrics.metric_default;
590 vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
591 : VTYPE_NONPSEUDO_IS;
592 process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist,
Peter Szilagyid034aa02011-10-01 17:22:51 +0400593 depth + 1, adj, family);
hassof390d2c2004-09-10 20:48:21 +0000594 }
595 }
hasso82a84282005-09-26 18:15:36 +0000596 if (lsp->tlv_data.te_is_neighs)
597 {
598 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node,
599 te_is_neigh))
600 {
601 uint32_t metric;
602 if (!memcmp (te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
603 continue;
604 memcpy (&metric, te_is_neigh->te_metric, 3);
605 dist = cost + ntohl (metric << 8);
606 vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS
607 : VTYPE_NONPSEUDO_TE_IS;
608 process_N (spftree, vtype, (void *) te_is_neigh->neigh_id, dist,
Peter Szilagyid034aa02011-10-01 17:22:51 +0400609 depth + 1, adj, family);
hasso82a84282005-09-26 18:15:36 +0000610 }
611 }
hassof390d2c2004-09-10 20:48:21 +0000612 if (family == AF_INET && lsp->tlv_data.ipv4_int_reachs)
613 {
614 prefix.family = AF_INET;
paul1eb8ef22005-04-07 07:30:20 +0000615 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_int_reachs,
616 node, ipreach))
hassof390d2c2004-09-10 20:48:21 +0000617 {
hassof390d2c2004-09-10 20:48:21 +0000618 dist = cost + ipreach->metrics.metric_default;
619 vtype = VTYPE_IPREACH_INTERNAL;
620 prefix.u.prefix4 = ipreach->prefix;
621 prefix.prefixlen = ip_masklen (ipreach->mask);
622 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
Peter Szilagyid034aa02011-10-01 17:22:51 +0400623 adj, family);
hassof390d2c2004-09-10 20:48:21 +0000624 }
625 }
626
627 if (family == AF_INET && lsp->tlv_data.ipv4_ext_reachs)
628 {
629 prefix.family = AF_INET;
paul1eb8ef22005-04-07 07:30:20 +0000630 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_ext_reachs,
631 node, ipreach))
hassof390d2c2004-09-10 20:48:21 +0000632 {
hassof390d2c2004-09-10 20:48:21 +0000633 dist = cost + ipreach->metrics.metric_default;
634 vtype = VTYPE_IPREACH_EXTERNAL;
635 prefix.u.prefix4 = ipreach->prefix;
636 prefix.prefixlen = ip_masklen (ipreach->mask);
637 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
Peter Szilagyid034aa02011-10-01 17:22:51 +0400638 adj, family);
hassof390d2c2004-09-10 20:48:21 +0000639 }
640 }
hasso82a84282005-09-26 18:15:36 +0000641 if (family == AF_INET && lsp->tlv_data.te_ipv4_reachs)
642 {
643 prefix.family = AF_INET;
644 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_ipv4_reachs,
645 node, te_ipv4_reach))
646 {
647 dist = cost + ntohl (te_ipv4_reach->te_metric);
648 vtype = VTYPE_IPREACH_TE;
649 prefix.u.prefix4 = newprefix2inaddr (&te_ipv4_reach->prefix_start,
650 te_ipv4_reach->control);
651 prefix.prefixlen = (te_ipv4_reach->control & 0x3F);
652 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
Peter Szilagyid034aa02011-10-01 17:22:51 +0400653 adj, family);
hasso82a84282005-09-26 18:15:36 +0000654 }
655 }
jardineb5d44e2003-12-23 08:09:43 +0000656#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000657 if (family == AF_INET6 && lsp->tlv_data.ipv6_reachs)
658 {
659 prefix.family = AF_INET6;
paul1eb8ef22005-04-07 07:30:20 +0000660 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv6_reachs,
661 node, ip6reach))
hassof390d2c2004-09-10 20:48:21 +0000662 {
hassof390d2c2004-09-10 20:48:21 +0000663 dist = cost + ip6reach->metric;
664 vtype = (ip6reach->control_info & CTRL_INFO_DISTRIBUTION) ?
665 VTYPE_IP6REACH_EXTERNAL : VTYPE_IP6REACH_INTERNAL;
666 prefix.prefixlen = ip6reach->prefix_len;
667 memcpy (&prefix.u.prefix6.s6_addr, ip6reach->prefix,
668 PSIZE (ip6reach->prefix_len));
669 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
Peter Szilagyid034aa02011-10-01 17:22:51 +0400670 adj, family);
hassof390d2c2004-09-10 20:48:21 +0000671 }
672 }
jardineb5d44e2003-12-23 08:09:43 +0000673#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000674 }
675
jardineb5d44e2003-12-23 08:09:43 +0000676 if (fragnode == NULL)
677 fragnode = listhead (lsp->lspu.frags);
hassof390d2c2004-09-10 20:48:21 +0000678 else
paul1eb8ef22005-04-07 07:30:20 +0000679 fragnode = listnextnode (fragnode);
jardineb5d44e2003-12-23 08:09:43 +0000680
hassof390d2c2004-09-10 20:48:21 +0000681 if (fragnode)
682 {
paul1eb8ef22005-04-07 07:30:20 +0000683 lsp = listgetdata (fragnode);
hassof390d2c2004-09-10 20:48:21 +0000684 goto lspfragloop;
685 }
686
jardineb5d44e2003-12-23 08:09:43 +0000687 return ISIS_OK;
688}
689
hasso92365882005-01-18 13:53:33 +0000690static int
hassof390d2c2004-09-10 20:48:21 +0000691isis_spf_process_pseudo_lsp (struct isis_spftree *spftree,
692 struct isis_lsp *lsp, uint16_t cost,
Peter Szilagyid034aa02011-10-01 17:22:51 +0400693 uint16_t depth, int family,
694 struct isis_adjacency *adj)
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;
Peter Szilagyid034aa02011-10-01 17:22:51 +0400718 if ((depth > 0 || isis_find_vertex
719 (spftree->tents, (void *) is_neigh->neigh_id, vtype) == NULL)
hasso82a84282005-09-26 18:15:36 +0000720 && 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) */
Peter Szilagyid034aa02011-10-01 17:22:51 +0400724 isis_spf_add2tent (spftree, vtype, is_neigh->neigh_id, 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;
Peter Szilagyid034aa02011-10-01 17:22:51 +0400736 if ((depth > 0 || isis_find_vertex
737 (spftree->tents, (void *) te_is_neigh->neigh_id, vtype) == NULL)
hasso82a84282005-09-26 18:15:36 +0000738 && isis_find_vertex (spftree->paths, (void *) te_is_neigh->neigh_id,
739 vtype) == NULL)
740 {
741 /* C.2.5 i) */
Peter Szilagyid034aa02011-10-01 17:22:51 +0400742 isis_spf_add2tent (spftree, vtype, te_is_neigh->neigh_id, adj,
hasso82a84282005-09-26 18:15:36 +0000743 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");
hassof390d2c2004-09-10 20:48:21 +0000863 break;
864 case ISIS_SYSTYPE_UNKNOWN:
865 default:
866 zlog_warn ("isis_spf_preload_tent unknow adj type");
867 }
paul1eb8ef22005-04-07 07:30:20 +0000868 anode = listnextnode (anode);
hassof390d2c2004-09-10 20:48:21 +0000869 }
870 list_delete (adj_list);
871 /*
872 * Add the pseudonode
873 */
874 if (level == 1)
875 memcpy (lsp_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
876 else
877 memcpy (lsp_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
878 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
879 adj = isis_adj_lookup (lsp_id, adjdb);
880 /* if no adj, we are the dis or error */
881 if (!adj && !circuit->u.bc.is_dr[level - 1])
882 {
883 zlog_warn ("ISIS-Spf: No adjacency found for DR");
884 }
Peter Szilagyid034aa02011-10-01 17:22:51 +0400885 else if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0)
hassof390d2c2004-09-10 20:48:21 +0000886 {
887 zlog_warn ("ISIS-Spf: No lsp found for DR");
888 }
889 else
890 {
hasso82a84282005-09-26 18:15:36 +0000891 isis_spf_process_pseudo_lsp (spftree, lsp,
Peter Szilagyid034aa02011-10-01 17:22:51 +0400892 circuit->te_metric[level - 1], 0, family, adj);
hassof390d2c2004-09-10 20:48:21 +0000893
894 }
895 }
896 else if (circuit->circ_type == CIRCUIT_T_P2P)
897 {
898 adj = circuit->u.p2p.neighbor;
899 if (!adj)
900 continue;
901 switch (adj->sys_type)
902 {
903 case ISIS_SYSTYPE_ES:
904 isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
hasso82a84282005-09-26 18:15:36 +0000905 circuit->te_metric[level - 1], family);
hassof390d2c2004-09-10 20:48:21 +0000906 break;
907 case ISIS_SYSTYPE_IS:
908 case ISIS_SYSTYPE_L1_IS:
909 case ISIS_SYSTYPE_L2_IS:
910 if (speaks (&adj->nlpids, family))
911 isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS, adj->sysid,
hasso82a84282005-09-26 18:15:36 +0000912 adj, circuit->te_metric[level - 1],
hassof390d2c2004-09-10 20:48:21 +0000913 family);
914 break;
915 case ISIS_SYSTYPE_UNKNOWN:
916 default:
917 zlog_warn ("isis_spf_preload_tent unknow adj type");
918 break;
919 }
920 }
jardineb5d44e2003-12-23 08:09:43 +0000921 else
hassof390d2c2004-09-10 20:48:21 +0000922 {
923 zlog_warn ("isis_spf_preload_tent unsupported media");
924 retval = ISIS_WARNING;
925 }
926
jardineb5d44e2003-12-23 08:09:43 +0000927 }
jardineb5d44e2003-12-23 08:09:43 +0000928
929 return retval;
930}
931
932/*
933 * The parent(s) for vertex is set when added to TENT list
934 * now we just put the child pointer(s) in place
935 */
hasso92365882005-01-18 13:53:33 +0000936static void
jardineb5d44e2003-12-23 08:09:43 +0000937add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex,
hassofac1f7c2005-09-26 18:26:26 +0000938 struct isis_area *area, int level)
jardineb5d44e2003-12-23 08:09:43 +0000939{
jardineb5d44e2003-12-23 08:09:43 +0000940#ifdef EXTREME_DEBUG
941 u_char buff[BUFSIZ];
942#endif /* EXTREME_DEBUG */
943 listnode_add (spftree->paths, vertex);
944
hassof390d2c2004-09-10 20:48:21 +0000945#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000946 zlog_debug ("ISIS-Spf: added %s %s depth %d dist %d to PATHS",
947 vtype2string (vertex->type), vid2string (vertex, buff),
948 vertex->depth, vertex->d_N);
hassof390d2c2004-09-10 20:48:21 +0000949#endif /* EXTREME_DEBUG */
950 if (vertex->type > VTYPE_ES)
951 {
952 if (listcount (vertex->Adj_N) > 0)
hassofac1f7c2005-09-26 18:26:26 +0000953 isis_route_create ((struct prefix *) &vertex->N.prefix, vertex->d_N,
954 vertex->depth, vertex->Adj_N, area, level);
hassof390d2c2004-09-10 20:48:21 +0000955 else if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000956 zlog_debug ("ISIS-Spf: no adjacencies do not install route");
hassof390d2c2004-09-10 20:48:21 +0000957 }
958
jardineb5d44e2003-12-23 08:09:43 +0000959 return;
960}
961
hasso92365882005-01-18 13:53:33 +0000962static void
jardineb5d44e2003-12-23 08:09:43 +0000963init_spt (struct isis_spftree *spftree)
964{
hassof7c43dc2004-09-26 16:24:14 +0000965 spftree->tents->del = spftree->paths->del = (void (*)(void *)) isis_vertex_del;
jardineb5d44e2003-12-23 08:09:43 +0000966 list_delete_all_node (spftree->tents);
967 list_delete_all_node (spftree->paths);
968 spftree->tents->del = spftree->paths->del = NULL;
hassof390d2c2004-09-10 20:48:21 +0000969
jardineb5d44e2003-12-23 08:09:43 +0000970 return;
971}
972
hasso92365882005-01-18 13:53:33 +0000973static int
jardineb5d44e2003-12-23 08:09:43 +0000974isis_run_spf (struct isis_area *area, int level, int family)
975{
976 int retval = ISIS_OK;
977 struct listnode *node;
978 struct isis_vertex *vertex;
hassof390d2c2004-09-10 20:48:21 +0000979 struct isis_spftree *spftree = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000980 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
981 struct isis_lsp *lsp;
Peter Szilagyid034aa02011-10-01 17:22:51 +0400982 struct isis_adjacency *adj = NULL;
hassofac1f7c2005-09-26 18:26:26 +0000983 struct route_table *table = NULL;
984 struct route_node *rode;
985 struct isis_route_info *rinfo;
hassof390d2c2004-09-10 20:48:21 +0000986
jardineb5d44e2003-12-23 08:09:43 +0000987 if (family == AF_INET)
988 spftree = area->spftree[level - 1];
989#ifdef HAVE_IPV6
990 else if (family == AF_INET6)
991 spftree = area->spftree6[level - 1];
992#endif
hassof390d2c2004-09-10 20:48:21 +0000993
jardineb5d44e2003-12-23 08:09:43 +0000994 assert (spftree);
995
hassofac1f7c2005-09-26 18:26:26 +0000996 /* Make all routes in current route table inactive. */
997 if (family == AF_INET)
998 table = area->route_table[level - 1];
Paul Jakma41b36e92006-12-08 01:09:50 +0000999#ifdef HAVE_IPV6
hassofac1f7c2005-09-26 18:26:26 +00001000 else if (family == AF_INET6)
1001 table = area->route_table6[level - 1];
Paul Jakma41b36e92006-12-08 01:09:50 +00001002#endif
hassofac1f7c2005-09-26 18:26:26 +00001003
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 {
Peter Szilagyid034aa02011-10-01 17:22:51 +04001043 if (listcount(vertex->Adj_N) == 0) {
1044 continue;
1045 }
1046 adj = listgetdata(vertex->Adj_N->head);
1047
hassof390d2c2004-09-10 20:48:21 +00001048 memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
1049 LSP_FRAGMENT (lsp_id) = 0;
1050 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
1051 if (lsp)
1052 {
1053 if (LSP_PSEUDO_ID (lsp_id))
1054 {
1055 isis_spf_process_pseudo_lsp (spftree, lsp, vertex->d_N,
Peter Szilagyid034aa02011-10-01 17:22:51 +04001056 vertex->depth, family, adj);
hassof390d2c2004-09-10 20:48:21 +00001057
1058 }
1059 else
1060 {
1061 isis_spf_process_lsp (spftree, lsp, vertex->d_N,
Peter Szilagyid034aa02011-10-01 17:22:51 +04001062 vertex->depth, family, adj);
hassof390d2c2004-09-10 20:48:21 +00001063 }
1064 }
1065 else
1066 {
1067 zlog_warn ("ISIS-Spf: No LSP found for %s",
1068 rawlspid_print (lsp_id));
1069 }
1070 }
1071 }
1072
hasso13fb40a2005-10-01 06:03:04 +00001073out:
jardineb5d44e2003-12-23 08:09:43 +00001074 thread_add_event (master, isis_route_validate, area, 0);
1075 spftree->lastrun = time (NULL);
1076 spftree->pending = 0;
hassof390d2c2004-09-10 20:48:21 +00001077
jardineb5d44e2003-12-23 08:09:43 +00001078 return retval;
1079}
1080
1081int
1082isis_run_spf_l1 (struct thread *thread)
1083{
1084 struct isis_area *area;
1085 int retval = ISIS_OK;
1086
hassof390d2c2004-09-10 20:48:21 +00001087 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001088 assert (area);
1089
hasso12a5cae2004-09-19 19:39:26 +00001090 area->spftree[0]->t_spf = NULL;
1091
hassof390d2c2004-09-10 20:48:21 +00001092 if (!(area->is_type & IS_LEVEL_1))
1093 {
1094 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001095 zlog_warn ("ISIS-SPF (%s) area does not share level",
1096 area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001097 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001098 }
jardineb5d44e2003-12-23 08:09:43 +00001099
hassof390d2c2004-09-10 20:48:21 +00001100 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001101 zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001102
jardineb5d44e2003-12-23 08:09:43 +00001103 if (area->ip_circuits)
1104 retval = isis_run_spf (area, 1, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001105
1106 THREAD_TIMER_ON (master, area->spftree[0]->t_spf, isis_run_spf_l1, area,
1107 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1108
jardineb5d44e2003-12-23 08:09:43 +00001109 return retval;
1110}
1111
1112int
1113isis_run_spf_l2 (struct thread *thread)
1114{
1115 struct isis_area *area;
1116 int retval = ISIS_OK;
1117
hassof390d2c2004-09-10 20:48:21 +00001118 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001119 assert (area);
hassof390d2c2004-09-10 20:48:21 +00001120
hasso12a5cae2004-09-19 19:39:26 +00001121 area->spftree[1]->t_spf = NULL;
1122
hassof390d2c2004-09-10 20:48:21 +00001123 if (!(area->is_type & IS_LEVEL_2))
1124 {
1125 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001126 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001127 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001128 }
hassof390d2c2004-09-10 20:48:21 +00001129
1130 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001131 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag);
jardineb5d44e2003-12-23 08:09:43 +00001132
1133 if (area->ip_circuits)
1134 retval = isis_run_spf (area, 2, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001135
1136 THREAD_TIMER_ON (master, area->spftree[1]->t_spf, isis_run_spf_l2, area,
1137 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
jardineb5d44e2003-12-23 08:09:43 +00001138
1139 return retval;
1140}
1141
hassof390d2c2004-09-10 20:48:21 +00001142int
jardineb5d44e2003-12-23 08:09:43 +00001143isis_spf_schedule (struct isis_area *area, int level)
1144{
1145 int retval = ISIS_OK;
1146 struct isis_spftree *spftree = area->spftree[level - 1];
1147 time_t diff, now = time (NULL);
1148
1149 if (spftree->pending)
1150 return retval;
1151
hassof390d2c2004-09-10 20:48:21 +00001152 diff = now - spftree->lastrun;
jardineb5d44e2003-12-23 08:09:43 +00001153
1154 /* FIXME: let's wait a minute before doing the SPF */
hassof390d2c2004-09-10 20:48:21 +00001155 if (now - isis->uptime < 60 || isis->uptime == 0)
1156 {
1157 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001158 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area, 60);
hassof390d2c2004-09-10 20:48:21 +00001159 else
hasso12a5cae2004-09-19 19:39:26 +00001160 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area, 60);
jardineb5d44e2003-12-23 08:09:43 +00001161
hassof390d2c2004-09-10 20:48:21 +00001162 spftree->pending = 1;
1163 return retval;
1164 }
hasso12a5cae2004-09-19 19:39:26 +00001165
1166 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001167
hassof390d2c2004-09-10 20:48:21 +00001168 if (diff < MINIMUM_SPF_INTERVAL)
1169 {
1170 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001171 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
1172 MINIMUM_SPF_INTERVAL - diff);
hassof390d2c2004-09-10 20:48:21 +00001173 else
hasso12a5cae2004-09-19 19:39:26 +00001174 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
1175 MINIMUM_SPF_INTERVAL - diff);
jardineb5d44e2003-12-23 08:09:43 +00001176
hassof390d2c2004-09-10 20:48:21 +00001177 spftree->pending = 1;
1178 }
1179 else
1180 {
1181 spftree->pending = 0;
1182 retval = isis_run_spf (area, level, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001183 if (level == 1)
1184 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
1185 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1186 else
1187 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
1188 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
hassof390d2c2004-09-10 20:48:21 +00001189 }
jardineb5d44e2003-12-23 08:09:43 +00001190
1191 return retval;
1192}
1193
1194#ifdef HAVE_IPV6
hasso92365882005-01-18 13:53:33 +00001195static int
hasso12a5cae2004-09-19 19:39:26 +00001196isis_run_spf6_l1 (struct thread *thread)
1197{
1198 struct isis_area *area;
1199 int retval = ISIS_OK;
1200
1201 area = THREAD_ARG (thread);
1202 assert (area);
1203
1204 area->spftree6[0]->t_spf = NULL;
1205
1206 if (!(area->is_type & IS_LEVEL_1))
1207 {
1208 if (isis->debugs & DEBUG_SPF_EVENTS)
1209 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
1210 return ISIS_WARNING;
1211 }
1212
1213 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001214 zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001215
1216 if (area->ipv6_circuits)
1217 retval = isis_run_spf (area, 1, AF_INET6);
1218
1219 THREAD_TIMER_ON (master, area->spftree6[0]->t_spf, isis_run_spf6_l1, area,
1220 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1221
1222 return retval;
1223}
1224
hasso92365882005-01-18 13:53:33 +00001225static int
hasso12a5cae2004-09-19 19:39:26 +00001226isis_run_spf6_l2 (struct thread *thread)
1227{
1228 struct isis_area *area;
1229 int retval = ISIS_OK;
1230
1231 area = THREAD_ARG (thread);
1232 assert (area);
1233
1234 area->spftree6[1]->t_spf = NULL;
1235
1236 if (!(area->is_type & IS_LEVEL_2))
1237 {
1238 if (isis->debugs & DEBUG_SPF_EVENTS)
1239 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
1240 return ISIS_WARNING;
1241 }
1242
1243 if (isis->debugs & DEBUG_SPF_EVENTS)
hassofac1f7c2005-09-26 18:26:26 +00001244 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF.", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001245
1246 if (area->ipv6_circuits)
1247 retval = isis_run_spf (area, 2, AF_INET6);
1248
1249 THREAD_TIMER_ON (master, area->spftree6[1]->t_spf, isis_run_spf6_l2, area,
1250 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1251
1252 return retval;
1253}
1254
1255int
jardineb5d44e2003-12-23 08:09:43 +00001256isis_spf_schedule6 (struct isis_area *area, int level)
1257{
1258 int retval = ISIS_OK;
1259 struct isis_spftree *spftree = area->spftree6[level - 1];
1260 time_t diff, now = time (NULL);
1261
1262 if (spftree->pending)
1263 return retval;
1264
hassof390d2c2004-09-10 20:48:21 +00001265 diff = now - spftree->lastrun;
1266
jardineb5d44e2003-12-23 08:09:43 +00001267 /* FIXME: let's wait a minute before doing the SPF */
hassof390d2c2004-09-10 20:48:21 +00001268 if (now - isis->uptime < 60 || isis->uptime == 0)
1269 {
1270 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001271 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area, 60);
hassof390d2c2004-09-10 20:48:21 +00001272 else
hasso12a5cae2004-09-19 19:39:26 +00001273 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area, 60);
jardineb5d44e2003-12-23 08:09:43 +00001274
hassof390d2c2004-09-10 20:48:21 +00001275 spftree->pending = 1;
1276 return retval;
1277 }
hasso12a5cae2004-09-19 19:39:26 +00001278
1279 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001280
hassof390d2c2004-09-10 20:48:21 +00001281 if (diff < MINIMUM_SPF_INTERVAL)
1282 {
1283 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001284 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
1285 MINIMUM_SPF_INTERVAL - diff);
hassof390d2c2004-09-10 20:48:21 +00001286 else
hasso12a5cae2004-09-19 19:39:26 +00001287 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
1288 MINIMUM_SPF_INTERVAL - diff);
jardineb5d44e2003-12-23 08:09:43 +00001289
hassof390d2c2004-09-10 20:48:21 +00001290 spftree->pending = 1;
1291 }
1292 else
1293 {
1294 spftree->pending = 0;
1295 retval = isis_run_spf (area, level, AF_INET6);
hasso12a5cae2004-09-19 19:39:26 +00001296
1297 if (level == 1)
1298 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
1299 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1300 else
1301 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
1302 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
hassof390d2c2004-09-10 20:48:21 +00001303 }
jardineb5d44e2003-12-23 08:09:43 +00001304
1305 return retval;
1306}
jardineb5d44e2003-12-23 08:09:43 +00001307#endif
1308
hasso92365882005-01-18 13:53:33 +00001309static void
jardineb5d44e2003-12-23 08:09:43 +00001310isis_print_paths (struct vty *vty, struct list *paths)
1311{
paul1eb8ef22005-04-07 07:30:20 +00001312 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +00001313 struct isis_vertex *vertex;
1314 struct isis_dynhn *dyn, *nh_dyn = NULL;
1315 struct isis_adjacency *adj;
hasso92365882005-01-18 13:53:33 +00001316#if 0
jardineb5d44e2003-12-23 08:09:43 +00001317 u_char buff[255];
hasso92365882005-01-18 13:53:33 +00001318#endif /* 0 */
jardineb5d44e2003-12-23 08:09:43 +00001319
1320 vty_out (vty, "System Id Metric Next-Hop"
hassof390d2c2004-09-10 20:48:21 +00001321 " Interface SNPA%s", VTY_NEWLINE);
paul1eb8ef22005-04-07 07:30:20 +00001322
1323 for (ALL_LIST_ELEMENTS_RO (paths, node, vertex))
hassof390d2c2004-09-10 20:48:21 +00001324 {
hassof390d2c2004-09-10 20:48:21 +00001325 if (vertex->type != VTYPE_NONPSEUDO_IS)
1326 continue;
1327 if (memcmp (vertex->N.id, isis->sysid, ISIS_SYS_ID_LEN) == 0)
1328 {
hassoc3d26c72005-03-07 08:54:41 +00001329 vty_out (vty, "%s --%s", host.name?host.name:"",
1330 VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +00001331 }
1332 else
1333 {
1334 dyn = dynhn_find_by_id ((u_char *) vertex->N.id);
paul1eb8ef22005-04-07 07:30:20 +00001335 adj = listgetdata (listhead (vertex->Adj_N));
hassof390d2c2004-09-10 20:48:21 +00001336 if (adj)
1337 {
1338 nh_dyn = dynhn_find_by_id (adj->sysid);
1339 vty_out (vty, "%-20s %-10u %-20s %-11s %-5s%s",
1340 (dyn != NULL) ? dyn->name.name :
Paul Jakma41b36e92006-12-08 01:09:50 +00001341 (const u_char *)rawlspid_print ((u_char *) vertex->N.id),
hassof390d2c2004-09-10 20:48:21 +00001342 vertex->d_N, (nh_dyn != NULL) ? nh_dyn->name.name :
Paul Jakma41b36e92006-12-08 01:09:50 +00001343 (const u_char *)rawlspid_print (adj->sysid),
hassof390d2c2004-09-10 20:48:21 +00001344 adj->circuit->interface->name,
1345 snpa_print (adj->snpa), VTY_NEWLINE);
1346 }
1347 else
1348 {
1349 vty_out (vty, "%s %u %s", dyn ? dyn->name.name :
Paul Jakma41b36e92006-12-08 01:09:50 +00001350 (const u_char *) rawlspid_print (vertex->N.id),
hassof390d2c2004-09-10 20:48:21 +00001351 vertex->d_N, VTY_NEWLINE);
1352 }
1353 }
jardineb5d44e2003-12-23 08:09:43 +00001354#if 0
hassof390d2c2004-09-10 20:48:21 +00001355 vty_out (vty, "%s %s %u %s", vtype2string (vertex->type),
1356 vid2string (vertex, buff), vertex->d_N, VTY_NEWLINE);
jardineb5d44e2003-12-23 08:09:43 +00001357#endif
hassof390d2c2004-09-10 20:48:21 +00001358 }
jardineb5d44e2003-12-23 08:09:43 +00001359}
1360
1361DEFUN (show_isis_topology,
1362 show_isis_topology_cmd,
1363 "show isis topology",
1364 SHOW_STR
1365 "IS-IS information\n"
1366 "IS-IS paths to Intermediate Systems\n")
1367{
1368 struct listnode *node;
1369 struct isis_area *area;
1370 int level;
hassof390d2c2004-09-10 20:48:21 +00001371
jardineb5d44e2003-12-23 08:09:43 +00001372 if (!isis->area_list || isis->area_list->count == 0)
1373 return CMD_SUCCESS;
1374
paul1eb8ef22005-04-07 07:30:20 +00001375 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001376 {
hassof390d2c2004-09-10 20:48:21 +00001377 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1378 VTY_NEWLINE);
1379
1380 for (level = 0; level < ISIS_LEVELS; level++)
1381 {
1382 if (area->ip_circuits > 0 && area->spftree[level]
1383 && area->spftree[level]->paths->count > 0)
1384 {
1385 vty_out (vty, "IS-IS paths to level-%d routers that speak IP%s",
1386 level + 1, VTY_NEWLINE);
1387 isis_print_paths (vty, area->spftree[level]->paths);
1388 }
jardineb5d44e2003-12-23 08:09:43 +00001389#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001390 if (area->ipv6_circuits > 0 && area->spftree6[level]
1391 && area->spftree6[level]->paths->count > 0)
1392 {
1393 vty_out (vty,
1394 "IS-IS paths to level-%d routers that speak IPv6%s",
1395 level + 1, VTY_NEWLINE);
1396 isis_print_paths (vty, area->spftree6[level]->paths);
1397 }
jardineb5d44e2003-12-23 08:09:43 +00001398#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +00001399 }
jardineb5d44e2003-12-23 08:09:43 +00001400 }
jardineb5d44e2003-12-23 08:09:43 +00001401
1402 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001403}
jardineb5d44e2003-12-23 08:09:43 +00001404
1405DEFUN (show_isis_topology_l1,
1406 show_isis_topology_l1_cmd,
1407 "show isis topology level-1",
1408 SHOW_STR
1409 "IS-IS information\n"
1410 "IS-IS paths to Intermediate Systems\n"
1411 "Paths to all level-1 routers in the area\n")
1412{
1413 struct listnode *node;
1414 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001415
jardineb5d44e2003-12-23 08:09:43 +00001416 if (!isis->area_list || isis->area_list->count == 0)
1417 return CMD_SUCCESS;
1418
paul1eb8ef22005-04-07 07:30:20 +00001419 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001420 {
hassof390d2c2004-09-10 20:48:21 +00001421 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1422 VTY_NEWLINE);
1423
1424 if (area->ip_circuits > 0 && area->spftree[0]
1425 && area->spftree[0]->paths->count > 0)
1426 {
1427 vty_out (vty, "IS-IS paths to level-1 routers that speak IP%s",
1428 VTY_NEWLINE);
1429 isis_print_paths (vty, area->spftree[0]->paths);
1430 }
jardineb5d44e2003-12-23 08:09:43 +00001431#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001432 if (area->ipv6_circuits > 0 && area->spftree6[0]
1433 && area->spftree6[0]->paths->count > 0)
1434 {
1435 vty_out (vty, "IS-IS paths to level-1 routers that speak IPv6%s",
1436 VTY_NEWLINE);
1437 isis_print_paths (vty, area->spftree6[0]->paths);
1438 }
jardineb5d44e2003-12-23 08:09:43 +00001439#endif /* HAVE_IPV6 */
1440 }
1441
jardineb5d44e2003-12-23 08:09:43 +00001442 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001443}
jardineb5d44e2003-12-23 08:09:43 +00001444
1445DEFUN (show_isis_topology_l2,
1446 show_isis_topology_l2_cmd,
1447 "show isis topology level-2",
1448 SHOW_STR
1449 "IS-IS information\n"
1450 "IS-IS paths to Intermediate Systems\n"
1451 "Paths to all level-2 routers in the domain\n")
1452{
1453 struct listnode *node;
1454 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001455
jardineb5d44e2003-12-23 08:09:43 +00001456 if (!isis->area_list || isis->area_list->count == 0)
1457 return CMD_SUCCESS;
1458
paul1eb8ef22005-04-07 07:30:20 +00001459 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001460 {
hassof390d2c2004-09-10 20:48:21 +00001461 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1462 VTY_NEWLINE);
1463
1464 if (area->ip_circuits > 0 && area->spftree[1]
1465 && area->spftree[1]->paths->count > 0)
1466 {
1467 vty_out (vty, "IS-IS paths to level-2 routers that speak IP%s",
1468 VTY_NEWLINE);
1469 isis_print_paths (vty, area->spftree[1]->paths);
1470 }
jardineb5d44e2003-12-23 08:09:43 +00001471#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001472 if (area->ipv6_circuits > 0 && area->spftree6[1]
1473 && area->spftree6[1]->paths->count > 0)
1474 {
1475 vty_out (vty, "IS-IS paths to level-2 routers that speak IPv6%s",
1476 VTY_NEWLINE);
1477 isis_print_paths (vty, area->spftree6[1]->paths);
1478 }
jardineb5d44e2003-12-23 08:09:43 +00001479#endif /* HAVE_IPV6 */
1480 }
1481
jardineb5d44e2003-12-23 08:09:43 +00001482 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001483}
jardineb5d44e2003-12-23 08:09:43 +00001484
1485void
1486isis_spf_cmds_init ()
1487{
1488 install_element (VIEW_NODE, &show_isis_topology_cmd);
1489 install_element (VIEW_NODE, &show_isis_topology_l1_cmd);
1490 install_element (VIEW_NODE, &show_isis_topology_l2_cmd);
1491
1492 install_element (ENABLE_NODE, &show_isis_topology_cmd);
1493 install_element (ENABLE_NODE, &show_isis_topology_l1_cmd);
1494 install_element (ENABLE_NODE, &show_isis_topology_l2_cmd);
1495}