]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_spf.c
ospf6d: address more trivial compiler warnings
[mirror_frr.git] / ospf6d / ospf6_spf.c
1 /*
2 * Copyright (C) 2003 Yasuhiro Ohara
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 */
21
22 /* Shortest Path First calculation for OSPFv3 */
23
24 #include <zebra.h>
25
26 #include "log.h"
27 #include "memory.h"
28 #include "command.h"
29 #include "vty.h"
30 #include "prefix.h"
31 #include "pqueue.h"
32 #include "linklist.h"
33 #include "thread.h"
34
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"
42 #include "ospf6d.h"
43
44 unsigned char conf_debug_ospf6_spf = 0;
45
46 static int
47 ospf6_vertex_cmp (void *a, void *b)
48 {
49 struct ospf6_vertex *va = (struct ospf6_vertex *) a;
50 struct ospf6_vertex *vb = (struct ospf6_vertex *) b;
51
52 /* ascending order */
53 if (va->cost != vb->cost)
54 return (va->cost - vb->cost);
55 return (va->hops - vb->hops);
56 }
57
58 static int
59 ospf6_vertex_id_cmp (void *a, void *b)
60 {
61 struct ospf6_vertex *va = (struct ospf6_vertex *) a;
62 struct ospf6_vertex *vb = (struct ospf6_vertex *) b;
63 int ret = 0;
64
65 ret = ntohl (ospf6_linkstate_prefix_adv_router (&va->vertex_id)) -
66 ntohl (ospf6_linkstate_prefix_adv_router (&vb->vertex_id));
67 if (ret)
68 return ret;
69
70 ret = ntohl (ospf6_linkstate_prefix_id (&va->vertex_id)) -
71 ntohl (ospf6_linkstate_prefix_id (&vb->vertex_id));
72 return ret;
73 }
74
75 static struct ospf6_vertex *
76 ospf6_vertex_create (struct ospf6_lsa *lsa)
77 {
78 struct ospf6_vertex *v;
79 int i;
80
81 v = (struct ospf6_vertex *)
82 XMALLOC (MTYPE_OSPF6_VERTEX, sizeof (struct ospf6_vertex));
83
84 /* type */
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;
89 else
90 assert (0);
91
92 /* vertex_id */
93 ospf6_linkstate_prefix (lsa->header->adv_router, lsa->header->id,
94 &v->vertex_id);
95
96 /* name */
97 ospf6_linkstate_prefix2str (&v->vertex_id, v->name, sizeof (v->name));
98
99 /* Associated LSA */
100 v->lsa = lsa;
101
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);
107
108 for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
109 ospf6_nexthop_clear (&v->nexthop[i]);
110
111 v->parent = NULL;
112 v->child_list = list_new ();
113 v->child_list->cmp = ospf6_vertex_id_cmp;
114
115 return v;
116 }
117
118 static void
119 ospf6_vertex_delete (struct ospf6_vertex *v)
120 {
121 list_delete (v->child_list);
122 XFREE (MTYPE_OSPF6_VERTEX, v);
123 }
124
125 static struct ospf6_lsa *
126 ospf6_lsdesc_lsa (caddr_t lsdesc, struct ospf6_vertex *v)
127 {
128 struct ospf6_lsa *lsa;
129 u_int16_t type = 0;
130 u_int32_t id = 0, adv_router = 0;
131
132 if (VERTEX_IS_TYPE (NETWORK, v))
133 {
134 type = htons (OSPF6_LSTYPE_ROUTER);
135 id = htonl (0);
136 adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc);
137 }
138 else
139 {
140 if (ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, lsdesc))
141 {
142 type = htons (OSPF6_LSTYPE_ROUTER);
143 id = htonl (0);
144 adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc);
145 }
146 else if (ROUTER_LSDESC_IS_TYPE (TRANSIT_NETWORK, lsdesc))
147 {
148 type = htons (OSPF6_LSTYPE_NETWORK);
149 id = htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc));
150 adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc);
151 }
152 }
153
154 lsa = ospf6_lsdb_lookup (type, id, adv_router, v->area->lsdb);
155
156 if (IS_OSPF6_DEBUG_SPF (PROCESS))
157 {
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));
161 if (lsa)
162 zlog_debug (" Link to: %s", lsa->name);
163 else
164 zlog_debug (" Link to: [%s Id:%s Adv:%s] No LSA",
165 ospf6_lstype_name (type), ibuf, abuf);
166 }
167
168 return lsa;
169 }
170
171 static char *
172 ospf6_lsdesc_backlink (struct ospf6_lsa *lsa,
173 caddr_t lsdesc, struct ospf6_vertex *v)
174 {
175 caddr_t backlink, found = NULL;
176 int size;
177
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)
183 {
184 assert (! (OSPF6_LSA_IS_TYPE (NETWORK, lsa) &&
185 VERTEX_IS_TYPE (NETWORK, v)));
186
187 if (OSPF6_LSA_IS_TYPE (NETWORK, lsa) &&
188 NETWORK_LSDESC_GET_NBR_ROUTERID (backlink)
189 == v->lsa->header->adv_router)
190 found = backlink;
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))
197 found = backlink;
198 else
199 {
200 if (! ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, backlink) ||
201 ! ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, lsdesc))
202 continue;
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))
207 continue;
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)
212 continue;
213 found = backlink;
214 }
215 }
216
217 if (IS_OSPF6_DEBUG_SPF (PROCESS))
218 zlog_debug (" Backlink %s", (found ? "OK" : "FAIL"));
219
220 return found;
221 }
222
223 static void
224 ospf6_nexthop_calc (struct ospf6_vertex *w, struct ospf6_vertex *v,
225 caddr_t lsdesc)
226 {
227 int i, ifindex;
228 struct ospf6_interface *oi;
229 u_int16_t type;
230 u_int32_t adv_router;
231 struct ospf6_lsa *lsa;
232 struct ospf6_link_lsa *link_lsa;
233 char buf[64];
234
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);
239 if (oi == NULL)
240 {
241 if (IS_OSPF6_DEBUG_SPF (PROCESS))
242 zlog_debug ("Can't find interface in SPF: ifindex %d", ifindex);
243 return;
244 }
245
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));
250
251 i = 0;
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))
254 {
255 if (VERTEX_IS_TYPE (ROUTER, v) &&
256 htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc)) != lsa->header->id)
257 continue;
258
259 link_lsa = (struct ospf6_link_lsa *) OSPF6_LSA_HEADER_END (lsa->header);
260 if (IS_OSPF6_DEBUG_SPF (PROCESS))
261 {
262 inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf));
263 zlog_debug (" nexthop %s from %s", buf, lsa->name);
264 }
265
266 if (i < OSPF6_MULTI_PATH_LIMIT)
267 {
268 memcpy (&w->nexthop[i].address, &link_lsa->linklocal_addr,
269 sizeof (struct in6_addr));
270 w->nexthop[i].ifindex = ifindex;
271 i++;
272 }
273 }
274
275 if (i == 0 && IS_OSPF6_DEBUG_SPF (PROCESS))
276 zlog_debug ("No nexthop for %s found", w->name);
277 }
278
279 static int
280 ospf6_spf_install (struct ospf6_vertex *v,
281 struct ospf6_route_table *result_table)
282 {
283 struct ospf6_route *route;
284 int i, j;
285 struct ospf6_vertex *prev;
286
287 if (IS_OSPF6_DEBUG_SPF (PROCESS))
288 zlog_debug ("SPF install %s hops %d cost %d",
289 v->name, v->hops, v->cost);
290
291 route = ospf6_route_lookup (&v->vertex_id, result_table);
292 if (route && route->path.cost < v->cost)
293 {
294 if (IS_OSPF6_DEBUG_SPF (PROCESS))
295 zlog_debug (" already installed with lower cost (%d), ignore",
296 route->path.cost);
297 ospf6_vertex_delete (v);
298 return -1;
299 }
300 else if (route && route->path.cost == v->cost)
301 {
302 if (IS_OSPF6_DEBUG_SPF (PROCESS))
303 zlog_debug (" another path found, merge");
304
305 for (i = 0; ospf6_nexthop_is_set (&v->nexthop[i]) &&
306 i < OSPF6_MULTI_PATH_LIMIT; i++)
307 {
308 for (j = 0; j < OSPF6_MULTI_PATH_LIMIT; j++)
309 {
310 if (ospf6_nexthop_is_set (&route->nexthop[j]))
311 {
312 if (ospf6_nexthop_is_same (&route->nexthop[j],
313 &v->nexthop[i]))
314 break;
315 else
316 continue;
317 }
318 ospf6_nexthop_copy (&route->nexthop[j], &v->nexthop[i]);
319 break;
320 }
321 }
322
323 prev = (struct ospf6_vertex *) route->route_option;
324 assert (prev->hops <= v->hops);
325 ospf6_vertex_delete (v);
326
327 return -1;
328 }
329
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
333 Priority-Queue. */
334
335 /* the case where the route exists already is handled and returned
336 up to here. */
337 assert (route == NULL);
338
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];
353
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]);
357
358 if (v->parent)
359 listnode_add_sort (v->parent->child_list, v);
360 route->route_option = v;
361
362 ospf6_route_add (route, result_table);
363 return 0;
364 }
365
366 void
367 ospf6_spf_table_finish (struct ospf6_route_table *result_table)
368 {
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))
373 {
374 v = (struct ospf6_vertex *) route->route_option;
375 ospf6_vertex_delete (v);
376 ospf6_route_remove (route, result_table);
377 }
378 }
379
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 */
382 void
383 ospf6_spf_calculation (u_int32_t router_id,
384 struct ospf6_route_table *result_table,
385 struct ospf6_area *oa)
386 {
387 struct pqueue *candidate_list;
388 struct ospf6_vertex *root, *v, *w;
389 int i;
390 int size;
391 caddr_t lsdesc;
392 struct ospf6_lsa *lsa;
393
394 /* initialize */
395 candidate_list = pqueue_create ();
396 candidate_list->cmp = ospf6_vertex_cmp;
397
398 ospf6_spf_table_finish (result_table);
399
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);
404 if (lsa == NULL)
405 return;
406 root = ospf6_vertex_create (lsa);
407 root->area = oa;
408 root->cost = 0;
409 root->hops = 0;
410 root->nexthop[0].ifindex = 0; /* loopbak I/F is better ... */
411 inet_pton (AF_INET6, "::1", &root->nexthop[0].address);
412
413 /* Actually insert root to the candidate-list as the only candidate */
414 pqueue_enqueue (root, candidate_list);
415
416 /* Iterate until candidate-list becomes empty */
417 while (candidate_list->size)
418 {
419 /* get closest candidate from priority queue */
420 v = pqueue_dequeue (candidate_list);
421
422 /* installing may result in merging or rejecting of the vertex */
423 if (ospf6_spf_install (v, result_table) < 0)
424 continue;
425
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)
432 {
433 lsa = ospf6_lsdesc_lsa (lsdesc, v);
434 if (lsa == NULL)
435 continue;
436
437 if (! ospf6_lsdesc_backlink (lsa, lsdesc, v))
438 continue;
439
440 w = ospf6_vertex_create (lsa);
441 w->area = oa;
442 w->parent = v;
443 if (VERTEX_IS_TYPE (ROUTER, v))
444 {
445 w->cost = v->cost + ROUTER_LSDESC_GET_METRIC (lsdesc);
446 w->hops = v->hops + (VERTEX_IS_TYPE (NETWORK, w) ? 0 : 1);
447 }
448 else /* NETWORK */
449 {
450 w->cost = v->cost;
451 w->hops = v->hops + 1;
452 }
453
454 /* nexthop calculation */
455 if (w->hops == 0)
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);
459 else
460 {
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]);
464 }
465
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);
471 }
472 }
473
474 pqueue_delete (candidate_list);
475 }
476
477 static void
478 ospf6_spf_log_database (struct ospf6_area *oa)
479 {
480 char *p, *end, buffer[256];
481 struct listnode *node;
482 struct ospf6_interface *oi;
483
484 p = buffer;
485 end = buffer + sizeof (buffer);
486
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);
491
492 for (ALL_LIST_ELEMENTS_RO (oa->if_list, node, oi))
493 {
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);
497 }
498
499 zlog_debug ("%s", buffer);
500 }
501
502 static int
503 ospf6_spf_calculation_thread (struct thread *t)
504 {
505 struct ospf6_area *oa;
506 struct timeval start, end, runtime;
507
508 oa = (struct ospf6_area *) THREAD_ARG (t);
509 oa->thread_spf_calculation = NULL;
510
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);
515
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);
521
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);
525
526 ospf6_intra_route_calculation (oa);
527 ospf6_intra_brouter_calculation (oa);
528
529 return 0;
530 }
531
532 void
533 ospf6_spf_schedule (struct ospf6_area *oa)
534 {
535 if (oa->thread_spf_calculation)
536 return;
537 oa->thread_spf_calculation =
538 thread_add_event (master, ospf6_spf_calculation_thread, oa, 0);
539 }
540
541 void
542 ospf6_spf_display_subtree (struct vty *vty, const char *prefix, int rest,
543 struct ospf6_vertex *v)
544 {
545 struct listnode *node, *nnode;
546 struct ospf6_vertex *c;
547 char *next_prefix;
548 int len;
549 int restnum;
550
551 /* "prefix" is the space prefix of the display line */
552 vty_out (vty, "%s+-%s [%d]%s", prefix, v->name, v->cost, VNL);
553
554 len = strlen (prefix) + 4;
555 next_prefix = (char *) malloc (len);
556 if (next_prefix == NULL)
557 {
558 vty_out (vty, "malloc failed%s", VNL);
559 return;
560 }
561 snprintf (next_prefix, len, "%s%s", prefix, (rest ? "| " : " "));
562
563 restnum = listcount (v->child_list);
564 for (ALL_LIST_ELEMENTS (v->child_list, node, nnode, c))
565 {
566 restnum--;
567 ospf6_spf_display_subtree (vty, next_prefix, restnum, c);
568 }
569
570 free (next_prefix);
571 }
572
573 DEFUN (debug_ospf6_spf_process,
574 debug_ospf6_spf_process_cmd,
575 "debug ospf6 spf process",
576 DEBUG_STR
577 OSPF6_STR
578 "Debug SPF Calculation\n"
579 "Debug Detailed SPF Process\n"
580 )
581 {
582 unsigned char level = 0;
583 level = OSPF6_DEBUG_SPF_PROCESS;
584 OSPF6_DEBUG_SPF_ON (level);
585 return CMD_SUCCESS;
586 }
587
588 DEFUN (debug_ospf6_spf_time,
589 debug_ospf6_spf_time_cmd,
590 "debug ospf6 spf time",
591 DEBUG_STR
592 OSPF6_STR
593 "Debug SPF Calculation\n"
594 "Measure time taken by SPF Calculation\n"
595 )
596 {
597 unsigned char level = 0;
598 level = OSPF6_DEBUG_SPF_TIME;
599 OSPF6_DEBUG_SPF_ON (level);
600 return CMD_SUCCESS;
601 }
602
603 DEFUN (debug_ospf6_spf_database,
604 debug_ospf6_spf_database_cmd,
605 "debug ospf6 spf database",
606 DEBUG_STR
607 OSPF6_STR
608 "Debug SPF Calculation\n"
609 "Log number of LSAs at SPF Calculation time\n"
610 )
611 {
612 unsigned char level = 0;
613 level = OSPF6_DEBUG_SPF_DATABASE;
614 OSPF6_DEBUG_SPF_ON (level);
615 return CMD_SUCCESS;
616 }
617
618 DEFUN (no_debug_ospf6_spf_process,
619 no_debug_ospf6_spf_process_cmd,
620 "no debug ospf6 spf process",
621 NO_STR
622 DEBUG_STR
623 OSPF6_STR
624 "Quit Debugging SPF Calculation\n"
625 "Quit Debugging Detailed SPF Process\n"
626 )
627 {
628 unsigned char level = 0;
629 level = OSPF6_DEBUG_SPF_PROCESS;
630 OSPF6_DEBUG_SPF_OFF (level);
631 return CMD_SUCCESS;
632 }
633
634 DEFUN (no_debug_ospf6_spf_time,
635 no_debug_ospf6_spf_time_cmd,
636 "no debug ospf6 spf time",
637 NO_STR
638 DEBUG_STR
639 OSPF6_STR
640 "Quit Debugging SPF Calculation\n"
641 "Quit Measuring time taken by SPF Calculation\n"
642 )
643 {
644 unsigned char level = 0;
645 level = OSPF6_DEBUG_SPF_TIME;
646 OSPF6_DEBUG_SPF_OFF (level);
647 return CMD_SUCCESS;
648 }
649
650 DEFUN (no_debug_ospf6_spf_database,
651 no_debug_ospf6_spf_database_cmd,
652 "no debug ospf6 spf database",
653 NO_STR
654 DEBUG_STR
655 OSPF6_STR
656 "Debug SPF Calculation\n"
657 "Quit Logging number of LSAs at SPF Calculation time\n"
658 )
659 {
660 unsigned char level = 0;
661 level = OSPF6_DEBUG_SPF_DATABASE;
662 OSPF6_DEBUG_SPF_OFF (level);
663 return CMD_SUCCESS;
664 }
665
666 int
667 config_write_ospf6_debug_spf (struct vty *vty)
668 {
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);
675 return 0;
676 }
677
678 void
679 install_element_ospf6_debug_spf (void)
680 {
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);
693 }
694
695 void
696 ospf6_spf_init (void)
697 {
698 }
699
700