]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_spf.c
cumulus: Add new daemons to daemons file
[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"
ca1f4309
DS
39#include "ospf6_proto.h"
40#include "ospf6_abr.h"
718e3744 41#include "ospf6_spf.h"
508e53e2 42#include "ospf6_intra.h"
718e3744 43#include "ospf6_interface.h"
049207c3 44#include "ospf6d.h"
1f9a9fff 45#include "ospf6_abr.h"
718e3744 46
508e53e2 47unsigned char conf_debug_ospf6_spf = 0;
718e3744 48
c3c0ac83
DS
49static void
50ospf6_spf_copy_nexthops_to_route (struct ospf6_route *rt,
51 struct ospf6_vertex *v)
52{
53 if (rt && v)
54 ospf6_copy_nexthops (rt->nh_list, v->nh_list);
55}
56
57static void
58ospf6_spf_merge_nexthops_to_route (struct ospf6_route *rt,
59 struct ospf6_vertex *v)
60{
61 if (rt && v)
62 ospf6_merge_nexthops (rt->nh_list, v->nh_list);
63}
64
ed2eb093 65static unsigned int
c3c0ac83
DS
66ospf6_spf_get_ifindex_from_nh (struct ospf6_vertex *v)
67{
68 struct ospf6_nexthop *nh;
69 struct listnode *node;
70
71 if (v)
72 {
73 node = listhead(v->nh_list);
74 if (node)
75 {
76 nh = listgetdata (node);
77 if (nh)
78 return (nh->ifindex);
79 }
80 }
ed2eb093 81 return 0;
c3c0ac83
DS
82}
83
6ac29a51 84static int
508e53e2 85ospf6_vertex_cmp (void *a, void *b)
718e3744 86{
508e53e2 87 struct ospf6_vertex *va = (struct ospf6_vertex *) a;
88 struct ospf6_vertex *vb = (struct ospf6_vertex *) b;
718e3744 89
508e53e2 90 /* ascending order */
403138e1
DT
91 if (va->cost != vb->cost)
92 return (va->cost - vb->cost);
93 return (va->hops - vb->hops);
718e3744 94}
95
6ac29a51 96static int
508e53e2 97ospf6_vertex_id_cmp (void *a, void *b)
718e3744 98{
508e53e2 99 struct ospf6_vertex *va = (struct ospf6_vertex *) a;
100 struct ospf6_vertex *vb = (struct ospf6_vertex *) b;
101 int ret = 0;
718e3744 102
508e53e2 103 ret = ntohl (ospf6_linkstate_prefix_adv_router (&va->vertex_id)) -
104 ntohl (ospf6_linkstate_prefix_adv_router (&vb->vertex_id));
105 if (ret)
106 return ret;
718e3744 107
508e53e2 108 ret = ntohl (ospf6_linkstate_prefix_id (&va->vertex_id)) -
109 ntohl (ospf6_linkstate_prefix_id (&vb->vertex_id));
718e3744 110 return ret;
111}
112
6ac29a51 113static struct ospf6_vertex *
508e53e2 114ospf6_vertex_create (struct ospf6_lsa *lsa)
718e3744 115{
508e53e2 116 struct ospf6_vertex *v;
718e3744 117
508e53e2 118 v = (struct ospf6_vertex *)
119 XMALLOC (MTYPE_OSPF6_VERTEX, sizeof (struct ospf6_vertex));
718e3744 120
508e53e2 121 /* type */
122 if (ntohs (lsa->header->type) == OSPF6_LSTYPE_ROUTER)
123 v->type = OSPF6_VERTEX_TYPE_ROUTER;
124 else if (ntohs (lsa->header->type) == OSPF6_LSTYPE_NETWORK)
125 v->type = OSPF6_VERTEX_TYPE_NETWORK;
718e3744 126 else
508e53e2 127 assert (0);
718e3744 128
508e53e2 129 /* vertex_id */
130 ospf6_linkstate_prefix (lsa->header->adv_router, lsa->header->id,
131 &v->vertex_id);
718e3744 132
508e53e2 133 /* name */
134 ospf6_linkstate_prefix2str (&v->vertex_id, v->name, sizeof (v->name));
718e3744 135
c3c0ac83
DS
136 if (IS_OSPF6_DEBUG_SPF (PROCESS))
137 zlog_debug ("%s: Creating vertex %s of type %s", __func__, v->name,
138 ((ntohs (lsa->header->type) == OSPF6_LSTYPE_ROUTER) ? "Router" : "N/W"));
139
508e53e2 140 /* Associated LSA */
141 v->lsa = lsa;
718e3744 142
508e53e2 143 /* capability bits + options */
144 v->capability = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header));
145 v->options[0] = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header) + 1);
146 v->options[1] = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header) + 2);
147 v->options[2] = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header) + 3);
718e3744 148
c3c0ac83 149 v->nh_list = list_new();
718e3744 150
508e53e2 151 v->parent = NULL;
152 v->child_list = list_new ();
153 v->child_list->cmp = ospf6_vertex_id_cmp;
718e3744 154
508e53e2 155 return v;
718e3744 156}
157
6ac29a51 158static void
508e53e2 159ospf6_vertex_delete (struct ospf6_vertex *v)
718e3744 160{
3f6d6a5d 161 list_delete(v->nh_list);
508e53e2 162 list_delete (v->child_list);
163 XFREE (MTYPE_OSPF6_VERTEX, v);
718e3744 164}
165
6ac29a51 166static struct ospf6_lsa *
508e53e2 167ospf6_lsdesc_lsa (caddr_t lsdesc, struct ospf6_vertex *v)
718e3744 168{
508e53e2 169 struct ospf6_lsa *lsa;
170 u_int16_t type = 0;
171 u_int32_t id = 0, adv_router = 0;
718e3744 172
508e53e2 173 if (VERTEX_IS_TYPE (NETWORK, v))
718e3744 174 {
508e53e2 175 type = htons (OSPF6_LSTYPE_ROUTER);
176 id = htonl (0);
177 adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc);
718e3744 178 }
179 else
180 {
508e53e2 181 if (ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, lsdesc))
718e3744 182 {
508e53e2 183 type = htons (OSPF6_LSTYPE_ROUTER);
718e3744 184 id = htonl (0);
508e53e2 185 adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc);
718e3744 186 }
508e53e2 187 else if (ROUTER_LSDESC_IS_TYPE (TRANSIT_NETWORK, lsdesc))
718e3744 188 {
508e53e2 189 type = htons (OSPF6_LSTYPE_NETWORK);
190 id = htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc));
191 adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc);
718e3744 192 }
718e3744 193 }
194
508e53e2 195 lsa = ospf6_lsdb_lookup (type, id, adv_router, v->area->lsdb);
718e3744 196
3b68735f 197 if (IS_OSPF6_DEBUG_SPF (PROCESS))
718e3744 198 {
508e53e2 199 char ibuf[16], abuf[16];
200 inet_ntop (AF_INET, &id, ibuf, sizeof (ibuf));
201 inet_ntop (AF_INET, &adv_router, abuf, sizeof (abuf));
202 if (lsa)
c6487d61 203 zlog_debug (" Link to: %s", lsa->name);
508e53e2 204 else
c6487d61 205 zlog_debug (" Link to: [%s Id:%s Adv:%s] No LSA",
206 ospf6_lstype_name (type), ibuf, abuf);
718e3744 207 }
208
508e53e2 209 return lsa;
718e3744 210}
211
6ac29a51 212static char *
508e53e2 213ospf6_lsdesc_backlink (struct ospf6_lsa *lsa,
214 caddr_t lsdesc, struct ospf6_vertex *v)
718e3744 215{
508e53e2 216 caddr_t backlink, found = NULL;
217 int size;
718e3744 218
508e53e2 219 size = (OSPF6_LSA_IS_TYPE (ROUTER, lsa) ?
220 sizeof (struct ospf6_router_lsdesc) :
221 sizeof (struct ospf6_network_lsdesc));
222 for (backlink = OSPF6_LSA_HEADER_END (lsa->header) + 4;
223 backlink + size <= OSPF6_LSA_END (lsa->header); backlink += size)
718e3744 224 {
508e53e2 225 assert (! (OSPF6_LSA_IS_TYPE (NETWORK, lsa) &&
226 VERTEX_IS_TYPE (NETWORK, v)));
718e3744 227
508e53e2 228 if (OSPF6_LSA_IS_TYPE (NETWORK, lsa) &&
229 NETWORK_LSDESC_GET_NBR_ROUTERID (backlink)
230 == v->lsa->header->adv_router)
231 found = backlink;
232 else if (VERTEX_IS_TYPE (NETWORK, v) &&
233 ROUTER_LSDESC_IS_TYPE (TRANSIT_NETWORK, backlink) &&
234 ROUTER_LSDESC_GET_NBR_ROUTERID (backlink)
235 == v->lsa->header->adv_router &&
236 ROUTER_LSDESC_GET_NBR_IFID (backlink)
237 == ntohl (v->lsa->header->id))
238 found = backlink;
239 else
240 {
241 if (! ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, backlink) ||
242 ! ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, lsdesc))
243 continue;
244 if (ROUTER_LSDESC_GET_NBR_IFID (backlink) !=
245 ROUTER_LSDESC_GET_IFID (lsdesc) ||
246 ROUTER_LSDESC_GET_NBR_IFID (lsdesc) !=
247 ROUTER_LSDESC_GET_IFID (backlink))
248 continue;
249 if (ROUTER_LSDESC_GET_NBR_ROUTERID (backlink) !=
250 v->lsa->header->adv_router ||
251 ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc) !=
252 lsa->header->adv_router)
253 continue;
254 found = backlink;
255 }
718e3744 256 }
718e3744 257
3b68735f 258 if (IS_OSPF6_DEBUG_SPF (PROCESS))
c6487d61 259 zlog_debug (" Backlink %s", (found ? "OK" : "FAIL"));
718e3744 260
508e53e2 261 return found;
718e3744 262}
263
6ac29a51 264static void
508e53e2 265ospf6_nexthop_calc (struct ospf6_vertex *w, struct ospf6_vertex *v,
266 caddr_t lsdesc)
718e3744 267{
c3c0ac83 268 int i;
b892f1dd 269 ifindex_t ifindex;
508e53e2 270 struct ospf6_interface *oi;
271 u_int16_t type;
272 u_int32_t adv_router;
273 struct ospf6_lsa *lsa;
274 struct ospf6_link_lsa *link_lsa;
275 char buf[64];
718e3744 276
508e53e2 277 assert (VERTEX_IS_TYPE (ROUTER, w));
c3c0ac83 278 ifindex = (VERTEX_IS_TYPE (NETWORK, v) ? ospf6_spf_get_ifindex_from_nh (v) :
508e53e2 279 ROUTER_LSDESC_GET_IFID (lsdesc));
ed2eb093 280 if (ifindex == 0)
c3c0ac83
DS
281 {
282 zlog_err ("No nexthop ifindex at vertex %s", v->name);
283 return;
284 }
285
508e53e2 286 oi = ospf6_interface_lookup_by_ifindex (ifindex);
287 if (oi == NULL)
718e3744 288 {
3b68735f 289 if (IS_OSPF6_DEBUG_SPF (PROCESS))
c6487d61 290 zlog_debug ("Can't find interface in SPF: ifindex %d", ifindex);
508e53e2 291 return;
718e3744 292 }
293
508e53e2 294 type = htons (OSPF6_LSTYPE_LINK);
295 adv_router = (VERTEX_IS_TYPE (NETWORK, v) ?
296 NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc) :
297 ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc));
718e3744 298
508e53e2 299 i = 0;
300 for (lsa = ospf6_lsdb_type_router_head (type, adv_router, oi->lsdb); lsa;
301 lsa = ospf6_lsdb_type_router_next (type, adv_router, lsa))
718e3744 302 {
508e53e2 303 if (VERTEX_IS_TYPE (ROUTER, v) &&
304 htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc)) != lsa->header->id)
718e3744 305 continue;
306
508e53e2 307 link_lsa = (struct ospf6_link_lsa *) OSPF6_LSA_HEADER_END (lsa->header);
3b68735f 308 if (IS_OSPF6_DEBUG_SPF (PROCESS))
508e53e2 309 {
310 inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf));
c6487d61 311 zlog_debug (" nexthop %s from %s", buf, lsa->name);
508e53e2 312 }
718e3744 313
c3c0ac83
DS
314 ospf6_add_nexthop (w->nh_list, ifindex, &link_lsa->linklocal_addr);
315 i++;
718e3744 316 }
317
3b68735f 318 if (i == 0 && IS_OSPF6_DEBUG_SPF (PROCESS))
c6487d61 319 zlog_debug ("No nexthop for %s found", w->name);
718e3744 320}
321
6ac29a51 322static int
508e53e2 323ospf6_spf_install (struct ospf6_vertex *v,
324 struct ospf6_route_table *result_table)
718e3744 325{
c3c0ac83 326 struct ospf6_route *route, *parent_route;
87362ceb 327 struct ospf6_vertex *prev;
718e3744 328
3b68735f 329 if (IS_OSPF6_DEBUG_SPF (PROCESS))
c6487d61 330 zlog_debug ("SPF install %s hops %d cost %d",
331 v->name, v->hops, v->cost);
718e3744 332
508e53e2 333 route = ospf6_route_lookup (&v->vertex_id, result_table);
334 if (route && route->path.cost < v->cost)
718e3744 335 {
3b68735f 336 if (IS_OSPF6_DEBUG_SPF (PROCESS))
c6487d61 337 zlog_debug (" already installed with lower cost (%d), ignore",
338 route->path.cost);
508e53e2 339 ospf6_vertex_delete (v);
340 return -1;
718e3744 341 }
508e53e2 342 else if (route && route->path.cost == v->cost)
718e3744 343 {
3b68735f 344 if (IS_OSPF6_DEBUG_SPF (PROCESS))
c6487d61 345 zlog_debug (" another path found, merge");
718e3744 346
c3c0ac83 347 ospf6_spf_merge_nexthops_to_route (route, v);
718e3744 348
508e53e2 349 prev = (struct ospf6_vertex *) route->route_option;
403138e1
DT
350 assert (prev->hops <= v->hops);
351 ospf6_vertex_delete (v);
718e3744 352
508e53e2 353 return -1;
718e3744 354 }
508e53e2 355
356 /* There should be no case where candidate being installed (variable
357 "v") is closer than the one in the SPF tree (variable "route").
6452df09 358 In the case something has gone wrong with the behavior of
508e53e2 359 Priority-Queue. */
6452df09 360
361 /* the case where the route exists already is handled and returned
362 up to here. */
508e53e2 363 assert (route == NULL);
364
365 route = ospf6_route_create ();
366 memcpy (&route->prefix, &v->vertex_id, sizeof (struct prefix));
367 route->type = OSPF6_DEST_TYPE_LINKSTATE;
368 route->path.type = OSPF6_PATH_TYPE_INTRA;
369 route->path.origin.type = v->lsa->header->type;
370 route->path.origin.id = v->lsa->header->id;
371 route->path.origin.adv_router = v->lsa->header->adv_router;
372 route->path.metric_type = 1;
373 route->path.cost = v->cost;
c3c0ac83 374 route->path.u.cost_e2 = v->hops;
508e53e2 375 route->path.router_bits = v->capability;
376 route->path.options[0] = v->options[0];
377 route->path.options[1] = v->options[1];
378 route->path.options[2] = v->options[2];
379
c3c0ac83
DS
380 ospf6_spf_copy_nexthops_to_route (route, v);
381
382 /*
383 * The SPF logic implementation does not transfer the multipathing properties
384 * of a parent to a child node. Thus if there was a 3-way multipath to a
385 * node's parent and a single hop from the parent to the child, the logic of
386 * creating new vertices and computing next hops prevents there from being 3
387 * paths to the child node. This is primarily because the resolution of
388 * multipath is done in this routine, not in the main spf loop.
389 *
390 * The following logic addresses that problem by merging the parent's nexthop
391 * information with the child's, if the parent is not the root of the tree.
392 * This is based on the assumption that before a node's route is installed,
393 * its parent's route's nexthops have already been installed.
394 */
395 if (v->parent && v->parent->hops)
396 {
397 parent_route = ospf6_route_lookup (&v->parent->vertex_id, result_table);
398 if (parent_route)
399 {
400 ospf6_route_merge_nexthops (route, parent_route);
401 }
402 }
508e53e2 403
404 if (v->parent)
405 listnode_add_sort (v->parent->child_list, v);
406 route->route_option = v;
407
408 ospf6_route_add (route, result_table);
409 return 0;
718e3744 410}
411
508e53e2 412void
413ospf6_spf_table_finish (struct ospf6_route_table *result_table)
718e3744 414{
0f23bb67 415 struct ospf6_route *route, *nroute;
718e3744 416 struct ospf6_vertex *v;
508e53e2 417 for (route = ospf6_route_head (result_table); route;
0f23bb67 418 route = nroute)
718e3744 419 {
0f23bb67 420 nroute = ospf6_route_next (route);
508e53e2 421 v = (struct ospf6_vertex *) route->route_option;
422 ospf6_vertex_delete (v);
423 ospf6_route_remove (route, result_table);
718e3744 424 }
718e3744 425}
426
a0edf674
DD
427static const char *ospf6_spf_reason_str[] =
428 {
429 "R+",
430 "R-",
431 "N+",
432 "N-",
433 "L+",
434 "L-",
435 "R*",
436 "N*",
437 };
438
439void ospf6_spf_reason_string (unsigned int reason, char *buf, int size)
440{
ed2eb093 441 unsigned int bit;
a0edf674
DD
442 int len = 0;
443
444 if (!buf)
445 return;
446
e531bbe2 447 for (bit = 0; bit < array_size(ospf6_spf_reason_str); bit++)
a0edf674
DD
448 {
449 if ((reason & (1 << bit)) && (len < size))
450 {
451 len += snprintf((buf + len), (size - len), "%s%s",
452 (len > 0) ? ", " : "", ospf6_spf_reason_str[bit]);
453 }
454 }
455}
456
6452df09 457/* RFC2328 16.1. Calculating the shortest-path tree for an area */
458/* RFC2740 3.8.1. Calculating the shortest path tree for an area */
508e53e2 459void
460ospf6_spf_calculation (u_int32_t router_id,
461 struct ospf6_route_table *result_table,
462 struct ospf6_area *oa)
463{
464 struct pqueue *candidate_list;
465 struct ospf6_vertex *root, *v, *w;
508e53e2 466 int size;
467 caddr_t lsdesc;
468 struct ospf6_lsa *lsa;
c3c0ac83 469 struct in6_addr address;
718e3744 470
b48cebbb
TG
471 ospf6_spf_table_finish (result_table);
472
508e53e2 473 /* Install the calculating router itself as the root of the SPF tree */
474 /* construct root vertex */
475 lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_ROUTER), htonl (0),
c3c0ac83 476 router_id, oa->lsdb_self);
508e53e2 477 if (lsa == NULL)
c3c0ac83
DS
478 {
479 if (IS_OSPF6_DEBUG_SPF (PROCESS))
480 zlog_debug ("%s: No router LSA for area %s\n",
481 __func__, oa->name);
482 return;
483 }
1d19234e
TG
484
485 /* initialize */
486 candidate_list = pqueue_create ();
487 candidate_list->cmp = ospf6_vertex_cmp;
488
508e53e2 489 root = ospf6_vertex_create (lsa);
490 root->area = oa;
491 root->cost = 0;
492 root->hops = 0;
c3c0ac83 493 inet_pton (AF_INET6, "::1", &address);
718e3744 494
508e53e2 495 /* Actually insert root to the candidate-list as the only candidate */
496 pqueue_enqueue (root, candidate_list);
718e3744 497
508e53e2 498 /* Iterate until candidate-list becomes empty */
499 while (candidate_list->size)
718e3744 500 {
508e53e2 501 /* get closest candidate from priority queue */
502 v = pqueue_dequeue (candidate_list);
718e3744 503
6452df09 504 /* installing may result in merging or rejecting of the vertex */
508e53e2 505 if (ospf6_spf_install (v, result_table) < 0)
506 continue;
718e3744 507
f41b4a02
DD
508 /* Skip overloaded routers */
509 if ((OSPF6_LSA_IS_TYPE (ROUTER, v->lsa) &&
510 ospf6_router_is_stub_router (v->lsa)))
511 continue;
512
508e53e2 513 /* For each LS description in the just-added vertex V's LSA */
514 size = (VERTEX_IS_TYPE (ROUTER, v) ?
515 sizeof (struct ospf6_router_lsdesc) :
516 sizeof (struct ospf6_network_lsdesc));
517 for (lsdesc = OSPF6_LSA_HEADER_END (v->lsa->header) + 4;
518 lsdesc + size <= OSPF6_LSA_END (v->lsa->header); lsdesc += size)
718e3744 519 {
508e53e2 520 lsa = ospf6_lsdesc_lsa (lsdesc, v);
521 if (lsa == NULL)
718e3744 522 continue;
523
c3c0ac83
DS
524 if (OSPF6_LSA_IS_MAXAGE (lsa))
525 continue;
526
508e53e2 527 if (! ospf6_lsdesc_backlink (lsa, lsdesc, v))
528 continue;
718e3744 529
508e53e2 530 w = ospf6_vertex_create (lsa);
531 w->area = oa;
532 w->parent = v;
533 if (VERTEX_IS_TYPE (ROUTER, v))
718e3744 534 {
508e53e2 535 w->cost = v->cost + ROUTER_LSDESC_GET_METRIC (lsdesc);
536 w->hops = v->hops + (VERTEX_IS_TYPE (NETWORK, w) ? 0 : 1);
718e3744 537 }
508e53e2 538 else /* NETWORK */
718e3744 539 {
508e53e2 540 w->cost = v->cost;
541 w->hops = v->hops + 1;
718e3744 542 }
543
508e53e2 544 /* nexthop calculation */
545 if (w->hops == 0)
c3c0ac83 546 ospf6_add_nexthop (w->nh_list, ROUTER_LSDESC_GET_IFID (lsdesc), NULL);
508e53e2 547 else if (w->hops == 1 && v->hops == 0)
548 ospf6_nexthop_calc (w, v, lsdesc);
718e3744 549 else
550 {
c3c0ac83 551 ospf6_copy_nexthops (w->nh_list, v->nh_list);
718e3744 552 }
553
508e53e2 554 /* add new candidate to the candidate_list */
3b68735f 555 if (IS_OSPF6_DEBUG_SPF (PROCESS))
c6487d61 556 zlog_debug (" New candidate: %s hops %d cost %d",
557 w->name, w->hops, w->cost);
508e53e2 558 pqueue_enqueue (w, candidate_list);
718e3744 559 }
560 }
561
508e53e2 562 pqueue_delete (candidate_list);
ea86e404
VB
563
564 oa->spf_calculation++;
718e3744 565}
566
6ac29a51 567static void
2680aa2b 568ospf6_spf_log_database (struct ospf6_area *oa)
569{
570 char *p, *end, buffer[256];
571 struct listnode *node;
572 struct ospf6_interface *oi;
573
574 p = buffer;
575 end = buffer + sizeof (buffer);
576
577 snprintf (p, end - p, "SPF on DB (#LSAs):");
578 p = (buffer + strlen (buffer) < end ? buffer + strlen (buffer) : end);
579 snprintf (p, end - p, " Area %s: %d", oa->name, oa->lsdb->count);
580 p = (buffer + strlen (buffer) < end ? buffer + strlen (buffer) : end);
581
1eb8ef25 582 for (ALL_LIST_ELEMENTS_RO (oa->if_list, node, oi))
2680aa2b 583 {
2680aa2b 584 snprintf (p, end - p, " I/F %s: %d",
585 oi->interface->name, oi->lsdb->count);
586 p = (buffer + strlen (buffer) < end ? buffer + strlen (buffer) : end);
587 }
588
c6487d61 589 zlog_debug ("%s", buffer);
2680aa2b 590}
591
6ac29a51 592static int
718e3744 593ospf6_spf_calculation_thread (struct thread *t)
594{
508e53e2 595 struct ospf6_area *oa;
3810e06e 596 struct ospf6 *ospf6;
508e53e2 597 struct timeval start, end, runtime;
3810e06e 598 struct listnode *node;
a0edf674
DD
599 int areas_processed = 0;
600 char rbuf[32];
718e3744 601
3810e06e
DD
602 ospf6 = (struct ospf6 *)THREAD_ARG (t);
603 ospf6->t_spf_calc = NULL;
718e3744 604
605 /* execute SPF calculation */
cf672a86 606 monotime(&start);
3810e06e 607
ca1f4309
DS
608 if (ospf6_is_router_abr (ospf6))
609 ospf6_abr_range_reset_cost (ospf6);
610
3810e06e
DD
611 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa))
612 {
613
614 if (oa == ospf6->backbone)
615 continue;
616
617 if (IS_OSPF6_DEBUG_SPF (PROCESS))
618 zlog_debug ("SPF calculation for Area %s", oa->name);
619 if (IS_OSPF6_DEBUG_SPF (DATABASE))
620 ospf6_spf_log_database (oa);
621
622 ospf6_spf_calculation (ospf6->router_id, oa->spf_table, oa);
623 ospf6_intra_route_calculation (oa);
624 ospf6_intra_brouter_calculation (oa);
a0edf674
DD
625
626 areas_processed++;
3810e06e
DD
627 }
628
629 if (ospf6->backbone)
630 {
631 if (IS_OSPF6_DEBUG_SPF (PROCESS))
632 zlog_debug ("SPF calculation for Backbone area %s",
633 ospf6->backbone->name);
634 if (IS_OSPF6_DEBUG_SPF (DATABASE))
635 ospf6_spf_log_database(ospf6->backbone);
636
637 ospf6_spf_calculation(ospf6->router_id, ospf6->backbone->spf_table,
638 ospf6->backbone);
639 ospf6_intra_route_calculation(ospf6->backbone);
640 ospf6_intra_brouter_calculation(ospf6->backbone);
a0edf674 641 areas_processed++;
3810e06e
DD
642 }
643
ca1f4309
DS
644 if (ospf6_is_router_abr (ospf6))
645 ospf6_abr_defaults_to_stub (ospf6);
3810e06e 646
cf672a86 647 monotime(&end);
2680aa2b 648 timersub (&end, &start, &runtime);
718e3744 649
3810e06e
DD
650 ospf6->ts_spf_duration = runtime;
651
a0edf674
DD
652 ospf6_spf_reason_string(ospf6->spf_reason, rbuf, sizeof(rbuf));
653
3b68735f 654 if (IS_OSPF6_DEBUG_SPF (PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
8f2c16aa
DL
655 zlog_debug ("SPF runtime: %lld sec %lld usec",
656 (long long)runtime.tv_sec, (long long)runtime.tv_usec);
718e3744 657
8f2c16aa
DL
658 zlog_info("SPF processing: # Areas: %d, SPF runtime: %lld sec %lld usec, "
659 "Reason: %s\n", areas_processed,
660 (long long)runtime.tv_sec, (long long)runtime.tv_usec,
a0edf674
DD
661 rbuf);
662 ospf6->last_spf_reason = ospf6->spf_reason;
663 ospf6_reset_spf_reason(ospf6);
718e3744 664 return 0;
665}
666
3810e06e
DD
667/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
668 set timer for SPF calc. */
718e3744 669void
a0edf674 670ospf6_spf_schedule (struct ospf6 *ospf6, unsigned int reason)
718e3744 671{
3810e06e 672 unsigned long delay, elapsed, ht;
3810e06e 673
a0edf674
DD
674 ospf6_set_spf_reason(ospf6, reason);
675
3810e06e 676 if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
a0edf674
DD
677 {
678 char rbuf[32];
679 ospf6_spf_reason_string(reason, rbuf, sizeof(rbuf));
680 zlog_debug ("SPF: calculation timer scheduled (reason %s)", rbuf);
681 }
3810e06e
DD
682
683 /* OSPF instance does not exist. */
684 if (ospf6 == NULL)
718e3744 685 return;
3810e06e
DD
686
687 /* SPF calculation timer is already scheduled. */
688 if (ospf6->t_spf_calc)
689 {
690 if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
691 zlog_debug ("SPF: calculation timer is already scheduled: %p",
6c4f4e6e 692 (void *)ospf6->t_spf_calc);
3810e06e
DD
693 return;
694 }
695
6ced0e7f 696 elapsed = monotime_since(&ospf6->ts_spf, NULL) / 1000LL;
3810e06e
DD
697 ht = ospf6->spf_holdtime * ospf6->spf_hold_multiplier;
698
699 if (ht > ospf6->spf_max_holdtime)
700 ht = ospf6->spf_max_holdtime;
701
702 /* Get SPF calculation delay time. */
703 if (elapsed < ht)
704 {
705 /* Got an event within the hold time of last SPF. We need to
706 * increase the hold_multiplier, if it's not already at/past
707 * maximum value, and wasn't already increased..
708 */
709 if (ht < ospf6->spf_max_holdtime)
710 ospf6->spf_hold_multiplier++;
711
712 /* always honour the SPF initial delay */
713 if ( (ht - elapsed) < ospf6->spf_delay)
714 delay = ospf6->spf_delay;
715 else
716 delay = ht - elapsed;
717 }
718 else
719 {
720 /* Event is past required hold-time of last SPF */
721 delay = ospf6->spf_delay;
722 ospf6->spf_hold_multiplier = 1;
723 }
724
725 if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
726 zlog_debug ("SPF: calculation timer delay = %ld", delay);
727
728 zlog_info ("SPF: Scheduled in %ld msec", delay);
729
730 ospf6->t_spf_calc =
731 thread_add_timer_msec (master, ospf6_spf_calculation_thread, ospf6, delay);
718e3744 732}
733
734void
0c083ee9 735ospf6_spf_display_subtree (struct vty *vty, const char *prefix, int rest,
508e53e2 736 struct ospf6_vertex *v)
718e3744 737{
1eb8ef25 738 struct listnode *node, *nnode;
508e53e2 739 struct ospf6_vertex *c;
740 char *next_prefix;
741 int len;
742 int restnum;
718e3744 743
508e53e2 744 /* "prefix" is the space prefix of the display line */
049207c3 745 vty_out (vty, "%s+-%s [%d]%s", prefix, v->name, v->cost, VNL);
718e3744 746
508e53e2 747 len = strlen (prefix) + 4;
748 next_prefix = (char *) malloc (len);
749 if (next_prefix == NULL)
718e3744 750 {
049207c3 751 vty_out (vty, "malloc failed%s", VNL);
508e53e2 752 return;
718e3744 753 }
508e53e2 754 snprintf (next_prefix, len, "%s%s", prefix, (rest ? "| " : " "));
718e3744 755
508e53e2 756 restnum = listcount (v->child_list);
1eb8ef25 757 for (ALL_LIST_ELEMENTS (v->child_list, node, nnode, c))
718e3744 758 {
508e53e2 759 restnum--;
760 ospf6_spf_display_subtree (vty, next_prefix, restnum, c);
718e3744 761 }
718e3744 762
508e53e2 763 free (next_prefix);
718e3744 764}
765
3b68735f 766DEFUN (debug_ospf6_spf_process,
767 debug_ospf6_spf_process_cmd,
768 "debug ospf6 spf process",
508e53e2 769 DEBUG_STR
770 OSPF6_STR
771 "Debug SPF Calculation\n"
3b68735f 772 "Debug Detailed SPF Process\n"
508e53e2 773 )
718e3744 774{
508e53e2 775 unsigned char level = 0;
3b68735f 776 level = OSPF6_DEBUG_SPF_PROCESS;
508e53e2 777 OSPF6_DEBUG_SPF_ON (level);
778 return CMD_SUCCESS;
718e3744 779}
780
3b68735f 781DEFUN (debug_ospf6_spf_time,
782 debug_ospf6_spf_time_cmd,
783 "debug ospf6 spf time",
508e53e2 784 DEBUG_STR
718e3744 785 OSPF6_STR
508e53e2 786 "Debug SPF Calculation\n"
3b68735f 787 "Measure time taken by SPF Calculation\n"
508e53e2 788 )
718e3744 789{
508e53e2 790 unsigned char level = 0;
3b68735f 791 level = OSPF6_DEBUG_SPF_TIME;
508e53e2 792 OSPF6_DEBUG_SPF_ON (level);
718e3744 793 return CMD_SUCCESS;
794}
795
2680aa2b 796DEFUN (debug_ospf6_spf_database,
797 debug_ospf6_spf_database_cmd,
798 "debug ospf6 spf database",
799 DEBUG_STR
800 OSPF6_STR
801 "Debug SPF Calculation\n"
802 "Log number of LSAs at SPF Calculation time\n"
803 )
804{
805 unsigned char level = 0;
806 level = OSPF6_DEBUG_SPF_DATABASE;
807 OSPF6_DEBUG_SPF_ON (level);
808 return CMD_SUCCESS;
809}
810
3b68735f 811DEFUN (no_debug_ospf6_spf_process,
812 no_debug_ospf6_spf_process_cmd,
813 "no debug ospf6 spf process",
508e53e2 814 NO_STR
815 DEBUG_STR
816 OSPF6_STR
817 "Quit Debugging SPF Calculation\n"
3b68735f 818 "Quit Debugging Detailed SPF Process\n"
508e53e2 819 )
718e3744 820{
508e53e2 821 unsigned char level = 0;
3b68735f 822 level = OSPF6_DEBUG_SPF_PROCESS;
508e53e2 823 OSPF6_DEBUG_SPF_OFF (level);
824 return CMD_SUCCESS;
718e3744 825}
826
3b68735f 827DEFUN (no_debug_ospf6_spf_time,
828 no_debug_ospf6_spf_time_cmd,
829 "no debug ospf6 spf time",
508e53e2 830 NO_STR
831 DEBUG_STR
718e3744 832 OSPF6_STR
508e53e2 833 "Quit Debugging SPF Calculation\n"
3b68735f 834 "Quit Measuring time taken by SPF Calculation\n"
508e53e2 835 )
718e3744 836{
508e53e2 837 unsigned char level = 0;
3b68735f 838 level = OSPF6_DEBUG_SPF_TIME;
508e53e2 839 OSPF6_DEBUG_SPF_OFF (level);
718e3744 840 return CMD_SUCCESS;
841}
842
2680aa2b 843DEFUN (no_debug_ospf6_spf_database,
844 no_debug_ospf6_spf_database_cmd,
845 "no debug ospf6 spf database",
846 NO_STR
847 DEBUG_STR
848 OSPF6_STR
849 "Debug SPF Calculation\n"
850 "Quit Logging number of LSAs at SPF Calculation time\n"
851 )
852{
853 unsigned char level = 0;
854 level = OSPF6_DEBUG_SPF_DATABASE;
855 OSPF6_DEBUG_SPF_OFF (level);
856 return CMD_SUCCESS;
857}
858
3810e06e
DD
859static int
860ospf6_timers_spf_set (struct vty *vty, unsigned int delay,
861 unsigned int hold,
862 unsigned int max)
863{
cdc2d765 864 VTY_DECLVAR_CONTEXT(ospf6, ospf);
3810e06e
DD
865
866 ospf->spf_delay = delay;
867 ospf->spf_holdtime = hold;
868 ospf->spf_max_holdtime = max;
869
870 return CMD_SUCCESS;
871}
872
873DEFUN (ospf6_timers_throttle_spf,
874 ospf6_timers_throttle_spf_cmd,
6147e2c6 875 "timers throttle spf (0-600000) (0-600000) (0-600000)",
3810e06e
DD
876 "Adjust routing timers\n"
877 "Throttling adaptive timer\n"
878 "OSPF6 SPF timers\n"
879 "Delay (msec) from first change received till SPF calculation\n"
880 "Initial hold time (msec) between consecutive SPF calculations\n"
881 "Maximum hold time (msec)\n")
882{
51c26414
DW
883 int idx_number = 3;
884 int idx_number_2 = 4;
885 int idx_number_3 = 5;
3810e06e
DD
886 unsigned int delay, hold, max;
887
51c26414
DW
888 VTY_GET_INTEGER_RANGE ("SPF delay timer", delay, argv[idx_number]->arg, 0, 600000);
889 VTY_GET_INTEGER_RANGE ("SPF hold timer", hold, argv[idx_number_2]->arg, 0, 600000);
890 VTY_GET_INTEGER_RANGE ("SPF max-hold timer", max, argv[idx_number_3]->arg, 0, 600000);
3810e06e
DD
891
892 return ospf6_timers_spf_set (vty, delay, hold, max);
893}
894
895DEFUN (no_ospf6_timers_throttle_spf,
896 no_ospf6_timers_throttle_spf_cmd,
1d68dbfe 897 "no timers throttle spf [(0-600000) (0-600000) (0-600000)]",
3810e06e
DD
898 NO_STR
899 "Adjust routing timers\n"
900 "Throttling adaptive timer\n"
1d68dbfe
DW
901 "OSPF6 SPF timers\n"
902 "Delay (msec) from first change received till SPF calculation\n"
903 "Initial hold time (msec) between consecutive SPF calculations\n"
904 "Maximum hold time (msec)\n")
3810e06e
DD
905{
906 return ospf6_timers_spf_set (vty,
907 OSPF_SPF_DELAY_DEFAULT,
908 OSPF_SPF_HOLDTIME_DEFAULT,
909 OSPF_SPF_MAX_HOLDTIME_DEFAULT);
910}
911
813d4307 912
508e53e2 913int
914config_write_ospf6_debug_spf (struct vty *vty)
718e3744 915{
3b68735f 916 if (IS_OSPF6_DEBUG_SPF (PROCESS))
917 vty_out (vty, "debug ospf6 spf process%s", VNL);
918 if (IS_OSPF6_DEBUG_SPF (TIME))
919 vty_out (vty, "debug ospf6 spf time%s", VNL);
2680aa2b 920 if (IS_OSPF6_DEBUG_SPF (DATABASE))
921 vty_out (vty, "debug ospf6 spf database%s", VNL);
508e53e2 922 return 0;
718e3744 923}
924
3810e06e
DD
925void
926ospf6_spf_config_write (struct vty *vty)
927{
928
929 if (ospf6->spf_delay != OSPF_SPF_DELAY_DEFAULT ||
930 ospf6->spf_holdtime != OSPF_SPF_HOLDTIME_DEFAULT ||
931 ospf6->spf_max_holdtime != OSPF_SPF_MAX_HOLDTIME_DEFAULT)
932 vty_out (vty, " timers throttle spf %d %d %d%s",
933 ospf6->spf_delay, ospf6->spf_holdtime,
934 ospf6->spf_max_holdtime, VTY_NEWLINE);
935
936}
937
508e53e2 938void
6ac29a51 939install_element_ospf6_debug_spf (void)
508e53e2 940{
3b68735f 941 install_element (ENABLE_NODE, &debug_ospf6_spf_process_cmd);
942 install_element (ENABLE_NODE, &debug_ospf6_spf_time_cmd);
2680aa2b 943 install_element (ENABLE_NODE, &debug_ospf6_spf_database_cmd);
3b68735f 944 install_element (ENABLE_NODE, &no_debug_ospf6_spf_process_cmd);
945 install_element (ENABLE_NODE, &no_debug_ospf6_spf_time_cmd);
2680aa2b 946 install_element (ENABLE_NODE, &no_debug_ospf6_spf_database_cmd);
3b68735f 947 install_element (CONFIG_NODE, &debug_ospf6_spf_process_cmd);
948 install_element (CONFIG_NODE, &debug_ospf6_spf_time_cmd);
2680aa2b 949 install_element (CONFIG_NODE, &debug_ospf6_spf_database_cmd);
3b68735f 950 install_element (CONFIG_NODE, &no_debug_ospf6_spf_process_cmd);
951 install_element (CONFIG_NODE, &no_debug_ospf6_spf_time_cmd);
2680aa2b 952 install_element (CONFIG_NODE, &no_debug_ospf6_spf_database_cmd);
508e53e2 953}
718e3744 954
955void
6ac29a51 956ospf6_spf_init (void)
718e3744 957{
3810e06e
DD
958 install_element (OSPF6_NODE, &ospf6_timers_throttle_spf_cmd);
959 install_element (OSPF6_NODE, &no_ospf6_timers_throttle_spf_cmd);
718e3744 960}