blob: da0ee131b7fa3ea5c996d310d15dbf3a96702928 [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
Paul Jakma6ac29a52008-08-15 13:45:30 +010046static int
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 */
Dmitrij Tejblum403138e2011-01-13 18:25:40 +030053 if (va->cost != vb->cost)
54 return (va->cost - vb->cost);
55 return (va->hops - vb->hops);
paul718e3742002-12-13 20:15:29 +000056}
57
Paul Jakma6ac29a52008-08-15 13:45:30 +010058static int
hasso508e53e2004-05-18 18:57:06 +000059ospf6_vertex_id_cmp (void *a, void *b)
paul718e3742002-12-13 20:15:29 +000060{
hasso508e53e2004-05-18 18:57:06 +000061 struct ospf6_vertex *va = (struct ospf6_vertex *) a;
62 struct ospf6_vertex *vb = (struct ospf6_vertex *) b;
63 int ret = 0;
paul718e3742002-12-13 20:15:29 +000064
hasso508e53e2004-05-18 18:57:06 +000065 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;
paul718e3742002-12-13 20:15:29 +000069
hasso508e53e2004-05-18 18:57:06 +000070 ret = ntohl (ospf6_linkstate_prefix_id (&va->vertex_id)) -
71 ntohl (ospf6_linkstate_prefix_id (&vb->vertex_id));
paul718e3742002-12-13 20:15:29 +000072 return ret;
73}
74
Paul Jakma6ac29a52008-08-15 13:45:30 +010075static struct ospf6_vertex *
hasso508e53e2004-05-18 18:57:06 +000076ospf6_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
Paul Jakma6ac29a52008-08-15 13:45:30 +0100118static void
hasso508e53e2004-05-18 18:57:06 +0000119ospf6_vertex_delete (struct ospf6_vertex *v)
paul718e3742002-12-13 20:15:29 +0000120{
hasso508e53e2004-05-18 18:57:06 +0000121 list_delete (v->child_list);
paul718e3742002-12-13 20:15:29 +0000122 XFREE (MTYPE_OSPF6_VERTEX, v);
123}
124
Paul Jakma6ac29a52008-08-15 13:45:30 +0100125static struct ospf6_lsa *
hasso508e53e2004-05-18 18:57:06 +0000126ospf6_lsdesc_lsa (caddr_t lsdesc, struct ospf6_vertex *v)
paul718e3742002-12-13 20:15:29 +0000127{
paul718e3742002-12-13 20:15:29 +0000128 struct ospf6_lsa *lsa;
hasso508e53e2004-05-18 18:57:06 +0000129 u_int16_t type = 0;
130 u_int32_t id = 0, adv_router = 0;
paul718e3742002-12-13 20:15:29 +0000131
hasso508e53e2004-05-18 18:57:06 +0000132 if (VERTEX_IS_TYPE (NETWORK, v))
paul718e3742002-12-13 20:15:29 +0000133 {
hasso508e53e2004-05-18 18:57:06 +0000134 type = htons (OSPF6_LSTYPE_ROUTER);
135 id = htonl (0);
136 adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc);
paul718e3742002-12-13 20:15:29 +0000137 }
paul718e3742002-12-13 20:15:29 +0000138 else
paul718e3742002-12-13 20:15:29 +0000139 {
hasso508e53e2004-05-18 18:57:06 +0000140 if (ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, lsdesc))
paul718e3742002-12-13 20:15:29 +0000141 {
hasso508e53e2004-05-18 18:57:06 +0000142 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);
paul718e3742002-12-13 20:15:29 +0000151 }
152 }
153
hasso508e53e2004-05-18 18:57:06 +0000154 lsa = ospf6_lsdb_lookup (type, id, adv_router, v->area->lsdb);
paul718e3742002-12-13 20:15:29 +0000155
hasso3b687352004-08-19 06:56:53 +0000156 if (IS_OSPF6_DEBUG_SPF (PROCESS))
paul718e3742002-12-13 20:15:29 +0000157 {
hasso508e53e2004-05-18 18:57:06 +0000158 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)
hassoc6487d62004-12-24 06:00:11 +0000162 zlog_debug (" Link to: %s", lsa->name);
hasso508e53e2004-05-18 18:57:06 +0000163 else
hassoc6487d62004-12-24 06:00:11 +0000164 zlog_debug (" Link to: [%s Id:%s Adv:%s] No LSA",
165 ospf6_lstype_name (type), ibuf, abuf);
paul718e3742002-12-13 20:15:29 +0000166 }
167
hasso508e53e2004-05-18 18:57:06 +0000168 return lsa;
169}
170
Paul Jakma6ac29a52008-08-15 13:45:30 +0100171static char *
hasso508e53e2004-05-18 18:57:06 +0000172ospf6_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
hasso3b687352004-08-19 06:56:53 +0000217 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hassoc6487d62004-12-24 06:00:11 +0000218 zlog_debug (" Backlink %s", (found ? "OK" : "FAIL"));
hasso508e53e2004-05-18 18:57:06 +0000219
220 return found;
221}
222
Paul Jakma6ac29a52008-08-15 13:45:30 +0100223static void
hasso508e53e2004-05-18 18:57:06 +0000224ospf6_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 {
hasso3b687352004-08-19 06:56:53 +0000241 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hassoc6487d62004-12-24 06:00:11 +0000242 zlog_debug ("Can't find interface in SPF: ifindex %d", ifindex);
hasso508e53e2004-05-18 18:57:06 +0000243 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);
hasso3b687352004-08-19 06:56:53 +0000260 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hasso508e53e2004-05-18 18:57:06 +0000261 {
262 inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000263 zlog_debug (" nexthop %s from %s", buf, lsa->name);
hasso508e53e2004-05-18 18:57:06 +0000264 }
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
hasso3b687352004-08-19 06:56:53 +0000275 if (i == 0 && IS_OSPF6_DEBUG_SPF (PROCESS))
hassoc6487d62004-12-24 06:00:11 +0000276 zlog_debug ("No nexthop for %s found", w->name);
hasso508e53e2004-05-18 18:57:06 +0000277}
278
Paul Jakma6ac29a52008-08-15 13:45:30 +0100279static int
hasso508e53e2004-05-18 18:57:06 +0000280ospf6_spf_install (struct ospf6_vertex *v,
281 struct ospf6_route_table *result_table)
282{
283 struct ospf6_route *route;
284 int i, j;
Denis Ovsienko87362ce2011-08-27 22:19:34 +0400285 struct ospf6_vertex *prev;
hasso508e53e2004-05-18 18:57:06 +0000286
hasso3b687352004-08-19 06:56:53 +0000287 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hassoc6487d62004-12-24 06:00:11 +0000288 zlog_debug ("SPF install %s hops %d cost %d",
289 v->name, v->hops, v->cost);
hasso508e53e2004-05-18 18:57:06 +0000290
291 route = ospf6_route_lookup (&v->vertex_id, result_table);
292 if (route && route->path.cost < v->cost)
293 {
hasso3b687352004-08-19 06:56:53 +0000294 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hassoc6487d62004-12-24 06:00:11 +0000295 zlog_debug (" already installed with lower cost (%d), ignore",
296 route->path.cost);
hasso508e53e2004-05-18 18:57:06 +0000297 ospf6_vertex_delete (v);
298 return -1;
299 }
300 else if (route && route->path.cost == v->cost)
301 {
hasso3b687352004-08-19 06:56:53 +0000302 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hassoc6487d62004-12-24 06:00:11 +0000303 zlog_debug (" another path found, merge");
hasso508e53e2004-05-18 18:57:06 +0000304
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;
Dmitrij Tejblum403138e2011-01-13 18:25:40 +0300324 assert (prev->hops <= v->hops);
325 ospf6_vertex_delete (v);
hasso508e53e2004-05-18 18:57:06 +0000326
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").
hasso6452df02004-08-15 05:52:07 +0000332 In the case something has gone wrong with the behavior of
hasso508e53e2004-05-18 18:57:06 +0000333 Priority-Queue. */
hasso6452df02004-08-15 05:52:07 +0000334
335 /* the case where the route exists already is handled and returned
336 up to here. */
hasso508e53e2004-05-18 18:57:06 +0000337 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);
paul718e3742002-12-13 20:15:29 +0000363 return 0;
364}
365
hasso508e53e2004-05-18 18:57:06 +0000366void
367ospf6_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
hasso6452df02004-08-15 05:52:07 +0000380/* RFC2328 16.1. Calculating the shortest-path tree for an area */
381/* RFC2740 3.8.1. Calculating the shortest path tree for an area */
hasso508e53e2004-05-18 18:57:06 +0000382void
383ospf6_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
Tom Goffb48cebb2011-12-14 14:11:29 +0400394 ospf6_spf_table_finish (result_table);
395
hasso508e53e2004-05-18 18:57:06 +0000396 /* Install the calculating router itself as the root of the SPF tree */
397 /* construct root vertex */
398 lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_ROUTER), htonl (0),
399 router_id, oa->lsdb);
400 if (lsa == NULL)
401 return;
Tom Goff1d192342010-11-10 13:02:38 -0800402
403 /* initialize */
404 candidate_list = pqueue_create ();
405 candidate_list->cmp = ospf6_vertex_cmp;
406
hasso508e53e2004-05-18 18:57:06 +0000407 root = ospf6_vertex_create (lsa);
408 root->area = oa;
409 root->cost = 0;
410 root->hops = 0;
hasso6452df02004-08-15 05:52:07 +0000411 root->nexthop[0].ifindex = 0; /* loopbak I/F is better ... */
hasso508e53e2004-05-18 18:57:06 +0000412 inet_pton (AF_INET6, "::1", &root->nexthop[0].address);
413
414 /* Actually insert root to the candidate-list as the only candidate */
415 pqueue_enqueue (root, candidate_list);
416
417 /* Iterate until candidate-list becomes empty */
418 while (candidate_list->size)
419 {
420 /* get closest candidate from priority queue */
421 v = pqueue_dequeue (candidate_list);
422
hasso6452df02004-08-15 05:52:07 +0000423 /* installing may result in merging or rejecting of the vertex */
hasso508e53e2004-05-18 18:57:06 +0000424 if (ospf6_spf_install (v, result_table) < 0)
425 continue;
426
427 /* For each LS description in the just-added vertex V's LSA */
428 size = (VERTEX_IS_TYPE (ROUTER, v) ?
429 sizeof (struct ospf6_router_lsdesc) :
430 sizeof (struct ospf6_network_lsdesc));
431 for (lsdesc = OSPF6_LSA_HEADER_END (v->lsa->header) + 4;
432 lsdesc + size <= OSPF6_LSA_END (v->lsa->header); lsdesc += size)
433 {
434 lsa = ospf6_lsdesc_lsa (lsdesc, v);
435 if (lsa == NULL)
436 continue;
437
438 if (! ospf6_lsdesc_backlink (lsa, lsdesc, v))
439 continue;
440
441 w = ospf6_vertex_create (lsa);
442 w->area = oa;
443 w->parent = v;
444 if (VERTEX_IS_TYPE (ROUTER, v))
445 {
446 w->cost = v->cost + ROUTER_LSDESC_GET_METRIC (lsdesc);
447 w->hops = v->hops + (VERTEX_IS_TYPE (NETWORK, w) ? 0 : 1);
448 }
449 else /* NETWORK */
450 {
451 w->cost = v->cost;
452 w->hops = v->hops + 1;
453 }
454
455 /* nexthop calculation */
456 if (w->hops == 0)
457 w->nexthop[0].ifindex = ROUTER_LSDESC_GET_IFID (lsdesc);
458 else if (w->hops == 1 && v->hops == 0)
459 ospf6_nexthop_calc (w, v, lsdesc);
460 else
461 {
462 for (i = 0; ospf6_nexthop_is_set (&v->nexthop[i]) &&
463 i < OSPF6_MULTI_PATH_LIMIT; i++)
464 ospf6_nexthop_copy (&w->nexthop[i], &v->nexthop[i]);
465 }
466
467 /* add new candidate to the candidate_list */
hasso3b687352004-08-19 06:56:53 +0000468 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hassoc6487d62004-12-24 06:00:11 +0000469 zlog_debug (" New candidate: %s hops %d cost %d",
470 w->name, w->hops, w->cost);
hasso508e53e2004-05-18 18:57:06 +0000471 pqueue_enqueue (w, candidate_list);
472 }
473 }
474
475 pqueue_delete (candidate_list);
Vincent Bernatea86e402012-06-04 10:29:49 +0200476
477 oa->spf_calculation++;
hasso508e53e2004-05-18 18:57:06 +0000478}
479
Paul Jakma6ac29a52008-08-15 13:45:30 +0100480static void
hasso2680aa22004-11-25 20:54:46 +0000481ospf6_spf_log_database (struct ospf6_area *oa)
482{
483 char *p, *end, buffer[256];
484 struct listnode *node;
485 struct ospf6_interface *oi;
486
487 p = buffer;
488 end = buffer + sizeof (buffer);
489
490 snprintf (p, end - p, "SPF on DB (#LSAs):");
491 p = (buffer + strlen (buffer) < end ? buffer + strlen (buffer) : end);
492 snprintf (p, end - p, " Area %s: %d", oa->name, oa->lsdb->count);
493 p = (buffer + strlen (buffer) < end ? buffer + strlen (buffer) : end);
494
paul1eb8ef22005-04-07 07:30:20 +0000495 for (ALL_LIST_ELEMENTS_RO (oa->if_list, node, oi))
hasso2680aa22004-11-25 20:54:46 +0000496 {
hasso2680aa22004-11-25 20:54:46 +0000497 snprintf (p, end - p, " I/F %s: %d",
498 oi->interface->name, oi->lsdb->count);
499 p = (buffer + strlen (buffer) < end ? buffer + strlen (buffer) : end);
500 }
501
hassoc6487d62004-12-24 06:00:11 +0000502 zlog_debug ("%s", buffer);
hasso2680aa22004-11-25 20:54:46 +0000503}
504
Paul Jakma6ac29a52008-08-15 13:45:30 +0100505static int
paul718e3742002-12-13 20:15:29 +0000506ospf6_spf_calculation_thread (struct thread *t)
507{
hasso508e53e2004-05-18 18:57:06 +0000508 struct ospf6_area *oa;
509 struct timeval start, end, runtime;
paul718e3742002-12-13 20:15:29 +0000510
hasso508e53e2004-05-18 18:57:06 +0000511 oa = (struct ospf6_area *) THREAD_ARG (t);
512 oa->thread_spf_calculation = NULL;
paul718e3742002-12-13 20:15:29 +0000513
hasso2680aa22004-11-25 20:54:46 +0000514 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hassoc6487d62004-12-24 06:00:11 +0000515 zlog_debug ("SPF calculation for Area %s", oa->name);
hasso2680aa22004-11-25 20:54:46 +0000516 if (IS_OSPF6_DEBUG_SPF (DATABASE))
517 ospf6_spf_log_database (oa);
paul718e3742002-12-13 20:15:29 +0000518
519 /* execute SPF calculation */
Takashi Sogabe86f72dc2009-06-22 13:07:02 +0900520 quagga_gettime (QUAGGA_CLK_MONOTONIC, &start);
hasso508e53e2004-05-18 18:57:06 +0000521 ospf6_spf_calculation (oa->ospf6->router_id, oa->spf_table, oa);
Takashi Sogabe86f72dc2009-06-22 13:07:02 +0900522 quagga_gettime (QUAGGA_CLK_MONOTONIC, &end);
hasso2680aa22004-11-25 20:54:46 +0000523 timersub (&end, &start, &runtime);
paul718e3742002-12-13 20:15:29 +0000524
hasso3b687352004-08-19 06:56:53 +0000525 if (IS_OSPF6_DEBUG_SPF (PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
hassoc6487d62004-12-24 06:00:11 +0000526 zlog_debug ("SPF runtime: %ld sec %ld usec",
527 runtime.tv_sec, runtime.tv_usec);
paul718e3742002-12-13 20:15:29 +0000528
hasso508e53e2004-05-18 18:57:06 +0000529 ospf6_intra_route_calculation (oa);
hasso6452df02004-08-15 05:52:07 +0000530 ospf6_intra_brouter_calculation (oa);
paul718e3742002-12-13 20:15:29 +0000531
532 return 0;
533}
534
535void
hasso508e53e2004-05-18 18:57:06 +0000536ospf6_spf_schedule (struct ospf6_area *oa)
paul718e3742002-12-13 20:15:29 +0000537{
hasso508e53e2004-05-18 18:57:06 +0000538 if (oa->thread_spf_calculation)
paul718e3742002-12-13 20:15:29 +0000539 return;
hasso508e53e2004-05-18 18:57:06 +0000540 oa->thread_spf_calculation =
541 thread_add_event (master, ospf6_spf_calculation_thread, oa, 0);
paul718e3742002-12-13 20:15:29 +0000542}
543
544void
paul0c083ee2004-10-10 12:54:58 +0000545ospf6_spf_display_subtree (struct vty *vty, const char *prefix, int rest,
hasso508e53e2004-05-18 18:57:06 +0000546 struct ospf6_vertex *v)
paul718e3742002-12-13 20:15:29 +0000547{
paul1eb8ef22005-04-07 07:30:20 +0000548 struct listnode *node, *nnode;
hasso508e53e2004-05-18 18:57:06 +0000549 struct ospf6_vertex *c;
550 char *next_prefix;
551 int len;
paul718e3742002-12-13 20:15:29 +0000552 int restnum;
paul718e3742002-12-13 20:15:29 +0000553
hasso508e53e2004-05-18 18:57:06 +0000554 /* "prefix" is the space prefix of the display line */
hasso049207c2004-08-04 20:02:13 +0000555 vty_out (vty, "%s+-%s [%d]%s", prefix, v->name, v->cost, VNL);
paul718e3742002-12-13 20:15:29 +0000556
hasso508e53e2004-05-18 18:57:06 +0000557 len = strlen (prefix) + 4;
558 next_prefix = (char *) malloc (len);
559 if (next_prefix == NULL)
paul718e3742002-12-13 20:15:29 +0000560 {
hasso049207c2004-08-04 20:02:13 +0000561 vty_out (vty, "malloc failed%s", VNL);
paul718e3742002-12-13 20:15:29 +0000562 return;
563 }
hasso508e53e2004-05-18 18:57:06 +0000564 snprintf (next_prefix, len, "%s%s", prefix, (rest ? "| " : " "));
paul718e3742002-12-13 20:15:29 +0000565
hasso508e53e2004-05-18 18:57:06 +0000566 restnum = listcount (v->child_list);
paul1eb8ef22005-04-07 07:30:20 +0000567 for (ALL_LIST_ELEMENTS (v->child_list, node, nnode, c))
paul718e3742002-12-13 20:15:29 +0000568 {
hasso508e53e2004-05-18 18:57:06 +0000569 restnum--;
570 ospf6_spf_display_subtree (vty, next_prefix, restnum, c);
paul718e3742002-12-13 20:15:29 +0000571 }
572
hasso508e53e2004-05-18 18:57:06 +0000573 free (next_prefix);
paul718e3742002-12-13 20:15:29 +0000574}
575
hasso3b687352004-08-19 06:56:53 +0000576DEFUN (debug_ospf6_spf_process,
577 debug_ospf6_spf_process_cmd,
578 "debug ospf6 spf process",
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 "Debug Detailed SPF Process\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_PROCESS;
hasso508e53e2004-05-18 18:57:06 +0000587 OSPF6_DEBUG_SPF_ON (level);
paul718e3742002-12-13 20:15:29 +0000588 return CMD_SUCCESS;
589}
590
hasso3b687352004-08-19 06:56:53 +0000591DEFUN (debug_ospf6_spf_time,
592 debug_ospf6_spf_time_cmd,
593 "debug ospf6 spf time",
hasso508e53e2004-05-18 18:57:06 +0000594 DEBUG_STR
paul718e3742002-12-13 20:15:29 +0000595 OSPF6_STR
hasso508e53e2004-05-18 18:57:06 +0000596 "Debug SPF Calculation\n"
hasso3b687352004-08-19 06:56:53 +0000597 "Measure time taken by SPF Calculation\n"
hasso508e53e2004-05-18 18:57:06 +0000598 )
paul718e3742002-12-13 20:15:29 +0000599{
hasso508e53e2004-05-18 18:57:06 +0000600 unsigned char level = 0;
hasso3b687352004-08-19 06:56:53 +0000601 level = OSPF6_DEBUG_SPF_TIME;
hasso508e53e2004-05-18 18:57:06 +0000602 OSPF6_DEBUG_SPF_ON (level);
603 return CMD_SUCCESS;
paul718e3742002-12-13 20:15:29 +0000604}
605
hasso2680aa22004-11-25 20:54:46 +0000606DEFUN (debug_ospf6_spf_database,
607 debug_ospf6_spf_database_cmd,
608 "debug ospf6 spf database",
609 DEBUG_STR
610 OSPF6_STR
611 "Debug SPF Calculation\n"
612 "Log number of LSAs at SPF Calculation time\n"
613 )
614{
615 unsigned char level = 0;
616 level = OSPF6_DEBUG_SPF_DATABASE;
617 OSPF6_DEBUG_SPF_ON (level);
618 return CMD_SUCCESS;
619}
620
hasso3b687352004-08-19 06:56:53 +0000621DEFUN (no_debug_ospf6_spf_process,
622 no_debug_ospf6_spf_process_cmd,
623 "no debug ospf6 spf process",
hasso508e53e2004-05-18 18:57:06 +0000624 NO_STR
625 DEBUG_STR
paul718e3742002-12-13 20:15:29 +0000626 OSPF6_STR
hasso508e53e2004-05-18 18:57:06 +0000627 "Quit Debugging SPF Calculation\n"
hasso3b687352004-08-19 06:56:53 +0000628 "Quit Debugging Detailed SPF Process\n"
hasso508e53e2004-05-18 18:57:06 +0000629 )
630{
631 unsigned char level = 0;
hasso3b687352004-08-19 06:56:53 +0000632 level = OSPF6_DEBUG_SPF_PROCESS;
hasso508e53e2004-05-18 18:57:06 +0000633 OSPF6_DEBUG_SPF_OFF (level);
634 return CMD_SUCCESS;
635}
paul718e3742002-12-13 20:15:29 +0000636
hasso3b687352004-08-19 06:56:53 +0000637DEFUN (no_debug_ospf6_spf_time,
638 no_debug_ospf6_spf_time_cmd,
639 "no debug ospf6 spf time",
hasso508e53e2004-05-18 18:57:06 +0000640 NO_STR
641 DEBUG_STR
paul718e3742002-12-13 20:15:29 +0000642 OSPF6_STR
hasso508e53e2004-05-18 18:57:06 +0000643 "Quit Debugging SPF Calculation\n"
hasso3b687352004-08-19 06:56:53 +0000644 "Quit Measuring time taken by SPF Calculation\n"
hasso508e53e2004-05-18 18:57:06 +0000645 )
646{
647 unsigned char level = 0;
hasso3b687352004-08-19 06:56:53 +0000648 level = OSPF6_DEBUG_SPF_TIME;
hasso508e53e2004-05-18 18:57:06 +0000649 OSPF6_DEBUG_SPF_OFF (level);
650 return CMD_SUCCESS;
651}
652
hasso2680aa22004-11-25 20:54:46 +0000653DEFUN (no_debug_ospf6_spf_database,
654 no_debug_ospf6_spf_database_cmd,
655 "no debug ospf6 spf database",
656 NO_STR
657 DEBUG_STR
658 OSPF6_STR
659 "Debug SPF Calculation\n"
660 "Quit Logging number of LSAs at SPF Calculation time\n"
661 )
662{
663 unsigned char level = 0;
664 level = OSPF6_DEBUG_SPF_DATABASE;
665 OSPF6_DEBUG_SPF_OFF (level);
666 return CMD_SUCCESS;
667}
668
hasso508e53e2004-05-18 18:57:06 +0000669int
670config_write_ospf6_debug_spf (struct vty *vty)
671{
hasso3b687352004-08-19 06:56:53 +0000672 if (IS_OSPF6_DEBUG_SPF (PROCESS))
673 vty_out (vty, "debug ospf6 spf process%s", VNL);
674 if (IS_OSPF6_DEBUG_SPF (TIME))
675 vty_out (vty, "debug ospf6 spf time%s", VNL);
hasso2680aa22004-11-25 20:54:46 +0000676 if (IS_OSPF6_DEBUG_SPF (DATABASE))
677 vty_out (vty, "debug ospf6 spf database%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000678 return 0;
679}
680
681void
Paul Jakma6ac29a52008-08-15 13:45:30 +0100682install_element_ospf6_debug_spf (void)
hasso508e53e2004-05-18 18:57:06 +0000683{
hasso3b687352004-08-19 06:56:53 +0000684 install_element (ENABLE_NODE, &debug_ospf6_spf_process_cmd);
685 install_element (ENABLE_NODE, &debug_ospf6_spf_time_cmd);
hasso2680aa22004-11-25 20:54:46 +0000686 install_element (ENABLE_NODE, &debug_ospf6_spf_database_cmd);
hasso3b687352004-08-19 06:56:53 +0000687 install_element (ENABLE_NODE, &no_debug_ospf6_spf_process_cmd);
688 install_element (ENABLE_NODE, &no_debug_ospf6_spf_time_cmd);
hasso2680aa22004-11-25 20:54:46 +0000689 install_element (ENABLE_NODE, &no_debug_ospf6_spf_database_cmd);
hasso3b687352004-08-19 06:56:53 +0000690 install_element (CONFIG_NODE, &debug_ospf6_spf_process_cmd);
691 install_element (CONFIG_NODE, &debug_ospf6_spf_time_cmd);
hasso2680aa22004-11-25 20:54:46 +0000692 install_element (CONFIG_NODE, &debug_ospf6_spf_database_cmd);
hasso3b687352004-08-19 06:56:53 +0000693 install_element (CONFIG_NODE, &no_debug_ospf6_spf_process_cmd);
694 install_element (CONFIG_NODE, &no_debug_ospf6_spf_time_cmd);
hasso2680aa22004-11-25 20:54:46 +0000695 install_element (CONFIG_NODE, &no_debug_ospf6_spf_database_cmd);
hasso508e53e2004-05-18 18:57:06 +0000696}
paul718e3742002-12-13 20:15:29 +0000697
698void
Paul Jakma6ac29a52008-08-15 13:45:30 +0100699ospf6_spf_init (void)
paul718e3742002-12-13 20:15:29 +0000700{
paul718e3742002-12-13 20:15:29 +0000701}
702
hasso508e53e2004-05-18 18:57:06 +0000703