blob: 5d0b161f4755672ea05326011fbd4030588482c4 [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 {
Fritz Reichmannc25eaff2011-10-01 17:43:12 +04001033 /* C.2.7 a) 1) */
hassof390d2c2004-09-10 20:48:21 +00001034 node = listhead (spftree->tents);
paul1eb8ef22005-04-07 07:30:20 +00001035 vertex = listgetdata (node);
Fritz Reichmannc25eaff2011-10-01 17:43:12 +04001036
1037 /* C.2.7 a) 2) */
hassof390d2c2004-09-10 20:48:21 +00001038 list_delete_node (spftree->tents, node);
Fritz Reichmannc25eaff2011-10-01 17:43:12 +04001039
1040 /* C.2.7 a) 3) */
hassof390d2c2004-09-10 20:48:21 +00001041 if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type))
1042 continue;
hassofac1f7c2005-09-26 18:26:26 +00001043 add_to_paths (spftree, vertex, area, level);
Fritz Reichmannc25eaff2011-10-01 17:43:12 +04001044
hassof390d2c2004-09-10 20:48:21 +00001045 if (vertex->type == VTYPE_PSEUDO_IS ||
Fritz Reichmannc25eaff2011-10-01 17:43:12 +04001046 vertex->type == VTYPE_NONPSEUDO_IS ||
1047 vertex->type == VTYPE_PSEUDO_TE_IS ||
1048 vertex->type == VTYPE_NONPSEUDO_TE_IS )
hassof390d2c2004-09-10 20:48:21 +00001049 {
Peter Szilagyid034aa02011-10-01 17:22:51 +04001050 if (listcount(vertex->Adj_N) == 0) {
1051 continue;
1052 }
1053 adj = listgetdata(vertex->Adj_N->head);
1054
hassof390d2c2004-09-10 20:48:21 +00001055 memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
1056 LSP_FRAGMENT (lsp_id) = 0;
1057 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
1058 if (lsp)
1059 {
1060 if (LSP_PSEUDO_ID (lsp_id))
1061 {
1062 isis_spf_process_pseudo_lsp (spftree, lsp, vertex->d_N,
Peter Szilagyid034aa02011-10-01 17:22:51 +04001063 vertex->depth, family, adj);
hassof390d2c2004-09-10 20:48:21 +00001064 }
1065 else
1066 {
1067 isis_spf_process_lsp (spftree, lsp, vertex->d_N,
Peter Szilagyid034aa02011-10-01 17:22:51 +04001068 vertex->depth, family, adj);
hassof390d2c2004-09-10 20:48:21 +00001069 }
1070 }
1071 else
1072 {
1073 zlog_warn ("ISIS-Spf: No LSP found for %s",
1074 rawlspid_print (lsp_id));
1075 }
1076 }
1077 }
1078
hasso13fb40a2005-10-01 06:03:04 +00001079out:
jardineb5d44e2003-12-23 08:09:43 +00001080 thread_add_event (master, isis_route_validate, area, 0);
1081 spftree->lastrun = time (NULL);
1082 spftree->pending = 0;
hassof390d2c2004-09-10 20:48:21 +00001083
jardineb5d44e2003-12-23 08:09:43 +00001084 return retval;
1085}
1086
1087int
1088isis_run_spf_l1 (struct thread *thread)
1089{
1090 struct isis_area *area;
1091 int retval = ISIS_OK;
1092
hassof390d2c2004-09-10 20:48:21 +00001093 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001094 assert (area);
1095
hasso12a5cae2004-09-19 19:39:26 +00001096 area->spftree[0]->t_spf = NULL;
1097
hassof390d2c2004-09-10 20:48:21 +00001098 if (!(area->is_type & IS_LEVEL_1))
1099 {
1100 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001101 zlog_warn ("ISIS-SPF (%s) area does not share level",
1102 area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001103 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001104 }
jardineb5d44e2003-12-23 08:09:43 +00001105
hassof390d2c2004-09-10 20:48:21 +00001106 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001107 zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001108
jardineb5d44e2003-12-23 08:09:43 +00001109 if (area->ip_circuits)
1110 retval = isis_run_spf (area, 1, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001111
1112 THREAD_TIMER_ON (master, area->spftree[0]->t_spf, isis_run_spf_l1, area,
1113 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1114
jardineb5d44e2003-12-23 08:09:43 +00001115 return retval;
1116}
1117
1118int
1119isis_run_spf_l2 (struct thread *thread)
1120{
1121 struct isis_area *area;
1122 int retval = ISIS_OK;
1123
hassof390d2c2004-09-10 20:48:21 +00001124 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001125 assert (area);
hassof390d2c2004-09-10 20:48:21 +00001126
hasso12a5cae2004-09-19 19:39:26 +00001127 area->spftree[1]->t_spf = NULL;
1128
hassof390d2c2004-09-10 20:48:21 +00001129 if (!(area->is_type & IS_LEVEL_2))
1130 {
1131 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001132 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001133 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001134 }
hassof390d2c2004-09-10 20:48:21 +00001135
1136 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001137 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag);
jardineb5d44e2003-12-23 08:09:43 +00001138
1139 if (area->ip_circuits)
1140 retval = isis_run_spf (area, 2, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001141
1142 THREAD_TIMER_ON (master, area->spftree[1]->t_spf, isis_run_spf_l2, area,
1143 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
jardineb5d44e2003-12-23 08:09:43 +00001144
1145 return retval;
1146}
1147
hassof390d2c2004-09-10 20:48:21 +00001148int
jardineb5d44e2003-12-23 08:09:43 +00001149isis_spf_schedule (struct isis_area *area, int level)
1150{
1151 int retval = ISIS_OK;
1152 struct isis_spftree *spftree = area->spftree[level - 1];
1153 time_t diff, now = time (NULL);
1154
1155 if (spftree->pending)
1156 return retval;
1157
hassof390d2c2004-09-10 20:48:21 +00001158 diff = now - spftree->lastrun;
jardineb5d44e2003-12-23 08:09:43 +00001159
1160 /* FIXME: let's wait a minute before doing the SPF */
hassof390d2c2004-09-10 20:48:21 +00001161 if (now - isis->uptime < 60 || isis->uptime == 0)
1162 {
1163 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001164 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area, 60);
hassof390d2c2004-09-10 20:48:21 +00001165 else
hasso12a5cae2004-09-19 19:39:26 +00001166 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area, 60);
jardineb5d44e2003-12-23 08:09:43 +00001167
hassof390d2c2004-09-10 20:48:21 +00001168 spftree->pending = 1;
1169 return retval;
1170 }
hasso12a5cae2004-09-19 19:39:26 +00001171
1172 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001173
hassof390d2c2004-09-10 20:48:21 +00001174 if (diff < MINIMUM_SPF_INTERVAL)
1175 {
1176 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001177 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
1178 MINIMUM_SPF_INTERVAL - diff);
hassof390d2c2004-09-10 20:48:21 +00001179 else
hasso12a5cae2004-09-19 19:39:26 +00001180 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
1181 MINIMUM_SPF_INTERVAL - diff);
jardineb5d44e2003-12-23 08:09:43 +00001182
hassof390d2c2004-09-10 20:48:21 +00001183 spftree->pending = 1;
1184 }
1185 else
1186 {
1187 spftree->pending = 0;
1188 retval = isis_run_spf (area, level, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001189 if (level == 1)
1190 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
1191 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1192 else
1193 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
1194 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
hassof390d2c2004-09-10 20:48:21 +00001195 }
jardineb5d44e2003-12-23 08:09:43 +00001196
1197 return retval;
1198}
1199
1200#ifdef HAVE_IPV6
hasso92365882005-01-18 13:53:33 +00001201static int
hasso12a5cae2004-09-19 19:39:26 +00001202isis_run_spf6_l1 (struct thread *thread)
1203{
1204 struct isis_area *area;
1205 int retval = ISIS_OK;
1206
1207 area = THREAD_ARG (thread);
1208 assert (area);
1209
1210 area->spftree6[0]->t_spf = NULL;
1211
1212 if (!(area->is_type & IS_LEVEL_1))
1213 {
1214 if (isis->debugs & DEBUG_SPF_EVENTS)
1215 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
1216 return ISIS_WARNING;
1217 }
1218
1219 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001220 zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001221
1222 if (area->ipv6_circuits)
1223 retval = isis_run_spf (area, 1, AF_INET6);
1224
1225 THREAD_TIMER_ON (master, area->spftree6[0]->t_spf, isis_run_spf6_l1, area,
1226 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1227
1228 return retval;
1229}
1230
hasso92365882005-01-18 13:53:33 +00001231static int
hasso12a5cae2004-09-19 19:39:26 +00001232isis_run_spf6_l2 (struct thread *thread)
1233{
1234 struct isis_area *area;
1235 int retval = ISIS_OK;
1236
1237 area = THREAD_ARG (thread);
1238 assert (area);
1239
1240 area->spftree6[1]->t_spf = NULL;
1241
1242 if (!(area->is_type & IS_LEVEL_2))
1243 {
1244 if (isis->debugs & DEBUG_SPF_EVENTS)
1245 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
1246 return ISIS_WARNING;
1247 }
1248
1249 if (isis->debugs & DEBUG_SPF_EVENTS)
hassofac1f7c2005-09-26 18:26:26 +00001250 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF.", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001251
1252 if (area->ipv6_circuits)
1253 retval = isis_run_spf (area, 2, AF_INET6);
1254
1255 THREAD_TIMER_ON (master, area->spftree6[1]->t_spf, isis_run_spf6_l2, area,
1256 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1257
1258 return retval;
1259}
1260
1261int
jardineb5d44e2003-12-23 08:09:43 +00001262isis_spf_schedule6 (struct isis_area *area, int level)
1263{
1264 int retval = ISIS_OK;
1265 struct isis_spftree *spftree = area->spftree6[level - 1];
1266 time_t diff, now = time (NULL);
1267
1268 if (spftree->pending)
1269 return retval;
1270
hassof390d2c2004-09-10 20:48:21 +00001271 diff = now - spftree->lastrun;
1272
jardineb5d44e2003-12-23 08:09:43 +00001273 /* FIXME: let's wait a minute before doing the SPF */
hassof390d2c2004-09-10 20:48:21 +00001274 if (now - isis->uptime < 60 || isis->uptime == 0)
1275 {
1276 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001277 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area, 60);
hassof390d2c2004-09-10 20:48:21 +00001278 else
hasso12a5cae2004-09-19 19:39:26 +00001279 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area, 60);
jardineb5d44e2003-12-23 08:09:43 +00001280
hassof390d2c2004-09-10 20:48:21 +00001281 spftree->pending = 1;
1282 return retval;
1283 }
hasso12a5cae2004-09-19 19:39:26 +00001284
1285 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001286
hassof390d2c2004-09-10 20:48:21 +00001287 if (diff < MINIMUM_SPF_INTERVAL)
1288 {
1289 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001290 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
1291 MINIMUM_SPF_INTERVAL - diff);
hassof390d2c2004-09-10 20:48:21 +00001292 else
hasso12a5cae2004-09-19 19:39:26 +00001293 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
1294 MINIMUM_SPF_INTERVAL - diff);
jardineb5d44e2003-12-23 08:09:43 +00001295
hassof390d2c2004-09-10 20:48:21 +00001296 spftree->pending = 1;
1297 }
1298 else
1299 {
1300 spftree->pending = 0;
1301 retval = isis_run_spf (area, level, AF_INET6);
hasso12a5cae2004-09-19 19:39:26 +00001302
1303 if (level == 1)
1304 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
1305 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1306 else
1307 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
1308 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
hassof390d2c2004-09-10 20:48:21 +00001309 }
jardineb5d44e2003-12-23 08:09:43 +00001310
1311 return retval;
1312}
jardineb5d44e2003-12-23 08:09:43 +00001313#endif
1314
hasso92365882005-01-18 13:53:33 +00001315static void
jardineb5d44e2003-12-23 08:09:43 +00001316isis_print_paths (struct vty *vty, struct list *paths)
1317{
paul1eb8ef22005-04-07 07:30:20 +00001318 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +00001319 struct isis_vertex *vertex;
1320 struct isis_dynhn *dyn, *nh_dyn = NULL;
1321 struct isis_adjacency *adj;
hasso92365882005-01-18 13:53:33 +00001322#if 0
jardineb5d44e2003-12-23 08:09:43 +00001323 u_char buff[255];
hasso92365882005-01-18 13:53:33 +00001324#endif /* 0 */
jardineb5d44e2003-12-23 08:09:43 +00001325
1326 vty_out (vty, "System Id Metric Next-Hop"
hassof390d2c2004-09-10 20:48:21 +00001327 " Interface SNPA%s", VTY_NEWLINE);
paul1eb8ef22005-04-07 07:30:20 +00001328
1329 for (ALL_LIST_ELEMENTS_RO (paths, node, vertex))
hassof390d2c2004-09-10 20:48:21 +00001330 {
hassof390d2c2004-09-10 20:48:21 +00001331 if (vertex->type != VTYPE_NONPSEUDO_IS)
1332 continue;
1333 if (memcmp (vertex->N.id, isis->sysid, ISIS_SYS_ID_LEN) == 0)
1334 {
hassoc3d26c72005-03-07 08:54:41 +00001335 vty_out (vty, "%s --%s", host.name?host.name:"",
1336 VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +00001337 }
1338 else
1339 {
1340 dyn = dynhn_find_by_id ((u_char *) vertex->N.id);
paul1eb8ef22005-04-07 07:30:20 +00001341 adj = listgetdata (listhead (vertex->Adj_N));
hassof390d2c2004-09-10 20:48:21 +00001342 if (adj)
1343 {
1344 nh_dyn = dynhn_find_by_id (adj->sysid);
1345 vty_out (vty, "%-20s %-10u %-20s %-11s %-5s%s",
1346 (dyn != NULL) ? dyn->name.name :
Paul Jakma41b36e92006-12-08 01:09:50 +00001347 (const u_char *)rawlspid_print ((u_char *) vertex->N.id),
hassof390d2c2004-09-10 20:48:21 +00001348 vertex->d_N, (nh_dyn != NULL) ? nh_dyn->name.name :
Paul Jakma41b36e92006-12-08 01:09:50 +00001349 (const u_char *)rawlspid_print (adj->sysid),
hassof390d2c2004-09-10 20:48:21 +00001350 adj->circuit->interface->name,
1351 snpa_print (adj->snpa), VTY_NEWLINE);
1352 }
1353 else
1354 {
1355 vty_out (vty, "%s %u %s", dyn ? dyn->name.name :
Paul Jakma41b36e92006-12-08 01:09:50 +00001356 (const u_char *) rawlspid_print (vertex->N.id),
hassof390d2c2004-09-10 20:48:21 +00001357 vertex->d_N, VTY_NEWLINE);
1358 }
1359 }
jardineb5d44e2003-12-23 08:09:43 +00001360#if 0
hassof390d2c2004-09-10 20:48:21 +00001361 vty_out (vty, "%s %s %u %s", vtype2string (vertex->type),
1362 vid2string (vertex, buff), vertex->d_N, VTY_NEWLINE);
jardineb5d44e2003-12-23 08:09:43 +00001363#endif
hassof390d2c2004-09-10 20:48:21 +00001364 }
jardineb5d44e2003-12-23 08:09:43 +00001365}
1366
1367DEFUN (show_isis_topology,
1368 show_isis_topology_cmd,
1369 "show isis topology",
1370 SHOW_STR
1371 "IS-IS information\n"
1372 "IS-IS paths to Intermediate Systems\n")
1373{
1374 struct listnode *node;
1375 struct isis_area *area;
1376 int level;
hassof390d2c2004-09-10 20:48:21 +00001377
jardineb5d44e2003-12-23 08:09:43 +00001378 if (!isis->area_list || isis->area_list->count == 0)
1379 return CMD_SUCCESS;
1380
paul1eb8ef22005-04-07 07:30:20 +00001381 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001382 {
hassof390d2c2004-09-10 20:48:21 +00001383 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1384 VTY_NEWLINE);
1385
1386 for (level = 0; level < ISIS_LEVELS; level++)
1387 {
1388 if (area->ip_circuits > 0 && area->spftree[level]
1389 && area->spftree[level]->paths->count > 0)
1390 {
1391 vty_out (vty, "IS-IS paths to level-%d routers that speak IP%s",
1392 level + 1, VTY_NEWLINE);
1393 isis_print_paths (vty, area->spftree[level]->paths);
1394 }
jardineb5d44e2003-12-23 08:09:43 +00001395#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001396 if (area->ipv6_circuits > 0 && area->spftree6[level]
1397 && area->spftree6[level]->paths->count > 0)
1398 {
1399 vty_out (vty,
1400 "IS-IS paths to level-%d routers that speak IPv6%s",
1401 level + 1, VTY_NEWLINE);
1402 isis_print_paths (vty, area->spftree6[level]->paths);
1403 }
jardineb5d44e2003-12-23 08:09:43 +00001404#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +00001405 }
jardineb5d44e2003-12-23 08:09:43 +00001406 }
jardineb5d44e2003-12-23 08:09:43 +00001407
1408 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001409}
jardineb5d44e2003-12-23 08:09:43 +00001410
1411DEFUN (show_isis_topology_l1,
1412 show_isis_topology_l1_cmd,
1413 "show isis topology level-1",
1414 SHOW_STR
1415 "IS-IS information\n"
1416 "IS-IS paths to Intermediate Systems\n"
1417 "Paths to all level-1 routers in the area\n")
1418{
1419 struct listnode *node;
1420 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001421
jardineb5d44e2003-12-23 08:09:43 +00001422 if (!isis->area_list || isis->area_list->count == 0)
1423 return CMD_SUCCESS;
1424
paul1eb8ef22005-04-07 07:30:20 +00001425 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001426 {
hassof390d2c2004-09-10 20:48:21 +00001427 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1428 VTY_NEWLINE);
1429
1430 if (area->ip_circuits > 0 && area->spftree[0]
1431 && area->spftree[0]->paths->count > 0)
1432 {
1433 vty_out (vty, "IS-IS paths to level-1 routers that speak IP%s",
1434 VTY_NEWLINE);
1435 isis_print_paths (vty, area->spftree[0]->paths);
1436 }
jardineb5d44e2003-12-23 08:09:43 +00001437#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001438 if (area->ipv6_circuits > 0 && area->spftree6[0]
1439 && area->spftree6[0]->paths->count > 0)
1440 {
1441 vty_out (vty, "IS-IS paths to level-1 routers that speak IPv6%s",
1442 VTY_NEWLINE);
1443 isis_print_paths (vty, area->spftree6[0]->paths);
1444 }
jardineb5d44e2003-12-23 08:09:43 +00001445#endif /* HAVE_IPV6 */
1446 }
1447
jardineb5d44e2003-12-23 08:09:43 +00001448 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001449}
jardineb5d44e2003-12-23 08:09:43 +00001450
1451DEFUN (show_isis_topology_l2,
1452 show_isis_topology_l2_cmd,
1453 "show isis topology level-2",
1454 SHOW_STR
1455 "IS-IS information\n"
1456 "IS-IS paths to Intermediate Systems\n"
1457 "Paths to all level-2 routers in the domain\n")
1458{
1459 struct listnode *node;
1460 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001461
jardineb5d44e2003-12-23 08:09:43 +00001462 if (!isis->area_list || isis->area_list->count == 0)
1463 return CMD_SUCCESS;
1464
paul1eb8ef22005-04-07 07:30:20 +00001465 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001466 {
hassof390d2c2004-09-10 20:48:21 +00001467 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1468 VTY_NEWLINE);
1469
1470 if (area->ip_circuits > 0 && area->spftree[1]
1471 && area->spftree[1]->paths->count > 0)
1472 {
1473 vty_out (vty, "IS-IS paths to level-2 routers that speak IP%s",
1474 VTY_NEWLINE);
1475 isis_print_paths (vty, area->spftree[1]->paths);
1476 }
jardineb5d44e2003-12-23 08:09:43 +00001477#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001478 if (area->ipv6_circuits > 0 && area->spftree6[1]
1479 && area->spftree6[1]->paths->count > 0)
1480 {
1481 vty_out (vty, "IS-IS paths to level-2 routers that speak IPv6%s",
1482 VTY_NEWLINE);
1483 isis_print_paths (vty, area->spftree6[1]->paths);
1484 }
jardineb5d44e2003-12-23 08:09:43 +00001485#endif /* HAVE_IPV6 */
1486 }
1487
jardineb5d44e2003-12-23 08:09:43 +00001488 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001489}
jardineb5d44e2003-12-23 08:09:43 +00001490
1491void
1492isis_spf_cmds_init ()
1493{
1494 install_element (VIEW_NODE, &show_isis_topology_cmd);
1495 install_element (VIEW_NODE, &show_isis_topology_l1_cmd);
1496 install_element (VIEW_NODE, &show_isis_topology_l2_cmd);
1497
1498 install_element (ENABLE_NODE, &show_isis_topology_cmd);
1499 install_element (ENABLE_NODE, &show_isis_topology_l1_cmd);
1500 install_element (ENABLE_NODE, &show_isis_topology_l2_cmd);
1501}