blob: fc5b05ab9bc878e7fa6334c5456f8f7e06dd7905 [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
61/* performace issue ???? */
62void
hassof390d2c2004-09-10 20:48:21 +000063union_adjlist (struct list *target, struct list *source)
jardineb5d44e2003-12-23 08:09:43 +000064{
65 struct isis_adjacency *adj, *adj2;
66 struct listnode *node, *node2;
hassof390d2c2004-09-10 20:48:21 +000067
hasso529d65b2004-12-24 00:14:50 +000068 zlog_debug ("Union adjlist!");
hassof390d2c2004-09-10 20:48:21 +000069 for (node = listhead (source); node; nextnode (node))
70 {
71 adj = getdata (node);
72
73 /* lookup adjacency in the source list */
74 for (node2 = listhead (target); node2; nextnode (node2))
75 {
76 adj2 = getdata (node2);
77 if (adj == adj2)
78 break;
79 }
80
81 if (!node2)
82 listnode_add (target, adj);
jardineb5d44e2003-12-23 08:09:43 +000083 }
jardineb5d44e2003-12-23 08:09:43 +000084}
85
jardineb5d44e2003-12-23 08:09:43 +000086/* 7.2.7 */
hassof390d2c2004-09-10 20:48:21 +000087void
jardineb5d44e2003-12-23 08:09:43 +000088remove_excess_adjs (struct list *adjs)
89{
90 struct listnode *node, *excess = NULL;
91 struct isis_adjacency *adj, *candidate = NULL;
92 int comp;
93
hassof390d2c2004-09-10 20:48:21 +000094 for (node = listhead (adjs); node; nextnode (node))
95 {
96 if (excess == NULL)
97 excess = node;
98 candidate = getdata (excess);
99 adj = getdata (node);
100 if (candidate->sys_type < adj->sys_type)
101 {
102 excess = node;
103 candidate = adj;
104 continue;
105 }
106 if (candidate->sys_type > adj->sys_type)
107 continue;
108
109 comp = memcmp (candidate->sysid, adj->sysid, ISIS_SYS_ID_LEN);
110 if (comp > 0)
111 {
112 excess = node;
113 candidate = adj;
114 continue;
115 }
116 if (comp < 0)
117 continue;
118
119 if (candidate->circuit->circuit_id > adj->circuit->circuit_id)
120 {
121 excess = node;
122 candidate = adj;
123 continue;
124 }
125
126 if (candidate->circuit->circuit_id < adj->circuit->circuit_id)
127 continue;
128
129 comp = memcmp (candidate->snpa, adj->snpa, ETH_ALEN);
130 if (comp > 0)
131 {
132 excess = node;
133 candidate = adj;
134 continue;
135 }
jardineb5d44e2003-12-23 08:09:43 +0000136 }
137
jardineb5d44e2003-12-23 08:09:43 +0000138 list_delete_node (adjs, excess);
139
140 return;
141}
142
143const char *
144vtype2string (enum vertextype vtype)
145{
hassof390d2c2004-09-10 20:48:21 +0000146 switch (vtype)
147 {
148 case VTYPE_PSEUDO_IS:
149 return "pseudo_IS";
150 break;
151 case VTYPE_NONPSEUDO_IS:
152 return "IS";
153 break;
154 case VTYPE_ES:
155 return "ES";
156 break;
157 case VTYPE_IPREACH_INTERNAL:
158 return "IP internal";
159 break;
160 case VTYPE_IPREACH_EXTERNAL:
161 return "IP external";
162 break;
jardineb5d44e2003-12-23 08:09:43 +0000163#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000164 case VTYPE_IP6REACH_INTERNAL:
165 return "IP6 internal";
166 break;
167 case VTYPE_IP6REACH_EXTERNAL:
168 return "IP6 external";
169 break;
170#endif /* HAVE_IPV6 */
171 default:
172 return "UNKNOWN";
173 }
174 return NULL; /* Not reached */
jardineb5d44e2003-12-23 08:09:43 +0000175}
176
hasso1cd80842004-10-07 20:07:40 +0000177const char *
hassof390d2c2004-09-10 20:48:21 +0000178vid2string (struct isis_vertex *vertex, u_char * buff)
jardineb5d44e2003-12-23 08:09:43 +0000179{
hassof390d2c2004-09-10 20:48:21 +0000180 switch (vertex->type)
181 {
182 case VTYPE_PSEUDO_IS:
183 return rawlspid_print (vertex->N.id);
184 break;
185 case VTYPE_NONPSEUDO_IS:
186 case VTYPE_ES:
187 return sysid_print (vertex->N.id);
188 break;
189 case VTYPE_IPREACH_INTERNAL:
190 case VTYPE_IPREACH_EXTERNAL:
jardineb5d44e2003-12-23 08:09:43 +0000191#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000192 case VTYPE_IP6REACH_INTERNAL:
193 case VTYPE_IP6REACH_EXTERNAL:
194#endif /* HAVE_IPV6 */
hassof7c43dc2004-09-26 16:24:14 +0000195 prefix2str ((struct prefix *) &vertex->N.prefix, (char *) buff, BUFSIZ);
hassof390d2c2004-09-10 20:48:21 +0000196 break;
197 default:
198 return "UNKNOWN";
199 }
200
hassof7c43dc2004-09-26 16:24:14 +0000201 return (char *) buff;
jardineb5d44e2003-12-23 08:09:43 +0000202}
203
204struct isis_spftree *
205isis_spftree_new ()
206{
207 struct isis_spftree *tree;
208
209 tree = XMALLOC (MTYPE_ISIS_SPFTREE, sizeof (struct isis_spftree));
hassof390d2c2004-09-10 20:48:21 +0000210 if (tree == NULL)
211 {
212 zlog_err ("ISIS-Spf: isis_spftree_new Out of memory!");
213 return NULL;
214 }
jardineb5d44e2003-12-23 08:09:43 +0000215 memset (tree, 0, sizeof (struct isis_spftree));
216
217 tree->tents = list_new ();
hassof390d2c2004-09-10 20:48:21 +0000218 tree->paths = list_new ();
jardineb5d44e2003-12-23 08:09:43 +0000219 return tree;
220}
221
222void
223isis_vertex_del (struct isis_vertex *vertex)
224{
jardineb5d44e2003-12-23 08:09:43 +0000225 list_delete (vertex->Adj_N);
226
227 XFREE (MTYPE_ISIS_VERTEX, vertex);
hassof390d2c2004-09-10 20:48:21 +0000228
jardineb5d44e2003-12-23 08:09:43 +0000229 return;
230}
231
232void
233isis_spftree_del (struct isis_spftree *spftree)
234{
hassof7c43dc2004-09-26 16:24:14 +0000235 spftree->tents->del = (void (*)(void *)) isis_vertex_del;
jardineb5d44e2003-12-23 08:09:43 +0000236 list_delete (spftree->tents);
hassof390d2c2004-09-10 20:48:21 +0000237
hassof7c43dc2004-09-26 16:24:14 +0000238 spftree->paths->del = (void (*)(void *)) isis_vertex_del;
jardineb5d44e2003-12-23 08:09:43 +0000239 list_delete (spftree->paths);
240
241 XFREE (MTYPE_ISIS_SPFTREE, spftree);
242
243 return;
244}
245
hassof390d2c2004-09-10 20:48:21 +0000246void
jardineb5d44e2003-12-23 08:09:43 +0000247spftree_area_init (struct isis_area *area)
248{
hassof390d2c2004-09-10 20:48:21 +0000249 if ((area->is_type & IS_LEVEL_1) && area->spftree[0] == NULL)
250 {
251 area->spftree[0] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000252#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000253 area->spftree6[0] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000254#endif
255
hassof390d2c2004-09-10 20:48:21 +0000256 /* thread_add_timer (master, isis_run_spf_l1, area,
257 isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */
258 }
259
260 if ((area->is_type & IS_LEVEL_2) && area->spftree[1] == NULL)
261 {
262 area->spftree[1] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000263#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000264 area->spftree6[1] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000265#endif
hassof390d2c2004-09-10 20:48:21 +0000266 /* thread_add_timer (master, isis_run_spf_l2, area,
267 isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */
268 }
jardineb5d44e2003-12-23 08:09:43 +0000269
270 return;
271}
272
273struct isis_vertex *
274isis_vertex_new (void *id, enum vertextype vtype)
275{
276 struct isis_vertex *vertex;
277
278 vertex = XMALLOC (MTYPE_ISIS_VERTEX, sizeof (struct isis_vertex));
hassof390d2c2004-09-10 20:48:21 +0000279 if (vertex == NULL)
280 {
281 zlog_err ("isis_vertex_new Out of memory!");
282 return NULL;
283 }
284
jardineb5d44e2003-12-23 08:09:43 +0000285 memset (vertex, 0, sizeof (struct isis_vertex));
286 vertex->type = vtype;
hassof390d2c2004-09-10 20:48:21 +0000287 switch (vtype)
288 {
289 case VTYPE_ES:
290 case VTYPE_NONPSEUDO_IS:
291 memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN);
292 break;
293 case VTYPE_PSEUDO_IS:
294 memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN + 1);
295 break;
296 case VTYPE_IPREACH_INTERNAL:
297 case VTYPE_IPREACH_EXTERNAL:
jardineb5d44e2003-12-23 08:09:43 +0000298#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000299 case VTYPE_IP6REACH_INTERNAL:
300 case VTYPE_IP6REACH_EXTERNAL:
301#endif /* HAVE_IPV6 */
302 memcpy (&vertex->N.prefix, (struct prefix *) id,
303 sizeof (struct prefix));
304 break;
305 default:
306 zlog_err ("WTF!");
307 }
jardineb5d44e2003-12-23 08:09:43 +0000308
309 vertex->Adj_N = list_new ();
hassof390d2c2004-09-10 20:48:21 +0000310
jardineb5d44e2003-12-23 08:09:43 +0000311 return vertex;
312}
313
314/*
315 * Add this IS to the root of SPT
316 */
317void
318isis_spf_add_self (struct isis_spftree *spftree, struct isis_area *area,
hassof390d2c2004-09-10 20:48:21 +0000319 int level)
jardineb5d44e2003-12-23 08:09:43 +0000320{
321 struct isis_vertex *vertex;
322 struct isis_lsp *lsp;
323 u_char lspid[ISIS_SYS_ID_LEN + 2];
324#ifdef EXTREME_DEBUG
325 u_char buff[BUFSIZ];
326#endif /* EXTREME_DEBUG */
327 memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN);
hassof390d2c2004-09-10 20:48:21 +0000328 LSP_PSEUDO_ID (lspid) = 0;
329 LSP_FRAGMENT (lspid) = 0;
330
jardineb5d44e2003-12-23 08:09:43 +0000331 lsp = lsp_search (lspid, area->lspdb[level - 1]);
hassof390d2c2004-09-10 20:48:21 +0000332
jardineb5d44e2003-12-23 08:09:43 +0000333 if (lsp == NULL)
334 zlog_warn ("ISIS-Spf: could not find own l%d LSP!", level);
hassof390d2c2004-09-10 20:48:21 +0000335
jardineb5d44e2003-12-23 08:09:43 +0000336 vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_IS);
337 vertex->lsp = lsp;
338
339 listnode_add (spftree->paths, vertex);
340
341#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000342 zlog_debug ("ISIS-Spf: added this IS %s %s depth %d dist %d to PATHS",
343 vtype2string (vertex->type), vid2string (vertex, buff),
344 vertex->depth, vertex->d_N);
jardineb5d44e2003-12-23 08:09:43 +0000345#endif /* EXTREME_DEBUG */
346
347 return;
348}
349
350struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000351isis_find_vertex (struct list *list, void *id, enum vertextype vtype)
jardineb5d44e2003-12-23 08:09:43 +0000352{
353 struct listnode *node;
354 struct isis_vertex *vertex;
355 struct prefix *p1, *p2;
356
hassof390d2c2004-09-10 20:48:21 +0000357 for (node = listhead (list); node; nextnode (node))
358 {
359 vertex = getdata (node);
360 if (vertex->type != vtype)
361 continue;
362 switch (vtype)
363 {
364 case VTYPE_ES:
365 case VTYPE_NONPSEUDO_IS:
366 if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN) == 0)
367 return vertex;
368 break;
369 case VTYPE_PSEUDO_IS:
370 if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN + 1) == 0)
371 return vertex;
372 break;
373 case VTYPE_IPREACH_INTERNAL:
374 case VTYPE_IPREACH_EXTERNAL:
jardineb5d44e2003-12-23 08:09:43 +0000375#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000376 case VTYPE_IP6REACH_INTERNAL:
377 case VTYPE_IP6REACH_EXTERNAL:
jardineb5d44e2003-12-23 08:09:43 +0000378#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000379 p1 = (struct prefix *) id;
380 p2 = (struct prefix *) &vertex->N.id;
381 if (p1->family == p2->family && p1->prefixlen == p2->prefixlen &&
382 memcmp (&p1->u.prefix, &p2->u.prefix,
383 PSIZE (p1->prefixlen)) == 0)
384 return vertex;
385 break;
386 }
jardineb5d44e2003-12-23 08:09:43 +0000387 }
jardineb5d44e2003-12-23 08:09:43 +0000388
389 return NULL;
390}
391
jardineb5d44e2003-12-23 08:09:43 +0000392/*
393 * Add a vertex to TENT sorted by cost and by vertextype on tie break situation
394 */
395struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000396isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype,
397 void *id, struct isis_adjacency *adj, u_int16_t cost,
398 int depth, int family)
jardineb5d44e2003-12-23 08:09:43 +0000399{
400 struct isis_vertex *vertex, *v;
401 struct listnode *node;
hassof390d2c2004-09-10 20:48:21 +0000402#ifdef EXTREME_DEBUG
jardineb5d44e2003-12-23 08:09:43 +0000403 u_char buff[BUFSIZ];
404#endif
405
406 vertex = isis_vertex_new (id, vtype);
407 vertex->d_N = cost;
408 vertex->depth = depth;
hassof390d2c2004-09-10 20:48:21 +0000409
jardineb5d44e2003-12-23 08:09:43 +0000410 if (adj)
411 listnode_add (vertex->Adj_N, adj);
hassof390d2c2004-09-10 20:48:21 +0000412#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000413 zlog_debug ("ISIS-Spf: add to TENT %s %s depth %d dist %d",
414 vtype2string (vertex->type), vid2string (vertex, buff),
415 vertex->depth, vertex->d_N);
jardineb5d44e2003-12-23 08:09:43 +0000416#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000417 listnode_add (spftree->tents, vertex);
418 if (list_isempty (spftree->tents))
419 {
420 listnode_add (spftree->tents, vertex);
421 return vertex;
jardineb5d44e2003-12-23 08:09:43 +0000422 }
hassof390d2c2004-09-10 20:48:21 +0000423 for (node = listhead (spftree->tents); node; nextnode (node))
424 {
425 v = getdata (node);
426 if (v->d_N > vertex->d_N)
427 {
428 list_add_node_prev (spftree->tents, node, vertex);
429 break;
430 }
431 else if (v->d_N == vertex->d_N)
432 {
433 /* Tie break, add according to type */
434 while (v && v->d_N == vertex->d_N && v->type > vertex->type)
435 {
436 if (v->type > vertex->type)
437 {
438 break;
439 }
440 nextnode (node);
441 (node) ? (v = getdata (node)) : (v = NULL);
442 }
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
455struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000456isis_spf_add_local (struct isis_spftree *spftree, enum vertextype vtype,
457 void *id, struct isis_adjacency *adj, u_int16_t cost,
458 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
489void
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 */
551int
hassof390d2c2004-09-10 20:48:21 +0000552isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp,
553 uint16_t cost, uint16_t depth, int family)
jardineb5d44e2003-12-23 08:09:43 +0000554{
555 struct listnode *node, *fragnode = NULL;
556 u_int16_t dist;
557 struct is_neigh *is_neigh;
558 struct ipv4_reachability *ipreach;
559 enum vertextype vtype;
560 struct prefix prefix;
561#ifdef HAVE_IPV6
562 struct ipv6_reachability *ip6reach;
563#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000564
jardineb5d44e2003-12-23 08:09:43 +0000565
566 if (!lsp->adj)
567 return ISIS_WARNING;
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 {
583 for (node = listhead (lsp->tlv_data.is_neighs); node;
584 nextnode (node))
585 {
586 is_neigh = getdata (node);
587 /* C.2.6 a) */
588 /* Two way connectivity */
589 if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
590 continue;
591 dist = cost + is_neigh->metrics.metric_default;
592 vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
593 : VTYPE_NONPSEUDO_IS;
594 process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist,
595 depth + 1, lsp->adj, family);
596 }
597 }
598 if (family == AF_INET && lsp->tlv_data.ipv4_int_reachs)
599 {
600 prefix.family = AF_INET;
601 for (node = listhead (lsp->tlv_data.ipv4_int_reachs); node;
602 nextnode (node))
603 {
604 ipreach = getdata (node);
605 dist = cost + ipreach->metrics.metric_default;
606 vtype = VTYPE_IPREACH_INTERNAL;
607 prefix.u.prefix4 = ipreach->prefix;
608 prefix.prefixlen = ip_masklen (ipreach->mask);
609 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
610 lsp->adj, family);
611 }
612 }
613
614 if (family == AF_INET && lsp->tlv_data.ipv4_ext_reachs)
615 {
616 prefix.family = AF_INET;
617 for (node = listhead (lsp->tlv_data.ipv4_ext_reachs); node;
618 nextnode (node))
619 {
620 ipreach = getdata (node);
621 dist = cost + ipreach->metrics.metric_default;
622 vtype = VTYPE_IPREACH_EXTERNAL;
623 prefix.u.prefix4 = ipreach->prefix;
624 prefix.prefixlen = ip_masklen (ipreach->mask);
625 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
626 lsp->adj, family);
627 }
628 }
jardineb5d44e2003-12-23 08:09:43 +0000629#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000630 if (family == AF_INET6 && lsp->tlv_data.ipv6_reachs)
631 {
632 prefix.family = AF_INET6;
633 for (node = listhead (lsp->tlv_data.ipv6_reachs); node;
634 nextnode (node))
635 {
636 ip6reach = getdata (node);
637 dist = cost + ip6reach->metric;
638 vtype = (ip6reach->control_info & CTRL_INFO_DISTRIBUTION) ?
639 VTYPE_IP6REACH_EXTERNAL : VTYPE_IP6REACH_INTERNAL;
640 prefix.prefixlen = ip6reach->prefix_len;
641 memcpy (&prefix.u.prefix6.s6_addr, ip6reach->prefix,
642 PSIZE (ip6reach->prefix_len));
643 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
644 lsp->adj, family);
645 }
646 }
jardineb5d44e2003-12-23 08:09:43 +0000647#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000648 }
649
jardineb5d44e2003-12-23 08:09:43 +0000650 if (fragnode == NULL)
651 fragnode = listhead (lsp->lspu.frags);
hassof390d2c2004-09-10 20:48:21 +0000652 else
hasso1cd80842004-10-07 20:07:40 +0000653 nextnode (fragnode);
jardineb5d44e2003-12-23 08:09:43 +0000654
hassof390d2c2004-09-10 20:48:21 +0000655 if (fragnode)
656 {
657 lsp = getdata (fragnode);
658 goto lspfragloop;
659 }
660
jardineb5d44e2003-12-23 08:09:43 +0000661 return ISIS_OK;
662}
663
664int
hassof390d2c2004-09-10 20:48:21 +0000665isis_spf_process_pseudo_lsp (struct isis_spftree *spftree,
666 struct isis_lsp *lsp, uint16_t cost,
667 uint16_t depth, int family)
jardineb5d44e2003-12-23 08:09:43 +0000668{
669 struct listnode *node, *fragnode = NULL;
670 struct is_neigh *is_neigh;
671 enum vertextype vtype;
hassof390d2c2004-09-10 20:48:21 +0000672
673pseudofragloop:
674
675 if (lsp->lsp_header->seq_num == 0)
676 {
677 zlog_warn ("isis_spf_process_pseudo_lsp(): lsp with 0 seq_num"
678 " - do not process");
679 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +0000680 }
hassof390d2c2004-09-10 20:48:21 +0000681
682 for (node = (lsp->tlv_data.is_neighs ?
683 listhead (lsp->tlv_data.is_neighs) : NULL);
684 node; nextnode (node))
685 {
686 is_neigh = getdata (node);
687 vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
688 : VTYPE_NONPSEUDO_IS;
689 /* Two way connectivity */
690 if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
691 continue;
692 if (isis_find_vertex
693 (spftree->tents, (void *) is_neigh->neigh_id, vtype) == NULL
694 && isis_find_vertex (spftree->paths, (void *) is_neigh->neigh_id,
695 vtype) == NULL)
696 {
697 /* C.2.5 i) */
698 isis_spf_add2tent (spftree, vtype, is_neigh->neigh_id, lsp->adj,
699 cost, depth, family);
700 }
701 }
702
jardineb5d44e2003-12-23 08:09:43 +0000703 if (fragnode == NULL)
704 fragnode = listhead (lsp->lspu.frags);
hassof390d2c2004-09-10 20:48:21 +0000705 else
hasso1cd80842004-10-07 20:07:40 +0000706 nextnode (fragnode);
jardineb5d44e2003-12-23 08:09:43 +0000707
hassof390d2c2004-09-10 20:48:21 +0000708 if (fragnode)
709 {
710 lsp = getdata (fragnode);
711 goto pseudofragloop;
712 }
jardineb5d44e2003-12-23 08:09:43 +0000713
jardineb5d44e2003-12-23 08:09:43 +0000714 return ISIS_OK;
715}
hassof390d2c2004-09-10 20:48:21 +0000716
jardineb5d44e2003-12-23 08:09:43 +0000717int
hassof390d2c2004-09-10 20:48:21 +0000718isis_spf_preload_tent (struct isis_spftree *spftree,
719 struct isis_area *area, int level, int family)
jardineb5d44e2003-12-23 08:09:43 +0000720{
721 struct isis_vertex *vertex;
722 struct isis_circuit *circuit;
723 struct listnode *cnode, *anode, *ipnode;
724 struct isis_adjacency *adj;
725 struct isis_lsp *lsp;
726 struct list *adj_list;
727 struct list *adjdb;
728 struct prefix_ipv4 *ipv4;
729 struct prefix prefix;
730 int retval = ISIS_OK;
731 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
732#ifdef HAVE_IPV6
733 struct prefix_ipv6 *ipv6;
734#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000735
736 for (cnode = listhead (area->circuit_list); cnode; nextnode (cnode))
737 {
738 circuit = getdata (cnode);
739 if (circuit->state != C_STATE_UP)
jardineb5d44e2003-12-23 08:09:43 +0000740 continue;
hassof390d2c2004-09-10 20:48:21 +0000741 if (!(circuit->circuit_is_type & level))
742 continue;
743 if (family == AF_INET && !circuit->ip_router)
744 continue;
745#ifdef HAVE_IPV6
746 if (family == AF_INET6 && !circuit->ipv6_router)
747 continue;
748#endif /* HAVE_IPV6 */
749 /*
750 * Add IP(v6) addresses of this circuit
jardineb5d44e2003-12-23 08:09:43 +0000751 */
hassof390d2c2004-09-10 20:48:21 +0000752 if (family == AF_INET)
753 {
754 prefix.family = AF_INET;
755 for (ipnode =
756 (circuit->ip_addrs ? listhead (circuit->ip_addrs) : NULL);
757 ipnode; nextnode (ipnode))
758 {
759 ipv4 = getdata (ipnode);
760 prefix.u.prefix4 = ipv4->prefix;
761 prefix.prefixlen = ipv4->prefixlen;
762 isis_spf_add_local (spftree, VTYPE_IPREACH_INTERNAL, &prefix,
763 NULL, 0, family);
764 }
765 }
766#ifdef HAVE_IPV6
767 if (family == AF_INET6)
768 {
769 prefix.family = AF_INET6;
770 for (ipnode = (circuit->ipv6_non_link ? listhead
771 (circuit->ipv6_non_link) : NULL); ipnode;
772 nextnode (ipnode))
773 {
774 ipv6 = getdata (ipnode);
775 prefix.prefixlen = ipv6->prefixlen;
776 prefix.u.prefix6 = ipv6->prefix;
777 isis_spf_add_local (spftree, VTYPE_IP6REACH_INTERNAL,
778 &prefix, NULL, 0, family);
779 }
780 }
781#endif /* HAVE_IPV6 */
782 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
783 {
784 /*
785 * Add the adjacencies
786 */
787 adj_list = list_new ();
788 adjdb = circuit->u.bc.adjdb[level - 1];
789 isis_adj_build_up_list (adjdb, adj_list);
790 if (listcount (adj_list) == 0)
791 {
792 list_delete (adj_list);
793 zlog_warn ("ISIS-Spf: no L%d adjacencies on circuit %s",
794 level, circuit->interface->name);
795 continue;
796 }
797 anode = listhead (adj_list);
798 while (anode)
799 {
800 adj = getdata (anode);
801 if (!speaks (&adj->nlpids, family))
802 {
hasso1cd80842004-10-07 20:07:40 +0000803 nextnode (anode);
hassof390d2c2004-09-10 20:48:21 +0000804 continue;
805 }
806 switch (adj->sys_type)
807 {
808 case ISIS_SYSTYPE_ES:
809 isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
810 circuit->metrics[level -
811 1].metric_default,
812 family);
813 break;
814 case ISIS_SYSTYPE_IS:
815 case ISIS_SYSTYPE_L1_IS:
816 case ISIS_SYSTYPE_L2_IS:
817 vertex =
818 isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS,
819 adj->sysid, adj,
820 circuit->metrics[level -
821 1].metric_default,
822 family);
823 memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN);
824 LSP_PSEUDO_ID (lsp_id) = 0;
825 LSP_FRAGMENT (lsp_id) = 0;
826 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
827 if (!lsp)
828 zlog_warn ("No lsp found for IS adjacency");
829 /* else {
830 isis_spf_process_lsp (spftree, lsp, vertex->d_N, 1, family);
831 } */
832 break;
833 case ISIS_SYSTYPE_UNKNOWN:
834 default:
835 zlog_warn ("isis_spf_preload_tent unknow adj type");
836 }
hasso1cd80842004-10-07 20:07:40 +0000837 nextnode (anode);
hassof390d2c2004-09-10 20:48:21 +0000838 }
839 list_delete (adj_list);
840 /*
841 * Add the pseudonode
842 */
843 if (level == 1)
844 memcpy (lsp_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
845 else
846 memcpy (lsp_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
847 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
848 adj = isis_adj_lookup (lsp_id, adjdb);
849 /* if no adj, we are the dis or error */
850 if (!adj && !circuit->u.bc.is_dr[level - 1])
851 {
852 zlog_warn ("ISIS-Spf: No adjacency found for DR");
853 }
854 if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0)
855 {
856 zlog_warn ("ISIS-Spf: No lsp found for DR");
857 }
858 else
859 {
860 isis_spf_process_pseudo_lsp
861 (spftree, lsp, circuit->metrics[level - 1].metric_default, 0,
862 family);
863
864 }
865 }
866 else if (circuit->circ_type == CIRCUIT_T_P2P)
867 {
868 adj = circuit->u.p2p.neighbor;
869 if (!adj)
870 continue;
871 switch (adj->sys_type)
872 {
873 case ISIS_SYSTYPE_ES:
874 isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
875 circuit->metrics[level - 1].metric_default,
876 family);
877 break;
878 case ISIS_SYSTYPE_IS:
879 case ISIS_SYSTYPE_L1_IS:
880 case ISIS_SYSTYPE_L2_IS:
881 if (speaks (&adj->nlpids, family))
882 isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS, adj->sysid,
883 adj,
884 circuit->metrics[level -
885 1].metric_default,
886 family);
887 break;
888 case ISIS_SYSTYPE_UNKNOWN:
889 default:
890 zlog_warn ("isis_spf_preload_tent unknow adj type");
891 break;
892 }
893 }
jardineb5d44e2003-12-23 08:09:43 +0000894 else
hassof390d2c2004-09-10 20:48:21 +0000895 {
896 zlog_warn ("isis_spf_preload_tent unsupported media");
897 retval = ISIS_WARNING;
898 }
899
jardineb5d44e2003-12-23 08:09:43 +0000900 }
jardineb5d44e2003-12-23 08:09:43 +0000901
902 return retval;
903}
904
905/*
906 * The parent(s) for vertex is set when added to TENT list
907 * now we just put the child pointer(s) in place
908 */
909void
910add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex,
hassof390d2c2004-09-10 20:48:21 +0000911 struct isis_area *area)
jardineb5d44e2003-12-23 08:09:43 +0000912{
jardineb5d44e2003-12-23 08:09:43 +0000913#ifdef EXTREME_DEBUG
914 u_char buff[BUFSIZ];
915#endif /* EXTREME_DEBUG */
916 listnode_add (spftree->paths, vertex);
917
hassof390d2c2004-09-10 20:48:21 +0000918#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000919 zlog_debug ("ISIS-Spf: added %s %s depth %d dist %d to PATHS",
920 vtype2string (vertex->type), vid2string (vertex, buff),
921 vertex->depth, vertex->d_N);
hassof390d2c2004-09-10 20:48:21 +0000922#endif /* EXTREME_DEBUG */
923 if (vertex->type > VTYPE_ES)
924 {
925 if (listcount (vertex->Adj_N) > 0)
926 isis_route_create ((struct prefix *) &vertex->N.prefix,
927 vertex->d_N, vertex->depth, vertex->Adj_N, area);
928 else if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000929 zlog_debug ("ISIS-Spf: no adjacencies do not install route");
hassof390d2c2004-09-10 20:48:21 +0000930 }
931
jardineb5d44e2003-12-23 08:09:43 +0000932 return;
933}
934
jardineb5d44e2003-12-23 08:09:43 +0000935void
936init_spt (struct isis_spftree *spftree)
937{
hassof7c43dc2004-09-26 16:24:14 +0000938 spftree->tents->del = spftree->paths->del = (void (*)(void *)) isis_vertex_del;
jardineb5d44e2003-12-23 08:09:43 +0000939 list_delete_all_node (spftree->tents);
940 list_delete_all_node (spftree->paths);
941 spftree->tents->del = spftree->paths->del = NULL;
hassof390d2c2004-09-10 20:48:21 +0000942
jardineb5d44e2003-12-23 08:09:43 +0000943 return;
944}
945
946int
947isis_run_spf (struct isis_area *area, int level, int family)
948{
949 int retval = ISIS_OK;
950 struct listnode *node;
951 struct isis_vertex *vertex;
hassof390d2c2004-09-10 20:48:21 +0000952 struct isis_spftree *spftree = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000953 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
954 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +0000955
jardineb5d44e2003-12-23 08:09:43 +0000956 if (family == AF_INET)
957 spftree = area->spftree[level - 1];
958#ifdef HAVE_IPV6
959 else if (family == AF_INET6)
960 spftree = area->spftree6[level - 1];
961#endif
hassof390d2c2004-09-10 20:48:21 +0000962
jardineb5d44e2003-12-23 08:09:43 +0000963 assert (spftree);
964
965 /*
966 * C.2.5 Step 0
967 */
968 init_spt (spftree);
969 /* a) */
970 isis_spf_add_self (spftree, area, level);
971 /* b) */
972 retval = isis_spf_preload_tent (spftree, area, level, family);
hassof390d2c2004-09-10 20:48:21 +0000973
jardineb5d44e2003-12-23 08:09:43 +0000974 /*
975 * C.2.7 Step 2
976 */
hassof390d2c2004-09-10 20:48:21 +0000977 if (listcount (spftree->tents) == 0)
978 {
979 zlog_warn ("ISIS-Spf: TENT is empty");
980 spftree->lastrun = time (NULL);
981 return retval;
jardineb5d44e2003-12-23 08:09:43 +0000982 }
hassof390d2c2004-09-10 20:48:21 +0000983
984 while (listcount (spftree->tents) > 0)
985 {
986 node = listhead (spftree->tents);
987 vertex = getdata (node);
988 /* Remove from tent list */
989 list_delete_node (spftree->tents, node);
990 if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type))
991 continue;
992 add_to_paths (spftree, vertex, area);
993 if (vertex->type == VTYPE_PSEUDO_IS ||
994 vertex->type == VTYPE_NONPSEUDO_IS)
995 {
996 memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
997 LSP_FRAGMENT (lsp_id) = 0;
998 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
999 if (lsp)
1000 {
1001 if (LSP_PSEUDO_ID (lsp_id))
1002 {
1003 isis_spf_process_pseudo_lsp (spftree, lsp, vertex->d_N,
1004 vertex->depth, family);
1005
1006 }
1007 else
1008 {
1009 isis_spf_process_lsp (spftree, lsp, vertex->d_N,
1010 vertex->depth, family);
1011 }
1012 }
1013 else
1014 {
1015 zlog_warn ("ISIS-Spf: No LSP found for %s",
1016 rawlspid_print (lsp_id));
1017 }
1018 }
1019 }
1020
jardineb5d44e2003-12-23 08:09:43 +00001021 thread_add_event (master, isis_route_validate, area, 0);
1022 spftree->lastrun = time (NULL);
1023 spftree->pending = 0;
hassof390d2c2004-09-10 20:48:21 +00001024
jardineb5d44e2003-12-23 08:09:43 +00001025 return retval;
1026}
1027
1028int
1029isis_run_spf_l1 (struct thread *thread)
1030{
1031 struct isis_area *area;
1032 int retval = ISIS_OK;
1033
hassof390d2c2004-09-10 20:48:21 +00001034 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001035 assert (area);
1036
hasso12a5cae2004-09-19 19:39:26 +00001037 area->spftree[0]->t_spf = NULL;
1038
hassof390d2c2004-09-10 20:48:21 +00001039 if (!(area->is_type & IS_LEVEL_1))
1040 {
1041 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001042 zlog_warn ("ISIS-SPF (%s) area does not share level",
1043 area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001044 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001045 }
jardineb5d44e2003-12-23 08:09:43 +00001046
hassof390d2c2004-09-10 20:48:21 +00001047 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001048 zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001049
jardineb5d44e2003-12-23 08:09:43 +00001050 if (area->ip_circuits)
1051 retval = isis_run_spf (area, 1, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001052
1053 THREAD_TIMER_ON (master, area->spftree[0]->t_spf, isis_run_spf_l1, area,
1054 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1055
jardineb5d44e2003-12-23 08:09:43 +00001056 return retval;
1057}
1058
1059int
1060isis_run_spf_l2 (struct thread *thread)
1061{
1062 struct isis_area *area;
1063 int retval = ISIS_OK;
1064
hassof390d2c2004-09-10 20:48:21 +00001065 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001066 assert (area);
hassof390d2c2004-09-10 20:48:21 +00001067
hasso12a5cae2004-09-19 19:39:26 +00001068 area->spftree[1]->t_spf = NULL;
1069
hassof390d2c2004-09-10 20:48:21 +00001070 if (!(area->is_type & IS_LEVEL_2))
1071 {
1072 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001073 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001074 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001075 }
hassof390d2c2004-09-10 20:48:21 +00001076
1077 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001078 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag);
jardineb5d44e2003-12-23 08:09:43 +00001079
1080 if (area->ip_circuits)
1081 retval = isis_run_spf (area, 2, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001082
1083 THREAD_TIMER_ON (master, area->spftree[1]->t_spf, isis_run_spf_l2, area,
1084 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
jardineb5d44e2003-12-23 08:09:43 +00001085
1086 return retval;
1087}
1088
hassof390d2c2004-09-10 20:48:21 +00001089int
jardineb5d44e2003-12-23 08:09:43 +00001090isis_spf_schedule (struct isis_area *area, int level)
1091{
1092 int retval = ISIS_OK;
1093 struct isis_spftree *spftree = area->spftree[level - 1];
1094 time_t diff, now = time (NULL);
1095
1096 if (spftree->pending)
1097 return retval;
1098
hassof390d2c2004-09-10 20:48:21 +00001099 diff = now - spftree->lastrun;
jardineb5d44e2003-12-23 08:09:43 +00001100
1101 /* FIXME: let's wait a minute before doing the SPF */
hassof390d2c2004-09-10 20:48:21 +00001102 if (now - isis->uptime < 60 || isis->uptime == 0)
1103 {
1104 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001105 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area, 60);
hassof390d2c2004-09-10 20:48:21 +00001106 else
hasso12a5cae2004-09-19 19:39:26 +00001107 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area, 60);
jardineb5d44e2003-12-23 08:09:43 +00001108
hassof390d2c2004-09-10 20:48:21 +00001109 spftree->pending = 1;
1110 return retval;
1111 }
hasso12a5cae2004-09-19 19:39:26 +00001112
1113 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001114
hassof390d2c2004-09-10 20:48:21 +00001115 if (diff < MINIMUM_SPF_INTERVAL)
1116 {
1117 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001118 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
1119 MINIMUM_SPF_INTERVAL - diff);
hassof390d2c2004-09-10 20:48:21 +00001120 else
hasso12a5cae2004-09-19 19:39:26 +00001121 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
1122 MINIMUM_SPF_INTERVAL - diff);
jardineb5d44e2003-12-23 08:09:43 +00001123
hassof390d2c2004-09-10 20:48:21 +00001124 spftree->pending = 1;
1125 }
1126 else
1127 {
1128 spftree->pending = 0;
1129 retval = isis_run_spf (area, level, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001130 if (level == 1)
1131 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
1132 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1133 else
1134 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
1135 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
hassof390d2c2004-09-10 20:48:21 +00001136 }
jardineb5d44e2003-12-23 08:09:43 +00001137
1138 return retval;
1139}
1140
1141#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001142int
hasso12a5cae2004-09-19 19:39:26 +00001143isis_run_spf6_l1 (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[0]->t_spf = NULL;
1152
1153 if (!(area->is_type & IS_LEVEL_1))
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) L1 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, 1, AF_INET6);
1165
1166 THREAD_TIMER_ON (master, area->spftree6[0]->t_spf, isis_run_spf6_l1, area,
1167 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1168
1169 return retval;
1170}
1171
1172int
1173isis_run_spf6_l2 (struct thread *thread)
1174{
1175 struct isis_area *area;
1176 int retval = ISIS_OK;
1177
1178 area = THREAD_ARG (thread);
1179 assert (area);
1180
1181 area->spftree6[1]->t_spf = NULL;
1182
1183 if (!(area->is_type & IS_LEVEL_2))
1184 {
1185 if (isis->debugs & DEBUG_SPF_EVENTS)
1186 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
1187 return ISIS_WARNING;
1188 }
1189
1190 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001191 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001192
1193 if (area->ipv6_circuits)
1194 retval = isis_run_spf (area, 2, AF_INET6);
1195
1196 THREAD_TIMER_ON (master, area->spftree6[1]->t_spf, isis_run_spf6_l2, area,
1197 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1198
1199 return retval;
1200}
1201
1202int
jardineb5d44e2003-12-23 08:09:43 +00001203isis_spf_schedule6 (struct isis_area *area, int level)
1204{
1205 int retval = ISIS_OK;
1206 struct isis_spftree *spftree = area->spftree6[level - 1];
1207 time_t diff, now = time (NULL);
1208
1209 if (spftree->pending)
1210 return retval;
1211
hassof390d2c2004-09-10 20:48:21 +00001212 diff = now - spftree->lastrun;
1213
jardineb5d44e2003-12-23 08:09:43 +00001214 /* FIXME: let's wait a minute before doing the SPF */
hassof390d2c2004-09-10 20:48:21 +00001215 if (now - isis->uptime < 60 || isis->uptime == 0)
1216 {
1217 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001218 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area, 60);
hassof390d2c2004-09-10 20:48:21 +00001219 else
hasso12a5cae2004-09-19 19:39:26 +00001220 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area, 60);
jardineb5d44e2003-12-23 08:09:43 +00001221
hassof390d2c2004-09-10 20:48:21 +00001222 spftree->pending = 1;
1223 return retval;
1224 }
hasso12a5cae2004-09-19 19:39:26 +00001225
1226 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001227
hassof390d2c2004-09-10 20:48:21 +00001228 if (diff < MINIMUM_SPF_INTERVAL)
1229 {
1230 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001231 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
1232 MINIMUM_SPF_INTERVAL - diff);
hassof390d2c2004-09-10 20:48:21 +00001233 else
hasso12a5cae2004-09-19 19:39:26 +00001234 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
1235 MINIMUM_SPF_INTERVAL - diff);
jardineb5d44e2003-12-23 08:09:43 +00001236
hassof390d2c2004-09-10 20:48:21 +00001237 spftree->pending = 1;
1238 }
1239 else
1240 {
1241 spftree->pending = 0;
1242 retval = isis_run_spf (area, level, AF_INET6);
hasso12a5cae2004-09-19 19:39:26 +00001243
1244 if (level == 1)
1245 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
1246 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1247 else
1248 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
1249 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
hassof390d2c2004-09-10 20:48:21 +00001250 }
jardineb5d44e2003-12-23 08:09:43 +00001251
1252 return retval;
1253}
jardineb5d44e2003-12-23 08:09:43 +00001254#endif
1255
1256void
1257isis_print_paths (struct vty *vty, struct list *paths)
1258{
1259 struct listnode *node, *anode;
1260 struct isis_vertex *vertex;
1261 struct isis_dynhn *dyn, *nh_dyn = NULL;
1262 struct isis_adjacency *adj;
1263#ifdef EXTREME_DEBUG
1264 u_char buff[255];
hassof390d2c2004-09-10 20:48:21 +00001265#endif
jardineb5d44e2003-12-23 08:09:43 +00001266
1267 vty_out (vty, "System Id Metric Next-Hop"
hassof390d2c2004-09-10 20:48:21 +00001268 " Interface SNPA%s", VTY_NEWLINE);
1269 for (node = listhead (paths); node; nextnode (node))
1270 {
1271 vertex = getdata (node);
1272 if (vertex->type != VTYPE_NONPSEUDO_IS)
1273 continue;
1274 if (memcmp (vertex->N.id, isis->sysid, ISIS_SYS_ID_LEN) == 0)
1275 {
1276 vty_out (vty, "%s --%s", host.name, VTY_NEWLINE);
1277 }
1278 else
1279 {
1280 dyn = dynhn_find_by_id ((u_char *) vertex->N.id);
1281 anode = listhead (vertex->Adj_N);
1282 adj = getdata (anode);
1283 if (adj)
1284 {
1285 nh_dyn = dynhn_find_by_id (adj->sysid);
1286 vty_out (vty, "%-20s %-10u %-20s %-11s %-5s%s",
1287 (dyn != NULL) ? dyn->name.name :
1288 (u_char *) rawlspid_print ((u_char *) vertex->N.id),
1289 vertex->d_N, (nh_dyn != NULL) ? nh_dyn->name.name :
1290 (u_char *) rawlspid_print (adj->sysid),
1291 adj->circuit->interface->name,
1292 snpa_print (adj->snpa), VTY_NEWLINE);
1293 }
1294 else
1295 {
1296 vty_out (vty, "%s %u %s", dyn ? dyn->name.name :
1297 (u_char *) rawlspid_print (vertex->N.id),
1298 vertex->d_N, VTY_NEWLINE);
1299 }
1300 }
jardineb5d44e2003-12-23 08:09:43 +00001301#if 0
hassof390d2c2004-09-10 20:48:21 +00001302 vty_out (vty, "%s %s %u %s", vtype2string (vertex->type),
1303 vid2string (vertex, buff), vertex->d_N, VTY_NEWLINE);
jardineb5d44e2003-12-23 08:09:43 +00001304#endif
hassof390d2c2004-09-10 20:48:21 +00001305 }
jardineb5d44e2003-12-23 08:09:43 +00001306}
1307
1308DEFUN (show_isis_topology,
1309 show_isis_topology_cmd,
1310 "show isis topology",
1311 SHOW_STR
1312 "IS-IS information\n"
1313 "IS-IS paths to Intermediate Systems\n")
1314{
1315 struct listnode *node;
1316 struct isis_area *area;
1317 int level;
hassof390d2c2004-09-10 20:48:21 +00001318
jardineb5d44e2003-12-23 08:09:43 +00001319 if (!isis->area_list || isis->area_list->count == 0)
1320 return CMD_SUCCESS;
1321
hassof390d2c2004-09-10 20:48:21 +00001322 for (node = listhead (isis->area_list); node; nextnode (node))
1323 {
1324 area = getdata (node);
jardineb5d44e2003-12-23 08:09:43 +00001325
hassof390d2c2004-09-10 20:48:21 +00001326 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1327 VTY_NEWLINE);
1328
1329 for (level = 0; level < ISIS_LEVELS; level++)
1330 {
1331 if (area->ip_circuits > 0 && area->spftree[level]
1332 && area->spftree[level]->paths->count > 0)
1333 {
1334 vty_out (vty, "IS-IS paths to level-%d routers that speak IP%s",
1335 level + 1, VTY_NEWLINE);
1336 isis_print_paths (vty, area->spftree[level]->paths);
1337 }
jardineb5d44e2003-12-23 08:09:43 +00001338#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001339 if (area->ipv6_circuits > 0 && area->spftree6[level]
1340 && area->spftree6[level]->paths->count > 0)
1341 {
1342 vty_out (vty,
1343 "IS-IS paths to level-%d routers that speak IPv6%s",
1344 level + 1, VTY_NEWLINE);
1345 isis_print_paths (vty, area->spftree6[level]->paths);
1346 }
jardineb5d44e2003-12-23 08:09:43 +00001347#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +00001348 }
jardineb5d44e2003-12-23 08:09:43 +00001349 }
jardineb5d44e2003-12-23 08:09:43 +00001350
1351 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001352}
jardineb5d44e2003-12-23 08:09:43 +00001353
1354DEFUN (show_isis_topology_l1,
1355 show_isis_topology_l1_cmd,
1356 "show isis topology level-1",
1357 SHOW_STR
1358 "IS-IS information\n"
1359 "IS-IS paths to Intermediate Systems\n"
1360 "Paths to all level-1 routers in the area\n")
1361{
1362 struct listnode *node;
1363 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001364
jardineb5d44e2003-12-23 08:09:43 +00001365 if (!isis->area_list || isis->area_list->count == 0)
1366 return CMD_SUCCESS;
1367
hassof390d2c2004-09-10 20:48:21 +00001368 for (node = listhead (isis->area_list); node; nextnode (node))
1369 {
1370 area = getdata (node);
jardineb5d44e2003-12-23 08:09:43 +00001371
hassof390d2c2004-09-10 20:48:21 +00001372 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1373 VTY_NEWLINE);
1374
1375 if (area->ip_circuits > 0 && area->spftree[0]
1376 && area->spftree[0]->paths->count > 0)
1377 {
1378 vty_out (vty, "IS-IS paths to level-1 routers that speak IP%s",
1379 VTY_NEWLINE);
1380 isis_print_paths (vty, area->spftree[0]->paths);
1381 }
jardineb5d44e2003-12-23 08:09:43 +00001382#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001383 if (area->ipv6_circuits > 0 && area->spftree6[0]
1384 && area->spftree6[0]->paths->count > 0)
1385 {
1386 vty_out (vty, "IS-IS paths to level-1 routers that speak IPv6%s",
1387 VTY_NEWLINE);
1388 isis_print_paths (vty, area->spftree6[0]->paths);
1389 }
jardineb5d44e2003-12-23 08:09:43 +00001390#endif /* HAVE_IPV6 */
1391 }
1392
jardineb5d44e2003-12-23 08:09:43 +00001393 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001394}
jardineb5d44e2003-12-23 08:09:43 +00001395
1396DEFUN (show_isis_topology_l2,
1397 show_isis_topology_l2_cmd,
1398 "show isis topology level-2",
1399 SHOW_STR
1400 "IS-IS information\n"
1401 "IS-IS paths to Intermediate Systems\n"
1402 "Paths to all level-2 routers in the domain\n")
1403{
1404 struct listnode *node;
1405 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001406
jardineb5d44e2003-12-23 08:09:43 +00001407 if (!isis->area_list || isis->area_list->count == 0)
1408 return CMD_SUCCESS;
1409
hassof390d2c2004-09-10 20:48:21 +00001410 for (node = listhead (isis->area_list); node; nextnode (node))
1411 {
1412 area = getdata (node);
jardineb5d44e2003-12-23 08:09:43 +00001413
hassof390d2c2004-09-10 20:48:21 +00001414 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1415 VTY_NEWLINE);
1416
1417 if (area->ip_circuits > 0 && area->spftree[1]
1418 && area->spftree[1]->paths->count > 0)
1419 {
1420 vty_out (vty, "IS-IS paths to level-2 routers that speak IP%s",
1421 VTY_NEWLINE);
1422 isis_print_paths (vty, area->spftree[1]->paths);
1423 }
jardineb5d44e2003-12-23 08:09:43 +00001424#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001425 if (area->ipv6_circuits > 0 && area->spftree6[1]
1426 && area->spftree6[1]->paths->count > 0)
1427 {
1428 vty_out (vty, "IS-IS paths to level-2 routers that speak IPv6%s",
1429 VTY_NEWLINE);
1430 isis_print_paths (vty, area->spftree6[1]->paths);
1431 }
jardineb5d44e2003-12-23 08:09:43 +00001432#endif /* HAVE_IPV6 */
1433 }
1434
jardineb5d44e2003-12-23 08:09:43 +00001435 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001436}
jardineb5d44e2003-12-23 08:09:43 +00001437
1438void
1439isis_spf_cmds_init ()
1440{
1441 install_element (VIEW_NODE, &show_isis_topology_cmd);
1442 install_element (VIEW_NODE, &show_isis_topology_l1_cmd);
1443 install_element (VIEW_NODE, &show_isis_topology_l2_cmd);
1444
1445 install_element (ENABLE_NODE, &show_isis_topology_cmd);
1446 install_element (ENABLE_NODE, &show_isis_topology_l1_cmd);
1447 install_element (ENABLE_NODE, &show_isis_topology_l2_cmd);
1448}