]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_spf.c
SVN revision 907 from Zebra cvs repository.
[mirror_frr.git] / ospf6d / ospf6_spf.c
CommitLineData
718e3744 1/*
508e53e2 2 * Copyright (C) 2003 Yasuhiro Ohara
718e3744 3 *
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 */
508e53e2 21
718e3744 22/* Shortest Path First calculation for OSPFv3 */
23
508e53e2 24#include <zebra.h>
718e3744 25
508e53e2 26#include "log.h"
27#include "memory.h"
28#include "command.h"
29#include "vty.h"
718e3744 30#include "prefix.h"
508e53e2 31#include "pqueue.h"
32#include "linklist.h"
33#include "thread.h"
718e3744 34
718e3744 35#include "ospf6_lsa.h"
36#include "ospf6_lsdb.h"
37#include "ospf6_route.h"
508e53e2 38#include "ospf6_area.h"
718e3744 39#include "ospf6_spf.h"
508e53e2 40#include "ospf6_intra.h"
718e3744 41#include "ospf6_interface.h"
049207c3 42#include "ospf6d.h"
718e3744 43
508e53e2 44unsigned char conf_debug_ospf6_spf = 0;
718e3744 45
46int
508e53e2 47ospf6_vertex_cmp (void *a, void *b)
718e3744 48{
508e53e2 49 struct ospf6_vertex *va = (struct ospf6_vertex *) a;
50 struct ospf6_vertex *vb = (struct ospf6_vertex *) b;
718e3744 51
508e53e2 52 /* ascending order */
53 return (va->cost - vb->cost);
718e3744 54}
55
508e53e2 56int
57ospf6_vertex_id_cmp (void *a, void *b)
718e3744 58{
508e53e2 59 struct ospf6_vertex *va = (struct ospf6_vertex *) a;
60 struct ospf6_vertex *vb = (struct ospf6_vertex *) b;
61 int ret = 0;
718e3744 62
508e53e2 63 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;
718e3744 67
508e53e2 68 ret = ntohl (ospf6_linkstate_prefix_id (&va->vertex_id)) -
69 ntohl (ospf6_linkstate_prefix_id (&vb->vertex_id));
718e3744 70 return ret;
71}
72
508e53e2 73struct ospf6_vertex *
74ospf6_vertex_create (struct ospf6_lsa *lsa)
718e3744 75{
508e53e2 76 struct ospf6_vertex *v;
77 int i;
718e3744 78
508e53e2 79 v = (struct ospf6_vertex *)
80 XMALLOC (MTYPE_OSPF6_VERTEX, sizeof (struct ospf6_vertex));
718e3744 81
508e53e2 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;
718e3744 87 else
508e53e2 88 assert (0);
718e3744 89
508e53e2 90 /* vertex_id */
91 ospf6_linkstate_prefix (lsa->header->adv_router, lsa->header->id,
92 &v->vertex_id);
718e3744 93
508e53e2 94 /* name */
95 ospf6_linkstate_prefix2str (&v->vertex_id, v->name, sizeof (v->name));
718e3744 96
508e53e2 97 /* Associated LSA */
98 v->lsa = lsa;
718e3744 99
508e53e2 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);
718e3744 105
508e53e2 106 for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
107 ospf6_nexthop_clear (&v->nexthop[i]);
718e3744 108
508e53e2 109 v->parent = NULL;
110 v->child_list = list_new ();
111 v->child_list->cmp = ospf6_vertex_id_cmp;
718e3744 112
508e53e2 113 return v;
718e3744 114}
115
508e53e2 116void
117ospf6_vertex_delete (struct ospf6_vertex *v)
718e3744 118{
508e53e2 119 list_delete (v->child_list);
120 XFREE (MTYPE_OSPF6_VERTEX, v);
718e3744 121}
122
508e53e2 123struct ospf6_lsa *
124ospf6_lsdesc_lsa (caddr_t lsdesc, struct ospf6_vertex *v)
718e3744 125{
508e53e2 126 struct ospf6_lsa *lsa;
127 u_int16_t type = 0;
128 u_int32_t id = 0, adv_router = 0;
718e3744 129
508e53e2 130 if (VERTEX_IS_TYPE (NETWORK, v))
718e3744 131 {
508e53e2 132 type = htons (OSPF6_LSTYPE_ROUTER);
133 id = htonl (0);
134 adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc);
718e3744 135 }
136 else
137 {
508e53e2 138 if (ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, lsdesc))
718e3744 139 {
508e53e2 140 type = htons (OSPF6_LSTYPE_ROUTER);
718e3744 141 id = htonl (0);
508e53e2 142 adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc);
718e3744 143 }
508e53e2 144 else if (ROUTER_LSDESC_IS_TYPE (TRANSIT_NETWORK, lsdesc))
718e3744 145 {
508e53e2 146 type = htons (OSPF6_LSTYPE_NETWORK);
147 id = htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc));
148 adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc);
718e3744 149 }
718e3744 150 }
151
508e53e2 152 lsa = ospf6_lsdb_lookup (type, id, adv_router, v->area->lsdb);
718e3744 153
508e53e2 154 if (IS_OSPF6_DEBUG_SPF (DETAIL))
718e3744 155 {
508e53e2 156 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);
718e3744 164 }
165
508e53e2 166 return lsa;
718e3744 167}
168
508e53e2 169char *
170ospf6_lsdesc_backlink (struct ospf6_lsa *lsa,
171 caddr_t lsdesc, struct ospf6_vertex *v)
718e3744 172{
508e53e2 173 caddr_t backlink, found = NULL;
174 int size;
718e3744 175
508e53e2 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)
718e3744 181 {
508e53e2 182 assert (! (OSPF6_LSA_IS_TYPE (NETWORK, lsa) &&
183 VERTEX_IS_TYPE (NETWORK, v)));
718e3744 184
508e53e2 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 }
718e3744 213 }
718e3744 214
508e53e2 215 if (IS_OSPF6_DEBUG_SPF (DETAIL))
216 zlog_info (" Backlink %s", (found ? "OK" : "FAIL"));
718e3744 217
508e53e2 218 return found;
718e3744 219}
220
508e53e2 221void
222ospf6_nexthop_calc (struct ospf6_vertex *w, struct ospf6_vertex *v,
223 caddr_t lsdesc)
718e3744 224{
508e53e2 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];
718e3744 232
508e53e2 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)
718e3744 238 {
508e53e2 239 if (IS_OSPF6_DEBUG_SPF (SUMMARY))
240 zlog_warn ("Can't find interface in SPF: ifindex %d", ifindex);
241 return;
718e3744 242 }
243
508e53e2 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));
718e3744 248
508e53e2 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))
718e3744 252 {
508e53e2 253 if (VERTEX_IS_TYPE (ROUTER, v) &&
254 htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc)) != lsa->header->id)
718e3744 255 continue;
256
508e53e2 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 }
718e3744 263
508e53e2 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 }
718e3744 271 }
272
508e53e2 273 if (i == 0 && IS_OSPF6_DEBUG_SPF (SUMMARY))
274 zlog_info ("No nexthop for %s found", w->name);
718e3744 275}
276
508e53e2 277int
278ospf6_spf_install (struct ospf6_vertex *v,
279 struct ospf6_route_table *result_table)
718e3744 280{
508e53e2 281 struct ospf6_route *route;
282 int i, j;
283 struct ospf6_vertex *prev, *w;
718e3744 284 listnode node;
718e3744 285
508e53e2 286 if (IS_OSPF6_DEBUG_SPF (SUMMARY))
287 zlog_info ("SPF install %s hops %d cost %d",
288 v->name, v->hops, v->cost);
718e3744 289
508e53e2 290 route = ospf6_route_lookup (&v->vertex_id, result_table);
291 if (route && route->path.cost < v->cost)
718e3744 292 {
508e53e2 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;
718e3744 298 }
508e53e2 299 else if (route && route->path.cost == v->cost)
718e3744 300 {
508e53e2 301 if (IS_OSPF6_DEBUG_SPF (SUMMARY))
302 zlog_info (" another path found, merge");
718e3744 303
508e53e2 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 }
718e3744 321
508e53e2 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);
718e3744 333
508e53e2 334 ospf6_vertex_delete (prev);
335 route->route_option = v;
336 }
337 else
338 ospf6_vertex_delete (v);
718e3744 339
508e53e2 340 return -1;
718e3744 341 }
508e53e2 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);
373 return 0;
718e3744 374}
375
508e53e2 376void
377ospf6_spf_table_finish (struct ospf6_route_table *result_table)
718e3744 378{
508e53e2 379 struct ospf6_route *route;
718e3744 380 struct ospf6_vertex *v;
508e53e2 381 for (route = ospf6_route_head (result_table); route;
382 route = ospf6_route_next (route))
718e3744 383 {
508e53e2 384 v = (struct ospf6_vertex *) route->route_option;
385 ospf6_vertex_delete (v);
386 ospf6_route_remove (route, result_table);
718e3744 387 }
718e3744 388}
389
508e53e2 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;
718e3744 401
508e53e2 402 /* initialize */
403 candidate_list = pqueue_create ();
404 candidate_list->cmp = ospf6_vertex_cmp;
718e3744 405
508e53e2 406 ospf6_spf_table_finish (result_table);
718e3744 407
508e53e2 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);
718e3744 420
508e53e2 421 /* Actually insert root to the candidate-list as the only candidate */
422 pqueue_enqueue (root, candidate_list);
718e3744 423
508e53e2 424 /* Iterate until candidate-list becomes empty */
425 while (candidate_list->size)
718e3744 426 {
508e53e2 427 /* get closest candidate from priority queue */
428 v = pqueue_dequeue (candidate_list);
718e3744 429
508e53e2 430 /* install may result in merging and rejecting of the vertex */
431 if (ospf6_spf_install (v, result_table) < 0)
432 continue;
718e3744 433
508e53e2 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)
718e3744 440 {
508e53e2 441 lsa = ospf6_lsdesc_lsa (lsdesc, v);
442 if (lsa == NULL)
718e3744 443 continue;
444
508e53e2 445 if (! ospf6_lsdesc_backlink (lsa, lsdesc, v))
446 continue;
718e3744 447
508e53e2 448 w = ospf6_vertex_create (lsa);
449 w->area = oa;
450 w->parent = v;
451 if (VERTEX_IS_TYPE (ROUTER, v))
718e3744 452 {
508e53e2 453 w->cost = v->cost + ROUTER_LSDESC_GET_METRIC (lsdesc);
454 w->hops = v->hops + (VERTEX_IS_TYPE (NETWORK, w) ? 0 : 1);
718e3744 455 }
508e53e2 456 else /* NETWORK */
718e3744 457 {
508e53e2 458 w->cost = v->cost;
459 w->hops = v->hops + 1;
718e3744 460 }
461
508e53e2 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);
718e3744 467 else
468 {
508e53e2 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]);
718e3744 472 }
473
508e53e2 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);
718e3744 479 }
480 }
481
508e53e2 482 pqueue_delete (candidate_list);
718e3744 483}
484
485int
486ospf6_spf_calculation_thread (struct thread *t)
487{
508e53e2 488 struct ospf6_area *oa;
489 struct timeval start, end, runtime;
718e3744 490
508e53e2 491 oa = (struct ospf6_area *) THREAD_ARG (t);
492 oa->thread_spf_calculation = NULL;
718e3744 493
508e53e2 494 if (IS_OSPF6_DEBUG_SPF (SUMMARY))
495 zlog_info ("SPF calculation for area %s", oa->name);
718e3744 496
497 /* execute SPF calculation */
498 gettimeofday (&start, (struct timezone *) NULL);
508e53e2 499 ospf6_spf_calculation (oa->ospf6->router_id, oa->spf_table, oa);
718e3744 500 gettimeofday (&end, (struct timezone *) NULL);
501
508e53e2 502 if (IS_OSPF6_DEBUG_SPF (SUMMARY))
718e3744 503 {
508e53e2 504 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);
718e3744 507 }
508
508e53e2 509 ospf6_intra_route_calculation (oa);
510 ospf6_intra_asbr_calculation (oa);
718e3744 511
512 return 0;
513}
514
515void
508e53e2 516ospf6_spf_schedule (struct ospf6_area *oa)
718e3744 517{
508e53e2 518 if (oa->thread_spf_calculation)
718e3744 519 return;
508e53e2 520 oa->thread_spf_calculation =
521 thread_add_event (master, ospf6_spf_calculation_thread, oa, 0);
718e3744 522}
523
524void
508e53e2 525ospf6_spf_display_subtree (struct vty *vty, char *prefix, int rest,
526 struct ospf6_vertex *v)
718e3744 527{
528 listnode node;
508e53e2 529 struct ospf6_vertex *c;
530 char *next_prefix;
531 int len;
532 int restnum;
718e3744 533
508e53e2 534 /* "prefix" is the space prefix of the display line */
049207c3 535 vty_out (vty, "%s+-%s [%d]%s", prefix, v->name, v->cost, VNL);
718e3744 536
508e53e2 537 len = strlen (prefix) + 4;
538 next_prefix = (char *) malloc (len);
539 if (next_prefix == NULL)
718e3744 540 {
049207c3 541 vty_out (vty, "malloc failed%s", VNL);
508e53e2 542 return;
718e3744 543 }
508e53e2 544 snprintf (next_prefix, len, "%s%s", prefix, (rest ? "| " : " "));
718e3744 545
508e53e2 546 restnum = listcount (v->child_list);
547 LIST_LOOP (v->child_list, c, node)
718e3744 548 {
508e53e2 549 restnum--;
550 ospf6_spf_display_subtree (vty, next_prefix, restnum, c);
718e3744 551 }
718e3744 552
508e53e2 553 free (next_prefix);
718e3744 554}
555
508e53e2 556DEFUN (debug_ospf6_spf_detail,
557 debug_ospf6_spf_detail_cmd,
558 "debug ospf6 spf detail",
559 DEBUG_STR
560 OSPF6_STR
561 "Debug SPF Calculation\n"
562 "Debug Detailed SPF\n"
563 )
718e3744 564{
508e53e2 565 unsigned char level = 0;
566 level = OSPF6_DEBUG_SPF_SUMMARY | OSPF6_DEBUG_SPF_DETAIL;
567 OSPF6_DEBUG_SPF_ON (level);
568 return CMD_SUCCESS;
718e3744 569}
570
508e53e2 571DEFUN (debug_ospf6_spf,
572 debug_ospf6_spf_cmd,
573 "debug ospf6 spf",
574 DEBUG_STR
718e3744 575 OSPF6_STR
508e53e2 576 "Debug SPF Calculation\n"
577 )
718e3744 578{
508e53e2 579 unsigned char level = 0;
580 level = OSPF6_DEBUG_SPF_SUMMARY;
581 OSPF6_DEBUG_SPF_ON (level);
718e3744 582 return CMD_SUCCESS;
583}
584
508e53e2 585DEFUN (no_debug_ospf6_spf_detail,
586 no_debug_ospf6_spf_detail_cmd,
587 "no debug ospf6 spf detail",
588 NO_STR
589 DEBUG_STR
590 OSPF6_STR
591 "Quit Debugging SPF Calculation\n"
592 "Quit Debugging Detailed SPF (change to debug summary)\n"
593 )
718e3744 594{
508e53e2 595 unsigned char level = 0;
596 level = OSPF6_DEBUG_SPF_DETAIL;
597 OSPF6_DEBUG_SPF_OFF (level);
598 return CMD_SUCCESS;
718e3744 599}
600
508e53e2 601DEFUN (no_debug_ospf6_spf,
602 no_debug_ospf6_spf_cmd,
603 "no debug ospf6 spf",
604 NO_STR
605 DEBUG_STR
718e3744 606 OSPF6_STR
508e53e2 607 "Quit Debugging SPF Calculation\n"
608 )
718e3744 609{
508e53e2 610 unsigned char level = 0;
611 level = OSPF6_DEBUG_SPF_SUMMARY | OSPF6_DEBUG_SPF_DETAIL;
612 OSPF6_DEBUG_SPF_OFF (level);
718e3744 613 return CMD_SUCCESS;
614}
615
508e53e2 616int
617config_write_ospf6_debug_spf (struct vty *vty)
718e3744 618{
508e53e2 619 if (IS_OSPF6_DEBUG_SPF (DETAIL))
049207c3 620 vty_out (vty, "debug ospf6 spf detail%s", VNL);
508e53e2 621 else if (IS_OSPF6_DEBUG_SPF (SUMMARY))
049207c3 622 vty_out (vty, "debug ospf6 spf%s", VNL);
508e53e2 623 return 0;
718e3744 624}
625
508e53e2 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}
718e3744 638
639void
640ospf6_spf_init ()
641{
718e3744 642}
643
508e53e2 644