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
;
395 candidate_list
= pqueue_create ();
396 candidate_list
->cmp
= ospf6_vertex_cmp
;
398 ospf6_spf_table_finish (result_table
);
400 /* Install the calculating router itself as the root of the SPF tree */
401 /* construct root vertex */
402 lsa
= ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_ROUTER
), htonl (0),
403 router_id
, oa
->lsdb
);
406 root
= ospf6_vertex_create (lsa
);
410 root
->nexthop
[0].ifindex
= 0; /* loopbak I/F is better ... */
411 inet_pton (AF_INET6
, "::1", &root
->nexthop
[0].address
);
413 /* Actually insert root to the candidate-list as the only candidate */
414 pqueue_enqueue (root
, candidate_list
);
416 /* Iterate until candidate-list becomes empty */
417 while (candidate_list
->size
)
419 /* get closest candidate from priority queue */
420 v
= pqueue_dequeue (candidate_list
);
422 /* installing may result in merging or rejecting of the vertex */
423 if (ospf6_spf_install (v
, result_table
) < 0)
426 /* For each LS description in the just-added vertex V's LSA */
427 size
= (VERTEX_IS_TYPE (ROUTER
, v
) ?
428 sizeof (struct ospf6_router_lsdesc
) :
429 sizeof (struct ospf6_network_lsdesc
));
430 for (lsdesc
= OSPF6_LSA_HEADER_END (v
->lsa
->header
) + 4;
431 lsdesc
+ size
<= OSPF6_LSA_END (v
->lsa
->header
); lsdesc
+= size
)
433 lsa
= ospf6_lsdesc_lsa (lsdesc
, v
);
437 if (! ospf6_lsdesc_backlink (lsa
, lsdesc
, v
))
440 w
= ospf6_vertex_create (lsa
);
443 if (VERTEX_IS_TYPE (ROUTER
, v
))
445 w
->cost
= v
->cost
+ ROUTER_LSDESC_GET_METRIC (lsdesc
);
446 w
->hops
= v
->hops
+ (VERTEX_IS_TYPE (NETWORK
, w
) ? 0 : 1);
451 w
->hops
= v
->hops
+ 1;
454 /* nexthop calculation */
456 w
->nexthop
[0].ifindex
= ROUTER_LSDESC_GET_IFID (lsdesc
);
457 else if (w
->hops
== 1 && v
->hops
== 0)
458 ospf6_nexthop_calc (w
, v
, lsdesc
);
461 for (i
= 0; ospf6_nexthop_is_set (&v
->nexthop
[i
]) &&
462 i
< OSPF6_MULTI_PATH_LIMIT
; i
++)
463 ospf6_nexthop_copy (&w
->nexthop
[i
], &v
->nexthop
[i
]);
466 /* add new candidate to the candidate_list */
467 if (IS_OSPF6_DEBUG_SPF (PROCESS
))
468 zlog_debug (" New candidate: %s hops %d cost %d",
469 w
->name
, w
->hops
, w
->cost
);
470 pqueue_enqueue (w
, candidate_list
);
474 pqueue_delete (candidate_list
);
478 ospf6_spf_log_database (struct ospf6_area
*oa
)
480 char *p
, *end
, buffer
[256];
481 struct listnode
*node
;
482 struct ospf6_interface
*oi
;
485 end
= buffer
+ sizeof (buffer
);
487 snprintf (p
, end
- p
, "SPF on DB (#LSAs):");
488 p
= (buffer
+ strlen (buffer
) < end
? buffer
+ strlen (buffer
) : end
);
489 snprintf (p
, end
- p
, " Area %s: %d", oa
->name
, oa
->lsdb
->count
);
490 p
= (buffer
+ strlen (buffer
) < end
? buffer
+ strlen (buffer
) : end
);
492 for (ALL_LIST_ELEMENTS_RO (oa
->if_list
, node
, oi
))
494 snprintf (p
, end
- p
, " I/F %s: %d",
495 oi
->interface
->name
, oi
->lsdb
->count
);
496 p
= (buffer
+ strlen (buffer
) < end
? buffer
+ strlen (buffer
) : end
);
499 zlog_debug ("%s", buffer
);
503 ospf6_spf_calculation_thread (struct thread
*t
)
505 struct ospf6_area
*oa
;
506 struct timeval start
, end
, runtime
;
508 oa
= (struct ospf6_area
*) THREAD_ARG (t
);
509 oa
->thread_spf_calculation
= NULL
;
511 if (IS_OSPF6_DEBUG_SPF (PROCESS
))
512 zlog_debug ("SPF calculation for Area %s", oa
->name
);
513 if (IS_OSPF6_DEBUG_SPF (DATABASE
))
514 ospf6_spf_log_database (oa
);
516 /* execute SPF calculation */
517 quagga_gettime (QUAGGA_CLK_MONOTONIC
, &start
);
518 ospf6_spf_calculation (oa
->ospf6
->router_id
, oa
->spf_table
, oa
);
519 quagga_gettime (QUAGGA_CLK_MONOTONIC
, &end
);
520 timersub (&end
, &start
, &runtime
);
522 if (IS_OSPF6_DEBUG_SPF (PROCESS
) || IS_OSPF6_DEBUG_SPF (TIME
))
523 zlog_debug ("SPF runtime: %ld sec %ld usec",
524 runtime
.tv_sec
, runtime
.tv_usec
);
526 ospf6_intra_route_calculation (oa
);
527 ospf6_intra_brouter_calculation (oa
);
533 ospf6_spf_schedule (struct ospf6_area
*oa
)
535 if (oa
->thread_spf_calculation
)
537 oa
->thread_spf_calculation
=
538 thread_add_event (master
, ospf6_spf_calculation_thread
, oa
, 0);
542 ospf6_spf_display_subtree (struct vty
*vty
, const char *prefix
, int rest
,
543 struct ospf6_vertex
*v
)
545 struct listnode
*node
, *nnode
;
546 struct ospf6_vertex
*c
;
551 /* "prefix" is the space prefix of the display line */
552 vty_out (vty
, "%s+-%s [%d]%s", prefix
, v
->name
, v
->cost
, VNL
);
554 len
= strlen (prefix
) + 4;
555 next_prefix
= (char *) malloc (len
);
556 if (next_prefix
== NULL
)
558 vty_out (vty
, "malloc failed%s", VNL
);
561 snprintf (next_prefix
, len
, "%s%s", prefix
, (rest
? "| " : " "));
563 restnum
= listcount (v
->child_list
);
564 for (ALL_LIST_ELEMENTS (v
->child_list
, node
, nnode
, c
))
567 ospf6_spf_display_subtree (vty
, next_prefix
, restnum
, c
);
573 DEFUN (debug_ospf6_spf_process
,
574 debug_ospf6_spf_process_cmd
,
575 "debug ospf6 spf process",
578 "Debug SPF Calculation\n"
579 "Debug Detailed SPF Process\n"
582 unsigned char level
= 0;
583 level
= OSPF6_DEBUG_SPF_PROCESS
;
584 OSPF6_DEBUG_SPF_ON (level
);
588 DEFUN (debug_ospf6_spf_time
,
589 debug_ospf6_spf_time_cmd
,
590 "debug ospf6 spf time",
593 "Debug SPF Calculation\n"
594 "Measure time taken by SPF Calculation\n"
597 unsigned char level
= 0;
598 level
= OSPF6_DEBUG_SPF_TIME
;
599 OSPF6_DEBUG_SPF_ON (level
);
603 DEFUN (debug_ospf6_spf_database
,
604 debug_ospf6_spf_database_cmd
,
605 "debug ospf6 spf database",
608 "Debug SPF Calculation\n"
609 "Log number of LSAs at SPF Calculation time\n"
612 unsigned char level
= 0;
613 level
= OSPF6_DEBUG_SPF_DATABASE
;
614 OSPF6_DEBUG_SPF_ON (level
);
618 DEFUN (no_debug_ospf6_spf_process
,
619 no_debug_ospf6_spf_process_cmd
,
620 "no debug ospf6 spf process",
624 "Quit Debugging SPF Calculation\n"
625 "Quit Debugging Detailed SPF Process\n"
628 unsigned char level
= 0;
629 level
= OSPF6_DEBUG_SPF_PROCESS
;
630 OSPF6_DEBUG_SPF_OFF (level
);
634 DEFUN (no_debug_ospf6_spf_time
,
635 no_debug_ospf6_spf_time_cmd
,
636 "no debug ospf6 spf time",
640 "Quit Debugging SPF Calculation\n"
641 "Quit Measuring time taken by SPF Calculation\n"
644 unsigned char level
= 0;
645 level
= OSPF6_DEBUG_SPF_TIME
;
646 OSPF6_DEBUG_SPF_OFF (level
);
650 DEFUN (no_debug_ospf6_spf_database
,
651 no_debug_ospf6_spf_database_cmd
,
652 "no debug ospf6 spf database",
656 "Debug SPF Calculation\n"
657 "Quit Logging number of LSAs at SPF Calculation time\n"
660 unsigned char level
= 0;
661 level
= OSPF6_DEBUG_SPF_DATABASE
;
662 OSPF6_DEBUG_SPF_OFF (level
);
667 config_write_ospf6_debug_spf (struct vty
*vty
)
669 if (IS_OSPF6_DEBUG_SPF (PROCESS
))
670 vty_out (vty
, "debug ospf6 spf process%s", VNL
);
671 if (IS_OSPF6_DEBUG_SPF (TIME
))
672 vty_out (vty
, "debug ospf6 spf time%s", VNL
);
673 if (IS_OSPF6_DEBUG_SPF (DATABASE
))
674 vty_out (vty
, "debug ospf6 spf database%s", VNL
);
679 install_element_ospf6_debug_spf (void)
681 install_element (ENABLE_NODE
, &debug_ospf6_spf_process_cmd
);
682 install_element (ENABLE_NODE
, &debug_ospf6_spf_time_cmd
);
683 install_element (ENABLE_NODE
, &debug_ospf6_spf_database_cmd
);
684 install_element (ENABLE_NODE
, &no_debug_ospf6_spf_process_cmd
);
685 install_element (ENABLE_NODE
, &no_debug_ospf6_spf_time_cmd
);
686 install_element (ENABLE_NODE
, &no_debug_ospf6_spf_database_cmd
);
687 install_element (CONFIG_NODE
, &debug_ospf6_spf_process_cmd
);
688 install_element (CONFIG_NODE
, &debug_ospf6_spf_time_cmd
);
689 install_element (CONFIG_NODE
, &debug_ospf6_spf_database_cmd
);
690 install_element (CONFIG_NODE
, &no_debug_ospf6_spf_process_cmd
);
691 install_element (CONFIG_NODE
, &no_debug_ospf6_spf_time_cmd
);
692 install_element (CONFIG_NODE
, &no_debug_ospf6_spf_database_cmd
);
696 ospf6_spf_init (void)