]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_spf.c
[lib] mes_lookup string lookup table argument should be marked const
[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
3b68735f 154 if (IS_OSPF6_DEBUG_SPF (PROCESS))
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)
c6487d61 160 zlog_debug (" Link to: %s", lsa->name);
508e53e2 161 else
c6487d61 162 zlog_debug (" 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
3b68735f 215 if (IS_OSPF6_DEBUG_SPF (PROCESS))
c6487d61 216 zlog_debug (" 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 {
3b68735f 239 if (IS_OSPF6_DEBUG_SPF (PROCESS))
c6487d61 240 zlog_debug ("Can't find interface in SPF: ifindex %d", ifindex);
508e53e2 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);
3b68735f 258 if (IS_OSPF6_DEBUG_SPF (PROCESS))
508e53e2 259 {
260 inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf));
c6487d61 261 zlog_debug (" nexthop %s from %s", buf, lsa->name);
508e53e2 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
3b68735f 273 if (i == 0 && IS_OSPF6_DEBUG_SPF (PROCESS))
c6487d61 274 zlog_debug ("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;
1eb8ef25 284 struct listnode *node, *nnode;
718e3744 285
3b68735f 286 if (IS_OSPF6_DEBUG_SPF (PROCESS))
c6487d61 287 zlog_debug ("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 {
3b68735f 293 if (IS_OSPF6_DEBUG_SPF (PROCESS))
c6487d61 294 zlog_debug (" already installed with lower cost (%d), ignore",
295 route->path.cost);
508e53e2 296 ospf6_vertex_delete (v);
297 return -1;
718e3744 298 }
508e53e2 299 else if (route && route->path.cost == v->cost)
718e3744 300 {
3b68735f 301 if (IS_OSPF6_DEBUG_SPF (PROCESS))
c6487d61 302 zlog_debug (" 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 {
1eb8ef25 325 for (ALL_LIST_ELEMENTS (prev->child_list, node, nnode, w))
508e53e2 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").
6452df09 345 In the case something has gone wrong with the behavior of
508e53e2 346 Priority-Queue. */
6452df09 347
348 /* the case where the route exists already is handled and returned
349 up to here. */
508e53e2 350 assert (route == NULL);
351
352 route = ospf6_route_create ();
353 memcpy (&route->prefix, &v->vertex_id, sizeof (struct prefix));
354 route->type = OSPF6_DEST_TYPE_LINKSTATE;
355 route->path.type = OSPF6_PATH_TYPE_INTRA;
356 route->path.origin.type = v->lsa->header->type;
357 route->path.origin.id = v->lsa->header->id;
358 route->path.origin.adv_router = v->lsa->header->adv_router;
359 route->path.metric_type = 1;
360 route->path.cost = v->cost;
361 route->path.cost_e2 = v->hops;
362 route->path.router_bits = v->capability;
363 route->path.options[0] = v->options[0];
364 route->path.options[1] = v->options[1];
365 route->path.options[2] = v->options[2];
366
367 for (i = 0; ospf6_nexthop_is_set (&v->nexthop[i]) &&
368 i < OSPF6_MULTI_PATH_LIMIT; i++)
369 ospf6_nexthop_copy (&route->nexthop[i], &v->nexthop[i]);
370
371 if (v->parent)
372 listnode_add_sort (v->parent->child_list, v);
373 route->route_option = v;
374
375 ospf6_route_add (route, result_table);
376 return 0;
718e3744 377}
378
508e53e2 379void
380ospf6_spf_table_finish (struct ospf6_route_table *result_table)
718e3744 381{
508e53e2 382 struct ospf6_route *route;
718e3744 383 struct ospf6_vertex *v;
508e53e2 384 for (route = ospf6_route_head (result_table); route;
385 route = ospf6_route_next (route))
718e3744 386 {
508e53e2 387 v = (struct ospf6_vertex *) route->route_option;
388 ospf6_vertex_delete (v);
389 ospf6_route_remove (route, result_table);
718e3744 390 }
718e3744 391}
392
6452df09 393/* RFC2328 16.1. Calculating the shortest-path tree for an area */
394/* RFC2740 3.8.1. Calculating the shortest path tree for an area */
508e53e2 395void
396ospf6_spf_calculation (u_int32_t router_id,
397 struct ospf6_route_table *result_table,
398 struct ospf6_area *oa)
399{
400 struct pqueue *candidate_list;
401 struct ospf6_vertex *root, *v, *w;
402 int i;
403 int size;
404 caddr_t lsdesc;
405 struct ospf6_lsa *lsa;
718e3744 406
508e53e2 407 /* initialize */
408 candidate_list = pqueue_create ();
409 candidate_list->cmp = ospf6_vertex_cmp;
718e3744 410
508e53e2 411 ospf6_spf_table_finish (result_table);
718e3744 412
508e53e2 413 /* Install the calculating router itself as the root of the SPF tree */
414 /* construct root vertex */
415 lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_ROUTER), htonl (0),
416 router_id, oa->lsdb);
417 if (lsa == NULL)
418 return;
419 root = ospf6_vertex_create (lsa);
420 root->area = oa;
421 root->cost = 0;
422 root->hops = 0;
6452df09 423 root->nexthop[0].ifindex = 0; /* loopbak I/F is better ... */
508e53e2 424 inet_pton (AF_INET6, "::1", &root->nexthop[0].address);
718e3744 425
508e53e2 426 /* Actually insert root to the candidate-list as the only candidate */
427 pqueue_enqueue (root, candidate_list);
718e3744 428
508e53e2 429 /* Iterate until candidate-list becomes empty */
430 while (candidate_list->size)
718e3744 431 {
508e53e2 432 /* get closest candidate from priority queue */
433 v = pqueue_dequeue (candidate_list);
718e3744 434
6452df09 435 /* installing may result in merging or rejecting of the vertex */
508e53e2 436 if (ospf6_spf_install (v, result_table) < 0)
437 continue;
718e3744 438
508e53e2 439 /* For each LS description in the just-added vertex V's LSA */
440 size = (VERTEX_IS_TYPE (ROUTER, v) ?
441 sizeof (struct ospf6_router_lsdesc) :
442 sizeof (struct ospf6_network_lsdesc));
443 for (lsdesc = OSPF6_LSA_HEADER_END (v->lsa->header) + 4;
444 lsdesc + size <= OSPF6_LSA_END (v->lsa->header); lsdesc += size)
718e3744 445 {
508e53e2 446 lsa = ospf6_lsdesc_lsa (lsdesc, v);
447 if (lsa == NULL)
718e3744 448 continue;
449
508e53e2 450 if (! ospf6_lsdesc_backlink (lsa, lsdesc, v))
451 continue;
718e3744 452
508e53e2 453 w = ospf6_vertex_create (lsa);
454 w->area = oa;
455 w->parent = v;
456 if (VERTEX_IS_TYPE (ROUTER, v))
718e3744 457 {
508e53e2 458 w->cost = v->cost + ROUTER_LSDESC_GET_METRIC (lsdesc);
459 w->hops = v->hops + (VERTEX_IS_TYPE (NETWORK, w) ? 0 : 1);
718e3744 460 }
508e53e2 461 else /* NETWORK */
718e3744 462 {
508e53e2 463 w->cost = v->cost;
464 w->hops = v->hops + 1;
718e3744 465 }
466
508e53e2 467 /* nexthop calculation */
468 if (w->hops == 0)
469 w->nexthop[0].ifindex = ROUTER_LSDESC_GET_IFID (lsdesc);
470 else if (w->hops == 1 && v->hops == 0)
471 ospf6_nexthop_calc (w, v, lsdesc);
718e3744 472 else
473 {
508e53e2 474 for (i = 0; ospf6_nexthop_is_set (&v->nexthop[i]) &&
475 i < OSPF6_MULTI_PATH_LIMIT; i++)
476 ospf6_nexthop_copy (&w->nexthop[i], &v->nexthop[i]);
718e3744 477 }
478
508e53e2 479 /* add new candidate to the candidate_list */
3b68735f 480 if (IS_OSPF6_DEBUG_SPF (PROCESS))
c6487d61 481 zlog_debug (" New candidate: %s hops %d cost %d",
482 w->name, w->hops, w->cost);
508e53e2 483 pqueue_enqueue (w, candidate_list);
718e3744 484 }
485 }
486
508e53e2 487 pqueue_delete (candidate_list);
718e3744 488}
489
2680aa2b 490void
491ospf6_spf_log_database (struct ospf6_area *oa)
492{
493 char *p, *end, buffer[256];
494 struct listnode *node;
495 struct ospf6_interface *oi;
496
497 p = buffer;
498 end = buffer + sizeof (buffer);
499
500 snprintf (p, end - p, "SPF on DB (#LSAs):");
501 p = (buffer + strlen (buffer) < end ? buffer + strlen (buffer) : end);
502 snprintf (p, end - p, " Area %s: %d", oa->name, oa->lsdb->count);
503 p = (buffer + strlen (buffer) < end ? buffer + strlen (buffer) : end);
504
1eb8ef25 505 for (ALL_LIST_ELEMENTS_RO (oa->if_list, node, oi))
2680aa2b 506 {
2680aa2b 507 snprintf (p, end - p, " I/F %s: %d",
508 oi->interface->name, oi->lsdb->count);
509 p = (buffer + strlen (buffer) < end ? buffer + strlen (buffer) : end);
510 }
511
c6487d61 512 zlog_debug ("%s", buffer);
2680aa2b 513}
514
718e3744 515int
516ospf6_spf_calculation_thread (struct thread *t)
517{
508e53e2 518 struct ospf6_area *oa;
519 struct timeval start, end, runtime;
718e3744 520
508e53e2 521 oa = (struct ospf6_area *) THREAD_ARG (t);
522 oa->thread_spf_calculation = NULL;
718e3744 523
2680aa2b 524 if (IS_OSPF6_DEBUG_SPF (PROCESS))
c6487d61 525 zlog_debug ("SPF calculation for Area %s", oa->name);
2680aa2b 526 if (IS_OSPF6_DEBUG_SPF (DATABASE))
527 ospf6_spf_log_database (oa);
718e3744 528
529 /* execute SPF calculation */
530 gettimeofday (&start, (struct timezone *) NULL);
508e53e2 531 ospf6_spf_calculation (oa->ospf6->router_id, oa->spf_table, oa);
718e3744 532 gettimeofday (&end, (struct timezone *) NULL);
2680aa2b 533 timersub (&end, &start, &runtime);
718e3744 534
3b68735f 535 if (IS_OSPF6_DEBUG_SPF (PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
c6487d61 536 zlog_debug ("SPF runtime: %ld sec %ld usec",
537 runtime.tv_sec, runtime.tv_usec);
718e3744 538
508e53e2 539 ospf6_intra_route_calculation (oa);
6452df09 540 ospf6_intra_brouter_calculation (oa);
718e3744 541
542 return 0;
543}
544
545void
508e53e2 546ospf6_spf_schedule (struct ospf6_area *oa)
718e3744 547{
508e53e2 548 if (oa->thread_spf_calculation)
718e3744 549 return;
508e53e2 550 oa->thread_spf_calculation =
551 thread_add_event (master, ospf6_spf_calculation_thread, oa, 0);
718e3744 552}
553
554void
0c083ee9 555ospf6_spf_display_subtree (struct vty *vty, const char *prefix, int rest,
508e53e2 556 struct ospf6_vertex *v)
718e3744 557{
1eb8ef25 558 struct listnode *node, *nnode;
508e53e2 559 struct ospf6_vertex *c;
560 char *next_prefix;
561 int len;
562 int restnum;
718e3744 563
508e53e2 564 /* "prefix" is the space prefix of the display line */
049207c3 565 vty_out (vty, "%s+-%s [%d]%s", prefix, v->name, v->cost, VNL);
718e3744 566
508e53e2 567 len = strlen (prefix) + 4;
568 next_prefix = (char *) malloc (len);
569 if (next_prefix == NULL)
718e3744 570 {
049207c3 571 vty_out (vty, "malloc failed%s", VNL);
508e53e2 572 return;
718e3744 573 }
508e53e2 574 snprintf (next_prefix, len, "%s%s", prefix, (rest ? "| " : " "));
718e3744 575
508e53e2 576 restnum = listcount (v->child_list);
1eb8ef25 577 for (ALL_LIST_ELEMENTS (v->child_list, node, nnode, c))
718e3744 578 {
508e53e2 579 restnum--;
580 ospf6_spf_display_subtree (vty, next_prefix, restnum, c);
718e3744 581 }
718e3744 582
508e53e2 583 free (next_prefix);
718e3744 584}
585
3b68735f 586DEFUN (debug_ospf6_spf_process,
587 debug_ospf6_spf_process_cmd,
588 "debug ospf6 spf process",
508e53e2 589 DEBUG_STR
590 OSPF6_STR
591 "Debug SPF Calculation\n"
3b68735f 592 "Debug Detailed SPF Process\n"
508e53e2 593 )
718e3744 594{
508e53e2 595 unsigned char level = 0;
3b68735f 596 level = OSPF6_DEBUG_SPF_PROCESS;
508e53e2 597 OSPF6_DEBUG_SPF_ON (level);
598 return CMD_SUCCESS;
718e3744 599}
600
3b68735f 601DEFUN (debug_ospf6_spf_time,
602 debug_ospf6_spf_time_cmd,
603 "debug ospf6 spf time",
508e53e2 604 DEBUG_STR
718e3744 605 OSPF6_STR
508e53e2 606 "Debug SPF Calculation\n"
3b68735f 607 "Measure time taken by SPF Calculation\n"
508e53e2 608 )
718e3744 609{
508e53e2 610 unsigned char level = 0;
3b68735f 611 level = OSPF6_DEBUG_SPF_TIME;
508e53e2 612 OSPF6_DEBUG_SPF_ON (level);
718e3744 613 return CMD_SUCCESS;
614}
615
2680aa2b 616DEFUN (debug_ospf6_spf_database,
617 debug_ospf6_spf_database_cmd,
618 "debug ospf6 spf database",
619 DEBUG_STR
620 OSPF6_STR
621 "Debug SPF Calculation\n"
622 "Log number of LSAs at SPF Calculation time\n"
623 )
624{
625 unsigned char level = 0;
626 level = OSPF6_DEBUG_SPF_DATABASE;
627 OSPF6_DEBUG_SPF_ON (level);
628 return CMD_SUCCESS;
629}
630
3b68735f 631DEFUN (no_debug_ospf6_spf_process,
632 no_debug_ospf6_spf_process_cmd,
633 "no debug ospf6 spf process",
508e53e2 634 NO_STR
635 DEBUG_STR
636 OSPF6_STR
637 "Quit Debugging SPF Calculation\n"
3b68735f 638 "Quit Debugging Detailed SPF Process\n"
508e53e2 639 )
718e3744 640{
508e53e2 641 unsigned char level = 0;
3b68735f 642 level = OSPF6_DEBUG_SPF_PROCESS;
508e53e2 643 OSPF6_DEBUG_SPF_OFF (level);
644 return CMD_SUCCESS;
718e3744 645}
646
3b68735f 647DEFUN (no_debug_ospf6_spf_time,
648 no_debug_ospf6_spf_time_cmd,
649 "no debug ospf6 spf time",
508e53e2 650 NO_STR
651 DEBUG_STR
718e3744 652 OSPF6_STR
508e53e2 653 "Quit Debugging SPF Calculation\n"
3b68735f 654 "Quit Measuring time taken by SPF Calculation\n"
508e53e2 655 )
718e3744 656{
508e53e2 657 unsigned char level = 0;
3b68735f 658 level = OSPF6_DEBUG_SPF_TIME;
508e53e2 659 OSPF6_DEBUG_SPF_OFF (level);
718e3744 660 return CMD_SUCCESS;
661}
662
2680aa2b 663DEFUN (no_debug_ospf6_spf_database,
664 no_debug_ospf6_spf_database_cmd,
665 "no debug ospf6 spf database",
666 NO_STR
667 DEBUG_STR
668 OSPF6_STR
669 "Debug SPF Calculation\n"
670 "Quit Logging number of LSAs at SPF Calculation time\n"
671 )
672{
673 unsigned char level = 0;
674 level = OSPF6_DEBUG_SPF_DATABASE;
675 OSPF6_DEBUG_SPF_OFF (level);
676 return CMD_SUCCESS;
677}
678
508e53e2 679int
680config_write_ospf6_debug_spf (struct vty *vty)
718e3744 681{
3b68735f 682 if (IS_OSPF6_DEBUG_SPF (PROCESS))
683 vty_out (vty, "debug ospf6 spf process%s", VNL);
684 if (IS_OSPF6_DEBUG_SPF (TIME))
685 vty_out (vty, "debug ospf6 spf time%s", VNL);
2680aa2b 686 if (IS_OSPF6_DEBUG_SPF (DATABASE))
687 vty_out (vty, "debug ospf6 spf database%s", VNL);
508e53e2 688 return 0;
718e3744 689}
690
508e53e2 691void
692install_element_ospf6_debug_spf ()
693{
3b68735f 694 install_element (ENABLE_NODE, &debug_ospf6_spf_process_cmd);
695 install_element (ENABLE_NODE, &debug_ospf6_spf_time_cmd);
2680aa2b 696 install_element (ENABLE_NODE, &debug_ospf6_spf_database_cmd);
3b68735f 697 install_element (ENABLE_NODE, &no_debug_ospf6_spf_process_cmd);
698 install_element (ENABLE_NODE, &no_debug_ospf6_spf_time_cmd);
2680aa2b 699 install_element (ENABLE_NODE, &no_debug_ospf6_spf_database_cmd);
3b68735f 700 install_element (CONFIG_NODE, &debug_ospf6_spf_process_cmd);
701 install_element (CONFIG_NODE, &debug_ospf6_spf_time_cmd);
2680aa2b 702 install_element (CONFIG_NODE, &debug_ospf6_spf_database_cmd);
3b68735f 703 install_element (CONFIG_NODE, &no_debug_ospf6_spf_process_cmd);
704 install_element (CONFIG_NODE, &no_debug_ospf6_spf_time_cmd);
2680aa2b 705 install_element (CONFIG_NODE, &no_debug_ospf6_spf_database_cmd);
508e53e2 706}
718e3744 707
708void
709ospf6_spf_init ()
710{
718e3744 711}
712
508e53e2 713