blob: 79539b2fb64d807950045814f0179b19497266e0 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
hasso508e53e2004-05-18 18:57:06 +00002 * Copyright (C) 2003 Yasuhiro Ohara
paul718e3742002-12-13 20:15:29 +00003 *
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 */
hasso508e53e2004-05-18 18:57:06 +000021
paul718e3742002-12-13 20:15:29 +000022/* Shortest Path First calculation for OSPFv3 */
23
hasso508e53e2004-05-18 18:57:06 +000024#include <zebra.h>
paul718e3742002-12-13 20:15:29 +000025
hasso508e53e2004-05-18 18:57:06 +000026#include "log.h"
27#include "memory.h"
28#include "command.h"
29#include "vty.h"
paul718e3742002-12-13 20:15:29 +000030#include "prefix.h"
hasso508e53e2004-05-18 18:57:06 +000031#include "pqueue.h"
32#include "linklist.h"
33#include "thread.h"
paul718e3742002-12-13 20:15:29 +000034
paul718e3742002-12-13 20:15:29 +000035#include "ospf6_lsa.h"
36#include "ospf6_lsdb.h"
37#include "ospf6_route.h"
paul718e3742002-12-13 20:15:29 +000038#include "ospf6_area.h"
hasso508e53e2004-05-18 18:57:06 +000039#include "ospf6_spf.h"
40#include "ospf6_intra.h"
41#include "ospf6_interface.h"
hasso049207c2004-08-04 20:02:13 +000042#include "ospf6d.h"
paul718e3742002-12-13 20:15:29 +000043
hasso508e53e2004-05-18 18:57:06 +000044unsigned char conf_debug_ospf6_spf = 0;
paul718e3742002-12-13 20:15:29 +000045
46int
hasso508e53e2004-05-18 18:57:06 +000047ospf6_vertex_cmp (void *a, void *b)
paul718e3742002-12-13 20:15:29 +000048{
hasso508e53e2004-05-18 18:57:06 +000049 struct ospf6_vertex *va = (struct ospf6_vertex *) a;
50 struct ospf6_vertex *vb = (struct ospf6_vertex *) b;
51
52 /* ascending order */
53 return (va->cost - vb->cost);
paul718e3742002-12-13 20:15:29 +000054}
55
56int
hasso508e53e2004-05-18 18:57:06 +000057ospf6_vertex_id_cmp (void *a, void *b)
paul718e3742002-12-13 20:15:29 +000058{
hasso508e53e2004-05-18 18:57:06 +000059 struct ospf6_vertex *va = (struct ospf6_vertex *) a;
60 struct ospf6_vertex *vb = (struct ospf6_vertex *) b;
61 int ret = 0;
paul718e3742002-12-13 20:15:29 +000062
hasso508e53e2004-05-18 18:57:06 +000063 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;
paul718e3742002-12-13 20:15:29 +000067
hasso508e53e2004-05-18 18:57:06 +000068 ret = ntohl (ospf6_linkstate_prefix_id (&va->vertex_id)) -
69 ntohl (ospf6_linkstate_prefix_id (&vb->vertex_id));
paul718e3742002-12-13 20:15:29 +000070 return ret;
71}
72
hasso508e53e2004-05-18 18:57:06 +000073struct ospf6_vertex *
74ospf6_vertex_create (struct ospf6_lsa *lsa)
75{
76 struct ospf6_vertex *v;
77 int i;
78
79 v = (struct ospf6_vertex *)
80 XMALLOC (MTYPE_OSPF6_VERTEX, sizeof (struct ospf6_vertex));
81
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;
87 else
88 assert (0);
89
90 /* vertex_id */
91 ospf6_linkstate_prefix (lsa->header->adv_router, lsa->header->id,
92 &v->vertex_id);
93
94 /* name */
95 ospf6_linkstate_prefix2str (&v->vertex_id, v->name, sizeof (v->name));
96
97 /* Associated LSA */
98 v->lsa = lsa;
99
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);
105
106 for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
107 ospf6_nexthop_clear (&v->nexthop[i]);
108
109 v->parent = NULL;
110 v->child_list = list_new ();
111 v->child_list->cmp = ospf6_vertex_id_cmp;
112
113 return v;
114}
115
paul718e3742002-12-13 20:15:29 +0000116void
hasso508e53e2004-05-18 18:57:06 +0000117ospf6_vertex_delete (struct ospf6_vertex *v)
paul718e3742002-12-13 20:15:29 +0000118{
hasso508e53e2004-05-18 18:57:06 +0000119 list_delete (v->child_list);
paul718e3742002-12-13 20:15:29 +0000120 XFREE (MTYPE_OSPF6_VERTEX, v);
121}
122
hasso508e53e2004-05-18 18:57:06 +0000123struct ospf6_lsa *
124ospf6_lsdesc_lsa (caddr_t lsdesc, struct ospf6_vertex *v)
paul718e3742002-12-13 20:15:29 +0000125{
paul718e3742002-12-13 20:15:29 +0000126 struct ospf6_lsa *lsa;
hasso508e53e2004-05-18 18:57:06 +0000127 u_int16_t type = 0;
128 u_int32_t id = 0, adv_router = 0;
paul718e3742002-12-13 20:15:29 +0000129
hasso508e53e2004-05-18 18:57:06 +0000130 if (VERTEX_IS_TYPE (NETWORK, v))
paul718e3742002-12-13 20:15:29 +0000131 {
hasso508e53e2004-05-18 18:57:06 +0000132 type = htons (OSPF6_LSTYPE_ROUTER);
133 id = htonl (0);
134 adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc);
paul718e3742002-12-13 20:15:29 +0000135 }
paul718e3742002-12-13 20:15:29 +0000136 else
paul718e3742002-12-13 20:15:29 +0000137 {
hasso508e53e2004-05-18 18:57:06 +0000138 if (ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, lsdesc))
paul718e3742002-12-13 20:15:29 +0000139 {
hasso508e53e2004-05-18 18:57:06 +0000140 type = htons (OSPF6_LSTYPE_ROUTER);
141 id = htonl (0);
142 adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc);
143 }
144 else if (ROUTER_LSDESC_IS_TYPE (TRANSIT_NETWORK, lsdesc))
145 {
146 type = htons (OSPF6_LSTYPE_NETWORK);
147 id = htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc));
148 adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc);
paul718e3742002-12-13 20:15:29 +0000149 }
150 }
151
hasso508e53e2004-05-18 18:57:06 +0000152 lsa = ospf6_lsdb_lookup (type, id, adv_router, v->area->lsdb);
paul718e3742002-12-13 20:15:29 +0000153
hasso3b687352004-08-19 06:56:53 +0000154 if (IS_OSPF6_DEBUG_SPF (PROCESS))
paul718e3742002-12-13 20:15:29 +0000155 {
hasso508e53e2004-05-18 18:57:06 +0000156 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)
160 zlog_info (" Link to: %s", lsa->name);
161 else
162 zlog_info (" Link to: [%s Id:%s Adv:%s] No LSA",
hasso1e058382004-09-01 21:36:14 +0000163 ospf6_lstype_name (type), ibuf, abuf);
paul718e3742002-12-13 20:15:29 +0000164 }
165
hasso508e53e2004-05-18 18:57:06 +0000166 return lsa;
167}
168
169char *
170ospf6_lsdesc_backlink (struct ospf6_lsa *lsa,
171 caddr_t lsdesc, struct ospf6_vertex *v)
172{
173 caddr_t backlink, found = NULL;
174 int size;
175
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)
181 {
182 assert (! (OSPF6_LSA_IS_TYPE (NETWORK, lsa) &&
183 VERTEX_IS_TYPE (NETWORK, v)));
184
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 }
213 }
214
hasso3b687352004-08-19 06:56:53 +0000215 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hasso508e53e2004-05-18 18:57:06 +0000216 zlog_info (" Backlink %s", (found ? "OK" : "FAIL"));
217
218 return found;
219}
220
221void
222ospf6_nexthop_calc (struct ospf6_vertex *w, struct ospf6_vertex *v,
223 caddr_t lsdesc)
224{
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];
232
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)
238 {
hasso3b687352004-08-19 06:56:53 +0000239 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hasso508e53e2004-05-18 18:57:06 +0000240 zlog_warn ("Can't find interface in SPF: ifindex %d", ifindex);
241 return;
242 }
243
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));
248
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))
252 {
253 if (VERTEX_IS_TYPE (ROUTER, v) &&
254 htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc)) != lsa->header->id)
255 continue;
256
257 link_lsa = (struct ospf6_link_lsa *) OSPF6_LSA_HEADER_END (lsa->header);
hasso3b687352004-08-19 06:56:53 +0000258 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hasso508e53e2004-05-18 18:57:06 +0000259 {
260 inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf));
261 zlog_info (" nexthop %s from %s", buf, lsa->name);
262 }
263
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 }
271 }
272
hasso3b687352004-08-19 06:56:53 +0000273 if (i == 0 && IS_OSPF6_DEBUG_SPF (PROCESS))
hasso508e53e2004-05-18 18:57:06 +0000274 zlog_info ("No nexthop for %s found", w->name);
275}
276
277int
278ospf6_spf_install (struct ospf6_vertex *v,
279 struct ospf6_route_table *result_table)
280{
281 struct ospf6_route *route;
282 int i, j;
283 struct ospf6_vertex *prev, *w;
hasso52dc7ee2004-09-23 19:18:23 +0000284 struct listnode *node;
hasso508e53e2004-05-18 18:57:06 +0000285
hasso3b687352004-08-19 06:56:53 +0000286 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hasso508e53e2004-05-18 18:57:06 +0000287 zlog_info ("SPF install %s hops %d cost %d",
288 v->name, v->hops, v->cost);
289
290 route = ospf6_route_lookup (&v->vertex_id, result_table);
291 if (route && route->path.cost < v->cost)
292 {
hasso3b687352004-08-19 06:56:53 +0000293 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hasso508e53e2004-05-18 18:57:06 +0000294 zlog_info (" already installed with lower cost (%d), ignore",
295 route->path.cost);
296 ospf6_vertex_delete (v);
297 return -1;
298 }
299 else if (route && route->path.cost == v->cost)
300 {
hasso3b687352004-08-19 06:56:53 +0000301 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hasso508e53e2004-05-18 18:57:06 +0000302 zlog_info (" another path found, merge");
303
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 }
321
322 prev = (struct ospf6_vertex *) route->route_option;
323 if (prev->hops > v->hops)
324 {
325 LIST_LOOP (prev->child_list, w, node)
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);
333
334 ospf6_vertex_delete (prev);
335 route->route_option = v;
336 }
337 else
338 ospf6_vertex_delete (v);
339
340 return -1;
341 }
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").
hasso6452df02004-08-15 05:52:07 +0000345 In the case something has gone wrong with the behavior of
hasso508e53e2004-05-18 18:57:06 +0000346 Priority-Queue. */
hasso6452df02004-08-15 05:52:07 +0000347
348 /* the case where the route exists already is handled and returned
349 up to here. */
hasso508e53e2004-05-18 18:57:06 +0000350 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);
paul718e3742002-12-13 20:15:29 +0000376 return 0;
377}
378
hasso508e53e2004-05-18 18:57:06 +0000379void
380ospf6_spf_table_finish (struct ospf6_route_table *result_table)
381{
382 struct ospf6_route *route;
383 struct ospf6_vertex *v;
384 for (route = ospf6_route_head (result_table); route;
385 route = ospf6_route_next (route))
386 {
387 v = (struct ospf6_vertex *) route->route_option;
388 ospf6_vertex_delete (v);
389 ospf6_route_remove (route, result_table);
390 }
391}
392
hasso6452df02004-08-15 05:52:07 +0000393/* RFC2328 16.1. Calculating the shortest-path tree for an area */
394/* RFC2740 3.8.1. Calculating the shortest path tree for an area */
hasso508e53e2004-05-18 18:57:06 +0000395void
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;
406
407 /* initialize */
408 candidate_list = pqueue_create ();
409 candidate_list->cmp = ospf6_vertex_cmp;
410
411 ospf6_spf_table_finish (result_table);
412
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;
hasso6452df02004-08-15 05:52:07 +0000423 root->nexthop[0].ifindex = 0; /* loopbak I/F is better ... */
hasso508e53e2004-05-18 18:57:06 +0000424 inet_pton (AF_INET6, "::1", &root->nexthop[0].address);
425
426 /* Actually insert root to the candidate-list as the only candidate */
427 pqueue_enqueue (root, candidate_list);
428
429 /* Iterate until candidate-list becomes empty */
430 while (candidate_list->size)
431 {
432 /* get closest candidate from priority queue */
433 v = pqueue_dequeue (candidate_list);
434
hasso6452df02004-08-15 05:52:07 +0000435 /* installing may result in merging or rejecting of the vertex */
hasso508e53e2004-05-18 18:57:06 +0000436 if (ospf6_spf_install (v, result_table) < 0)
437 continue;
438
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)
445 {
446 lsa = ospf6_lsdesc_lsa (lsdesc, v);
447 if (lsa == NULL)
448 continue;
449
450 if (! ospf6_lsdesc_backlink (lsa, lsdesc, v))
451 continue;
452
453 w = ospf6_vertex_create (lsa);
454 w->area = oa;
455 w->parent = v;
456 if (VERTEX_IS_TYPE (ROUTER, v))
457 {
458 w->cost = v->cost + ROUTER_LSDESC_GET_METRIC (lsdesc);
459 w->hops = v->hops + (VERTEX_IS_TYPE (NETWORK, w) ? 0 : 1);
460 }
461 else /* NETWORK */
462 {
463 w->cost = v->cost;
464 w->hops = v->hops + 1;
465 }
466
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);
472 else
473 {
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]);
477 }
478
479 /* add new candidate to the candidate_list */
hasso3b687352004-08-19 06:56:53 +0000480 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hasso508e53e2004-05-18 18:57:06 +0000481 zlog_info (" New candidate: %s hops %d cost %d",
482 w->name, w->hops, w->cost);
483 pqueue_enqueue (w, candidate_list);
484 }
485 }
486
487 pqueue_delete (candidate_list);
488}
489
paul718e3742002-12-13 20:15:29 +0000490int
491ospf6_spf_calculation_thread (struct thread *t)
492{
hasso508e53e2004-05-18 18:57:06 +0000493 struct ospf6_area *oa;
494 struct timeval start, end, runtime;
paul718e3742002-12-13 20:15:29 +0000495
hasso508e53e2004-05-18 18:57:06 +0000496 oa = (struct ospf6_area *) THREAD_ARG (t);
497 oa->thread_spf_calculation = NULL;
paul718e3742002-12-13 20:15:29 +0000498
hasso3b687352004-08-19 06:56:53 +0000499 if (IS_OSPF6_DEBUG_SPF (PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
hasso508e53e2004-05-18 18:57:06 +0000500 zlog_info ("SPF calculation for area %s", oa->name);
paul718e3742002-12-13 20:15:29 +0000501
502 /* execute SPF calculation */
503 gettimeofday (&start, (struct timezone *) NULL);
hasso508e53e2004-05-18 18:57:06 +0000504 ospf6_spf_calculation (oa->ospf6->router_id, oa->spf_table, oa);
paul718e3742002-12-13 20:15:29 +0000505 gettimeofday (&end, (struct timezone *) NULL);
506
hasso3b687352004-08-19 06:56:53 +0000507 if (IS_OSPF6_DEBUG_SPF (PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
paul718e3742002-12-13 20:15:29 +0000508 {
hasso508e53e2004-05-18 18:57:06 +0000509 timersub (&end, &start, &runtime);
510 zlog_info ("SPF calculation for area %s: runtime %ld sec %ld usec",
511 oa->name, runtime.tv_sec, runtime.tv_usec);
paul718e3742002-12-13 20:15:29 +0000512 }
513
hasso508e53e2004-05-18 18:57:06 +0000514 ospf6_intra_route_calculation (oa);
hasso6452df02004-08-15 05:52:07 +0000515 ospf6_intra_brouter_calculation (oa);
paul718e3742002-12-13 20:15:29 +0000516
517 return 0;
518}
519
520void
hasso508e53e2004-05-18 18:57:06 +0000521ospf6_spf_schedule (struct ospf6_area *oa)
paul718e3742002-12-13 20:15:29 +0000522{
hasso508e53e2004-05-18 18:57:06 +0000523 if (oa->thread_spf_calculation)
paul718e3742002-12-13 20:15:29 +0000524 return;
hasso508e53e2004-05-18 18:57:06 +0000525 oa->thread_spf_calculation =
526 thread_add_event (master, ospf6_spf_calculation_thread, oa, 0);
paul718e3742002-12-13 20:15:29 +0000527}
528
529void
hasso508e53e2004-05-18 18:57:06 +0000530ospf6_spf_display_subtree (struct vty *vty, char *prefix, int rest,
531 struct ospf6_vertex *v)
paul718e3742002-12-13 20:15:29 +0000532{
hasso52dc7ee2004-09-23 19:18:23 +0000533 struct listnode *node;
hasso508e53e2004-05-18 18:57:06 +0000534 struct ospf6_vertex *c;
535 char *next_prefix;
536 int len;
paul718e3742002-12-13 20:15:29 +0000537 int restnum;
paul718e3742002-12-13 20:15:29 +0000538
hasso508e53e2004-05-18 18:57:06 +0000539 /* "prefix" is the space prefix of the display line */
hasso049207c2004-08-04 20:02:13 +0000540 vty_out (vty, "%s+-%s [%d]%s", prefix, v->name, v->cost, VNL);
paul718e3742002-12-13 20:15:29 +0000541
hasso508e53e2004-05-18 18:57:06 +0000542 len = strlen (prefix) + 4;
543 next_prefix = (char *) malloc (len);
544 if (next_prefix == NULL)
paul718e3742002-12-13 20:15:29 +0000545 {
hasso049207c2004-08-04 20:02:13 +0000546 vty_out (vty, "malloc failed%s", VNL);
paul718e3742002-12-13 20:15:29 +0000547 return;
548 }
hasso508e53e2004-05-18 18:57:06 +0000549 snprintf (next_prefix, len, "%s%s", prefix, (rest ? "| " : " "));
paul718e3742002-12-13 20:15:29 +0000550
hasso508e53e2004-05-18 18:57:06 +0000551 restnum = listcount (v->child_list);
552 LIST_LOOP (v->child_list, c, node)
paul718e3742002-12-13 20:15:29 +0000553 {
hasso508e53e2004-05-18 18:57:06 +0000554 restnum--;
555 ospf6_spf_display_subtree (vty, next_prefix, restnum, c);
paul718e3742002-12-13 20:15:29 +0000556 }
557
hasso508e53e2004-05-18 18:57:06 +0000558 free (next_prefix);
paul718e3742002-12-13 20:15:29 +0000559}
560
hasso3b687352004-08-19 06:56:53 +0000561DEFUN (debug_ospf6_spf_process,
562 debug_ospf6_spf_process_cmd,
563 "debug ospf6 spf process",
hasso508e53e2004-05-18 18:57:06 +0000564 DEBUG_STR
paul718e3742002-12-13 20:15:29 +0000565 OSPF6_STR
hasso508e53e2004-05-18 18:57:06 +0000566 "Debug SPF Calculation\n"
hasso3b687352004-08-19 06:56:53 +0000567 "Debug Detailed SPF Process\n"
hasso508e53e2004-05-18 18:57:06 +0000568 )
paul718e3742002-12-13 20:15:29 +0000569{
hasso508e53e2004-05-18 18:57:06 +0000570 unsigned char level = 0;
hasso3b687352004-08-19 06:56:53 +0000571 level = OSPF6_DEBUG_SPF_PROCESS;
hasso508e53e2004-05-18 18:57:06 +0000572 OSPF6_DEBUG_SPF_ON (level);
paul718e3742002-12-13 20:15:29 +0000573 return CMD_SUCCESS;
574}
575
hasso3b687352004-08-19 06:56:53 +0000576DEFUN (debug_ospf6_spf_time,
577 debug_ospf6_spf_time_cmd,
578 "debug ospf6 spf time",
hasso508e53e2004-05-18 18:57:06 +0000579 DEBUG_STR
paul718e3742002-12-13 20:15:29 +0000580 OSPF6_STR
hasso508e53e2004-05-18 18:57:06 +0000581 "Debug SPF Calculation\n"
hasso3b687352004-08-19 06:56:53 +0000582 "Measure time taken by SPF Calculation\n"
hasso508e53e2004-05-18 18:57:06 +0000583 )
paul718e3742002-12-13 20:15:29 +0000584{
hasso508e53e2004-05-18 18:57:06 +0000585 unsigned char level = 0;
hasso3b687352004-08-19 06:56:53 +0000586 level = OSPF6_DEBUG_SPF_TIME;
hasso508e53e2004-05-18 18:57:06 +0000587 OSPF6_DEBUG_SPF_ON (level);
588 return CMD_SUCCESS;
paul718e3742002-12-13 20:15:29 +0000589}
590
hasso3b687352004-08-19 06:56:53 +0000591DEFUN (no_debug_ospf6_spf_process,
592 no_debug_ospf6_spf_process_cmd,
593 "no debug ospf6 spf process",
hasso508e53e2004-05-18 18:57:06 +0000594 NO_STR
595 DEBUG_STR
paul718e3742002-12-13 20:15:29 +0000596 OSPF6_STR
hasso508e53e2004-05-18 18:57:06 +0000597 "Quit Debugging SPF Calculation\n"
hasso3b687352004-08-19 06:56:53 +0000598 "Quit Debugging Detailed SPF Process\n"
hasso508e53e2004-05-18 18:57:06 +0000599 )
600{
601 unsigned char level = 0;
hasso3b687352004-08-19 06:56:53 +0000602 level = OSPF6_DEBUG_SPF_PROCESS;
hasso508e53e2004-05-18 18:57:06 +0000603 OSPF6_DEBUG_SPF_OFF (level);
604 return CMD_SUCCESS;
605}
paul718e3742002-12-13 20:15:29 +0000606
hasso3b687352004-08-19 06:56:53 +0000607DEFUN (no_debug_ospf6_spf_time,
608 no_debug_ospf6_spf_time_cmd,
609 "no debug ospf6 spf time",
hasso508e53e2004-05-18 18:57:06 +0000610 NO_STR
611 DEBUG_STR
paul718e3742002-12-13 20:15:29 +0000612 OSPF6_STR
hasso508e53e2004-05-18 18:57:06 +0000613 "Quit Debugging SPF Calculation\n"
hasso3b687352004-08-19 06:56:53 +0000614 "Quit Measuring time taken by SPF Calculation\n"
hasso508e53e2004-05-18 18:57:06 +0000615 )
616{
617 unsigned char level = 0;
hasso3b687352004-08-19 06:56:53 +0000618 level = OSPF6_DEBUG_SPF_TIME;
hasso508e53e2004-05-18 18:57:06 +0000619 OSPF6_DEBUG_SPF_OFF (level);
620 return CMD_SUCCESS;
621}
622
623int
624config_write_ospf6_debug_spf (struct vty *vty)
625{
hasso3b687352004-08-19 06:56:53 +0000626 if (IS_OSPF6_DEBUG_SPF (PROCESS))
627 vty_out (vty, "debug ospf6 spf process%s", VNL);
628 if (IS_OSPF6_DEBUG_SPF (TIME))
629 vty_out (vty, "debug ospf6 spf time%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000630 return 0;
631}
632
633void
634install_element_ospf6_debug_spf ()
635{
hasso3b687352004-08-19 06:56:53 +0000636 install_element (ENABLE_NODE, &debug_ospf6_spf_process_cmd);
637 install_element (ENABLE_NODE, &debug_ospf6_spf_time_cmd);
638 install_element (ENABLE_NODE, &no_debug_ospf6_spf_process_cmd);
639 install_element (ENABLE_NODE, &no_debug_ospf6_spf_time_cmd);
640 install_element (CONFIG_NODE, &debug_ospf6_spf_process_cmd);
641 install_element (CONFIG_NODE, &debug_ospf6_spf_time_cmd);
642 install_element (CONFIG_NODE, &no_debug_ospf6_spf_process_cmd);
643 install_element (CONFIG_NODE, &no_debug_ospf6_spf_time_cmd);
hasso508e53e2004-05-18 18:57:06 +0000644}
paul718e3742002-12-13 20:15:29 +0000645
646void
647ospf6_spf_init ()
648{
paul718e3742002-12-13 20:15:29 +0000649}
650
hasso508e53e2004-05-18 18:57:06 +0000651