blob: ab18d38525babc7e08c8e4f9b3f39f0d7f1e780f [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"
Paul Jakma7aa9dce2014-09-19 14:42:23 +010043#include "ospf6_abr.h"
paul718e3742002-12-13 20:15:29 +000044
hasso508e53e2004-05-18 18:57:06 +000045unsigned char conf_debug_ospf6_spf = 0;
paul718e3742002-12-13 20:15:29 +000046
Paul Jakma6ac29a52008-08-15 13:45:30 +010047static int
hasso508e53e2004-05-18 18:57:06 +000048ospf6_vertex_cmp (void *a, void *b)
paul718e3742002-12-13 20:15:29 +000049{
hasso508e53e2004-05-18 18:57:06 +000050 struct ospf6_vertex *va = (struct ospf6_vertex *) a;
51 struct ospf6_vertex *vb = (struct ospf6_vertex *) b;
52
53 /* ascending order */
Dmitrij Tejblum403138e2011-01-13 18:25:40 +030054 if (va->cost != vb->cost)
55 return (va->cost - vb->cost);
56 return (va->hops - vb->hops);
paul718e3742002-12-13 20:15:29 +000057}
58
Paul Jakma6ac29a52008-08-15 13:45:30 +010059static int
hasso508e53e2004-05-18 18:57:06 +000060ospf6_vertex_id_cmp (void *a, void *b)
paul718e3742002-12-13 20:15:29 +000061{
hasso508e53e2004-05-18 18:57:06 +000062 struct ospf6_vertex *va = (struct ospf6_vertex *) a;
63 struct ospf6_vertex *vb = (struct ospf6_vertex *) b;
64 int ret = 0;
paul718e3742002-12-13 20:15:29 +000065
hasso508e53e2004-05-18 18:57:06 +000066 ret = ntohl (ospf6_linkstate_prefix_adv_router (&va->vertex_id)) -
67 ntohl (ospf6_linkstate_prefix_adv_router (&vb->vertex_id));
68 if (ret)
69 return ret;
paul718e3742002-12-13 20:15:29 +000070
hasso508e53e2004-05-18 18:57:06 +000071 ret = ntohl (ospf6_linkstate_prefix_id (&va->vertex_id)) -
72 ntohl (ospf6_linkstate_prefix_id (&vb->vertex_id));
paul718e3742002-12-13 20:15:29 +000073 return ret;
74}
75
Paul Jakma6ac29a52008-08-15 13:45:30 +010076static struct ospf6_vertex *
hasso508e53e2004-05-18 18:57:06 +000077ospf6_vertex_create (struct ospf6_lsa *lsa)
78{
79 struct ospf6_vertex *v;
80 int i;
81
82 v = (struct ospf6_vertex *)
83 XMALLOC (MTYPE_OSPF6_VERTEX, sizeof (struct ospf6_vertex));
84
85 /* type */
86 if (ntohs (lsa->header->type) == OSPF6_LSTYPE_ROUTER)
87 v->type = OSPF6_VERTEX_TYPE_ROUTER;
88 else if (ntohs (lsa->header->type) == OSPF6_LSTYPE_NETWORK)
89 v->type = OSPF6_VERTEX_TYPE_NETWORK;
90 else
91 assert (0);
92
93 /* vertex_id */
94 ospf6_linkstate_prefix (lsa->header->adv_router, lsa->header->id,
95 &v->vertex_id);
96
97 /* name */
98 ospf6_linkstate_prefix2str (&v->vertex_id, v->name, sizeof (v->name));
99
100 /* Associated LSA */
101 v->lsa = lsa;
102
103 /* capability bits + options */
104 v->capability = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header));
105 v->options[0] = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header) + 1);
106 v->options[1] = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header) + 2);
107 v->options[2] = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header) + 3);
108
109 for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
110 ospf6_nexthop_clear (&v->nexthop[i]);
111
112 v->parent = NULL;
113 v->child_list = list_new ();
114 v->child_list->cmp = ospf6_vertex_id_cmp;
115
116 return v;
117}
118
Paul Jakma6ac29a52008-08-15 13:45:30 +0100119static void
hasso508e53e2004-05-18 18:57:06 +0000120ospf6_vertex_delete (struct ospf6_vertex *v)
paul718e3742002-12-13 20:15:29 +0000121{
hasso508e53e2004-05-18 18:57:06 +0000122 list_delete (v->child_list);
paul718e3742002-12-13 20:15:29 +0000123 XFREE (MTYPE_OSPF6_VERTEX, v);
124}
125
Paul Jakma6ac29a52008-08-15 13:45:30 +0100126static struct ospf6_lsa *
hasso508e53e2004-05-18 18:57:06 +0000127ospf6_lsdesc_lsa (caddr_t lsdesc, struct ospf6_vertex *v)
paul718e3742002-12-13 20:15:29 +0000128{
paul718e3742002-12-13 20:15:29 +0000129 struct ospf6_lsa *lsa;
hasso508e53e2004-05-18 18:57:06 +0000130 u_int16_t type = 0;
131 u_int32_t id = 0, adv_router = 0;
paul718e3742002-12-13 20:15:29 +0000132
hasso508e53e2004-05-18 18:57:06 +0000133 if (VERTEX_IS_TYPE (NETWORK, v))
paul718e3742002-12-13 20:15:29 +0000134 {
hasso508e53e2004-05-18 18:57:06 +0000135 type = htons (OSPF6_LSTYPE_ROUTER);
136 id = htonl (0);
137 adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc);
paul718e3742002-12-13 20:15:29 +0000138 }
paul718e3742002-12-13 20:15:29 +0000139 else
paul718e3742002-12-13 20:15:29 +0000140 {
hasso508e53e2004-05-18 18:57:06 +0000141 if (ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, lsdesc))
paul718e3742002-12-13 20:15:29 +0000142 {
hasso508e53e2004-05-18 18:57:06 +0000143 type = htons (OSPF6_LSTYPE_ROUTER);
144 id = htonl (0);
145 adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc);
146 }
147 else if (ROUTER_LSDESC_IS_TYPE (TRANSIT_NETWORK, lsdesc))
148 {
149 type = htons (OSPF6_LSTYPE_NETWORK);
150 id = htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc));
151 adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc);
paul718e3742002-12-13 20:15:29 +0000152 }
153 }
154
hasso508e53e2004-05-18 18:57:06 +0000155 lsa = ospf6_lsdb_lookup (type, id, adv_router, v->area->lsdb);
paul718e3742002-12-13 20:15:29 +0000156
hasso3b687352004-08-19 06:56:53 +0000157 if (IS_OSPF6_DEBUG_SPF (PROCESS))
paul718e3742002-12-13 20:15:29 +0000158 {
hasso508e53e2004-05-18 18:57:06 +0000159 char ibuf[16], abuf[16];
160 inet_ntop (AF_INET, &id, ibuf, sizeof (ibuf));
161 inet_ntop (AF_INET, &adv_router, abuf, sizeof (abuf));
162 if (lsa)
hassoc6487d62004-12-24 06:00:11 +0000163 zlog_debug (" Link to: %s", lsa->name);
hasso508e53e2004-05-18 18:57:06 +0000164 else
hassoc6487d62004-12-24 06:00:11 +0000165 zlog_debug (" Link to: [%s Id:%s Adv:%s] No LSA",
166 ospf6_lstype_name (type), ibuf, abuf);
paul718e3742002-12-13 20:15:29 +0000167 }
168
hasso508e53e2004-05-18 18:57:06 +0000169 return lsa;
170}
171
Paul Jakma6ac29a52008-08-15 13:45:30 +0100172static char *
hasso508e53e2004-05-18 18:57:06 +0000173ospf6_lsdesc_backlink (struct ospf6_lsa *lsa,
174 caddr_t lsdesc, struct ospf6_vertex *v)
175{
176 caddr_t backlink, found = NULL;
177 int size;
178
179 size = (OSPF6_LSA_IS_TYPE (ROUTER, lsa) ?
180 sizeof (struct ospf6_router_lsdesc) :
181 sizeof (struct ospf6_network_lsdesc));
182 for (backlink = OSPF6_LSA_HEADER_END (lsa->header) + 4;
183 backlink + size <= OSPF6_LSA_END (lsa->header); backlink += size)
184 {
185 assert (! (OSPF6_LSA_IS_TYPE (NETWORK, lsa) &&
186 VERTEX_IS_TYPE (NETWORK, v)));
187
188 if (OSPF6_LSA_IS_TYPE (NETWORK, lsa) &&
189 NETWORK_LSDESC_GET_NBR_ROUTERID (backlink)
190 == v->lsa->header->adv_router)
191 found = backlink;
192 else if (VERTEX_IS_TYPE (NETWORK, v) &&
193 ROUTER_LSDESC_IS_TYPE (TRANSIT_NETWORK, backlink) &&
194 ROUTER_LSDESC_GET_NBR_ROUTERID (backlink)
195 == v->lsa->header->adv_router &&
196 ROUTER_LSDESC_GET_NBR_IFID (backlink)
197 == ntohl (v->lsa->header->id))
198 found = backlink;
199 else
200 {
201 if (! ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, backlink) ||
202 ! ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, lsdesc))
203 continue;
204 if (ROUTER_LSDESC_GET_NBR_IFID (backlink) !=
205 ROUTER_LSDESC_GET_IFID (lsdesc) ||
206 ROUTER_LSDESC_GET_NBR_IFID (lsdesc) !=
207 ROUTER_LSDESC_GET_IFID (backlink))
208 continue;
209 if (ROUTER_LSDESC_GET_NBR_ROUTERID (backlink) !=
210 v->lsa->header->adv_router ||
211 ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc) !=
212 lsa->header->adv_router)
213 continue;
214 found = backlink;
215 }
216 }
217
hasso3b687352004-08-19 06:56:53 +0000218 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hassoc6487d62004-12-24 06:00:11 +0000219 zlog_debug (" Backlink %s", (found ? "OK" : "FAIL"));
hasso508e53e2004-05-18 18:57:06 +0000220
221 return found;
222}
223
Paul Jakma6ac29a52008-08-15 13:45:30 +0100224static void
hasso508e53e2004-05-18 18:57:06 +0000225ospf6_nexthop_calc (struct ospf6_vertex *w, struct ospf6_vertex *v,
226 caddr_t lsdesc)
227{
Paul Jakma9099f9b2016-01-18 10:12:10 +0000228 int i;
229 ifindex_t ifindex;
hasso508e53e2004-05-18 18:57:06 +0000230 struct ospf6_interface *oi;
231 u_int16_t type;
232 u_int32_t adv_router;
233 struct ospf6_lsa *lsa;
234 struct ospf6_link_lsa *link_lsa;
235 char buf[64];
236
237 assert (VERTEX_IS_TYPE (ROUTER, w));
238 ifindex = (VERTEX_IS_TYPE (NETWORK, v) ? v->nexthop[0].ifindex :
Paul Jakma9099f9b2016-01-18 10:12:10 +0000239 /* v is the local router & the interface_id is a local ifindex */
240 (ifindex_t) ROUTER_LSDESC_GET_IFID (lsdesc));
241 assert (ifindex >= 0);
242
hasso508e53e2004-05-18 18:57:06 +0000243 oi = ospf6_interface_lookup_by_ifindex (ifindex);
244 if (oi == NULL)
245 {
hasso3b687352004-08-19 06:56:53 +0000246 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hassoc6487d62004-12-24 06:00:11 +0000247 zlog_debug ("Can't find interface in SPF: ifindex %d", ifindex);
hasso508e53e2004-05-18 18:57:06 +0000248 return;
249 }
250
251 type = htons (OSPF6_LSTYPE_LINK);
252 adv_router = (VERTEX_IS_TYPE (NETWORK, v) ?
253 NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc) :
254 ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc));
255
256 i = 0;
257 for (lsa = ospf6_lsdb_type_router_head (type, adv_router, oi->lsdb); lsa;
258 lsa = ospf6_lsdb_type_router_next (type, adv_router, lsa))
259 {
260 if (VERTEX_IS_TYPE (ROUTER, v) &&
261 htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc)) != lsa->header->id)
262 continue;
263
264 link_lsa = (struct ospf6_link_lsa *) OSPF6_LSA_HEADER_END (lsa->header);
hasso3b687352004-08-19 06:56:53 +0000265 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hasso508e53e2004-05-18 18:57:06 +0000266 {
267 inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000268 zlog_debug (" nexthop %s from %s", buf, lsa->name);
hasso508e53e2004-05-18 18:57:06 +0000269 }
270
271 if (i < OSPF6_MULTI_PATH_LIMIT)
272 {
273 memcpy (&w->nexthop[i].address, &link_lsa->linklocal_addr,
274 sizeof (struct in6_addr));
275 w->nexthop[i].ifindex = ifindex;
276 i++;
277 }
278 }
279
hasso3b687352004-08-19 06:56:53 +0000280 if (i == 0 && IS_OSPF6_DEBUG_SPF (PROCESS))
hassoc6487d62004-12-24 06:00:11 +0000281 zlog_debug ("No nexthop for %s found", w->name);
hasso508e53e2004-05-18 18:57:06 +0000282}
283
Paul Jakma6ac29a52008-08-15 13:45:30 +0100284static int
hasso508e53e2004-05-18 18:57:06 +0000285ospf6_spf_install (struct ospf6_vertex *v,
286 struct ospf6_route_table *result_table)
287{
288 struct ospf6_route *route;
289 int i, j;
Denis Ovsienko87362ce2011-08-27 22:19:34 +0400290 struct ospf6_vertex *prev;
hasso508e53e2004-05-18 18:57:06 +0000291
hasso3b687352004-08-19 06:56:53 +0000292 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hassoc6487d62004-12-24 06:00:11 +0000293 zlog_debug ("SPF install %s hops %d cost %d",
294 v->name, v->hops, v->cost);
hasso508e53e2004-05-18 18:57:06 +0000295
296 route = ospf6_route_lookup (&v->vertex_id, result_table);
297 if (route && route->path.cost < v->cost)
298 {
hasso3b687352004-08-19 06:56:53 +0000299 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hassoc6487d62004-12-24 06:00:11 +0000300 zlog_debug (" already installed with lower cost (%d), ignore",
301 route->path.cost);
hasso508e53e2004-05-18 18:57:06 +0000302 ospf6_vertex_delete (v);
303 return -1;
304 }
305 else if (route && route->path.cost == v->cost)
306 {
hasso3b687352004-08-19 06:56:53 +0000307 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hassoc6487d62004-12-24 06:00:11 +0000308 zlog_debug (" another path found, merge");
hasso508e53e2004-05-18 18:57:06 +0000309
310 for (i = 0; ospf6_nexthop_is_set (&v->nexthop[i]) &&
311 i < OSPF6_MULTI_PATH_LIMIT; i++)
312 {
313 for (j = 0; j < OSPF6_MULTI_PATH_LIMIT; j++)
314 {
315 if (ospf6_nexthop_is_set (&route->nexthop[j]))
316 {
317 if (ospf6_nexthop_is_same (&route->nexthop[j],
318 &v->nexthop[i]))
319 break;
320 else
321 continue;
322 }
323 ospf6_nexthop_copy (&route->nexthop[j], &v->nexthop[i]);
324 break;
325 }
326 }
327
328 prev = (struct ospf6_vertex *) route->route_option;
Dmitrij Tejblum403138e2011-01-13 18:25:40 +0300329 assert (prev->hops <= v->hops);
330 ospf6_vertex_delete (v);
hasso508e53e2004-05-18 18:57:06 +0000331
332 return -1;
333 }
334
335 /* There should be no case where candidate being installed (variable
336 "v") is closer than the one in the SPF tree (variable "route").
hasso6452df02004-08-15 05:52:07 +0000337 In the case something has gone wrong with the behavior of
hasso508e53e2004-05-18 18:57:06 +0000338 Priority-Queue. */
hasso6452df02004-08-15 05:52:07 +0000339
340 /* the case where the route exists already is handled and returned
341 up to here. */
hasso508e53e2004-05-18 18:57:06 +0000342 assert (route == NULL);
343
344 route = ospf6_route_create ();
345 memcpy (&route->prefix, &v->vertex_id, sizeof (struct prefix));
346 route->type = OSPF6_DEST_TYPE_LINKSTATE;
347 route->path.type = OSPF6_PATH_TYPE_INTRA;
348 route->path.origin.type = v->lsa->header->type;
349 route->path.origin.id = v->lsa->header->id;
350 route->path.origin.adv_router = v->lsa->header->adv_router;
351 route->path.metric_type = 1;
352 route->path.cost = v->cost;
353 route->path.cost_e2 = v->hops;
354 route->path.router_bits = v->capability;
355 route->path.options[0] = v->options[0];
356 route->path.options[1] = v->options[1];
357 route->path.options[2] = v->options[2];
358
359 for (i = 0; ospf6_nexthop_is_set (&v->nexthop[i]) &&
360 i < OSPF6_MULTI_PATH_LIMIT; i++)
361 ospf6_nexthop_copy (&route->nexthop[i], &v->nexthop[i]);
362
363 if (v->parent)
364 listnode_add_sort (v->parent->child_list, v);
365 route->route_option = v;
366
367 ospf6_route_add (route, result_table);
paul718e3742002-12-13 20:15:29 +0000368 return 0;
369}
370
hasso508e53e2004-05-18 18:57:06 +0000371void
372ospf6_spf_table_finish (struct ospf6_route_table *result_table)
373{
Vipin Kumar8c075ef2015-05-19 18:03:53 -0700374 struct ospf6_route *route, *nroute;
hasso508e53e2004-05-18 18:57:06 +0000375 struct ospf6_vertex *v;
376 for (route = ospf6_route_head (result_table); route;
Vipin Kumar8c075ef2015-05-19 18:03:53 -0700377 route = nroute)
hasso508e53e2004-05-18 18:57:06 +0000378 {
Vipin Kumar8c075ef2015-05-19 18:03:53 -0700379 nroute = ospf6_route_next (route);
hasso508e53e2004-05-18 18:57:06 +0000380 v = (struct ospf6_vertex *) route->route_option;
381 ospf6_vertex_delete (v);
382 ospf6_route_remove (route, result_table);
383 }
384}
385
Dinesh Dutta0edf672013-08-26 03:40:23 +0000386static const char *ospf6_spf_reason_str[] =
387 {
388 "R+",
389 "R-",
390 "N+",
391 "N-",
392 "L+",
393 "L-",
394 "R*",
395 "N*",
396 };
397
398void ospf6_spf_reason_string (unsigned int reason, char *buf, int size)
399{
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100400 size_t bit;
Dinesh Dutta0edf672013-08-26 03:40:23 +0000401 int len = 0;
402
403 if (!buf)
404 return;
405
406 for (bit = 0; bit <= (sizeof(ospf6_spf_reason_str) / sizeof(char *)); bit++)
407 {
408 if ((reason & (1 << bit)) && (len < size))
409 {
410 len += snprintf((buf + len), (size - len), "%s%s",
411 (len > 0) ? ", " : "", ospf6_spf_reason_str[bit]);
412 }
413 }
414}
415
hasso6452df02004-08-15 05:52:07 +0000416/* RFC2328 16.1. Calculating the shortest-path tree for an area */
417/* RFC2740 3.8.1. Calculating the shortest path tree for an area */
hasso508e53e2004-05-18 18:57:06 +0000418void
419ospf6_spf_calculation (u_int32_t router_id,
420 struct ospf6_route_table *result_table,
421 struct ospf6_area *oa)
422{
423 struct pqueue *candidate_list;
424 struct ospf6_vertex *root, *v, *w;
425 int i;
426 int size;
427 caddr_t lsdesc;
428 struct ospf6_lsa *lsa;
429
Tom Goffb48cebb2011-12-14 14:11:29 +0400430 ospf6_spf_table_finish (result_table);
431
hasso508e53e2004-05-18 18:57:06 +0000432 /* Install the calculating router itself as the root of the SPF tree */
433 /* construct root vertex */
434 lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_ROUTER), htonl (0),
435 router_id, oa->lsdb);
436 if (lsa == NULL)
437 return;
Tom Goff1d192342010-11-10 13:02:38 -0800438
439 /* initialize */
440 candidate_list = pqueue_create ();
441 candidate_list->cmp = ospf6_vertex_cmp;
442
hasso508e53e2004-05-18 18:57:06 +0000443 root = ospf6_vertex_create (lsa);
444 root->area = oa;
445 root->cost = 0;
446 root->hops = 0;
hasso6452df02004-08-15 05:52:07 +0000447 root->nexthop[0].ifindex = 0; /* loopbak I/F is better ... */
hasso508e53e2004-05-18 18:57:06 +0000448 inet_pton (AF_INET6, "::1", &root->nexthop[0].address);
449
450 /* Actually insert root to the candidate-list as the only candidate */
451 pqueue_enqueue (root, candidate_list);
452
453 /* Iterate until candidate-list becomes empty */
454 while (candidate_list->size)
455 {
456 /* get closest candidate from priority queue */
457 v = pqueue_dequeue (candidate_list);
458
hasso6452df02004-08-15 05:52:07 +0000459 /* installing may result in merging or rejecting of the vertex */
hasso508e53e2004-05-18 18:57:06 +0000460 if (ospf6_spf_install (v, result_table) < 0)
461 continue;
462
Dinesh Duttf41b4a02013-08-24 08:00:37 +0000463 /* Skip overloaded routers */
464 if ((OSPF6_LSA_IS_TYPE (ROUTER, v->lsa) &&
465 ospf6_router_is_stub_router (v->lsa)))
466 continue;
467
hasso508e53e2004-05-18 18:57:06 +0000468 /* For each LS description in the just-added vertex V's LSA */
469 size = (VERTEX_IS_TYPE (ROUTER, v) ?
470 sizeof (struct ospf6_router_lsdesc) :
471 sizeof (struct ospf6_network_lsdesc));
472 for (lsdesc = OSPF6_LSA_HEADER_END (v->lsa->header) + 4;
473 lsdesc + size <= OSPF6_LSA_END (v->lsa->header); lsdesc += size)
474 {
475 lsa = ospf6_lsdesc_lsa (lsdesc, v);
476 if (lsa == NULL)
477 continue;
478
479 if (! ospf6_lsdesc_backlink (lsa, lsdesc, v))
480 continue;
481
482 w = ospf6_vertex_create (lsa);
483 w->area = oa;
484 w->parent = v;
485 if (VERTEX_IS_TYPE (ROUTER, v))
486 {
487 w->cost = v->cost + ROUTER_LSDESC_GET_METRIC (lsdesc);
488 w->hops = v->hops + (VERTEX_IS_TYPE (NETWORK, w) ? 0 : 1);
489 }
490 else /* NETWORK */
491 {
492 w->cost = v->cost;
493 w->hops = v->hops + 1;
494 }
495
496 /* nexthop calculation */
497 if (w->hops == 0)
498 w->nexthop[0].ifindex = ROUTER_LSDESC_GET_IFID (lsdesc);
499 else if (w->hops == 1 && v->hops == 0)
500 ospf6_nexthop_calc (w, v, lsdesc);
501 else
502 {
503 for (i = 0; ospf6_nexthop_is_set (&v->nexthop[i]) &&
504 i < OSPF6_MULTI_PATH_LIMIT; i++)
505 ospf6_nexthop_copy (&w->nexthop[i], &v->nexthop[i]);
506 }
507
508 /* add new candidate to the candidate_list */
hasso3b687352004-08-19 06:56:53 +0000509 if (IS_OSPF6_DEBUG_SPF (PROCESS))
hassoc6487d62004-12-24 06:00:11 +0000510 zlog_debug (" New candidate: %s hops %d cost %d",
511 w->name, w->hops, w->cost);
hasso508e53e2004-05-18 18:57:06 +0000512 pqueue_enqueue (w, candidate_list);
513 }
514 }
515
516 pqueue_delete (candidate_list);
Vincent Bernatea86e402012-06-04 10:29:49 +0200517
518 oa->spf_calculation++;
hasso508e53e2004-05-18 18:57:06 +0000519}
520
Paul Jakma6ac29a52008-08-15 13:45:30 +0100521static void
hasso2680aa22004-11-25 20:54:46 +0000522ospf6_spf_log_database (struct ospf6_area *oa)
523{
524 char *p, *end, buffer[256];
525 struct listnode *node;
526 struct ospf6_interface *oi;
527
528 p = buffer;
529 end = buffer + sizeof (buffer);
530
531 snprintf (p, end - p, "SPF on DB (#LSAs):");
532 p = (buffer + strlen (buffer) < end ? buffer + strlen (buffer) : end);
533 snprintf (p, end - p, " Area %s: %d", oa->name, oa->lsdb->count);
534 p = (buffer + strlen (buffer) < end ? buffer + strlen (buffer) : end);
535
paul1eb8ef22005-04-07 07:30:20 +0000536 for (ALL_LIST_ELEMENTS_RO (oa->if_list, node, oi))
hasso2680aa22004-11-25 20:54:46 +0000537 {
hasso2680aa22004-11-25 20:54:46 +0000538 snprintf (p, end - p, " I/F %s: %d",
539 oi->interface->name, oi->lsdb->count);
540 p = (buffer + strlen (buffer) < end ? buffer + strlen (buffer) : end);
541 }
542
hassoc6487d62004-12-24 06:00:11 +0000543 zlog_debug ("%s", buffer);
hasso2680aa22004-11-25 20:54:46 +0000544}
545
Paul Jakma6ac29a52008-08-15 13:45:30 +0100546static int
paul718e3742002-12-13 20:15:29 +0000547ospf6_spf_calculation_thread (struct thread *t)
548{
hasso508e53e2004-05-18 18:57:06 +0000549 struct ospf6_area *oa;
Dinesh Dutt3810e062013-08-24 07:54:09 +0000550 struct ospf6 *ospf6;
hasso508e53e2004-05-18 18:57:06 +0000551 struct timeval start, end, runtime;
Dinesh Dutt3810e062013-08-24 07:54:09 +0000552 struct listnode *node;
553 struct ospf6_route *route;
Dinesh Dutta0edf672013-08-26 03:40:23 +0000554 int areas_processed = 0;
555 char rbuf[32];
paul718e3742002-12-13 20:15:29 +0000556
Dinesh Dutt3810e062013-08-24 07:54:09 +0000557 ospf6 = (struct ospf6 *)THREAD_ARG (t);
558 ospf6->t_spf_calc = NULL;
paul718e3742002-12-13 20:15:29 +0000559
560 /* execute SPF calculation */
Takashi Sogabe86f72dc2009-06-22 13:07:02 +0900561 quagga_gettime (QUAGGA_CLK_MONOTONIC, &start);
Dinesh Dutt3810e062013-08-24 07:54:09 +0000562
563 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa))
564 {
565
566 if (oa == ospf6->backbone)
567 continue;
568
569 if (IS_OSPF6_DEBUG_SPF (PROCESS))
570 zlog_debug ("SPF calculation for Area %s", oa->name);
571 if (IS_OSPF6_DEBUG_SPF (DATABASE))
572 ospf6_spf_log_database (oa);
573
574 ospf6_spf_calculation (ospf6->router_id, oa->spf_table, oa);
575 ospf6_intra_route_calculation (oa);
576 ospf6_intra_brouter_calculation (oa);
Dinesh Dutta0edf672013-08-26 03:40:23 +0000577
578 areas_processed++;
Dinesh Dutt3810e062013-08-24 07:54:09 +0000579 }
580
581 if (ospf6->backbone)
582 {
583 if (IS_OSPF6_DEBUG_SPF (PROCESS))
584 zlog_debug ("SPF calculation for Backbone area %s",
585 ospf6->backbone->name);
586 if (IS_OSPF6_DEBUG_SPF (DATABASE))
587 ospf6_spf_log_database(ospf6->backbone);
588
589 ospf6_spf_calculation(ospf6->router_id, ospf6->backbone->spf_table,
590 ospf6->backbone);
591 ospf6_intra_route_calculation(ospf6->backbone);
592 ospf6_intra_brouter_calculation(ospf6->backbone);
Dinesh Dutta0edf672013-08-26 03:40:23 +0000593 areas_processed++;
Dinesh Dutt3810e062013-08-24 07:54:09 +0000594 }
595
596 /* Redo summaries if required */
597 for (route = ospf6_route_head (ospf6->route_table); route;
598 route = ospf6_route_next (route))
599 ospf6_abr_originate_summary(route);
600
Takashi Sogabe86f72dc2009-06-22 13:07:02 +0900601 quagga_gettime (QUAGGA_CLK_MONOTONIC, &end);
hasso2680aa22004-11-25 20:54:46 +0000602 timersub (&end, &start, &runtime);
paul718e3742002-12-13 20:15:29 +0000603
Dinesh Dutt3810e062013-08-24 07:54:09 +0000604 ospf6->ts_spf_duration = runtime;
605
Dinesh Dutta0edf672013-08-26 03:40:23 +0000606 ospf6_spf_reason_string(ospf6->spf_reason, rbuf, sizeof(rbuf));
607
hasso3b687352004-08-19 06:56:53 +0000608 if (IS_OSPF6_DEBUG_SPF (PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
David Lamparteref008d22015-03-03 08:48:11 +0100609 zlog_debug ("SPF runtime: %lld sec %lld usec",
610 (long long)runtime.tv_sec, (long long)runtime.tv_usec);
paul718e3742002-12-13 20:15:29 +0000611
David Lamparteref008d22015-03-03 08:48:11 +0100612 zlog_info("SPF processing: # Areas: %d, SPF runtime: %lld sec %lld usec, "
613 "Reason: %s\n", areas_processed,
614 (long long)runtime.tv_sec, (long long)runtime.tv_usec,
Dinesh Dutta0edf672013-08-26 03:40:23 +0000615 rbuf);
616 ospf6->last_spf_reason = ospf6->spf_reason;
617 ospf6_reset_spf_reason(ospf6);
paul718e3742002-12-13 20:15:29 +0000618 return 0;
619}
620
Dinesh Dutt3810e062013-08-24 07:54:09 +0000621/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
622 set timer for SPF calc. */
paul718e3742002-12-13 20:15:29 +0000623void
Dinesh Dutta0edf672013-08-26 03:40:23 +0000624ospf6_spf_schedule (struct ospf6 *ospf6, unsigned int reason)
paul718e3742002-12-13 20:15:29 +0000625{
Dinesh Dutt3810e062013-08-24 07:54:09 +0000626 unsigned long delay, elapsed, ht;
627 struct timeval now, result;
628
Dinesh Dutta0edf672013-08-26 03:40:23 +0000629 ospf6_set_spf_reason(ospf6, reason);
630
Dinesh Dutt3810e062013-08-24 07:54:09 +0000631 if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
Dinesh Dutta0edf672013-08-26 03:40:23 +0000632 {
633 char rbuf[32];
634 ospf6_spf_reason_string(reason, rbuf, sizeof(rbuf));
635 zlog_debug ("SPF: calculation timer scheduled (reason %s)", rbuf);
636 }
Dinesh Dutt3810e062013-08-24 07:54:09 +0000637
638 /* OSPF instance does not exist. */
639 if (ospf6 == NULL)
paul718e3742002-12-13 20:15:29 +0000640 return;
Dinesh Dutt3810e062013-08-24 07:54:09 +0000641
642 /* SPF calculation timer is already scheduled. */
643 if (ospf6->t_spf_calc)
644 {
645 if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
646 zlog_debug ("SPF: calculation timer is already scheduled: %p",
David Lampartereed3c482015-03-03 08:51:53 +0100647 (void *)ospf6->t_spf_calc);
Dinesh Dutt3810e062013-08-24 07:54:09 +0000648 return;
649 }
650
651 /* XXX Monotic timers: we only care about relative time here. */
652 now = recent_relative_time ();
653 timersub (&now, &ospf6->ts_spf, &result);
654
655 elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
656 ht = ospf6->spf_holdtime * ospf6->spf_hold_multiplier;
657
658 if (ht > ospf6->spf_max_holdtime)
659 ht = ospf6->spf_max_holdtime;
660
661 /* Get SPF calculation delay time. */
662 if (elapsed < ht)
663 {
664 /* Got an event within the hold time of last SPF. We need to
665 * increase the hold_multiplier, if it's not already at/past
666 * maximum value, and wasn't already increased..
667 */
668 if (ht < ospf6->spf_max_holdtime)
669 ospf6->spf_hold_multiplier++;
670
671 /* always honour the SPF initial delay */
672 if ( (ht - elapsed) < ospf6->spf_delay)
673 delay = ospf6->spf_delay;
674 else
675 delay = ht - elapsed;
676 }
677 else
678 {
679 /* Event is past required hold-time of last SPF */
680 delay = ospf6->spf_delay;
681 ospf6->spf_hold_multiplier = 1;
682 }
683
684 if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
685 zlog_debug ("SPF: calculation timer delay = %ld", delay);
686
687 zlog_info ("SPF: Scheduled in %ld msec", delay);
688
689 ospf6->t_spf_calc =
690 thread_add_timer_msec (master, ospf6_spf_calculation_thread, ospf6, delay);
paul718e3742002-12-13 20:15:29 +0000691}
692
693void
paul0c083ee2004-10-10 12:54:58 +0000694ospf6_spf_display_subtree (struct vty *vty, const char *prefix, int rest,
hasso508e53e2004-05-18 18:57:06 +0000695 struct ospf6_vertex *v)
paul718e3742002-12-13 20:15:29 +0000696{
paul1eb8ef22005-04-07 07:30:20 +0000697 struct listnode *node, *nnode;
hasso508e53e2004-05-18 18:57:06 +0000698 struct ospf6_vertex *c;
699 char *next_prefix;
700 int len;
paul718e3742002-12-13 20:15:29 +0000701 int restnum;
paul718e3742002-12-13 20:15:29 +0000702
hasso508e53e2004-05-18 18:57:06 +0000703 /* "prefix" is the space prefix of the display line */
hasso049207c2004-08-04 20:02:13 +0000704 vty_out (vty, "%s+-%s [%d]%s", prefix, v->name, v->cost, VNL);
paul718e3742002-12-13 20:15:29 +0000705
hasso508e53e2004-05-18 18:57:06 +0000706 len = strlen (prefix) + 4;
707 next_prefix = (char *) malloc (len);
708 if (next_prefix == NULL)
paul718e3742002-12-13 20:15:29 +0000709 {
hasso049207c2004-08-04 20:02:13 +0000710 vty_out (vty, "malloc failed%s", VNL);
paul718e3742002-12-13 20:15:29 +0000711 return;
712 }
hasso508e53e2004-05-18 18:57:06 +0000713 snprintf (next_prefix, len, "%s%s", prefix, (rest ? "| " : " "));
paul718e3742002-12-13 20:15:29 +0000714
hasso508e53e2004-05-18 18:57:06 +0000715 restnum = listcount (v->child_list);
paul1eb8ef22005-04-07 07:30:20 +0000716 for (ALL_LIST_ELEMENTS (v->child_list, node, nnode, c))
paul718e3742002-12-13 20:15:29 +0000717 {
hasso508e53e2004-05-18 18:57:06 +0000718 restnum--;
719 ospf6_spf_display_subtree (vty, next_prefix, restnum, c);
paul718e3742002-12-13 20:15:29 +0000720 }
721
hasso508e53e2004-05-18 18:57:06 +0000722 free (next_prefix);
paul718e3742002-12-13 20:15:29 +0000723}
724
hasso3b687352004-08-19 06:56:53 +0000725DEFUN (debug_ospf6_spf_process,
726 debug_ospf6_spf_process_cmd,
727 "debug ospf6 spf process",
hasso508e53e2004-05-18 18:57:06 +0000728 DEBUG_STR
paul718e3742002-12-13 20:15:29 +0000729 OSPF6_STR
hasso508e53e2004-05-18 18:57:06 +0000730 "Debug SPF Calculation\n"
hasso3b687352004-08-19 06:56:53 +0000731 "Debug Detailed SPF Process\n"
hasso508e53e2004-05-18 18:57:06 +0000732 )
paul718e3742002-12-13 20:15:29 +0000733{
hasso508e53e2004-05-18 18:57:06 +0000734 unsigned char level = 0;
hasso3b687352004-08-19 06:56:53 +0000735 level = OSPF6_DEBUG_SPF_PROCESS;
hasso508e53e2004-05-18 18:57:06 +0000736 OSPF6_DEBUG_SPF_ON (level);
paul718e3742002-12-13 20:15:29 +0000737 return CMD_SUCCESS;
738}
739
hasso3b687352004-08-19 06:56:53 +0000740DEFUN (debug_ospf6_spf_time,
741 debug_ospf6_spf_time_cmd,
742 "debug ospf6 spf time",
hasso508e53e2004-05-18 18:57:06 +0000743 DEBUG_STR
paul718e3742002-12-13 20:15:29 +0000744 OSPF6_STR
hasso508e53e2004-05-18 18:57:06 +0000745 "Debug SPF Calculation\n"
hasso3b687352004-08-19 06:56:53 +0000746 "Measure time taken by SPF Calculation\n"
hasso508e53e2004-05-18 18:57:06 +0000747 )
paul718e3742002-12-13 20:15:29 +0000748{
hasso508e53e2004-05-18 18:57:06 +0000749 unsigned char level = 0;
hasso3b687352004-08-19 06:56:53 +0000750 level = OSPF6_DEBUG_SPF_TIME;
hasso508e53e2004-05-18 18:57:06 +0000751 OSPF6_DEBUG_SPF_ON (level);
752 return CMD_SUCCESS;
paul718e3742002-12-13 20:15:29 +0000753}
754
hasso2680aa22004-11-25 20:54:46 +0000755DEFUN (debug_ospf6_spf_database,
756 debug_ospf6_spf_database_cmd,
757 "debug ospf6 spf database",
758 DEBUG_STR
759 OSPF6_STR
760 "Debug SPF Calculation\n"
761 "Log number of LSAs at SPF Calculation time\n"
762 )
763{
764 unsigned char level = 0;
765 level = OSPF6_DEBUG_SPF_DATABASE;
766 OSPF6_DEBUG_SPF_ON (level);
767 return CMD_SUCCESS;
768}
769
hasso3b687352004-08-19 06:56:53 +0000770DEFUN (no_debug_ospf6_spf_process,
771 no_debug_ospf6_spf_process_cmd,
772 "no debug ospf6 spf process",
hasso508e53e2004-05-18 18:57:06 +0000773 NO_STR
774 DEBUG_STR
paul718e3742002-12-13 20:15:29 +0000775 OSPF6_STR
hasso508e53e2004-05-18 18:57:06 +0000776 "Quit Debugging SPF Calculation\n"
hasso3b687352004-08-19 06:56:53 +0000777 "Quit Debugging Detailed SPF Process\n"
hasso508e53e2004-05-18 18:57:06 +0000778 )
779{
780 unsigned char level = 0;
hasso3b687352004-08-19 06:56:53 +0000781 level = OSPF6_DEBUG_SPF_PROCESS;
hasso508e53e2004-05-18 18:57:06 +0000782 OSPF6_DEBUG_SPF_OFF (level);
783 return CMD_SUCCESS;
784}
paul718e3742002-12-13 20:15:29 +0000785
hasso3b687352004-08-19 06:56:53 +0000786DEFUN (no_debug_ospf6_spf_time,
787 no_debug_ospf6_spf_time_cmd,
788 "no debug ospf6 spf time",
hasso508e53e2004-05-18 18:57:06 +0000789 NO_STR
790 DEBUG_STR
paul718e3742002-12-13 20:15:29 +0000791 OSPF6_STR
hasso508e53e2004-05-18 18:57:06 +0000792 "Quit Debugging SPF Calculation\n"
hasso3b687352004-08-19 06:56:53 +0000793 "Quit Measuring time taken by SPF Calculation\n"
hasso508e53e2004-05-18 18:57:06 +0000794 )
795{
796 unsigned char level = 0;
hasso3b687352004-08-19 06:56:53 +0000797 level = OSPF6_DEBUG_SPF_TIME;
hasso508e53e2004-05-18 18:57:06 +0000798 OSPF6_DEBUG_SPF_OFF (level);
799 return CMD_SUCCESS;
800}
801
hasso2680aa22004-11-25 20:54:46 +0000802DEFUN (no_debug_ospf6_spf_database,
803 no_debug_ospf6_spf_database_cmd,
804 "no debug ospf6 spf database",
805 NO_STR
806 DEBUG_STR
807 OSPF6_STR
808 "Debug SPF Calculation\n"
809 "Quit Logging number of LSAs at SPF Calculation time\n"
810 )
811{
812 unsigned char level = 0;
813 level = OSPF6_DEBUG_SPF_DATABASE;
814 OSPF6_DEBUG_SPF_OFF (level);
815 return CMD_SUCCESS;
816}
817
Dinesh Dutt3810e062013-08-24 07:54:09 +0000818static int
819ospf6_timers_spf_set (struct vty *vty, unsigned int delay,
820 unsigned int hold,
821 unsigned int max)
822{
823 struct ospf6 *ospf = vty->index;
824
825 ospf->spf_delay = delay;
826 ospf->spf_holdtime = hold;
827 ospf->spf_max_holdtime = max;
828
829 return CMD_SUCCESS;
830}
831
832DEFUN (ospf6_timers_throttle_spf,
833 ospf6_timers_throttle_spf_cmd,
834 "timers throttle spf <0-600000> <0-600000> <0-600000>",
835 "Adjust routing timers\n"
836 "Throttling adaptive timer\n"
837 "OSPF6 SPF timers\n"
838 "Delay (msec) from first change received till SPF calculation\n"
839 "Initial hold time (msec) between consecutive SPF calculations\n"
840 "Maximum hold time (msec)\n")
841{
842 unsigned int delay, hold, max;
843
844 if (argc != 3)
845 {
846 vty_out (vty, "Insufficient arguments%s", VTY_NEWLINE);
847 return CMD_WARNING;
848 }
849
850 VTY_GET_INTEGER_RANGE ("SPF delay timer", delay, argv[0], 0, 600000);
851 VTY_GET_INTEGER_RANGE ("SPF hold timer", hold, argv[1], 0, 600000);
852 VTY_GET_INTEGER_RANGE ("SPF max-hold timer", max, argv[2], 0, 600000);
853
854 return ospf6_timers_spf_set (vty, delay, hold, max);
855}
856
857DEFUN (no_ospf6_timers_throttle_spf,
858 no_ospf6_timers_throttle_spf_cmd,
859 "no timers throttle spf",
860 NO_STR
861 "Adjust routing timers\n"
862 "Throttling adaptive timer\n"
863 "OSPF6 SPF timers\n")
864{
865 return ospf6_timers_spf_set (vty,
866 OSPF_SPF_DELAY_DEFAULT,
867 OSPF_SPF_HOLDTIME_DEFAULT,
868 OSPF_SPF_MAX_HOLDTIME_DEFAULT);
869}
870
hasso508e53e2004-05-18 18:57:06 +0000871int
872config_write_ospf6_debug_spf (struct vty *vty)
873{
hasso3b687352004-08-19 06:56:53 +0000874 if (IS_OSPF6_DEBUG_SPF (PROCESS))
875 vty_out (vty, "debug ospf6 spf process%s", VNL);
876 if (IS_OSPF6_DEBUG_SPF (TIME))
877 vty_out (vty, "debug ospf6 spf time%s", VNL);
hasso2680aa22004-11-25 20:54:46 +0000878 if (IS_OSPF6_DEBUG_SPF (DATABASE))
879 vty_out (vty, "debug ospf6 spf database%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000880 return 0;
881}
882
883void
Dinesh Dutt3810e062013-08-24 07:54:09 +0000884ospf6_spf_config_write (struct vty *vty)
885{
886
887 if (ospf6->spf_delay != OSPF_SPF_DELAY_DEFAULT ||
888 ospf6->spf_holdtime != OSPF_SPF_HOLDTIME_DEFAULT ||
889 ospf6->spf_max_holdtime != OSPF_SPF_MAX_HOLDTIME_DEFAULT)
890 vty_out (vty, " timers throttle spf %d %d %d%s",
891 ospf6->spf_delay, ospf6->spf_holdtime,
892 ospf6->spf_max_holdtime, VTY_NEWLINE);
893
894}
895
896void
Paul Jakma6ac29a52008-08-15 13:45:30 +0100897install_element_ospf6_debug_spf (void)
hasso508e53e2004-05-18 18:57:06 +0000898{
hasso3b687352004-08-19 06:56:53 +0000899 install_element (ENABLE_NODE, &debug_ospf6_spf_process_cmd);
900 install_element (ENABLE_NODE, &debug_ospf6_spf_time_cmd);
hasso2680aa22004-11-25 20:54:46 +0000901 install_element (ENABLE_NODE, &debug_ospf6_spf_database_cmd);
hasso3b687352004-08-19 06:56:53 +0000902 install_element (ENABLE_NODE, &no_debug_ospf6_spf_process_cmd);
903 install_element (ENABLE_NODE, &no_debug_ospf6_spf_time_cmd);
hasso2680aa22004-11-25 20:54:46 +0000904 install_element (ENABLE_NODE, &no_debug_ospf6_spf_database_cmd);
hasso3b687352004-08-19 06:56:53 +0000905 install_element (CONFIG_NODE, &debug_ospf6_spf_process_cmd);
906 install_element (CONFIG_NODE, &debug_ospf6_spf_time_cmd);
hasso2680aa22004-11-25 20:54:46 +0000907 install_element (CONFIG_NODE, &debug_ospf6_spf_database_cmd);
hasso3b687352004-08-19 06:56:53 +0000908 install_element (CONFIG_NODE, &no_debug_ospf6_spf_process_cmd);
909 install_element (CONFIG_NODE, &no_debug_ospf6_spf_time_cmd);
hasso2680aa22004-11-25 20:54:46 +0000910 install_element (CONFIG_NODE, &no_debug_ospf6_spf_database_cmd);
hasso508e53e2004-05-18 18:57:06 +0000911}
paul718e3742002-12-13 20:15:29 +0000912
913void
Paul Jakma6ac29a52008-08-15 13:45:30 +0100914ospf6_spf_init (void)
paul718e3742002-12-13 20:15:29 +0000915{
Dinesh Dutt3810e062013-08-24 07:54:09 +0000916 install_element (OSPF6_NODE, &ospf6_timers_throttle_spf_cmd);
917 install_element (OSPF6_NODE, &no_ospf6_timers_throttle_spf_cmd);
paul718e3742002-12-13 20:15:29 +0000918}