blob: 1a5a2db0038a6d4a22aaf11a3e7e1c2174f066ca [file] [log] [blame]
jardineb5d44e2003-12-23 08:09:43 +00001/*
2 * IS-IS Rout(e)ing protocol - isis_spf.c
3 * The SPT algorithm
4 *
5 * Copyright (C) 2001,2002 Sampo Saaristo
6 * Tampere University of Technology
7 * Institute of Communications Engineering
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public Licenseas published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <zebra.h>
jardineb5d44e2003-12-23 08:09:43 +000027
28#include "thread.h"
29#include "linklist.h"
30#include "vty.h"
31#include "log.h"
32#include "command.h"
33#include "memory.h"
34#include "prefix.h"
35#include "hash.h"
36#include "if.h"
37#include "table.h"
38
39#include "isis_constants.h"
40#include "isis_common.h"
41#include "dict.h"
42#include "isisd.h"
43#include "isis_misc.h"
44#include "isis_adjacency.h"
45#include "isis_circuit.h"
46#include "isis_tlv.h"
47#include "isis_pdu.h"
48#include "isis_lsp.h"
49#include "isis_dynhn.h"
50#include "isis_spf.h"
51#include "isis_route.h"
52#include "isis_csm.h"
53
54extern struct isis *isis;
55extern struct thread_master *master;
56extern struct host host;
57
58int isis_run_spf_l1 (struct thread *thread);
59int isis_run_spf_l2 (struct thread *thread);
60
jardineb5d44e2003-12-23 08:09:43 +000061/* 7.2.7 */
hasso92365882005-01-18 13:53:33 +000062static void
jardineb5d44e2003-12-23 08:09:43 +000063remove_excess_adjs (struct list *adjs)
64{
paul1eb8ef22005-04-07 07:30:20 +000065 struct listnode *node, *nnode, *excess = NULL;
jardineb5d44e2003-12-23 08:09:43 +000066 struct isis_adjacency *adj, *candidate = NULL;
67 int comp;
68
paul1eb8ef22005-04-07 07:30:20 +000069 for (ALL_LIST_ELEMENTS (adjs, node, nnode, adj))
hassof390d2c2004-09-10 20:48:21 +000070 {
71 if (excess == NULL)
72 excess = node;
paul1eb8ef22005-04-07 07:30:20 +000073 candidate = listgetdata (excess);
74
hassof390d2c2004-09-10 20:48:21 +000075 if (candidate->sys_type < adj->sys_type)
76 {
77 excess = node;
78 candidate = adj;
79 continue;
80 }
81 if (candidate->sys_type > adj->sys_type)
82 continue;
83
84 comp = memcmp (candidate->sysid, adj->sysid, ISIS_SYS_ID_LEN);
85 if (comp > 0)
86 {
87 excess = node;
88 candidate = adj;
89 continue;
90 }
91 if (comp < 0)
92 continue;
93
94 if (candidate->circuit->circuit_id > adj->circuit->circuit_id)
95 {
96 excess = node;
97 candidate = adj;
98 continue;
99 }
100
101 if (candidate->circuit->circuit_id < adj->circuit->circuit_id)
102 continue;
103
104 comp = memcmp (candidate->snpa, adj->snpa, ETH_ALEN);
105 if (comp > 0)
106 {
107 excess = node;
108 candidate = adj;
109 continue;
110 }
jardineb5d44e2003-12-23 08:09:43 +0000111 }
112
jardineb5d44e2003-12-23 08:09:43 +0000113 list_delete_node (adjs, excess);
114
115 return;
116}
117
hasso92365882005-01-18 13:53:33 +0000118#ifdef EXTREME_DEBUG
119static const char *
jardineb5d44e2003-12-23 08:09:43 +0000120vtype2string (enum vertextype vtype)
121{
hassof390d2c2004-09-10 20:48:21 +0000122 switch (vtype)
123 {
124 case VTYPE_PSEUDO_IS:
125 return "pseudo_IS";
126 break;
127 case VTYPE_NONPSEUDO_IS:
128 return "IS";
129 break;
130 case VTYPE_ES:
131 return "ES";
132 break;
133 case VTYPE_IPREACH_INTERNAL:
134 return "IP internal";
135 break;
136 case VTYPE_IPREACH_EXTERNAL:
137 return "IP external";
138 break;
jardineb5d44e2003-12-23 08:09:43 +0000139#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000140 case VTYPE_IP6REACH_INTERNAL:
141 return "IP6 internal";
142 break;
143 case VTYPE_IP6REACH_EXTERNAL:
144 return "IP6 external";
145 break;
146#endif /* HAVE_IPV6 */
147 default:
148 return "UNKNOWN";
149 }
150 return NULL; /* Not reached */
jardineb5d44e2003-12-23 08:09:43 +0000151}
152
hasso92365882005-01-18 13:53:33 +0000153static const char *
hassof390d2c2004-09-10 20:48:21 +0000154vid2string (struct isis_vertex *vertex, u_char * buff)
jardineb5d44e2003-12-23 08:09:43 +0000155{
hassof390d2c2004-09-10 20:48:21 +0000156 switch (vertex->type)
157 {
158 case VTYPE_PSEUDO_IS:
159 return rawlspid_print (vertex->N.id);
160 break;
161 case VTYPE_NONPSEUDO_IS:
162 case VTYPE_ES:
163 return sysid_print (vertex->N.id);
164 break;
165 case VTYPE_IPREACH_INTERNAL:
166 case VTYPE_IPREACH_EXTERNAL:
jardineb5d44e2003-12-23 08:09:43 +0000167#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000168 case VTYPE_IP6REACH_INTERNAL:
169 case VTYPE_IP6REACH_EXTERNAL:
170#endif /* HAVE_IPV6 */
hassof7c43dc2004-09-26 16:24:14 +0000171 prefix2str ((struct prefix *) &vertex->N.prefix, (char *) buff, BUFSIZ);
hassof390d2c2004-09-10 20:48:21 +0000172 break;
173 default:
174 return "UNKNOWN";
175 }
176
hassof7c43dc2004-09-26 16:24:14 +0000177 return (char *) buff;
jardineb5d44e2003-12-23 08:09:43 +0000178}
hasso92365882005-01-18 13:53:33 +0000179#endif /* EXTREME_DEBUG */
jardineb5d44e2003-12-23 08:09:43 +0000180
hasso92365882005-01-18 13:53:33 +0000181static struct isis_spftree *
jardineb5d44e2003-12-23 08:09:43 +0000182isis_spftree_new ()
183{
184 struct isis_spftree *tree;
185
186 tree = XMALLOC (MTYPE_ISIS_SPFTREE, sizeof (struct isis_spftree));
hassof390d2c2004-09-10 20:48:21 +0000187 if (tree == NULL)
188 {
189 zlog_err ("ISIS-Spf: isis_spftree_new Out of memory!");
190 return NULL;
191 }
jardineb5d44e2003-12-23 08:09:43 +0000192 memset (tree, 0, sizeof (struct isis_spftree));
193
194 tree->tents = list_new ();
hassof390d2c2004-09-10 20:48:21 +0000195 tree->paths = list_new ();
jardineb5d44e2003-12-23 08:09:43 +0000196 return tree;
197}
198
hasso92365882005-01-18 13:53:33 +0000199static void
jardineb5d44e2003-12-23 08:09:43 +0000200isis_vertex_del (struct isis_vertex *vertex)
201{
jardineb5d44e2003-12-23 08:09:43 +0000202 list_delete (vertex->Adj_N);
203
204 XFREE (MTYPE_ISIS_VERTEX, vertex);
hassof390d2c2004-09-10 20:48:21 +0000205
jardineb5d44e2003-12-23 08:09:43 +0000206 return;
207}
208
hasso92365882005-01-18 13:53:33 +0000209#if 0 /* HT: Not used yet. */
210static void
jardineb5d44e2003-12-23 08:09:43 +0000211isis_spftree_del (struct isis_spftree *spftree)
212{
hassof7c43dc2004-09-26 16:24:14 +0000213 spftree->tents->del = (void (*)(void *)) isis_vertex_del;
jardineb5d44e2003-12-23 08:09:43 +0000214 list_delete (spftree->tents);
hassof390d2c2004-09-10 20:48:21 +0000215
hassof7c43dc2004-09-26 16:24:14 +0000216 spftree->paths->del = (void (*)(void *)) isis_vertex_del;
jardineb5d44e2003-12-23 08:09:43 +0000217 list_delete (spftree->paths);
218
219 XFREE (MTYPE_ISIS_SPFTREE, spftree);
220
221 return;
222}
hasso92365882005-01-18 13:53:33 +0000223#endif
jardineb5d44e2003-12-23 08:09:43 +0000224
hassof390d2c2004-09-10 20:48:21 +0000225void
jardineb5d44e2003-12-23 08:09:43 +0000226spftree_area_init (struct isis_area *area)
227{
hassof390d2c2004-09-10 20:48:21 +0000228 if ((area->is_type & IS_LEVEL_1) && area->spftree[0] == NULL)
229 {
230 area->spftree[0] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000231#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000232 area->spftree6[0] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000233#endif
234
hassof390d2c2004-09-10 20:48:21 +0000235 /* thread_add_timer (master, isis_run_spf_l1, area,
236 isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */
237 }
238
239 if ((area->is_type & IS_LEVEL_2) && area->spftree[1] == NULL)
240 {
241 area->spftree[1] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000242#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000243 area->spftree6[1] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000244#endif
hassof390d2c2004-09-10 20:48:21 +0000245 /* thread_add_timer (master, isis_run_spf_l2, area,
246 isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */
247 }
jardineb5d44e2003-12-23 08:09:43 +0000248
249 return;
250}
251
hasso92365882005-01-18 13:53:33 +0000252static struct isis_vertex *
jardineb5d44e2003-12-23 08:09:43 +0000253isis_vertex_new (void *id, enum vertextype vtype)
254{
255 struct isis_vertex *vertex;
256
257 vertex = XMALLOC (MTYPE_ISIS_VERTEX, sizeof (struct isis_vertex));
hassof390d2c2004-09-10 20:48:21 +0000258 if (vertex == NULL)
259 {
260 zlog_err ("isis_vertex_new Out of memory!");
261 return NULL;
262 }
263
jardineb5d44e2003-12-23 08:09:43 +0000264 memset (vertex, 0, sizeof (struct isis_vertex));
265 vertex->type = vtype;
hassof390d2c2004-09-10 20:48:21 +0000266 switch (vtype)
267 {
268 case VTYPE_ES:
269 case VTYPE_NONPSEUDO_IS:
270 memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN);
271 break;
272 case VTYPE_PSEUDO_IS:
273 memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN + 1);
274 break;
275 case VTYPE_IPREACH_INTERNAL:
276 case VTYPE_IPREACH_EXTERNAL:
jardineb5d44e2003-12-23 08:09:43 +0000277#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000278 case VTYPE_IP6REACH_INTERNAL:
279 case VTYPE_IP6REACH_EXTERNAL:
280#endif /* HAVE_IPV6 */
281 memcpy (&vertex->N.prefix, (struct prefix *) id,
282 sizeof (struct prefix));
283 break;
284 default:
285 zlog_err ("WTF!");
286 }
jardineb5d44e2003-12-23 08:09:43 +0000287
288 vertex->Adj_N = list_new ();
hassof390d2c2004-09-10 20:48:21 +0000289
jardineb5d44e2003-12-23 08:09:43 +0000290 return vertex;
291}
292
293/*
294 * Add this IS to the root of SPT
295 */
hasso92365882005-01-18 13:53:33 +0000296static void
jardineb5d44e2003-12-23 08:09:43 +0000297isis_spf_add_self (struct isis_spftree *spftree, struct isis_area *area,
hassof390d2c2004-09-10 20:48:21 +0000298 int level)
jardineb5d44e2003-12-23 08:09:43 +0000299{
300 struct isis_vertex *vertex;
301 struct isis_lsp *lsp;
302 u_char lspid[ISIS_SYS_ID_LEN + 2];
303#ifdef EXTREME_DEBUG
304 u_char buff[BUFSIZ];
305#endif /* EXTREME_DEBUG */
306 memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN);
hassof390d2c2004-09-10 20:48:21 +0000307 LSP_PSEUDO_ID (lspid) = 0;
308 LSP_FRAGMENT (lspid) = 0;
309
jardineb5d44e2003-12-23 08:09:43 +0000310 lsp = lsp_search (lspid, area->lspdb[level - 1]);
hassof390d2c2004-09-10 20:48:21 +0000311
jardineb5d44e2003-12-23 08:09:43 +0000312 if (lsp == NULL)
313 zlog_warn ("ISIS-Spf: could not find own l%d LSP!", level);
hassof390d2c2004-09-10 20:48:21 +0000314
jardineb5d44e2003-12-23 08:09:43 +0000315 vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_IS);
316 vertex->lsp = lsp;
317
318 listnode_add (spftree->paths, vertex);
319
320#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000321 zlog_debug ("ISIS-Spf: added this IS %s %s depth %d dist %d to PATHS",
322 vtype2string (vertex->type), vid2string (vertex, buff),
323 vertex->depth, vertex->d_N);
jardineb5d44e2003-12-23 08:09:43 +0000324#endif /* EXTREME_DEBUG */
325
326 return;
327}
328
hasso92365882005-01-18 13:53:33 +0000329static struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000330isis_find_vertex (struct list *list, void *id, enum vertextype vtype)
jardineb5d44e2003-12-23 08:09:43 +0000331{
332 struct listnode *node;
333 struct isis_vertex *vertex;
334 struct prefix *p1, *p2;
335
paul1eb8ef22005-04-07 07:30:20 +0000336 for (ALL_LIST_ELEMENTS_RO (list, node, vertex))
hassof390d2c2004-09-10 20:48:21 +0000337 {
hassof390d2c2004-09-10 20:48:21 +0000338 if (vertex->type != vtype)
339 continue;
340 switch (vtype)
341 {
342 case VTYPE_ES:
343 case VTYPE_NONPSEUDO_IS:
344 if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN) == 0)
345 return vertex;
346 break;
347 case VTYPE_PSEUDO_IS:
348 if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN + 1) == 0)
349 return vertex;
350 break;
351 case VTYPE_IPREACH_INTERNAL:
352 case VTYPE_IPREACH_EXTERNAL:
jardineb5d44e2003-12-23 08:09:43 +0000353#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000354 case VTYPE_IP6REACH_INTERNAL:
355 case VTYPE_IP6REACH_EXTERNAL:
jardineb5d44e2003-12-23 08:09:43 +0000356#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000357 p1 = (struct prefix *) id;
358 p2 = (struct prefix *) &vertex->N.id;
359 if (p1->family == p2->family && p1->prefixlen == p2->prefixlen &&
360 memcmp (&p1->u.prefix, &p2->u.prefix,
361 PSIZE (p1->prefixlen)) == 0)
362 return vertex;
363 break;
364 }
jardineb5d44e2003-12-23 08:09:43 +0000365 }
jardineb5d44e2003-12-23 08:09:43 +0000366
367 return NULL;
368}
369
jardineb5d44e2003-12-23 08:09:43 +0000370/*
371 * Add a vertex to TENT sorted by cost and by vertextype on tie break situation
372 */
hasso92365882005-01-18 13:53:33 +0000373static struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000374isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype,
375 void *id, struct isis_adjacency *adj, u_int16_t cost,
376 int depth, int family)
jardineb5d44e2003-12-23 08:09:43 +0000377{
378 struct isis_vertex *vertex, *v;
379 struct listnode *node;
hassof390d2c2004-09-10 20:48:21 +0000380#ifdef EXTREME_DEBUG
jardineb5d44e2003-12-23 08:09:43 +0000381 u_char buff[BUFSIZ];
382#endif
383
384 vertex = isis_vertex_new (id, vtype);
385 vertex->d_N = cost;
386 vertex->depth = depth;
hassof390d2c2004-09-10 20:48:21 +0000387
jardineb5d44e2003-12-23 08:09:43 +0000388 if (adj)
389 listnode_add (vertex->Adj_N, adj);
hassof390d2c2004-09-10 20:48:21 +0000390#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000391 zlog_debug ("ISIS-Spf: add to TENT %s %s depth %d dist %d",
392 vtype2string (vertex->type), vid2string (vertex, buff),
393 vertex->depth, vertex->d_N);
jardineb5d44e2003-12-23 08:09:43 +0000394#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000395 listnode_add (spftree->tents, vertex);
396 if (list_isempty (spftree->tents))
397 {
398 listnode_add (spftree->tents, vertex);
399 return vertex;
jardineb5d44e2003-12-23 08:09:43 +0000400 }
paul1eb8ef22005-04-07 07:30:20 +0000401
402 /* XXX: This cant use the standard ALL_LIST_ELEMENT macro */
403 for (node = listhead (spftree->tents); node; node = listnextnode (node))
hassof390d2c2004-09-10 20:48:21 +0000404 {
paul1eb8ef22005-04-07 07:30:20 +0000405 v = listgetdata (node);
hassof390d2c2004-09-10 20:48:21 +0000406 if (v->d_N > vertex->d_N)
407 {
408 list_add_node_prev (spftree->tents, node, vertex);
409 break;
410 }
411 else if (v->d_N == vertex->d_N)
412 {
413 /* Tie break, add according to type */
414 while (v && v->d_N == vertex->d_N && v->type > vertex->type)
415 {
416 if (v->type > vertex->type)
417 {
418 break;
419 }
paul1eb8ef22005-04-07 07:30:20 +0000420 /* XXX: this seems dubious, node is the loop iterator */
421 node = listnextnode (node);
422 (node) ? (v = listgetdata (node)) : (v = NULL);
hassof390d2c2004-09-10 20:48:21 +0000423 }
424 list_add_node_prev (spftree->tents, node, vertex);
425 break;
426 }
427 else if (node->next == NULL)
428 {
429 list_add_node_next (spftree->tents, node, vertex);
430 break;
431 }
432 }
jardineb5d44e2003-12-23 08:09:43 +0000433 return vertex;
434}
435
hasso92365882005-01-18 13:53:33 +0000436static struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000437isis_spf_add_local (struct isis_spftree *spftree, enum vertextype vtype,
438 void *id, struct isis_adjacency *adj, u_int16_t cost,
439 int family)
jardineb5d44e2003-12-23 08:09:43 +0000440{
441 struct isis_vertex *vertex;
jardineb5d44e2003-12-23 08:09:43 +0000442
hassof390d2c2004-09-10 20:48:21 +0000443 vertex = isis_find_vertex (spftree->tents, id, vtype);
444
445 if (vertex)
446 {
447 /* C.2.5 c) */
448 if (vertex->d_N == cost)
449 {
450 if (adj)
451 listnode_add (vertex->Adj_N, adj);
452 /* d) */
453 if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
454 remove_excess_adjs (vertex->Adj_N);
455 }
456 /* f) */
457 else if (vertex->d_N > cost)
458 {
459 listnode_delete (spftree->tents, vertex);
460 goto add2tent;
461 }
462 /* e) do nothing */
463 return vertex;
464 }
465
466add2tent:
jardineb5d44e2003-12-23 08:09:43 +0000467 return isis_spf_add2tent (spftree, vtype, id, adj, cost, 1, family);
468}
469
hasso92365882005-01-18 13:53:33 +0000470static void
hassof390d2c2004-09-10 20:48:21 +0000471process_N (struct isis_spftree *spftree, enum vertextype vtype, void *id,
472 u_int16_t dist, u_int16_t depth, struct isis_adjacency *adj,
473 int family)
jardineb5d44e2003-12-23 08:09:43 +0000474{
475 struct isis_vertex *vertex;
476#ifdef EXTREME_DEBUG
477 u_char buff[255];
478#endif
479
480 /* C.2.6 b) */
481 if (dist > MAX_PATH_METRIC)
482 return;
483 /* c) */
484 vertex = isis_find_vertex (spftree->paths, id, vtype);
hassof390d2c2004-09-10 20:48:21 +0000485 if (vertex)
486 {
jardineb5d44e2003-12-23 08:09:43 +0000487#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000488 zlog_debug ("ISIS-Spf: process_N %s %s dist %d already found from PATH",
489 vtype2string (vtype), vid2string (vertex, buff), dist);
jardineb5d44e2003-12-23 08:09:43 +0000490#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000491 assert (dist >= vertex->d_N);
492 return;
493 }
jardineb5d44e2003-12-23 08:09:43 +0000494
495 vertex = isis_find_vertex (spftree->tents, id, vtype);
hassof390d2c2004-09-10 20:48:21 +0000496 /* d) */
497 if (vertex)
498 {
499 /* 1) */
jardineb5d44e2003-12-23 08:09:43 +0000500#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000501 zlog_debug ("ISIS-Spf: process_N %s %s dist %d",
502 vtype2string (vtype), vid2string (vertex, buff), dist);
jardineb5d44e2003-12-23 08:09:43 +0000503#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000504 if (vertex->d_N == dist)
505 {
506 if (adj)
507 listnode_add (vertex->Adj_N, adj);
508 /* 2) */
509 if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
510 remove_excess_adjs (vertex->Adj_N);
511 /* 3) */
512 return;
513 }
514 else if (vertex->d_N < dist)
515 {
516 return;
517 /* 4) */
518 }
519 else
520 {
521 listnode_delete (spftree->tents, vertex);
522 }
jardineb5d44e2003-12-23 08:09:43 +0000523 }
hassof390d2c2004-09-10 20:48:21 +0000524
jardineb5d44e2003-12-23 08:09:43 +0000525 isis_spf_add2tent (spftree, vtype, id, adj, dist, depth, family);
526 return;
527}
528
529/*
530 * C.2.6 Step 1
531 */
hasso92365882005-01-18 13:53:33 +0000532static int
hassof390d2c2004-09-10 20:48:21 +0000533isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp,
534 uint16_t cost, uint16_t depth, int family)
jardineb5d44e2003-12-23 08:09:43 +0000535{
536 struct listnode *node, *fragnode = NULL;
537 u_int16_t dist;
538 struct is_neigh *is_neigh;
539 struct ipv4_reachability *ipreach;
540 enum vertextype vtype;
541 struct prefix prefix;
542#ifdef HAVE_IPV6
543 struct ipv6_reachability *ip6reach;
544#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000545
jardineb5d44e2003-12-23 08:09:43 +0000546
547 if (!lsp->adj)
548 return ISIS_WARNING;
hassof390d2c2004-09-10 20:48:21 +0000549 if (lsp->tlv_data.nlpids == NULL || !speaks (lsp->tlv_data.nlpids, family))
jardineb5d44e2003-12-23 08:09:43 +0000550 return ISIS_OK;
551
hassof390d2c2004-09-10 20:48:21 +0000552lspfragloop:
553 if (lsp->lsp_header->seq_num == 0)
554 {
555 zlog_warn ("isis_spf_process_lsp(): lsp with 0 seq_num"
556 " - do not process");
557 return ISIS_WARNING;
558 }
jardineb5d44e2003-12-23 08:09:43 +0000559
hassof390d2c2004-09-10 20:48:21 +0000560 if (!ISIS_MASK_LSP_OL_BIT (lsp->lsp_header->lsp_bits))
561 {
562 if (lsp->tlv_data.is_neighs)
563 {
paul1eb8ef22005-04-07 07:30:20 +0000564 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh))
hassof390d2c2004-09-10 20:48:21 +0000565 {
hassof390d2c2004-09-10 20:48:21 +0000566 /* C.2.6 a) */
567 /* Two way connectivity */
568 if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
569 continue;
570 dist = cost + is_neigh->metrics.metric_default;
571 vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
572 : VTYPE_NONPSEUDO_IS;
573 process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist,
574 depth + 1, lsp->adj, family);
575 }
576 }
577 if (family == AF_INET && lsp->tlv_data.ipv4_int_reachs)
578 {
579 prefix.family = AF_INET;
paul1eb8ef22005-04-07 07:30:20 +0000580 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_int_reachs,
581 node, ipreach))
hassof390d2c2004-09-10 20:48:21 +0000582 {
hassof390d2c2004-09-10 20:48:21 +0000583 dist = cost + ipreach->metrics.metric_default;
584 vtype = VTYPE_IPREACH_INTERNAL;
585 prefix.u.prefix4 = ipreach->prefix;
586 prefix.prefixlen = ip_masklen (ipreach->mask);
587 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
588 lsp->adj, family);
589 }
590 }
591
592 if (family == AF_INET && lsp->tlv_data.ipv4_ext_reachs)
593 {
594 prefix.family = AF_INET;
paul1eb8ef22005-04-07 07:30:20 +0000595 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_ext_reachs,
596 node, ipreach))
hassof390d2c2004-09-10 20:48:21 +0000597 {
hassof390d2c2004-09-10 20:48:21 +0000598 dist = cost + ipreach->metrics.metric_default;
599 vtype = VTYPE_IPREACH_EXTERNAL;
600 prefix.u.prefix4 = ipreach->prefix;
601 prefix.prefixlen = ip_masklen (ipreach->mask);
602 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
603 lsp->adj, family);
604 }
605 }
jardineb5d44e2003-12-23 08:09:43 +0000606#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000607 if (family == AF_INET6 && lsp->tlv_data.ipv6_reachs)
608 {
609 prefix.family = AF_INET6;
paul1eb8ef22005-04-07 07:30:20 +0000610 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv6_reachs,
611 node, ip6reach))
hassof390d2c2004-09-10 20:48:21 +0000612 {
hassof390d2c2004-09-10 20:48:21 +0000613 dist = cost + ip6reach->metric;
614 vtype = (ip6reach->control_info & CTRL_INFO_DISTRIBUTION) ?
615 VTYPE_IP6REACH_EXTERNAL : VTYPE_IP6REACH_INTERNAL;
616 prefix.prefixlen = ip6reach->prefix_len;
617 memcpy (&prefix.u.prefix6.s6_addr, ip6reach->prefix,
618 PSIZE (ip6reach->prefix_len));
619 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
620 lsp->adj, family);
621 }
622 }
jardineb5d44e2003-12-23 08:09:43 +0000623#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000624 }
625
jardineb5d44e2003-12-23 08:09:43 +0000626 if (fragnode == NULL)
627 fragnode = listhead (lsp->lspu.frags);
hassof390d2c2004-09-10 20:48:21 +0000628 else
paul1eb8ef22005-04-07 07:30:20 +0000629 fragnode = listnextnode (fragnode);
jardineb5d44e2003-12-23 08:09:43 +0000630
hassof390d2c2004-09-10 20:48:21 +0000631 if (fragnode)
632 {
paul1eb8ef22005-04-07 07:30:20 +0000633 lsp = listgetdata (fragnode);
hassof390d2c2004-09-10 20:48:21 +0000634 goto lspfragloop;
635 }
636
jardineb5d44e2003-12-23 08:09:43 +0000637 return ISIS_OK;
638}
639
hasso92365882005-01-18 13:53:33 +0000640static int
hassof390d2c2004-09-10 20:48:21 +0000641isis_spf_process_pseudo_lsp (struct isis_spftree *spftree,
642 struct isis_lsp *lsp, uint16_t cost,
643 uint16_t depth, int family)
jardineb5d44e2003-12-23 08:09:43 +0000644{
paul1eb8ef22005-04-07 07:30:20 +0000645 struct listnode *node, *nnode, *fragnode = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000646 struct is_neigh *is_neigh;
647 enum vertextype vtype;
hassof390d2c2004-09-10 20:48:21 +0000648
649pseudofragloop:
650
651 if (lsp->lsp_header->seq_num == 0)
652 {
653 zlog_warn ("isis_spf_process_pseudo_lsp(): lsp with 0 seq_num"
654 " - do not process");
655 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +0000656 }
hassof390d2c2004-09-10 20:48:21 +0000657
paul1eb8ef22005-04-07 07:30:20 +0000658 for (ALL_LIST_ELEMENTS (lsp->tlv_data.is_neighs, node, nnode, is_neigh))
hassof390d2c2004-09-10 20:48:21 +0000659 {
hassof390d2c2004-09-10 20:48:21 +0000660 vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
661 : VTYPE_NONPSEUDO_IS;
662 /* Two way connectivity */
663 if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
664 continue;
665 if (isis_find_vertex
666 (spftree->tents, (void *) is_neigh->neigh_id, vtype) == NULL
667 && isis_find_vertex (spftree->paths, (void *) is_neigh->neigh_id,
668 vtype) == NULL)
669 {
670 /* C.2.5 i) */
671 isis_spf_add2tent (spftree, vtype, is_neigh->neigh_id, lsp->adj,
672 cost, depth, family);
673 }
674 }
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 pseudofragloop;
685 }
jardineb5d44e2003-12-23 08:09:43 +0000686
jardineb5d44e2003-12-23 08:09:43 +0000687 return ISIS_OK;
688}
hassof390d2c2004-09-10 20:48:21 +0000689
hasso92365882005-01-18 13:53:33 +0000690static int
hassof390d2c2004-09-10 20:48:21 +0000691isis_spf_preload_tent (struct isis_spftree *spftree,
692 struct isis_area *area, int level, int family)
jardineb5d44e2003-12-23 08:09:43 +0000693{
694 struct isis_vertex *vertex;
695 struct isis_circuit *circuit;
paul1eb8ef22005-04-07 07:30:20 +0000696 struct listnode *cnode, *cnnode;
697 struct listnode *anode;
698 struct listnode *ipnode, *ipnnode;
jardineb5d44e2003-12-23 08:09:43 +0000699 struct isis_adjacency *adj;
700 struct isis_lsp *lsp;
701 struct list *adj_list;
702 struct list *adjdb;
703 struct prefix_ipv4 *ipv4;
704 struct prefix prefix;
705 int retval = ISIS_OK;
706 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
707#ifdef HAVE_IPV6
708 struct prefix_ipv6 *ipv6;
709#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000710
paul1eb8ef22005-04-07 07:30:20 +0000711 for (ALL_LIST_ELEMENTS (area->circuit_list, cnode, cnnode, circuit))
hassof390d2c2004-09-10 20:48:21 +0000712 {
hassof390d2c2004-09-10 20:48:21 +0000713 if (circuit->state != C_STATE_UP)
jardineb5d44e2003-12-23 08:09:43 +0000714 continue;
hassof390d2c2004-09-10 20:48:21 +0000715 if (!(circuit->circuit_is_type & level))
716 continue;
717 if (family == AF_INET && !circuit->ip_router)
718 continue;
719#ifdef HAVE_IPV6
720 if (family == AF_INET6 && !circuit->ipv6_router)
721 continue;
722#endif /* HAVE_IPV6 */
723 /*
724 * Add IP(v6) addresses of this circuit
jardineb5d44e2003-12-23 08:09:43 +0000725 */
hassof390d2c2004-09-10 20:48:21 +0000726 if (family == AF_INET)
727 {
728 prefix.family = AF_INET;
paul1eb8ef22005-04-07 07:30:20 +0000729 for (ALL_LIST_ELEMENTS (circuit->ip_addrs, ipnode, ipnnode, ipv4))
hassof390d2c2004-09-10 20:48:21 +0000730 {
hassof390d2c2004-09-10 20:48:21 +0000731 prefix.u.prefix4 = ipv4->prefix;
732 prefix.prefixlen = ipv4->prefixlen;
733 isis_spf_add_local (spftree, VTYPE_IPREACH_INTERNAL, &prefix,
734 NULL, 0, family);
735 }
736 }
737#ifdef HAVE_IPV6
738 if (family == AF_INET6)
739 {
740 prefix.family = AF_INET6;
paul1eb8ef22005-04-07 07:30:20 +0000741 for (ALL_LIST_ELEMENTS (circuit->ipv6_non_link,
742 ipnode, ipnnode, ipv6))
hassof390d2c2004-09-10 20:48:21 +0000743 {
hassof390d2c2004-09-10 20:48:21 +0000744 prefix.prefixlen = ipv6->prefixlen;
745 prefix.u.prefix6 = ipv6->prefix;
746 isis_spf_add_local (spftree, VTYPE_IP6REACH_INTERNAL,
747 &prefix, NULL, 0, family);
748 }
749 }
750#endif /* HAVE_IPV6 */
751 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
752 {
753 /*
754 * Add the adjacencies
755 */
756 adj_list = list_new ();
757 adjdb = circuit->u.bc.adjdb[level - 1];
758 isis_adj_build_up_list (adjdb, adj_list);
759 if (listcount (adj_list) == 0)
760 {
761 list_delete (adj_list);
hassoc89c05d2005-09-04 21:36:36 +0000762 if (isis->debugs & DEBUG_SPF_EVENTS)
763 zlog_debug ("ISIS-Spf: no L%d adjacencies on circuit %s",
764 level, circuit->interface->name);
hassof390d2c2004-09-10 20:48:21 +0000765 continue;
766 }
767 anode = listhead (adj_list);
768 while (anode)
769 {
paul1eb8ef22005-04-07 07:30:20 +0000770 adj = listgetdata (anode);
hassof390d2c2004-09-10 20:48:21 +0000771 if (!speaks (&adj->nlpids, family))
772 {
paul1eb8ef22005-04-07 07:30:20 +0000773 anode = listnextnode (anode);
hassof390d2c2004-09-10 20:48:21 +0000774 continue;
775 }
776 switch (adj->sys_type)
777 {
778 case ISIS_SYSTYPE_ES:
779 isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
780 circuit->metrics[level -
781 1].metric_default,
782 family);
783 break;
784 case ISIS_SYSTYPE_IS:
785 case ISIS_SYSTYPE_L1_IS:
786 case ISIS_SYSTYPE_L2_IS:
787 vertex =
788 isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS,
789 adj->sysid, adj,
790 circuit->metrics[level -
791 1].metric_default,
792 family);
793 memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN);
794 LSP_PSEUDO_ID (lsp_id) = 0;
795 LSP_FRAGMENT (lsp_id) = 0;
796 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
797 if (!lsp)
798 zlog_warn ("No lsp found for IS adjacency");
799 /* else {
800 isis_spf_process_lsp (spftree, lsp, vertex->d_N, 1, family);
801 } */
802 break;
803 case ISIS_SYSTYPE_UNKNOWN:
804 default:
805 zlog_warn ("isis_spf_preload_tent unknow adj type");
806 }
paul1eb8ef22005-04-07 07:30:20 +0000807 anode = listnextnode (anode);
hassof390d2c2004-09-10 20:48:21 +0000808 }
809 list_delete (adj_list);
810 /*
811 * Add the pseudonode
812 */
813 if (level == 1)
814 memcpy (lsp_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
815 else
816 memcpy (lsp_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
817 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
818 adj = isis_adj_lookup (lsp_id, adjdb);
819 /* if no adj, we are the dis or error */
820 if (!adj && !circuit->u.bc.is_dr[level - 1])
821 {
822 zlog_warn ("ISIS-Spf: No adjacency found for DR");
823 }
824 if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0)
825 {
826 zlog_warn ("ISIS-Spf: No lsp found for DR");
827 }
828 else
829 {
830 isis_spf_process_pseudo_lsp
831 (spftree, lsp, circuit->metrics[level - 1].metric_default, 0,
832 family);
833
834 }
835 }
836 else if (circuit->circ_type == CIRCUIT_T_P2P)
837 {
838 adj = circuit->u.p2p.neighbor;
839 if (!adj)
840 continue;
841 switch (adj->sys_type)
842 {
843 case ISIS_SYSTYPE_ES:
844 isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
845 circuit->metrics[level - 1].metric_default,
846 family);
847 break;
848 case ISIS_SYSTYPE_IS:
849 case ISIS_SYSTYPE_L1_IS:
850 case ISIS_SYSTYPE_L2_IS:
851 if (speaks (&adj->nlpids, family))
852 isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS, adj->sysid,
853 adj,
854 circuit->metrics[level -
855 1].metric_default,
856 family);
857 break;
858 case ISIS_SYSTYPE_UNKNOWN:
859 default:
860 zlog_warn ("isis_spf_preload_tent unknow adj type");
861 break;
862 }
863 }
jardineb5d44e2003-12-23 08:09:43 +0000864 else
hassof390d2c2004-09-10 20:48:21 +0000865 {
866 zlog_warn ("isis_spf_preload_tent unsupported media");
867 retval = ISIS_WARNING;
868 }
869
jardineb5d44e2003-12-23 08:09:43 +0000870 }
jardineb5d44e2003-12-23 08:09:43 +0000871
872 return retval;
873}
874
875/*
876 * The parent(s) for vertex is set when added to TENT list
877 * now we just put the child pointer(s) in place
878 */
hasso92365882005-01-18 13:53:33 +0000879static void
jardineb5d44e2003-12-23 08:09:43 +0000880add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex,
hassof390d2c2004-09-10 20:48:21 +0000881 struct isis_area *area)
jardineb5d44e2003-12-23 08:09:43 +0000882{
jardineb5d44e2003-12-23 08:09:43 +0000883#ifdef EXTREME_DEBUG
884 u_char buff[BUFSIZ];
885#endif /* EXTREME_DEBUG */
886 listnode_add (spftree->paths, vertex);
887
hassof390d2c2004-09-10 20:48:21 +0000888#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000889 zlog_debug ("ISIS-Spf: added %s %s depth %d dist %d to PATHS",
890 vtype2string (vertex->type), vid2string (vertex, buff),
891 vertex->depth, vertex->d_N);
hassof390d2c2004-09-10 20:48:21 +0000892#endif /* EXTREME_DEBUG */
893 if (vertex->type > VTYPE_ES)
894 {
895 if (listcount (vertex->Adj_N) > 0)
896 isis_route_create ((struct prefix *) &vertex->N.prefix,
897 vertex->d_N, vertex->depth, vertex->Adj_N, area);
898 else if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000899 zlog_debug ("ISIS-Spf: no adjacencies do not install route");
hassof390d2c2004-09-10 20:48:21 +0000900 }
901
jardineb5d44e2003-12-23 08:09:43 +0000902 return;
903}
904
hasso92365882005-01-18 13:53:33 +0000905static void
jardineb5d44e2003-12-23 08:09:43 +0000906init_spt (struct isis_spftree *spftree)
907{
hassof7c43dc2004-09-26 16:24:14 +0000908 spftree->tents->del = spftree->paths->del = (void (*)(void *)) isis_vertex_del;
jardineb5d44e2003-12-23 08:09:43 +0000909 list_delete_all_node (spftree->tents);
910 list_delete_all_node (spftree->paths);
911 spftree->tents->del = spftree->paths->del = NULL;
hassof390d2c2004-09-10 20:48:21 +0000912
jardineb5d44e2003-12-23 08:09:43 +0000913 return;
914}
915
hasso92365882005-01-18 13:53:33 +0000916static int
jardineb5d44e2003-12-23 08:09:43 +0000917isis_run_spf (struct isis_area *area, int level, int family)
918{
919 int retval = ISIS_OK;
920 struct listnode *node;
921 struct isis_vertex *vertex;
hassof390d2c2004-09-10 20:48:21 +0000922 struct isis_spftree *spftree = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000923 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
924 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +0000925
jardineb5d44e2003-12-23 08:09:43 +0000926 if (family == AF_INET)
927 spftree = area->spftree[level - 1];
928#ifdef HAVE_IPV6
929 else if (family == AF_INET6)
930 spftree = area->spftree6[level - 1];
931#endif
hassof390d2c2004-09-10 20:48:21 +0000932
jardineb5d44e2003-12-23 08:09:43 +0000933 assert (spftree);
934
935 /*
936 * C.2.5 Step 0
937 */
938 init_spt (spftree);
939 /* a) */
940 isis_spf_add_self (spftree, area, level);
941 /* b) */
942 retval = isis_spf_preload_tent (spftree, area, level, family);
hassof390d2c2004-09-10 20:48:21 +0000943
jardineb5d44e2003-12-23 08:09:43 +0000944 /*
945 * C.2.7 Step 2
946 */
hassof390d2c2004-09-10 20:48:21 +0000947 if (listcount (spftree->tents) == 0)
948 {
949 zlog_warn ("ISIS-Spf: TENT is empty");
950 spftree->lastrun = time (NULL);
951 return retval;
jardineb5d44e2003-12-23 08:09:43 +0000952 }
hassof390d2c2004-09-10 20:48:21 +0000953
954 while (listcount (spftree->tents) > 0)
955 {
956 node = listhead (spftree->tents);
paul1eb8ef22005-04-07 07:30:20 +0000957 vertex = listgetdata (node);
hassof390d2c2004-09-10 20:48:21 +0000958 /* Remove from tent list */
959 list_delete_node (spftree->tents, node);
960 if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type))
961 continue;
962 add_to_paths (spftree, vertex, area);
963 if (vertex->type == VTYPE_PSEUDO_IS ||
964 vertex->type == VTYPE_NONPSEUDO_IS)
965 {
966 memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
967 LSP_FRAGMENT (lsp_id) = 0;
968 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
969 if (lsp)
970 {
971 if (LSP_PSEUDO_ID (lsp_id))
972 {
973 isis_spf_process_pseudo_lsp (spftree, lsp, vertex->d_N,
974 vertex->depth, family);
975
976 }
977 else
978 {
979 isis_spf_process_lsp (spftree, lsp, vertex->d_N,
980 vertex->depth, family);
981 }
982 }
983 else
984 {
985 zlog_warn ("ISIS-Spf: No LSP found for %s",
986 rawlspid_print (lsp_id));
987 }
988 }
989 }
990
jardineb5d44e2003-12-23 08:09:43 +0000991 thread_add_event (master, isis_route_validate, area, 0);
992 spftree->lastrun = time (NULL);
993 spftree->pending = 0;
hassof390d2c2004-09-10 20:48:21 +0000994
jardineb5d44e2003-12-23 08:09:43 +0000995 return retval;
996}
997
998int
999isis_run_spf_l1 (struct thread *thread)
1000{
1001 struct isis_area *area;
1002 int retval = ISIS_OK;
1003
hassof390d2c2004-09-10 20:48:21 +00001004 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001005 assert (area);
1006
hasso12a5cae2004-09-19 19:39:26 +00001007 area->spftree[0]->t_spf = NULL;
1008
hassof390d2c2004-09-10 20:48:21 +00001009 if (!(area->is_type & IS_LEVEL_1))
1010 {
1011 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001012 zlog_warn ("ISIS-SPF (%s) area does not share level",
1013 area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001014 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001015 }
jardineb5d44e2003-12-23 08:09:43 +00001016
hassof390d2c2004-09-10 20:48:21 +00001017 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001018 zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001019
jardineb5d44e2003-12-23 08:09:43 +00001020 if (area->ip_circuits)
1021 retval = isis_run_spf (area, 1, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001022
1023 THREAD_TIMER_ON (master, area->spftree[0]->t_spf, isis_run_spf_l1, area,
1024 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1025
jardineb5d44e2003-12-23 08:09:43 +00001026 return retval;
1027}
1028
1029int
1030isis_run_spf_l2 (struct thread *thread)
1031{
1032 struct isis_area *area;
1033 int retval = ISIS_OK;
1034
hassof390d2c2004-09-10 20:48:21 +00001035 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001036 assert (area);
hassof390d2c2004-09-10 20:48:21 +00001037
hasso12a5cae2004-09-19 19:39:26 +00001038 area->spftree[1]->t_spf = NULL;
1039
hassof390d2c2004-09-10 20:48:21 +00001040 if (!(area->is_type & IS_LEVEL_2))
1041 {
1042 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001043 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001044 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001045 }
hassof390d2c2004-09-10 20:48:21 +00001046
1047 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001048 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag);
jardineb5d44e2003-12-23 08:09:43 +00001049
1050 if (area->ip_circuits)
1051 retval = isis_run_spf (area, 2, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001052
1053 THREAD_TIMER_ON (master, area->spftree[1]->t_spf, isis_run_spf_l2, area,
1054 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
jardineb5d44e2003-12-23 08:09:43 +00001055
1056 return retval;
1057}
1058
hassof390d2c2004-09-10 20:48:21 +00001059int
jardineb5d44e2003-12-23 08:09:43 +00001060isis_spf_schedule (struct isis_area *area, int level)
1061{
1062 int retval = ISIS_OK;
1063 struct isis_spftree *spftree = area->spftree[level - 1];
1064 time_t diff, now = time (NULL);
1065
1066 if (spftree->pending)
1067 return retval;
1068
hassof390d2c2004-09-10 20:48:21 +00001069 diff = now - spftree->lastrun;
jardineb5d44e2003-12-23 08:09:43 +00001070
1071 /* FIXME: let's wait a minute before doing the SPF */
hassof390d2c2004-09-10 20:48:21 +00001072 if (now - isis->uptime < 60 || isis->uptime == 0)
1073 {
1074 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001075 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area, 60);
hassof390d2c2004-09-10 20:48:21 +00001076 else
hasso12a5cae2004-09-19 19:39:26 +00001077 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area, 60);
jardineb5d44e2003-12-23 08:09:43 +00001078
hassof390d2c2004-09-10 20:48:21 +00001079 spftree->pending = 1;
1080 return retval;
1081 }
hasso12a5cae2004-09-19 19:39:26 +00001082
1083 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001084
hassof390d2c2004-09-10 20:48:21 +00001085 if (diff < MINIMUM_SPF_INTERVAL)
1086 {
1087 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001088 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
1089 MINIMUM_SPF_INTERVAL - diff);
hassof390d2c2004-09-10 20:48:21 +00001090 else
hasso12a5cae2004-09-19 19:39:26 +00001091 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
1092 MINIMUM_SPF_INTERVAL - diff);
jardineb5d44e2003-12-23 08:09:43 +00001093
hassof390d2c2004-09-10 20:48:21 +00001094 spftree->pending = 1;
1095 }
1096 else
1097 {
1098 spftree->pending = 0;
1099 retval = isis_run_spf (area, level, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001100 if (level == 1)
1101 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
1102 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1103 else
1104 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
1105 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
hassof390d2c2004-09-10 20:48:21 +00001106 }
jardineb5d44e2003-12-23 08:09:43 +00001107
1108 return retval;
1109}
1110
1111#ifdef HAVE_IPV6
hasso92365882005-01-18 13:53:33 +00001112static int
hasso12a5cae2004-09-19 19:39:26 +00001113isis_run_spf6_l1 (struct thread *thread)
1114{
1115 struct isis_area *area;
1116 int retval = ISIS_OK;
1117
1118 area = THREAD_ARG (thread);
1119 assert (area);
1120
1121 area->spftree6[0]->t_spf = NULL;
1122
1123 if (!(area->is_type & IS_LEVEL_1))
1124 {
1125 if (isis->debugs & DEBUG_SPF_EVENTS)
1126 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
1127 return ISIS_WARNING;
1128 }
1129
1130 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001131 zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001132
1133 if (area->ipv6_circuits)
1134 retval = isis_run_spf (area, 1, AF_INET6);
1135
1136 THREAD_TIMER_ON (master, area->spftree6[0]->t_spf, isis_run_spf6_l1, area,
1137 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1138
1139 return retval;
1140}
1141
hasso92365882005-01-18 13:53:33 +00001142static int
hasso12a5cae2004-09-19 19:39:26 +00001143isis_run_spf6_l2 (struct thread *thread)
1144{
1145 struct isis_area *area;
1146 int retval = ISIS_OK;
1147
1148 area = THREAD_ARG (thread);
1149 assert (area);
1150
1151 area->spftree6[1]->t_spf = NULL;
1152
1153 if (!(area->is_type & IS_LEVEL_2))
1154 {
1155 if (isis->debugs & DEBUG_SPF_EVENTS)
1156 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
1157 return ISIS_WARNING;
1158 }
1159
1160 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001161 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001162
1163 if (area->ipv6_circuits)
1164 retval = isis_run_spf (area, 2, AF_INET6);
1165
1166 THREAD_TIMER_ON (master, area->spftree6[1]->t_spf, isis_run_spf6_l2, area,
1167 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1168
1169 return retval;
1170}
1171
1172int
jardineb5d44e2003-12-23 08:09:43 +00001173isis_spf_schedule6 (struct isis_area *area, int level)
1174{
1175 int retval = ISIS_OK;
1176 struct isis_spftree *spftree = area->spftree6[level - 1];
1177 time_t diff, now = time (NULL);
1178
1179 if (spftree->pending)
1180 return retval;
1181
hassof390d2c2004-09-10 20:48:21 +00001182 diff = now - spftree->lastrun;
1183
jardineb5d44e2003-12-23 08:09:43 +00001184 /* FIXME: let's wait a minute before doing the SPF */
hassof390d2c2004-09-10 20:48:21 +00001185 if (now - isis->uptime < 60 || isis->uptime == 0)
1186 {
1187 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001188 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area, 60);
hassof390d2c2004-09-10 20:48:21 +00001189 else
hasso12a5cae2004-09-19 19:39:26 +00001190 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area, 60);
jardineb5d44e2003-12-23 08:09:43 +00001191
hassof390d2c2004-09-10 20:48:21 +00001192 spftree->pending = 1;
1193 return retval;
1194 }
hasso12a5cae2004-09-19 19:39:26 +00001195
1196 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001197
hassof390d2c2004-09-10 20:48:21 +00001198 if (diff < MINIMUM_SPF_INTERVAL)
1199 {
1200 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001201 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
1202 MINIMUM_SPF_INTERVAL - diff);
hassof390d2c2004-09-10 20:48:21 +00001203 else
hasso12a5cae2004-09-19 19:39:26 +00001204 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
1205 MINIMUM_SPF_INTERVAL - diff);
jardineb5d44e2003-12-23 08:09:43 +00001206
hassof390d2c2004-09-10 20:48:21 +00001207 spftree->pending = 1;
1208 }
1209 else
1210 {
1211 spftree->pending = 0;
1212 retval = isis_run_spf (area, level, AF_INET6);
hasso12a5cae2004-09-19 19:39:26 +00001213
1214 if (level == 1)
1215 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
1216 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1217 else
1218 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
1219 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
hassof390d2c2004-09-10 20:48:21 +00001220 }
jardineb5d44e2003-12-23 08:09:43 +00001221
1222 return retval;
1223}
jardineb5d44e2003-12-23 08:09:43 +00001224#endif
1225
hasso92365882005-01-18 13:53:33 +00001226static void
jardineb5d44e2003-12-23 08:09:43 +00001227isis_print_paths (struct vty *vty, struct list *paths)
1228{
paul1eb8ef22005-04-07 07:30:20 +00001229 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +00001230 struct isis_vertex *vertex;
1231 struct isis_dynhn *dyn, *nh_dyn = NULL;
1232 struct isis_adjacency *adj;
hasso92365882005-01-18 13:53:33 +00001233#if 0
jardineb5d44e2003-12-23 08:09:43 +00001234 u_char buff[255];
hasso92365882005-01-18 13:53:33 +00001235#endif /* 0 */
jardineb5d44e2003-12-23 08:09:43 +00001236
1237 vty_out (vty, "System Id Metric Next-Hop"
hassof390d2c2004-09-10 20:48:21 +00001238 " Interface SNPA%s", VTY_NEWLINE);
paul1eb8ef22005-04-07 07:30:20 +00001239
1240 for (ALL_LIST_ELEMENTS_RO (paths, node, vertex))
hassof390d2c2004-09-10 20:48:21 +00001241 {
hassof390d2c2004-09-10 20:48:21 +00001242 if (vertex->type != VTYPE_NONPSEUDO_IS)
1243 continue;
1244 if (memcmp (vertex->N.id, isis->sysid, ISIS_SYS_ID_LEN) == 0)
1245 {
hassoc3d26c72005-03-07 08:54:41 +00001246 vty_out (vty, "%s --%s", host.name?host.name:"",
1247 VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +00001248 }
1249 else
1250 {
1251 dyn = dynhn_find_by_id ((u_char *) vertex->N.id);
paul1eb8ef22005-04-07 07:30:20 +00001252 adj = listgetdata (listhead (vertex->Adj_N));
hassof390d2c2004-09-10 20:48:21 +00001253 if (adj)
1254 {
1255 nh_dyn = dynhn_find_by_id (adj->sysid);
1256 vty_out (vty, "%-20s %-10u %-20s %-11s %-5s%s",
1257 (dyn != NULL) ? dyn->name.name :
1258 (u_char *) rawlspid_print ((u_char *) vertex->N.id),
1259 vertex->d_N, (nh_dyn != NULL) ? nh_dyn->name.name :
1260 (u_char *) rawlspid_print (adj->sysid),
1261 adj->circuit->interface->name,
1262 snpa_print (adj->snpa), VTY_NEWLINE);
1263 }
1264 else
1265 {
1266 vty_out (vty, "%s %u %s", dyn ? dyn->name.name :
1267 (u_char *) rawlspid_print (vertex->N.id),
1268 vertex->d_N, VTY_NEWLINE);
1269 }
1270 }
jardineb5d44e2003-12-23 08:09:43 +00001271#if 0
hassof390d2c2004-09-10 20:48:21 +00001272 vty_out (vty, "%s %s %u %s", vtype2string (vertex->type),
1273 vid2string (vertex, buff), vertex->d_N, VTY_NEWLINE);
jardineb5d44e2003-12-23 08:09:43 +00001274#endif
hassof390d2c2004-09-10 20:48:21 +00001275 }
jardineb5d44e2003-12-23 08:09:43 +00001276}
1277
1278DEFUN (show_isis_topology,
1279 show_isis_topology_cmd,
1280 "show isis topology",
1281 SHOW_STR
1282 "IS-IS information\n"
1283 "IS-IS paths to Intermediate Systems\n")
1284{
1285 struct listnode *node;
1286 struct isis_area *area;
1287 int level;
hassof390d2c2004-09-10 20:48:21 +00001288
jardineb5d44e2003-12-23 08:09:43 +00001289 if (!isis->area_list || isis->area_list->count == 0)
1290 return CMD_SUCCESS;
1291
paul1eb8ef22005-04-07 07:30:20 +00001292 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001293 {
hassof390d2c2004-09-10 20:48:21 +00001294 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1295 VTY_NEWLINE);
1296
1297 for (level = 0; level < ISIS_LEVELS; level++)
1298 {
1299 if (area->ip_circuits > 0 && area->spftree[level]
1300 && area->spftree[level]->paths->count > 0)
1301 {
1302 vty_out (vty, "IS-IS paths to level-%d routers that speak IP%s",
1303 level + 1, VTY_NEWLINE);
1304 isis_print_paths (vty, area->spftree[level]->paths);
1305 }
jardineb5d44e2003-12-23 08:09:43 +00001306#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001307 if (area->ipv6_circuits > 0 && area->spftree6[level]
1308 && area->spftree6[level]->paths->count > 0)
1309 {
1310 vty_out (vty,
1311 "IS-IS paths to level-%d routers that speak IPv6%s",
1312 level + 1, VTY_NEWLINE);
1313 isis_print_paths (vty, area->spftree6[level]->paths);
1314 }
jardineb5d44e2003-12-23 08:09:43 +00001315#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +00001316 }
jardineb5d44e2003-12-23 08:09:43 +00001317 }
jardineb5d44e2003-12-23 08:09:43 +00001318
1319 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001320}
jardineb5d44e2003-12-23 08:09:43 +00001321
1322DEFUN (show_isis_topology_l1,
1323 show_isis_topology_l1_cmd,
1324 "show isis topology level-1",
1325 SHOW_STR
1326 "IS-IS information\n"
1327 "IS-IS paths to Intermediate Systems\n"
1328 "Paths to all level-1 routers in the area\n")
1329{
1330 struct listnode *node;
1331 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001332
jardineb5d44e2003-12-23 08:09:43 +00001333 if (!isis->area_list || isis->area_list->count == 0)
1334 return CMD_SUCCESS;
1335
paul1eb8ef22005-04-07 07:30:20 +00001336 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001337 {
hassof390d2c2004-09-10 20:48:21 +00001338 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1339 VTY_NEWLINE);
1340
1341 if (area->ip_circuits > 0 && area->spftree[0]
1342 && area->spftree[0]->paths->count > 0)
1343 {
1344 vty_out (vty, "IS-IS paths to level-1 routers that speak IP%s",
1345 VTY_NEWLINE);
1346 isis_print_paths (vty, area->spftree[0]->paths);
1347 }
jardineb5d44e2003-12-23 08:09:43 +00001348#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001349 if (area->ipv6_circuits > 0 && area->spftree6[0]
1350 && area->spftree6[0]->paths->count > 0)
1351 {
1352 vty_out (vty, "IS-IS paths to level-1 routers that speak IPv6%s",
1353 VTY_NEWLINE);
1354 isis_print_paths (vty, area->spftree6[0]->paths);
1355 }
jardineb5d44e2003-12-23 08:09:43 +00001356#endif /* HAVE_IPV6 */
1357 }
1358
jardineb5d44e2003-12-23 08:09:43 +00001359 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001360}
jardineb5d44e2003-12-23 08:09:43 +00001361
1362DEFUN (show_isis_topology_l2,
1363 show_isis_topology_l2_cmd,
1364 "show isis topology level-2",
1365 SHOW_STR
1366 "IS-IS information\n"
1367 "IS-IS paths to Intermediate Systems\n"
1368 "Paths to all level-2 routers in the domain\n")
1369{
1370 struct listnode *node;
1371 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001372
jardineb5d44e2003-12-23 08:09:43 +00001373 if (!isis->area_list || isis->area_list->count == 0)
1374 return CMD_SUCCESS;
1375
paul1eb8ef22005-04-07 07:30:20 +00001376 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001377 {
hassof390d2c2004-09-10 20:48:21 +00001378 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1379 VTY_NEWLINE);
1380
1381 if (area->ip_circuits > 0 && area->spftree[1]
1382 && area->spftree[1]->paths->count > 0)
1383 {
1384 vty_out (vty, "IS-IS paths to level-2 routers that speak IP%s",
1385 VTY_NEWLINE);
1386 isis_print_paths (vty, area->spftree[1]->paths);
1387 }
jardineb5d44e2003-12-23 08:09:43 +00001388#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001389 if (area->ipv6_circuits > 0 && area->spftree6[1]
1390 && area->spftree6[1]->paths->count > 0)
1391 {
1392 vty_out (vty, "IS-IS paths to level-2 routers that speak IPv6%s",
1393 VTY_NEWLINE);
1394 isis_print_paths (vty, area->spftree6[1]->paths);
1395 }
jardineb5d44e2003-12-23 08:09:43 +00001396#endif /* HAVE_IPV6 */
1397 }
1398
jardineb5d44e2003-12-23 08:09:43 +00001399 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001400}
jardineb5d44e2003-12-23 08:09:43 +00001401
1402void
1403isis_spf_cmds_init ()
1404{
1405 install_element (VIEW_NODE, &show_isis_topology_cmd);
1406 install_element (VIEW_NODE, &show_isis_topology_l1_cmd);
1407 install_element (VIEW_NODE, &show_isis_topology_l2_cmd);
1408
1409 install_element (ENABLE_NODE, &show_isis_topology_cmd);
1410 install_element (ENABLE_NODE, &show_isis_topology_l1_cmd);
1411 install_element (ENABLE_NODE, &show_isis_topology_l2_cmd);
1412}