blob: 10b73b83b914f74d9412c1a7e301764158e4c87a [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
hasso508e53e2004-05-18 18:57:06 +00002 * Copyright (C) 2003 Yasuhiro Ohara
paul718e3742002-12-13 20:15:29 +00003 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
hasso508e53e2004-05-18 18:57:06 +000021
paul718e3742002-12-13 20:15:29 +000022/* Shortest Path First calculation for OSPFv3 */
23
hasso508e53e2004-05-18 18:57:06 +000024#include <zebra.h>
paul718e3742002-12-13 20:15:29 +000025
hasso508e53e2004-05-18 18:57:06 +000026#include "log.h"
27#include "memory.h"
28#include "command.h"
29#include "vty.h"
paul718e3742002-12-13 20:15:29 +000030#include "prefix.h"
hasso508e53e2004-05-18 18:57:06 +000031#include "pqueue.h"
32#include "linklist.h"
33#include "thread.h"
paul718e3742002-12-13 20:15:29 +000034
hasso508e53e2004-05-18 18:57:06 +000035#include "ospf6d.h"
paul718e3742002-12-13 20:15:29 +000036#include "ospf6_lsa.h"
37#include "ospf6_lsdb.h"
38#include "ospf6_route.h"
paul718e3742002-12-13 20:15:29 +000039#include "ospf6_area.h"
hasso508e53e2004-05-18 18:57:06 +000040#include "ospf6_spf.h"
41#include "ospf6_intra.h"
42#include "ospf6_interface.h"
paul718e3742002-12-13 20:15:29 +000043
hasso508e53e2004-05-18 18:57:06 +000044unsigned char conf_debug_ospf6_spf = 0;
paul718e3742002-12-13 20:15:29 +000045
46int
hasso508e53e2004-05-18 18:57:06 +000047ospf6_vertex_cmp (void *a, void *b)
paul718e3742002-12-13 20:15:29 +000048{
hasso508e53e2004-05-18 18:57:06 +000049 struct ospf6_vertex *va = (struct ospf6_vertex *) a;
50 struct ospf6_vertex *vb = (struct ospf6_vertex *) b;
51
52 /* ascending order */
53 return (va->cost - vb->cost);
paul718e3742002-12-13 20:15:29 +000054}
55
56int
hasso508e53e2004-05-18 18:57:06 +000057ospf6_vertex_id_cmp (void *a, void *b)
paul718e3742002-12-13 20:15:29 +000058{
hasso508e53e2004-05-18 18:57:06 +000059 struct ospf6_vertex *va = (struct ospf6_vertex *) a;
60 struct ospf6_vertex *vb = (struct ospf6_vertex *) b;
61 int ret = 0;
paul718e3742002-12-13 20:15:29 +000062
hasso508e53e2004-05-18 18:57:06 +000063 ret = ntohl (ospf6_linkstate_prefix_adv_router (&va->vertex_id)) -
64 ntohl (ospf6_linkstate_prefix_adv_router (&vb->vertex_id));
65 if (ret)
66 return ret;
paul718e3742002-12-13 20:15:29 +000067
hasso508e53e2004-05-18 18:57:06 +000068 ret = ntohl (ospf6_linkstate_prefix_id (&va->vertex_id)) -
69 ntohl (ospf6_linkstate_prefix_id (&vb->vertex_id));
paul718e3742002-12-13 20:15:29 +000070 return ret;
71}
72
hasso508e53e2004-05-18 18:57:06 +000073struct ospf6_vertex *
74ospf6_vertex_create (struct ospf6_lsa *lsa)
75{
76 struct ospf6_vertex *v;
77 int i;
78
79 v = (struct ospf6_vertex *)
80 XMALLOC (MTYPE_OSPF6_VERTEX, sizeof (struct ospf6_vertex));
81
82 /* type */
83 if (ntohs (lsa->header->type) == OSPF6_LSTYPE_ROUTER)
84 v->type = OSPF6_VERTEX_TYPE_ROUTER;
85 else if (ntohs (lsa->header->type) == OSPF6_LSTYPE_NETWORK)
86 v->type = OSPF6_VERTEX_TYPE_NETWORK;
87 else
88 assert (0);
89
90 /* vertex_id */
91 ospf6_linkstate_prefix (lsa->header->adv_router, lsa->header->id,
92 &v->vertex_id);
93
94 /* name */
95 ospf6_linkstate_prefix2str (&v->vertex_id, v->name, sizeof (v->name));
96
97 /* Associated LSA */
98 v->lsa = lsa;
99
100 /* capability bits + options */
101 v->capability = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header));
102 v->options[0] = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header) + 1);
103 v->options[1] = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header) + 2);
104 v->options[2] = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header) + 3);
105
106 for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
107 ospf6_nexthop_clear (&v->nexthop[i]);
108
109 v->parent = NULL;
110 v->child_list = list_new ();
111 v->child_list->cmp = ospf6_vertex_id_cmp;
112
113 return v;
114}
115
paul718e3742002-12-13 20:15:29 +0000116void
hasso508e53e2004-05-18 18:57:06 +0000117ospf6_vertex_delete (struct ospf6_vertex *v)
paul718e3742002-12-13 20:15:29 +0000118{
hasso508e53e2004-05-18 18:57:06 +0000119 list_delete (v->child_list);
paul718e3742002-12-13 20:15:29 +0000120 XFREE (MTYPE_OSPF6_VERTEX, v);
121}
122
hasso508e53e2004-05-18 18:57:06 +0000123struct ospf6_lsa *
124ospf6_lsdesc_lsa (caddr_t lsdesc, struct ospf6_vertex *v)
paul718e3742002-12-13 20:15:29 +0000125{
paul718e3742002-12-13 20:15:29 +0000126 struct ospf6_lsa *lsa;
hasso508e53e2004-05-18 18:57:06 +0000127 u_int16_t type = 0;
128 u_int32_t id = 0, adv_router = 0;
paul718e3742002-12-13 20:15:29 +0000129
hasso508e53e2004-05-18 18:57:06 +0000130 if (VERTEX_IS_TYPE (NETWORK, v))
paul718e3742002-12-13 20:15:29 +0000131 {
hasso508e53e2004-05-18 18:57:06 +0000132 type = htons (OSPF6_LSTYPE_ROUTER);
133 id = htonl (0);
134 adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc);
paul718e3742002-12-13 20:15:29 +0000135 }
paul718e3742002-12-13 20:15:29 +0000136 else
paul718e3742002-12-13 20:15:29 +0000137 {
hasso508e53e2004-05-18 18:57:06 +0000138 if (ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, lsdesc))
paul718e3742002-12-13 20:15:29 +0000139 {
hasso508e53e2004-05-18 18:57:06 +0000140 type = htons (OSPF6_LSTYPE_ROUTER);
141 id = htonl (0);
142 adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc);
143 }
144 else if (ROUTER_LSDESC_IS_TYPE (TRANSIT_NETWORK, lsdesc))
145 {
146 type = htons (OSPF6_LSTYPE_NETWORK);
147 id = htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc));
148 adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc);
paul718e3742002-12-13 20:15:29 +0000149 }
150 }
151
hasso508e53e2004-05-18 18:57:06 +0000152 lsa = ospf6_lsdb_lookup (type, id, adv_router, v->area->lsdb);
paul718e3742002-12-13 20:15:29 +0000153
hasso508e53e2004-05-18 18:57:06 +0000154 if (IS_OSPF6_DEBUG_SPF (DETAIL))
paul718e3742002-12-13 20:15:29 +0000155 {
hasso508e53e2004-05-18 18:57:06 +0000156 char ibuf[16], abuf[16];
157 inet_ntop (AF_INET, &id, ibuf, sizeof (ibuf));
158 inet_ntop (AF_INET, &adv_router, abuf, sizeof (abuf));
159 if (lsa)
160 zlog_info (" Link to: %s", lsa->name);
161 else
162 zlog_info (" Link to: [%s Id:%s Adv:%s] No LSA",
163 OSPF6_LSTYPE_NAME (type), ibuf, abuf);
paul718e3742002-12-13 20:15:29 +0000164 }
165
hasso508e53e2004-05-18 18:57:06 +0000166 return lsa;
167}
168
169char *
170ospf6_lsdesc_backlink (struct ospf6_lsa *lsa,
171 caddr_t lsdesc, struct ospf6_vertex *v)
172{
173 caddr_t backlink, found = NULL;
174 int size;
175
176 size = (OSPF6_LSA_IS_TYPE (ROUTER, lsa) ?
177 sizeof (struct ospf6_router_lsdesc) :
178 sizeof (struct ospf6_network_lsdesc));
179 for (backlink = OSPF6_LSA_HEADER_END (lsa->header) + 4;
180 backlink + size <= OSPF6_LSA_END (lsa->header); backlink += size)
181 {
182 assert (! (OSPF6_LSA_IS_TYPE (NETWORK, lsa) &&
183 VERTEX_IS_TYPE (NETWORK, v)));
184
185 if (OSPF6_LSA_IS_TYPE (NETWORK, lsa) &&
186 NETWORK_LSDESC_GET_NBR_ROUTERID (backlink)
187 == v->lsa->header->adv_router)
188 found = backlink;
189 else if (VERTEX_IS_TYPE (NETWORK, v) &&
190 ROUTER_LSDESC_IS_TYPE (TRANSIT_NETWORK, backlink) &&
191 ROUTER_LSDESC_GET_NBR_ROUTERID (backlink)
192 == v->lsa->header->adv_router &&
193 ROUTER_LSDESC_GET_NBR_IFID (backlink)
194 == ntohl (v->lsa->header->id))
195 found = backlink;
196 else
197 {
198 if (! ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, backlink) ||
199 ! ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, lsdesc))
200 continue;
201 if (ROUTER_LSDESC_GET_NBR_IFID (backlink) !=
202 ROUTER_LSDESC_GET_IFID (lsdesc) ||
203 ROUTER_LSDESC_GET_NBR_IFID (lsdesc) !=
204 ROUTER_LSDESC_GET_IFID (backlink))
205 continue;
206 if (ROUTER_LSDESC_GET_NBR_ROUTERID (backlink) !=
207 v->lsa->header->adv_router ||
208 ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc) !=
209 lsa->header->adv_router)
210 continue;
211 found = backlink;
212 }
213 }
214
215 if (IS_OSPF6_DEBUG_SPF (DETAIL))
216 zlog_info (" Backlink %s", (found ? "OK" : "FAIL"));
217
218 return found;
219}
220
221void
222ospf6_nexthop_calc (struct ospf6_vertex *w, struct ospf6_vertex *v,
223 caddr_t lsdesc)
224{
225 int i, ifindex;
226 struct ospf6_interface *oi;
227 u_int16_t type;
228 u_int32_t adv_router;
229 struct ospf6_lsa *lsa;
230 struct ospf6_link_lsa *link_lsa;
231 char buf[64];
232
233 assert (VERTEX_IS_TYPE (ROUTER, w));
234 ifindex = (VERTEX_IS_TYPE (NETWORK, v) ? v->nexthop[0].ifindex :
235 ROUTER_LSDESC_GET_IFID (lsdesc));
236 oi = ospf6_interface_lookup_by_ifindex (ifindex);
237 if (oi == NULL)
238 {
239 if (IS_OSPF6_DEBUG_SPF (SUMMARY))
240 zlog_warn ("Can't find interface in SPF: ifindex %d", ifindex);
241 return;
242 }
243
244 type = htons (OSPF6_LSTYPE_LINK);
245 adv_router = (VERTEX_IS_TYPE (NETWORK, v) ?
246 NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc) :
247 ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc));
248
249 i = 0;
250 for (lsa = ospf6_lsdb_type_router_head (type, adv_router, oi->lsdb); lsa;
251 lsa = ospf6_lsdb_type_router_next (type, adv_router, lsa))
252 {
253 if (VERTEX_IS_TYPE (ROUTER, v) &&
254 htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc)) != lsa->header->id)
255 continue;
256
257 link_lsa = (struct ospf6_link_lsa *) OSPF6_LSA_HEADER_END (lsa->header);
258 if (IS_OSPF6_DEBUG_SPF (DETAIL))
259 {
260 inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf));
261 zlog_info (" nexthop %s from %s", buf, lsa->name);
262 }
263
264 if (i < OSPF6_MULTI_PATH_LIMIT)
265 {
266 memcpy (&w->nexthop[i].address, &link_lsa->linklocal_addr,
267 sizeof (struct in6_addr));
268 w->nexthop[i].ifindex = ifindex;
269 i++;
270 }
271 }
272
273 if (i == 0 && IS_OSPF6_DEBUG_SPF (SUMMARY))
274 zlog_info ("No nexthop for %s found", w->name);
275}
276
277int
278ospf6_spf_install (struct ospf6_vertex *v,
279 struct ospf6_route_table *result_table)
280{
281 struct ospf6_route *route;
282 int i, j;
283 struct ospf6_vertex *prev, *w;
284 listnode node;
285
286 if (IS_OSPF6_DEBUG_SPF (SUMMARY))
287 zlog_info ("SPF install %s hops %d cost %d",
288 v->name, v->hops, v->cost);
289
290 route = ospf6_route_lookup (&v->vertex_id, result_table);
291 if (route && route->path.cost < v->cost)
292 {
293 if (IS_OSPF6_DEBUG_SPF (SUMMARY))
294 zlog_info (" already installed with lower cost (%d), ignore",
295 route->path.cost);
296 ospf6_vertex_delete (v);
297 return -1;
298 }
299 else if (route && route->path.cost == v->cost)
300 {
301 if (IS_OSPF6_DEBUG_SPF (SUMMARY))
302 zlog_info (" another path found, merge");
303
304 for (i = 0; ospf6_nexthop_is_set (&v->nexthop[i]) &&
305 i < OSPF6_MULTI_PATH_LIMIT; i++)
306 {
307 for (j = 0; j < OSPF6_MULTI_PATH_LIMIT; j++)
308 {
309 if (ospf6_nexthop_is_set (&route->nexthop[j]))
310 {
311 if (ospf6_nexthop_is_same (&route->nexthop[j],
312 &v->nexthop[i]))
313 break;
314 else
315 continue;
316 }
317 ospf6_nexthop_copy (&route->nexthop[j], &v->nexthop[i]);
318 break;
319 }
320 }
321
322 prev = (struct ospf6_vertex *) route->route_option;
323 if (prev->hops > v->hops)
324 {
325 LIST_LOOP (prev->child_list, w, node)
326 {
327 assert (w->parent == prev);
328 w->parent = v;
329 listnode_add_sort (v->child_list, w);
330 }
331 listnode_delete (prev->parent->child_list, prev);
332 listnode_add_sort (v->parent->child_list, v);
333
334 ospf6_vertex_delete (prev);
335 route->route_option = v;
336 }
337 else
338 ospf6_vertex_delete (v);
339
340 return -1;
341 }
342
343 /* There should be no case where candidate being installed (variable
344 "v") is closer than the one in the SPF tree (variable "route").
345 In the case something's gone wrong with the behavior of
346 Priority-Queue. */
347 assert (route == NULL);
348
349 route = ospf6_route_create ();
350 memcpy (&route->prefix, &v->vertex_id, sizeof (struct prefix));
351 route->type = OSPF6_DEST_TYPE_LINKSTATE;
352 route->path.type = OSPF6_PATH_TYPE_INTRA;
353 route->path.origin.type = v->lsa->header->type;
354 route->path.origin.id = v->lsa->header->id;
355 route->path.origin.adv_router = v->lsa->header->adv_router;
356 route->path.metric_type = 1;
357 route->path.cost = v->cost;
358 route->path.cost_e2 = v->hops;
359 route->path.router_bits = v->capability;
360 route->path.options[0] = v->options[0];
361 route->path.options[1] = v->options[1];
362 route->path.options[2] = v->options[2];
363
364 for (i = 0; ospf6_nexthop_is_set (&v->nexthop[i]) &&
365 i < OSPF6_MULTI_PATH_LIMIT; i++)
366 ospf6_nexthop_copy (&route->nexthop[i], &v->nexthop[i]);
367
368 if (v->parent)
369 listnode_add_sort (v->parent->child_list, v);
370 route->route_option = v;
371
372 ospf6_route_add (route, result_table);
paul718e3742002-12-13 20:15:29 +0000373 return 0;
374}
375
hasso508e53e2004-05-18 18:57:06 +0000376void
377ospf6_spf_table_finish (struct ospf6_route_table *result_table)
378{
379 struct ospf6_route *route;
380 struct ospf6_vertex *v;
381 for (route = ospf6_route_head (result_table); route;
382 route = ospf6_route_next (route))
383 {
384 v = (struct ospf6_vertex *) route->route_option;
385 ospf6_vertex_delete (v);
386 ospf6_route_remove (route, result_table);
387 }
388}
389
390void
391ospf6_spf_calculation (u_int32_t router_id,
392 struct ospf6_route_table *result_table,
393 struct ospf6_area *oa)
394{
395 struct pqueue *candidate_list;
396 struct ospf6_vertex *root, *v, *w;
397 int i;
398 int size;
399 caddr_t lsdesc;
400 struct ospf6_lsa *lsa;
401
402 /* initialize */
403 candidate_list = pqueue_create ();
404 candidate_list->cmp = ospf6_vertex_cmp;
405
406 ospf6_spf_table_finish (result_table);
407
408 /* Install the calculating router itself as the root of the SPF tree */
409 /* construct root vertex */
410 lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_ROUTER), htonl (0),
411 router_id, oa->lsdb);
412 if (lsa == NULL)
413 return;
414 root = ospf6_vertex_create (lsa);
415 root->area = oa;
416 root->cost = 0;
417 root->hops = 0;
418 root->nexthop[0].ifindex = 0; /* should have been loopbak I/F ... */
419 inet_pton (AF_INET6, "::1", &root->nexthop[0].address);
420
421 /* Actually insert root to the candidate-list as the only candidate */
422 pqueue_enqueue (root, candidate_list);
423
424 /* Iterate until candidate-list becomes empty */
425 while (candidate_list->size)
426 {
427 /* get closest candidate from priority queue */
428 v = pqueue_dequeue (candidate_list);
429
430 /* install may result in merging and rejecting of the vertex */
431 if (ospf6_spf_install (v, result_table) < 0)
432 continue;
433
434 /* For each LS description in the just-added vertex V's LSA */
435 size = (VERTEX_IS_TYPE (ROUTER, v) ?
436 sizeof (struct ospf6_router_lsdesc) :
437 sizeof (struct ospf6_network_lsdesc));
438 for (lsdesc = OSPF6_LSA_HEADER_END (v->lsa->header) + 4;
439 lsdesc + size <= OSPF6_LSA_END (v->lsa->header); lsdesc += size)
440 {
441 lsa = ospf6_lsdesc_lsa (lsdesc, v);
442 if (lsa == NULL)
443 continue;
444
445 if (! ospf6_lsdesc_backlink (lsa, lsdesc, v))
446 continue;
447
448 w = ospf6_vertex_create (lsa);
449 w->area = oa;
450 w->parent = v;
451 if (VERTEX_IS_TYPE (ROUTER, v))
452 {
453 w->cost = v->cost + ROUTER_LSDESC_GET_METRIC (lsdesc);
454 w->hops = v->hops + (VERTEX_IS_TYPE (NETWORK, w) ? 0 : 1);
455 }
456 else /* NETWORK */
457 {
458 w->cost = v->cost;
459 w->hops = v->hops + 1;
460 }
461
462 /* nexthop calculation */
463 if (w->hops == 0)
464 w->nexthop[0].ifindex = ROUTER_LSDESC_GET_IFID (lsdesc);
465 else if (w->hops == 1 && v->hops == 0)
466 ospf6_nexthop_calc (w, v, lsdesc);
467 else
468 {
469 for (i = 0; ospf6_nexthop_is_set (&v->nexthop[i]) &&
470 i < OSPF6_MULTI_PATH_LIMIT; i++)
471 ospf6_nexthop_copy (&w->nexthop[i], &v->nexthop[i]);
472 }
473
474 /* add new candidate to the candidate_list */
475 if (IS_OSPF6_DEBUG_SPF (SUMMARY))
476 zlog_info (" New candidate: %s hops %d cost %d",
477 w->name, w->hops, w->cost);
478 pqueue_enqueue (w, candidate_list);
479 }
480 }
481
482 pqueue_delete (candidate_list);
483}
484
paul718e3742002-12-13 20:15:29 +0000485int
486ospf6_spf_calculation_thread (struct thread *t)
487{
hasso508e53e2004-05-18 18:57:06 +0000488 struct ospf6_area *oa;
489 struct timeval start, end, runtime;
paul718e3742002-12-13 20:15:29 +0000490
hasso508e53e2004-05-18 18:57:06 +0000491 oa = (struct ospf6_area *) THREAD_ARG (t);
492 oa->thread_spf_calculation = NULL;
paul718e3742002-12-13 20:15:29 +0000493
hasso508e53e2004-05-18 18:57:06 +0000494 if (IS_OSPF6_DEBUG_SPF (SUMMARY))
495 zlog_info ("SPF calculation for area %s", oa->name);
paul718e3742002-12-13 20:15:29 +0000496
497 /* execute SPF calculation */
498 gettimeofday (&start, (struct timezone *) NULL);
hasso508e53e2004-05-18 18:57:06 +0000499 ospf6_spf_calculation (oa->ospf6->router_id, oa->spf_table, oa);
paul718e3742002-12-13 20:15:29 +0000500 gettimeofday (&end, (struct timezone *) NULL);
501
hasso508e53e2004-05-18 18:57:06 +0000502 if (IS_OSPF6_DEBUG_SPF (SUMMARY))
paul718e3742002-12-13 20:15:29 +0000503 {
hasso508e53e2004-05-18 18:57:06 +0000504 timersub (&end, &start, &runtime);
505 zlog_info ("SPF calculation for area %s: runtime %ld sec %ld usec",
506 oa->name, runtime.tv_sec, runtime.tv_usec);
paul718e3742002-12-13 20:15:29 +0000507 }
508
hasso508e53e2004-05-18 18:57:06 +0000509 ospf6_intra_route_calculation (oa);
510 ospf6_intra_asbr_calculation (oa);
paul718e3742002-12-13 20:15:29 +0000511
512 return 0;
513}
514
515void
hasso508e53e2004-05-18 18:57:06 +0000516ospf6_spf_schedule (struct ospf6_area *oa)
paul718e3742002-12-13 20:15:29 +0000517{
hasso508e53e2004-05-18 18:57:06 +0000518 if (oa->thread_spf_calculation)
paul718e3742002-12-13 20:15:29 +0000519 return;
hasso508e53e2004-05-18 18:57:06 +0000520 oa->thread_spf_calculation =
521 thread_add_event (master, ospf6_spf_calculation_thread, oa, 0);
paul718e3742002-12-13 20:15:29 +0000522}
523
524void
hasso508e53e2004-05-18 18:57:06 +0000525ospf6_spf_display_subtree (struct vty *vty, char *prefix, int rest,
526 struct ospf6_vertex *v)
paul718e3742002-12-13 20:15:29 +0000527{
528 listnode node;
hasso508e53e2004-05-18 18:57:06 +0000529 struct ospf6_vertex *c;
530 char *next_prefix;
531 int len;
paul718e3742002-12-13 20:15:29 +0000532 int restnum;
paul718e3742002-12-13 20:15:29 +0000533
hasso508e53e2004-05-18 18:57:06 +0000534 /* "prefix" is the space prefix of the display line */
535 vty_out (vty, "%s+-%s [%d]%s", prefix, v->name, v->cost, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000536
hasso508e53e2004-05-18 18:57:06 +0000537 len = strlen (prefix) + 4;
538 next_prefix = (char *) malloc (len);
539 if (next_prefix == NULL)
paul718e3742002-12-13 20:15:29 +0000540 {
hasso508e53e2004-05-18 18:57:06 +0000541 vty_out (vty, "malloc failed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000542 return;
543 }
hasso508e53e2004-05-18 18:57:06 +0000544 snprintf (next_prefix, len, "%s%s", prefix, (rest ? "| " : " "));
paul718e3742002-12-13 20:15:29 +0000545
hasso508e53e2004-05-18 18:57:06 +0000546 restnum = listcount (v->child_list);
547 LIST_LOOP (v->child_list, c, node)
paul718e3742002-12-13 20:15:29 +0000548 {
hasso508e53e2004-05-18 18:57:06 +0000549 restnum--;
550 ospf6_spf_display_subtree (vty, next_prefix, restnum, c);
paul718e3742002-12-13 20:15:29 +0000551 }
552
hasso508e53e2004-05-18 18:57:06 +0000553 free (next_prefix);
paul718e3742002-12-13 20:15:29 +0000554}
555
hasso508e53e2004-05-18 18:57:06 +0000556DEFUN (debug_ospf6_spf_detail,
557 debug_ospf6_spf_detail_cmd,
558 "debug ospf6 spf detail",
559 DEBUG_STR
paul718e3742002-12-13 20:15:29 +0000560 OSPF6_STR
hasso508e53e2004-05-18 18:57:06 +0000561 "Debug SPF Calculation\n"
562 "Debug Detailed SPF\n"
563 )
paul718e3742002-12-13 20:15:29 +0000564{
hasso508e53e2004-05-18 18:57:06 +0000565 unsigned char level = 0;
566 level = OSPF6_DEBUG_SPF_SUMMARY | OSPF6_DEBUG_SPF_DETAIL;
567 OSPF6_DEBUG_SPF_ON (level);
paul718e3742002-12-13 20:15:29 +0000568 return CMD_SUCCESS;
569}
570
hasso508e53e2004-05-18 18:57:06 +0000571DEFUN (debug_ospf6_spf,
572 debug_ospf6_spf_cmd,
573 "debug ospf6 spf",
574 DEBUG_STR
paul718e3742002-12-13 20:15:29 +0000575 OSPF6_STR
hasso508e53e2004-05-18 18:57:06 +0000576 "Debug SPF Calculation\n"
577 )
paul718e3742002-12-13 20:15:29 +0000578{
hasso508e53e2004-05-18 18:57:06 +0000579 unsigned char level = 0;
580 level = OSPF6_DEBUG_SPF_SUMMARY;
581 OSPF6_DEBUG_SPF_ON (level);
582 return CMD_SUCCESS;
paul718e3742002-12-13 20:15:29 +0000583}
584
hasso508e53e2004-05-18 18:57:06 +0000585DEFUN (no_debug_ospf6_spf_detail,
586 no_debug_ospf6_spf_detail_cmd,
587 "no debug ospf6 spf detail",
588 NO_STR
589 DEBUG_STR
paul718e3742002-12-13 20:15:29 +0000590 OSPF6_STR
hasso508e53e2004-05-18 18:57:06 +0000591 "Quit Debugging SPF Calculation\n"
592 "Quit Debugging Detailed SPF (change to debug summary)\n"
593 )
594{
595 unsigned char level = 0;
596 level = OSPF6_DEBUG_SPF_DETAIL;
597 OSPF6_DEBUG_SPF_OFF (level);
598 return CMD_SUCCESS;
599}
paul718e3742002-12-13 20:15:29 +0000600
hasso508e53e2004-05-18 18:57:06 +0000601DEFUN (no_debug_ospf6_spf,
602 no_debug_ospf6_spf_cmd,
603 "no debug ospf6 spf",
604 NO_STR
605 DEBUG_STR
paul718e3742002-12-13 20:15:29 +0000606 OSPF6_STR
hasso508e53e2004-05-18 18:57:06 +0000607 "Quit Debugging SPF Calculation\n"
608 )
609{
610 unsigned char level = 0;
611 level = OSPF6_DEBUG_SPF_SUMMARY | OSPF6_DEBUG_SPF_DETAIL;
612 OSPF6_DEBUG_SPF_OFF (level);
613 return CMD_SUCCESS;
614}
615
616int
617config_write_ospf6_debug_spf (struct vty *vty)
618{
619 if (IS_OSPF6_DEBUG_SPF (DETAIL))
620 vty_out (vty, "debug ospf6 spf detail%s", VTY_NEWLINE);
621 else if (IS_OSPF6_DEBUG_SPF (SUMMARY))
622 vty_out (vty, "debug ospf6 spf%s", VTY_NEWLINE);
623 return 0;
624}
625
626void
627install_element_ospf6_debug_spf ()
628{
629 install_element (ENABLE_NODE, &debug_ospf6_spf_cmd);
630 install_element (ENABLE_NODE, &debug_ospf6_spf_detail_cmd);
631 install_element (ENABLE_NODE, &no_debug_ospf6_spf_cmd);
632 install_element (ENABLE_NODE, &no_debug_ospf6_spf_detail_cmd);
633 install_element (CONFIG_NODE, &debug_ospf6_spf_cmd);
634 install_element (CONFIG_NODE, &debug_ospf6_spf_detail_cmd);
635 install_element (CONFIG_NODE, &no_debug_ospf6_spf_cmd);
636 install_element (CONFIG_NODE, &no_debug_ospf6_spf_detail_cmd);
637}
paul718e3742002-12-13 20:15:29 +0000638
639void
640ospf6_spf_init ()
641{
paul718e3742002-12-13 20:15:29 +0000642}
643
hasso508e53e2004-05-18 18:57:06 +0000644