blob: ba7acbfb0d844d94ce149f35d74c475a14144736 [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
hasso92365882005-01-18 13:53:33 +000061#if 0
62/* performace issue ???? HT: Old or new code? */
63static void
hassof390d2c2004-09-10 20:48:21 +000064union_adjlist (struct list *target, struct list *source)
jardineb5d44e2003-12-23 08:09:43 +000065{
66 struct isis_adjacency *adj, *adj2;
67 struct listnode *node, *node2;
hassof390d2c2004-09-10 20:48:21 +000068
hasso529d65b2004-12-24 00:14:50 +000069 zlog_debug ("Union adjlist!");
paul1eb8ef22005-04-07 07:30:20 +000070 for (ALL_LIST_ELEMENTS_RO (source, node, adj))
hassof390d2c2004-09-10 20:48:21 +000071 {
hassof390d2c2004-09-10 20:48:21 +000072 /* lookup adjacency in the source list */
paul1eb8ef22005-04-07 07:30:20 +000073 for (ALL_LIST_ELEMENTS_RO (target, node2, adj2))
74 if (adj == adj2)
hassof390d2c2004-09-10 20:48:21 +000075 break;
paul1eb8ef22005-04-07 07:30:20 +000076
hassof390d2c2004-09-10 20:48:21 +000077 if (!node2)
78 listnode_add (target, adj);
jardineb5d44e2003-12-23 08:09:43 +000079 }
jardineb5d44e2003-12-23 08:09:43 +000080}
hasso92365882005-01-18 13:53:33 +000081#endif
jardineb5d44e2003-12-23 08:09:43 +000082
jardineb5d44e2003-12-23 08:09:43 +000083/* 7.2.7 */
hasso92365882005-01-18 13:53:33 +000084static void
jardineb5d44e2003-12-23 08:09:43 +000085remove_excess_adjs (struct list *adjs)
86{
paul1eb8ef22005-04-07 07:30:20 +000087 struct listnode *node, *nnode, *excess = NULL;
jardineb5d44e2003-12-23 08:09:43 +000088 struct isis_adjacency *adj, *candidate = NULL;
89 int comp;
90
paul1eb8ef22005-04-07 07:30:20 +000091 for (ALL_LIST_ELEMENTS (adjs, node, nnode, adj))
hassof390d2c2004-09-10 20:48:21 +000092 {
93 if (excess == NULL)
94 excess = node;
paul1eb8ef22005-04-07 07:30:20 +000095 candidate = listgetdata (excess);
96
hassof390d2c2004-09-10 20:48:21 +000097 if (candidate->sys_type < adj->sys_type)
98 {
99 excess = node;
100 candidate = adj;
101 continue;
102 }
103 if (candidate->sys_type > adj->sys_type)
104 continue;
105
106 comp = memcmp (candidate->sysid, adj->sysid, ISIS_SYS_ID_LEN);
107 if (comp > 0)
108 {
109 excess = node;
110 candidate = adj;
111 continue;
112 }
113 if (comp < 0)
114 continue;
115
116 if (candidate->circuit->circuit_id > adj->circuit->circuit_id)
117 {
118 excess = node;
119 candidate = adj;
120 continue;
121 }
122
123 if (candidate->circuit->circuit_id < adj->circuit->circuit_id)
124 continue;
125
126 comp = memcmp (candidate->snpa, adj->snpa, ETH_ALEN);
127 if (comp > 0)
128 {
129 excess = node;
130 candidate = adj;
131 continue;
132 }
jardineb5d44e2003-12-23 08:09:43 +0000133 }
134
jardineb5d44e2003-12-23 08:09:43 +0000135 list_delete_node (adjs, excess);
136
137 return;
138}
139
hasso92365882005-01-18 13:53:33 +0000140#ifdef EXTREME_DEBUG
141static const char *
jardineb5d44e2003-12-23 08:09:43 +0000142vtype2string (enum vertextype vtype)
143{
hassof390d2c2004-09-10 20:48:21 +0000144 switch (vtype)
145 {
146 case VTYPE_PSEUDO_IS:
147 return "pseudo_IS";
148 break;
149 case VTYPE_NONPSEUDO_IS:
150 return "IS";
151 break;
152 case VTYPE_ES:
153 return "ES";
154 break;
155 case VTYPE_IPREACH_INTERNAL:
156 return "IP internal";
157 break;
158 case VTYPE_IPREACH_EXTERNAL:
159 return "IP external";
160 break;
jardineb5d44e2003-12-23 08:09:43 +0000161#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000162 case VTYPE_IP6REACH_INTERNAL:
163 return "IP6 internal";
164 break;
165 case VTYPE_IP6REACH_EXTERNAL:
166 return "IP6 external";
167 break;
168#endif /* HAVE_IPV6 */
169 default:
170 return "UNKNOWN";
171 }
172 return NULL; /* Not reached */
jardineb5d44e2003-12-23 08:09:43 +0000173}
174
hasso92365882005-01-18 13:53:33 +0000175static const char *
hassof390d2c2004-09-10 20:48:21 +0000176vid2string (struct isis_vertex *vertex, u_char * buff)
jardineb5d44e2003-12-23 08:09:43 +0000177{
hassof390d2c2004-09-10 20:48:21 +0000178 switch (vertex->type)
179 {
180 case VTYPE_PSEUDO_IS:
181 return rawlspid_print (vertex->N.id);
182 break;
183 case VTYPE_NONPSEUDO_IS:
184 case VTYPE_ES:
185 return sysid_print (vertex->N.id);
186 break;
187 case VTYPE_IPREACH_INTERNAL:
188 case VTYPE_IPREACH_EXTERNAL:
jardineb5d44e2003-12-23 08:09:43 +0000189#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000190 case VTYPE_IP6REACH_INTERNAL:
191 case VTYPE_IP6REACH_EXTERNAL:
192#endif /* HAVE_IPV6 */
hassof7c43dc2004-09-26 16:24:14 +0000193 prefix2str ((struct prefix *) &vertex->N.prefix, (char *) buff, BUFSIZ);
hassof390d2c2004-09-10 20:48:21 +0000194 break;
195 default:
196 return "UNKNOWN";
197 }
198
hassof7c43dc2004-09-26 16:24:14 +0000199 return (char *) buff;
jardineb5d44e2003-12-23 08:09:43 +0000200}
hasso92365882005-01-18 13:53:33 +0000201#endif /* EXTREME_DEBUG */
jardineb5d44e2003-12-23 08:09:43 +0000202
hasso92365882005-01-18 13:53:33 +0000203static struct isis_spftree *
jardineb5d44e2003-12-23 08:09:43 +0000204isis_spftree_new ()
205{
206 struct isis_spftree *tree;
207
208 tree = XMALLOC (MTYPE_ISIS_SPFTREE, sizeof (struct isis_spftree));
hassof390d2c2004-09-10 20:48:21 +0000209 if (tree == NULL)
210 {
211 zlog_err ("ISIS-Spf: isis_spftree_new Out of memory!");
212 return NULL;
213 }
jardineb5d44e2003-12-23 08:09:43 +0000214 memset (tree, 0, sizeof (struct isis_spftree));
215
216 tree->tents = list_new ();
hassof390d2c2004-09-10 20:48:21 +0000217 tree->paths = list_new ();
jardineb5d44e2003-12-23 08:09:43 +0000218 return tree;
219}
220
hasso92365882005-01-18 13:53:33 +0000221static void
jardineb5d44e2003-12-23 08:09:43 +0000222isis_vertex_del (struct isis_vertex *vertex)
223{
jardineb5d44e2003-12-23 08:09:43 +0000224 list_delete (vertex->Adj_N);
225
226 XFREE (MTYPE_ISIS_VERTEX, vertex);
hassof390d2c2004-09-10 20:48:21 +0000227
jardineb5d44e2003-12-23 08:09:43 +0000228 return;
229}
230
hasso92365882005-01-18 13:53:33 +0000231#if 0 /* HT: Not used yet. */
232static void
jardineb5d44e2003-12-23 08:09:43 +0000233isis_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}
hasso92365882005-01-18 13:53:33 +0000245#endif
jardineb5d44e2003-12-23 08:09:43 +0000246
hassof390d2c2004-09-10 20:48:21 +0000247void
jardineb5d44e2003-12-23 08:09:43 +0000248spftree_area_init (struct isis_area *area)
249{
hassof390d2c2004-09-10 20:48:21 +0000250 if ((area->is_type & IS_LEVEL_1) && area->spftree[0] == NULL)
251 {
252 area->spftree[0] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000253#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000254 area->spftree6[0] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000255#endif
256
hassof390d2c2004-09-10 20:48:21 +0000257 /* thread_add_timer (master, isis_run_spf_l1, area,
258 isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */
259 }
260
261 if ((area->is_type & IS_LEVEL_2) && area->spftree[1] == NULL)
262 {
263 area->spftree[1] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000264#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000265 area->spftree6[1] = isis_spftree_new ();
jardineb5d44e2003-12-23 08:09:43 +0000266#endif
hassof390d2c2004-09-10 20:48:21 +0000267 /* thread_add_timer (master, isis_run_spf_l2, area,
268 isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */
269 }
jardineb5d44e2003-12-23 08:09:43 +0000270
271 return;
272}
273
hasso92365882005-01-18 13:53:33 +0000274static struct isis_vertex *
jardineb5d44e2003-12-23 08:09:43 +0000275isis_vertex_new (void *id, enum vertextype vtype)
276{
277 struct isis_vertex *vertex;
278
279 vertex = XMALLOC (MTYPE_ISIS_VERTEX, sizeof (struct isis_vertex));
hassof390d2c2004-09-10 20:48:21 +0000280 if (vertex == NULL)
281 {
282 zlog_err ("isis_vertex_new Out of memory!");
283 return NULL;
284 }
285
jardineb5d44e2003-12-23 08:09:43 +0000286 memset (vertex, 0, sizeof (struct isis_vertex));
287 vertex->type = vtype;
hassof390d2c2004-09-10 20:48:21 +0000288 switch (vtype)
289 {
290 case VTYPE_ES:
291 case VTYPE_NONPSEUDO_IS:
292 memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN);
293 break;
294 case VTYPE_PSEUDO_IS:
295 memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN + 1);
296 break;
297 case VTYPE_IPREACH_INTERNAL:
298 case VTYPE_IPREACH_EXTERNAL:
jardineb5d44e2003-12-23 08:09:43 +0000299#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000300 case VTYPE_IP6REACH_INTERNAL:
301 case VTYPE_IP6REACH_EXTERNAL:
302#endif /* HAVE_IPV6 */
303 memcpy (&vertex->N.prefix, (struct prefix *) id,
304 sizeof (struct prefix));
305 break;
306 default:
307 zlog_err ("WTF!");
308 }
jardineb5d44e2003-12-23 08:09:43 +0000309
310 vertex->Adj_N = list_new ();
hassof390d2c2004-09-10 20:48:21 +0000311
jardineb5d44e2003-12-23 08:09:43 +0000312 return vertex;
313}
314
315/*
316 * Add this IS to the root of SPT
317 */
hasso92365882005-01-18 13:53:33 +0000318static void
jardineb5d44e2003-12-23 08:09:43 +0000319isis_spf_add_self (struct isis_spftree *spftree, struct isis_area *area,
hassof390d2c2004-09-10 20:48:21 +0000320 int level)
jardineb5d44e2003-12-23 08:09:43 +0000321{
322 struct isis_vertex *vertex;
323 struct isis_lsp *lsp;
324 u_char lspid[ISIS_SYS_ID_LEN + 2];
325#ifdef EXTREME_DEBUG
326 u_char buff[BUFSIZ];
327#endif /* EXTREME_DEBUG */
328 memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN);
hassof390d2c2004-09-10 20:48:21 +0000329 LSP_PSEUDO_ID (lspid) = 0;
330 LSP_FRAGMENT (lspid) = 0;
331
jardineb5d44e2003-12-23 08:09:43 +0000332 lsp = lsp_search (lspid, area->lspdb[level - 1]);
hassof390d2c2004-09-10 20:48:21 +0000333
jardineb5d44e2003-12-23 08:09:43 +0000334 if (lsp == NULL)
335 zlog_warn ("ISIS-Spf: could not find own l%d LSP!", level);
hassof390d2c2004-09-10 20:48:21 +0000336
jardineb5d44e2003-12-23 08:09:43 +0000337 vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_IS);
338 vertex->lsp = lsp;
339
340 listnode_add (spftree->paths, vertex);
341
342#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000343 zlog_debug ("ISIS-Spf: added this IS %s %s depth %d dist %d to PATHS",
344 vtype2string (vertex->type), vid2string (vertex, buff),
345 vertex->depth, vertex->d_N);
jardineb5d44e2003-12-23 08:09:43 +0000346#endif /* EXTREME_DEBUG */
347
348 return;
349}
350
hasso92365882005-01-18 13:53:33 +0000351static struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000352isis_find_vertex (struct list *list, void *id, enum vertextype vtype)
jardineb5d44e2003-12-23 08:09:43 +0000353{
354 struct listnode *node;
355 struct isis_vertex *vertex;
356 struct prefix *p1, *p2;
357
paul1eb8ef22005-04-07 07:30:20 +0000358 for (ALL_LIST_ELEMENTS_RO (list, node, vertex))
hassof390d2c2004-09-10 20:48:21 +0000359 {
hassof390d2c2004-09-10 20:48:21 +0000360 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 */
hasso92365882005-01-18 13:53:33 +0000395static struct 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 }
paul1eb8ef22005-04-07 07:30:20 +0000423
424 /* XXX: This cant use the standard ALL_LIST_ELEMENT macro */
425 for (node = listhead (spftree->tents); node; node = listnextnode (node))
hassof390d2c2004-09-10 20:48:21 +0000426 {
paul1eb8ef22005-04-07 07:30:20 +0000427 v = listgetdata (node);
hassof390d2c2004-09-10 20:48:21 +0000428 if (v->d_N > vertex->d_N)
429 {
430 list_add_node_prev (spftree->tents, node, vertex);
431 break;
432 }
433 else if (v->d_N == vertex->d_N)
434 {
435 /* Tie break, add according to type */
436 while (v && v->d_N == vertex->d_N && v->type > vertex->type)
437 {
438 if (v->type > vertex->type)
439 {
440 break;
441 }
paul1eb8ef22005-04-07 07:30:20 +0000442 /* XXX: this seems dubious, node is the loop iterator */
443 node = listnextnode (node);
444 (node) ? (v = listgetdata (node)) : (v = NULL);
hassof390d2c2004-09-10 20:48:21 +0000445 }
446 list_add_node_prev (spftree->tents, node, vertex);
447 break;
448 }
449 else if (node->next == NULL)
450 {
451 list_add_node_next (spftree->tents, node, vertex);
452 break;
453 }
454 }
jardineb5d44e2003-12-23 08:09:43 +0000455 return vertex;
456}
457
hasso92365882005-01-18 13:53:33 +0000458static struct isis_vertex *
hassof390d2c2004-09-10 20:48:21 +0000459isis_spf_add_local (struct isis_spftree *spftree, enum vertextype vtype,
460 void *id, struct isis_adjacency *adj, u_int16_t cost,
461 int family)
jardineb5d44e2003-12-23 08:09:43 +0000462{
463 struct isis_vertex *vertex;
jardineb5d44e2003-12-23 08:09:43 +0000464
hassof390d2c2004-09-10 20:48:21 +0000465 vertex = isis_find_vertex (spftree->tents, id, vtype);
466
467 if (vertex)
468 {
469 /* C.2.5 c) */
470 if (vertex->d_N == cost)
471 {
472 if (adj)
473 listnode_add (vertex->Adj_N, adj);
474 /* d) */
475 if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
476 remove_excess_adjs (vertex->Adj_N);
477 }
478 /* f) */
479 else if (vertex->d_N > cost)
480 {
481 listnode_delete (spftree->tents, vertex);
482 goto add2tent;
483 }
484 /* e) do nothing */
485 return vertex;
486 }
487
488add2tent:
jardineb5d44e2003-12-23 08:09:43 +0000489 return isis_spf_add2tent (spftree, vtype, id, adj, cost, 1, family);
490}
491
hasso92365882005-01-18 13:53:33 +0000492static void
hassof390d2c2004-09-10 20:48:21 +0000493process_N (struct isis_spftree *spftree, enum vertextype vtype, void *id,
494 u_int16_t dist, u_int16_t depth, struct isis_adjacency *adj,
495 int family)
jardineb5d44e2003-12-23 08:09:43 +0000496{
497 struct isis_vertex *vertex;
498#ifdef EXTREME_DEBUG
499 u_char buff[255];
500#endif
501
502 /* C.2.6 b) */
503 if (dist > MAX_PATH_METRIC)
504 return;
505 /* c) */
506 vertex = isis_find_vertex (spftree->paths, id, vtype);
hassof390d2c2004-09-10 20:48:21 +0000507 if (vertex)
508 {
jardineb5d44e2003-12-23 08:09:43 +0000509#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000510 zlog_debug ("ISIS-Spf: process_N %s %s dist %d already found from PATH",
511 vtype2string (vtype), vid2string (vertex, buff), dist);
jardineb5d44e2003-12-23 08:09:43 +0000512#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000513 assert (dist >= vertex->d_N);
514 return;
515 }
jardineb5d44e2003-12-23 08:09:43 +0000516
517 vertex = isis_find_vertex (spftree->tents, id, vtype);
hassof390d2c2004-09-10 20:48:21 +0000518 /* d) */
519 if (vertex)
520 {
521 /* 1) */
jardineb5d44e2003-12-23 08:09:43 +0000522#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000523 zlog_debug ("ISIS-Spf: process_N %s %s dist %d",
524 vtype2string (vtype), vid2string (vertex, buff), dist);
jardineb5d44e2003-12-23 08:09:43 +0000525#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000526 if (vertex->d_N == dist)
527 {
528 if (adj)
529 listnode_add (vertex->Adj_N, adj);
530 /* 2) */
531 if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
532 remove_excess_adjs (vertex->Adj_N);
533 /* 3) */
534 return;
535 }
536 else if (vertex->d_N < dist)
537 {
538 return;
539 /* 4) */
540 }
541 else
542 {
543 listnode_delete (spftree->tents, vertex);
544 }
jardineb5d44e2003-12-23 08:09:43 +0000545 }
hassof390d2c2004-09-10 20:48:21 +0000546
jardineb5d44e2003-12-23 08:09:43 +0000547 isis_spf_add2tent (spftree, vtype, id, adj, dist, depth, family);
548 return;
549}
550
551/*
552 * C.2.6 Step 1
553 */
hasso92365882005-01-18 13:53:33 +0000554static int
hassof390d2c2004-09-10 20:48:21 +0000555isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp,
556 uint16_t cost, uint16_t depth, int family)
jardineb5d44e2003-12-23 08:09:43 +0000557{
558 struct listnode *node, *fragnode = NULL;
559 u_int16_t dist;
560 struct is_neigh *is_neigh;
561 struct ipv4_reachability *ipreach;
562 enum vertextype vtype;
563 struct prefix prefix;
564#ifdef HAVE_IPV6
565 struct ipv6_reachability *ip6reach;
566#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000567
jardineb5d44e2003-12-23 08:09:43 +0000568
569 if (!lsp->adj)
570 return ISIS_WARNING;
hassof390d2c2004-09-10 20:48:21 +0000571 if (lsp->tlv_data.nlpids == NULL || !speaks (lsp->tlv_data.nlpids, family))
jardineb5d44e2003-12-23 08:09:43 +0000572 return ISIS_OK;
573
hassof390d2c2004-09-10 20:48:21 +0000574lspfragloop:
575 if (lsp->lsp_header->seq_num == 0)
576 {
577 zlog_warn ("isis_spf_process_lsp(): lsp with 0 seq_num"
578 " - do not process");
579 return ISIS_WARNING;
580 }
jardineb5d44e2003-12-23 08:09:43 +0000581
hassof390d2c2004-09-10 20:48:21 +0000582 if (!ISIS_MASK_LSP_OL_BIT (lsp->lsp_header->lsp_bits))
583 {
584 if (lsp->tlv_data.is_neighs)
585 {
paul1eb8ef22005-04-07 07:30:20 +0000586 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh))
hassof390d2c2004-09-10 20:48:21 +0000587 {
hassof390d2c2004-09-10 20:48:21 +0000588 /* C.2.6 a) */
589 /* Two way connectivity */
590 if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
591 continue;
592 dist = cost + is_neigh->metrics.metric_default;
593 vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
594 : VTYPE_NONPSEUDO_IS;
595 process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist,
596 depth + 1, lsp->adj, family);
597 }
598 }
599 if (family == AF_INET && lsp->tlv_data.ipv4_int_reachs)
600 {
601 prefix.family = AF_INET;
paul1eb8ef22005-04-07 07:30:20 +0000602 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_int_reachs,
603 node, ipreach))
hassof390d2c2004-09-10 20:48:21 +0000604 {
hassof390d2c2004-09-10 20:48:21 +0000605 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;
paul1eb8ef22005-04-07 07:30:20 +0000617 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_ext_reachs,
618 node, ipreach))
hassof390d2c2004-09-10 20:48:21 +0000619 {
hassof390d2c2004-09-10 20:48:21 +0000620 dist = cost + ipreach->metrics.metric_default;
621 vtype = VTYPE_IPREACH_EXTERNAL;
622 prefix.u.prefix4 = ipreach->prefix;
623 prefix.prefixlen = ip_masklen (ipreach->mask);
624 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
625 lsp->adj, family);
626 }
627 }
jardineb5d44e2003-12-23 08:09:43 +0000628#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000629 if (family == AF_INET6 && lsp->tlv_data.ipv6_reachs)
630 {
631 prefix.family = AF_INET6;
paul1eb8ef22005-04-07 07:30:20 +0000632 for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv6_reachs,
633 node, ip6reach))
hassof390d2c2004-09-10 20:48:21 +0000634 {
hassof390d2c2004-09-10 20:48:21 +0000635 dist = cost + ip6reach->metric;
636 vtype = (ip6reach->control_info & CTRL_INFO_DISTRIBUTION) ?
637 VTYPE_IP6REACH_EXTERNAL : VTYPE_IP6REACH_INTERNAL;
638 prefix.prefixlen = ip6reach->prefix_len;
639 memcpy (&prefix.u.prefix6.s6_addr, ip6reach->prefix,
640 PSIZE (ip6reach->prefix_len));
641 process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
642 lsp->adj, family);
643 }
644 }
jardineb5d44e2003-12-23 08:09:43 +0000645#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000646 }
647
jardineb5d44e2003-12-23 08:09:43 +0000648 if (fragnode == NULL)
649 fragnode = listhead (lsp->lspu.frags);
hassof390d2c2004-09-10 20:48:21 +0000650 else
paul1eb8ef22005-04-07 07:30:20 +0000651 fragnode = listnextnode (fragnode);
jardineb5d44e2003-12-23 08:09:43 +0000652
hassof390d2c2004-09-10 20:48:21 +0000653 if (fragnode)
654 {
paul1eb8ef22005-04-07 07:30:20 +0000655 lsp = listgetdata (fragnode);
hassof390d2c2004-09-10 20:48:21 +0000656 goto lspfragloop;
657 }
658
jardineb5d44e2003-12-23 08:09:43 +0000659 return ISIS_OK;
660}
661
hasso92365882005-01-18 13:53:33 +0000662static int
hassof390d2c2004-09-10 20:48:21 +0000663isis_spf_process_pseudo_lsp (struct isis_spftree *spftree,
664 struct isis_lsp *lsp, uint16_t cost,
665 uint16_t depth, int family)
jardineb5d44e2003-12-23 08:09:43 +0000666{
paul1eb8ef22005-04-07 07:30:20 +0000667 struct listnode *node, *nnode, *fragnode = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000668 struct is_neigh *is_neigh;
669 enum vertextype vtype;
hassof390d2c2004-09-10 20:48:21 +0000670
671pseudofragloop:
672
673 if (lsp->lsp_header->seq_num == 0)
674 {
675 zlog_warn ("isis_spf_process_pseudo_lsp(): lsp with 0 seq_num"
676 " - do not process");
677 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +0000678 }
hassof390d2c2004-09-10 20:48:21 +0000679
paul1eb8ef22005-04-07 07:30:20 +0000680 for (ALL_LIST_ELEMENTS (lsp->tlv_data.is_neighs, node, nnode, is_neigh))
hassof390d2c2004-09-10 20:48:21 +0000681 {
hassof390d2c2004-09-10 20:48:21 +0000682 vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
683 : VTYPE_NONPSEUDO_IS;
684 /* Two way connectivity */
685 if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
686 continue;
687 if (isis_find_vertex
688 (spftree->tents, (void *) is_neigh->neigh_id, vtype) == NULL
689 && isis_find_vertex (spftree->paths, (void *) is_neigh->neigh_id,
690 vtype) == NULL)
691 {
692 /* C.2.5 i) */
693 isis_spf_add2tent (spftree, vtype, is_neigh->neigh_id, lsp->adj,
694 cost, depth, family);
695 }
696 }
697
jardineb5d44e2003-12-23 08:09:43 +0000698 if (fragnode == NULL)
699 fragnode = listhead (lsp->lspu.frags);
hassof390d2c2004-09-10 20:48:21 +0000700 else
paul1eb8ef22005-04-07 07:30:20 +0000701 fragnode = listnextnode (fragnode);
jardineb5d44e2003-12-23 08:09:43 +0000702
hassof390d2c2004-09-10 20:48:21 +0000703 if (fragnode)
704 {
paul1eb8ef22005-04-07 07:30:20 +0000705 lsp = listgetdata (fragnode);
hassof390d2c2004-09-10 20:48:21 +0000706 goto pseudofragloop;
707 }
jardineb5d44e2003-12-23 08:09:43 +0000708
jardineb5d44e2003-12-23 08:09:43 +0000709 return ISIS_OK;
710}
hassof390d2c2004-09-10 20:48:21 +0000711
hasso92365882005-01-18 13:53:33 +0000712static int
hassof390d2c2004-09-10 20:48:21 +0000713isis_spf_preload_tent (struct isis_spftree *spftree,
714 struct isis_area *area, int level, int family)
jardineb5d44e2003-12-23 08:09:43 +0000715{
716 struct isis_vertex *vertex;
717 struct isis_circuit *circuit;
paul1eb8ef22005-04-07 07:30:20 +0000718 struct listnode *cnode, *cnnode;
719 struct listnode *anode;
720 struct listnode *ipnode, *ipnnode;
jardineb5d44e2003-12-23 08:09:43 +0000721 struct isis_adjacency *adj;
722 struct isis_lsp *lsp;
723 struct list *adj_list;
724 struct list *adjdb;
725 struct prefix_ipv4 *ipv4;
726 struct prefix prefix;
727 int retval = ISIS_OK;
728 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
729#ifdef HAVE_IPV6
730 struct prefix_ipv6 *ipv6;
731#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000732
paul1eb8ef22005-04-07 07:30:20 +0000733 for (ALL_LIST_ELEMENTS (area->circuit_list, cnode, cnnode, circuit))
hassof390d2c2004-09-10 20:48:21 +0000734 {
hassof390d2c2004-09-10 20:48:21 +0000735 if (circuit->state != C_STATE_UP)
jardineb5d44e2003-12-23 08:09:43 +0000736 continue;
hassof390d2c2004-09-10 20:48:21 +0000737 if (!(circuit->circuit_is_type & level))
738 continue;
739 if (family == AF_INET && !circuit->ip_router)
740 continue;
741#ifdef HAVE_IPV6
742 if (family == AF_INET6 && !circuit->ipv6_router)
743 continue;
744#endif /* HAVE_IPV6 */
745 /*
746 * Add IP(v6) addresses of this circuit
jardineb5d44e2003-12-23 08:09:43 +0000747 */
hassof390d2c2004-09-10 20:48:21 +0000748 if (family == AF_INET)
749 {
750 prefix.family = AF_INET;
paul1eb8ef22005-04-07 07:30:20 +0000751 for (ALL_LIST_ELEMENTS (circuit->ip_addrs, ipnode, ipnnode, ipv4))
hassof390d2c2004-09-10 20:48:21 +0000752 {
hassof390d2c2004-09-10 20:48:21 +0000753 prefix.u.prefix4 = ipv4->prefix;
754 prefix.prefixlen = ipv4->prefixlen;
755 isis_spf_add_local (spftree, VTYPE_IPREACH_INTERNAL, &prefix,
756 NULL, 0, family);
757 }
758 }
759#ifdef HAVE_IPV6
760 if (family == AF_INET6)
761 {
762 prefix.family = AF_INET6;
paul1eb8ef22005-04-07 07:30:20 +0000763 for (ALL_LIST_ELEMENTS (circuit->ipv6_non_link,
764 ipnode, ipnnode, ipv6))
hassof390d2c2004-09-10 20:48:21 +0000765 {
hassof390d2c2004-09-10 20:48:21 +0000766 prefix.prefixlen = ipv6->prefixlen;
767 prefix.u.prefix6 = ipv6->prefix;
768 isis_spf_add_local (spftree, VTYPE_IP6REACH_INTERNAL,
769 &prefix, NULL, 0, family);
770 }
771 }
772#endif /* HAVE_IPV6 */
773 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
774 {
775 /*
776 * Add the adjacencies
777 */
778 adj_list = list_new ();
779 adjdb = circuit->u.bc.adjdb[level - 1];
780 isis_adj_build_up_list (adjdb, adj_list);
781 if (listcount (adj_list) == 0)
782 {
783 list_delete (adj_list);
hassoc89c05d2005-09-04 21:36:36 +0000784 if (isis->debugs & DEBUG_SPF_EVENTS)
785 zlog_debug ("ISIS-Spf: no L%d adjacencies on circuit %s",
786 level, circuit->interface->name);
hassof390d2c2004-09-10 20:48:21 +0000787 continue;
788 }
789 anode = listhead (adj_list);
790 while (anode)
791 {
paul1eb8ef22005-04-07 07:30:20 +0000792 adj = listgetdata (anode);
hassof390d2c2004-09-10 20:48:21 +0000793 if (!speaks (&adj->nlpids, family))
794 {
paul1eb8ef22005-04-07 07:30:20 +0000795 anode = listnextnode (anode);
hassof390d2c2004-09-10 20:48:21 +0000796 continue;
797 }
798 switch (adj->sys_type)
799 {
800 case ISIS_SYSTYPE_ES:
801 isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
802 circuit->metrics[level -
803 1].metric_default,
804 family);
805 break;
806 case ISIS_SYSTYPE_IS:
807 case ISIS_SYSTYPE_L1_IS:
808 case ISIS_SYSTYPE_L2_IS:
809 vertex =
810 isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS,
811 adj->sysid, adj,
812 circuit->metrics[level -
813 1].metric_default,
814 family);
815 memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN);
816 LSP_PSEUDO_ID (lsp_id) = 0;
817 LSP_FRAGMENT (lsp_id) = 0;
818 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
819 if (!lsp)
820 zlog_warn ("No lsp found for IS adjacency");
821 /* else {
822 isis_spf_process_lsp (spftree, lsp, vertex->d_N, 1, family);
823 } */
824 break;
825 case ISIS_SYSTYPE_UNKNOWN:
826 default:
827 zlog_warn ("isis_spf_preload_tent unknow adj type");
828 }
paul1eb8ef22005-04-07 07:30:20 +0000829 anode = listnextnode (anode);
hassof390d2c2004-09-10 20:48:21 +0000830 }
831 list_delete (adj_list);
832 /*
833 * Add the pseudonode
834 */
835 if (level == 1)
836 memcpy (lsp_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
837 else
838 memcpy (lsp_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
839 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
840 adj = isis_adj_lookup (lsp_id, adjdb);
841 /* if no adj, we are the dis or error */
842 if (!adj && !circuit->u.bc.is_dr[level - 1])
843 {
844 zlog_warn ("ISIS-Spf: No adjacency found for DR");
845 }
846 if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0)
847 {
848 zlog_warn ("ISIS-Spf: No lsp found for DR");
849 }
850 else
851 {
852 isis_spf_process_pseudo_lsp
853 (spftree, lsp, circuit->metrics[level - 1].metric_default, 0,
854 family);
855
856 }
857 }
858 else if (circuit->circ_type == CIRCUIT_T_P2P)
859 {
860 adj = circuit->u.p2p.neighbor;
861 if (!adj)
862 continue;
863 switch (adj->sys_type)
864 {
865 case ISIS_SYSTYPE_ES:
866 isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
867 circuit->metrics[level - 1].metric_default,
868 family);
869 break;
870 case ISIS_SYSTYPE_IS:
871 case ISIS_SYSTYPE_L1_IS:
872 case ISIS_SYSTYPE_L2_IS:
873 if (speaks (&adj->nlpids, family))
874 isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS, adj->sysid,
875 adj,
876 circuit->metrics[level -
877 1].metric_default,
878 family);
879 break;
880 case ISIS_SYSTYPE_UNKNOWN:
881 default:
882 zlog_warn ("isis_spf_preload_tent unknow adj type");
883 break;
884 }
885 }
jardineb5d44e2003-12-23 08:09:43 +0000886 else
hassof390d2c2004-09-10 20:48:21 +0000887 {
888 zlog_warn ("isis_spf_preload_tent unsupported media");
889 retval = ISIS_WARNING;
890 }
891
jardineb5d44e2003-12-23 08:09:43 +0000892 }
jardineb5d44e2003-12-23 08:09:43 +0000893
894 return retval;
895}
896
897/*
898 * The parent(s) for vertex is set when added to TENT list
899 * now we just put the child pointer(s) in place
900 */
hasso92365882005-01-18 13:53:33 +0000901static void
jardineb5d44e2003-12-23 08:09:43 +0000902add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex,
hassof390d2c2004-09-10 20:48:21 +0000903 struct isis_area *area)
jardineb5d44e2003-12-23 08:09:43 +0000904{
jardineb5d44e2003-12-23 08:09:43 +0000905#ifdef EXTREME_DEBUG
906 u_char buff[BUFSIZ];
907#endif /* EXTREME_DEBUG */
908 listnode_add (spftree->paths, vertex);
909
hassof390d2c2004-09-10 20:48:21 +0000910#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000911 zlog_debug ("ISIS-Spf: added %s %s depth %d dist %d to PATHS",
912 vtype2string (vertex->type), vid2string (vertex, buff),
913 vertex->depth, vertex->d_N);
hassof390d2c2004-09-10 20:48:21 +0000914#endif /* EXTREME_DEBUG */
915 if (vertex->type > VTYPE_ES)
916 {
917 if (listcount (vertex->Adj_N) > 0)
918 isis_route_create ((struct prefix *) &vertex->N.prefix,
919 vertex->d_N, vertex->depth, vertex->Adj_N, area);
920 else if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000921 zlog_debug ("ISIS-Spf: no adjacencies do not install route");
hassof390d2c2004-09-10 20:48:21 +0000922 }
923
jardineb5d44e2003-12-23 08:09:43 +0000924 return;
925}
926
hasso92365882005-01-18 13:53:33 +0000927static void
jardineb5d44e2003-12-23 08:09:43 +0000928init_spt (struct isis_spftree *spftree)
929{
hassof7c43dc2004-09-26 16:24:14 +0000930 spftree->tents->del = spftree->paths->del = (void (*)(void *)) isis_vertex_del;
jardineb5d44e2003-12-23 08:09:43 +0000931 list_delete_all_node (spftree->tents);
932 list_delete_all_node (spftree->paths);
933 spftree->tents->del = spftree->paths->del = NULL;
hassof390d2c2004-09-10 20:48:21 +0000934
jardineb5d44e2003-12-23 08:09:43 +0000935 return;
936}
937
hasso92365882005-01-18 13:53:33 +0000938static int
jardineb5d44e2003-12-23 08:09:43 +0000939isis_run_spf (struct isis_area *area, int level, int family)
940{
941 int retval = ISIS_OK;
942 struct listnode *node;
943 struct isis_vertex *vertex;
hassof390d2c2004-09-10 20:48:21 +0000944 struct isis_spftree *spftree = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000945 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
946 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +0000947
jardineb5d44e2003-12-23 08:09:43 +0000948 if (family == AF_INET)
949 spftree = area->spftree[level - 1];
950#ifdef HAVE_IPV6
951 else if (family == AF_INET6)
952 spftree = area->spftree6[level - 1];
953#endif
hassof390d2c2004-09-10 20:48:21 +0000954
jardineb5d44e2003-12-23 08:09:43 +0000955 assert (spftree);
956
957 /*
958 * C.2.5 Step 0
959 */
960 init_spt (spftree);
961 /* a) */
962 isis_spf_add_self (spftree, area, level);
963 /* b) */
964 retval = isis_spf_preload_tent (spftree, area, level, family);
hassof390d2c2004-09-10 20:48:21 +0000965
jardineb5d44e2003-12-23 08:09:43 +0000966 /*
967 * C.2.7 Step 2
968 */
hassof390d2c2004-09-10 20:48:21 +0000969 if (listcount (spftree->tents) == 0)
970 {
971 zlog_warn ("ISIS-Spf: TENT is empty");
972 spftree->lastrun = time (NULL);
973 return retval;
jardineb5d44e2003-12-23 08:09:43 +0000974 }
hassof390d2c2004-09-10 20:48:21 +0000975
976 while (listcount (spftree->tents) > 0)
977 {
978 node = listhead (spftree->tents);
paul1eb8ef22005-04-07 07:30:20 +0000979 vertex = listgetdata (node);
hassof390d2c2004-09-10 20:48:21 +0000980 /* Remove from tent list */
981 list_delete_node (spftree->tents, node);
982 if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type))
983 continue;
984 add_to_paths (spftree, vertex, area);
985 if (vertex->type == VTYPE_PSEUDO_IS ||
986 vertex->type == VTYPE_NONPSEUDO_IS)
987 {
988 memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
989 LSP_FRAGMENT (lsp_id) = 0;
990 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
991 if (lsp)
992 {
993 if (LSP_PSEUDO_ID (lsp_id))
994 {
995 isis_spf_process_pseudo_lsp (spftree, lsp, vertex->d_N,
996 vertex->depth, family);
997
998 }
999 else
1000 {
1001 isis_spf_process_lsp (spftree, lsp, vertex->d_N,
1002 vertex->depth, family);
1003 }
1004 }
1005 else
1006 {
1007 zlog_warn ("ISIS-Spf: No LSP found for %s",
1008 rawlspid_print (lsp_id));
1009 }
1010 }
1011 }
1012
jardineb5d44e2003-12-23 08:09:43 +00001013 thread_add_event (master, isis_route_validate, area, 0);
1014 spftree->lastrun = time (NULL);
1015 spftree->pending = 0;
hassof390d2c2004-09-10 20:48:21 +00001016
jardineb5d44e2003-12-23 08:09:43 +00001017 return retval;
1018}
1019
1020int
1021isis_run_spf_l1 (struct thread *thread)
1022{
1023 struct isis_area *area;
1024 int retval = ISIS_OK;
1025
hassof390d2c2004-09-10 20:48:21 +00001026 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001027 assert (area);
1028
hasso12a5cae2004-09-19 19:39:26 +00001029 area->spftree[0]->t_spf = NULL;
1030
hassof390d2c2004-09-10 20:48:21 +00001031 if (!(area->is_type & IS_LEVEL_1))
1032 {
1033 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001034 zlog_warn ("ISIS-SPF (%s) area does not share level",
1035 area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001036 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001037 }
jardineb5d44e2003-12-23 08:09:43 +00001038
hassof390d2c2004-09-10 20:48:21 +00001039 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001040 zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001041
jardineb5d44e2003-12-23 08:09:43 +00001042 if (area->ip_circuits)
1043 retval = isis_run_spf (area, 1, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001044
1045 THREAD_TIMER_ON (master, area->spftree[0]->t_spf, isis_run_spf_l1, area,
1046 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1047
jardineb5d44e2003-12-23 08:09:43 +00001048 return retval;
1049}
1050
1051int
1052isis_run_spf_l2 (struct thread *thread)
1053{
1054 struct isis_area *area;
1055 int retval = ISIS_OK;
1056
hassof390d2c2004-09-10 20:48:21 +00001057 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001058 assert (area);
hassof390d2c2004-09-10 20:48:21 +00001059
hasso12a5cae2004-09-19 19:39:26 +00001060 area->spftree[1]->t_spf = NULL;
1061
hassof390d2c2004-09-10 20:48:21 +00001062 if (!(area->is_type & IS_LEVEL_2))
1063 {
1064 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001065 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001066 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001067 }
hassof390d2c2004-09-10 20:48:21 +00001068
1069 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001070 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag);
jardineb5d44e2003-12-23 08:09:43 +00001071
1072 if (area->ip_circuits)
1073 retval = isis_run_spf (area, 2, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001074
1075 THREAD_TIMER_ON (master, area->spftree[1]->t_spf, isis_run_spf_l2, area,
1076 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
jardineb5d44e2003-12-23 08:09:43 +00001077
1078 return retval;
1079}
1080
hassof390d2c2004-09-10 20:48:21 +00001081int
jardineb5d44e2003-12-23 08:09:43 +00001082isis_spf_schedule (struct isis_area *area, int level)
1083{
1084 int retval = ISIS_OK;
1085 struct isis_spftree *spftree = area->spftree[level - 1];
1086 time_t diff, now = time (NULL);
1087
1088 if (spftree->pending)
1089 return retval;
1090
hassof390d2c2004-09-10 20:48:21 +00001091 diff = now - spftree->lastrun;
jardineb5d44e2003-12-23 08:09:43 +00001092
1093 /* FIXME: let's wait a minute before doing the SPF */
hassof390d2c2004-09-10 20:48:21 +00001094 if (now - isis->uptime < 60 || isis->uptime == 0)
1095 {
1096 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001097 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area, 60);
hassof390d2c2004-09-10 20:48:21 +00001098 else
hasso12a5cae2004-09-19 19:39:26 +00001099 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area, 60);
jardineb5d44e2003-12-23 08:09:43 +00001100
hassof390d2c2004-09-10 20:48:21 +00001101 spftree->pending = 1;
1102 return retval;
1103 }
hasso12a5cae2004-09-19 19:39:26 +00001104
1105 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001106
hassof390d2c2004-09-10 20:48:21 +00001107 if (diff < MINIMUM_SPF_INTERVAL)
1108 {
1109 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001110 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
1111 MINIMUM_SPF_INTERVAL - diff);
hassof390d2c2004-09-10 20:48:21 +00001112 else
hasso12a5cae2004-09-19 19:39:26 +00001113 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
1114 MINIMUM_SPF_INTERVAL - diff);
jardineb5d44e2003-12-23 08:09:43 +00001115
hassof390d2c2004-09-10 20:48:21 +00001116 spftree->pending = 1;
1117 }
1118 else
1119 {
1120 spftree->pending = 0;
1121 retval = isis_run_spf (area, level, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001122 if (level == 1)
1123 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
1124 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1125 else
1126 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
1127 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
hassof390d2c2004-09-10 20:48:21 +00001128 }
jardineb5d44e2003-12-23 08:09:43 +00001129
1130 return retval;
1131}
1132
1133#ifdef HAVE_IPV6
hasso92365882005-01-18 13:53:33 +00001134static int
hasso12a5cae2004-09-19 19:39:26 +00001135isis_run_spf6_l1 (struct thread *thread)
1136{
1137 struct isis_area *area;
1138 int retval = ISIS_OK;
1139
1140 area = THREAD_ARG (thread);
1141 assert (area);
1142
1143 area->spftree6[0]->t_spf = NULL;
1144
1145 if (!(area->is_type & IS_LEVEL_1))
1146 {
1147 if (isis->debugs & DEBUG_SPF_EVENTS)
1148 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
1149 return ISIS_WARNING;
1150 }
1151
1152 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001153 zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001154
1155 if (area->ipv6_circuits)
1156 retval = isis_run_spf (area, 1, AF_INET6);
1157
1158 THREAD_TIMER_ON (master, area->spftree6[0]->t_spf, isis_run_spf6_l1, area,
1159 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1160
1161 return retval;
1162}
1163
hasso92365882005-01-18 13:53:33 +00001164static int
hasso12a5cae2004-09-19 19:39:26 +00001165isis_run_spf6_l2 (struct thread *thread)
1166{
1167 struct isis_area *area;
1168 int retval = ISIS_OK;
1169
1170 area = THREAD_ARG (thread);
1171 assert (area);
1172
1173 area->spftree6[1]->t_spf = NULL;
1174
1175 if (!(area->is_type & IS_LEVEL_2))
1176 {
1177 if (isis->debugs & DEBUG_SPF_EVENTS)
1178 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
1179 return ISIS_WARNING;
1180 }
1181
1182 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001183 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001184
1185 if (area->ipv6_circuits)
1186 retval = isis_run_spf (area, 2, AF_INET6);
1187
1188 THREAD_TIMER_ON (master, area->spftree6[1]->t_spf, isis_run_spf6_l2, area,
1189 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1190
1191 return retval;
1192}
1193
1194int
jardineb5d44e2003-12-23 08:09:43 +00001195isis_spf_schedule6 (struct isis_area *area, int level)
1196{
1197 int retval = ISIS_OK;
1198 struct isis_spftree *spftree = area->spftree6[level - 1];
1199 time_t diff, now = time (NULL);
1200
1201 if (spftree->pending)
1202 return retval;
1203
hassof390d2c2004-09-10 20:48:21 +00001204 diff = now - spftree->lastrun;
1205
jardineb5d44e2003-12-23 08:09:43 +00001206 /* FIXME: let's wait a minute before doing the SPF */
hassof390d2c2004-09-10 20:48:21 +00001207 if (now - isis->uptime < 60 || isis->uptime == 0)
1208 {
1209 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001210 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area, 60);
hassof390d2c2004-09-10 20:48:21 +00001211 else
hasso12a5cae2004-09-19 19:39:26 +00001212 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area, 60);
jardineb5d44e2003-12-23 08:09:43 +00001213
hassof390d2c2004-09-10 20:48:21 +00001214 spftree->pending = 1;
1215 return retval;
1216 }
hasso12a5cae2004-09-19 19:39:26 +00001217
1218 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001219
hassof390d2c2004-09-10 20:48:21 +00001220 if (diff < MINIMUM_SPF_INTERVAL)
1221 {
1222 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001223 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
1224 MINIMUM_SPF_INTERVAL - diff);
hassof390d2c2004-09-10 20:48:21 +00001225 else
hasso12a5cae2004-09-19 19:39:26 +00001226 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
1227 MINIMUM_SPF_INTERVAL - diff);
jardineb5d44e2003-12-23 08:09:43 +00001228
hassof390d2c2004-09-10 20:48:21 +00001229 spftree->pending = 1;
1230 }
1231 else
1232 {
1233 spftree->pending = 0;
1234 retval = isis_run_spf (area, level, AF_INET6);
hasso12a5cae2004-09-19 19:39:26 +00001235
1236 if (level == 1)
1237 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
1238 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1239 else
1240 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
1241 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
hassof390d2c2004-09-10 20:48:21 +00001242 }
jardineb5d44e2003-12-23 08:09:43 +00001243
1244 return retval;
1245}
jardineb5d44e2003-12-23 08:09:43 +00001246#endif
1247
hasso92365882005-01-18 13:53:33 +00001248static void
jardineb5d44e2003-12-23 08:09:43 +00001249isis_print_paths (struct vty *vty, struct list *paths)
1250{
paul1eb8ef22005-04-07 07:30:20 +00001251 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +00001252 struct isis_vertex *vertex;
1253 struct isis_dynhn *dyn, *nh_dyn = NULL;
1254 struct isis_adjacency *adj;
hasso92365882005-01-18 13:53:33 +00001255#if 0
jardineb5d44e2003-12-23 08:09:43 +00001256 u_char buff[255];
hasso92365882005-01-18 13:53:33 +00001257#endif /* 0 */
jardineb5d44e2003-12-23 08:09:43 +00001258
1259 vty_out (vty, "System Id Metric Next-Hop"
hassof390d2c2004-09-10 20:48:21 +00001260 " Interface SNPA%s", VTY_NEWLINE);
paul1eb8ef22005-04-07 07:30:20 +00001261
1262 for (ALL_LIST_ELEMENTS_RO (paths, node, vertex))
hassof390d2c2004-09-10 20:48:21 +00001263 {
hassof390d2c2004-09-10 20:48:21 +00001264 if (vertex->type != VTYPE_NONPSEUDO_IS)
1265 continue;
1266 if (memcmp (vertex->N.id, isis->sysid, ISIS_SYS_ID_LEN) == 0)
1267 {
hassoc3d26c72005-03-07 08:54:41 +00001268 vty_out (vty, "%s --%s", host.name?host.name:"",
1269 VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +00001270 }
1271 else
1272 {
1273 dyn = dynhn_find_by_id ((u_char *) vertex->N.id);
paul1eb8ef22005-04-07 07:30:20 +00001274 adj = listgetdata (listhead (vertex->Adj_N));
hassof390d2c2004-09-10 20:48:21 +00001275 if (adj)
1276 {
1277 nh_dyn = dynhn_find_by_id (adj->sysid);
1278 vty_out (vty, "%-20s %-10u %-20s %-11s %-5s%s",
1279 (dyn != NULL) ? dyn->name.name :
1280 (u_char *) rawlspid_print ((u_char *) vertex->N.id),
1281 vertex->d_N, (nh_dyn != NULL) ? nh_dyn->name.name :
1282 (u_char *) rawlspid_print (adj->sysid),
1283 adj->circuit->interface->name,
1284 snpa_print (adj->snpa), VTY_NEWLINE);
1285 }
1286 else
1287 {
1288 vty_out (vty, "%s %u %s", dyn ? dyn->name.name :
1289 (u_char *) rawlspid_print (vertex->N.id),
1290 vertex->d_N, VTY_NEWLINE);
1291 }
1292 }
jardineb5d44e2003-12-23 08:09:43 +00001293#if 0
hassof390d2c2004-09-10 20:48:21 +00001294 vty_out (vty, "%s %s %u %s", vtype2string (vertex->type),
1295 vid2string (vertex, buff), vertex->d_N, VTY_NEWLINE);
jardineb5d44e2003-12-23 08:09:43 +00001296#endif
hassof390d2c2004-09-10 20:48:21 +00001297 }
jardineb5d44e2003-12-23 08:09:43 +00001298}
1299
1300DEFUN (show_isis_topology,
1301 show_isis_topology_cmd,
1302 "show isis topology",
1303 SHOW_STR
1304 "IS-IS information\n"
1305 "IS-IS paths to Intermediate Systems\n")
1306{
1307 struct listnode *node;
1308 struct isis_area *area;
1309 int level;
hassof390d2c2004-09-10 20:48:21 +00001310
jardineb5d44e2003-12-23 08:09:43 +00001311 if (!isis->area_list || isis->area_list->count == 0)
1312 return CMD_SUCCESS;
1313
paul1eb8ef22005-04-07 07:30:20 +00001314 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001315 {
hassof390d2c2004-09-10 20:48:21 +00001316 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1317 VTY_NEWLINE);
1318
1319 for (level = 0; level < ISIS_LEVELS; level++)
1320 {
1321 if (area->ip_circuits > 0 && area->spftree[level]
1322 && area->spftree[level]->paths->count > 0)
1323 {
1324 vty_out (vty, "IS-IS paths to level-%d routers that speak IP%s",
1325 level + 1, VTY_NEWLINE);
1326 isis_print_paths (vty, area->spftree[level]->paths);
1327 }
jardineb5d44e2003-12-23 08:09:43 +00001328#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001329 if (area->ipv6_circuits > 0 && area->spftree6[level]
1330 && area->spftree6[level]->paths->count > 0)
1331 {
1332 vty_out (vty,
1333 "IS-IS paths to level-%d routers that speak IPv6%s",
1334 level + 1, VTY_NEWLINE);
1335 isis_print_paths (vty, area->spftree6[level]->paths);
1336 }
jardineb5d44e2003-12-23 08:09:43 +00001337#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +00001338 }
jardineb5d44e2003-12-23 08:09:43 +00001339 }
jardineb5d44e2003-12-23 08:09:43 +00001340
1341 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001342}
jardineb5d44e2003-12-23 08:09:43 +00001343
1344DEFUN (show_isis_topology_l1,
1345 show_isis_topology_l1_cmd,
1346 "show isis topology level-1",
1347 SHOW_STR
1348 "IS-IS information\n"
1349 "IS-IS paths to Intermediate Systems\n"
1350 "Paths to all level-1 routers in the area\n")
1351{
1352 struct listnode *node;
1353 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001354
jardineb5d44e2003-12-23 08:09:43 +00001355 if (!isis->area_list || isis->area_list->count == 0)
1356 return CMD_SUCCESS;
1357
paul1eb8ef22005-04-07 07:30:20 +00001358 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001359 {
hassof390d2c2004-09-10 20:48:21 +00001360 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1361 VTY_NEWLINE);
1362
1363 if (area->ip_circuits > 0 && area->spftree[0]
1364 && area->spftree[0]->paths->count > 0)
1365 {
1366 vty_out (vty, "IS-IS paths to level-1 routers that speak IP%s",
1367 VTY_NEWLINE);
1368 isis_print_paths (vty, area->spftree[0]->paths);
1369 }
jardineb5d44e2003-12-23 08:09:43 +00001370#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001371 if (area->ipv6_circuits > 0 && area->spftree6[0]
1372 && area->spftree6[0]->paths->count > 0)
1373 {
1374 vty_out (vty, "IS-IS paths to level-1 routers that speak IPv6%s",
1375 VTY_NEWLINE);
1376 isis_print_paths (vty, area->spftree6[0]->paths);
1377 }
jardineb5d44e2003-12-23 08:09:43 +00001378#endif /* HAVE_IPV6 */
1379 }
1380
jardineb5d44e2003-12-23 08:09:43 +00001381 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001382}
jardineb5d44e2003-12-23 08:09:43 +00001383
1384DEFUN (show_isis_topology_l2,
1385 show_isis_topology_l2_cmd,
1386 "show isis topology level-2",
1387 SHOW_STR
1388 "IS-IS information\n"
1389 "IS-IS paths to Intermediate Systems\n"
1390 "Paths to all level-2 routers in the domain\n")
1391{
1392 struct listnode *node;
1393 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001394
jardineb5d44e2003-12-23 08:09:43 +00001395 if (!isis->area_list || isis->area_list->count == 0)
1396 return CMD_SUCCESS;
1397
paul1eb8ef22005-04-07 07:30:20 +00001398 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001399 {
hassof390d2c2004-09-10 20:48:21 +00001400 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1401 VTY_NEWLINE);
1402
1403 if (area->ip_circuits > 0 && area->spftree[1]
1404 && area->spftree[1]->paths->count > 0)
1405 {
1406 vty_out (vty, "IS-IS paths to level-2 routers that speak IP%s",
1407 VTY_NEWLINE);
1408 isis_print_paths (vty, area->spftree[1]->paths);
1409 }
jardineb5d44e2003-12-23 08:09:43 +00001410#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001411 if (area->ipv6_circuits > 0 && area->spftree6[1]
1412 && area->spftree6[1]->paths->count > 0)
1413 {
1414 vty_out (vty, "IS-IS paths to level-2 routers that speak IPv6%s",
1415 VTY_NEWLINE);
1416 isis_print_paths (vty, area->spftree6[1]->paths);
1417 }
jardineb5d44e2003-12-23 08:09:43 +00001418#endif /* HAVE_IPV6 */
1419 }
1420
jardineb5d44e2003-12-23 08:09:43 +00001421 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001422}
jardineb5d44e2003-12-23 08:09:43 +00001423
1424void
1425isis_spf_cmds_init ()
1426{
1427 install_element (VIEW_NODE, &show_isis_topology_cmd);
1428 install_element (VIEW_NODE, &show_isis_topology_l1_cmd);
1429 install_element (VIEW_NODE, &show_isis_topology_l2_cmd);
1430
1431 install_element (ENABLE_NODE, &show_isis_topology_cmd);
1432 install_element (ENABLE_NODE, &show_isis_topology_l1_cmd);
1433 install_element (ENABLE_NODE, &show_isis_topology_l2_cmd);
1434}