blob: dc5765a577ec4f94723fef833be20cc2f2a73f16 [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);
784 zlog_warn ("ISIS-Spf: no L%d adjacencies on circuit %s",
785 level, circuit->interface->name);
786 continue;
787 }
788 anode = listhead (adj_list);
789 while (anode)
790 {
paul1eb8ef22005-04-07 07:30:20 +0000791 adj = listgetdata (anode);
hassof390d2c2004-09-10 20:48:21 +0000792 if (!speaks (&adj->nlpids, family))
793 {
paul1eb8ef22005-04-07 07:30:20 +0000794 anode = listnextnode (anode);
hassof390d2c2004-09-10 20:48:21 +0000795 continue;
796 }
797 switch (adj->sys_type)
798 {
799 case ISIS_SYSTYPE_ES:
800 isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
801 circuit->metrics[level -
802 1].metric_default,
803 family);
804 break;
805 case ISIS_SYSTYPE_IS:
806 case ISIS_SYSTYPE_L1_IS:
807 case ISIS_SYSTYPE_L2_IS:
808 vertex =
809 isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS,
810 adj->sysid, adj,
811 circuit->metrics[level -
812 1].metric_default,
813 family);
814 memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN);
815 LSP_PSEUDO_ID (lsp_id) = 0;
816 LSP_FRAGMENT (lsp_id) = 0;
817 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
818 if (!lsp)
819 zlog_warn ("No lsp found for IS adjacency");
820 /* else {
821 isis_spf_process_lsp (spftree, lsp, vertex->d_N, 1, family);
822 } */
823 break;
824 case ISIS_SYSTYPE_UNKNOWN:
825 default:
826 zlog_warn ("isis_spf_preload_tent unknow adj type");
827 }
paul1eb8ef22005-04-07 07:30:20 +0000828 anode = listnextnode (anode);
hassof390d2c2004-09-10 20:48:21 +0000829 }
830 list_delete (adj_list);
831 /*
832 * Add the pseudonode
833 */
834 if (level == 1)
835 memcpy (lsp_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
836 else
837 memcpy (lsp_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
838 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
839 adj = isis_adj_lookup (lsp_id, adjdb);
840 /* if no adj, we are the dis or error */
841 if (!adj && !circuit->u.bc.is_dr[level - 1])
842 {
843 zlog_warn ("ISIS-Spf: No adjacency found for DR");
844 }
845 if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0)
846 {
847 zlog_warn ("ISIS-Spf: No lsp found for DR");
848 }
849 else
850 {
851 isis_spf_process_pseudo_lsp
852 (spftree, lsp, circuit->metrics[level - 1].metric_default, 0,
853 family);
854
855 }
856 }
857 else if (circuit->circ_type == CIRCUIT_T_P2P)
858 {
859 adj = circuit->u.p2p.neighbor;
860 if (!adj)
861 continue;
862 switch (adj->sys_type)
863 {
864 case ISIS_SYSTYPE_ES:
865 isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
866 circuit->metrics[level - 1].metric_default,
867 family);
868 break;
869 case ISIS_SYSTYPE_IS:
870 case ISIS_SYSTYPE_L1_IS:
871 case ISIS_SYSTYPE_L2_IS:
872 if (speaks (&adj->nlpids, family))
873 isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS, adj->sysid,
874 adj,
875 circuit->metrics[level -
876 1].metric_default,
877 family);
878 break;
879 case ISIS_SYSTYPE_UNKNOWN:
880 default:
881 zlog_warn ("isis_spf_preload_tent unknow adj type");
882 break;
883 }
884 }
jardineb5d44e2003-12-23 08:09:43 +0000885 else
hassof390d2c2004-09-10 20:48:21 +0000886 {
887 zlog_warn ("isis_spf_preload_tent unsupported media");
888 retval = ISIS_WARNING;
889 }
890
jardineb5d44e2003-12-23 08:09:43 +0000891 }
jardineb5d44e2003-12-23 08:09:43 +0000892
893 return retval;
894}
895
896/*
897 * The parent(s) for vertex is set when added to TENT list
898 * now we just put the child pointer(s) in place
899 */
hasso92365882005-01-18 13:53:33 +0000900static void
jardineb5d44e2003-12-23 08:09:43 +0000901add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex,
hassof390d2c2004-09-10 20:48:21 +0000902 struct isis_area *area)
jardineb5d44e2003-12-23 08:09:43 +0000903{
jardineb5d44e2003-12-23 08:09:43 +0000904#ifdef EXTREME_DEBUG
905 u_char buff[BUFSIZ];
906#endif /* EXTREME_DEBUG */
907 listnode_add (spftree->paths, vertex);
908
hassof390d2c2004-09-10 20:48:21 +0000909#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000910 zlog_debug ("ISIS-Spf: added %s %s depth %d dist %d to PATHS",
911 vtype2string (vertex->type), vid2string (vertex, buff),
912 vertex->depth, vertex->d_N);
hassof390d2c2004-09-10 20:48:21 +0000913#endif /* EXTREME_DEBUG */
914 if (vertex->type > VTYPE_ES)
915 {
916 if (listcount (vertex->Adj_N) > 0)
917 isis_route_create ((struct prefix *) &vertex->N.prefix,
918 vertex->d_N, vertex->depth, vertex->Adj_N, area);
919 else if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000920 zlog_debug ("ISIS-Spf: no adjacencies do not install route");
hassof390d2c2004-09-10 20:48:21 +0000921 }
922
jardineb5d44e2003-12-23 08:09:43 +0000923 return;
924}
925
hasso92365882005-01-18 13:53:33 +0000926static void
jardineb5d44e2003-12-23 08:09:43 +0000927init_spt (struct isis_spftree *spftree)
928{
hassof7c43dc2004-09-26 16:24:14 +0000929 spftree->tents->del = spftree->paths->del = (void (*)(void *)) isis_vertex_del;
jardineb5d44e2003-12-23 08:09:43 +0000930 list_delete_all_node (spftree->tents);
931 list_delete_all_node (spftree->paths);
932 spftree->tents->del = spftree->paths->del = NULL;
hassof390d2c2004-09-10 20:48:21 +0000933
jardineb5d44e2003-12-23 08:09:43 +0000934 return;
935}
936
hasso92365882005-01-18 13:53:33 +0000937static int
jardineb5d44e2003-12-23 08:09:43 +0000938isis_run_spf (struct isis_area *area, int level, int family)
939{
940 int retval = ISIS_OK;
941 struct listnode *node;
942 struct isis_vertex *vertex;
hassof390d2c2004-09-10 20:48:21 +0000943 struct isis_spftree *spftree = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000944 u_char lsp_id[ISIS_SYS_ID_LEN + 2];
945 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +0000946
jardineb5d44e2003-12-23 08:09:43 +0000947 if (family == AF_INET)
948 spftree = area->spftree[level - 1];
949#ifdef HAVE_IPV6
950 else if (family == AF_INET6)
951 spftree = area->spftree6[level - 1];
952#endif
hassof390d2c2004-09-10 20:48:21 +0000953
jardineb5d44e2003-12-23 08:09:43 +0000954 assert (spftree);
955
956 /*
957 * C.2.5 Step 0
958 */
959 init_spt (spftree);
960 /* a) */
961 isis_spf_add_self (spftree, area, level);
962 /* b) */
963 retval = isis_spf_preload_tent (spftree, area, level, family);
hassof390d2c2004-09-10 20:48:21 +0000964
jardineb5d44e2003-12-23 08:09:43 +0000965 /*
966 * C.2.7 Step 2
967 */
hassof390d2c2004-09-10 20:48:21 +0000968 if (listcount (spftree->tents) == 0)
969 {
970 zlog_warn ("ISIS-Spf: TENT is empty");
971 spftree->lastrun = time (NULL);
972 return retval;
jardineb5d44e2003-12-23 08:09:43 +0000973 }
hassof390d2c2004-09-10 20:48:21 +0000974
975 while (listcount (spftree->tents) > 0)
976 {
977 node = listhead (spftree->tents);
paul1eb8ef22005-04-07 07:30:20 +0000978 vertex = listgetdata (node);
hassof390d2c2004-09-10 20:48:21 +0000979 /* Remove from tent list */
980 list_delete_node (spftree->tents, node);
981 if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type))
982 continue;
983 add_to_paths (spftree, vertex, area);
984 if (vertex->type == VTYPE_PSEUDO_IS ||
985 vertex->type == VTYPE_NONPSEUDO_IS)
986 {
987 memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
988 LSP_FRAGMENT (lsp_id) = 0;
989 lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
990 if (lsp)
991 {
992 if (LSP_PSEUDO_ID (lsp_id))
993 {
994 isis_spf_process_pseudo_lsp (spftree, lsp, vertex->d_N,
995 vertex->depth, family);
996
997 }
998 else
999 {
1000 isis_spf_process_lsp (spftree, lsp, vertex->d_N,
1001 vertex->depth, family);
1002 }
1003 }
1004 else
1005 {
1006 zlog_warn ("ISIS-Spf: No LSP found for %s",
1007 rawlspid_print (lsp_id));
1008 }
1009 }
1010 }
1011
jardineb5d44e2003-12-23 08:09:43 +00001012 thread_add_event (master, isis_route_validate, area, 0);
1013 spftree->lastrun = time (NULL);
1014 spftree->pending = 0;
hassof390d2c2004-09-10 20:48:21 +00001015
jardineb5d44e2003-12-23 08:09:43 +00001016 return retval;
1017}
1018
1019int
1020isis_run_spf_l1 (struct thread *thread)
1021{
1022 struct isis_area *area;
1023 int retval = ISIS_OK;
1024
hassof390d2c2004-09-10 20:48:21 +00001025 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001026 assert (area);
1027
hasso12a5cae2004-09-19 19:39:26 +00001028 area->spftree[0]->t_spf = NULL;
1029
hassof390d2c2004-09-10 20:48:21 +00001030 if (!(area->is_type & IS_LEVEL_1))
1031 {
1032 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001033 zlog_warn ("ISIS-SPF (%s) area does not share level",
1034 area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001035 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001036 }
jardineb5d44e2003-12-23 08:09:43 +00001037
hassof390d2c2004-09-10 20:48:21 +00001038 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001039 zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001040
jardineb5d44e2003-12-23 08:09:43 +00001041 if (area->ip_circuits)
1042 retval = isis_run_spf (area, 1, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001043
1044 THREAD_TIMER_ON (master, area->spftree[0]->t_spf, isis_run_spf_l1, area,
1045 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1046
jardineb5d44e2003-12-23 08:09:43 +00001047 return retval;
1048}
1049
1050int
1051isis_run_spf_l2 (struct thread *thread)
1052{
1053 struct isis_area *area;
1054 int retval = ISIS_OK;
1055
hassof390d2c2004-09-10 20:48:21 +00001056 area = THREAD_ARG (thread);
jardineb5d44e2003-12-23 08:09:43 +00001057 assert (area);
hassof390d2c2004-09-10 20:48:21 +00001058
hasso12a5cae2004-09-19 19:39:26 +00001059 area->spftree[1]->t_spf = NULL;
1060
hassof390d2c2004-09-10 20:48:21 +00001061 if (!(area->is_type & IS_LEVEL_2))
1062 {
1063 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso12a5cae2004-09-19 19:39:26 +00001064 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
hassof390d2c2004-09-10 20:48:21 +00001065 return ISIS_WARNING;
jardineb5d44e2003-12-23 08:09:43 +00001066 }
hassof390d2c2004-09-10 20:48:21 +00001067
1068 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001069 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag);
jardineb5d44e2003-12-23 08:09:43 +00001070
1071 if (area->ip_circuits)
1072 retval = isis_run_spf (area, 2, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001073
1074 THREAD_TIMER_ON (master, area->spftree[1]->t_spf, isis_run_spf_l2, area,
1075 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
jardineb5d44e2003-12-23 08:09:43 +00001076
1077 return retval;
1078}
1079
hassof390d2c2004-09-10 20:48:21 +00001080int
jardineb5d44e2003-12-23 08:09:43 +00001081isis_spf_schedule (struct isis_area *area, int level)
1082{
1083 int retval = ISIS_OK;
1084 struct isis_spftree *spftree = area->spftree[level - 1];
1085 time_t diff, now = time (NULL);
1086
1087 if (spftree->pending)
1088 return retval;
1089
hassof390d2c2004-09-10 20:48:21 +00001090 diff = now - spftree->lastrun;
jardineb5d44e2003-12-23 08:09:43 +00001091
1092 /* FIXME: let's wait a minute before doing the SPF */
hassof390d2c2004-09-10 20:48:21 +00001093 if (now - isis->uptime < 60 || isis->uptime == 0)
1094 {
1095 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001096 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area, 60);
hassof390d2c2004-09-10 20:48:21 +00001097 else
hasso12a5cae2004-09-19 19:39:26 +00001098 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area, 60);
jardineb5d44e2003-12-23 08:09:43 +00001099
hassof390d2c2004-09-10 20:48:21 +00001100 spftree->pending = 1;
1101 return retval;
1102 }
hasso12a5cae2004-09-19 19:39:26 +00001103
1104 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001105
hassof390d2c2004-09-10 20:48:21 +00001106 if (diff < MINIMUM_SPF_INTERVAL)
1107 {
1108 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001109 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
1110 MINIMUM_SPF_INTERVAL - diff);
hassof390d2c2004-09-10 20:48:21 +00001111 else
hasso12a5cae2004-09-19 19:39:26 +00001112 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
1113 MINIMUM_SPF_INTERVAL - diff);
jardineb5d44e2003-12-23 08:09:43 +00001114
hassof390d2c2004-09-10 20:48:21 +00001115 spftree->pending = 1;
1116 }
1117 else
1118 {
1119 spftree->pending = 0;
1120 retval = isis_run_spf (area, level, AF_INET);
hasso12a5cae2004-09-19 19:39:26 +00001121 if (level == 1)
1122 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
1123 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1124 else
1125 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
1126 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
hassof390d2c2004-09-10 20:48:21 +00001127 }
jardineb5d44e2003-12-23 08:09:43 +00001128
1129 return retval;
1130}
1131
1132#ifdef HAVE_IPV6
hasso92365882005-01-18 13:53:33 +00001133static int
hasso12a5cae2004-09-19 19:39:26 +00001134isis_run_spf6_l1 (struct thread *thread)
1135{
1136 struct isis_area *area;
1137 int retval = ISIS_OK;
1138
1139 area = THREAD_ARG (thread);
1140 assert (area);
1141
1142 area->spftree6[0]->t_spf = NULL;
1143
1144 if (!(area->is_type & IS_LEVEL_1))
1145 {
1146 if (isis->debugs & DEBUG_SPF_EVENTS)
1147 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
1148 return ISIS_WARNING;
1149 }
1150
1151 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001152 zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001153
1154 if (area->ipv6_circuits)
1155 retval = isis_run_spf (area, 1, AF_INET6);
1156
1157 THREAD_TIMER_ON (master, area->spftree6[0]->t_spf, isis_run_spf6_l1, area,
1158 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1159
1160 return retval;
1161}
1162
hasso92365882005-01-18 13:53:33 +00001163static int
hasso12a5cae2004-09-19 19:39:26 +00001164isis_run_spf6_l2 (struct thread *thread)
1165{
1166 struct isis_area *area;
1167 int retval = ISIS_OK;
1168
1169 area = THREAD_ARG (thread);
1170 assert (area);
1171
1172 area->spftree6[1]->t_spf = NULL;
1173
1174 if (!(area->is_type & IS_LEVEL_2))
1175 {
1176 if (isis->debugs & DEBUG_SPF_EVENTS)
1177 zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
1178 return ISIS_WARNING;
1179 }
1180
1181 if (isis->debugs & DEBUG_SPF_EVENTS)
hasso529d65b2004-12-24 00:14:50 +00001182 zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag);
hasso12a5cae2004-09-19 19:39:26 +00001183
1184 if (area->ipv6_circuits)
1185 retval = isis_run_spf (area, 2, AF_INET6);
1186
1187 THREAD_TIMER_ON (master, area->spftree6[1]->t_spf, isis_run_spf6_l2, area,
1188 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1189
1190 return retval;
1191}
1192
1193int
jardineb5d44e2003-12-23 08:09:43 +00001194isis_spf_schedule6 (struct isis_area *area, int level)
1195{
1196 int retval = ISIS_OK;
1197 struct isis_spftree *spftree = area->spftree6[level - 1];
1198 time_t diff, now = time (NULL);
1199
1200 if (spftree->pending)
1201 return retval;
1202
hassof390d2c2004-09-10 20:48:21 +00001203 diff = now - spftree->lastrun;
1204
jardineb5d44e2003-12-23 08:09:43 +00001205 /* FIXME: let's wait a minute before doing the SPF */
hassof390d2c2004-09-10 20:48:21 +00001206 if (now - isis->uptime < 60 || isis->uptime == 0)
1207 {
1208 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001209 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area, 60);
hassof390d2c2004-09-10 20:48:21 +00001210 else
hasso12a5cae2004-09-19 19:39:26 +00001211 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area, 60);
jardineb5d44e2003-12-23 08:09:43 +00001212
hassof390d2c2004-09-10 20:48:21 +00001213 spftree->pending = 1;
1214 return retval;
1215 }
hasso12a5cae2004-09-19 19:39:26 +00001216
1217 THREAD_TIMER_OFF (spftree->t_spf);
jardineb5d44e2003-12-23 08:09:43 +00001218
hassof390d2c2004-09-10 20:48:21 +00001219 if (diff < MINIMUM_SPF_INTERVAL)
1220 {
1221 if (level == 1)
hasso12a5cae2004-09-19 19:39:26 +00001222 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
1223 MINIMUM_SPF_INTERVAL - diff);
hassof390d2c2004-09-10 20:48:21 +00001224 else
hasso12a5cae2004-09-19 19:39:26 +00001225 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
1226 MINIMUM_SPF_INTERVAL - diff);
jardineb5d44e2003-12-23 08:09:43 +00001227
hassof390d2c2004-09-10 20:48:21 +00001228 spftree->pending = 1;
1229 }
1230 else
1231 {
1232 spftree->pending = 0;
1233 retval = isis_run_spf (area, level, AF_INET6);
hasso12a5cae2004-09-19 19:39:26 +00001234
1235 if (level == 1)
1236 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
1237 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
1238 else
1239 THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
1240 isis_jitter (PERIODIC_SPF_INTERVAL, 10));
hassof390d2c2004-09-10 20:48:21 +00001241 }
jardineb5d44e2003-12-23 08:09:43 +00001242
1243 return retval;
1244}
jardineb5d44e2003-12-23 08:09:43 +00001245#endif
1246
hasso92365882005-01-18 13:53:33 +00001247static void
jardineb5d44e2003-12-23 08:09:43 +00001248isis_print_paths (struct vty *vty, struct list *paths)
1249{
paul1eb8ef22005-04-07 07:30:20 +00001250 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +00001251 struct isis_vertex *vertex;
1252 struct isis_dynhn *dyn, *nh_dyn = NULL;
1253 struct isis_adjacency *adj;
hasso92365882005-01-18 13:53:33 +00001254#if 0
jardineb5d44e2003-12-23 08:09:43 +00001255 u_char buff[255];
hasso92365882005-01-18 13:53:33 +00001256#endif /* 0 */
jardineb5d44e2003-12-23 08:09:43 +00001257
1258 vty_out (vty, "System Id Metric Next-Hop"
hassof390d2c2004-09-10 20:48:21 +00001259 " Interface SNPA%s", VTY_NEWLINE);
paul1eb8ef22005-04-07 07:30:20 +00001260
1261 for (ALL_LIST_ELEMENTS_RO (paths, node, vertex))
hassof390d2c2004-09-10 20:48:21 +00001262 {
hassof390d2c2004-09-10 20:48:21 +00001263 if (vertex->type != VTYPE_NONPSEUDO_IS)
1264 continue;
1265 if (memcmp (vertex->N.id, isis->sysid, ISIS_SYS_ID_LEN) == 0)
1266 {
hassoc3d26c72005-03-07 08:54:41 +00001267 vty_out (vty, "%s --%s", host.name?host.name:"",
1268 VTY_NEWLINE);
hassof390d2c2004-09-10 20:48:21 +00001269 }
1270 else
1271 {
1272 dyn = dynhn_find_by_id ((u_char *) vertex->N.id);
paul1eb8ef22005-04-07 07:30:20 +00001273 adj = listgetdata (listhead (vertex->Adj_N));
hassof390d2c2004-09-10 20:48:21 +00001274 if (adj)
1275 {
1276 nh_dyn = dynhn_find_by_id (adj->sysid);
1277 vty_out (vty, "%-20s %-10u %-20s %-11s %-5s%s",
1278 (dyn != NULL) ? dyn->name.name :
1279 (u_char *) rawlspid_print ((u_char *) vertex->N.id),
1280 vertex->d_N, (nh_dyn != NULL) ? nh_dyn->name.name :
1281 (u_char *) rawlspid_print (adj->sysid),
1282 adj->circuit->interface->name,
1283 snpa_print (adj->snpa), VTY_NEWLINE);
1284 }
1285 else
1286 {
1287 vty_out (vty, "%s %u %s", dyn ? dyn->name.name :
1288 (u_char *) rawlspid_print (vertex->N.id),
1289 vertex->d_N, VTY_NEWLINE);
1290 }
1291 }
jardineb5d44e2003-12-23 08:09:43 +00001292#if 0
hassof390d2c2004-09-10 20:48:21 +00001293 vty_out (vty, "%s %s %u %s", vtype2string (vertex->type),
1294 vid2string (vertex, buff), vertex->d_N, VTY_NEWLINE);
jardineb5d44e2003-12-23 08:09:43 +00001295#endif
hassof390d2c2004-09-10 20:48:21 +00001296 }
jardineb5d44e2003-12-23 08:09:43 +00001297}
1298
1299DEFUN (show_isis_topology,
1300 show_isis_topology_cmd,
1301 "show isis topology",
1302 SHOW_STR
1303 "IS-IS information\n"
1304 "IS-IS paths to Intermediate Systems\n")
1305{
1306 struct listnode *node;
1307 struct isis_area *area;
1308 int level;
hassof390d2c2004-09-10 20:48:21 +00001309
jardineb5d44e2003-12-23 08:09:43 +00001310 if (!isis->area_list || isis->area_list->count == 0)
1311 return CMD_SUCCESS;
1312
paul1eb8ef22005-04-07 07:30:20 +00001313 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001314 {
hassof390d2c2004-09-10 20:48:21 +00001315 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1316 VTY_NEWLINE);
1317
1318 for (level = 0; level < ISIS_LEVELS; level++)
1319 {
1320 if (area->ip_circuits > 0 && area->spftree[level]
1321 && area->spftree[level]->paths->count > 0)
1322 {
1323 vty_out (vty, "IS-IS paths to level-%d routers that speak IP%s",
1324 level + 1, VTY_NEWLINE);
1325 isis_print_paths (vty, area->spftree[level]->paths);
1326 }
jardineb5d44e2003-12-23 08:09:43 +00001327#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001328 if (area->ipv6_circuits > 0 && area->spftree6[level]
1329 && area->spftree6[level]->paths->count > 0)
1330 {
1331 vty_out (vty,
1332 "IS-IS paths to level-%d routers that speak IPv6%s",
1333 level + 1, VTY_NEWLINE);
1334 isis_print_paths (vty, area->spftree6[level]->paths);
1335 }
jardineb5d44e2003-12-23 08:09:43 +00001336#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +00001337 }
jardineb5d44e2003-12-23 08:09:43 +00001338 }
jardineb5d44e2003-12-23 08:09:43 +00001339
1340 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001341}
jardineb5d44e2003-12-23 08:09:43 +00001342
1343DEFUN (show_isis_topology_l1,
1344 show_isis_topology_l1_cmd,
1345 "show isis topology level-1",
1346 SHOW_STR
1347 "IS-IS information\n"
1348 "IS-IS paths to Intermediate Systems\n"
1349 "Paths to all level-1 routers in the area\n")
1350{
1351 struct listnode *node;
1352 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001353
jardineb5d44e2003-12-23 08:09:43 +00001354 if (!isis->area_list || isis->area_list->count == 0)
1355 return CMD_SUCCESS;
1356
paul1eb8ef22005-04-07 07:30:20 +00001357 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001358 {
hassof390d2c2004-09-10 20:48:21 +00001359 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1360 VTY_NEWLINE);
1361
1362 if (area->ip_circuits > 0 && area->spftree[0]
1363 && area->spftree[0]->paths->count > 0)
1364 {
1365 vty_out (vty, "IS-IS paths to level-1 routers that speak IP%s",
1366 VTY_NEWLINE);
1367 isis_print_paths (vty, area->spftree[0]->paths);
1368 }
jardineb5d44e2003-12-23 08:09:43 +00001369#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001370 if (area->ipv6_circuits > 0 && area->spftree6[0]
1371 && area->spftree6[0]->paths->count > 0)
1372 {
1373 vty_out (vty, "IS-IS paths to level-1 routers that speak IPv6%s",
1374 VTY_NEWLINE);
1375 isis_print_paths (vty, area->spftree6[0]->paths);
1376 }
jardineb5d44e2003-12-23 08:09:43 +00001377#endif /* HAVE_IPV6 */
1378 }
1379
jardineb5d44e2003-12-23 08:09:43 +00001380 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001381}
jardineb5d44e2003-12-23 08:09:43 +00001382
1383DEFUN (show_isis_topology_l2,
1384 show_isis_topology_l2_cmd,
1385 "show isis topology level-2",
1386 SHOW_STR
1387 "IS-IS information\n"
1388 "IS-IS paths to Intermediate Systems\n"
1389 "Paths to all level-2 routers in the domain\n")
1390{
1391 struct listnode *node;
1392 struct isis_area *area;
hassof390d2c2004-09-10 20:48:21 +00001393
jardineb5d44e2003-12-23 08:09:43 +00001394 if (!isis->area_list || isis->area_list->count == 0)
1395 return CMD_SUCCESS;
1396
paul1eb8ef22005-04-07 07:30:20 +00001397 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
hassof390d2c2004-09-10 20:48:21 +00001398 {
hassof390d2c2004-09-10 20:48:21 +00001399 vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
1400 VTY_NEWLINE);
1401
1402 if (area->ip_circuits > 0 && area->spftree[1]
1403 && area->spftree[1]->paths->count > 0)
1404 {
1405 vty_out (vty, "IS-IS paths to level-2 routers that speak IP%s",
1406 VTY_NEWLINE);
1407 isis_print_paths (vty, area->spftree[1]->paths);
1408 }
jardineb5d44e2003-12-23 08:09:43 +00001409#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +00001410 if (area->ipv6_circuits > 0 && area->spftree6[1]
1411 && area->spftree6[1]->paths->count > 0)
1412 {
1413 vty_out (vty, "IS-IS paths to level-2 routers that speak IPv6%s",
1414 VTY_NEWLINE);
1415 isis_print_paths (vty, area->spftree6[1]->paths);
1416 }
jardineb5d44e2003-12-23 08:09:43 +00001417#endif /* HAVE_IPV6 */
1418 }
1419
jardineb5d44e2003-12-23 08:09:43 +00001420 return CMD_SUCCESS;
hassof390d2c2004-09-10 20:48:21 +00001421}
jardineb5d44e2003-12-23 08:09:43 +00001422
1423void
1424isis_spf_cmds_init ()
1425{
1426 install_element (VIEW_NODE, &show_isis_topology_cmd);
1427 install_element (VIEW_NODE, &show_isis_topology_l1_cmd);
1428 install_element (VIEW_NODE, &show_isis_topology_l2_cmd);
1429
1430 install_element (ENABLE_NODE, &show_isis_topology_cmd);
1431 install_element (ENABLE_NODE, &show_isis_topology_l1_cmd);
1432 install_element (ENABLE_NODE, &show_isis_topology_l2_cmd);
1433}