2 * Copyright (C) 2003 Yasuhiro Ohara
4 * This file is part of GNU Zebra.
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
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.
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.
22 /* Shortest Path First calculation for OSPFv3 */
35 #include "ospf6_lsa.h"
36 #include "ospf6_lsdb.h"
37 #include "ospf6_route.h"
38 #include "ospf6_area.h"
39 #include "ospf6_spf.h"
40 #include "ospf6_intra.h"
41 #include "ospf6_interface.h"
44 unsigned char conf_debug_ospf6_spf
= 0;
47 ospf6_vertex_cmp (void *a
, void *b
)
49 struct ospf6_vertex
*va
= (struct ospf6_vertex
*) a
;
50 struct ospf6_vertex
*vb
= (struct ospf6_vertex
*) b
;
53 if (va
->cost
!= vb
->cost
)
54 return (va
->cost
- vb
->cost
);
55 return (va
->hops
- vb
->hops
);
59 ospf6_vertex_id_cmp (void *a
, void *b
)
61 struct ospf6_vertex
*va
= (struct ospf6_vertex
*) a
;
62 struct ospf6_vertex
*vb
= (struct ospf6_vertex
*) b
;
65 ret
= ntohl (ospf6_linkstate_prefix_adv_router (&va
->vertex_id
)) -
66 ntohl (ospf6_linkstate_prefix_adv_router (&vb
->vertex_id
));
70 ret
= ntohl (ospf6_linkstate_prefix_id (&va
->vertex_id
)) -
71 ntohl (ospf6_linkstate_prefix_id (&vb
->vertex_id
));
75 static struct ospf6_vertex
*
76 ospf6_vertex_create (struct ospf6_lsa
*lsa
)
78 struct ospf6_vertex
*v
;
81 v
= (struct ospf6_vertex
*)
82 XMALLOC (MTYPE_OSPF6_VERTEX
, sizeof (struct ospf6_vertex
));
85 if (ntohs (lsa
->header
->type
) == OSPF6_LSTYPE_ROUTER
)
86 v
->type
= OSPF6_VERTEX_TYPE_ROUTER
;
87 else if (ntohs (lsa
->header
->type
) == OSPF6_LSTYPE_NETWORK
)
88 v
->type
= OSPF6_VERTEX_TYPE_NETWORK
;
93 ospf6_linkstate_prefix (lsa
->header
->adv_router
, lsa
->header
->id
,
97 ospf6_linkstate_prefix2str (&v
->vertex_id
, v
->name
, sizeof (v
->name
));
102 /* capability bits + options */
103 v
->capability
= *(u_char
*)(OSPF6_LSA_HEADER_END (lsa
->header
));
104 v
->options
[0] = *(u_char
*)(OSPF6_LSA_HEADER_END (lsa
->header
) + 1);
105 v
->options
[1] = *(u_char
*)(OSPF6_LSA_HEADER_END (lsa
->header
) + 2);
106 v
->options
[2] = *(u_char
*)(OSPF6_LSA_HEADER_END (lsa
->header
) + 3);
108 for (i
= 0; i
< OSPF6_MULTI_PATH_LIMIT
; i
++)
109 ospf6_nexthop_clear (&v
->nexthop
[i
]);
112 v
->child_list
= list_new ();
113 v
->child_list
->cmp
= ospf6_vertex_id_cmp
;
119 ospf6_vertex_delete (struct ospf6_vertex
*v
)
121 list_delete (v
->child_list
);
122 XFREE (MTYPE_OSPF6_VERTEX
, v
);
125 static struct ospf6_lsa
*
126 ospf6_lsdesc_lsa (caddr_t lsdesc
, struct ospf6_vertex
*v
)
128 struct ospf6_lsa
*lsa
;
130 u_int32_t id
= 0, adv_router
= 0;
132 if (VERTEX_IS_TYPE (NETWORK
, v
))
134 type
= htons (OSPF6_LSTYPE_ROUTER
);
136 adv_router
= NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc
);
140 if (ROUTER_LSDESC_IS_TYPE (POINTTOPOINT
, lsdesc
))
142 type
= htons (OSPF6_LSTYPE_ROUTER
);
144 adv_router
= ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc
);
146 else if (ROUTER_LSDESC_IS_TYPE (TRANSIT_NETWORK
, lsdesc
))
148 type
= htons (OSPF6_LSTYPE_NETWORK
);
149 id
= htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc
));
150 adv_router
= ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc
);
154 lsa
= ospf6_lsdb_lookup (type
, id
, adv_router
, v
->area
->lsdb
);
156 if (IS_OSPF6_DEBUG_SPF (PROCESS
))
158 char ibuf
[16], abuf
[16];
159 inet_ntop (AF_INET
, &id
, ibuf
, sizeof (ibuf
));
160 inet_ntop (AF_INET
, &adv_router
, abuf
, sizeof (abuf
));
162 zlog_debug (" Link to: %s", lsa
->name
);
164 zlog_debug (" Link to: [%s Id:%s Adv:%s] No LSA",
165 ospf6_lstype_name (type
), ibuf
, abuf
);
172 ospf6_lsdesc_backlink (struct ospf6_lsa
*lsa
,
173 caddr_t lsdesc
, struct ospf6_vertex
*v
)
175 caddr_t backlink
, found
= NULL
;
178 size
= (OSPF6_LSA_IS_TYPE (ROUTER
, lsa
) ?
179 sizeof (struct ospf6_router_lsdesc
) :
180 sizeof (struct ospf6_network_lsdesc
));
181 for (backlink
= OSPF6_LSA_HEADER_END (lsa
->header
) + 4;
182 backlink
+ size
<= OSPF6_LSA_END (lsa
->header
); backlink
+= size
)
184 assert (! (OSPF6_LSA_IS_TYPE (NETWORK
, lsa
) &&
185 VERTEX_IS_TYPE (NETWORK
, v
)));
187 if (OSPF6_LSA_IS_TYPE (NETWORK
, lsa
) &&
188 NETWORK_LSDESC_GET_NBR_ROUTERID (backlink
)
189 == v
->lsa
->header
->adv_router
)
191 else if (VERTEX_IS_TYPE (NETWORK
, v
) &&
192 ROUTER_LSDESC_IS_TYPE (TRANSIT_NETWORK
, backlink
) &&
193 ROUTER_LSDESC_GET_NBR_ROUTERID (backlink
)
194 == v
->lsa
->header
->adv_router
&&
195 ROUTER_LSDESC_GET_NBR_IFID (backlink
)
196 == ntohl (v
->lsa
->header
->id
))
200 if (! ROUTER_LSDESC_IS_TYPE (POINTTOPOINT
, backlink
) ||
201 ! ROUTER_LSDESC_IS_TYPE (POINTTOPOINT
, lsdesc
))
203 if (ROUTER_LSDESC_GET_NBR_IFID (backlink
) !=
204 ROUTER_LSDESC_GET_IFID (lsdesc
) ||
205 ROUTER_LSDESC_GET_NBR_IFID (lsdesc
) !=
206 ROUTER_LSDESC_GET_IFID (backlink
))
208 if (ROUTER_LSDESC_GET_NBR_ROUTERID (backlink
) !=
209 v
->lsa
->header
->adv_router
||
210 ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc
) !=
211 lsa
->header
->adv_router
)
217 if (IS_OSPF6_DEBUG_SPF (PROCESS
))
218 zlog_debug (" Backlink %s", (found
? "OK" : "FAIL"));
224 ospf6_nexthop_calc (struct ospf6_vertex
*w
, struct ospf6_vertex
*v
,
228 struct ospf6_interface
*oi
;
230 u_int32_t adv_router
;
231 struct ospf6_lsa
*lsa
;
232 struct ospf6_link_lsa
*link_lsa
;
235 assert (VERTEX_IS_TYPE (ROUTER
, w
));
236 ifindex
= (VERTEX_IS_TYPE (NETWORK
, v
) ? v
->nexthop
[0].ifindex
:
237 ROUTER_LSDESC_GET_IFID (lsdesc
));
238 oi
= ospf6_interface_lookup_by_ifindex (ifindex
);
241 if (IS_OSPF6_DEBUG_SPF (PROCESS
))
242 zlog_debug ("Can't find interface in SPF: ifindex %d", ifindex
);
246 type
= htons (OSPF6_LSTYPE_LINK
);
247 adv_router
= (VERTEX_IS_TYPE (NETWORK
, v
) ?
248 NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc
) :
249 ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc
));
252 for (lsa
= ospf6_lsdb_type_router_head (type
, adv_router
, oi
->lsdb
); lsa
;
253 lsa
= ospf6_lsdb_type_router_next (type
, adv_router
, lsa
))
255 if (VERTEX_IS_TYPE (ROUTER
, v
) &&
256 htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc
)) != lsa
->header
->id
)
259 link_lsa
= (struct ospf6_link_lsa
*) OSPF6_LSA_HEADER_END (lsa
->header
);
260 if (IS_OSPF6_DEBUG_SPF (PROCESS
))
262 inet_ntop (AF_INET6
, &link_lsa
->linklocal_addr
, buf
, sizeof (buf
));
263 zlog_debug (" nexthop %s from %s", buf
, lsa
->name
);
266 if (i
< OSPF6_MULTI_PATH_LIMIT
)
268 memcpy (&w
->nexthop
[i
].address
, &link_lsa
->linklocal_addr
,
269 sizeof (struct in6_addr
));
270 w
->nexthop
[i
].ifindex
= ifindex
;
275 if (i
== 0 && IS_OSPF6_DEBUG_SPF (PROCESS
))
276 zlog_debug ("No nexthop for %s found", w
->name
);
280 ospf6_spf_install (struct ospf6_vertex
*v
,
281 struct ospf6_route_table
*result_table
)
283 struct ospf6_route
*route
;
285 struct ospf6_vertex
*prev
;
287 if (IS_OSPF6_DEBUG_SPF (PROCESS
))
288 zlog_debug ("SPF install %s hops %d cost %d",
289 v
->name
, v
->hops
, v
->cost
);
291 route
= ospf6_route_lookup (&v
->vertex_id
, result_table
);
292 if (route
&& route
->path
.cost
< v
->cost
)
294 if (IS_OSPF6_DEBUG_SPF (PROCESS
))
295 zlog_debug (" already installed with lower cost (%d), ignore",
297 ospf6_vertex_delete (v
);
300 else if (route
&& route
->path
.cost
== v
->cost
)
302 if (IS_OSPF6_DEBUG_SPF (PROCESS
))
303 zlog_debug (" another path found, merge");
305 for (i
= 0; ospf6_nexthop_is_set (&v
->nexthop
[i
]) &&
306 i
< OSPF6_MULTI_PATH_LIMIT
; i
++)
308 for (j
= 0; j
< OSPF6_MULTI_PATH_LIMIT
; j
++)
310 if (ospf6_nexthop_is_set (&route
->nexthop
[j
]))
312 if (ospf6_nexthop_is_same (&route
->nexthop
[j
],
318 ospf6_nexthop_copy (&route
->nexthop
[j
], &v
->nexthop
[i
]);
323 prev
= (struct ospf6_vertex
*) route
->route_option
;
324 assert (prev
->hops
<= v
->hops
);
325 ospf6_vertex_delete (v
);
330 /* There should be no case where candidate being installed (variable
331 "v") is closer than the one in the SPF tree (variable "route").
332 In the case something has gone wrong with the behavior of
335 /* the case where the route exists already is handled and returned
337 assert (route
== NULL
);
339 route
= ospf6_route_create ();
340 memcpy (&route
->prefix
, &v
->vertex_id
, sizeof (struct prefix
));
341 route
->type
= OSPF6_DEST_TYPE_LINKSTATE
;
342 route
->path
.type
= OSPF6_PATH_TYPE_INTRA
;
343 route
->path
.origin
.type
= v
->lsa
->header
->type
;
344 route
->path
.origin
.id
= v
->lsa
->header
->id
;
345 route
->path
.origin
.adv_router
= v
->lsa
->header
->adv_router
;
346 route
->path
.metric_type
= 1;
347 route
->path
.cost
= v
->cost
;
348 route
->path
.cost_e2
= v
->hops
;
349 route
->path
.router_bits
= v
->capability
;
350 route
->path
.options
[0] = v
->options
[0];
351 route
->path
.options
[1] = v
->options
[1];
352 route
->path
.options
[2] = v
->options
[2];
354 for (i
= 0; ospf6_nexthop_is_set (&v
->nexthop
[i
]) &&
355 i
< OSPF6_MULTI_PATH_LIMIT
; i
++)
356 ospf6_nexthop_copy (&route
->nexthop
[i
], &v
->nexthop
[i
]);
359 listnode_add_sort (v
->parent
->child_list
, v
);
360 route
->route_option
= v
;
362 ospf6_route_add (route
, result_table
);
367 ospf6_spf_table_finish (struct ospf6_route_table
*result_table
)
369 struct ospf6_route
*route
;
370 struct ospf6_vertex
*v
;
371 for (route
= ospf6_route_head (result_table
); route
;
372 route
= ospf6_route_next (route
))
374 v
= (struct ospf6_vertex
*) route
->route_option
;
375 ospf6_vertex_delete (v
);
376 ospf6_route_remove (route
, result_table
);
380 /* RFC2328 16.1. Calculating the shortest-path tree for an area */
381 /* RFC2740 3.8.1. Calculating the shortest path tree for an area */
383 ospf6_spf_calculation (u_int32_t router_id
,
384 struct ospf6_route_table
*result_table
,
385 struct ospf6_area
*oa
)
387 struct pqueue
*candidate_list
;
388 struct ospf6_vertex
*root
, *v
, *w
;
392 struct ospf6_lsa
*lsa
;
394 ospf6_spf_table_finish (result_table
);
396 /* Install the calculating router itself as the root of the SPF tree */
397 /* construct root vertex */
398 lsa
= ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_ROUTER
), htonl (0),
399 router_id
, oa
->lsdb
);
404 candidate_list
= pqueue_create ();
405 candidate_list
->cmp
= ospf6_vertex_cmp
;
407 root
= ospf6_vertex_create (lsa
);
411 root
->nexthop
[0].ifindex
= 0; /* loopbak I/F is better ... */
412 inet_pton (AF_INET6
, "::1", &root
->nexthop
[0].address
);
414 /* Actually insert root to the candidate-list as the only candidate */
415 pqueue_enqueue (root
, candidate_list
);
417 /* Iterate until candidate-list becomes empty */
418 while (candidate_list
->size
)
420 /* get closest candidate from priority queue */
421 v
= pqueue_dequeue (candidate_list
);
423 /* installing may result in merging or rejecting of the vertex */
424 if (ospf6_spf_install (v
, result_table
) < 0)
427 /* For each LS description in the just-added vertex V's LSA */
428 size
= (VERTEX_IS_TYPE (ROUTER
, v
) ?
429 sizeof (struct ospf6_router_lsdesc
) :
430 sizeof (struct ospf6_network_lsdesc
));
431 for (lsdesc
= OSPF6_LSA_HEADER_END (v
->lsa
->header
) + 4;
432 lsdesc
+ size
<= OSPF6_LSA_END (v
->lsa
->header
); lsdesc
+= size
)
434 lsa
= ospf6_lsdesc_lsa (lsdesc
, v
);
438 if (! ospf6_lsdesc_backlink (lsa
, lsdesc
, v
))
441 w
= ospf6_vertex_create (lsa
);
444 if (VERTEX_IS_TYPE (ROUTER
, v
))
446 w
->cost
= v
->cost
+ ROUTER_LSDESC_GET_METRIC (lsdesc
);
447 w
->hops
= v
->hops
+ (VERTEX_IS_TYPE (NETWORK
, w
) ? 0 : 1);
452 w
->hops
= v
->hops
+ 1;
455 /* nexthop calculation */
457 w
->nexthop
[0].ifindex
= ROUTER_LSDESC_GET_IFID (lsdesc
);
458 else if (w
->hops
== 1 && v
->hops
== 0)
459 ospf6_nexthop_calc (w
, v
, lsdesc
);
462 for (i
= 0; ospf6_nexthop_is_set (&v
->nexthop
[i
]) &&
463 i
< OSPF6_MULTI_PATH_LIMIT
; i
++)
464 ospf6_nexthop_copy (&w
->nexthop
[i
], &v
->nexthop
[i
]);
467 /* add new candidate to the candidate_list */
468 if (IS_OSPF6_DEBUG_SPF (PROCESS
))
469 zlog_debug (" New candidate: %s hops %d cost %d",
470 w
->name
, w
->hops
, w
->cost
);
471 pqueue_enqueue (w
, candidate_list
);
475 pqueue_delete (candidate_list
);
479 ospf6_spf_log_database (struct ospf6_area
*oa
)
481 char *p
, *end
, buffer
[256];
482 struct listnode
*node
;
483 struct ospf6_interface
*oi
;
486 end
= buffer
+ sizeof (buffer
);
488 snprintf (p
, end
- p
, "SPF on DB (#LSAs):");
489 p
= (buffer
+ strlen (buffer
) < end
? buffer
+ strlen (buffer
) : end
);
490 snprintf (p
, end
- p
, " Area %s: %d", oa
->name
, oa
->lsdb
->count
);
491 p
= (buffer
+ strlen (buffer
) < end
? buffer
+ strlen (buffer
) : end
);
493 for (ALL_LIST_ELEMENTS_RO (oa
->if_list
, node
, oi
))
495 snprintf (p
, end
- p
, " I/F %s: %d",
496 oi
->interface
->name
, oi
->lsdb
->count
);
497 p
= (buffer
+ strlen (buffer
) < end
? buffer
+ strlen (buffer
) : end
);
500 zlog_debug ("%s", buffer
);
504 ospf6_spf_calculation_thread (struct thread
*t
)
506 struct ospf6_area
*oa
;
507 struct timeval start
, end
, runtime
;
509 oa
= (struct ospf6_area
*) THREAD_ARG (t
);
510 oa
->thread_spf_calculation
= NULL
;
512 if (IS_OSPF6_DEBUG_SPF (PROCESS
))
513 zlog_debug ("SPF calculation for Area %s", oa
->name
);
514 if (IS_OSPF6_DEBUG_SPF (DATABASE
))
515 ospf6_spf_log_database (oa
);
517 /* execute SPF calculation */
518 quagga_gettime (QUAGGA_CLK_MONOTONIC
, &start
);
519 ospf6_spf_calculation (oa
->ospf6
->router_id
, oa
->spf_table
, oa
);
520 quagga_gettime (QUAGGA_CLK_MONOTONIC
, &end
);
521 timersub (&end
, &start
, &runtime
);
523 if (IS_OSPF6_DEBUG_SPF (PROCESS
) || IS_OSPF6_DEBUG_SPF (TIME
))
524 zlog_debug ("SPF runtime: %ld sec %ld usec",
525 runtime
.tv_sec
, runtime
.tv_usec
);
527 ospf6_intra_route_calculation (oa
);
528 ospf6_intra_brouter_calculation (oa
);
534 ospf6_spf_schedule (struct ospf6_area
*oa
)
536 if (oa
->thread_spf_calculation
)
538 oa
->thread_spf_calculation
=
539 thread_add_event (master
, ospf6_spf_calculation_thread
, oa
, 0);
543 ospf6_spf_display_subtree (struct vty
*vty
, const char *prefix
, int rest
,
544 struct ospf6_vertex
*v
)
546 struct listnode
*node
, *nnode
;
547 struct ospf6_vertex
*c
;
552 /* "prefix" is the space prefix of the display line */
553 vty_out (vty
, "%s+-%s [%d]%s", prefix
, v
->name
, v
->cost
, VNL
);
555 len
= strlen (prefix
) + 4;
556 next_prefix
= (char *) malloc (len
);
557 if (next_prefix
== NULL
)
559 vty_out (vty
, "malloc failed%s", VNL
);
562 snprintf (next_prefix
, len
, "%s%s", prefix
, (rest
? "| " : " "));
564 restnum
= listcount (v
->child_list
);
565 for (ALL_LIST_ELEMENTS (v
->child_list
, node
, nnode
, c
))
568 ospf6_spf_display_subtree (vty
, next_prefix
, restnum
, c
);
574 DEFUN (debug_ospf6_spf_process
,
575 debug_ospf6_spf_process_cmd
,
576 "debug ospf6 spf process",
579 "Debug SPF Calculation\n"
580 "Debug Detailed SPF Process\n"
583 unsigned char level
= 0;
584 level
= OSPF6_DEBUG_SPF_PROCESS
;
585 OSPF6_DEBUG_SPF_ON (level
);
589 DEFUN (debug_ospf6_spf_time
,
590 debug_ospf6_spf_time_cmd
,
591 "debug ospf6 spf time",
594 "Debug SPF Calculation\n"
595 "Measure time taken by SPF Calculation\n"
598 unsigned char level
= 0;
599 level
= OSPF6_DEBUG_SPF_TIME
;
600 OSPF6_DEBUG_SPF_ON (level
);
604 DEFUN (debug_ospf6_spf_database
,
605 debug_ospf6_spf_database_cmd
,
606 "debug ospf6 spf database",
609 "Debug SPF Calculation\n"
610 "Log number of LSAs at SPF Calculation time\n"
613 unsigned char level
= 0;
614 level
= OSPF6_DEBUG_SPF_DATABASE
;
615 OSPF6_DEBUG_SPF_ON (level
);
619 DEFUN (no_debug_ospf6_spf_process
,
620 no_debug_ospf6_spf_process_cmd
,
621 "no debug ospf6 spf process",
625 "Quit Debugging SPF Calculation\n"
626 "Quit Debugging Detailed SPF Process\n"
629 unsigned char level
= 0;
630 level
= OSPF6_DEBUG_SPF_PROCESS
;
631 OSPF6_DEBUG_SPF_OFF (level
);
635 DEFUN (no_debug_ospf6_spf_time
,
636 no_debug_ospf6_spf_time_cmd
,
637 "no debug ospf6 spf time",
641 "Quit Debugging SPF Calculation\n"
642 "Quit Measuring time taken by SPF Calculation\n"
645 unsigned char level
= 0;
646 level
= OSPF6_DEBUG_SPF_TIME
;
647 OSPF6_DEBUG_SPF_OFF (level
);
651 DEFUN (no_debug_ospf6_spf_database
,
652 no_debug_ospf6_spf_database_cmd
,
653 "no debug ospf6 spf database",
657 "Debug SPF Calculation\n"
658 "Quit Logging number of LSAs at SPF Calculation time\n"
661 unsigned char level
= 0;
662 level
= OSPF6_DEBUG_SPF_DATABASE
;
663 OSPF6_DEBUG_SPF_OFF (level
);
668 config_write_ospf6_debug_spf (struct vty
*vty
)
670 if (IS_OSPF6_DEBUG_SPF (PROCESS
))
671 vty_out (vty
, "debug ospf6 spf process%s", VNL
);
672 if (IS_OSPF6_DEBUG_SPF (TIME
))
673 vty_out (vty
, "debug ospf6 spf time%s", VNL
);
674 if (IS_OSPF6_DEBUG_SPF (DATABASE
))
675 vty_out (vty
, "debug ospf6 spf database%s", VNL
);
680 install_element_ospf6_debug_spf (void)
682 install_element (ENABLE_NODE
, &debug_ospf6_spf_process_cmd
);
683 install_element (ENABLE_NODE
, &debug_ospf6_spf_time_cmd
);
684 install_element (ENABLE_NODE
, &debug_ospf6_spf_database_cmd
);
685 install_element (ENABLE_NODE
, &no_debug_ospf6_spf_process_cmd
);
686 install_element (ENABLE_NODE
, &no_debug_ospf6_spf_time_cmd
);
687 install_element (ENABLE_NODE
, &no_debug_ospf6_spf_database_cmd
);
688 install_element (CONFIG_NODE
, &debug_ospf6_spf_process_cmd
);
689 install_element (CONFIG_NODE
, &debug_ospf6_spf_time_cmd
);
690 install_element (CONFIG_NODE
, &debug_ospf6_spf_database_cmd
);
691 install_element (CONFIG_NODE
, &no_debug_ospf6_spf_process_cmd
);
692 install_element (CONFIG_NODE
, &no_debug_ospf6_spf_time_cmd
);
693 install_element (CONFIG_NODE
, &no_debug_ospf6_spf_database_cmd
);
697 ospf6_spf_init (void)